Commit 585ba158 authored by Miri Korenblit's avatar Miri Korenblit Committed by Johannes Berg

wifi: iwlwifi: mvm: don't always disable EMLSR due to BT coex

2.4 GHz/LB (low band) link can't be used in an EMLSR links pair when
BT is on. But EMLSR is still allowed for a pair of links which none of
them operates in LB.
In the existing code, EMLSR will always be disabled if one of the
usable links is in LB (and BT is on).
Move this check to the code that verifies a specific pair of links,
and only if one of these links operates on LB - disable EMLSR.

Fixes: 10159a45 ("wifi: iwlwifi: disable eSR when BT is active")
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240416134215.2841006b5cc4.I45ffd583f593daa950322852ceb9454cbf497e24@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 9c692112
......@@ -652,10 +652,49 @@ struct iwl_mvm_link_sel_data {
bool active;
};
static bool iwl_mvm_mld_valid_link_pair(struct iwl_mvm_link_sel_data *a,
static bool iwl_mvm_mld_valid_link_pair(struct ieee80211_vif *vif,
struct iwl_mvm_link_sel_data *a,
struct iwl_mvm_link_sel_data *b)
{
return a->band != b->band;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
if (a->band == b->band)
return false;
/* 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 true;
}
static u8
iwl_mvm_set_link_selection_data(struct ieee80211_vif *vif,
struct iwl_mvm_link_sel_data *data,
unsigned long usable_links)
{
u8 n_data = 0;
unsigned long link_id;
rcu_read_lock();
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
struct ieee80211_bss_conf *link_conf =
rcu_dereference(vif->link_conf[link_id]);
if (WARN_ON_ONCE(!link_conf))
continue;
data[n_data].link_id = link_id;
data[n_data].band = link_conf->chanreq.oper.chan->band;
data[n_data].width = link_conf->chanreq.oper.width;
data[n_data].active = vif->active_links & BIT(link_id);
n_data++;
}
rcu_read_unlock();
return n_data;
}
void iwl_mvm_mld_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
......@@ -665,7 +704,7 @@ void iwl_mvm_mld_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
unsigned long usable_links = ieee80211_vif_usable_links(vif);
u32 max_active_links = iwl_mvm_max_active_links(mvm, vif);
u16 new_active_links;
u8 link_id, n_data = 0, i, j;
u8 n_data, i, j;
if (!IWL_MVM_AUTO_EML_ENABLE)
return;
......@@ -690,23 +729,7 @@ void iwl_mvm_mld_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (hweight16(vif->active_links) == max_active_links)
return;
rcu_read_lock();
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
struct ieee80211_bss_conf *link_conf =
rcu_dereference(vif->link_conf[link_id]);
if (WARN_ON_ONCE(!link_conf))
continue;
data[n_data].link_id = link_id;
data[n_data].band = link_conf->chanreq.oper.chan->band;
data[n_data].width = link_conf->chanreq.oper.width;
data[n_data].active = vif->active_links & BIT(link_id);
n_data++;
}
rcu_read_unlock();
n_data = iwl_mvm_set_link_selection_data(vif, data, usable_links);
/* this is expected to be the current active link */
if (n_data == 1)
......@@ -730,7 +753,8 @@ void iwl_mvm_mld_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (i == j)
continue;
if (iwl_mvm_mld_valid_link_pair(&data[i], &data[j]))
if (iwl_mvm_mld_valid_link_pair(vif, &data[i],
&data[j]))
break;
}
......@@ -746,7 +770,7 @@ void iwl_mvm_mld_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (i == j)
continue;
if (iwl_mvm_mld_valid_link_pair(&data[i],
if (iwl_mvm_mld_valid_link_pair(vif, &data[i],
&data[j]))
break;
}
......@@ -1343,11 +1367,10 @@ static bool iwl_mvm_can_enter_esr(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
unsigned long desired_links)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
u16 usable_links = ieee80211_vif_usable_links(vif);
struct iwl_mvm_link_sel_data data[IEEE80211_MLD_MAX_NUM_LINKS];
const struct wiphy_iftype_ext_capab *ext_capa;
bool ret = true;
int link_id;
u8 n_data;
if (!ieee80211_vif_is_mld(vif) || !vif->cfg.assoc ||
hweight16(usable_links) <= 1)
......@@ -1362,21 +1385,13 @@ static bool iwl_mvm_can_enter_esr(struct iwl_mvm *mvm,
!(ext_capa->eml_capabilities & IEEE80211_EML_CAP_EMLSR_SUPP))
return false;
for_each_set_bit(link_id, &desired_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))
continue;
n_data = iwl_mvm_set_link_selection_data(vif, data, desired_links);
/* BT Coex effects eSR mode only if one of the link is on LB */
if (link_conf->chanreq.oper.chan->band != NL80211_BAND_2GHZ)
continue;
if (n_data != 2)
return false;
return !(mvmvif->esr_disable_reason & IWL_MVM_ESR_DISABLE_COEX);
}
return ret;
return iwl_mvm_mld_valid_link_pair(vif, &data[0], &data[1]);
}
static bool iwl_mvm_mld_can_activate_links(struct ieee80211_hw *hw,
......
......@@ -1589,15 +1589,14 @@ static inline int iwl_mvm_max_active_links(struct iwl_mvm *mvm,
struct iwl_trans *trans = mvm->fwrt.trans;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
lockdep_assert_held(&mvm->mutex);
if (vif->type == NL80211_IFTYPE_AP)
return mvm->fw->ucode_capa.num_beacons;
/* Check if HW supports eSR or STR */
if ((iwl_mvm_is_esr_supported(trans) &&
!mvmvif->esr_disable_reason) ||
((CSR_HW_RFID_TYPE(trans->hw_rf_id) == IWL_CFG_RF_TYPE_FM &&
CSR_HW_RFID_IS_CDB(trans->hw_rf_id))))
!(mvmvif->esr_disable_reason & ~IWL_MVM_ESR_DISABLE_COEX)) ||
(CSR_HW_RFID_TYPE(trans->hw_rf_id) == IWL_CFG_RF_TYPE_FM &&
CSR_HW_RFID_IS_CDB(trans->hw_rf_id)))
return IWL_MVM_FW_MAX_ACTIVE_LINKS_NUM;
return 1;
......
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