blob: 90b13ed1ae4ca5eaf91d90127b0da4dc438395fd [file] [log] [blame]
Sujithfb9987d2010-03-17 14:25:25 +05301/*
2 * Copyright (c) 2010 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#ifdef CONFIG_ATH9K_HTC_DEBUGFS
20static struct dentry *ath9k_debugfs_root;
21#endif
22
23/*************/
24/* Utilities */
25/*************/
26
27static void ath_update_txpow(struct ath9k_htc_priv *priv)
28{
29 struct ath_hw *ah = priv->ah;
30 u32 txpow;
31
32 if (priv->curtxpow != priv->txpowlimit) {
33 ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit);
34 /* read back in case value is clamped */
35 ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow);
36 priv->curtxpow = txpow;
37 }
38}
39
40/* HACK Alert: Use 11NG for 2.4, use 11NA for 5 */
41static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv,
42 struct ath9k_channel *ichan)
43{
44 enum htc_phymode mode;
45
46 mode = HTC_MODE_AUTO;
47
48 switch (ichan->chanmode) {
49 case CHANNEL_G:
50 case CHANNEL_G_HT20:
51 case CHANNEL_G_HT40PLUS:
52 case CHANNEL_G_HT40MINUS:
53 mode = HTC_MODE_11NG;
54 break;
55 case CHANNEL_A:
56 case CHANNEL_A_HT20:
57 case CHANNEL_A_HT40PLUS:
58 case CHANNEL_A_HT40MINUS:
59 mode = HTC_MODE_11NA;
60 break;
61 default:
62 break;
63 }
64
65 return mode;
66}
67
68static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
69 struct ieee80211_hw *hw,
70 struct ath9k_channel *hchan)
71{
72 struct ath_hw *ah = priv->ah;
73 struct ath_common *common = ath9k_hw_common(ah);
74 struct ieee80211_conf *conf = &common->hw->conf;
75 bool fastcc = true;
76 struct ieee80211_channel *channel = hw->conf.channel;
77 enum htc_phymode mode;
78 u16 htc_mode;
79 u8 cmd_rsp;
80 int ret;
81
82 if (priv->op_flags & OP_INVALID)
83 return -EIO;
84
85 if (priv->op_flags & OP_FULL_RESET)
86 fastcc = false;
87
88 /* Fiddle around with fastcc later on, for now just use full reset */
89 fastcc = false;
90
91 htc_stop(priv->htc);
92 WMI_CMD(WMI_DISABLE_INTR_CMDID);
93 WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
94 WMI_CMD(WMI_STOP_RECV_CMDID);
95
96 ath_print(common, ATH_DBG_CONFIG,
97 "(%u MHz) -> (%u MHz), HT: %d, HT40: %d\n",
98 priv->ah->curchan->channel,
99 channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf));
100
101 ret = ath9k_hw_reset(ah, hchan, fastcc);
102 if (ret) {
103 ath_print(common, ATH_DBG_FATAL,
104 "Unable to reset channel (%u Mhz) "
105 "reset status %d\n", channel->center_freq, ret);
106 goto err;
107 }
108
109 ath_update_txpow(priv);
110
111 WMI_CMD(WMI_START_RECV_CMDID);
112 if (ret)
113 goto err;
114
115 ath9k_host_rx_init(priv);
116
117 mode = ath9k_htc_get_curmode(priv, hchan);
118 htc_mode = cpu_to_be16(mode);
119 WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode);
120 if (ret)
121 goto err;
122
123 WMI_CMD(WMI_ENABLE_INTR_CMDID);
124 if (ret)
125 goto err;
126
127 htc_start(priv->htc);
128
129 priv->op_flags &= ~OP_FULL_RESET;
130err:
131 return ret;
132}
133
134static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
135{
136 struct ath_common *common = ath9k_hw_common(priv->ah);
137 struct ath9k_htc_target_vif hvif;
138 int ret = 0;
139 u8 cmd_rsp;
140
141 if (priv->nvifs > 0)
142 return -ENOBUFS;
143
144 memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
145 memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
146
147 hvif.opmode = cpu_to_be32(HTC_M_MONITOR);
148 priv->ah->opmode = NL80211_IFTYPE_MONITOR;
149 hvif.index = priv->nvifs;
150
151 WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif);
152 if (ret)
153 return ret;
154
155 priv->nvifs++;
156 return 0;
157}
158
159static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
160{
161 struct ath_common *common = ath9k_hw_common(priv->ah);
162 struct ath9k_htc_target_vif hvif;
163 int ret = 0;
164 u8 cmd_rsp;
165
166 memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
167 memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
168 hvif.index = 0; /* Should do for now */
169 WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
170 priv->nvifs--;
171
172 return ret;
173}
174
175static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
176 struct ieee80211_vif *vif,
177 struct ieee80211_sta *sta)
178{
179 struct ath_common *common = ath9k_hw_common(priv->ah);
180 struct ath9k_htc_target_sta tsta;
181 struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv;
182 struct ath9k_htc_sta *ista;
183 int ret;
184 u8 cmd_rsp;
185
186 if (priv->nstations >= ATH9K_HTC_MAX_STA)
187 return -ENOBUFS;
188
189 memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta));
190
191 if (sta) {
192 ista = (struct ath9k_htc_sta *) sta->drv_priv;
193 memcpy(&tsta.macaddr, sta->addr, ETH_ALEN);
194 memcpy(&tsta.bssid, common->curbssid, ETH_ALEN);
195 tsta.associd = common->curaid;
196 tsta.is_vif_sta = 0;
197 tsta.valid = true;
198 ista->index = priv->nstations;
199 } else {
200 memcpy(&tsta.macaddr, vif->addr, ETH_ALEN);
201 tsta.is_vif_sta = 1;
202 }
203
204 tsta.sta_index = priv->nstations;
205 tsta.vif_index = avp->index;
206 tsta.maxampdu = 0xffff;
207 if (sta && sta->ht_cap.ht_supported)
208 tsta.flags = cpu_to_be16(ATH_HTC_STA_HT);
209
210 WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);
211 if (ret) {
212 if (sta)
213 ath_print(common, ATH_DBG_FATAL,
214 "Unable to add station entry for: %pM\n", sta->addr);
215 return ret;
216 }
217
218 if (sta)
219 ath_print(common, ATH_DBG_CONFIG,
220 "Added a station entry for: %pM (idx: %d)\n",
221 sta->addr, tsta.sta_index);
222
223 priv->nstations++;
224 return 0;
225}
226
227static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv,
228 struct ieee80211_vif *vif,
229 struct ieee80211_sta *sta)
230{
231 struct ath_common *common = ath9k_hw_common(priv->ah);
232 struct ath9k_htc_sta *ista;
233 int ret;
234 u8 cmd_rsp, sta_idx;
235
236 if (sta) {
237 ista = (struct ath9k_htc_sta *) sta->drv_priv;
238 sta_idx = ista->index;
239 } else {
240 sta_idx = 0;
241 }
242
243 WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx);
244 if (ret) {
245 if (sta)
246 ath_print(common, ATH_DBG_FATAL,
247 "Unable to remove station entry for: %pM\n",
248 sta->addr);
249 return ret;
250 }
251
252 if (sta)
253 ath_print(common, ATH_DBG_CONFIG,
254 "Removed a station entry for: %pM (idx: %d)\n",
255 sta->addr, sta_idx);
256
257 priv->nstations--;
258 return 0;
259}
260
261static int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv)
262{
263 struct ath9k_htc_cap_target tcap;
264 int ret;
265 u8 cmd_rsp;
266
267 memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target));
268
269 /* FIXME: Values are hardcoded */
270 tcap.flags = 0x240c40;
271 tcap.flags_ext = 0x80601000;
272 tcap.ampdu_limit = 0xffff0000;
273 tcap.ampdu_subframes = 20;
274 tcap.tx_chainmask_legacy = 1;
275 tcap.protmode = 1;
276 tcap.tx_chainmask = 1;
277
278 WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap);
279
280 return ret;
281}
282
283static int ath9k_htc_init_rate(struct ath9k_htc_priv *priv,
284 struct ieee80211_vif *vif,
285 struct ieee80211_sta *sta)
286{
287 struct ath_common *common = ath9k_hw_common(priv->ah);
288 struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
289 struct ieee80211_supported_band *sband;
290 struct ath9k_htc_target_rate trate;
291 u32 caps = 0;
292 u8 cmd_rsp;
293 int i, j, ret;
294
295 memset(&trate, 0, sizeof(trate));
296
297 /* Only 2GHz is supported */
298 sband = priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ];
299
300 for (i = 0, j = 0; i < sband->n_bitrates; i++) {
301 if (sta->supp_rates[sband->band] & BIT(i)) {
302 priv->tgt_rate.rates.legacy_rates.rs_rates[j]
303 = (sband->bitrates[i].bitrate * 2) / 10;
304 j++;
305 }
306 }
307 priv->tgt_rate.rates.legacy_rates.rs_nrates = j;
308
309 if (sta->ht_cap.ht_supported) {
310 for (i = 0, j = 0; i < 77; i++) {
311 if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
312 priv->tgt_rate.rates.ht_rates.rs_rates[j++] = i;
313 if (j == ATH_HTC_RATE_MAX)
314 break;
315 }
316 priv->tgt_rate.rates.ht_rates.rs_nrates = j;
317
318 caps = WLAN_RC_HT_FLAG;
319 if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
320 caps |= WLAN_RC_40_FLAG;
321 if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
322 caps |= WLAN_RC_SGI_FLAG;
323
324 }
325
326 priv->tgt_rate.sta_index = ista->index;
327 priv->tgt_rate.isnew = 1;
328 trate = priv->tgt_rate;
329 priv->tgt_rate.capflags = caps;
330 trate.capflags = cpu_to_be32(caps);
331
332 WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate);
333 if (ret) {
334 ath_print(common, ATH_DBG_FATAL,
335 "Unable to initialize Rate information on target\n");
336 return ret;
337 }
338
339 ath_print(common, ATH_DBG_CONFIG,
340 "Updated target STA: %pM (caps: 0x%x)\n", sta->addr, caps);
341 return 0;
342}
343
344static bool check_rc_update(struct ieee80211_hw *hw, bool *cw40)
345{
346 struct ath9k_htc_priv *priv = hw->priv;
347 struct ieee80211_conf *conf = &hw->conf;
348
349 if (!conf_is_ht(conf))
350 return false;
351
352 if (!(priv->op_flags & OP_ASSOCIATED) ||
353 (priv->op_flags & OP_SCANNING))
354 return false;
355
356 if (conf_is_ht40(conf)) {
357 if (priv->ah->curchan->chanmode &
358 (CHANNEL_HT40PLUS | CHANNEL_HT40MINUS)) {
359 return false;
360 } else {
361 *cw40 = true;
362 return true;
363 }
364 } else { /* ht20 */
365 if (priv->ah->curchan->chanmode & CHANNEL_HT20)
366 return false;
367 else
368 return true;
369 }
370}
371
372static void ath9k_htc_rc_update(struct ath9k_htc_priv *priv, bool is_cw40)
373{
374 struct ath9k_htc_target_rate trate;
375 struct ath_common *common = ath9k_hw_common(priv->ah);
376 int ret;
377 u8 cmd_rsp;
378
379 memset(&trate, 0, sizeof(trate));
380
381 trate = priv->tgt_rate;
382
383 if (is_cw40)
384 priv->tgt_rate.capflags |= WLAN_RC_40_FLAG;
385 else
386 priv->tgt_rate.capflags &= ~WLAN_RC_40_FLAG;
387
388 trate.capflags = cpu_to_be32(priv->tgt_rate.capflags);
389
390 WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate);
391 if (ret) {
392 ath_print(common, ATH_DBG_FATAL,
393 "Unable to update Rate information on target\n");
394 return;
395 }
396
397 ath_print(common, ATH_DBG_CONFIG, "Rate control updated with "
398 "caps:0x%x on target\n", priv->tgt_rate.capflags);
399}
400
401static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv,
402 struct ieee80211_vif *vif,
403 u8 *sta_addr, u8 tid, bool oper)
404{
405 struct ath_common *common = ath9k_hw_common(priv->ah);
406 struct ath9k_htc_target_aggr aggr;
407 struct ieee80211_sta *sta = NULL;
408 struct ath9k_htc_sta *ista = (struct ath9k_htc_sta *) sta->drv_priv;
409 int ret = 0;
410 u8 cmd_rsp;
411
412 if (tid > ATH9K_HTC_MAX_TID)
413 return -EINVAL;
414
Sujithfb9987d2010-03-17 14:25:25 +0530415 memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr));
416
Sujithef98c3c2010-03-29 16:07:11 +0530417 rcu_read_lock();
418
419 /* Check if we are able to retrieve the station */
420 sta = ieee80211_find_sta(vif, sta_addr);
421 if (!sta) {
422 rcu_read_unlock();
423 return -EINVAL;
424 }
425
426 ista = (struct ath9k_htc_sta *) sta->drv_priv;
Sujithfb9987d2010-03-17 14:25:25 +0530427
428 if (oper)
429 ista->tid_state[tid] = AGGR_START;
430 else
431 ista->tid_state[tid] = AGGR_STOP;
432
Sujithef98c3c2010-03-29 16:07:11 +0530433 aggr.sta_index = ista->index;
434
435 rcu_read_unlock();
436
437 aggr.tidno = tid;
438 aggr.aggr_enable = oper;
439
Sujithfb9987d2010-03-17 14:25:25 +0530440 WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr);
441 if (ret)
442 ath_print(common, ATH_DBG_CONFIG,
443 "Unable to %s TX aggregation for (%pM, %d)\n",
444 (oper) ? "start" : "stop", sta->addr, tid);
445 else
446 ath_print(common, ATH_DBG_CONFIG,
447 "%s aggregation for (%pM, %d)\n",
448 (oper) ? "Starting" : "Stopping", sta->addr, tid);
449
450 return ret;
451}
452
453void ath9k_htc_aggr_work(struct work_struct *work)
454{
455 int ret = 0;
456 struct ath9k_htc_priv *priv =
457 container_of(work, struct ath9k_htc_priv,
458 ath9k_aggr_work.work);
459 struct ath9k_htc_aggr_work *wk = &priv->aggr_work;
460
461 mutex_lock(&wk->mutex);
462
463 switch (wk->action) {
464 case IEEE80211_AMPDU_TX_START:
465 ret = ath9k_htc_aggr_oper(priv, wk->vif, wk->sta_addr,
466 wk->tid, true);
467 if (!ret)
468 ieee80211_start_tx_ba_cb(wk->vif, wk->sta_addr,
469 wk->tid);
470 break;
471 case IEEE80211_AMPDU_TX_STOP:
472 ath9k_htc_aggr_oper(priv, wk->vif, wk->sta_addr,
473 wk->tid, false);
474 ieee80211_stop_tx_ba_cb(wk->vif, wk->sta_addr, wk->tid);
475 break;
476 default:
477 ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL,
478 "Unknown AMPDU action\n");
479 }
480
481 mutex_unlock(&wk->mutex);
482}
483
484/*********/
485/* DEBUG */
486/*********/
487
488#ifdef CONFIG_ATH9K_HTC_DEBUGFS
489
490static int ath9k_debugfs_open(struct inode *inode, struct file *file)
491{
492 file->private_data = inode->i_private;
493 return 0;
494}
495
496static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
497 size_t count, loff_t *ppos)
498{
499 struct ath9k_htc_priv *priv =
500 (struct ath9k_htc_priv *) file->private_data;
501 struct ath9k_htc_target_stats cmd_rsp;
502 char buf[512];
503 unsigned int len = 0;
504 int ret = 0;
505
506 memset(&cmd_rsp, 0, sizeof(cmd_rsp));
507
508 WMI_CMD(WMI_TGT_STATS_CMDID);
509 if (ret)
510 return -EINVAL;
511
512
513 len += snprintf(buf + len, sizeof(buf) - len,
514 "%19s : %10u\n", "TX Short Retries",
515 be32_to_cpu(cmd_rsp.tx_shortretry));
516 len += snprintf(buf + len, sizeof(buf) - len,
517 "%19s : %10u\n", "TX Long Retries",
518 be32_to_cpu(cmd_rsp.tx_longretry));
519 len += snprintf(buf + len, sizeof(buf) - len,
520 "%19s : %10u\n", "TX Xretries",
521 be32_to_cpu(cmd_rsp.tx_xretries));
522 len += snprintf(buf + len, sizeof(buf) - len,
523 "%19s : %10u\n", "TX Unaggr. Xretries",
524 be32_to_cpu(cmd_rsp.ht_txunaggr_xretry));
525 len += snprintf(buf + len, sizeof(buf) - len,
526 "%19s : %10u\n", "TX Xretries (HT)",
527 be32_to_cpu(cmd_rsp.ht_tx_xretries));
528 len += snprintf(buf + len, sizeof(buf) - len,
529 "%19s : %10u\n", "TX Rate", priv->debug.txrate);
530
531 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
532}
533
534static const struct file_operations fops_tgt_stats = {
535 .read = read_file_tgt_stats,
536 .open = ath9k_debugfs_open,
537 .owner = THIS_MODULE
538};
539
540static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
541 size_t count, loff_t *ppos)
542{
543 struct ath9k_htc_priv *priv =
544 (struct ath9k_htc_priv *) file->private_data;
545 char buf[512];
546 unsigned int len = 0;
547
548 len += snprintf(buf + len, sizeof(buf) - len,
549 "%20s : %10u\n", "Buffers queued",
550 priv->debug.tx_stats.buf_queued);
551 len += snprintf(buf + len, sizeof(buf) - len,
552 "%20s : %10u\n", "Buffers completed",
553 priv->debug.tx_stats.buf_completed);
554 len += snprintf(buf + len, sizeof(buf) - len,
555 "%20s : %10u\n", "SKBs queued",
556 priv->debug.tx_stats.skb_queued);
557 len += snprintf(buf + len, sizeof(buf) - len,
558 "%20s : %10u\n", "SKBs completed",
559 priv->debug.tx_stats.skb_completed);
560
561 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
562}
563
564static const struct file_operations fops_xmit = {
565 .read = read_file_xmit,
566 .open = ath9k_debugfs_open,
567 .owner = THIS_MODULE
568};
569
570static ssize_t read_file_recv(struct file *file, char __user *user_buf,
571 size_t count, loff_t *ppos)
572{
573 struct ath9k_htc_priv *priv =
574 (struct ath9k_htc_priv *) file->private_data;
575 char buf[512];
576 unsigned int len = 0;
577
578 len += snprintf(buf + len, sizeof(buf) - len,
579 "%20s : %10u\n", "SKBs allocated",
580 priv->debug.rx_stats.skb_allocated);
581 len += snprintf(buf + len, sizeof(buf) - len,
582 "%20s : %10u\n", "SKBs completed",
583 priv->debug.rx_stats.skb_completed);
584 len += snprintf(buf + len, sizeof(buf) - len,
585 "%20s : %10u\n", "SKBs Dropped",
586 priv->debug.rx_stats.skb_dropped);
587
588 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
589}
590
591static const struct file_operations fops_recv = {
592 .read = read_file_recv,
593 .open = ath9k_debugfs_open,
594 .owner = THIS_MODULE
595};
596
Sujithe1572c52010-03-24 13:42:13 +0530597int ath9k_htc_init_debug(struct ath_hw *ah)
Sujithfb9987d2010-03-17 14:25:25 +0530598{
599 struct ath_common *common = ath9k_hw_common(ah);
600 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
601
602 if (!ath9k_debugfs_root)
603 return -ENOENT;
604
605 priv->debug.debugfs_phy = debugfs_create_dir(wiphy_name(priv->hw->wiphy),
606 ath9k_debugfs_root);
607 if (!priv->debug.debugfs_phy)
608 goto err;
609
610 priv->debug.debugfs_tgt_stats = debugfs_create_file("tgt_stats", S_IRUSR,
611 priv->debug.debugfs_phy,
612 priv, &fops_tgt_stats);
613 if (!priv->debug.debugfs_tgt_stats)
614 goto err;
615
616
617 priv->debug.debugfs_xmit = debugfs_create_file("xmit", S_IRUSR,
618 priv->debug.debugfs_phy,
619 priv, &fops_xmit);
620 if (!priv->debug.debugfs_xmit)
621 goto err;
622
623 priv->debug.debugfs_recv = debugfs_create_file("recv", S_IRUSR,
624 priv->debug.debugfs_phy,
625 priv, &fops_recv);
626 if (!priv->debug.debugfs_recv)
627 goto err;
628
629 return 0;
630
631err:
Sujithe1572c52010-03-24 13:42:13 +0530632 ath9k_htc_exit_debug(ah);
Sujithfb9987d2010-03-17 14:25:25 +0530633 return -ENOMEM;
634}
635
Sujithe1572c52010-03-24 13:42:13 +0530636void ath9k_htc_exit_debug(struct ath_hw *ah)
Sujithfb9987d2010-03-17 14:25:25 +0530637{
638 struct ath_common *common = ath9k_hw_common(ah);
639 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
640
641 debugfs_remove(priv->debug.debugfs_recv);
642 debugfs_remove(priv->debug.debugfs_xmit);
643 debugfs_remove(priv->debug.debugfs_tgt_stats);
644 debugfs_remove(priv->debug.debugfs_phy);
645}
646
Sujithe1572c52010-03-24 13:42:13 +0530647int ath9k_htc_debug_create_root(void)
Sujithfb9987d2010-03-17 14:25:25 +0530648{
649 ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
650 if (!ath9k_debugfs_root)
651 return -ENOENT;
652
653 return 0;
654}
655
Sujithe1572c52010-03-24 13:42:13 +0530656void ath9k_htc_debug_remove_root(void)
Sujithfb9987d2010-03-17 14:25:25 +0530657{
658 debugfs_remove(ath9k_debugfs_root);
659 ath9k_debugfs_root = NULL;
660}
661
662#endif /* CONFIG_ATH9K_HTC_DEBUGFS */
663
664/*******/
665/* ANI */
666/*******/
667
668static void ath_start_ani(struct ath9k_htc_priv *priv)
669{
670 struct ath_common *common = ath9k_hw_common(priv->ah);
671 unsigned long timestamp = jiffies_to_msecs(jiffies);
672
673 common->ani.longcal_timer = timestamp;
674 common->ani.shortcal_timer = timestamp;
675 common->ani.checkani_timer = timestamp;
676
677 ieee80211_queue_delayed_work(common->hw, &priv->ath9k_ani_work,
678 msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
679}
680
681void ath9k_ani_work(struct work_struct *work)
682{
683 struct ath9k_htc_priv *priv =
684 container_of(work, struct ath9k_htc_priv,
685 ath9k_ani_work.work);
686 struct ath_hw *ah = priv->ah;
687 struct ath_common *common = ath9k_hw_common(ah);
688 bool longcal = false;
689 bool shortcal = false;
690 bool aniflag = false;
691 unsigned int timestamp = jiffies_to_msecs(jiffies);
692 u32 cal_interval, short_cal_interval;
693
694 short_cal_interval = ATH_STA_SHORT_CALINTERVAL;
695
696 /* Long calibration runs independently of short calibration. */
697 if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
698 longcal = true;
699 ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
700 common->ani.longcal_timer = timestamp;
701 }
702
703 /* Short calibration applies only while caldone is false */
704 if (!common->ani.caldone) {
705 if ((timestamp - common->ani.shortcal_timer) >=
706 short_cal_interval) {
707 shortcal = true;
708 ath_print(common, ATH_DBG_ANI,
709 "shortcal @%lu\n", jiffies);
710 common->ani.shortcal_timer = timestamp;
711 common->ani.resetcal_timer = timestamp;
712 }
713 } else {
714 if ((timestamp - common->ani.resetcal_timer) >=
715 ATH_RESTART_CALINTERVAL) {
716 common->ani.caldone = ath9k_hw_reset_calvalid(ah);
717 if (common->ani.caldone)
718 common->ani.resetcal_timer = timestamp;
719 }
720 }
721
722 /* Verify whether we must check ANI */
723 if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) {
724 aniflag = true;
725 common->ani.checkani_timer = timestamp;
726 }
727
728 /* Skip all processing if there's nothing to do. */
729 if (longcal || shortcal || aniflag) {
730 /* Call ANI routine if necessary */
731 if (aniflag)
732 ath9k_hw_ani_monitor(ah, ah->curchan);
733
734 /* Perform calibration if necessary */
735 if (longcal || shortcal) {
736 common->ani.caldone =
737 ath9k_hw_calibrate(ah, ah->curchan,
738 common->rx_chainmask,
739 longcal);
740
741 if (longcal)
742 common->ani.noise_floor =
743 ath9k_hw_getchan_noise(ah, ah->curchan);
744
745 ath_print(common, ATH_DBG_ANI,
746 " calibrate chan %u/%x nf: %d\n",
747 ah->curchan->channel,
748 ah->curchan->channelFlags,
749 common->ani.noise_floor);
750 }
751 }
752
753 /*
754 * Set timer interval based on previous results.
755 * The interval must be the shortest necessary to satisfy ANI,
756 * short calibration and long calibration.
757 */
758 cal_interval = ATH_LONG_CALINTERVAL;
759 if (priv->ah->config.enable_ani)
760 cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL);
761 if (!common->ani.caldone)
762 cal_interval = min(cal_interval, (u32)short_cal_interval);
763
764 ieee80211_queue_delayed_work(common->hw, &priv->ath9k_ani_work,
765 msecs_to_jiffies(cal_interval));
766}
767
768/*******/
769/* LED */
770/*******/
771
772static void ath9k_led_blink_work(struct work_struct *work)
773{
774 struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
775 ath9k_led_blink_work.work);
776
777 if (!(priv->op_flags & OP_LED_ASSOCIATED))
778 return;
779
780 if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
781 (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
782 ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
783 else
784 ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
785 (priv->op_flags & OP_LED_ON) ? 1 : 0);
786
787 ieee80211_queue_delayed_work(priv->hw,
788 &priv->ath9k_led_blink_work,
789 (priv->op_flags & OP_LED_ON) ?
790 msecs_to_jiffies(priv->led_off_duration) :
791 msecs_to_jiffies(priv->led_on_duration));
792
793 priv->led_on_duration = priv->led_on_cnt ?
794 max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) :
795 ATH_LED_ON_DURATION_IDLE;
796 priv->led_off_duration = priv->led_off_cnt ?
797 max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) :
798 ATH_LED_OFF_DURATION_IDLE;
799 priv->led_on_cnt = priv->led_off_cnt = 0;
800
801 if (priv->op_flags & OP_LED_ON)
802 priv->op_flags &= ~OP_LED_ON;
803 else
804 priv->op_flags |= OP_LED_ON;
805}
806
807static void ath9k_led_brightness_work(struct work_struct *work)
808{
809 struct ath_led *led = container_of(work, struct ath_led,
810 brightness_work.work);
811 struct ath9k_htc_priv *priv = led->priv;
812
813 switch (led->brightness) {
814 case LED_OFF:
815 if (led->led_type == ATH_LED_ASSOC ||
816 led->led_type == ATH_LED_RADIO) {
817 ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
818 (led->led_type == ATH_LED_RADIO));
819 priv->op_flags &= ~OP_LED_ASSOCIATED;
820 if (led->led_type == ATH_LED_RADIO)
821 priv->op_flags &= ~OP_LED_ON;
822 } else {
823 priv->led_off_cnt++;
824 }
825 break;
826 case LED_FULL:
827 if (led->led_type == ATH_LED_ASSOC) {
828 priv->op_flags |= OP_LED_ASSOCIATED;
829 ieee80211_queue_delayed_work(priv->hw,
830 &priv->ath9k_led_blink_work, 0);
831 } else if (led->led_type == ATH_LED_RADIO) {
832 ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
833 priv->op_flags |= OP_LED_ON;
834 } else {
835 priv->led_on_cnt++;
836 }
837 break;
838 default:
839 break;
840 }
841}
842
843static void ath9k_led_brightness(struct led_classdev *led_cdev,
844 enum led_brightness brightness)
845{
846 struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
847 struct ath9k_htc_priv *priv = led->priv;
848
849 led->brightness = brightness;
850 if (!(priv->op_flags & OP_LED_DEINIT))
851 ieee80211_queue_delayed_work(priv->hw,
852 &led->brightness_work, 0);
853}
854
855static void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv)
856{
857 cancel_delayed_work_sync(&priv->radio_led.brightness_work);
858 cancel_delayed_work_sync(&priv->assoc_led.brightness_work);
859 cancel_delayed_work_sync(&priv->tx_led.brightness_work);
860 cancel_delayed_work_sync(&priv->rx_led.brightness_work);
861}
862
863static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led,
864 char *trigger)
865{
866 int ret;
867
868 led->priv = priv;
869 led->led_cdev.name = led->name;
870 led->led_cdev.default_trigger = trigger;
871 led->led_cdev.brightness_set = ath9k_led_brightness;
872
873 ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev);
874 if (ret)
875 ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL,
876 "Failed to register led:%s", led->name);
877 else
878 led->registered = 1;
879
880 INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work);
881
882 return ret;
883}
884
885static void ath9k_unregister_led(struct ath_led *led)
886{
887 if (led->registered) {
888 led_classdev_unregister(&led->led_cdev);
889 led->registered = 0;
890 }
891}
892
893void ath9k_deinit_leds(struct ath9k_htc_priv *priv)
894{
895 priv->op_flags |= OP_LED_DEINIT;
896 ath9k_unregister_led(&priv->assoc_led);
897 priv->op_flags &= ~OP_LED_ASSOCIATED;
898 ath9k_unregister_led(&priv->tx_led);
899 ath9k_unregister_led(&priv->rx_led);
900 ath9k_unregister_led(&priv->radio_led);
901 ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
902}
903
904void ath9k_init_leds(struct ath9k_htc_priv *priv)
905{
906 char *trigger;
907 int ret;
908
909 if (AR_SREV_9287(priv->ah))
910 priv->ah->led_pin = ATH_LED_PIN_9287;
911 else if (AR_SREV_9271(priv->ah))
912 priv->ah->led_pin = ATH_LED_PIN_9271;
913 else
914 priv->ah->led_pin = ATH_LED_PIN_DEF;
915
916 /* Configure gpio 1 for output */
917 ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin,
918 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
919 /* LED off, active low */
920 ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
921
922 INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work);
923
924 trigger = ieee80211_get_radio_led_name(priv->hw);
925 snprintf(priv->radio_led.name, sizeof(priv->radio_led.name),
926 "ath9k-%s::radio", wiphy_name(priv->hw->wiphy));
927 ret = ath9k_register_led(priv, &priv->radio_led, trigger);
928 priv->radio_led.led_type = ATH_LED_RADIO;
929 if (ret)
930 goto fail;
931
932 trigger = ieee80211_get_assoc_led_name(priv->hw);
933 snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name),
934 "ath9k-%s::assoc", wiphy_name(priv->hw->wiphy));
935 ret = ath9k_register_led(priv, &priv->assoc_led, trigger);
936 priv->assoc_led.led_type = ATH_LED_ASSOC;
937 if (ret)
938 goto fail;
939
940 trigger = ieee80211_get_tx_led_name(priv->hw);
941 snprintf(priv->tx_led.name, sizeof(priv->tx_led.name),
942 "ath9k-%s::tx", wiphy_name(priv->hw->wiphy));
943 ret = ath9k_register_led(priv, &priv->tx_led, trigger);
944 priv->tx_led.led_type = ATH_LED_TX;
945 if (ret)
946 goto fail;
947
948 trigger = ieee80211_get_rx_led_name(priv->hw);
949 snprintf(priv->rx_led.name, sizeof(priv->rx_led.name),
950 "ath9k-%s::rx", wiphy_name(priv->hw->wiphy));
951 ret = ath9k_register_led(priv, &priv->rx_led, trigger);
952 priv->rx_led.led_type = ATH_LED_RX;
953 if (ret)
954 goto fail;
955
956 priv->op_flags &= ~OP_LED_DEINIT;
957
958 return;
959
960fail:
961 cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
962 ath9k_deinit_leds(priv);
963}
964
965/*******************/
966/* Rfkill */
967/*******************/
968
969static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv)
970{
971 return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) ==
972 priv->ah->rfkill_polarity;
973}
974
975static void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw)
976{
977 struct ath9k_htc_priv *priv = hw->priv;
978 bool blocked = !!ath_is_rfkill_set(priv);
979
980 wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
981}
982
983void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
984{
985 if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
986 wiphy_rfkill_start_polling(priv->hw->wiphy);
987}
988
989/**********************/
990/* mac80211 Callbacks */
991/**********************/
992
993static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
994{
995 struct ieee80211_hdr *hdr;
996 struct ath9k_htc_priv *priv = hw->priv;
997 int padpos, padsize;
998
999 hdr = (struct ieee80211_hdr *) skb->data;
1000
1001 /* Add the padding after the header if this is not already done */
1002 padpos = ath9k_cmn_padpos(hdr->frame_control);
1003 padsize = padpos & 3;
1004 if (padsize && skb->len > padpos) {
1005 if (skb_headroom(skb) < padsize)
1006 return -1;
1007 skb_push(skb, padsize);
1008 memmove(skb->data, skb->data + padsize, padpos);
1009 }
1010
1011 if (ath9k_htc_tx_start(priv, skb) != 0) {
1012 ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, "Tx failed");
1013 goto fail_tx;
1014 }
1015
1016 return 0;
1017
1018fail_tx:
1019 dev_kfree_skb_any(skb);
1020 return 0;
1021}
1022
1023static int ath9k_htc_start(struct ieee80211_hw *hw)
1024{
1025 struct ath9k_htc_priv *priv = hw->priv;
1026 struct ath_hw *ah = priv->ah;
1027 struct ath_common *common = ath9k_hw_common(ah);
1028 struct ieee80211_channel *curchan = hw->conf.channel;
1029 struct ath9k_channel *init_channel;
1030 int ret = 0;
1031 enum htc_phymode mode;
1032 u16 htc_mode;
1033 u8 cmd_rsp;
1034
1035 ath_print(common, ATH_DBG_CONFIG,
1036 "Starting driver with initial channel: %d MHz\n",
1037 curchan->center_freq);
1038
1039 mutex_lock(&priv->mutex);
1040
1041 /* setup initial channel */
1042 init_channel = ath9k_cmn_get_curchannel(hw, ah);
1043
1044 /* Reset SERDES registers */
1045 ath9k_hw_configpcipowersave(ah, 0, 0);
1046
1047 ath9k_hw_htc_resetinit(ah);
1048 ret = ath9k_hw_reset(ah, init_channel, false);
1049 if (ret) {
1050 ath_print(common, ATH_DBG_FATAL,
1051 "Unable to reset hardware; reset status %d "
1052 "(freq %u MHz)\n", ret, curchan->center_freq);
1053 goto mutex_unlock;
1054 }
1055
1056 ath_update_txpow(priv);
1057
1058 mode = ath9k_htc_get_curmode(priv, init_channel);
1059 htc_mode = cpu_to_be16(mode);
1060 WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode);
1061 if (ret)
1062 goto mutex_unlock;
1063
1064 WMI_CMD(WMI_ATH_INIT_CMDID);
1065 if (ret)
1066 goto mutex_unlock;
1067
1068 WMI_CMD(WMI_START_RECV_CMDID);
1069 if (ret)
1070 goto mutex_unlock;
1071
1072 ath9k_host_rx_init(priv);
1073
1074 priv->op_flags &= ~OP_INVALID;
1075 htc_start(priv->htc);
1076
1077mutex_unlock:
1078 mutex_unlock(&priv->mutex);
1079 return ret;
1080}
1081
1082static void ath9k_htc_stop(struct ieee80211_hw *hw)
1083{
1084 struct ath9k_htc_priv *priv = hw->priv;
1085 struct ath_hw *ah = priv->ah;
1086 struct ath_common *common = ath9k_hw_common(ah);
1087 int ret = 0;
1088 u8 cmd_rsp;
1089
1090 mutex_lock(&priv->mutex);
1091
1092 if (priv->op_flags & OP_INVALID) {
1093 ath_print(common, ATH_DBG_ANY, "Device not present\n");
1094 mutex_unlock(&priv->mutex);
1095 return;
1096 }
1097
1098 htc_stop(priv->htc);
1099 WMI_CMD(WMI_DISABLE_INTR_CMDID);
1100 WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
1101 WMI_CMD(WMI_STOP_RECV_CMDID);
1102 ath9k_hw_phy_disable(ah);
1103 ath9k_hw_disable(ah);
1104 ath9k_hw_configpcipowersave(ah, 1, 1);
1105 ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
1106
1107 cancel_delayed_work_sync(&priv->ath9k_ani_work);
1108 cancel_delayed_work_sync(&priv->ath9k_aggr_work);
1109 cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
1110 ath9k_led_stop_brightness(priv);
1111 skb_queue_purge(&priv->tx_queue);
1112
1113 /* Remove monitor interface here */
1114 if (ah->opmode == NL80211_IFTYPE_MONITOR) {
1115 if (ath9k_htc_remove_monitor_interface(priv))
1116 ath_print(common, ATH_DBG_FATAL,
1117 "Unable to remove monitor interface\n");
1118 else
1119 ath_print(common, ATH_DBG_CONFIG,
1120 "Monitor interface removed\n");
1121 }
1122
1123 priv->op_flags |= OP_INVALID;
1124 mutex_unlock(&priv->mutex);
1125
1126 ath_print(common, ATH_DBG_CONFIG, "Driver halt\n");
1127}
1128
1129static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
1130 struct ieee80211_vif *vif)
1131{
1132 struct ath9k_htc_priv *priv = hw->priv;
1133 struct ath9k_htc_vif *avp = (void *)vif->drv_priv;
1134 struct ath_common *common = ath9k_hw_common(priv->ah);
1135 struct ath9k_htc_target_vif hvif;
1136 int ret = 0;
1137 u8 cmd_rsp;
1138
1139 mutex_lock(&priv->mutex);
1140
1141 /* Only one interface for now */
1142 if (priv->nvifs > 0) {
1143 ret = -ENOBUFS;
1144 goto out;
1145 }
1146
1147 memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
1148 memcpy(&hvif.myaddr, vif->addr, ETH_ALEN);
1149
1150 switch (vif->type) {
1151 case NL80211_IFTYPE_STATION:
1152 hvif.opmode = cpu_to_be32(HTC_M_STA);
1153 break;
1154 case NL80211_IFTYPE_ADHOC:
1155 hvif.opmode = cpu_to_be32(HTC_M_IBSS);
1156 break;
1157 default:
1158 ath_print(common, ATH_DBG_FATAL,
1159 "Interface type %d not yet supported\n", vif->type);
1160 ret = -EOPNOTSUPP;
1161 goto out;
1162 }
1163
1164 ath_print(common, ATH_DBG_CONFIG,
1165 "Attach a VIF of type: %d\n", vif->type);
1166
1167 priv->ah->opmode = vif->type;
1168
1169 /* Index starts from zero on the target */
1170 avp->index = hvif.index = priv->nvifs;
1171 hvif.rtsthreshold = cpu_to_be16(2304);
1172 WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif);
1173 if (ret)
1174 goto out;
1175
1176 priv->nvifs++;
1177
1178 /*
1179 * We need a node in target to tx mgmt frames
1180 * before association.
1181 */
1182 ret = ath9k_htc_add_station(priv, vif, NULL);
1183 if (ret)
1184 goto out;
1185
1186 ret = ath9k_htc_update_cap_target(priv);
1187 if (ret)
1188 ath_print(common, ATH_DBG_CONFIG, "Failed to update"
1189 " capability in target \n");
1190
1191 priv->vif = vif;
1192out:
1193 mutex_unlock(&priv->mutex);
1194 return ret;
1195}
1196
1197static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
1198 struct ieee80211_vif *vif)
1199{
1200 struct ath9k_htc_priv *priv = hw->priv;
1201 struct ath_common *common = ath9k_hw_common(priv->ah);
1202 struct ath9k_htc_vif *avp = (void *)vif->drv_priv;
1203 struct ath9k_htc_target_vif hvif;
1204 int ret = 0;
1205 u8 cmd_rsp;
1206
1207 ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n");
1208
1209 mutex_lock(&priv->mutex);
1210
1211 memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
1212 memcpy(&hvif.myaddr, vif->addr, ETH_ALEN);
1213 hvif.index = avp->index;
1214 WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
1215 priv->nvifs--;
1216
1217 ath9k_htc_remove_station(priv, vif, NULL);
1218
1219 if (vif->type == NL80211_IFTYPE_ADHOC) {
1220 spin_lock_bh(&priv->beacon_lock);
1221 if (priv->beacon)
1222 dev_kfree_skb_any(priv->beacon);
1223 priv->beacon = NULL;
1224 spin_unlock_bh(&priv->beacon_lock);
1225 }
1226
1227 priv->vif = NULL;
1228
1229 mutex_unlock(&priv->mutex);
1230}
1231
1232static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
1233{
1234 struct ath9k_htc_priv *priv = hw->priv;
1235 struct ath_common *common = ath9k_hw_common(priv->ah);
1236 struct ieee80211_conf *conf = &hw->conf;
1237
1238 mutex_lock(&priv->mutex);
1239
1240 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
1241 struct ieee80211_channel *curchan = hw->conf.channel;
1242 int pos = curchan->hw_value;
1243 bool is_cw40 = false;
1244
1245 ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
1246 curchan->center_freq);
1247
1248 if (check_rc_update(hw, &is_cw40))
1249 ath9k_htc_rc_update(priv, is_cw40);
1250
1251 ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]);
1252
1253 if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
1254 ath_print(common, ATH_DBG_FATAL,
1255 "Unable to set channel\n");
1256 mutex_unlock(&priv->mutex);
1257 return -EINVAL;
1258 }
1259
1260 }
1261
1262 if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
1263 if (conf->flags & IEEE80211_CONF_MONITOR) {
1264 if (ath9k_htc_add_monitor_interface(priv))
1265 ath_print(common, ATH_DBG_FATAL,
1266 "Failed to set monitor mode\n");
1267 else
1268 ath_print(common, ATH_DBG_CONFIG,
1269 "HW opmode set to Monitor mode\n");
1270 }
1271 }
1272
1273 mutex_unlock(&priv->mutex);
1274
1275 return 0;
1276}
1277
1278#define SUPPORTED_FILTERS \
1279 (FIF_PROMISC_IN_BSS | \
1280 FIF_ALLMULTI | \
1281 FIF_CONTROL | \
1282 FIF_PSPOLL | \
1283 FIF_OTHER_BSS | \
1284 FIF_BCN_PRBRESP_PROMISC | \
1285 FIF_FCSFAIL)
1286
1287static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
1288 unsigned int changed_flags,
1289 unsigned int *total_flags,
1290 u64 multicast)
1291{
1292 struct ath9k_htc_priv *priv = hw->priv;
1293 u32 rfilt;
1294
1295 mutex_lock(&priv->mutex);
1296
1297 changed_flags &= SUPPORTED_FILTERS;
1298 *total_flags &= SUPPORTED_FILTERS;
1299
1300 priv->rxfilter = *total_flags;
Sujith0995d112010-03-29 16:07:09 +05301301 rfilt = ath9k_htc_calcrxfilter(priv);
Sujithfb9987d2010-03-17 14:25:25 +05301302 ath9k_hw_setrxfilter(priv->ah, rfilt);
1303
1304 ath_print(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG,
1305 "Set HW RX filter: 0x%x\n", rfilt);
1306
1307 mutex_unlock(&priv->mutex);
1308}
1309
1310static void ath9k_htc_sta_notify(struct ieee80211_hw *hw,
1311 struct ieee80211_vif *vif,
1312 enum sta_notify_cmd cmd,
1313 struct ieee80211_sta *sta)
1314{
1315 struct ath9k_htc_priv *priv = hw->priv;
1316 int ret;
1317
1318 switch (cmd) {
1319 case STA_NOTIFY_ADD:
1320 ret = ath9k_htc_add_station(priv, vif, sta);
1321 if (!ret)
1322 ath9k_htc_init_rate(priv, vif, sta);
1323 break;
1324 case STA_NOTIFY_REMOVE:
1325 ath9k_htc_remove_station(priv, vif, sta);
1326 break;
1327 default:
1328 break;
1329 }
1330}
1331
1332static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue,
1333 const struct ieee80211_tx_queue_params *params)
1334{
1335 struct ath9k_htc_priv *priv = hw->priv;
1336 struct ath_common *common = ath9k_hw_common(priv->ah);
1337 struct ath9k_tx_queue_info qi;
1338 int ret = 0, qnum;
1339
1340 if (queue >= WME_NUM_AC)
1341 return 0;
1342
1343 mutex_lock(&priv->mutex);
1344
1345 memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
1346
1347 qi.tqi_aifs = params->aifs;
1348 qi.tqi_cwmin = params->cw_min;
1349 qi.tqi_cwmax = params->cw_max;
1350 qi.tqi_burstTime = params->txop;
1351
1352 qnum = get_hw_qnum(queue, priv->hwq_map);
1353
1354 ath_print(common, ATH_DBG_CONFIG,
1355 "Configure tx [queue/hwq] [%d/%d], "
1356 "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
1357 queue, qnum, params->aifs, params->cw_min,
1358 params->cw_max, params->txop);
1359
Sujithe1572c52010-03-24 13:42:13 +05301360 ret = ath_htc_txq_update(priv, qnum, &qi);
Sujithfb9987d2010-03-17 14:25:25 +05301361 if (ret)
1362 ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n");
1363
1364 mutex_unlock(&priv->mutex);
1365
1366 return ret;
1367}
1368
1369static int ath9k_htc_set_key(struct ieee80211_hw *hw,
1370 enum set_key_cmd cmd,
1371 struct ieee80211_vif *vif,
1372 struct ieee80211_sta *sta,
1373 struct ieee80211_key_conf *key)
1374{
1375 struct ath9k_htc_priv *priv = hw->priv;
1376 struct ath_common *common = ath9k_hw_common(priv->ah);
1377 int ret = 0;
1378
Sujithe1572c52010-03-24 13:42:13 +05301379 if (htc_modparam_nohwcrypt)
Sujithfb9987d2010-03-17 14:25:25 +05301380 return -ENOSPC;
1381
1382 mutex_lock(&priv->mutex);
1383 ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n");
1384
1385 switch (cmd) {
1386 case SET_KEY:
1387 ret = ath9k_cmn_key_config(common, vif, sta, key);
1388 if (ret >= 0) {
1389 key->hw_key_idx = ret;
1390 /* push IV and Michael MIC generation to stack */
1391 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
1392 if (key->alg == ALG_TKIP)
1393 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
1394 if (priv->ah->sw_mgmt_crypto && key->alg == ALG_CCMP)
1395 key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
1396 ret = 0;
1397 }
1398 break;
1399 case DISABLE_KEY:
1400 ath9k_cmn_key_delete(common, key);
1401 break;
1402 default:
1403 ret = -EINVAL;
1404 }
1405
1406 mutex_unlock(&priv->mutex);
1407
1408 return ret;
1409}
1410
1411static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
1412 struct ieee80211_vif *vif,
1413 struct ieee80211_bss_conf *bss_conf,
1414 u32 changed)
1415{
1416 struct ath9k_htc_priv *priv = hw->priv;
1417 struct ath_hw *ah = priv->ah;
1418 struct ath_common *common = ath9k_hw_common(ah);
1419
1420 mutex_lock(&priv->mutex);
1421
1422 if (changed & BSS_CHANGED_ASSOC) {
1423 common->curaid = bss_conf->assoc ?
1424 bss_conf->aid : 0;
1425 ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
1426 bss_conf->assoc);
1427
1428 if (bss_conf->assoc) {
1429 priv->op_flags |= OP_ASSOCIATED;
1430 ath_start_ani(priv);
1431 } else {
1432 priv->op_flags &= ~OP_ASSOCIATED;
1433 cancel_delayed_work_sync(&priv->ath9k_ani_work);
1434 }
1435 }
1436
1437 if (changed & BSS_CHANGED_BSSID) {
1438 /* Set BSSID */
1439 memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
1440 ath9k_hw_write_associd(ah);
1441
1442 ath_print(common, ATH_DBG_CONFIG,
1443 "BSSID: %pM aid: 0x%x\n",
1444 common->curbssid, common->curaid);
1445 }
1446
1447 if ((changed & BSS_CHANGED_BEACON_INT) ||
1448 (changed & BSS_CHANGED_BEACON) ||
1449 ((changed & BSS_CHANGED_BEACON_ENABLED) &&
1450 bss_conf->enable_beacon)) {
1451 priv->op_flags |= OP_ENABLE_BEACON;
1452 ath9k_htc_beacon_config(priv, vif, bss_conf);
1453 }
1454
1455 if (changed & BSS_CHANGED_BEACON)
1456 ath9k_htc_beacon_update(priv, vif);
1457
1458 if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
1459 !bss_conf->enable_beacon) {
1460 priv->op_flags &= ~OP_ENABLE_BEACON;
1461 ath9k_htc_beacon_config(priv, vif, bss_conf);
1462 }
1463
1464 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
1465 ath_print(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n",
1466 bss_conf->use_short_preamble);
1467 if (bss_conf->use_short_preamble)
1468 priv->op_flags |= OP_PREAMBLE_SHORT;
1469 else
1470 priv->op_flags &= ~OP_PREAMBLE_SHORT;
1471 }
1472
1473 if (changed & BSS_CHANGED_ERP_CTS_PROT) {
1474 ath_print(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n",
1475 bss_conf->use_cts_prot);
1476 if (bss_conf->use_cts_prot &&
1477 hw->conf.channel->band != IEEE80211_BAND_5GHZ)
1478 priv->op_flags |= OP_PROTECT_ENABLE;
1479 else
1480 priv->op_flags &= ~OP_PROTECT_ENABLE;
1481 }
1482
1483 if (changed & BSS_CHANGED_ERP_SLOT) {
1484 if (bss_conf->use_short_slot)
1485 ah->slottime = 9;
1486 else
1487 ah->slottime = 20;
1488
1489 ath9k_hw_init_global_settings(ah);
1490 }
1491
1492 mutex_unlock(&priv->mutex);
1493}
1494
1495static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw)
1496{
1497 struct ath9k_htc_priv *priv = hw->priv;
1498 u64 tsf;
1499
1500 mutex_lock(&priv->mutex);
1501 tsf = ath9k_hw_gettsf64(priv->ah);
1502 mutex_unlock(&priv->mutex);
1503
1504 return tsf;
1505}
1506
1507static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf)
1508{
1509 struct ath9k_htc_priv *priv = hw->priv;
1510
1511 mutex_lock(&priv->mutex);
1512 ath9k_hw_settsf64(priv->ah, tsf);
1513 mutex_unlock(&priv->mutex);
1514}
1515
1516static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw)
1517{
1518 struct ath9k_htc_priv *priv = hw->priv;
1519
1520 mutex_lock(&priv->mutex);
1521 ath9k_hw_reset_tsf(priv->ah);
1522 mutex_unlock(&priv->mutex);
1523}
1524
1525static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
1526 struct ieee80211_vif *vif,
1527 enum ieee80211_ampdu_mlme_action action,
1528 struct ieee80211_sta *sta,
1529 u16 tid, u16 *ssn)
1530{
1531 struct ath9k_htc_priv *priv = hw->priv;
1532 struct ath9k_htc_aggr_work *work = &priv->aggr_work;
1533 struct ath9k_htc_sta *ista;
1534
1535 switch (action) {
1536 case IEEE80211_AMPDU_RX_START:
1537 break;
1538 case IEEE80211_AMPDU_RX_STOP:
1539 break;
1540 case IEEE80211_AMPDU_TX_START:
1541 case IEEE80211_AMPDU_TX_STOP:
1542 if (!(priv->op_flags & OP_TXAGGR))
1543 return -ENOTSUPP;
1544 memcpy(work->sta_addr, sta->addr, ETH_ALEN);
1545 work->hw = hw;
1546 work->vif = vif;
1547 work->action = action;
1548 work->tid = tid;
1549 ieee80211_queue_delayed_work(hw, &priv->ath9k_aggr_work, 0);
1550 break;
1551 case IEEE80211_AMPDU_TX_OPERATIONAL:
1552 ista = (struct ath9k_htc_sta *) sta->drv_priv;
1553 ista->tid_state[tid] = AGGR_OPERATIONAL;
1554 break;
1555 default:
1556 ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL,
1557 "Unknown AMPDU action\n");
1558 }
1559
1560 return 0;
1561}
1562
1563static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw)
1564{
1565 struct ath9k_htc_priv *priv = hw->priv;
1566
1567 mutex_lock(&priv->mutex);
1568 spin_lock_bh(&priv->beacon_lock);
1569 priv->op_flags |= OP_SCANNING;
1570 spin_unlock_bh(&priv->beacon_lock);
1571 cancel_delayed_work_sync(&priv->ath9k_ani_work);
1572 mutex_unlock(&priv->mutex);
1573}
1574
1575static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
1576{
1577 struct ath9k_htc_priv *priv = hw->priv;
1578
1579 mutex_lock(&priv->mutex);
1580 spin_lock_bh(&priv->beacon_lock);
1581 priv->op_flags &= ~OP_SCANNING;
1582 spin_unlock_bh(&priv->beacon_lock);
1583 priv->op_flags |= OP_FULL_RESET;
1584 ath_start_ani(priv);
1585 mutex_unlock(&priv->mutex);
1586}
1587
1588static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
1589{
1590 return 0;
1591}
1592
1593static void ath9k_htc_set_coverage_class(struct ieee80211_hw *hw,
1594 u8 coverage_class)
1595{
1596 struct ath9k_htc_priv *priv = hw->priv;
1597
1598 mutex_lock(&priv->mutex);
1599 priv->ah->coverage_class = coverage_class;
1600 ath9k_hw_init_global_settings(priv->ah);
1601 mutex_unlock(&priv->mutex);
1602}
1603
1604struct ieee80211_ops ath9k_htc_ops = {
1605 .tx = ath9k_htc_tx,
1606 .start = ath9k_htc_start,
1607 .stop = ath9k_htc_stop,
1608 .add_interface = ath9k_htc_add_interface,
1609 .remove_interface = ath9k_htc_remove_interface,
1610 .config = ath9k_htc_config,
1611 .configure_filter = ath9k_htc_configure_filter,
1612 .sta_notify = ath9k_htc_sta_notify,
1613 .conf_tx = ath9k_htc_conf_tx,
1614 .bss_info_changed = ath9k_htc_bss_info_changed,
1615 .set_key = ath9k_htc_set_key,
1616 .get_tsf = ath9k_htc_get_tsf,
1617 .set_tsf = ath9k_htc_set_tsf,
1618 .reset_tsf = ath9k_htc_reset_tsf,
1619 .ampdu_action = ath9k_htc_ampdu_action,
1620 .sw_scan_start = ath9k_htc_sw_scan_start,
1621 .sw_scan_complete = ath9k_htc_sw_scan_complete,
1622 .set_rts_threshold = ath9k_htc_set_rts_threshold,
1623 .rfkill_poll = ath9k_htc_rfkill_poll_state,
1624 .set_coverage_class = ath9k_htc_set_coverage_class,
1625};