xref: /openbmc/linux/drivers/net/wireless/mediatek/mt76/mt76x0/main.c (revision 2e7c04aec86758e0adfcad4a24c86593b45807a3)
1 /*
2  * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
3  * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
4  * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2
8  * as published by the Free Software Foundation
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  */
15 
16 #include "mt76x0.h"
17 #include "mac.h"
18 #include <linux/etherdevice.h>
19 
20 static int mt76x0_start(struct ieee80211_hw *hw)
21 {
22 	struct mt76x0_dev *dev = hw->priv;
23 	int ret;
24 
25 	mutex_lock(&dev->mutex);
26 
27 	ret = mt76x0_mac_start(dev);
28 	if (ret)
29 		goto out;
30 
31 	ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work,
32 				     MT_CALIBRATE_INTERVAL);
33 	ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
34 				     MT_CALIBRATE_INTERVAL);
35 out:
36 	mutex_unlock(&dev->mutex);
37 	return ret;
38 }
39 
40 static void mt76x0_stop(struct ieee80211_hw *hw)
41 {
42 	struct mt76x0_dev *dev = hw->priv;
43 
44 	mutex_lock(&dev->mutex);
45 
46 	cancel_delayed_work_sync(&dev->cal_work);
47 	cancel_delayed_work_sync(&dev->mac_work);
48 	mt76x0_mac_stop(dev);
49 
50 	mutex_unlock(&dev->mutex);
51 }
52 
53 
54 static int mt76x0_add_interface(struct ieee80211_hw *hw,
55 				 struct ieee80211_vif *vif)
56 {
57 	struct mt76x0_dev *dev = hw->priv;
58 	struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv;
59 	unsigned int idx;
60 
61 	idx = ffs(~dev->vif_mask);
62 	if (!idx || idx > 8)
63 		return -ENOSPC;
64 
65 	idx--;
66 	dev->vif_mask |= BIT(idx);
67 
68 	mvif->idx = idx;
69 	mvif->group_wcid.idx = GROUP_WCID(idx);
70 	mvif->group_wcid.hw_key_idx = -1;
71 
72 	return 0;
73 }
74 
75 static void mt76x0_remove_interface(struct ieee80211_hw *hw,
76 				     struct ieee80211_vif *vif)
77 {
78 	struct mt76x0_dev *dev = hw->priv;
79 	struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv;
80 	unsigned int wcid = mvif->group_wcid.idx;
81 
82 	dev->wcid_mask[wcid / BITS_PER_LONG] &= ~BIT(wcid % BITS_PER_LONG);
83 }
84 
85 static int mt76x0_config(struct ieee80211_hw *hw, u32 changed)
86 {
87 	struct mt76x0_dev *dev = hw->priv;
88 	int ret = 0;
89 
90 	mutex_lock(&dev->mutex);
91 
92 	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
93 		if (!(hw->conf.flags & IEEE80211_CONF_MONITOR))
94 			dev->rxfilter |= MT_RX_FILTR_CFG_PROMISC;
95 		else
96 			dev->rxfilter &= ~MT_RX_FILTR_CFG_PROMISC;
97 
98 		mt76_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter);
99 	}
100 
101 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
102 		ieee80211_stop_queues(hw);
103 		ret = mt76x0_phy_set_channel(dev, &hw->conf.chandef);
104 		ieee80211_wake_queues(hw);
105 	}
106 
107 	mutex_unlock(&dev->mutex);
108 
109 	return ret;
110 }
111 
112 static void
113 mt76_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
114 		      unsigned int *total_flags, u64 multicast)
115 {
116 	struct mt76x0_dev *dev = hw->priv;
117 	u32 flags = 0;
118 
119 #define MT76_FILTER(_flag, _hw) do { \
120 		flags |= *total_flags & FIF_##_flag;			\
121 		dev->rxfilter &= ~(_hw);				\
122 		dev->rxfilter |= !(flags & FIF_##_flag) * (_hw);	\
123 	} while (0)
124 
125 	mutex_lock(&dev->mutex);
126 
127 	dev->rxfilter &= ~MT_RX_FILTR_CFG_OTHER_BSS;
128 
129 	MT76_FILTER(FCSFAIL, MT_RX_FILTR_CFG_CRC_ERR);
130 	MT76_FILTER(PLCPFAIL, MT_RX_FILTR_CFG_PHY_ERR);
131 	MT76_FILTER(CONTROL, MT_RX_FILTR_CFG_ACK |
132 			     MT_RX_FILTR_CFG_CTS |
133 			     MT_RX_FILTR_CFG_CFEND |
134 			     MT_RX_FILTR_CFG_CFACK |
135 			     MT_RX_FILTR_CFG_BA |
136 			     MT_RX_FILTR_CFG_CTRL_RSV);
137 	MT76_FILTER(PSPOLL, MT_RX_FILTR_CFG_PSPOLL);
138 
139 	*total_flags = flags;
140 	mt76_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter);
141 
142 	mutex_unlock(&dev->mutex);
143 }
144 
145 static void
146 mt76x0_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
147 			 struct ieee80211_bss_conf *info, u32 changed)
148 {
149 	struct mt76x0_dev *dev = hw->priv;
150 
151 	mutex_lock(&dev->mutex);
152 
153 	if (changed & BSS_CHANGED_ASSOC)
154 		mt76x0_phy_con_cal_onoff(dev, info);
155 
156 	if (changed & BSS_CHANGED_BSSID) {
157 		mt76x0_addr_wr(dev, MT_MAC_BSSID_DW0, info->bssid);
158 
159 		/* Note: this is a hack because beacon_int is not changed
160 		 *	 on leave nor is any more appropriate event generated.
161 		 *	 rt2x00 doesn't seem to be bothered though.
162 		 */
163 		if (is_zero_ether_addr(info->bssid))
164 			mt76x0_mac_config_tsf(dev, false, 0);
165 	}
166 
167 	if (changed & BSS_CHANGED_BASIC_RATES) {
168 		mt76_wr(dev, MT_LEGACY_BASIC_RATE, info->basic_rates);
169 		mt76_wr(dev, MT_HT_FBK_CFG0, 0x65432100);
170 		mt76_wr(dev, MT_HT_FBK_CFG1, 0xedcba980);
171 		mt76_wr(dev, MT_LG_FBK_CFG0, 0xedcba988);
172 		mt76_wr(dev, MT_LG_FBK_CFG1, 0x00002100);
173 	}
174 
175 	if (changed & BSS_CHANGED_BEACON_INT)
176 		mt76x0_mac_config_tsf(dev, true, info->beacon_int);
177 
178 	if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT)
179 		mt76x0_mac_set_protection(dev, info->use_cts_prot,
180 					   info->ht_operation_mode);
181 
182 	if (changed & BSS_CHANGED_ERP_PREAMBLE)
183 		mt76x0_mac_set_short_preamble(dev, info->use_short_preamble);
184 
185 	if (changed & BSS_CHANGED_ERP_SLOT) {
186 		int slottime = info->use_short_slot ? 9 : 20;
187 
188 		mt76_rmw_field(dev, MT_BKOFF_SLOT_CFG,
189 			       MT_BKOFF_SLOT_CFG_SLOTTIME, slottime);
190 	}
191 
192 	if (changed & BSS_CHANGED_ASSOC)
193 		mt76x0_phy_recalibrate_after_assoc(dev);
194 
195 	mutex_unlock(&dev->mutex);
196 }
197 
198 static int
199 mt76x0_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
200 		struct ieee80211_sta *sta)
201 {
202 	struct mt76x0_dev *dev = hw->priv;
203 	struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
204 	struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv;
205 	int ret = 0;
206 	int idx = 0;
207 
208 	mutex_lock(&dev->mutex);
209 
210 	idx = mt76_wcid_alloc(dev->wcid_mask, ARRAY_SIZE(dev->wcid));
211 	if (idx < 0) {
212 		ret = -ENOSPC;
213 		goto out;
214 	}
215 
216 	msta->wcid.idx = idx;
217 	msta->wcid.hw_key_idx = -1;
218 	mt76x0_mac_wcid_setup(dev, idx, mvif->idx, sta->addr);
219 	mt76_clear(dev, MT_WCID_DROP(idx), MT_WCID_DROP_MASK(idx));
220 	rcu_assign_pointer(dev->wcid[idx], &msta->wcid);
221 	mt76x0_mac_set_ampdu_factor(dev);
222 
223 out:
224 	mutex_unlock(&dev->mutex);
225 
226 	return ret;
227 }
228 
229 static int
230 mt76x0_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
231 		   struct ieee80211_sta *sta)
232 {
233 	struct mt76x0_dev *dev = hw->priv;
234 	struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
235 	int idx = msta->wcid.idx;
236 
237 	mutex_lock(&dev->mutex);
238 	rcu_assign_pointer(dev->wcid[idx], NULL);
239 	mt76_set(dev, MT_WCID_DROP(idx), MT_WCID_DROP_MASK(idx));
240 	dev->wcid_mask[idx / BITS_PER_LONG] &= ~BIT(idx % BITS_PER_LONG);
241 	mt76x0_mac_wcid_setup(dev, idx, 0, NULL);
242 	mt76x0_mac_set_ampdu_factor(dev);
243 	mutex_unlock(&dev->mutex);
244 
245 	return 0;
246 }
247 
248 static void
249 mt76x0_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
250 		   enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
251 {
252 }
253 
254 static void
255 mt76x0_sw_scan(struct ieee80211_hw *hw,
256 		struct ieee80211_vif *vif,
257 		const u8 *mac_addr)
258 {
259 	struct mt76x0_dev *dev = hw->priv;
260 
261 	cancel_delayed_work_sync(&dev->cal_work);
262 	mt76x0_agc_save(dev);
263 	set_bit(MT76_SCANNING, &dev->mt76.state);
264 }
265 
266 static void
267 mt76x0_sw_scan_complete(struct ieee80211_hw *hw,
268 			 struct ieee80211_vif *vif)
269 {
270 	struct mt76x0_dev *dev = hw->priv;
271 
272 	mt76x0_agc_restore(dev);
273 	clear_bit(MT76_SCANNING, &dev->mt76.state);
274 
275 	ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
276 				     MT_CALIBRATE_INTERVAL);
277 }
278 
279 static int
280 mt76x0_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
281 		struct ieee80211_vif *vif, struct ieee80211_sta *sta,
282 		struct ieee80211_key_conf *key)
283 {
284 	struct mt76x0_dev *dev = hw->priv;
285 	struct mt76_vif *mvif = (struct mt76_vif *) vif->drv_priv;
286 	struct mt76_sta *msta = sta ? (struct mt76_sta *) sta->drv_priv : NULL;
287 	struct mt76_wcid *wcid = msta ? &msta->wcid : &mvif->group_wcid;
288 	int idx = key->keyidx;
289 	int ret;
290 
291 	if (cmd == SET_KEY) {
292 		key->hw_key_idx = wcid->idx;
293 		wcid->hw_key_idx = idx;
294 	} else {
295 		if (idx == wcid->hw_key_idx)
296 			wcid->hw_key_idx = -1;
297 
298 		key = NULL;
299 	}
300 
301 	if (!msta) {
302 		if (key || wcid->hw_key_idx == idx) {
303 			ret = mt76x0_mac_wcid_set_key(dev, wcid->idx, key);
304 			if (ret)
305 				return ret;
306 		}
307 
308 		return mt76x0_mac_shared_key_setup(dev, mvif->idx, idx, key);
309 	}
310 
311 	return mt76x0_mac_wcid_set_key(dev, msta->wcid.idx, key);
312 }
313 
314 static int mt76x0_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
315 {
316 	struct mt76x0_dev *dev = hw->priv;
317 
318 	mt76_rmw_field(dev, MT_TX_RTS_CFG, MT_TX_RTS_CFG_THRESH, value);
319 
320 	return 0;
321 }
322 
323 static int
324 mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
325 		  struct ieee80211_ampdu_params *params)
326 {
327 	struct mt76x0_dev *dev = hw->priv;
328 	struct ieee80211_sta *sta = params->sta;
329 	enum ieee80211_ampdu_mlme_action action = params->action;
330 	u16 tid = params->tid;
331 	u16 *ssn = &params->ssn;
332 	struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
333 
334 	WARN_ON(msta->wcid.idx > N_WCIDS);
335 
336 	switch (action) {
337 	case IEEE80211_AMPDU_RX_START:
338 		mt76_set(dev, MT_WCID_ADDR(msta->wcid.idx) + 4, BIT(16 + tid));
339 		break;
340 	case IEEE80211_AMPDU_RX_STOP:
341 		mt76_clear(dev, MT_WCID_ADDR(msta->wcid.idx) + 4, BIT(16 + tid));
342 		break;
343 	case IEEE80211_AMPDU_TX_OPERATIONAL:
344 		ieee80211_send_bar(vif, sta->addr, tid, msta->agg_ssn[tid]);
345 		break;
346 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
347 	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
348 		break;
349 	case IEEE80211_AMPDU_TX_START:
350 		msta->agg_ssn[tid] = *ssn << 4;
351 		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
352 		break;
353 	case IEEE80211_AMPDU_TX_STOP_CONT:
354 		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
355 		break;
356 	}
357 
358 	return 0;
359 }
360 
361 static void
362 mt76_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
363 			 struct ieee80211_sta *sta)
364 {
365 	struct mt76x0_dev *dev = hw->priv;
366 	struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
367 	struct ieee80211_sta_rates *rates;
368 	struct ieee80211_tx_rate rate = {};
369 
370 	rcu_read_lock();
371 	rates = rcu_dereference(sta->rates);
372 
373 	if (!rates)
374 		goto out;
375 
376 	rate.idx = rates->rate[0].idx;
377 	rate.flags = rates->rate[0].flags;
378 	mt76x0_mac_wcid_set_rate(dev, &msta->wcid, &rate);
379 
380 out:
381 	rcu_read_unlock();
382 }
383 
384 const struct ieee80211_ops mt76x0_ops = {
385 	.tx = mt76x0_tx,
386 	.start = mt76x0_start,
387 	.stop = mt76x0_stop,
388 	.add_interface = mt76x0_add_interface,
389 	.remove_interface = mt76x0_remove_interface,
390 	.config = mt76x0_config,
391 	.configure_filter = mt76_configure_filter,
392 	.bss_info_changed = mt76x0_bss_info_changed,
393 	.sta_add = mt76x0_sta_add,
394 	.sta_remove = mt76x0_sta_remove,
395 	.sta_notify = mt76x0_sta_notify,
396 	.set_key = mt76x0_set_key,
397 	.conf_tx = mt76x0_conf_tx,
398 	.sw_scan_start = mt76x0_sw_scan,
399 	.sw_scan_complete = mt76x0_sw_scan_complete,
400 	.ampdu_action = mt76_ampdu_action,
401 	.sta_rate_tbl_update = mt76_sta_rate_tbl_update,
402 	.set_rts_threshold = mt76x0_set_rts_threshold,
403 };
404