[RFT/RFC 1/5] ath10k: amsdu rx, buid one big frame
Janusz Dziedzic
janusz.dziedzic at tieto.com
Thu Jul 10 04:45:10 PDT 2014
Temporary patch, to check if will solve ampdu reordering issue.
Signed-off-by: Janusz Dziedzic <janusz.dziedzic at tieto.com>
---
drivers/net/wireless/ath/ath10k/htt_rx.c | 71 +++++++++++++++++++++---------
1 file changed, 50 insertions(+), 21 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 57d5a97..2a0526b 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -874,12 +874,15 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
{
struct htt_rx_desc *rxd;
struct sk_buff *skb = skb_in;
- struct sk_buff *first;
+ struct sk_buff *first, *frame = NULL, *tmp;
enum rx_msdu_decap_format fmt;
enum htt_rx_mpdu_encrypt_type enctype;
struct ieee80211_hdr *hdr;
- u8 hdr_buf[64], addr[ETH_ALEN], *qos;
+ u8 hdr_buf[64], addr[ETH_ALEN];
unsigned int hdr_len;
+ struct amsdu_subframe_hdr subframe_hdr;
+ unsigned int size = 0;
+ u8 padding;
rxd = (void *)skb->data - sizeof(*rxd);
enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
@@ -890,6 +893,21 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
memcpy(hdr_buf, hdr, hdr_len);
hdr = (struct ieee80211_hdr *)hdr_buf;
+ /* Check size we will need */
+ tmp = skb_in;
+ while (tmp) {
+ size = size + tmp->len;
+ tmp = tmp->next;
+ }
+
+ frame = dev_alloc_skb(size + skb_headroom(skb_in));
+ if (!frame) {
+ dev_kfree_skb_any(skb_in);
+ return;
+ }
+
+ skb_reserve(frame, skb_headroom(skb_in));
+
first = skb;
while (skb) {
void *decap_hdr;
@@ -922,19 +940,28 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
memcpy(addr, ieee80211_get_DA(hdr), ETH_ALEN);
skb_pull(skb, hdr_len);
- /* push original 802.11 header */
- hdr = (struct ieee80211_hdr *)hdr_buf;
- hdr_len = ieee80211_hdrlen(hdr->frame_control);
- memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
+ /* cfg80211 expect this padding */
+ padding = (4 - (skb->len + sizeof(subframe_hdr))) & 0x3;
+ skb_put(skb, padding);
- /* original A-MSDU header has the bit set but we're
- * not including A-MSDU subframe header */
- hdr = (struct ieee80211_hdr *)skb->data;
- qos = ieee80211_get_qos_ctl(hdr);
- qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
+ /* build amsdu subframe header */
+ memcpy(&subframe_hdr.dst, addr, ETH_ALEN);
+ memcpy(&subframe_hdr.src, ieee80211_get_SA(hdr), ETH_ALEN);
+ subframe_hdr.len = __cpu_to_be16(skb->len) ;
- /* original 802.11 header has a different DA */
- memcpy(ieee80211_get_DA(hdr), addr, ETH_ALEN);
+ /* push back amsdu hdr */
+ memcpy(skb_push(skb, sizeof(subframe_hdr)), &subframe_hdr,
+ sizeof(subframe_hdr));
+
+ if (skb == first) {
+ /* push back orginal 80211 header */
+ hdr = (struct ieee80211_hdr *)hdr_buf;
+ hdr_len = ieee80211_hdrlen(hdr->frame_control);
+ memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
+
+ /* original 802.11 header has a different DA */
+ memcpy(ieee80211_get_DA(hdr), addr, ETH_ALEN);
+ }
break;
case RX_MSDU_DECAP_ETHERNET2_DIX:
/* strip ethernet header and insert decapped 802.11
@@ -956,19 +983,21 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
}
skb_in = skb;
- ath10k_htt_rx_h_protected(htt, rx_status, skb_in, enctype, fmt,
- false);
+
+ if (skb_in == first)
+ ath10k_htt_rx_h_protected(htt, rx_status, skb_in,
+ enctype, fmt, false);
+
+ memcpy(skb_put(frame, skb_in->len), skb_in->data, skb_in->len);
+
skb = skb->next;
skb_in->next = NULL;
- if (skb)
- rx_status->flag |= RX_FLAG_AMSDU_MORE;
- else
- rx_status->flag &= ~RX_FLAG_AMSDU_MORE;
-
- ath10k_process_rx(htt->ar, rx_status, skb_in);
+ /* We don't need this skb anymore */
+ dev_kfree_skb(skb_in);
}
+ ath10k_process_rx(htt->ar, rx_status, frame);
/* FIXME: It might be nice to re-assemble the A-MSDU when there's a
* monitor interface active for sniffing purposes. */
}
--
1.7.9.5
More information about the ath10k
mailing list