Commit 72c19df2 authored by Miri Korenblit's avatar Miri Korenblit Committed by Johannes Berg

wifi: iwlwifi: cleanup EMLSR when BT is active handling

BT Coex disables EMLSR only for a 2.4 GHz link, but doesn't block the
vif from using EMLSR with a different link pair. In addition, storing it
in mvmvif:disable_esr_reason requires extracting the BT Coex bit before
checking if EMLSR is blocked or not for a specific vif.

Therefore, change the BT Coex bit to be an exit reason and not a
blocker. On link selection, EMLSR mode will be re-calculated for the 2.4
GHz link instead of checking that bit.

While at it, move the relevant function declarations to the EMLSR
functions area in mvm.h
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240505091420.a2e93b67c895.I183a0039ef076613144648cc46fbe9ab3d47c574@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 2f324144
...@@ -257,38 +257,28 @@ static void iwl_mvm_bt_coex_tcm_based_ci(struct iwl_mvm *mvm, ...@@ -257,38 +257,28 @@ static void iwl_mvm_bt_coex_tcm_based_ci(struct iwl_mvm *mvm,
* This function receives the LB link id and checks if eSR should be * This function receives the LB link id and checks if eSR should be
* enabled or disabled (due to BT coex) * enabled or disabled (due to BT coex)
*/ */
static bool bool
iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm, iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
int link_id) s32 link_rssi,
bool primary)
{ {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
bool have_wifi_loss_rate = bool have_wifi_loss_rate =
iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
BT_PROFILE_NOTIFICATION, 0) > 4; BT_PROFILE_NOTIFICATION, 0) > 4;
s8 link_rssi = 0;
u8 wifi_loss_rate; u8 wifi_loss_rate;
lockdep_assert_held(&mvm->mutex);
if (mvm->last_bt_notif.wifi_loss_low_rssi == BT_OFF) if (mvm->last_bt_notif.wifi_loss_low_rssi == BT_OFF)
return true; return true;
/* If LB link is the primary one we should always disable eSR */ if (primary)
if (link_id == iwl_mvm_get_primary_link(vif))
return false; return false;
/* The feature is not supported */ /* The feature is not supported */
if (!have_wifi_loss_rate) if (!have_wifi_loss_rate)
return true; return true;
/*
* We might not have a link_info when checking whether we can
* (re)enable eSR - the LB link might not exist yet
*/
if (link_info)
link_rssi = (s8)link_info->beacon_stats.avg_signal;
/* /*
* In case we don't know the RSSI - take the lower wifi loss, * In case we don't know the RSSI - take the lower wifi loss,
...@@ -298,7 +288,7 @@ iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm, ...@@ -298,7 +288,7 @@ iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm,
if (!link_rssi) if (!link_rssi)
wifi_loss_rate = mvm->last_bt_notif.wifi_loss_mid_high_rssi; wifi_loss_rate = mvm->last_bt_notif.wifi_loss_mid_high_rssi;
else if (!(mvmvif->esr_disable_reason & IWL_MVM_ESR_BLOCKED_COEX)) else if (mvmvif->esr_active)
/* RSSI needs to get really low to disable eSR... */ /* RSSI needs to get really low to disable eSR... */
wifi_loss_rate = wifi_loss_rate =
link_rssi <= -IWL_MVM_BT_COEX_DISABLE_ESR_THRESH ? link_rssi <= -IWL_MVM_BT_COEX_DISABLE_ESR_THRESH ?
...@@ -318,20 +308,20 @@ void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm, ...@@ -318,20 +308,20 @@ void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
int link_id) int link_id)
{ {
bool enable; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_vif_link_info *link = mvmvif->link[link_id];
if (!ieee80211_vif_is_mld(vif) || if (!ieee80211_vif_is_mld(vif) ||
!iwl_mvm_vif_from_mac80211(vif)->authorized) !iwl_mvm_vif_from_mac80211(vif)->authorized ||
WARN_ON(!link))
return; return;
enable = iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif, link_id); if (!iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif,
(s8)link->beacon_stats.avg_signal,
if (enable) link_id == iwl_mvm_get_primary_link(vif)))
iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_COEX);
else
/* In case we decided to exit eSR - stay with the primary */ /* In case we decided to exit eSR - stay with the primary */
iwl_mvm_block_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_COEX, iwl_mvm_exit_esr(mvm, vif, IWL_MVM_ESR_EXIT_COEX,
iwl_mvm_get_primary_link(vif)); iwl_mvm_get_primary_link(vif));
} }
static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm, static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm,
...@@ -515,10 +505,6 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, ...@@ -515,10 +505,6 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
return; return;
} }
/* When BT is off this will be 0 */
if (data->notif->wifi_loss_low_rssi == BT_OFF)
iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_COEX);
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++)
iwl_mvm_bt_notif_per_link(mvm, vif, data, link_id); iwl_mvm_bt_notif_per_link(mvm, vif, data, link_id);
} }
......
...@@ -592,7 +592,8 @@ s8 iwl_mvm_get_esr_rssi_thresh(struct iwl_mvm *mvm, ...@@ -592,7 +592,8 @@ s8 iwl_mvm_get_esr_rssi_thresh(struct iwl_mvm *mvm,
static u32 static u32
iwl_mvm_esr_disallowed_with_link(struct ieee80211_vif *vif, iwl_mvm_esr_disallowed_with_link(struct ieee80211_vif *vif,
const struct iwl_mvm_link_sel_data *link) const struct iwl_mvm_link_sel_data *link,
bool primary)
{ {
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm *mvm = mvmvif->mvm; struct iwl_mvm *mvm = mvmvif->mvm;
...@@ -601,8 +602,10 @@ iwl_mvm_esr_disallowed_with_link(struct ieee80211_vif *vif, ...@@ -601,8 +602,10 @@ iwl_mvm_esr_disallowed_with_link(struct ieee80211_vif *vif,
/* BT Coex effects eSR mode only if one of the links is on LB */ /* BT Coex effects eSR mode only if one of the links is on LB */
if (link->chandef->chan->band == NL80211_BAND_2GHZ && if (link->chandef->chan->band == NL80211_BAND_2GHZ &&
mvmvif->esr_disable_reason & IWL_MVM_ESR_BLOCKED_COEX) (!iwl_mvm_bt_coex_calculate_esr_mode(mvm, vif, link->signal,
ret |= IWL_MVM_ESR_BLOCKED_COEX; primary)))
ret |= IWL_MVM_ESR_EXIT_COEX;
thresh = iwl_mvm_get_esr_rssi_thresh(mvm, link->chandef, thresh = iwl_mvm_get_esr_rssi_thresh(mvm, link->chandef,
false); false);
...@@ -622,8 +625,8 @@ bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif, ...@@ -622,8 +625,8 @@ bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif,
const struct iwl_mvm_link_sel_data *b) const struct iwl_mvm_link_sel_data *b)
{ {
/* Per-link considerations */ /* Per-link considerations */
if (iwl_mvm_esr_disallowed_with_link(vif, a) || if (iwl_mvm_esr_disallowed_with_link(vif, a, true) ||
iwl_mvm_esr_disallowed_with_link(vif, b)) iwl_mvm_esr_disallowed_with_link(vif, b, false))
return false; return false;
/* Per-combination considerations */ /* Per-combination considerations */
......
...@@ -3877,23 +3877,6 @@ iwl_mvm_sta_state_auth_to_assoc(struct ieee80211_hw *hw, ...@@ -3877,23 +3877,6 @@ iwl_mvm_sta_state_auth_to_assoc(struct ieee80211_hw *hw,
return callbacks->update_sta(mvm, vif, sta); return callbacks->update_sta(mvm, vif, sta);
} }
static void iwl_mvm_bt_coex_update_vif_esr(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
unsigned long usable_links = ieee80211_vif_usable_links(vif);
u8 link_id;
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
struct ieee80211_bss_conf *link_conf =
link_conf_dereference_protected(vif, link_id);
if (WARN_ON_ONCE(!link_conf))
return;
if (link_conf->chanreq.oper.chan->band == NL80211_BAND_2GHZ)
iwl_mvm_bt_coex_update_link_esr(mvm, vif, link_id);
}
}
static int static int
iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm, iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm,
...@@ -3928,9 +3911,6 @@ iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm, ...@@ -3928,9 +3911,6 @@ iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm,
memset(&mvmvif->last_esr_exit, 0, memset(&mvmvif->last_esr_exit, 0,
sizeof(mvmvif->last_esr_exit)); sizeof(mvmvif->last_esr_exit));
/* Calculate eSR mode due to BT coex */
iwl_mvm_bt_coex_update_vif_esr(mvm, vif);
/* when client is authorized (AP station marked as such), /* when client is authorized (AP station marked as such),
* try to enable the best link(s). * try to enable the best link(s).
*/ */
......
...@@ -1180,7 +1180,7 @@ bool iwl_mvm_esr_allowed_on_vif(struct iwl_mvm *mvm, ...@@ -1180,7 +1180,7 @@ bool iwl_mvm_esr_allowed_on_vif(struct iwl_mvm *mvm,
!(ext_capa->eml_capabilities & IEEE80211_EML_CAP_EMLSR_SUPP)) !(ext_capa->eml_capabilities & IEEE80211_EML_CAP_EMLSR_SUPP))
return false; return false;
return !(mvmvif->esr_disable_reason & ~IWL_MVM_ESR_BLOCKED_COEX); return !mvmvif->esr_disable_reason;
} }
static bool iwl_mvm_mld_can_activate_links(struct ieee80211_hw *hw, static bool iwl_mvm_mld_can_activate_links(struct ieee80211_hw *hw,
......
...@@ -353,20 +353,21 @@ struct iwl_mvm_vif_link_info { ...@@ -353,20 +353,21 @@ struct iwl_mvm_vif_link_info {
* For the blocking reasons - use iwl_mvm_(un)block_esr(), and for the exit * For the blocking reasons - use iwl_mvm_(un)block_esr(), and for the exit
* reasons - use iwl_mvm_exit_esr(). * reasons - use iwl_mvm_exit_esr().
* *
* @IWL_MVM_ESR_BLOCKED_COEX: COEX is preventing the enablement of EMLSR
* @IWL_MVM_ESR_BLOCKED_PREVENTION: Prevent EMLSR to avoid entering and exiting * @IWL_MVM_ESR_BLOCKED_PREVENTION: Prevent EMLSR to avoid entering and exiting
* in a loop. * in a loop.
* @IWL_MVM_ESR_BLOCKED_WOWLAN: WOWLAN is preventing the enablement of EMLSR * @IWL_MVM_ESR_BLOCKED_WOWLAN: WOWLAN is preventing the enablement of EMLSR
* @IWL_MVM_ESR_EXIT_MISSED_BEACON: exited EMLSR due to missed beacons * @IWL_MVM_ESR_EXIT_MISSED_BEACON: exited EMLSR due to missed beacons
* @IWL_MVM_ESR_EXIT_LOW_RSSI: link is deactivated/not allowed for EMLSR * @IWL_MVM_ESR_EXIT_LOW_RSSI: link is deactivated/not allowed for EMLSR
* due to low RSSI. * due to low RSSI.
* @IWL_MVM_ESR_EXIT_COEX: link is deactivated/not allowed for EMLSR
* due to BT Coex.
*/ */
enum iwl_mvm_esr_state { enum iwl_mvm_esr_state {
IWL_MVM_ESR_BLOCKED_COEX = 0x1, IWL_MVM_ESR_BLOCKED_PREVENTION = 0x1,
IWL_MVM_ESR_BLOCKED_PREVENTION = 0x2, IWL_MVM_ESR_BLOCKED_WOWLAN = 0x2,
IWL_MVM_ESR_BLOCKED_WOWLAN = 0x4,
IWL_MVM_ESR_EXIT_MISSED_BEACON = 0x10000, IWL_MVM_ESR_EXIT_MISSED_BEACON = 0x10000,
IWL_MVM_ESR_EXIT_LOW_RSSI = 0x20000, IWL_MVM_ESR_EXIT_LOW_RSSI = 0x20000,
IWL_MVM_ESR_EXIT_COEX = 0x40000,
}; };
#define IWL_MVM_BLOCK_ESR_REASONS 0xffff #define IWL_MVM_BLOCK_ESR_REASONS 0xffff
...@@ -2221,9 +2222,6 @@ bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm, ...@@ -2221,9 +2222,6 @@ bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
u8 iwl_mvm_bt_coex_get_single_ant_msk(struct iwl_mvm *mvm, u8 enabled_ants); u8 iwl_mvm_bt_coex_get_single_ant_msk(struct iwl_mvm *mvm, u8 enabled_ants);
u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *info, u8 ac); struct ieee80211_tx_info *info, u8 ac);
void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
int link_id);
/* beacon filtering */ /* beacon filtering */
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
...@@ -2888,5 +2886,12 @@ void iwl_mvm_exit_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -2888,5 +2886,12 @@ void iwl_mvm_exit_esr(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
s8 iwl_mvm_get_esr_rssi_thresh(struct iwl_mvm *mvm, s8 iwl_mvm_get_esr_rssi_thresh(struct iwl_mvm *mvm,
const struct cfg80211_chan_def *chandef, const struct cfg80211_chan_def *chandef,
bool low); bool low);
void iwl_mvm_bt_coex_update_link_esr(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
int link_id);
bool
iwl_mvm_bt_coex_calculate_esr_mode(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
s32 link_rssi,
bool primary);
#endif /* __IWL_MVM_H__ */ #endif /* __IWL_MVM_H__ */
...@@ -37,7 +37,20 @@ static struct cfg80211_bss bss = {}; ...@@ -37,7 +37,20 @@ static struct cfg80211_bss bss = {};
static struct ieee80211_bss_conf link_conf = {.bss = &bss}; static struct ieee80211_bss_conf link_conf = {.bss = &bss};
static struct iwl_mvm mvm = {}; static const struct iwl_fw_cmd_version entry = {
.group = LEGACY_GROUP,
.cmd = BT_PROFILE_NOTIFICATION,
.notif_ver = 4
};
static struct iwl_fw fw = {
.ucode_capa = {
.n_cmd_versions = 1,
.cmd_versions = &entry,
},
};
static struct iwl_mvm mvm = {.fw = &fw};
static const struct link_grading_case { static const struct link_grading_case {
const char *desc; const char *desc;
...@@ -217,7 +230,7 @@ kunit_test_suite(link_grading); ...@@ -217,7 +230,7 @@ kunit_test_suite(link_grading);
static const struct valid_link_pair_case { static const struct valid_link_pair_case {
const char *desc; const char *desc;
u32 esr_disable_reason; bool bt;
struct ieee80211_channel *chan_a; struct ieee80211_channel *chan_a;
struct ieee80211_channel *chan_b; struct ieee80211_channel *chan_b;
enum nl80211_chan_width cw_a; enum nl80211_chan_width cw_a;
...@@ -240,7 +253,7 @@ static const struct valid_link_pair_case { ...@@ -240,7 +253,7 @@ static const struct valid_link_pair_case {
}, },
{ {
.desc = "LB + HB, with BT.", .desc = "LB + HB, with BT.",
.esr_disable_reason = 0x1, .bt = true,
.chan_a = &chan_2ghz, .chan_a = &chan_2ghz,
.chan_b = &chan_5ghz, .chan_b = &chan_5ghz,
.valid = false, .valid = false,
...@@ -370,7 +383,7 @@ static void test_valid_link_pair(struct kunit *test) ...@@ -370,7 +383,7 @@ static void test_valid_link_pair(struct kunit *test)
#endif #endif
mvm.trans = trans; mvm.trans = trans;
mvmvif->esr_disable_reason = params->esr_disable_reason; mvm.last_bt_notif.wifi_loss_low_rssi = params->bt;
mvmvif->mvm = &mvm; mvmvif->mvm = &mvm;
result = iwl_mvm_mld_valid_link_pair(vif, &link_a, &link_b); result = iwl_mvm_mld_valid_link_pair(vif, &link_a, &link_b);
......
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