blob: a581775f0a8b58f7fb920d4c296539ad73c1bb61 [file] [log] [blame]
developer7e2761e2023-10-12 08:11:13 +08001From dda3205c68ab3b38945f0066be5fc95ba067f3af Mon Sep 17 00:00:00 2001
2From: Benjamin Lin <benjamin-jw.lin@mediatek.com>
3Date: Mon, 11 Sep 2023 16:35:15 +0800
4Subject: [PATCH 78/98] wifi: mt76: mt7996: add support for HW-ATF
5 initialization
6
7---
8 mt7996/init.c | 43 ++++++++
9 mt7996/mcu.c | 263 +++++++++++++++++++++++++++++++++++++++++++-----
10 mt7996/mcu.h | 1 +
11 mt7996/mt7996.h | 94 +++++++++++++++++
12 4 files changed, 376 insertions(+), 25 deletions(-)
13
14diff --git a/mt7996/init.c b/mt7996/init.c
15index d539af0..d1db1d7 100644
16--- a/mt7996/init.c
17+++ b/mt7996/init.c
18@@ -553,6 +553,37 @@ int mt7996_txbf_init(struct mt7996_dev *dev)
19 return mt7996_mcu_set_txbf(dev, BF_HW_EN_UPDATE);
20 }
21
22+static int mt7996_vow_init(struct mt7996_phy *phy)
23+{
24+ struct mt7996_vow_ctrl *vow = &phy->dev->vow;
25+ int ret;
26+
27+ vow->atf_enable = true;
28+ vow->watf_enable = false;
29+ vow->max_deficit = 64;
30+ vow->sch_type = VOW_SCH_TYPE_FOLLOW_POLICY;
31+ vow->sch_policy = VOW_SCH_POLICY_SRR;
32+
33+ vow->drr_quantum[0] = VOW_DRR_QUANTUM_L0;
34+ vow->drr_quantum[1] = VOW_DRR_QUANTUM_L1;
35+ vow->drr_quantum[2] = VOW_DRR_QUANTUM_L2;
36+ vow->drr_quantum[3] = VOW_DRR_QUANTUM_L3;
37+ vow->drr_quantum[4] = VOW_DRR_QUANTUM_L4;
38+ vow->drr_quantum[5] = VOW_DRR_QUANTUM_L5;
39+ vow->drr_quantum[6] = VOW_DRR_QUANTUM_L6;
40+ vow->drr_quantum[7] = VOW_DRR_QUANTUM_L7;
41+
42+ ret = mt7996_mcu_set_vow_drr_ctrl(phy, NULL, VOW_DRR_CTRL_AIRTIME_DEFICIT_BOUND);
43+ if (ret)
44+ return ret;
45+
46+ ret = mt7996_mcu_set_vow_drr_ctrl(phy, NULL, VOW_DRR_CTRL_AIRTIME_QUANTUM_ALL);
47+ if (ret)
48+ return ret;
49+
50+ return mt7996_mcu_set_vow_feature_ctrl(phy);
51+}
52+
53 static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
54 enum mt76_band_id band)
55 {
56@@ -626,6 +657,12 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
57 if (ret)
58 goto error;
59
60+ if (mt7996_vow_should_enable(dev)) {
61+ ret = mt7996_vow_init(phy);
62+ if (ret)
63+ goto error;
64+ }
65+
66 ret = mt7996_init_debugfs(phy);
67 if (ret)
68 goto error;
69@@ -1315,6 +1352,12 @@ int mt7996_register_device(struct mt7996_dev *dev)
70
71 dev->recovery.hw_init_done = true;
72
73+ if (mt7996_vow_should_enable(dev)) {
74+ ret = mt7996_vow_init(&dev->phy);
75+ if (ret)
76+ goto error;
77+ }
78+
79 ret = mt7996_init_debugfs(&dev->phy);
80 if (ret)
81 goto error;
82diff --git a/mt7996/mcu.c b/mt7996/mcu.c
83index b2cb627..1915a22 100644
84--- a/mt7996/mcu.c
85+++ b/mt7996/mcu.c
86@@ -2147,34 +2147,35 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
87 }
88
89 static int
90-mt7996_mcu_add_group(struct mt7996_dev *dev, struct ieee80211_vif *vif,
91- struct ieee80211_sta *sta)
92+mt7996_mcu_sta_init_vow(struct mt7996_phy *phy, struct mt7996_sta *msta)
93 {
94-#define MT_STA_BSS_GROUP 1
95- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
96- struct mt7996_sta *msta;
97- struct {
98- u8 __rsv1[4];
99+ struct mt7996_vow_sta_ctrl *vow = &msta->vow;
100+ u8 omac_idx = msta->vif->mt76.omac_idx;
101+ int ret;
102
103- __le16 tag;
104- __le16 len;
105- __le16 wlan_idx;
106- u8 __rsv2[2];
107- __le32 action;
108- __le32 val;
109- u8 __rsv3[8];
110- } __packed req = {
111- .tag = cpu_to_le16(UNI_VOW_DRR_CTRL),
112- .len = cpu_to_le16(sizeof(req) - 4),
113- .action = cpu_to_le32(MT_STA_BSS_GROUP),
114- .val = cpu_to_le32(mvif->mt76.idx % 16),
115- };
116+ /* Assignment of STA BSS group index aligns FW.
117+ * Each band has its own BSS group bitmap space.
118+ * 0: BSS 0
119+ * 4..18: BSS 0x11..0x1f
120+ */
121+ vow->bss_grp_idx = (omac_idx <= HW_BSSID_MAX)
122+ ? omac_idx
123+ : HW_BSSID_MAX + omac_idx - EXT_BSSID_START;
124+ vow->paused = false;
125+ vow->drr_quantum[IEEE80211_AC_VO] = VOW_DRR_QUANTUM_IDX0;
126+ vow->drr_quantum[IEEE80211_AC_VI] = VOW_DRR_QUANTUM_IDX1;
127+ vow->drr_quantum[IEEE80211_AC_BE] = VOW_DRR_QUANTUM_IDX2;
128+ vow->drr_quantum[IEEE80211_AC_BK] = VOW_DRR_QUANTUM_IDX2;
129+
130+ ret = mt7996_mcu_set_vow_drr_ctrl(phy, msta, VOW_DRR_CTRL_STA_BSS_GROUP);
131+ if (ret)
132+ return ret;
133
134- msta = sta ? (struct mt7996_sta *)sta->drv_priv : &mvif->sta;
135- req.wlan_idx = cpu_to_le16(msta->wcid.idx);
136+ ret = mt7996_mcu_set_vow_drr_ctrl(phy, msta, VOW_DRR_CTRL_STA_PAUSE);
137+ if (ret)
138+ return ret;
139
140- return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(VOW), &req,
141- sizeof(req), true);
142+ return mt7996_mcu_set_vow_drr_ctrl(phy, msta, VOW_DRR_CTRL_STA_ALL);
143 }
144
145 int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
146@@ -2228,7 +2229,7 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
147 mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta);
148 }
149
150- ret = mt7996_mcu_add_group(dev, vif, sta);
151+ ret = mt7996_mcu_sta_init_vow(mvif->phy, msta);
152 if (ret) {
153 dev_kfree_skb(skb);
154 return ret;
155@@ -5027,6 +5028,218 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
156 MCU_WM_UNI_CMD(TXPOWER), true);
157 }
158
159+int mt7996_mcu_set_vow_drr_ctrl(struct mt7996_phy *phy, struct mt7996_sta *msta,
160+ enum vow_drr_ctrl_id id)
161+{
162+ struct mt7996_vow_sta_ctrl *vow = msta ? &msta->vow : NULL;
163+ u32 val = 0;
164+ struct {
165+ u8 __rsv1[4];
166+
167+ __le16 tag;
168+ __le16 len;
169+ __le16 wlan_idx;
170+ u8 band_idx;
171+ u8 wmm_idx;
172+ __le32 ctrl_id;
173+
174+ union {
175+ __le32 val;
176+ u8 drr_quantum[VOW_DRR_QUANTUM_NUM];
177+ };
178+
179+ u8 __rsv2[3];
180+ u8 omac_idx;
181+ } __packed req = {
182+ .tag = cpu_to_le16(UNI_VOW_DRR_CTRL),
183+ .len = cpu_to_le16(sizeof(req) - 4),
184+ .wlan_idx = cpu_to_le16(msta ? msta->wcid.idx : 0),
185+ .band_idx = phy->mt76->band_idx,
186+ .wmm_idx = msta ? msta->vif->mt76.wmm_idx : 0,
187+ .ctrl_id = cpu_to_le32(id),
188+ .omac_idx = msta ? msta->vif->mt76.omac_idx : 0
189+ };
190+
191+ switch (id) {
192+ case VOW_DRR_CTRL_STA_ALL:
193+ val |= FIELD_PREP(MT7996_DRR_STA_BSS_GRP_MASK, vow->bss_grp_idx);
194+ val |= FIELD_PREP(MT7996_DRR_STA_AC0_QNTM_MASK, vow->drr_quantum[IEEE80211_AC_BK]);
195+ val |= FIELD_PREP(MT7996_DRR_STA_AC1_QNTM_MASK, vow->drr_quantum[IEEE80211_AC_BE]);
196+ val |= FIELD_PREP(MT7996_DRR_STA_AC2_QNTM_MASK, vow->drr_quantum[IEEE80211_AC_VI]);
197+ val |= FIELD_PREP(MT7996_DRR_STA_AC3_QNTM_MASK, vow->drr_quantum[IEEE80211_AC_VO]);
198+ req.val = cpu_to_le32(val);
199+ break;
200+ case VOW_DRR_CTRL_STA_BSS_GROUP:
201+ req.val = cpu_to_le32(vow->bss_grp_idx);
202+ break;
203+ case VOW_DRR_CTRL_AIRTIME_DEFICIT_BOUND:
204+ req.val = cpu_to_le32(phy->dev->vow.max_deficit);
205+ break;
206+ case VOW_DRR_CTRL_AIRTIME_QUANTUM_ALL:
207+ memcpy(req.drr_quantum, phy->dev->vow.drr_quantum, VOW_DRR_QUANTUM_NUM);
208+ break;
209+ case VOW_DRR_CTRL_STA_PAUSE:
210+ req.val = cpu_to_le32(vow->paused);
211+ break;
212+ default:
213+ dev_err(phy->dev->mt76.dev, "Unknown VoW DRR Control ID: %u\n", id);
214+ return -EINVAL;
215+ }
216+
217+ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(VOW),
218+ &req, sizeof(req), true);
219+}
220+
221+int mt7996_mcu_set_vow_feature_ctrl(struct mt7996_phy *phy)
222+{
223+ struct mt7996_vow_ctrl *vow = &phy->dev->vow;
224+ struct {
225+ u8 __rsv1[4];
226+
227+ __le16 tag;
228+ __le16 len;
229+
230+ /* DW0 */
231+ __le16 apply_bwc_enable_per_grp;
232+ __le16 apply_bwc_refill_period : 1;
233+ __le16 __rsv2 : 3;
234+ __le16 apply_band1_search_rule : 1;
235+ __le16 apply_band0_search_rule : 1;
236+ __le16 __rsv3 : 3;
237+ __le16 apply_watf_enable : 1;
238+ __le16 __rsv4 : 2;
239+ __le16 apply_grp_no_change_in_txop : 1;
240+ __le16 apply_atf_enable : 1;
241+ __le16 apply_bwc_token_refill_enable : 1;
242+ __le16 apply_bwc_enable : 1;
243+
244+ /* DW1 */
245+ __le16 apply_bwc_check_time_token_per_grp;
246+ __le16 __rsv5;
247+
248+ /* DW2 */
249+ __le16 apply_bwc_check_len_token_per_grp;
250+ __le16 __rsv6;
251+
252+ /* DW3 */
253+ u8 band_idx;
254+ u8 __rsv7[3];
255+
256+ /* DW4 */
257+ __le32 __rsv8;
258+
259+ /* DW5 */
260+ __le16 bwc_enable_per_grp;
261+ __le16 bwc_refill_period : 3;
262+ __le16 __rsv9 : 1;
263+ __le16 band1_search_rule : 1;
264+ __le16 band0_search_rule : 1;
265+ __le16 __rsv10 : 3;
266+ __le16 watf_enable : 1;
267+ __le16 __rsv11 : 2;
268+ __le16 grp_no_change_in_txop : 1;
269+ __le16 atf_enable : 1;
270+ __le16 bwc_token_refill_enable : 1;
271+ __le16 bwc_enable : 1;
272+
273+ /* DW6 */
274+ __le16 bwc_check_time_token_per_grp;
275+ __le16 __rsv12;
276+
277+ /* DW7 */
278+ __le16 bwc_check_len_token_per_grp;
279+ __le16 __rsv13;
280+
281+ /* DW8 */
282+ __le32 apply_atf_rts_sta_lock : 1;
283+ __le32 atf_rts_sta_lock : 1;
284+ __le32 apply_atf_keep_quantum : 1;
285+ __le32 atf_keep_quantum : 1;
286+ __le32 apply_tx_cnt_mode_ctrl : 1;
287+ __le32 tx_cnt_mode_ctrl : 4;
288+ __le32 apply_tx_measure_mode_enable : 1;
289+ __le32 tx_measure_mode_enable : 1;
290+ __le32 apply_backoff_ctrl : 1;
291+ __le32 backoff_bound_enable : 1;
292+ __le32 backoff_bound : 5;
293+ __le32 apply_atf_rts_fail_charge : 1;
294+ __le32 atf_rts_fail_charge : 1;
295+ __le32 apply_zero_eifs : 1;
296+ __le32 zero_eifs : 1;
297+ __le32 apply_rx_rifs_enable : 1;
298+ __le32 rx_rifs_enable : 1;
299+ __le32 apply_vow_ctrl : 1;
300+ __le32 vow_ctrl_val : 1;
301+ __le32 vow_ctrl_bit : 5;
302+ __le32 __rsv14 : 1;
303+
304+ /* DW9 */
305+ __le32 apply_spl_sta_num : 1;
306+ __le32 spl_sta_num : 3;
307+ __le32 dbg_lvl : 2;
308+ __le32 apply_atf_sch_ctrl : 1;
309+ __le32 atf_sch_type : 2;
310+ __le32 atf_sch_policy : 2;
311+ __le32 __rsv15 : 21;
312+ } __packed req = {
313+ .tag = cpu_to_le16(UNI_VOW_FEATURE_CTRL),
314+ .len = cpu_to_le16(sizeof(req) - 4),
315+ /* DW0 */
316+ .apply_bwc_enable_per_grp = cpu_to_le16(0xffff),
317+ .apply_bwc_refill_period = true,
318+ .apply_band1_search_rule = true,
319+ .apply_band0_search_rule = true,
320+ .apply_watf_enable = true,
321+ .apply_grp_no_change_in_txop = true,
322+ .apply_atf_enable = true,
323+ .apply_bwc_token_refill_enable = true,
324+ .apply_bwc_enable = true,
325+ /* DW1 */
326+ .apply_bwc_check_time_token_per_grp = cpu_to_le16(0xffff),
327+ /* DW2 */
328+ .apply_bwc_check_len_token_per_grp = cpu_to_le16(0xffff),
329+ /* DW3 */
330+ .band_idx = phy->mt76->band_idx,
331+ /* DW5 */
332+ .bwc_enable_per_grp = cpu_to_le16(0xffff),
333+ .bwc_refill_period = VOW_REFILL_PERIOD_32US,
334+ .band1_search_rule = VOW_SEARCH_WMM_FIRST,
335+ .band0_search_rule = VOW_SEARCH_WMM_FIRST,
336+ .watf_enable = vow->watf_enable,
337+ .grp_no_change_in_txop = true,
338+ .atf_enable = vow->atf_enable,
339+ .bwc_token_refill_enable = true,
340+ .bwc_enable = false,
341+ /* DW6 */
342+ .bwc_check_time_token_per_grp = cpu_to_le16(0x0),
343+ /* DW7 */
344+ .bwc_check_len_token_per_grp = cpu_to_le16(0x0),
345+ /* DW8 */
346+ .apply_atf_rts_sta_lock = false,
347+ .apply_atf_keep_quantum = true,
348+ .atf_keep_quantum = true,
349+ .apply_tx_cnt_mode_ctrl = false,
350+ .apply_tx_measure_mode_enable = false,
351+ .apply_backoff_ctrl = false,
352+ .apply_atf_rts_fail_charge = false,
353+ .apply_zero_eifs = false,
354+ .apply_rx_rifs_enable = false,
355+ .apply_vow_ctrl = true,
356+ .vow_ctrl_val = true,
357+ /* Reset DRR table when SER occurs. */
358+ .vow_ctrl_bit = 26,
359+ /* DW9 */
360+ .apply_spl_sta_num = false,
361+ .dbg_lvl = 0,
362+ .apply_atf_sch_ctrl = true,
363+ .atf_sch_type = vow->sch_type,
364+ .atf_sch_policy = vow->sch_policy
365+ };
366+
367+ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(VOW),
368+ &req, sizeof(req), true);
369+}
370+
371 #ifdef CONFIG_MTK_VENDOR
372 void mt7996_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
373 {
374diff --git a/mt7996/mcu.h b/mt7996/mcu.h
375index 0aa68f7..fb81645 100644
376--- a/mt7996/mcu.h
377+++ b/mt7996/mcu.h
378@@ -860,6 +860,7 @@ enum {
379
380 enum {
381 UNI_VOW_DRR_CTRL,
382+ UNI_VOW_FEATURE_CTRL,
383 UNI_VOW_RX_AT_AIRTIME_EN = 0x0b,
384 UNI_VOW_RX_AT_AIRTIME_CLR_EN = 0x0e,
385 UNI_VOW_RED_ENABLE = 0x18,
386diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
387index 4333d51..ba73520 100644
388--- a/mt7996/mt7996.h
389+++ b/mt7996/mt7996.h
390@@ -107,6 +107,12 @@
391 #define MT7996_RX_MSDU_PAGE_SIZE (128 + \
392 SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
393
394+#define MT7996_DRR_STA_BSS_GRP_MASK GENMASK(5, 0)
395+#define MT7996_DRR_STA_AC0_QNTM_MASK GENMASK(10, 8)
396+#define MT7996_DRR_STA_AC1_QNTM_MASK GENMASK(14, 12)
397+#define MT7996_DRR_STA_AC2_QNTM_MASK GENMASK(18, 16)
398+#define MT7996_DRR_STA_AC3_QNTM_MASK GENMASK(22, 20)
399+
400 struct mt7996_vif;
401 struct mt7996_sta;
402 struct mt7996_dfs_pulse;
403@@ -187,6 +193,79 @@ struct mt7996_twt_flow {
404
405 DECLARE_EWMA(avg_signal, 10, 8)
406
407+enum {
408+ VOW_SEARCH_AC_FIRST,
409+ VOW_SEARCH_WMM_FIRST
410+};
411+
412+enum {
413+ VOW_REFILL_PERIOD_1US,
414+ VOW_REFILL_PERIOD_2US,
415+ VOW_REFILL_PERIOD_4US,
416+ VOW_REFILL_PERIOD_8US,
417+ VOW_REFILL_PERIOD_16US,
418+ VOW_REFILL_PERIOD_32US,
419+ VOW_REFILL_PERIOD_64US,
420+ VOW_REFILL_PERIOD_128US
421+};
422+
423+/* Default DRR airtime quantum of each level */
424+enum {
425+ VOW_DRR_QUANTUM_L0 = 6,
426+ VOW_DRR_QUANTUM_L1 = 12,
427+ VOW_DRR_QUANTUM_L2 = 16,
428+ VOW_DRR_QUANTUM_L3 = 20,
429+ VOW_DRR_QUANTUM_L4 = 24,
430+ VOW_DRR_QUANTUM_L5 = 28,
431+ VOW_DRR_QUANTUM_L6 = 32,
432+ VOW_DRR_QUANTUM_L7 = 36
433+};
434+
435+enum {
436+ VOW_DRR_QUANTUM_IDX0,
437+ VOW_DRR_QUANTUM_IDX1,
438+ VOW_DRR_QUANTUM_IDX2,
439+ VOW_DRR_QUANTUM_IDX3,
440+ VOW_DRR_QUANTUM_IDX4,
441+ VOW_DRR_QUANTUM_IDX5,
442+ VOW_DRR_QUANTUM_IDX6,
443+ VOW_DRR_QUANTUM_IDX7,
444+ VOW_DRR_QUANTUM_NUM
445+};
446+
447+enum {
448+ VOW_SCH_TYPE_FOLLOW_POLICY,
449+ VOW_SCH_TYPE_FOLLOW_HW
450+};
451+
452+enum {
453+ VOW_SCH_POLICY_SRR, /* Shared Round-Robin */
454+ VOW_SCH_POLICY_WRR /* Weighted Round-Robin */
455+};
456+
457+enum vow_drr_ctrl_id {
458+ VOW_DRR_CTRL_STA_ALL,
459+ VOW_DRR_CTRL_STA_BSS_GROUP,
460+ VOW_DRR_CTRL_AIRTIME_DEFICIT_BOUND = 0x10,
461+ VOW_DRR_CTRL_AIRTIME_QUANTUM_ALL = 0x28,
462+ VOW_DRR_CTRL_STA_PAUSE = 0x30
463+};
464+
465+struct mt7996_vow_ctrl {
466+ bool atf_enable;
467+ bool watf_enable;
468+ u8 drr_quantum[VOW_DRR_QUANTUM_NUM];
469+ u8 max_deficit;
470+ u8 sch_type;
471+ u8 sch_policy;
472+};
473+
474+struct mt7996_vow_sta_ctrl {
475+ bool paused;
476+ u8 bss_grp_idx;
477+ u8 drr_quantum[IEEE80211_NUM_ACS];
478+};
479+
480 struct mt7996_sta {
481 struct mt76_wcid wcid; /* must be first */
482
483@@ -206,6 +285,8 @@ struct mt7996_sta {
484 u8 flowid_mask;
485 struct mt7996_twt_flow flow[MT7996_MAX_STA_TWT_AGRT];
486 } twt;
487+
488+ struct mt7996_vow_sta_ctrl vow;
489 };
490
491 struct mt7996_vif {
492@@ -470,6 +551,7 @@ struct mt7996_dev {
493
494 u8 wtbl_size_group;
495
496+ struct mt7996_vow_ctrl vow;
497 #ifdef CONFIG_MTK_DEBUG
498 u16 wlan_idx;
499 struct {
500@@ -697,6 +779,10 @@ void mt7996_mcu_scs_sta_poll(struct work_struct *work);
501 void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb);
502 #endif
503
504+int mt7996_mcu_set_vow_drr_ctrl(struct mt7996_phy *phy, struct mt7996_sta *msta,
505+ enum vow_drr_ctrl_id id);
506+int mt7996_mcu_set_vow_feature_ctrl(struct mt7996_phy *phy);
507+
508 static inline u16 mt7996_eeprom_size(struct mt7996_dev *dev)
509 {
510 return is_mt7996(&dev->mt76) ? MT7996_EEPROM_SIZE : MT7992_EEPROM_SIZE;
511@@ -749,6 +835,14 @@ static inline u16 mt7996_rx_chainmask(struct mt7996_phy *phy)
512 return tx_chainmask | (BIT(fls(tx_chainmask)) * phy->has_aux_rx);
513 }
514
515+static inline bool
516+mt7996_vow_should_enable(struct mt7996_dev *dev)
517+{
518+ return !wiphy_ext_feature_isset(mt76_hw(dev)->wiphy,
519+ NL80211_EXT_FEATURE_AIRTIME_FAIRNESS) ||
520+ mtk_wed_device_active(&dev->mt76.mmio.wed);
521+}
522+
523 void mt7996_mac_init(struct mt7996_dev *dev);
524 u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
525 bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
526--
5272.18.0
528