Skip to content

Commit

Permalink
wifi: iwlwifi: mvm: exit EMLSR if secondary link is not used
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Miri Korenblit authored and Johannes Berg committed May 6, 2024
1 parent bf0212f commit df966c9
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 2 deletions.
3 changes: 2 additions & 1 deletion drivers/net/wireless/intel/iwlwifi/mvm/link.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down
37 changes: 36 additions & 1 deletion drivers/net/wireless/intel/iwlwifi/mvm/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);
Expand All @@ -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.
Expand All @@ -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,
Expand Down

0 comments on commit df966c9

Please sign in to comment.