blob: 605599eb6d3fc4907e138528fc7bb82c205b28a4 [file] [log] [blame]
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001/*
2 * Copyright (c) 2008 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/* mac80211 and PCI callbacks */
18
19#include <linux/nl80211.h>
20#include "core.h"
21
22#define ATH_PCI_VERSION "0.1"
23
24#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
25#define IEEE80211_ACTION_CAT_HT 7
26#define IEEE80211_ACTION_HT_TXCHWIDTH 0
27
28static char *dev_info = "ath9k";
29
30MODULE_AUTHOR("Atheros Communications");
31MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
32MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
33MODULE_LICENSE("Dual BSD/GPL");
34
35static struct pci_device_id ath_pci_id_table[] __devinitdata = {
36 { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */
37 { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */
38 { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */
39 { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */
40 { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
41 { 0 }
42};
43
44static int ath_get_channel(struct ath_softc *sc,
45 struct ieee80211_channel *chan)
46{
47 int i;
48
49 for (i = 0; i < sc->sc_ah->ah_nchan; i++) {
50 if (sc->sc_ah->ah_channels[i].channel == chan->center_freq)
51 return i;
52 }
53
54 return -1;
55}
56
57static u32 ath_get_extchanmode(struct ath_softc *sc,
58 struct ieee80211_channel *chan)
59{
60 u32 chanmode = 0;
61 u8 ext_chan_offset = sc->sc_ht_info.ext_chan_offset;
62 enum ath9k_ht_macmode tx_chan_width = sc->sc_ht_info.tx_chan_width;
63
64 switch (chan->band) {
65 case IEEE80211_BAND_2GHZ:
66 if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE) &&
67 (tx_chan_width == ATH9K_HT_MACMODE_20))
68 chanmode = CHANNEL_G_HT20;
69 if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) &&
70 (tx_chan_width == ATH9K_HT_MACMODE_2040))
71 chanmode = CHANNEL_G_HT40PLUS;
72 if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) &&
73 (tx_chan_width == ATH9K_HT_MACMODE_2040))
74 chanmode = CHANNEL_G_HT40MINUS;
75 break;
76 case IEEE80211_BAND_5GHZ:
77 if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE) &&
78 (tx_chan_width == ATH9K_HT_MACMODE_20))
79 chanmode = CHANNEL_A_HT20;
80 if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) &&
81 (tx_chan_width == ATH9K_HT_MACMODE_2040))
82 chanmode = CHANNEL_A_HT40PLUS;
83 if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) &&
84 (tx_chan_width == ATH9K_HT_MACMODE_2040))
85 chanmode = CHANNEL_A_HT40MINUS;
86 break;
87 default:
88 break;
89 }
90
91 return chanmode;
92}
93
94
95static int ath_setkey_tkip(struct ath_softc *sc,
96 struct ieee80211_key_conf *key,
97 struct ath9k_keyval *hk,
98 const u8 *addr)
99{
100 u8 *key_rxmic = NULL;
101 u8 *key_txmic = NULL;
102
103 key_txmic = key->key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
104 key_rxmic = key->key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
105
106 if (addr == NULL) {
107 /* Group key installation */
108 memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
109 return ath_keyset(sc, key->keyidx, hk, addr);
110 }
111 if (!sc->sc_splitmic) {
112 /*
113 * data key goes at first index,
114 * the hal handles the MIC keys at index+64.
115 */
116 memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
117 memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
118 return ath_keyset(sc, key->keyidx, hk, addr);
119 }
120 /*
121 * TX key goes at first index, RX key at +32.
122 * The hal handles the MIC keys at index+64.
123 */
124 memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
125 if (!ath_keyset(sc, key->keyidx, hk, NULL)) {
126 /* Txmic entry failed. No need to proceed further */
127 DPRINTF(sc, ATH_DBG_KEYCACHE,
128 "%s Setting TX MIC Key Failed\n", __func__);
129 return 0;
130 }
131
132 memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
133 /* XXX delete tx key on failure? */
134 return ath_keyset(sc, key->keyidx+32, hk, addr);
135}
136
137static int ath_key_config(struct ath_softc *sc,
138 const u8 *addr,
139 struct ieee80211_key_conf *key)
140{
141 struct ieee80211_vif *vif;
142 struct ath9k_keyval hk;
143 const u8 *mac = NULL;
144 int ret = 0;
145 enum ieee80211_if_types opmode;
146
147 memset(&hk, 0, sizeof(hk));
148
149 switch (key->alg) {
150 case ALG_WEP:
151 hk.kv_type = ATH9K_CIPHER_WEP;
152 break;
153 case ALG_TKIP:
154 hk.kv_type = ATH9K_CIPHER_TKIP;
155 break;
156 case ALG_CCMP:
157 hk.kv_type = ATH9K_CIPHER_AES_CCM;
158 break;
159 default:
160 return -EINVAL;
161 }
162
163 hk.kv_len = key->keylen;
164 memcpy(hk.kv_val, key->key, key->keylen);
165
166 if (!sc->sc_vaps[0])
167 return -EIO;
168
169 vif = sc->sc_vaps[0]->av_if_data;
170 opmode = vif->type;
171
172 /*
173 * Strategy:
174 * For _M_STA mc tx, we will not setup a key at all since we never
175 * tx mc.
176 * _M_STA mc rx, we will use the keyID.
177 * for _M_IBSS mc tx, we will use the keyID, and no macaddr.
178 * for _M_IBSS mc rx, we will alloc a slot and plumb the mac of the
179 * peer node. BUT we will plumb a cleartext key so that we can do
180 * perSta default key table lookup in software.
181 */
182 if (is_broadcast_ether_addr(addr)) {
183 switch (opmode) {
184 case IEEE80211_IF_TYPE_STA:
185 /* default key: could be group WPA key
186 * or could be static WEP key */
187 mac = NULL;
188 break;
189 case IEEE80211_IF_TYPE_IBSS:
190 break;
191 case IEEE80211_IF_TYPE_AP:
192 break;
193 default:
194 ASSERT(0);
195 break;
196 }
197 } else {
198 mac = addr;
199 }
200
201 if (key->alg == ALG_TKIP)
202 ret = ath_setkey_tkip(sc, key, &hk, mac);
203 else
204 ret = ath_keyset(sc, key->keyidx, &hk, mac);
205
206 if (!ret)
207 return -EIO;
208
209 sc->sc_keytype = hk.kv_type;
210 return 0;
211}
212
213static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
214{
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700215 int freeslot;
216
Sujithff9b6622008-08-14 13:27:16 +0530217 freeslot = (key->keyidx >= 4) ? 1 : 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700218 ath_key_reset(sc, key->keyidx, freeslot);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700219}
220
221static void setup_ht_cap(struct ieee80211_ht_info *ht_info)
222{
223/* Until mac80211 includes these fields */
224
225#define IEEE80211_HT_CAP_DSSSCCK40 0x1000
226#define IEEE80211_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */
227#define IEEE80211_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */
228
229 ht_info->ht_supported = 1;
230 ht_info->cap = (u16)IEEE80211_HT_CAP_SUP_WIDTH
231 |(u16)IEEE80211_HT_CAP_MIMO_PS
232 |(u16)IEEE80211_HT_CAP_SGI_40
233 |(u16)IEEE80211_HT_CAP_DSSSCCK40;
234
235 ht_info->ampdu_factor = IEEE80211_HT_CAP_MAXRXAMPDU_65536;
236 ht_info->ampdu_density = IEEE80211_HT_CAP_MPDUDENSITY_8;
237 /* setup supported mcs set */
238 memset(ht_info->supp_mcs_set, 0, 16);
239 ht_info->supp_mcs_set[0] = 0xff;
240 ht_info->supp_mcs_set[1] = 0xff;
241 ht_info->supp_mcs_set[12] = IEEE80211_HT_CAP_MCS_TX_DEFINED;
242}
243
244static int ath_rate2idx(struct ath_softc *sc, int rate)
245{
246 int i = 0, cur_band, n_rates;
247 struct ieee80211_hw *hw = sc->hw;
248
249 cur_band = hw->conf.channel->band;
250 n_rates = sc->sbands[cur_band].n_bitrates;
251
252 for (i = 0; i < n_rates; i++) {
253 if (sc->sbands[cur_band].bitrates[i].bitrate == rate)
254 break;
255 }
256
257 /*
258 * NB:mac80211 validates rx rate index against the supported legacy rate
259 * index only (should be done against ht rates also), return the highest
260 * legacy rate index for rx rate which does not match any one of the
261 * supported basic and extended rates to make mac80211 happy.
262 * The following hack will be cleaned up once the issue with
263 * the rx rate index validation in mac80211 is fixed.
264 */
265 if (i == n_rates)
266 return n_rates - 1;
267 return i;
268}
269
270static void ath9k_rx_prepare(struct ath_softc *sc,
271 struct sk_buff *skb,
272 struct ath_recv_status *status,
273 struct ieee80211_rx_status *rx_status)
274{
275 struct ieee80211_hw *hw = sc->hw;
276 struct ieee80211_channel *curchan = hw->conf.channel;
277
278 memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
279
280 rx_status->mactime = status->tsf;
281 rx_status->band = curchan->band;
282 rx_status->freq = curchan->center_freq;
283 rx_status->noise = ATH_DEFAULT_NOISE_FLOOR;
284 rx_status->signal = rx_status->noise + status->rssi;
285 rx_status->rate_idx = ath_rate2idx(sc, (status->rateKbps / 100));
286 rx_status->antenna = status->antenna;
287 rx_status->qual = status->rssi * 100 / 64;
288
289 if (status->flags & ATH_RX_MIC_ERROR)
290 rx_status->flag |= RX_FLAG_MMIC_ERROR;
291 if (status->flags & ATH_RX_FCS_ERROR)
292 rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
293
294 rx_status->flag |= RX_FLAG_TSFT;
295}
296
297static u8 parse_mpdudensity(u8 mpdudensity)
298{
299 /*
300 * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
301 * 0 for no restriction
302 * 1 for 1/4 us
303 * 2 for 1/2 us
304 * 3 for 1 us
305 * 4 for 2 us
306 * 5 for 4 us
307 * 6 for 8 us
308 * 7 for 16 us
309 */
310 switch (mpdudensity) {
311 case 0:
312 return 0;
313 case 1:
314 case 2:
315 case 3:
316 /* Our lower layer calculations limit our precision to
317 1 microsecond */
318 return 1;
319 case 4:
320 return 2;
321 case 5:
322 return 4;
323 case 6:
324 return 8;
325 case 7:
326 return 16;
327 default:
328 return 0;
329 }
330}
331
332static int ath9k_start(struct ieee80211_hw *hw)
333{
334 struct ath_softc *sc = hw->priv;
335 struct ieee80211_channel *curchan = hw->conf.channel;
336 int error = 0, pos;
337
338 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Starting driver with "
339 "initial channel: %d MHz\n", __func__, curchan->center_freq);
340
341 /* setup initial channel */
342
343 pos = ath_get_channel(sc, curchan);
344 if (pos == -1) {
345 DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__);
346 return -EINVAL;
347 }
348
349 sc->sc_ah->ah_channels[pos].chanmode =
350 (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A;
351
352 /* open ath_dev */
353 error = ath_open(sc, &sc->sc_ah->ah_channels[pos]);
354 if (error) {
355 DPRINTF(sc, ATH_DBG_FATAL,
356 "%s: Unable to complete ath_open\n", __func__);
357 return error;
358 }
359
360 ieee80211_wake_queues(hw);
361 return 0;
362}
363
364static int ath9k_tx(struct ieee80211_hw *hw,
365 struct sk_buff *skb)
366{
367 struct ath_softc *sc = hw->priv;
368 int hdrlen, padsize;
Jouni Malinen147583c2008-08-11 14:01:50 +0300369 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
370
371 /*
372 * As a temporary workaround, assign seq# here; this will likely need
373 * to be cleaned up to work better with Beacon transmission and virtual
374 * BSSes.
375 */
376 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
377 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
378 if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
379 sc->seq_no += 0x10;
380 hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
381 hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
382 }
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700383
384 /* Add the padding after the header if this is not already done */
385 hdrlen = ieee80211_get_hdrlen_from_skb(skb);
386 if (hdrlen & 3) {
387 padsize = hdrlen % 4;
388 if (skb_headroom(skb) < padsize)
389 return -1;
390 skb_push(skb, padsize);
391 memmove(skb->data, skb->data + padsize, hdrlen);
392 }
393
394 DPRINTF(sc, ATH_DBG_XMIT, "%s: transmitting packet, skb: %p\n",
395 __func__,
396 skb);
397
398 if (ath_tx_start(sc, skb) != 0) {
399 DPRINTF(sc, ATH_DBG_XMIT, "%s: TX failed\n", __func__);
400 dev_kfree_skb_any(skb);
401 /* FIXME: Check for proper return value from ATH_DEV */
402 return 0;
403 }
404
405 return 0;
406}
407
408static void ath9k_stop(struct ieee80211_hw *hw)
409{
410 struct ath_softc *sc = hw->priv;
411 int error;
412
413 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Driver halt\n", __func__);
414
415 error = ath_suspend(sc);
416 if (error)
417 DPRINTF(sc, ATH_DBG_CONFIG,
418 "%s: Device is no longer present\n", __func__);
419
420 ieee80211_stop_queues(hw);
421}
422
423static int ath9k_add_interface(struct ieee80211_hw *hw,
424 struct ieee80211_if_init_conf *conf)
425{
426 struct ath_softc *sc = hw->priv;
427 int error, ic_opmode = 0;
428
429 /* Support only vap for now */
430
431 if (sc->sc_nvaps)
432 return -ENOBUFS;
433
434 switch (conf->type) {
435 case IEEE80211_IF_TYPE_STA:
436 ic_opmode = ATH9K_M_STA;
437 break;
438 case IEEE80211_IF_TYPE_IBSS:
439 ic_opmode = ATH9K_M_IBSS;
440 break;
Jouni Malinen2ad67de2008-08-11 14:01:47 +0300441 case IEEE80211_IF_TYPE_AP:
442 ic_opmode = ATH9K_M_HOSTAP;
443 break;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700444 default:
445 DPRINTF(sc, ATH_DBG_FATAL,
Jouni Malinen2ad67de2008-08-11 14:01:47 +0300446 "%s: Interface type %d not yet supported\n",
447 __func__, conf->type);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700448 return -EOPNOTSUPP;
449 }
450
451 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a VAP of type: %d\n",
452 __func__,
453 ic_opmode);
454
455 error = ath_vap_attach(sc, 0, conf->vif, ic_opmode);
456 if (error) {
457 DPRINTF(sc, ATH_DBG_FATAL,
458 "%s: Unable to attach vap, error: %d\n",
459 __func__, error);
460 return error;
461 }
462
463 return 0;
464}
465
466static void ath9k_remove_interface(struct ieee80211_hw *hw,
467 struct ieee80211_if_init_conf *conf)
468{
469 struct ath_softc *sc = hw->priv;
470 struct ath_vap *avp;
471 int error;
472
473 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach VAP\n", __func__);
474
475 avp = sc->sc_vaps[0];
476 if (avp == NULL) {
477 DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
478 __func__);
479 return;
480 }
481
482#ifdef CONFIG_SLOW_ANT_DIV
483 ath_slow_ant_div_stop(&sc->sc_antdiv);
484#endif
485
486 /* Update ratectrl */
487 ath_rate_newstate(sc, avp);
488
489 /* Reclaim beacon resources */
Sujithb4696c8b2008-08-11 14:04:52 +0530490 if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP ||
491 sc->sc_ah->ah_opmode == ATH9K_M_IBSS) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700492 ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
493 ath_beacon_return(sc, avp);
494 }
495
496 /* Set interrupt mask */
497 sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
498 ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask & ~ATH9K_INT_GLOBAL);
Sujith672840a2008-08-11 14:05:08 +0530499 sc->sc_flags &= ~SC_OP_BEACONS;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700500
501 error = ath_vap_detach(sc, 0);
502 if (error)
503 DPRINTF(sc, ATH_DBG_FATAL,
504 "%s: Unable to detach vap, error: %d\n",
505 __func__, error);
506}
507
508static int ath9k_config(struct ieee80211_hw *hw,
509 struct ieee80211_conf *conf)
510{
511 struct ath_softc *sc = hw->priv;
512 struct ieee80211_channel *curchan = hw->conf.channel;
513 int pos;
514
515 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
516 __func__,
517 curchan->center_freq);
518
519 pos = ath_get_channel(sc, curchan);
520 if (pos == -1) {
521 DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__);
522 return -EINVAL;
523 }
524
525 sc->sc_ah->ah_channels[pos].chanmode =
Sujith86b89ee2008-08-07 10:54:57 +0530526 (curchan->band == IEEE80211_BAND_2GHZ) ?
527 CHANNEL_G : CHANNEL_A;
528
529 if (sc->sc_curaid && hw->conf.ht_conf.ht_supported)
530 sc->sc_ah->ah_channels[pos].chanmode =
531 ath_get_extchanmode(sc, curchan);
532
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700533 sc->sc_config.txpowlimit = 2 * conf->power_level;
534
535 /* set h/w channel */
536 if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0)
537 DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to set channel\n",
538 __func__);
539
540 return 0;
541}
542
543static int ath9k_config_interface(struct ieee80211_hw *hw,
544 struct ieee80211_vif *vif,
545 struct ieee80211_if_conf *conf)
546{
547 struct ath_softc *sc = hw->priv;
Jouni Malinen2ad67de2008-08-11 14:01:47 +0300548 struct ath_hal *ah = sc->sc_ah;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700549 struct ath_vap *avp;
550 u32 rfilt = 0;
551 int error, i;
552 DECLARE_MAC_BUF(mac);
553
554 avp = sc->sc_vaps[0];
555 if (avp == NULL) {
556 DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
557 __func__);
558 return -EINVAL;
559 }
560
Jouni Malinen2ad67de2008-08-11 14:01:47 +0300561 /* TODO: Need to decide which hw opmode to use for multi-interface
562 * cases */
563 if (vif->type == IEEE80211_IF_TYPE_AP &&
564 ah->ah_opmode != ATH9K_M_HOSTAP) {
565 ah->ah_opmode = ATH9K_M_HOSTAP;
566 ath9k_hw_setopmode(ah);
567 ath9k_hw_write_associd(ah, sc->sc_myaddr, 0);
568 /* Request full reset to get hw opmode changed properly */
569 sc->sc_flags |= SC_OP_FULL_RESET;
570 }
571
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700572 if ((conf->changed & IEEE80211_IFCC_BSSID) &&
573 !is_zero_ether_addr(conf->bssid)) {
574 switch (vif->type) {
575 case IEEE80211_IF_TYPE_STA:
576 case IEEE80211_IF_TYPE_IBSS:
577 /* Update ratectrl about the new state */
578 ath_rate_newstate(sc, avp);
579
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700580 /* Set BSSID */
581 memcpy(sc->sc_curbssid, conf->bssid, ETH_ALEN);
582 sc->sc_curaid = 0;
583 ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid,
584 sc->sc_curaid);
585
586 /* Set aggregation protection mode parameters */
587 sc->sc_config.ath_aggr_prot = 0;
588
589 /*
590 * Reset our TSF so that its value is lower than the
591 * beacon that we are trying to catch.
592 * Only then hw will update its TSF register with the
593 * new beacon. Reset the TSF before setting the BSSID
594 * to avoid allowing in any frames that would update
595 * our TSF only to have us clear it
596 * immediately thereafter.
597 */
598 ath9k_hw_reset_tsf(sc->sc_ah);
599
600 /* Disable BMISS interrupt when we're not associated */
601 ath9k_hw_set_interrupts(sc->sc_ah,
602 sc->sc_imask &
603 ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS));
604 sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
605
606 DPRINTF(sc, ATH_DBG_CONFIG,
607 "%s: RX filter 0x%x bssid %s aid 0x%x\n",
608 __func__, rfilt,
609 print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
610
611 /* need to reconfigure the beacon */
Sujith672840a2008-08-11 14:05:08 +0530612 sc->sc_flags &= ~SC_OP_BEACONS ;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700613
614 break;
615 default:
616 break;
617 }
618 }
619
620 if ((conf->changed & IEEE80211_IFCC_BEACON) &&
Sujithff9b6622008-08-14 13:27:16 +0530621 ((vif->type == IEEE80211_IF_TYPE_IBSS) ||
622 (vif->type == IEEE80211_IF_TYPE_AP))) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700623 /*
624 * Allocate and setup the beacon frame.
625 *
626 * Stop any previous beacon DMA. This may be
627 * necessary, for example, when an ibss merge
628 * causes reconfiguration; we may be called
629 * with beacon transmission active.
630 */
631 ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
632
633 error = ath_beacon_alloc(sc, 0);
634 if (error != 0)
635 return error;
636
637 ath_beacon_sync(sc, 0);
638 }
639
640 /* Check for WLAN_CAPABILITY_PRIVACY ? */
641 if ((avp->av_opmode != IEEE80211_IF_TYPE_STA)) {
642 for (i = 0; i < IEEE80211_WEP_NKID; i++)
643 if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i))
644 ath9k_hw_keysetmac(sc->sc_ah,
645 (u16)i,
646 sc->sc_curbssid);
647 }
648
649 /* Only legacy IBSS for now */
650 if (vif->type == IEEE80211_IF_TYPE_IBSS)
651 ath_update_chainmask(sc, 0);
652
653 return 0;
654}
655
656#define SUPPORTED_FILTERS \
657 (FIF_PROMISC_IN_BSS | \
658 FIF_ALLMULTI | \
659 FIF_CONTROL | \
660 FIF_OTHER_BSS | \
661 FIF_BCN_PRBRESP_PROMISC | \
662 FIF_FCSFAIL)
663
Sujith7dcfdcd2008-08-11 14:03:13 +0530664/* FIXME: sc->sc_full_reset ? */
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700665static void ath9k_configure_filter(struct ieee80211_hw *hw,
666 unsigned int changed_flags,
667 unsigned int *total_flags,
668 int mc_count,
669 struct dev_mc_list *mclist)
670{
671 struct ath_softc *sc = hw->priv;
Sujith7dcfdcd2008-08-11 14:03:13 +0530672 u32 rfilt;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700673
674 changed_flags &= SUPPORTED_FILTERS;
675 *total_flags &= SUPPORTED_FILTERS;
676
Sujith7dcfdcd2008-08-11 14:03:13 +0530677 sc->rx_filter = *total_flags;
678 rfilt = ath_calcrxfilter(sc);
679 ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
680
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700681 if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
682 if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
Sujith7dcfdcd2008-08-11 14:03:13 +0530683 ath9k_hw_write_associd(sc->sc_ah, ath_bcast_mac, 0);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700684 }
Sujith7dcfdcd2008-08-11 14:03:13 +0530685
686 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set HW RX filter: 0x%x\n",
687 __func__, sc->rx_filter);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700688}
689
690static void ath9k_sta_notify(struct ieee80211_hw *hw,
691 struct ieee80211_vif *vif,
692 enum sta_notify_cmd cmd,
693 const u8 *addr)
694{
695 struct ath_softc *sc = hw->priv;
696 struct ath_node *an;
697 unsigned long flags;
698 DECLARE_MAC_BUF(mac);
699
700 spin_lock_irqsave(&sc->node_lock, flags);
701 an = ath_node_find(sc, (u8 *) addr);
702 spin_unlock_irqrestore(&sc->node_lock, flags);
703
704 switch (cmd) {
705 case STA_NOTIFY_ADD:
706 spin_lock_irqsave(&sc->node_lock, flags);
707 if (!an) {
708 ath_node_attach(sc, (u8 *)addr, 0);
709 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %s\n",
710 __func__,
711 print_mac(mac, addr));
712 } else {
713 ath_node_get(sc, (u8 *)addr);
714 }
715 spin_unlock_irqrestore(&sc->node_lock, flags);
716 break;
717 case STA_NOTIFY_REMOVE:
718 if (!an)
719 DPRINTF(sc, ATH_DBG_FATAL,
720 "%s: Removal of a non-existent node\n",
721 __func__);
722 else {
723 ath_node_put(sc, an, ATH9K_BH_STATUS_INTACT);
724 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Put a node: %s\n",
725 __func__,
726 print_mac(mac, addr));
727 }
728 break;
729 default:
730 break;
731 }
732}
733
734static int ath9k_conf_tx(struct ieee80211_hw *hw,
735 u16 queue,
736 const struct ieee80211_tx_queue_params *params)
737{
738 struct ath_softc *sc = hw->priv;
Sujithea9880f2008-08-07 10:53:10 +0530739 struct ath9k_tx_queue_info qi;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700740 int ret = 0, qnum;
741
742 if (queue >= WME_NUM_AC)
743 return 0;
744
745 qi.tqi_aifs = params->aifs;
746 qi.tqi_cwmin = params->cw_min;
747 qi.tqi_cwmax = params->cw_max;
748 qi.tqi_burstTime = params->txop;
749 qnum = ath_get_hal_qnum(queue, sc);
750
751 DPRINTF(sc, ATH_DBG_CONFIG,
752 "%s: Configure tx [queue/halq] [%d/%d], "
753 "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
754 __func__,
755 queue,
756 qnum,
757 params->aifs,
758 params->cw_min,
759 params->cw_max,
760 params->txop);
761
762 ret = ath_txq_update(sc, qnum, &qi);
763 if (ret)
764 DPRINTF(sc, ATH_DBG_FATAL,
765 "%s: TXQ Update failed\n", __func__);
766
767 return ret;
768}
769
770static int ath9k_set_key(struct ieee80211_hw *hw,
771 enum set_key_cmd cmd,
772 const u8 *local_addr,
773 const u8 *addr,
774 struct ieee80211_key_conf *key)
775{
776 struct ath_softc *sc = hw->priv;
777 int ret = 0;
778
779 DPRINTF(sc, ATH_DBG_KEYCACHE, " %s: Set HW Key\n", __func__);
780
781 switch (cmd) {
782 case SET_KEY:
783 ret = ath_key_config(sc, addr, key);
784 if (!ret) {
785 set_bit(key->keyidx, sc->sc_keymap);
786 key->hw_key_idx = key->keyidx;
787 /* push IV and Michael MIC generation to stack */
788 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
789 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
790 }
791 break;
792 case DISABLE_KEY:
793 ath_key_delete(sc, key);
794 clear_bit(key->keyidx, sc->sc_keymap);
795 sc->sc_keytype = ATH9K_CIPHER_CLR;
796 break;
797 default:
798 ret = -EINVAL;
799 }
800
801 return ret;
802}
803
804static void ath9k_ht_conf(struct ath_softc *sc,
805 struct ieee80211_bss_conf *bss_conf)
806{
807#define IEEE80211_HT_CAP_40MHZ_INTOLERANT BIT(14)
808 struct ath_ht_info *ht_info = &sc->sc_ht_info;
809
810 if (bss_conf->assoc_ht) {
811 ht_info->ext_chan_offset =
812 bss_conf->ht_bss_conf->bss_cap &
813 IEEE80211_HT_IE_CHA_SEC_OFFSET;
814
815 if (!(bss_conf->ht_conf->cap &
816 IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
817 (bss_conf->ht_bss_conf->bss_cap &
818 IEEE80211_HT_IE_CHA_WIDTH))
819 ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040;
820 else
821 ht_info->tx_chan_width = ATH9K_HT_MACMODE_20;
822
823 ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width);
824 ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
825 bss_conf->ht_conf->ampdu_factor);
826 ht_info->mpdudensity =
827 parse_mpdudensity(bss_conf->ht_conf->ampdu_density);
828
829 }
830
831#undef IEEE80211_HT_CAP_40MHZ_INTOLERANT
832}
833
834static void ath9k_bss_assoc_info(struct ath_softc *sc,
835 struct ieee80211_bss_conf *bss_conf)
836{
837 struct ieee80211_hw *hw = sc->hw;
838 struct ieee80211_channel *curchan = hw->conf.channel;
839 struct ath_vap *avp;
840 int pos;
841 DECLARE_MAC_BUF(mac);
842
843 if (bss_conf->assoc) {
844 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Bss Info ASSOC %d\n",
845 __func__,
846 bss_conf->aid);
847
848 avp = sc->sc_vaps[0];
849 if (avp == NULL) {
850 DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
851 __func__);
852 return;
853 }
854
855 /* New association, store aid */
856 if (avp->av_opmode == ATH9K_M_STA) {
857 sc->sc_curaid = bss_conf->aid;
858 ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid,
859 sc->sc_curaid);
860 }
861
862 /* Configure the beacon */
863 ath_beacon_config(sc, 0);
Sujith672840a2008-08-11 14:05:08 +0530864 sc->sc_flags |= SC_OP_BEACONS;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700865
866 /* Reset rssi stats */
867 sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
868 sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
869 sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
870 sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER;
871
872 /* Update chainmask */
873 ath_update_chainmask(sc, bss_conf->assoc_ht);
874
875 DPRINTF(sc, ATH_DBG_CONFIG,
876 "%s: bssid %s aid 0x%x\n",
877 __func__,
878 print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
879
880 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
881 __func__,
882 curchan->center_freq);
883
884 pos = ath_get_channel(sc, curchan);
885 if (pos == -1) {
886 DPRINTF(sc, ATH_DBG_FATAL,
887 "%s: Invalid channel\n", __func__);
888 return;
889 }
890
891 if (hw->conf.ht_conf.ht_supported)
892 sc->sc_ah->ah_channels[pos].chanmode =
893 ath_get_extchanmode(sc, curchan);
894 else
895 sc->sc_ah->ah_channels[pos].chanmode =
896 (curchan->band == IEEE80211_BAND_2GHZ) ?
897 CHANNEL_G : CHANNEL_A;
898
899 /* set h/w channel */
900 if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0)
901 DPRINTF(sc, ATH_DBG_FATAL,
902 "%s: Unable to set channel\n",
903 __func__);
904
905 ath_rate_newstate(sc, avp);
906 /* Update ratectrl about the new state */
907 ath_rc_node_update(hw, avp->rc_node);
908 } else {
909 DPRINTF(sc, ATH_DBG_CONFIG,
910 "%s: Bss Info DISSOC\n", __func__);
911 sc->sc_curaid = 0;
912 }
913}
914
915static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
916 struct ieee80211_vif *vif,
917 struct ieee80211_bss_conf *bss_conf,
918 u32 changed)
919{
920 struct ath_softc *sc = hw->priv;
921
922 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
923 DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed PREAMBLE %d\n",
924 __func__,
925 bss_conf->use_short_preamble);
926 if (bss_conf->use_short_preamble)
Sujith672840a2008-08-11 14:05:08 +0530927 sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700928 else
Sujith672840a2008-08-11 14:05:08 +0530929 sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700930 }
931
932 if (changed & BSS_CHANGED_ERP_CTS_PROT) {
933 DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed CTS PROT %d\n",
934 __func__,
935 bss_conf->use_cts_prot);
936 if (bss_conf->use_cts_prot &&
937 hw->conf.channel->band != IEEE80211_BAND_5GHZ)
Sujith672840a2008-08-11 14:05:08 +0530938 sc->sc_flags |= SC_OP_PROTECT_ENABLE;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700939 else
Sujith672840a2008-08-11 14:05:08 +0530940 sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700941 }
942
943 if (changed & BSS_CHANGED_HT) {
944 DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed HT %d\n",
945 __func__,
946 bss_conf->assoc_ht);
947 ath9k_ht_conf(sc, bss_conf);
948 }
949
950 if (changed & BSS_CHANGED_ASSOC) {
951 DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed ASSOC %d\n",
952 __func__,
953 bss_conf->assoc);
954 ath9k_bss_assoc_info(sc, bss_conf);
955 }
956}
957
958static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
959{
960 u64 tsf;
961 struct ath_softc *sc = hw->priv;
962 struct ath_hal *ah = sc->sc_ah;
963
964 tsf = ath9k_hw_gettsf64(ah);
965
966 return tsf;
967}
968
969static void ath9k_reset_tsf(struct ieee80211_hw *hw)
970{
971 struct ath_softc *sc = hw->priv;
972 struct ath_hal *ah = sc->sc_ah;
973
974 ath9k_hw_reset_tsf(ah);
975}
976
977static int ath9k_ampdu_action(struct ieee80211_hw *hw,
978 enum ieee80211_ampdu_mlme_action action,
979 const u8 *addr,
980 u16 tid,
981 u16 *ssn)
982{
983 struct ath_softc *sc = hw->priv;
984 int ret = 0;
985
986 switch (action) {
987 case IEEE80211_AMPDU_RX_START:
988 ret = ath_rx_aggr_start(sc, addr, tid, ssn);
989 if (ret < 0)
990 DPRINTF(sc, ATH_DBG_FATAL,
991 "%s: Unable to start RX aggregation\n",
992 __func__);
993 break;
994 case IEEE80211_AMPDU_RX_STOP:
995 ret = ath_rx_aggr_stop(sc, addr, tid);
996 if (ret < 0)
997 DPRINTF(sc, ATH_DBG_FATAL,
998 "%s: Unable to stop RX aggregation\n",
999 __func__);
1000 break;
1001 case IEEE80211_AMPDU_TX_START:
1002 ret = ath_tx_aggr_start(sc, addr, tid, ssn);
1003 if (ret < 0)
1004 DPRINTF(sc, ATH_DBG_FATAL,
1005 "%s: Unable to start TX aggregation\n",
1006 __func__);
1007 else
1008 ieee80211_start_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid);
1009 break;
1010 case IEEE80211_AMPDU_TX_STOP:
1011 ret = ath_tx_aggr_stop(sc, addr, tid);
1012 if (ret < 0)
1013 DPRINTF(sc, ATH_DBG_FATAL,
1014 "%s: Unable to stop TX aggregation\n",
1015 __func__);
1016
1017 ieee80211_stop_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid);
1018 break;
1019 default:
1020 DPRINTF(sc, ATH_DBG_FATAL,
1021 "%s: Unknown AMPDU action\n", __func__);
1022 }
1023
1024 return ret;
1025}
1026
1027static struct ieee80211_ops ath9k_ops = {
1028 .tx = ath9k_tx,
1029 .start = ath9k_start,
1030 .stop = ath9k_stop,
1031 .add_interface = ath9k_add_interface,
1032 .remove_interface = ath9k_remove_interface,
1033 .config = ath9k_config,
1034 .config_interface = ath9k_config_interface,
1035 .configure_filter = ath9k_configure_filter,
1036 .get_stats = NULL,
1037 .sta_notify = ath9k_sta_notify,
1038 .conf_tx = ath9k_conf_tx,
1039 .get_tx_stats = NULL,
1040 .bss_info_changed = ath9k_bss_info_changed,
1041 .set_tim = NULL,
1042 .set_key = ath9k_set_key,
1043 .hw_scan = NULL,
1044 .get_tkip_seq = NULL,
1045 .set_rts_threshold = NULL,
1046 .set_frag_threshold = NULL,
1047 .set_retry_limit = NULL,
1048 .get_tsf = ath9k_get_tsf,
1049 .reset_tsf = ath9k_reset_tsf,
1050 .tx_last_beacon = NULL,
1051 .ampdu_action = ath9k_ampdu_action
1052};
1053
1054void ath_get_beaconconfig(struct ath_softc *sc,
1055 int if_id,
1056 struct ath_beacon_config *conf)
1057{
1058 struct ieee80211_hw *hw = sc->hw;
1059
1060 /* fill in beacon config data */
1061
1062 conf->beacon_interval = hw->conf.beacon_int;
1063 conf->listen_interval = 100;
1064 conf->dtim_count = 1;
1065 conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval;
1066}
1067
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001068void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
1069 struct ath_xmit_status *tx_status, struct ath_node *an)
1070{
1071 struct ieee80211_hw *hw = sc->hw;
1072 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
1073
1074 DPRINTF(sc, ATH_DBG_XMIT,
1075 "%s: TX complete: skb: %p\n", __func__, skb);
1076
1077 if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK ||
1078 tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
1079 /* free driver's private data area of tx_info */
1080 if (tx_info->driver_data[0] != NULL)
1081 kfree(tx_info->driver_data[0]);
1082 tx_info->driver_data[0] = NULL;
1083 }
1084
1085 if (tx_status->flags & ATH_TX_BAR) {
1086 tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
1087 tx_status->flags &= ~ATH_TX_BAR;
1088 }
Jouni Malinen580f0b82008-08-11 14:01:49 +03001089
1090 if (tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY)) {
1091 if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
1092 /* Frame was not ACKed, but an ACK was expected */
1093 tx_info->status.excessive_retries = 1;
1094 }
1095 } else {
1096 /* Frame was ACKed */
1097 tx_info->flags |= IEEE80211_TX_STAT_ACK;
1098 }
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001099
1100 tx_info->status.retry_count = tx_status->retries;
1101
1102 ieee80211_tx_status(hw, skb);
1103 if (an)
1104 ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE);
1105}
1106
1107int ath__rx_indicate(struct ath_softc *sc,
1108 struct sk_buff *skb,
1109 struct ath_recv_status *status,
1110 u16 keyix)
1111{
1112 struct ieee80211_hw *hw = sc->hw;
1113 struct ath_node *an = NULL;
1114 struct ieee80211_rx_status rx_status;
1115 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1116 int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
1117 int padsize;
1118 enum ATH_RX_TYPE st;
1119
1120 /* see if any padding is done by the hw and remove it */
1121 if (hdrlen & 3) {
1122 padsize = hdrlen % 4;
1123 memmove(skb->data + padsize, skb->data, hdrlen);
1124 skb_pull(skb, padsize);
1125 }
1126
1127 /* remove FCS before passing up to protocol stack */
1128 skb_trim(skb, (skb->len - FCS_LEN));
1129
1130 /* Prepare rx status */
1131 ath9k_rx_prepare(sc, skb, status, &rx_status);
1132
1133 if (!(keyix == ATH9K_RXKEYIX_INVALID) &&
1134 !(status->flags & ATH_RX_DECRYPT_ERROR)) {
1135 rx_status.flag |= RX_FLAG_DECRYPTED;
1136 } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED)
1137 && !(status->flags & ATH_RX_DECRYPT_ERROR)
1138 && skb->len >= hdrlen + 4) {
1139 keyix = skb->data[hdrlen + 3] >> 6;
1140
1141 if (test_bit(keyix, sc->sc_keymap))
1142 rx_status.flag |= RX_FLAG_DECRYPTED;
1143 }
1144
1145 spin_lock_bh(&sc->node_lock);
1146 an = ath_node_find(sc, hdr->addr2);
1147 spin_unlock_bh(&sc->node_lock);
1148
1149 if (an) {
1150 ath_rx_input(sc, an,
1151 hw->conf.ht_conf.ht_supported,
1152 skb, status, &st);
1153 }
1154 if (!an || (st != ATH_RX_CONSUMED))
1155 __ieee80211_rx(hw, skb, &rx_status);
1156
1157 return 0;
1158}
1159
1160int ath_rx_subframe(struct ath_node *an,
1161 struct sk_buff *skb,
1162 struct ath_recv_status *status)
1163{
1164 struct ath_softc *sc = an->an_sc;
1165 struct ieee80211_hw *hw = sc->hw;
1166 struct ieee80211_rx_status rx_status;
1167
1168 /* Prepare rx status */
1169 ath9k_rx_prepare(sc, skb, status, &rx_status);
1170 if (!(status->flags & ATH_RX_DECRYPT_ERROR))
1171 rx_status.flag |= RX_FLAG_DECRYPTED;
1172
1173 __ieee80211_rx(hw, skb, &rx_status);
1174
1175 return 0;
1176}
1177
1178enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc)
1179{
1180 return sc->sc_ht_info.tx_chan_width;
1181}
1182
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001183static int ath_detach(struct ath_softc *sc)
1184{
1185 struct ieee80211_hw *hw = sc->hw;
1186
1187 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__);
1188
1189 /* Unregister hw */
1190
1191 ieee80211_unregister_hw(hw);
1192
1193 /* unregister Rate control */
1194 ath_rate_control_unregister();
1195
1196 /* tx/rx cleanup */
1197
1198 ath_rx_cleanup(sc);
1199 ath_tx_cleanup(sc);
1200
1201 /* Deinit */
1202
1203 ath_deinit(sc);
1204
1205 return 0;
1206}
1207
1208static int ath_attach(u16 devid,
1209 struct ath_softc *sc)
1210{
1211 struct ieee80211_hw *hw = sc->hw;
1212 int error = 0;
1213
1214 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach ATH hw\n", __func__);
1215
1216 error = ath_init(devid, sc);
1217 if (error != 0)
1218 return error;
1219
1220 /* Init nodes */
1221
1222 INIT_LIST_HEAD(&sc->node_list);
1223 spin_lock_init(&sc->node_lock);
1224
1225 /* get mac address from hardware and set in mac80211 */
1226
1227 SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr);
1228
1229 /* setup channels and rates */
1230
1231 sc->sbands[IEEE80211_BAND_2GHZ].channels =
1232 sc->channels[IEEE80211_BAND_2GHZ];
1233 sc->sbands[IEEE80211_BAND_2GHZ].bitrates =
1234 sc->rates[IEEE80211_BAND_2GHZ];
1235 sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
1236
Sujith60b67f52008-08-07 10:52:38 +05301237 if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001238 /* Setup HT capabilities for 2.4Ghz*/
1239 setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_info);
1240
1241 hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
1242 &sc->sbands[IEEE80211_BAND_2GHZ];
1243
Sujith86b89ee2008-08-07 10:54:57 +05301244 if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001245 sc->sbands[IEEE80211_BAND_5GHZ].channels =
1246 sc->channels[IEEE80211_BAND_5GHZ];
1247 sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
1248 sc->rates[IEEE80211_BAND_5GHZ];
1249 sc->sbands[IEEE80211_BAND_5GHZ].band =
1250 IEEE80211_BAND_5GHZ;
1251
Sujith60b67f52008-08-07 10:52:38 +05301252 if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001253 /* Setup HT capabilities for 5Ghz*/
1254 setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_info);
1255
1256 hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
1257 &sc->sbands[IEEE80211_BAND_5GHZ];
1258 }
1259
1260 /* FIXME: Have to figure out proper hw init values later */
1261
1262 hw->queues = 4;
1263 hw->ampdu_queues = 1;
1264
1265 /* Register rate control */
1266 hw->rate_control_algorithm = "ath9k_rate_control";
1267 error = ath_rate_control_register();
1268 if (error != 0) {
1269 DPRINTF(sc, ATH_DBG_FATAL,
1270 "%s: Unable to register rate control "
1271 "algorithm:%d\n", __func__, error);
1272 ath_rate_control_unregister();
1273 goto bad;
1274 }
1275
1276 error = ieee80211_register_hw(hw);
1277 if (error != 0) {
1278 ath_rate_control_unregister();
1279 goto bad;
1280 }
1281
1282 /* initialize tx/rx engine */
1283
1284 error = ath_tx_init(sc, ATH_TXBUF);
1285 if (error != 0)
1286 goto bad1;
1287
1288 error = ath_rx_init(sc, ATH_RXBUF);
1289 if (error != 0)
1290 goto bad1;
1291
1292 return 0;
1293bad1:
1294 ath_detach(sc);
1295bad:
1296 return error;
1297}
1298
1299static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1300{
1301 void __iomem *mem;
1302 struct ath_softc *sc;
1303 struct ieee80211_hw *hw;
1304 const char *athname;
1305 u8 csz;
1306 u32 val;
1307 int ret = 0;
1308
1309 if (pci_enable_device(pdev))
1310 return -EIO;
1311
1312 /* XXX 32-bit addressing only */
1313 if (pci_set_dma_mask(pdev, 0xffffffff)) {
1314 printk(KERN_ERR "ath_pci: 32-bit DMA not available\n");
1315 ret = -ENODEV;
1316 goto bad;
1317 }
1318
1319 /*
1320 * Cache line size is used to size and align various
1321 * structures used to communicate with the hardware.
1322 */
1323 pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
1324 if (csz == 0) {
1325 /*
1326 * Linux 2.4.18 (at least) writes the cache line size
1327 * register as a 16-bit wide register which is wrong.
1328 * We must have this setup properly for rx buffer
1329 * DMA to work so force a reasonable value here if it
1330 * comes up zero.
1331 */
1332 csz = L1_CACHE_BYTES / sizeof(u32);
1333 pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
1334 }
1335 /*
1336 * The default setting of latency timer yields poor results,
1337 * set it to the value used by other systems. It may be worth
1338 * tweaking this setting more.
1339 */
1340 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
1341
1342 pci_set_master(pdev);
1343
1344 /*
1345 * Disable the RETRY_TIMEOUT register (0x41) to keep
1346 * PCI Tx retries from interfering with C3 CPU state.
1347 */
1348 pci_read_config_dword(pdev, 0x40, &val);
1349 if ((val & 0x0000ff00) != 0)
1350 pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
1351
1352 ret = pci_request_region(pdev, 0, "ath9k");
1353 if (ret) {
1354 dev_err(&pdev->dev, "PCI memory region reserve error\n");
1355 ret = -ENODEV;
1356 goto bad;
1357 }
1358
1359 mem = pci_iomap(pdev, 0, 0);
1360 if (!mem) {
1361 printk(KERN_ERR "PCI memory map error\n") ;
1362 ret = -EIO;
1363 goto bad1;
1364 }
1365
1366 hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
1367 if (hw == NULL) {
1368 printk(KERN_ERR "ath_pci: no memory for ieee80211_hw\n");
1369 goto bad2;
1370 }
1371
1372 hw->flags = IEEE80211_HW_SIGNAL_DBM |
1373 IEEE80211_HW_NOISE_DBM;
1374
1375 SET_IEEE80211_DEV(hw, &pdev->dev);
1376 pci_set_drvdata(pdev, hw);
1377
1378 sc = hw->priv;
1379 sc->hw = hw;
1380 sc->pdev = pdev;
1381 sc->mem = mem;
1382
1383 if (ath_attach(id->device, sc) != 0) {
1384 ret = -ENODEV;
1385 goto bad3;
1386 }
1387
1388 /* setup interrupt service routine */
1389
1390 if (request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath", sc)) {
1391 printk(KERN_ERR "%s: request_irq failed\n",
1392 wiphy_name(hw->wiphy));
1393 ret = -EIO;
1394 goto bad4;
1395 }
1396
1397 athname = ath9k_hw_probe(id->vendor, id->device);
1398
1399 printk(KERN_INFO "%s: %s: mem=0x%lx, irq=%d\n",
1400 wiphy_name(hw->wiphy),
1401 athname ? athname : "Atheros ???",
1402 (unsigned long)mem, pdev->irq);
1403
1404 return 0;
1405bad4:
1406 ath_detach(sc);
1407bad3:
1408 ieee80211_free_hw(hw);
1409bad2:
1410 pci_iounmap(pdev, mem);
1411bad1:
1412 pci_release_region(pdev, 0);
1413bad:
1414 pci_disable_device(pdev);
1415 return ret;
1416}
1417
1418static void ath_pci_remove(struct pci_dev *pdev)
1419{
1420 struct ieee80211_hw *hw = pci_get_drvdata(pdev);
1421 struct ath_softc *sc = hw->priv;
1422
1423 if (pdev->irq)
1424 free_irq(pdev->irq, sc);
1425 ath_detach(sc);
1426 pci_iounmap(pdev, sc->mem);
1427 pci_release_region(pdev, 0);
1428 pci_disable_device(pdev);
1429 ieee80211_free_hw(hw);
1430}
1431
1432#ifdef CONFIG_PM
1433
1434static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
1435{
1436 pci_save_state(pdev);
1437 pci_disable_device(pdev);
1438 pci_set_power_state(pdev, 3);
1439
1440 return 0;
1441}
1442
1443static int ath_pci_resume(struct pci_dev *pdev)
1444{
1445 u32 val;
1446 int err;
1447
1448 err = pci_enable_device(pdev);
1449 if (err)
1450 return err;
1451 pci_restore_state(pdev);
1452 /*
1453 * Suspend/Resume resets the PCI configuration space, so we have to
1454 * re-disable the RETRY_TIMEOUT register (0x41) to keep
1455 * PCI Tx retries from interfering with C3 CPU state
1456 */
1457 pci_read_config_dword(pdev, 0x40, &val);
1458 if ((val & 0x0000ff00) != 0)
1459 pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
1460
1461 return 0;
1462}
1463
1464#endif /* CONFIG_PM */
1465
1466MODULE_DEVICE_TABLE(pci, ath_pci_id_table);
1467
1468static struct pci_driver ath_pci_driver = {
1469 .name = "ath9k",
1470 .id_table = ath_pci_id_table,
1471 .probe = ath_pci_probe,
1472 .remove = ath_pci_remove,
1473#ifdef CONFIG_PM
1474 .suspend = ath_pci_suspend,
1475 .resume = ath_pci_resume,
1476#endif /* CONFIG_PM */
1477};
1478
1479static int __init init_ath_pci(void)
1480{
1481 printk(KERN_INFO "%s: %s\n", dev_info, ATH_PCI_VERSION);
1482
1483 if (pci_register_driver(&ath_pci_driver) < 0) {
1484 printk(KERN_ERR
1485 "ath_pci: No devices found, driver not installed.\n");
1486 pci_unregister_driver(&ath_pci_driver);
1487 return -ENODEV;
1488 }
1489
1490 return 0;
1491}
1492module_init(init_ath_pci);
1493
1494static void __exit exit_ath_pci(void)
1495{
1496 pci_unregister_driver(&ath_pci_driver);
1497 printk(KERN_INFO "%s: driver unloaded\n", dev_info);
1498}
1499module_exit(exit_ath_pci);