* [PATCH mt76] wifi: mt76: mt7996: Enable MLO support for client interfaces
@ 2025-09-01 13:02 Lorenzo Bianconi
0 siblings, 0 replies; only message in thread
From: Lorenzo Bianconi @ 2025-09-01 13:02 UTC (permalink / raw)
To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
Lorenzo Bianconi
Report MT7996 MLO STA capabilities to mac80211 stack.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mac80211.c | 52 ++++++++++++++++++++++++
drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
drivers/net/wireless/mediatek/mt76/mt7925/main.c | 52 +-----------------------
drivers/net/wireless/mediatek/mt76/mt7996/init.c | 8 ++++
drivers/net/wireless/mediatek/mt76/mt7996/main.c | 32 ++++++++++++---
5 files changed, 88 insertions(+), 57 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index 3afe4c4cd7bbec5d317be4155f232eec7d41b62e..903e5a4251a47f92e2f647c84ade5eff06b24eba 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -2019,3 +2019,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);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 8dd5c29fb75b5c0c879350f3af15b71f12630a96..d518a5441418bce5ae477e7f15dde56b6cb5b87d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -1871,6 +1871,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)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index 47abf5f0486076a77b949a6d59b2eddba4b186ce..f9ab24b05327c57f0b094a552d3bc598f9a74dc1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -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)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
index 29e0cf966bcac5ab805b927fd73b7a23d15877ec..428b431b2910a06b7f3daded9cea1bbe1427fbb7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
@@ -78,6 +78,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),
},
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index 7f3a117c52bd3438b6bb41a068bbf11658dfba42..341ed090d2b85bac3ad99035a8649c9bdbd78424 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -1212,6 +1212,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,
@@ -1229,16 +1247,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);
}
---
base-commit: 035ba65d13516fa2afa78203ba3ef54fd70584af
change-id: 20250829-mt7996-enable-mlo-client-119156569321
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2025-09-01 16:50 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-01 13:02 [PATCH mt76] wifi: mt76: mt7996: Enable MLO support for client interfaces Lorenzo Bianconi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).