From 53d649ae79a760785d7f74ccf9830f3fe0e82380 Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Sun, 11 Jan 2026 19:39:16 +0200 Subject: [PATCH] wifi: iwlwifi: mld: prevent EMLSR when NAN is active EMLSR is not allowed when NAN is active. Block EMLSR when starting NAN, and unblock EMLSR when NAN is stopped. Reviewed-by: Ilan Peer Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20260111193638.8baef343023a.Ie94e5f32db003ebce33bde65e0ed8c6d98673b5a@changeid --- .../net/wireless/intel/iwlwifi/mld/iface.h | 2 ++ .../net/wireless/intel/iwlwifi/mld/mac80211.c | 3 +++ drivers/net/wireless/intel/iwlwifi/mld/mlo.c | 20 ++++++++++++++++--- drivers/net/wireless/intel/iwlwifi/mld/mlo.h | 5 +++++ drivers/net/wireless/intel/iwlwifi/mld/nan.c | 18 +++++++++++++++-- 5 files changed, 43 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.h b/drivers/net/wireless/intel/iwlwifi/mld/iface.h index a3573d20f214a..62fca166afd1e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/iface.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.h @@ -32,6 +32,7 @@ enum iwl_mld_cca_40mhz_wa_status { * link is preventing EMLSR. This is a temporary blocking that is set when * there is an indication that a non-BSS interface is to be added. * @IWL_MLD_EMLSR_BLOCKED_TPT: throughput is too low to make EMLSR worthwhile + * @IWL_MLD_EMLSR_BLOCKED_NAN: NAN is preventing EMLSR. */ enum iwl_mld_emlsr_blocked { IWL_MLD_EMLSR_BLOCKED_PREVENTION = 0x1, @@ -40,6 +41,7 @@ enum iwl_mld_emlsr_blocked { IWL_MLD_EMLSR_BLOCKED_NON_BSS = 0x8, IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS = 0x10, IWL_MLD_EMLSR_BLOCKED_TPT = 0x20, + IWL_MLD_EMLSR_BLOCKED_NAN = 0x40, }; /** diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c index 411a2d56e5f00..df8221277d51b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c @@ -1784,6 +1784,9 @@ static int iwl_mld_move_sta_state_up(struct iwl_mld *mld, /* Ensure any block due to a non-BSS link is synced */ iwl_mld_emlsr_check_non_bss_block(mld, 0); + /* Ensure NAN block is synced */ + iwl_mld_emlsr_check_nan_block(mld, vif); + /* Block EMLSR until a certain throughput it reached */ if (!mld->fw_status.in_hw_restart && IWL_MLD_ENTER_EMLSR_TPT_THRESH > 0) diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c index 87f67ddfced47..f842f5183223b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c @@ -12,7 +12,8 @@ HOW(ROC) \ HOW(NON_BSS) \ HOW(TMP_NON_BSS) \ - HOW(TPT) + HOW(TPT) \ + HOW(NAN) static const char * iwl_mld_get_emlsr_blocked_string(enum iwl_mld_emlsr_blocked blocked) @@ -478,8 +479,8 @@ iwl_mld_vif_iter_update_emlsr_block(void *_data, u8 *mac, } } -static int iwl_mld_update_emlsr_block(struct iwl_mld *mld, bool block, - enum iwl_mld_emlsr_blocked reason) +int iwl_mld_update_emlsr_block(struct iwl_mld *mld, bool block, + enum iwl_mld_emlsr_blocked reason) { struct iwl_mld_update_emlsr_block_data block_data = { .block = block, @@ -1210,3 +1211,16 @@ void iwl_mld_stop_ignoring_tpt_updates(struct iwl_mld *mld) iwl_mld_ignore_tpt_iter, &start); } + +int iwl_mld_emlsr_check_nan_block(struct iwl_mld *mld, struct ieee80211_vif *vif) +{ + if (mld->nan_device_vif && + ieee80211_vif_nan_started(mld->nan_device_vif)) + return iwl_mld_block_emlsr_sync(mld, vif, + IWL_MLD_EMLSR_BLOCKED_NAN, + iwl_mld_get_primary_link(vif)); + + iwl_mld_unblock_emlsr(mld, vif, IWL_MLD_EMLSR_BLOCKED_NAN); + + return 0; +} diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.h b/drivers/net/wireless/intel/iwlwifi/mld/mlo.h index d936589fe39dc..ccc3a7afa0955 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.h @@ -150,6 +150,11 @@ void iwl_mld_emlsr_check_chan_load(struct ieee80211_hw *hw, */ void iwl_mld_retry_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif); +int iwl_mld_emlsr_check_nan_block(struct iwl_mld *mld, struct ieee80211_vif *vif); + +int iwl_mld_update_emlsr_block(struct iwl_mld *mld, bool block, + enum iwl_mld_emlsr_blocked reason); + struct iwl_mld_link_sel_data { u8 link_id; const struct cfg80211_chan_def *chandef; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/nan.c b/drivers/net/wireless/intel/iwlwifi/mld/nan.c index e7a2c1ec7494b..d4298f44baf77 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/nan.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/nan.c @@ -5,6 +5,7 @@ #include "mld.h" #include "iface.h" +#include "mlo.h" #include "fw/api/mac-cfg.h" #define IWL_NAN_DISOVERY_BEACON_INTERNVAL_TU 512 @@ -130,15 +131,25 @@ int iwl_mld_start_nan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, IWL_DEBUG_MAC80211(mld, "NAN: start: bands=0x%x\n", conf->bands); - ret = iwl_mld_add_aux_sta(mld, aux_sta); + ret = iwl_mld_update_emlsr_block(mld, true, IWL_MLD_EMLSR_BLOCKED_NAN); if (ret) return ret; + ret = iwl_mld_add_aux_sta(mld, aux_sta); + if (ret) + goto unblock_emlsr; + ret = iwl_mld_nan_config(mld, vif, conf, FW_CTXT_ACTION_ADD); if (ret) { IWL_ERR(mld, "Failed to start NAN. ret=%d\n", ret); - iwl_mld_remove_aux_sta(mld, vif); + goto remove_aux; } + return 0; + +remove_aux: + iwl_mld_remove_aux_sta(mld, vif); +unblock_emlsr: + iwl_mld_update_emlsr_block(mld, false, IWL_MLD_EMLSR_BLOCKED_NAN); return ret; } @@ -190,6 +201,9 @@ int iwl_mld_stop_nan(struct ieee80211_hw *hw, iwl_mld_cancel_notifications_of_object(mld, IWL_MLD_OBJECT_TYPE_NAN, 0); + + iwl_mld_update_emlsr_block(mld, false, IWL_MLD_EMLSR_BLOCKED_NAN); + return 0; } -- 2.47.3