htc_drv_init.c revision fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18df
1fb9987d0f748c983bb795a86f47522313f701a08Sujith/*
2fb9987d0f748c983bb795a86f47522313f701a08Sujith * Copyright (c) 2010 Atheros Communications Inc.
3fb9987d0f748c983bb795a86f47522313f701a08Sujith *
4fb9987d0f748c983bb795a86f47522313f701a08Sujith * Permission to use, copy, modify, and/or distribute this software for any
5fb9987d0f748c983bb795a86f47522313f701a08Sujith * purpose with or without fee is hereby granted, provided that the above
6fb9987d0f748c983bb795a86f47522313f701a08Sujith * copyright notice and this permission notice appear in all copies.
7fb9987d0f748c983bb795a86f47522313f701a08Sujith *
8fb9987d0f748c983bb795a86f47522313f701a08Sujith * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9fb9987d0f748c983bb795a86f47522313f701a08Sujith * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10fb9987d0f748c983bb795a86f47522313f701a08Sujith * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11fb9987d0f748c983bb795a86f47522313f701a08Sujith * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12fb9987d0f748c983bb795a86f47522313f701a08Sujith * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13fb9987d0f748c983bb795a86f47522313f701a08Sujith * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14fb9987d0f748c983bb795a86f47522313f701a08Sujith * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15fb9987d0f748c983bb795a86f47522313f701a08Sujith */
16fb9987d0f748c983bb795a86f47522313f701a08Sujith
17fb9987d0f748c983bb795a86f47522313f701a08Sujith#include "htc.h"
18fb9987d0f748c983bb795a86f47522313f701a08Sujith
19fb9987d0f748c983bb795a86f47522313f701a08SujithMODULE_AUTHOR("Atheros Communications");
20fb9987d0f748c983bb795a86f47522313f701a08SujithMODULE_LICENSE("Dual BSD/GPL");
21fb9987d0f748c983bb795a86f47522313f701a08SujithMODULE_DESCRIPTION("Atheros driver 802.11n HTC based wireless devices");
22fb9987d0f748c983bb795a86f47522313f701a08Sujith
23fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic unsigned int ath9k_debug = ATH_DBG_DEFAULT;
24fb9987d0f748c983bb795a86f47522313f701a08Sujithmodule_param_named(debug, ath9k_debug, uint, 0);
25fb9987d0f748c983bb795a86f47522313f701a08SujithMODULE_PARM_DESC(debug, "Debugging mask");
26fb9987d0f748c983bb795a86f47522313f701a08Sujith
27e1572c5eeca8ef87a250322364584458b2dadb35Sujithint htc_modparam_nohwcrypt;
28e1572c5eeca8ef87a250322364584458b2dadb35Sujithmodule_param_named(nohwcrypt, htc_modparam_nohwcrypt, int, 0444);
29fb9987d0f748c983bb795a86f47522313f701a08SujithMODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
30fb9987d0f748c983bb795a86f47522313f701a08Sujith
31fb9987d0f748c983bb795a86f47522313f701a08Sujith#define CHAN2G(_freq, _idx)  { \
32fb9987d0f748c983bb795a86f47522313f701a08Sujith	.center_freq = (_freq), \
33fb9987d0f748c983bb795a86f47522313f701a08Sujith	.hw_value = (_idx), \
34fb9987d0f748c983bb795a86f47522313f701a08Sujith	.max_power = 20, \
35fb9987d0f748c983bb795a86f47522313f701a08Sujith}
36fb9987d0f748c983bb795a86f47522313f701a08Sujith
37ea46e644e80bd4ac778964afd998df4f666486d4Sujith#define CHAN5G(_freq, _idx) { \
38ea46e644e80bd4ac778964afd998df4f666486d4Sujith	.band = IEEE80211_BAND_5GHZ, \
39ea46e644e80bd4ac778964afd998df4f666486d4Sujith	.center_freq = (_freq), \
40ea46e644e80bd4ac778964afd998df4f666486d4Sujith	.hw_value = (_idx), \
41ea46e644e80bd4ac778964afd998df4f666486d4Sujith	.max_power = 20, \
42ea46e644e80bd4ac778964afd998df4f666486d4Sujith}
43ea46e644e80bd4ac778964afd998df4f666486d4Sujith
4421cb987914cb5334af78378141efed77505ea987Vivek Natarajan#define ATH_HTC_BTCOEX_PRODUCT_ID "wb193"
4521cb987914cb5334af78378141efed77505ea987Vivek Natarajan
46fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic struct ieee80211_channel ath9k_2ghz_channels[] = {
47fb9987d0f748c983bb795a86f47522313f701a08Sujith	CHAN2G(2412, 0), /* Channel 1 */
48fb9987d0f748c983bb795a86f47522313f701a08Sujith	CHAN2G(2417, 1), /* Channel 2 */
49fb9987d0f748c983bb795a86f47522313f701a08Sujith	CHAN2G(2422, 2), /* Channel 3 */
50fb9987d0f748c983bb795a86f47522313f701a08Sujith	CHAN2G(2427, 3), /* Channel 4 */
51fb9987d0f748c983bb795a86f47522313f701a08Sujith	CHAN2G(2432, 4), /* Channel 5 */
52fb9987d0f748c983bb795a86f47522313f701a08Sujith	CHAN2G(2437, 5), /* Channel 6 */
53fb9987d0f748c983bb795a86f47522313f701a08Sujith	CHAN2G(2442, 6), /* Channel 7 */
54fb9987d0f748c983bb795a86f47522313f701a08Sujith	CHAN2G(2447, 7), /* Channel 8 */
55fb9987d0f748c983bb795a86f47522313f701a08Sujith	CHAN2G(2452, 8), /* Channel 9 */
56fb9987d0f748c983bb795a86f47522313f701a08Sujith	CHAN2G(2457, 9), /* Channel 10 */
57fb9987d0f748c983bb795a86f47522313f701a08Sujith	CHAN2G(2462, 10), /* Channel 11 */
58fb9987d0f748c983bb795a86f47522313f701a08Sujith	CHAN2G(2467, 11), /* Channel 12 */
59fb9987d0f748c983bb795a86f47522313f701a08Sujith	CHAN2G(2472, 12), /* Channel 13 */
60fb9987d0f748c983bb795a86f47522313f701a08Sujith	CHAN2G(2484, 13), /* Channel 14 */
61fb9987d0f748c983bb795a86f47522313f701a08Sujith};
62fb9987d0f748c983bb795a86f47522313f701a08Sujith
63ea46e644e80bd4ac778964afd998df4f666486d4Sujithstatic struct ieee80211_channel ath9k_5ghz_channels[] = {
64ea46e644e80bd4ac778964afd998df4f666486d4Sujith	/* _We_ call this UNII 1 */
65ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5180, 14), /* Channel 36 */
66ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5200, 15), /* Channel 40 */
67ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5220, 16), /* Channel 44 */
68ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5240, 17), /* Channel 48 */
69ea46e644e80bd4ac778964afd998df4f666486d4Sujith	/* _We_ call this UNII 2 */
70ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5260, 18), /* Channel 52 */
71ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5280, 19), /* Channel 56 */
72ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5300, 20), /* Channel 60 */
73ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5320, 21), /* Channel 64 */
74ea46e644e80bd4ac778964afd998df4f666486d4Sujith	/* _We_ call this "Middle band" */
75ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5500, 22), /* Channel 100 */
76ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5520, 23), /* Channel 104 */
77ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5540, 24), /* Channel 108 */
78ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5560, 25), /* Channel 112 */
79ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5580, 26), /* Channel 116 */
80ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5600, 27), /* Channel 120 */
81ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5620, 28), /* Channel 124 */
82ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5640, 29), /* Channel 128 */
83ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5660, 30), /* Channel 132 */
84ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5680, 31), /* Channel 136 */
85ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5700, 32), /* Channel 140 */
86ea46e644e80bd4ac778964afd998df4f666486d4Sujith	/* _We_ call this UNII 3 */
87ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5745, 33), /* Channel 149 */
88ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5765, 34), /* Channel 153 */
89ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5785, 35), /* Channel 157 */
90ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5805, 36), /* Channel 161 */
91ea46e644e80bd4ac778964afd998df4f666486d4Sujith	CHAN5G(5825, 37), /* Channel 165 */
92ea46e644e80bd4ac778964afd998df4f666486d4Sujith};
93ea46e644e80bd4ac778964afd998df4f666486d4Sujith
94fb9987d0f748c983bb795a86f47522313f701a08Sujith/* Atheros hardware rate code addition for short premble */
95fb9987d0f748c983bb795a86f47522313f701a08Sujith#define SHPCHECK(__hw_rate, __flags) \
96fb9987d0f748c983bb795a86f47522313f701a08Sujith	((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04) : 0)
97fb9987d0f748c983bb795a86f47522313f701a08Sujith
98fb9987d0f748c983bb795a86f47522313f701a08Sujith#define RATE(_bitrate, _hw_rate, _flags) {		\
99fb9987d0f748c983bb795a86f47522313f701a08Sujith	.bitrate	= (_bitrate),			\
100fb9987d0f748c983bb795a86f47522313f701a08Sujith	.flags		= (_flags),			\
101fb9987d0f748c983bb795a86f47522313f701a08Sujith	.hw_value	= (_hw_rate),			\
102fb9987d0f748c983bb795a86f47522313f701a08Sujith	.hw_value_short = (SHPCHECK(_hw_rate, _flags))	\
103fb9987d0f748c983bb795a86f47522313f701a08Sujith}
104fb9987d0f748c983bb795a86f47522313f701a08Sujith
105fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic struct ieee80211_rate ath9k_legacy_rates[] = {
106fb9987d0f748c983bb795a86f47522313f701a08Sujith	RATE(10, 0x1b, 0),
107fb9987d0f748c983bb795a86f47522313f701a08Sujith	RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp : 0x1e */
108fb9987d0f748c983bb795a86f47522313f701a08Sujith	RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp: 0x1d */
109fb9987d0f748c983bb795a86f47522313f701a08Sujith	RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), /* short: 0x1c */
110fb9987d0f748c983bb795a86f47522313f701a08Sujith	RATE(60, 0x0b, 0),
111fb9987d0f748c983bb795a86f47522313f701a08Sujith	RATE(90, 0x0f, 0),
112fb9987d0f748c983bb795a86f47522313f701a08Sujith	RATE(120, 0x0a, 0),
113fb9987d0f748c983bb795a86f47522313f701a08Sujith	RATE(180, 0x0e, 0),
114fb9987d0f748c983bb795a86f47522313f701a08Sujith	RATE(240, 0x09, 0),
115fb9987d0f748c983bb795a86f47522313f701a08Sujith	RATE(360, 0x0d, 0),
116fb9987d0f748c983bb795a86f47522313f701a08Sujith	RATE(480, 0x08, 0),
117fb9987d0f748c983bb795a86f47522313f701a08Sujith	RATE(540, 0x0c, 0),
118fb9987d0f748c983bb795a86f47522313f701a08Sujith};
119fb9987d0f748c983bb795a86f47522313f701a08Sujith
120fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
121fb9987d0f748c983bb795a86f47522313f701a08Sujith{
122fb9987d0f748c983bb795a86f47522313f701a08Sujith	int time_left;
123fb9987d0f748c983bb795a86f47522313f701a08Sujith
124d8c49ffb2e2a47b23fec7f469435e7b112e2e569Sujith.Manoharan@atheros.com	if (atomic_read(&priv->htc->tgt_ready) > 0) {
125d8c49ffb2e2a47b23fec7f469435e7b112e2e569Sujith.Manoharan@atheros.com		atomic_dec(&priv->htc->tgt_ready);
126d8c49ffb2e2a47b23fec7f469435e7b112e2e569Sujith.Manoharan@atheros.com		return 0;
127d8c49ffb2e2a47b23fec7f469435e7b112e2e569Sujith.Manoharan@atheros.com	}
128d8c49ffb2e2a47b23fec7f469435e7b112e2e569Sujith.Manoharan@atheros.com
129fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* Firmware can take up to 50ms to get ready, to be safe use 1 second */
130fb9987d0f748c983bb795a86f47522313f701a08Sujith	time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ);
131fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (!time_left) {
132fb9987d0f748c983bb795a86f47522313f701a08Sujith		dev_err(priv->dev, "ath9k_htc: Target is unresponsive\n");
133fb9987d0f748c983bb795a86f47522313f701a08Sujith		return -ETIMEDOUT;
134fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
135fb9987d0f748c983bb795a86f47522313f701a08Sujith
136d8c49ffb2e2a47b23fec7f469435e7b112e2e569Sujith.Manoharan@atheros.com	atomic_dec(&priv->htc->tgt_ready);
137d8c49ffb2e2a47b23fec7f469435e7b112e2e569Sujith.Manoharan@atheros.com
138fb9987d0f748c983bb795a86f47522313f701a08Sujith	return 0;
139fb9987d0f748c983bb795a86f47522313f701a08Sujith}
140fb9987d0f748c983bb795a86f47522313f701a08Sujith
141fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void ath9k_deinit_priv(struct ath9k_htc_priv *priv)
142fb9987d0f748c983bb795a86f47522313f701a08Sujith{
143e1572c5eeca8ef87a250322364584458b2dadb35Sujith	ath9k_htc_exit_debug(priv->ah);
144fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_hw_deinit(priv->ah);
145fb9987d0f748c983bb795a86f47522313f701a08Sujith	tasklet_kill(&priv->wmi_tasklet);
146fb9987d0f748c983bb795a86f47522313f701a08Sujith	tasklet_kill(&priv->rx_tasklet);
147fb9987d0f748c983bb795a86f47522313f701a08Sujith	tasklet_kill(&priv->tx_tasklet);
148fb9987d0f748c983bb795a86f47522313f701a08Sujith	kfree(priv->ah);
149fb9987d0f748c983bb795a86f47522313f701a08Sujith	priv->ah = NULL;
150fb9987d0f748c983bb795a86f47522313f701a08Sujith}
151fb9987d0f748c983bb795a86f47522313f701a08Sujith
152fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void ath9k_deinit_device(struct ath9k_htc_priv *priv)
153fb9987d0f748c983bb795a86f47522313f701a08Sujith{
154fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ieee80211_hw *hw = priv->hw;
155fb9987d0f748c983bb795a86f47522313f701a08Sujith
156fb9987d0f748c983bb795a86f47522313f701a08Sujith	wiphy_rfkill_stop_polling(hw->wiphy);
157fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_deinit_leds(priv);
158fb9987d0f748c983bb795a86f47522313f701a08Sujith	ieee80211_unregister_hw(hw);
159fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_rx_cleanup(priv);
160fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_tx_cleanup(priv);
161fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_deinit_priv(priv);
162fb9987d0f748c983bb795a86f47522313f701a08Sujith}
163fb9987d0f748c983bb795a86f47522313f701a08Sujith
164fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv,
165fb9987d0f748c983bb795a86f47522313f701a08Sujith					u16 service_id,
166fb9987d0f748c983bb795a86f47522313f701a08Sujith					void (*tx) (void *,
167fb9987d0f748c983bb795a86f47522313f701a08Sujith						    struct sk_buff *,
168fb9987d0f748c983bb795a86f47522313f701a08Sujith						    enum htc_endpoint_id,
169fb9987d0f748c983bb795a86f47522313f701a08Sujith						    bool txok),
170fb9987d0f748c983bb795a86f47522313f701a08Sujith					enum htc_endpoint_id *ep_id)
171fb9987d0f748c983bb795a86f47522313f701a08Sujith{
172fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct htc_service_connreq req;
173fb9987d0f748c983bb795a86f47522313f701a08Sujith
174fb9987d0f748c983bb795a86f47522313f701a08Sujith	memset(&req, 0, sizeof(struct htc_service_connreq));
175fb9987d0f748c983bb795a86f47522313f701a08Sujith
176fb9987d0f748c983bb795a86f47522313f701a08Sujith	req.service_id = service_id;
177fb9987d0f748c983bb795a86f47522313f701a08Sujith	req.ep_callbacks.priv = priv;
178fb9987d0f748c983bb795a86f47522313f701a08Sujith	req.ep_callbacks.rx = ath9k_htc_rxep;
179fb9987d0f748c983bb795a86f47522313f701a08Sujith	req.ep_callbacks.tx = tx;
180fb9987d0f748c983bb795a86f47522313f701a08Sujith
181fb9987d0f748c983bb795a86f47522313f701a08Sujith	return htc_connect_service(priv->htc, &req, ep_id);
182fb9987d0f748c983bb795a86f47522313f701a08Sujith}
183fb9987d0f748c983bb795a86f47522313f701a08Sujith
184fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharanstatic int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid,
185fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan				   u32 drv_info)
186fb9987d0f748c983bb795a86f47522313f701a08Sujith{
187fb9987d0f748c983bb795a86f47522313f701a08Sujith	int ret;
188fb9987d0f748c983bb795a86f47522313f701a08Sujith
189fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* WMI CMD*/
190fb9987d0f748c983bb795a86f47522313f701a08Sujith	ret = ath9k_wmi_connect(priv->htc, priv->wmi, &priv->wmi_cmd_ep);
191fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret)
192fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err;
193fb9987d0f748c983bb795a86f47522313f701a08Sujith
194fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* Beacon */
1959c6dda4e2dfea970a7105e3805f0195bc3079f2fSujith	ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, ath9k_htc_beaconep,
196fb9987d0f748c983bb795a86f47522313f701a08Sujith				    &priv->beacon_ep);
197fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret)
198fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err;
199fb9987d0f748c983bb795a86f47522313f701a08Sujith
200fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* CAB */
201fb9987d0f748c983bb795a86f47522313f701a08Sujith	ret = ath9k_htc_connect_svc(priv, WMI_CAB_SVC, ath9k_htc_txep,
202fb9987d0f748c983bb795a86f47522313f701a08Sujith				    &priv->cab_ep);
203fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret)
204fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err;
205fb9987d0f748c983bb795a86f47522313f701a08Sujith
206fb9987d0f748c983bb795a86f47522313f701a08Sujith
207fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* UAPSD */
208fb9987d0f748c983bb795a86f47522313f701a08Sujith	ret = ath9k_htc_connect_svc(priv, WMI_UAPSD_SVC, ath9k_htc_txep,
209fb9987d0f748c983bb795a86f47522313f701a08Sujith				    &priv->uapsd_ep);
210fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret)
211fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err;
212fb9987d0f748c983bb795a86f47522313f701a08Sujith
213fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* MGMT */
214fb9987d0f748c983bb795a86f47522313f701a08Sujith	ret = ath9k_htc_connect_svc(priv, WMI_MGMT_SVC, ath9k_htc_txep,
215fb9987d0f748c983bb795a86f47522313f701a08Sujith				    &priv->mgmt_ep);
216fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret)
217fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err;
218fb9987d0f748c983bb795a86f47522313f701a08Sujith
219fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* DATA BE */
220fb9987d0f748c983bb795a86f47522313f701a08Sujith	ret = ath9k_htc_connect_svc(priv, WMI_DATA_BE_SVC, ath9k_htc_txep,
221fb9987d0f748c983bb795a86f47522313f701a08Sujith				    &priv->data_be_ep);
222fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret)
223fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err;
224fb9987d0f748c983bb795a86f47522313f701a08Sujith
225fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* DATA BK */
226fb9987d0f748c983bb795a86f47522313f701a08Sujith	ret = ath9k_htc_connect_svc(priv, WMI_DATA_BK_SVC, ath9k_htc_txep,
227fb9987d0f748c983bb795a86f47522313f701a08Sujith				    &priv->data_bk_ep);
228fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret)
229fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err;
230fb9987d0f748c983bb795a86f47522313f701a08Sujith
231fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* DATA VI */
232fb9987d0f748c983bb795a86f47522313f701a08Sujith	ret = ath9k_htc_connect_svc(priv, WMI_DATA_VI_SVC, ath9k_htc_txep,
233fb9987d0f748c983bb795a86f47522313f701a08Sujith				    &priv->data_vi_ep);
234fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret)
235fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err;
236fb9987d0f748c983bb795a86f47522313f701a08Sujith
237fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* DATA VO */
238fb9987d0f748c983bb795a86f47522313f701a08Sujith	ret = ath9k_htc_connect_svc(priv, WMI_DATA_VO_SVC, ath9k_htc_txep,
239fb9987d0f748c983bb795a86f47522313f701a08Sujith				    &priv->data_vo_ep);
240fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret)
241fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err;
242fb9987d0f748c983bb795a86f47522313f701a08Sujith
2436267dc709c6ef1c0926e18ff2859238992dea658Sujith	/*
2446267dc709c6ef1c0926e18ff2859238992dea658Sujith	 * Setup required credits before initializing HTC.
2456267dc709c6ef1c0926e18ff2859238992dea658Sujith	 * This is a bit hacky, but, since queuing is done in
2466267dc709c6ef1c0926e18ff2859238992dea658Sujith	 * the HIF layer, shouldn't matter much.
2476267dc709c6ef1c0926e18ff2859238992dea658Sujith	 */
2486267dc709c6ef1c0926e18ff2859238992dea658Sujith
249fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan	if (drv_info & AR7010_DEVICE)
2506267dc709c6ef1c0926e18ff2859238992dea658Sujith		priv->htc->credits = 45;
251fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan	else
2524e63f768c3b85ae2b3ea6251231fd5cc46ec598dSujith		priv->htc->credits = 33;
2536267dc709c6ef1c0926e18ff2859238992dea658Sujith
254fb9987d0f748c983bb795a86f47522313f701a08Sujith	ret = htc_init(priv->htc);
255fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret)
256fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err;
257fb9987d0f748c983bb795a86f47522313f701a08Sujith
2586267dc709c6ef1c0926e18ff2859238992dea658Sujith	dev_info(priv->dev, "ath9k_htc: HTC initialized with %d credits\n",
2596267dc709c6ef1c0926e18ff2859238992dea658Sujith		 priv->htc->credits);
2606267dc709c6ef1c0926e18ff2859238992dea658Sujith
261fb9987d0f748c983bb795a86f47522313f701a08Sujith	return 0;
262fb9987d0f748c983bb795a86f47522313f701a08Sujith
263fb9987d0f748c983bb795a86f47522313f701a08Sujitherr:
264fb9987d0f748c983bb795a86f47522313f701a08Sujith	dev_err(priv->dev, "ath9k_htc: Unable to initialize HTC services\n");
265fb9987d0f748c983bb795a86f47522313f701a08Sujith	return ret;
266fb9987d0f748c983bb795a86f47522313f701a08Sujith}
267fb9987d0f748c983bb795a86f47522313f701a08Sujith
268fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic int ath9k_reg_notifier(struct wiphy *wiphy,
269fb9987d0f748c983bb795a86f47522313f701a08Sujith			      struct regulatory_request *request)
270fb9987d0f748c983bb795a86f47522313f701a08Sujith{
271fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
272fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath9k_htc_priv *priv = hw->priv;
273fb9987d0f748c983bb795a86f47522313f701a08Sujith
274fb9987d0f748c983bb795a86f47522313f701a08Sujith	return ath_reg_notifier_apply(wiphy, request,
275fb9987d0f748c983bb795a86f47522313f701a08Sujith				      ath9k_hw_regulatory(priv->ah));
276fb9987d0f748c983bb795a86f47522313f701a08Sujith}
277fb9987d0f748c983bb795a86f47522313f701a08Sujith
2784a22fe108e62367c10c3abeb469d6972ba3299f5Sujithstatic unsigned int ath9k_regread(void *hw_priv, u32 reg_offset)
279fb9987d0f748c983bb795a86f47522313f701a08Sujith{
280fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath_hw *ah = (struct ath_hw *) hw_priv;
281fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath_common *common = ath9k_hw_common(ah);
282fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
283fb9987d0f748c983bb795a86f47522313f701a08Sujith	__be32 val, reg = cpu_to_be32(reg_offset);
284fb9987d0f748c983bb795a86f47522313f701a08Sujith	int r;
285fb9987d0f748c983bb795a86f47522313f701a08Sujith
286fb9987d0f748c983bb795a86f47522313f701a08Sujith	r = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
287fb9987d0f748c983bb795a86f47522313f701a08Sujith			  (u8 *) &reg, sizeof(reg),
288fb9987d0f748c983bb795a86f47522313f701a08Sujith			  (u8 *) &val, sizeof(val),
289fb9987d0f748c983bb795a86f47522313f701a08Sujith			  100);
290fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (unlikely(r)) {
291fb9987d0f748c983bb795a86f47522313f701a08Sujith		ath_print(common, ATH_DBG_WMI,
292fb9987d0f748c983bb795a86f47522313f701a08Sujith			  "REGISTER READ FAILED: (0x%04x, %d)\n",
293fb9987d0f748c983bb795a86f47522313f701a08Sujith			   reg_offset, r);
294fb9987d0f748c983bb795a86f47522313f701a08Sujith		return -EIO;
295fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
296fb9987d0f748c983bb795a86f47522313f701a08Sujith
297fb9987d0f748c983bb795a86f47522313f701a08Sujith	return be32_to_cpu(val);
298fb9987d0f748c983bb795a86f47522313f701a08Sujith}
299fb9987d0f748c983bb795a86f47522313f701a08Sujith
3004a22fe108e62367c10c3abeb469d6972ba3299f5Sujithstatic void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)
301fb9987d0f748c983bb795a86f47522313f701a08Sujith{
302fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath_hw *ah = (struct ath_hw *) hw_priv;
303fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath_common *common = ath9k_hw_common(ah);
304fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
30507b2fa5a2368accf0fe6cb16e7eca6d1150554edJoe Perches	const __be32 buf[2] = {
306fb9987d0f748c983bb795a86f47522313f701a08Sujith		cpu_to_be32(reg_offset),
307fb9987d0f748c983bb795a86f47522313f701a08Sujith		cpu_to_be32(val),
308fb9987d0f748c983bb795a86f47522313f701a08Sujith	};
309fb9987d0f748c983bb795a86f47522313f701a08Sujith	int r;
310fb9987d0f748c983bb795a86f47522313f701a08Sujith
311fb9987d0f748c983bb795a86f47522313f701a08Sujith	r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
312fb9987d0f748c983bb795a86f47522313f701a08Sujith			  (u8 *) &buf, sizeof(buf),
313fb9987d0f748c983bb795a86f47522313f701a08Sujith			  (u8 *) &val, sizeof(val),
314fb9987d0f748c983bb795a86f47522313f701a08Sujith			  100);
315fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (unlikely(r)) {
316fb9987d0f748c983bb795a86f47522313f701a08Sujith		ath_print(common, ATH_DBG_WMI,
317fb9987d0f748c983bb795a86f47522313f701a08Sujith			  "REGISTER WRITE FAILED:(0x%04x, %d)\n",
318fb9987d0f748c983bb795a86f47522313f701a08Sujith			  reg_offset, r);
319fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
320fb9987d0f748c983bb795a86f47522313f701a08Sujith}
321fb9987d0f748c983bb795a86f47522313f701a08Sujith
3224a22fe108e62367c10c3abeb469d6972ba3299f5Sujithstatic void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset)
3234a22fe108e62367c10c3abeb469d6972ba3299f5Sujith{
3244a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3254a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	struct ath_common *common = ath9k_hw_common(ah);
3264a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3274a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	u32 rsp_status;
3284a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	int r;
3294a22fe108e62367c10c3abeb469d6972ba3299f5Sujith
3304a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	mutex_lock(&priv->wmi->multi_write_mutex);
3314a22fe108e62367c10c3abeb469d6972ba3299f5Sujith
3324a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	/* Store the register/value */
3334a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	priv->wmi->multi_write[priv->wmi->multi_write_idx].reg =
3344a22fe108e62367c10c3abeb469d6972ba3299f5Sujith		cpu_to_be32(reg_offset);
3354a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	priv->wmi->multi_write[priv->wmi->multi_write_idx].val =
3364a22fe108e62367c10c3abeb469d6972ba3299f5Sujith		cpu_to_be32(val);
3374a22fe108e62367c10c3abeb469d6972ba3299f5Sujith
3384a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	priv->wmi->multi_write_idx++;
3394a22fe108e62367c10c3abeb469d6972ba3299f5Sujith
3404a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	/* If the buffer is full, send it out. */
3414a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	if (priv->wmi->multi_write_idx == MAX_CMD_NUMBER) {
3424a22fe108e62367c10c3abeb469d6972ba3299f5Sujith		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
3434a22fe108e62367c10c3abeb469d6972ba3299f5Sujith			  (u8 *) &priv->wmi->multi_write,
3444a22fe108e62367c10c3abeb469d6972ba3299f5Sujith			  sizeof(struct register_write) * priv->wmi->multi_write_idx,
3454a22fe108e62367c10c3abeb469d6972ba3299f5Sujith			  (u8 *) &rsp_status, sizeof(rsp_status),
3464a22fe108e62367c10c3abeb469d6972ba3299f5Sujith			  100);
3474a22fe108e62367c10c3abeb469d6972ba3299f5Sujith		if (unlikely(r)) {
3484a22fe108e62367c10c3abeb469d6972ba3299f5Sujith			ath_print(common, ATH_DBG_WMI,
3494a22fe108e62367c10c3abeb469d6972ba3299f5Sujith				  "REGISTER WRITE FAILED, multi len: %d\n",
3504a22fe108e62367c10c3abeb469d6972ba3299f5Sujith				  priv->wmi->multi_write_idx);
3514a22fe108e62367c10c3abeb469d6972ba3299f5Sujith		}
3524a22fe108e62367c10c3abeb469d6972ba3299f5Sujith		priv->wmi->multi_write_idx = 0;
3534a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	}
3544a22fe108e62367c10c3abeb469d6972ba3299f5Sujith
3554a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	mutex_unlock(&priv->wmi->multi_write_mutex);
3564a22fe108e62367c10c3abeb469d6972ba3299f5Sujith}
3574a22fe108e62367c10c3abeb469d6972ba3299f5Sujith
3584a22fe108e62367c10c3abeb469d6972ba3299f5Sujithstatic void ath9k_regwrite(void *hw_priv, u32 val, u32 reg_offset)
3594a22fe108e62367c10c3abeb469d6972ba3299f5Sujith{
3604a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3614a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	struct ath_common *common = ath9k_hw_common(ah);
3624a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3634a22fe108e62367c10c3abeb469d6972ba3299f5Sujith
3644a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	if (atomic_read(&priv->wmi->mwrite_cnt))
3654a22fe108e62367c10c3abeb469d6972ba3299f5Sujith		ath9k_regwrite_buffer(hw_priv, val, reg_offset);
3664a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	else
3674a22fe108e62367c10c3abeb469d6972ba3299f5Sujith		ath9k_regwrite_single(hw_priv, val, reg_offset);
3684a22fe108e62367c10c3abeb469d6972ba3299f5Sujith}
3694a22fe108e62367c10c3abeb469d6972ba3299f5Sujith
3704a22fe108e62367c10c3abeb469d6972ba3299f5Sujithstatic void ath9k_enable_regwrite_buffer(void *hw_priv)
3714a22fe108e62367c10c3abeb469d6972ba3299f5Sujith{
3724a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3734a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	struct ath_common *common = ath9k_hw_common(ah);
3744a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3754a22fe108e62367c10c3abeb469d6972ba3299f5Sujith
3764a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	atomic_inc(&priv->wmi->mwrite_cnt);
3774a22fe108e62367c10c3abeb469d6972ba3299f5Sujith}
3784a22fe108e62367c10c3abeb469d6972ba3299f5Sujith
3794a22fe108e62367c10c3abeb469d6972ba3299f5Sujithstatic void ath9k_regwrite_flush(void *hw_priv)
3804a22fe108e62367c10c3abeb469d6972ba3299f5Sujith{
3814a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3824a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	struct ath_common *common = ath9k_hw_common(ah);
3834a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3844a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	u32 rsp_status;
3854a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	int r;
3864a22fe108e62367c10c3abeb469d6972ba3299f5Sujith
387435c1610f46dc4d86a6633adb037b18109e6ffdcFelix Fietkau	atomic_dec(&priv->wmi->mwrite_cnt);
388435c1610f46dc4d86a6633adb037b18109e6ffdcFelix Fietkau
3894a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	mutex_lock(&priv->wmi->multi_write_mutex);
3904a22fe108e62367c10c3abeb469d6972ba3299f5Sujith
3914a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	if (priv->wmi->multi_write_idx) {
3924a22fe108e62367c10c3abeb469d6972ba3299f5Sujith		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
3934a22fe108e62367c10c3abeb469d6972ba3299f5Sujith			  (u8 *) &priv->wmi->multi_write,
3944a22fe108e62367c10c3abeb469d6972ba3299f5Sujith			  sizeof(struct register_write) * priv->wmi->multi_write_idx,
3954a22fe108e62367c10c3abeb469d6972ba3299f5Sujith			  (u8 *) &rsp_status, sizeof(rsp_status),
3964a22fe108e62367c10c3abeb469d6972ba3299f5Sujith			  100);
3974a22fe108e62367c10c3abeb469d6972ba3299f5Sujith		if (unlikely(r)) {
3984a22fe108e62367c10c3abeb469d6972ba3299f5Sujith			ath_print(common, ATH_DBG_WMI,
3994a22fe108e62367c10c3abeb469d6972ba3299f5Sujith				  "REGISTER WRITE FAILED, multi len: %d\n",
4004a22fe108e62367c10c3abeb469d6972ba3299f5Sujith				  priv->wmi->multi_write_idx);
4014a22fe108e62367c10c3abeb469d6972ba3299f5Sujith		}
4024a22fe108e62367c10c3abeb469d6972ba3299f5Sujith		priv->wmi->multi_write_idx = 0;
4034a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	}
4044a22fe108e62367c10c3abeb469d6972ba3299f5Sujith
4054a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	mutex_unlock(&priv->wmi->multi_write_mutex);
4064a22fe108e62367c10c3abeb469d6972ba3299f5Sujith}
4074a22fe108e62367c10c3abeb469d6972ba3299f5Sujith
408fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic const struct ath_ops ath9k_common_ops = {
4094a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	.read = ath9k_regread,
4104a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	.write = ath9k_regwrite,
4114a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	.enable_write_buffer = ath9k_enable_regwrite_buffer,
4124a22fe108e62367c10c3abeb469d6972ba3299f5Sujith	.write_flush = ath9k_regwrite_flush,
413fb9987d0f748c983bb795a86f47522313f701a08Sujith};
414fb9987d0f748c983bb795a86f47522313f701a08Sujith
415fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void ath_usb_read_cachesize(struct ath_common *common, int *csz)
416fb9987d0f748c983bb795a86f47522313f701a08Sujith{
417fb9987d0f748c983bb795a86f47522313f701a08Sujith	*csz = L1_CACHE_BYTES >> 2;
418fb9987d0f748c983bb795a86f47522313f701a08Sujith}
419fb9987d0f748c983bb795a86f47522313f701a08Sujith
420fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
421fb9987d0f748c983bb795a86f47522313f701a08Sujith{
422fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath_hw *ah = (struct ath_hw *) common->ah;
423fb9987d0f748c983bb795a86f47522313f701a08Sujith
424fb9987d0f748c983bb795a86f47522313f701a08Sujith	(void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
425fb9987d0f748c983bb795a86f47522313f701a08Sujith
426fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (!ath9k_hw_wait(ah,
427fb9987d0f748c983bb795a86f47522313f701a08Sujith			   AR_EEPROM_STATUS_DATA,
428fb9987d0f748c983bb795a86f47522313f701a08Sujith			   AR_EEPROM_STATUS_DATA_BUSY |
429fb9987d0f748c983bb795a86f47522313f701a08Sujith			   AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
430fb9987d0f748c983bb795a86f47522313f701a08Sujith			   AH_WAIT_TIMEOUT))
431fb9987d0f748c983bb795a86f47522313f701a08Sujith		return false;
432fb9987d0f748c983bb795a86f47522313f701a08Sujith
433fb9987d0f748c983bb795a86f47522313f701a08Sujith	*data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
434fb9987d0f748c983bb795a86f47522313f701a08Sujith		   AR_EEPROM_STATUS_DATA_VAL);
435fb9987d0f748c983bb795a86f47522313f701a08Sujith
436fb9987d0f748c983bb795a86f47522313f701a08Sujith	return true;
437fb9987d0f748c983bb795a86f47522313f701a08Sujith}
438fb9987d0f748c983bb795a86f47522313f701a08Sujith
439fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic const struct ath_bus_ops ath9k_usb_bus_ops = {
440497ad9adf44013dc9054f80c627acc44d4c90d37Sujith	.ath_bus_type = ATH_USB,
441fb9987d0f748c983bb795a86f47522313f701a08Sujith	.read_cachesize = ath_usb_read_cachesize,
442fb9987d0f748c983bb795a86f47522313f701a08Sujith	.eeprom_read = ath_usb_eeprom_read,
443fb9987d0f748c983bb795a86f47522313f701a08Sujith};
444fb9987d0f748c983bb795a86f47522313f701a08Sujith
445fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void setup_ht_cap(struct ath9k_htc_priv *priv,
446fb9987d0f748c983bb795a86f47522313f701a08Sujith			 struct ieee80211_sta_ht_cap *ht_info)
447fb9987d0f748c983bb795a86f47522313f701a08Sujith{
4486debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith	struct ath_common *common = ath9k_hw_common(priv->ah);
4496debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith	u8 tx_streams, rx_streams;
4506debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith	int i;
4516debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith
452fb9987d0f748c983bb795a86f47522313f701a08Sujith	ht_info->ht_supported = true;
453fb9987d0f748c983bb795a86f47522313f701a08Sujith	ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
454fb9987d0f748c983bb795a86f47522313f701a08Sujith		       IEEE80211_HT_CAP_SM_PS |
455fb9987d0f748c983bb795a86f47522313f701a08Sujith		       IEEE80211_HT_CAP_SGI_40 |
456fb9987d0f748c983bb795a86f47522313f701a08Sujith		       IEEE80211_HT_CAP_DSSSCCK40;
457fb9987d0f748c983bb795a86f47522313f701a08Sujith
458b4dec5e8f5c02f75d8c08dd377193f73b553bfe2Sujith	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
459b4dec5e8f5c02f75d8c08dd377193f73b553bfe2Sujith		ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
460b4dec5e8f5c02f75d8c08dd377193f73b553bfe2Sujith
46117525f96aeeed156bd4a6dee21816100f77b0c71Sujith	ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
46217525f96aeeed156bd4a6dee21816100f77b0c71Sujith
463fb9987d0f748c983bb795a86f47522313f701a08Sujith	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
464fb9987d0f748c983bb795a86f47522313f701a08Sujith	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
465fb9987d0f748c983bb795a86f47522313f701a08Sujith
466fb9987d0f748c983bb795a86f47522313f701a08Sujith	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
4676debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith
4686debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith	/* ath9k_htc supports only 1 or 2 stream devices */
4696debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith	tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2);
4706debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith	rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2);
4716debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith
4726debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith	ath_print(common, ATH_DBG_CONFIG,
4736debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith		  "TX streams %d, RX streams: %d\n",
4746debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith		  tx_streams, rx_streams);
4756debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith
4766debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith	if (tx_streams != rx_streams) {
4776debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
4786debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith		ht_info->mcs.tx_params |= ((tx_streams - 1) <<
4796debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith					   IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
4806debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith	}
4816debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith
4826debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith	for (i = 0; i < rx_streams; i++)
4836debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith		ht_info->mcs.rx_mask[i] = 0xff;
4846debecad452d3bbe5affc0a21bc0bb452f867cd8Sujith
485fb9987d0f748c983bb795a86f47522313f701a08Sujith	ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
486fb9987d0f748c983bb795a86f47522313f701a08Sujith}
487fb9987d0f748c983bb795a86f47522313f701a08Sujith
488fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic int ath9k_init_queues(struct ath9k_htc_priv *priv)
489fb9987d0f748c983bb795a86f47522313f701a08Sujith{
490fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath_common *common = ath9k_hw_common(priv->ah);
491fb9987d0f748c983bb795a86f47522313f701a08Sujith	int i;
492fb9987d0f748c983bb795a86f47522313f701a08Sujith
493fb9987d0f748c983bb795a86f47522313f701a08Sujith	for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++)
494fb9987d0f748c983bb795a86f47522313f701a08Sujith		priv->hwq_map[i] = -1;
495fb9987d0f748c983bb795a86f47522313f701a08Sujith
496ca74b83b66dbd289a395c6243695d746c76676ccSujith	priv->beaconq = ath9k_hw_beaconq_setup(priv->ah);
497ca74b83b66dbd289a395c6243695d746c76676ccSujith	if (priv->beaconq == -1) {
498ca74b83b66dbd289a395c6243695d746c76676ccSujith		ath_print(common, ATH_DBG_FATAL,
499ca74b83b66dbd289a395c6243695d746c76676ccSujith			  "Unable to setup BEACON xmit queue\n");
500ca74b83b66dbd289a395c6243695d746c76676ccSujith		goto err;
501ca74b83b66dbd289a395c6243695d746c76676ccSujith	}
502ca74b83b66dbd289a395c6243695d746c76676ccSujith
503ca74b83b66dbd289a395c6243695d746c76676ccSujith	priv->cabq = ath9k_htc_cabq_setup(priv);
504ca74b83b66dbd289a395c6243695d746c76676ccSujith	if (priv->cabq == -1) {
505ca74b83b66dbd289a395c6243695d746c76676ccSujith		ath_print(common, ATH_DBG_FATAL,
506ca74b83b66dbd289a395c6243695d746c76676ccSujith			  "Unable to setup CAB xmit queue\n");
507ca74b83b66dbd289a395c6243695d746c76676ccSujith		goto err;
508ca74b83b66dbd289a395c6243695d746c76676ccSujith	}
509ca74b83b66dbd289a395c6243695d746c76676ccSujith
510e8c35a77e3408171852bde4914b650cf5b83e0d1Felix Fietkau	if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) {
511fb9987d0f748c983bb795a86f47522313f701a08Sujith		ath_print(common, ATH_DBG_FATAL,
512fb9987d0f748c983bb795a86f47522313f701a08Sujith			  "Unable to setup xmit queue for BE traffic\n");
513fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err;
514fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
515fb9987d0f748c983bb795a86f47522313f701a08Sujith
516e8c35a77e3408171852bde4914b650cf5b83e0d1Felix Fietkau	if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) {
517fb9987d0f748c983bb795a86f47522313f701a08Sujith		ath_print(common, ATH_DBG_FATAL,
518fb9987d0f748c983bb795a86f47522313f701a08Sujith			  "Unable to setup xmit queue for BK traffic\n");
519fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err;
520fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
521e8c35a77e3408171852bde4914b650cf5b83e0d1Felix Fietkau	if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) {
522fb9987d0f748c983bb795a86f47522313f701a08Sujith		ath_print(common, ATH_DBG_FATAL,
523fb9987d0f748c983bb795a86f47522313f701a08Sujith			  "Unable to setup xmit queue for VI traffic\n");
524fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err;
525fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
526e8c35a77e3408171852bde4914b650cf5b83e0d1Felix Fietkau	if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) {
527fb9987d0f748c983bb795a86f47522313f701a08Sujith		ath_print(common, ATH_DBG_FATAL,
528fb9987d0f748c983bb795a86f47522313f701a08Sujith			  "Unable to setup xmit queue for VO traffic\n");
529fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err;
530fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
531fb9987d0f748c983bb795a86f47522313f701a08Sujith
532fb9987d0f748c983bb795a86f47522313f701a08Sujith	return 0;
533fb9987d0f748c983bb795a86f47522313f701a08Sujith
534fb9987d0f748c983bb795a86f47522313f701a08Sujitherr:
535fb9987d0f748c983bb795a86f47522313f701a08Sujith	return -EINVAL;
536fb9987d0f748c983bb795a86f47522313f701a08Sujith}
537fb9987d0f748c983bb795a86f47522313f701a08Sujith
538fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void ath9k_init_crypto(struct ath9k_htc_priv *priv)
539fb9987d0f748c983bb795a86f47522313f701a08Sujith{
540fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath_common *common = ath9k_hw_common(priv->ah);
541fb9987d0f748c983bb795a86f47522313f701a08Sujith	int i = 0;
542fb9987d0f748c983bb795a86f47522313f701a08Sujith
543fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* Get the hardware key cache size. */
544fb9987d0f748c983bb795a86f47522313f701a08Sujith	common->keymax = priv->ah->caps.keycache_size;
545fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (common->keymax > ATH_KEYMAX) {
546fb9987d0f748c983bb795a86f47522313f701a08Sujith		ath_print(common, ATH_DBG_ANY,
547fb9987d0f748c983bb795a86f47522313f701a08Sujith			  "Warning, using only %u entries in %u key cache\n",
548fb9987d0f748c983bb795a86f47522313f701a08Sujith			  ATH_KEYMAX, common->keymax);
549fb9987d0f748c983bb795a86f47522313f701a08Sujith		common->keymax = ATH_KEYMAX;
550fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
551fb9987d0f748c983bb795a86f47522313f701a08Sujith
552e2b626248b0799bd14be40ce290c6681a8419512Rajkumar Manoharan	if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
553e2b626248b0799bd14be40ce290c6681a8419512Rajkumar Manoharan		common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
554e2b626248b0799bd14be40ce290c6681a8419512Rajkumar Manoharan
555fb9987d0f748c983bb795a86f47522313f701a08Sujith	/*
556fb9987d0f748c983bb795a86f47522313f701a08Sujith	 * Reset the key cache since some parts do not
557fb9987d0f748c983bb795a86f47522313f701a08Sujith	 * reset the contents on initial power up.
558fb9987d0f748c983bb795a86f47522313f701a08Sujith	 */
559fb9987d0f748c983bb795a86f47522313f701a08Sujith	for (i = 0; i < common->keymax; i++)
560040e539e8e8d5585e1c3d7d15fa7215d3a691258Bruno Randolf		ath_hw_keyreset(common, (u16) i);
561fb9987d0f748c983bb795a86f47522313f701a08Sujith}
562fb9987d0f748c983bb795a86f47522313f701a08Sujith
563fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
564fb9987d0f748c983bb795a86f47522313f701a08Sujith{
565d4659912b557e9f68c0ad8be14e2cafd3210dd16Felix Fietkau	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
566fb9987d0f748c983bb795a86f47522313f701a08Sujith		priv->sbands[IEEE80211_BAND_2GHZ].channels =
567fb9987d0f748c983bb795a86f47522313f701a08Sujith			ath9k_2ghz_channels;
568fb9987d0f748c983bb795a86f47522313f701a08Sujith		priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
569fb9987d0f748c983bb795a86f47522313f701a08Sujith		priv->sbands[IEEE80211_BAND_2GHZ].n_channels =
570fb9987d0f748c983bb795a86f47522313f701a08Sujith			ARRAY_SIZE(ath9k_2ghz_channels);
571fb9987d0f748c983bb795a86f47522313f701a08Sujith		priv->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
572fb9987d0f748c983bb795a86f47522313f701a08Sujith		priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
573fb9987d0f748c983bb795a86f47522313f701a08Sujith			ARRAY_SIZE(ath9k_legacy_rates);
574fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
575ea46e644e80bd4ac778964afd998df4f666486d4Sujith
576d4659912b557e9f68c0ad8be14e2cafd3210dd16Felix Fietkau	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
577ea46e644e80bd4ac778964afd998df4f666486d4Sujith		priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels;
578ea46e644e80bd4ac778964afd998df4f666486d4Sujith		priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
579ea46e644e80bd4ac778964afd998df4f666486d4Sujith		priv->sbands[IEEE80211_BAND_5GHZ].n_channels =
580ea46e644e80bd4ac778964afd998df4f666486d4Sujith			ARRAY_SIZE(ath9k_5ghz_channels);
581ea46e644e80bd4ac778964afd998df4f666486d4Sujith		priv->sbands[IEEE80211_BAND_5GHZ].bitrates =
582ea46e644e80bd4ac778964afd998df4f666486d4Sujith			ath9k_legacy_rates + 4;
583ea46e644e80bd4ac778964afd998df4f666486d4Sujith		priv->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
584ea46e644e80bd4ac778964afd998df4f666486d4Sujith			ARRAY_SIZE(ath9k_legacy_rates) - 4;
585ea46e644e80bd4ac778964afd998df4f666486d4Sujith	}
586fb9987d0f748c983bb795a86f47522313f701a08Sujith}
587fb9987d0f748c983bb795a86f47522313f701a08Sujith
588fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void ath9k_init_misc(struct ath9k_htc_priv *priv)
589fb9987d0f748c983bb795a86f47522313f701a08Sujith{
590fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath_common *common = ath9k_hw_common(priv->ah);
591fb9987d0f748c983bb795a86f47522313f701a08Sujith
592fb9987d0f748c983bb795a86f47522313f701a08Sujith	common->tx_chainmask = priv->ah->caps.tx_chainmask;
593fb9987d0f748c983bb795a86f47522313f701a08Sujith	common->rx_chainmask = priv->ah->caps.rx_chainmask;
594fb9987d0f748c983bb795a86f47522313f701a08Sujith
595364734fafbba0c3133e482db78149b9a823ae7a5Felix Fietkau	memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
596fb9987d0f748c983bb795a86f47522313f701a08Sujith
5979f01a84e81d10e38daa504348217895fe414a24bSujith	priv->ah->opmode = NL80211_IFTYPE_STATION;
598fb9987d0f748c983bb795a86f47522313f701a08Sujith}
599fb9987d0f748c983bb795a86f47522313f701a08Sujith
60021cb987914cb5334af78378141efed77505ea987Vivek Natarajanstatic void ath9k_init_btcoex(struct ath9k_htc_priv *priv)
60121cb987914cb5334af78378141efed77505ea987Vivek Natarajan{
60221cb987914cb5334af78378141efed77505ea987Vivek Natarajan	int qnum;
60321cb987914cb5334af78378141efed77505ea987Vivek Natarajan
60421cb987914cb5334af78378141efed77505ea987Vivek Natarajan	switch (priv->ah->btcoex_hw.scheme) {
60521cb987914cb5334af78378141efed77505ea987Vivek Natarajan	case ATH_BTCOEX_CFG_NONE:
60621cb987914cb5334af78378141efed77505ea987Vivek Natarajan		break;
60721cb987914cb5334af78378141efed77505ea987Vivek Natarajan	case ATH_BTCOEX_CFG_3WIRE:
60821cb987914cb5334af78378141efed77505ea987Vivek Natarajan		priv->ah->btcoex_hw.btactive_gpio = 7;
60921cb987914cb5334af78378141efed77505ea987Vivek Natarajan		priv->ah->btcoex_hw.btpriority_gpio = 6;
61021cb987914cb5334af78378141efed77505ea987Vivek Natarajan		priv->ah->btcoex_hw.wlanactive_gpio = 8;
61121cb987914cb5334af78378141efed77505ea987Vivek Natarajan		priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
61221cb987914cb5334af78378141efed77505ea987Vivek Natarajan		ath9k_hw_btcoex_init_3wire(priv->ah);
61321cb987914cb5334af78378141efed77505ea987Vivek Natarajan		ath_htc_init_btcoex_work(priv);
61421cb987914cb5334af78378141efed77505ea987Vivek Natarajan		qnum = priv->hwq_map[WME_AC_BE];
61521cb987914cb5334af78378141efed77505ea987Vivek Natarajan		ath9k_hw_init_btcoex_hw(priv->ah, qnum);
61621cb987914cb5334af78378141efed77505ea987Vivek Natarajan		break;
61721cb987914cb5334af78378141efed77505ea987Vivek Natarajan	default:
61821cb987914cb5334af78378141efed77505ea987Vivek Natarajan		WARN_ON(1);
61921cb987914cb5334af78378141efed77505ea987Vivek Natarajan		break;
62021cb987914cb5334af78378141efed77505ea987Vivek Natarajan	}
62121cb987914cb5334af78378141efed77505ea987Vivek Natarajan}
62221cb987914cb5334af78378141efed77505ea987Vivek Natarajan
62321cb987914cb5334af78378141efed77505ea987Vivek Natarajanstatic int ath9k_init_priv(struct ath9k_htc_priv *priv,
624fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan			   u16 devid, char *product,
625fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan			   u32 drv_info)
626fb9987d0f748c983bb795a86f47522313f701a08Sujith{
627fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath_hw *ah = NULL;
628fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath_common *common;
629fb9987d0f748c983bb795a86f47522313f701a08Sujith	int ret = 0, csz = 0;
630fb9987d0f748c983bb795a86f47522313f701a08Sujith
631fb9987d0f748c983bb795a86f47522313f701a08Sujith	priv->op_flags |= OP_INVALID;
632fb9987d0f748c983bb795a86f47522313f701a08Sujith
633fb9987d0f748c983bb795a86f47522313f701a08Sujith	ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
634fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (!ah)
635fb9987d0f748c983bb795a86f47522313f701a08Sujith		return -ENOMEM;
636fb9987d0f748c983bb795a86f47522313f701a08Sujith
637fb9987d0f748c983bb795a86f47522313f701a08Sujith	ah->hw_version.devid = devid;
638fb9987d0f748c983bb795a86f47522313f701a08Sujith	ah->hw_version.subsysid = 0; /* FIXME */
639f8afa42b01c7a9f45b7cbaadb0481a0eeb96f18dFelix Fietkau	ah->ah_flags |= AH_USE_EEPROM;
640fb9987d0f748c983bb795a86f47522313f701a08Sujith	priv->ah = ah;
641fb9987d0f748c983bb795a86f47522313f701a08Sujith
642fb9987d0f748c983bb795a86f47522313f701a08Sujith	common = ath9k_hw_common(ah);
643fb9987d0f748c983bb795a86f47522313f701a08Sujith	common->ops = &ath9k_common_ops;
644fb9987d0f748c983bb795a86f47522313f701a08Sujith	common->bus_ops = &ath9k_usb_bus_ops;
645fb9987d0f748c983bb795a86f47522313f701a08Sujith	common->ah = ah;
646fb9987d0f748c983bb795a86f47522313f701a08Sujith	common->hw = priv->hw;
647fb9987d0f748c983bb795a86f47522313f701a08Sujith	common->priv = priv;
648fb9987d0f748c983bb795a86f47522313f701a08Sujith	common->debug_mask = ath9k_debug;
649fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan	common->driver_info = drv_info;
650fb9987d0f748c983bb795a86f47522313f701a08Sujith
651fb9987d0f748c983bb795a86f47522313f701a08Sujith	spin_lock_init(&priv->wmi->wmi_lock);
652fb9987d0f748c983bb795a86f47522313f701a08Sujith	spin_lock_init(&priv->beacon_lock);
6537757dfed5809b03aa61c7d7f5ff8092f85df8583Sujith	spin_lock_init(&priv->tx_lock);
654fb9987d0f748c983bb795a86f47522313f701a08Sujith	mutex_init(&priv->mutex);
655bde748a40d4d5a9915def6772e208848c105e616Vivek Natarajan	mutex_init(&priv->htc_pm_lock);
656fb9987d0f748c983bb795a86f47522313f701a08Sujith	tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet,
657fb9987d0f748c983bb795a86f47522313f701a08Sujith		     (unsigned long)priv);
658fb9987d0f748c983bb795a86f47522313f701a08Sujith	tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
659fb9987d0f748c983bb795a86f47522313f701a08Sujith		     (unsigned long)priv);
660fb9987d0f748c983bb795a86f47522313f701a08Sujith	tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv);
661fb9987d0f748c983bb795a86f47522313f701a08Sujith	INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work);
662bde748a40d4d5a9915def6772e208848c105e616Vivek Natarajan	INIT_WORK(&priv->ps_work, ath9k_ps_work);
663fb9987d0f748c983bb795a86f47522313f701a08Sujith
664fb9987d0f748c983bb795a86f47522313f701a08Sujith	/*
665fb9987d0f748c983bb795a86f47522313f701a08Sujith	 * Cache line size is used to size and align various
666fb9987d0f748c983bb795a86f47522313f701a08Sujith	 * structures used to communicate with the hardware.
667fb9987d0f748c983bb795a86f47522313f701a08Sujith	 */
668fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath_read_cachesize(common, &csz);
669fb9987d0f748c983bb795a86f47522313f701a08Sujith	common->cachelsz = csz << 2; /* convert to bytes */
670fb9987d0f748c983bb795a86f47522313f701a08Sujith
671fb9987d0f748c983bb795a86f47522313f701a08Sujith	ret = ath9k_hw_init(ah);
672fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret) {
673fb9987d0f748c983bb795a86f47522313f701a08Sujith		ath_print(common, ATH_DBG_FATAL,
674fb9987d0f748c983bb795a86f47522313f701a08Sujith			  "Unable to initialize hardware; "
675fb9987d0f748c983bb795a86f47522313f701a08Sujith			  "initialization status: %d\n", ret);
676fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err_hw;
677fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
678fb9987d0f748c983bb795a86f47522313f701a08Sujith
679e1572c5eeca8ef87a250322364584458b2dadb35Sujith	ret = ath9k_htc_init_debug(ah);
680fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret) {
681fb9987d0f748c983bb795a86f47522313f701a08Sujith		ath_print(common, ATH_DBG_FATAL,
682fb9987d0f748c983bb795a86f47522313f701a08Sujith			  "Unable to create debugfs files\n");
683fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err_debug;
684fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
685fb9987d0f748c983bb795a86f47522313f701a08Sujith
686fb9987d0f748c983bb795a86f47522313f701a08Sujith	ret = ath9k_init_queues(priv);
687fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret)
688fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err_queues;
689fb9987d0f748c983bb795a86f47522313f701a08Sujith
690fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_init_crypto(priv);
691fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_init_channels_rates(priv);
692fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_init_misc(priv);
693fb9987d0f748c983bb795a86f47522313f701a08Sujith
69421cb987914cb5334af78378141efed77505ea987Vivek Natarajan	if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) {
69521cb987914cb5334af78378141efed77505ea987Vivek Natarajan		ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE;
69621cb987914cb5334af78378141efed77505ea987Vivek Natarajan		ath9k_init_btcoex(priv);
69721cb987914cb5334af78378141efed77505ea987Vivek Natarajan	}
69821cb987914cb5334af78378141efed77505ea987Vivek Natarajan
699fb9987d0f748c983bb795a86f47522313f701a08Sujith	return 0;
700fb9987d0f748c983bb795a86f47522313f701a08Sujith
701fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_queues:
702e1572c5eeca8ef87a250322364584458b2dadb35Sujith	ath9k_htc_exit_debug(ah);
703fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_debug:
704fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_hw_deinit(ah);
705fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_hw:
706fb9987d0f748c983bb795a86f47522313f701a08Sujith
707fb9987d0f748c983bb795a86f47522313f701a08Sujith	kfree(ah);
708fb9987d0f748c983bb795a86f47522313f701a08Sujith	priv->ah = NULL;
709fb9987d0f748c983bb795a86f47522313f701a08Sujith
710fb9987d0f748c983bb795a86f47522313f701a08Sujith	return ret;
711fb9987d0f748c983bb795a86f47522313f701a08Sujith}
712fb9987d0f748c983bb795a86f47522313f701a08Sujith
713fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
714fb9987d0f748c983bb795a86f47522313f701a08Sujith			       struct ieee80211_hw *hw)
715fb9987d0f748c983bb795a86f47522313f701a08Sujith{
716fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath_common *common = ath9k_hw_common(priv->ah);
717fb9987d0f748c983bb795a86f47522313f701a08Sujith
718fb9987d0f748c983bb795a86f47522313f701a08Sujith	hw->flags = IEEE80211_HW_SIGNAL_DBM |
719fb9987d0f748c983bb795a86f47522313f701a08Sujith		IEEE80211_HW_AMPDU_AGGREGATION |
720fb9987d0f748c983bb795a86f47522313f701a08Sujith		IEEE80211_HW_SPECTRUM_MGMT |
72132fbccafed7e935432b601f0453c2b702a385a25Sujith		IEEE80211_HW_HAS_RATE_CONTROL |
722bde748a40d4d5a9915def6772e208848c105e616Vivek Natarajan		IEEE80211_HW_RX_INCLUDES_FCS |
723bde748a40d4d5a9915def6772e208848c105e616Vivek Natarajan		IEEE80211_HW_SUPPORTS_PS |
724bde748a40d4d5a9915def6772e208848c105e616Vivek Natarajan		IEEE80211_HW_PS_NULLFUNC_STACK;
725fb9987d0f748c983bb795a86f47522313f701a08Sujith
726fb9987d0f748c983bb795a86f47522313f701a08Sujith	hw->wiphy->interface_modes =
727fb9987d0f748c983bb795a86f47522313f701a08Sujith		BIT(NL80211_IFTYPE_STATION) |
728fb9987d0f748c983bb795a86f47522313f701a08Sujith		BIT(NL80211_IFTYPE_ADHOC);
729fb9987d0f748c983bb795a86f47522313f701a08Sujith
730bde748a40d4d5a9915def6772e208848c105e616Vivek Natarajan	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
731bde748a40d4d5a9915def6772e208848c105e616Vivek Natarajan
732fb9987d0f748c983bb795a86f47522313f701a08Sujith	hw->queues = 4;
733fb9987d0f748c983bb795a86f47522313f701a08Sujith	hw->channel_change_time = 5000;
734fb9987d0f748c983bb795a86f47522313f701a08Sujith	hw->max_listen_interval = 10;
735fb9987d0f748c983bb795a86f47522313f701a08Sujith	hw->vif_data_size = sizeof(struct ath9k_htc_vif);
736fb9987d0f748c983bb795a86f47522313f701a08Sujith	hw->sta_data_size = sizeof(struct ath9k_htc_sta);
737fb9987d0f748c983bb795a86f47522313f701a08Sujith
738fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* tx_frame_hdr is larger than tx_mgmt_hdr anyway */
739fb9987d0f748c983bb795a86f47522313f701a08Sujith	hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) +
740fb9987d0f748c983bb795a86f47522313f701a08Sujith		sizeof(struct htc_frame_hdr) + 4;
741fb9987d0f748c983bb795a86f47522313f701a08Sujith
742d4659912b557e9f68c0ad8be14e2cafd3210dd16Felix Fietkau	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
743fb9987d0f748c983bb795a86f47522313f701a08Sujith		hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
744fb9987d0f748c983bb795a86f47522313f701a08Sujith			&priv->sbands[IEEE80211_BAND_2GHZ];
745d4659912b557e9f68c0ad8be14e2cafd3210dd16Felix Fietkau	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
746ea46e644e80bd4ac778964afd998df4f666486d4Sujith		hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
747ea46e644e80bd4ac778964afd998df4f666486d4Sujith			&priv->sbands[IEEE80211_BAND_5GHZ];
748fb9987d0f748c983bb795a86f47522313f701a08Sujith
749fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
750d4659912b557e9f68c0ad8be14e2cafd3210dd16Felix Fietkau		if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
751fb9987d0f748c983bb795a86f47522313f701a08Sujith			setup_ht_cap(priv,
752fb9987d0f748c983bb795a86f47522313f701a08Sujith				     &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap);
753d4659912b557e9f68c0ad8be14e2cafd3210dd16Felix Fietkau		if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
754ea46e644e80bd4ac778964afd998df4f666486d4Sujith			setup_ht_cap(priv,
755ea46e644e80bd4ac778964afd998df4f666486d4Sujith				     &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap);
756fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
757fb9987d0f748c983bb795a86f47522313f701a08Sujith
758fb9987d0f748c983bb795a86f47522313f701a08Sujith	SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
759fb9987d0f748c983bb795a86f47522313f701a08Sujith}
760fb9987d0f748c983bb795a86f47522313f701a08Sujith
76121cb987914cb5334af78378141efed77505ea987Vivek Natarajanstatic int ath9k_init_device(struct ath9k_htc_priv *priv,
762fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan			     u16 devid, char *product, u32 drv_info)
763fb9987d0f748c983bb795a86f47522313f701a08Sujith{
764fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ieee80211_hw *hw = priv->hw;
765fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath_common *common;
766fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath_hw *ah;
767fb9987d0f748c983bb795a86f47522313f701a08Sujith	int error = 0;
768fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath_regulatory *reg;
769fb9987d0f748c983bb795a86f47522313f701a08Sujith
770fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* Bring up device */
771fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan	error = ath9k_init_priv(priv, devid, product, drv_info);
772fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (error != 0)
773fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err_init;
774fb9987d0f748c983bb795a86f47522313f701a08Sujith
775fb9987d0f748c983bb795a86f47522313f701a08Sujith	ah = priv->ah;
776fb9987d0f748c983bb795a86f47522313f701a08Sujith	common = ath9k_hw_common(ah);
777fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_set_hw_capab(priv, hw);
778fb9987d0f748c983bb795a86f47522313f701a08Sujith
779fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* Initialize regulatory */
780fb9987d0f748c983bb795a86f47522313f701a08Sujith	error = ath_regd_init(&common->regulatory, priv->hw->wiphy,
781fb9987d0f748c983bb795a86f47522313f701a08Sujith			      ath9k_reg_notifier);
782fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (error)
783fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err_regd;
784fb9987d0f748c983bb795a86f47522313f701a08Sujith
785fb9987d0f748c983bb795a86f47522313f701a08Sujith	reg = &common->regulatory;
786fb9987d0f748c983bb795a86f47522313f701a08Sujith
787fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* Setup TX */
788fb9987d0f748c983bb795a86f47522313f701a08Sujith	error = ath9k_tx_init(priv);
789fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (error != 0)
790fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err_tx;
791fb9987d0f748c983bb795a86f47522313f701a08Sujith
792fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* Setup RX */
793fb9987d0f748c983bb795a86f47522313f701a08Sujith	error = ath9k_rx_init(priv);
794fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (error != 0)
795fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err_rx;
796fb9987d0f748c983bb795a86f47522313f701a08Sujith
797fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* Register with mac80211 */
798fb9987d0f748c983bb795a86f47522313f701a08Sujith	error = ieee80211_register_hw(hw);
799fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (error)
800fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err_register;
801fb9987d0f748c983bb795a86f47522313f701a08Sujith
802fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* Handle world regulatory */
803fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (!ath_is_world_regd(reg)) {
804fb9987d0f748c983bb795a86f47522313f701a08Sujith		error = regulatory_hint(hw->wiphy, reg->alpha2);
805fb9987d0f748c983bb795a86f47522313f701a08Sujith		if (error)
806fb9987d0f748c983bb795a86f47522313f701a08Sujith			goto err_world;
807fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
808fb9987d0f748c983bb795a86f47522313f701a08Sujith
809fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_init_leds(priv);
810fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_start_rfkill_poll(priv);
811fb9987d0f748c983bb795a86f47522313f701a08Sujith
812fb9987d0f748c983bb795a86f47522313f701a08Sujith	return 0;
813fb9987d0f748c983bb795a86f47522313f701a08Sujith
814fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_world:
815fb9987d0f748c983bb795a86f47522313f701a08Sujith	ieee80211_unregister_hw(hw);
816fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_register:
817fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_rx_cleanup(priv);
818fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_rx:
819fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_tx_cleanup(priv);
820fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_tx:
821fb9987d0f748c983bb795a86f47522313f701a08Sujith	/* Nothing */
822fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_regd:
823fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_deinit_priv(priv);
824fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_init:
825fb9987d0f748c983bb795a86f47522313f701a08Sujith	return error;
826fb9987d0f748c983bb795a86f47522313f701a08Sujith}
827fb9987d0f748c983bb795a86f47522313f701a08Sujith
828fb9987d0f748c983bb795a86f47522313f701a08Sujithint ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
829fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan			   u16 devid, char *product, u32 drv_info)
830fb9987d0f748c983bb795a86f47522313f701a08Sujith{
831fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ieee80211_hw *hw;
832fb9987d0f748c983bb795a86f47522313f701a08Sujith	struct ath9k_htc_priv *priv;
833fb9987d0f748c983bb795a86f47522313f701a08Sujith	int ret;
834fb9987d0f748c983bb795a86f47522313f701a08Sujith
835fb9987d0f748c983bb795a86f47522313f701a08Sujith	hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops);
836fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (!hw)
837fb9987d0f748c983bb795a86f47522313f701a08Sujith		return -ENOMEM;
838fb9987d0f748c983bb795a86f47522313f701a08Sujith
839fb9987d0f748c983bb795a86f47522313f701a08Sujith	priv = hw->priv;
840fb9987d0f748c983bb795a86f47522313f701a08Sujith	priv->hw = hw;
841fb9987d0f748c983bb795a86f47522313f701a08Sujith	priv->htc = htc_handle;
842fb9987d0f748c983bb795a86f47522313f701a08Sujith	priv->dev = dev;
843fb9987d0f748c983bb795a86f47522313f701a08Sujith	htc_handle->drv_priv = priv;
844fb9987d0f748c983bb795a86f47522313f701a08Sujith	SET_IEEE80211_DEV(hw, priv->dev);
845fb9987d0f748c983bb795a86f47522313f701a08Sujith
846fb9987d0f748c983bb795a86f47522313f701a08Sujith	ret = ath9k_htc_wait_for_target(priv);
847fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret)
848fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err_free;
849fb9987d0f748c983bb795a86f47522313f701a08Sujith
850fb9987d0f748c983bb795a86f47522313f701a08Sujith	priv->wmi = ath9k_init_wmi(priv);
851fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (!priv->wmi) {
852fb9987d0f748c983bb795a86f47522313f701a08Sujith		ret = -EINVAL;
853fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err_free;
854fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
855fb9987d0f748c983bb795a86f47522313f701a08Sujith
856fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan	ret = ath9k_init_htc_services(priv, devid, drv_info);
857fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret)
858fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err_init;
859fb9987d0f748c983bb795a86f47522313f701a08Sujith
860a3be14b76da111ebe4d245b0542613f9317104e7Sujith	/* The device may have been unplugged earlier. */
861a3be14b76da111ebe4d245b0542613f9317104e7Sujith	priv->op_flags &= ~OP_UNPLUGGED;
862a3be14b76da111ebe4d245b0542613f9317104e7Sujith
863fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan	ret = ath9k_init_device(priv, devid, product, drv_info);
864fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret)
865fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err_init;
866fb9987d0f748c983bb795a86f47522313f701a08Sujith
867fb9987d0f748c983bb795a86f47522313f701a08Sujith	return 0;
868fb9987d0f748c983bb795a86f47522313f701a08Sujith
869fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_init:
870fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_deinit_wmi(priv);
871fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_free:
872fb9987d0f748c983bb795a86f47522313f701a08Sujith	ieee80211_free_hw(hw);
873fb9987d0f748c983bb795a86f47522313f701a08Sujith	return ret;
874fb9987d0f748c983bb795a86f47522313f701a08Sujith}
875fb9987d0f748c983bb795a86f47522313f701a08Sujith
876fb9987d0f748c983bb795a86f47522313f701a08Sujithvoid ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
877fb9987d0f748c983bb795a86f47522313f701a08Sujith{
878fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (htc_handle->drv_priv) {
879a3be14b76da111ebe4d245b0542613f9317104e7Sujith
880a3be14b76da111ebe4d245b0542613f9317104e7Sujith		/* Check if the device has been yanked out. */
881a3be14b76da111ebe4d245b0542613f9317104e7Sujith		if (hotunplug)
882a3be14b76da111ebe4d245b0542613f9317104e7Sujith			htc_handle->drv_priv->op_flags |= OP_UNPLUGGED;
883a3be14b76da111ebe4d245b0542613f9317104e7Sujith
884fb9987d0f748c983bb795a86f47522313f701a08Sujith		ath9k_deinit_device(htc_handle->drv_priv);
885fb9987d0f748c983bb795a86f47522313f701a08Sujith		ath9k_deinit_wmi(htc_handle->drv_priv);
886fb9987d0f748c983bb795a86f47522313f701a08Sujith		ieee80211_free_hw(htc_handle->drv_priv->hw);
887fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
888fb9987d0f748c983bb795a86f47522313f701a08Sujith}
889fb9987d0f748c983bb795a86f47522313f701a08Sujith
890fb9987d0f748c983bb795a86f47522313f701a08Sujith#ifdef CONFIG_PM
891fb9987d0f748c983bb795a86f47522313f701a08Sujithint ath9k_htc_resume(struct htc_target *htc_handle)
892fb9987d0f748c983bb795a86f47522313f701a08Sujith{
893fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan	struct ath9k_htc_priv *priv = htc_handle->drv_priv;
894fb9987d0f748c983bb795a86f47522313f701a08Sujith	int ret;
895fb9987d0f748c983bb795a86f47522313f701a08Sujith
896fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan	ret = ath9k_htc_wait_for_target(priv);
897fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (ret)
898fb9987d0f748c983bb795a86f47522313f701a08Sujith		return ret;
899fb9987d0f748c983bb795a86f47522313f701a08Sujith
900fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan	ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid,
901fa6e15e0b5952fd2cd99fc6d4f4473f6b9da18dfRajkumar Manoharan				      priv->ah->common.driver_info);
902fb9987d0f748c983bb795a86f47522313f701a08Sujith	return ret;
903fb9987d0f748c983bb795a86f47522313f701a08Sujith}
904fb9987d0f748c983bb795a86f47522313f701a08Sujith#endif
905fb9987d0f748c983bb795a86f47522313f701a08Sujith
906fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic int __init ath9k_htc_init(void)
907fb9987d0f748c983bb795a86f47522313f701a08Sujith{
908fb9987d0f748c983bb795a86f47522313f701a08Sujith	int error;
909fb9987d0f748c983bb795a86f47522313f701a08Sujith
910e1572c5eeca8ef87a250322364584458b2dadb35Sujith	error = ath9k_htc_debug_create_root();
911fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (error < 0) {
912fb9987d0f748c983bb795a86f47522313f701a08Sujith		printk(KERN_ERR
913fb9987d0f748c983bb795a86f47522313f701a08Sujith			"ath9k_htc: Unable to create debugfs root: %d\n",
914fb9987d0f748c983bb795a86f47522313f701a08Sujith			error);
915fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err_dbg;
916fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
917fb9987d0f748c983bb795a86f47522313f701a08Sujith
918fb9987d0f748c983bb795a86f47522313f701a08Sujith	error = ath9k_hif_usb_init();
919fb9987d0f748c983bb795a86f47522313f701a08Sujith	if (error < 0) {
920fb9987d0f748c983bb795a86f47522313f701a08Sujith		printk(KERN_ERR
921fb9987d0f748c983bb795a86f47522313f701a08Sujith			"ath9k_htc: No USB devices found,"
922fb9987d0f748c983bb795a86f47522313f701a08Sujith			" driver not installed.\n");
923fb9987d0f748c983bb795a86f47522313f701a08Sujith		error = -ENODEV;
924fb9987d0f748c983bb795a86f47522313f701a08Sujith		goto err_usb;
925fb9987d0f748c983bb795a86f47522313f701a08Sujith	}
926fb9987d0f748c983bb795a86f47522313f701a08Sujith
927fb9987d0f748c983bb795a86f47522313f701a08Sujith	return 0;
928fb9987d0f748c983bb795a86f47522313f701a08Sujith
929fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_usb:
930e1572c5eeca8ef87a250322364584458b2dadb35Sujith	ath9k_htc_debug_remove_root();
931fb9987d0f748c983bb795a86f47522313f701a08Sujitherr_dbg:
932fb9987d0f748c983bb795a86f47522313f701a08Sujith	return error;
933fb9987d0f748c983bb795a86f47522313f701a08Sujith}
934fb9987d0f748c983bb795a86f47522313f701a08Sujithmodule_init(ath9k_htc_init);
935fb9987d0f748c983bb795a86f47522313f701a08Sujith
936fb9987d0f748c983bb795a86f47522313f701a08Sujithstatic void __exit ath9k_htc_exit(void)
937fb9987d0f748c983bb795a86f47522313f701a08Sujith{
938fb9987d0f748c983bb795a86f47522313f701a08Sujith	ath9k_hif_usb_exit();
939e1572c5eeca8ef87a250322364584458b2dadb35Sujith	ath9k_htc_debug_remove_root();
940fb9987d0f748c983bb795a86f47522313f701a08Sujith	printk(KERN_INFO "ath9k_htc: Driver unloaded\n");
941fb9987d0f748c983bb795a86f47522313f701a08Sujith}
942fb9987d0f748c983bb795a86f47522313f701a08Sujithmodule_exit(ath9k_htc_exit);
943