Copy the HT, VHT and HE capabilities from the sbands: - The HT capabilities from the 2.4 GHz sband (there is no difference between the bands anyway). - The VHT capabilities from the 5 GHz sband, obviously. - The HE capabilities from the 2.4 GHz and for NL80211_IFTYPE_STATION. Fix it up to include also the needed 5 GHz bits. For HE, there are bits that are band-dependent and iftype-dependent. For those set to what makes most sense, and leave a comment to re-visit. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit --- .../wireless/intel/iwlwifi/iwl-nvm-parse.c | 46 ++++++++++++++++++- .../wireless/intel/iwlwifi/iwl-nvm-utils.h | 8 +++- .../net/wireless/intel/iwlwifi/mld/mac80211.c | 6 ++- 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 2aa47c5fa7d4..0736c8c00d4e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2005-2014, 2018-2023, 2025 Intel Corporation + * Copyright (C) 2005-2014, 2018-2023, 2025-2026 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -1053,6 +1053,46 @@ static void iwl_init_he_hw_capab(struct iwl_trans *trans, iwl_init_he_6ghz_capa(trans, data, sband, tx_chains, rx_chains); } +static void +iwl_init_nan_phy_capa(const struct iwl_fw *fw, struct iwl_nvm_data *data) +{ + const struct ieee80211_sta_he_cap *he_cap; + + if (!fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_NAN_SYNC_SUPPORT)) + return; + + data->nan_phy_capa.ht = data->bands[NL80211_BAND_2GHZ].ht_cap; + data->nan_phy_capa.vht = data->bands[NL80211_BAND_5GHZ].vht_cap; + + he_cap = ieee80211_get_he_iftype_cap(&data->bands[NL80211_BAND_2GHZ], + NL80211_IFTYPE_STATION); + if (he_cap) { + data->nan_phy_capa.he = *he_cap; + data->nan_phy_capa.he.he_cap_elem.phy_cap_info[0] |= + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; + } + + /* + * FIXME: we copied HE capabilities from the 2.4 GHz band, + * but there are bits that are band-dependent: + * + * IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_1 - 2.4 GHz - set + * IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3 - 5 GHz - not set + * IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G - set + * IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G - set + * IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G - set + * + * We copied from STA iftype - so we have the following bits set: + * IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS + * IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS + * IEEE80211_HE_PHY_CAP7_MAX_NC_1 + * IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO + * + * Need to check which one should actually be set for NAN. + */ +} + void iwl_reinit_cab(struct iwl_trans *trans, struct iwl_nvm_data *data, u8 tx_chains, u8 rx_chains, const struct iwl_fw *fw) { @@ -1081,6 +1121,8 @@ void iwl_reinit_cab(struct iwl_trans *trans, struct iwl_nvm_data *data, if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax) iwl_init_he_hw_capab(trans, data, sband, tx_chains, rx_chains, fw); + + iwl_init_nan_phy_capa(fw, data); } IWL_EXPORT_SYMBOL(iwl_reinit_cab); @@ -2105,6 +2147,8 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, iwl_init_sbands(trans, nvm, channel_profile, tx_ant, rx_ant, sbands_flags, v4, fw); + iwl_init_nan_phy_capa(fw, nvm); + iwl_free_resp(&hcmd); return nvm; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-utils.h b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-utils.h index ac0a29a1c31f..e0c31f328a6c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-utils.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-utils.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2005-2014, 2018, 2020-2023 Intel Corporation + * Copyright (C) 2005-2014, 2018, 2020-2023, 2026 Intel Corporation * Copyright (C) 2015 Intel Mobile Communications GmbH */ #ifndef __iwl_eeprom_parse_h__ @@ -55,6 +55,12 @@ struct iwl_nvm_data { struct ieee80211_sband_iftype_data uhb[2]; } iftd; + struct { + struct ieee80211_sta_ht_cap ht; + struct ieee80211_sta_vht_cap vht; + struct ieee80211_sta_he_cap he; + } nan_phy_capa; + struct ieee80211_channel channels[]; }; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c index b48ebec18dd5..e66b304f345a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2024-2025 Intel Corporation + * Copyright (C) 2024-2026 Intel Corporation */ #include @@ -360,6 +360,10 @@ static void iwl_mac_hw_set_wiphy(struct iwl_mld *mld) hw->wiphy->nan_capa.dev_capabilities = NAN_DEV_CAPA_EXT_KEY_ID_SUPPORTED | NAN_DEV_CAPA_NDPE_SUPPORTED; + + hw->wiphy->nan_capa.phy.ht = mld->nvm_data->nan_phy_capa.ht; + hw->wiphy->nan_capa.phy.vht = mld->nvm_data->nan_phy_capa.vht; + hw->wiphy->nan_capa.phy.he = mld->nvm_data->nan_phy_capa.he; } else { wiphy->iface_combinations = iwl_mld_iface_combinations; /* Do not include NAN combinations */ -- 2.34.1