Commit bfa35368 authored by Ben Greear's avatar Ben Greear Committed by Kalle Valo

ath10k: support msdu chaining

Consolidate the list of msdu skbs into the msdu-head skb, delete the
rest of the skbs, pass the msdu-head skb on up the stack as normal.

Tested with high-speed TCP and UDP traffic on modified firmware that
supports raw-rx.
Signed-off-by: default avatarBen Greear <greearb@candelatech.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 69244e56
...@@ -398,6 +398,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -398,6 +398,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
msdu_len = MS(__le32_to_cpu(rx_desc->msdu_start.info0), msdu_len = MS(__le32_to_cpu(rx_desc->msdu_start.info0),
RX_MSDU_START_INFO0_MSDU_LENGTH); RX_MSDU_START_INFO0_MSDU_LENGTH);
msdu_chained = rx_desc->frag_info.ring2_more_count; msdu_chained = rx_desc->frag_info.ring2_more_count;
msdu_chaining = msdu_chained;
if (msdu_len_invalid) if (msdu_len_invalid)
msdu_len = 0; msdu_len = 0;
...@@ -425,7 +426,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -425,7 +426,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
msdu->next = next; msdu->next = next;
msdu = next; msdu = next;
msdu_chaining = 1;
} }
last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) & last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) &
...@@ -901,6 +901,57 @@ static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb) ...@@ -901,6 +901,57 @@ 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)
{
struct sk_buff *next = msdu_head->next;
struct sk_buff *to_free = next;
int space;
int total_len = 0;
/* TODO: Might could optimize this by using
* skb_try_coalesce or similar method to
* decrease copying, or maybe get mac80211 to
* provide a way to just receive a list of
* skb?
*/
msdu_head->next = NULL;
/* Allocate total length all at once. */
while (next) {
total_len += next->len;
next = next->next;
}
space = total_len - skb_tailroom(msdu_head);
if ((space > 0) &&
(pskb_expand_head(msdu_head, 0, space, GFP_ATOMIC) < 0)) {
/* TODO: bump some rx-oom error stat */
/* put it back together so we can free the
* whole list at once.
*/
msdu_head->next = to_free;
return -1;
}
/* Walk list again, copying contents into
* msdu_head
*/
next = to_free;
while (next) {
skb_copy_from_linear_data(next, skb_put(msdu_head, next->len),
next->len);
next = next->next;
}
/* If here, we have consolidated skb. Free the
* fragments and pass the main skb on up the
* stack.
*/
ath10k_htt_rx_free_msdu_chain(to_free);
return 0;
}
static void ath10k_htt_rx_handler(struct ath10k_htt *htt, static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
struct htt_rx_indication *rx) struct htt_rx_indication *rx)
{ {
...@@ -991,10 +1042,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, ...@@ -991,10 +1042,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
continue; continue;
} }
/* FIXME: we do not support chaining yet. if (msdu_chaining &&
* this needs investigation */ (ath10k_unchain_msdu(msdu_head) < 0)) {
if (msdu_chaining) {
ath10k_warn("htt rx msdu_chaining is true\n");
ath10k_htt_rx_free_msdu_chain(msdu_head); ath10k_htt_rx_free_msdu_chain(msdu_head);
continue; continue;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment