提交 9aa505d2 编写于 作者: M Michal Kazior 提交者: Kalle Valo

ath10k: start using sk_buff_head

Instead of using manual sk_buff linking via ->next
use sk_buff_head. It's more robust, cleaner and
there's plenty of helper functions in kernel
already to manage sk_buff_head.
Signed-off-by: NMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: NKalle Valo <kvalo@qca.qualcomm.com>
上级 47b6308b
...@@ -301,27 +301,15 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt) ...@@ -301,27 +301,15 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt)
return msdu; return msdu;
} }
static void ath10k_htt_rx_free_msdu_chain(struct sk_buff *skb)
{
struct sk_buff *next;
while (skb) {
next = skb->next;
dev_kfree_skb_any(skb);
skb = next;
}
}
/* return: < 0 fatal error, 0 - non chained msdu, 1 chained msdu */ /* return: < 0 fatal error, 0 - non chained msdu, 1 chained msdu */
static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
u8 **fw_desc, int *fw_desc_len, u8 **fw_desc, int *fw_desc_len,
struct sk_buff **head_msdu, struct sk_buff_head *amsdu,
struct sk_buff **tail_msdu,
u32 *attention) u32 *attention)
{ {
struct ath10k *ar = htt->ar; struct ath10k *ar = htt->ar;
int msdu_len, msdu_chaining = 0; int msdu_len, msdu_chaining = 0;
struct sk_buff *msdu, *next; struct sk_buff *msdu;
struct htt_rx_desc *rx_desc; struct htt_rx_desc *rx_desc;
lockdep_assert_held(&htt->rx_ring.lock); lockdep_assert_held(&htt->rx_ring.lock);
...@@ -331,10 +319,19 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -331,10 +319,19 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
return -1; return -1;
} }
msdu = *head_msdu = ath10k_htt_rx_netbuf_pop(htt); for (;;) {
while (msdu) {
int last_msdu, msdu_len_invalid, msdu_chained; int last_msdu, msdu_len_invalid, msdu_chained;
msdu = ath10k_htt_rx_netbuf_pop(htt);
if (!msdu) {
ath10k_err(ar, "failed to pop msdu\n");
__skb_queue_purge(amsdu);
htt->rx_confused = true;
break;
}
__skb_queue_tail(amsdu, msdu);
rx_desc = (struct htt_rx_desc *)msdu->data; rx_desc = (struct htt_rx_desc *)msdu->data;
/* FIXME: we must report msdu payload since this is what caller /* FIXME: we must report msdu payload since this is what caller
...@@ -352,10 +349,8 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -352,10 +349,8 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
*/ */
if (!(__le32_to_cpu(rx_desc->attention.flags) if (!(__le32_to_cpu(rx_desc->attention.flags)
& RX_ATTENTION_FLAGS_MSDU_DONE)) { & RX_ATTENTION_FLAGS_MSDU_DONE)) {
ath10k_htt_rx_free_msdu_chain(*head_msdu); ath10k_err(ar, "popped an incomplete msdu\n");
*head_msdu = NULL; __skb_queue_purge(amsdu);
msdu = NULL;
ath10k_err(ar, "htt rx stopped. cannot recover\n");
htt->rx_confused = true; htt->rx_confused = true;
break; break;
} }
...@@ -421,25 +416,20 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -421,25 +416,20 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
skb_put(msdu, min(msdu_len, HTT_RX_MSDU_SIZE)); skb_put(msdu, min(msdu_len, HTT_RX_MSDU_SIZE));
msdu_len -= msdu->len; msdu_len -= msdu->len;
/* FIXME: Do chained buffers include htt_rx_desc or not? */ /* Note: Chained buffers do not contain rx descriptor */
while (msdu_chained--) { while (msdu_chained--) {
struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt); msdu = ath10k_htt_rx_netbuf_pop(htt);
if (!msdu) {
if (!next) {
ath10k_warn(ar, "failed to pop chained msdu\n"); ath10k_warn(ar, "failed to pop chained msdu\n");
ath10k_htt_rx_free_msdu_chain(*head_msdu); __skb_queue_purge(amsdu);
*head_msdu = NULL;
msdu = NULL;
htt->rx_confused = true; htt->rx_confused = true;
break; break;
} }
skb_trim(next, 0); __skb_queue_tail(amsdu, msdu);
skb_put(next, min(msdu_len, HTT_RX_BUF_SIZE)); skb_trim(msdu, 0);
msdu_len -= next->len; skb_put(msdu, min(msdu_len, HTT_RX_BUF_SIZE));
msdu_len -= msdu->len;
msdu->next = next;
msdu = next;
msdu_chaining = 1; msdu_chaining = 1;
} }
...@@ -448,18 +438,12 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -448,18 +438,12 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
trace_ath10k_htt_rx_desc(ar, &rx_desc->attention, trace_ath10k_htt_rx_desc(ar, &rx_desc->attention,
sizeof(*rx_desc) - sizeof(u32)); sizeof(*rx_desc) - sizeof(u32));
if (last_msdu) {
msdu->next = NULL;
break;
}
next = ath10k_htt_rx_netbuf_pop(htt); if (last_msdu)
msdu->next = next; break;
msdu = next;
} }
*tail_msdu = msdu;
if (*head_msdu == NULL) if (skb_queue_empty(amsdu))
msdu_chaining = -1; msdu_chaining = -1;
/* /*
...@@ -915,11 +899,11 @@ static int ath10k_htt_rx_nwifi_hdrlen(struct ieee80211_hdr *hdr) ...@@ -915,11 +899,11 @@ static int ath10k_htt_rx_nwifi_hdrlen(struct ieee80211_hdr *hdr)
static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
struct ieee80211_rx_status *rx_status, struct ieee80211_rx_status *rx_status,
struct sk_buff *skb_in) struct sk_buff_head *amsdu)
{ {
struct ath10k *ar = htt->ar; struct ath10k *ar = htt->ar;
struct htt_rx_desc *rxd; struct htt_rx_desc *rxd;
struct sk_buff *skb = skb_in; struct sk_buff *skb;
struct sk_buff *first; struct sk_buff *first;
enum rx_msdu_decap_format fmt; enum rx_msdu_decap_format fmt;
enum htt_rx_mpdu_encrypt_type enctype; enum htt_rx_mpdu_encrypt_type enctype;
...@@ -927,7 +911,9 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, ...@@ -927,7 +911,9 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
u8 hdr_buf[64], da[ETH_ALEN], sa[ETH_ALEN], *qos; u8 hdr_buf[64], da[ETH_ALEN], sa[ETH_ALEN], *qos;
unsigned int hdr_len; unsigned int hdr_len;
rxd = (void *)skb->data - sizeof(*rxd); first = skb_peek(amsdu);
rxd = (void *)first->data - sizeof(*rxd);
enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
RX_MPDU_START_INFO0_ENCRYPT_TYPE); RX_MPDU_START_INFO0_ENCRYPT_TYPE);
...@@ -936,8 +922,7 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, ...@@ -936,8 +922,7 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
memcpy(hdr_buf, hdr, hdr_len); memcpy(hdr_buf, hdr, hdr_len);
hdr = (struct ieee80211_hdr *)hdr_buf; hdr = (struct ieee80211_hdr *)hdr_buf;
first = skb; while ((skb = __skb_dequeue(amsdu))) {
while (skb) {
void *decap_hdr; void *decap_hdr;
int len; int len;
...@@ -1005,18 +990,15 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, ...@@ -1005,18 +990,15 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
break; break;
} }
skb_in = skb; ath10k_htt_rx_h_protected(htt, rx_status, skb, enctype, fmt,
ath10k_htt_rx_h_protected(htt, rx_status, skb_in, enctype, fmt,
false); false);
skb = skb->next;
skb_in->next = NULL;
if (skb) if (skb_queue_empty(amsdu))
rx_status->flag |= RX_FLAG_AMSDU_MORE;
else
rx_status->flag &= ~RX_FLAG_AMSDU_MORE; rx_status->flag &= ~RX_FLAG_AMSDU_MORE;
else
rx_status->flag |= RX_FLAG_AMSDU_MORE;
ath10k_process_rx(htt->ar, rx_status, skb_in); ath10k_process_rx(htt->ar, rx_status, skb);
} }
/* FIXME: It might be nice to re-assemble the A-MSDU when there's a /* FIXME: It might be nice to re-assemble the A-MSDU when there's a
...@@ -1035,13 +1017,6 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt, ...@@ -1035,13 +1017,6 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt,
int hdr_len; int hdr_len;
void *rfc1042; void *rfc1042;
/* This shouldn't happen. If it does than it may be a FW bug. */
if (skb->next) {
ath10k_warn(ar, "htt rx received chained non A-MSDU frame\n");
ath10k_htt_rx_free_msdu_chain(skb->next);
skb->next = NULL;
}
rxd = (void *)skb->data - sizeof(*rxd); rxd = (void *)skb->data - sizeof(*rxd);
fmt = MS(__le32_to_cpu(rxd->msdu_start.info1), fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
RX_MSDU_START_INFO1_DECAP_FORMAT); RX_MSDU_START_INFO1_DECAP_FORMAT);
...@@ -1127,10 +1102,9 @@ static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb) ...@@ -1127,10 +1102,9 @@ static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb)
return CHECKSUM_UNNECESSARY; return CHECKSUM_UNNECESSARY;
} }
static int ath10k_unchain_msdu(struct sk_buff *msdu_head) static int ath10k_unchain_msdu(struct sk_buff_head *amsdu)
{ {
struct sk_buff *next = msdu_head->next; struct sk_buff *skb, *first;
struct sk_buff *to_free = next;
int space; int space;
int total_len = 0; int total_len = 0;
...@@ -1141,40 +1115,33 @@ static int ath10k_unchain_msdu(struct sk_buff *msdu_head) ...@@ -1141,40 +1115,33 @@ static int ath10k_unchain_msdu(struct sk_buff *msdu_head)
* skb? * skb?
*/ */
msdu_head->next = NULL; first = __skb_dequeue(amsdu);
/* Allocate total length all at once. */ /* Allocate total length all at once. */
while (next) { skb_queue_walk(amsdu, skb)
total_len += next->len; total_len += skb->len;
next = next->next;
}
space = total_len - skb_tailroom(msdu_head); space = total_len - skb_tailroom(first);
if ((space > 0) && if ((space > 0) &&
(pskb_expand_head(msdu_head, 0, space, GFP_ATOMIC) < 0)) { (pskb_expand_head(first, 0, space, GFP_ATOMIC) < 0)) {
/* TODO: bump some rx-oom error stat */ /* TODO: bump some rx-oom error stat */
/* put it back together so we can free the /* put it back together so we can free the
* whole list at once. * whole list at once.
*/ */
msdu_head->next = to_free; __skb_queue_head(amsdu, first);
return -1; return -1;
} }
/* Walk list again, copying contents into /* Walk list again, copying contents into
* msdu_head * msdu_head
*/ */
next = to_free; while ((skb = __skb_dequeue(amsdu))) {
while (next) { skb_copy_from_linear_data(skb, skb_put(first, skb->len),
skb_copy_from_linear_data(next, skb_put(msdu_head, next->len), skb->len);
next->len); dev_kfree_skb_any(skb);
next = next->next;
} }
/* If here, we have consolidated skb. Free the __skb_queue_head(amsdu, first);
* fragments and pass the main skb on up the
* stack.
*/
ath10k_htt_rx_free_msdu_chain(to_free);
return 0; return 0;
} }
...@@ -1223,6 +1190,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, ...@@ -1223,6 +1190,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
struct ath10k *ar = htt->ar; struct ath10k *ar = htt->ar;
struct ieee80211_rx_status *rx_status = &htt->rx_status; struct ieee80211_rx_status *rx_status = &htt->rx_status;
struct htt_rx_indication_mpdu_range *mpdu_ranges; struct htt_rx_indication_mpdu_range *mpdu_ranges;
struct sk_buff_head amsdu;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
int num_mpdu_ranges; int num_mpdu_ranges;
u32 attention; u32 attention;
...@@ -1271,35 +1239,28 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, ...@@ -1271,35 +1239,28 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
for (i = 0; i < num_mpdu_ranges; i++) { for (i = 0; i < num_mpdu_ranges; i++) {
for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) { for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) {
struct sk_buff *msdu_head, *msdu_tail;
attention = 0; attention = 0;
msdu_head = NULL; __skb_queue_head_init(&amsdu);
msdu_tail = NULL; ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc,
ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc_len, &amsdu,
&fw_desc,
&fw_desc_len,
&msdu_head,
&msdu_tail,
&attention); &attention);
if (ret < 0) { if (ret < 0) {
ath10k_warn(ar, "failed to pop amsdu from htt rx ring %d\n", ath10k_warn(ar, "failed to pop amsdu from htt rx ring %d\n",
ret); ret);
ath10k_htt_rx_free_msdu_chain(msdu_head); __skb_queue_purge(&amsdu);
continue; continue;
} }
if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head, if (!ath10k_htt_rx_amsdu_allowed(htt, skb_peek(&amsdu),
channel_set, channel_set,
attention)) { attention)) {
ath10k_htt_rx_free_msdu_chain(msdu_head); __skb_queue_purge(&amsdu);
continue; continue;
} }
if (ret > 0 && if (ret > 0 && ath10k_unchain_msdu(&amsdu) < 0) {
ath10k_unchain_msdu(msdu_head) < 0) { __skb_queue_purge(&amsdu);
ath10k_htt_rx_free_msdu_chain(msdu_head);
continue; continue;
} }
...@@ -1313,12 +1274,13 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, ...@@ -1313,12 +1274,13 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
else else
rx_status->flag &= ~RX_FLAG_MMIC_ERROR; rx_status->flag &= ~RX_FLAG_MMIC_ERROR;
hdr = ath10k_htt_rx_skb_get_hdr(msdu_head); hdr = ath10k_htt_rx_skb_get_hdr(skb_peek(&amsdu));
if (ath10k_htt_rx_hdr_is_amsdu(hdr)) if (ath10k_htt_rx_hdr_is_amsdu(hdr))
ath10k_htt_rx_amsdu(htt, rx_status, msdu_head); ath10k_htt_rx_amsdu(htt, rx_status, &amsdu);
else else
ath10k_htt_rx_msdu(htt, rx_status, msdu_head); ath10k_htt_rx_msdu(htt, rx_status,
__skb_dequeue(&amsdu));
} }
} }
...@@ -1329,12 +1291,13 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, ...@@ -1329,12 +1291,13 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
struct htt_rx_fragment_indication *frag) struct htt_rx_fragment_indication *frag)
{ {
struct ath10k *ar = htt->ar; struct ath10k *ar = htt->ar;
struct sk_buff *msdu_head, *msdu_tail; struct sk_buff *msdu;
enum htt_rx_mpdu_encrypt_type enctype; enum htt_rx_mpdu_encrypt_type enctype;
struct htt_rx_desc *rxd; struct htt_rx_desc *rxd;
enum rx_msdu_decap_format fmt; enum rx_msdu_decap_format fmt;
struct ieee80211_rx_status *rx_status = &htt->rx_status; struct ieee80211_rx_status *rx_status = &htt->rx_status;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
struct sk_buff_head amsdu;
int ret; int ret;
bool tkip_mic_err; bool tkip_mic_err;
bool decrypt_err; bool decrypt_err;
...@@ -1346,13 +1309,11 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, ...@@ -1346,13 +1309,11 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
fw_desc_len = __le16_to_cpu(frag->fw_rx_desc_bytes); fw_desc_len = __le16_to_cpu(frag->fw_rx_desc_bytes);
fw_desc = (u8 *)frag->fw_msdu_rx_desc; fw_desc = (u8 *)frag->fw_msdu_rx_desc;
msdu_head = NULL; __skb_queue_head_init(&amsdu);
msdu_tail = NULL;
spin_lock_bh(&htt->rx_ring.lock); spin_lock_bh(&htt->rx_ring.lock);
ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len, ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len,
&msdu_head, &msdu_tail, &amsdu, &attention);
&attention);
spin_unlock_bh(&htt->rx_ring.lock); spin_unlock_bh(&htt->rx_ring.lock);
tasklet_schedule(&htt->rx_replenish_task); tasklet_schedule(&htt->rx_replenish_task);
...@@ -1362,15 +1323,23 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, ...@@ -1362,15 +1323,23 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
if (ret) { if (ret) {
ath10k_warn(ar, "failed to pop amsdu from httr rx ring for fragmented rx %d\n", ath10k_warn(ar, "failed to pop amsdu from httr rx ring for fragmented rx %d\n",
ret); ret);
ath10k_htt_rx_free_msdu_chain(msdu_head); __skb_queue_purge(&amsdu);
return; return;
} }
if (skb_queue_len(&amsdu) != 1) {
ath10k_warn(ar, "failed to pop frag amsdu: too many msdus\n");
__skb_queue_purge(&amsdu);
return;
}
msdu = __skb_dequeue(&amsdu);
/* FIXME: implement signal strength */ /* FIXME: implement signal strength */
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL; rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
hdr = (struct ieee80211_hdr *)msdu_head->data; hdr = (struct ieee80211_hdr *)msdu->data;
rxd = (void *)msdu_head->data - sizeof(*rxd); rxd = (void *)msdu->data - sizeof(*rxd);
tkip_mic_err = !!(attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR); tkip_mic_err = !!(attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
decrypt_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR); decrypt_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR);
fmt = MS(__le32_to_cpu(rxd->msdu_start.info1), fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
...@@ -1378,22 +1347,22 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, ...@@ -1378,22 +1347,22 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
if (fmt != RX_MSDU_DECAP_RAW) { if (fmt != RX_MSDU_DECAP_RAW) {
ath10k_warn(ar, "we dont support non-raw fragmented rx yet\n"); ath10k_warn(ar, "we dont support non-raw fragmented rx yet\n");
dev_kfree_skb_any(msdu_head); dev_kfree_skb_any(msdu);
goto end; goto end;
} }
enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
RX_MPDU_START_INFO0_ENCRYPT_TYPE); RX_MPDU_START_INFO0_ENCRYPT_TYPE);
ath10k_htt_rx_h_protected(htt, rx_status, msdu_head, enctype, fmt, ath10k_htt_rx_h_protected(htt, rx_status, msdu, enctype, fmt,
true); true);
msdu_head->ip_summed = ath10k_htt_rx_get_csum_state(msdu_head); msdu->ip_summed = ath10k_htt_rx_get_csum_state(msdu);
if (tkip_mic_err) if (tkip_mic_err)
ath10k_warn(ar, "tkip mic error\n"); ath10k_warn(ar, "tkip mic error\n");
if (decrypt_err) { if (decrypt_err) {
ath10k_warn(ar, "decryption err in fragmented rx\n"); ath10k_warn(ar, "decryption err in fragmented rx\n");
dev_kfree_skb_any(msdu_head); dev_kfree_skb_any(msdu);
goto end; goto end;
} }
...@@ -1402,11 +1371,11 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, ...@@ -1402,11 +1371,11 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
paramlen = ath10k_htt_rx_crypto_param_len(ar, enctype); paramlen = ath10k_htt_rx_crypto_param_len(ar, enctype);
/* It is more efficient to move the header than the payload */ /* It is more efficient to move the header than the payload */
memmove((void *)msdu_head->data + paramlen, memmove((void *)msdu->data + paramlen,
(void *)msdu_head->data, (void *)msdu->data,
hdrlen); hdrlen);
skb_pull(msdu_head, paramlen); skb_pull(msdu, paramlen);
hdr = (struct ieee80211_hdr *)msdu_head->data; hdr = (struct ieee80211_hdr *)msdu->data;
} }
/* remove trailing FCS */ /* remove trailing FCS */
...@@ -1420,17 +1389,17 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, ...@@ -1420,17 +1389,17 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
trim += MICHAEL_MIC_LEN; trim += MICHAEL_MIC_LEN;
if (trim > msdu_head->len) { if (trim > msdu->len) {
ath10k_warn(ar, "htt rx fragment: trailer longer than the frame itself? drop\n"); ath10k_warn(ar, "htt rx fragment: trailer longer than the frame itself? drop\n");
dev_kfree_skb_any(msdu_head); dev_kfree_skb_any(msdu);
goto end; goto end;
} }
skb_trim(msdu_head, msdu_head->len - trim); skb_trim(msdu, msdu->len - trim);
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx frag mpdu: ", ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx frag mpdu: ",
msdu_head->data, msdu_head->len); msdu->data, msdu->len);
ath10k_process_rx(htt->ar, rx_status, msdu_head); ath10k_process_rx(htt->ar, rx_status, msdu);
end: end:
if (fw_desc_len > 0) { if (fw_desc_len > 0) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册