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>
19 static int mt7601u_start(struct ieee80211_hw
*hw
)
21 struct mt7601u_dev
*dev
= hw
->priv
;
24 mutex_lock(&dev
->mutex
);
26 ret
= mt7601u_mac_start(dev
);
30 ieee80211_queue_delayed_work(dev
->hw
, &dev
->mac_work
,
31 MT_CALIBRATE_INTERVAL
);
32 ieee80211_queue_delayed_work(dev
->hw
, &dev
->cal_work
,
33 MT_CALIBRATE_INTERVAL
);
35 mutex_unlock(&dev
->mutex
);
39 static void mt7601u_stop(struct ieee80211_hw
*hw
)
41 struct mt7601u_dev
*dev
= hw
->priv
;
43 mutex_lock(&dev
->mutex
);
45 cancel_delayed_work_sync(&dev
->cal_work
);
46 cancel_delayed_work_sync(&dev
->mac_work
);
47 mt7601u_mac_stop(dev
);
49 mutex_unlock(&dev
->mutex
);
52 static int mt7601u_add_interface(struct ieee80211_hw
*hw
,
53 struct ieee80211_vif
*vif
)
55 struct mt7601u_dev
*dev
= hw
->priv
;
56 struct mt76_vif
*mvif
= (struct mt76_vif
*) vif
->drv_priv
;
58 unsigned int wcid
= GROUP_WCID(idx
);
60 /* Note: for AP do the AP-STA things mt76 does:
62 * - do mac address tricks
67 if (!ether_addr_equal(dev
->macaddr
, vif
->addr
))
68 mt7601u_set_macaddr(dev
, vif
->addr
);
70 if (dev
->wcid_mask
[wcid
/ BITS_PER_LONG
] & BIT(wcid
% BITS_PER_LONG
))
72 dev
->wcid_mask
[wcid
/ BITS_PER_LONG
] |= BIT(wcid
% BITS_PER_LONG
);
73 mvif
->group_wcid
.idx
= wcid
;
74 mvif
->group_wcid
.hw_key_idx
= -1;
79 static void mt7601u_remove_interface(struct ieee80211_hw
*hw
,
80 struct ieee80211_vif
*vif
)
82 struct mt7601u_dev
*dev
= hw
->priv
;
83 struct mt76_vif
*mvif
= (struct mt76_vif
*) vif
->drv_priv
;
84 unsigned int wcid
= mvif
->group_wcid
.idx
;
86 dev
->wcid_mask
[wcid
/ BITS_PER_LONG
] &= ~BIT(wcid
% BITS_PER_LONG
);
89 static int mt7601u_config(struct ieee80211_hw
*hw
, u32 changed
)
91 struct mt7601u_dev
*dev
= hw
->priv
;
94 mutex_lock(&dev
->mutex
);
96 if (changed
& IEEE80211_CONF_CHANGE_CHANNEL
) {
97 ieee80211_stop_queues(hw
);
98 ret
= mt7601u_phy_set_channel(dev
, &hw
->conf
.chandef
);
99 ieee80211_wake_queues(hw
);
102 mutex_unlock(&dev
->mutex
);
108 mt76_configure_filter(struct ieee80211_hw
*hw
, unsigned int changed_flags
,
109 unsigned int *total_flags
, u64 multicast
)
111 struct mt7601u_dev
*dev
= hw
->priv
;
114 #define MT76_FILTER(_flag, _hw) do { \
115 flags |= *total_flags & FIF_##_flag; \
116 dev->rxfilter &= ~(_hw); \
117 dev->rxfilter |= !(flags & FIF_##_flag) * (_hw); \
120 mutex_lock(&dev
->mutex
);
122 dev
->rxfilter
&= ~MT_RX_FILTR_CFG_OTHER_BSS
;
124 MT76_FILTER(OTHER_BSS
, MT_RX_FILTR_CFG_PROMISC
);
125 MT76_FILTER(FCSFAIL
, MT_RX_FILTR_CFG_CRC_ERR
);
126 MT76_FILTER(PLCPFAIL
, MT_RX_FILTR_CFG_PHY_ERR
);
127 MT76_FILTER(CONTROL
, MT_RX_FILTR_CFG_ACK
|
128 MT_RX_FILTR_CFG_CTS
|
129 MT_RX_FILTR_CFG_CFEND
|
130 MT_RX_FILTR_CFG_CFACK
|
132 MT_RX_FILTR_CFG_CTRL_RSV
);
133 MT76_FILTER(PSPOLL
, MT_RX_FILTR_CFG_PSPOLL
);
135 *total_flags
= flags
;
136 mt76_wr(dev
, MT_RX_FILTR_CFG
, dev
->rxfilter
);
138 mutex_unlock(&dev
->mutex
);
142 mt7601u_bss_info_changed(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
143 struct ieee80211_bss_conf
*info
, u32 changed
)
145 struct mt7601u_dev
*dev
= hw
->priv
;
147 mutex_lock(&dev
->mutex
);
149 if (changed
& BSS_CHANGED_ASSOC
)
150 mt7601u_phy_con_cal_onoff(dev
, info
);
152 if (changed
& BSS_CHANGED_BSSID
) {
153 mt7601u_addr_wr(dev
, MT_MAC_BSSID_DW0
, info
->bssid
);
155 /* Note: this is a hack because beacon_int is not changed
156 * on leave nor is any more appropriate event generated.
157 * rt2x00 doesn't seem to be bothered though.
159 if (is_zero_ether_addr(info
->bssid
))
160 mt7601u_mac_config_tsf(dev
, false, 0);
163 if (changed
& BSS_CHANGED_BASIC_RATES
) {
164 mt7601u_wr(dev
, MT_LEGACY_BASIC_RATE
, info
->basic_rates
);
165 mt7601u_wr(dev
, MT_HT_FBK_CFG0
, 0x65432100);
166 mt7601u_wr(dev
, MT_HT_FBK_CFG1
, 0xedcba980);
167 mt7601u_wr(dev
, MT_LG_FBK_CFG0
, 0xedcba988);
168 mt7601u_wr(dev
, MT_LG_FBK_CFG1
, 0x00002100);
171 if (changed
& BSS_CHANGED_BEACON_INT
)
172 mt7601u_mac_config_tsf(dev
, true, info
->beacon_int
);
174 if (changed
& BSS_CHANGED_HT
|| changed
& BSS_CHANGED_ERP_CTS_PROT
)
175 mt7601u_mac_set_protection(dev
, info
->use_cts_prot
,
176 info
->ht_operation_mode
);
178 if (changed
& BSS_CHANGED_ERP_PREAMBLE
)
179 mt7601u_mac_set_short_preamble(dev
, info
->use_short_preamble
);
181 if (changed
& BSS_CHANGED_ERP_SLOT
) {
182 int slottime
= info
->use_short_slot
? 9 : 20;
184 mt76_rmw_field(dev
, MT_BKOFF_SLOT_CFG
,
185 MT_BKOFF_SLOT_CFG_SLOTTIME
, slottime
);
188 if (changed
& BSS_CHANGED_ASSOC
)
189 mt7601u_phy_recalibrate_after_assoc(dev
);
191 mutex_unlock(&dev
->mutex
);
195 mt76_wcid_alloc(struct mt7601u_dev
*dev
)
199 for (i
= 0; i
< ARRAY_SIZE(dev
->wcid_mask
); i
++) {
200 idx
= ffs(~dev
->wcid_mask
[i
]);
205 dev
->wcid_mask
[i
] |= BIT(idx
);
209 idx
= i
* BITS_PER_LONG
+ idx
;
217 mt7601u_sta_add(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
218 struct ieee80211_sta
*sta
)
220 struct mt7601u_dev
*dev
= hw
->priv
;
221 struct mt76_sta
*msta
= (struct mt76_sta
*) sta
->drv_priv
;
222 struct mt76_vif
*mvif
= (struct mt76_vif
*) vif
->drv_priv
;
226 mutex_lock(&dev
->mutex
);
228 idx
= mt76_wcid_alloc(dev
);
234 msta
->wcid
.idx
= idx
;
235 msta
->wcid
.hw_key_idx
= -1;
236 mt7601u_mac_wcid_setup(dev
, idx
, mvif
->idx
, sta
->addr
);
237 mt76_clear(dev
, MT_WCID_DROP(idx
), MT_WCID_DROP_MASK(idx
));
238 rcu_assign_pointer(dev
->wcid
[idx
], &msta
->wcid
);
239 mt7601u_mac_set_ampdu_factor(dev
);
242 mutex_unlock(&dev
->mutex
);
248 mt7601u_sta_remove(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
249 struct ieee80211_sta
*sta
)
251 struct mt7601u_dev
*dev
= hw
->priv
;
252 struct mt76_sta
*msta
= (struct mt76_sta
*) sta
->drv_priv
;
253 int idx
= msta
->wcid
.idx
;
255 mutex_lock(&dev
->mutex
);
256 rcu_assign_pointer(dev
->wcid
[idx
], NULL
);
257 mt76_set(dev
, MT_WCID_DROP(idx
), MT_WCID_DROP_MASK(idx
));
258 dev
->wcid_mask
[idx
/ BITS_PER_LONG
] &= ~BIT(idx
% BITS_PER_LONG
);
259 mt7601u_mac_wcid_setup(dev
, idx
, 0, NULL
);
260 mt7601u_mac_set_ampdu_factor(dev
);
261 mutex_unlock(&dev
->mutex
);
267 mt7601u_sta_notify(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
268 enum sta_notify_cmd cmd
, struct ieee80211_sta
*sta
)
273 mt7601u_sw_scan(struct ieee80211_hw
*hw
,
274 struct ieee80211_vif
*vif
,
277 struct mt7601u_dev
*dev
= hw
->priv
;
279 mt7601u_agc_save(dev
);
280 set_bit(MT7601U_STATE_SCANNING
, &dev
->state
);
284 mt7601u_sw_scan_complete(struct ieee80211_hw
*hw
,
285 struct ieee80211_vif
*vif
)
287 struct mt7601u_dev
*dev
= hw
->priv
;
289 mt7601u_agc_restore(dev
);
290 clear_bit(MT7601U_STATE_SCANNING
, &dev
->state
);
292 ieee80211_queue_delayed_work(dev
->hw
, &dev
->cal_work
,
293 MT_CALIBRATE_INTERVAL
);
294 if (dev
->freq_cal
.enabled
)
295 ieee80211_queue_delayed_work(dev
->hw
, &dev
->freq_cal
.work
,
296 MT_FREQ_CAL_INIT_DELAY
);
300 mt7601u_set_key(struct ieee80211_hw
*hw
, enum set_key_cmd cmd
,
301 struct ieee80211_vif
*vif
, struct ieee80211_sta
*sta
,
302 struct ieee80211_key_conf
*key
)
304 struct mt7601u_dev
*dev
= hw
->priv
;
305 struct mt76_vif
*mvif
= (struct mt76_vif
*) vif
->drv_priv
;
306 struct mt76_sta
*msta
= sta
? (struct mt76_sta
*) sta
->drv_priv
: NULL
;
307 struct mt76_wcid
*wcid
= msta
? &msta
->wcid
: &mvif
->group_wcid
;
308 int idx
= key
->keyidx
;
311 if (cmd
== SET_KEY
) {
312 key
->hw_key_idx
= wcid
->idx
;
313 wcid
->hw_key_idx
= idx
;
315 if (idx
== wcid
->hw_key_idx
)
316 wcid
->hw_key_idx
= -1;
322 if (key
|| wcid
->hw_key_idx
== idx
) {
323 ret
= mt76_mac_wcid_set_key(dev
, wcid
->idx
, key
);
328 return mt76_mac_shared_key_setup(dev
, mvif
->idx
, idx
, key
);
331 return mt76_mac_wcid_set_key(dev
, msta
->wcid
.idx
, key
);
334 static int mt7601u_set_rts_threshold(struct ieee80211_hw
*hw
, u32 value
)
336 struct mt7601u_dev
*dev
= hw
->priv
;
338 mt76_rmw_field(dev
, MT_TX_RTS_CFG
, MT_TX_RTS_CFG_THRESH
, value
);
344 mt76_ampdu_action(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
345 struct ieee80211_ampdu_params
*params
)
347 struct mt7601u_dev
*dev
= hw
->priv
;
348 struct ieee80211_sta
*sta
= params
->sta
;
349 enum ieee80211_ampdu_mlme_action action
= params
->action
;
350 u16 tid
= params
->tid
;
351 u16
*ssn
= ¶ms
->ssn
;
352 struct mt76_sta
*msta
= (struct mt76_sta
*) sta
->drv_priv
;
354 WARN_ON(msta
->wcid
.idx
> GROUP_WCID(0));
357 case IEEE80211_AMPDU_RX_START
:
358 mt76_set(dev
, MT_WCID_ADDR(msta
->wcid
.idx
) + 4, BIT(16 + tid
));
360 case IEEE80211_AMPDU_RX_STOP
:
361 mt76_clear(dev
, MT_WCID_ADDR(msta
->wcid
.idx
) + 4,
364 case IEEE80211_AMPDU_TX_OPERATIONAL
:
365 ieee80211_send_bar(vif
, sta
->addr
, tid
, msta
->agg_ssn
[tid
]);
367 case IEEE80211_AMPDU_TX_STOP_FLUSH
:
368 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT
:
370 case IEEE80211_AMPDU_TX_START
:
371 msta
->agg_ssn
[tid
] = *ssn
<< 4;
372 ieee80211_start_tx_ba_cb_irqsafe(vif
, sta
->addr
, tid
);
374 case IEEE80211_AMPDU_TX_STOP_CONT
:
375 ieee80211_stop_tx_ba_cb_irqsafe(vif
, sta
->addr
, tid
);
383 mt76_sta_rate_tbl_update(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
384 struct ieee80211_sta
*sta
)
386 struct mt7601u_dev
*dev
= hw
->priv
;
387 struct mt76_sta
*msta
= (struct mt76_sta
*) sta
->drv_priv
;
388 struct ieee80211_sta_rates
*rates
;
389 struct ieee80211_tx_rate rate
= {};
392 rates
= rcu_dereference(sta
->rates
);
397 rate
.idx
= rates
->rate
[0].idx
;
398 rate
.flags
= rates
->rate
[0].flags
;
399 mt76_mac_wcid_set_rate(dev
, &msta
->wcid
, &rate
);
405 const struct ieee80211_ops mt7601u_ops
= {
407 .start
= mt7601u_start
,
408 .stop
= mt7601u_stop
,
409 .add_interface
= mt7601u_add_interface
,
410 .remove_interface
= mt7601u_remove_interface
,
411 .config
= mt7601u_config
,
412 .configure_filter
= mt76_configure_filter
,
413 .bss_info_changed
= mt7601u_bss_info_changed
,
414 .sta_add
= mt7601u_sta_add
,
415 .sta_remove
= mt7601u_sta_remove
,
416 .sta_notify
= mt7601u_sta_notify
,
417 .set_key
= mt7601u_set_key
,
418 .conf_tx
= mt7601u_conf_tx
,
419 .sw_scan_start
= mt7601u_sw_scan
,
420 .sw_scan_complete
= mt7601u_sw_scan_complete
,
421 .ampdu_action
= mt76_ampdu_action
,
422 .sta_rate_tbl_update
= mt76_sta_rate_tbl_update
,
423 .set_rts_threshold
= mt7601u_set_rts_threshold
,