Skip to content

Commit 336c7d6

Browse files
LorenzoBianconinbd168
authored andcommitted
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>
1 parent d66b95c commit 336c7d6

5 files changed

Lines changed: 88 additions & 57 deletions

File tree

drivers/net/wireless/mediatek/mt76/mac80211.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,3 +2019,55 @@ void mt76_vif_cleanup(struct mt76_dev *dev, struct ieee80211_vif *vif)
20192019
mt76_abort_roc(mvif->roc_phy);
20202020
}
20212021
EXPORT_SYMBOL_GPL(mt76_vif_cleanup);
2022+
2023+
u16 mt76_select_links(struct ieee80211_vif *vif, int max_active_links)
2024+
{
2025+
unsigned long usable_links = ieee80211_vif_usable_links(vif);
2026+
struct {
2027+
u8 link_id;
2028+
enum nl80211_band band;
2029+
} data[IEEE80211_MLD_MAX_NUM_LINKS];
2030+
unsigned int link_id;
2031+
int i, n_data = 0;
2032+
u16 sel_links = 0;
2033+
2034+
if (!ieee80211_vif_is_mld(vif))
2035+
return 0;
2036+
2037+
if (vif->active_links == usable_links)
2038+
return vif->active_links;
2039+
2040+
rcu_read_lock();
2041+
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
2042+
struct ieee80211_bss_conf *link_conf;
2043+
2044+
link_conf = rcu_dereference(vif->link_conf[link_id]);
2045+
if (WARN_ON_ONCE(!link_conf))
2046+
continue;
2047+
2048+
data[n_data].link_id = link_id;
2049+
data[n_data].band = link_conf->chanreq.oper.chan->band;
2050+
n_data++;
2051+
}
2052+
rcu_read_unlock();
2053+
2054+
for (i = 0; i < n_data; i++) {
2055+
int j;
2056+
2057+
if (!(BIT(data[i].link_id) & vif->active_links))
2058+
continue;
2059+
2060+
sel_links = BIT(data[i].link_id);
2061+
for (j = 0; j < n_data; j++) {
2062+
if (data[i].band != data[j].band) {
2063+
sel_links |= BIT(data[j].link_id);
2064+
if (hweight16(sel_links) == max_active_links)
2065+
break;
2066+
}
2067+
}
2068+
break;
2069+
}
2070+
2071+
return sel_links;
2072+
}
2073+
EXPORT_SYMBOL_GPL(mt76_select_links);

drivers/net/wireless/mediatek/mt76/mt76.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1871,6 +1871,7 @@ mt76_vif_init(struct ieee80211_vif *vif, struct mt76_vif_data *mvif)
18711871
}
18721872

18731873
void mt76_vif_cleanup(struct mt76_dev *dev, struct ieee80211_vif *vif);
1874+
u16 mt76_select_links(struct ieee80211_vif *vif, int max_active_links);
18741875

18751876
static inline struct mt76_vif_link *
18761877
mt76_vif_link(struct mt76_dev *dev, struct ieee80211_vif *vif, int link_id)

drivers/net/wireless/mediatek/mt76/mt7925/main.c

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -988,56 +988,6 @@ int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
988988
}
989989
EXPORT_SYMBOL_GPL(mt7925_mac_sta_add);
990990

