diff mbox series

[01/15] wifi: iwlwifi: cleanup EMLSR when BT is active handling

Message ID 20240505091420.a2e93b67c895.I183a0039ef076613144648cc46fbe9ab3d47c574@changeid
State New
Headers show
Series wifi: iwlwifi: updates - 2024-05-05 | expand

Commit Message

Miri Korenblit May 5, 2024, 6:19 a.m. UTC
BT Coex disables EMLSR only for a 2.4 GHz link, but doesn't block the
vif from using EMLSR with a different link pair. In addition, storing it
in mvmvif:disable_esr_reason requires extracting the BT Coex bit before
checking if EMLSR is blocked or not for a specific vif.

Therefore, change the BT Coex bit to be an exit reason and not a
blocker. On link selection, EMLSR mode will be re-calculated for the 2.4
GHz link instead of checking that bit.

While at it, move the relevant function declarations to the EMLSR
functions area in mvm.h

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/intel/iwlwifi/mvm/coex.c | 42 +++++++------------
 drivers/net/wireless/intel/iwlwifi/mvm/link.c | 13 +++---
 .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 20 ---------
 .../wireless/intel/iwlwifi/mvm/mld-mac80211.c |  2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/mvm.h  | 21 ++++++----
 .../wireless/intel/iwlwifi/mvm/tests/links.c  | 21 ++++++++--
 6 files changed, 53 insertions(+), 66 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
index c7987676335a..ad3e14a0d043 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c
@@ -257,38 +257,28 @@  static void iwl_mvm_bt_coex_tcm_based_ci(struct iwl_mvm *mvm,
  * This function receives the LB link id and checks if eSR should be
  * enabled or disabled (due to BT coex)
  */
-static bool
+bool
 iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm,
 				   struct ieee80211_vif *vif,
-				   int link_id)
+				   s32 link_rssi,
+				   bool primary)
 {
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-	struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
 	bool have_wifi_loss_rate =
 		iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
 					BT_PROFILE_NOTIFICATION, 0) > 4;
-	s8 link_rssi = 0;
 	u8 wifi_loss_rate;
 
-	lockdep_assert_held(&mvm->mutex);
-
 	if (mvm->last_bt_notif.wifi_loss_low_rssi == BT_OFF)
 		return true;
 
-	 /* If LB link is the primary one we should always disable eSR */
-	if (link_id == iwl_mvm_get_primary_link(vif))
+	if (primary)
 		return false;
 
 	/* The feature is not supported */
 	if (!have_wifi_loss_rate)
 		return true;
 
-	/*
-	 * We might not have a link_info when checking whether we can
-	 * (re)enable eSR - the LB link might not exist yet
-	 */
-	if (link_info)
-		link_rssi = (s8)link_info->beacon_stats.avg_signal;
 
 	/*
 	 * In case we don't know the RSSI - take the lower wifi loss,
@@ -298,7 +288,7 @@  iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm,
 	if (!link_rssi)
 		wifi_loss_rate = mvm->last_bt_notif.wifi_loss_mid_high_rssi;
 
-	else if (!(mvmvif->esr_disable_reason & IWL_MVM_ESR_BLOCKED_COEX))
+	else if (mvmvif->esr_active)
 		 /* RSSI needs to get really low to disable eSR... */
 		wifi_loss_rate =
 			link_rssi <= -IWL_MVM_BT_COEX_DISABLE_ESR_THRESH ?
@@ -318,20 +308,20 @@  void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm,
 				     struct ieee80211_vif *vif,
 				     int link_id)
 {
-	bool enable;
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	struct iwl_mvm_vif_link_info *link = mvmvif->link[link_id];
 
 	if (!ieee80211_vif_is_mld(vif) ||
-	    !iwl_mvm_vif_from_mac80211(vif)->authorized)
+	    !iwl_mvm_vif_from_mac80211(vif)->authorized ||
+	    WARN_ON(!link))
 		return;
 
-	enable = iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif, link_id);
-
-	if (enable)
-		iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_COEX);
-	else
+	if (!iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif,
+						(s8)link->beacon_stats.avg_signal,
+						link_id == iwl_mvm_get_primary_link(vif)))
 		/* In case we decided to exit eSR - stay with the primary */
-		iwl_mvm_block_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_COEX,
-				  iwl_mvm_get_primary_link(vif));
+		iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_COEX,
+				 iwl_mvm_get_primary_link(vif));
 }
 
 static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm,
