]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: iwlwifi: mvm: skip short statistics window when updating EMLSR
authorBenjamin Berg <benjamin.berg@intel.com>
Fri, 27 Dec 2024 08:00:58 +0000 (10:00 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 13 Jan 2025 13:01:51 +0000 (14:01 +0100)
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 <benjamin.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20241227095718.0eb0f2044535.Ic2af92737ccfc873f3b6c228704238ebb9f983ca@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/rx.c

index e4ce3257c6634dc81ce78ab5dbf28b0d2991bc90..341a2a7a49ec9be7f58801e7d75fd18db050ad72 100644 (file)
@@ -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);
 
index 9e72db9bab4014b7d7745bc748078a2f8e17a1a0..00aac76e85092397e4116c2a5751badc9588c300 100644 (file)
@@ -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);