From: Avinash Bhatt Date: Sat, 21 Mar 2026 17:29:18 +0000 (+0200) Subject: wifi: iwlwifi: mld: block EMLSR during TDLS connections X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4d56037a02bd;p=thirdparty%2Fkernel%2Flinux.git wifi: iwlwifi: mld: block EMLSR during TDLS connections TDLS (Tunneled Direct Link Setup) requires single-link operation for direct peer-to-peer communication, which is incompatible with EMLSR (Enhanced Multi-Link Single Radio) mode where the radio switches between multiple links. Block EMLSR when the first TDLS peer is added and unblock when the last TDLS peer is removed. The block/unblock APIs handle exiting EMLSR and triggering link selection automatically. Signed-off-by: Avinash Bhatt Reviewed-by: Emmanuel Grumbach Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20260321192637.c1376b0259dd.I016587eb1570f7a7a64c0c95e0636e955a640350@changeid --- diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.h b/drivers/net/wireless/intel/iwlwifi/mld/iface.h index 3e106c93f0db6..0857ae28be8e2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/iface.h +++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.h @@ -33,6 +33,7 @@ enum iwl_mld_cca_40mhz_wa_status { * 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. + * @IWL_MLD_EMLSR_BLOCKED_TDLS: TDLS connection is preventing EMLSR. */ enum iwl_mld_emlsr_blocked { IWL_MLD_EMLSR_BLOCKED_PREVENTION = 0x1, @@ -42,6 +43,7 @@ enum iwl_mld_emlsr_blocked { IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS = 0x10, IWL_MLD_EMLSR_BLOCKED_TPT = 0x20, IWL_MLD_EMLSR_BLOCKED_NAN = 0x40, + IWL_MLD_EMLSR_BLOCKED_TDLS = 0x80, }; /** diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c index 9dec981a2bc59..e3aec814aa0df 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c @@ -1759,10 +1759,19 @@ static int iwl_mld_move_sta_state_up(struct iwl_mld *mld, if (ret) return ret; - /* just added first TDLS STA, so disable PM */ - if (sta->tdls && tdls_count == 0) + /* just added first TDLS STA, so disable PM and block EMLSR */ + if (sta->tdls && tdls_count == 0) { iwl_mld_update_mac_power(mld, vif, false); + /* TDLS requires single-link operation with + * direct peer communication. + * Block and exit EMLSR when TDLS is established. + */ + iwl_mld_block_emlsr(mld, vif, + IWL_MLD_EMLSR_BLOCKED_TDLS, + iwl_mld_get_primary_link(vif)); + } + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) mld_vif->ap_sta = sta; @@ -1898,8 +1907,14 @@ static int iwl_mld_move_sta_state_down(struct iwl_mld *mld, iwl_mld_remove_sta(mld, sta); if (sta->tdls && iwl_mld_tdls_sta_count(mld) == 0) { - /* just removed last TDLS STA, so enable PM */ + /* just removed last TDLS STA, so enable PM + * and unblock EMLSR + */ iwl_mld_update_mac_power(mld, vif, false); + + /* Unblock EMLSR when TDLS connection is torn down */ + iwl_mld_unblock_emlsr(mld, vif, + IWL_MLD_EMLSR_BLOCKED_TDLS); } } else { return -EINVAL; diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c index f693f92e42b4c..9362e02d9e769 100644 --- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c +++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c @@ -13,7 +13,8 @@ HOW(NON_BSS) \ HOW(TMP_NON_BSS) \ HOW(TPT) \ - HOW(NAN) + HOW(NAN) \ + HOW(TDLS) static const char * iwl_mld_get_emlsr_blocked_string(enum iwl_mld_emlsr_blocked blocked)