]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: iwlwifi: mld: block EMLSR during TDLS connections
authorAvinash Bhatt <avinash.bhatt@intel.com>
Sat, 21 Mar 2026 17:29:18 +0000 (19:29 +0200)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Wed, 25 Mar 2026 09:31:58 +0000 (11:31 +0200)
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 <avinash.bhatt@intel.com>
Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20260321192637.c1376b0259dd.I016587eb1570f7a7a64c0c95e0636e955a640350@changeid
drivers/net/wireless/intel/iwlwifi/mld/iface.h
drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
drivers/net/wireless/intel/iwlwifi/mld/mlo.c

index 3e106c93f0db68af5a53285eff621175a58ad3e9..0857ae28be8e23776ab8d4a0a78cbf06e07d19fb 100644 (file)
@@ -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,
 };
 
 /**
index 9dec981a2bc59abf6fc5d72a3dc2dfb649524741..e3aec814aa0dfc4108918fd08c9f0a5cba14ca79 100644 (file)
@@ -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;
index f693f92e42b4c651ac1827ecaab251bb8b1a7f57..9362e02d9e769ade58fd2e3ad4345a6cd4959fa2 100644 (file)
@@ -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)