blob: b855fe1adc394f428bfdeee05047a2f056062359 [file] [log] [blame]
Sujith55624202010-01-08 10:36:02 +05301/*
Sujith Manoharan5b681382011-05-17 13:36:18 +05302 * Copyright (c) 2008-2011 Atheros Communications Inc.
Sujith55624202010-01-08 10:36:02 +05303 *
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
Alexey Dobriyanb7f080c2011-06-16 11:01:34 +000017#include <linux/dma-mapping.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090018#include <linux/slab.h>
Felix Fietkau6fb1b1e2011-03-19 13:55:39 +010019#include <linux/ath9k_platform.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090020
Sujith55624202010-01-08 10:36:02 +053021#include "ath9k.h"
22
23static char *dev_info = "ath9k";
24
25MODULE_AUTHOR("Atheros Communications");
26MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
27MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
28MODULE_LICENSE("Dual BSD/GPL");
29
30static unsigned int ath9k_debug = ATH_DBG_DEFAULT;
31module_param_named(debug, ath9k_debug, uint, 0);
32MODULE_PARM_DESC(debug, "Debugging mask");
33
John W. Linville3e6109c2011-01-05 09:39:17 -050034int ath9k_modparam_nohwcrypt;
35module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444);
Sujith55624202010-01-08 10:36:02 +053036MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
37
Vivek Natarajan93dbbcc2010-08-25 19:34:52 +053038int led_blink;
Vivek Natarajan9a75c2f2010-06-22 11:52:37 +053039module_param_named(blink, led_blink, int, 0444);
40MODULE_PARM_DESC(blink, "Enable LED blink on activity");
41
Vasanthakumar Thiagarajan8f5dcb12010-11-26 06:10:06 -080042static int ath9k_btcoex_enable;
43module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444);
44MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
45
Rajkumar Manoharand5847472010-12-20 14:39:51 +053046bool is_ath9k_unloaded;
Sujith55624202010-01-08 10:36:02 +053047/* We use the hw_value as an index into our private channel structure */
48
49#define CHAN2G(_freq, _idx) { \
Mohammed Shafi Shajakhanb1c1d002010-12-17 20:44:36 +053050 .band = IEEE80211_BAND_2GHZ, \
Sujith55624202010-01-08 10:36:02 +053051 .center_freq = (_freq), \
52 .hw_value = (_idx), \
53 .max_power = 20, \
54}
55
56#define CHAN5G(_freq, _idx) { \
57 .band = IEEE80211_BAND_5GHZ, \
58 .center_freq = (_freq), \
59 .hw_value = (_idx), \
60 .max_power = 20, \
61}
62
63/* Some 2 GHz radios are actually tunable on 2312-2732
64 * on 5 MHz steps, we support the channels which we know
65 * we have calibration data for all cards though to make
66 * this static */
Felix Fietkauf209f522010-10-01 01:06:53 +020067static const struct ieee80211_channel ath9k_2ghz_chantable[] = {
Sujith55624202010-01-08 10:36:02 +053068 CHAN2G(2412, 0), /* Channel 1 */
69 CHAN2G(2417, 1), /* Channel 2 */
70 CHAN2G(2422, 2), /* Channel 3 */
71 CHAN2G(2427, 3), /* Channel 4 */
72 CHAN2G(2432, 4), /* Channel 5 */
73 CHAN2G(2437, 5), /* Channel 6 */
74 CHAN2G(2442, 6), /* Channel 7 */
75 CHAN2G(2447, 7), /* Channel 8 */
76 CHAN2G(2452, 8), /* Channel 9 */
77 CHAN2G(2457, 9), /* Channel 10 */
78 CHAN2G(2462, 10), /* Channel 11 */
79 CHAN2G(2467, 11), /* Channel 12 */
80 CHAN2G(2472, 12), /* Channel 13 */
81 CHAN2G(2484, 13), /* Channel 14 */
82};
83
84/* Some 5 GHz radios are actually tunable on XXXX-YYYY
85 * on 5 MHz steps, we support the channels which we know
86 * we have calibration data for all cards though to make
87 * this static */
Felix Fietkauf209f522010-10-01 01:06:53 +020088static const struct ieee80211_channel ath9k_5ghz_chantable[] = {
Sujith55624202010-01-08 10:36:02 +053089 /* _We_ call this UNII 1 */
90 CHAN5G(5180, 14), /* Channel 36 */
91 CHAN5G(5200, 15), /* Channel 40 */
92 CHAN5G(5220, 16), /* Channel 44 */
93 CHAN5G(5240, 17), /* Channel 48 */
94 /* _We_ call this UNII 2 */
95 CHAN5G(5260, 18), /* Channel 52 */
96 CHAN5G(5280, 19), /* Channel 56 */
97 CHAN5G(5300, 20), /* Channel 60 */
98 CHAN5G(5320, 21), /* Channel 64 */
99 /* _We_ call this "Middle band" */
100 CHAN5G(5500, 22), /* Channel 100 */
101 CHAN5G(5520, 23), /* Channel 104 */
102 CHAN5G(5540, 24), /* Channel 108 */
103 CHAN5G(5560, 25), /* Channel 112 */
104 CHAN5G(5580, 26), /* Channel 116 */
105 CHAN5G(5600, 27), /* Channel 120 */
106 CHAN5G(5620, 28), /* Channel 124 */
107 CHAN5G(5640, 29), /* Channel 128 */
108 CHAN5G(5660, 30), /* Channel 132 */
109 CHAN5G(5680, 31), /* Channel 136 */
110 CHAN5G(5700, 32), /* Channel 140 */
111 /* _We_ call this UNII 3 */
112 CHAN5G(5745, 33), /* Channel 149 */
113 CHAN5G(5765, 34), /* Channel 153 */
114 CHAN5G(5785, 35), /* Channel 157 */
115 CHAN5G(5805, 36), /* Channel 161 */
116 CHAN5G(5825, 37), /* Channel 165 */
117};
118
119/* Atheros hardware rate code addition for short premble */
120#define SHPCHECK(__hw_rate, __flags) \
121 ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0)
122
123#define RATE(_bitrate, _hw_rate, _flags) { \
124 .bitrate = (_bitrate), \
125 .flags = (_flags), \
126 .hw_value = (_hw_rate), \
127 .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \
128}
129
130static struct ieee80211_rate ath9k_legacy_rates[] = {
131 RATE(10, 0x1b, 0),
132 RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE),
133 RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE),
134 RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE),
135 RATE(60, 0x0b, 0),
136 RATE(90, 0x0f, 0),
137 RATE(120, 0x0a, 0),
138 RATE(180, 0x0e, 0),
139 RATE(240, 0x09, 0),
140 RATE(360, 0x0d, 0),
141 RATE(480, 0x08, 0),
142 RATE(540, 0x0c, 0),
143};
144
Felix Fietkau0cf55c22011-02-27 22:26:40 +0100145#ifdef CONFIG_MAC80211_LEDS
146static const struct ieee80211_tpt_blink ath9k_tpt_blink[] = {
147 { .throughput = 0 * 1024, .blink_time = 334 },
148 { .throughput = 1 * 1024, .blink_time = 260 },
149 { .throughput = 5 * 1024, .blink_time = 220 },
150 { .throughput = 10 * 1024, .blink_time = 190 },
151 { .throughput = 20 * 1024, .blink_time = 170 },
152 { .throughput = 50 * 1024, .blink_time = 150 },
153 { .throughput = 70 * 1024, .blink_time = 130 },
154 { .throughput = 100 * 1024, .blink_time = 110 },
155 { .throughput = 200 * 1024, .blink_time = 80 },
156 { .throughput = 300 * 1024, .blink_time = 50 },
157};
158#endif
159
Sujith285f2dd2010-01-08 10:36:07 +0530160static void ath9k_deinit_softc(struct ath_softc *sc);
Sujith55624202010-01-08 10:36:02 +0530161
162/*
163 * Read and write, they both share the same lock. We do this to serialize
164 * reads and writes on Atheros 802.11n PCI devices only. This is required
165 * as the FIFO on these devices can only accept sanely 2 requests.
166 */
167
168static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
169{
170 struct ath_hw *ah = (struct ath_hw *) hw_priv;
171 struct ath_common *common = ath9k_hw_common(ah);
172 struct ath_softc *sc = (struct ath_softc *) common->priv;
173
174 if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
175 unsigned long flags;
176 spin_lock_irqsave(&sc->sc_serial_rw, flags);
177 iowrite32(val, sc->mem + reg_offset);
178 spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
179 } else
180 iowrite32(val, sc->mem + reg_offset);
181}
182
183static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
184{
185 struct ath_hw *ah = (struct ath_hw *) hw_priv;
186 struct ath_common *common = ath9k_hw_common(ah);
187 struct ath_softc *sc = (struct ath_softc *) common->priv;
188 u32 val;
189
190 if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
191 unsigned long flags;
192 spin_lock_irqsave(&sc->sc_serial_rw, flags);
193 val = ioread32(sc->mem + reg_offset);
194 spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
195 } else
196 val = ioread32(sc->mem + reg_offset);
197 return val;
198}
199
Felix Fietkau845e03c2011-03-23 20:57:25 +0100200static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
201{
202 struct ath_hw *ah = (struct ath_hw *) hw_priv;
203 struct ath_common *common = ath9k_hw_common(ah);
204 struct ath_softc *sc = (struct ath_softc *) common->priv;
205 unsigned long uninitialized_var(flags);
206 u32 val;
207
208 if (ah->config.serialize_regmode == SER_REG_MODE_ON)
209 spin_lock_irqsave(&sc->sc_serial_rw, flags);
210
211 val = ioread32(sc->mem + reg_offset);
212 val &= ~clr;
213 val |= set;
214 iowrite32(val, sc->mem + reg_offset);
215
216 if (ah->config.serialize_regmode == SER_REG_MODE_ON)
217 spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
218
219 return val;
220}
221
Sujith55624202010-01-08 10:36:02 +0530222/**************************/
223/* Initialization */
224/**************************/
225
226static void setup_ht_cap(struct ath_softc *sc,
227 struct ieee80211_sta_ht_cap *ht_info)
228{
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200229 struct ath_hw *ah = sc->sc_ah;
230 struct ath_common *common = ath9k_hw_common(ah);
Sujith55624202010-01-08 10:36:02 +0530231 u8 tx_streams, rx_streams;
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200232 int i, max_streams;
Sujith55624202010-01-08 10:36:02 +0530233
234 ht_info->ht_supported = true;
235 ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
236 IEEE80211_HT_CAP_SM_PS |
237 IEEE80211_HT_CAP_SGI_40 |
238 IEEE80211_HT_CAP_DSSSCCK40;
239
Luis R. Rodriguezb0a33442010-04-15 17:39:39 -0400240 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC)
241 ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
242
Vasanthakumar Thiagarajan6473d242010-05-13 18:42:38 -0700243 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
244 ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
245
Sujith55624202010-01-08 10:36:02 +0530246 ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
247 ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
248
Gabor Juhos72161982011-06-21 11:23:42 +0200249 if (AR_SREV_9330(ah) || AR_SREV_9485(ah))
Vasanthakumar Thiagarajan7f1c7a62010-12-06 04:27:41 -0800250 max_streams = 1;
251 else if (AR_SREV_9300_20_OR_LATER(ah))
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200252 max_streams = 3;
253 else
254 max_streams = 2;
255
Felix Fietkau7a370812010-09-22 12:34:52 +0200256 if (AR_SREV_9280_20_OR_LATER(ah)) {
Felix Fietkau074a8c02010-04-19 19:57:36 +0200257 if (max_streams >= 2)
258 ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
259 ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
260 }
261
Sujith55624202010-01-08 10:36:02 +0530262 /* set up supported mcs set */
263 memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
Sujith61389f32010-06-02 15:53:37 +0530264 tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams);
265 rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams);
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200266
Joe Perches226afe62010-12-02 19:12:37 -0800267 ath_dbg(common, ATH_DBG_CONFIG,
268 "TX streams %d, RX streams: %d\n",
269 tx_streams, rx_streams);
Sujith55624202010-01-08 10:36:02 +0530270
271 if (tx_streams != rx_streams) {
Sujith55624202010-01-08 10:36:02 +0530272 ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
273 ht_info->mcs.tx_params |= ((tx_streams - 1) <<
274 IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
275 }
276
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200277 for (i = 0; i < rx_streams; i++)
278 ht_info->mcs.rx_mask[i] = 0xff;
Sujith55624202010-01-08 10:36:02 +0530279
280 ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
281}
282
283static int ath9k_reg_notifier(struct wiphy *wiphy,
284 struct regulatory_request *request)
285{
286 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
Felix Fietkau9ac586152011-01-24 19:23:18 +0100287 struct ath_softc *sc = hw->priv;
Sujith55624202010-01-08 10:36:02 +0530288 struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah);
289
290 return ath_reg_notifier_apply(wiphy, request, reg);
291}
292
293/*
294 * This function will allocate both the DMA descriptor structure, and the
295 * buffers it contains. These are used to contain the descriptors used
296 * by the system.
297*/
298int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
299 struct list_head *head, const char *name,
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400300 int nbuf, int ndesc, bool is_tx)
Sujith55624202010-01-08 10:36:02 +0530301{
Sujith55624202010-01-08 10:36:02 +0530302 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400303 u8 *ds;
Sujith55624202010-01-08 10:36:02 +0530304 struct ath_buf *bf;
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400305 int i, bsize, error, desc_len;
Sujith55624202010-01-08 10:36:02 +0530306
Joe Perches226afe62010-12-02 19:12:37 -0800307 ath_dbg(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",
308 name, nbuf, ndesc);
Sujith55624202010-01-08 10:36:02 +0530309
310 INIT_LIST_HEAD(head);
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400311
312 if (is_tx)
313 desc_len = sc->sc_ah->caps.tx_desc_len;
314 else
315 desc_len = sizeof(struct ath_desc);
316
Sujith55624202010-01-08 10:36:02 +0530317 /* ath_desc must be a multiple of DWORDs */
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400318 if ((desc_len % 4) != 0) {
Joe Perches38002762010-12-02 19:12:36 -0800319 ath_err(common, "ath_desc not DWORD aligned\n");
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400320 BUG_ON((desc_len % 4) != 0);
Sujith55624202010-01-08 10:36:02 +0530321 error = -ENOMEM;
322 goto fail;
323 }
324
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400325 dd->dd_desc_len = desc_len * nbuf * ndesc;
Sujith55624202010-01-08 10:36:02 +0530326
327 /*
328 * Need additional DMA memory because we can't use
329 * descriptors that cross the 4K page boundary. Assume
330 * one skipped descriptor per 4K page.
331 */
332 if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
333 u32 ndesc_skipped =
334 ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len);
335 u32 dma_len;
336
337 while (ndesc_skipped) {
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400338 dma_len = ndesc_skipped * desc_len;
Sujith55624202010-01-08 10:36:02 +0530339 dd->dd_desc_len += dma_len;
340
341 ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len);
Joe Perchesee289b62010-05-17 22:47:34 -0700342 }
Sujith55624202010-01-08 10:36:02 +0530343 }
344
345 /* allocate descriptors */
346 dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
347 &dd->dd_desc_paddr, GFP_KERNEL);
348 if (dd->dd_desc == NULL) {
349 error = -ENOMEM;
350 goto fail;
351 }
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400352 ds = (u8 *) dd->dd_desc;
Joe Perches226afe62010-12-02 19:12:37 -0800353 ath_dbg(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
354 name, ds, (u32) dd->dd_desc_len,
355 ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
Sujith55624202010-01-08 10:36:02 +0530356
357 /* allocate buffers */
358 bsize = sizeof(struct ath_buf) * nbuf;
359 bf = kzalloc(bsize, GFP_KERNEL);
360 if (bf == NULL) {
361 error = -ENOMEM;
362 goto fail2;
363 }
364 dd->dd_bufptr = bf;
365
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400366 for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {
Sujith55624202010-01-08 10:36:02 +0530367 bf->bf_desc = ds;
368 bf->bf_daddr = DS2PHYS(dd, ds);
369
370 if (!(sc->sc_ah->caps.hw_caps &
371 ATH9K_HW_CAP_4KB_SPLITTRANS)) {
372 /*
373 * Skip descriptor addresses which can cause 4KB
374 * boundary crossing (addr + length) with a 32 dword
375 * descriptor fetch.
376 */
377 while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
378 BUG_ON((caddr_t) bf->bf_desc >=
379 ((caddr_t) dd->dd_desc +
380 dd->dd_desc_len));
381
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400382 ds += (desc_len * ndesc);
Sujith55624202010-01-08 10:36:02 +0530383 bf->bf_desc = ds;
384 bf->bf_daddr = DS2PHYS(dd, ds);
385 }
386 }
387 list_add_tail(&bf->list, head);
388 }
389 return 0;
390fail2:
391 dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
392 dd->dd_desc_paddr);
393fail:
394 memset(dd, 0, sizeof(*dd));
395 return error;
Sujith55624202010-01-08 10:36:02 +0530396}
397
Mohammed Shafi Shajakhandb7ec382010-12-22 12:20:12 +0530398void ath9k_init_crypto(struct ath_softc *sc)
Sujith55624202010-01-08 10:36:02 +0530399{
Sujith285f2dd2010-01-08 10:36:07 +0530400 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
401 int i = 0;
Sujith55624202010-01-08 10:36:02 +0530402
403 /* Get the hardware key cache size. */
Felix Fietkau6de12a12011-03-23 20:57:31 +0100404 common->keymax = AR_KEYTABLE_SIZE;
Sujith55624202010-01-08 10:36:02 +0530405
406 /*
407 * Reset the key cache since some parts do not
408 * reset the contents on initial power up.
409 */
410 for (i = 0; i < common->keymax; i++)
Bruno Randolf040e5392010-09-08 16:05:04 +0900411 ath_hw_keyreset(common, (u16) i);
Sujith55624202010-01-08 10:36:02 +0530412
Felix Fietkau716f7fc2010-06-12 17:22:28 +0200413 /*
Sujith55624202010-01-08 10:36:02 +0530414 * Check whether the separate key cache entries
415 * are required to handle both tx+rx MIC keys.
416 * With split mic keys the number of stations is limited
417 * to 27 otherwise 59.
418 */
Bruno Randolf117675d2010-09-08 16:04:54 +0900419 if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
420 common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
Sujith285f2dd2010-01-08 10:36:07 +0530421}
Sujith55624202010-01-08 10:36:02 +0530422
Sujith285f2dd2010-01-08 10:36:07 +0530423static int ath9k_init_btcoex(struct ath_softc *sc)
424{
Felix Fietkau066dae92010-11-07 14:59:39 +0100425 struct ath_txq *txq;
426 int r;
Sujith285f2dd2010-01-08 10:36:07 +0530427
428 switch (sc->sc_ah->btcoex_hw.scheme) {
429 case ATH_BTCOEX_CFG_NONE:
430 break;
431 case ATH_BTCOEX_CFG_2WIRE:
432 ath9k_hw_btcoex_init_2wire(sc->sc_ah);
433 break;
434 case ATH_BTCOEX_CFG_3WIRE:
435 ath9k_hw_btcoex_init_3wire(sc->sc_ah);
436 r = ath_init_btcoex_timer(sc);
437 if (r)
438 return -1;
Felix Fietkau066dae92010-11-07 14:59:39 +0100439 txq = sc->tx.txq_map[WME_AC_BE];
440 ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
Sujith285f2dd2010-01-08 10:36:07 +0530441 sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
442 break;
443 default:
444 WARN_ON(1);
445 break;
Sujith55624202010-01-08 10:36:02 +0530446 }
447
Sujith285f2dd2010-01-08 10:36:07 +0530448 return 0;
449}
Sujith55624202010-01-08 10:36:02 +0530450
Sujith285f2dd2010-01-08 10:36:07 +0530451static int ath9k_init_queues(struct ath_softc *sc)
452{
Sujith285f2dd2010-01-08 10:36:07 +0530453 int i = 0;
Sujith55624202010-01-08 10:36:02 +0530454
Sujith285f2dd2010-01-08 10:36:07 +0530455 sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
Sujith285f2dd2010-01-08 10:36:07 +0530456 sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
Sujith55624202010-01-08 10:36:02 +0530457
Sujith285f2dd2010-01-08 10:36:07 +0530458 sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
459 ath_cabq_update(sc);
460
Ben Greear60f2d1d2011-01-09 23:11:52 -0800461 for (i = 0; i < WME_NUM_AC; i++) {
Felix Fietkau066dae92010-11-07 14:59:39 +0100462 sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
Ben Greear60f2d1d2011-01-09 23:11:52 -0800463 sc->tx.txq_map[i]->mac80211_qnum = i;
464 }
Sujith285f2dd2010-01-08 10:36:07 +0530465 return 0;
Sujith285f2dd2010-01-08 10:36:07 +0530466}
467
Felix Fietkauf209f522010-10-01 01:06:53 +0200468static int ath9k_init_channels_rates(struct ath_softc *sc)
Sujith285f2dd2010-01-08 10:36:07 +0530469{
Felix Fietkauf209f522010-10-01 01:06:53 +0200470 void *channels;
471
Felix Fietkaucac42202010-10-09 02:39:30 +0200472 BUILD_BUG_ON(ARRAY_SIZE(ath9k_2ghz_chantable) +
473 ARRAY_SIZE(ath9k_5ghz_chantable) !=
474 ATH9K_NUM_CHANNELS);
475
Felix Fietkaud4659912010-10-14 16:02:39 +0200476 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
Felix Fietkauf209f522010-10-01 01:06:53 +0200477 channels = kmemdup(ath9k_2ghz_chantable,
478 sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
479 if (!channels)
480 return -ENOMEM;
481
482 sc->sbands[IEEE80211_BAND_2GHZ].channels = channels;
Sujith55624202010-01-08 10:36:02 +0530483 sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
484 sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
485 ARRAY_SIZE(ath9k_2ghz_chantable);
486 sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
487 sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
488 ARRAY_SIZE(ath9k_legacy_rates);
489 }
490
Felix Fietkaud4659912010-10-14 16:02:39 +0200491 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
Felix Fietkauf209f522010-10-01 01:06:53 +0200492 channels = kmemdup(ath9k_5ghz_chantable,
493 sizeof(ath9k_5ghz_chantable), GFP_KERNEL);
494 if (!channels) {
495 if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
496 kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
497 return -ENOMEM;
498 }
499
500 sc->sbands[IEEE80211_BAND_5GHZ].channels = channels;
Sujith55624202010-01-08 10:36:02 +0530501 sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
502 sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
503 ARRAY_SIZE(ath9k_5ghz_chantable);
504 sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
505 ath9k_legacy_rates + 4;
506 sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
507 ARRAY_SIZE(ath9k_legacy_rates) - 4;
508 }
Felix Fietkauf209f522010-10-01 01:06:53 +0200509 return 0;
Sujith285f2dd2010-01-08 10:36:07 +0530510}
Sujith55624202010-01-08 10:36:02 +0530511
Sujith285f2dd2010-01-08 10:36:07 +0530512static void ath9k_init_misc(struct ath_softc *sc)
513{
514 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
515 int i = 0;
Sujith285f2dd2010-01-08 10:36:07 +0530516 setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
517
518 sc->config.txpowlimit = ATH_TXPOWER_MAX;
519
520 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
521 sc->sc_flags |= SC_OP_TXAGGR;
522 sc->sc_flags |= SC_OP_RXAGGR;
Sujith55624202010-01-08 10:36:02 +0530523 }
524
Sujith285f2dd2010-01-08 10:36:07 +0530525 common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
526 common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
527
Luis R. Rodriguez8fe65362010-04-15 17:38:14 -0400528 ath9k_hw_set_diversity(sc->sc_ah, true);
Sujith285f2dd2010-01-08 10:36:07 +0530529 sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
530
Felix Fietkau364734f2010-09-14 20:22:44 +0200531 memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
Sujith285f2dd2010-01-08 10:36:07 +0530532
533 sc->beacon.slottime = ATH9K_SLOT_TIME_9;
534
Felix Fietkau7545daf2011-01-24 19:23:16 +0100535 for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++)
Sujith285f2dd2010-01-08 10:36:07 +0530536 sc->beacon.bslot[i] = NULL;
Vasanthakumar Thiagarajan102885a2010-09-02 01:34:43 -0700537
538 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
539 sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
Sujith285f2dd2010-01-08 10:36:07 +0530540}
541
542static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
543 const struct ath_bus_ops *bus_ops)
544{
Felix Fietkau6fb1b1e2011-03-19 13:55:39 +0100545 struct ath9k_platform_data *pdata = sc->dev->platform_data;
Sujith285f2dd2010-01-08 10:36:07 +0530546 struct ath_hw *ah = NULL;
547 struct ath_common *common;
548 int ret = 0, i;
549 int csz = 0;
550
Sujith285f2dd2010-01-08 10:36:07 +0530551 ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
552 if (!ah)
553 return -ENOMEM;
554
Ben Greear233536e2011-01-09 23:11:44 -0800555 ah->hw = sc->hw;
Sujith285f2dd2010-01-08 10:36:07 +0530556 ah->hw_version.devid = devid;
557 ah->hw_version.subsysid = subsysid;
Felix Fietkauf9f84e92011-03-23 20:57:24 +0100558 ah->reg_ops.read = ath9k_ioread32;
559 ah->reg_ops.write = ath9k_iowrite32;
Felix Fietkau845e03c2011-03-23 20:57:25 +0100560 ah->reg_ops.rmw = ath9k_reg_rmw;
Sujith285f2dd2010-01-08 10:36:07 +0530561 sc->sc_ah = ah;
562
Felix Fietkau6de66dd2011-03-19 13:55:40 +0100563 if (!pdata) {
Felix Fietkaua05b5d452010-11-17 04:25:33 +0100564 ah->ah_flags |= AH_USE_EEPROM;
Felix Fietkau6de66dd2011-03-19 13:55:40 +0100565 sc->sc_ah->led_pin = -1;
566 } else {
567 sc->sc_ah->gpio_mask = pdata->gpio_mask;
568 sc->sc_ah->gpio_val = pdata->gpio_val;
569 sc->sc_ah->led_pin = pdata->led_pin;
Vasanthakumar Thiagarajanf2f5f2a2011-04-19 19:29:01 +0530570 ah->is_clk_25mhz = pdata->is_clk_25mhz;
Gabor Juhos37625612011-06-21 11:23:23 +0200571 ah->get_mac_revision = pdata->get_mac_revision;
Gabor Juhos7d95847c2011-06-21 11:23:51 +0200572 ah->external_reset = pdata->external_reset;
Felix Fietkau6de66dd2011-03-19 13:55:40 +0100573 }
Felix Fietkaua05b5d452010-11-17 04:25:33 +0100574
Sujith285f2dd2010-01-08 10:36:07 +0530575 common = ath9k_hw_common(ah);
Felix Fietkauf9f84e92011-03-23 20:57:24 +0100576 common->ops = &ah->reg_ops;
Sujith285f2dd2010-01-08 10:36:07 +0530577 common->bus_ops = bus_ops;
578 common->ah = ah;
579 common->hw = sc->hw;
580 common->priv = sc;
581 common->debug_mask = ath9k_debug;
Vasanthakumar Thiagarajan8f5dcb12010-11-26 06:10:06 -0800582 common->btcoex_enabled = ath9k_btcoex_enable == 1;
Mohammed Shafi Shajakhan05c0be22011-05-26 10:56:15 +0530583 common->disable_ani = false;
Ben Greear20b257442010-10-15 15:04:09 -0700584 spin_lock_init(&common->cc_lock);
Sujith285f2dd2010-01-08 10:36:07 +0530585
Sujith285f2dd2010-01-08 10:36:07 +0530586 spin_lock_init(&sc->sc_serial_rw);
587 spin_lock_init(&sc->sc_pm_lock);
588 mutex_init(&sc->mutex);
Ben Greear7f010c92011-01-09 23:11:49 -0800589#ifdef CONFIG_ATH9K_DEBUGFS
590 spin_lock_init(&sc->nodes_lock);
591 INIT_LIST_HEAD(&sc->nodes);
592#endif
Sujith285f2dd2010-01-08 10:36:07 +0530593 tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
594 tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
595 (unsigned long)sc);
596
597 /*
598 * Cache line size is used to size and align various
599 * structures used to communicate with the hardware.
600 */
601 ath_read_cachesize(common, &csz);
602 common->cachelsz = csz << 2; /* convert to bytes */
603
Luis R. Rodriguezd70357d2010-04-15 17:38:06 -0400604 /* Initializes the hardware for all supported chipsets */
Sujith285f2dd2010-01-08 10:36:07 +0530605 ret = ath9k_hw_init(ah);
Luis R. Rodriguezd70357d2010-04-15 17:38:06 -0400606 if (ret)
Sujith285f2dd2010-01-08 10:36:07 +0530607 goto err_hw;
Sujith285f2dd2010-01-08 10:36:07 +0530608
Felix Fietkau6fb1b1e2011-03-19 13:55:39 +0100609 if (pdata && pdata->macaddr)
610 memcpy(common->macaddr, pdata->macaddr, ETH_ALEN);
611
Sujith285f2dd2010-01-08 10:36:07 +0530612 ret = ath9k_init_queues(sc);
613 if (ret)
614 goto err_queues;
615
616 ret = ath9k_init_btcoex(sc);
617 if (ret)
618 goto err_btcoex;
619
Felix Fietkauf209f522010-10-01 01:06:53 +0200620 ret = ath9k_init_channels_rates(sc);
621 if (ret)
622 goto err_btcoex;
623
Sujith285f2dd2010-01-08 10:36:07 +0530624 ath9k_init_crypto(sc);
Sujith285f2dd2010-01-08 10:36:07 +0530625 ath9k_init_misc(sc);
626
Sujith55624202010-01-08 10:36:02 +0530627 return 0;
Sujith285f2dd2010-01-08 10:36:07 +0530628
629err_btcoex:
Sujith55624202010-01-08 10:36:02 +0530630 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
631 if (ATH_TXQ_SETUP(sc, i))
632 ath_tx_cleanupq(sc, &sc->tx.txq[i]);
Sujith285f2dd2010-01-08 10:36:07 +0530633err_queues:
Sujith285f2dd2010-01-08 10:36:07 +0530634 ath9k_hw_deinit(ah);
635err_hw:
Sujith55624202010-01-08 10:36:02 +0530636
Sujith285f2dd2010-01-08 10:36:07 +0530637 kfree(ah);
638 sc->sc_ah = NULL;
639
640 return ret;
Sujith55624202010-01-08 10:36:02 +0530641}
642
Felix Fietkaubabcbc22010-10-20 02:09:46 +0200643static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
644{
645 struct ieee80211_supported_band *sband;
646 struct ieee80211_channel *chan;
647 struct ath_hw *ah = sc->sc_ah;
648 struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
649 int i;
650
651 sband = &sc->sbands[band];
652 for (i = 0; i < sband->n_channels; i++) {
653 chan = &sband->channels[i];
654 ah->curchan = &ah->channels[chan->hw_value];
655 ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
656 ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
657 chan->max_power = reg->max_power_level / 2;
658 }
659}
660
661static void ath9k_init_txpower_limits(struct ath_softc *sc)
662{
663 struct ath_hw *ah = sc->sc_ah;
664 struct ath9k_channel *curchan = ah->curchan;
665
666 if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
667 ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
668 if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
669 ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
670
671 ah->curchan = curchan;
672}
673
Sujith285f2dd2010-01-08 10:36:07 +0530674void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
Sujith55624202010-01-08 10:36:02 +0530675{
Sujith285f2dd2010-01-08 10:36:07 +0530676 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
677
Sujith55624202010-01-08 10:36:02 +0530678 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
679 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
680 IEEE80211_HW_SIGNAL_DBM |
Sujith55624202010-01-08 10:36:02 +0530681 IEEE80211_HW_SUPPORTS_PS |
682 IEEE80211_HW_PS_NULLFUNC_STACK |
Vivek Natarajan05df4982010-02-09 11:34:50 +0530683 IEEE80211_HW_SPECTRUM_MGMT |
Mohammed Shafi Shajakhanbd8027a2010-12-30 12:18:01 +0530684 IEEE80211_HW_REPORTS_TX_ACK_STATUS;
Sujith55624202010-01-08 10:36:02 +0530685
Luis R. Rodriguez5ffaf8a2010-02-02 11:58:33 -0500686 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
687 hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
688
John W. Linville3e6109c2011-01-05 09:39:17 -0500689 if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt)
Sujith55624202010-01-08 10:36:02 +0530690 hw->flags |= IEEE80211_HW_MFP_CAPABLE;
691
692 hw->wiphy->interface_modes =
Johannes Bergc426ee22010-11-26 11:38:04 +0100693 BIT(NL80211_IFTYPE_P2P_GO) |
694 BIT(NL80211_IFTYPE_P2P_CLIENT) |
Sujith55624202010-01-08 10:36:02 +0530695 BIT(NL80211_IFTYPE_AP) |
Bill Jordane51f3ef2010-10-01 11:20:39 -0400696 BIT(NL80211_IFTYPE_WDS) |
Sujith55624202010-01-08 10:36:02 +0530697 BIT(NL80211_IFTYPE_STATION) |
698 BIT(NL80211_IFTYPE_ADHOC) |
699 BIT(NL80211_IFTYPE_MESH_POINT);
700
Luis R. Rodriguez008443d2010-09-16 15:12:36 -0400701 if (AR_SREV_5416(sc->sc_ah))
702 hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
Sujith55624202010-01-08 10:36:02 +0530703
Jouni Malinencfdc9a82011-03-23 14:52:19 +0200704 hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
705
Sujith55624202010-01-08 10:36:02 +0530706 hw->queues = 4;
707 hw->max_rates = 4;
708 hw->channel_change_time = 5000;
709 hw->max_listen_interval = 10;
Felix Fietkau65896512010-01-24 03:26:11 +0100710 hw->max_rate_tries = 10;
Sujith55624202010-01-08 10:36:02 +0530711 hw->sta_data_size = sizeof(struct ath_node);
712 hw->vif_data_size = sizeof(struct ath_vif);
713
Felix Fietkau6e5c2b42010-09-20 13:45:40 +0200714#ifdef CONFIG_ATH9K_RATE_CONTROL
Sujith55624202010-01-08 10:36:02 +0530715 hw->rate_control_algorithm = "ath9k_rate_control";
Felix Fietkau6e5c2b42010-09-20 13:45:40 +0200716#endif
Sujith55624202010-01-08 10:36:02 +0530717
Felix Fietkaud4659912010-10-14 16:02:39 +0200718 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
Sujith55624202010-01-08 10:36:02 +0530719 hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
720 &sc->sbands[IEEE80211_BAND_2GHZ];
Felix Fietkaud4659912010-10-14 16:02:39 +0200721 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
Sujith55624202010-01-08 10:36:02 +0530722 hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
723 &sc->sbands[IEEE80211_BAND_5GHZ];
Sujith285f2dd2010-01-08 10:36:07 +0530724
725 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
Felix Fietkaud4659912010-10-14 16:02:39 +0200726 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
Sujith285f2dd2010-01-08 10:36:07 +0530727 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
Felix Fietkaud4659912010-10-14 16:02:39 +0200728 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
Sujith285f2dd2010-01-08 10:36:07 +0530729 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
730 }
731
732 SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
Sujith55624202010-01-08 10:36:02 +0530733}
734
Sujith285f2dd2010-01-08 10:36:07 +0530735int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
Sujith55624202010-01-08 10:36:02 +0530736 const struct ath_bus_ops *bus_ops)
737{
738 struct ieee80211_hw *hw = sc->hw;
739 struct ath_common *common;
740 struct ath_hw *ah;
Sujith285f2dd2010-01-08 10:36:07 +0530741 int error = 0;
Sujith55624202010-01-08 10:36:02 +0530742 struct ath_regulatory *reg;
743
Sujith285f2dd2010-01-08 10:36:07 +0530744 /* Bring up device */
745 error = ath9k_init_softc(devid, sc, subsysid, bus_ops);
Sujith55624202010-01-08 10:36:02 +0530746 if (error != 0)
Sujith285f2dd2010-01-08 10:36:07 +0530747 goto error_init;
Sujith55624202010-01-08 10:36:02 +0530748
749 ah = sc->sc_ah;
750 common = ath9k_hw_common(ah);
Sujith285f2dd2010-01-08 10:36:07 +0530751 ath9k_set_hw_capab(sc, hw);
Sujith55624202010-01-08 10:36:02 +0530752
Sujith285f2dd2010-01-08 10:36:07 +0530753 /* Initialize regulatory */
Sujith55624202010-01-08 10:36:02 +0530754 error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
755 ath9k_reg_notifier);
756 if (error)
Sujith285f2dd2010-01-08 10:36:07 +0530757 goto error_regd;
Sujith55624202010-01-08 10:36:02 +0530758
759 reg = &common->regulatory;
760
Sujith285f2dd2010-01-08 10:36:07 +0530761 /* Setup TX DMA */
Sujith55624202010-01-08 10:36:02 +0530762 error = ath_tx_init(sc, ATH_TXBUF);
763 if (error != 0)
Sujith285f2dd2010-01-08 10:36:07 +0530764 goto error_tx;
Sujith55624202010-01-08 10:36:02 +0530765
Sujith285f2dd2010-01-08 10:36:07 +0530766 /* Setup RX DMA */
Sujith55624202010-01-08 10:36:02 +0530767 error = ath_rx_init(sc, ATH_RXBUF);
768 if (error != 0)
Sujith285f2dd2010-01-08 10:36:07 +0530769 goto error_rx;
770
Felix Fietkaubabcbc22010-10-20 02:09:46 +0200771 ath9k_init_txpower_limits(sc);
772
Felix Fietkau0cf55c22011-02-27 22:26:40 +0100773#ifdef CONFIG_MAC80211_LEDS
774 /* must be initialized before ieee80211_register_hw */
775 sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
776 IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink,
777 ARRAY_SIZE(ath9k_tpt_blink));
778#endif
779
Sujith285f2dd2010-01-08 10:36:07 +0530780 /* Register with mac80211 */
781 error = ieee80211_register_hw(hw);
782 if (error)
783 goto error_register;
784
Ben Greeareb272442010-11-29 14:13:22 -0800785 error = ath9k_init_debug(ah);
786 if (error) {
Joe Perches38002762010-12-02 19:12:36 -0800787 ath_err(common, "Unable to create debugfs files\n");
Ben Greeareb272442010-11-29 14:13:22 -0800788 goto error_world;
789 }
790
Sujith285f2dd2010-01-08 10:36:07 +0530791 /* Handle world regulatory */
792 if (!ath_is_world_regd(reg)) {
793 error = regulatory_hint(hw->wiphy, reg->alpha2);
794 if (error)
795 goto error_world;
796 }
Sujith55624202010-01-08 10:36:02 +0530797
Felix Fietkau347809f2010-07-02 00:09:52 +0200798 INIT_WORK(&sc->hw_check_work, ath_hw_check);
Felix Fietkau9f42c2b2010-06-12 00:34:01 -0400799 INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
Senthil Balasubramanian9eab61c2011-04-22 11:32:11 +0530800 INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
Felix Fietkau9ac586152011-01-24 19:23:18 +0100801 sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
Sujith55624202010-01-08 10:36:02 +0530802
Sujith55624202010-01-08 10:36:02 +0530803 ath_init_leds(sc);
Sujith55624202010-01-08 10:36:02 +0530804 ath_start_rfkill_poll(sc);
805
806 return 0;
807
Sujith285f2dd2010-01-08 10:36:07 +0530808error_world:
809 ieee80211_unregister_hw(hw);
810error_register:
811 ath_rx_cleanup(sc);
812error_rx:
813 ath_tx_cleanup(sc);
814error_tx:
815 /* Nothing */
816error_regd:
817 ath9k_deinit_softc(sc);
818error_init:
Sujith55624202010-01-08 10:36:02 +0530819 return error;
820}
821
822/*****************************/
823/* De-Initialization */
824/*****************************/
825
Sujith285f2dd2010-01-08 10:36:07 +0530826static void ath9k_deinit_softc(struct ath_softc *sc)
Sujith55624202010-01-08 10:36:02 +0530827{
Sujith285f2dd2010-01-08 10:36:07 +0530828 int i = 0;
Sujith55624202010-01-08 10:36:02 +0530829
Felix Fietkauf209f522010-10-01 01:06:53 +0200830 if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
831 kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
832
833 if (sc->sbands[IEEE80211_BAND_5GHZ].channels)
834 kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);
835
Sujith285f2dd2010-01-08 10:36:07 +0530836 if ((sc->btcoex.no_stomp_timer) &&
837 sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
838 ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
Sujith55624202010-01-08 10:36:02 +0530839
Sujith285f2dd2010-01-08 10:36:07 +0530840 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
841 if (ATH_TXQ_SETUP(sc, i))
842 ath_tx_cleanupq(sc, &sc->tx.txq[i]);
843
Sujith285f2dd2010-01-08 10:36:07 +0530844 ath9k_hw_deinit(sc->sc_ah);
845
Sujith736b3a22010-03-17 14:25:24 +0530846 kfree(sc->sc_ah);
847 sc->sc_ah = NULL;
Sujith55624202010-01-08 10:36:02 +0530848}
849
Sujith285f2dd2010-01-08 10:36:07 +0530850void ath9k_deinit_device(struct ath_softc *sc)
Sujith55624202010-01-08 10:36:02 +0530851{
852 struct ieee80211_hw *hw = sc->hw;
Sujith55624202010-01-08 10:36:02 +0530853
854 ath9k_ps_wakeup(sc);
855
Sujith55624202010-01-08 10:36:02 +0530856 wiphy_rfkill_stop_polling(sc->hw->wiphy);
Sujith285f2dd2010-01-08 10:36:07 +0530857 ath_deinit_leds(sc);
Sujith55624202010-01-08 10:36:02 +0530858
Rajkumar Manoharanc7c18062011-01-27 18:39:38 +0530859 ath9k_ps_restore(sc);
860
Sujith55624202010-01-08 10:36:02 +0530861 ieee80211_unregister_hw(hw);
862 ath_rx_cleanup(sc);
863 ath_tx_cleanup(sc);
Sujith285f2dd2010-01-08 10:36:07 +0530864 ath9k_deinit_softc(sc);
Sujith55624202010-01-08 10:36:02 +0530865}
866
867void ath_descdma_cleanup(struct ath_softc *sc,
868 struct ath_descdma *dd,
869 struct list_head *head)
870{
871 dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
872 dd->dd_desc_paddr);
873
874 INIT_LIST_HEAD(head);
875 kfree(dd->dd_bufptr);
876 memset(dd, 0, sizeof(*dd));
877}
878
Sujith55624202010-01-08 10:36:02 +0530879/************************/
880/* Module Hooks */
881/************************/
882
883static int __init ath9k_init(void)
884{
885 int error;
886
887 /* Register rate control algorithm */
888 error = ath_rate_control_register();
889 if (error != 0) {
890 printk(KERN_ERR
891 "ath9k: Unable to register rate control "
892 "algorithm: %d\n",
893 error);
894 goto err_out;
895 }
896
Sujith55624202010-01-08 10:36:02 +0530897 error = ath_pci_init();
898 if (error < 0) {
899 printk(KERN_ERR
900 "ath9k: No PCI devices found, driver not installed.\n");
901 error = -ENODEV;
Ben Greeareb272442010-11-29 14:13:22 -0800902 goto err_rate_unregister;
Sujith55624202010-01-08 10:36:02 +0530903 }
904
905 error = ath_ahb_init();
906 if (error < 0) {
907 error = -ENODEV;
908 goto err_pci_exit;
909 }
910
911 return 0;
912
913 err_pci_exit:
914 ath_pci_exit();
915
Sujith55624202010-01-08 10:36:02 +0530916 err_rate_unregister:
917 ath_rate_control_unregister();
918 err_out:
919 return error;
920}
921module_init(ath9k_init);
922
923static void __exit ath9k_exit(void)
924{
Rajkumar Manoharand5847472010-12-20 14:39:51 +0530925 is_ath9k_unloaded = true;
Sujith55624202010-01-08 10:36:02 +0530926 ath_ahb_exit();
927 ath_pci_exit();
Sujith55624202010-01-08 10:36:02 +0530928 ath_rate_control_unregister();
929 printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
930}
931module_exit(ath9k_exit);