blob: 1338a688de5dcd42e3099f678d0246d9410f4b00 [file] [log] [blame]
developer05f3b2b2024-08-19 19:17:34 +08001From 9fb46d0e65f5f37975a71ad433db8290ee586566 Mon Sep 17 00:00:00 2001
developer66e89bc2024-04-23 14:50:01 +08002From: Shayne Chen <shayne.chen@mediatek.com>
3Date: Wed, 29 Nov 2023 10:12:39 +0800
developer05f3b2b2024-08-19 19:17:34 +08004Subject: [PATCH 095/199] mtk: mt76: mt7996: support multi-link sta links and
developer66e89bc2024-04-23 14:50:01 +08005 MLO sta callbacks
6
7Rework add_sta functions to add_link_sta functions, and support
8.change_sta_links callback.
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 | 309 +++++++++++++++++++++++++++++++++++++-----------
16 mt7996/mcu.c | 117 ++++++++++++++++++
17 mt7996/mcu.h | 29 +++++
18 mt7996/mt7996.h | 7 ++
19 4 files changed, 396 insertions(+), 66 deletions(-)
developer66e89bc2024-04-23 14:50:01 +080020
developer66e89bc2024-04-23 14:50:01 +080021diff --git a/mt7996/main.c b/mt7996/main.c
developer05f3b2b2024-08-19 19:17:34 +080022index 3abae2fe..e850942f 100644
developer66e89bc2024-04-23 14:50:01 +080023--- a/mt7996/main.c
24+++ b/mt7996/main.c
developer05f3b2b2024-08-19 19:17:34 +080025@@ -932,42 +932,234 @@ mt7996_channel_switch_beacon(struct ieee80211_hw *hw,
developer66e89bc2024-04-23 14:50:01 +080026 mutex_unlock(&dev->mt76.mutex);
27 }
28
29+static void mt7996_remove_link_sta(struct mt7996_dev *dev,
30+ struct ieee80211_bss_conf *conf,
31+ struct mt7996_bss_conf *mconf,
32+ struct ieee80211_link_sta *link_sta,
33+ struct mt7996_link_sta *mlink)
34+{
35+ struct ieee80211_sta *sta = link_sta->sta;
36+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
37+ int i;
38+
39+ if (!mlink)
40+ return;
41+
42+ for (i = 0; i < ARRAY_SIZE(mlink->wcid.aggr); i++)
43+ mt76_rx_aggr_stop(&dev->mt76, &mlink->wcid, i);
44+
45+ if (sta->mlo)
46+ mt7996_mcu_teardown_mld_sta(dev, mconf, mlink);
47+ else
48+ mt7996_mcu_add_sta(dev, conf, mconf, link_sta, mlink, false, false);
49+
50+ mt7996_mac_wtbl_update(dev, mlink->wcid.idx,
51+ MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
52+
53+ for (i = 0; i < ARRAY_SIZE(mlink->twt.flow); i++)
54+ mt7996_mac_twt_teardown_flow(dev, mlink, i);
55+
56+ rcu_assign_pointer(mlink->sta->link[mlink->wcid.link_id], NULL);
57+
58+ spin_lock_bh(&dev->mt76.sta_poll_lock);
59+ if (!list_empty(&mlink->wcid.poll_list))
60+ list_del_init(&mlink->wcid.poll_list);
61+ if (!list_empty(&mlink->rc_list))
62+ list_del_init(&mlink->rc_list);
63+ spin_unlock_bh(&dev->mt76.sta_poll_lock);
64+
65+ /* TODO: update primary link */
66+ if (sta->valid_links) {
67+ if (mlink->wcid.link_id == msta->pri_link)
68+ msta->pri_link = msta->sec_link;
69+
70+ if (sta->valid_links & ~(BIT(msta->pri_link)))
71+ msta->sec_link = __ffs(sta->valid_links & ~(BIT(msta->pri_link)));
72+ else
73+ msta->sec_link = msta->pri_link;
74+ }
75+
76+ mt76_wcid_cleanup(&dev->mt76, &mlink->wcid);
77+ mt76_wcid_mask_clear(dev->mt76.wcid_mask, mlink->wcid.idx);
78+ mt76_wcid_mask_clear(dev->mt76.wcid_phy_mask, mlink->wcid.idx);
79+
80+ if (mlink != &msta->deflink)
81+ kfree(mlink);
82+}
83+
84+static int mt7996_add_link_sta(struct mt7996_dev *dev,
85+ struct ieee80211_bss_conf *conf,
86+ struct mt7996_bss_conf *mconf,
87+ struct ieee80211_link_sta *link_sta, bool assoc)
88+{
89+ struct ieee80211_sta *sta = link_sta->sta;
90+ struct mt7996_vif *mvif = (struct mt7996_vif *)conf->vif->drv_priv;
91+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
92+ u8 link_id = link_sta->link_id;
93+ struct mt7996_link_sta *mlink = NULL;
94+ int idx, ret;
95+
96+ if (!rcu_access_pointer(msta->link[link_id])) {
97+ idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA);
98+ if (idx < 0)
99+ return -ENOSPC;
100+
101+ if (sta->mlo) {
102+ mlink = kzalloc(sizeof(*mlink), GFP_KERNEL);
103+ if (!mlink)
104+ return -ENOMEM;
105+ } else {
106+ mlink = &msta->deflink;
107+ }
108+
109+ INIT_LIST_HEAD(&mlink->rc_list);
110+ INIT_LIST_HEAD(&mlink->wcid.poll_list);
111+ msta->vif = mvif;
112+ mlink->wcid.sta = 1;
113+ mlink->wcid.idx = idx;
114+ mlink->wcid.phy_idx = mconf->phy->mt76->band_idx;
115+ mlink->wcid.tx_info |= MT_WCID_TX_INFO_SET;
116+ mlink->wcid.def_wcid = &msta->deflink.wcid;
117+ mlink->sta = msta;
118+ if (sta->valid_links) {
119+ mlink->wcid.link_valid = true;
120+ mlink->wcid.link_id = link_id;
121+ if (sta->valid_links & ~(BIT(msta->pri_link)))
122+ msta->sec_link = __ffs(sta->valid_links &
123+ ~(BIT(msta->pri_link)));
124+ else
125+ msta->sec_link = msta->pri_link;
126+ }
127+
128+ rcu_assign_pointer(msta->link[link_id], mlink);
129+
130+ ewma_signal_init(&mlink->wcid.rssi);
131+ if (mconf->phy->mt76->band_idx == MT_BAND1)
132+ mt76_wcid_mask_set(dev->mt76.wcid_phy_mask, idx);
133+ rcu_assign_pointer(dev->mt76.wcid[idx], &mlink->wcid);
134+ mt76_wcid_init(&mlink->wcid);
135+ }
136+
137+ if (!assoc)
138+ return 0;
139+
140+ if (!mlink)
141+ mlink = mlink_dereference_protected(msta, link_id);
142+ mt7996_mac_wtbl_update(dev, mlink->wcid.idx,
143+ MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
144+
145+ ret = mt7996_mcu_add_sta(dev, conf, mconf, link_sta, mlink, true, true);
146+ if (ret)
147+ goto error;
148+
149+ ret = mt7996_mcu_add_rate_ctrl(dev, conf, mconf, link_sta, mlink, false);
150+ if (ret)
151+ goto error;
152+
153+ ewma_avg_signal_init(&mlink->avg_ack_signal);
154+
155+ return 0;
156+error:
157+ mt7996_remove_link_sta(dev, conf, mconf, link_sta, mlink);
158+ return ret;
159+}
160+
161+static void
162+mt7996_mac_sta_remove_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
163+ struct ieee80211_sta *sta, unsigned long rem)
164+{
165+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
166+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
167+ unsigned int link_id;
168+
169+ for_each_set_bit(link_id, &rem, IEEE80211_MLD_MAX_NUM_LINKS) {
170+ struct mt7996_bss_conf *mconf =
171+ mconf_dereference_protected(mvif, link_id);
172+ struct mt7996_link_sta *mlink =
173+ mlink_dereference_protected(msta, link_id);
174+ struct ieee80211_bss_conf *conf =
175+ link_conf_dereference_protected(vif, link_id);
176+ struct ieee80211_link_sta *link_sta =
177+ link_sta_dereference_protected(sta, link_id);
178+
179+ mt7996_remove_link_sta(dev, conf, mconf, link_sta, mlink);
180+ }
181+}
182+
183+static int
184+mt7996_mac_sta_add_links(struct mt7996_dev *dev, struct ieee80211_vif *vif,
185+ struct ieee80211_sta *sta, unsigned long add,
186+ bool assoc)
187+{
188+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
189+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
190+ struct mt7996_link_sta *mlink;
191+ unsigned int link_id;
192+ int i, ret;
193+
194+ for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
195+ struct mt7996_bss_conf *mconf =
196+ mconf_dereference_protected(mvif, link_id);
197+ struct ieee80211_bss_conf *conf =
198+ link_conf_dereference_protected(vif, link_id);
199+ struct ieee80211_link_sta *link_sta =
200+ link_sta_dereference_protected(sta, link_id);
201+
202+ ret = mt7996_add_link_sta(dev, conf, mconf, link_sta, assoc);
203+ if (ret)
204+ goto error;
205+ }
206+
207+ if (!assoc)
208+ return 0;
209+
210+ mlink = mlink_dereference_protected(msta, msta->pri_link);
211+ for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
212+ struct mt76_txq *mtxq;
213+
214+ if (!sta->txq[i])
215+ continue;
216+ mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
217+ mtxq->wcid = mlink->wcid.idx;
218+ }
219+
220+ ret = mt7996_mcu_add_mld_sta(dev, vif, sta, add);
221+ if (ret)
222+ goto error;
223+
224+ return 0;
225+error:
226+ mt7996_mac_sta_remove_links(dev, vif, sta, add);
227+ return ret;
228+}
229+
230 int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
231 struct ieee80211_sta *sta)
232 {
233 struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
234- struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
235 struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
236- struct mt7996_bss_conf *mconf = mconf_dereference_protected(mvif, 0);
237- struct mt7996_link_sta *mlink = &msta->deflink;
238- u8 band_idx = mconf->phy->mt76->band_idx;
239- int idx;
240+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
241+ struct mt7996_bss_conf *mconf;
242+ u8 link_id = sta->valid_links ? __ffs(sta->valid_links) : 0;
243+ unsigned long add = BIT(link_id);
244+ int ret;
245
246 #ifdef CONFIG_MTK_VENDOR
247 struct mt7996_phy *phy = &dev->phy;
248 #endif
249
250- idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7996_WTBL_STA);
251- if (idx < 0)
252- return -ENOSPC;
253-
254- INIT_LIST_HEAD(&mlink->rc_list);
255- INIT_LIST_HEAD(&mlink->wcid.poll_list);
256- msta->vif = mvif;
257- mlink->wcid.sta = 1;
258- mlink->wcid.idx = idx;
259- mlink->wcid.phy_idx = band_idx;
260- mlink->wcid.tx_info |= MT_WCID_TX_INFO_SET;
261- mlink->sta = msta;
262-
263- rcu_assign_pointer(msta->link[0], mlink);
264+ msta->pri_link = link_id;
265+ ret = mt7996_mac_sta_add_links(dev, vif, sta, add, false);
266+ if (ret)
267+ return ret;
268
269 #ifdef CONFIG_MTK_VENDOR
270+ mconf = mconf_dereference_protected(mvif, link_id);
271 mt7996_vendor_amnt_sta_remove(mconf->phy, sta);
272 #endif
273
274 #ifdef CONFIG_MTK_VENDOR
275- switch (band_idx) {
276+ switch (mconf->phy->mt76->band_idx) {
277 case MT_BAND1:
278 phy = mt7996_phy2(dev);
279 break;
developer05f3b2b2024-08-19 19:17:34 +0800280@@ -990,28 +1182,11 @@ void mt7996_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
developer66e89bc2024-04-23 14:50:01 +0800281 struct ieee80211_sta *sta)
282 {
283 struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
284- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
285- struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
286- struct mt7996_bss_conf *mconf;
287- struct mt7996_link_sta *mlink;
288- struct ieee80211_bss_conf *conf;
289- struct ieee80211_link_sta *link_sta;
290+ unsigned long add = sta->valid_links ?: BIT(0);
291
292 mutex_lock(&dev->mt76.mutex);
293
294- conf = link_conf_dereference_protected(vif, 0);
295- mconf = mconf_dereference_protected(mvif, 0);
296- link_sta = link_sta_dereference_protected(sta, 0);
297- mlink = mlink_dereference_protected(msta, 0);
298-
299- mt7996_mac_wtbl_update(dev, mlink->wcid.idx,
300- MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
301-
302- mt7996_mcu_add_sta(dev, conf, mconf, link_sta, mlink, true, true);
303- mt7996_mcu_add_rate_ctrl(dev, conf, mconf, link_sta, mlink, false);
304- mlink->wcid.tx_info |= MT_WCID_TX_INFO_SET;
305-
306- ewma_avg_signal_init(&mlink->avg_ack_signal);
307+ mt7996_mac_sta_add_links(dev, vif, sta, add, true);
308
309 mutex_unlock(&dev->mt76.mutex);
310 }
developer05f3b2b2024-08-19 19:17:34 +0800311@@ -1020,34 +1195,9 @@ void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
developer66e89bc2024-04-23 14:50:01 +0800312 struct ieee80211_sta *sta)
313 {
314 struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
315- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
316- struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
317- struct mt7996_bss_conf *mconf;
318- struct mt7996_link_sta *mlink;
319- struct ieee80211_bss_conf *conf;
320- struct ieee80211_link_sta *link_sta;
321- int i;
322-
323- conf = link_conf_dereference_protected(vif, 0);
324- mconf = mconf_dereference_protected(mvif, 0);
325- link_sta = link_sta_dereference_protected(sta, 0);
326- mlink = mlink_dereference_protected(msta, 0);
327- mt7996_mcu_add_sta(dev, conf, mconf, link_sta, mlink, false, false);
328-
329- mt7996_mac_wtbl_update(dev, mlink->wcid.idx,
330- MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
331-
332- for (i = 0; i < ARRAY_SIZE(mlink->twt.flow); i++)
333- mt7996_mac_twt_teardown_flow(dev, mlink, i);
334+ unsigned long rem = sta->valid_links ?: BIT(0);
335
336- spin_lock_bh(&mdev->sta_poll_lock);
337- if (!list_empty(&mlink->wcid.poll_list))
338- list_del_init(&mlink->wcid.poll_list);
339- if (!list_empty(&mlink->rc_list))
340- list_del_init(&mlink->rc_list);
341- spin_unlock_bh(&mdev->sta_poll_lock);
342-
343- rcu_assign_pointer(msta->link[0], NULL);
344+ mt7996_mac_sta_remove_links(dev, vif, sta, rem);
345 }
346
347 static void mt7996_tx(struct ieee80211_hw *hw,
developer05f3b2b2024-08-19 19:17:34 +0800348@@ -2162,6 +2312,32 @@ mt7996_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
developer66e89bc2024-04-23 14:50:01 +0800349 return ret;
350 }
351
352+static int
353+mt7996_change_sta_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
354+ struct ieee80211_sta *sta, u16 old_links, u16 new_links)
355+{
356+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
357+ unsigned long add = new_links & ~old_links;
358+ unsigned long rem = old_links & ~new_links;
359+ int ret = 0;
360+
361+ mutex_lock(&dev->mt76.mutex);
362+
363+ if (rem)
364+ mt7996_mac_sta_remove_links(dev, vif, sta, rem);
365+
366+ ret = mt7996_mac_sta_add_links(dev, vif, sta, add, false);
367+ if (ret)
368+ goto remove;
369+
370+ goto out;
371+remove:
372+ mt7996_mac_sta_remove_links(dev, vif, sta, add);
373+out:
374+ mutex_unlock(&dev->mt76.mutex);
375+ return ret;
376+}
377+
378 const struct ieee80211_ops mt7996_ops = {
developer05f3b2b2024-08-19 19:17:34 +0800379 .add_chanctx = ieee80211_emulate_add_chanctx,
380 .remove_chanctx = ieee80211_emulate_remove_chanctx,
381@@ -2223,4 +2399,5 @@ const struct ieee80211_ops mt7996_ops = {
developer66e89bc2024-04-23 14:50:01 +0800382 .unassign_vif_chanctx = mt7996_unassign_vif_chanctx,
383 .switch_vif_chanctx = mt7996_switch_vif_chanctx,
384 .change_vif_links = mt7996_change_vif_links,
385+ .change_sta_links = mt7996_change_sta_links,
386 };
387diff --git a/mt7996/mcu.c b/mt7996/mcu.c
developer05f3b2b2024-08-19 19:17:34 +0800388index d3e244ee..7138230e 100644
developer66e89bc2024-04-23 14:50:01 +0800389--- a/mt7996/mcu.c
390+++ b/mt7996/mcu.c
developer05f3b2b2024-08-19 19:17:34 +0800391@@ -2426,6 +2426,123 @@ out:
developer66e89bc2024-04-23 14:50:01 +0800392 MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
393 }
394
395+static void
396+mt7996_mcu_sta_mld_setup_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
397+ struct ieee80211_sta *sta)
398+{
399+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
400+ struct sta_rec_mld_setup *mld_setup;
401+ struct mld_setup_link *mld_setup_link;
402+ struct mt7996_link_sta *mlink;
403+ struct mt7996_bss_conf *mconf;
404+ struct tlv *tlv;
405+ unsigned long valid_links = sta->valid_links;
406+ unsigned int link_id;
407+
408+ mlink = mlink_dereference_protected(msta, msta->pri_link);
409+ if (!mlink)
410+ return;
411+
412+ tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MLD,
413+ sizeof(*mld_setup) +
414+ sizeof(struct mld_setup_link) *
415+ hweight16(sta->valid_links));
416+
417+ mld_setup = (struct sta_rec_mld_setup *)tlv;
418+ memcpy(mld_setup->mld_addr, sta->addr, ETH_ALEN);
419+ mld_setup->setup_wcid = cpu_to_le16(mlink->wcid.idx);
420+ mld_setup->primary_id = cpu_to_le16(mlink->wcid.idx);
421+ if (msta->sec_link != msta->pri_link) {
422+ mlink = mlink_dereference_protected(msta, msta->sec_link);
423+ if (!mlink)
424+ return;
425+ }
426+ mld_setup->seconed_id = cpu_to_le16(mlink->wcid.idx);
427+ mld_setup->link_num = hweight16(sta->valid_links);
428+
429+ mld_setup_link = (struct mld_setup_link *)mld_setup->link_info;
430+ for_each_set_bit(link_id, &valid_links, IEEE80211_MLD_MAX_NUM_LINKS) {
431+ mlink = mlink_dereference_protected(msta, link_id);
432+ mconf = mconf_dereference_protected(msta->vif, link_id);
433+
434+ mld_setup_link->wcid = cpu_to_le16(mlink->wcid.idx);
435+ mld_setup_link->bss_idx = mconf->mt76.idx;
436+ mld_setup_link++;
437+ }
438+}
439+
440+static void
441+mt7996_mcu_sta_eht_mld_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
442+ struct ieee80211_sta *sta)
443+{
444+ struct sta_rec_eht_mld *eht_mld;
445+ struct tlv *tlv;
446+ int i;
447+
448+ tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT_MLD, sizeof(*eht_mld));
449+ eht_mld = (struct sta_rec_eht_mld *)tlv;
450+
451+ for (i = 0; i < ARRAY_SIZE(eht_mld->str_cap); i++)
452+ eht_mld->str_cap[i] = 0x7;
453+ /* TODO:
454+ eht_mld->nsep = ;
455+ eht_mld->eml_cap = cpu_to_le16()
456+ */
457+}
458+
459+int mt7996_mcu_add_mld_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
460+ struct ieee80211_sta *sta, unsigned long add)
461+{
462+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
463+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
464+ unsigned int link_id;
465+
466+ if (!sta->mlo)
467+ return 0;
468+
469+ for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
470+ struct mt7996_bss_conf *mconf =
471+ mconf_dereference_protected(mvif, link_id);
472+ struct mt7996_link_sta *mlink =
473+ mlink_dereference_protected(msta, link_id);
474+ struct sk_buff *skb;
475+ int ret;
476+
477+ skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mconf->mt76,
478+ &mlink->wcid,
479+ MT7996_STA_UPDATE_MAX_SIZE);
480+ if (IS_ERR(skb))
481+ return PTR_ERR(skb);
482+ /* starec mld setup */
483+ mt7996_mcu_sta_mld_setup_tlv(dev, skb, sta);
484+ /* starec eht mld */
485+ mt7996_mcu_sta_eht_mld_tlv(dev, skb, sta);
486+ ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
487+ MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
488+ if (ret)
489+ return ret;
490+ }
491+ return 0;
492+}
493+int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
494+ struct mt7996_bss_conf *mconf,
495+ struct mt7996_link_sta *mlink)
496+{
497+ struct sk_buff *skb;
498+
499+ skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76,
500+ &mconf->mt76,
501+ &mlink->wcid,
502+ MT7996_STA_UPDATE_MAX_SIZE);
503+ if (IS_ERR(skb))
504+ return PTR_ERR(skb);
505+
developer05f3b2b2024-08-19 19:17:34 +0800506+ mt76_connac_mcu_add_tlv(skb, STA_REC_MLD_OFF, sizeof(struct tlv));
developer66e89bc2024-04-23 14:50:01 +0800507+
508+ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
509+ MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
510+}
511+
512 static int
513 mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
514 struct sk_buff *skb,
515diff --git a/mt7996/mcu.h b/mt7996/mcu.h
developer05f3b2b2024-08-19 19:17:34 +0800516index b15796dc..23d44cd3 100644
developer66e89bc2024-04-23 14:50:01 +0800517--- a/mt7996/mcu.h
518+++ b/mt7996/mcu.h
developer05f3b2b2024-08-19 19:17:34 +0800519@@ -692,6 +692,35 @@ struct sta_rec_hdr_trans {
developer66e89bc2024-04-23 14:50:01 +0800520 u8 mesh;
521 } __packed;
522
523+struct sta_rec_mld_setup {
524+ __le16 tag;
525+ __le16 len;
526+ u8 mld_addr[ETH_ALEN];
527+ __le16 primary_id;
528+ __le16 seconed_id;
529+ __le16 setup_wcid;
530+ u8 link_num;
531+ u8 info;
532+ u8 __rsv[2];
533+ u8 link_info[];
534+} __packed;
535+
536+struct mld_setup_link {
537+ __le16 wcid;
538+ u8 bss_idx;
539+ u8 __rsv[1];
540+} __packed;
541+
542+struct sta_rec_eht_mld {
543+ __le16 tag;
544+ __le16 len;
545+ u8 nsep;
546+ u8 __rsv1[2];
547+ u8 str_cap[__MT_MAX_BAND];
548+ __le16 eml_cap;
549+ u8 __rsv2[4];
550+} __packed;
551+
552 struct hdr_trans_en {
553 __le16 tag;
554 __le16 len;
555diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developer05f3b2b2024-08-19 19:17:34 +0800556index 09b1088e..4775e1f8 100644
developer66e89bc2024-04-23 14:50:01 +0800557--- a/mt7996/mt7996.h
558+++ b/mt7996/mt7996.h
developer05f3b2b2024-08-19 19:17:34 +0800559@@ -330,6 +330,8 @@ struct mt7996_sta {
developer66e89bc2024-04-23 14:50:01 +0800560 struct mt7996_link_sta __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
561
562 struct mt7996_vif *vif;
563+ u8 pri_link;
564+ u8 sec_link;
565 };
566
567 struct mt7996_bss_conf {
developer05f3b2b2024-08-19 19:17:34 +0800568@@ -857,6 +859,9 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_bss_conf *conf,
developer66e89bc2024-04-23 14:50:01 +0800569 struct mt7996_bss_conf *mconf,
570 struct ieee80211_link_sta *link_sta,
571 struct mt7996_link_sta *mlink, bool enable, bool newly);
572+int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
573+ struct mt7996_bss_conf *mconf,
574+ struct mt7996_link_sta *mlink);
575 int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
576 struct ieee80211_ampdu_params *params,
577 bool add);
developer05f3b2b2024-08-19 19:17:34 +0800578@@ -880,6 +885,8 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
developer66e89bc2024-04-23 14:50:01 +0800579 struct mt7996_bss_conf *mconf,
580 struct ieee80211_link_sta *link_sta,
581 struct mt7996_link_sta *mlink, bool changed);
582+int mt7996_mcu_add_mld_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
583+ struct ieee80211_sta *sta, unsigned long add);
584 int mt7996_set_channel(struct mt7996_phy *phy, struct cfg80211_chan_def *chandef);
585 int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag);
586 int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct mt7996_bss_conf *mconf);
587--
developer9237f442024-06-14 17:13:04 +08005882.18.0
developer66e89bc2024-04-23 14:50:01 +0800589