From: Johannes Berg <johannes.berg@xxxxxxxxx> Due to the iwl_mld_get_chandef_from_chanctx() logic, even after the OMI handshake to reduce bandwidth the driver wouldn't apply that to the PHY context, since it always uses the normal, not the reduced, configuration on 6 GHz (not strictly always, but OMI will only apply if the original bandwidth is > 80 MHz.) Fix this by making that selection contingent on AP mode. Refactor the code a bit to also make it clearer why the min_def isn't used in that case (for FILS.) Signed-off-by: Johannes Berg <johannes.berg@xxxxxxxxx> Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@xxxxxxxxx> --- drivers/net/wireless/intel/iwlwifi/mld/link.c | 2 +- .../net/wireless/intel/iwlwifi/mld/mac80211.c | 4 +- drivers/net/wireless/intel/iwlwifi/mld/phy.c | 49 +++++++++++++++++-- drivers/net/wireless/intel/iwlwifi/mld/phy.h | 3 +- .../wireless/intel/iwlwifi/mld/tests/utils.c | 2 +- 5 files changed, 50 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c index f6d482817f1b..1db69aee4e9f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c @@ -67,7 +67,7 @@ static void iwl_mld_fill_rates(struct iwl_mld *mld, __le32 *cck_rates, __le32 *ofdm_rates) { struct cfg80211_chan_def *chandef = - iwl_mld_get_chandef_from_chanctx(chan_ctx); + iwl_mld_get_chandef_from_chanctx(mld, chan_ctx); struct ieee80211_supported_band *sband = mld->hw->wiphy->bands[chandef->chan->band]; unsigned long basic = link->basic_rates; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c index 27ef41d69479..91e201fde72a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c @@ -840,7 +840,7 @@ int iwl_mld_add_chanctx(struct ieee80211_hw *hw, phy->mld = mld; phy->fw_id = fw_id; - phy->chandef = *iwl_mld_get_chandef_from_chanctx(ctx); + phy->chandef = *iwl_mld_get_chandef_from_chanctx(mld, ctx); ret = iwl_mld_phy_fw_action(mld, ctx, FW_CTXT_ACTION_ADD); if (ret) { @@ -872,7 +872,7 @@ void iwl_mld_change_chanctx(struct ieee80211_hw *hw, struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw); struct iwl_mld_phy *phy = iwl_mld_phy_from_mac80211(ctx); struct cfg80211_chan_def *chandef = - iwl_mld_get_chandef_from_chanctx(ctx); + iwl_mld_get_chandef_from_chanctx(mld, ctx); /* We don't care about these */ if (!(changed & ~(IEEE80211_CHANCTX_CHANGE_RX_CHAINS | diff --git a/drivers/net/wireless/intel/iwlwifi/mld/phy.c b/drivers/net/wireless/intel/iwlwifi/mld/phy.c index c38f101628de..2fbc8090088b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/phy.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/phy.c @@ -22,16 +22,55 @@ int iwl_mld_allocate_fw_phy_id(struct iwl_mld *mld) } EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_allocate_fw_phy_id); -struct cfg80211_chan_def * -iwl_mld_get_chandef_from_chanctx(struct ieee80211_chanctx_conf *ctx) +struct iwl_mld_chanctx_usage_data { + struct iwl_mld *mld; + struct ieee80211_chanctx_conf *ctx; + bool use_def; +}; + +static bool iwl_mld_chanctx_fils_enabled(struct ieee80211_vif *vif, + struct ieee80211_chanctx_conf *ctx) { - bool use_def = cfg80211_channel_is_psc(ctx->def.chan) || + if (vif->type != NL80211_IFTYPE_AP) + return false; + + return cfg80211_channel_is_psc(ctx->def.chan) || (ctx->def.chan->band == NL80211_BAND_6GHZ && ctx->def.width >= NL80211_CHAN_WIDTH_80); +} + +static void iwl_mld_chanctx_usage_iter(void *_data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct iwl_mld_chanctx_usage_data *data = _data; + struct ieee80211_bss_conf *link_conf; + int link_id; + + for_each_vif_active_link(vif, link_conf, link_id) { + if (rcu_access_pointer(link_conf->chanctx_conf) != data->ctx) + continue; + + if (iwl_mld_chanctx_fils_enabled(vif, data->ctx)) + data->use_def = true; + } +} + +struct cfg80211_chan_def * +iwl_mld_get_chandef_from_chanctx(struct iwl_mld *mld, + struct ieee80211_chanctx_conf *ctx) +{ + struct iwl_mld_chanctx_usage_data data = { + .mld = mld, + .ctx = ctx, + }; + + ieee80211_iterate_active_interfaces_mtx(mld->hw, + IEEE80211_IFACE_ITER_NORMAL, + iwl_mld_chanctx_usage_iter, + &data); - return use_def ? &ctx->def : &ctx->min_def; + return data.use_def ? &ctx->def : &ctx->min_def; } -EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_get_chandef_from_chanctx); static u8 iwl_mld_nl80211_width_to_fw(enum nl80211_chan_width width) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/phy.h b/drivers/net/wireless/intel/iwlwifi/mld/phy.h index 357bc9fe9624..2212a89321b7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/phy.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/phy.h @@ -48,7 +48,8 @@ int iwl_mld_allocate_fw_phy_id(struct iwl_mld *mld); int iwl_mld_phy_fw_action(struct iwl_mld *mld, struct ieee80211_chanctx_conf *ctx, u32 action); struct cfg80211_chan_def * -iwl_mld_get_chandef_from_chanctx(struct ieee80211_chanctx_conf *ctx); +iwl_mld_get_chandef_from_chanctx(struct iwl_mld *mld, + struct ieee80211_chanctx_conf *ctx); u8 iwl_mld_get_fw_ctrl_pos(const struct cfg80211_chan_def *chandef); #endif /* __iwl_mld_phy_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c b/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c index b6049918b5db..6331cd91cdf6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c @@ -169,7 +169,7 @@ iwlmld_kunit_add_chanctx_from_def(struct cfg80211_chan_def *def) phy->fw_id = fw_id; phy->mld = mld; - phy->chandef = *iwl_mld_get_chandef_from_chanctx(ctx); + phy->chandef = *def; return ctx; } -- 2.34.1