From: Benjamin Berg Date: Fri, 27 Dec 2024 08:00:58 +0000 (+0200) Subject: wifi: iwlwifi: mvm: skip short statistics window when updating EMLSR X-Git-Tag: v6.14-rc1~162^2~20^2~105 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=83bb3633a2ce16be2043bac2316aa34530d2f271;p=thirdparty%2Flinux.git wifi: iwlwifi: mvm: skip short statistics window when updating EMLSR The statistics are not synchronized with the time that we enter EMLSR. This means that we can receive the statistic notification just after having cleared the counters, causing us to immediately exit EMLSR again. Fix this by checking that most of the time for the window has passed. If that is not the case, ignore this window and wait for the next notification. Signed-off-by: Benjamin Berg Signed-off-by: Miri Korenblit Link: https://patch.msgid.link/20241227095718.0eb0f2044535.Ic2af92737ccfc873f3b6c228704238ebb9f983ca@changeid Signed-off-by: Johannes Berg --- diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c index e4ce3257c6634..341a2a7a49ec9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c @@ -210,32 +210,6 @@ static unsigned int iwl_mvm_mld_count_active_links(struct iwl_mvm_vif *mvmvif) return n_active; } -static void iwl_mvm_restart_mpdu_count(struct iwl_mvm *mvm, - struct iwl_mvm_vif *mvmvif) -{ - struct ieee80211_sta *ap_sta = mvmvif->ap_sta; - struct iwl_mvm_sta *mvmsta; - - lockdep_assert_held(&mvm->mutex); - - if (!ap_sta) - return; - - mvmsta = iwl_mvm_sta_from_mac80211(ap_sta); - if (!mvmsta->mpdu_counters) - return; - - for (int q = 0; q < mvm->trans->num_rx_queues; q++) { - spin_lock_bh(&mvmsta->mpdu_counters[q].lock); - memset(mvmsta->mpdu_counters[q].per_link, 0, - sizeof(mvmsta->mpdu_counters[q].per_link)); - mvmsta->mpdu_counters[q].window_start = jiffies; - spin_unlock_bh(&mvmsta->mpdu_counters[q].lock); - } - - IWL_DEBUG_INFO(mvm, "MPDU counters are cleared\n"); -} - static int iwl_mvm_esr_mode_active(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { @@ -269,13 +243,6 @@ static int iwl_mvm_esr_mode_active(struct iwl_mvm *mvm, else mvmvif->primary_link = __ffs(vif->active_links); - /* - * Restart the MPDU counters and the counting window, so when the - * statistics arrive (which is where we look at the counters) we - * will be at the end of the window. - */ - iwl_mvm_restart_mpdu_count(mvm, mvmvif); - iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_ESR_LINK_UP, NULL); @@ -447,9 +414,6 @@ static int iwl_mvm_esr_mode_inactive(struct iwl_mvm *mvm, break; } - /* Start a new counting window */ - iwl_mvm_restart_mpdu_count(mvm, mvmvif); - iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_ESR_LINK_DOWN, NULL); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index 9e72db9bab401..00aac76e85092 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -962,6 +962,9 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm, #define SEC_LINK_MIN_TX 3000 #define SEC_LINK_MIN_RX 400 +/* Accept a ~20% short window to avoid issues due to jitter */ +#define IWL_MVM_TPT_MIN_COUNT_WINDOW (IWL_MVM_TPT_COUNT_WINDOW_SEC * HZ * 4 / 5) + static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm) { struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm); @@ -971,6 +974,7 @@ static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm) unsigned long sec_link_tx = 0, sec_link_rx = 0; u8 sec_link_tx_perc, sec_link_rx_perc; u8 sec_link; + bool skip = false; lockdep_assert_held(&mvm->mutex); @@ -1010,13 +1014,25 @@ static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm) /* * In EMLSR we have statistics every 5 seconds, so we can reset * the counters upon every statistics notification. + * The FW sends the notification regularly, but it will be + * misaligned at the start. Skipping the measurement if it is + * short will synchronize us. */ + if (jiffies - mvmsta->mpdu_counters[q].window_start < + IWL_MVM_TPT_MIN_COUNT_WINDOW) + skip = true; + mvmsta->mpdu_counters[q].window_start = jiffies; memset(mvmsta->mpdu_counters[q].per_link, 0, sizeof(mvmsta->mpdu_counters[q].per_link)); spin_unlock_bh(&mvmsta->mpdu_counters[q].lock); } + if (skip) { + IWL_DEBUG_INFO(mvm, "MPDU statistics window was short\n"); + return; + } + IWL_DEBUG_INFO(mvm, "total Tx MPDUs: %ld. total Rx MPDUs: %ld\n", total_tx, total_rx);