]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/net/wireless/mediatek/mt76/mt76x2_main.c
mt76: stop tx queues from the driver callback instead of common code
[linux.git] / drivers / net / wireless / mediatek / mt76 / mt76x2_main.c
1 /*
2  * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include "mt76x2.h"
18
19 static int
20 mt76x2_start(struct ieee80211_hw *hw)
21 {
22         struct mt76x2_dev *dev = hw->priv;
23         int ret;
24
25         mutex_lock(&dev->mutex);
26
27         ret = mt76x2_mac_start(dev);
28         if (ret)
29                 goto out;
30
31         ret = mt76x2_phy_start(dev);
32         if (ret)
33                 goto out;
34
35         ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
36                                      MT_CALIBRATE_INTERVAL);
37
38         set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
39
40 out:
41         mutex_unlock(&dev->mutex);
42         return ret;
43 }
44
45 static void
46 mt76x2_stop(struct ieee80211_hw *hw)
47 {
48         struct mt76x2_dev *dev = hw->priv;
49
50         mutex_lock(&dev->mutex);
51         clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
52         mt76x2_stop_hardware(dev);
53         mutex_unlock(&dev->mutex);
54 }
55
56 static void
57 mt76x2_txq_init(struct mt76x2_dev *dev, struct ieee80211_txq *txq)
58 {
59         struct mt76_txq *mtxq;
60
61         if (!txq)
62                 return;
63
64         mtxq = (struct mt76_txq *) txq->drv_priv;
65         if (txq->sta) {
66                 struct mt76x2_sta *sta;
67
68                 sta = (struct mt76x2_sta *) txq->sta->drv_priv;
69                 mtxq->wcid = &sta->wcid;
70         } else {
71                 struct mt76x2_vif *mvif;
72
73                 mvif = (struct mt76x2_vif *) txq->vif->drv_priv;
74                 mtxq->wcid = &mvif->group_wcid;
75         }
76
77         mt76_txq_init(&dev->mt76, txq);
78 }
79
80 static int
81 mt76x2_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
82 {
83         struct mt76x2_dev *dev = hw->priv;
84         struct mt76x2_vif *mvif = (struct mt76x2_vif *) vif->drv_priv;
85         unsigned int idx = 0;
86
87         if (vif->addr[0] & BIT(1))
88                 idx = 1 + (((dev->mt76.macaddr[0] ^ vif->addr[0]) >> 2) & 7);
89
90         /*
91          * Client mode typically only has one configurable BSSID register,
92          * which is used for bssidx=0. This is linked to the MAC address.
93          * Since mac80211 allows changing interface types, and we cannot
94          * force the use of the primary MAC address for a station mode
95          * interface, we need some other way of configuring a per-interface
96          * remote BSSID.
97          * The hardware provides an AP-Client feature, where bssidx 0-7 are
98          * used for AP mode and bssidx 8-15 for client mode.
99          * We shift the station interface bss index by 8 to force the
100          * hardware to recognize the BSSID.
101          * The resulting bssidx mismatch for unicast frames is ignored by hw.
102          */
103         if (vif->type == NL80211_IFTYPE_STATION)
104                 idx += 8;
105
106         mvif->idx = idx;
107         mvif->group_wcid.idx = 254 - idx;
108         mvif->group_wcid.hw_key_idx = -1;
109         mt76x2_txq_init(dev, vif->txq);
110
111         return 0;
112 }
113
114 static void
115 mt76x2_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
116 {
117         struct mt76x2_dev *dev = hw->priv;
118
119         mt76_txq_remove(&dev->mt76, vif->txq);
120 }
121
122 static int
123 mt76x2_set_channel(struct mt76x2_dev *dev, struct cfg80211_chan_def *chandef)
124 {
125         int ret;
126
127         mt76_set_channel(&dev->mt76);
128
129         tasklet_disable(&dev->pre_tbtt_tasklet);
130         tasklet_disable(&dev->dfs_pd.dfs_tasklet);
131         cancel_delayed_work_sync(&dev->cal_work);
132
133         mt76x2_mac_stop(dev, true);
134         ret = mt76x2_phy_set_channel(dev, chandef);
135
136         /* channel cycle counters read-and-clear */
137         mt76_rr(dev, MT_CH_IDLE);
138         mt76_rr(dev, MT_CH_BUSY);
139
140         mt76x2_dfs_init_params(dev);
141
142         mt76x2_mac_resume(dev);
143         tasklet_enable(&dev->dfs_pd.dfs_tasklet);
144         tasklet_enable(&dev->pre_tbtt_tasklet);
145
146         return ret;
147 }
148
149 static int
150 mt76x2_config(struct ieee80211_hw *hw, u32 changed)
151 {
152         struct mt76x2_dev *dev = hw->priv;
153         int ret = 0;
154
155         mutex_lock(&dev->mutex);
156
157         if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
158                 if (!(hw->conf.flags & IEEE80211_CONF_MONITOR))
159                         dev->rxfilter |= MT_RX_FILTR_CFG_PROMISC;
160                 else
161                         dev->rxfilter &= ~MT_RX_FILTR_CFG_PROMISC;
162
163                 mt76_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter);
164         }
165
166         if (changed & IEEE80211_CONF_CHANGE_POWER) {
167                 dev->txpower_conf = hw->conf.power_level * 2;
168
169                 /* convert to per-chain power for 2x2 devices */
170                 dev->txpower_conf -= 6;
171
172                 if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) {
173                         mt76x2_phy_set_txpower(dev);
174                         mt76x2_tx_set_txpwr_auto(dev, dev->txpower_conf);
175                 }
176         }
177
178         if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
179                 ieee80211_stop_queues(hw);
180                 ret = mt76x2_set_channel(dev, &hw->conf.chandef);
181                 ieee80211_wake_queues(hw);
182         }
183
184         mutex_unlock(&dev->mutex);
185
186         return ret;
187 }
188
189 static void
190 mt76x2_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
191                         unsigned int *total_flags, u64 multicast)
192 {
193         struct mt76x2_dev *dev = hw->priv;
194         u32 flags = 0;
195
196 #define MT76_FILTER(_flag, _hw) do { \
197                 flags |= *total_flags & FIF_##_flag;                    \
198                 dev->rxfilter &= ~(_hw);                                \
199                 dev->rxfilter |= !(flags & FIF_##_flag) * (_hw);        \
200         } while (0)
201
202         mutex_lock(&dev->mutex);
203
204         dev->rxfilter &= ~MT_RX_FILTR_CFG_OTHER_BSS;
205
206         MT76_FILTER(FCSFAIL, MT_RX_FILTR_CFG_CRC_ERR);
207         MT76_FILTER(PLCPFAIL, MT_RX_FILTR_CFG_PHY_ERR);
208         MT76_FILTER(CONTROL, MT_RX_FILTR_CFG_ACK |
209                              MT_RX_FILTR_CFG_CTS |
210                              MT_RX_FILTR_CFG_CFEND |
211                              MT_RX_FILTR_CFG_CFACK |
212                              MT_RX_FILTR_CFG_BA |
213                              MT_RX_FILTR_CFG_CTRL_RSV);
214         MT76_FILTER(PSPOLL, MT_RX_FILTR_CFG_PSPOLL);
215
216         *total_flags = flags;
217         mt76_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter);
218
219         mutex_unlock(&dev->mutex);
220 }
221
222 static void
223 mt76x2_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
224                         struct ieee80211_bss_conf *info, u32 changed)
225 {
226         struct mt76x2_dev *dev = hw->priv;
227         struct mt76x2_vif *mvif = (struct mt76x2_vif *) vif->drv_priv;
228
229         mutex_lock(&dev->mutex);
230
231         if (changed & BSS_CHANGED_BSSID)
232                 mt76x2_mac_set_bssid(dev, mvif->idx, info->bssid);
233
234         if (changed & BSS_CHANGED_BEACON_INT)
235                 mt76_rmw_field(dev, MT_BEACON_TIME_CFG,
236                                MT_BEACON_TIME_CFG_INTVAL,
237                                info->beacon_int << 4);
238
239         if (changed & BSS_CHANGED_BEACON_ENABLED) {
240                 tasklet_disable(&dev->pre_tbtt_tasklet);
241                 mt76x2_mac_set_beacon_enable(dev, mvif->idx,
242                                              info->enable_beacon);
243                 tasklet_enable(&dev->pre_tbtt_tasklet);
244         }
245
246         if (changed & BSS_CHANGED_ERP_SLOT) {
247                 int slottime = info->use_short_slot ? 9 : 20;
248
249                 dev->slottime = slottime;
250                 mt76_rmw_field(dev, MT_BKOFF_SLOT_CFG,
251                                MT_BKOFF_SLOT_CFG_SLOTTIME, slottime);
252         }
253
254         mutex_unlock(&dev->mutex);
255 }
256
257 static int
258 mt76x2_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
259                struct ieee80211_sta *sta)
260 {
261         struct mt76x2_dev *dev = hw->priv;
262         struct mt76x2_sta *msta = (struct mt76x2_sta *) sta->drv_priv;
263         struct mt76x2_vif *mvif = (struct mt76x2_vif *) vif->drv_priv;
264         int ret = 0;
265         int idx = 0;
266         int i;
267
268         mutex_lock(&dev->mutex);
269
270         idx = mt76_wcid_alloc(dev->wcid_mask, ARRAY_SIZE(dev->wcid));
271         if (idx < 0) {
272                 ret = -ENOSPC;
273                 goto out;
274         }
275
276         msta->vif = mvif;
277         msta->wcid.sta = 1;
278         msta->wcid.idx = idx;
279         msta->wcid.hw_key_idx = -1;
280         mt76x2_mac_wcid_setup(dev, idx, mvif->idx, sta->addr);
281         mt76x2_mac_wcid_set_drop(dev, idx, false);
282         for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
283                 mt76x2_txq_init(dev, sta->txq[i]);
284
285         if (vif->type == NL80211_IFTYPE_AP)
286                 set_bit(MT_WCID_FLAG_CHECK_PS, &msta->wcid.flags);
287
288         rcu_assign_pointer(dev->wcid[idx], &msta->wcid);
289
290 out:
291         mutex_unlock(&dev->mutex);
292
293         return ret;
294 }
295
296 static int
297 mt76x2_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
298                   struct ieee80211_sta *sta)
299 {
300         struct mt76x2_dev *dev = hw->priv;
301         struct mt76x2_sta *msta = (struct mt76x2_sta *) sta->drv_priv;
302         int idx = msta->wcid.idx;
303         int i;
304
305         mutex_lock(&dev->mutex);
306         rcu_assign_pointer(dev->wcid[idx], NULL);
307         for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
308                 mt76_txq_remove(&dev->mt76, sta->txq[i]);
309         mt76x2_mac_wcid_set_drop(dev, idx, true);
310         mt76_wcid_free(dev->wcid_mask, idx);
311         mt76x2_mac_wcid_setup(dev, idx, 0, NULL);
312         mutex_unlock(&dev->mutex);
313
314         return 0;
315 }
316
317 void
318 mt76x2_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps)
319 {
320         struct mt76x2_sta *msta = (struct mt76x2_sta *) sta->drv_priv;
321         struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76);
322         int idx = msta->wcid.idx;
323
324         mt76_stop_tx_queues(&dev->mt76, sta, true);
325         mt76x2_mac_wcid_set_drop(dev, idx, ps);
326 }
327
328 static int
329 mt76x2_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
330                struct ieee80211_vif *vif, struct ieee80211_sta *sta,
331                struct ieee80211_key_conf *key)
332 {
333         struct mt76x2_dev *dev = hw->priv;
334         struct mt76x2_vif *mvif = (struct mt76x2_vif *) vif->drv_priv;
335         struct mt76x2_sta *msta;
336         struct mt76_wcid *wcid;
337         int idx = key->keyidx;
338         int ret;
339
340         /* fall back to sw encryption for unsupported ciphers */
341         switch (key->cipher) {
342         case WLAN_CIPHER_SUITE_WEP40:
343         case WLAN_CIPHER_SUITE_WEP104:
344         case WLAN_CIPHER_SUITE_TKIP:
345         case WLAN_CIPHER_SUITE_CCMP:
346                 break;
347         default:
348                 return -EOPNOTSUPP;
349         }
350
351         /*
352          * The hardware does not support per-STA RX GTK, fall back
353          * to software mode for these.
354          */
355         if ((vif->type == NL80211_IFTYPE_ADHOC ||
356              vif->type == NL80211_IFTYPE_MESH_POINT) &&
357             (key->cipher == WLAN_CIPHER_SUITE_TKIP ||
358              key->cipher == WLAN_CIPHER_SUITE_CCMP) &&
359             !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
360                 return -EOPNOTSUPP;
361
362         msta = sta ? (struct mt76x2_sta *) sta->drv_priv : NULL;
363         wcid = msta ? &msta->wcid : &mvif->group_wcid;
364
365         if (cmd == SET_KEY) {
366                 key->hw_key_idx = wcid->idx;
367                 wcid->hw_key_idx = idx;
368                 if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) {
369                         key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
370                         wcid->sw_iv = true;
371                 }
372         } else {
373                 if (idx == wcid->hw_key_idx) {
374                         wcid->hw_key_idx = -1;
375                         wcid->sw_iv = true;
376                 }
377
378                 key = NULL;
379         }
380         mt76_wcid_key_setup(&dev->mt76, wcid, key);
381
382         if (!msta) {
383                 if (key || wcid->hw_key_idx == idx) {
384                         ret = mt76x2_mac_wcid_set_key(dev, wcid->idx, key);
385                         if (ret)
386                                 return ret;
387                 }
388
389                 return mt76x2_mac_shared_key_setup(dev, mvif->idx, idx, key);
390         }
391
392         return mt76x2_mac_wcid_set_key(dev, msta->wcid.idx, key);
393 }
394
395 static int
396 mt76x2_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
397                const struct ieee80211_tx_queue_params *params)
398 {
399         struct mt76x2_dev *dev = hw->priv;
400         u8 cw_min = 5, cw_max = 10, qid;
401         u32 val;
402
403         qid = dev->mt76.q_tx[queue].hw_idx;
404
405         if (params->cw_min)
406                 cw_min = fls(params->cw_min);
407         if (params->cw_max)
408                 cw_max = fls(params->cw_max);
409
410         val = FIELD_PREP(MT_EDCA_CFG_TXOP, params->txop) |
411               FIELD_PREP(MT_EDCA_CFG_AIFSN, params->aifs) |
412               FIELD_PREP(MT_EDCA_CFG_CWMIN, cw_min) |
413               FIELD_PREP(MT_EDCA_CFG_CWMAX, cw_max);
414         mt76_wr(dev, MT_EDCA_CFG_AC(qid), val);
415
416         val = mt76_rr(dev, MT_WMM_TXOP(qid));
417         val &= ~(MT_WMM_TXOP_MASK << MT_WMM_TXOP_SHIFT(qid));
418         val |= params->txop << MT_WMM_TXOP_SHIFT(qid);
419         mt76_wr(dev, MT_WMM_TXOP(qid), val);
420
421         val = mt76_rr(dev, MT_WMM_AIFSN);
422         val &= ~(MT_WMM_AIFSN_MASK << MT_WMM_AIFSN_SHIFT(qid));
423         val |= params->aifs << MT_WMM_AIFSN_SHIFT(qid);
424         mt76_wr(dev, MT_WMM_AIFSN, val);
425
426         val = mt76_rr(dev, MT_WMM_CWMIN);
427         val &= ~(MT_WMM_CWMIN_MASK << MT_WMM_CWMIN_SHIFT(qid));
428         val |= cw_min << MT_WMM_CWMIN_SHIFT(qid);
429         mt76_wr(dev, MT_WMM_CWMIN, val);
430
431         val = mt76_rr(dev, MT_WMM_CWMAX);
432         val &= ~(MT_WMM_CWMAX_MASK << MT_WMM_CWMAX_SHIFT(qid));
433         val |= cw_max << MT_WMM_CWMAX_SHIFT(qid);
434         mt76_wr(dev, MT_WMM_CWMAX, val);
435
436         return 0;
437 }
438
439 static void
440 mt76x2_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
441                const u8 *mac)
442 {
443         struct mt76x2_dev *dev = hw->priv;
444
445         tasklet_disable(&dev->pre_tbtt_tasklet);
446         set_bit(MT76_SCANNING, &dev->mt76.state);
447 }
448
449 static void
450 mt76x2_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
451 {
452         struct mt76x2_dev *dev = hw->priv;
453
454         clear_bit(MT76_SCANNING, &dev->mt76.state);
455         tasklet_enable(&dev->pre_tbtt_tasklet);
456         mt76_txq_schedule_all(&dev->mt76);
457 }
458
459 static void
460 mt76x2_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
461              u32 queues, bool drop)
462 {
463 }
464
465 static int
466 mt76x2_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm)
467 {
468         struct mt76x2_dev *dev = hw->priv;
469
470         *dbm = dev->txpower_cur / 2;
471
472         /* convert from per-chain power to combined output on 2x2 devices */
473         *dbm += 3;
474
475         return 0;
476 }
477
478 static int
479 mt76x2_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
480                     struct ieee80211_ampdu_params *params)
481 {
482         enum ieee80211_ampdu_mlme_action action = params->action;
483         struct ieee80211_sta *sta = params->sta;
484         struct mt76x2_dev *dev = hw->priv;
485         struct mt76x2_sta *msta = (struct mt76x2_sta *) sta->drv_priv;
486         struct ieee80211_txq *txq = sta->txq[params->tid];
487         u16 tid = params->tid;
488         u16 *ssn = &params->ssn;
489         struct mt76_txq *mtxq;
490
491         if (!txq)
492                 return -EINVAL;
493
494         mtxq = (struct mt76_txq *)txq->drv_priv;
495
496         switch (action) {
497         case IEEE80211_AMPDU_RX_START:
498                 mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, *ssn, params->buf_size);
499                 mt76_set(dev, MT_WCID_ADDR(msta->wcid.idx) + 4, BIT(16 + tid));
500                 break;
501         case IEEE80211_AMPDU_RX_STOP:
502                 mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid);
503                 mt76_clear(dev, MT_WCID_ADDR(msta->wcid.idx) + 4,
504                            BIT(16 + tid));
505                 break;
506         case IEEE80211_AMPDU_TX_OPERATIONAL:
507                 mtxq->aggr = true;
508                 mtxq->send_bar = false;
509                 ieee80211_send_bar(vif, sta->addr, tid, mtxq->agg_ssn);
510                 break;
511         case IEEE80211_AMPDU_TX_STOP_FLUSH:
512         case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
513                 mtxq->aggr = false;
514                 ieee80211_send_bar(vif, sta->addr, tid, mtxq->agg_ssn);
515                 break;
516         case IEEE80211_AMPDU_TX_START:
517                 mtxq->agg_ssn = *ssn << 4;
518                 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
519                 break;
520         case IEEE80211_AMPDU_TX_STOP_CONT:
521                 mtxq->aggr = false;
522                 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
523                 break;
524         }
525
526         return 0;
527 }
528
529 static void
530 mt76x2_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
531                            struct ieee80211_sta *sta)
532 {
533         struct mt76x2_dev *dev = hw->priv;
534         struct mt76x2_sta *msta = (struct mt76x2_sta *) sta->drv_priv;
535         struct ieee80211_sta_rates *rates = rcu_dereference(sta->rates);
536         struct ieee80211_tx_rate rate = {};
537
538         if (!rates)
539                 return;
540
541         rate.idx = rates->rate[0].idx;
542         rate.flags = rates->rate[0].flags;
543         mt76x2_mac_wcid_set_rate(dev, &msta->wcid, &rate);
544         msta->wcid.max_txpwr_adj = mt76x2_tx_get_max_txpwr_adj(dev, &rate);
545 }
546
547 static void mt76x2_set_coverage_class(struct ieee80211_hw *hw,
548                                       s16 coverage_class)
549 {
550         struct mt76x2_dev *dev = hw->priv;
551
552         mutex_lock(&dev->mutex);
553         dev->coverage_class = coverage_class;
554         mt76x2_set_tx_ackto(dev);
555         mutex_unlock(&dev->mutex);
556 }
557
558 static int
559 mt76x2_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
560 {
561         return 0;
562 }
563
564 static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant,
565                               u32 rx_ant)
566 {
567         struct mt76x2_dev *dev = hw->priv;
568
569         if (!tx_ant || tx_ant > 3 || tx_ant != rx_ant)
570                 return -EINVAL;
571
572         mutex_lock(&dev->mutex);
573
574         dev->chainmask = (tx_ant == 3) ? 0x202 : 0x101;
575         dev->mt76.antenna_mask = tx_ant;
576
577         mt76_set_stream_caps(&dev->mt76, true);
578         mt76x2_phy_set_antenna(dev);
579
580         mutex_unlock(&dev->mutex);
581
582         return 0;
583 }
584
585 static int mt76x2_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant,
586                               u32 *rx_ant)
587 {
588         struct mt76x2_dev *dev = hw->priv;
589
590         mutex_lock(&dev->mutex);
591         *tx_ant = dev->mt76.antenna_mask;
592         *rx_ant = dev->mt76.antenna_mask;
593         mutex_unlock(&dev->mutex);
594
595         return 0;
596 }
597
598 const struct ieee80211_ops mt76x2_ops = {
599         .tx = mt76x2_tx,
600         .start = mt76x2_start,
601         .stop = mt76x2_stop,
602         .add_interface = mt76x2_add_interface,
603         .remove_interface = mt76x2_remove_interface,
604         .config = mt76x2_config,
605         .configure_filter = mt76x2_configure_filter,
606         .bss_info_changed = mt76x2_bss_info_changed,
607         .sta_add = mt76x2_sta_add,
608         .sta_remove = mt76x2_sta_remove,
609         .set_key = mt76x2_set_key,
610         .conf_tx = mt76x2_conf_tx,
611         .sw_scan_start = mt76x2_sw_scan,
612         .sw_scan_complete = mt76x2_sw_scan_complete,
613         .flush = mt76x2_flush,
614         .ampdu_action = mt76x2_ampdu_action,
615         .get_txpower = mt76x2_get_txpower,
616         .wake_tx_queue = mt76_wake_tx_queue,
617         .sta_rate_tbl_update = mt76x2_sta_rate_tbl_update,
618         .release_buffered_frames = mt76_release_buffered_frames,
619         .set_coverage_class = mt76x2_set_coverage_class,
620         .get_survey = mt76_get_survey,
621         .set_tim = mt76x2_set_tim,
622         .set_antenna = mt76x2_set_antenna,
623         .get_antenna = mt76x2_get_antenna,
624 };
625