blob: b0e5e716b167f68c765f04f26bd9a02f67308f04 [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
Mohammed Shafi Shajakhan4dc35302010-12-14 13:18:28 +053044int ath9k_pm_qos_value = ATH9K_PM_QOS_DEFAULT_VALUE;
45module_param_named(pmqos, ath9k_pm_qos_value, int, S_IRUSR | S_IRGRP | S_IROTH);
46MODULE_PARM_DESC(pmqos, "User specified PM-QOS value");
47
Sujith55624202010-01-08 10:36:02 +053048/* We use the hw_value as an index into our private channel structure */
49
50#define CHAN2G(_freq, _idx) { \
Mohammed Shafi Shajakhanb1c1d002010-12-17 20:44:36 +053051 .band = IEEE80211_BAND_2GHZ, \
Sujith55624202010-01-08 10:36:02 +053052 .center_freq = (_freq), \
53 .hw_value = (_idx), \
54 .max_power = 20, \
55}
56
57#define CHAN5G(_freq, _idx) { \
58 .band = IEEE80211_BAND_5GHZ, \
59 .center_freq = (_freq), \
60 .hw_value = (_idx), \
61 .max_power = 20, \
62}
63
64/* Some 2 GHz radios are actually tunable on 2312-2732
65 * on 5 MHz steps, we support the channels which we know
66 * we have calibration data for all cards though to make
67 * this static */
Felix Fietkauf209f522010-10-01 01:06:53 +020068static const struct ieee80211_channel ath9k_2ghz_chantable[] = {
Sujith55624202010-01-08 10:36:02 +053069 CHAN2G(2412, 0), /* Channel 1 */
70 CHAN2G(2417, 1), /* Channel 2 */
71 CHAN2G(2422, 2), /* Channel 3 */
72 CHAN2G(2427, 3), /* Channel 4 */
73 CHAN2G(2432, 4), /* Channel 5 */
74 CHAN2G(2437, 5), /* Channel 6 */
75 CHAN2G(2442, 6), /* Channel 7 */
76 CHAN2G(2447, 7), /* Channel 8 */
77 CHAN2G(2452, 8), /* Channel 9 */
78 CHAN2G(2457, 9), /* Channel 10 */
79 CHAN2G(2462, 10), /* Channel 11 */
80 CHAN2G(2467, 11), /* Channel 12 */
81 CHAN2G(2472, 12), /* Channel 13 */
82 CHAN2G(2484, 13), /* Channel 14 */
83};
84
85/* Some 5 GHz radios are actually tunable on XXXX-YYYY
86 * on 5 MHz steps, we support the channels which we know
87 * we have calibration data for all cards though to make
88 * this static */
Felix Fietkauf209f522010-10-01 01:06:53 +020089static const struct ieee80211_channel ath9k_5ghz_chantable[] = {
Sujith55624202010-01-08 10:36:02 +053090 /* _We_ call this UNII 1 */
91 CHAN5G(5180, 14), /* Channel 36 */
92 CHAN5G(5200, 15), /* Channel 40 */
93 CHAN5G(5220, 16), /* Channel 44 */
94 CHAN5G(5240, 17), /* Channel 48 */
95 /* _We_ call this UNII 2 */
96 CHAN5G(5260, 18), /* Channel 52 */
97 CHAN5G(5280, 19), /* Channel 56 */
98 CHAN5G(5300, 20), /* Channel 60 */
99 CHAN5G(5320, 21), /* Channel 64 */
100 /* _We_ call this "Middle band" */
101 CHAN5G(5500, 22), /* Channel 100 */
102 CHAN5G(5520, 23), /* Channel 104 */
103 CHAN5G(5540, 24), /* Channel 108 */
104 CHAN5G(5560, 25), /* Channel 112 */
105 CHAN5G(5580, 26), /* Channel 116 */
106 CHAN5G(5600, 27), /* Channel 120 */
107 CHAN5G(5620, 28), /* Channel 124 */
108 CHAN5G(5640, 29), /* Channel 128 */
109 CHAN5G(5660, 30), /* Channel 132 */
110 CHAN5G(5680, 31), /* Channel 136 */
111 CHAN5G(5700, 32), /* Channel 140 */
112 /* _We_ call this UNII 3 */
113 CHAN5G(5745, 33), /* Channel 149 */
114 CHAN5G(5765, 34), /* Channel 153 */
115 CHAN5G(5785, 35), /* Channel 157 */
116 CHAN5G(5805, 36), /* Channel 161 */
117 CHAN5G(5825, 37), /* Channel 165 */
118};
119
120/* Atheros hardware rate code addition for short premble */
121#define SHPCHECK(__hw_rate, __flags) \
122 ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0)
123
124#define RATE(_bitrate, _hw_rate, _flags) { \
125 .bitrate = (_bitrate), \
126 .flags = (_flags), \
127 .hw_value = (_hw_rate), \
128 .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \
129}
130
131static struct ieee80211_rate ath9k_legacy_rates[] = {
132 RATE(10, 0x1b, 0),
133 RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE),
134 RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE),
135 RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE),
136 RATE(60, 0x0b, 0),
137 RATE(90, 0x0f, 0),
138 RATE(120, 0x0a, 0),
139 RATE(180, 0x0e, 0),
140 RATE(240, 0x09, 0),
141 RATE(360, 0x0d, 0),
142 RATE(480, 0x08, 0),
143 RATE(540, 0x0c, 0),
144};
145
Sujith285f2dd2010-01-08 10:36:07 +0530146static void ath9k_deinit_softc(struct ath_softc *sc);
Sujith55624202010-01-08 10:36:02 +0530147
148/*
149 * Read and write, they both share the same lock. We do this to serialize
150 * reads and writes on Atheros 802.11n PCI devices only. This is required
151 * as the FIFO on these devices can only accept sanely 2 requests.
152 */
153
154static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
155{
156 struct ath_hw *ah = (struct ath_hw *) hw_priv;
157 struct ath_common *common = ath9k_hw_common(ah);
158 struct ath_softc *sc = (struct ath_softc *) common->priv;
159
160 if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
161 unsigned long flags;
162 spin_lock_irqsave(&sc->sc_serial_rw, flags);
163 iowrite32(val, sc->mem + reg_offset);
164 spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
165 } else
166 iowrite32(val, sc->mem + reg_offset);
167}
168
169static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
170{
171 struct ath_hw *ah = (struct ath_hw *) hw_priv;
172 struct ath_common *common = ath9k_hw_common(ah);
173 struct ath_softc *sc = (struct ath_softc *) common->priv;
174 u32 val;
175
176 if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
177 unsigned long flags;
178 spin_lock_irqsave(&sc->sc_serial_rw, flags);
179 val = ioread32(sc->mem + reg_offset);
180 spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
181 } else
182 val = ioread32(sc->mem + reg_offset);
183 return val;
184}
185
186static const struct ath_ops ath9k_common_ops = {
187 .read = ath9k_ioread32,
188 .write = ath9k_iowrite32,
189};
190
191/**************************/
192/* Initialization */
193/**************************/
194
195static void setup_ht_cap(struct ath_softc *sc,
196 struct ieee80211_sta_ht_cap *ht_info)
197{
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200198 struct ath_hw *ah = sc->sc_ah;
199 struct ath_common *common = ath9k_hw_common(ah);
Sujith55624202010-01-08 10:36:02 +0530200 u8 tx_streams, rx_streams;
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200201 int i, max_streams;
Sujith55624202010-01-08 10:36:02 +0530202
203 ht_info->ht_supported = true;
204 ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
205 IEEE80211_HT_CAP_SM_PS |
206 IEEE80211_HT_CAP_SGI_40 |
207 IEEE80211_HT_CAP_DSSSCCK40;
208
Luis R. Rodriguezb0a33442010-04-15 17:39:39 -0400209 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC)
210 ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
211
Vasanthakumar Thiagarajan6473d242010-05-13 18:42:38 -0700212 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
213 ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
214
Sujith55624202010-01-08 10:36:02 +0530215 ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
216 ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
217
Vasanthakumar Thiagarajan7f1c7a62010-12-06 04:27:41 -0800218 if (AR_SREV_9485(ah))
219 max_streams = 1;
220 else if (AR_SREV_9300_20_OR_LATER(ah))
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200221 max_streams = 3;
222 else
223 max_streams = 2;
224
Felix Fietkau7a370812010-09-22 12:34:52 +0200225 if (AR_SREV_9280_20_OR_LATER(ah)) {
Felix Fietkau074a8c02010-04-19 19:57:36 +0200226 if (max_streams >= 2)
227 ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
228 ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
229 }
230
Sujith55624202010-01-08 10:36:02 +0530231 /* set up supported mcs set */
232 memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
Sujith61389f32010-06-02 15:53:37 +0530233 tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams);
234 rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams);
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200235
Joe Perches226afe62010-12-02 19:12:37 -0800236 ath_dbg(common, ATH_DBG_CONFIG,
237 "TX streams %d, RX streams: %d\n",
238 tx_streams, rx_streams);
Sujith55624202010-01-08 10:36:02 +0530239
240 if (tx_streams != rx_streams) {
Sujith55624202010-01-08 10:36:02 +0530241 ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
242 ht_info->mcs.tx_params |= ((tx_streams - 1) <<
243 IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
244 }
245
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200246 for (i = 0; i < rx_streams; i++)
247 ht_info->mcs.rx_mask[i] = 0xff;
Sujith55624202010-01-08 10:36:02 +0530248
249 ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
250}
251
252static int ath9k_reg_notifier(struct wiphy *wiphy,
253 struct regulatory_request *request)
254{
255 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
256 struct ath_wiphy *aphy = hw->priv;
257 struct ath_softc *sc = aphy->sc;
258 struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah);
259
260 return ath_reg_notifier_apply(wiphy, request, reg);
261}
262
263/*
264 * This function will allocate both the DMA descriptor structure, and the
265 * buffers it contains. These are used to contain the descriptors used
266 * by the system.
267*/
268int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
269 struct list_head *head, const char *name,
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400270 int nbuf, int ndesc, bool is_tx)
Sujith55624202010-01-08 10:36:02 +0530271{
272#define DS2PHYS(_dd, _ds) \
273 ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
274#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
275#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
276 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400277 u8 *ds;
Sujith55624202010-01-08 10:36:02 +0530278 struct ath_buf *bf;
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400279 int i, bsize, error, desc_len;
Sujith55624202010-01-08 10:36:02 +0530280
Joe Perches226afe62010-12-02 19:12:37 -0800281 ath_dbg(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",
282 name, nbuf, ndesc);
Sujith55624202010-01-08 10:36:02 +0530283
284 INIT_LIST_HEAD(head);
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400285
286 if (is_tx)
287 desc_len = sc->sc_ah->caps.tx_desc_len;
288 else
289 desc_len = sizeof(struct ath_desc);
290
Sujith55624202010-01-08 10:36:02 +0530291 /* ath_desc must be a multiple of DWORDs */
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400292 if ((desc_len % 4) != 0) {
Joe Perches38002762010-12-02 19:12:36 -0800293 ath_err(common, "ath_desc not DWORD aligned\n");
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400294 BUG_ON((desc_len % 4) != 0);
Sujith55624202010-01-08 10:36:02 +0530295 error = -ENOMEM;
296 goto fail;
297 }
298
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400299 dd->dd_desc_len = desc_len * nbuf * ndesc;
Sujith55624202010-01-08 10:36:02 +0530300
301 /*
302 * Need additional DMA memory because we can't use
303 * descriptors that cross the 4K page boundary. Assume
304 * one skipped descriptor per 4K page.
305 */
306 if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
307 u32 ndesc_skipped =
308 ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len);
309 u32 dma_len;
310
311 while (ndesc_skipped) {
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400312 dma_len = ndesc_skipped * desc_len;
Sujith55624202010-01-08 10:36:02 +0530313 dd->dd_desc_len += dma_len;
314
315 ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len);
Joe Perchesee289b62010-05-17 22:47:34 -0700316 }
Sujith55624202010-01-08 10:36:02 +0530317 }
318
319 /* allocate descriptors */
320 dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
321 &dd->dd_desc_paddr, GFP_KERNEL);
322 if (dd->dd_desc == NULL) {
323 error = -ENOMEM;
324 goto fail;
325 }
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400326 ds = (u8 *) dd->dd_desc;
Joe Perches226afe62010-12-02 19:12:37 -0800327 ath_dbg(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
328 name, ds, (u32) dd->dd_desc_len,
329 ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
Sujith55624202010-01-08 10:36:02 +0530330
331 /* allocate buffers */
332 bsize = sizeof(struct ath_buf) * nbuf;
333 bf = kzalloc(bsize, GFP_KERNEL);
334 if (bf == NULL) {
335 error = -ENOMEM;
336 goto fail2;
337 }
338 dd->dd_bufptr = bf;
339
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400340 for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {
Sujith55624202010-01-08 10:36:02 +0530341 bf->bf_desc = ds;
342 bf->bf_daddr = DS2PHYS(dd, ds);
343
344 if (!(sc->sc_ah->caps.hw_caps &
345 ATH9K_HW_CAP_4KB_SPLITTRANS)) {
346 /*
347 * Skip descriptor addresses which can cause 4KB
348 * boundary crossing (addr + length) with a 32 dword
349 * descriptor fetch.
350 */
351 while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
352 BUG_ON((caddr_t) bf->bf_desc >=
353 ((caddr_t) dd->dd_desc +
354 dd->dd_desc_len));
355
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400356 ds += (desc_len * ndesc);
Sujith55624202010-01-08 10:36:02 +0530357 bf->bf_desc = ds;
358 bf->bf_daddr = DS2PHYS(dd, ds);
359 }
360 }
361 list_add_tail(&bf->list, head);
362 }
363 return 0;
364fail2:
365 dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
366 dd->dd_desc_paddr);
367fail:
368 memset(dd, 0, sizeof(*dd));
369 return error;
370#undef ATH_DESC_4KB_BOUND_CHECK
371#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
372#undef DS2PHYS
373}
374
Sujith285f2dd2010-01-08 10:36:07 +0530375static void ath9k_init_crypto(struct ath_softc *sc)
Sujith55624202010-01-08 10:36:02 +0530376{
Sujith285f2dd2010-01-08 10:36:07 +0530377 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
378 int i = 0;
Sujith55624202010-01-08 10:36:02 +0530379
380 /* Get the hardware key cache size. */
Sujith285f2dd2010-01-08 10:36:07 +0530381 common->keymax = sc->sc_ah->caps.keycache_size;
Sujith55624202010-01-08 10:36:02 +0530382 if (common->keymax > ATH_KEYMAX) {
Joe Perches226afe62010-12-02 19:12:37 -0800383 ath_dbg(common, ATH_DBG_ANY,
384 "Warning, using only %u entries in %u key cache\n",
385 ATH_KEYMAX, common->keymax);
Sujith55624202010-01-08 10:36:02 +0530386 common->keymax = ATH_KEYMAX;
387 }
388
389 /*
390 * Reset the key cache since some parts do not
391 * reset the contents on initial power up.
392 */
393 for (i = 0; i < common->keymax; i++)
Bruno Randolf040e5392010-09-08 16:05:04 +0900394 ath_hw_keyreset(common, (u16) i);
Sujith55624202010-01-08 10:36:02 +0530395
Felix Fietkau716f7fc2010-06-12 17:22:28 +0200396 /*
Sujith55624202010-01-08 10:36:02 +0530397 * Check whether the separate key cache entries
398 * are required to handle both tx+rx MIC keys.
399 * With split mic keys the number of stations is limited
400 * to 27 otherwise 59.
401 */
Bruno Randolf117675d2010-09-08 16:04:54 +0900402 if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
403 common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
Sujith285f2dd2010-01-08 10:36:07 +0530404}
Sujith55624202010-01-08 10:36:02 +0530405
Sujith285f2dd2010-01-08 10:36:07 +0530406static int ath9k_init_btcoex(struct ath_softc *sc)
407{
Felix Fietkau066dae92010-11-07 14:59:39 +0100408 struct ath_txq *txq;
409 int r;
Sujith285f2dd2010-01-08 10:36:07 +0530410
411 switch (sc->sc_ah->btcoex_hw.scheme) {
412 case ATH_BTCOEX_CFG_NONE:
413 break;
414 case ATH_BTCOEX_CFG_2WIRE:
415 ath9k_hw_btcoex_init_2wire(sc->sc_ah);
416 break;
417 case ATH_BTCOEX_CFG_3WIRE:
418 ath9k_hw_btcoex_init_3wire(sc->sc_ah);
419 r = ath_init_btcoex_timer(sc);
420 if (r)
421 return -1;
Felix Fietkau066dae92010-11-07 14:59:39 +0100422 txq = sc->tx.txq_map[WME_AC_BE];
423 ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
Sujith285f2dd2010-01-08 10:36:07 +0530424 sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
425 break;
426 default:
427 WARN_ON(1);
428 break;
Sujith55624202010-01-08 10:36:02 +0530429 }
430
Sujith285f2dd2010-01-08 10:36:07 +0530431 return 0;
432}
Sujith55624202010-01-08 10:36:02 +0530433
Sujith285f2dd2010-01-08 10:36:07 +0530434static int ath9k_init_queues(struct ath_softc *sc)
435{
Sujith285f2dd2010-01-08 10:36:07 +0530436 int i = 0;
Sujith55624202010-01-08 10:36:02 +0530437
Sujith285f2dd2010-01-08 10:36:07 +0530438 sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
Sujith285f2dd2010-01-08 10:36:07 +0530439 sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
Sujith55624202010-01-08 10:36:02 +0530440
Sujith285f2dd2010-01-08 10:36:07 +0530441 sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
442 ath_cabq_update(sc);
443
Felix Fietkau066dae92010-11-07 14:59:39 +0100444 for (i = 0; i < WME_NUM_AC; i++)
445 sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
Sujith285f2dd2010-01-08 10:36:07 +0530446
447 return 0;
Sujith285f2dd2010-01-08 10:36:07 +0530448}
449
Felix Fietkauf209f522010-10-01 01:06:53 +0200450static int ath9k_init_channels_rates(struct ath_softc *sc)
Sujith285f2dd2010-01-08 10:36:07 +0530451{
Felix Fietkauf209f522010-10-01 01:06:53 +0200452 void *channels;
453
Felix Fietkaucac42202010-10-09 02:39:30 +0200454 BUILD_BUG_ON(ARRAY_SIZE(ath9k_2ghz_chantable) +
455 ARRAY_SIZE(ath9k_5ghz_chantable) !=
456 ATH9K_NUM_CHANNELS);
457
Felix Fietkaud4659912010-10-14 16:02:39 +0200458 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
Felix Fietkauf209f522010-10-01 01:06:53 +0200459 channels = kmemdup(ath9k_2ghz_chantable,
460 sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
461 if (!channels)
462 return -ENOMEM;
463
464 sc->sbands[IEEE80211_BAND_2GHZ].channels = channels;
Sujith55624202010-01-08 10:36:02 +0530465 sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
466 sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
467 ARRAY_SIZE(ath9k_2ghz_chantable);
468 sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
469 sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
470 ARRAY_SIZE(ath9k_legacy_rates);
471 }
472
Felix Fietkaud4659912010-10-14 16:02:39 +0200473 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
Felix Fietkauf209f522010-10-01 01:06:53 +0200474 channels = kmemdup(ath9k_5ghz_chantable,
475 sizeof(ath9k_5ghz_chantable), GFP_KERNEL);
476 if (!channels) {
477 if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
478 kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
479 return -ENOMEM;
480 }
481
482 sc->sbands[IEEE80211_BAND_5GHZ].channels = channels;
Sujith55624202010-01-08 10:36:02 +0530483 sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
484 sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
485 ARRAY_SIZE(ath9k_5ghz_chantable);
486 sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
487 ath9k_legacy_rates + 4;
488 sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
489 ARRAY_SIZE(ath9k_legacy_rates) - 4;
490 }
Felix Fietkauf209f522010-10-01 01:06:53 +0200491 return 0;
Sujith285f2dd2010-01-08 10:36:07 +0530492}
Sujith55624202010-01-08 10:36:02 +0530493
Sujith285f2dd2010-01-08 10:36:07 +0530494static void ath9k_init_misc(struct ath_softc *sc)
495{
496 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
497 int i = 0;
498
Sujith285f2dd2010-01-08 10:36:07 +0530499 setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
500
501 sc->config.txpowlimit = ATH_TXPOWER_MAX;
502
503 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
504 sc->sc_flags |= SC_OP_TXAGGR;
505 sc->sc_flags |= SC_OP_RXAGGR;
Sujith55624202010-01-08 10:36:02 +0530506 }
507
Sujith285f2dd2010-01-08 10:36:07 +0530508 common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
509 common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
510
Luis R. Rodriguez8fe65362010-04-15 17:38:14 -0400511 ath9k_hw_set_diversity(sc->sc_ah, true);
Sujith285f2dd2010-01-08 10:36:07 +0530512 sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
513
Felix Fietkau364734f2010-09-14 20:22:44 +0200514 memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
Sujith285f2dd2010-01-08 10:36:07 +0530515
516 sc->beacon.slottime = ATH9K_SLOT_TIME_9;
517
518 for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
519 sc->beacon.bslot[i] = NULL;
520 sc->beacon.bslot_aphy[i] = NULL;
521 }
Vasanthakumar Thiagarajan102885a2010-09-02 01:34:43 -0700522
523 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
524 sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
Sujith285f2dd2010-01-08 10:36:07 +0530525}
526
527static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
528 const struct ath_bus_ops *bus_ops)
529{
530 struct ath_hw *ah = NULL;
531 struct ath_common *common;
532 int ret = 0, i;
533 int csz = 0;
534
Sujith285f2dd2010-01-08 10:36:07 +0530535 ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
536 if (!ah)
537 return -ENOMEM;
538
539 ah->hw_version.devid = devid;
540 ah->hw_version.subsysid = subsysid;
541 sc->sc_ah = ah;
542
Felix Fietkaua05b5d452010-11-17 04:25:33 +0100543 if (!sc->dev->platform_data)
544 ah->ah_flags |= AH_USE_EEPROM;
545
Sujith285f2dd2010-01-08 10:36:07 +0530546 common = ath9k_hw_common(ah);
547 common->ops = &ath9k_common_ops;
548 common->bus_ops = bus_ops;
549 common->ah = ah;
550 common->hw = sc->hw;
551 common->priv = sc;
552 common->debug_mask = ath9k_debug;
Vasanthakumar Thiagarajan8f5dcb12010-11-26 06:10:06 -0800553 common->btcoex_enabled = ath9k_btcoex_enable == 1;
Ben Greear20b257442010-10-15 15:04:09 -0700554 spin_lock_init(&common->cc_lock);
Sujith285f2dd2010-01-08 10:36:07 +0530555
556 spin_lock_init(&sc->wiphy_lock);
Sujith285f2dd2010-01-08 10:36:07 +0530557 spin_lock_init(&sc->sc_serial_rw);
558 spin_lock_init(&sc->sc_pm_lock);
559 mutex_init(&sc->mutex);
560 tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
561 tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
562 (unsigned long)sc);
563
564 /*
565 * Cache line size is used to size and align various
566 * structures used to communicate with the hardware.
567 */
568 ath_read_cachesize(common, &csz);
569 common->cachelsz = csz << 2; /* convert to bytes */
570
Luis R. Rodriguezd70357d2010-04-15 17:38:06 -0400571 /* Initializes the hardware for all supported chipsets */
Sujith285f2dd2010-01-08 10:36:07 +0530572 ret = ath9k_hw_init(ah);
Luis R. Rodriguezd70357d2010-04-15 17:38:06 -0400573 if (ret)
Sujith285f2dd2010-01-08 10:36:07 +0530574 goto err_hw;
Sujith285f2dd2010-01-08 10:36:07 +0530575
Sujith285f2dd2010-01-08 10:36:07 +0530576 ret = ath9k_init_queues(sc);
577 if (ret)
578 goto err_queues;
579
580 ret = ath9k_init_btcoex(sc);
581 if (ret)
582 goto err_btcoex;
583
Felix Fietkauf209f522010-10-01 01:06:53 +0200584 ret = ath9k_init_channels_rates(sc);
585 if (ret)
586 goto err_btcoex;
587
Sujith285f2dd2010-01-08 10:36:07 +0530588 ath9k_init_crypto(sc);
Sujith285f2dd2010-01-08 10:36:07 +0530589 ath9k_init_misc(sc);
590
Sujith55624202010-01-08 10:36:02 +0530591 return 0;
Sujith285f2dd2010-01-08 10:36:07 +0530592
593err_btcoex:
Sujith55624202010-01-08 10:36:02 +0530594 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
595 if (ATH_TXQ_SETUP(sc, i))
596 ath_tx_cleanupq(sc, &sc->tx.txq[i]);
Sujith285f2dd2010-01-08 10:36:07 +0530597err_queues:
Sujith285f2dd2010-01-08 10:36:07 +0530598 ath9k_hw_deinit(ah);
599err_hw:
600 tasklet_kill(&sc->intr_tq);
601 tasklet_kill(&sc->bcon_tasklet);
Sujith55624202010-01-08 10:36:02 +0530602
Sujith285f2dd2010-01-08 10:36:07 +0530603 kfree(ah);
604 sc->sc_ah = NULL;
605
606 return ret;
Sujith55624202010-01-08 10:36:02 +0530607}
608
Felix Fietkaubabcbc22010-10-20 02:09:46 +0200609static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
610{
611 struct ieee80211_supported_band *sband;
612 struct ieee80211_channel *chan;
613 struct ath_hw *ah = sc->sc_ah;
614 struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
615 int i;
616
617 sband = &sc->sbands[band];
618 for (i = 0; i < sband->n_channels; i++) {
619 chan = &sband->channels[i];
620 ah->curchan = &ah->channels[chan->hw_value];
621 ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
622 ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
623 chan->max_power = reg->max_power_level / 2;
624 }
625}
626
627static void ath9k_init_txpower_limits(struct ath_softc *sc)
628{
629 struct ath_hw *ah = sc->sc_ah;
630 struct ath9k_channel *curchan = ah->curchan;
631
632 if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
633 ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
634 if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
635 ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
636
637 ah->curchan = curchan;
638}
639
Sujith285f2dd2010-01-08 10:36:07 +0530640void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
Sujith55624202010-01-08 10:36:02 +0530641{
Sujith285f2dd2010-01-08 10:36:07 +0530642 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
643
Sujith55624202010-01-08 10:36:02 +0530644 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
645 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
646 IEEE80211_HW_SIGNAL_DBM |
Sujith55624202010-01-08 10:36:02 +0530647 IEEE80211_HW_SUPPORTS_PS |
648 IEEE80211_HW_PS_NULLFUNC_STACK |
Vivek Natarajan05df4982010-02-09 11:34:50 +0530649 IEEE80211_HW_SPECTRUM_MGMT |
Mohammed Shafi Shajakhan0ce3bcf2010-12-07 21:14:15 +0530650 IEEE80211_HW_REPORTS_TX_ACK_STATUS |
651 IEEE80211_HW_NEED_DTIM_PERIOD;
Sujith55624202010-01-08 10:36:02 +0530652
Luis R. Rodriguez5ffaf8a2010-02-02 11:58:33 -0500653 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
654 hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
655
Sujith55624202010-01-08 10:36:02 +0530656 if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt)
657 hw->flags |= IEEE80211_HW_MFP_CAPABLE;
658
659 hw->wiphy->interface_modes =
Johannes Bergc426ee22010-11-26 11:38:04 +0100660 BIT(NL80211_IFTYPE_P2P_GO) |
661 BIT(NL80211_IFTYPE_P2P_CLIENT) |
Sujith55624202010-01-08 10:36:02 +0530662 BIT(NL80211_IFTYPE_AP) |
Bill Jordane51f3ef2010-10-01 11:20:39 -0400663 BIT(NL80211_IFTYPE_WDS) |
Sujith55624202010-01-08 10:36:02 +0530664 BIT(NL80211_IFTYPE_STATION) |
665 BIT(NL80211_IFTYPE_ADHOC) |
666 BIT(NL80211_IFTYPE_MESH_POINT);
667
Luis R. Rodriguez008443d2010-09-16 15:12:36 -0400668 if (AR_SREV_5416(sc->sc_ah))
669 hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
Sujith55624202010-01-08 10:36:02 +0530670
671 hw->queues = 4;
672 hw->max_rates = 4;
673 hw->channel_change_time = 5000;
674 hw->max_listen_interval = 10;
Felix Fietkau65896512010-01-24 03:26:11 +0100675 hw->max_rate_tries = 10;
Sujith55624202010-01-08 10:36:02 +0530676 hw->sta_data_size = sizeof(struct ath_node);
677 hw->vif_data_size = sizeof(struct ath_vif);
678
Felix Fietkau6e5c2b42010-09-20 13:45:40 +0200679#ifdef CONFIG_ATH9K_RATE_CONTROL
Sujith55624202010-01-08 10:36:02 +0530680 hw->rate_control_algorithm = "ath9k_rate_control";
Felix Fietkau6e5c2b42010-09-20 13:45:40 +0200681#endif
Sujith55624202010-01-08 10:36:02 +0530682
Felix Fietkaud4659912010-10-14 16:02:39 +0200683 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
Sujith55624202010-01-08 10:36:02 +0530684 hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
685 &sc->sbands[IEEE80211_BAND_2GHZ];
Felix Fietkaud4659912010-10-14 16:02:39 +0200686 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
Sujith55624202010-01-08 10:36:02 +0530687 hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
688 &sc->sbands[IEEE80211_BAND_5GHZ];
Sujith285f2dd2010-01-08 10:36:07 +0530689
690 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
Felix Fietkaud4659912010-10-14 16:02:39 +0200691 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
Sujith285f2dd2010-01-08 10:36:07 +0530692 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
Felix Fietkaud4659912010-10-14 16:02:39 +0200693 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
Sujith285f2dd2010-01-08 10:36:07 +0530694 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
695 }
696
697 SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
Sujith55624202010-01-08 10:36:02 +0530698}
699
Sujith285f2dd2010-01-08 10:36:07 +0530700int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
Sujith55624202010-01-08 10:36:02 +0530701 const struct ath_bus_ops *bus_ops)
702{
703 struct ieee80211_hw *hw = sc->hw;
Felix Fietkau9fa23e12010-10-15 20:03:31 +0200704 struct ath_wiphy *aphy = hw->priv;
Sujith55624202010-01-08 10:36:02 +0530705 struct ath_common *common;
706 struct ath_hw *ah;
Sujith285f2dd2010-01-08 10:36:07 +0530707 int error = 0;
Sujith55624202010-01-08 10:36:02 +0530708 struct ath_regulatory *reg;
709
Sujith285f2dd2010-01-08 10:36:07 +0530710 /* Bring up device */
711 error = ath9k_init_softc(devid, sc, subsysid, bus_ops);
Sujith55624202010-01-08 10:36:02 +0530712 if (error != 0)
Sujith285f2dd2010-01-08 10:36:07 +0530713 goto error_init;
Sujith55624202010-01-08 10:36:02 +0530714
715 ah = sc->sc_ah;
716 common = ath9k_hw_common(ah);
Sujith285f2dd2010-01-08 10:36:07 +0530717 ath9k_set_hw_capab(sc, hw);
Sujith55624202010-01-08 10:36:02 +0530718
Sujith285f2dd2010-01-08 10:36:07 +0530719 /* Initialize regulatory */
Sujith55624202010-01-08 10:36:02 +0530720 error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
721 ath9k_reg_notifier);
722 if (error)
Sujith285f2dd2010-01-08 10:36:07 +0530723 goto error_regd;
Sujith55624202010-01-08 10:36:02 +0530724
725 reg = &common->regulatory;
726
Sujith285f2dd2010-01-08 10:36:07 +0530727 /* Setup TX DMA */
Sujith55624202010-01-08 10:36:02 +0530728 error = ath_tx_init(sc, ATH_TXBUF);
729 if (error != 0)
Sujith285f2dd2010-01-08 10:36:07 +0530730 goto error_tx;
Sujith55624202010-01-08 10:36:02 +0530731
Sujith285f2dd2010-01-08 10:36:07 +0530732 /* Setup RX DMA */
Sujith55624202010-01-08 10:36:02 +0530733 error = ath_rx_init(sc, ATH_RXBUF);
734 if (error != 0)
Sujith285f2dd2010-01-08 10:36:07 +0530735 goto error_rx;
736
Felix Fietkaubabcbc22010-10-20 02:09:46 +0200737 ath9k_init_txpower_limits(sc);
738
Sujith285f2dd2010-01-08 10:36:07 +0530739 /* Register with mac80211 */
740 error = ieee80211_register_hw(hw);
741 if (error)
742 goto error_register;
743
Ben Greeareb272442010-11-29 14:13:22 -0800744 error = ath9k_init_debug(ah);
745 if (error) {
Joe Perches38002762010-12-02 19:12:36 -0800746 ath_err(common, "Unable to create debugfs files\n");
Ben Greeareb272442010-11-29 14:13:22 -0800747 goto error_world;
748 }
749
Sujith285f2dd2010-01-08 10:36:07 +0530750 /* Handle world regulatory */
751 if (!ath_is_world_regd(reg)) {
752 error = regulatory_hint(hw->wiphy, reg->alpha2);
753 if (error)
754 goto error_world;
755 }
Sujith55624202010-01-08 10:36:02 +0530756
Felix Fietkau347809f2010-07-02 00:09:52 +0200757 INIT_WORK(&sc->hw_check_work, ath_hw_check);
Felix Fietkau9f42c2b2010-06-12 00:34:01 -0400758 INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
Sujith55624202010-01-08 10:36:02 +0530759 INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
760 INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
761 sc->wiphy_scheduler_int = msecs_to_jiffies(500);
Felix Fietkau9fa23e12010-10-15 20:03:31 +0200762 aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
Sujith55624202010-01-08 10:36:02 +0530763
Sujith55624202010-01-08 10:36:02 +0530764 ath_init_leds(sc);
Sujith55624202010-01-08 10:36:02 +0530765 ath_start_rfkill_poll(sc);
766
Gabor Juhos98c316e2010-11-25 18:26:07 +0100767 pm_qos_add_request(&sc->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
Vivek Natarajan10598c12010-10-30 22:05:13 +0530768 PM_QOS_DEFAULT_VALUE);
769
Sujith55624202010-01-08 10:36:02 +0530770 return 0;
771
Sujith285f2dd2010-01-08 10:36:07 +0530772error_world:
773 ieee80211_unregister_hw(hw);
774error_register:
775 ath_rx_cleanup(sc);
776error_rx:
777 ath_tx_cleanup(sc);
778error_tx:
779 /* Nothing */
780error_regd:
781 ath9k_deinit_softc(sc);
782error_init:
Sujith55624202010-01-08 10:36:02 +0530783 return error;
784}
785
786/*****************************/
787/* De-Initialization */
788/*****************************/
789
Sujith285f2dd2010-01-08 10:36:07 +0530790static void ath9k_deinit_softc(struct ath_softc *sc)
Sujith55624202010-01-08 10:36:02 +0530791{
Sujith285f2dd2010-01-08 10:36:07 +0530792 int i = 0;
Sujith55624202010-01-08 10:36:02 +0530793
Felix Fietkauf209f522010-10-01 01:06:53 +0200794 if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
795 kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
796
797 if (sc->sbands[IEEE80211_BAND_5GHZ].channels)
798 kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);
799
Sujith285f2dd2010-01-08 10:36:07 +0530800 if ((sc->btcoex.no_stomp_timer) &&
801 sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
802 ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
Sujith55624202010-01-08 10:36:02 +0530803
Sujith285f2dd2010-01-08 10:36:07 +0530804 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
805 if (ATH_TXQ_SETUP(sc, i))
806 ath_tx_cleanupq(sc, &sc->tx.txq[i]);
807
Sujith285f2dd2010-01-08 10:36:07 +0530808 ath9k_hw_deinit(sc->sc_ah);
809
810 tasklet_kill(&sc->intr_tq);
811 tasklet_kill(&sc->bcon_tasklet);
Sujith736b3a22010-03-17 14:25:24 +0530812
813 kfree(sc->sc_ah);
814 sc->sc_ah = NULL;
Sujith55624202010-01-08 10:36:02 +0530815}
816
Sujith285f2dd2010-01-08 10:36:07 +0530817void ath9k_deinit_device(struct ath_softc *sc)
Sujith55624202010-01-08 10:36:02 +0530818{
819 struct ieee80211_hw *hw = sc->hw;
Sujith55624202010-01-08 10:36:02 +0530820 int i = 0;
821
822 ath9k_ps_wakeup(sc);
823
Sujith55624202010-01-08 10:36:02 +0530824 wiphy_rfkill_stop_polling(sc->hw->wiphy);
Sujith285f2dd2010-01-08 10:36:07 +0530825 ath_deinit_leds(sc);
Sujith55624202010-01-08 10:36:02 +0530826
827 for (i = 0; i < sc->num_sec_wiphy; i++) {
828 struct ath_wiphy *aphy = sc->sec_wiphy[i];
829 if (aphy == NULL)
830 continue;
831 sc->sec_wiphy[i] = NULL;
832 ieee80211_unregister_hw(aphy->hw);
833 ieee80211_free_hw(aphy->hw);
834 }
Sujith285f2dd2010-01-08 10:36:07 +0530835
Sujith55624202010-01-08 10:36:02 +0530836 ieee80211_unregister_hw(hw);
Gabor Juhos98c316e2010-11-25 18:26:07 +0100837 pm_qos_remove_request(&sc->pm_qos_req);
Sujith55624202010-01-08 10:36:02 +0530838 ath_rx_cleanup(sc);
839 ath_tx_cleanup(sc);
Sujith285f2dd2010-01-08 10:36:07 +0530840 ath9k_deinit_softc(sc);
Rajkumar Manoharan447a42c2010-07-08 12:12:29 +0530841 kfree(sc->sec_wiphy);
Sujith55624202010-01-08 10:36:02 +0530842}
843
844void ath_descdma_cleanup(struct ath_softc *sc,
845 struct ath_descdma *dd,
846 struct list_head *head)
847{
848 dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
849 dd->dd_desc_paddr);
850
851 INIT_LIST_HEAD(head);
852 kfree(dd->dd_bufptr);
853 memset(dd, 0, sizeof(*dd));
854}
855
Sujith55624202010-01-08 10:36:02 +0530856/************************/
857/* Module Hooks */
858/************************/
859
860static int __init ath9k_init(void)
861{
862 int error;
863
864 /* Register rate control algorithm */
865 error = ath_rate_control_register();
866 if (error != 0) {
867 printk(KERN_ERR
868 "ath9k: Unable to register rate control "
869 "algorithm: %d\n",
870 error);
871 goto err_out;
872 }
873
Sujith55624202010-01-08 10:36:02 +0530874 error = ath_pci_init();
875 if (error < 0) {
876 printk(KERN_ERR
877 "ath9k: No PCI devices found, driver not installed.\n");
878 error = -ENODEV;
Ben Greeareb272442010-11-29 14:13:22 -0800879 goto err_rate_unregister;
Sujith55624202010-01-08 10:36:02 +0530880 }
881
882 error = ath_ahb_init();
883 if (error < 0) {
884 error = -ENODEV;
885 goto err_pci_exit;
886 }
887
888 return 0;
889
890 err_pci_exit:
891 ath_pci_exit();
892
Sujith55624202010-01-08 10:36:02 +0530893 err_rate_unregister:
894 ath_rate_control_unregister();
895 err_out:
896 return error;
897}
898module_init(ath9k_init);
899
900static void __exit ath9k_exit(void)
901{
902 ath_ahb_exit();
903 ath_pci_exit();
Sujith55624202010-01-08 10:36:02 +0530904 ath_rate_control_unregister();
905 printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
906}
907module_exit(ath9k_exit);