]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/net/wireless/ath/ath10k/htt_rx.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide
[karo-tx-linux.git] / drivers / net / wireless / ath / ath10k / htt_rx.c
index 1b7a04366256febc8438e02a01eb979102cb1d39..6060dda4e9101ac73c92cafb597c1d71592bb00e 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,50 @@ 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;
+               }
+
+               if (mcs > 0x09) {
+                       ath10k_warn(ar, "invalid MCS received %u\n", mcs);
+                       ath10k_warn(ar, "rxd %08x mpdu start %08x %08x msdu start %08x %08x ppdu start %08x %08x %08x %08x %08x\n",
+                                   __le32_to_cpu(rxd->attention.flags),
+                                   __le32_to_cpu(rxd->mpdu_start.info0),
+                                   __le32_to_cpu(rxd->mpdu_start.info1),
+                                   __le32_to_cpu(rxd->msdu_start.common.info0),
+                                   __le32_to_cpu(rxd->msdu_start.common.info1),
+                                   rxd->ppdu_start.info0,
+                                   __le32_to_cpu(rxd->ppdu_start.info1),
+                                   __le32_to_cpu(rxd->ppdu_start.info2),
+                                   __le32_to_cpu(rxd->ppdu_start.info3),
+                                   __le32_to_cpu(rxd->ppdu_start.info4));
+
+                       ath10k_warn(ar, "msdu end %08x mpdu end %08x\n",
+                                   __le32_to_cpu(rxd->msdu_end.common.info0),
+                                   __le32_to_cpu(rxd->mpdu_end.info0));
+
+                       ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL,
+                                       "rx desc msdu payload: ",
+                                       rxd->msdu_payload, 50);
+               }
 
                status->rate_idx = mcs;
                status->vht_nss = nss;
@@ -2082,6 +2125,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
        /* Free the indication buffer */
        dev_kfree_skb_any(skb);
 }
+EXPORT_SYMBOL(ath10k_htt_t2h_msg_handler);
 
 static void ath10k_htt_txrx_compl_task(unsigned long ptr)
 {