blob: db2ebfa5e56e38255838911f7bea194895233848 [file] [log] [blame]
developer05f3b2b2024-08-19 19:17:34 +08001From db6f06e9685bd4297e87b10b6f2550b4430e3b0a Mon Sep 17 00:00:00 2001
developer66e89bc2024-04-23 14:50:01 +08002From: Shayne Chen <shayne.chen@mediatek.com>
3Date: Thu, 23 Nov 2023 18:22:11 +0800
developer05f3b2b2024-08-19 19:17:34 +08004Subject: [PATCH 094/199] mtk: mt76: mt7996: support multi-link vif links and
developer66e89bc2024-04-23 14:50:01 +08005 MLO bss callbacks
6
7Rework add/remove interface functions to add/remove bss_conf functions,
8and also switch to callbacks for MLO bss.
9This is a preliminary patch to add MLO support for mt7996 chipsets.
10
11Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com>
12Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
13Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
14---
developer05f3b2b2024-08-19 19:17:34 +080015 mt7996/main.c | 295 +++++++++++++++++++++++++++++++++++++++---------
developer66e89bc2024-04-23 14:50:01 +080016 mt7996/mcu.c | 29 +++--
17 mt7996/mt7996.h | 9 ++
developer05f3b2b2024-08-19 19:17:34 +080018 3 files changed, 267 insertions(+), 66 deletions(-)
developer66e89bc2024-04-23 14:50:01 +080019
20diff --git a/mt7996/main.c b/mt7996/main.c
developer05f3b2b2024-08-19 19:17:34 +080021index e071c5fa..3abae2fe 100644
developer66e89bc2024-04-23 14:50:01 +080022--- a/mt7996/main.c
23+++ b/mt7996/main.c
24@@ -205,6 +205,38 @@ static int get_omac_idx(enum nl80211_iftype type, u64 mask)
25 return -1;
26 }
27
28+static int get_own_mld_idx(u64 mask, bool group_mld)
29+{
30+ u8 start, end;
31+ int i;
32+
33+ if (group_mld) {
34+ start = 0;
35+ end = 15;
36+ } else {
37+ start = 16;
38+ end = 63;
39+ }
40+
41+ i = get_free_idx(mask, start, end);
42+ if (i)
43+ return i - 1;
44+
45+ return -1;
46+}
47+
48+static int get_mld_remap_idx(u64 mask)
49+{
50+ u8 start = 0, end = 15;
51+ int i;
52+
53+ i = get_free_idx(mask, start, end);
54+ if (i)
55+ return i - 1;
56+
57+ return -1;
58+}
59+
60 static void mt7996_init_bitrate_mask(struct mt7996_bss_conf *mconf)
61 {
62 int i;
63@@ -223,48 +255,108 @@ static void mt7996_init_bitrate_mask(struct mt7996_bss_conf *mconf)
64 }
65 }
66
67-static int mt7996_add_interface(struct ieee80211_hw *hw,
68- struct ieee80211_vif *vif)
69+static void mt7996_remove_bss_conf(struct ieee80211_vif *vif,
70+ struct ieee80211_bss_conf *conf,
71+ struct mt7996_bss_conf *mconf)
72 {
73- struct ieee80211_bss_conf *conf = &vif->bss_conf;
74+ struct mt7996_phy *phy = mconf->phy;
75+ struct mt7996_dev *dev = phy->dev;
76 struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
77- struct mt7996_bss_conf *mconf = &mvif->deflink;
78- struct mt7996_link_sta *mlink = &mvif->sta.deflink;
79- struct mt7996_dev *dev = mt7996_hw_dev(hw);
80- struct mt7996_phy *phy = mt7996_hw_phy(hw);
81+ u8 link_id = conf->link_id;
82+ struct mt7996_link_sta *mlink =
83+ mlink_dereference_protected(&mvif->sta, link_id);
84+
85+ if (!mlink)
86+ return;
87+
88+ mt7996_mcu_add_sta(dev, conf, mconf, NULL, mlink, false, false);
89+ mt7996_mcu_add_bss_info(phy, conf, mconf, mlink, false);
90+ mt7996_mcu_add_dev_info(phy, conf, mconf, false);
91+
92+ rcu_assign_pointer(dev->mt76.wcid[mlink->wcid.idx], NULL);
93+ rcu_assign_pointer(mvif->link[link_id], NULL);
94+ rcu_assign_pointer(mvif->sta.link[link_id], NULL);
95+
96+ dev->mt76.vif_mask &= ~BIT_ULL(mconf->mt76.idx);
97+ dev->mld_id_mask &= ~BIT_ULL(mconf->own_mld_id);
98+ phy->omac_mask &= ~BIT_ULL(mconf->mt76.omac_idx);
99+
100+ spin_lock_bh(&dev->mt76.sta_poll_lock);
101+ if (!list_empty(&mlink->wcid.poll_list))
102+ list_del_init(&mlink->wcid.poll_list);
103+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
104+
105+ mt76_wcid_cleanup(&dev->mt76, &mlink->wcid);
106+
107+ if (mlink != &mvif->sta.deflink)
108+ kfree(mlink);
109+
110+ if (mconf != &mvif->deflink)
111+ kfree(mconf);
112+}
113+
114+static int mt7996_add_bss_conf(struct mt7996_phy *phy,
115+ struct ieee80211_vif *vif,
116+ struct ieee80211_bss_conf *conf)
117+{
118+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
119+ struct mt7996_dev *dev = phy->dev;
120+ struct mt7996_bss_conf *mconf;
121+ struct mt7996_link_sta *mlink;
122 struct mt76_txq *mtxq;
123 u8 band_idx = phy->mt76->band_idx;
124- int idx, ret = 0;
125-
126- mutex_lock(&dev->mt76.mutex);
127+ u8 link_id = conf->link_id;
128+ int idx, ret;
129
130- if (vif->type == NL80211_IFTYPE_MONITOR &&
131- is_zero_ether_addr(vif->addr))
132- phy->monitor_vif = vif;
133+ if (conf != &vif->bss_conf) {
134+ mconf = kzalloc(sizeof(*mconf), GFP_KERNEL);
135+ if (!mconf)
136+ return -ENOMEM;
137+ } else {
138+ mconf = &mvif->deflink;
139+ }
140
141 mconf->mt76.idx = __ffs64(~dev->mt76.vif_mask);
142 if (mconf->mt76.idx >= mt7996_max_interface_num(dev)) {
143 ret = -ENOSPC;
144- goto out;
145+ goto error;
146 }
147
148 idx = get_omac_idx(vif->type, phy->omac_mask);
149 if (idx < 0) {
150 ret = -ENOSPC;
151- goto out;
152+ goto error;
153+ }
154+
155+ mconf->own_mld_id = get_own_mld_idx(dev->mld_id_mask, false);
156+ if (mconf->own_mld_id < 0) {
157+ ret = -ENOSPC;
158+ goto error;
159 }
160+
161 mconf->mt76.omac_idx = idx;
162 mconf->vif = mvif;
163 mconf->phy = phy;
164 mconf->mt76.band_idx = band_idx;
developer05f3b2b2024-08-19 19:17:34 +0800165 mconf->mt76.wmm_idx = vif->type == NL80211_IFTYPE_AP ? 0 : 3;
developer66e89bc2024-04-23 14:50:01 +0800166- mvif->dev = dev;
167+ mconf->link_id = link_id;
168
169 ret = mt7996_mcu_add_dev_info(phy, conf, mconf, true);
170 if (ret)
171- goto out;
172+ goto error;
173+
174+ if (ieee80211_vif_is_mld(vif)) {
175+ mlink = kzalloc(sizeof(*mlink), GFP_KERNEL);
176+ if (!mlink) {
177+ ret = -ENOMEM;
178+ goto error;
179+ }
180+ } else {
181+ mlink = &mvif->sta.deflink;
182+ }
183
184 dev->mt76.vif_mask |= BIT_ULL(mconf->mt76.idx);
185+ dev->mld_id_mask |= BIT_ULL(mconf->own_mld_id);
186 phy->omac_mask |= BIT_ULL(mconf->mt76.omac_idx);
187
188 idx = MT7996_WTBL_RESERVED - mconf->mt76.idx;
189@@ -275,6 +367,9 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
190 mlink->wcid.phy_idx = band_idx;
191 mlink->wcid.hw_key_idx = -1;
192 mlink->wcid.tx_info |= MT_WCID_TX_INFO_SET;
193+ mlink->wcid.def_wcid = &mvif->sta.deflink.wcid;
194+ mlink->wcid.link_id = link_id;
195+ mlink->wcid.link_valid = ieee80211_vif_is_mld(vif);
196 mlink->sta = &mvif->sta;
197 mlink->sta->vif = mvif;
198 mt76_wcid_init(&mlink->wcid);
199@@ -296,7 +391,6 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
200 mconf->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL + 4;
201 else
202 mconf->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL;
203-
204 mt7996_init_bitrate_mask(mconf);
205
206 mt7996_mcu_add_bss_info(phy, conf, mconf, mlink, true);
207@@ -306,10 +400,32 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
208 if (vif->type != NL80211_IFTYPE_STATION)
209 mt7996_mcu_add_sta(dev, conf, mconf, NULL, mlink, true, true);
210 rcu_assign_pointer(dev->mt76.wcid[idx], &mlink->wcid);
211- rcu_assign_pointer(mvif->link[0], mconf);
212- rcu_assign_pointer(mvif->sta.link[0], mlink);
213+ rcu_assign_pointer(mvif->link[link_id], mconf);
214+ rcu_assign_pointer(mvif->sta.link[link_id], mlink);
215
216-out:
217+ return 0;
218+error:
219+ mt7996_remove_bss_conf(vif, conf, mconf);
220+ return ret;
221+}
222+
223+static int mt7996_add_interface(struct ieee80211_hw *hw,
224+ struct ieee80211_vif *vif)
225+{
226+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
227+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
228+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
229+ int ret = 0;
230+
231+ mutex_lock(&dev->mt76.mutex);
232+ if (vif->type == NL80211_IFTYPE_MONITOR &&
233+ is_zero_ether_addr(vif->addr))
234+ phy->monitor_vif = vif;
235+
236+ mvif->dev = dev;
237+ mvif->sta.vif = mvif;
238+
239+ ret = mt7996_add_bss_conf(phy, vif, &vif->bss_conf);
240 mutex_unlock(&dev->mt76.mutex);
241
242 return ret;
243@@ -321,38 +437,23 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
244 struct ieee80211_bss_conf *conf;
245 struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
246 struct mt7996_bss_conf *mconf;
247- struct mt7996_link_sta *mlink = &mvif->sta.deflink;
248 struct mt7996_dev *dev = mt7996_hw_dev(hw);
249 struct mt7996_phy *phy = mt7996_hw_phy(hw);
250- int idx = mlink->wcid.idx;
251
252 cancel_delayed_work_sync(&phy->scan_work);
253
254 mutex_lock(&dev->mt76.mutex);
255
256- conf = link_conf_dereference_protected(vif, 0);
257- mconf = mconf_dereference_protected(mvif, 0);
258- mt7996_mcu_add_sta(dev, conf, mconf, NULL, mlink, false, false);
259- mt7996_mcu_add_bss_info(phy, conf, mconf, mlink, false);
260+ if (test_bit(MT76_SCANNING, &phy->mt76->state))
261+ mt7996_scan_complete(phy, true);
262
263 if (vif == phy->monitor_vif)
264 phy->monitor_vif = NULL;
265
266- mt7996_mcu_add_dev_info(phy, conf, mconf, false);
267-
268- rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
269-
270- dev->mt76.vif_mask &= ~BIT_ULL(mconf->mt76.idx);
271- phy->omac_mask &= ~BIT_ULL(mconf->mt76.omac_idx);
272-
273- spin_lock_bh(&dev->mt76.sta_poll_lock);
274- if (!list_empty(&mlink->wcid.poll_list))
275- list_del_init(&mlink->wcid.poll_list);
276- spin_unlock_bh(&dev->mt76.sta_poll_lock);
277+ conf = link_conf_dereference_protected(vif, 0);
278+ mconf = mconf_dereference_protected(mvif, 0);
279
280- mt76_wcid_cleanup(&dev->mt76, &mlink->wcid);
281- rcu_assign_pointer(mvif->link[0], NULL);
282- rcu_assign_pointer(mvif->sta.link[0], NULL);
283+ mt7996_remove_bss_conf(vif, conf, mconf);
284
285 mutex_unlock(&dev->mt76.mutex);
286 }
developer05f3b2b2024-08-19 19:17:34 +0800287@@ -720,10 +821,31 @@ mt7996_update_mu_group(struct ieee80211_hw *hw, struct ieee80211_bss_conf *conf,
developer66e89bc2024-04-23 14:50:01 +0800288 mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS3(band), mu[3]);
289 }
290
291-static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
292- struct ieee80211_vif *vif,
293- struct ieee80211_bss_conf *info,
294- u64 changed)
295+static void mt7996_vif_cfg_changed(struct ieee80211_hw *hw,
296+ struct ieee80211_vif *vif, u64 changed)
297+{
298+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
299+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
300+
301+ mutex_lock(&dev->mt76.mutex);
302+
303+ if (changed & BSS_CHANGED_ASSOC && vif->cfg.assoc) {
304+ struct ieee80211_bss_conf *conf = &vif->bss_conf;
305+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
306+ struct mt7996_bss_conf *mconf = mconf_dereference_protected(mvif, 0);
307+ struct mt7996_link_sta *mlink = mlink_dereference_protected(&mvif->sta, 0);
308+
309+ mt7996_mcu_add_bss_info(phy, conf, mconf, mlink, true);
310+ mt7996_mcu_add_sta(dev, conf, mconf, NULL, mlink, true, false);
311+ }
312+
313+ mutex_unlock(&dev->mt76.mutex);
314+}
315+
316+static void mt7996_link_info_changed(struct ieee80211_hw *hw,
317+ struct ieee80211_vif *vif,
318+ struct ieee80211_bss_conf *info,
319+ u64 changed)
320 {
321 struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
322 struct mt7996_bss_conf *mconf;
developer05f3b2b2024-08-19 19:17:34 +0800323@@ -739,7 +861,6 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
developer66e89bc2024-04-23 14:50:01 +0800324 * and then peer references bss_info_rfch to set bandwidth cap.
325 */
326 if ((changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) ||
327- (changed & BSS_CHANGED_ASSOC && vif->cfg.assoc) ||
328 (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon)) {
329 mt7996_mcu_add_bss_info(phy, info, mconf, mlink, true);
330 mt7996_mcu_add_sta(dev, info, mconf, NULL, mlink, true,
developer05f3b2b2024-08-19 19:17:34 +0800331@@ -1082,7 +1203,7 @@ mt7996_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
developer66e89bc2024-04-23 14:50:01 +0800332 u64 ret;
333
334 mutex_lock(&dev->mt76.mutex);
335- mconf = mconf_dereference_protected(mvif, 0);
336+ mconf = mconf_dereference_protected(mvif, mvif->master_link_id);
337 ret = __mt7996_get_tsf(hw, mconf);
338 mutex_unlock(&dev->mt76.mutex);
339
developer05f3b2b2024-08-19 19:17:34 +0800340@@ -1105,7 +1226,7 @@ mt7996_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
developer66e89bc2024-04-23 14:50:01 +0800341
342 mutex_lock(&dev->mt76.mutex);
343
344- mconf = mconf_dereference_protected(mvif, 0);
345+ mconf = mconf_dereference_protected(mvif, mvif->master_link_id);
346 n = mconf->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
347 : mconf->mt76.omac_idx;
348 mt76_wr(dev, MT_LPON_UTTR0(phy->mt76->band_idx), tsf.t32[0]);
developer05f3b2b2024-08-19 19:17:34 +0800349@@ -1133,7 +1254,7 @@ mt7996_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
developer66e89bc2024-04-23 14:50:01 +0800350
351 mutex_lock(&dev->mt76.mutex);
352
353- mconf = mconf_dereference_protected(mvif, 0);
354+ mconf = mconf_dereference_protected(mvif, mvif->master_link_id);
355 n = mconf->mt76.omac_idx > HW_BSSID_MAX ? HW_BSSID_0
356 : mconf->mt76.omac_idx;
357 mt76_wr(dev, MT_LPON_UTTR0(phy->mt76->band_idx), tsf.t32[0]);
developer05f3b2b2024-08-19 19:17:34 +0800358@@ -1308,7 +1429,7 @@ mt7996_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
developer66e89bc2024-04-23 14:50:01 +0800359 u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED;
360
361 mutex_lock(&dev->mt76.mutex);
362- mconf = mconf_dereference_protected(mvif, 0);
363+ mconf = mconf_dereference_protected(mvif, mvif->master_link_id);
364 mconf->bitrate_mask = *mask;
365 mutex_unlock(&dev->mt76.mutex);
366
developer05f3b2b2024-08-19 19:17:34 +0800367@@ -1528,7 +1649,7 @@ void mt7996_get_et_stats(struct ieee80211_hw *hw,
developer66e89bc2024-04-23 14:50:01 +0800368 int i, ei = 0;
369
370 mutex_lock(&dev->mt76.mutex);
371- mconf = mconf_dereference_protected(mvif, 0);
372+ mconf = mconf_dereference_protected(mvif, mvif->master_link_id);
373 wi.idx = mconf->mt76.idx,
374
375 mt7996_mac_update_stats(phy);
developer05f3b2b2024-08-19 19:17:34 +0800376@@ -1901,6 +2022,8 @@ mt7996_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
developer66e89bc2024-04-23 14:50:01 +0800377 struct mt7996_phy *phy = ctx->phy;
378 struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
379 struct mt7996_bss_conf *mconf;
380+ u8 link_id = link_conf->link_id;
381+ int ret;
382
383 wiphy_info(hw->wiphy, "Assign VIF (addr: %pM, type: %d, link_id: %d) to channel context: %d MHz\n",
384 vif->addr, vif->type, link_conf->link_id,
developer05f3b2b2024-08-19 19:17:34 +0800385@@ -1908,10 +2031,24 @@ mt7996_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
developer66e89bc2024-04-23 14:50:01 +0800386
387 mutex_lock(&phy->dev->mt76.mutex);
388
389- mconf = mconf_dereference_protected(mvif, 0);
390+ /* remove first */
391+ if (rcu_access_pointer(mvif->link[link_id]))
392+ mt7996_remove_bss_conf(vif, link_conf,
393+ mconf_dereference_protected(mvif, link_id));
394+
395+ ret = mt7996_add_bss_conf(phy, vif, link_conf);
396+ if (ret) {
397+ mutex_unlock(&phy->dev->mt76.mutex);
398+ return ret;
399+ }
400+
401+ mconf = mconf_dereference_protected(mvif, link_id);
402 mconf->chanctx = ctx;
403 ctx->nbss_assigned++;
404
405+ if (mt7996_hw_phy(hw) == phy)
406+ mvif->master_link_id = link_id;
407+
408 mutex_unlock(&phy->dev->mt76.mutex);
409
410 return 0;
developer05f3b2b2024-08-19 19:17:34 +0800411@@ -1937,7 +2074,7 @@ mt7996_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
developer66e89bc2024-04-23 14:50:01 +0800412 if (test_bit(MT76_SCANNING, &phy->mt76->state))
413 mt7996_scan_complete(phy, true);
414
415- mconf = mconf_dereference_protected(mvif, 0);
416+ mconf = mconf_dereference_protected(mvif, link_conf->link_id);
417 mconf->chanctx = NULL;
418 ctx->nbss_assigned--;
419
developer05f3b2b2024-08-19 19:17:34 +0800420@@ -1977,6 +2114,54 @@ mt7996_switch_vif_chanctx(struct ieee80211_hw *hw,
developer66e89bc2024-04-23 14:50:01 +0800421 return mt7996_set_channel(phy, &new_ctx->chandef);
422 }
423
424+static int
425+mt7996_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
426+ u16 old_links, u16 new_links,
427+ struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
428+{
429+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
430+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
431+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
432+ unsigned long rem = old_links & ~new_links;
433+ unsigned int link_id;
434+ int ret = 0;
435+
436+ if (old_links == new_links)
437+ return 0;
438+
439+ mutex_lock(&dev->mt76.mutex);
440+
developer66e89bc2024-04-23 14:50:01 +0800441+ /* remove first */
442+ for_each_set_bit(link_id, &rem, IEEE80211_MLD_MAX_NUM_LINKS) {
443+ struct mt7996_bss_conf *mconf =
444+ mconf_dereference_protected(mvif, link_id);
445+
446+ if (!mconf)
447+ continue;
448+
449+ mt7996_remove_bss_conf(vif, old[link_id], mconf);
450+ }
451+
452+ if (!old_links) {
453+ mvif->group_mld_id = get_own_mld_idx(dev->mld_id_mask, true);
454+ dev->mld_id_mask |= BIT_ULL(mvif->group_mld_id);
455+
456+ mvif->mld_remap_id = get_mld_remap_idx(dev->mld_remap_id_mask);
457+ dev->mld_remap_id_mask |= BIT_ULL(mvif->mld_remap_id);
458+ }
459+
460+ /* fallback to non-MLO interface */
461+ if (!new_links) {
462+ ret = mt7996_add_bss_conf(phy, vif, &vif->bss_conf);
463+ dev->mld_id_mask &= ~BIT_ULL(mvif->group_mld_id);
464+ dev->mld_remap_id_mask &= ~BIT_ULL(mvif->mld_remap_id);
465+ }
466+
467+ mutex_unlock(&dev->mt76.mutex);
468+
469+ return ret;
470+}
471+
472 const struct ieee80211_ops mt7996_ops = {
developer05f3b2b2024-08-19 19:17:34 +0800473 .add_chanctx = ieee80211_emulate_add_chanctx,
474 .remove_chanctx = ieee80211_emulate_remove_chanctx,
475@@ -1990,7 +2175,8 @@ const struct ieee80211_ops mt7996_ops = {
developer66e89bc2024-04-23 14:50:01 +0800476 .config = mt7996_config,
477 .conf_tx = mt7996_conf_tx,
478 .configure_filter = mt7996_configure_filter,
479- .bss_info_changed = mt7996_bss_info_changed,
480+ .vif_cfg_changed = mt7996_vif_cfg_changed,
481+ .link_info_changed = mt7996_link_info_changed,
482 .sta_state = mt76_sta_state,
483 .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
484 .sta_rc_update = mt7996_sta_rc_update,
developer05f3b2b2024-08-19 19:17:34 +0800485@@ -2036,4 +2222,5 @@ const struct ieee80211_ops mt7996_ops = {
developer66e89bc2024-04-23 14:50:01 +0800486 .assign_vif_chanctx = mt7996_assign_vif_chanctx,
487 .unassign_vif_chanctx = mt7996_unassign_vif_chanctx,
488 .switch_vif_chanctx = mt7996_switch_vif_chanctx,
489+ .change_vif_links = mt7996_change_vif_links,
490 };
491diff --git a/mt7996/mcu.c b/mt7996/mcu.c
developer05f3b2b2024-08-19 19:17:34 +0800492index 20b84c93..d3e244ee 100644
developer66e89bc2024-04-23 14:50:01 +0800493--- a/mt7996/mcu.c
494+++ b/mt7996/mcu.c
495@@ -1047,15 +1047,23 @@ static void
496 mt7996_mcu_bss_mld_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
497 struct mt7996_bss_conf *mconf)
498 {
499+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
500 struct bss_mld_tlv *mld;
501 struct tlv *tlv;
502
503 tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_MLD, sizeof(*mld));
504-
505 mld = (struct bss_mld_tlv *)tlv;
506- mld->group_mld_id = 0xff;
507- mld->own_mld_id = mconf->mt76.idx;
508- mld->remap_idx = 0xff;
509+
510+ if (ieee80211_vif_is_mld(vif)) {
511+ mld->group_mld_id = mvif->group_mld_id;
512+ mld->remap_idx = mvif->mld_remap_id;
513+ memcpy(mld->mac_addr, vif->addr, ETH_ALEN);
514+ } else {
515+ mld->group_mld_id = 0xff;
516+ mld->remap_idx = 0xff;
517+ }
518+
519+ mld->own_mld_id = mconf->own_mld_id;
520 }
521
522 static void
523@@ -1136,13 +1144,11 @@ mt7996_mcu_bss_ifs_timing_tlv(struct sk_buff *skb, struct mt7996_phy *phy)
524 }
525
526 static int
527-mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
528- struct ieee80211_bss_conf *conf,
529- struct mt7996_bss_conf *mconf,
530- struct ieee80211_sta *sta,
531- struct mt76_phy *phy, u16 wlan_idx,
532- bool enable)
533+mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_bss_conf *conf,
534+ struct mt7996_bss_conf *mconf, struct ieee80211_sta *sta,
535+ u16 wlan_idx, bool enable)
536 {
537+ struct mt76_phy *phy = mconf->phy->mt76;
538 struct ieee80211_vif *vif = conf->vif;
539 struct cfg80211_chan_def *chandef = &phy->chandef;
540 struct mt76_connac_bss_basic_tlv *bss;
541@@ -1254,8 +1260,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy,
542 return PTR_ERR(skb);
543
544 /* bss_basic must be first */
545- mt7996_mcu_bss_basic_tlv(skb, conf, mconf, NULL, phy->mt76,
546- mlink->wcid.idx, enable);
547+ mt7996_mcu_bss_basic_tlv(skb, conf, mconf, NULL, mlink->wcid.idx, enable);
548 mt7996_mcu_bss_sec_tlv(skb, mconf);
549
550 if (vif->type == NL80211_IFTYPE_MONITOR)
551diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developer05f3b2b2024-08-19 19:17:34 +0800552index 1732ff36..09b1088e 100644
developer66e89bc2024-04-23 14:50:01 +0800553--- a/mt7996/mt7996.h
554+++ b/mt7996/mt7996.h
developer05f3b2b2024-08-19 19:17:34 +0800555@@ -341,6 +341,9 @@ struct mt7996_bss_conf {
developer66e89bc2024-04-23 14:50:01 +0800556 struct cfg80211_bitrate_mask bitrate_mask;
557
558 struct mt7996_chanctx *chanctx;
559+
560+ u8 link_id;
561+ u8 own_mld_id;
562 };
563
564 struct mt7996_vif {
developer05f3b2b2024-08-19 19:17:34 +0800565@@ -349,6 +352,10 @@ struct mt7996_vif {
developer66e89bc2024-04-23 14:50:01 +0800566
567 struct mt7996_sta sta;
568 struct mt7996_dev *dev;
569+
570+ u8 master_link_id;
571+ u8 group_mld_id;
572+ u8 mld_remap_id;
573 };
574
575 /* crash-dump */
developer05f3b2b2024-08-19 19:17:34 +0800576@@ -550,6 +557,8 @@ struct mt7996_dev {
developer66e89bc2024-04-23 14:50:01 +0800577 u16 chainmask;
578 u8 chainshift[__MT_MAX_BAND];
579 u32 hif_idx;
580+ u64 mld_id_mask;
581+ u64 mld_remap_id_mask;
582
583 struct work_struct init_work;
584 struct work_struct rc_work;
585--
developer9237f442024-06-14 17:13:04 +08005862.18.0
developer66e89bc2024-04-23 14:50:01 +0800587