blob: c5df98139c4df7592d00d41958825d33b64220a0 [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>
Paul Gortmaker9d9779e2011-07-03 15:21:01 -040020#include <linux/module.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090021
Sujith55624202010-01-08 10:36:02 +053022#include "ath9k.h"
23
24static char *dev_info = "ath9k";
25
26MODULE_AUTHOR("Atheros Communications");
27MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
28MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards");
29MODULE_LICENSE("Dual BSD/GPL");
30
31static unsigned int ath9k_debug = ATH_DBG_DEFAULT;
32module_param_named(debug, ath9k_debug, uint, 0);
33MODULE_PARM_DESC(debug, "Debugging mask");
34
John W. Linville3e6109c2011-01-05 09:39:17 -050035int ath9k_modparam_nohwcrypt;
36module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444);
Sujith55624202010-01-08 10:36:02 +053037MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
38
Vivek Natarajan93dbbcc2010-08-25 19:34:52 +053039int led_blink;
Vivek Natarajan9a75c2f2010-06-22 11:52:37 +053040module_param_named(blink, led_blink, int, 0444);
41MODULE_PARM_DESC(blink, "Enable LED blink on activity");
42
Vasanthakumar Thiagarajan8f5dcb12010-11-26 06:10:06 -080043static int ath9k_btcoex_enable;
44module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444);
45MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
46
Rajkumar Manoharand5847472010-12-20 14:39:51 +053047bool is_ath9k_unloaded;
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
Felix Fietkau0cf55c22011-02-27 22:26:40 +0100146#ifdef CONFIG_MAC80211_LEDS
147static const struct ieee80211_tpt_blink ath9k_tpt_blink[] = {
148 { .throughput = 0 * 1024, .blink_time = 334 },
149 { .throughput = 1 * 1024, .blink_time = 260 },
150 { .throughput = 5 * 1024, .blink_time = 220 },
151 { .throughput = 10 * 1024, .blink_time = 190 },
152 { .throughput = 20 * 1024, .blink_time = 170 },
153 { .throughput = 50 * 1024, .blink_time = 150 },
154 { .throughput = 70 * 1024, .blink_time = 130 },
155 { .throughput = 100 * 1024, .blink_time = 110 },
156 { .throughput = 200 * 1024, .blink_time = 80 },
157 { .throughput = 300 * 1024, .blink_time = 50 },
158};
159#endif
160
Sujith285f2dd2010-01-08 10:36:07 +0530161static void ath9k_deinit_softc(struct ath_softc *sc);
Sujith55624202010-01-08 10:36:02 +0530162
163/*
164 * Read and write, they both share the same lock. We do this to serialize
165 * reads and writes on Atheros 802.11n PCI devices only. This is required
166 * as the FIFO on these devices can only accept sanely 2 requests.
167 */
168
169static void ath9k_iowrite32(void *hw_priv, u32 val, 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
175 if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
176 unsigned long flags;
177 spin_lock_irqsave(&sc->sc_serial_rw, flags);
178 iowrite32(val, sc->mem + reg_offset);
179 spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
180 } else
181 iowrite32(val, sc->mem + reg_offset);
182}
183
184static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
185{
186 struct ath_hw *ah = (struct ath_hw *) hw_priv;
187 struct ath_common *common = ath9k_hw_common(ah);
188 struct ath_softc *sc = (struct ath_softc *) common->priv;
189 u32 val;
190
191 if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
192 unsigned long flags;
193 spin_lock_irqsave(&sc->sc_serial_rw, flags);
194 val = ioread32(sc->mem + reg_offset);
195 spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
196 } else
197 val = ioread32(sc->mem + reg_offset);
198 return val;
199}
200
Rajkumar Manoharan5479de62011-07-17 11:43:02 +0530201static unsigned int __ath9k_reg_rmw(struct ath_softc *sc, u32 reg_offset,
202 u32 set, u32 clr)
203{
204 u32 val;
205
206 val = ioread32(sc->mem + reg_offset);
207 val &= ~clr;
208 val |= set;
209 iowrite32(val, sc->mem + reg_offset);
210
211 return val;
212}
213
Felix Fietkau845e03c2011-03-23 20:57:25 +0100214static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
215{
216 struct ath_hw *ah = (struct ath_hw *) hw_priv;
217 struct ath_common *common = ath9k_hw_common(ah);
218 struct ath_softc *sc = (struct ath_softc *) common->priv;
219 unsigned long uninitialized_var(flags);
220 u32 val;
221
Rajkumar Manoharan5479de62011-07-17 11:43:02 +0530222 if (ah->config.serialize_regmode == SER_REG_MODE_ON) {
Felix Fietkau845e03c2011-03-23 20:57:25 +0100223 spin_lock_irqsave(&sc->sc_serial_rw, flags);
Rajkumar Manoharan5479de62011-07-17 11:43:02 +0530224 val = __ath9k_reg_rmw(sc, reg_offset, set, clr);
Felix Fietkau845e03c2011-03-23 20:57:25 +0100225 spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
Rajkumar Manoharan5479de62011-07-17 11:43:02 +0530226 } else
227 val = __ath9k_reg_rmw(sc, reg_offset, set, clr);
Felix Fietkau845e03c2011-03-23 20:57:25 +0100228
229 return val;
230}
231
Sujith55624202010-01-08 10:36:02 +0530232/**************************/
233/* Initialization */
234/**************************/
235
236static void setup_ht_cap(struct ath_softc *sc,
237 struct ieee80211_sta_ht_cap *ht_info)
238{
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200239 struct ath_hw *ah = sc->sc_ah;
240 struct ath_common *common = ath9k_hw_common(ah);
Sujith55624202010-01-08 10:36:02 +0530241 u8 tx_streams, rx_streams;
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200242 int i, max_streams;
Sujith55624202010-01-08 10:36:02 +0530243
244 ht_info->ht_supported = true;
245 ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
246 IEEE80211_HT_CAP_SM_PS |
247 IEEE80211_HT_CAP_SGI_40 |
248 IEEE80211_HT_CAP_DSSSCCK40;
249
Luis R. Rodriguezb0a33442010-04-15 17:39:39 -0400250 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC)
251 ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
252
Vasanthakumar Thiagarajan6473d242010-05-13 18:42:38 -0700253 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
254 ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
255
Sujith55624202010-01-08 10:36:02 +0530256 ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
257 ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
258
Gabor Juhos72161982011-06-21 11:23:42 +0200259 if (AR_SREV_9330(ah) || AR_SREV_9485(ah))
Vasanthakumar Thiagarajan7f1c7a62010-12-06 04:27:41 -0800260 max_streams = 1;
Mohammed Shafi Shajakhane7104192011-12-01 18:14:01 +0530261 else if (AR_SREV_9462(ah))
262 max_streams = 2;
Vasanthakumar Thiagarajan7f1c7a62010-12-06 04:27:41 -0800263 else if (AR_SREV_9300_20_OR_LATER(ah))
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200264 max_streams = 3;
265 else
266 max_streams = 2;
267
Felix Fietkau7a370812010-09-22 12:34:52 +0200268 if (AR_SREV_9280_20_OR_LATER(ah)) {
Felix Fietkau074a8c02010-04-19 19:57:36 +0200269 if (max_streams >= 2)
270 ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
271 ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
272 }
273
Sujith55624202010-01-08 10:36:02 +0530274 /* set up supported mcs set */
275 memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
Felix Fietkau82b2d332011-09-03 01:40:23 +0200276 tx_streams = ath9k_cmn_count_streams(ah->txchainmask, max_streams);
277 rx_streams = ath9k_cmn_count_streams(ah->rxchainmask, max_streams);
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200278
Joe Perches226afe62010-12-02 19:12:37 -0800279 ath_dbg(common, ATH_DBG_CONFIG,
280 "TX streams %d, RX streams: %d\n",
281 tx_streams, rx_streams);
Sujith55624202010-01-08 10:36:02 +0530282
283 if (tx_streams != rx_streams) {
Sujith55624202010-01-08 10:36:02 +0530284 ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
285 ht_info->mcs.tx_params |= ((tx_streams - 1) <<
286 IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
287 }
288
Felix Fietkau3bb065a2010-04-19 19:57:34 +0200289 for (i = 0; i < rx_streams; i++)
290 ht_info->mcs.rx_mask[i] = 0xff;
Sujith55624202010-01-08 10:36:02 +0530291
292 ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
293}
294
295static int ath9k_reg_notifier(struct wiphy *wiphy,
296 struct regulatory_request *request)
297{
298 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
Felix Fietkau9ac58612011-01-24 19:23:18 +0100299 struct ath_softc *sc = hw->priv;
Rajkumar Manoharan687f5452011-12-08 23:59:25 +0530300 struct ath_hw *ah = sc->sc_ah;
301 struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
302 int ret;
Sujith55624202010-01-08 10:36:02 +0530303
Rajkumar Manoharan687f5452011-12-08 23:59:25 +0530304 ret = ath_reg_notifier_apply(wiphy, request, reg);
305
306 /* Set tx power */
307 if (ah->curchan) {
308 sc->config.txpowlimit = 2 * ah->curchan->chan->max_power;
309 ath9k_ps_wakeup(sc);
310 ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
311 sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
312 ath9k_ps_restore(sc);
313 }
314
315 return ret;
Sujith55624202010-01-08 10:36:02 +0530316}
317
318/*
319 * This function will allocate both the DMA descriptor structure, and the
320 * buffers it contains. These are used to contain the descriptors used
321 * by the system.
322*/
323int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
324 struct list_head *head, const char *name,
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400325 int nbuf, int ndesc, bool is_tx)
Sujith55624202010-01-08 10:36:02 +0530326{
Sujith55624202010-01-08 10:36:02 +0530327 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400328 u8 *ds;
Sujith55624202010-01-08 10:36:02 +0530329 struct ath_buf *bf;
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400330 int i, bsize, error, desc_len;
Sujith55624202010-01-08 10:36:02 +0530331
Joe Perches226afe62010-12-02 19:12:37 -0800332 ath_dbg(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",
333 name, nbuf, ndesc);
Sujith55624202010-01-08 10:36:02 +0530334
335 INIT_LIST_HEAD(head);
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400336
337 if (is_tx)
338 desc_len = sc->sc_ah->caps.tx_desc_len;
339 else
340 desc_len = sizeof(struct ath_desc);
341
Sujith55624202010-01-08 10:36:02 +0530342 /* ath_desc must be a multiple of DWORDs */
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400343 if ((desc_len % 4) != 0) {
Joe Perches38002762010-12-02 19:12:36 -0800344 ath_err(common, "ath_desc not DWORD aligned\n");
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400345 BUG_ON((desc_len % 4) != 0);
Sujith55624202010-01-08 10:36:02 +0530346 error = -ENOMEM;
347 goto fail;
348 }
349
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400350 dd->dd_desc_len = desc_len * nbuf * ndesc;
Sujith55624202010-01-08 10:36:02 +0530351
352 /*
353 * Need additional DMA memory because we can't use
354 * descriptors that cross the 4K page boundary. Assume
355 * one skipped descriptor per 4K page.
356 */
357 if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
358 u32 ndesc_skipped =
359 ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len);
360 u32 dma_len;
361
362 while (ndesc_skipped) {
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400363 dma_len = ndesc_skipped * desc_len;
Sujith55624202010-01-08 10:36:02 +0530364 dd->dd_desc_len += dma_len;
365
366 ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len);
Joe Perchesee289b62010-05-17 22:47:34 -0700367 }
Sujith55624202010-01-08 10:36:02 +0530368 }
369
370 /* allocate descriptors */
371 dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
372 &dd->dd_desc_paddr, GFP_KERNEL);
373 if (dd->dd_desc == NULL) {
374 error = -ENOMEM;
375 goto fail;
376 }
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400377 ds = (u8 *) dd->dd_desc;
Joe Perches226afe62010-12-02 19:12:37 -0800378 ath_dbg(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
379 name, ds, (u32) dd->dd_desc_len,
380 ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
Sujith55624202010-01-08 10:36:02 +0530381
382 /* allocate buffers */
383 bsize = sizeof(struct ath_buf) * nbuf;
384 bf = kzalloc(bsize, GFP_KERNEL);
385 if (bf == NULL) {
386 error = -ENOMEM;
387 goto fail2;
388 }
389 dd->dd_bufptr = bf;
390
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400391 for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {
Sujith55624202010-01-08 10:36:02 +0530392 bf->bf_desc = ds;
393 bf->bf_daddr = DS2PHYS(dd, ds);
394
395 if (!(sc->sc_ah->caps.hw_caps &
396 ATH9K_HW_CAP_4KB_SPLITTRANS)) {
397 /*
398 * Skip descriptor addresses which can cause 4KB
399 * boundary crossing (addr + length) with a 32 dword
400 * descriptor fetch.
401 */
402 while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
403 BUG_ON((caddr_t) bf->bf_desc >=
404 ((caddr_t) dd->dd_desc +
405 dd->dd_desc_len));
406
Vasanthakumar Thiagarajan4adfcde2010-04-15 17:39:33 -0400407 ds += (desc_len * ndesc);
Sujith55624202010-01-08 10:36:02 +0530408 bf->bf_desc = ds;
409 bf->bf_daddr = DS2PHYS(dd, ds);
410 }
411 }
412 list_add_tail(&bf->list, head);
413 }
414 return 0;
415fail2:
416 dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
417 dd->dd_desc_paddr);
418fail:
419 memset(dd, 0, sizeof(*dd));
420 return error;
Sujith55624202010-01-08 10:36:02 +0530421}
422
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;
Mohammed Shafi Shajakhan16659f62011-11-30 10:41:16 +0530426 struct ath_hw *ah = sc->sc_ah;
Felix Fietkau066dae92010-11-07 14:59:39 +0100427 int r;
Sujith285f2dd2010-01-08 10:36:07 +0530428
429 switch (sc->sc_ah->btcoex_hw.scheme) {
430 case ATH_BTCOEX_CFG_NONE:
431 break;
432 case ATH_BTCOEX_CFG_2WIRE:
433 ath9k_hw_btcoex_init_2wire(sc->sc_ah);
434 break;
435 case ATH_BTCOEX_CFG_3WIRE:
436 ath9k_hw_btcoex_init_3wire(sc->sc_ah);
437 r = ath_init_btcoex_timer(sc);
438 if (r)
439 return -1;
Felix Fietkau066dae92010-11-07 14:59:39 +0100440 txq = sc->tx.txq_map[WME_AC_BE];
441 ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
Sujith285f2dd2010-01-08 10:36:07 +0530442 sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
Mohammed Shafi Shajakhan19686dd2011-11-30 10:41:28 +0530443 break;
444 case ATH_BTCOEX_CFG_MCI:
445 sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
Rajkumar Manoharan7dc181c2011-10-24 18:19:49 +0530446 sc->btcoex.duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE;
447 INIT_LIST_HEAD(&sc->btcoex.mci.info);
Mohammed Shafi Shajakhan19686dd2011-11-30 10:41:28 +0530448
449 r = ath_mci_setup(sc);
450 if (r)
451 return r;
452
Mohammed Shafi Shajakhan16659f62011-11-30 10:41:16 +0530453 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) {
454 ah->btcoex_hw.mci.ready = false;
455 ah->btcoex_hw.mci.bt_state = 0;
456 ah->btcoex_hw.mci.bt_ver_major = 3;
457 ah->btcoex_hw.mci.bt_ver_minor = 0;
458 ah->btcoex_hw.mci.bt_version_known = false;
459 ah->btcoex_hw.mci.update_2g5g = true;
460 ah->btcoex_hw.mci.is_2g = true;
461 ah->btcoex_hw.mci.wlan_channels_update = false;
462 ah->btcoex_hw.mci.wlan_channels[0] = 0x00000000;
463 ah->btcoex_hw.mci.wlan_channels[1] = 0xffffffff;
464 ah->btcoex_hw.mci.wlan_channels[2] = 0xffffffff;
465 ah->btcoex_hw.mci.wlan_channels[3] = 0x7fffffff;
466 ah->btcoex_hw.mci.query_bt = true;
467 ah->btcoex_hw.mci.unhalt_bt_gpm = true;
468 ah->btcoex_hw.mci.halted_bt_gpm = false;
469 ah->btcoex_hw.mci.need_flush_btinfo = false;
470 ah->btcoex_hw.mci.wlan_cal_seq = 0;
471 ah->btcoex_hw.mci.wlan_cal_done = 0;
472 ah->btcoex_hw.mci.config = 0x2201;
473 }
Sujith285f2dd2010-01-08 10:36:07 +0530474 break;
475 default:
476 WARN_ON(1);
477 break;
Sujith55624202010-01-08 10:36:02 +0530478 }
479
Sujith285f2dd2010-01-08 10:36:07 +0530480 return 0;
481}
Sujith55624202010-01-08 10:36:02 +0530482
Sujith285f2dd2010-01-08 10:36:07 +0530483static int ath9k_init_queues(struct ath_softc *sc)
484{
Sujith285f2dd2010-01-08 10:36:07 +0530485 int i = 0;
Sujith55624202010-01-08 10:36:02 +0530486
Sujith285f2dd2010-01-08 10:36:07 +0530487 sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
Sujith285f2dd2010-01-08 10:36:07 +0530488 sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
Sujith55624202010-01-08 10:36:02 +0530489
Sujith285f2dd2010-01-08 10:36:07 +0530490 sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
491 ath_cabq_update(sc);
492
Ben Greear60f2d1d2011-01-09 23:11:52 -0800493 for (i = 0; i < WME_NUM_AC; i++) {
Felix Fietkau066dae92010-11-07 14:59:39 +0100494 sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
Ben Greear60f2d1d2011-01-09 23:11:52 -0800495 sc->tx.txq_map[i]->mac80211_qnum = i;
496 }
Sujith285f2dd2010-01-08 10:36:07 +0530497 return 0;
Sujith285f2dd2010-01-08 10:36:07 +0530498}
499
Felix Fietkauf209f522010-10-01 01:06:53 +0200500static int ath9k_init_channels_rates(struct ath_softc *sc)
Sujith285f2dd2010-01-08 10:36:07 +0530501{
Felix Fietkauf209f522010-10-01 01:06:53 +0200502 void *channels;
503
Felix Fietkaucac42202010-10-09 02:39:30 +0200504 BUILD_BUG_ON(ARRAY_SIZE(ath9k_2ghz_chantable) +
505 ARRAY_SIZE(ath9k_5ghz_chantable) !=
506 ATH9K_NUM_CHANNELS);
507
Felix Fietkaud4659912010-10-14 16:02:39 +0200508 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
Felix Fietkauf209f522010-10-01 01:06:53 +0200509 channels = kmemdup(ath9k_2ghz_chantable,
510 sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
511 if (!channels)
512 return -ENOMEM;
513
514 sc->sbands[IEEE80211_BAND_2GHZ].channels = channels;
Sujith55624202010-01-08 10:36:02 +0530515 sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
516 sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
517 ARRAY_SIZE(ath9k_2ghz_chantable);
518 sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
519 sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
520 ARRAY_SIZE(ath9k_legacy_rates);
521 }
522
Felix Fietkaud4659912010-10-14 16:02:39 +0200523 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
Felix Fietkauf209f522010-10-01 01:06:53 +0200524 channels = kmemdup(ath9k_5ghz_chantable,
525 sizeof(ath9k_5ghz_chantable), GFP_KERNEL);
526 if (!channels) {
527 if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
528 kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
529 return -ENOMEM;
530 }
531
532 sc->sbands[IEEE80211_BAND_5GHZ].channels = channels;
Sujith55624202010-01-08 10:36:02 +0530533 sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
534 sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
535 ARRAY_SIZE(ath9k_5ghz_chantable);
536 sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
537 ath9k_legacy_rates + 4;
538 sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
539 ARRAY_SIZE(ath9k_legacy_rates) - 4;
540 }
Felix Fietkauf209f522010-10-01 01:06:53 +0200541 return 0;
Sujith285f2dd2010-01-08 10:36:07 +0530542}
Sujith55624202010-01-08 10:36:02 +0530543
Sujith285f2dd2010-01-08 10:36:07 +0530544static void ath9k_init_misc(struct ath_softc *sc)
545{
546 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
547 int i = 0;
Sujith285f2dd2010-01-08 10:36:07 +0530548 setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
549
550 sc->config.txpowlimit = ATH_TXPOWER_MAX;
551
552 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
553 sc->sc_flags |= SC_OP_TXAGGR;
554 sc->sc_flags |= SC_OP_RXAGGR;
Sujith55624202010-01-08 10:36:02 +0530555 }
556
Sujith285f2dd2010-01-08 10:36:07 +0530557 sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
558
Felix Fietkau364734f2010-09-14 20:22:44 +0200559 memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
Sujith285f2dd2010-01-08 10:36:07 +0530560
561 sc->beacon.slottime = ATH9K_SLOT_TIME_9;
562
Felix Fietkau7545daf2011-01-24 19:23:16 +0100563 for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++)
Sujith285f2dd2010-01-08 10:36:07 +0530564 sc->beacon.bslot[i] = NULL;
Vasanthakumar Thiagarajan102885a2010-09-02 01:34:43 -0700565
566 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
567 sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
Sujith285f2dd2010-01-08 10:36:07 +0530568}
569
Pavel Roskineb93e892011-07-23 03:55:39 -0400570static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
Sujith285f2dd2010-01-08 10:36:07 +0530571 const struct ath_bus_ops *bus_ops)
572{
Felix Fietkau6fb1b1e2011-03-19 13:55:39 +0100573 struct ath9k_platform_data *pdata = sc->dev->platform_data;
Sujith285f2dd2010-01-08 10:36:07 +0530574 struct ath_hw *ah = NULL;
575 struct ath_common *common;
576 int ret = 0, i;
577 int csz = 0;
578
Sujith285f2dd2010-01-08 10:36:07 +0530579 ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
580 if (!ah)
581 return -ENOMEM;
582
Ben Greear233536e2011-01-09 23:11:44 -0800583 ah->hw = sc->hw;
Sujith285f2dd2010-01-08 10:36:07 +0530584 ah->hw_version.devid = devid;
Felix Fietkauf9f84e92011-03-23 20:57:24 +0100585 ah->reg_ops.read = ath9k_ioread32;
586 ah->reg_ops.write = ath9k_iowrite32;
Felix Fietkau845e03c2011-03-23 20:57:25 +0100587 ah->reg_ops.rmw = ath9k_reg_rmw;
Rajkumar Manoharane8fe7332011-08-05 18:59:41 +0530588 atomic_set(&ah->intr_ref_cnt, -1);
Sujith285f2dd2010-01-08 10:36:07 +0530589 sc->sc_ah = ah;
590
Felix Fietkau6de66dd2011-03-19 13:55:40 +0100591 if (!pdata) {
Felix Fietkaua05b5d42010-11-17 04:25:33 +0100592 ah->ah_flags |= AH_USE_EEPROM;
Felix Fietkau6de66dd2011-03-19 13:55:40 +0100593 sc->sc_ah->led_pin = -1;
594 } else {
595 sc->sc_ah->gpio_mask = pdata->gpio_mask;
596 sc->sc_ah->gpio_val = pdata->gpio_val;
597 sc->sc_ah->led_pin = pdata->led_pin;
Vasanthakumar Thiagarajanf2f5f2a2011-04-19 19:29:01 +0530598 ah->is_clk_25mhz = pdata->is_clk_25mhz;
Gabor Juhos37625612011-06-21 11:23:23 +0200599 ah->get_mac_revision = pdata->get_mac_revision;
Gabor Juhos7d95847c2011-06-21 11:23:51 +0200600 ah->external_reset = pdata->external_reset;
Felix Fietkau6de66dd2011-03-19 13:55:40 +0100601 }
Felix Fietkaua05b5d42010-11-17 04:25:33 +0100602
Sujith285f2dd2010-01-08 10:36:07 +0530603 common = ath9k_hw_common(ah);
Felix Fietkauf9f84e92011-03-23 20:57:24 +0100604 common->ops = &ah->reg_ops;
Sujith285f2dd2010-01-08 10:36:07 +0530605 common->bus_ops = bus_ops;
606 common->ah = ah;
607 common->hw = sc->hw;
608 common->priv = sc;
609 common->debug_mask = ath9k_debug;
Vasanthakumar Thiagarajan8f5dcb12010-11-26 06:10:06 -0800610 common->btcoex_enabled = ath9k_btcoex_enable == 1;
Mohammed Shafi Shajakhan05c0be22011-05-26 10:56:15 +0530611 common->disable_ani = false;
Ben Greear20b25742010-10-15 15:04:09 -0700612 spin_lock_init(&common->cc_lock);
Sujith285f2dd2010-01-08 10:36:07 +0530613
Sujith285f2dd2010-01-08 10:36:07 +0530614 spin_lock_init(&sc->sc_serial_rw);
615 spin_lock_init(&sc->sc_pm_lock);
616 mutex_init(&sc->mutex);
Ben Greear7f010c92011-01-09 23:11:49 -0800617#ifdef CONFIG_ATH9K_DEBUGFS
618 spin_lock_init(&sc->nodes_lock);
Rajkumar Manoharancf3af742011-08-27 16:17:47 +0530619 spin_lock_init(&sc->debug.samp_lock);
Ben Greear7f010c92011-01-09 23:11:49 -0800620 INIT_LIST_HEAD(&sc->nodes);
621#endif
Sujith285f2dd2010-01-08 10:36:07 +0530622 tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
623 tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
624 (unsigned long)sc);
625
626 /*
627 * Cache line size is used to size and align various
628 * structures used to communicate with the hardware.
629 */
630 ath_read_cachesize(common, &csz);
631 common->cachelsz = csz << 2; /* convert to bytes */
632
Luis R. Rodriguezd70357d2010-04-15 17:38:06 -0400633 /* Initializes the hardware for all supported chipsets */
Sujith285f2dd2010-01-08 10:36:07 +0530634 ret = ath9k_hw_init(ah);
Luis R. Rodriguezd70357d2010-04-15 17:38:06 -0400635 if (ret)
Sujith285f2dd2010-01-08 10:36:07 +0530636 goto err_hw;
Sujith285f2dd2010-01-08 10:36:07 +0530637
Felix Fietkau6fb1b1e2011-03-19 13:55:39 +0100638 if (pdata && pdata->macaddr)
639 memcpy(common->macaddr, pdata->macaddr, ETH_ALEN);
640
Sujith285f2dd2010-01-08 10:36:07 +0530641 ret = ath9k_init_queues(sc);
642 if (ret)
643 goto err_queues;
644
645 ret = ath9k_init_btcoex(sc);
646 if (ret)
647 goto err_btcoex;
648
Felix Fietkauf209f522010-10-01 01:06:53 +0200649 ret = ath9k_init_channels_rates(sc);
650 if (ret)
651 goto err_btcoex;
652
Rajkumar Manoharanf82b4bd2011-08-13 10:28:15 +0530653 ath9k_cmn_init_crypto(sc->sc_ah);
Sujith285f2dd2010-01-08 10:36:07 +0530654 ath9k_init_misc(sc);
655
Sujith55624202010-01-08 10:36:02 +0530656 return 0;
Sujith285f2dd2010-01-08 10:36:07 +0530657
658err_btcoex:
Sujith55624202010-01-08 10:36:02 +0530659 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
660 if (ATH_TXQ_SETUP(sc, i))
661 ath_tx_cleanupq(sc, &sc->tx.txq[i]);
Sujith285f2dd2010-01-08 10:36:07 +0530662err_queues:
Sujith285f2dd2010-01-08 10:36:07 +0530663 ath9k_hw_deinit(ah);
664err_hw:
Sujith55624202010-01-08 10:36:02 +0530665
Sujith285f2dd2010-01-08 10:36:07 +0530666 kfree(ah);
667 sc->sc_ah = NULL;
668
669 return ret;
Sujith55624202010-01-08 10:36:02 +0530670}
671
Felix Fietkaubabcbc22010-10-20 02:09:46 +0200672static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
673{
674 struct ieee80211_supported_band *sband;
675 struct ieee80211_channel *chan;
676 struct ath_hw *ah = sc->sc_ah;
Felix Fietkaubabcbc22010-10-20 02:09:46 +0200677 int i;
678
679 sband = &sc->sbands[band];
680 for (i = 0; i < sband->n_channels; i++) {
681 chan = &sband->channels[i];
682 ah->curchan = &ah->channels[chan->hw_value];
683 ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
684 ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
Felix Fietkaubabcbc22010-10-20 02:09:46 +0200685 }
686}
687
688static void ath9k_init_txpower_limits(struct ath_softc *sc)
689{
690 struct ath_hw *ah = sc->sc_ah;
691 struct ath9k_channel *curchan = ah->curchan;
692
693 if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
694 ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
695 if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
696 ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
697
698 ah->curchan = curchan;
699}
700
Felix Fietkau43c35282011-09-03 01:40:27 +0200701void ath9k_reload_chainmask_settings(struct ath_softc *sc)
702{
703 if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT))
704 return;
705
706 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
707 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
708 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
709 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
710}
711
712
Sujith285f2dd2010-01-08 10:36:07 +0530713void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
Sujith55624202010-01-08 10:36:02 +0530714{
Felix Fietkau43c35282011-09-03 01:40:27 +0200715 struct ath_hw *ah = sc->sc_ah;
716 struct ath_common *common = ath9k_hw_common(ah);
Sujith285f2dd2010-01-08 10:36:07 +0530717
Sujith55624202010-01-08 10:36:02 +0530718 hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
719 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
720 IEEE80211_HW_SIGNAL_DBM |
Sujith55624202010-01-08 10:36:02 +0530721 IEEE80211_HW_SUPPORTS_PS |
722 IEEE80211_HW_PS_NULLFUNC_STACK |
Vivek Natarajan05df4982010-02-09 11:34:50 +0530723 IEEE80211_HW_SPECTRUM_MGMT |
Mohammed Shafi Shajakhanbd8027a2010-12-30 12:18:01 +0530724 IEEE80211_HW_REPORTS_TX_ACK_STATUS;
Sujith55624202010-01-08 10:36:02 +0530725
Luis R. Rodriguez5ffaf8a2010-02-02 11:58:33 -0500726 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
727 hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
728
John W. Linville3e6109c2011-01-05 09:39:17 -0500729 if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt)
Sujith55624202010-01-08 10:36:02 +0530730 hw->flags |= IEEE80211_HW_MFP_CAPABLE;
731
732 hw->wiphy->interface_modes =
Johannes Bergc426ee22010-11-26 11:38:04 +0100733 BIT(NL80211_IFTYPE_P2P_GO) |
734 BIT(NL80211_IFTYPE_P2P_CLIENT) |
Sujith55624202010-01-08 10:36:02 +0530735 BIT(NL80211_IFTYPE_AP) |
Bill Jordane51f3ef2010-10-01 11:20:39 -0400736 BIT(NL80211_IFTYPE_WDS) |
Sujith55624202010-01-08 10:36:02 +0530737 BIT(NL80211_IFTYPE_STATION) |
738 BIT(NL80211_IFTYPE_ADHOC) |
739 BIT(NL80211_IFTYPE_MESH_POINT);
740
Luis R. Rodriguez008443d2010-09-16 15:12:36 -0400741 if (AR_SREV_5416(sc->sc_ah))
742 hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
Sujith55624202010-01-08 10:36:02 +0530743
Jouni Malinencfdc9a82011-03-23 14:52:19 +0200744 hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
Jouni Malinenfd656232011-10-27 17:31:50 +0300745 hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
Jouni Malinencfdc9a82011-03-23 14:52:19 +0200746
Sujith55624202010-01-08 10:36:02 +0530747 hw->queues = 4;
748 hw->max_rates = 4;
749 hw->channel_change_time = 5000;
750 hw->max_listen_interval = 10;
Felix Fietkau65896512010-01-24 03:26:11 +0100751 hw->max_rate_tries = 10;
Sujith55624202010-01-08 10:36:02 +0530752 hw->sta_data_size = sizeof(struct ath_node);
753 hw->vif_data_size = sizeof(struct ath_vif);
754
Felix Fietkau43c35282011-09-03 01:40:27 +0200755 hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
756 hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
757
758 /* single chain devices with rx diversity */
759 if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
760 hw->wiphy->available_antennas_rx = BIT(0) | BIT(1);
761
762 sc->ant_rx = hw->wiphy->available_antennas_rx;
763 sc->ant_tx = hw->wiphy->available_antennas_tx;
764
Felix Fietkau6e5c2b42010-09-20 13:45:40 +0200765#ifdef CONFIG_ATH9K_RATE_CONTROL
Sujith55624202010-01-08 10:36:02 +0530766 hw->rate_control_algorithm = "ath9k_rate_control";
Felix Fietkau6e5c2b42010-09-20 13:45:40 +0200767#endif
Sujith55624202010-01-08 10:36:02 +0530768
Felix Fietkaud4659912010-10-14 16:02:39 +0200769 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
Sujith55624202010-01-08 10:36:02 +0530770 hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
771 &sc->sbands[IEEE80211_BAND_2GHZ];
Felix Fietkaud4659912010-10-14 16:02:39 +0200772 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
Sujith55624202010-01-08 10:36:02 +0530773 hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
774 &sc->sbands[IEEE80211_BAND_5GHZ];
Sujith285f2dd2010-01-08 10:36:07 +0530775
Felix Fietkau43c35282011-09-03 01:40:27 +0200776 ath9k_reload_chainmask_settings(sc);
Sujith285f2dd2010-01-08 10:36:07 +0530777
778 SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
Sujith55624202010-01-08 10:36:02 +0530779}
780
Pavel Roskineb93e892011-07-23 03:55:39 -0400781int ath9k_init_device(u16 devid, struct ath_softc *sc,
Sujith55624202010-01-08 10:36:02 +0530782 const struct ath_bus_ops *bus_ops)
783{
784 struct ieee80211_hw *hw = sc->hw;
785 struct ath_common *common;
786 struct ath_hw *ah;
Sujith285f2dd2010-01-08 10:36:07 +0530787 int error = 0;
Sujith55624202010-01-08 10:36:02 +0530788 struct ath_regulatory *reg;
789
Sujith285f2dd2010-01-08 10:36:07 +0530790 /* Bring up device */
Pavel Roskineb93e892011-07-23 03:55:39 -0400791 error = ath9k_init_softc(devid, sc, bus_ops);
Sujith55624202010-01-08 10:36:02 +0530792 if (error != 0)
Sujith285f2dd2010-01-08 10:36:07 +0530793 goto error_init;
Sujith55624202010-01-08 10:36:02 +0530794
795 ah = sc->sc_ah;
796 common = ath9k_hw_common(ah);
Sujith285f2dd2010-01-08 10:36:07 +0530797 ath9k_set_hw_capab(sc, hw);
Sujith55624202010-01-08 10:36:02 +0530798
Sujith285f2dd2010-01-08 10:36:07 +0530799 /* Initialize regulatory */
Sujith55624202010-01-08 10:36:02 +0530800 error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
801 ath9k_reg_notifier);
802 if (error)
Sujith285f2dd2010-01-08 10:36:07 +0530803 goto error_regd;
Sujith55624202010-01-08 10:36:02 +0530804
805 reg = &common->regulatory;
806
Sujith285f2dd2010-01-08 10:36:07 +0530807 /* Setup TX DMA */
Sujith55624202010-01-08 10:36:02 +0530808 error = ath_tx_init(sc, ATH_TXBUF);
809 if (error != 0)
Sujith285f2dd2010-01-08 10:36:07 +0530810 goto error_tx;
Sujith55624202010-01-08 10:36:02 +0530811
Sujith285f2dd2010-01-08 10:36:07 +0530812 /* Setup RX DMA */
Sujith55624202010-01-08 10:36:02 +0530813 error = ath_rx_init(sc, ATH_RXBUF);
814 if (error != 0)
Sujith285f2dd2010-01-08 10:36:07 +0530815 goto error_rx;
816
Felix Fietkaubabcbc22010-10-20 02:09:46 +0200817 ath9k_init_txpower_limits(sc);
818
Felix Fietkau0cf55c22011-02-27 22:26:40 +0100819#ifdef CONFIG_MAC80211_LEDS
820 /* must be initialized before ieee80211_register_hw */
821 sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
822 IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink,
823 ARRAY_SIZE(ath9k_tpt_blink));
824#endif
825
Sujith285f2dd2010-01-08 10:36:07 +0530826 /* Register with mac80211 */
827 error = ieee80211_register_hw(hw);
828 if (error)
829 goto error_register;
830
Ben Greeareb272442010-11-29 14:13:22 -0800831 error = ath9k_init_debug(ah);
832 if (error) {
Joe Perches38002762010-12-02 19:12:36 -0800833 ath_err(common, "Unable to create debugfs files\n");
Ben Greeareb272442010-11-29 14:13:22 -0800834 goto error_world;
835 }
836
Sujith285f2dd2010-01-08 10:36:07 +0530837 /* Handle world regulatory */
838 if (!ath_is_world_regd(reg)) {
839 error = regulatory_hint(hw->wiphy, reg->alpha2);
840 if (error)
841 goto error_world;
842 }
Sujith55624202010-01-08 10:36:02 +0530843
Felix Fietkau236de512011-09-03 01:40:25 +0200844 INIT_WORK(&sc->hw_reset_work, ath_reset_work);
Felix Fietkau347809f2010-07-02 00:09:52 +0200845 INIT_WORK(&sc->hw_check_work, ath_hw_check);
Felix Fietkau9f42c2b2010-06-12 00:34:01 -0400846 INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
Senthil Balasubramanian9eab61c2011-04-22 11:32:11 +0530847 INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
Felix Fietkau9ac58612011-01-24 19:23:18 +0100848 sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
Sujith55624202010-01-08 10:36:02 +0530849
Sujith55624202010-01-08 10:36:02 +0530850 ath_init_leds(sc);
Sujith55624202010-01-08 10:36:02 +0530851 ath_start_rfkill_poll(sc);
852
853 return 0;
854
Sujith285f2dd2010-01-08 10:36:07 +0530855error_world:
856 ieee80211_unregister_hw(hw);
857error_register:
858 ath_rx_cleanup(sc);
859error_rx:
860 ath_tx_cleanup(sc);
861error_tx:
862 /* Nothing */
863error_regd:
864 ath9k_deinit_softc(sc);
865error_init:
Sujith55624202010-01-08 10:36:02 +0530866 return error;
867}
868
869/*****************************/
870/* De-Initialization */
871/*****************************/
872
Sujith285f2dd2010-01-08 10:36:07 +0530873static void ath9k_deinit_softc(struct ath_softc *sc)
Sujith55624202010-01-08 10:36:02 +0530874{
Sujith285f2dd2010-01-08 10:36:07 +0530875 int i = 0;
Sujith55624202010-01-08 10:36:02 +0530876
Felix Fietkauf209f522010-10-01 01:06:53 +0200877 if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
878 kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
879
880 if (sc->sbands[IEEE80211_BAND_5GHZ].channels)
881 kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);
882
Sujith285f2dd2010-01-08 10:36:07 +0530883 if ((sc->btcoex.no_stomp_timer) &&
884 sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
885 ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
Sujith55624202010-01-08 10:36:02 +0530886
Mohammed Shafi Shajakhan19686dd2011-11-30 10:41:28 +0530887 if (sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_MCI)
888 ath_mci_cleanup(sc);
889
Sujith285f2dd2010-01-08 10:36:07 +0530890 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
891 if (ATH_TXQ_SETUP(sc, i))
892 ath_tx_cleanupq(sc, &sc->tx.txq[i]);
893
Sujith285f2dd2010-01-08 10:36:07 +0530894 ath9k_hw_deinit(sc->sc_ah);
895
Sujith736b3a22010-03-17 14:25:24 +0530896 kfree(sc->sc_ah);
897 sc->sc_ah = NULL;
Sujith55624202010-01-08 10:36:02 +0530898}
899
Sujith285f2dd2010-01-08 10:36:07 +0530900void ath9k_deinit_device(struct ath_softc *sc)
Sujith55624202010-01-08 10:36:02 +0530901{
902 struct ieee80211_hw *hw = sc->hw;
Sujith55624202010-01-08 10:36:02 +0530903
904 ath9k_ps_wakeup(sc);
905
Sujith55624202010-01-08 10:36:02 +0530906 wiphy_rfkill_stop_polling(sc->hw->wiphy);
Sujith285f2dd2010-01-08 10:36:07 +0530907 ath_deinit_leds(sc);
Sujith55624202010-01-08 10:36:02 +0530908
Rajkumar Manoharanc7c18062011-01-27 18:39:38 +0530909 ath9k_ps_restore(sc);
910
Sujith55624202010-01-08 10:36:02 +0530911 ieee80211_unregister_hw(hw);
912 ath_rx_cleanup(sc);
913 ath_tx_cleanup(sc);
Sujith285f2dd2010-01-08 10:36:07 +0530914 ath9k_deinit_softc(sc);
Sujith55624202010-01-08 10:36:02 +0530915}
916
917void ath_descdma_cleanup(struct ath_softc *sc,
918 struct ath_descdma *dd,
919 struct list_head *head)
920{
921 dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
922 dd->dd_desc_paddr);
923
924 INIT_LIST_HEAD(head);
925 kfree(dd->dd_bufptr);
926 memset(dd, 0, sizeof(*dd));
927}
928
Sujith55624202010-01-08 10:36:02 +0530929/************************/
930/* Module Hooks */
931/************************/
932
933static int __init ath9k_init(void)
934{
935 int error;
936
937 /* Register rate control algorithm */
938 error = ath_rate_control_register();
939 if (error != 0) {
940 printk(KERN_ERR
941 "ath9k: Unable to register rate control "
942 "algorithm: %d\n",
943 error);
944 goto err_out;
945 }
946
Sujith55624202010-01-08 10:36:02 +0530947 error = ath_pci_init();
948 if (error < 0) {
949 printk(KERN_ERR
950 "ath9k: No PCI devices found, driver not installed.\n");
951 error = -ENODEV;
Ben Greeareb272442010-11-29 14:13:22 -0800952 goto err_rate_unregister;
Sujith55624202010-01-08 10:36:02 +0530953 }
954
955 error = ath_ahb_init();
956 if (error < 0) {
957 error = -ENODEV;
958 goto err_pci_exit;
959 }
960
961 return 0;
962
963 err_pci_exit:
964 ath_pci_exit();
965
Sujith55624202010-01-08 10:36:02 +0530966 err_rate_unregister:
967 ath_rate_control_unregister();
968 err_out:
969 return error;
970}
971module_init(ath9k_init);
972
973static void __exit ath9k_exit(void)
974{
Rajkumar Manoharand5847472010-12-20 14:39:51 +0530975 is_ath9k_unloaded = true;
Sujith55624202010-01-08 10:36:02 +0530976 ath_ahb_exit();
977 ath_pci_exit();
Sujith55624202010-01-08 10:36:02 +0530978 ath_rate_control_unregister();
979 printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
980}
981module_exit(ath9k_exit);