Commit 1381eb5c authored by Johannes Berg's avatar Johannes Berg Committed by Luca Coelho
Browse files

iwlwifi: correct HE capabilities



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: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20210617100544.e8d0b02ec86b.Ia6ef8cc0480d38af25e6ac45fad9fb15bdfcbc2c@changeid


Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent b26d4996
Loading
Loading
Loading
Loading
+66 −48
Original line number Diff line number Diff line
// 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++)
		iwl_nvm_fixup_sband_iftd(trans, sband, &iftype_data[i],
					 tx_chains, rx_chains);

		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;
		}
	}
	iwl_init_he_6ghz_capa(trans, data, sband, tx_chains, rx_chains);
}