wifi: iwlwifi: mld: allow EMLSR for unequal bandwidth
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>
Wed, 12 Mar 2025 22:22:30 +0000 (00:22 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 18 Mar 2025 08:51:25 +0000 (09:51 +0100)
Allow EMLSR if the bandwidths of the links are unequal if one of the
following conditions is true:
1. in low latency mode
2. bandwidth of the secondary link is greater than the bandwidth of the
   primary
3. the primary link is active and is loaded enough to justify EMLSR

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Link: https://patch.msgid.link/20250313002008.150c330711c4.Ifd72d2e076783991852a7f1756948b4f0efb9fea@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/mld/iface.h
drivers/net/wireless/intel/iwlwifi/mld/low_latency.c
drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
drivers/net/wireless/intel/iwlwifi/mld/mlo.c
drivers/net/wireless/intel/iwlwifi/mld/mlo.h

index 550ae3c..d1d56b0 100644 (file)
@@ -52,8 +52,6 @@ enum iwl_mld_emlsr_blocked {
  * @IWL_MLD_EMLSR_EXIT_FAIL_ENTRY: FW failed to enter EMLSR
  * @IWL_MLD_EMLSR_EXIT_CSA: EMLSR prevented due to channel switch on link
  * @IWL_MLD_EMLSR_EXIT_EQUAL_BAND: EMLSR prevented as both links share the band
- * @IWL_MLD_EMLSR_EXIT_BANDWIDTH: Bandwidths of primary and secondary links are
- *      not equal
  * @IWL_MLD_EMLSR_EXIT_LOW_RSSI: Link RSSI is unsuitable for EMLSR
  * @IWL_MLD_EMLSR_EXIT_LINK_USAGE: Exit EMLSR due to low TPT on secondary link
  * @IWL_MLD_EMLSR_EXIT_BT_COEX: Exit EMLSR due to BT coexistence
@@ -68,13 +66,12 @@ enum iwl_mld_emlsr_exit {
        IWL_MLD_EMLSR_EXIT_FAIL_ENTRY           = 0x4,
        IWL_MLD_EMLSR_EXIT_CSA                  = 0x8,
        IWL_MLD_EMLSR_EXIT_EQUAL_BAND           = 0x10,
-       IWL_MLD_EMLSR_EXIT_BANDWIDTH            = 0x20,
-       IWL_MLD_EMLSR_EXIT_LOW_RSSI             = 0x40,
-       IWL_MLD_EMLSR_EXIT_LINK_USAGE           = 0x80,
-       IWL_MLD_EMLSR_EXIT_BT_COEX              = 0x100,
-       IWL_MLD_EMLSR_EXIT_CHAN_LOAD            = 0x200,
-       IWL_MLD_EMLSR_EXIT_RFI                  = 0x400,
-       IWL_MLD_EMLSR_EXIT_FW_REQUEST           = 0x800,
+       IWL_MLD_EMLSR_EXIT_LOW_RSSI             = 0x20,
+       IWL_MLD_EMLSR_EXIT_LINK_USAGE           = 0x40,
+       IWL_MLD_EMLSR_EXIT_BT_COEX              = 0x80,
+       IWL_MLD_EMLSR_EXIT_CHAN_LOAD            = 0x100,
+       IWL_MLD_EMLSR_EXIT_RFI                  = 0x200,
+       IWL_MLD_EMLSR_EXIT_FW_REQUEST           = 0x400,
 };
 
 /**
index e74e667..a4a612a 100644 (file)
@@ -7,6 +7,7 @@
 #include "low_latency.h"
 #include "hcmd.h"
 #include "power.h"
+#include "mlo.h"
 
 #define MLD_LL_WK_INTERVAL_MSEC 500
 #define MLD_LL_PERIOD (HZ * MLD_LL_WK_INTERVAL_MSEC / 1000)
@@ -230,6 +231,9 @@ void iwl_mld_vif_update_low_latency(struct iwl_mld *mld,
                return;
 
        iwl_mld_update_mac_power(mld, vif, false);
+
+       if (low_latency)
+               iwl_mld_retry_emlsr(mld, vif);
 }
 
 static bool iwl_mld_is_vo_vi_pkt(struct ieee80211_hdr *hdr)
index f662398..938cf59 100644 (file)
@@ -1187,15 +1187,11 @@ iwl_mld_mac80211_link_info_changed_sta(struct iwl_mld *mld,
                bw = ieee80211_chan_width_to_rx_bw(link_conf->chanreq.oper.width);
 
                iwl_mld_omi_ap_changed_bw(mld, link_conf, bw);
-       }
 
-       if (changes & BSS_CHANGED_BANDWIDTH) {
-               if (iwl_mld_emlsr_active(vif))
-                       iwl_mld_emlsr_check_equal_bw(mld, vif, link_conf);
-               else
-                       /* Channel load threshold may have changed */
-                       iwl_mld_retry_emlsr(mld, vif);
        }
+
+       if (changes & BSS_CHANGED_BANDWIDTH)
+               iwl_mld_retry_emlsr(mld, vif);
 }
 
 static int iwl_mld_update_mu_groups(struct iwl_mld *mld,
index 8f6da90..9342f03 100644 (file)
@@ -47,7 +47,6 @@ static void iwl_mld_print_emlsr_blocked(struct iwl_mld *mld, u32 mask)
        HOW(FAIL_ENTRY)                 \
        HOW(CSA)                        \
        HOW(EQUAL_BAND)                 \
-       HOW(BANDWIDTH)                  \
        HOW(LOW_RSSI)                   \
        HOW(LINK_USAGE)                 \
        HOW(BT_COEX)                    \
@@ -748,6 +747,7 @@ iwl_mld_channel_load_allows_emlsr(struct iwl_mld *mld,
        struct iwl_mld_link *link_a =
                iwl_mld_link_dereference_check(mld_vif, a->link_id);
        struct ieee80211_chanctx_conf *chanctx_a = NULL;
+       u32 bw_a, bw_b, ratio;
        u32 primary_load_perc;
 
        if (!link_a || !link_a->active) {
@@ -765,7 +765,34 @@ iwl_mld_channel_load_allows_emlsr(struct iwl_mld *mld,
 
        IWL_DEBUG_EHT(mld, "Average channel load not by us: %u\n", primary_load_perc);
 
-       return primary_load_perc > iwl_mld_get_min_chan_load_thresh(chanctx_a);
+       if (primary_load_perc < iwl_mld_get_min_chan_load_thresh(chanctx_a)) {
+               IWL_DEBUG_EHT(mld, "Channel load is below the minimum threshold\n");
+               return false;
+       }
+
+       if (iwl_mld_vif_low_latency(mld_vif)) {
+               IWL_DEBUG_EHT(mld, "Low latency vif, EMLSR is allowed\n");
+               return true;
+       }
+
+       if (a->chandef->width <= b->chandef->width)
+               return true;
+
+       bw_a = nl80211_chan_width_to_mhz(a->chandef->width);
+       bw_b = nl80211_chan_width_to_mhz(b->chandef->width);
+       ratio = bw_a / bw_b;
+
+       switch (ratio) {
+       case 2:
+               return primary_load_perc > 25;
+       case 4:
+               return primary_load_perc > 40;
+       case 8:
+       case 16:
+               return primary_load_perc > 50;
+       }
+
+       return false;
 }
 
 static bool
@@ -784,12 +811,6 @@ iwl_mld_valid_emlsr_pair(struct ieee80211_vif *vif,
 
        if (a->chandef->chan->band == b->chandef->chan->band)
                reason_mask |= IWL_MLD_EMLSR_EXIT_EQUAL_BAND;
-       if (a->chandef->width != b->chandef->width) {
-               /* TODO: task=EMLSR task=statistics
-                * replace BANDWIDTH exit reason with channel load criteria
-                */
-               reason_mask |= IWL_MLD_EMLSR_EXIT_BANDWIDTH;
-       }
        if (!iwl_mld_channel_load_allows_emlsr(mld, vif, a, b))
                reason_mask |= IWL_MLD_EMLSR_EXIT_CHAN_LOAD;
 
@@ -941,23 +962,6 @@ void iwl_mld_select_links(struct iwl_mld *mld)
                                                NULL);
 }
 
-void iwl_mld_emlsr_check_equal_bw(struct iwl_mld *mld,
-                                 struct ieee80211_vif *vif,
-                                 struct ieee80211_bss_conf *link)
-{
-       u8 other_link_id = iwl_mld_get_other_link(vif, link->link_id);
-       struct ieee80211_bss_conf *other_link =
-               link_conf_dereference_check(vif, other_link_id);
-
-       if (!ieee80211_vif_link_active(vif, link->link_id) ||
-           WARN_ON(link->link_id == other_link_id || !other_link))
-               return;
-
-       if (link->chanreq.oper.width != other_link->chanreq.oper.width)
-               iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_BANDWIDTH,
-                                  iwl_mld_get_primary_link(vif));
-}
-
 static void iwl_mld_emlsr_check_bt_iter(void *_data, u8 *mac,
                                        struct ieee80211_vif *vif)
 {
@@ -1038,10 +1042,15 @@ static void iwl_mld_chan_load_update_iter(void *_data, u8 *mac,
        } else {
                u32 old_chan_load = data->prev_chan_load_not_by_us;
                u32 new_chan_load = phy->avg_channel_load_not_by_us;
-               u32 thresh = iwl_mld_get_min_chan_load_thresh(chanctx);
+               u32 min_thresh = iwl_mld_get_min_chan_load_thresh(chanctx);
+
+#define THRESHOLD_CROSSED(threshold) \
+       (old_chan_load <= (threshold) && new_chan_load > (threshold))
 
-               if (old_chan_load <= thresh && new_chan_load > thresh)
+               if (THRESHOLD_CROSSED(min_thresh) || THRESHOLD_CROSSED(25) ||
+                   THRESHOLD_CROSSED(40) || THRESHOLD_CROSSED(50))
                        iwl_mld_retry_emlsr(mld, vif);
+#undef THRESHOLD_CROSSED
        }
 }
 
index a5fbe19..6c652c1 100644 (file)
@@ -134,10 +134,6 @@ void iwl_mld_emlsr_unblock_tpt_wk(struct wiphy *wiphy, struct wiphy_work *wk);
 
 void iwl_mld_select_links(struct iwl_mld *mld);
 
-void iwl_mld_emlsr_check_equal_bw(struct iwl_mld *mld,
-                                 struct ieee80211_vif *vif,
-                                 struct ieee80211_bss_conf *link);
-
 void iwl_mld_emlsr_check_bt(struct iwl_mld *mld);
 
 void iwl_mld_emlsr_check_chan_load(struct ieee80211_hw *hw,