991-
static u16
992-
mt7925_mac_select_links(struct mt76_dev *mdev, struct ieee80211_vif *vif)
993-
{
994-
unsigned long usable_links = ieee80211_vif_usable_links(vif);
995-
struct {
996-
u8 link_id;
997-
enum nl80211_band band;
998-
} data[IEEE80211_MLD_MAX_NUM_LINKS];
999-
u8 link_id, i, j, n_data = 0;
1000-
u16 sel_links = 0;
1001-
1002-
if (!ieee80211_vif_is_mld(vif))
1003-
return 0;
1004-
1005-
if (vif->active_links == usable_links)
1006-
return vif->active_links;
1007-
1008-
rcu_read_lock();
1009-
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
1010-
struct ieee80211_bss_conf *link_conf =
1011-
rcu_dereference(vif->link_conf[link_id]);
1012-
1013-
if (WARN_ON_ONCE(!link_conf))
1014-
continue;
1015-
1016-
data[n_data].link_id = link_id;
1017-
data[n_data].band = link_conf->chanreq.oper.chan->band;
1018-
n_data++;
1019-
}
1020-
rcu_read_unlock();
1021-
1022-
for (i = 0; i < n_data; i++) {
1023-
if (!(BIT(data[i].link_id) & vif->active_links))
1024-
continue;
1025-
1026-
sel_links = BIT(data[i].link_id);
1027-
1028-
for (j = 0; j < n_data; j++) {
1029-
if (data[i].band != data[j].band) {
1030-
sel_links |= BIT(data[j].link_id);
1031-
break;
1032-
}
1033-
}
1034-
1035-
break;
1036-
}
1037-
1038-
return sel_links;
1039-
}
1040-
1041991
static void
1042992
mt7925_mac_set_links(struct mt76_dev *mdev, struct ieee80211_vif *vif)
1043993
{
@@ -1048,7 +998,7 @@ mt7925_mac_set_links(struct mt76_dev *mdev, struct ieee80211_vif *vif)
1048998
struct cfg80211_chan_def *chandef = &link_conf->chanreq.oper;
1049999
enum nl80211_band band = chandef->chan->band, secondary_band;
10501000

1051-
u16 sel_links = mt7925_mac_select_links(mdev, vif);
1001+
u16 sel_links = mt76_select_links(vif, 2);
10521002
u8 secondary_link_id = __ffs(~BIT(mvif->deflink_id) & sel_links);
10531003

10541004
if (!ieee80211_vif_is_mld(vif) || hweight16(sel_links) < 2)

drivers/net/wireless/mediatek/mt76/mt7996/init.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ static const struct wiphy_iftype_ext_capab iftypes_ext_capa[] = {
7979
.mld_capa_and_ops =
8080
FIELD_PREP_CONST(IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS,
8181
MT7996_MAX_RADIOS - 1),
82+
}, {
83+
.iftype = NL80211_IFTYPE_STATION,
84+
.extended_capabilities = if_types_ext_capa_ap,
85+
.extended_capabilities_mask = if_types_ext_capa_ap,
86+
.extended_capabilities_len = sizeof(if_types_ext_capa_ap),
87+
.mld_capa_and_ops =
88+
FIELD_PREP_CONST(IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS,
89+
MT7996_MAX_RADIOS - 1),
8290
},
8391
};
8492

drivers/net/wireless/mediatek/mt76/mt7996/main.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,24 @@ mt7996_mac_sta_remove(struct mt7996_dev *dev, struct ieee80211_vif *vif,
12131213
mutex_unlock(&dev->mt76.mutex);
12141214
}
12151215

1216+
static void
1217+
mt7996_set_active_links(struct ieee80211_vif *vif)
1218+
{
1219+
u16 active_links;
1220+
1221+
if (vif->type != NL80211_IFTYPE_STATION)
1222+
return;
1223+
1224+
if (!ieee80211_vif_is_mld(vif))
1225+
return;
1226+
1227+
active_links = mt76_select_links(vif, MT7996_MAX_RADIOS);
1228+
if (hweight16(active_links) < 2)
1229+
return;
1230+
1231+
ieee80211_set_active_links_async(vif, active_links);
1232+
}
1233+
12161234
static int
12171235
mt7996_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
12181236
struct ieee80211_sta *sta, enum ieee80211_sta_state old_state,
@@ -1230,16 +1248,18 @@ mt7996_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
12301248
mt7996_mac_sta_remove(dev, vif, sta);
12311249

12321250
if (old_state == IEEE80211_STA_AUTH &&
1233-
new_state == IEEE80211_STA_ASSOC)
1251+
new_state == IEEE80211_STA_ASSOC) {
1252+
mt7996_set_active_links(vif);
12341253
ev = MT76_STA_EVENT_ASSOC;
1235-
else if (old_state == IEEE80211_STA_ASSOC &&
1236-
new_state == IEEE80211_STA_AUTHORIZED)
1254+
} else if (old_state == IEEE80211_STA_ASSOC &&
1255+
new_state == IEEE80211_STA_AUTHORIZED) {
12371256
ev = MT76_STA_EVENT_AUTHORIZE;
1238-
else if (old_state == IEEE80211_STA_ASSOC &&
1239-
new_state == IEEE80211_STA_AUTH)
1257+
} else if (old_state == IEEE80211_STA_ASSOC &&
1258+
new_state == IEEE80211_STA_AUTH) {
12401259
ev = MT76_STA_EVENT_DISASSOC;
1241-
else
1260+
} else {
12421261
return 0;
1262+
}
12431263

12441264
return mt7996_mac_sta_event(dev, vif, sta, ev);
12451265
}

0 commit comments

Comments
 (0)