summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>2024-02-18 09:08:41 +0200
committeriwlwifi publisher <>2024-04-17 13:00:01 +0000
commit5fa937814762fd4a8ed59772d9436cadab41b73d (patch)
tree8bc08bb33fd8b685c0d920fff2b7c50604d457d8
parenta8d789444663000b00826575df8ca7df8335cbbe (diff)
downloadbackport-iwlwifi-5fa937814762fd4a8ed59772d9436cadab41b73d.tar.gz
wifi: iwlwifi: mvm: implement EMLSR prevention mechanism.
Address scenarios where repeated entry and exit from esr occur, such as encountering missed beacons on a specific link, while still discovering that link during a scan. To mitigate this, introduce the esr prevention mechanism, which operates as follows: - On each exit from esr event, record the timestamp and the exit reason. - If two consecutive exits happen for the same reason within a 400-second window, enforce a 300-second esr prevention. - If a third exit for the same reason occurs within 400 seconds from the second exit, enforce an extended esr prevention of 600 seconds. type=feature ticket=jira:WIFI-387632 Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Change-Id: I6406db40cf25eabdba602afd783466473b909216 Reviewed-on: https://gerritwcs.ir.intel.com/c/iwlwifi-stack-dev/+/95075 Tested-by: iil_jenkins iil_jenkins <EC.GER.UNIX.IIL.JENKINS@INTEL.COM> tested: iil_jenkins iil_jenkins <EC.GER.UNIX.IIL.JENKINS@INTEL.COM> automatic-review: iil_jenkins iil_jenkins <EC.GER.UNIX.IIL.JENKINS@INTEL.COM> Reviewed-by: Johannes Berg <johannes.berg@intel.com> x-iwlwifi-stack-dev: 4c897125aca006e28e9065915b3a2f8fdf8310c1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/link.c52
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c22
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h23
-rw-r--r--versions2
4 files changed, 98 insertions, 1 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
index 4983fc3441..8e1f90268c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c
@@ -710,6 +710,55 @@ u8 iwl_mvm_get_other_link(struct ieee80211_vif *vif, u8 link_id)
}
}
+/* Reasons that can cause esr prevention */
+#define IWL_MVM_ESR_PREVENT_REASONS IWL_MVM_ESR_EXIT_MISSED_BEACON
+#define IWL_MVM_PREVENT_ESR_TIMEOUT (HZ * 400)
+#define IWL_MVM_ESR_PREVENT_SHORT (HZ * 300)
+#define IWL_MVM_ESR_PREVENT_LONG (HZ * 600)
+
+static void iwl_mvm_recalc_esr_prevention(struct iwl_mvm *mvm,
+ struct iwl_mvm_vif *mvmvif,
+ enum iwl_mvm_esr_state reason)
+{
+ unsigned long now = jiffies;
+ unsigned long delay;
+ bool timeout_expired =
+ time_after(now, mvmvif->last_esr_exit.ts +
+ IWL_MVM_PREVENT_ESR_TIMEOUT);
+
+ if (WARN_ON(!(IWL_MVM_ESR_PREVENT_REASONS & reason)))
+ return;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ mvmvif->last_esr_exit.ts = now;
+
+ if (timeout_expired ||
+ mvmvif->last_esr_exit.reason != reason) {
+ mvmvif->last_esr_exit.reason = reason;
+ mvmvif->exit_same_reason_count = 1;
+ return;
+ }
+
+ mvmvif->exit_same_reason_count++;
+ if (WARN_ON(mvmvif->exit_same_reason_count < 2 ||
+ mvmvif->exit_same_reason_count > 3))
+ return;
+
+ mvmvif->esr_disable_reason |= IWL_MVM_ESR_BLOCKED_PREVENTION;
+
+ delay = mvmvif->exit_same_reason_count == 2 ?
+ IWL_MVM_ESR_PREVENT_SHORT :
+ IWL_MVM_ESR_PREVENT_LONG;
+
+ IWL_DEBUG_INFO(mvm,
+ "Preventing EMLSR for %ld seconds due to %u exits with the reason 0x%x\n",
+ delay / HZ, mvmvif->exit_same_reason_count, reason);
+
+ wiphy_delayed_work_queue(mvm->hw->wiphy,
+ &mvmvif->prevent_esr_done_wk, delay);
+}
+
/* API to exit eSR mode */
void iwl_mvm_exit_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum iwl_mvm_esr_state reason,
@@ -736,6 +785,9 @@ void iwl_mvm_exit_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
reason, vif->active_links, new_active_links);
ieee80211_set_active_links_async(vif, new_active_links);
+
+ if (IWL_MVM_ESR_PREVENT_REASONS & reason)
+ iwl_mvm_recalc_esr_prevention(mvm, mvmvif, reason);
}
void iwl_mvm_block_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 092a7d8240..2839dd2831 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -4063,6 +4063,19 @@ static void iwl_mvm_bt_coex_update_vif_esr(struct iwl_mvm *mvm,
}
}
+static void iwl_mvm_prevent_esr_done_wk(struct wiphy *wiphy,
+ struct wiphy_work *wk)
+{
+ struct iwl_mvm_vif *mvmvif =
+ container_of(wk, struct iwl_mvm_vif, prevent_esr_done_wk.work);
+ struct iwl_mvm *mvm = mvmvif->mvm;
+ struct ieee80211_vif *vif = iwl_mvm_get_bss_vif(mvm);
+
+ mutex_lock(&mvm->mutex);
+ iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_PREVENTION);
+ mutex_unlock(&mvm->mutex);
+}
+
static int
iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
@@ -4090,6 +4103,12 @@ iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm,
callbacks->mac_ctxt_changed(mvm, vif, false);
iwl_mvm_mei_host_associated(mvm, vif, mvm_sta);
+ memset(&mvmvif->last_esr_exit, 0,
+ sizeof(mvmvif->last_esr_exit));
+
+ wiphy_delayed_work_init(&mvmvif->prevent_esr_done_wk,
+ iwl_mvm_prevent_esr_done_wk);
+
/* Calculate eSR mode due to BT coex */
iwl_mvm_bt_coex_update_vif_esr(mvm, vif);
@@ -4145,6 +4164,9 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm,
/* disable beacon filtering */
iwl_mvm_disable_beacon_filter(mvm, vif);
+
+ wiphy_delayed_work_cancel(mvm->hw->wiphy,
+ &mvmvif->prevent_esr_done_wk);
}
return 0;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index dff022f78d..5e8b047380 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -356,16 +356,30 @@ struct iwl_mvm_vif_link_info {
* 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_EXIT_MISSED_BEACON: exited EMLSR due to missed beacons
*/
enum iwl_mvm_esr_state {
IWL_MVM_ESR_BLOCKED_COEX = 0x1,
+ IWL_MVM_ESR_BLOCKED_PREVENTION = 0x2,
IWL_MVM_ESR_EXIT_MISSED_BEACON = 0x10000,
};
#define IWL_MVM_BLOCK_ESR_REASONS 0xffff
/**
+ * struct iwl_mvm_esr_exit - details of the last exit from EMLSR mode.
+ * @reason: The reason for the last exit from EMLSR.
+ * &iwl_mvm_prevent_esr_reasons. Will be 0 before exiting EMLSR.
+ * @ts: the time stamp of the last time we existed EMLSR.
+ */
+struct iwl_mvm_esr_exit {
+ unsigned long ts;
+ enum iwl_mvm_esr_state reason;
+};
+
+/**
* struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context
* @mvm: pointer back to the mvm struct
* @id: between 0 and 3
@@ -403,6 +417,11 @@ enum iwl_mvm_esr_state {
* @pm_enabled: indicates powersave is enabled
* @primary_link: primary link in eSR. Valid only for an associated MLD vif,
* and in eSR mode. Valid only for a STA.
+ * @last_esr_exit: Details of the last exit from EMLSR.
+ * @exit_same_reason_count: The number of times we exited due to the specified
+ * @last_esr_exit::reason, only counting exits due to
+ * &IWL_MVM_ESR_PREVENT_REASONS.
+ * @prevent_esr_done_wk: work that should be done when esr prevention ends.
*/
struct iwl_mvm_vif {
struct iwl_mvm *mvm;
@@ -496,6 +515,10 @@ struct iwl_mvm_vif {
u16 max_tx_op;
u8 primary_link;
+ struct iwl_mvm_esr_exit last_esr_exit;
+ u8 exit_same_reason_count;
+ struct wiphy_delayed_work prevent_esr_done_wk;
+
struct iwl_mvm_vif_link_info deflink;
struct iwl_mvm_vif_link_info *link[IEEE80211_MLD_MAX_NUM_LINKS];
};
diff --git a/versions b/versions
index 0dede0f76f..92499f6835 100644
--- a/versions
+++ b/versions
@@ -2,4 +2,4 @@ BACKPORTS_VERSION="(see git)"
BACKPORTED_KERNEL_VERSION="(see git)"
BACKPORTED_KERNEL_NAME="iwlwifi"
BACKPORTS_BUILD_TSTAMP=__DATE__ \" \" __TIME__
-BACKPORTS_GIT_TRACKED="iwlwifi-stack-public:master:11949:df9aeee2"
+BACKPORTS_GIT_TRACKED="iwlwifi-stack-public:master:11950:4c897125"