iwlwifi: correct HE capabilities
authorJohannes Berg <johannes.berg@intel.com>
Thu, 17 Jun 2021 07:08:47 +0000 (10:08 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Tue, 22 Jun 2021 12:11:41 +0000 (15:11 +0300)
The (default) HE capabilities for our devices weren't handled
correctly, adjust them to match the correct capabilities of
the devices.

Since the device regulatory will not allow 160 MHz on 5 GHz,
don't advertise this capability by default; do it only if an
NVM file is being loaded that might change the regulatory
parameters.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20210617100544.e8d0b02ec86b.Ia6ef8cc0480d38af25e6ac45fad9fb15bdfcbc2c@changeid
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c

index fc75d04..bff6533 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2005-2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2021 Intel Corporation
  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
  * Copyright (C) 2016-2017 Intel Deutschland GmbH
  */
@@ -549,8 +549,7 @@ static const struct ieee80211_sband_iftype_data iwl_he_capa[] = {
                                .mac_cap_info[2] =
                                        IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP,
                                .mac_cap_info[3] =
-                                       IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
-                                       IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_2,
+                                       IEEE80211_HE_MAC_CAP3_OMI_CONTROL,
                                .mac_cap_info[4] =
                                        IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU |
                                        IEEE80211_HE_MAC_CAP4_MULTI_TID_AGG_TX_QOS_B39,
@@ -579,25 +578,20 @@ static const struct ieee80211_sband_iftype_data iwl_he_capa[] = {
                                        IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
                                        IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_8 |
                                        IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_8,
-                               .phy_cap_info[5] =
-                                       IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2 |
-                                       IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2,
                                .phy_cap_info[6] =
                                        IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB |
                                        IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB |
                                        IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT,
                                .phy_cap_info[7] =
                                        IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP |
-                                       IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI |
-                                       IEEE80211_HE_PHY_CAP7_MAX_NC_1,
+                                       IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI,
                                .phy_cap_info[8] =
                                        IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |
                                        IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
                                        IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
                                        IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU |
-                                       IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_2x996,
+                                       IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242,
                                .phy_cap_info[9] =
-                                       IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |
                                        IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
                                        IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB |
                                        IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_RESERVED,
@@ -632,19 +626,11 @@ static const struct ieee80211_sband_iftype_data iwl_he_capa[] = {
                                .mac_cap_info[1] =
                                        IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US |
                                        IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8,
-                               .mac_cap_info[2] =
-                                       IEEE80211_HE_MAC_CAP2_BSR,
                                .mac_cap_info[3] =
-                                       IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
-                                       IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_2,
-                               .mac_cap_info[4] =
-                                       IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU,
-                               .mac_cap_info[5] =
-                                       IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU,
+                                       IEEE80211_HE_MAC_CAP3_OMI_CONTROL,
                                .phy_cap_info[0] =
                                        IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
-                                       IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
-                                       IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G,
+                                       IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G,
                                .phy_cap_info[1] =
                                        IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD,
                                .phy_cap_info[2] =
@@ -654,27 +640,14 @@ static const struct ieee80211_sband_iftype_data iwl_he_capa[] = {
                                        IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_1 |
                                        IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_NO_DCM |
                                        IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1,
-                               .phy_cap_info[4] =
-                                       IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
-                                       IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_8 |
-                                       IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_8,
-                               .phy_cap_info[5] =
-                                       IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2 |
-                                       IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2,
                                .phy_cap_info[6] =
                                        IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT,
                                .phy_cap_info[7] =
-                                       IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI |
-                                       IEEE80211_HE_PHY_CAP7_MAX_NC_1,
+                                       IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI,
                                .phy_cap_info[8] =
                                        IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI |
-                                       IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
-                                       IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
-                                       IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU |
-                                       IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_2x996,
+                                       IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242,
                                .phy_cap_info[9] =
-                                       IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
-                                       IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB |
                                        IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_RESERVED,
                        },
                        /*
@@ -745,12 +718,66 @@ static void iwl_init_he_6ghz_capa(struct iwl_trans *trans,
                iftype_data[i].he_6ghz_capa.capa = cpu_to_le16(he_6ghz_capa);
 }
 
+static void
+iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
+                        struct ieee80211_supported_band *sband,
+                        struct ieee80211_sband_iftype_data *iftype_data,
+                        u8 tx_chains, u8 rx_chains)
+{
+       bool is_ap = iftype_data->types_mask & BIT(NL80211_IFTYPE_AP);
+
+       /* Advertise an A-MPDU exponent extension based on
+        * operating band
+        */
+       if (sband->band != NL80211_BAND_2GHZ)
+               iftype_data->he_cap.he_cap_elem.mac_cap_info[3] |=
+                       IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_1;
+       else
+               iftype_data->he_cap.he_cap_elem.mac_cap_info[3] |=
+                       IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3;
+
+       if (is_ap && iwlwifi_mod_params.nvm_file)
+               iftype_data->he_cap.he_cap_elem.phy_cap_info[0] |=
+                       IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
+
+       if ((tx_chains & rx_chains) == ANT_AB) {
+               iftype_data->he_cap.he_cap_elem.phy_cap_info[5] |=
+                       IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2 |
+                       IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2;
+               if (!is_ap)
+                       iftype_data->he_cap.he_cap_elem.phy_cap_info[7] |=
+                               IEEE80211_HE_PHY_CAP7_MAX_NC_2;
+       } else if (!is_ap) {
+               /* If not 2x2, we need to indicate 1x1 in the
+                * Midamble RX Max NSTS - but not for AP mode
+                */
+               iftype_data->he_cap.he_cap_elem.phy_cap_info[1] &=
+                       ~IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS;
+               iftype_data->he_cap.he_cap_elem.phy_cap_info[2] &=
+                       ~IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS;
+               iftype_data->he_cap.he_cap_elem.phy_cap_info[7] |=
+                       IEEE80211_HE_PHY_CAP7_MAX_NC_1;
+       }
+
+       switch (CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
+       case IWL_CFG_RF_TYPE_GF:
+       case IWL_CFG_RF_TYPE_MR:
+               iftype_data->he_cap.he_cap_elem.phy_cap_info[9] |=
+                       IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
+               if (!is_ap)
+                       iftype_data->he_cap.he_cap_elem.phy_cap_info[9] |=
+                               IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
+               break;
+       }
+}
+
 static void iwl_init_he_hw_capab(struct iwl_trans *trans,
                                 struct iwl_nvm_data *data,
                                 struct ieee80211_supported_band *sband,
                                 u8 tx_chains, u8 rx_chains)
 {
        struct ieee80211_sband_iftype_data *iftype_data;
+       int i;
 
        /* should only initialize once */
        if (WARN_ON(sband->iftype_data))
@@ -777,19 +804,10 @@ static void iwl_init_he_hw_capab(struct iwl_trans *trans,
        sband->iftype_data = iftype_data;
        sband->n_iftype_data = ARRAY_SIZE(iwl_he_capa);
 
-       /* If not 2x2, we need to indicate 1x1 in the Midamble RX Max NSTS */
-       if ((tx_chains & rx_chains) != ANT_AB) {
-               int i;
-
-               for (i = 0; i < sband->n_iftype_data; i++) {
-                       iftype_data[i].he_cap.he_cap_elem.phy_cap_info[1] &=
-                               ~IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS;
-                       iftype_data[i].he_cap.he_cap_elem.phy_cap_info[2] &=
-                               ~IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS;
-                       iftype_data[i].he_cap.he_cap_elem.phy_cap_info[7] &=
-                               ~IEEE80211_HE_PHY_CAP7_MAX_NC_MASK;
-               }
-       }
+       for (i = 0; i < sband->n_iftype_data; i++)
+               iwl_nvm_fixup_sband_iftd(trans, sband, &iftype_data[i],
+                                        tx_chains, rx_chains);
+
        iwl_init_he_6ghz_capa(trans, data, sband, tx_chains, rx_chains);
 }