]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/net/wireless/mediatek/mt76/mt76x2_main.c
mt76x0: pci: add mt76x0e_cleanup routine
[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 #include "mt76x02_util.h"
19
20 static int
21 mt76x2_start(struct ieee80211_hw *hw)
22 {
23         struct mt76x2_dev *dev = hw->priv;
24         int ret;
25
26         mutex_lock(&dev->mt76.mutex);
27
28         ret = mt76x2_mac_start(dev);
29         if (ret)
30                 goto out;
31
32         ret = mt76x2_phy_start(dev);
33         if (ret)
34                 goto out;
35
36         ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
37                                      MT_CALIBRATE_INTERVAL);
38
39         set_bit(MT76_STATE_RUNNING, &dev->mt76.state);
40
41 out:
42         mutex_unlock(&dev->mt76.mutex);
43         return ret;
44 }
45
46 static void
47 mt76x2_stop(struct ieee80211_hw *hw)
48 {
49         struct mt76x2_dev *dev = hw->priv;
50
51         mutex_lock(&dev->mt76.mutex);
52         clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
53         mt76x2_stop_hardware(dev);
54         mutex_unlock(&dev->mt76.mutex);
55 }
56
57 static int
58 mt76x2_set_channel(struct mt76x2_dev *dev, struct cfg80211_chan_def *chandef)
59 {
60         int ret;
61
62         cancel_delayed_work_sync(&dev->cal_work);
63
64         set_bit(MT76_RESET, &dev->mt76.state);
65
66         mt76_set_channel(&dev->mt76);
67
68         tasklet_disable(&dev->pre_tbtt_tasklet);
69         tasklet_disable(&dev->dfs_pd.dfs_tasklet);
70
71         mt76x2_mac_stop(dev, true);
72         ret = mt76x2_phy_set_channel(dev, chandef);
73
74         /* channel cycle counters read-and-clear */
75         mt76_rr(dev, MT_CH_IDLE);
76         mt76_rr(dev, MT_CH_BUSY);
77
78         mt76x2_dfs_init_params(dev);
79
80         mt76x2_mac_resume(dev);
81         tasklet_enable(&dev->dfs_pd.dfs_tasklet);
82         tasklet_enable(&dev->pre_tbtt_tasklet);
83
84         clear_bit(MT76_RESET, &dev->mt76.state);
85
86         mt76_txq_schedule_all(&dev->mt76);
87
88         return ret;
89 }
90
91 static int
92 mt76x2_config(struct ieee80211_hw *hw, u32 changed)
93 {
94         struct mt76x2_dev *dev = hw->priv;
95         int ret = 0;
96
97         mutex_lock(&dev->mt76.mutex);
98
99         if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
100                 if (!(hw->conf.flags & IEEE80211_CONF_MONITOR))
101                         dev->mt76.rxfilter |= MT_RX_FILTR_CFG_PROMISC;
102                 else
103                         dev->mt76.rxfilter &= ~MT_RX_FILTR_CFG_PROMISC;
104
105                 mt76_wr(dev, MT_RX_FILTR_CFG, dev->mt76.rxfilter);
106         }
107
108         if (changed & IEEE80211_CONF_CHANGE_POWER) {
109                 dev->mt76.txpower_conf = hw->conf.power_level * 2;
110
111                 /* convert to per-chain power for 2x2 devices */
112                 dev->mt76.txpower_conf -= 6;
113
114                 if (test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) {
115                         mt76x2_phy_set_txpower(dev);
116                         mt76x2_tx_set_txpwr_auto(dev, dev->mt76.txpower_conf);
117                 }
118         }
119
120         if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
121                 ieee80211_stop_queues(hw);
122                 ret = mt76x2_set_channel(dev, &hw->conf.chandef);
123                 ieee80211_wake_queues(hw);
124         }
125
126         mutex_unlock(&dev->mt76.mutex);
127
128         return ret;
129 }
130
131 static void
132 mt76x2_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
133                         struct ieee80211_bss_conf *info, u32 changed)
134 {
135         struct mt76x2_dev *dev = hw->priv;
136         struct mt76x02_vif *mvif = (struct mt76x02_vif *) vif->drv_priv;
137
138         mutex_lock(&dev->mt76.mutex);
139
140         if (changed & BSS_CHANGED_BSSID)
141                 mt76x2_mac_set_bssid(dev, mvif->idx, info->bssid);
142
143         if (changed & BSS_CHANGED_BEACON_INT) {
144                 mt76_rmw_field(dev, MT_BEACON_TIME_CFG,
145                                MT_BEACON_TIME_CFG_INTVAL,
146                                info->beacon_int << 4);
147                 dev->beacon_int = info->beacon_int;
148                 dev->tbtt_count = 0;
149         }
150
151         if (changed & BSS_CHANGED_BEACON_ENABLED) {
152                 tasklet_disable(&dev->pre_tbtt_tasklet);
153                 mt76x2_mac_set_beacon_enable(dev, mvif->idx,
154                                              info->enable_beacon);
155                 tasklet_enable(&dev->pre_tbtt_tasklet);
156         }
157
158         if (changed & BSS_CHANGED_ERP_SLOT) {
159                 int slottime = info->use_short_slot ? 9 : 20;
160
161                 dev->slottime = slottime;
162                 mt76x2_set_tx_ackto(dev);
163         }
164
165         mutex_unlock(&dev->mt76.mutex);
166 }
167
168 void
169 mt76x2_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps)
170 {
171         struct mt76x02_sta *msta = (struct mt76x02_sta *) sta->drv_priv;
172         struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76);
173         int idx = msta->wcid.idx;
174
175         mt76_stop_tx_queues(&dev->mt76, sta, true);
176         mt76x02_mac_wcid_set_drop(&dev->mt76, idx, ps);
177 }
178
179 static void
180 mt76x2_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
181                const u8 *mac)
182 {
183         struct mt76x2_dev *dev = hw->priv;
184
185         tasklet_disable(&dev->pre_tbtt_tasklet);
186         set_bit(MT76_SCANNING, &dev->mt76.state);
187 }
188
189 static void
190 mt76x2_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
191 {
192         struct mt76x2_dev *dev = hw->priv;
193
194         clear_bit(MT76_SCANNING, &dev->mt76.state);
195         tasklet_enable(&dev->pre_tbtt_tasklet);
196 }
197
198 static void
199 mt76x2_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
200              u32 queues, bool drop)
201 {
202 }
203
204 static int
205 mt76x2_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm)
206 {
207         struct mt76x2_dev *dev = hw->priv;
208
209         *dbm = dev->mt76.txpower_cur / 2;
210
211         /* convert from per-chain power to combined output on 2x2 devices */
212         *dbm += 3;
213
214         return 0;
215 }
216
217 static void mt76x2_set_coverage_class(struct ieee80211_hw *hw,
218                                       s16 coverage_class)
219 {
220         struct mt76x2_dev *dev = hw->priv;
221
222         mutex_lock(&dev->mt76.mutex);
223         dev->coverage_class = coverage_class;
224         mt76x2_set_tx_ackto(dev);
225         mutex_unlock(&dev->mt76.mutex);
226 }
227
228 static int
229 mt76x2_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
230 {
231         return 0;
232 }
233
234 static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant,
235                               u32 rx_ant)
236 {
237         struct mt76x2_dev *dev = hw->priv;
238
239         if (!tx_ant || tx_ant > 3 || tx_ant != rx_ant)
240                 return -EINVAL;
241
242         mutex_lock(&dev->mt76.mutex);
243
244         dev->mt76.chainmask = (tx_ant == 3) ? 0x202 : 0x101;
245         dev->mt76.antenna_mask = tx_ant;
246
247         mt76_set_stream_caps(&dev->mt76, true);
248         mt76x2_phy_set_antenna(dev);
249
250         mutex_unlock(&dev->mt76.mutex);
251
252         return 0;
253 }
254
255 static int mt76x2_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant,
256                               u32 *rx_ant)
257 {
258         struct mt76x2_dev *dev = hw->priv;
259
260         mutex_lock(&dev->mt76.mutex);
261         *tx_ant = dev->mt76.antenna_mask;
262         *rx_ant = dev->mt76.antenna_mask;
263         mutex_unlock(&dev->mt76.mutex);
264
265         return 0;
266 }
267
268 static int
269 mt76x2_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
270 {
271         struct mt76x2_dev *dev = hw->priv;
272
273         if (val != ~0 && val > 0xffff)
274                 return -EINVAL;
275
276         mutex_lock(&dev->mutex);
277         mt76x2_mac_set_tx_protection(dev, val);
278         mutex_unlock(&dev->mutex);
279
280         return 0;
281 }
282
283 const struct ieee80211_ops mt76x2_ops = {
284         .tx = mt76x2_tx,
285         .start = mt76x2_start,
286         .stop = mt76x2_stop,
287         .add_interface = mt76x02_add_interface,
288         .remove_interface = mt76x02_remove_interface,
289         .config = mt76x2_config,
290         .configure_filter = mt76x02_configure_filter,
291         .bss_info_changed = mt76x2_bss_info_changed,
292         .sta_add = mt76x02_sta_add,
293         .sta_remove = mt76x02_sta_remove,
294         .set_key = mt76x02_set_key,
295         .conf_tx = mt76x02_conf_tx,
296         .sw_scan_start = mt76x2_sw_scan,
297         .sw_scan_complete = mt76x2_sw_scan_complete,
298         .flush = mt76x2_flush,
299         .ampdu_action = mt76x02_ampdu_action,
300         .get_txpower = mt76x2_get_txpower,
301         .wake_tx_queue = mt76_wake_tx_queue,
302         .sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
303         .release_buffered_frames = mt76_release_buffered_frames,
304         .set_coverage_class = mt76x2_set_coverage_class,
305         .get_survey = mt76_get_survey,
306         .set_tim = mt76x2_set_tim,
307         .set_antenna = mt76x2_set_antenna,
308         .get_antenna = mt76x2_get_antenna,
309         .set_rts_threshold = mt76x2_set_rts_threshold,
310 };
311