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: Ben Greear <greearb@candelatech.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
parent
69244e5656
commit
bfa353689a
1 changed files with 54 additions and 5 deletions
|
@ -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,
|
||||||
|
|
||||||
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)
|
||||||
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,
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue