Commit 72c19df2 authored by Miri Korenblit's avatar Miri Korenblit Committed by Johannes Berg
Browse files

wifi: iwlwifi: cleanup EMLSR when BT is active handling



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: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240505091420.a2e93b67c895.I183a0039ef076613144648cc46fbe9ab3d47c574@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 2f324144
Loading
Loading
Loading
Loading
+14 −28
Original line number Diff line number Diff line
@@ -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,19 +308,19 @@ 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_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_COEX,
				 iwl_mvm_get_primary_link(vif));
}

@@ -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);
}
+8 −5
Original line number Diff line number Diff line
@@ -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 */
+0 −20
Original line number Diff line number Diff line
@@ -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).
		 */
+1 −1
Original line number Diff line number Diff line
@@ -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,
+13 −8
Original line number Diff line number Diff line
@@ -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__ */
Loading