Skip to content

Commit

Permalink
wifi: iwlwifi: mvm: move EMLSR/links code
Browse files Browse the repository at this point in the history
The functions that are link related, so they should be in link.c and
not in mld-mac80211.c. Move them.
Also move the different prototypes to the right place in mvm.h

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Link: https://msgid.link/20240416134215.e7c368256fa0.I6b15805a7c8a75d1814f1a829601daf4d3788731@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Miri Korenblit authored and Johannes Berg committed Apr 19, 2024
1 parent 287bc41 commit 1b9b7d3
Show file tree
Hide file tree
Showing 3 changed files with 228 additions and 222 deletions.
184 changes: 184 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/mvm/link.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,3 +501,187 @@ unsigned int iwl_mvm_get_link_grade(struct ieee80211_bss_conf *link_conf)
return grade;
}
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mvm_get_link_grade);

/*
* This function receives a subset of the usable links bitmap and
* returns the primary link id, and -1 if such link doesn't exist
* (e.g. non-MLO connection) or wasn't found.
*/
int iwl_mvm_mld_get_primary_link(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
unsigned long usable_links)
{
struct iwl_mvm_link_sel_data data[IEEE80211_MLD_MAX_NUM_LINKS];
u8 link_id, n_data = 0;

if (!ieee80211_vif_is_mld(vif) || !vif->cfg.assoc)
return -1;

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))
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 = true;
n_data++;
}

if (n_data <= 1)
return -1;

/* The logic should be modified to handle more than 2 links */
WARN_ON_ONCE(n_data > 2);

/* Primary link is the link with the wider bandwidth or higher band */
if (data[0].width > data[1].width)
return data[0].link_id;
if (data[0].width < data[1].width)
return data[1].link_id;
if (data[0].band >= data[1].band)
return data[0].link_id;

return data[1].link_id;
}

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;
}

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)
{
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;
}

void iwl_mvm_mld_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool valid_links_changed)
{
struct iwl_mvm_link_sel_data data[IEEE80211_MLD_MAX_NUM_LINKS];
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 n_data, i, j;

if (!IWL_MVM_AUTO_EML_ENABLE)
return;

/* The logic below is a simple version that doesn't suit more than 2
* links
*/
WARN_ON_ONCE(max_active_links > 2);

/* if only a single active link is supported, assume that the one
* selected by higher layer for connection establishment is the best.
*/
if (max_active_links == 1 && !valid_links_changed)
return;

/* If we are already using the maximal number of active links, don't do
* any change. This can later be optimized to pick a 'better' link pair.
*/
if (hweight16(vif->active_links) == max_active_links)
return;

if (!iwl_mvm_esr_allowed_on_vif(mvm, vif))
return;

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)
return;

new_active_links = 0;

/* Assume that after association only a single link is active, thus,
* select only the 2nd link
*/
if (!valid_links_changed) {
for (i = 0; i < n_data; i++) {
if (data[i].active)
break;
}

if (WARN_ON_ONCE(i == n_data))
return;

for (j = 0; j < n_data; j++) {
if (i == j)
continue;

if (iwl_mvm_mld_valid_link_pair(vif, &data[i],
&data[j]))
break;
}

if (j != n_data)
new_active_links = BIT(data[i].link_id) |
BIT(data[j].link_id);
} else {
/* Try to find a valid link pair for EMLSR operation. If a pair
* is not found continue using the current active link.
*/
for (i = 0; i < n_data; i++) {
for (j = 0; j < n_data; j++) {
if (i == j)
continue;

if (iwl_mvm_mld_valid_link_pair(vif, &data[i],
&data[j]))
break;
}

/* found a valid pair for EMLSR, use it */
if (j != n_data) {
new_active_links = BIT(data[i].link_id) |
BIT(data[j].link_id);
break;
}
}
}

if (!new_active_links)
return;

if (vif->active_links != new_active_links)
ieee80211_set_active_links_async(vif, new_active_links);
}
Loading

0 comments on commit 1b9b7d3

Please sign in to comment.