Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / net / wireless / mediatek / mt76 / mt76x2 / usb_main.c
1 /*
2  * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
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 "mt76x2u.h"
18
19 static int mt76x2u_start(struct ieee80211_hw *hw)
20 {
21         struct mt76x02_dev *dev = hw->priv;
22         int ret;
23
24         ret = mt76x2u_mac_start(dev);
25         if (ret)
26                 return ret;
27
28         ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work,
29                                      MT_MAC_WORK_INTERVAL);
30         set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
31
32         return 0;
33 }
34
35 static void mt76x2u_stop(struct ieee80211_hw *hw)
36 {
37         struct mt76x02_dev *dev = hw->priv;
38
39         clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
40         mt76u_stop_tx(&dev->mt76);
41         mt76x2u_stop_hw(dev);
42 }
43
44 static int
45 mt76x2u_set_channel(struct mt76x02_dev *dev,
46                     struct cfg80211_chan_def *chandef)
47 {
48         int err;
49
50         cancel_delayed_work_sync(&dev->cal_work);
51         dev->beacon_ops->pre_tbtt_enable(dev, false);
52
53         mutex_lock(&dev->mt76.mutex);
54         set_bit(MT76_RESET, &dev->mt76.state);
55
56         mt76_set_channel(&dev->mt76);
57
58         mt76x2_mac_stop(dev, false);
59
60         err = mt76x2u_phy_set_channel(dev, chandef);
61
62         mt76x2_mac_resume(dev);
63
64         clear_bit(MT76_RESET, &dev->mt76.state);
65         mutex_unlock(&dev->mt76.mutex);
66
67         dev->beacon_ops->pre_tbtt_enable(dev, true);
68         mt76_txq_schedule_all(&dev->mt76);
69
70         return err;
71 }
72
73 static int
74 mt76x2u_config(struct ieee80211_hw *hw, u32 changed)
75 {
76         struct mt76x02_dev *dev = hw->priv;
77         int err = 0;
78
79         mutex_lock(&dev->mt76.mutex);
80
81         if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
82                 if (!(hw->conf.flags & IEEE80211_CONF_MONITOR))
83                         dev->mt76.rxfilter |= MT_RX_FILTR_CFG_PROMISC;
84                 else
85                         dev->mt76.rxfilter &= ~MT_RX_FILTR_CFG_PROMISC;
86                 mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);
87         }
88
89         if (changed & IEEE80211_CONF_CHANGE_POWER) {
90                 dev->mt76.txpower_conf = hw->conf.power_level * 2;
91
92                 /* convert to per-chain power for 2x2 devices */
93                 dev->mt76.txpower_conf -= 6;
94
95                 if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state))
96                         mt76x2_phy_set_txpower(dev);
97         }
98
99         mutex_unlock(&dev->mt76.mutex);
100
101         if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
102                 ieee80211_stop_queues(hw);
103                 err = mt76x2u_set_channel(dev, &hw->conf.chandef);
104                 ieee80211_wake_queues(hw);
105         }
106
107         return err;
108 }
109
110 const struct ieee80211_ops mt76x2u_ops = {
111         .tx = mt76x02_tx,
112         .start = mt76x2u_start,
113         .stop = mt76x2u_stop,
114         .add_interface = mt76x02_add_interface,
115         .remove_interface = mt76x02_remove_interface,
116         .sta_state = mt76_sta_state,
117         .set_key = mt76x02_set_key,
118         .ampdu_action = mt76x02_ampdu_action,
119         .config = mt76x2u_config,
120         .wake_tx_queue = mt76_wake_tx_queue,
121         .bss_info_changed = mt76x02_bss_info_changed,
122         .configure_filter = mt76x02_configure_filter,
123         .conf_tx = mt76x02_conf_tx,
124         .sw_scan_start = mt76x02_sw_scan,
125         .sw_scan_complete = mt76x02_sw_scan_complete,
126         .sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
127         .get_txpower = mt76_get_txpower,
128         .set_tim = mt76_set_tim,
129         .release_buffered_frames = mt76_release_buffered_frames,
130 };