diff mbox series

[wireless-next,03/15] wifi: iwlwifi: mld: track channel_load_not_by_us

Message ID 20250308235203.dd443fc5b178.I68b2fed197aae14888159b7a73bf40c2f346f41f@changeid
State New
Headers show
Series wifi: iwlwifi: updates - 2025-03-08 | expand

Commit Message

Miri Korenblit March 8, 2025, 10:01 p.m. UTC
For each channel context, track the avarage channel load by others in the
driver specific phy data, to be used by EMLSR.
Due to FW limitations, this value is incorrect in EMLSR, so it is
shouldn't be used in EMLSR.
On EMLSR exit, clear it so the wrong value won't be used.

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
 .../net/wireless/intel/iwlwifi/mld/mac80211.c |  1 +
 drivers/net/wireless/intel/iwlwifi/mld/mlo.c  | 21 +++++++++++++++++++
 drivers/net/wireless/intel/iwlwifi/mld/phy.h  |  5 +++++
 .../net/wireless/intel/iwlwifi/mld/stats.c    | 10 ++++++++-
 .../wireless/intel/iwlwifi/mld/tests/utils.c  |  1 +
 5 files changed, 37 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
index ba149581e25d..b01a41f9b013 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
@@ -847,6 +847,7 @@  int iwl_mld_add_chanctx(struct ieee80211_hw *hw,
 	if (fw_id < 0)
 		return fw_id;
 
+	phy->mld = mld;
 	phy->fw_id = fw_id;
 	phy->chandef = *iwl_mld_get_chandef_from_chanctx(ctx);
 
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
index 99c8501129b8..b68092be9aed 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/mlo.c
@@ -3,6 +3,7 @@ 
  * Copyright (C) 2024-2025 Intel Corporation
  */
 #include "mlo.h"
+#include "phy.h"
 
 /* Block reasons helper */
 #define HANDLE_EMLSR_BLOCKED_REASONS(HOW)	\
@@ -177,6 +178,19 @@  static void iwl_mld_check_emlsr_prevention(struct iwl_mld *mld,
 				 &mld_vif->emlsr.prevent_done_wk, delay);
 }
 
+static void iwl_mld_clear_avg_chan_load_iter(struct ieee80211_hw *hw,
+					     struct ieee80211_chanctx_conf *ctx,
+					     void *dat)
+{
+	struct iwl_mld_phy *phy = iwl_mld_phy_from_mac80211(ctx);
+
+	/* It is ok to do it for all chanctx (and not only for the ones that
+	 * belong to the EMLSR vif) since EMLSR is not allowed if there is
+	 * another vif.
+	 */
+	phy->avg_channel_load_not_by_us = 0;
+}
+
 static int _iwl_mld_exit_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif,
 			       enum iwl_mld_emlsr_exit exit, u8 link_to_keep,
 			       bool sync)
@@ -215,6 +229,13 @@  static int _iwl_mld_exit_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif,
 	/* Update latest exit reason and check EMLSR prevention */
 	iwl_mld_check_emlsr_prevention(mld, mld_vif, exit);
 
+	/* channel_load_not_by_us is invalid when in EMLSR.
+	 * Clear it so wrong values won't be used.
+	 */
+	ieee80211_iter_chan_contexts_atomic(mld->hw,
+					    iwl_mld_clear_avg_chan_load_iter,
+					    NULL);
+
 	return ret;
 }
 
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/phy.h b/drivers/net/wireless/intel/iwlwifi/mld/phy.h
index 3dfb8ca994e2..357bc9fe9624 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/phy.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/phy.h
@@ -15,6 +15,9 @@ 
  *	with. Used to detect a no-op when the chanctx changes.
  * @channel_load_by_us: channel load on this channel caused by
  *	the NIC itself, as indicated by firmware
+ * @avg_channel_load_not_by_us: averaged channel load on this channel caused by
+ *	others. This value is invalid when in EMLSR (due to FW limitations)
+ * @mld: pointer to the MLD context
  */
 struct iwl_mld_phy {
 	/* Add here fields that need clean up on hw restart */
@@ -24,6 +27,8 @@  struct iwl_mld_phy {
 	);
 	/* And here fields that survive a hw restart */
 	u32 channel_load_by_us;
+	u32 avg_channel_load_not_by_us;
+	struct iwl_mld *mld;
 };
 
 static inline struct iwl_mld_phy *
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/stats.c b/drivers/net/wireless/intel/iwlwifi/mld/stats.c
index 842b9b9fdd8c..5633885c49ff 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/stats.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/stats.c
@@ -461,6 +461,7 @@  static void iwl_mld_fill_chanctx_stats(struct ieee80211_hw *hw,
 {
 	struct iwl_mld_phy *phy = iwl_mld_phy_from_mac80211(ctx);
 	const struct iwl_stats_ntfy_per_phy *per_phy = data;
+	u32 new_load;
 
 	if (WARN_ON(phy->fw_id >= IWL_STATS_MAX_PHY_OPERATIONAL))
 		return;
@@ -468,7 +469,14 @@  static void iwl_mld_fill_chanctx_stats(struct ieee80211_hw *hw,
 	phy->channel_load_by_us =
 		le32_to_cpu(per_phy[phy->fw_id].channel_load_by_us);
 
-	/* TODO: channel load not by us (task=statistics) */
+	new_load = le32_to_cpu(per_phy[phy->fw_id].channel_load_not_by_us);
+	if (IWL_FW_CHECK(phy->mld, new_load > 100, "Invalid channel load %u\n",
+			 new_load))
+		return;
+
+	/* give a weight of 0.5 for the old value */
+	phy->avg_channel_load_not_by_us =
+		(new_load >> 1) + (phy->avg_channel_load_not_by_us >> 1);
 }
 
 static void
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c b/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c
index a8c1e6c72138..b6049918b5db 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.c
@@ -168,6 +168,7 @@  iwlmld_kunit_add_chanctx_from_def(struct cfg80211_chan_def *def)
 	KUNIT_ASSERT_GE(test, fw_id, 0);
 
 	phy->fw_id = fw_id;
+	phy->mld = mld;
 	phy->chandef = *iwl_mld_get_chandef_from_chanctx(ctx);
 
 	return ctx;