@@ -515,10 +505,6 @@  static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
 		return;
 	}
 
-	/* When BT is off this will be 0 */
-	if (data->notif->wifi_loss_low_rssi == BT_OFF)
-		iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_COEX);
-
 	for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++)
 		iwl_mvm_bt_notif_per_link(mvm, vif, data, link_id);
 }
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index 84b497b22d83..733e1f77c171 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -592,7 +592,8 @@  s8 iwl_mvm_get_esr_rssi_thresh(struct iwl_mvm *mvm,
 
 static u32
 iwl_mvm_esr_disallowed_with_link(struct ieee80211_vif *vif,
-				 const struct iwl_mvm_link_sel_data *link)
+				 const struct iwl_mvm_link_sel_data *link,
+				 bool primary)
 {
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	struct iwl_mvm *mvm = mvmvif->mvm;
@@ -601,8 +602,10 @@  iwl_mvm_esr_disallowed_with_link(struct ieee80211_vif *vif,
 
 	/* BT Coex effects eSR mode only if one of the links is on LB */
 	if (link->chandef->chan->band == NL80211_BAND_2GHZ &&
-	    mvmvif->esr_disable_reason & IWL_MVM_ESR_BLOCKED_COEX)
-		ret |= IWL_MVM_ESR_BLOCKED_COEX;
+	    (!iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif, link->signal,
+						 primary)))
+		ret |= IWL_MVM_ESR_EXIT_COEX;
+
 	thresh = iwl_mvm_get_esr_rssi_thresh(mvm, link->chandef,
 					     false);
 
@@ -622,8 +625,8 @@  bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif,
 				 const struct iwl_mvm_link_sel_data *b)
 {
 	/* Per-link considerations */
-	if (iwl_mvm_esr_disallowed_with_link(vif, a) ||
-	    iwl_mvm_esr_disallowed_with_link(vif, b))
+	if (iwl_mvm_esr_disallowed_with_link(vif, a, true) ||
+	    iwl_mvm_esr_disallowed_with_link(vif, b, false))
 		return false;
 
 	/* Per-combination considerations */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index c631de70253d..eab40211404f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -3877,23 +3877,6 @@  iwl_mvm_sta_state_auth_to_assoc(struct ieee80211_hw *hw,
 	return callbacks->update_sta(mvm, vif, sta);
 }
 
-static void iwl_mvm_bt_coex_update_vif_esr(struct iwl_mvm *mvm,
-					   struct ieee80211_vif *vif)
-{
-	unsigned long usable_links = ieee80211_vif_usable_links(vif);
-	u8 link_id;
-
-	for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
-		struct ieee80211_bss_conf *link_conf =
-			link_conf_dereference_protected(vif, link_id);
-
-		if (WARN_ON_ONCE(!link_conf))
-			return;
-
-		if (link_conf->chanreq.oper.chan->band == NL80211_BAND_2GHZ)
-			iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id);
-	}
-}
 
 static int
 iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm,
@@ -3928,9 +3911,6 @@  iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm,
 		memset(&mvmvif->last_esr_exit, 0,
 		       sizeof(mvmvif->last_esr_exit));
 
-		/* Calculate eSR mode due to BT coex */
-		iwl_mvm_bt_coex_update_vif_esr(mvm, vif);
-
 		/* when client is authorized (AP station marked as such),
 		 * try to enable the best link(s).
 		 */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
index 986176d94210..e16f1eee8473 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
@@ -1180,7 +1180,7 @@  bool iwl_mvm_esr_allowed_on_vif(struct iwl_mvm *mvm,
 	    !(ext_capa->eml_capabilities & IEEE80211_EML_CAP_EMLSR_SUPP))
 		return false;
 
