Search Linux Wireless

[PATCH wireless-next 07/15] wifi: iwlwifi: mld: allow EMLSR for unequal bandwidth

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@xxxxxxxxx>
---
 .../net/wireless/intel/iwlwifi/mld/iface.h    | 15 ++---
 .../wireless/intel/iwlwifi/mld/low_latency.c  |  4 ++
 .../net/wireless/intel/iwlwifi/mld/mac80211.c | 10 +--
 drivers/net/wireless/intel/iwlwifi/mld/mlo.c  | 63 +++++++++++--------
 drivers/net/wireless/intel/iwlwifi/mld/mlo.h  |  4 --
 5 files changed, 49 insertions(+), 47 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/iface.h b/drivers/net/wireless/intel/iwlwifi/mld/iface.h
index 550ae3c9d766..d1d56b081bf6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/iface.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/iface.h
@@ -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,
 };
 
 /**
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/low_latency.c b/drivers/net/wireless/intel/iwlwifi/mld/low_latency.c
index e74e66735f52..a4a612afb3b3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/low_latency.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/low_latency.c
@@ -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)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
index f6623988fff6..938cf5900a29 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
@@ -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,
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
index 8f6da90bf82c..9342f03c0908 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
@@ -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
 	}
 }
 
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.h b/drivers/net/wireless/intel/iwlwifi/mld/mlo.h
index a5fbe1919c6d..6c652c17069f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.h
@@ -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,
-- 
2.34.1





[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux