Commit 6cf7df9f authored by Miri Korenblit's avatar Miri Korenblit Committed by Johannes Berg

wifi: iwlwifi: mvm: Add helper functions to update EMLSR status

There are reasons for which we need to exit EMLSR, but not to block it
completely, and there are reasons for which we need to block EMLSR.

For both reason types we have the enum iwl_mvm_esr_state, when the
blocking reasons are stored in the `mvmvif::esr_disable_reason` bitmap.

This change introduces the APIs to use in the different cases:
- iwl_mvm_exit_esr - will exit from EMLSR mode.
- iwl_mvm_block_esr - will update the bitmap and exit EMLSR, to
  be used for the blocking reasons only.
- iwl_mvm_unblock_esr - will update the bitmap. To be used for the
  blocking reasons only.
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Reviewed-by: default avatarJohannes Berg <johannes.berg@intel.com>
Link: https://msgid.link/20240416134215.d54142a75876.I552926065521f5f848c37b0bd845494bd7865fb7@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 07bf5297
......@@ -253,28 +253,6 @@ static void iwl_mvm_bt_coex_tcm_based_ci(struct iwl_mvm *mvm,
swap(data->primary, data->secondary);
}
static void iwl_mvm_bt_coex_enable_esr(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, bool enable)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
lockdep_assert_held(&mvm->mutex);
if (!vif->cfg.assoc || !ieee80211_vif_is_mld(vif))
return;
/* Done already */
if ((mvmvif->esr_disable_reason & IWL_MVM_ESR_DISABLE_COEX) == !enable)
return;
if (enable)
mvmvif->esr_disable_reason &= ~IWL_MVM_ESR_DISABLE_COEX;
else
mvmvif->esr_disable_reason |= IWL_MVM_ESR_DISABLE_COEX;
iwl_mvm_recalc_esr(mvm, vif);
}
/*
* This function receives the LB link id and checks if eSR should be
* enabled or disabled (due to BT coex)
......@@ -320,7 +298,7 @@ iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm,
if (!link_rssi)
wifi_loss_rate = mvm->last_bt_notif.wifi_loss_mid_high_rssi;
else if (!(mvmvif->esr_disable_reason & IWL_MVM_ESR_DISABLE_COEX))
else if (!(mvmvif->esr_disable_reason & IWL_MVM_ESR_BLOCKED_COEX))
/* RSSI needs to get really low to disable eSR... */
wifi_loss_rate =
link_rssi <= -IWL_MVM_BT_COEX_DISABLE_ESR_THRESH ?
......@@ -348,7 +326,12 @@ void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm,
enable = iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif, link_id);
iwl_mvm_bt_coex_enable_esr(mvm, vif, enable);
if (enable)
iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_COEX);
else
/* In case we decided to exit eSR - stay with the primary */
iwl_mvm_block_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_COEX,
iwl_mvm_get_primary_link(vif));
}
static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm,
......@@ -534,7 +517,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
/* When BT is off this will be 0 */
if (data->notif->wifi_loss_low_rssi == BT_OFF)
iwl_mvm_bt_coex_enable_esr(mvm, vif, true);
iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_COEX);
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++)
iwl_mvm_bt_notif_per_link(mvm, vif, data, link_id);
......
......@@ -560,7 +560,7 @@ bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif,
/* BT Coex effects eSR mode only if one of the link is on LB */
if (a->band == NL80211_BAND_2GHZ || b->band == NL80211_BAND_2GHZ)
return !(mvmvif->esr_disable_reason & IWL_MVM_ESR_DISABLE_COEX);
return !(mvmvif->esr_disable_reason & IWL_MVM_ESR_BLOCKED_COEX);
return true;
}
......@@ -691,3 +691,72 @@ u8 iwl_mvm_get_primary_link(struct ieee80211_vif *vif)
return __ffs(vif->active_links);
}
/* API to exit eSR mode */
void iwl_mvm_exit_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum iwl_mvm_esr_state reason,
u8 link_to_keep)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u16 new_active_links;
lockdep_assert_held(&mvm->mutex);
/* Nothing to do */
if (!mvmvif->esr_active)
return;
if (WARN_ON(!ieee80211_vif_is_mld(vif) || !mvmvif->authorized))
return;
if (WARN_ON(!(vif->active_links & BIT(link_to_keep))))
link_to_keep = __ffs(vif->active_links);
new_active_links = BIT(link_to_keep);
IWL_DEBUG_INFO(mvm,
"Exiting EMLSR. Reason = 0x%x. Current active links=0x%x, new active links = 0x%x\n",
reason, vif->active_links, new_active_links);
ieee80211_set_active_links_async(vif, new_active_links);
}
#define IWL_MVM_BLOCK_ESR_REASONS IWL_MVM_ESR_BLOCKED_COEX
void iwl_mvm_block_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum iwl_mvm_esr_state reason,
u8 link_to_keep)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
lockdep_assert_held(&mvm->mutex);
/* This should be called only with disable reasons */
if (WARN_ON(!(reason & IWL_MVM_BLOCK_ESR_REASONS)))
return;
if (!(mvmvif->esr_disable_reason & reason))
IWL_DEBUG_INFO(mvm, "Blocking EMSLR mode. reason = 0x%x\n",
reason);
mvmvif->esr_disable_reason |= reason;
iwl_mvm_exit_esr(mvm, vif, reason, link_to_keep);
}
void iwl_mvm_unblock_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum iwl_mvm_esr_state reason)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
lockdep_assert_held(&mvm->mutex);
/* This should be called only with disable reasons */
if (WARN_ON(!(reason & IWL_MVM_BLOCK_ESR_REASONS)))
return;
if (mvmvif->esr_disable_reason & reason)
IWL_DEBUG_INFO(mvm, "Unblocking EMSLR mode. reason = 0x%x\n",
reason);
mvmvif->esr_disable_reason &= ~reason;
}
......@@ -1151,28 +1151,6 @@ iwl_mvm_mld_change_sta_links(struct ieee80211_hw *hw,
return ret;
}
void iwl_mvm_recalc_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
bool enable = !mvmvif->esr_disable_reason;
u16 new_active_links;
/* Nothing to do */
if (mvmvif->esr_active == enable)
return;
/* The next link selection will enter eSR if possible */
if (enable)
return;
/*
* Find the primary link, as we want to switch to it and drop the
* secondary one.
*/
new_active_links = BIT(iwl_mvm_get_primary_link(vif));
ieee80211_set_active_links_async(vif, new_active_links);
}
bool iwl_mvm_esr_allowed_on_vif(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
......@@ -1194,7 +1172,7 @@ bool iwl_mvm_esr_allowed_on_vif(struct iwl_mvm *mvm,
!(ext_capa->eml_capabilities & IEEE80211_EML_CAP_EMLSR_SUPP))
return false;
return !(mvmvif->esr_disable_reason & ~IWL_MVM_ESR_DISABLE_COEX);
return !(mvmvif->esr_disable_reason & ~IWL_MVM_ESR_BLOCKED_COEX);
}
/*
......
......@@ -346,11 +346,17 @@ struct iwl_mvm_vif_link_info {
};
/**
* enum iwl_mvm_esr_disable_reason - reasons for which we can't enable EMLSR
* @IWL_MVM_ESR_DISABLE_COEX: COEX is preventing the enablement of EMLSR
* enum iwl_mvm_esr_state - defines reasons for which the EMLSR is exited or
* blocked.
* The low 16 bits are used for blocking reasons, and the 16 higher bits
* are used for exit reasons.
* For the blocking reasons - use iwl_mvm_(un)block_esr(), and for the exit
* reasons - use iwl_mvm_exit_esr().
*
* @IWL_MVM_ESR_BLOCKED_COEX: COEX is preventing the enablement of EMLSR
*/
enum iwl_mvm_esr_disable_reason {
IWL_MVM_ESR_DISABLE_COEX = BIT(0),
enum iwl_mvm_esr_state {
IWL_MVM_ESR_BLOCKED_COEX = 0x1,
};
/**
......@@ -386,7 +392,7 @@ enum iwl_mvm_esr_disable_reason {
* @deflink: default link data for use in non-MLO
* @link: link data for each link in MLO
* @esr_active: indicates eSR mode is active
* @esr_disable_reason: a bitmap of enum iwl_mvm_esr_disable_reason
* @esr_disable_reason: a bitmap of &enum iwl_mvm_esr_state
* @pm_enabled: indicates powersave is enabled
* @link_selection_res: bitmap of active links as it was decided in the last
* link selection. Valid only for a MLO vif after assoc. 0 if there wasn't
......@@ -2836,8 +2842,15 @@ int iwl_mvm_roc_add_cmd(struct iwl_mvm *mvm,
int duration, u32 activity);
/* EMLSR */
void iwl_mvm_recalc_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
bool iwl_mvm_esr_allowed_on_vif(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
void iwl_mvm_block_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum iwl_mvm_esr_state reason,
u8 link_to_keep);
void iwl_mvm_unblock_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum iwl_mvm_esr_state reason);
void iwl_mvm_exit_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum iwl_mvm_esr_state reason,
u8 link_to_keep);
#endif /* __IWL_MVM_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment