blob: c57d6b859c043207a11883b7a2584241c16aa7dd [file] [log] [blame]
Sujithfb9987d2010-03-17 14:25:25 +05301/*
Sujith Manoharan5b681382011-05-17 13:36:18 +05302 * Copyright (c) 2010-2011 Atheros Communications Inc.
Sujithfb9987d2010-03-17 14:25:25 +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
Joe Perches516304b2012-03-18 17:30:52 -070017#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
Sujithfb9987d2010-03-17 14:25:25 +053019#include "htc.h"
20
21MODULE_AUTHOR("Atheros Communications");
22MODULE_LICENSE("Dual BSD/GPL");
23MODULE_DESCRIPTION("Atheros driver 802.11n HTC based wireless devices");
24
25static unsigned int ath9k_debug = ATH_DBG_DEFAULT;
26module_param_named(debug, ath9k_debug, uint, 0);
27MODULE_PARM_DESC(debug, "Debugging mask");
28
Sujithe1572c52010-03-24 13:42:13 +053029int htc_modparam_nohwcrypt;
30module_param_named(nohwcrypt, htc_modparam_nohwcrypt, int, 0444);
Sujithfb9987d2010-03-17 14:25:25 +053031MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
32
Mohammed Shafi Shajakhan7f34778e2012-09-04 19:33:38 +053033static int ath9k_htc_btcoex_enable;
34module_param_named(btcoex_enable, ath9k_htc_btcoex_enable, int, 0444);
35MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
36
Oleksij Rempel6bca6102014-01-30 09:14:53 +010037static int ath9k_ps_enable;
38module_param_named(ps_enable, ath9k_ps_enable, int, 0444);
39MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave");
40
Sujithfb9987d2010-03-17 14:25:25 +053041#define CHAN2G(_freq, _idx) { \
42 .center_freq = (_freq), \
43 .hw_value = (_idx), \
44 .max_power = 20, \
45}
46
Sujithea46e642010-06-02 15:53:50 +053047#define CHAN5G(_freq, _idx) { \
48 .band = IEEE80211_BAND_5GHZ, \
49 .center_freq = (_freq), \
50 .hw_value = (_idx), \
51 .max_power = 20, \
52}
53
Sujithfb9987d2010-03-17 14:25:25 +053054static struct ieee80211_channel ath9k_2ghz_channels[] = {
55 CHAN2G(2412, 0), /* Channel 1 */
56 CHAN2G(2417, 1), /* Channel 2 */
57 CHAN2G(2422, 2), /* Channel 3 */
58 CHAN2G(2427, 3), /* Channel 4 */
59 CHAN2G(2432, 4), /* Channel 5 */
60 CHAN2G(2437, 5), /* Channel 6 */
61 CHAN2G(2442, 6), /* Channel 7 */
62 CHAN2G(2447, 7), /* Channel 8 */
63 CHAN2G(2452, 8), /* Channel 9 */
64 CHAN2G(2457, 9), /* Channel 10 */
65 CHAN2G(2462, 10), /* Channel 11 */
66 CHAN2G(2467, 11), /* Channel 12 */
67 CHAN2G(2472, 12), /* Channel 13 */
68 CHAN2G(2484, 13), /* Channel 14 */
69};
70
Sujithea46e642010-06-02 15:53:50 +053071static struct ieee80211_channel ath9k_5ghz_channels[] = {
72 /* _We_ call this UNII 1 */
73 CHAN5G(5180, 14), /* Channel 36 */
74 CHAN5G(5200, 15), /* Channel 40 */
75 CHAN5G(5220, 16), /* Channel 44 */
76 CHAN5G(5240, 17), /* Channel 48 */
77 /* _We_ call this UNII 2 */
78 CHAN5G(5260, 18), /* Channel 52 */
79 CHAN5G(5280, 19), /* Channel 56 */
80 CHAN5G(5300, 20), /* Channel 60 */
81 CHAN5G(5320, 21), /* Channel 64 */
82 /* _We_ call this "Middle band" */
83 CHAN5G(5500, 22), /* Channel 100 */
84 CHAN5G(5520, 23), /* Channel 104 */
85 CHAN5G(5540, 24), /* Channel 108 */
86 CHAN5G(5560, 25), /* Channel 112 */
87 CHAN5G(5580, 26), /* Channel 116 */
88 CHAN5G(5600, 27), /* Channel 120 */
89 CHAN5G(5620, 28), /* Channel 124 */
90 CHAN5G(5640, 29), /* Channel 128 */
91 CHAN5G(5660, 30), /* Channel 132 */
92 CHAN5G(5680, 31), /* Channel 136 */
93 CHAN5G(5700, 32), /* Channel 140 */
94 /* _We_ call this UNII 3 */
95 CHAN5G(5745, 33), /* Channel 149 */
96 CHAN5G(5765, 34), /* Channel 153 */
97 CHAN5G(5785, 35), /* Channel 157 */
98 CHAN5G(5805, 36), /* Channel 161 */
99 CHAN5G(5825, 37), /* Channel 165 */
100};
101
Sujithfb9987d2010-03-17 14:25:25 +0530102/* Atheros hardware rate code addition for short premble */
103#define SHPCHECK(__hw_rate, __flags) \
104 ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04) : 0)
105
106#define RATE(_bitrate, _hw_rate, _flags) { \
107 .bitrate = (_bitrate), \
108 .flags = (_flags), \
109 .hw_value = (_hw_rate), \
110 .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \
111}
112
113static struct ieee80211_rate ath9k_legacy_rates[] = {
114 RATE(10, 0x1b, 0),
115 RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp : 0x1e */
116 RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp: 0x1d */
117 RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), /* short: 0x1c */
118 RATE(60, 0x0b, 0),
119 RATE(90, 0x0f, 0),
120 RATE(120, 0x0a, 0),
121 RATE(180, 0x0e, 0),
122 RATE(240, 0x09, 0),
123 RATE(360, 0x0d, 0),
124 RATE(480, 0x08, 0),
125 RATE(540, 0x0c, 0),
126};
127
Sujith Manoharand244f212011-04-28 16:14:05 +0530128#ifdef CONFIG_MAC80211_LEDS
129static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = {
130 { .throughput = 0 * 1024, .blink_time = 334 },
131 { .throughput = 1 * 1024, .blink_time = 260 },
132 { .throughput = 5 * 1024, .blink_time = 220 },
133 { .throughput = 10 * 1024, .blink_time = 190 },
134 { .throughput = 20 * 1024, .blink_time = 170 },
135 { .throughput = 50 * 1024, .blink_time = 150 },
136 { .throughput = 70 * 1024, .blink_time = 130 },
137 { .throughput = 100 * 1024, .blink_time = 110 },
138 { .throughput = 200 * 1024, .blink_time = 80 },
139 { .throughput = 300 * 1024, .blink_time = 50 },
140};
141#endif
142
Sujithfb9987d2010-03-17 14:25:25 +0530143static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
144{
145 int time_left;
146
Sujith.Manoharan@atheros.comd8c49ff2010-05-11 16:24:43 +0530147 if (atomic_read(&priv->htc->tgt_ready) > 0) {
148 atomic_dec(&priv->htc->tgt_ready);
149 return 0;
150 }
151
Sujithfb9987d2010-03-17 14:25:25 +0530152 /* Firmware can take up to 50ms to get ready, to be safe use 1 second */
153 time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ);
154 if (!time_left) {
155 dev_err(priv->dev, "ath9k_htc: Target is unresponsive\n");
156 return -ETIMEDOUT;
157 }
158
Sujith.Manoharan@atheros.comd8c49ff2010-05-11 16:24:43 +0530159 atomic_dec(&priv->htc->tgt_ready);
160
Sujithfb9987d2010-03-17 14:25:25 +0530161 return 0;
162}
163
164static void ath9k_deinit_priv(struct ath9k_htc_priv *priv)
165{
Sujithfb9987d2010-03-17 14:25:25 +0530166 ath9k_hw_deinit(priv->ah);
Sujithfb9987d2010-03-17 14:25:25 +0530167 kfree(priv->ah);
168 priv->ah = NULL;
169}
170
171static void ath9k_deinit_device(struct ath9k_htc_priv *priv)
172{
173 struct ieee80211_hw *hw = priv->hw;
174
175 wiphy_rfkill_stop_polling(hw->wiphy);
176 ath9k_deinit_leds(priv);
177 ieee80211_unregister_hw(hw);
178 ath9k_rx_cleanup(priv);
179 ath9k_tx_cleanup(priv);
180 ath9k_deinit_priv(priv);
181}
182
183static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv,
184 u16 service_id,
185 void (*tx) (void *,
186 struct sk_buff *,
187 enum htc_endpoint_id,
188 bool txok),
189 enum htc_endpoint_id *ep_id)
190{
191 struct htc_service_connreq req;
192
193 memset(&req, 0, sizeof(struct htc_service_connreq));
194
195 req.service_id = service_id;
196 req.ep_callbacks.priv = priv;
197 req.ep_callbacks.rx = ath9k_htc_rxep;
198 req.ep_callbacks.tx = tx;
199
200 return htc_connect_service(priv->htc, &req, ep_id);
201}
202
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +0530203static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid,
204 u32 drv_info)
Sujithfb9987d2010-03-17 14:25:25 +0530205{
206 int ret;
207
208 /* WMI CMD*/
209 ret = ath9k_wmi_connect(priv->htc, priv->wmi, &priv->wmi_cmd_ep);
210 if (ret)
211 goto err;
212
213 /* Beacon */
Sujith9c6dda42010-05-06 14:45:47 +0530214 ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, ath9k_htc_beaconep,
Sujithfb9987d2010-03-17 14:25:25 +0530215 &priv->beacon_ep);
216 if (ret)
217 goto err;
218
219 /* CAB */
220 ret = ath9k_htc_connect_svc(priv, WMI_CAB_SVC, ath9k_htc_txep,
221 &priv->cab_ep);
222 if (ret)
223 goto err;
224
225
226 /* UAPSD */
227 ret = ath9k_htc_connect_svc(priv, WMI_UAPSD_SVC, ath9k_htc_txep,
228 &priv->uapsd_ep);
229 if (ret)
230 goto err;
231
232 /* MGMT */
233 ret = ath9k_htc_connect_svc(priv, WMI_MGMT_SVC, ath9k_htc_txep,
234 &priv->mgmt_ep);
235 if (ret)
236 goto err;
237
238 /* DATA BE */
239 ret = ath9k_htc_connect_svc(priv, WMI_DATA_BE_SVC, ath9k_htc_txep,
240 &priv->data_be_ep);
241 if (ret)
242 goto err;
243
244 /* DATA BK */
245 ret = ath9k_htc_connect_svc(priv, WMI_DATA_BK_SVC, ath9k_htc_txep,
246 &priv->data_bk_ep);
247 if (ret)
248 goto err;
249
250 /* DATA VI */
251 ret = ath9k_htc_connect_svc(priv, WMI_DATA_VI_SVC, ath9k_htc_txep,
252 &priv->data_vi_ep);
253 if (ret)
254 goto err;
255
256 /* DATA VO */
257 ret = ath9k_htc_connect_svc(priv, WMI_DATA_VO_SVC, ath9k_htc_txep,
258 &priv->data_vo_ep);
259 if (ret)
260 goto err;
261
Sujith6267dc72010-06-02 15:53:54 +0530262 /*
263 * Setup required credits before initializing HTC.
264 * This is a bit hacky, but, since queuing is done in
265 * the HIF layer, shouldn't matter much.
266 */
267
Sujith Manoharan0b5ead92010-12-07 16:31:38 +0530268 if (IS_AR7010_DEVICE(drv_info))
Sujith Manoharand108e8b2011-05-17 12:42:24 +0530269 priv->htc->credits = 45;
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +0530270 else
Sujith4e63f762010-06-17 10:29:01 +0530271 priv->htc->credits = 33;
Sujith6267dc72010-06-02 15:53:54 +0530272
Sujithfb9987d2010-03-17 14:25:25 +0530273 ret = htc_init(priv->htc);
274 if (ret)
275 goto err;
276
Sujith6267dc72010-06-02 15:53:54 +0530277 dev_info(priv->dev, "ath9k_htc: HTC initialized with %d credits\n",
278 priv->htc->credits);
279
Sujithfb9987d2010-03-17 14:25:25 +0530280 return 0;
281
282err:
283 dev_err(priv->dev, "ath9k_htc: Unable to initialize HTC services\n");
284 return ret;
285}
286
Luis R. Rodriguez0c0280b2013-01-11 18:39:36 +0000287static void ath9k_reg_notifier(struct wiphy *wiphy,
288 struct regulatory_request *request)
Sujithfb9987d2010-03-17 14:25:25 +0530289{
290 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
291 struct ath9k_htc_priv *priv = hw->priv;
292
Luis R. Rodriguez0c0280b2013-01-11 18:39:36 +0000293 ath_reg_notifier_apply(wiphy, request,
294 ath9k_hw_regulatory(priv->ah));
Sujithfb9987d2010-03-17 14:25:25 +0530295}
296
Sujith4a22fe12010-04-16 11:53:53 +0530297static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset)
Sujithfb9987d2010-03-17 14:25:25 +0530298{
299 struct ath_hw *ah = (struct ath_hw *) hw_priv;
300 struct ath_common *common = ath9k_hw_common(ah);
301 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
302 __be32 val, reg = cpu_to_be32(reg_offset);
303 int r;
304
305 r = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
306 (u8 *) &reg, sizeof(reg),
307 (u8 *) &val, sizeof(val),
308 100);
309 if (unlikely(r)) {
Joe Perchesd2182b62011-12-15 14:55:53 -0800310 ath_dbg(common, WMI, "REGISTER READ FAILED: (0x%04x, %d)\n",
Joe Perches226afe62010-12-02 19:12:37 -0800311 reg_offset, r);
Sujithfb9987d2010-03-17 14:25:25 +0530312 return -EIO;
313 }
314
315 return be32_to_cpu(val);
316}
317
Sujith Manoharan09a525d2011-01-04 13:17:18 +0530318static void ath9k_multi_regread(void *hw_priv, u32 *addr,
319 u32 *val, u16 count)
320{
321 struct ath_hw *ah = (struct ath_hw *) hw_priv;
322 struct ath_common *common = ath9k_hw_common(ah);
323 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
324 __be32 tmpaddr[8];
325 __be32 tmpval[8];
326 int i, ret;
327
328 for (i = 0; i < count; i++) {
329 tmpaddr[i] = cpu_to_be32(addr[i]);
330 }
331
332 ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
333 (u8 *)tmpaddr , sizeof(u32) * count,
334 (u8 *)tmpval, sizeof(u32) * count,
335 100);
336 if (unlikely(ret)) {
Joe Perchesd2182b62011-12-15 14:55:53 -0800337 ath_dbg(common, WMI,
Sujith Manoharan09a525d2011-01-04 13:17:18 +0530338 "Multiple REGISTER READ FAILED (count: %d)\n", count);
339 }
340
341 for (i = 0; i < count; i++) {
342 val[i] = be32_to_cpu(tmpval[i]);
343 }
344}
345
Sujith4a22fe12010-04-16 11:53:53 +0530346static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)
Sujithfb9987d2010-03-17 14:25:25 +0530347{
348 struct ath_hw *ah = (struct ath_hw *) hw_priv;
349 struct ath_common *common = ath9k_hw_common(ah);
350 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
Joe Perches07b2fa52010-11-20 18:38:53 -0800351 const __be32 buf[2] = {
Sujithfb9987d2010-03-17 14:25:25 +0530352 cpu_to_be32(reg_offset),
353 cpu_to_be32(val),
354 };
355 int r;
356
357 r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
358 (u8 *) &buf, sizeof(buf),
359 (u8 *) &val, sizeof(val),
360 100);
361 if (unlikely(r)) {
Joe Perchesd2182b62011-12-15 14:55:53 -0800362 ath_dbg(common, WMI, "REGISTER WRITE FAILED:(0x%04x, %d)\n",
Joe Perches226afe62010-12-02 19:12:37 -0800363 reg_offset, r);
Sujithfb9987d2010-03-17 14:25:25 +0530364 }
365}
366
Sujith4a22fe12010-04-16 11:53:53 +0530367static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset)
368{
369 struct ath_hw *ah = (struct ath_hw *) hw_priv;
370 struct ath_common *common = ath9k_hw_common(ah);
371 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
372 u32 rsp_status;
373 int r;
374
375 mutex_lock(&priv->wmi->multi_write_mutex);
376
377 /* Store the register/value */
378 priv->wmi->multi_write[priv->wmi->multi_write_idx].reg =
379 cpu_to_be32(reg_offset);
380 priv->wmi->multi_write[priv->wmi->multi_write_idx].val =
381 cpu_to_be32(val);
382
383 priv->wmi->multi_write_idx++;
384
385 /* If the buffer is full, send it out. */
386 if (priv->wmi->multi_write_idx == MAX_CMD_NUMBER) {
387 r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
388 (u8 *) &priv->wmi->multi_write,
389 sizeof(struct register_write) * priv->wmi->multi_write_idx,
390 (u8 *) &rsp_status, sizeof(rsp_status),
391 100);
392 if (unlikely(r)) {
Joe Perchesd2182b62011-12-15 14:55:53 -0800393 ath_dbg(common, WMI,
Joe Perches226afe62010-12-02 19:12:37 -0800394 "REGISTER WRITE FAILED, multi len: %d\n",
395 priv->wmi->multi_write_idx);
Sujith4a22fe12010-04-16 11:53:53 +0530396 }
397 priv->wmi->multi_write_idx = 0;
398 }
399
400 mutex_unlock(&priv->wmi->multi_write_mutex);
401}
402
403static void ath9k_regwrite(void *hw_priv, u32 val, u32 reg_offset)
404{
405 struct ath_hw *ah = (struct ath_hw *) hw_priv;
406 struct ath_common *common = ath9k_hw_common(ah);
407 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
408
409 if (atomic_read(&priv->wmi->mwrite_cnt))
410 ath9k_regwrite_buffer(hw_priv, val, reg_offset);
411 else
412 ath9k_regwrite_single(hw_priv, val, reg_offset);
413}
414
415static void ath9k_enable_regwrite_buffer(void *hw_priv)
416{
417 struct ath_hw *ah = (struct ath_hw *) hw_priv;
418 struct ath_common *common = ath9k_hw_common(ah);
419 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
420
421 atomic_inc(&priv->wmi->mwrite_cnt);
422}
423
Sujith4a22fe12010-04-16 11:53:53 +0530424static void ath9k_regwrite_flush(void *hw_priv)
425{
426 struct ath_hw *ah = (struct ath_hw *) hw_priv;
427 struct ath_common *common = ath9k_hw_common(ah);
428 struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
429 u32 rsp_status;
430 int r;
431
Felix Fietkau435c1612010-10-05 12:03:42 +0200432 atomic_dec(&priv->wmi->mwrite_cnt);
433
Sujith4a22fe12010-04-16 11:53:53 +0530434 mutex_lock(&priv->wmi->multi_write_mutex);
435
436 if (priv->wmi->multi_write_idx) {
437 r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
438 (u8 *) &priv->wmi->multi_write,
439 sizeof(struct register_write) * priv->wmi->multi_write_idx,
440 (u8 *) &rsp_status, sizeof(rsp_status),
441 100);
442 if (unlikely(r)) {
Joe Perchesd2182b62011-12-15 14:55:53 -0800443 ath_dbg(common, WMI,
Joe Perches226afe62010-12-02 19:12:37 -0800444 "REGISTER WRITE FAILED, multi len: %d\n",
445 priv->wmi->multi_write_idx);
Sujith4a22fe12010-04-16 11:53:53 +0530446 }
447 priv->wmi->multi_write_idx = 0;
448 }
449
450 mutex_unlock(&priv->wmi->multi_write_mutex);
451}
452
Felix Fietkau845e03c2011-03-23 20:57:25 +0100453static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
454{
455 u32 val;
456
457 val = ath9k_regread(hw_priv, reg_offset);
458 val &= ~clr;
459 val |= set;
460 ath9k_regwrite(hw_priv, val, reg_offset);
461 return val;
462}
463
Sujithfb9987d2010-03-17 14:25:25 +0530464static void ath_usb_read_cachesize(struct ath_common *common, int *csz)
465{
466 *csz = L1_CACHE_BYTES >> 2;
467}
468
469static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
470{
471 struct ath_hw *ah = (struct ath_hw *) common->ah;
472
473 (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
474
475 if (!ath9k_hw_wait(ah,
476 AR_EEPROM_STATUS_DATA,
477 AR_EEPROM_STATUS_DATA_BUSY |
478 AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
479 AH_WAIT_TIMEOUT))
480 return false;
481
482 *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
483 AR_EEPROM_STATUS_DATA_VAL);
484
485 return true;
486}
487
488static const struct ath_bus_ops ath9k_usb_bus_ops = {
Sujith497ad9a2010-04-01 10:28:20 +0530489 .ath_bus_type = ATH_USB,
Sujithfb9987d2010-03-17 14:25:25 +0530490 .read_cachesize = ath_usb_read_cachesize,
491 .eeprom_read = ath_usb_eeprom_read,
492};
493
494static void setup_ht_cap(struct ath9k_htc_priv *priv,
495 struct ieee80211_sta_ht_cap *ht_info)
496{
Sujith6debeca2010-06-02 15:53:40 +0530497 struct ath_common *common = ath9k_hw_common(priv->ah);
498 u8 tx_streams, rx_streams;
499 int i;
500
Sujithfb9987d2010-03-17 14:25:25 +0530501 ht_info->ht_supported = true;
502 ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
503 IEEE80211_HT_CAP_SM_PS |
504 IEEE80211_HT_CAP_SGI_40 |
505 IEEE80211_HT_CAP_DSSSCCK40;
506
Sujithb4dec5e2010-05-17 12:01:19 +0530507 if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
508 ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
509
Sujith17525f92010-05-17 12:01:21 +0530510 ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
511
Sujithfb9987d2010-03-17 14:25:25 +0530512 ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
513 ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
514
515 memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
Sujith6debeca2010-06-02 15:53:40 +0530516
517 /* ath9k_htc supports only 1 or 2 stream devices */
Felix Fietkau82b2d332011-09-03 01:40:23 +0200518 tx_streams = ath9k_cmn_count_streams(priv->ah->txchainmask, 2);
519 rx_streams = ath9k_cmn_count_streams(priv->ah->rxchainmask, 2);
Sujith6debeca2010-06-02 15:53:40 +0530520
Joe Perchesd2182b62011-12-15 14:55:53 -0800521 ath_dbg(common, CONFIG, "TX streams %d, RX streams: %d\n",
Joe Perches226afe62010-12-02 19:12:37 -0800522 tx_streams, rx_streams);
Sujith6debeca2010-06-02 15:53:40 +0530523
Oleksij Rempela226c3d2013-06-09 18:51:24 +0200524 if (tx_streams >= 2)
525 ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
526
Sujith6debeca2010-06-02 15:53:40 +0530527 if (tx_streams != rx_streams) {
528 ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
529 ht_info->mcs.tx_params |= ((tx_streams - 1) <<
530 IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
531 }
532
533 for (i = 0; i < rx_streams; i++)
534 ht_info->mcs.rx_mask[i] = 0xff;
535
Sujithfb9987d2010-03-17 14:25:25 +0530536 ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
537}
538
539static int ath9k_init_queues(struct ath9k_htc_priv *priv)
540{
541 struct ath_common *common = ath9k_hw_common(priv->ah);
542 int i;
543
544 for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++)
545 priv->hwq_map[i] = -1;
546
Sujithca74b832010-05-14 11:18:56 +0530547 priv->beaconq = ath9k_hw_beaconq_setup(priv->ah);
548 if (priv->beaconq == -1) {
Joe Perches38002762010-12-02 19:12:36 -0800549 ath_err(common, "Unable to setup BEACON xmit queue\n");
Sujithca74b832010-05-14 11:18:56 +0530550 goto err;
551 }
552
553 priv->cabq = ath9k_htc_cabq_setup(priv);
554 if (priv->cabq == -1) {
Joe Perches38002762010-12-02 19:12:36 -0800555 ath_err(common, "Unable to setup CAB xmit queue\n");
Sujithca74b832010-05-14 11:18:56 +0530556 goto err;
557 }
558
Sujith Manoharanbea843c2012-11-21 18:13:10 +0530559 if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_BE)) {
Joe Perches38002762010-12-02 19:12:36 -0800560 ath_err(common, "Unable to setup xmit queue for BE traffic\n");
Sujithfb9987d2010-03-17 14:25:25 +0530561 goto err;
562 }
563
Sujith Manoharanbea843c2012-11-21 18:13:10 +0530564 if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_BK)) {
Joe Perches38002762010-12-02 19:12:36 -0800565 ath_err(common, "Unable to setup xmit queue for BK traffic\n");
Sujithfb9987d2010-03-17 14:25:25 +0530566 goto err;
567 }
Sujith Manoharanbea843c2012-11-21 18:13:10 +0530568 if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_VI)) {
Joe Perches38002762010-12-02 19:12:36 -0800569 ath_err(common, "Unable to setup xmit queue for VI traffic\n");
Sujithfb9987d2010-03-17 14:25:25 +0530570 goto err;
571 }
Sujith Manoharanbea843c2012-11-21 18:13:10 +0530572 if (!ath9k_htc_txq_setup(priv, IEEE80211_AC_VO)) {
Joe Perches38002762010-12-02 19:12:36 -0800573 ath_err(common, "Unable to setup xmit queue for VO traffic\n");
Sujithfb9987d2010-03-17 14:25:25 +0530574 goto err;
575 }
576
577 return 0;
578
579err:
580 return -EINVAL;
581}
582
Sujithfb9987d2010-03-17 14:25:25 +0530583static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
584{
Felix Fietkaud4659912010-10-14 16:02:39 +0200585 if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
Sujithfb9987d2010-03-17 14:25:25 +0530586 priv->sbands[IEEE80211_BAND_2GHZ].channels =
587 ath9k_2ghz_channels;
588 priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
589 priv->sbands[IEEE80211_BAND_2GHZ].n_channels =
590 ARRAY_SIZE(ath9k_2ghz_channels);
591 priv->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
592 priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
593 ARRAY_SIZE(ath9k_legacy_rates);
594 }
Sujithea46e642010-06-02 15:53:50 +0530595
Felix Fietkaud4659912010-10-14 16:02:39 +0200596 if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
Sujithea46e642010-06-02 15:53:50 +0530597 priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels;
598 priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
599 priv->sbands[IEEE80211_BAND_5GHZ].n_channels =
600 ARRAY_SIZE(ath9k_5ghz_channels);
601 priv->sbands[IEEE80211_BAND_5GHZ].bitrates =
602 ath9k_legacy_rates + 4;
603 priv->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
604 ARRAY_SIZE(ath9k_legacy_rates) - 4;
605 }
Sujithfb9987d2010-03-17 14:25:25 +0530606}
607
608static void ath9k_init_misc(struct ath9k_htc_priv *priv)
609{
610 struct ath_common *common = ath9k_hw_common(priv->ah);
611
Felix Fietkau364734f2010-09-14 20:22:44 +0200612 memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
Sujithfb9987d2010-03-17 14:25:25 +0530613
Sujith9f01a842010-03-29 16:07:20 +0530614 priv->ah->opmode = NL80211_IFTYPE_STATION;
Sujithfb9987d2010-03-17 14:25:25 +0530615}
616
Vivek Natarajan21cb9872010-08-18 19:57:49 +0530617static int ath9k_init_priv(struct ath9k_htc_priv *priv,
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +0530618 u16 devid, char *product,
619 u32 drv_info)
Sujithfb9987d2010-03-17 14:25:25 +0530620{
621 struct ath_hw *ah = NULL;
622 struct ath_common *common;
Sujith Manoharan832f6a12011-04-13 11:23:08 +0530623 int i, ret = 0, csz = 0;
Sujithfb9987d2010-03-17 14:25:25 +0530624
Sujith Manoharand8a2c512012-06-25 13:54:41 +0530625 set_bit(OP_INVALID, &priv->op_flags);
Sujithfb9987d2010-03-17 14:25:25 +0530626
627 ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
628 if (!ah)
629 return -ENOMEM;
630
631 ah->hw_version.devid = devid;
Sujith Manoharan0b5ead92010-12-07 16:31:38 +0530632 ah->hw_version.usbdev = drv_info;
Felix Fietkauf8afa422010-11-22 18:26:51 +0100633 ah->ah_flags |= AH_USE_EEPROM;
Felix Fietkauf9f84e92011-03-23 20:57:24 +0100634 ah->reg_ops.read = ath9k_regread;
635 ah->reg_ops.multi_read = ath9k_multi_regread;
636 ah->reg_ops.write = ath9k_regwrite;
637 ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer;
638 ah->reg_ops.write_flush = ath9k_regwrite_flush;
Felix Fietkau845e03c2011-03-23 20:57:25 +0100639 ah->reg_ops.rmw = ath9k_reg_rmw;
Sujithfb9987d2010-03-17 14:25:25 +0530640 priv->ah = ah;
641
642 common = ath9k_hw_common(ah);
Felix Fietkauf9f84e92011-03-23 20:57:24 +0100643 common->ops = &ah->reg_ops;
Sujithfb9987d2010-03-17 14:25:25 +0530644 common->bus_ops = &ath9k_usb_bus_ops;
645 common->ah = ah;
646 common->hw = priv->hw;
647 common->priv = priv;
648 common->debug_mask = ath9k_debug;
Mohammed Shafi Shajakhan7f34778e2012-09-04 19:33:38 +0530649 common->btcoex_enabled = ath9k_htc_btcoex_enable == 1;
Sujithfb9987d2010-03-17 14:25:25 +0530650
Sujithfb9987d2010-03-17 14:25:25 +0530651 spin_lock_init(&priv->beacon_lock);
Sujith Manoharan658ef042011-04-13 11:25:00 +0530652 spin_lock_init(&priv->tx.tx_lock);
Sujithfb9987d2010-03-17 14:25:25 +0530653 mutex_init(&priv->mutex);
Vivek Natarajanbde748a2010-04-05 14:48:05 +0530654 mutex_init(&priv->htc_pm_lock);
Sujithfb9987d2010-03-17 14:25:25 +0530655 tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
656 (unsigned long)priv);
Sujith Manoharan27876a22011-04-13 11:26:18 +0530657 tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet,
Sujith Manoharan73908672010-12-28 14:28:27 +0530658 (unsigned long)priv);
Sujith Manoharana2362542011-02-21 07:49:38 +0530659 INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work);
Vivek Natarajanbde748a2010-04-05 14:48:05 +0530660 INIT_WORK(&priv->ps_work, ath9k_ps_work);
Sujith Manoharan73908672010-12-28 14:28:27 +0530661 INIT_WORK(&priv->fatal_work, ath9k_fatal_work);
Sujith Manoharan859c3ca2011-04-13 11:26:39 +0530662 setup_timer(&priv->tx.cleanup_timer, ath9k_htc_tx_cleanup_timer,
663 (unsigned long)priv);
Sujithfb9987d2010-03-17 14:25:25 +0530664
665 /*
666 * Cache line size is used to size and align various
667 * structures used to communicate with the hardware.
668 */
669 ath_read_cachesize(common, &csz);
670 common->cachelsz = csz << 2; /* convert to bytes */
671
672 ret = ath9k_hw_init(ah);
673 if (ret) {
Joe Perches38002762010-12-02 19:12:36 -0800674 ath_err(common,
675 "Unable to initialize hardware; initialization status: %d\n",
676 ret);
Sujithfb9987d2010-03-17 14:25:25 +0530677 goto err_hw;
678 }
679
Sujithfb9987d2010-03-17 14:25:25 +0530680 ret = ath9k_init_queues(priv);
681 if (ret)
682 goto err_queues;
683
Sujith Manoharan832f6a12011-04-13 11:23:08 +0530684 for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)
685 priv->cur_beacon_conf.bslot[i] = NULL;
686
Rajkumar Manoharanf82b4bd2011-08-13 10:28:15 +0530687 ath9k_cmn_init_crypto(ah);
Sujithfb9987d2010-03-17 14:25:25 +0530688 ath9k_init_channels_rates(priv);
689 ath9k_init_misc(priv);
Sujith Manoharancee53412012-02-22 12:41:41 +0530690 ath9k_htc_init_btcoex(priv, product);
Vivek Natarajan21cb9872010-08-18 19:57:49 +0530691
Sujithfb9987d2010-03-17 14:25:25 +0530692 return 0;
693
694err_queues:
Sujithfb9987d2010-03-17 14:25:25 +0530695 ath9k_hw_deinit(ah);
696err_hw:
697
698 kfree(ah);
699 priv->ah = NULL;
700
701 return ret;
702}
703
Mohammed Shafi Shajakhan8b0b6be2012-10-08 21:30:52 +0530704static const struct ieee80211_iface_limit if_limits[] = {
705 { .max = 2, .types = BIT(NL80211_IFTYPE_STATION) |
706 BIT(NL80211_IFTYPE_P2P_CLIENT) },
707 { .max = 2, .types = BIT(NL80211_IFTYPE_AP) |
Thomas Pedersen0c9acaa2013-06-26 15:06:58 -0700708#ifdef CONFIG_MAC80211_MESH
709 BIT(NL80211_IFTYPE_MESH_POINT) |
710#endif
711 BIT(NL80211_IFTYPE_P2P_GO) },
Mohammed Shafi Shajakhan8b0b6be2012-10-08 21:30:52 +0530712};
713
714static const struct ieee80211_iface_combination if_comb = {
715 .limits = if_limits,
716 .n_limits = ARRAY_SIZE(if_limits),
717 .max_interfaces = 2,
718 .num_different_channels = 1,
719};
720
Sujithfb9987d2010-03-17 14:25:25 +0530721static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
722 struct ieee80211_hw *hw)
723{
724 struct ath_common *common = ath9k_hw_common(priv->ah);
Ben Greear156652b2013-06-19 14:02:14 -0700725 struct base_eep_header *pBase;
Sujithfb9987d2010-03-17 14:25:25 +0530726
727 hw->flags = IEEE80211_HW_SIGNAL_DBM |
728 IEEE80211_HW_AMPDU_AGGREGATION |
729 IEEE80211_HW_SPECTRUM_MGMT |
Sujith32fbcca2010-03-30 08:48:27 +0530730 IEEE80211_HW_HAS_RATE_CONTROL |
Vivek Natarajanbde748a2010-04-05 14:48:05 +0530731 IEEE80211_HW_RX_INCLUDES_FCS |
Sujith Manoharan7d547eb2011-04-13 11:23:34 +0530732 IEEE80211_HW_PS_NULLFUNC_STACK |
Rajkumar Manoharan8ae2e122011-07-08 18:12:03 +0530733 IEEE80211_HW_REPORTS_TX_ACK_STATUS |
Javier Cardonabd4a85e2013-05-08 10:16:47 -0700734 IEEE80211_HW_MFP_CAPABLE |
Sujith Manoharan7d547eb2011-04-13 11:23:34 +0530735 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
Sujithfb9987d2010-03-17 14:25:25 +0530736
Oleksij Rempel6bca6102014-01-30 09:14:53 +0100737 if (ath9k_ps_enable)
738 hw->flags |= IEEE80211_HW_SUPPORTS_PS;
739
Sujithfb9987d2010-03-17 14:25:25 +0530740 hw->wiphy->interface_modes =
741 BIT(NL80211_IFTYPE_STATION) |
Sujith Manoharan09d5b942011-04-13 11:27:06 +0530742 BIT(NL80211_IFTYPE_ADHOC) |
743 BIT(NL80211_IFTYPE_AP) |
744 BIT(NL80211_IFTYPE_P2P_GO) |
Javier Cardona594e65b2013-05-08 10:16:46 -0700745 BIT(NL80211_IFTYPE_P2P_CLIENT) |
746 BIT(NL80211_IFTYPE_MESH_POINT);
Sujithfb9987d2010-03-17 14:25:25 +0530747
Mohammed Shafi Shajakhan8b0b6be2012-10-08 21:30:52 +0530748 hw->wiphy->iface_combinations = &if_comb;
749 hw->wiphy->n_iface_combinations = 1;
750
Vivek Natarajanbde748a2010-04-05 14:48:05 +0530751 hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
752
Johannes Berg81ddbb52012-03-26 18:47:18 +0200753 hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN |
754 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
Antonio Quartullid7d312c2012-01-17 23:13:30 +0100755
Sujithfb9987d2010-03-17 14:25:25 +0530756 hw->queues = 4;
Sujith Manoharanfb1c0782012-06-25 13:54:30 +0530757 hw->max_listen_interval = 1;
Sujith Manoharan3a0593e2011-04-20 14:33:28 +0530758
Sujithfb9987d2010-03-17 14:25:25 +0530759 hw->vif_data_size = sizeof(struct ath9k_htc_vif);
760 hw->sta_data_size = sizeof(struct ath9k_htc_sta);
761
762 /* tx_frame_hdr is larger than tx_mgmt_hdr anyway */
763 hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) +
764 sizeof(struct htc_frame_hdr) + 4;
765
Felix Fietkaud4659912010-10-14 16:02:39 +0200766 if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
Sujithfb9987d2010-03-17 14:25:25 +0530767 hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
768 &priv->sbands[IEEE80211_BAND_2GHZ];
Felix Fietkaud4659912010-10-14 16:02:39 +0200769 if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
Sujithea46e642010-06-02 15:53:50 +0530770 hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
771 &priv->sbands[IEEE80211_BAND_5GHZ];
Sujithfb9987d2010-03-17 14:25:25 +0530772
773 if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
Felix Fietkaud4659912010-10-14 16:02:39 +0200774 if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
Sujithfb9987d2010-03-17 14:25:25 +0530775 setup_ht_cap(priv,
776 &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap);
Felix Fietkaud4659912010-10-14 16:02:39 +0200777 if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
Sujithea46e642010-06-02 15:53:50 +0530778 setup_ht_cap(priv,
779 &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap);
Sujithfb9987d2010-03-17 14:25:25 +0530780 }
781
Ben Greear156652b2013-06-19 14:02:14 -0700782 pBase = ath9k_htc_get_eeprom_base(priv);
783 if (pBase) {
784 hw->wiphy->available_antennas_rx = pBase->rxMask;
785 hw->wiphy->available_antennas_tx = pBase->txMask;
786 }
787
Sujithfb9987d2010-03-17 14:25:25 +0530788 SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
789}
790
Sujith Manoharan29bbfb22011-04-13 11:22:51 +0530791static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv)
792{
793 struct ieee80211_hw *hw = priv->hw;
794 struct wmi_fw_version cmd_rsp;
795 int ret;
796
797 memset(&cmd_rsp, 0, sizeof(cmd_rsp));
798
799 WMI_CMD(WMI_GET_FW_VERSION);
800 if (ret)
801 return -EINVAL;
802
803 priv->fw_version_major = be16_to_cpu(cmd_rsp.major);
804 priv->fw_version_minor = be16_to_cpu(cmd_rsp.minor);
805
Jiri Pirko81135542013-01-06 02:12:51 +0000806 snprintf(hw->wiphy->fw_version, sizeof(hw->wiphy->fw_version), "%d.%d",
Sujith Manoharan29bbfb22011-04-13 11:22:51 +0530807 priv->fw_version_major,
808 priv->fw_version_minor);
809
810 dev_info(priv->dev, "ath9k_htc: FW Version: %d.%d\n",
811 priv->fw_version_major,
812 priv->fw_version_minor);
813
Sujith Manoharan3a0593e2011-04-20 14:33:28 +0530814 /*
815 * Check if the available FW matches the driver's
816 * required version.
817 */
818 if (priv->fw_version_major != MAJOR_VERSION_REQ ||
Felix Fietkau319e7bd2013-04-07 21:10:48 +0200819 priv->fw_version_minor < MINOR_VERSION_REQ) {
Sujith Manoharan3a0593e2011-04-20 14:33:28 +0530820 dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n",
821 MAJOR_VERSION_REQ, MINOR_VERSION_REQ);
822 return -EINVAL;
823 }
824
Sujith Manoharan29bbfb22011-04-13 11:22:51 +0530825 return 0;
826}
827
Vivek Natarajan21cb9872010-08-18 19:57:49 +0530828static int ath9k_init_device(struct ath9k_htc_priv *priv,
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +0530829 u16 devid, char *product, u32 drv_info)
Sujithfb9987d2010-03-17 14:25:25 +0530830{
831 struct ieee80211_hw *hw = priv->hw;
832 struct ath_common *common;
833 struct ath_hw *ah;
834 int error = 0;
835 struct ath_regulatory *reg;
Sujith Manoharan3e3f1d12011-02-21 07:50:30 +0530836 char hw_name[64];
Sujithfb9987d2010-03-17 14:25:25 +0530837
838 /* Bring up device */
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +0530839 error = ath9k_init_priv(priv, devid, product, drv_info);
Sujithfb9987d2010-03-17 14:25:25 +0530840 if (error != 0)
841 goto err_init;
842
843 ah = priv->ah;
844 common = ath9k_hw_common(ah);
845 ath9k_set_hw_capab(priv, hw);
846
Sujith Manoharan29bbfb22011-04-13 11:22:51 +0530847 error = ath9k_init_firmware_version(priv);
848 if (error != 0)
849 goto err_fw;
850
Sujithfb9987d2010-03-17 14:25:25 +0530851 /* Initialize regulatory */
852 error = ath_regd_init(&common->regulatory, priv->hw->wiphy,
853 ath9k_reg_notifier);
854 if (error)
855 goto err_regd;
856
857 reg = &common->regulatory;
858
859 /* Setup TX */
860 error = ath9k_tx_init(priv);
861 if (error != 0)
862 goto err_tx;
863
864 /* Setup RX */
865 error = ath9k_rx_init(priv);
866 if (error != 0)
867 goto err_rx;
868
Oleksij Rempeldc2a87f2013-07-19 20:16:17 +0200869 ath9k_hw_disable(priv->ah);
Sujith Manoharand244f212011-04-28 16:14:05 +0530870#ifdef CONFIG_MAC80211_LEDS
871 /* must be initialized before ieee80211_register_hw */
872 priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw,
873 IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_htc_tpt_blink,
874 ARRAY_SIZE(ath9k_htc_tpt_blink));
875#endif
876
Sujithfb9987d2010-03-17 14:25:25 +0530877 /* Register with mac80211 */
878 error = ieee80211_register_hw(hw);
879 if (error)
880 goto err_register;
881
882 /* Handle world regulatory */
883 if (!ath_is_world_regd(reg)) {
884 error = regulatory_hint(hw->wiphy, reg->alpha2);
885 if (error)
886 goto err_world;
887 }
888
Rajkumar Manoharane5facc72011-04-15 15:42:24 +0530889 error = ath9k_htc_init_debug(priv->ah);
890 if (error) {
891 ath_err(common, "Unable to create debugfs files\n");
892 goto err_world;
893 }
894
Joe Perchesd2182b62011-12-15 14:55:53 -0800895 ath_dbg(common, CONFIG,
896 "WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, BE:%d, BK:%d, VI:%d, VO:%d\n",
Sujith Manoharan3e3f1d12011-02-21 07:50:30 +0530897 priv->wmi_cmd_ep,
898 priv->beacon_ep,
899 priv->cab_ep,
900 priv->uapsd_ep,
901 priv->mgmt_ep,
902 priv->data_be_ep,
903 priv->data_bk_ep,
904 priv->data_vi_ep,
905 priv->data_vo_ep);
906
907 ath9k_hw_name(priv->ah, hw_name, sizeof(hw_name));
908 wiphy_info(hw->wiphy, "%s\n", hw_name);
909
Sujithfb9987d2010-03-17 14:25:25 +0530910 ath9k_init_leds(priv);
911 ath9k_start_rfkill_poll(priv);
912
913 return 0;
914
915err_world:
916 ieee80211_unregister_hw(hw);
917err_register:
918 ath9k_rx_cleanup(priv);
919err_rx:
920 ath9k_tx_cleanup(priv);
921err_tx:
922 /* Nothing */
923err_regd:
Sujith Manoharan29bbfb22011-04-13 11:22:51 +0530924 /* Nothing */
925err_fw:
Sujithfb9987d2010-03-17 14:25:25 +0530926 ath9k_deinit_priv(priv);
927err_init:
928 return error;
929}
930
931int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +0530932 u16 devid, char *product, u32 drv_info)
Sujithfb9987d2010-03-17 14:25:25 +0530933{
934 struct ieee80211_hw *hw;
935 struct ath9k_htc_priv *priv;
936 int ret;
937
938 hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops);
939 if (!hw)
940 return -ENOMEM;
941
942 priv = hw->priv;
943 priv->hw = hw;
944 priv->htc = htc_handle;
945 priv->dev = dev;
946 htc_handle->drv_priv = priv;
947 SET_IEEE80211_DEV(hw, priv->dev);
948
949 ret = ath9k_htc_wait_for_target(priv);
950 if (ret)
951 goto err_free;
952
953 priv->wmi = ath9k_init_wmi(priv);
954 if (!priv->wmi) {
955 ret = -EINVAL;
956 goto err_free;
957 }
958
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +0530959 ret = ath9k_init_htc_services(priv, devid, drv_info);
Sujithfb9987d2010-03-17 14:25:25 +0530960 if (ret)
961 goto err_init;
962
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +0530963 ret = ath9k_init_device(priv, devid, product, drv_info);
Sujithfb9987d2010-03-17 14:25:25 +0530964 if (ret)
965 goto err_init;
966
967 return 0;
968
969err_init:
970 ath9k_deinit_wmi(priv);
971err_free:
972 ieee80211_free_hw(hw);
973 return ret;
974}
975
976void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
977{
978 if (htc_handle->drv_priv) {
Sujitha3be14b2010-04-23 10:28:10 +0530979
980 /* Check if the device has been yanked out. */
981 if (hotunplug)
Sujith Manoharan97dcec52010-12-20 08:02:42 +0530982 htc_handle->drv_priv->ah->ah_flags |= AH_UNPLUGGED;
Sujitha3be14b2010-04-23 10:28:10 +0530983
Sujithfb9987d2010-03-17 14:25:25 +0530984 ath9k_deinit_device(htc_handle->drv_priv);
985 ath9k_deinit_wmi(htc_handle->drv_priv);
986 ieee80211_free_hw(htc_handle->drv_priv->hw);
987 }
988}
989
990#ifdef CONFIG_PM
Sujith Manoharanf933ebe2010-12-01 12:30:27 +0530991
992void ath9k_htc_suspend(struct htc_target *htc_handle)
993{
994 ath9k_htc_setpower(htc_handle->drv_priv, ATH9K_PM_FULL_SLEEP);
995}
996
Sujithfb9987d2010-03-17 14:25:25 +0530997int ath9k_htc_resume(struct htc_target *htc_handle)
998{
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +0530999 struct ath9k_htc_priv *priv = htc_handle->drv_priv;
Sujithfb9987d2010-03-17 14:25:25 +05301000 int ret;
1001
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +05301002 ret = ath9k_htc_wait_for_target(priv);
Sujithfb9987d2010-03-17 14:25:25 +05301003 if (ret)
1004 return ret;
1005
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +05301006 ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid,
Sujith Manoharan0b5ead92010-12-07 16:31:38 +05301007 priv->ah->hw_version.usbdev);
Oleksij Rempel1e51aca2013-12-12 15:30:36 +01001008 ath9k_configure_leds(priv);
1009
Sujithfb9987d2010-03-17 14:25:25 +05301010 return ret;
1011}
1012#endif
1013
1014static int __init ath9k_htc_init(void)
1015{
Rajkumar Manoharane5facc72011-04-15 15:42:24 +05301016 if (ath9k_hif_usb_init() < 0) {
Joe Perches516304b2012-03-18 17:30:52 -07001017 pr_err("No USB devices found, driver not installed\n");
Rajkumar Manoharane5facc72011-04-15 15:42:24 +05301018 return -ENODEV;
Sujithfb9987d2010-03-17 14:25:25 +05301019 }
1020
1021 return 0;
Sujithfb9987d2010-03-17 14:25:25 +05301022}
1023module_init(ath9k_htc_init);
1024
1025static void __exit ath9k_htc_exit(void)
1026{
1027 ath9k_hif_usb_exit();
Joe Perches516304b2012-03-18 17:30:52 -07001028 pr_info("Driver unloaded\n");
Sujithfb9987d2010-03-17 14:25:25 +05301029}
1030module_exit(ath9k_htc_exit);