blob: 1819f1223962c5ea9574dfbde0fb988a2b5a7818 [file] [log] [blame]
developerd0c89452024-10-11 16:53:27 +08001From a025d78199c2a329723707c689075c34d7c780e5 Mon Sep 17 00:00:00 2001
developer05f3b2b2024-08-19 19:17:34 +08002From: Shayne Chen <shayne.chen@mediatek.com>
3Date: Fri, 31 May 2024 18:14:59 +0800
developerd0c89452024-10-11 16:53:27 +08004Subject: [PATCH 170/223] mtk: mt76: mt7996: add AP affiliated link removal
developer05f3b2b2024-08-19 19:17:34 +08005 support
6
7Add support for ap link removal of MLD reconfiguration.
8
developerd0c89452024-10-11 16:53:27 +08009Change-Id: I27a611dcf6698f89f6a3a67f893a166d2afe6b1f
developer05f3b2b2024-08-19 19:17:34 +080010Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
11---
12 mt76_connac_mcu.h | 3 +
13 mt7996/main.c | 68 ++++++++++++---
14 mt7996/mcu.c | 217 ++++++++++++++++++++++++++++++++++++++++++++++
15 mt7996/mcu.h | 89 ++++++++++++++++++-
16 mt7996/mt7996.h | 2 +
17 5 files changed, 367 insertions(+), 12 deletions(-)
18
19diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
developerd0c89452024-10-11 16:53:27 +080020index 302567e3..4976d944 100644
developer05f3b2b2024-08-19 19:17:34 +080021--- a/mt76_connac_mcu.h
22+++ b/mt76_connac_mcu.h
developerd0c89452024-10-11 16:53:27 +080023@@ -1079,6 +1079,7 @@ enum {
developer05f3b2b2024-08-19 19:17:34 +080024 MCU_UNI_EVENT_PP = 0x5a,
25 MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
26 MCU_UNI_EVENT_ALL_STA_INFO = 0x6e,
27+ MCU_UNI_EVENT_MLD = 0x81,
28 };
29
30 #define MCU_UNI_CMD_EVENT BIT(1)
developerd0c89452024-10-11 16:53:27 +080031@@ -1324,6 +1325,7 @@ enum {
developer05f3b2b2024-08-19 19:17:34 +080032 MCU_UNI_CMD_ALL_STA_INFO = 0x6e,
33 MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
34 MCU_UNI_CMD_PTA_3WIRE_CTRL = 0x78,
35+ MCU_UNI_CMD_MLD = 0x82,
36 };
37
38 enum {
developerd0c89452024-10-11 16:53:27 +080039@@ -1398,6 +1400,7 @@ enum {
developer05f3b2b2024-08-19 19:17:34 +080040 UNI_BSS_INFO_PM_DISABLE = 27,
41 UNI_BSS_INFO_BCN_CRIT_UPDATE = 32,
42 UNI_BSS_INFO_BCN_STA_PROF_CSA = 37,
43+ UNI_BSS_INFO_BCN_ML_RECONF = 38,
44 };
45
46 enum {
47diff --git a/mt7996/main.c b/mt7996/main.c
developerd0c89452024-10-11 16:53:27 +080048index c95e7e35..6ad4558b 100644
developer05f3b2b2024-08-19 19:17:34 +080049--- a/mt7996/main.c
50+++ b/mt7996/main.c
51@@ -319,6 +319,21 @@ static void mt7996_remove_bss_conf(struct ieee80211_vif *vif,
52 list_del_init(&mlink->wcid.poll_list);
53 spin_unlock_bh(&dev->mt76.sta_poll_lock);
54
55+ /* reassign a new bss wcid if the previous one was removed */
56+ if (vif->txq && ieee80211_vif_is_mld(vif) &&
57+ hweight16(vif->valid_links) > 1) {
58+ struct mt76_txq *mtxq = (struct mt76_txq *)vif->txq->drv_priv;
59+
60+ if (mtxq->wcid == mlink->wcid.idx) {
61+ u8 new_link = __ffs(vif->valid_links & ~BIT(link_id));
62+ struct mt7996_link_sta *new_mlink =
63+ mlink_dereference_protected(&mvif->sta, new_link);
64+
65+ if (new_mlink)
66+ mtxq->wcid = new_mlink->wcid.idx;
67+ }
68+ }
69+
70 mt76_wcid_cleanup(&dev->mt76, &mlink->wcid);
71
72 if (mlink != &mvif->sta.deflink)
73@@ -425,7 +440,7 @@ static int mt7996_add_bss_conf(struct mt7996_phy *phy,
74 mt7996_mac_wtbl_update(dev, idx,
75 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
76
77- if (vif->txq) {
78+ if (vif->txq && hweight16(vif->valid_links) <= 1) {
79 mtxq = (struct mt76_txq *)vif->txq->drv_priv;
80 mtxq->wcid = idx;
81 }
82@@ -1128,6 +1143,8 @@ static void mt7996_remove_link_sta(struct mt7996_dev *dev,
83 {
84 struct ieee80211_sta *sta = link_sta->sta;
85 struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
86+ u16 valid_links = sta->valid_links;
87+ bool pri_changed;
88 int i;
89
90 if (!mlink)
91@@ -1148,6 +1165,7 @@ static void mt7996_remove_link_sta(struct mt7996_dev *dev,
92 mt7996_mac_twt_teardown_flow(dev, mlink, i);
93
94 rcu_assign_pointer(mlink->sta->link[mlink->wcid.link_id], NULL);
95+ rcu_assign_pointer(dev->mt76.wcid[mlink->wcid.idx], NULL);
96
97 spin_lock_bh(&dev->mt76.sta_poll_lock);
98 if (!list_empty(&mlink->wcid.poll_list))
99@@ -1156,17 +1174,41 @@ static void mt7996_remove_link_sta(struct mt7996_dev *dev,
100 list_del_init(&mlink->rc_list);
101 spin_unlock_bh(&dev->mt76.sta_poll_lock);
102
103- /* TODO: update primary link */
104- if (sta->valid_links) {
105- if (mlink->wcid.link_id == msta->pri_link)
106- msta->pri_link = msta->sec_link;
107+ valid_links &= ~BIT(mlink->wcid.link_id);
108+ if (!valid_links)
109+ goto done;
110
111- if (sta->valid_links & ~(BIT(msta->pri_link)))
112- msta->sec_link = __ffs(sta->valid_links & ~(BIT(msta->pri_link)));
113- else
114- msta->sec_link = msta->pri_link;
115+ /* update primary and secondary link */
116+ pri_changed = mlink->wcid.link_id == msta->pri_link;
117+ if (pri_changed)
118+ msta->pri_link = msta->sec_link;
119+
120+ if (valid_links & ~(BIT(msta->pri_link)))
121+ msta->sec_link = __ffs(valid_links & ~(BIT(msta->pri_link)));
122+ else
123+ msta->sec_link = msta->pri_link;
124+
125+ if (pri_changed) {
126+ struct mt7996_link_sta *mlink_new =
127+ mlink_dereference_protected(msta, msta->pri_link);
128+
129+ if (!mlink_new)
130+ goto done;
131+
132+ mlink_new->wcid.ampdu_state = mlink->wcid.ampdu_state;
133+ for (i = 0; i < ARRAY_SIZE(mlink->wcid.aggr); i++)
134+ rcu_assign_pointer(mlink_new->wcid.aggr[i], mlink->wcid.aggr[i]);
135+ for (i = 0; i < ARRAY_SIZE(sta->txq); i++) {
136+ struct mt76_txq *mtxq;
137+
138+ if (!sta->txq[i])
139+ continue;
140+ mtxq = (struct mt76_txq *)sta->txq[i]->drv_priv;
141+ mtxq->wcid = mlink_new->wcid.idx;
142+ }
143 }
144
145+done:
146 mt76_wcid_cleanup(&dev->mt76, &mlink->wcid);
147 mt76_wcid_mask_clear(dev->mt76.wcid_mask, mlink->wcid.idx);
148 mt76_wcid_mask_clear(dev->mt76.wcid_phy_mask, mlink->wcid.idx);
developerd0c89452024-10-11 16:53:27 +0800149@@ -3108,9 +3150,15 @@ mt7996_change_sta_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
developer05f3b2b2024-08-19 19:17:34 +0800150 mt76_vif_dbg(vif, "STA %pM old=0x%x, new=0x%x\n", sta->addr, old_links, new_links);
151 mutex_lock(&dev->mt76.mutex);
152
153- if (rem)
154+ if (rem) {
155 mt7996_mac_sta_remove_links(dev, vif, sta, rem);
156
157+ /* Todo: update hw info of MLD STA */
158+ /* ret = mt7996_mcu_add_mld_sta(dev, vif, sta, new_links); */
159+ /* if (ret) */
160+ /* goto remove; */
161+ }
162+
163 ret = mt7996_mac_sta_add_links(dev, vif, sta, add, false);
164 if (ret)
165 goto remove;
166diff --git a/mt7996/mcu.c b/mt7996/mcu.c
developerd0c89452024-10-11 16:53:27 +0800167index 856168f6..417c38a3 100644
developer05f3b2b2024-08-19 19:17:34 +0800168--- a/mt7996/mcu.c
169+++ b/mt7996/mcu.c
developerd0c89452024-10-11 16:53:27 +0800170@@ -1355,6 +1355,48 @@ mt7996_mcu_pp_event(struct mt7996_dev *dev, struct sk_buff *skb)
developer05f3b2b2024-08-19 19:17:34 +0800171 }
172 }
173
174+static void
175+mt7996_mcu_mld_reconf_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
176+{
177+ struct mt7996_mld_event_data *data = priv;
178+ struct mt7996_mcu_mld_ap_reconf_event *reconf = (void *)data->data;
179+
180+ if (!ether_addr_equal(vif->addr, data->mld_addr))
181+ return;
182+
183+ ieee80211_links_removed(vif, le16_to_cpu(reconf->link_bitmap));
184+}
185+
186+static void
187+mt7996_mcu_mld_event(struct mt7996_dev *dev, struct sk_buff *skb)
188+{
189+ struct mt7996_mcu_mld_event *event = (void *)skb->data;
190+ struct mt7996_mld_event_data data = {};
191+ struct tlv *tlv;
192+ int len;
193+
194+ memcpy(data.mld_addr, event->mld_addr, ETH_ALEN);
195+ skb_pull(skb, sizeof(*event));
196+ tlv = (struct tlv *)skb->data;
197+ len = skb->len;
198+
199+ while (len > 0 && le16_to_cpu(tlv->len) <= len) {
200+ switch (le16_to_cpu(tlv->tag)) {
201+ case UNI_EVENT_MLD_RECONF_AP_REM_TIMER:
202+ data.data = (u8 *)tlv;
203+ ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw,
204+ IEEE80211_IFACE_ITER_RESUME_ALL,
205+ mt7996_mcu_mld_reconf_finish, &data);
206+ break;
207+ default:
208+ break;
209+ }
210+
211+ len -= le16_to_cpu(tlv->len);
212+ tlv = (struct tlv *)((u8 *)(tlv) + le16_to_cpu(tlv->len));
213+ }
214+}
215+
216 static void
217 mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
218 {
developerd0c89452024-10-11 16:53:27 +0800219@@ -1383,6 +1425,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
developer05f3b2b2024-08-19 19:17:34 +0800220 case MCU_UNI_EVENT_PP:
221 mt7996_mcu_pp_event(dev, skb);
222 break;
223+ case MCU_UNI_EVENT_MLD:
224+ mt7996_mcu_mld_event(dev, skb);
225+ break;
226 #ifdef CONFIG_MTK_DEBUG
227 case MCU_UNI_EVENT_SR:
228 mt7996_mcu_rx_sr_event(dev, skb);
developerd0c89452024-10-11 16:53:27 +0800229@@ -3176,6 +3221,44 @@ out:
developer05f3b2b2024-08-19 19:17:34 +0800230 MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
231 }
232
233+int mt7996_mcu_add_mld_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
234+ struct ieee80211_sta *sta, unsigned long add)
235+{
236+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
237+ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
238+ u8 link_id;
239+
240+ if (!sta->mlo)
241+ return 0;
242+
243+ for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
244+ struct mt7996_bss_conf *mconf =
245+ mconf_dereference_protected(mvif, link_id);
246+ struct mt7996_link_sta *mlink =
247+ mlink_dereference_protected(msta, link_id);
248+ struct sk_buff *skb;
249+ int ret;
250+
251+ if (!mconf || !mlink)
252+ continue;
253+
254+ skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mconf->mt76,
255+ &mlink->wcid,
256+ MT7996_STA_UPDATE_MAX_SIZE);
257+ if (IS_ERR(skb))
258+ return PTR_ERR(skb);
259+ /* starec mld setup */
260+ mt7996_mcu_sta_mld_setup_tlv(dev, skb, sta, add);
261+ /* starec eht mld */
262+ mt7996_mcu_sta_eht_mld_tlv(dev, skb, sta);
263+ ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
264+ MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
265+ if (ret)
266+ return ret;
267+ }
268+ return 0;
269+}
270+
271 int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
272 struct mt7996_bss_conf *mconf,
273 struct mt7996_link_sta *mlink)
developerd0c89452024-10-11 16:53:27 +0800274@@ -3388,6 +3471,51 @@ int mt7996_mcu_add_dev_info(struct mt7996_phy *phy,
developer05f3b2b2024-08-19 19:17:34 +0800275 &data, sizeof(data), true);
276 }
277
278+static int
279+mt7996_mcu_mld_reconf(struct mt7996_dev *dev, struct ieee80211_vif *vif,
280+ u16 removed_links, u16 *removal_count)
281+{
282+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
283+ struct mld_req_hdr hdr = { .mld_idx = 0xff };
284+ struct mld_reconf_timer *rt;
285+ struct sk_buff *skb;
286+ struct tlv *tlv;
287+ int len = sizeof(hdr) + sizeof(*rt);
288+ unsigned long rem = removed_links;
289+ u8 link_id;
290+
291+ memcpy(hdr.mld_addr, vif->addr, ETH_ALEN);
292+
293+ skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, len);
294+ if (!skb)
295+ return -ENOMEM;
296+
297+ skb_put_data(skb, &hdr, sizeof(hdr));
298+
299+ tlv = mt7996_mcu_add_uni_tlv(skb, UNI_CMD_MLD_RECONF_AP_REM_TIMER, sizeof(*rt));
300+ rt = (struct mld_reconf_timer *)tlv;
301+ rt->link_bitmap = cpu_to_le16(removed_links);
302+
303+ for_each_set_bit(link_id, &rem, IEEE80211_MLD_MAX_NUM_LINKS) {
304+ struct ieee80211_bss_conf *conf =
305+ link_conf_dereference_protected(vif, link_id);
306+ struct mt7996_bss_conf *mconf =
307+ mconf_dereference_protected(mvif, link_id);
308+ u8 band_idx;
309+ u16 to_sec;
310+
311+ if (!conf || !mconf)
312+ continue;
313+
314+ band_idx = mconf->phy->mt76->band_idx;
315+ to_sec = conf->beacon_int * removal_count[link_id] / 1000;
316+ rt->to_sec[band_idx] = cpu_to_le16(to_sec);
317+ rt->bss_idx[band_idx] = mconf->mt76.idx;
318+ }
319+
320+ return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_WM_UNI_CMD(MLD), true);
321+}
322+
323 static void
324 mt7996_mcu_beacon_cntdwn(struct ieee80211_bss_conf *conf, struct sk_buff *rskb,
325 struct sk_buff *skb,
developerd0c89452024-10-11 16:53:27 +0800326@@ -3582,6 +3710,94 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_bss_conf *conf,
developer05f3b2b2024-08-19 19:17:34 +0800327 mt7996_packet_log_to_host(dev, skb->data, skb->len, PKT_BIN_DEBUG_TX, 0);
328 }
329
330+static void
331+mt7996_mcu_beacon_ml_reconf(struct mt7996_dev *dev,
332+ struct ieee80211_bss_conf *conf,
333+ struct sk_buff *rskb, struct sk_buff *skb,
334+ struct ieee80211_mutable_offsets *offs)
335+{
336+ struct mt7996_vif *mvif = (struct mt7996_vif *)conf->vif->drv_priv;
337+ struct bss_bcn_ml_reconf_tlv *reconf;
338+ struct bss_bcn_ml_reconf_offset *reconf_offs;
339+ const struct element *elem, *sub;
340+ struct tlv *tlv;
341+ u16 removal_offs[IEEE80211_MLD_MAX_NUM_LINKS] = {};
342+ u16 removal_count[IEEE80211_MLD_MAX_NUM_LINKS] = {};
343+ u16 tail_offset = offs->tim_offset + offs->tim_length;
344+ unsigned long removed_links = 0;
345+ bool has_reconf = false;
346+ u8 link_id, *beacon_tail = skb->data + tail_offset;
347+
348+ if (!ieee80211_vif_is_mld(conf->vif))
349+ return;
350+
351+ /* TODO: currently manually parse reconf info directly from the IE, it
352+ * is expected to be passed from upper layer in the future.
353+ */
354+ for_each_element_extid(elem, WLAN_EID_EXT_EHT_MULTI_LINK,
355+ beacon_tail, skb->len - tail_offset) {
356+ if (ieee80211_mle_type_ok(elem->data + 1,
357+ IEEE80211_ML_CONTROL_TYPE_RECONF,
358+ elem->datalen - 1)) {
359+ has_reconf = true;
360+ break;
361+ }
362+ }
363+
364+ if (!has_reconf)
365+ return;
366+
367+ for_each_mle_subelement(sub, elem->data + 1, elem->datalen - 1) {
368+ struct ieee80211_mle_per_sta_profile *prof = (void *)sub->data;
369+ u8 *pos = prof->variable;
370+ u16 control;
371+
372+ if (sub->id != IEEE80211_MLE_SUBELEM_PER_STA_PROFILE)
373+ continue;
374+
375+ if (!ieee80211_mle_reconf_sta_prof_size_ok(sub->data,
376+ sub->datalen))
377+ return;
378+
379+ control = le16_to_cpu(prof->control);
380+ link_id = control & IEEE80211_MLE_STA_RECONF_CONTROL_LINK_ID;
381+
382+ removed_links |= BIT(link_id);
383+
384+ if (control & IEEE80211_MLE_STA_RECONF_CONTROL_STA_MAC_ADDR_PRESENT)
385+ pos += 6;
386+
387+ if (control & IEEE80211_MLE_STA_RECONF_CONTROL_AP_REM_TIMER_PRESENT) {
388+ removal_offs[link_id] = pos - skb->data;
389+ removal_count[link_id] = le16_to_cpu(*(__le16 *)pos);
390+ }
391+ }
392+
393+ if (!removed_links)
394+ return;
395+
396+ /* the first link to be removed */
397+ if (conf->link_id == ffs(removed_links) - 1)
398+ mt7996_mcu_mld_reconf(dev, conf->vif, removed_links, removal_count);
399+
400+ tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_ML_RECONF,
401+ sizeof(*reconf) +
402+ sizeof(*reconf_offs) * hweight16(removed_links));
403+ reconf = (struct bss_bcn_ml_reconf_tlv *)tlv;
404+ reconf->reconf_count = hweight16(removed_links);
405+
406+ reconf_offs = (struct bss_bcn_ml_reconf_offset *)reconf->offset;
407+ for_each_set_bit(link_id, &removed_links, IEEE80211_MLD_MAX_NUM_LINKS) {
408+ struct mt7996_bss_conf *mconf =
409+ mconf_dereference_protected(mvif, link_id);
410+
411+ reconf_offs->ap_removal_timer_offs =
412+ cpu_to_le16(removal_offs[link_id]);
413+ reconf_offs->bss_idx = mconf->mt76.idx;
414+ reconf_offs++;
415+ }
416+}
417+
418 int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
419 struct ieee80211_bss_conf *conf,
420 struct mt7996_bss_conf *mconf, int en)
developerd0c89452024-10-11 16:53:27 +0800421@@ -3635,6 +3851,7 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
developer05f3b2b2024-08-19 19:17:34 +0800422 mt7996_mcu_beacon_cntdwn(conf, rskb, skb, &offs);
423 mt7996_mcu_beacon_sta_prof_csa(rskb, conf, &offs);
424 mt7996_mcu_beacon_crit_update(rskb, skb, conf, mconf, &offs);
425+ mt7996_mcu_beacon_ml_reconf(dev, conf, rskb, skb, &offs);
426 out:
427 dev_kfree_skb(skb);
428 return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
429diff --git a/mt7996/mcu.h b/mt7996/mcu.h
430index 739e357c..7c559d2b 100644
431--- a/mt7996/mcu.h
432+++ b/mt7996/mcu.h
433@@ -546,6 +546,20 @@ struct bss_bcn_sta_prof_cntdwn_tlv {
434 u8 pkt_content[9];
435 } __packed;
436
437+struct bss_bcn_ml_reconf_tlv {
438+ __le16 tag;
439+ __le16 len;
440+ u8 reconf_count;
441+ u8 rsv[3];
442+ u8 offset[];
443+} __packed;
444+
445+struct bss_bcn_ml_reconf_offset {
446+ __le16 ap_removal_timer_offs;
447+ u8 bss_idx;
448+ u8 rsv;
449+} __packed;
450+
451 struct bss_txcmd_tlv {
452 __le16 tag;
453 __le16 len;
454@@ -594,6 +608,17 @@ struct bss_mld_tlv {
455 u8 __rsv[3];
456 } __packed;
457
458+struct bss_mld_link_op_tlv {
459+ __le16 tag;
460+ __le16 len;
461+ u8 group_mld_id;
462+ u8 own_mld_id;
463+ u8 mac_addr[ETH_ALEN];
464+ u8 remap_idx;
465+ u8 link_operation;
466+ u8 rsv[2];
467+} __packed;
468+
469 struct sta_rec_ht_uni {
470 __le16 tag;
471 __le16 len;
472@@ -1003,8 +1028,9 @@ enum {
473 sizeof(struct bss_bcn_cntdwn_tlv) + \
474 sizeof(struct bss_bcn_mbss_tlv) + \
475 sizeof(struct bss_bcn_crit_update_tlv) + \
476- sizeof(struct bss_bcn_sta_prof_cntdwn_tlv)) \
477-
478+ sizeof(struct bss_bcn_sta_prof_cntdwn_tlv) + \
479+ sizeof(struct bss_bcn_ml_reconf_tlv) + \
480+ 3 * sizeof(struct bss_bcn_ml_reconf_offset))
481 #define MT7996_MAX_BSS_OFFLOAD_SIZE (MT7996_MAX_BEACON_SIZE + \
482 MT7996_BEACON_UPDATE_SIZE)
483
484@@ -1105,6 +1131,65 @@ enum {
485 UNI_CMD_THERMAL_PROTECT_DUTY_CONFIG,
486 };
487
488+struct mld_req_hdr {
489+ u8 ver;
490+ u8 mld_addr[ETH_ALEN];
491+ u8 mld_idx;
492+ u8 flag;
493+ u8 rsv[3];
494+ u8 buf[];
495+} __packed;
496+
497+struct mld_reconf_timer {
498+ __le16 tag;
499+ __le16 len;
500+ __le16 link_bitmap;
501+ __le16 to_sec[__MT_MAX_BAND]; /* timeout of reconf (second) */
502+ u8 bss_idx[__MT_MAX_BAND];
503+ u8 rsv;
504+} __packed;
505+
506+struct mld_reconf_stop_link {
507+ __le16 tag;
508+ __le16 len;
509+ __le16 link_bitmap;
510+ u8 rsv[2];
511+ u8 bss_idx[16];
512+} __packed;
513+
514+enum {
515+ UNI_CMD_MLD_RECONF_AP_REM_TIMER = 0x03,
516+};
517+
518+struct mt7996_mcu_mld_event {
519+ struct mt7996_mcu_rxd rxd;
520+
521+ /* fixed field */
522+ u8 ver;
523+ u8 mld_addr[ETH_ALEN];
524+ u8 mld_idx;
525+ u8 rsv[4];
526+ /* tlv */
527+ u8 buf[];
528+} __packed;
529+
530+struct mt7996_mld_event_data {
531+ u8 mld_addr[ETH_ALEN];
532+ u8 *data;
533+};
534+
535+struct mt7996_mcu_mld_ap_reconf_event {
536+ __le16 tag;
537+ __le16 len;
538+ __le16 link_bitmap;
539+ u8 bss_idx[3];
540+ u8 rsv[3];
541+} __packed;
542+
543+enum {
544+ UNI_EVENT_MLD_RECONF_AP_REM_TIMER = 0x04,
545+};
546+
547 struct tx_power_ctrl {
548 u8 _rsv[4];
549
550diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developerd0c89452024-10-11 16:53:27 +0800551index a02e976a..a7655a61 100644
developer05f3b2b2024-08-19 19:17:34 +0800552--- a/mt7996/mt7996.h
553+++ b/mt7996/mt7996.h
developerd0c89452024-10-11 16:53:27 +0800554@@ -1087,6 +1087,8 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev,
developer05f3b2b2024-08-19 19:17:34 +0800555 struct mt7996_bss_conf *mconf,
556 struct ieee80211_link_sta *link_sta,
557 struct mt7996_link_sta *mlink, bool changed);
558+int mt7996_mcu_add_mld_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
559+ struct ieee80211_sta *sta, unsigned long add);
560 int mt7996_set_channel(struct mt7996_phy *phy, struct cfg80211_chan_def *chandef);
561 int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag, bool sta);
562 int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct mt7996_bss_conf *mconf);
563--
developerd0c89452024-10-11 16:53:27 +08005642.45.2
developer05f3b2b2024-08-19 19:17:34 +0800565