2 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
17 #include <linux/etherdevice.h>
18 #include <linux/version.h>
20 static int mt7601u_start(struct ieee80211_hw
*hw
)
22 struct mt7601u_dev
*dev
= hw
->priv
;
25 mutex_lock(&dev
->mutex
);
27 ret
= mt7601u_mac_start(dev
);
31 ieee80211_queue_delayed_work(dev
->hw
, &dev
->mac_work
,
32 MT_CALIBRATE_INTERVAL
);
33 ieee80211_queue_delayed_work(dev
->hw
, &dev
->cal_work
,
34 MT_CALIBRATE_INTERVAL
);
36 mutex_unlock(&dev
->mutex
);
40 static void mt7601u_stop(struct ieee80211_hw
*hw
)
42 struct mt7601u_dev
*dev
= hw
->priv
;
44 mutex_lock(&dev
->mutex
);
46 cancel_delayed_work_sync(&dev
->cal_work
);
47 cancel_delayed_work_sync(&dev
->mac_work
);
48 mt7601u_mac_stop(dev
);
50 mutex_unlock(&dev
->mutex
);
53 static int mt7601u_add_interface(struct ieee80211_hw
*hw
,
54 struct ieee80211_vif
*vif
)
56 struct mt7601u_dev
*dev
= hw
->priv
;
57 struct mt76_vif
*mvif
= (struct mt76_vif
*) vif
->drv_priv
;
59 unsigned int wcid
= GROUP_WCID(idx
);
61 /* Note: for AP do the AP-STA things mt76 does:
63 * - do mac address tricks
68 if (dev
->wcid_mask
[wcid
/ BITS_PER_LONG
] & BIT(wcid
% BITS_PER_LONG
))
70 dev
->wcid_mask
[wcid
/ BITS_PER_LONG
] |= BIT(wcid
% BITS_PER_LONG
);
71 mvif
->group_wcid
.idx
= wcid
;
72 mvif
->group_wcid
.hw_key_idx
= -1;
77 static void mt7601u_remove_interface(struct ieee80211_hw
*hw
,
78 struct ieee80211_vif
*vif
)
80 struct mt7601u_dev
*dev
= hw
->priv
;
81 struct mt76_vif
*mvif
= (struct mt76_vif
*) vif
->drv_priv
;
82 unsigned int wcid
= mvif
->group_wcid
.idx
;
84 dev
->wcid_mask
[wcid
/ BITS_PER_LONG
] &= ~BIT(wcid
% BITS_PER_LONG
);
87 static int mt7601u_config(struct ieee80211_hw
*hw
, u32 changed
)
89 struct mt7601u_dev
*dev
= hw
->priv
;
92 mutex_lock(&dev
->mutex
);
94 if (changed
& IEEE80211_CONF_CHANGE_CHANNEL
) {
95 ieee80211_stop_queues(hw
);
96 ret
= mt7601u_phy_set_channel(dev
, &hw
->conf
.chandef
);
97 ieee80211_wake_queues(hw
);
100 mutex_unlock(&dev
->mutex
);
106 mt76_configure_filter(struct ieee80211_hw
*hw
, unsigned int changed_flags
,
107 unsigned int *total_flags
, u64 multicast
)
109 struct mt7601u_dev
*dev
= hw
->priv
;
112 #define MT76_FILTER(_flag, _hw) do { \
113 flags |= *total_flags & FIF_##_flag; \
114 dev->rxfilter &= ~(_hw); \
115 dev->rxfilter |= !(flags & FIF_##_flag) * (_hw); \
118 mutex_lock(&dev
->mutex
);
120 dev
->rxfilter
&= ~MT_RX_FILTR_CFG_OTHER_BSS
;
122 MT76_FILTER(OTHER_BSS
, MT_RX_FILTR_CFG_PROMISC
);
123 MT76_FILTER(FCSFAIL
, MT_RX_FILTR_CFG_CRC_ERR
);
124 MT76_FILTER(PLCPFAIL
, MT_RX_FILTR_CFG_PHY_ERR
);
125 MT76_FILTER(CONTROL
, MT_RX_FILTR_CFG_ACK
|
126 MT_RX_FILTR_CFG_CTS
|
127 MT_RX_FILTR_CFG_CFEND
|
128 MT_RX_FILTR_CFG_CFACK
|
130 MT_RX_FILTR_CFG_CTRL_RSV
);
131 MT76_FILTER(PSPOLL
, MT_RX_FILTR_CFG_PSPOLL
);
133 *total_flags
= flags
;
134 mt76_wr(dev
, MT_RX_FILTR_CFG
, dev
->rxfilter
);
136 mutex_unlock(&dev
->mutex
);
140 mt7601u_bss_info_changed(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
141 struct ieee80211_bss_conf
*info
, u32 changed
)
143 struct mt7601u_dev
*dev
= hw
->priv
;
145 mutex_lock(&dev
->mutex
);
147 if (changed
& BSS_CHANGED_ASSOC
)
148 mt7601u_phy_con_cal_onoff(dev
, info
);
150 if (changed
& BSS_CHANGED_BSSID
) {
151 mt7601u_addr_wr(dev
, MT_MAC_BSSID_DW0
, info
->bssid
);
153 /* Note: this is a hack because beacon_int is not changed
154 * on leave nor is any more appropriate event generated.
155 * rt2x00 doesn't seem to be bothered though.
157 if (is_zero_ether_addr(info
->bssid
))
158 mt7601u_mac_config_tsf(dev
, false, 0);
161 if (changed
& BSS_CHANGED_BASIC_RATES
) {
162 mt7601u_wr(dev
, MT_LEGACY_BASIC_RATE
, info
->basic_rates
);
163 mt7601u_wr(dev
, MT_HT_FBK_CFG0
, 0x65432100);
164 mt7601u_wr(dev
, MT_HT_FBK_CFG1
, 0xedcba980);
165 mt7601u_wr(dev
, MT_LG_FBK_CFG0
, 0xedcba988);
166 mt7601u_wr(dev
, MT_LG_FBK_CFG1
, 0x00002100);
169 if (changed
& BSS_CHANGED_BEACON_INT
)
170 mt7601u_mac_config_tsf(dev
, true, info
->beacon_int
);
172 if (changed
& BSS_CHANGED_HT
|| changed
& BSS_CHANGED_ERP_CTS_PROT
)
173 mt7601u_mac_set_protection(dev
, info
->use_cts_prot
,
174 info
->ht_operation_mode
);
176 if (changed
& BSS_CHANGED_ERP_PREAMBLE
)
177 mt7601u_mac_set_short_preamble(dev
, info
->use_short_preamble
);
179 if (changed
& BSS_CHANGED_ERP_SLOT
) {
180 int slottime
= info
->use_short_slot
? 9 : 20;
182 mt76_rmw_field(dev
, MT_BKOFF_SLOT_CFG
,
183 MT_BKOFF_SLOT_CFG_SLOTTIME
, slottime
);
186 if (changed
& BSS_CHANGED_ASSOC
)
187 mt7601u_phy_recalibrate_after_assoc(dev
);
189 mutex_unlock(&dev
->mutex
);
193 mt76_wcid_alloc(struct mt7601u_dev
*dev
)
197 for (i
= 0; i
< ARRAY_SIZE(dev
->wcid_mask
); i
++) {
198 idx
= ffs(~dev
->wcid_mask
[i
]);
203 dev
->wcid_mask
[i
] |= BIT(idx
);
207 idx
= i
* BITS_PER_LONG
+ idx
;
215 mt7601u_sta_add(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
216 struct ieee80211_sta
*sta
)
218 struct mt7601u_dev
*dev
= hw
->priv
;
219 struct mt76_sta
*msta
= (struct mt76_sta
*) sta
->drv_priv
;
220 struct mt76_vif
*mvif
= (struct mt76_vif
*) vif
->drv_priv
;
224 mutex_lock(&dev
->mutex
);
226 idx
= mt76_wcid_alloc(dev
);
232 msta
->wcid
.idx
= idx
;
233 msta
->wcid
.hw_key_idx
= -1;
234 mt7601u_mac_wcid_setup(dev
, idx
, mvif
->idx
, sta
->addr
);
235 mt76_clear(dev
, MT_WCID_DROP(idx
), MT_WCID_DROP_MASK(idx
));
236 rcu_assign_pointer(dev
->wcid
[idx
], &msta
->wcid
);
237 mt7601u_mac_set_ampdu_factor(dev
);
240 mutex_unlock(&dev
->mutex
);
246 mt7601u_sta_remove(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
247 struct ieee80211_sta
*sta
)
249 struct mt7601u_dev
*dev
= hw
->priv
;
250 struct mt76_sta
*msta
= (struct mt76_sta
*) sta
->drv_priv
;
251 int idx
= msta
->wcid
.idx
;
253 mutex_lock(&dev
->mutex
);
254 rcu_assign_pointer(dev
->wcid
[idx
], NULL
);
255 mt76_set(dev
, MT_WCID_DROP(idx
), MT_WCID_DROP_MASK(idx
));
256 dev
->wcid_mask
[idx
/ BITS_PER_LONG
] &= ~BIT(idx
% BITS_PER_LONG
);
257 mt7601u_mac_wcid_setup(dev
, idx
, 0, NULL
);
258 mt7601u_mac_set_ampdu_factor(dev
);
259 mutex_unlock(&dev
->mutex
);
265 mt7601u_sta_notify(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
266 enum sta_notify_cmd cmd
, struct ieee80211_sta
*sta
)
271 mt7601u_sw_scan(struct ieee80211_hw
*hw
,
272 struct ieee80211_vif
*vif
,
275 struct mt7601u_dev
*dev
= hw
->priv
;
277 mt7601u_agc_save(dev
);
278 set_bit(MT7601U_STATE_SCANNING
, &dev
->state
);
282 mt7601u_sw_scan_complete(struct ieee80211_hw
*hw
,
283 struct ieee80211_vif
*vif
)
285 struct mt7601u_dev
*dev
= hw
->priv
;
287 mt7601u_agc_restore(dev
);
288 clear_bit(MT7601U_STATE_SCANNING
, &dev
->state
);
292 mt7601u_set_key(struct ieee80211_hw
*hw
, enum set_key_cmd cmd
,
293 struct ieee80211_vif
*vif
, struct ieee80211_sta
*sta
,
294 struct ieee80211_key_conf
*key
)
296 struct mt7601u_dev
*dev
= hw
->priv
;
297 struct mt76_vif
*mvif
= (struct mt76_vif
*) vif
->drv_priv
;
298 struct mt76_sta
*msta
= sta
? (struct mt76_sta
*) sta
->drv_priv
: NULL
;
299 struct mt76_wcid
*wcid
= msta
? &msta
->wcid
: &mvif
->group_wcid
;
300 int idx
= key
->keyidx
;
303 if (cmd
== SET_KEY
) {
304 key
->hw_key_idx
= wcid
->idx
;
305 wcid
->hw_key_idx
= idx
;
307 if (idx
== wcid
->hw_key_idx
)
308 wcid
->hw_key_idx
= -1;
314 if (key
|| wcid
->hw_key_idx
== idx
) {
315 ret
= mt76_mac_wcid_set_key(dev
, wcid
->idx
, key
);
320 return mt76_mac_shared_key_setup(dev
, mvif
->idx
, idx
, key
);
323 return mt76_mac_wcid_set_key(dev
, msta
->wcid
.idx
, key
);
326 static int mt7601u_set_rts_threshold(struct ieee80211_hw
*hw
, u32 value
)
328 struct mt7601u_dev
*dev
= hw
->priv
;
330 mt76_rmw_field(dev
, MT_TX_RTS_CFG
, MT_TX_RTS_CFG_THRESH
, value
);
336 mt76_ampdu_action(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
337 struct ieee80211_ampdu_params
*params
)
339 struct mt7601u_dev
*dev
= hw
->priv
;
340 struct ieee80211_sta
*sta
= params
->sta
;
341 enum ieee80211_ampdu_mlme_action action
= params
->action
;
342 u16 tid
= params
->tid
;
343 u16
*ssn
= ¶ms
->ssn
;
344 struct mt76_sta
*msta
= (struct mt76_sta
*) sta
->drv_priv
;
346 WARN_ON(msta
->wcid
.idx
> GROUP_WCID(0));
349 case IEEE80211_AMPDU_RX_START
:
350 mt76_set(dev
, MT_WCID_ADDR(msta
->wcid
.idx
) + 4, BIT(16 + tid
));
352 case IEEE80211_AMPDU_RX_STOP
:
353 mt76_clear(dev
, MT_WCID_ADDR(msta
->wcid
.idx
) + 4,
356 case IEEE80211_AMPDU_TX_OPERATIONAL
:
357 ieee80211_send_bar(vif
, sta
->addr
, tid
, msta
->agg_ssn
[tid
]);
359 case IEEE80211_AMPDU_TX_STOP_FLUSH
:
360 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT
:
362 case IEEE80211_AMPDU_TX_START
:
363 msta
->agg_ssn
[tid
] = *ssn
<< 4;
364 ieee80211_start_tx_ba_cb_irqsafe(vif
, sta
->addr
, tid
);
366 case IEEE80211_AMPDU_TX_STOP_CONT
:
367 ieee80211_stop_tx_ba_cb_irqsafe(vif
, sta
->addr
, tid
);
375 mt76_sta_rate_tbl_update(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
376 struct ieee80211_sta
*sta
)
378 struct mt7601u_dev
*dev
= hw
->priv
;
379 struct mt76_sta
*msta
= (struct mt76_sta
*) sta
->drv_priv
;
380 struct ieee80211_sta_rates
*rates
;
381 struct ieee80211_tx_rate rate
= {};
384 rates
= rcu_dereference(sta
->rates
);
389 rate
.idx
= rates
->rate
[0].idx
;
390 rate
.flags
= rates
->rate
[0].flags
;
391 mt76_mac_wcid_set_rate(dev
, &msta
->wcid
, &rate
);
397 const struct ieee80211_ops mt7601u_ops
= {
399 .start
= mt7601u_start
,
400 .stop
= mt7601u_stop
,
401 .add_interface
= mt7601u_add_interface
,
402 .remove_interface
= mt7601u_remove_interface
,
403 .config
= mt7601u_config
,
404 .configure_filter
= mt76_configure_filter
,
405 .bss_info_changed
= mt7601u_bss_info_changed
,
406 .sta_add
= mt7601u_sta_add
,
407 .sta_remove
= mt7601u_sta_remove
,
408 .sta_notify
= mt7601u_sta_notify
,
409 .set_key
= mt7601u_set_key
,
410 .conf_tx
= mt7601u_conf_tx
,
411 .sw_scan_start
= mt7601u_sw_scan
,
412 .sw_scan_complete
= mt7601u_sw_scan_complete
,
413 .ampdu_action
= mt76_ampdu_action
,
414 .sta_rate_tbl_update
= mt76_sta_rate_tbl_update
,
415 .set_rts_threshold
= mt7601u_set_rts_threshold
,