blob: 2b519b387a298daf5ec495b42d1822f7a48129fd [file] [log] [blame]
Sujith55624202010-01-08 10:36:02 +05301/*
2 * Copyright (c) 2008-2009 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
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090017#include <linux/slab.h>
18
Sujith55624202010-01-08 10:36:02 +053019#include "ath9k.h"
20
21static char *dev_info = "ath9k";
22
23MODULE_AUTHOR("Atheros Communications");
24MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
25MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
26MODULE_LICENSE("Dual BSD/GPL");
27
28static unsigned int ath9k_debug = ATH_DBG_DEFAULT;
29module_param_named(debug, ath9k_debug, uint, 0);
30MODULE_PARM_DESC(debug, "Debugging mask");
31
32int modparam_nohwcrypt;
33module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
34MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
35
Vivek Natarajan93dbbcc2010-08-25 19:34:52 +053036int led_blink;
Vivek Natarajan9a75c2f2010-06-22 11:52:37 +053037module_param_named(blink, led_blink, int, 0444);
38MODULE_PARM_DESC(blink, "Enable LED blink on activity");
39
Vasanthakumar Thiagarajan8f5dcb12010-11-26 06:10:06 -080040static int ath9k_btcoex_enable;
41module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444);
42MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
43
Sujith55624202010-01-08 10:36:02 +053044/* We use the hw_value as an index into our private channel structure */
45
46#define CHAN2G(_freq, _idx) { \
47 .center_freq = (_freq), \
48 .hw_value = (_idx), \
49 .max_power = 20, \
50}
51
52#define CHAN5G(_freq, _idx) { \
53 .band = IEEE80211_BAND_5GHZ, \
54 .center_freq = (_freq), \
55 .hw_value = (_idx), \
56 .max_power = 20, \
57}
58
59/* Some 2 GHz radios are actually tunable on 2312-2732
60 * on 5 MHz steps, we support the channels which we know
61 * we have calibration data for all cards though to make
62 * this static */
Felix Fietkauf209f522010-10-01 01:06:53 +020063static const struct ieee80211_channel ath9k_2ghz_chantable[] = {
Sujith55624202010-01-08 10:36:02 +053064 CHAN2G(2412, 0), /* Channel 1 */
65 CHAN2G(2417, 1), /* Channel 2 */
66 CHAN2G(2422, 2), /* Channel 3 */
67 CHAN2G(2427, 3), /* Channel 4 */
68 CHAN2G(2432, 4), /* Channel 5 */
69 CHAN2G(2437, 5), /* Channel 6 */
70 CHAN2G(2442, 6), /* Channel 7 */
71 CHAN2G(2447, 7), /* Channel 8 */
72 CHAN2G(2452, 8), /* Channel 9 */
73 CHAN2G(2457, 9), /* Channel 10 */
74 CHAN2G(2462, 10), /* Channel 11 */
75 CHAN2G(2467, 11), /* Channel 12 */
76 CHAN2G(2472, 12), /* Channel 13 */
77 CHAN2G(2484, 13), /* Channel 14 */
78};
79
80/* Some 5 GHz radios are actually tunable on XXXX-YYYY
81 * on 5 MHz steps, we support the channels which we know
82 * we have calibration data for all cards though to make
83 * this static */
Felix Fietkauf209f522010-10-01 01:06:53 +020084static const struct ieee80211_channel ath9k_5ghz_chantable[] = {
Sujith55624202010-01-08 10:36:02 +053085 /* _We_ call this UNII 1 */
86 CHAN5G(5180, 14), /* Channel 36 */
87 CHAN5G(5200, 15), /* Channel 40 */
88 CHAN5G(5220, 16), /* Channel 44 */
89 CHAN5G(5240, 17), /* Channel 48 */
90 /* _We_ call this UNII 2 */
91 CHAN5G(5260, 18), /* Channel 52 */
92 CHAN5G(5280, 19), /* Channel 56 */
93 CHAN5G(5300, 20), /* Channel 60 */
94 CHAN5G(5320, 21), /* Channel 64 */
95 /* _We_ call this "Middle band" */
96 CHAN5G(5500, 22), /* Channel 100 */
97 CHAN5G(5520, 23), /* Channel 104 */
98 CHAN5G(5540, 24), /* Channel 108 */
99 CHAN5G(5560, 25), /* Channel 112 */
100 CHAN5G(5580, 26), /* Channel 116 */
101 CHAN5G(5600, 27), /* Channel 120 */
102 CHAN5G(5620, 28), /* Channel 124 */
103 CHAN5G(5640, 29), /* Channel 128 */
104 CHAN5G(5660, 30), /* Channel 132 */
105 CHAN5G(5680, 31), /* Channel 136 */
106 CHAN5G(5700, 32), /* Channel 140 */
107 /* _We_ call this UNII 3 */
108 CHAN5G(5745, 33), /* Channel 149 */
109 CHAN5G(5765, 34), /* Channel 153 */
110 CHAN5G(5785, 35), /* Channel 157 */
111 CHAN5G(5805, 36), /* Channel 161 */
112 CHAN5G(5825, 37), /* Channel 165 */
113};
114
115/* Atheros hardware rate code addition for short premble */
116#define SHPCHECK(__hw_rate, __flags) \
117 ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0)
118
119#define RATE(_bitrate, _hw_rate, _flags) { \
120 .bitrate = (_bitrate), \
121 .flags = (_flags), \
122 .hw_value = (_hw_rate), \
123 .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \
124}
125
126static struct ieee80211_rate ath9k_legacy_rates[] = {
127 RATE(10, 0x1b, 0),
128 RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE),
129 RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE),
130 RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE),
131 RATE(60, 0x0b, 0),
132 RATE(90, 0x0f, 0),
133 RATE(120, 0x0a, 0),
134 RATE(180, 0x0e, 0),
135 RATE(240, 0x09, 0),
136 RATE(360, 0x0d, 0),
137 RATE(480, 0x08, 0),
138 RATE(540, 0x0c, 0),
139};
140
Sujith285f2dd2010-01-08 10:36:07 +0530141static void ath9k_deinit_softc(struct ath_softc *sc);
Sujith55624202010-01-08 10:36:02 +0530142
143/*
144 * Read and write, they both share the same lock. We do this to serialize
145 * reads and writes on Atheros 802.11n PCI devices only. This is required
146 * as the FIFO on these devices can only accept sanely 2 requests.
147 */
148
149static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
150{
151 struct ath_hw *ah = (struct ath_hw *) hw_priv;
152 struct ath_common *common = ath9k_hw_common(ah);
153 struct ath_softc *sc = (struct ath_softc *) common->priv;
154
155 if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
156 unsigned long flags;
157 spin_lock_irqsave(&sc->sc_serial_rw, flags);
158 iowrite32(val, sc->mem + reg_offset);
159 spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
160 } else
161 iowrite32(val, sc->mem + reg_offset);
162}
163
164static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
165{
166 struct ath_hw *ah = (struct ath_hw *) hw_priv;
167 struct ath_common *common = ath9k_hw_common(ah);
168 struct ath_softc *sc = (struct ath_softc *) common->priv;
169 u32 val;
170
171 if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
172 unsigned long flags;
173 spin_lock_irqsave(&sc->sc_serial_rw, flags);
174 val = ioread32(sc->mem + reg_offset);
175 spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
176 } else
177 val = ioread32(sc->mem + reg_offset);
178 return val;
179}
180
181static const struct ath_ops ath9k_common_ops = {
182 .read = ath9k_ioread32,
183 .write = ath9k_iowrite32,
184};
185
186/**************************/
187/* Initialization */
188/**************************/
189
190static void setup_ht_cap(struct ath_softc *sc,
191 struct ieee80211_sta_ht_cap *ht_info)
192{
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200193 struct ath_hw *ah = sc->sc_ah;
194 struct ath_common *common = ath9k_hw_common(ah);
Sujith55624202010-01-08 10:36:02 +0530195 u8 tx_streams, rx_streams;
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200196 int i, max_streams;
Sujith55624202010-01-08 10:36:02 +0530197
198 ht_info->ht_supported = true;
199 ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
200 IEEE80211_HT_CAP_SM_PS |
201 IEEE80211_HT_CAP_SGI_40 |
202 IEEE80211_HT_CAP_DSSSCCK40;
203
Luis R. Rodriguezb0a33442010-04-15 17:39:39 -0400204 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC)
205 ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
206
Vasanthakumar Thiagarajan6473d242010-05-13 18:42:38 -0700207 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
208 ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
209
Sujith55624202010-01-08 10:36:02 +0530210 ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
211 ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
212
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200213 if (AR_SREV_9300_20_OR_LATER(ah))
214 max_streams = 3;
215 else
216 max_streams = 2;
217
Felix Fietkau7a370812010-09-22 12:34:52 +0200218 if (AR_SREV_9280_20_OR_LATER(ah)) {
Felix Fietkau074a8c02010-04-19 19:57:36 +0200219 if (max_streams >= 2)
220 ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
221 ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
222 }
223
Sujith55624202010-01-08 10:36:02 +0530224 /* set up supported mcs set */
225 memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
Sujith61389f32010-06-02 15:53:37 +0530226 tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams);
227 rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams);
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200228
229 ath_print(common, ATH_DBG_CONFIG,
230 "TX streams %d, RX streams: %d\n",
231 tx_streams, rx_streams);
Sujith55624202010-01-08 10:36:02 +0530232
233 if (tx_streams != rx_streams) {
Sujith55624202010-01-08 10:36:02 +0530234 ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
235 ht_info->mcs.tx_params |= ((tx_streams - 1) <<
236 IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
237 }
238
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200239 for (i = 0; i < rx_streams; i++)
240 ht_info->mcs.rx_mask[i] = 0xff;
Sujith55624202010-01-08 10:36:02 +0530241
242 ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
243}
244
245static int ath9k_reg_notifier(struct wiphy *wiphy,
246 struct regulatory_request *request)
247{
248 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
249 struct ath_wiphy *aphy = hw->priv;
250 struct ath_softc *sc = aphy->sc;
251 struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah);
252
253 return ath_reg_notifier_apply(wiphy, request, reg);
254}
255
256/*
257 * This function will allocate both the DMA descriptor structure, and the
258 * buffers it contains. These are used to contain the descriptors used
259 * by the system.
260*/
261int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
262 struct list_head *head, const char *name,
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400263 int nbuf, int ndesc, bool is_tx)
Sujith55624202010-01-08 10:36:02 +0530264{
265#define DS2PHYS(_dd, _ds) \
266 ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
267#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
268#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
269 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400270 u8 *ds;
Sujith55624202010-01-08 10:36:02 +0530271 struct ath_buf *bf;
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400272 int i, bsize, error, desc_len;
Sujith55624202010-01-08 10:36:02 +0530273
274 ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",
275 name, nbuf, ndesc);
276
277 INIT_LIST_HEAD(head);
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400278
279 if (is_tx)
280 desc_len = sc->sc_ah->caps.tx_desc_len;
281 else
282 desc_len = sizeof(struct ath_desc);
283
Sujith55624202010-01-08 10:36:02 +0530284 /* ath_desc must be a multiple of DWORDs */
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400285 if ((desc_len % 4) != 0) {
Joe Perches38002762010-12-02 19:12:36 -0800286 ath_err(common, "ath_desc not DWORD aligned\n");
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400287 BUG_ON((desc_len % 4) != 0);
Sujith55624202010-01-08 10:36:02 +0530288 error = -ENOMEM;
289 goto fail;
290 }
291
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400292 dd->dd_desc_len = desc_len * nbuf * ndesc;
Sujith55624202010-01-08 10:36:02 +0530293
294 /*
295 * Need additional DMA memory because we can't use
296 * descriptors that cross the 4K page boundary. Assume
297 * one skipped descriptor per 4K page.
298 */
299 if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
300 u32 ndesc_skipped =
301 ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len);
302 u32 dma_len;
303
304 while (ndesc_skipped) {
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400305 dma_len = ndesc_skipped * desc_len;
Sujith55624202010-01-08 10:36:02 +0530306 dd->dd_desc_len += dma_len;
307
308 ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len);
Joe Perchesee289b62010-05-17 22:47:34 -0700309 }
Sujith55624202010-01-08 10:36:02 +0530310 }
311
312 /* allocate descriptors */
313 dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
314 &dd->dd_desc_paddr, GFP_KERNEL);
315 if (dd->dd_desc == NULL) {
316 error = -ENOMEM;
317 goto fail;
318 }
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400319 ds = (u8 *) dd->dd_desc;
Sujith55624202010-01-08 10:36:02 +0530320 ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
321 name, ds, (u32) dd->dd_desc_len,
322 ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
323
324 /* allocate buffers */
325 bsize = sizeof(struct ath_buf) * nbuf;
326 bf = kzalloc(bsize, GFP_KERNEL);
327 if (bf == NULL) {
328 error = -ENOMEM;
329 goto fail2;
330 }
331 dd->dd_bufptr = bf;
332
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400333 for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {
Sujith55624202010-01-08 10:36:02 +0530334 bf->bf_desc = ds;
335 bf->bf_daddr = DS2PHYS(dd, ds);
336
337 if (!(sc->sc_ah->caps.hw_caps &
338 ATH9K_HW_CAP_4KB_SPLITTRANS)) {
339 /*
340 * Skip descriptor addresses which can cause 4KB
341 * boundary crossing (addr + length) with a 32 dword
342 * descriptor fetch.
343 */
344 while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
345 BUG_ON((caddr_t) bf->bf_desc >=
346 ((caddr_t) dd->dd_desc +
347 dd->dd_desc_len));
348
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400349 ds += (desc_len * ndesc);
Sujith55624202010-01-08 10:36:02 +0530350 bf->bf_desc = ds;
351 bf->bf_daddr = DS2PHYS(dd, ds);
352 }
353 }
354 list_add_tail(&bf->list, head);
355 }
356 return 0;
357fail2:
358 dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
359 dd->dd_desc_paddr);
360fail:
361 memset(dd, 0, sizeof(*dd));
362 return error;
363#undef ATH_DESC_4KB_BOUND_CHECK
364#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
365#undef DS2PHYS
366}
367
Sujith285f2dd2010-01-08 10:36:07 +0530368static void ath9k_init_crypto(struct ath_softc *sc)
Sujith55624202010-01-08 10:36:02 +0530369{
Sujith285f2dd2010-01-08 10:36:07 +0530370 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
371 int i = 0;
Sujith55624202010-01-08 10:36:02 +0530372
373 /* Get the hardware key cache size. */
Sujith285f2dd2010-01-08 10:36:07 +0530374 common->keymax = sc->sc_ah->caps.keycache_size;
Sujith55624202010-01-08 10:36:02 +0530375 if (common->keymax > ATH_KEYMAX) {
376 ath_print(common, ATH_DBG_ANY,
377 "Warning, using only %u entries in %u key cache\n",
378 ATH_KEYMAX, common->keymax);
379 common->keymax = ATH_KEYMAX;
380 }
381
382 /*
383 * Reset the key cache since some parts do not
384 * reset the contents on initial power up.
385 */
386 for (i = 0; i < common->keymax; i++)
Bruno Randolf040e5392010-09-08 16:05:04 +0900387 ath_hw_keyreset(common, (u16) i);
Sujith55624202010-01-08 10:36:02 +0530388
Felix Fietkau716f7fc2010-06-12 17:22:28 +0200389 /*
Sujith55624202010-01-08 10:36:02 +0530390 * Check whether the separate key cache entries
391 * are required to handle both tx+rx MIC keys.
392 * With split mic keys the number of stations is limited
393 * to 27 otherwise 59.
394 */
Bruno Randolf117675d2010-09-08 16:04:54 +0900395 if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
396 common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
Sujith285f2dd2010-01-08 10:36:07 +0530397}
Sujith55624202010-01-08 10:36:02 +0530398
Sujith285f2dd2010-01-08 10:36:07 +0530399static int ath9k_init_btcoex(struct ath_softc *sc)
400{
Felix Fietkau066dae92010-11-07 14:59:39 +0100401 struct ath_txq *txq;
402 int r;
Sujith285f2dd2010-01-08 10:36:07 +0530403
404 switch (sc->sc_ah->btcoex_hw.scheme) {
405 case ATH_BTCOEX_CFG_NONE:
406 break;
407 case ATH_BTCOEX_CFG_2WIRE:
408 ath9k_hw_btcoex_init_2wire(sc->sc_ah);
409 break;
410 case ATH_BTCOEX_CFG_3WIRE:
411 ath9k_hw_btcoex_init_3wire(sc->sc_ah);
412 r = ath_init_btcoex_timer(sc);
413 if (r)
414 return -1;
Felix Fietkau066dae92010-11-07 14:59:39 +0100415 txq = sc->tx.txq_map[WME_AC_BE];
416 ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
Sujith285f2dd2010-01-08 10:36:07 +0530417 sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
418 break;
419 default:
420 WARN_ON(1);
421 break;
Sujith55624202010-01-08 10:36:02 +0530422 }
423
Sujith285f2dd2010-01-08 10:36:07 +0530424 return 0;
425}
Sujith55624202010-01-08 10:36:02 +0530426
Sujith285f2dd2010-01-08 10:36:07 +0530427static int ath9k_init_queues(struct ath_softc *sc)
428{
Sujith285f2dd2010-01-08 10:36:07 +0530429 int i = 0;
Sujith55624202010-01-08 10:36:02 +0530430
Sujith285f2dd2010-01-08 10:36:07 +0530431 sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
Sujith285f2dd2010-01-08 10:36:07 +0530432 sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
Sujith55624202010-01-08 10:36:02 +0530433
Sujith285f2dd2010-01-08 10:36:07 +0530434 sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
435 ath_cabq_update(sc);
436
Felix Fietkau066dae92010-11-07 14:59:39 +0100437 for (i = 0; i < WME_NUM_AC; i++)
438 sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
Sujith285f2dd2010-01-08 10:36:07 +0530439
440 return 0;
Sujith285f2dd2010-01-08 10:36:07 +0530441}
442
Felix Fietkauf209f522010-10-01 01:06:53 +0200443static int ath9k_init_channels_rates(struct ath_softc *sc)
Sujith285f2dd2010-01-08 10:36:07 +0530444{
Felix Fietkauf209f522010-10-01 01:06:53 +0200445 void *channels;
446
Felix Fietkaucac42202010-10-09 02:39:30 +0200447 BUILD_BUG_ON(ARRAY_SIZE(ath9k_2ghz_chantable) +
448 ARRAY_SIZE(ath9k_5ghz_chantable) !=
449 ATH9K_NUM_CHANNELS);
450
Felix Fietkaud4659912010-10-14 16:02:39 +0200451 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
Felix Fietkauf209f522010-10-01 01:06:53 +0200452 channels = kmemdup(ath9k_2ghz_chantable,
453 sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
454 if (!channels)
455 return -ENOMEM;
456
457 sc->sbands[IEEE80211_BAND_2GHZ].channels = channels;
Sujith55624202010-01-08 10:36:02 +0530458 sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
459 sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
460 ARRAY_SIZE(ath9k_2ghz_chantable);
461 sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
462 sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
463 ARRAY_SIZE(ath9k_legacy_rates);
464 }
465
Felix Fietkaud4659912010-10-14 16:02:39 +0200466 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
Felix Fietkauf209f522010-10-01 01:06:53 +0200467 channels = kmemdup(ath9k_5ghz_chantable,
468 sizeof(ath9k_5ghz_chantable), GFP_KERNEL);
469 if (!channels) {
470 if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
471 kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
472 return -ENOMEM;
473 }
474
475 sc->sbands[IEEE80211_BAND_5GHZ].channels = channels;
Sujith55624202010-01-08 10:36:02 +0530476 sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
477 sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
478 ARRAY_SIZE(ath9k_5ghz_chantable);
479 sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
480 ath9k_legacy_rates + 4;
481 sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
482 ARRAY_SIZE(ath9k_legacy_rates) - 4;
483 }
Felix Fietkauf209f522010-10-01 01:06:53 +0200484 return 0;
Sujith285f2dd2010-01-08 10:36:07 +0530485}
Sujith55624202010-01-08 10:36:02 +0530486
Sujith285f2dd2010-01-08 10:36:07 +0530487static void ath9k_init_misc(struct ath_softc *sc)
488{
489 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
490 int i = 0;
491
Sujith285f2dd2010-01-08 10:36:07 +0530492 setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
493
494 sc->config.txpowlimit = ATH_TXPOWER_MAX;
495
496 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
497 sc->sc_flags |= SC_OP_TXAGGR;
498 sc->sc_flags |= SC_OP_RXAGGR;
Sujith55624202010-01-08 10:36:02 +0530499 }
500
Sujith285f2dd2010-01-08 10:36:07 +0530501 common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
502 common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
503
Luis R. Rodriguez8fe65362010-04-15 17:38:14 -0400504 ath9k_hw_set_diversity(sc->sc_ah, true);
Sujith285f2dd2010-01-08 10:36:07 +0530505 sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
506
Felix Fietkau364734f2010-09-14 20:22:44 +0200507 memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
Sujith285f2dd2010-01-08 10:36:07 +0530508
509 sc->beacon.slottime = ATH9K_SLOT_TIME_9;
510
511 for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
512 sc->beacon.bslot[i] = NULL;
513 sc->beacon.bslot_aphy[i] = NULL;
514 }
Vasanthakumar Thiagarajan102885a2010-09-02 01:34:43 -0700515
516 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
517 sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
Sujith285f2dd2010-01-08 10:36:07 +0530518}
519
520static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
521 const struct ath_bus_ops *bus_ops)
522{
523 struct ath_hw *ah = NULL;
524 struct ath_common *common;
525 int ret = 0, i;
526 int csz = 0;
527
Sujith285f2dd2010-01-08 10:36:07 +0530528 ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
529 if (!ah)
530 return -ENOMEM;
531
532 ah->hw_version.devid = devid;
533 ah->hw_version.subsysid = subsysid;
534 sc->sc_ah = ah;
535
Felix Fietkaua05b5d452010-11-17 04:25:33 +0100536 if (!sc->dev->platform_data)
537 ah->ah_flags |= AH_USE_EEPROM;
538
Sujith285f2dd2010-01-08 10:36:07 +0530539 common = ath9k_hw_common(ah);
540 common->ops = &ath9k_common_ops;
541 common->bus_ops = bus_ops;
542 common->ah = ah;
543 common->hw = sc->hw;
544 common->priv = sc;
545 common->debug_mask = ath9k_debug;
Vasanthakumar Thiagarajan8f5dcb12010-11-26 06:10:06 -0800546 common->btcoex_enabled = ath9k_btcoex_enable == 1;
Ben Greear20b257442010-10-15 15:04:09 -0700547 spin_lock_init(&common->cc_lock);
Sujith285f2dd2010-01-08 10:36:07 +0530548
549 spin_lock_init(&sc->wiphy_lock);
Sujith285f2dd2010-01-08 10:36:07 +0530550 spin_lock_init(&sc->sc_serial_rw);
551 spin_lock_init(&sc->sc_pm_lock);
552 mutex_init(&sc->mutex);
553 tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
554 tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
555 (unsigned long)sc);
556
557 /*
558 * Cache line size is used to size and align various
559 * structures used to communicate with the hardware.
560 */
561 ath_read_cachesize(common, &csz);
562 common->cachelsz = csz << 2; /* convert to bytes */
563
Luis R. Rodriguezd70357d2010-04-15 17:38:06 -0400564 /* Initializes the hardware for all supported chipsets */
Sujith285f2dd2010-01-08 10:36:07 +0530565 ret = ath9k_hw_init(ah);
Luis R. Rodriguezd70357d2010-04-15 17:38:06 -0400566 if (ret)
Sujith285f2dd2010-01-08 10:36:07 +0530567 goto err_hw;
Sujith285f2dd2010-01-08 10:36:07 +0530568
Sujith285f2dd2010-01-08 10:36:07 +0530569 ret = ath9k_init_queues(sc);
570 if (ret)
571 goto err_queues;
572
573 ret = ath9k_init_btcoex(sc);
574 if (ret)
575 goto err_btcoex;
576
Felix Fietkauf209f522010-10-01 01:06:53 +0200577 ret = ath9k_init_channels_rates(sc);
578 if (ret)
579 goto err_btcoex;
580
Sujith285f2dd2010-01-08 10:36:07 +0530581 ath9k_init_crypto(sc);
Sujith285f2dd2010-01-08 10:36:07 +0530582 ath9k_init_misc(sc);
583
Sujith55624202010-01-08 10:36:02 +0530584 return 0;
Sujith285f2dd2010-01-08 10:36:07 +0530585
586err_btcoex:
Sujith55624202010-01-08 10:36:02 +0530587 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
588 if (ATH_TXQ_SETUP(sc, i))
589 ath_tx_cleanupq(sc, &sc->tx.txq[i]);
Sujith285f2dd2010-01-08 10:36:07 +0530590err_queues:
Sujith285f2dd2010-01-08 10:36:07 +0530591 ath9k_hw_deinit(ah);
592err_hw:
593 tasklet_kill(&sc->intr_tq);
594 tasklet_kill(&sc->bcon_tasklet);
Sujith55624202010-01-08 10:36:02 +0530595
Sujith285f2dd2010-01-08 10:36:07 +0530596 kfree(ah);
597 sc->sc_ah = NULL;
598
599 return ret;
Sujith55624202010-01-08 10:36:02 +0530600}
601
Felix Fietkaubabcbc22010-10-20 02:09:46 +0200602static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
603{
604 struct ieee80211_supported_band *sband;
605 struct ieee80211_channel *chan;
606 struct ath_hw *ah = sc->sc_ah;
607 struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
608 int i;
609
610 sband = &sc->sbands[band];
611 for (i = 0; i < sband->n_channels; i++) {
612 chan = &sband->channels[i];
613 ah->curchan = &ah->channels[chan->hw_value];
614 ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
615 ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
616 chan->max_power = reg->max_power_level / 2;
617 }
618}
619
620static void ath9k_init_txpower_limits(struct ath_softc *sc)
621{
622 struct ath_hw *ah = sc->sc_ah;
623 struct ath9k_channel *curchan = ah->curchan;
624
625 if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
626 ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
627 if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
628 ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
629
630 ah->curchan = curchan;
631}
632
Sujith285f2dd2010-01-08 10:36:07 +0530633void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
Sujith55624202010-01-08 10:36:02 +0530634{
Sujith285f2dd2010-01-08 10:36:07 +0530635 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
636
Sujith55624202010-01-08 10:36:02 +0530637 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
638 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
639 IEEE80211_HW_SIGNAL_DBM |
Sujith55624202010-01-08 10:36:02 +0530640 IEEE80211_HW_SUPPORTS_PS |
641 IEEE80211_HW_PS_NULLFUNC_STACK |
Vivek Natarajan05df4982010-02-09 11:34:50 +0530642 IEEE80211_HW_SPECTRUM_MGMT |
643 IEEE80211_HW_REPORTS_TX_ACK_STATUS;
Sujith55624202010-01-08 10:36:02 +0530644
Luis R. Rodriguez5ffaf8a2010-02-02 11:58:33 -0500645 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
646 hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
647
Sujith55624202010-01-08 10:36:02 +0530648 if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt)
649 hw->flags |= IEEE80211_HW_MFP_CAPABLE;
650
651 hw->wiphy->interface_modes =
Johannes Bergc426ee22010-11-26 11:38:04 +0100652 BIT(NL80211_IFTYPE_P2P_GO) |
653 BIT(NL80211_IFTYPE_P2P_CLIENT) |
Sujith55624202010-01-08 10:36:02 +0530654 BIT(NL80211_IFTYPE_AP) |
Bill Jordane51f3ef2010-10-01 11:20:39 -0400655 BIT(NL80211_IFTYPE_WDS) |
Sujith55624202010-01-08 10:36:02 +0530656 BIT(NL80211_IFTYPE_STATION) |
657 BIT(NL80211_IFTYPE_ADHOC) |
658 BIT(NL80211_IFTYPE_MESH_POINT);
659
Luis R. Rodriguez008443d2010-09-16 15:12:36 -0400660 if (AR_SREV_5416(sc->sc_ah))
661 hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
Sujith55624202010-01-08 10:36:02 +0530662
663 hw->queues = 4;
664 hw->max_rates = 4;
665 hw->channel_change_time = 5000;
666 hw->max_listen_interval = 10;
Felix Fietkau65896512010-01-24 03:26:11 +0100667 hw->max_rate_tries = 10;
Sujith55624202010-01-08 10:36:02 +0530668 hw->sta_data_size = sizeof(struct ath_node);
669 hw->vif_data_size = sizeof(struct ath_vif);
670
Felix Fietkau6e5c2b42010-09-20 13:45:40 +0200671#ifdef CONFIG_ATH9K_RATE_CONTROL
Sujith55624202010-01-08 10:36:02 +0530672 hw->rate_control_algorithm = "ath9k_rate_control";
Felix Fietkau6e5c2b42010-09-20 13:45:40 +0200673#endif
Sujith55624202010-01-08 10:36:02 +0530674
Felix Fietkaud4659912010-10-14 16:02:39 +0200675 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
Sujith55624202010-01-08 10:36:02 +0530676 hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
677 &sc->sbands[IEEE80211_BAND_2GHZ];
Felix Fietkaud4659912010-10-14 16:02:39 +0200678 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
Sujith55624202010-01-08 10:36:02 +0530679 hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
680 &sc->sbands[IEEE80211_BAND_5GHZ];
Sujith285f2dd2010-01-08 10:36:07 +0530681
682 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
Felix Fietkaud4659912010-10-14 16:02:39 +0200683 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
Sujith285f2dd2010-01-08 10:36:07 +0530684 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
Felix Fietkaud4659912010-10-14 16:02:39 +0200685 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
Sujith285f2dd2010-01-08 10:36:07 +0530686 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
687 }
688
689 SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
Sujith55624202010-01-08 10:36:02 +0530690}
691
Sujith285f2dd2010-01-08 10:36:07 +0530692int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
Sujith55624202010-01-08 10:36:02 +0530693 const struct ath_bus_ops *bus_ops)
694{
695 struct ieee80211_hw *hw = sc->hw;
Felix Fietkau9fa23e12010-10-15 20:03:31 +0200696 struct ath_wiphy *aphy = hw->priv;
Sujith55624202010-01-08 10:36:02 +0530697 struct ath_common *common;
698 struct ath_hw *ah;
Sujith285f2dd2010-01-08 10:36:07 +0530699 int error = 0;
Sujith55624202010-01-08 10:36:02 +0530700 struct ath_regulatory *reg;
701
Sujith285f2dd2010-01-08 10:36:07 +0530702 /* Bring up device */
703 error = ath9k_init_softc(devid, sc, subsysid, bus_ops);
Sujith55624202010-01-08 10:36:02 +0530704 if (error != 0)
Sujith285f2dd2010-01-08 10:36:07 +0530705 goto error_init;
Sujith55624202010-01-08 10:36:02 +0530706
707 ah = sc->sc_ah;
708 common = ath9k_hw_common(ah);
Sujith285f2dd2010-01-08 10:36:07 +0530709 ath9k_set_hw_capab(sc, hw);
Sujith55624202010-01-08 10:36:02 +0530710
Sujith285f2dd2010-01-08 10:36:07 +0530711 /* Initialize regulatory */
Sujith55624202010-01-08 10:36:02 +0530712 error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
713 ath9k_reg_notifier);
714 if (error)
Sujith285f2dd2010-01-08 10:36:07 +0530715 goto error_regd;
Sujith55624202010-01-08 10:36:02 +0530716
717 reg = &common->regulatory;
718
Sujith285f2dd2010-01-08 10:36:07 +0530719 /* Setup TX DMA */
Sujith55624202010-01-08 10:36:02 +0530720 error = ath_tx_init(sc, ATH_TXBUF);
721 if (error != 0)
Sujith285f2dd2010-01-08 10:36:07 +0530722 goto error_tx;
Sujith55624202010-01-08 10:36:02 +0530723
Sujith285f2dd2010-01-08 10:36:07 +0530724 /* Setup RX DMA */
Sujith55624202010-01-08 10:36:02 +0530725 error = ath_rx_init(sc, ATH_RXBUF);
726 if (error != 0)
Sujith285f2dd2010-01-08 10:36:07 +0530727 goto error_rx;
728
Felix Fietkaubabcbc22010-10-20 02:09:46 +0200729 ath9k_init_txpower_limits(sc);
730
Sujith285f2dd2010-01-08 10:36:07 +0530731 /* Register with mac80211 */
732 error = ieee80211_register_hw(hw);
733 if (error)
734 goto error_register;
735
Ben Greeareb272442010-11-29 14:13:22 -0800736 error = ath9k_init_debug(ah);
737 if (error) {
Joe Perches38002762010-12-02 19:12:36 -0800738 ath_err(common, "Unable to create debugfs files\n");
Ben Greeareb272442010-11-29 14:13:22 -0800739 goto error_world;
740 }
741
Sujith285f2dd2010-01-08 10:36:07 +0530742 /* Handle world regulatory */
743 if (!ath_is_world_regd(reg)) {
744 error = regulatory_hint(hw->wiphy, reg->alpha2);
745 if (error)
746 goto error_world;
747 }
Sujith55624202010-01-08 10:36:02 +0530748
Felix Fietkau347809f2010-07-02 00:09:52 +0200749 INIT_WORK(&sc->hw_check_work, ath_hw_check);
Felix Fietkau9f42c2b2010-06-12 00:34:01 -0400750 INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
Sujith55624202010-01-08 10:36:02 +0530751 INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
752 INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
753 sc->wiphy_scheduler_int = msecs_to_jiffies(500);
Felix Fietkau9fa23e12010-10-15 20:03:31 +0200754 aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
Sujith55624202010-01-08 10:36:02 +0530755
Sujith55624202010-01-08 10:36:02 +0530756 ath_init_leds(sc);
Sujith55624202010-01-08 10:36:02 +0530757 ath_start_rfkill_poll(sc);
758
Gabor Juhos98c316e2010-11-25 18:26:07 +0100759 pm_qos_add_request(&sc->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
Vivek Natarajan10598c12010-10-30 22:05:13 +0530760 PM_QOS_DEFAULT_VALUE);
761
Sujith55624202010-01-08 10:36:02 +0530762 return 0;
763
Sujith285f2dd2010-01-08 10:36:07 +0530764error_world:
765 ieee80211_unregister_hw(hw);
766error_register:
767 ath_rx_cleanup(sc);
768error_rx:
769 ath_tx_cleanup(sc);
770error_tx:
771 /* Nothing */
772error_regd:
773 ath9k_deinit_softc(sc);
774error_init:
Sujith55624202010-01-08 10:36:02 +0530775 return error;
776}
777
778/*****************************/
779/* De-Initialization */
780/*****************************/
781
Sujith285f2dd2010-01-08 10:36:07 +0530782static void ath9k_deinit_softc(struct ath_softc *sc)
Sujith55624202010-01-08 10:36:02 +0530783{
Sujith285f2dd2010-01-08 10:36:07 +0530784 int i = 0;
Sujith55624202010-01-08 10:36:02 +0530785
Felix Fietkauf209f522010-10-01 01:06:53 +0200786 if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
787 kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
788
789 if (sc->sbands[IEEE80211_BAND_5GHZ].channels)
790 kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);
791
Sujith285f2dd2010-01-08 10:36:07 +0530792 if ((sc->btcoex.no_stomp_timer) &&
793 sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
794 ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
Sujith55624202010-01-08 10:36:02 +0530795
Sujith285f2dd2010-01-08 10:36:07 +0530796 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
797 if (ATH_TXQ_SETUP(sc, i))
798 ath_tx_cleanupq(sc, &sc->tx.txq[i]);
799
Sujith285f2dd2010-01-08 10:36:07 +0530800 ath9k_hw_deinit(sc->sc_ah);
801
802 tasklet_kill(&sc->intr_tq);
803 tasklet_kill(&sc->bcon_tasklet);
Sujith736b3a22010-03-17 14:25:24 +0530804
805 kfree(sc->sc_ah);
806 sc->sc_ah = NULL;
Sujith55624202010-01-08 10:36:02 +0530807}
808
Sujith285f2dd2010-01-08 10:36:07 +0530809void ath9k_deinit_device(struct ath_softc *sc)
Sujith55624202010-01-08 10:36:02 +0530810{
811 struct ieee80211_hw *hw = sc->hw;
Sujith55624202010-01-08 10:36:02 +0530812 int i = 0;
813
814 ath9k_ps_wakeup(sc);
815
Sujith55624202010-01-08 10:36:02 +0530816 wiphy_rfkill_stop_polling(sc->hw->wiphy);
Sujith285f2dd2010-01-08 10:36:07 +0530817 ath_deinit_leds(sc);
Sujith55624202010-01-08 10:36:02 +0530818
819 for (i = 0; i < sc->num_sec_wiphy; i++) {
820 struct ath_wiphy *aphy = sc->sec_wiphy[i];
821 if (aphy == NULL)
822 continue;
823 sc->sec_wiphy[i] = NULL;
824 ieee80211_unregister_hw(aphy->hw);
825 ieee80211_free_hw(aphy->hw);
826 }
Sujith285f2dd2010-01-08 10:36:07 +0530827
Sujith55624202010-01-08 10:36:02 +0530828 ieee80211_unregister_hw(hw);
Gabor Juhos98c316e2010-11-25 18:26:07 +0100829 pm_qos_remove_request(&sc->pm_qos_req);
Sujith55624202010-01-08 10:36:02 +0530830 ath_rx_cleanup(sc);
831 ath_tx_cleanup(sc);
Sujith285f2dd2010-01-08 10:36:07 +0530832 ath9k_deinit_softc(sc);
Rajkumar Manoharan447a42c2010-07-08 12:12:29 +0530833 kfree(sc->sec_wiphy);
Sujith55624202010-01-08 10:36:02 +0530834}
835
836void ath_descdma_cleanup(struct ath_softc *sc,
837 struct ath_descdma *dd,
838 struct list_head *head)
839{
840 dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
841 dd->dd_desc_paddr);
842
843 INIT_LIST_HEAD(head);
844 kfree(dd->dd_bufptr);
845 memset(dd, 0, sizeof(*dd));
846}
847
Sujith55624202010-01-08 10:36:02 +0530848/************************/
849/* Module Hooks */
850/************************/
851
852static int __init ath9k_init(void)
853{
854 int error;
855
856 /* Register rate control algorithm */
857 error = ath_rate_control_register();
858 if (error != 0) {
859 printk(KERN_ERR
860 "ath9k: Unable to register rate control "
861 "algorithm: %d\n",
862 error);
863 goto err_out;
864 }
865
Sujith55624202010-01-08 10:36:02 +0530866 error = ath_pci_init();
867 if (error < 0) {
868 printk(KERN_ERR
869 "ath9k: No PCI devices found, driver not installed.\n");
870 error = -ENODEV;
Ben Greeareb272442010-11-29 14:13:22 -0800871 goto err_rate_unregister;
Sujith55624202010-01-08 10:36:02 +0530872 }
873
874 error = ath_ahb_init();
875 if (error < 0) {
876 error = -ENODEV;
877 goto err_pci_exit;
878 }
879
880 return 0;
881
882 err_pci_exit:
883 ath_pci_exit();
884
Sujith55624202010-01-08 10:36:02 +0530885 err_rate_unregister:
886 ath_rate_control_unregister();
887 err_out:
888 return error;
889}
890module_init(ath9k_init);
891
892static void __exit ath9k_exit(void)
893{
894 ath_ahb_exit();
895 ath_pci_exit();
Sujith55624202010-01-08 10:36:02 +0530896 ath_rate_control_unregister();
897 printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
898}
899module_exit(ath9k_exit);