1 | /* |
2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
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 "htc.h" |
18 | |
19 | /*************/ |
20 | /* Utilities */ |
21 | /*************/ |
22 | |
23 | /* HACK Alert: Use 11NG for 2.4, use 11NA for 5 */ |
24 | static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, |
25 | struct ath9k_channel *ichan) |
26 | { |
27 | if (IS_CHAN_5GHZ(ichan)) |
28 | return HTC_MODE_11NA; |
29 | |
30 | return HTC_MODE_11NG; |
31 | } |
32 | |
33 | bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, |
34 | enum ath9k_power_mode mode) |
35 | { |
36 | bool ret; |
37 | |
38 | mutex_lock(&priv->htc_pm_lock); |
39 | ret = ath9k_hw_setpower(ah: priv->ah, mode); |
40 | mutex_unlock(lock: &priv->htc_pm_lock); |
41 | |
42 | return ret; |
43 | } |
44 | |
45 | void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv) |
46 | { |
47 | mutex_lock(&priv->htc_pm_lock); |
48 | if (++priv->ps_usecount != 1) |
49 | goto unlock; |
50 | ath9k_hw_setpower(ah: priv->ah, mode: ATH9K_PM_AWAKE); |
51 | |
52 | unlock: |
53 | mutex_unlock(lock: &priv->htc_pm_lock); |
54 | } |
55 | |
56 | void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv) |
57 | { |
58 | bool reset; |
59 | |
60 | mutex_lock(&priv->htc_pm_lock); |
61 | if (--priv->ps_usecount != 0) |
62 | goto unlock; |
63 | |
64 | if (priv->ps_idle) { |
65 | ath9k_hw_setrxabort(ah: priv->ah, set: true); |
66 | ath9k_hw_stopdmarecv(ah: priv->ah, reset: &reset); |
67 | ath9k_hw_setpower(ah: priv->ah, mode: ATH9K_PM_FULL_SLEEP); |
68 | } else if (priv->ps_enabled) { |
69 | ath9k_hw_setpower(ah: priv->ah, mode: ATH9K_PM_NETWORK_SLEEP); |
70 | } |
71 | |
72 | unlock: |
73 | mutex_unlock(lock: &priv->htc_pm_lock); |
74 | } |
75 | |
76 | void ath9k_ps_work(struct work_struct *work) |
77 | { |
78 | struct ath9k_htc_priv *priv = |
79 | container_of(work, struct ath9k_htc_priv, |
80 | ps_work); |
81 | ath9k_htc_setpower(priv, mode: ATH9K_PM_AWAKE); |
82 | |
83 | /* The chip wakes up after receiving the first beacon |
84 | while network sleep is enabled. For the driver to |
85 | be in sync with the hw, set the chip to awake and |
86 | only then set it to sleep. |
87 | */ |
88 | ath9k_htc_setpower(priv, mode: ATH9K_PM_NETWORK_SLEEP); |
89 | } |
90 | |
91 | static void ath9k_htc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) |
92 | { |
93 | struct ath9k_htc_priv *priv = data; |
94 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
95 | |
96 | if ((vif->type == NL80211_IFTYPE_AP || |
97 | vif->type == NL80211_IFTYPE_MESH_POINT) && |
98 | bss_conf->enable_beacon) { |
99 | priv->reconfig_beacon = true; |
100 | priv->rearm_ani = true; |
101 | } |
102 | |
103 | if (vif->cfg.assoc) { |
104 | priv->rearm_ani = true; |
105 | priv->reconfig_beacon = true; |
106 | } |
107 | } |
108 | |
109 | static void ath9k_htc_vif_reconfig(struct ath9k_htc_priv *priv) |
110 | { |
111 | priv->rearm_ani = false; |
112 | priv->reconfig_beacon = false; |
113 | |
114 | ieee80211_iterate_active_interfaces_atomic( |
115 | hw: priv->hw, iter_flags: IEEE80211_IFACE_ITER_RESUME_ALL, |
116 | iterator: ath9k_htc_vif_iter, data: priv); |
117 | if (priv->rearm_ani) |
118 | ath9k_htc_start_ani(priv); |
119 | |
120 | if (priv->reconfig_beacon) { |
121 | ath9k_htc_ps_wakeup(priv); |
122 | ath9k_htc_beacon_reconfig(priv); |
123 | ath9k_htc_ps_restore(priv); |
124 | } |
125 | } |
126 | |
127 | static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif) |
128 | { |
129 | struct ath9k_vif_iter_data *iter_data = data; |
130 | int i; |
131 | |
132 | if (iter_data->hw_macaddr != NULL) { |
133 | for (i = 0; i < ETH_ALEN; i++) |
134 | iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]); |
135 | } else { |
136 | iter_data->hw_macaddr = mac; |
137 | } |
138 | } |
139 | |
140 | static void ath9k_htc_set_mac_bssid_mask(struct ath9k_htc_priv *priv, |
141 | struct ieee80211_vif *vif) |
142 | { |
143 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
144 | struct ath9k_vif_iter_data iter_data; |
145 | |
146 | /* |
147 | * Pick the MAC address of the first interface as the new hardware |
148 | * MAC address. The hardware will use it together with the BSSID mask |
149 | * when matching addresses. |
150 | */ |
151 | iter_data.hw_macaddr = NULL; |
152 | eth_broadcast_addr(addr: iter_data.mask); |
153 | |
154 | if (vif) |
155 | ath9k_htc_bssid_iter(data: &iter_data, mac: vif->addr, vif); |
156 | |
157 | /* Get list of all active MAC addresses */ |
158 | ieee80211_iterate_active_interfaces_atomic( |
159 | hw: priv->hw, iter_flags: IEEE80211_IFACE_ITER_RESUME_ALL, |
160 | iterator: ath9k_htc_bssid_iter, data: &iter_data); |
161 | |
162 | memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); |
163 | |
164 | if (iter_data.hw_macaddr) |
165 | memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN); |
166 | |
167 | ath_hw_setbssidmask(common); |
168 | } |
169 | |
170 | static void ath9k_htc_set_opmode(struct ath9k_htc_priv *priv) |
171 | { |
172 | if (priv->num_ibss_vif) |
173 | priv->ah->opmode = NL80211_IFTYPE_ADHOC; |
174 | else if (priv->num_ap_vif) |
175 | priv->ah->opmode = NL80211_IFTYPE_AP; |
176 | else if (priv->num_mbss_vif) |
177 | priv->ah->opmode = NL80211_IFTYPE_MESH_POINT; |
178 | else |
179 | priv->ah->opmode = NL80211_IFTYPE_STATION; |
180 | |
181 | ath9k_hw_setopmode(ah: priv->ah); |
182 | } |
183 | |
184 | void ath9k_htc_reset(struct ath9k_htc_priv *priv) |
185 | { |
186 | struct ath_hw *ah = priv->ah; |
187 | struct ath_common *common = ath9k_hw_common(ah); |
188 | struct ieee80211_channel *channel = priv->hw->conf.chandef.chan; |
189 | struct ath9k_hw_cal_data *caldata = NULL; |
190 | enum htc_phymode mode; |
191 | __be16 htc_mode; |
192 | u8 cmd_rsp; |
193 | int ret; |
194 | |
195 | mutex_lock(&priv->mutex); |
196 | ath9k_htc_ps_wakeup(priv); |
197 | |
198 | ath9k_htc_stop_ani(priv); |
199 | ieee80211_stop_queues(hw: priv->hw); |
200 | |
201 | del_timer_sync(timer: &priv->tx.cleanup_timer); |
202 | ath9k_htc_tx_drain(priv); |
203 | |
204 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
205 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
206 | WMI_CMD(WMI_STOP_RECV_CMDID); |
207 | |
208 | ath9k_wmi_event_drain(priv); |
209 | |
210 | caldata = &priv->caldata; |
211 | ret = ath9k_hw_reset(ah, chan: ah->curchan, caldata, fastcc: false); |
212 | if (ret) { |
213 | ath_err(common, |
214 | "Unable to reset device (%u Mhz) reset status %d\n" , |
215 | channel->center_freq, ret); |
216 | } |
217 | |
218 | ath9k_cmn_update_txpow(ah, cur_txpow: priv->curtxpow, new_txpow: priv->txpowlimit, |
219 | txpower: &priv->curtxpow); |
220 | |
221 | WMI_CMD(WMI_START_RECV_CMDID); |
222 | ath9k_host_rx_init(priv); |
223 | |
224 | mode = ath9k_htc_get_curmode(priv, ichan: ah->curchan); |
225 | htc_mode = cpu_to_be16(mode); |
226 | WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); |
227 | |
228 | WMI_CMD(WMI_ENABLE_INTR_CMDID); |
229 | htc_start(target: priv->htc); |
230 | ath9k_htc_vif_reconfig(priv); |
231 | ieee80211_wake_queues(hw: priv->hw); |
232 | |
233 | mod_timer(timer: &priv->tx.cleanup_timer, |
234 | expires: jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); |
235 | |
236 | ath9k_htc_ps_restore(priv); |
237 | mutex_unlock(lock: &priv->mutex); |
238 | } |
239 | |
240 | static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, |
241 | struct ieee80211_hw *hw, |
242 | struct ath9k_channel *hchan) |
243 | { |
244 | struct ath_hw *ah = priv->ah; |
245 | struct ath_common *common = ath9k_hw_common(ah); |
246 | struct ieee80211_conf *conf = &common->hw->conf; |
247 | bool fastcc; |
248 | struct ieee80211_channel *channel = hw->conf.chandef.chan; |
249 | struct ath9k_hw_cal_data *caldata; |
250 | enum htc_phymode mode; |
251 | __be16 htc_mode; |
252 | u8 cmd_rsp; |
253 | int ret; |
254 | |
255 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) |
256 | return -EIO; |
257 | |
258 | fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); |
259 | |
260 | ath9k_htc_ps_wakeup(priv); |
261 | |
262 | ath9k_htc_stop_ani(priv); |
263 | del_timer_sync(timer: &priv->tx.cleanup_timer); |
264 | ath9k_htc_tx_drain(priv); |
265 | |
266 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
267 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
268 | WMI_CMD(WMI_STOP_RECV_CMDID); |
269 | |
270 | ath9k_wmi_event_drain(priv); |
271 | |
272 | ath_dbg(common, CONFIG, |
273 | "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n" , |
274 | priv->ah->curchan->channel, |
275 | channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf), |
276 | fastcc); |
277 | caldata = fastcc ? NULL : &priv->caldata; |
278 | ret = ath9k_hw_reset(ah, chan: hchan, caldata, fastcc); |
279 | if (ret) { |
280 | ath_err(common, |
281 | "Unable to reset channel (%u Mhz) reset status %d\n" , |
282 | channel->center_freq, ret); |
283 | goto err; |
284 | } |
285 | |
286 | ath9k_cmn_update_txpow(ah, cur_txpow: priv->curtxpow, new_txpow: priv->txpowlimit, |
287 | txpower: &priv->curtxpow); |
288 | |
289 | WMI_CMD(WMI_START_RECV_CMDID); |
290 | if (ret) |
291 | goto err; |
292 | |
293 | ath9k_host_rx_init(priv); |
294 | |
295 | mode = ath9k_htc_get_curmode(priv, ichan: hchan); |
296 | htc_mode = cpu_to_be16(mode); |
297 | WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); |
298 | if (ret) |
299 | goto err; |
300 | |
301 | WMI_CMD(WMI_ENABLE_INTR_CMDID); |
302 | if (ret) |
303 | goto err; |
304 | |
305 | htc_start(target: priv->htc); |
306 | |
307 | if (!test_bit(ATH_OP_SCANNING, &common->op_flags) && |
308 | !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) |
309 | ath9k_htc_vif_reconfig(priv); |
310 | |
311 | mod_timer(timer: &priv->tx.cleanup_timer, |
312 | expires: jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); |
313 | |
314 | /* perform spectral scan if requested. */ |
315 | if (test_bit(ATH_OP_SCANNING, &common->op_flags) && |
316 | priv->spec_priv.spectral_mode == SPECTRAL_CHANSCAN) |
317 | ath9k_cmn_spectral_scan_trigger(common, spec_priv: &priv->spec_priv); |
318 | err: |
319 | ath9k_htc_ps_restore(priv); |
320 | return ret; |
321 | } |
322 | |
323 | /* |
324 | * Monitor mode handling is a tad complicated because the firmware requires |
325 | * an interface to be created exclusively, while mac80211 doesn't associate |
326 | * an interface with the mode. |
327 | * |
328 | * So, for now, only one monitor interface can be configured. |
329 | */ |
330 | static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) |
331 | { |
332 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
333 | struct ath9k_htc_target_vif hvif; |
334 | int ret = 0; |
335 | u8 cmd_rsp; |
336 | |
337 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); |
338 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); |
339 | hvif.index = priv->mon_vif_idx; |
340 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); |
341 | if (ret) { |
342 | ath_err(common, "Unable to remove monitor interface at idx: %d\n" , |
343 | priv->mon_vif_idx); |
344 | } |
345 | |
346 | priv->nvifs--; |
347 | priv->vif_slot &= ~(1 << priv->mon_vif_idx); |
348 | } |
349 | |
350 | static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) |
351 | { |
352 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
353 | struct ath9k_htc_target_vif hvif; |
354 | struct ath9k_htc_target_sta tsta; |
355 | int ret = 0, sta_idx; |
356 | u8 cmd_rsp; |
357 | |
358 | if ((priv->nvifs >= ATH9K_HTC_MAX_VIF) || |
359 | (priv->nstations >= ATH9K_HTC_MAX_STA)) { |
360 | ret = -ENOBUFS; |
361 | goto err_vif; |
362 | } |
363 | |
364 | sta_idx = ffz(priv->sta_slot); |
365 | if ((sta_idx < 0) || (sta_idx > ATH9K_HTC_MAX_STA)) { |
366 | ret = -ENOBUFS; |
367 | goto err_vif; |
368 | } |
369 | |
370 | /* |
371 | * Add an interface. |
372 | */ |
373 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); |
374 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); |
375 | |
376 | hvif.opmode = HTC_M_MONITOR; |
377 | hvif.index = ffz(priv->vif_slot); |
378 | |
379 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); |
380 | if (ret) |
381 | goto err_vif; |
382 | |
383 | /* |
384 | * Assign the monitor interface index as a special case here. |
385 | * This is needed when the interface is brought down. |
386 | */ |
387 | priv->mon_vif_idx = hvif.index; |
388 | priv->vif_slot |= (1 << hvif.index); |
389 | |
390 | /* |
391 | * Set the hardware mode to monitor only if there are no |
392 | * other interfaces. |
393 | */ |
394 | if (!priv->nvifs) |
395 | priv->ah->opmode = NL80211_IFTYPE_MONITOR; |
396 | |
397 | priv->nvifs++; |
398 | |
399 | /* |
400 | * Associate a station with the interface for packet injection. |
401 | */ |
402 | memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta)); |
403 | |
404 | memcpy(&tsta.macaddr, common->macaddr, ETH_ALEN); |
405 | |
406 | tsta.is_vif_sta = 1; |
407 | tsta.sta_index = sta_idx; |
408 | tsta.vif_index = hvif.index; |
409 | tsta.maxampdu = cpu_to_be16(0xffff); |
410 | |
411 | WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); |
412 | if (ret) { |
413 | ath_err(common, "Unable to add station entry for monitor mode\n" ); |
414 | goto err_sta; |
415 | } |
416 | |
417 | priv->sta_slot |= (1 << sta_idx); |
418 | priv->nstations++; |
419 | priv->vif_sta_pos[priv->mon_vif_idx] = sta_idx; |
420 | priv->ah->is_monitoring = true; |
421 | |
422 | ath_dbg(common, CONFIG, |
423 | "Attached a monitor interface at idx: %d, sta idx: %d\n" , |
424 | priv->mon_vif_idx, sta_idx); |
425 | |
426 | return 0; |
427 | |
428 | err_sta: |
429 | /* |
430 | * Remove the interface from the target. |
431 | */ |
432 | __ath9k_htc_remove_monitor_interface(priv); |
433 | err_vif: |
434 | ath_dbg(common, FATAL, "Unable to attach a monitor interface\n" ); |
435 | |
436 | return ret; |
437 | } |
438 | |
439 | static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) |
440 | { |
441 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
442 | int ret = 0; |
443 | u8 cmd_rsp, sta_idx; |
444 | |
445 | __ath9k_htc_remove_monitor_interface(priv); |
446 | |
447 | sta_idx = priv->vif_sta_pos[priv->mon_vif_idx]; |
448 | |
449 | WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); |
450 | if (ret) { |
451 | ath_err(common, "Unable to remove station entry for monitor mode\n" ); |
452 | return ret; |
453 | } |
454 | |
455 | priv->sta_slot &= ~(1 << sta_idx); |
456 | priv->nstations--; |
457 | priv->ah->is_monitoring = false; |
458 | |
459 | ath_dbg(common, CONFIG, |
460 | "Removed a monitor interface at idx: %d, sta idx: %d\n" , |
461 | priv->mon_vif_idx, sta_idx); |
462 | |
463 | return 0; |
464 | } |
465 | |
466 | static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, |
467 | struct ieee80211_vif *vif, |
468 | struct ieee80211_sta *sta) |
469 | { |
470 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
471 | struct ath9k_htc_target_sta tsta; |
472 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; |
473 | struct ath9k_htc_sta *ista; |
474 | int ret, sta_idx; |
475 | u8 cmd_rsp; |
476 | u16 maxampdu; |
477 | |
478 | if (priv->nstations >= ATH9K_HTC_MAX_STA) |
479 | return -ENOBUFS; |
480 | |
481 | sta_idx = ffz(priv->sta_slot); |
482 | if ((sta_idx < 0) || (sta_idx > ATH9K_HTC_MAX_STA)) |
483 | return -ENOBUFS; |
484 | |
485 | memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta)); |
486 | |
487 | if (sta) { |
488 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
489 | memcpy(&tsta.macaddr, sta->addr, ETH_ALEN); |
490 | memcpy(&tsta.bssid, common->curbssid, ETH_ALEN); |
491 | ista->index = sta_idx; |
492 | tsta.is_vif_sta = 0; |
493 | maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + |
494 | sta->deflink.ht_cap.ampdu_factor); |
495 | tsta.maxampdu = cpu_to_be16(maxampdu); |
496 | } else { |
497 | memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); |
498 | tsta.is_vif_sta = 1; |
499 | tsta.maxampdu = cpu_to_be16(0xffff); |
500 | } |
501 | |
502 | tsta.sta_index = sta_idx; |
503 | tsta.vif_index = avp->index; |
504 | |
505 | WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); |
506 | if (ret) { |
507 | if (sta) |
508 | ath_err(common, |
509 | "Unable to add station entry for: %pM\n" , |
510 | sta->addr); |
511 | return ret; |
512 | } |
513 | |
514 | if (sta) { |
515 | ath_dbg(common, CONFIG, |
516 | "Added a station entry for: %pM (idx: %d)\n" , |
517 | sta->addr, tsta.sta_index); |
518 | } else { |
519 | ath_dbg(common, CONFIG, |
520 | "Added a station entry for VIF %d (idx: %d)\n" , |
521 | avp->index, tsta.sta_index); |
522 | } |
523 | |
524 | priv->sta_slot |= (1 << sta_idx); |
525 | priv->nstations++; |
526 | if (!sta) |
527 | priv->vif_sta_pos[avp->index] = sta_idx; |
528 | |
529 | return 0; |
530 | } |
531 | |
532 | static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv, |
533 | struct ieee80211_vif *vif, |
534 | struct ieee80211_sta *sta) |
535 | { |
536 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
537 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; |
538 | struct ath9k_htc_sta *ista; |
539 | int ret; |
540 | u8 cmd_rsp, sta_idx; |
541 | |
542 | if (sta) { |
543 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
544 | sta_idx = ista->index; |
545 | } else { |
546 | sta_idx = priv->vif_sta_pos[avp->index]; |
547 | } |
548 | |
549 | WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); |
550 | if (ret) { |
551 | if (sta) |
552 | ath_err(common, |
553 | "Unable to remove station entry for: %pM\n" , |
554 | sta->addr); |
555 | return ret; |
556 | } |
557 | |
558 | if (sta) { |
559 | ath_dbg(common, CONFIG, |
560 | "Removed a station entry for: %pM (idx: %d)\n" , |
561 | sta->addr, sta_idx); |
562 | } else { |
563 | ath_dbg(common, CONFIG, |
564 | "Removed a station entry for VIF %d (idx: %d)\n" , |
565 | avp->index, sta_idx); |
566 | } |
567 | |
568 | priv->sta_slot &= ~(1 << sta_idx); |
569 | priv->nstations--; |
570 | |
571 | return 0; |
572 | } |
573 | |
574 | int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, |
575 | u8 enable_coex) |
576 | { |
577 | struct ath9k_htc_cap_target tcap; |
578 | int ret; |
579 | u8 cmd_rsp; |
580 | |
581 | memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target)); |
582 | |
583 | tcap.ampdu_limit = cpu_to_be32(0xffff); |
584 | tcap.ampdu_subframes = 0xff; |
585 | tcap.enable_coex = enable_coex; |
586 | tcap.tx_chainmask = priv->ah->caps.tx_chainmask; |
587 | |
588 | WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap); |
589 | |
590 | return ret; |
591 | } |
592 | |
593 | static void ath9k_htc_setup_rate(struct ath9k_htc_priv *priv, |
594 | struct ieee80211_sta *sta, |
595 | struct ath9k_htc_target_rate *trate) |
596 | { |
597 | struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; |
598 | struct ieee80211_supported_band *sband; |
599 | u32 caps = 0; |
600 | int i, j; |
601 | |
602 | sband = priv->hw->wiphy->bands[priv->hw->conf.chandef.chan->band]; |
603 | |
604 | for (i = 0, j = 0; i < sband->n_bitrates; i++) { |
605 | if (sta->deflink.supp_rates[sband->band] & BIT(i)) { |
606 | trate->rates.legacy_rates.rs_rates[j] |
607 | = (sband->bitrates[i].bitrate * 2) / 10; |
608 | j++; |
609 | } |
610 | } |
611 | trate->rates.legacy_rates.rs_nrates = j; |
612 | |
613 | if (sta->deflink.ht_cap.ht_supported) { |
614 | for (i = 0, j = 0; i < 77; i++) { |
615 | if (sta->deflink.ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) |
616 | trate->rates.ht_rates.rs_rates[j++] = i; |
617 | if (j == ATH_HTC_RATE_MAX) |
618 | break; |
619 | } |
620 | trate->rates.ht_rates.rs_nrates = j; |
621 | |
622 | caps = WLAN_RC_HT_FLAG; |
623 | if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) |
624 | caps |= ATH_RC_TX_STBC_FLAG; |
625 | if (sta->deflink.ht_cap.mcs.rx_mask[1]) |
626 | caps |= WLAN_RC_DS_FLAG; |
627 | if ((sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && |
628 | (conf_is_ht40(conf: &priv->hw->conf))) |
629 | caps |= WLAN_RC_40_FLAG; |
630 | if (conf_is_ht40(conf: &priv->hw->conf) && |
631 | (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40)) |
632 | caps |= WLAN_RC_SGI_FLAG; |
633 | else if (conf_is_ht20(conf: &priv->hw->conf) && |
634 | (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20)) |
635 | caps |= WLAN_RC_SGI_FLAG; |
636 | } |
637 | |
638 | trate->sta_index = ista->index; |
639 | trate->isnew = 1; |
640 | trate->capflags = cpu_to_be32(caps); |
641 | } |
642 | |
643 | static int ath9k_htc_send_rate_cmd(struct ath9k_htc_priv *priv, |
644 | struct ath9k_htc_target_rate *trate) |
645 | { |
646 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
647 | int ret; |
648 | u8 cmd_rsp; |
649 | |
650 | WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, trate); |
651 | if (ret) { |
652 | ath_err(common, |
653 | "Unable to initialize Rate information on target\n" ); |
654 | } |
655 | |
656 | return ret; |
657 | } |
658 | |
659 | static void ath9k_htc_init_rate(struct ath9k_htc_priv *priv, |
660 | struct ieee80211_sta *sta) |
661 | { |
662 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
663 | struct ath9k_htc_target_rate trate; |
664 | int ret; |
665 | |
666 | memset(&trate, 0, sizeof(struct ath9k_htc_target_rate)); |
667 | ath9k_htc_setup_rate(priv, sta, trate: &trate); |
668 | ret = ath9k_htc_send_rate_cmd(priv, trate: &trate); |
669 | if (!ret) |
670 | ath_dbg(common, CONFIG, |
671 | "Updated target sta: %pM, rate caps: 0x%X\n" , |
672 | sta->addr, be32_to_cpu(trate.capflags)); |
673 | } |
674 | |
675 | static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv, |
676 | struct ieee80211_vif *vif, |
677 | struct ieee80211_bss_conf *bss_conf) |
678 | { |
679 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
680 | struct ath9k_htc_target_rate trate; |
681 | struct ieee80211_sta *sta; |
682 | int ret; |
683 | |
684 | memset(&trate, 0, sizeof(struct ath9k_htc_target_rate)); |
685 | |
686 | rcu_read_lock(); |
687 | sta = ieee80211_find_sta(vif, addr: bss_conf->bssid); |
688 | if (!sta) { |
689 | rcu_read_unlock(); |
690 | return; |
691 | } |
692 | ath9k_htc_setup_rate(priv, sta, trate: &trate); |
693 | rcu_read_unlock(); |
694 | |
695 | ret = ath9k_htc_send_rate_cmd(priv, trate: &trate); |
696 | if (!ret) |
697 | ath_dbg(common, CONFIG, |
698 | "Updated target sta: %pM, rate caps: 0x%X\n" , |
699 | bss_conf->bssid, be32_to_cpu(trate.capflags)); |
700 | } |
701 | |
702 | static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, |
703 | struct ieee80211_vif *vif, |
704 | struct ieee80211_sta *sta, |
705 | enum ieee80211_ampdu_mlme_action action, |
706 | u16 tid) |
707 | { |
708 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
709 | struct ath9k_htc_target_aggr aggr; |
710 | struct ath9k_htc_sta *ista; |
711 | int ret = 0; |
712 | u8 cmd_rsp; |
713 | |
714 | if (tid >= ATH9K_HTC_MAX_TID) |
715 | return -EINVAL; |
716 | |
717 | memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); |
718 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
719 | |
720 | aggr.sta_index = ista->index; |
721 | aggr.tidno = tid & 0xf; |
722 | aggr.aggr_enable = action == IEEE80211_AMPDU_TX_START; |
723 | |
724 | WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); |
725 | if (ret) |
726 | ath_dbg(common, CONFIG, |
727 | "Unable to %s TX aggregation for (%pM, %d)\n" , |
728 | (aggr.aggr_enable) ? "start" : "stop" , sta->addr, tid); |
729 | else |
730 | ath_dbg(common, CONFIG, |
731 | "%s TX aggregation for (%pM, %d)\n" , |
732 | (aggr.aggr_enable) ? "Starting" : "Stopping" , |
733 | sta->addr, tid); |
734 | |
735 | spin_lock_bh(lock: &priv->tx.tx_lock); |
736 | ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP; |
737 | spin_unlock_bh(lock: &priv->tx.tx_lock); |
738 | |
739 | return ret; |
740 | } |
741 | |
742 | /*******/ |
743 | /* ANI */ |
744 | /*******/ |
745 | |
746 | void ath9k_htc_start_ani(struct ath9k_htc_priv *priv) |
747 | { |
748 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
749 | unsigned long timestamp = jiffies_to_msecs(j: jiffies); |
750 | |
751 | common->ani.longcal_timer = timestamp; |
752 | common->ani.shortcal_timer = timestamp; |
753 | common->ani.checkani_timer = timestamp; |
754 | |
755 | set_bit(nr: ATH_OP_ANI_RUN, addr: &common->op_flags); |
756 | |
757 | ieee80211_queue_delayed_work(hw: common->hw, dwork: &priv->ani_work, |
758 | delay: msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); |
759 | } |
760 | |
761 | void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv) |
762 | { |
763 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
764 | cancel_delayed_work_sync(dwork: &priv->ani_work); |
765 | clear_bit(nr: ATH_OP_ANI_RUN, addr: &common->op_flags); |
766 | } |
767 | |
768 | void ath9k_htc_ani_work(struct work_struct *work) |
769 | { |
770 | struct ath9k_htc_priv *priv = |
771 | container_of(work, struct ath9k_htc_priv, ani_work.work); |
772 | struct ath_hw *ah = priv->ah; |
773 | struct ath_common *common = ath9k_hw_common(ah); |
774 | bool longcal = false; |
775 | bool shortcal = false; |
776 | bool aniflag = false; |
777 | unsigned int timestamp = jiffies_to_msecs(j: jiffies); |
778 | u32 cal_interval, short_cal_interval; |
779 | |
780 | short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? |
781 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; |
782 | |
783 | /* Only calibrate if awake */ |
784 | if (ah->power_mode != ATH9K_PM_AWAKE) |
785 | goto set_timer; |
786 | |
787 | /* Long calibration runs independently of short calibration. */ |
788 | if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { |
789 | longcal = true; |
790 | ath_dbg(common, ANI, "longcal @%lu\n" , jiffies); |
791 | common->ani.longcal_timer = timestamp; |
792 | } |
793 | |
794 | /* |
795 | * Short calibration applies only while caldone |
796 | * is false or -ETIMEDOUT |
797 | */ |
798 | if (common->ani.caldone <= 0) { |
799 | if ((timestamp - common->ani.shortcal_timer) >= |
800 | short_cal_interval) { |
801 | shortcal = true; |
802 | ath_dbg(common, ANI, "shortcal @%lu\n" , jiffies); |
803 | common->ani.shortcal_timer = timestamp; |
804 | common->ani.resetcal_timer = timestamp; |
805 | } |
806 | } else { |
807 | if ((timestamp - common->ani.resetcal_timer) >= |
808 | ATH_RESTART_CALINTERVAL) { |
809 | common->ani.caldone = ath9k_hw_reset_calvalid(ah); |
810 | if (common->ani.caldone) |
811 | common->ani.resetcal_timer = timestamp; |
812 | } |
813 | } |
814 | |
815 | /* Verify whether we must check ANI */ |
816 | if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { |
817 | aniflag = true; |
818 | common->ani.checkani_timer = timestamp; |
819 | } |
820 | |
821 | /* Skip all processing if there's nothing to do. */ |
822 | if (longcal || shortcal || aniflag) { |
823 | |
824 | ath9k_htc_ps_wakeup(priv); |
825 | |
826 | /* Call ANI routine if necessary */ |
827 | if (aniflag) |
828 | ath9k_hw_ani_monitor(ah, chan: ah->curchan); |
829 | |
830 | /* Perform calibration if necessary */ |
831 | if (longcal || shortcal) |
832 | common->ani.caldone = |
833 | ath9k_hw_calibrate(ah, chan: ah->curchan, |
834 | rxchainmask: ah->rxchainmask, longcal) > 0; |
835 | |
836 | ath9k_htc_ps_restore(priv); |
837 | } |
838 | |
839 | set_timer: |
840 | /* |
841 | * Set timer interval based on previous results. |
842 | * The interval must be the shortest necessary to satisfy ANI, |
843 | * short calibration and long calibration. |
844 | */ |
845 | cal_interval = ATH_LONG_CALINTERVAL; |
846 | cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); |
847 | /* |
848 | * Short calibration applies only while caldone |
849 | * is false or -ETIMEDOUT |
850 | */ |
851 | if (common->ani.caldone <= 0) |
852 | cal_interval = min(cal_interval, (u32)short_cal_interval); |
853 | |
854 | ieee80211_queue_delayed_work(hw: common->hw, dwork: &priv->ani_work, |
855 | delay: msecs_to_jiffies(m: cal_interval)); |
856 | } |
857 | |
858 | /**********************/ |
859 | /* mac80211 Callbacks */ |
860 | /**********************/ |
861 | |
862 | static void ath9k_htc_tx(struct ieee80211_hw *hw, |
863 | struct ieee80211_tx_control *control, |
864 | struct sk_buff *skb) |
865 | { |
866 | struct ieee80211_hdr *hdr; |
867 | struct ath9k_htc_priv *priv = hw->priv; |
868 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
869 | int padpos, padsize, ret, slot; |
870 | |
871 | hdr = (struct ieee80211_hdr *) skb->data; |
872 | |
873 | /* Add the padding after the header if this is not already done */ |
874 | padpos = ieee80211_hdrlen(fc: hdr->frame_control); |
875 | padsize = padpos & 3; |
876 | if (padsize && skb->len > padpos) { |
877 | if (skb_headroom(skb) < padsize) { |
878 | ath_dbg(common, XMIT, "No room for padding\n" ); |
879 | goto fail_tx; |
880 | } |
881 | skb_push(skb, len: padsize); |
882 | memmove(skb->data, skb->data + padsize, padpos); |
883 | } |
884 | |
885 | slot = ath9k_htc_tx_get_slot(priv); |
886 | if (slot < 0) { |
887 | ath_dbg(common, XMIT, "No free TX slot\n" ); |
888 | goto fail_tx; |
889 | } |
890 | |
891 | ret = ath9k_htc_tx_start(priv, sta: control->sta, skb, slot, is_cab: false); |
892 | if (ret != 0) { |
893 | ath_dbg(common, XMIT, "Tx failed\n" ); |
894 | goto clear_slot; |
895 | } |
896 | |
897 | ath9k_htc_check_stop_queues(priv); |
898 | |
899 | return; |
900 | |
901 | clear_slot: |
902 | ath9k_htc_tx_clear_slot(priv, slot); |
903 | fail_tx: |
904 | dev_kfree_skb_any(skb); |
905 | } |
906 | |
907 | static int ath9k_htc_start(struct ieee80211_hw *hw) |
908 | { |
909 | struct ath9k_htc_priv *priv = hw->priv; |
910 | struct ath_hw *ah = priv->ah; |
911 | struct ath_common *common = ath9k_hw_common(ah); |
912 | struct ieee80211_channel *curchan = hw->conf.chandef.chan; |
913 | struct ath9k_channel *init_channel; |
914 | int ret = 0; |
915 | enum htc_phymode mode; |
916 | __be16 htc_mode; |
917 | u8 cmd_rsp; |
918 | |
919 | mutex_lock(&priv->mutex); |
920 | |
921 | ath_dbg(common, CONFIG, |
922 | "Starting driver with initial channel: %d MHz\n" , |
923 | curchan->center_freq); |
924 | |
925 | /* Ensure that HW is awake before flushing RX */ |
926 | ath9k_htc_setpower(priv, mode: ATH9K_PM_AWAKE); |
927 | WMI_CMD(WMI_FLUSH_RECV_CMDID); |
928 | |
929 | /* setup initial channel */ |
930 | init_channel = ath9k_cmn_get_channel(hw, ah, chandef: &hw->conf.chandef); |
931 | |
932 | ret = ath9k_hw_reset(ah, chan: init_channel, caldata: ah->caldata, fastcc: false); |
933 | if (ret) { |
934 | ath_err(common, |
935 | "Unable to reset hardware; reset status %d (freq %u MHz)\n" , |
936 | ret, curchan->center_freq); |
937 | mutex_unlock(lock: &priv->mutex); |
938 | return ret; |
939 | } |
940 | |
941 | ath9k_cmn_update_txpow(ah, cur_txpow: priv->curtxpow, new_txpow: priv->txpowlimit, |
942 | txpower: &priv->curtxpow); |
943 | |
944 | mode = ath9k_htc_get_curmode(priv, ichan: init_channel); |
945 | htc_mode = cpu_to_be16(mode); |
946 | WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); |
947 | WMI_CMD(WMI_ATH_INIT_CMDID); |
948 | WMI_CMD(WMI_START_RECV_CMDID); |
949 | |
950 | ath9k_host_rx_init(priv); |
951 | |
952 | ret = ath9k_htc_update_cap_target(priv, enable_coex: 0); |
953 | if (ret) |
954 | ath_dbg(common, CONFIG, |
955 | "Failed to update capability in target\n" ); |
956 | |
957 | clear_bit(nr: ATH_OP_INVALID, addr: &common->op_flags); |
958 | htc_start(target: priv->htc); |
959 | |
960 | spin_lock_bh(lock: &priv->tx.tx_lock); |
961 | priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; |
962 | spin_unlock_bh(lock: &priv->tx.tx_lock); |
963 | |
964 | ieee80211_wake_queues(hw); |
965 | |
966 | mod_timer(timer: &priv->tx.cleanup_timer, |
967 | expires: jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); |
968 | |
969 | ath9k_htc_start_btcoex(priv); |
970 | |
971 | mutex_unlock(lock: &priv->mutex); |
972 | |
973 | return ret; |
974 | } |
975 | |
976 | static void ath9k_htc_stop(struct ieee80211_hw *hw) |
977 | { |
978 | struct ath9k_htc_priv *priv = hw->priv; |
979 | struct ath_hw *ah = priv->ah; |
980 | struct ath_common *common = ath9k_hw_common(ah); |
981 | int ret __attribute__ ((unused)); |
982 | u8 cmd_rsp; |
983 | |
984 | mutex_lock(&priv->mutex); |
985 | |
986 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) { |
987 | ath_dbg(common, ANY, "Device not present\n" ); |
988 | mutex_unlock(lock: &priv->mutex); |
989 | return; |
990 | } |
991 | |
992 | ath9k_htc_ps_wakeup(priv); |
993 | |
994 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
995 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
996 | WMI_CMD(WMI_STOP_RECV_CMDID); |
997 | |
998 | tasklet_kill(t: &priv->rx_tasklet); |
999 | |
1000 | del_timer_sync(timer: &priv->tx.cleanup_timer); |
1001 | ath9k_htc_tx_drain(priv); |
1002 | ath9k_wmi_event_drain(priv); |
1003 | |
1004 | mutex_unlock(lock: &priv->mutex); |
1005 | |
1006 | /* Cancel all the running timers/work .. */ |
1007 | cancel_work_sync(work: &priv->fatal_work); |
1008 | cancel_work_sync(work: &priv->ps_work); |
1009 | |
1010 | #ifdef CONFIG_MAC80211_LEDS |
1011 | cancel_work_sync(work: &priv->led_work); |
1012 | #endif |
1013 | ath9k_htc_stop_ani(priv); |
1014 | |
1015 | mutex_lock(&priv->mutex); |
1016 | |
1017 | ath9k_htc_stop_btcoex(priv); |
1018 | |
1019 | /* Remove a monitor interface if it's present. */ |
1020 | if (priv->ah->is_monitoring) |
1021 | ath9k_htc_remove_monitor_interface(priv); |
1022 | |
1023 | ath9k_hw_phy_disable(ah); |
1024 | ath9k_hw_disable(ah); |
1025 | ath9k_htc_ps_restore(priv); |
1026 | ath9k_htc_setpower(priv, mode: ATH9K_PM_FULL_SLEEP); |
1027 | |
1028 | set_bit(nr: ATH_OP_INVALID, addr: &common->op_flags); |
1029 | |
1030 | ath_dbg(common, CONFIG, "Driver halt\n" ); |
1031 | mutex_unlock(lock: &priv->mutex); |
1032 | } |
1033 | |
1034 | static int ath9k_htc_add_interface(struct ieee80211_hw *hw, |
1035 | struct ieee80211_vif *vif) |
1036 | { |
1037 | struct ath9k_htc_priv *priv = hw->priv; |
1038 | struct ath9k_htc_vif *avp = (void *)vif->drv_priv; |
1039 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
1040 | struct ath9k_htc_target_vif hvif; |
1041 | int ret = 0; |
1042 | u8 cmd_rsp; |
1043 | |
1044 | mutex_lock(&priv->mutex); |
1045 | |
1046 | ath9k_htc_ps_wakeup(priv); |
1047 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); |
1048 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); |
1049 | |
1050 | switch (vif->type) { |
1051 | case NL80211_IFTYPE_STATION: |
1052 | hvif.opmode = HTC_M_STA; |
1053 | break; |
1054 | case NL80211_IFTYPE_ADHOC: |
1055 | hvif.opmode = HTC_M_IBSS; |
1056 | break; |
1057 | case NL80211_IFTYPE_AP: |
1058 | hvif.opmode = HTC_M_HOSTAP; |
1059 | break; |
1060 | case NL80211_IFTYPE_MESH_POINT: |
1061 | hvif.opmode = HTC_M_WDS; /* close enough */ |
1062 | break; |
1063 | default: |
1064 | ath_err(common, |
1065 | "Interface type %d not yet supported\n" , vif->type); |
1066 | ret = -EOPNOTSUPP; |
1067 | goto out; |
1068 | } |
1069 | |
1070 | /* Index starts from zero on the target */ |
1071 | avp->index = hvif.index = ffz(priv->vif_slot); |
1072 | hvif.rtsthreshold = cpu_to_be16(2304); |
1073 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); |
1074 | if (ret) |
1075 | goto out; |
1076 | |
1077 | /* |
1078 | * We need a node in target to tx mgmt frames |
1079 | * before association. |
1080 | */ |
1081 | ret = ath9k_htc_add_station(priv, vif, NULL); |
1082 | if (ret) { |
1083 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); |
1084 | goto out; |
1085 | } |
1086 | |
1087 | ath9k_htc_set_mac_bssid_mask(priv, vif); |
1088 | |
1089 | priv->vif_slot |= (1 << avp->index); |
1090 | priv->nvifs++; |
1091 | |
1092 | INC_VIF(priv, vif->type); |
1093 | |
1094 | if ((vif->type == NL80211_IFTYPE_AP) || |
1095 | (vif->type == NL80211_IFTYPE_MESH_POINT) || |
1096 | (vif->type == NL80211_IFTYPE_ADHOC)) |
1097 | ath9k_htc_assign_bslot(priv, vif); |
1098 | |
1099 | ath9k_htc_set_opmode(priv); |
1100 | |
1101 | if ((priv->ah->opmode == NL80211_IFTYPE_AP) && |
1102 | !test_bit(ATH_OP_ANI_RUN, &common->op_flags)) { |
1103 | ath9k_hw_set_tsfadjust(ah: priv->ah, set: true); |
1104 | ath9k_htc_start_ani(priv); |
1105 | } |
1106 | |
1107 | ath_dbg(common, CONFIG, "Attach a VIF of type: %d at idx: %d\n" , |
1108 | vif->type, avp->index); |
1109 | |
1110 | out: |
1111 | ath9k_htc_ps_restore(priv); |
1112 | mutex_unlock(lock: &priv->mutex); |
1113 | |
1114 | return ret; |
1115 | } |
1116 | |
1117 | static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, |
1118 | struct ieee80211_vif *vif) |
1119 | { |
1120 | struct ath9k_htc_priv *priv = hw->priv; |
1121 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
1122 | struct ath9k_htc_vif *avp = (void *)vif->drv_priv; |
1123 | struct ath9k_htc_target_vif hvif; |
1124 | int ret = 0; |
1125 | u8 cmd_rsp; |
1126 | |
1127 | mutex_lock(&priv->mutex); |
1128 | ath9k_htc_ps_wakeup(priv); |
1129 | |
1130 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); |
1131 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); |
1132 | hvif.index = avp->index; |
1133 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); |
1134 | if (ret) { |
1135 | ath_err(common, "Unable to remove interface at idx: %d\n" , |
1136 | avp->index); |
1137 | } |
1138 | priv->nvifs--; |
1139 | priv->vif_slot &= ~(1 << avp->index); |
1140 | |
1141 | if (priv->csa_vif == vif) |
1142 | priv->csa_vif = NULL; |
1143 | |
1144 | ath9k_htc_remove_station(priv, vif, NULL); |
1145 | |
1146 | DEC_VIF(priv, vif->type); |
1147 | |
1148 | if ((vif->type == NL80211_IFTYPE_AP) || |
1149 | vif->type == NL80211_IFTYPE_MESH_POINT || |
1150 | (vif->type == NL80211_IFTYPE_ADHOC)) |
1151 | ath9k_htc_remove_bslot(priv, vif); |
1152 | |
1153 | ath9k_htc_set_opmode(priv); |
1154 | |
1155 | ath9k_htc_set_mac_bssid_mask(priv, vif); |
1156 | |
1157 | /* |
1158 | * Stop ANI only if there are no associated station interfaces. |
1159 | */ |
1160 | if ((vif->type == NL80211_IFTYPE_AP) && (priv->num_ap_vif == 0)) { |
1161 | priv->rearm_ani = false; |
1162 | ieee80211_iterate_active_interfaces_atomic( |
1163 | hw: priv->hw, iter_flags: IEEE80211_IFACE_ITER_RESUME_ALL, |
1164 | iterator: ath9k_htc_vif_iter, data: priv); |
1165 | if (!priv->rearm_ani) |
1166 | ath9k_htc_stop_ani(priv); |
1167 | } |
1168 | |
1169 | ath_dbg(common, CONFIG, "Detach Interface at idx: %d\n" , avp->index); |
1170 | |
1171 | ath9k_htc_ps_restore(priv); |
1172 | mutex_unlock(lock: &priv->mutex); |
1173 | } |
1174 | |
1175 | static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) |
1176 | { |
1177 | struct ath9k_htc_priv *priv = hw->priv; |
1178 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
1179 | struct ieee80211_conf *conf = &hw->conf; |
1180 | bool chip_reset = false; |
1181 | int ret = 0; |
1182 | |
1183 | mutex_lock(&priv->mutex); |
1184 | ath9k_htc_ps_wakeup(priv); |
1185 | |
1186 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1187 | mutex_lock(&priv->htc_pm_lock); |
1188 | |
1189 | priv->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); |
1190 | if (!priv->ps_idle) |
1191 | chip_reset = true; |
1192 | |
1193 | mutex_unlock(lock: &priv->htc_pm_lock); |
1194 | } |
1195 | |
1196 | /* |
1197 | * Monitor interface should be added before |
1198 | * IEEE80211_CONF_CHANGE_CHANNEL is handled. |
1199 | */ |
1200 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { |
1201 | if ((conf->flags & IEEE80211_CONF_MONITOR) && |
1202 | !priv->ah->is_monitoring) |
1203 | ath9k_htc_add_monitor_interface(priv); |
1204 | else if (priv->ah->is_monitoring) |
1205 | ath9k_htc_remove_monitor_interface(priv); |
1206 | } |
1207 | |
1208 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || chip_reset) { |
1209 | struct ieee80211_channel *curchan = hw->conf.chandef.chan; |
1210 | int pos = curchan->hw_value; |
1211 | |
1212 | ath_dbg(common, CONFIG, "Set channel: %d MHz\n" , |
1213 | curchan->center_freq); |
1214 | |
1215 | ath9k_cmn_get_channel(hw, ah: priv->ah, chandef: &hw->conf.chandef); |
1216 | if (ath9k_htc_set_channel(priv, hw, hchan: &priv->ah->channels[pos]) < 0) { |
1217 | ath_err(common, "Unable to set channel\n" ); |
1218 | ret = -EINVAL; |
1219 | goto out; |
1220 | } |
1221 | |
1222 | } |
1223 | |
1224 | if (changed & IEEE80211_CONF_CHANGE_PS) { |
1225 | if (conf->flags & IEEE80211_CONF_PS) { |
1226 | ath9k_htc_setpower(priv, mode: ATH9K_PM_NETWORK_SLEEP); |
1227 | priv->ps_enabled = true; |
1228 | } else { |
1229 | priv->ps_enabled = false; |
1230 | cancel_work_sync(work: &priv->ps_work); |
1231 | ath9k_htc_setpower(priv, mode: ATH9K_PM_AWAKE); |
1232 | } |
1233 | } |
1234 | |
1235 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
1236 | priv->txpowlimit = 2 * conf->power_level; |
1237 | ath9k_cmn_update_txpow(ah: priv->ah, cur_txpow: priv->curtxpow, |
1238 | new_txpow: priv->txpowlimit, txpower: &priv->curtxpow); |
1239 | } |
1240 | |
1241 | out: |
1242 | ath9k_htc_ps_restore(priv); |
1243 | mutex_unlock(lock: &priv->mutex); |
1244 | return ret; |
1245 | } |
1246 | |
1247 | #define SUPPORTED_FILTERS \ |
1248 | (FIF_ALLMULTI | \ |
1249 | FIF_CONTROL | \ |
1250 | FIF_PSPOLL | \ |
1251 | FIF_OTHER_BSS | \ |
1252 | FIF_BCN_PRBRESP_PROMISC | \ |
1253 | FIF_PROBE_REQ | \ |
1254 | FIF_MCAST_ACTION | \ |
1255 | FIF_FCSFAIL) |
1256 | |
1257 | static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, |
1258 | unsigned int changed_flags, |
1259 | unsigned int *total_flags, |
1260 | u64 multicast) |
1261 | { |
1262 | struct ath9k_htc_priv *priv = hw->priv; |
1263 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
1264 | u32 rfilt; |
1265 | |
1266 | mutex_lock(&priv->mutex); |
1267 | *total_flags &= SUPPORTED_FILTERS; |
1268 | |
1269 | if (test_bit(ATH_OP_INVALID, &common->op_flags)) { |
1270 | ath_dbg(ath9k_hw_common(priv->ah), ANY, |
1271 | "Unable to configure filter on invalid state\n" ); |
1272 | mutex_unlock(lock: &priv->mutex); |
1273 | return; |
1274 | } |
1275 | ath9k_htc_ps_wakeup(priv); |
1276 | |
1277 | priv->rxfilter = *total_flags; |
1278 | rfilt = ath9k_htc_calcrxfilter(priv); |
1279 | ath9k_hw_setrxfilter(ah: priv->ah, bits: rfilt); |
1280 | |
1281 | ath_dbg(ath9k_hw_common(priv->ah), CONFIG, "Set HW RX filter: 0x%x\n" , |
1282 | rfilt); |
1283 | |
1284 | ath9k_htc_ps_restore(priv); |
1285 | mutex_unlock(lock: &priv->mutex); |
1286 | } |
1287 | |
1288 | static void ath9k_htc_sta_rc_update_work(struct work_struct *work) |
1289 | { |
1290 | struct ath9k_htc_sta *ista = |
1291 | container_of(work, struct ath9k_htc_sta, rc_update_work); |
1292 | struct ieee80211_sta *sta = |
1293 | container_of((void *)ista, struct ieee80211_sta, drv_priv); |
1294 | struct ath9k_htc_priv *priv = ista->htc_priv; |
1295 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
1296 | struct ath9k_htc_target_rate trate; |
1297 | |
1298 | mutex_lock(&priv->mutex); |
1299 | ath9k_htc_ps_wakeup(priv); |
1300 | |
1301 | memset(&trate, 0, sizeof(struct ath9k_htc_target_rate)); |
1302 | ath9k_htc_setup_rate(priv, sta, trate: &trate); |
1303 | if (!ath9k_htc_send_rate_cmd(priv, trate: &trate)) |
1304 | ath_dbg(common, CONFIG, |
1305 | "Supported rates for sta: %pM updated, rate caps: 0x%X\n" , |
1306 | sta->addr, be32_to_cpu(trate.capflags)); |
1307 | else |
1308 | ath_dbg(common, CONFIG, |
1309 | "Unable to update supported rates for sta: %pM\n" , |
1310 | sta->addr); |
1311 | |
1312 | ath9k_htc_ps_restore(priv); |
1313 | mutex_unlock(lock: &priv->mutex); |
1314 | } |
1315 | |
1316 | static int ath9k_htc_sta_add(struct ieee80211_hw *hw, |
1317 | struct ieee80211_vif *vif, |
1318 | struct ieee80211_sta *sta) |
1319 | { |
1320 | struct ath9k_htc_priv *priv = hw->priv; |
1321 | struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; |
1322 | int ret; |
1323 | |
1324 | mutex_lock(&priv->mutex); |
1325 | ath9k_htc_ps_wakeup(priv); |
1326 | ret = ath9k_htc_add_station(priv, vif, sta); |
1327 | if (!ret) { |
1328 | INIT_WORK(&ista->rc_update_work, ath9k_htc_sta_rc_update_work); |
1329 | ista->htc_priv = priv; |
1330 | ath9k_htc_init_rate(priv, sta); |
1331 | } |
1332 | ath9k_htc_ps_restore(priv); |
1333 | mutex_unlock(lock: &priv->mutex); |
1334 | |
1335 | return ret; |
1336 | } |
1337 | |
1338 | static int ath9k_htc_sta_remove(struct ieee80211_hw *hw, |
1339 | struct ieee80211_vif *vif, |
1340 | struct ieee80211_sta *sta) |
1341 | { |
1342 | struct ath9k_htc_priv *priv = hw->priv; |
1343 | struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; |
1344 | int ret; |
1345 | |
1346 | cancel_work_sync(work: &ista->rc_update_work); |
1347 | |
1348 | mutex_lock(&priv->mutex); |
1349 | ath9k_htc_ps_wakeup(priv); |
1350 | htc_sta_drain(target: priv->htc, idx: ista->index); |
1351 | ret = ath9k_htc_remove_station(priv, vif, sta); |
1352 | ath9k_htc_ps_restore(priv); |
1353 | mutex_unlock(lock: &priv->mutex); |
1354 | |
1355 | return ret; |
1356 | } |
1357 | |
1358 | static void ath9k_htc_sta_rc_update(struct ieee80211_hw *hw, |
1359 | struct ieee80211_vif *vif, |
1360 | struct ieee80211_sta *sta, u32 changed) |
1361 | { |
1362 | struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv; |
1363 | |
1364 | if (!(changed & IEEE80211_RC_SUPP_RATES_CHANGED)) |
1365 | return; |
1366 | |
1367 | schedule_work(work: &ista->rc_update_work); |
1368 | } |
1369 | |
1370 | static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, |
1371 | struct ieee80211_vif *vif, |
1372 | unsigned int link_id, u16 queue, |
1373 | const struct ieee80211_tx_queue_params *params) |
1374 | { |
1375 | struct ath9k_htc_priv *priv = hw->priv; |
1376 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
1377 | struct ath9k_tx_queue_info qi; |
1378 | int ret = 0, qnum; |
1379 | |
1380 | if (queue >= IEEE80211_NUM_ACS) |
1381 | return 0; |
1382 | |
1383 | mutex_lock(&priv->mutex); |
1384 | ath9k_htc_ps_wakeup(priv); |
1385 | |
1386 | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); |
1387 | |
1388 | qi.tqi_aifs = params->aifs; |
1389 | qi.tqi_cwmin = params->cw_min; |
1390 | qi.tqi_cwmax = params->cw_max; |
1391 | qi.tqi_burstTime = params->txop * 32; |
1392 | |
1393 | qnum = get_hw_qnum(queue, hwq_map: priv->hwq_map); |
1394 | |
1395 | ath_dbg(common, CONFIG, |
1396 | "Configure tx [queue/hwq] [%d/%d], aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n" , |
1397 | queue, qnum, params->aifs, params->cw_min, |
1398 | params->cw_max, params->txop); |
1399 | |
1400 | ret = ath_htc_txq_update(priv, qnum, qinfo: &qi); |
1401 | if (ret) { |
1402 | ath_err(common, "TXQ Update failed\n" ); |
1403 | goto out; |
1404 | } |
1405 | |
1406 | if ((priv->ah->opmode == NL80211_IFTYPE_ADHOC) && |
1407 | (qnum == priv->hwq_map[IEEE80211_AC_BE])) |
1408 | ath9k_htc_beaconq_config(priv); |
1409 | out: |
1410 | ath9k_htc_ps_restore(priv); |
1411 | mutex_unlock(lock: &priv->mutex); |
1412 | |
1413 | return ret; |
1414 | } |
1415 | |
1416 | static int ath9k_htc_set_key(struct ieee80211_hw *hw, |
1417 | enum set_key_cmd cmd, |
1418 | struct ieee80211_vif *vif, |
1419 | struct ieee80211_sta *sta, |
1420 | struct ieee80211_key_conf *key) |
1421 | { |
1422 | struct ath9k_htc_priv *priv = hw->priv; |
1423 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
1424 | int ret = 0; |
1425 | |
1426 | if (htc_modparam_nohwcrypt) |
1427 | return -ENOSPC; |
1428 | |
1429 | if ((vif->type == NL80211_IFTYPE_ADHOC || |
1430 | vif->type == NL80211_IFTYPE_MESH_POINT) && |
1431 | (key->cipher == WLAN_CIPHER_SUITE_TKIP || |
1432 | key->cipher == WLAN_CIPHER_SUITE_CCMP) && |
1433 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { |
1434 | /* |
1435 | * For now, disable hw crypto for the RSN IBSS group keys. This |
1436 | * could be optimized in the future to use a modified key cache |
1437 | * design to support per-STA RX GTK, but until that gets |
1438 | * implemented, use of software crypto for group addressed |
1439 | * frames is a acceptable to allow RSN IBSS to be used. |
1440 | */ |
1441 | return -EOPNOTSUPP; |
1442 | } |
1443 | |
1444 | mutex_lock(&priv->mutex); |
1445 | ath_dbg(common, CONFIG, "Set HW Key\n" ); |
1446 | ath9k_htc_ps_wakeup(priv); |
1447 | |
1448 | switch (cmd) { |
1449 | case SET_KEY: |
1450 | ret = ath_key_config(common, vif, sta, key); |
1451 | if (ret >= 0) { |
1452 | key->hw_key_idx = ret; |
1453 | /* push IV and Michael MIC generation to stack */ |
1454 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1455 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) |
1456 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
1457 | if (priv->ah->sw_mgmt_crypto_tx && |
1458 | key->cipher == WLAN_CIPHER_SUITE_CCMP) |
1459 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; |
1460 | ret = 0; |
1461 | } |
1462 | break; |
1463 | case DISABLE_KEY: |
1464 | ath_key_delete(common, hw_key_idx: key->hw_key_idx); |
1465 | break; |
1466 | default: |
1467 | ret = -EINVAL; |
1468 | } |
1469 | |
1470 | ath9k_htc_ps_restore(priv); |
1471 | mutex_unlock(lock: &priv->mutex); |
1472 | |
1473 | return ret; |
1474 | } |
1475 | |
1476 | static void ath9k_htc_set_bssid(struct ath9k_htc_priv *priv) |
1477 | { |
1478 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
1479 | |
1480 | ath9k_hw_write_associd(ah: priv->ah); |
1481 | ath_dbg(common, CONFIG, "BSSID: %pM aid: 0x%x\n" , |
1482 | common->curbssid, common->curaid); |
1483 | } |
1484 | |
1485 | static void ath9k_htc_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) |
1486 | { |
1487 | struct ath9k_htc_priv *priv = data; |
1488 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
1489 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
1490 | |
1491 | if ((vif->type == NL80211_IFTYPE_STATION) && vif->cfg.assoc) { |
1492 | common->curaid = vif->cfg.aid; |
1493 | common->last_rssi = ATH_RSSI_DUMMY_MARKER; |
1494 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
1495 | set_bit(nr: ATH_OP_PRIM_STA_VIF, addr: &common->op_flags); |
1496 | } |
1497 | } |
1498 | |
1499 | static void ath9k_htc_choose_set_bssid(struct ath9k_htc_priv *priv) |
1500 | { |
1501 | if (priv->num_sta_assoc_vif == 1) { |
1502 | ieee80211_iterate_active_interfaces_atomic( |
1503 | hw: priv->hw, iter_flags: IEEE80211_IFACE_ITER_RESUME_ALL, |
1504 | iterator: ath9k_htc_bss_iter, data: priv); |
1505 | ath9k_htc_set_bssid(priv); |
1506 | } |
1507 | } |
1508 | |
1509 | static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, |
1510 | struct ieee80211_vif *vif, |
1511 | struct ieee80211_bss_conf *bss_conf, |
1512 | u64 changed) |
1513 | { |
1514 | struct ath9k_htc_priv *priv = hw->priv; |
1515 | struct ath_hw *ah = priv->ah; |
1516 | struct ath_common *common = ath9k_hw_common(ah); |
1517 | int slottime; |
1518 | |
1519 | mutex_lock(&priv->mutex); |
1520 | ath9k_htc_ps_wakeup(priv); |
1521 | |
1522 | if (changed & BSS_CHANGED_ASSOC) { |
1523 | ath_dbg(common, CONFIG, "BSS Changed ASSOC %d\n" , |
1524 | vif->cfg.assoc); |
1525 | |
1526 | vif->cfg.assoc ? |
1527 | priv->num_sta_assoc_vif++ : priv->num_sta_assoc_vif--; |
1528 | |
1529 | if (!vif->cfg.assoc) |
1530 | clear_bit(nr: ATH_OP_PRIM_STA_VIF, addr: &common->op_flags); |
1531 | |
1532 | if (priv->ah->opmode == NL80211_IFTYPE_STATION) { |
1533 | ath9k_htc_choose_set_bssid(priv); |
1534 | if (vif->cfg.assoc && (priv->num_sta_assoc_vif == 1)) |
1535 | ath9k_htc_start_ani(priv); |
1536 | else if (priv->num_sta_assoc_vif == 0) |
1537 | ath9k_htc_stop_ani(priv); |
1538 | } |
1539 | } |
1540 | |
1541 | if (changed & BSS_CHANGED_IBSS) { |
1542 | if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) { |
1543 | common->curaid = vif->cfg.aid; |
1544 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
1545 | ath9k_htc_set_bssid(priv); |
1546 | } |
1547 | } |
1548 | |
1549 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) { |
1550 | ath_dbg(common, CONFIG, "Beacon enabled for BSS: %pM\n" , |
1551 | bss_conf->bssid); |
1552 | ath9k_htc_set_tsfadjust(priv, vif); |
1553 | priv->cur_beacon_conf.enable_beacon = 1; |
1554 | ath9k_htc_beacon_config(priv, vif); |
1555 | } |
1556 | |
1557 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) { |
1558 | /* |
1559 | * Disable SWBA interrupt only if there are no |
1560 | * concurrent AP/mesh or IBSS interfaces. |
1561 | */ |
1562 | if ((priv->num_ap_vif + priv->num_mbss_vif <= 1) || |
1563 | priv->num_ibss_vif) { |
1564 | ath_dbg(common, CONFIG, |
1565 | "Beacon disabled for BSS: %pM\n" , |
1566 | bss_conf->bssid); |
1567 | priv->cur_beacon_conf.enable_beacon = 0; |
1568 | ath9k_htc_beacon_config(priv, vif); |
1569 | } |
1570 | } |
1571 | |
1572 | if (changed & BSS_CHANGED_BEACON_INT) { |
1573 | /* |
1574 | * Reset the HW TSF for the first AP or mesh interface. |
1575 | */ |
1576 | if (priv->nvifs == 1 && |
1577 | ((priv->ah->opmode == NL80211_IFTYPE_AP && |
1578 | vif->type == NL80211_IFTYPE_AP && |
1579 | priv->num_ap_vif == 1) || |
1580 | (priv->ah->opmode == NL80211_IFTYPE_MESH_POINT && |
1581 | vif->type == NL80211_IFTYPE_MESH_POINT && |
1582 | priv->num_mbss_vif == 1))) { |
1583 | set_bit(OP_TSF_RESET, addr: &priv->op_flags); |
1584 | } |
1585 | ath_dbg(common, CONFIG, |
1586 | "Beacon interval changed for BSS: %pM\n" , |
1587 | bss_conf->bssid); |
1588 | ath9k_htc_beacon_config(priv, vif); |
1589 | } |
1590 | |
1591 | if (changed & BSS_CHANGED_ERP_SLOT) { |
1592 | if (bss_conf->use_short_slot) |
1593 | slottime = 9; |
1594 | else |
1595 | slottime = 20; |
1596 | if (vif->type == NL80211_IFTYPE_AP) { |
1597 | /* |
1598 | * Defer update, so that connected stations can adjust |
1599 | * their settings at the same time. |
1600 | * See beacon.c for more details |
1601 | */ |
1602 | priv->beacon.slottime = slottime; |
1603 | priv->beacon.updateslot = UPDATE; |
1604 | } else { |
1605 | ah->slottime = slottime; |
1606 | ath9k_hw_init_global_settings(ah); |
1607 | } |
1608 | } |
1609 | |
1610 | if (changed & BSS_CHANGED_HT) |
1611 | ath9k_htc_update_rate(priv, vif, bss_conf); |
1612 | |
1613 | ath9k_htc_ps_restore(priv); |
1614 | mutex_unlock(lock: &priv->mutex); |
1615 | } |
1616 | |
1617 | static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw, |
1618 | struct ieee80211_vif *vif) |
1619 | { |
1620 | struct ath9k_htc_priv *priv = hw->priv; |
1621 | u64 tsf; |
1622 | |
1623 | mutex_lock(&priv->mutex); |
1624 | ath9k_htc_ps_wakeup(priv); |
1625 | tsf = ath9k_hw_gettsf64(ah: priv->ah); |
1626 | ath9k_htc_ps_restore(priv); |
1627 | mutex_unlock(lock: &priv->mutex); |
1628 | |
1629 | return tsf; |
1630 | } |
1631 | |
1632 | static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, |
1633 | struct ieee80211_vif *vif, u64 tsf) |
1634 | { |
1635 | struct ath9k_htc_priv *priv = hw->priv; |
1636 | |
1637 | mutex_lock(&priv->mutex); |
1638 | ath9k_htc_ps_wakeup(priv); |
1639 | ath9k_hw_settsf64(ah: priv->ah, tsf64: tsf); |
1640 | ath9k_htc_ps_restore(priv); |
1641 | mutex_unlock(lock: &priv->mutex); |
1642 | } |
1643 | |
1644 | static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw, |
1645 | struct ieee80211_vif *vif) |
1646 | { |
1647 | struct ath9k_htc_priv *priv = hw->priv; |
1648 | |
1649 | mutex_lock(&priv->mutex); |
1650 | ath9k_htc_ps_wakeup(priv); |
1651 | ath9k_hw_reset_tsf(ah: priv->ah); |
1652 | ath9k_htc_ps_restore(priv); |
1653 | mutex_unlock(lock: &priv->mutex); |
1654 | } |
1655 | |
1656 | static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, |
1657 | struct ieee80211_vif *vif, |
1658 | struct ieee80211_ampdu_params *params) |
1659 | { |
1660 | struct ath9k_htc_priv *priv = hw->priv; |
1661 | struct ath9k_htc_sta *ista; |
1662 | int ret = 0; |
1663 | struct ieee80211_sta *sta = params->sta; |
1664 | enum ieee80211_ampdu_mlme_action action = params->action; |
1665 | u16 tid = params->tid; |
1666 | |
1667 | mutex_lock(&priv->mutex); |
1668 | ath9k_htc_ps_wakeup(priv); |
1669 | |
1670 | switch (action) { |
1671 | case IEEE80211_AMPDU_RX_START: |
1672 | break; |
1673 | case IEEE80211_AMPDU_RX_STOP: |
1674 | break; |
1675 | case IEEE80211_AMPDU_TX_START: |
1676 | ret = ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid); |
1677 | if (!ret) |
1678 | ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; |
1679 | break; |
1680 | case IEEE80211_AMPDU_TX_STOP_CONT: |
1681 | case IEEE80211_AMPDU_TX_STOP_FLUSH: |
1682 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: |
1683 | ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid); |
1684 | ieee80211_stop_tx_ba_cb_irqsafe(vif, ra: sta->addr, tid); |
1685 | break; |
1686 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
1687 | if (tid >= ATH9K_HTC_MAX_TID) { |
1688 | ret = -EINVAL; |
1689 | break; |
1690 | } |
1691 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
1692 | spin_lock_bh(lock: &priv->tx.tx_lock); |
1693 | ista->tid_state[tid] = AGGR_OPERATIONAL; |
1694 | spin_unlock_bh(lock: &priv->tx.tx_lock); |
1695 | break; |
1696 | default: |
1697 | ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n" ); |
1698 | } |
1699 | |
1700 | ath9k_htc_ps_restore(priv); |
1701 | mutex_unlock(lock: &priv->mutex); |
1702 | |
1703 | return ret; |
1704 | } |
1705 | |
1706 | static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw, |
1707 | struct ieee80211_vif *vif, |
1708 | const u8 *mac_addr) |
1709 | { |
1710 | struct ath9k_htc_priv *priv = hw->priv; |
1711 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
1712 | |
1713 | mutex_lock(&priv->mutex); |
1714 | spin_lock_bh(lock: &priv->beacon_lock); |
1715 | set_bit(nr: ATH_OP_SCANNING, addr: &common->op_flags); |
1716 | spin_unlock_bh(lock: &priv->beacon_lock); |
1717 | cancel_work_sync(work: &priv->ps_work); |
1718 | ath9k_htc_stop_ani(priv); |
1719 | mutex_unlock(lock: &priv->mutex); |
1720 | } |
1721 | |
1722 | static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw, |
1723 | struct ieee80211_vif *vif) |
1724 | { |
1725 | struct ath9k_htc_priv *priv = hw->priv; |
1726 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
1727 | |
1728 | mutex_lock(&priv->mutex); |
1729 | spin_lock_bh(lock: &priv->beacon_lock); |
1730 | clear_bit(nr: ATH_OP_SCANNING, addr: &common->op_flags); |
1731 | spin_unlock_bh(lock: &priv->beacon_lock); |
1732 | ath9k_htc_ps_wakeup(priv); |
1733 | ath9k_htc_vif_reconfig(priv); |
1734 | ath9k_htc_ps_restore(priv); |
1735 | mutex_unlock(lock: &priv->mutex); |
1736 | } |
1737 | |
1738 | static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
1739 | { |
1740 | return 0; |
1741 | } |
1742 | |
1743 | static void ath9k_htc_set_coverage_class(struct ieee80211_hw *hw, |
1744 | s16 coverage_class) |
1745 | { |
1746 | struct ath9k_htc_priv *priv = hw->priv; |
1747 | |
1748 | mutex_lock(&priv->mutex); |
1749 | ath9k_htc_ps_wakeup(priv); |
1750 | priv->ah->coverage_class = coverage_class; |
1751 | ath9k_hw_init_global_settings(ah: priv->ah); |
1752 | ath9k_htc_ps_restore(priv); |
1753 | mutex_unlock(lock: &priv->mutex); |
1754 | } |
1755 | |
1756 | /* |
1757 | * Currently, this is used only for selecting the minimum rate |
1758 | * for management frames, rate selection for data frames remain |
1759 | * unaffected. |
1760 | */ |
1761 | static int ath9k_htc_set_bitrate_mask(struct ieee80211_hw *hw, |
1762 | struct ieee80211_vif *vif, |
1763 | const struct cfg80211_bitrate_mask *mask) |
1764 | { |
1765 | struct ath9k_htc_priv *priv = hw->priv; |
1766 | struct ath_common *common = ath9k_hw_common(ah: priv->ah); |
1767 | struct ath9k_htc_target_rate_mask tmask; |
1768 | struct ath9k_htc_vif *avp = (void *)vif->drv_priv; |
1769 | int ret = 0; |
1770 | u8 cmd_rsp; |
1771 | |
1772 | memset(&tmask, 0, sizeof(struct ath9k_htc_target_rate_mask)); |
1773 | |
1774 | tmask.vif_index = avp->index; |
1775 | tmask.band = NL80211_BAND_2GHZ; |
1776 | tmask.mask = cpu_to_be32(mask->control[NL80211_BAND_2GHZ].legacy); |
1777 | |
1778 | WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask); |
1779 | if (ret) { |
1780 | ath_err(common, |
1781 | "Unable to set 2G rate mask for " |
1782 | "interface at idx: %d\n" , avp->index); |
1783 | goto out; |
1784 | } |
1785 | |
1786 | tmask.band = NL80211_BAND_5GHZ; |
1787 | tmask.mask = cpu_to_be32(mask->control[NL80211_BAND_5GHZ].legacy); |
1788 | |
1789 | WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask); |
1790 | if (ret) { |
1791 | ath_err(common, |
1792 | "Unable to set 5G rate mask for " |
1793 | "interface at idx: %d\n" , avp->index); |
1794 | goto out; |
1795 | } |
1796 | |
1797 | ath_dbg(common, CONFIG, "Set bitrate masks: 0x%x, 0x%x\n" , |
1798 | mask->control[NL80211_BAND_2GHZ].legacy, |
1799 | mask->control[NL80211_BAND_5GHZ].legacy); |
1800 | out: |
1801 | return ret; |
1802 | } |
1803 | |
1804 | |
1805 | static int ath9k_htc_get_stats(struct ieee80211_hw *hw, |
1806 | struct ieee80211_low_level_stats *stats) |
1807 | { |
1808 | struct ath9k_htc_priv *priv = hw->priv; |
1809 | struct ath_hw *ah = priv->ah; |
1810 | struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats; |
1811 | |
1812 | stats->dot11ACKFailureCount = mib_stats->ackrcv_bad; |
1813 | stats->dot11RTSFailureCount = mib_stats->rts_bad; |
1814 | stats->dot11FCSErrorCount = mib_stats->fcs_bad; |
1815 | stats->dot11RTSSuccessCount = mib_stats->rts_good; |
1816 | |
1817 | return 0; |
1818 | } |
1819 | |
1820 | struct base_eep_header *ath9k_htc_get_eeprom_base(struct ath9k_htc_priv *priv) |
1821 | { |
1822 | struct base_eep_header *pBase = NULL; |
1823 | /* |
1824 | * This can be done since all the 3 EEPROM families have the |
1825 | * same base header upto a certain point, and we are interested in |
1826 | * the data only upto that point. |
1827 | */ |
1828 | |
1829 | if (AR_SREV_9271(priv->ah)) |
1830 | pBase = (struct base_eep_header *) |
1831 | &priv->ah->eeprom.map4k.baseEepHeader; |
1832 | else if (priv->ah->hw_version.usbdev == AR9280_USB) |
1833 | pBase = (struct base_eep_header *) |
1834 | &priv->ah->eeprom.def.baseEepHeader; |
1835 | else if (priv->ah->hw_version.usbdev == AR9287_USB) |
1836 | pBase = (struct base_eep_header *) |
1837 | &priv->ah->eeprom.map9287.baseEepHeader; |
1838 | return pBase; |
1839 | } |
1840 | |
1841 | |
1842 | static int ath9k_htc_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, |
1843 | u32 *rx_ant) |
1844 | { |
1845 | struct ath9k_htc_priv *priv = hw->priv; |
1846 | struct base_eep_header *pBase = ath9k_htc_get_eeprom_base(priv); |
1847 | if (pBase) { |
1848 | *tx_ant = pBase->txMask; |
1849 | *rx_ant = pBase->rxMask; |
1850 | } else { |
1851 | *tx_ant = 0; |
1852 | *rx_ant = 0; |
1853 | } |
1854 | return 0; |
1855 | } |
1856 | |
1857 | static void ath9k_htc_channel_switch_beacon(struct ieee80211_hw *hw, |
1858 | struct ieee80211_vif *vif, |
1859 | struct cfg80211_chan_def *chandef) |
1860 | { |
1861 | struct ath9k_htc_priv *priv = hw->priv; |
1862 | |
1863 | /* mac80211 does not support CSA in multi-if cases (yet) */ |
1864 | if (WARN_ON(priv->csa_vif)) |
1865 | return; |
1866 | |
1867 | priv->csa_vif = vif; |
1868 | } |
1869 | |
1870 | struct ieee80211_ops ath9k_htc_ops = { |
1871 | .add_chanctx = ieee80211_emulate_add_chanctx, |
1872 | .remove_chanctx = ieee80211_emulate_remove_chanctx, |
1873 | .change_chanctx = ieee80211_emulate_change_chanctx, |
1874 | .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx, |
1875 | .tx = ath9k_htc_tx, |
1876 | .wake_tx_queue = ieee80211_handle_wake_tx_queue, |
1877 | .start = ath9k_htc_start, |
1878 | .stop = ath9k_htc_stop, |
1879 | .add_interface = ath9k_htc_add_interface, |
1880 | .remove_interface = ath9k_htc_remove_interface, |
1881 | .config = ath9k_htc_config, |
1882 | .configure_filter = ath9k_htc_configure_filter, |
1883 | .sta_add = ath9k_htc_sta_add, |
1884 | .sta_remove = ath9k_htc_sta_remove, |
1885 | .conf_tx = ath9k_htc_conf_tx, |
1886 | .sta_rc_update = ath9k_htc_sta_rc_update, |
1887 | .bss_info_changed = ath9k_htc_bss_info_changed, |
1888 | .set_key = ath9k_htc_set_key, |
1889 | .get_tsf = ath9k_htc_get_tsf, |
1890 | .set_tsf = ath9k_htc_set_tsf, |
1891 | .reset_tsf = ath9k_htc_reset_tsf, |
1892 | .ampdu_action = ath9k_htc_ampdu_action, |
1893 | .sw_scan_start = ath9k_htc_sw_scan_start, |
1894 | .sw_scan_complete = ath9k_htc_sw_scan_complete, |
1895 | .set_rts_threshold = ath9k_htc_set_rts_threshold, |
1896 | .rfkill_poll = ath9k_htc_rfkill_poll_state, |
1897 | .set_coverage_class = ath9k_htc_set_coverage_class, |
1898 | .set_bitrate_mask = ath9k_htc_set_bitrate_mask, |
1899 | .get_stats = ath9k_htc_get_stats, |
1900 | .get_antenna = ath9k_htc_get_antenna, |
1901 | .channel_switch_beacon = ath9k_htc_channel_switch_beacon, |
1902 | |
1903 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS |
1904 | .get_et_sset_count = ath9k_htc_get_et_sset_count, |
1905 | .get_et_stats = ath9k_htc_get_et_stats, |
1906 | .get_et_strings = ath9k_htc_get_et_strings, |
1907 | #endif |
1908 | }; |
1909 | |