diff options
author | Miri Korenblit <miriam.rachel.korenblit@intel.com> | 2024-02-18 09:08:41 +0200 |
---|---|---|
committer | iwlwifi publisher <> | 2024-04-17 13:00:01 +0000 |
commit | 5fa937814762fd4a8ed59772d9436cadab41b73d (patch) | |
tree | 8bc08bb33fd8b685c0d920fff2b7c50604d457d8 | |
parent | a8d789444663000b00826575df8ca7df8335cbbe (diff) | |
download | backport-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.c | 52 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 23 | ||||
-rw-r--r-- | versions | 2 |
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]; }; @@ -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" |