wifi: iwlwifi: mvm: exit EMLSR if secondary link is not used
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>
Mon, 6 May 2024 07:04:17 +0000 (10:04 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 6 May 2024 14:33:26 +0000 (16:33 +0200)
Exit EMLSR mode if the secondary link is not used enough for Rx/Tx

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Link: https://msgid.link/20240506095953.99ad1d71e9b9.Ide825433488ec809773efdc36937e3089d0012df@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/link.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/rx.c

index 7e567a0b16aefb98ff678bb5cdd3c690f39f372b..6ec9a8e21a34ee024f2475b19cc91f2f191ffa05 100644 (file)
@@ -15,7 +15,8 @@
        HOW(EXIT_LOW_RSSI)              \
        HOW(EXIT_COEX)                  \
        HOW(EXIT_BANDWIDTH)             \
-       HOW(EXIT_CSA)
+       HOW(EXIT_CSA)                   \
+       HOW(EXIT_LINK_USAGE)
 
 static const char *const iwl_mvm_esr_states_names[] = {
 #define NAME_ENTRY(x) [ilog2(IWL_MVM_ESR_##x)] = #x,
index b96568f5640cd50ef1914e109526e333cebbc34b..1f58c727fa632df016241ed1a64ba5731d0b1d79 100644 (file)
@@ -369,6 +369,7 @@ struct iwl_mvm_vif_link_info {
  * @IWL_MVM_ESR_EXIT_BANDWIDTH: Bandwidths of primary and secondry links
  *     preventing the enablement of EMLSR
  * @IWL_MVM_ESR_EXIT_CSA: CSA happened, so exit EMLSR
+ * @IWL_MVM_ESR_EXIT_LINK_USAGE: Exit EMLSR due to low tpt on secondary link
  */
 enum iwl_mvm_esr_state {
        IWL_MVM_ESR_BLOCKED_PREVENTION  = 0x1,
@@ -381,6 +382,7 @@ enum iwl_mvm_esr_state {
        IWL_MVM_ESR_EXIT_COEX           = 0x40000,
        IWL_MVM_ESR_EXIT_BANDWIDTH      = 0x80000,
        IWL_MVM_ESR_EXIT_CSA            = 0x100000,
+       IWL_MVM_ESR_EXIT_LINK_USAGE     = 0x200000,
 };
 
 #define IWL_MVM_BLOCK_ESR_REASONS 0xffff
index 36083905457bc7e946b3e62daf77a1bb19727dca..4fa8066a89b6a196505efd2570c5f1773c2c06cb 100644 (file)
@@ -951,12 +951,19 @@ iwl_mvm_stat_iterator_all_links(struct iwl_mvm *mvm,
        }
 }
 
+#define SEC_LINK_MIN_PERC 10
+#define SEC_LINK_MIN_TX 3000
+#define SEC_LINK_MIN_RX 400
+
 static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm)
 {
        struct ieee80211_vif *bss_vif = iwl_mvm_get_bss_vif(mvm);
        struct iwl_mvm_vif *mvmvif;
        struct iwl_mvm_sta *mvmsta;
        unsigned long total_tx = 0, total_rx = 0;
+       unsigned long sec_link_tx = 0, sec_link_rx = 0;
+       u8 sec_link_tx_perc, sec_link_rx_perc;
+       u8 sec_link;
 
        lockdep_assert_held(&mvm->mutex);
 
@@ -973,6 +980,13 @@ static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm)
        if (!mvmsta->mpdu_counters)
                return;
 
+       /* Get the FW ID of the secondary link */
+       sec_link = iwl_mvm_get_other_link(bss_vif,
+                                         iwl_mvm_get_primary_link(bss_vif));
+       if (WARN_ON(!mvmvif->link[sec_link]))
+               return;
+       sec_link = mvmvif->link[sec_link]->fw_link_id;
+
        /* Sum up RX and TX MPDUs from the different queues/links */
        for (int q = 0; q < mvm->trans->num_rx_queues; q++) {
                spin_lock_bh(&mvmsta->mpdu_counters[q].lock);
@@ -982,6 +996,10 @@ static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm)
                        total_tx += mvmsta->mpdu_counters[q].per_link[link].tx;
                        total_rx += mvmsta->mpdu_counters[q].per_link[link].rx;
                }
+
+               sec_link_tx += mvmsta->mpdu_counters[q].per_link[sec_link].tx;
+               sec_link_rx += mvmsta->mpdu_counters[q].per_link[sec_link].rx;
+
                /*
                 * In EMLSR we have statistics every 5 seconds, so we can reset
                 * the counters upon every statistics notification.
@@ -994,9 +1012,26 @@ static void iwl_mvm_update_esr_mode_tpt(struct iwl_mvm *mvm)
 
        /* If we don't have enough MPDUs - exit EMLSR */
        if (total_tx < IWL_MVM_ENTER_ESR_TPT_THRESH &&
-           total_rx < IWL_MVM_ENTER_ESR_TPT_THRESH)
+           total_rx < IWL_MVM_ENTER_ESR_TPT_THRESH) {
                iwl_mvm_block_esr(mvm, bss_vif, IWL_MVM_ESR_BLOCKED_TPT,
                                  iwl_mvm_get_primary_link(bss_vif));
+               return;
+       }
+
+       /* Calculate the percentage of the secondary link TX/RX */
+       sec_link_tx_perc = total_tx ? sec_link_tx * 100 / total_tx : 0;
+       sec_link_rx_perc = total_rx ? sec_link_rx * 100 / total_rx : 0;
+
+       /*
+        * The TX/RX percentage is checked only if it exceeds the required
+        * minimum. In addition, RX is checked only if the TX check failed.
+        */
+       if ((total_tx > SEC_LINK_MIN_TX &&
+            sec_link_tx_perc < SEC_LINK_MIN_PERC) ||
+           (total_rx > SEC_LINK_MIN_RX &&
+            sec_link_rx_perc < SEC_LINK_MIN_PERC))
+               iwl_mvm_exit_esr(mvm, bss_vif, IWL_MVM_ESR_EXIT_LINK_USAGE,
+                                iwl_mvm_get_primary_link(bss_vif));
 }
 
 void iwl_mvm_handle_rx_system_oper_stats(struct iwl_mvm *mvm,