ath10k: fix mu-mimo rx status reporting
authorMichal Kazior <michal.kazior@tieto.com>
Thu, 27 Aug 2015 12:47:33 +0000 (14:47 +0200)
committerKalle Valo <kvalo@qca.qualcomm.com>
Wed, 9 Sep 2015 09:30:13 +0000 (12:30 +0300)
MU-MIMO Rx involves different interpretation of
the VHT-SIG-A compared to SU-MIMO.

The incorrect interpretation led ath10k to report
VHT MCS values greater than 9 which subsequently
prompted mac80211 to drop such frames. This
effectively broke Rx with MU-MIMO in many cases
and manifested with a kernel warning in the log
which looked like this:

  [   14.552520] WARNING: CPU: 2 PID: 0 at net/mac80211/rx.c:3578 ieee80211_rx+0x26c/0x940 [mac80211]()
  [   14.552522] Rate marked as a VHT rate but data is invalid: MCS: 10, NSS: 2
  ... call trace follows ...

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 1b7a04366256febc8438e02a01eb979102cb1d39..8ba8fa9004cfc67fb3f68cfba9d859c45c2a923c 100644 (file)
@@ -643,6 +643,8 @@ struct amsdu_subframe_hdr {
        __be16 len;
 } __packed;
 
+#define GROUP_ID_IS_SU_MIMO(x) ((x) == 0 || (x) == 63)
+
 static void ath10k_htt_rx_h_rates(struct ath10k *ar,
                                  struct ieee80211_rx_status *status,
                                  struct htt_rx_desc *rxd)
@@ -650,6 +652,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
        struct ieee80211_supported_band *sband;
        u8 cck, rate, bw, sgi, mcs, nss;
        u8 preamble = 0;
+       u8 group_id;
        u32 info1, info2, info3;
 
        info1 = __le32_to_cpu(rxd->ppdu_start.info1);
@@ -692,10 +695,27 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
        case HTT_RX_VHT_WITH_TXBF:
                /* VHT-SIG-A1 in info2, VHT-SIG-A2 in info3
                   TODO check this */
-               mcs = (info3 >> 4) & 0x0F;
-               nss = ((info2 >> 10) & 0x07) + 1;
                bw = info2 & 3;
                sgi = info3 & 1;
+               group_id = (info2 >> 4) & 0x3F;
+
+               if (GROUP_ID_IS_SU_MIMO(group_id)) {
+                       mcs = (info3 >> 4) & 0x0F;
+                       nss = ((info2 >> 10) & 0x07) + 1;
+               } else {
+                       /* Hardware doesn't decode VHT-SIG-B into Rx descriptor
+                        * so it's impossible to decode MCS. Also since
+                        * firmware consumes Group Id Management frames host
+                        * has no knowledge regarding group/user position
+                        * mapping so it's impossible to pick the correct Nsts
+                        * from VHT-SIG-A1.
+                        *
+                        * Bandwidth and SGI are valid so report the rateinfo
+                        * on best-effort basis.
+                        */
+                       mcs = 0;
+                       nss = 1;
+               }
 
                status->rate_idx = mcs;
                status->vht_nss = nss;