Merge branch 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-block.git] / drivers / net / wireless / mediatek / mt76 / mt7615 / main.c
CommitLineData
04b8e659
RL
1// SPDX-License-Identifier: ISC
2/* Copyright (C) 2019 MediaTek Inc.
3 *
4 * Author: Roy Luo <royluo@google.com>
5 * Ryder Lee <ryder.lee@mediatek.com>
6 * Felix Fietkau <nbd@nbd.name>
7 */
8
9#include <linux/etherdevice.h>
10#include <linux/platform_device.h>
11#include <linux/pci.h>
12#include <linux/module.h>
13#include "mt7615.h"
14
15static int mt7615_start(struct ieee80211_hw *hw)
16{
17 struct mt7615_dev *dev = hw->priv;
18
75601194
LB
19 mt7615_mac_reset_counters(dev);
20
863c15a1 21 dev->mt76.survey_time = ktime_get_boottime();
04b8e659
RL
22 set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
23 ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work,
24 MT7615_WATCHDOG_TIME);
25
26 return 0;
27}
28
29static void mt7615_stop(struct ieee80211_hw *hw)
30{
31 struct mt7615_dev *dev = hw->priv;
32
33 clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
34 cancel_delayed_work_sync(&dev->mt76.mac_work);
35}
36
37static int get_omac_idx(enum nl80211_iftype type, u32 mask)
38{
39 int i;
40
41 switch (type) {
42 case NL80211_IFTYPE_AP:
f4ec7fdf 43 case NL80211_IFTYPE_MESH_POINT:
7f4b7920 44 case NL80211_IFTYPE_ADHOC:
04b8e659
RL
45 /* ap use hw bssid 0 and ext bssid */
46 if (~mask & BIT(HW_BSSID_0))
47 return HW_BSSID_0;
48
49 for (i = EXT_BSSID_1; i < EXT_BSSID_END; i++)
50 if (~mask & BIT(i))
51 return i;
52
53 break;
54 case NL80211_IFTYPE_STATION:
55 /* sta use hw bssid other than 0 */
56 for (i = HW_BSSID_1; i < HW_BSSID_MAX; i++)
57 if (~mask & BIT(i))
58 return i;
59
60 break;
61 default:
62 WARN_ON(1);
63 break;
5d1ad7d7 64 }
04b8e659
RL
65
66 return -1;
67}
68
69static int mt7615_add_interface(struct ieee80211_hw *hw,
70 struct ieee80211_vif *vif)
71{
72 struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
73 struct mt7615_dev *dev = hw->priv;
74 struct mt76_txq *mtxq;
75 int idx, ret = 0;
76
77 mutex_lock(&dev->mt76.mutex);
78
79 mvif->idx = ffs(~dev->vif_mask) - 1;
80 if (mvif->idx >= MT7615_MAX_INTERFACES) {
81 ret = -ENOSPC;
82 goto out;
83 }
84
b1571a0e
DC
85 idx = get_omac_idx(vif->type, dev->omac_mask);
86 if (idx < 0) {
04b8e659
RL
87 ret = -ENOSPC;
88 goto out;
89 }
b1571a0e 90 mvif->omac_idx = idx;
04b8e659 91
49f1132c 92 /* TODO: DBDC support. Use band 0 for now */
04b8e659 93 mvif->band_idx = 0;
49f1132c 94 mvif->wmm_idx = mvif->idx % MT7615_MAX_WMM_SETS;
04b8e659
RL
95
96 ret = mt7615_mcu_set_dev_info(dev, vif, 1);
97 if (ret)
98 goto out;
99
100 dev->vif_mask |= BIT(mvif->idx);
101 dev->omac_mask |= BIT(mvif->omac_idx);
fe559aed 102 idx = MT7615_WTBL_RESERVED - mvif->idx;
b2c2f029
LB
103
104 INIT_LIST_HEAD(&mvif->sta.poll_list);
04b8e659
RL
105 mvif->sta.wcid.idx = idx;
106 mvif->sta.wcid.hw_key_idx = -1;
b2c2f029
LB
107 mt7615_mac_wtbl_update(dev, idx,
108 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
04b8e659
RL
109
110 rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
111 mtxq = (struct mt76_txq *)vif->txq->drv_priv;
112 mtxq->wcid = &mvif->sta.wcid;
113 mt76_txq_init(&dev->mt76, vif->txq);
114
115out:
116 mutex_unlock(&dev->mt76.mutex);
117
118 return ret;
119}
120
121static void mt7615_remove_interface(struct ieee80211_hw *hw,
122 struct ieee80211_vif *vif)
123{
124 struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
b2c2f029 125 struct mt7615_sta *msta = &mvif->sta;
04b8e659 126 struct mt7615_dev *dev = hw->priv;
b2c2f029 127 int idx = msta->wcid.idx;
04b8e659
RL
128
129 /* TODO: disable beacon for the bss */
130
131 mt7615_mcu_set_dev_info(dev, vif, 0);
132
133 rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
134 mt76_txq_remove(&dev->mt76, vif->txq);
135
136 mutex_lock(&dev->mt76.mutex);
137 dev->vif_mask &= ~BIT(mvif->idx);
138 dev->omac_mask &= ~BIT(mvif->omac_idx);
139 mutex_unlock(&dev->mt76.mutex);
b2c2f029
LB
140
141 spin_lock_bh(&dev->sta_poll_lock);
142 if (!list_empty(&msta->poll_list))
143 list_del_init(&msta->poll_list);
144 spin_unlock_bh(&dev->sta_poll_lock);
04b8e659
RL
145}
146
07d557f6 147static int mt7615_set_channel(struct mt7615_dev *dev)
04b8e659
RL
148{
149 int ret;
150
151 cancel_delayed_work_sync(&dev->mt76.mac_work);
7fe96541
LB
152
153 mutex_lock(&dev->mt76.mutex);
04b8e659
RL
154 set_bit(MT76_RESET, &dev->mt76.state);
155
d67a6646
LB
156 mt7615_dfs_check_channel(dev);
157
04b8e659
RL
158 mt76_set_channel(&dev->mt76);
159
160 ret = mt7615_mcu_set_channel(dev);
161 if (ret)
7fe96541 162 goto out;
04b8e659 163
d67a6646 164 ret = mt7615_dfs_init_radar_detector(dev);
49de79ad 165 mt7615_mac_cca_stats_reset(dev);
863c15a1 166 dev->mt76.survey_time = ktime_get_boottime();
6bfa6e38
LB
167
168 mt7615_mac_reset_counters(dev);
d67a6646 169
7fe96541 170out:
04b8e659 171 clear_bit(MT76_RESET, &dev->mt76.state);
7fe96541 172 mutex_unlock(&dev->mt76.mutex);
04b8e659
RL
173
174 mt76_txq_schedule_all(&dev->mt76);
175 ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work,
176 MT7615_WATCHDOG_TIME);
7fe96541 177 return ret;
04b8e659
RL
178}
179
180static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
181 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
182 struct ieee80211_key_conf *key)
183{
184 struct mt7615_dev *dev = hw->priv;
185 struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
186 struct mt7615_sta *msta = sta ? (struct mt7615_sta *)sta->drv_priv :
187 &mvif->sta;
188 struct mt76_wcid *wcid = &msta->wcid;
189 int idx = key->keyidx;
190
191 /* The hardware does not support per-STA RX GTK, fallback
192 * to software mode for these.
193 */
194 if ((vif->type == NL80211_IFTYPE_ADHOC ||
195 vif->type == NL80211_IFTYPE_MESH_POINT) &&
196 (key->cipher == WLAN_CIPHER_SUITE_TKIP ||
197 key->cipher == WLAN_CIPHER_SUITE_CCMP) &&
198 !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
199 return -EOPNOTSUPP;
200
4a926e30
LB
201 /* fall back to sw encryption for unsupported ciphers */
202 switch (key->cipher) {
01cfc1b4
LB
203 case WLAN_CIPHER_SUITE_AES_CMAC:
204 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
205 break;
4a926e30
LB
206 case WLAN_CIPHER_SUITE_WEP40:
207 case WLAN_CIPHER_SUITE_WEP104:
208 case WLAN_CIPHER_SUITE_TKIP:
209 case WLAN_CIPHER_SUITE_CCMP:
210 case WLAN_CIPHER_SUITE_CCMP_256:
211 case WLAN_CIPHER_SUITE_GCMP:
212 case WLAN_CIPHER_SUITE_GCMP_256:
213 case WLAN_CIPHER_SUITE_SMS4:
214 break;
215 default:
216 return -EOPNOTSUPP;
217 }
218
04b8e659
RL
219 if (cmd == SET_KEY) {
220 key->hw_key_idx = wcid->idx;
221 wcid->hw_key_idx = idx;
27b8a900
LB
222 } else if (idx == wcid->hw_key_idx) {
223 wcid->hw_key_idx = -1;
04b8e659 224 }
27b8a900
LB
225 mt76_wcid_key_setup(&dev->mt76, wcid,
226 cmd == SET_KEY ? key : NULL);
04b8e659 227
27b8a900 228 return mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
04b8e659
RL
229}
230
231static int mt7615_config(struct ieee80211_hw *hw, u32 changed)
232{
233 struct mt7615_dev *dev = hw->priv;
234 int ret = 0;
235
892fe32b 236 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
04b8e659 237 ieee80211_stop_queues(hw);
07d557f6 238 ret = mt7615_set_channel(dev);
04b8e659 239 ieee80211_wake_queues(hw);
04b8e659
RL
240 }
241
7fe96541
LB
242 mutex_lock(&dev->mt76.mutex);
243
61d36824
LB
244 if (changed & IEEE80211_CONF_CHANGE_POWER)
245 ret = mt7615_mcu_set_tx_power(dev);
246
04b8e659 247 if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
04b8e659
RL
248 if (!(hw->conf.flags & IEEE80211_CONF_MONITOR))
249 dev->mt76.rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;
250 else
251 dev->mt76.rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;
252
253 mt76_wr(dev, MT_WF_RFCR, dev->mt76.rxfilter);
04b8e659 254 }
892fe32b
LB
255
256 mutex_unlock(&dev->mt76.mutex);
257
04b8e659
RL
258 return ret;
259}
260
261static int
262mt7615_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
263 const struct ieee80211_tx_queue_params *params)
264{
49f1132c 265 struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
04b8e659 266 struct mt7615_dev *dev = hw->priv;
04b8e659 267
49f1132c
RL
268 queue += mvif->wmm_idx * MT7615_MAX_WMM_SETS;
269
270 return mt7615_mcu_set_wmm(dev, queue, params);
04b8e659
RL
271}
272
273static void mt7615_configure_filter(struct ieee80211_hw *hw,
274 unsigned int changed_flags,
275 unsigned int *total_flags,
276 u64 multicast)
277{
278 struct mt7615_dev *dev = hw->priv;
b4124a5b
FF
279 u32 ctl_flags = MT_WF_RFCR1_DROP_ACK |
280 MT_WF_RFCR1_DROP_BF_POLL |
281 MT_WF_RFCR1_DROP_BA |
282 MT_WF_RFCR1_DROP_CFEND |
283 MT_WF_RFCR1_DROP_CFACK;
04b8e659
RL
284 u32 flags = 0;
285
286#define MT76_FILTER(_flag, _hw) do { \
287 flags |= *total_flags & FIF_##_flag; \
288 dev->mt76.rxfilter &= ~(_hw); \
289 dev->mt76.rxfilter |= !(flags & FIF_##_flag) * (_hw); \
290 } while (0)
291
292 dev->mt76.rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS |
293 MT_WF_RFCR_DROP_OTHER_BEACON |
294 MT_WF_RFCR_DROP_FRAME_REPORT |
295 MT_WF_RFCR_DROP_PROBEREQ |
296 MT_WF_RFCR_DROP_MCAST_FILTERED |
297 MT_WF_RFCR_DROP_MCAST |
298 MT_WF_RFCR_DROP_BCAST |
299 MT_WF_RFCR_DROP_DUPLICATE |
300 MT_WF_RFCR_DROP_A2_BSSID |
301 MT_WF_RFCR_DROP_UNWANTED_CTL |
302 MT_WF_RFCR_DROP_STBC_MULTI);
303
304 MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM |
305 MT_WF_RFCR_DROP_A3_MAC |
306 MT_WF_RFCR_DROP_A3_BSSID);
307
308 MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL);
309
310 MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS |
311 MT_WF_RFCR_DROP_RTS |
312 MT_WF_RFCR_DROP_CTL_RSV |
313 MT_WF_RFCR_DROP_NDPA);
314
315 *total_flags = flags;
316 mt76_wr(dev, MT_WF_RFCR, dev->mt76.rxfilter);
b4124a5b
FF
317
318 if (*total_flags & FIF_CONTROL)
319 mt76_clear(dev, MT_WF_RFCR1, ctl_flags);
320 else
321 mt76_set(dev, MT_WF_RFCR1, ctl_flags);
04b8e659
RL
322}
323
324static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
325 struct ieee80211_vif *vif,
326 struct ieee80211_bss_conf *info,
327 u32 changed)
328{
329 struct mt7615_dev *dev = hw->priv;
330
331 mutex_lock(&dev->mt76.mutex);
332
e991c4c2
RL
333 if (changed & BSS_CHANGED_ASSOC)
334 mt7615_mcu_set_bss_info(dev, vif, info->assoc);
04b8e659
RL
335
336 /* TODO: update beacon content
337 * BSS_CHANGED_BEACON
338 */
339
340 if (changed & BSS_CHANGED_BEACON_ENABLED) {
598a4434
LB
341 mt7615_mcu_set_bss_info(dev, vif, info->enable_beacon);
342 mt7615_mcu_wtbl_bmc(dev, vif, info->enable_beacon);
343 mt7615_mcu_set_sta_rec_bmc(dev, vif, info->enable_beacon);
344 mt7615_mcu_set_bcn(dev, vif, info->enable_beacon);
04b8e659
RL
345 }
346
347 mutex_unlock(&dev->mt76.mutex);
348}
349
5ec87dc8
LB
350static void
351mt7615_channel_switch_beacon(struct ieee80211_hw *hw,
352 struct ieee80211_vif *vif,
353 struct cfg80211_chan_def *chandef)
354{
355 struct mt7615_dev *dev = hw->priv;
356
357 mutex_lock(&dev->mt76.mutex);
358 mt7615_mcu_set_bcn(dev, vif, true);
359 mutex_unlock(&dev->mt76.mutex);
360}
361
04b8e659
RL
362int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
363 struct ieee80211_sta *sta)
364{
365 struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
366 struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
367 struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
368 int idx;
369
370 idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7615_WTBL_STA - 1);
371 if (idx < 0)
372 return -ENOSPC;
373
b2c2f029 374 INIT_LIST_HEAD(&msta->poll_list);
04b8e659
RL
375 msta->vif = mvif;
376 msta->wcid.sta = 1;
377 msta->wcid.idx = idx;
b2c2f029
LB
378 mt7615_mac_wtbl_update(dev, idx,
379 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
04b8e659
RL
380
381 mt7615_mcu_add_wtbl(dev, vif, sta);
382 mt7615_mcu_set_sta_rec(dev, vif, sta, 1);
383
384 return 0;
385}
386
387void mt7615_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
388 struct ieee80211_sta *sta)
389{
390 struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
391
392 if (sta->ht_cap.ht_supported)
393 mt7615_mcu_set_ht_cap(dev, vif, sta);
394}
395
396void mt7615_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
397 struct ieee80211_sta *sta)
398{
399 struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
b2c2f029 400 struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
04b8e659
RL
401
402 mt7615_mcu_set_sta_rec(dev, vif, sta, 0);
b1722925 403 mt7615_mcu_del_wtbl(dev, sta);
b2c2f029
LB
404
405 mt7615_mac_wtbl_update(dev, msta->wcid.idx,
406 MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
407
408 spin_lock_bh(&dev->sta_poll_lock);
409 if (!list_empty(&msta->poll_list))
410 list_del_init(&msta->poll_list);
411 spin_unlock_bh(&dev->sta_poll_lock);
04b8e659
RL
412}
413
414static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw,
415 struct ieee80211_vif *vif,
416 struct ieee80211_sta *sta)
417{
418 struct mt7615_dev *dev = hw->priv;
419 struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
420 struct ieee80211_sta_rates *sta_rates = rcu_dereference(sta->rates);
421 int i;
422
423 spin_lock_bh(&dev->mt76.lock);
424 for (i = 0; i < ARRAY_SIZE(msta->rates); i++) {
425 msta->rates[i].idx = sta_rates->rate[i].idx;
426 msta->rates[i].count = sta_rates->rate[i].count;
427 msta->rates[i].flags = sta_rates->rate[i].flags;
428
429 if (msta->rates[i].idx < 0 || !msta->rates[i].count)
430 break;
431 }
432 msta->n_rates = i;
592ed85d 433 mt7615_mac_set_rates(dev, msta, NULL, msta->rates);
04b8e659
RL
434 msta->rate_probe = false;
435 spin_unlock_bh(&dev->mt76.lock);
436}
437
438static void mt7615_tx(struct ieee80211_hw *hw,
439 struct ieee80211_tx_control *control,
440 struct sk_buff *skb)
441{
442 struct mt7615_dev *dev = hw->priv;
443 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
444 struct ieee80211_vif *vif = info->control.vif;
445 struct mt76_wcid *wcid = &dev->mt76.global_wcid;
446
447 if (control->sta) {
448 struct mt7615_sta *sta;
449
450 sta = (struct mt7615_sta *)control->sta->drv_priv;
451 wcid = &sta->wcid;
452 }
453
454 if (vif && !control->sta) {
455 struct mt7615_vif *mvif;
456
457 mvif = (struct mt7615_vif *)vif->drv_priv;
458 wcid = &mvif->sta.wcid;
459 }
460
461 mt76_tx(&dev->mt76, control->sta, wcid, skb);
462}
463
464static int mt7615_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
465{
466 struct mt7615_dev *dev = hw->priv;
467
468 mutex_lock(&dev->mt76.mutex);
469 mt7615_mcu_set_rts_thresh(dev, val);
470 mutex_unlock(&dev->mt76.mutex);
471
472 return 0;
473}
474
475static int
476mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
477 struct ieee80211_ampdu_params *params)
478{
479 enum ieee80211_ampdu_mlme_action action = params->action;
480 struct mt7615_dev *dev = hw->priv;
481 struct ieee80211_sta *sta = params->sta;
482 struct ieee80211_txq *txq = sta->txq[params->tid];
483 struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
484 u16 tid = params->tid;
3d1e5cdd 485 u16 ssn = params->ssn;
04b8e659 486 struct mt76_txq *mtxq;
05d6c8cf 487 int ret = 0;
04b8e659
RL
488
489 if (!txq)
490 return -EINVAL;
491
492 mtxq = (struct mt76_txq *)txq->drv_priv;
493
1a817fa7 494 mutex_lock(&dev->mt76.mutex);
04b8e659
RL
495 switch (action) {
496 case IEEE80211_AMPDU_RX_START:
3d1e5cdd 497 mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn,
04b8e659
RL
498 params->buf_size);
499 mt7615_mcu_set_rx_ba(dev, params, 1);
500 break;
501 case IEEE80211_AMPDU_RX_STOP:
502 mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid);
503 mt7615_mcu_set_rx_ba(dev, params, 0);
504 break;
505 case IEEE80211_AMPDU_TX_OPERATIONAL:
506 mtxq->aggr = true;
507 mtxq->send_bar = false;
508 mt7615_mcu_set_tx_ba(dev, params, 1);
509 break;
510 case IEEE80211_AMPDU_TX_STOP_FLUSH:
511 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
512 mtxq->aggr = false;
04b8e659
RL
513 mt7615_mcu_set_tx_ba(dev, params, 0);
514 break;
515 case IEEE80211_AMPDU_TX_START:
3d1e5cdd 516 mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn);
05d6c8cf
MT
517 ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
518 break;
04b8e659
RL
519 case IEEE80211_AMPDU_TX_STOP_CONT:
520 mtxq->aggr = false;
521 mt7615_mcu_set_tx_ba(dev, params, 0);
522 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
523 break;
524 }
1a817fa7 525 mutex_unlock(&dev->mt76.mutex);
04b8e659 526
05d6c8cf 527 return ret;
04b8e659
RL
528}
529
04b8e659
RL
530const struct ieee80211_ops mt7615_ops = {
531 .tx = mt7615_tx,
532 .start = mt7615_start,
533 .stop = mt7615_stop,
534 .add_interface = mt7615_add_interface,
535 .remove_interface = mt7615_remove_interface,
536 .config = mt7615_config,
537 .conf_tx = mt7615_conf_tx,
538 .configure_filter = mt7615_configure_filter,
539 .bss_info_changed = mt7615_bss_info_changed,
540 .sta_state = mt76_sta_state,
541 .set_key = mt7615_set_key,
542 .ampdu_action = mt7615_ampdu_action,
543 .set_rts_threshold = mt7615_set_rts_threshold,
544 .wake_tx_queue = mt76_wake_tx_queue,
545 .sta_rate_tbl_update = mt7615_sta_rate_tbl_update,
8b8ab5c2
LB
546 .sw_scan_start = mt76_sw_scan,
547 .sw_scan_complete = mt76_sw_scan_complete,
04b8e659 548 .release_buffered_frames = mt76_release_buffered_frames,
2fccf4f0 549 .get_txpower = mt76_get_txpower,
5ec87dc8 550 .channel_switch_beacon = mt7615_channel_switch_beacon,
863c15a1 551 .get_survey = mt76_get_survey,
e49c76d4 552 .get_antenna = mt76_get_antenna,
04b8e659 553};