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