OSDN Git Service

ath11k: calculate the correct NSS of peer for HE capabilities
authorWen Gong <quic_wgong@quicinc.com>
Mon, 22 Nov 2021 11:13:57 +0000 (13:13 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 22 Nov 2021 14:33:10 +0000 (16:33 +0200)
When connected to 6G mode AP, it does not have VHT/HT capabilities,
so the NSS is not set, then it is 1 by default.

This patch is to calculate the NSS with supported HE-MCS and NSS set
of HE capabilities.

Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01280-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1

Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20211118095453.8030-1-quic_wgong@quicinc.com
drivers/net/wireless/ath/ath11k/mac.c

index 292b2b7..b85e9cf 100644 (file)
@@ -1920,7 +1920,6 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
        struct ath11k_vif *arvif = (void *)vif->drv_priv;
        struct cfg80211_chan_def def;
        const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
-       u8 ampdu_factor;
        enum nl80211_band band;
        u16 *he_mcs_mask;
        u8 max_nss, he_mcs;
@@ -1928,6 +1927,9 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
        int i, he_nss, nss_idx;
        bool user_rate_valid = true;
        u32 rx_nss, tx_nss, nss_160;
+       u8 ampdu_factor, rx_mcs_80, rx_mcs_160;
+       u16 mcs_160_map, mcs_80_map;
+       bool support_160;
 
        if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
                return;
@@ -1942,6 +1944,39 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
                return;
 
        arg->he_flag = true;
+       support_160 = !!(he_cap->he_cap_elem.phy_cap_info[0] &
+                 IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G);
+
+       /* Supported HE-MCS and NSS Set of peer he_cap is intersection with self he_cp */
+       mcs_160_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
+       mcs_80_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
+
+       if (support_160) {
+               for (i = 7; i >= 0; i--) {
+                       u8 mcs_160 = (mcs_160_map >> (2 * i)) & 3;
+
+                       if (mcs_160 != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
+                               rx_mcs_160 = i + 1;
+                               break;
+                       }
+               }
+       }
+
+       for (i = 7; i >= 0; i--) {
+               u8 mcs_80 = (mcs_80_map >> (2 * i)) & 3;
+
+               if (mcs_80 != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
+                       rx_mcs_80 = i + 1;
+                       break;
+               }
+       }
+
+       if (support_160)
+               max_nss = min(rx_mcs_80, rx_mcs_160);
+       else
+               max_nss = rx_mcs_80;
+
+       arg->peer_nss = min(sta->rx_nss, max_nss);
 
        memcpy_and_pad(&arg->peer_he_cap_macinfo,
                       sizeof(arg->peer_he_cap_macinfo),