ath10k: fix Native Wifi decap mode RX
authorMichal Kazior <michal.kazior@tieto.com>
Thu, 26 Sep 2013 07:12:23 +0000 (10:12 +0300)
committerKalle Valo <kvalo@qca.qualcomm.com>
Thu, 26 Sep 2013 07:12:23 +0000 (10:12 +0300)
NWifi decap mode always reports 802.11 Data
Frames, even when QoS Data Frames are actually
received.

This made mac80211 not report frame priority
properly (since there was no QoS Control field).

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath10k/htt_rx.c

index cdb4e6da7cc25c14c28051ff82d8f6e4869cc9bc..c4637f18734fc51f6e9938421c00e050680c0b84 100644 (file)
@@ -618,7 +618,7 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
        enum rx_msdu_decap_format fmt;
        enum htt_rx_mpdu_encrypt_type enctype;
        struct ieee80211_hdr *hdr;
-       u8 hdr_buf[64];
+       u8 hdr_buf[64], addr[ETH_ALEN], *qos;
        unsigned int hdr_len;
 
        rxd = (void *)skb->data - sizeof(*rxd);
@@ -673,7 +673,25 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
                        skb_trim(skb, skb->len - FCS_LEN);
                        break;
                case RX_MSDU_DECAP_NATIVE_WIFI:
-                       /* nothing to do */
+                       /* pull decapped header and copy DA */
+                       hdr = (struct ieee80211_hdr *)skb->data;
+                       hdr_len = ieee80211_hdrlen(hdr->frame_control);
+                       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);
+
+                       /* 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;
+
+                       /* 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
@@ -739,7 +757,15 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt, struct htt_rx_info *info)
                skb_trim(skb, skb->len - FCS_LEN);
                break;
        case RX_MSDU_DECAP_NATIVE_WIFI:
-               /* nothing to do here */
+               /* Pull decapped header */
+               hdr = (struct ieee80211_hdr *)skb->data;
+               hdr_len = ieee80211_hdrlen(hdr->frame_control);
+               skb_pull(skb, hdr_len);
+
+               /* Push original header */
+               hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status;
+               hdr_len = ieee80211_hdrlen(hdr->frame_control);
+               memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
                break;
        case RX_MSDU_DECAP_ETHERNET2_DIX:
                /* strip ethernet header and insert decapped 802.11 header and