mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 07:03:03 +02:00
wifi: mt76: mt7996: Enable MLO support for client interfaces
Report MT7996 MLO STA capabilities to mac80211 stack. Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Link: https://patch.msgid.link/20250901-mt7996-enable-mlo-client-v1-1-50c46317325d@kernel.org Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
24e2846f15
commit
f5160304d5
|
|
@ -2060,3 +2060,55 @@ void mt76_vif_cleanup(struct mt76_dev *dev, struct ieee80211_vif *vif)
|
|||
mt76_abort_roc(mvif->roc_phy);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_vif_cleanup);
|
||||
|
||||
u16 mt76_select_links(struct ieee80211_vif *vif, int max_active_links)
|
||||
{
|
||||
unsigned long usable_links = ieee80211_vif_usable_links(vif);
|
||||
struct {
|
||||
u8 link_id;
|
||||
enum nl80211_band band;
|
||||
} data[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
unsigned int link_id;
|
||||
int i, n_data = 0;
|
||||
u16 sel_links = 0;
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif))
|
||||
return 0;
|
||||
|
||||
if (vif->active_links == usable_links)
|
||||
return vif->active_links;
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
struct ieee80211_bss_conf *link_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;
|
||||
n_data++;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
for (i = 0; i < n_data; i++) {
|
||||
int j;
|
||||
|
||||
if (!(BIT(data[i].link_id) & vif->active_links))
|
||||
continue;
|
||||
|
||||
sel_links = BIT(data[i].link_id);
|
||||
for (j = 0; j < n_data; j++) {
|
||||
if (data[i].band != data[j].band) {
|
||||
sel_links |= BIT(data[j].link_id);
|
||||
if (hweight16(sel_links) == max_active_links)
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return sel_links;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_select_links);
|
||||
|
|
|
|||
|
|
@ -1872,6 +1872,7 @@ mt76_vif_init(struct ieee80211_vif *vif, struct mt76_vif_data *mvif)
|
|||
}
|
||||
|
||||
void mt76_vif_cleanup(struct mt76_dev *dev, struct ieee80211_vif *vif);
|
||||
u16 mt76_select_links(struct ieee80211_vif *vif, int max_active_links);
|
||||
|
||||
static inline struct mt76_vif_link *
|
||||
mt76_vif_link(struct mt76_dev *dev, struct ieee80211_vif *vif, int link_id)
|
||||
|
|
|
|||
|
|
@ -988,56 +988,6 @@ int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mt7925_mac_sta_add);
|
||||
|
||||
static u16
|
||||
mt7925_mac_select_links(struct mt76_dev *mdev, struct ieee80211_vif *vif)
|
||||
{
|
||||
unsigned long usable_links = ieee80211_vif_usable_links(vif);
|
||||
struct {
|
||||
u8 link_id;
|
||||
enum nl80211_band band;
|
||||
} data[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
u8 link_id, i, j, n_data = 0;
|
||||
u16 sel_links = 0;
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif))
|
||||
return 0;
|
||||
|
||||
if (vif->active_links == usable_links)
|
||||
return vif->active_links;
|
||||
|
||||
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;
|
||||
n_data++;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
for (i = 0; i < n_data; i++) {
|
||||
if (!(BIT(data[i].link_id) & vif->active_links))
|
||||
continue;
|
||||
|
||||
sel_links = BIT(data[i].link_id);
|
||||
|
||||
for (j = 0; j < n_data; j++) {
|
||||
if (data[i].band != data[j].band) {
|
||||
sel_links |= BIT(data[j].link_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return sel_links;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7925_mac_set_links(struct mt76_dev *mdev, struct ieee80211_vif *vif)
|
||||
{
|
||||
|
|
@ -1048,7 +998,7 @@ mt7925_mac_set_links(struct mt76_dev *mdev, struct ieee80211_vif *vif)
|
|||
struct cfg80211_chan_def *chandef = &link_conf->chanreq.oper;
|
||||
enum nl80211_band band = chandef->chan->band, secondary_band;
|
||||
|
||||
u16 sel_links = mt7925_mac_select_links(mdev, vif);
|
||||
u16 sel_links = mt76_select_links(vif, 2);
|
||||
u8 secondary_link_id = __ffs(~BIT(mvif->deflink_id) & sel_links);
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif) || hweight16(sel_links) < 2)
|
||||
|
|
|
|||
|
|
@ -79,6 +79,14 @@ static const struct wiphy_iftype_ext_capab iftypes_ext_capa[] = {
|
|||
.mld_capa_and_ops =
|
||||
FIELD_PREP_CONST(IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS,
|
||||
MT7996_MAX_RADIOS - 1),
|
||||
}, {
|
||||
.iftype = NL80211_IFTYPE_STATION,
|
||||
.extended_capabilities = if_types_ext_capa_ap,
|
||||
.extended_capabilities_mask = if_types_ext_capa_ap,
|
||||
.extended_capabilities_len = sizeof(if_types_ext_capa_ap),
|
||||
.mld_capa_and_ops =
|
||||
FIELD_PREP_CONST(IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS,
|
||||
MT7996_MAX_RADIOS - 1),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1220,6 +1220,24 @@ mt7996_mac_sta_remove(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
|||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_set_active_links(struct ieee80211_vif *vif)
|
||||
{
|
||||
u16 active_links;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
active_links = mt76_select_links(vif, MT7996_MAX_RADIOS);
|
||||
if (hweight16(active_links) < 2)
|
||||
return;
|
||||
|
||||
ieee80211_set_active_links_async(vif, active_links);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7996_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, enum ieee80211_sta_state old_state,
|
||||
|
|
@ -1237,16 +1255,18 @@ mt7996_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
mt7996_mac_sta_remove(dev, vif, sta);
|
||||
|
||||
if (old_state == IEEE80211_STA_AUTH &&
|
||||
new_state == IEEE80211_STA_ASSOC)
|
||||
new_state == IEEE80211_STA_ASSOC) {
|
||||
mt7996_set_active_links(vif);
|
||||
ev = MT76_STA_EVENT_ASSOC;
|
||||
else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTHORIZED)
|
||||
} else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTHORIZED) {
|
||||
ev = MT76_STA_EVENT_AUTHORIZE;
|
||||
else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTH)
|
||||
} else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTH) {
|
||||
ev = MT76_STA_EVENT_DISASSOC;
|
||||
else
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mt7996_mac_sta_event(dev, vif, sta, ev);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user