-	return !(mvmvif->esr_disable_reason & ~IWL_MVM_ESR_BLOCKED_COEX);
+	return !mvmvif->esr_disable_reason;
 }
 
 static bool iwl_mvm_mld_can_activate_links(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 421c927ec960..309711532042 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -353,20 +353,21 @@  struct iwl_mvm_vif_link_info {
  * For the blocking reasons - use iwl_mvm_(un)block_esr(), and for the exit
  * reasons - use iwl_mvm_exit_esr().
  *
- * @IWL_MVM_ESR_BLOCKED_COEX: COEX is preventing the enablement of EMLSR
  * @IWL_MVM_ESR_BLOCKED_PREVENTION: Prevent EMLSR to avoid entering and exiting
  *	in a loop.
  * @IWL_MVM_ESR_BLOCKED_WOWLAN: WOWLAN is preventing the enablement of EMLSR
  * @IWL_MVM_ESR_EXIT_MISSED_BEACON: exited EMLSR due to missed beacons
  * @IWL_MVM_ESR_EXIT_LOW_RSSI: link is deactivated/not allowed for EMLSR
  *	due to low RSSI.
+ * @IWL_MVM_ESR_EXIT_COEX: link is deactivated/not allowed for EMLSR
+ *	due to BT Coex.
  */
 enum iwl_mvm_esr_state {
-	IWL_MVM_ESR_BLOCKED_COEX	= 0x1,
-	IWL_MVM_ESR_BLOCKED_PREVENTION	= 0x2,
-	IWL_MVM_ESR_BLOCKED_WOWLAN	= 0x4,
+	IWL_MVM_ESR_BLOCKED_PREVENTION	= 0x1,
+	IWL_MVM_ESR_BLOCKED_WOWLAN	= 0x2,
 	IWL_MVM_ESR_EXIT_MISSED_BEACON	= 0x10000,
 	IWL_MVM_ESR_EXIT_LOW_RSSI	= 0x20000,
+	IWL_MVM_ESR_EXIT_COEX		= 0x40000,
 };
 
 #define IWL_MVM_BLOCK_ESR_REASONS 0xffff
@@ -2221,9 +2222,6 @@  bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
 u8 iwl_mvm_bt_coex_get_single_ant_msk(struct iwl_mvm *mvm, u8 enabled_ants);
 u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
 			   struct ieee80211_tx_info *info, u8 ac);
-void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm,
-				     struct ieee80211_vif *vif,
-				     int link_id);
 
 /* beacon filtering */
 #ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -2888,5 +2886,12 @@  void iwl_mvm_exit_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 s8 iwl_mvm_get_esr_rssi_thresh(struct iwl_mvm *mvm,
 			       const struct cfg80211_chan_def *chandef,
 			       bool low);
-
+void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm,
+				     struct ieee80211_vif *vif,
+				     int link_id);
+bool
+iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm,
+				   struct ieee80211_vif *vif,
+				   s32 link_rssi,
+				   bool primary);
 #endif /* __IWL_MVM_H__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c b/drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c
index 7446e0c168ee..217dbb823691 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c
@@ -37,7 +37,20 @@  static struct cfg80211_bss bss = {};
 
 static struct ieee80211_bss_conf link_conf = {.bss = &bss};
 
-static struct iwl_mvm mvm = {};
+static const struct iwl_fw_cmd_version entry = {
+	.group = LEGACY_GROUP,
+	.cmd = BT_PROFILE_NOTIFICATION,
+	.notif_ver = 4
+};
+
+static struct iwl_fw fw = {
+	.ucode_capa = {
+		.n_cmd_versions = 1,
+		.cmd_versions = &entry,
+	},
+};
+
+static struct iwl_mvm mvm = {.fw = &fw};
 
 static const struct link_grading_case {
 	const char *desc;
@@ -217,7 +230,7 @@  kunit_test_suite(link_grading);
 
 static const struct valid_link_pair_case {
 	const char *desc;
-	u32 esr_disable_reason;
+	bool bt;
 	struct ieee80211_channel *chan_a;
 	struct ieee80211_channel *chan_b;
 	enum nl80211_chan_width cw_a;
@@ -240,7 +253,7 @@  static const struct valid_link_pair_case {
 	},
 	{
 		.desc = "LB + HB, with BT.",
-		.esr_disable_reason = 0x1,
+		.bt = true,
 		.chan_a = &chan_2ghz,
 		.chan_b = &chan_5ghz,
 		.valid = false,
@@ -370,7 +383,7 @@  static void test_valid_link_pair(struct kunit *test)
 #endif
 	mvm.trans = trans;
 
-	mvmvif->esr_disable_reason = params->esr_disable_reason;
+	mvm.last_bt_notif.wifi_loss_low_rssi = params->bt;
 	mvmvif->mvm = &mvm;
 
 	result = iwl_mvm_mld_valid_link_pair(vif, &link_a, &link_b);