Commit 76f9864d authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by Johannes Berg
Browse files

wifi: iwlwifi: mvm: introduce esr_disable_reason



This will maintain a bitmap of reasons for which we want to avoid
enabling EMLSR.
For now, we have a single reason: BT coexistence, but we will add soon
more reasons. Make it a bitmap to make it easier to manage.

Since we'll impact the parameters that impact the enablement /
disablement of EMLSR from several places, introduce a generic function
that takes into account the current state and execute the decision that
must be taken.

Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240416134215.94c3590c6f27.I6a190da5025d0523ef483ffac0c64e26675041e6@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 332ff432
Loading
Loading
Loading
Loading
+8 −24
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
 * Copyright (C) 2013-2014, 2018-2020, 2022-2023 Intel Corporation
 * Copyright (C) 2013-2014, 2018-2020, 2022-2024 Intel Corporation
 * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
 */
#include <linux/ieee80211.h>
@@ -257,7 +257,6 @@ static void iwl_mvm_bt_coex_enable_esr(struct iwl_mvm *mvm,
				       struct ieee80211_vif *vif, bool enable)
{
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	int link_id;

	lockdep_assert_held(&mvm->mutex);

@@ -265,30 +264,15 @@ static void iwl_mvm_bt_coex_enable_esr(struct iwl_mvm *mvm,
		return;

	/* Done already */
	if (mvmvif->bt_coex_esr_disabled == !enable)
	if ((mvmvif->esr_disable_reason & IWL_MVM_ESR_DISABLE_COEX) == !enable)
		return;

	mvmvif->bt_coex_esr_disabled = !enable;

	/* Nothing to do */
	if (mvmvif->esr_active == enable)
		return;

	if (enable) {
		/* Try to re-enable eSR*/
		iwl_mvm_mld_select_links(mvm, vif, false);
		return;
	}

	/*
	 * Find the primary link, as we want to switch to it and drop the
	 * secondary one.
	 */
	link_id = iwl_mvm_mld_get_primary_link(mvm, vif, vif->active_links);
	WARN_ON(link_id < 0);
	if (enable)
		mvmvif->esr_disable_reason &= ~IWL_MVM_ESR_DISABLE_COEX;
	else
		mvmvif->esr_disable_reason |= IWL_MVM_ESR_DISABLE_COEX;

	ieee80211_set_active_links_async(vif,
					 vif->active_links & BIT(link_id));
	iwl_mvm_recalc_esr(mvm, vif);
}

/*
@@ -336,7 +320,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->bt_coex_esr_disabled)
	else if (!(mvmvif->esr_disable_reason & IWL_MVM_ESR_DISABLE_COEX))
		 /* RSSI needs to get really low to disable eSR... */
		wifi_loss_rate =
			link_rssi <= -IWL_MVM_BT_COEX_DISABLE_ESR_THRESH ?
+28 −1
Original line number Diff line number Diff line
@@ -1258,6 +1258,33 @@ int iwl_mvm_mld_get_primary_link(struct iwl_mvm *mvm,
	return data[1].link_id;
}

void iwl_mvm_recalc_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
	bool enable = !mvmvif->esr_disable_reason;
	int link_id;

	/* Nothing to do */
	if (mvmvif->esr_active == enable)
		return;

	if (enable) {
		/* Try to re-enable eSR */
		iwl_mvm_mld_select_links(mvm, vif, false);
		return;
	}

	/*
	 * Find the primary link, as we want to switch to it and drop the
	 * secondary one.
	 */
	link_id = iwl_mvm_mld_get_primary_link(mvm, vif, vif->active_links);
	WARN_ON(link_id < 0);

	ieee80211_set_active_links_async(vif,
					 vif->active_links & BIT(link_id));
}

/*
 * This function receives a bitmap of usable links and check if we can enter
 * eSR on those links.
@@ -1300,7 +1327,7 @@ static bool iwl_mvm_can_enter_esr(struct iwl_mvm *mvm,
							 primary_link);
		// Mark eSR as disabled for the next time
		if (!ret)
			mvmvif->bt_coex_esr_disabled = true;
			mvmvif->esr_disable_reason |= IWL_MVM_ESR_DISABLE_COEX;
		break;
	}

+15 −3
Original line number Diff line number Diff line
@@ -345,6 +345,14 @@ struct iwl_mvm_vif_link_info {
	struct iwl_mvm_link_bf_data bf_data;
};

/**
 * enum iwl_mvm_esr_disable_reason - reasons for which we can't enable EMLSR
 * @IWL_MVM_ESR_DISABLE_COEX: COEX is preventing the enablement of EMLSR
 */
enum iwl_mvm_esr_disable_reason {
	IWL_MVM_ESR_DISABLE_COEX	= BIT(0),
};

/**
 * struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context
 * @mvm: pointer back to the mvm struct
@@ -360,7 +368,6 @@ struct iwl_mvm_vif_link_info {
 * @pm_enabled - indicate if MAC power management is allowed
 * @monitor_active: indicates that monitor context is configured, and that the
 *	interface should get quota etc.
 * @bt_coex_esr_disabled: indicates if esr is disabled due to bt coex
 * @low_latency: bit flags for low latency
 *	see enum &iwl_mvm_low_latency_cause for causes.
 * @low_latency_actual: boolean, indicates low latency is set,
@@ -379,6 +386,7 @@ struct iwl_mvm_vif_link_info {
 * @deflink: default link data for use in non-MLO
 * @link: link data for each link in MLO
 * @esr_active: indicates eSR mode is active
 * @esr_disable_reason: a bitmap of enum iwl_mvm_esr_disable_reason
 * @pm_enabled: indicates powersave is enabled
 */
struct iwl_mvm_vif {
@@ -393,7 +401,6 @@ struct iwl_mvm_vif {
	bool pm_enabled;
	bool monitor_active;
	bool esr_active;
	bool bt_coex_esr_disabled;

	u8 low_latency: 6;
	u8 low_latency_actual: 1;
@@ -401,6 +408,7 @@ struct iwl_mvm_vif {
	u8 authorized:1;
	bool ps_disabled;

	u32 esr_disable_reason;
	u32 ap_beacon_time;
	bool bf_enabled;
	bool ba_enabled;
@@ -1587,7 +1595,7 @@ static inline int iwl_mvm_max_active_links(struct iwl_mvm *mvm,
		return mvm->fw->ucode_capa.num_beacons;

	if ((iwl_mvm_is_esr_supported(trans) &&
	     !mvmvif->bt_coex_esr_disabled) ||
	     !mvmvif->esr_disable_reason) ||
	    ((CSR_HW_RFID_TYPE(trans->hw_rf_id) == IWL_CFG_RF_TYPE_FM &&
	     CSR_HW_RFID_IS_CDB(trans->hw_rf_id))))
		return IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM;
@@ -2808,4 +2816,8 @@ int iwl_mvm_roc_add_cmd(struct iwl_mvm *mvm,
			struct ieee80211_channel *channel,
			struct ieee80211_vif *vif,
			int duration, u32 activity);

/* EMLSR */
void iwl_mvm_recalc_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif);

#endif /* __IWL_MVM_H__ */