1fb9987d0SSujith /*
25b68138eSSujith Manoharan  * Copyright (c) 2010-2011 Atheros Communications Inc.
3fb9987d0SSujith  *
4fb9987d0SSujith  * Permission to use, copy, modify, and/or distribute this software for any
5fb9987d0SSujith  * purpose with or without fee is hereby granted, provided that the above
6fb9987d0SSujith  * copyright notice and this permission notice appear in all copies.
7fb9987d0SSujith  *
8fb9987d0SSujith  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9fb9987d0SSujith  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10fb9987d0SSujith  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11fb9987d0SSujith  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12fb9987d0SSujith  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13fb9987d0SSujith  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14fb9987d0SSujith  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15fb9987d0SSujith  */
16fb9987d0SSujith 
17516304b0SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18516304b0SJoe Perches 
19fb9987d0SSujith #include "htc.h"
20fb9987d0SSujith 
21fb9987d0SSujith MODULE_AUTHOR("Atheros Communications");
22fb9987d0SSujith MODULE_LICENSE("Dual BSD/GPL");
23fb9987d0SSujith MODULE_DESCRIPTION("Atheros driver 802.11n HTC based wireless devices");
24fb9987d0SSujith 
25fb9987d0SSujith static unsigned int ath9k_debug = ATH_DBG_DEFAULT;
26fb9987d0SSujith module_param_named(debug, ath9k_debug, uint, 0);
27fb9987d0SSujith MODULE_PARM_DESC(debug, "Debugging mask");
28fb9987d0SSujith 
29e1572c5eSSujith int htc_modparam_nohwcrypt;
30e1572c5eSSujith module_param_named(nohwcrypt, htc_modparam_nohwcrypt, int, 0444);
31fb9987d0SSujith MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
32fb9987d0SSujith 
33fb9987d0SSujith #define CHAN2G(_freq, _idx)  { \
34fb9987d0SSujith 	.center_freq = (_freq), \
35fb9987d0SSujith 	.hw_value = (_idx), \
36fb9987d0SSujith 	.max_power = 20, \
37fb9987d0SSujith }
38fb9987d0SSujith 
39ea46e644SSujith #define CHAN5G(_freq, _idx) { \
40ea46e644SSujith 	.band = IEEE80211_BAND_5GHZ, \
41ea46e644SSujith 	.center_freq = (_freq), \
42ea46e644SSujith 	.hw_value = (_idx), \
43ea46e644SSujith 	.max_power = 20, \
44ea46e644SSujith }
45ea46e644SSujith 
46fb9987d0SSujith static struct ieee80211_channel ath9k_2ghz_channels[] = {
47fb9987d0SSujith 	CHAN2G(2412, 0), /* Channel 1 */
48fb9987d0SSujith 	CHAN2G(2417, 1), /* Channel 2 */
49fb9987d0SSujith 	CHAN2G(2422, 2), /* Channel 3 */
50fb9987d0SSujith 	CHAN2G(2427, 3), /* Channel 4 */
51fb9987d0SSujith 	CHAN2G(2432, 4), /* Channel 5 */
52fb9987d0SSujith 	CHAN2G(2437, 5), /* Channel 6 */
53fb9987d0SSujith 	CHAN2G(2442, 6), /* Channel 7 */
54fb9987d0SSujith 	CHAN2G(2447, 7), /* Channel 8 */
55fb9987d0SSujith 	CHAN2G(2452, 8), /* Channel 9 */
56fb9987d0SSujith 	CHAN2G(2457, 9), /* Channel 10 */
57fb9987d0SSujith 	CHAN2G(2462, 10), /* Channel 11 */
58fb9987d0SSujith 	CHAN2G(2467, 11), /* Channel 12 */
59fb9987d0SSujith 	CHAN2G(2472, 12), /* Channel 13 */
60fb9987d0SSujith 	CHAN2G(2484, 13), /* Channel 14 */
61fb9987d0SSujith };
62fb9987d0SSujith 
63ea46e644SSujith static struct ieee80211_channel ath9k_5ghz_channels[] = {
64ea46e644SSujith 	/* _We_ call this UNII 1 */
65ea46e644SSujith 	CHAN5G(5180, 14), /* Channel 36 */
66ea46e644SSujith 	CHAN5G(5200, 15), /* Channel 40 */
67ea46e644SSujith 	CHAN5G(5220, 16), /* Channel 44 */
68ea46e644SSujith 	CHAN5G(5240, 17), /* Channel 48 */
69ea46e644SSujith 	/* _We_ call this UNII 2 */
70ea46e644SSujith 	CHAN5G(5260, 18), /* Channel 52 */
71ea46e644SSujith 	CHAN5G(5280, 19), /* Channel 56 */
72ea46e644SSujith 	CHAN5G(5300, 20), /* Channel 60 */
73ea46e644SSujith 	CHAN5G(5320, 21), /* Channel 64 */
74ea46e644SSujith 	/* _We_ call this "Middle band" */
75ea46e644SSujith 	CHAN5G(5500, 22), /* Channel 100 */
76ea46e644SSujith 	CHAN5G(5520, 23), /* Channel 104 */
77ea46e644SSujith 	CHAN5G(5540, 24), /* Channel 108 */
78ea46e644SSujith 	CHAN5G(5560, 25), /* Channel 112 */
79ea46e644SSujith 	CHAN5G(5580, 26), /* Channel 116 */
80ea46e644SSujith 	CHAN5G(5600, 27), /* Channel 120 */
81ea46e644SSujith 	CHAN5G(5620, 28), /* Channel 124 */
82ea46e644SSujith 	CHAN5G(5640, 29), /* Channel 128 */
83ea46e644SSujith 	CHAN5G(5660, 30), /* Channel 132 */
84ea46e644SSujith 	CHAN5G(5680, 31), /* Channel 136 */
85ea46e644SSujith 	CHAN5G(5700, 32), /* Channel 140 */
86ea46e644SSujith 	/* _We_ call this UNII 3 */
87ea46e644SSujith 	CHAN5G(5745, 33), /* Channel 149 */
88ea46e644SSujith 	CHAN5G(5765, 34), /* Channel 153 */
89ea46e644SSujith 	CHAN5G(5785, 35), /* Channel 157 */
90ea46e644SSujith 	CHAN5G(5805, 36), /* Channel 161 */
91ea46e644SSujith 	CHAN5G(5825, 37), /* Channel 165 */
92ea46e644SSujith };
93ea46e644SSujith 
94fb9987d0SSujith /* Atheros hardware rate code addition for short premble */
95fb9987d0SSujith #define SHPCHECK(__hw_rate, __flags) \
96fb9987d0SSujith 	((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04) : 0)
97fb9987d0SSujith 
98fb9987d0SSujith #define RATE(_bitrate, _hw_rate, _flags) {		\
99fb9987d0SSujith 	.bitrate	= (_bitrate),			\
100fb9987d0SSujith 	.flags		= (_flags),			\
101fb9987d0SSujith 	.hw_value	= (_hw_rate),			\
102fb9987d0SSujith 	.hw_value_short = (SHPCHECK(_hw_rate, _flags))	\
103fb9987d0SSujith }
104fb9987d0SSujith 
105fb9987d0SSujith static struct ieee80211_rate ath9k_legacy_rates[] = {
106fb9987d0SSujith 	RATE(10, 0x1b, 0),
107fb9987d0SSujith 	RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp : 0x1e */
108fb9987d0SSujith 	RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), /* shortp: 0x1d */
109fb9987d0SSujith 	RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), /* short: 0x1c */
110fb9987d0SSujith 	RATE(60, 0x0b, 0),
111fb9987d0SSujith 	RATE(90, 0x0f, 0),
112fb9987d0SSujith 	RATE(120, 0x0a, 0),
113fb9987d0SSujith 	RATE(180, 0x0e, 0),
114fb9987d0SSujith 	RATE(240, 0x09, 0),
115fb9987d0SSujith 	RATE(360, 0x0d, 0),
116fb9987d0SSujith 	RATE(480, 0x08, 0),
117fb9987d0SSujith 	RATE(540, 0x0c, 0),
118fb9987d0SSujith };
119fb9987d0SSujith 
120d244f21eSSujith Manoharan #ifdef CONFIG_MAC80211_LEDS
121d244f21eSSujith Manoharan static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = {
122d244f21eSSujith Manoharan 	{ .throughput = 0 * 1024, .blink_time = 334 },
123d244f21eSSujith Manoharan 	{ .throughput = 1 * 1024, .blink_time = 260 },
124d244f21eSSujith Manoharan 	{ .throughput = 5 * 1024, .blink_time = 220 },
125d244f21eSSujith Manoharan 	{ .throughput = 10 * 1024, .blink_time = 190 },
126d244f21eSSujith Manoharan 	{ .throughput = 20 * 1024, .blink_time = 170 },
127d244f21eSSujith Manoharan 	{ .throughput = 50 * 1024, .blink_time = 150 },
128d244f21eSSujith Manoharan 	{ .throughput = 70 * 1024, .blink_time = 130 },
129d244f21eSSujith Manoharan 	{ .throughput = 100 * 1024, .blink_time = 110 },
130d244f21eSSujith Manoharan 	{ .throughput = 200 * 1024, .blink_time = 80 },
131d244f21eSSujith Manoharan 	{ .throughput = 300 * 1024, .blink_time = 50 },
132d244f21eSSujith Manoharan };
133d244f21eSSujith Manoharan #endif
134d244f21eSSujith Manoharan 
135fb9987d0SSujith static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
136fb9987d0SSujith {
137fb9987d0SSujith 	int time_left;
138fb9987d0SSujith 
139d8c49ffbSSujith.Manoharan@atheros.com 	if (atomic_read(&priv->htc->tgt_ready) > 0) {
140d8c49ffbSSujith.Manoharan@atheros.com 		atomic_dec(&priv->htc->tgt_ready);
141d8c49ffbSSujith.Manoharan@atheros.com 		return 0;
142d8c49ffbSSujith.Manoharan@atheros.com 	}
143d8c49ffbSSujith.Manoharan@atheros.com 
144fb9987d0SSujith 	/* Firmware can take up to 50ms to get ready, to be safe use 1 second */
145fb9987d0SSujith 	time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ);
146fb9987d0SSujith 	if (!time_left) {
147fb9987d0SSujith 		dev_err(priv->dev, "ath9k_htc: Target is unresponsive\n");
148fb9987d0SSujith 		return -ETIMEDOUT;
149fb9987d0SSujith 	}
150fb9987d0SSujith 
151d8c49ffbSSujith.Manoharan@atheros.com 	atomic_dec(&priv->htc->tgt_ready);
152d8c49ffbSSujith.Manoharan@atheros.com 
153fb9987d0SSujith 	return 0;
154fb9987d0SSujith }
155fb9987d0SSujith 
156fb9987d0SSujith static void ath9k_deinit_priv(struct ath9k_htc_priv *priv)
157fb9987d0SSujith {
158fb9987d0SSujith 	ath9k_hw_deinit(priv->ah);
159fb9987d0SSujith 	kfree(priv->ah);
160fb9987d0SSujith 	priv->ah = NULL;
161fb9987d0SSujith }
162fb9987d0SSujith 
163fb9987d0SSujith static void ath9k_deinit_device(struct ath9k_htc_priv *priv)
164fb9987d0SSujith {
165fb9987d0SSujith 	struct ieee80211_hw *hw = priv->hw;
166fb9987d0SSujith 
167fb9987d0SSujith 	wiphy_rfkill_stop_polling(hw->wiphy);
168fb9987d0SSujith 	ath9k_deinit_leds(priv);
169fb9987d0SSujith 	ieee80211_unregister_hw(hw);
170fb9987d0SSujith 	ath9k_rx_cleanup(priv);
171fb9987d0SSujith 	ath9k_tx_cleanup(priv);
172fb9987d0SSujith 	ath9k_deinit_priv(priv);
173fb9987d0SSujith }
174fb9987d0SSujith 
175fb9987d0SSujith static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv,
176fb9987d0SSujith 					u16 service_id,
177fb9987d0SSujith 					void (*tx) (void *,
178fb9987d0SSujith 						    struct sk_buff *,
179fb9987d0SSujith 						    enum htc_endpoint_id,
180fb9987d0SSujith 						    bool txok),
181fb9987d0SSujith 					enum htc_endpoint_id *ep_id)
182fb9987d0SSujith {
183fb9987d0SSujith 	struct htc_service_connreq req;
184fb9987d0SSujith 
185fb9987d0SSujith 	memset(&req, 0, sizeof(struct htc_service_connreq));
186fb9987d0SSujith 
187fb9987d0SSujith 	req.service_id = service_id;
188fb9987d0SSujith 	req.ep_callbacks.priv = priv;
189fb9987d0SSujith 	req.ep_callbacks.rx = ath9k_htc_rxep;
190fb9987d0SSujith 	req.ep_callbacks.tx = tx;
191fb9987d0SSujith 
192fb9987d0SSujith 	return htc_connect_service(priv->htc, &req, ep_id);
193fb9987d0SSujith }
194fb9987d0SSujith 
195fa6e15e0SRajkumar Manoharan static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid,
196fa6e15e0SRajkumar Manoharan 				   u32 drv_info)
197fb9987d0SSujith {
198fb9987d0SSujith 	int ret;
199fb9987d0SSujith 
200fb9987d0SSujith 	/* WMI CMD*/
201fb9987d0SSujith 	ret = ath9k_wmi_connect(priv->htc, priv->wmi, &priv->wmi_cmd_ep);
202fb9987d0SSujith 	if (ret)
203fb9987d0SSujith 		goto err;
204fb9987d0SSujith 
205fb9987d0SSujith 	/* Beacon */
2069c6dda4eSSujith 	ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, ath9k_htc_beaconep,
207fb9987d0SSujith 				    &priv->beacon_ep);
208fb9987d0SSujith 	if (ret)
209fb9987d0SSujith 		goto err;
210fb9987d0SSujith 
211fb9987d0SSujith 	/* CAB */
212fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_CAB_SVC, ath9k_htc_txep,
213fb9987d0SSujith 				    &priv->cab_ep);
214fb9987d0SSujith 	if (ret)
215fb9987d0SSujith 		goto err;
216fb9987d0SSujith 
217fb9987d0SSujith 
218fb9987d0SSujith 	/* UAPSD */
219fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_UAPSD_SVC, ath9k_htc_txep,
220fb9987d0SSujith 				    &priv->uapsd_ep);
221fb9987d0SSujith 	if (ret)
222fb9987d0SSujith 		goto err;
223fb9987d0SSujith 
224fb9987d0SSujith 	/* MGMT */
225fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_MGMT_SVC, ath9k_htc_txep,
226fb9987d0SSujith 				    &priv->mgmt_ep);
227fb9987d0SSujith 	if (ret)
228fb9987d0SSujith 		goto err;
229fb9987d0SSujith 
230fb9987d0SSujith 	/* DATA BE */
231fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_BE_SVC, ath9k_htc_txep,
232fb9987d0SSujith 				    &priv->data_be_ep);
233fb9987d0SSujith 	if (ret)
234fb9987d0SSujith 		goto err;
235fb9987d0SSujith 
236fb9987d0SSujith 	/* DATA BK */
237fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_BK_SVC, ath9k_htc_txep,
238fb9987d0SSujith 				    &priv->data_bk_ep);
239fb9987d0SSujith 	if (ret)
240fb9987d0SSujith 		goto err;
241fb9987d0SSujith 
242fb9987d0SSujith 	/* DATA VI */
243fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_VI_SVC, ath9k_htc_txep,
244fb9987d0SSujith 				    &priv->data_vi_ep);
245fb9987d0SSujith 	if (ret)
246fb9987d0SSujith 		goto err;
247fb9987d0SSujith 
248fb9987d0SSujith 	/* DATA VO */
249fb9987d0SSujith 	ret = ath9k_htc_connect_svc(priv, WMI_DATA_VO_SVC, ath9k_htc_txep,
250fb9987d0SSujith 				    &priv->data_vo_ep);
251fb9987d0SSujith 	if (ret)
252fb9987d0SSujith 		goto err;
253fb9987d0SSujith 
2546267dc70SSujith 	/*
2556267dc70SSujith 	 * Setup required credits before initializing HTC.
2566267dc70SSujith 	 * This is a bit hacky, but, since queuing is done in
2576267dc70SSujith 	 * the HIF layer, shouldn't matter much.
2586267dc70SSujith 	 */
2596267dc70SSujith 
2600b5ead91SSujith Manoharan 	if (IS_AR7010_DEVICE(drv_info))
261d108e8b9SSujith Manoharan 		priv->htc->credits = 45;
262fa6e15e0SRajkumar Manoharan 	else
2634e63f768SSujith 		priv->htc->credits = 33;
2646267dc70SSujith 
265fb9987d0SSujith 	ret = htc_init(priv->htc);
266fb9987d0SSujith 	if (ret)
267fb9987d0SSujith 		goto err;
268fb9987d0SSujith 
2696267dc70SSujith 	dev_info(priv->dev, "ath9k_htc: HTC initialized with %d credits\n",
2706267dc70SSujith 		 priv->htc->credits);
2716267dc70SSujith 
272fb9987d0SSujith 	return 0;
273fb9987d0SSujith 
274fb9987d0SSujith err:
275fb9987d0SSujith 	dev_err(priv->dev, "ath9k_htc: Unable to initialize HTC services\n");
276fb9987d0SSujith 	return ret;
277fb9987d0SSujith }
278fb9987d0SSujith 
279fb9987d0SSujith static int ath9k_reg_notifier(struct wiphy *wiphy,
280fb9987d0SSujith 			      struct regulatory_request *request)
281fb9987d0SSujith {
282fb9987d0SSujith 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
283fb9987d0SSujith 	struct ath9k_htc_priv *priv = hw->priv;
284fb9987d0SSujith 
285fb9987d0SSujith 	return ath_reg_notifier_apply(wiphy, request,
286fb9987d0SSujith 				      ath9k_hw_regulatory(priv->ah));
287fb9987d0SSujith }
288fb9987d0SSujith 
2894a22fe10SSujith static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset)
290fb9987d0SSujith {
291fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
292fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(ah);
293fb9987d0SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
294fb9987d0SSujith 	__be32 val, reg = cpu_to_be32(reg_offset);
295fb9987d0SSujith 	int r;
296fb9987d0SSujith 
297fb9987d0SSujith 	r = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
298fb9987d0SSujith 			  (u8 *) &reg, sizeof(reg),
299fb9987d0SSujith 			  (u8 *) &val, sizeof(val),
300fb9987d0SSujith 			  100);
301fb9987d0SSujith 	if (unlikely(r)) {
302d2182b69SJoe Perches 		ath_dbg(common, WMI, "REGISTER READ FAILED: (0x%04x, %d)\n",
303fb9987d0SSujith 			reg_offset, r);
304fb9987d0SSujith 		return -EIO;
305fb9987d0SSujith 	}
306fb9987d0SSujith 
307fb9987d0SSujith 	return be32_to_cpu(val);
308fb9987d0SSujith }
309fb9987d0SSujith 
31009a525d3SSujith Manoharan static void ath9k_multi_regread(void *hw_priv, u32 *addr,
31109a525d3SSujith Manoharan 				u32 *val, u16 count)
31209a525d3SSujith Manoharan {
31309a525d3SSujith Manoharan 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
31409a525d3SSujith Manoharan 	struct ath_common *common = ath9k_hw_common(ah);
31509a525d3SSujith Manoharan 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
31609a525d3SSujith Manoharan 	__be32 tmpaddr[8];
31709a525d3SSujith Manoharan 	__be32 tmpval[8];
31809a525d3SSujith Manoharan 	int i, ret;
31909a525d3SSujith Manoharan 
32009a525d3SSujith Manoharan        for (i = 0; i < count; i++) {
32109a525d3SSujith Manoharan 	       tmpaddr[i] = cpu_to_be32(addr[i]);
32209a525d3SSujith Manoharan        }
32309a525d3SSujith Manoharan 
32409a525d3SSujith Manoharan        ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
32509a525d3SSujith Manoharan 			   (u8 *)tmpaddr , sizeof(u32) * count,
32609a525d3SSujith Manoharan 			   (u8 *)tmpval, sizeof(u32) * count,
32709a525d3SSujith Manoharan 			   100);
32809a525d3SSujith Manoharan 	if (unlikely(ret)) {
329d2182b69SJoe Perches 		ath_dbg(common, WMI,
33009a525d3SSujith Manoharan 			"Multiple REGISTER READ FAILED (count: %d)\n", count);
33109a525d3SSujith Manoharan 	}
33209a525d3SSujith Manoharan 
33309a525d3SSujith Manoharan        for (i = 0; i < count; i++) {
33409a525d3SSujith Manoharan 	       val[i] = be32_to_cpu(tmpval[i]);
33509a525d3SSujith Manoharan        }
33609a525d3SSujith Manoharan }
33709a525d3SSujith Manoharan 
3384a22fe10SSujith static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)
339fb9987d0SSujith {
340fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
341fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(ah);
342fb9987d0SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
34307b2fa5aSJoe Perches 	const __be32 buf[2] = {
344fb9987d0SSujith 		cpu_to_be32(reg_offset),
345fb9987d0SSujith 		cpu_to_be32(val),
346fb9987d0SSujith 	};
347fb9987d0SSujith 	int r;
348fb9987d0SSujith 
349fb9987d0SSujith 	r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
350fb9987d0SSujith 			  (u8 *) &buf, sizeof(buf),
351fb9987d0SSujith 			  (u8 *) &val, sizeof(val),
352fb9987d0SSujith 			  100);
353fb9987d0SSujith 	if (unlikely(r)) {
354d2182b69SJoe Perches 		ath_dbg(common, WMI, "REGISTER WRITE FAILED:(0x%04x, %d)\n",
355fb9987d0SSujith 			reg_offset, r);
356fb9987d0SSujith 	}
357fb9987d0SSujith }
358fb9987d0SSujith 
3594a22fe10SSujith static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset)
3604a22fe10SSujith {
3614a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3624a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3634a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
3644a22fe10SSujith 	u32 rsp_status;
3654a22fe10SSujith 	int r;
3664a22fe10SSujith 
3674a22fe10SSujith 	mutex_lock(&priv->wmi->multi_write_mutex);
3684a22fe10SSujith 
3694a22fe10SSujith 	/* Store the register/value */
3704a22fe10SSujith 	priv->wmi->multi_write[priv->wmi->multi_write_idx].reg =
3714a22fe10SSujith 		cpu_to_be32(reg_offset);
3724a22fe10SSujith 	priv->wmi->multi_write[priv->wmi->multi_write_idx].val =
3734a22fe10SSujith 		cpu_to_be32(val);
3744a22fe10SSujith 
3754a22fe10SSujith 	priv->wmi->multi_write_idx++;
3764a22fe10SSujith 
3774a22fe10SSujith 	/* If the buffer is full, send it out. */
3784a22fe10SSujith 	if (priv->wmi->multi_write_idx == MAX_CMD_NUMBER) {
3794a22fe10SSujith 		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
3804a22fe10SSujith 			  (u8 *) &priv->wmi->multi_write,
3814a22fe10SSujith 			  sizeof(struct register_write) * priv->wmi->multi_write_idx,
3824a22fe10SSujith 			  (u8 *) &rsp_status, sizeof(rsp_status),
3834a22fe10SSujith 			  100);
3844a22fe10SSujith 		if (unlikely(r)) {
385d2182b69SJoe Perches 			ath_dbg(common, WMI,
3864a22fe10SSujith 				"REGISTER WRITE FAILED, multi len: %d\n",
3874a22fe10SSujith 				priv->wmi->multi_write_idx);
3884a22fe10SSujith 		}
3894a22fe10SSujith 		priv->wmi->multi_write_idx = 0;
3904a22fe10SSujith 	}
3914a22fe10SSujith 
3924a22fe10SSujith 	mutex_unlock(&priv->wmi->multi_write_mutex);
3934a22fe10SSujith }
3944a22fe10SSujith 
3954a22fe10SSujith static void ath9k_regwrite(void *hw_priv, u32 val, u32 reg_offset)
3964a22fe10SSujith {
3974a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
3984a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
3994a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
4004a22fe10SSujith 
4014a22fe10SSujith 	if (atomic_read(&priv->wmi->mwrite_cnt))
4024a22fe10SSujith 		ath9k_regwrite_buffer(hw_priv, val, reg_offset);
4034a22fe10SSujith 	else
4044a22fe10SSujith 		ath9k_regwrite_single(hw_priv, val, reg_offset);
4054a22fe10SSujith }
4064a22fe10SSujith 
4074a22fe10SSujith static void ath9k_enable_regwrite_buffer(void *hw_priv)
4084a22fe10SSujith {
4094a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
4104a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
4114a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
4124a22fe10SSujith 
4134a22fe10SSujith 	atomic_inc(&priv->wmi->mwrite_cnt);
4144a22fe10SSujith }
4154a22fe10SSujith 
4164a22fe10SSujith static void ath9k_regwrite_flush(void *hw_priv)
4174a22fe10SSujith {
4184a22fe10SSujith 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
4194a22fe10SSujith 	struct ath_common *common = ath9k_hw_common(ah);
4204a22fe10SSujith 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
4214a22fe10SSujith 	u32 rsp_status;
4224a22fe10SSujith 	int r;
4234a22fe10SSujith 
424435c1610SFelix Fietkau 	atomic_dec(&priv->wmi->mwrite_cnt);
425435c1610SFelix Fietkau 
4264a22fe10SSujith 	mutex_lock(&priv->wmi->multi_write_mutex);
4274a22fe10SSujith 
4284a22fe10SSujith 	if (priv->wmi->multi_write_idx) {
4294a22fe10SSujith 		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
4304a22fe10SSujith 			  (u8 *) &priv->wmi->multi_write,
4314a22fe10SSujith 			  sizeof(struct register_write) * priv->wmi->multi_write_idx,
4324a22fe10SSujith 			  (u8 *) &rsp_status, sizeof(rsp_status),
4334a22fe10SSujith 			  100);
4344a22fe10SSujith 		if (unlikely(r)) {
435d2182b69SJoe Perches 			ath_dbg(common, WMI,
4364a22fe10SSujith 				"REGISTER WRITE FAILED, multi len: %d\n",
4374a22fe10SSujith 				priv->wmi->multi_write_idx);
4384a22fe10SSujith 		}
4394a22fe10SSujith 		priv->wmi->multi_write_idx = 0;
4404a22fe10SSujith 	}
4414a22fe10SSujith 
4424a22fe10SSujith 	mutex_unlock(&priv->wmi->multi_write_mutex);
4434a22fe10SSujith }
4444a22fe10SSujith 
445845e03c9SFelix Fietkau static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr)
446845e03c9SFelix Fietkau {
447845e03c9SFelix Fietkau 	u32 val;
448845e03c9SFelix Fietkau 
449845e03c9SFelix Fietkau 	val = ath9k_regread(hw_priv, reg_offset);
450845e03c9SFelix Fietkau 	val &= ~clr;
451845e03c9SFelix Fietkau 	val |= set;
452845e03c9SFelix Fietkau 	ath9k_regwrite(hw_priv, val, reg_offset);
453845e03c9SFelix Fietkau 	return val;
454845e03c9SFelix Fietkau }
455845e03c9SFelix Fietkau 
456fb9987d0SSujith static void ath_usb_read_cachesize(struct ath_common *common, int *csz)
457fb9987d0SSujith {
458fb9987d0SSujith 	*csz = L1_CACHE_BYTES >> 2;
459fb9987d0SSujith }
460fb9987d0SSujith 
461fb9987d0SSujith static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
462fb9987d0SSujith {
463fb9987d0SSujith 	struct ath_hw *ah = (struct ath_hw *) common->ah;
464fb9987d0SSujith 
465fb9987d0SSujith 	(void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
466fb9987d0SSujith 
467fb9987d0SSujith 	if (!ath9k_hw_wait(ah,
468fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA,
469fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA_BUSY |
470fb9987d0SSujith 			   AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
471fb9987d0SSujith 			   AH_WAIT_TIMEOUT))
472fb9987d0SSujith 		return false;
473fb9987d0SSujith 
474fb9987d0SSujith 	*data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
475fb9987d0SSujith 		   AR_EEPROM_STATUS_DATA_VAL);
476fb9987d0SSujith 
477fb9987d0SSujith 	return true;
478fb9987d0SSujith }
479fb9987d0SSujith 
480fb9987d0SSujith static const struct ath_bus_ops ath9k_usb_bus_ops = {
481497ad9adSSujith 	.ath_bus_type = ATH_USB,
482fb9987d0SSujith 	.read_cachesize = ath_usb_read_cachesize,
483fb9987d0SSujith 	.eeprom_read = ath_usb_eeprom_read,
484fb9987d0SSujith };
485fb9987d0SSujith 
486fb9987d0SSujith static void setup_ht_cap(struct ath9k_htc_priv *priv,
487fb9987d0SSujith 			 struct ieee80211_sta_ht_cap *ht_info)
488fb9987d0SSujith {
4896debecadSSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
4906debecadSSujith 	u8 tx_streams, rx_streams;
4916debecadSSujith 	int i;
4926debecadSSujith 
493fb9987d0SSujith 	ht_info->ht_supported = true;
494fb9987d0SSujith 	ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
495fb9987d0SSujith 		       IEEE80211_HT_CAP_SM_PS |
496fb9987d0SSujith 		       IEEE80211_HT_CAP_SGI_40 |
497fb9987d0SSujith 		       IEEE80211_HT_CAP_DSSSCCK40;
498fb9987d0SSujith 
499b4dec5e8SSujith 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
500b4dec5e8SSujith 		ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
501b4dec5e8SSujith 
50217525f96SSujith 	ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
50317525f96SSujith 
504fb9987d0SSujith 	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
505fb9987d0SSujith 	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
506fb9987d0SSujith 
507fb9987d0SSujith 	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
5086debecadSSujith 
5096debecadSSujith 	/* ath9k_htc supports only 1 or 2 stream devices */
51082b2d334SFelix Fietkau 	tx_streams = ath9k_cmn_count_streams(priv->ah->txchainmask, 2);
51182b2d334SFelix Fietkau 	rx_streams = ath9k_cmn_count_streams(priv->ah->rxchainmask, 2);
5126debecadSSujith 
513d2182b69SJoe Perches 	ath_dbg(common, CONFIG, "TX streams %d, RX streams: %d\n",
5146debecadSSujith 		tx_streams, rx_streams);
5156debecadSSujith 
5166debecadSSujith 	if (tx_streams != rx_streams) {
5176debecadSSujith 		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
5186debecadSSujith 		ht_info->mcs.tx_params |= ((tx_streams - 1) <<
5196debecadSSujith 					   IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
5206debecadSSujith 	}
5216debecadSSujith 
5226debecadSSujith 	for (i = 0; i < rx_streams; i++)
5236debecadSSujith 		ht_info->mcs.rx_mask[i] = 0xff;
5246debecadSSujith 
525fb9987d0SSujith 	ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
526fb9987d0SSujith }
527fb9987d0SSujith 
528fb9987d0SSujith static int ath9k_init_queues(struct ath9k_htc_priv *priv)
529fb9987d0SSujith {
530fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
531fb9987d0SSujith 	int i;
532fb9987d0SSujith 
533fb9987d0SSujith 	for (i = 0; i < ARRAY_SIZE(priv->hwq_map); i++)
534fb9987d0SSujith 		priv->hwq_map[i] = -1;
535fb9987d0SSujith 
536ca74b83bSSujith 	priv->beaconq = ath9k_hw_beaconq_setup(priv->ah);
537ca74b83bSSujith 	if (priv->beaconq == -1) {
5383800276aSJoe Perches 		ath_err(common, "Unable to setup BEACON xmit queue\n");
539ca74b83bSSujith 		goto err;
540ca74b83bSSujith 	}
541ca74b83bSSujith 
542ca74b83bSSujith 	priv->cabq = ath9k_htc_cabq_setup(priv);
543ca74b83bSSujith 	if (priv->cabq == -1) {
5443800276aSJoe Perches 		ath_err(common, "Unable to setup CAB xmit queue\n");
545ca74b83bSSujith 		goto err;
546ca74b83bSSujith 	}
547ca74b83bSSujith 
548e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) {
5493800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for BE traffic\n");
550fb9987d0SSujith 		goto err;
551fb9987d0SSujith 	}
552fb9987d0SSujith 
553e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) {
5543800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for BK traffic\n");
555fb9987d0SSujith 		goto err;
556fb9987d0SSujith 	}
557e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) {
5583800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for VI traffic\n");
559fb9987d0SSujith 		goto err;
560fb9987d0SSujith 	}
561e8c35a77SFelix Fietkau 	if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) {
5623800276aSJoe Perches 		ath_err(common, "Unable to setup xmit queue for VO traffic\n");
563fb9987d0SSujith 		goto err;
564fb9987d0SSujith 	}
565fb9987d0SSujith 
566fb9987d0SSujith 	return 0;
567fb9987d0SSujith 
568fb9987d0SSujith err:
569fb9987d0SSujith 	return -EINVAL;
570fb9987d0SSujith }
571fb9987d0SSujith 
572fb9987d0SSujith static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
573fb9987d0SSujith {
574d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
575fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].channels =
576fb9987d0SSujith 			ath9k_2ghz_channels;
577fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
578fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].n_channels =
579fb9987d0SSujith 			ARRAY_SIZE(ath9k_2ghz_channels);
580fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
581fb9987d0SSujith 		priv->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
582fb9987d0SSujith 			ARRAY_SIZE(ath9k_legacy_rates);
583fb9987d0SSujith 	}
584ea46e644SSujith 
585d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
586ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels;
587ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
588ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].n_channels =
589ea46e644SSujith 			ARRAY_SIZE(ath9k_5ghz_channels);
590ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].bitrates =
591ea46e644SSujith 			ath9k_legacy_rates + 4;
592ea46e644SSujith 		priv->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
593ea46e644SSujith 			ARRAY_SIZE(ath9k_legacy_rates) - 4;
594ea46e644SSujith 	}
595fb9987d0SSujith }
596fb9987d0SSujith 
597fb9987d0SSujith static void ath9k_init_misc(struct ath9k_htc_priv *priv)
598fb9987d0SSujith {
599fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
600fb9987d0SSujith 
601fb9987d0SSujith 	memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
602fb9987d0SSujith 
6039f01a84eSSujith 	priv->ah->opmode = NL80211_IFTYPE_STATION;
604fb9987d0SSujith }
605fb9987d0SSujith 
60621cb9879SVivek Natarajan static int ath9k_init_priv(struct ath9k_htc_priv *priv,
607fa6e15e0SRajkumar Manoharan 			   u16 devid, char *product,
608fa6e15e0SRajkumar Manoharan 			   u32 drv_info)
609fb9987d0SSujith {
610fb9987d0SSujith 	struct ath_hw *ah = NULL;
611fb9987d0SSujith 	struct ath_common *common;
612832f6a18SSujith Manoharan 	int i, ret = 0, csz = 0;
613fb9987d0SSujith 
614d8a2c51cSSujith Manoharan 	set_bit(OP_INVALID, &priv->op_flags);
615fb9987d0SSujith 
616fb9987d0SSujith 	ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
617fb9987d0SSujith 	if (!ah)
618fb9987d0SSujith 		return -ENOMEM;
619fb9987d0SSujith 
620fb9987d0SSujith 	ah->hw_version.devid = devid;
6210b5ead91SSujith Manoharan 	ah->hw_version.usbdev = drv_info;
622f8afa42bSFelix Fietkau 	ah->ah_flags |= AH_USE_EEPROM;
623f9f84e96SFelix Fietkau 	ah->reg_ops.read = ath9k_regread;
624f9f84e96SFelix Fietkau 	ah->reg_ops.multi_read = ath9k_multi_regread;
625f9f84e96SFelix Fietkau 	ah->reg_ops.write = ath9k_regwrite;
626f9f84e96SFelix Fietkau 	ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer;
627f9f84e96SFelix Fietkau 	ah->reg_ops.write_flush = ath9k_regwrite_flush;
628845e03c9SFelix Fietkau 	ah->reg_ops.rmw = ath9k_reg_rmw;
629fb9987d0SSujith 	priv->ah = ah;
630fb9987d0SSujith 
631fb9987d0SSujith 	common = ath9k_hw_common(ah);
632f9f84e96SFelix Fietkau 	common->ops = &ah->reg_ops;
633fb9987d0SSujith 	common->bus_ops = &ath9k_usb_bus_ops;
634fb9987d0SSujith 	common->ah = ah;
635fb9987d0SSujith 	common->hw = priv->hw;
636fb9987d0SSujith 	common->priv = priv;
637fb9987d0SSujith 	common->debug_mask = ath9k_debug;
638fb9987d0SSujith 
639fb9987d0SSujith 	spin_lock_init(&priv->beacon_lock);
640658ef04fSSujith Manoharan 	spin_lock_init(&priv->tx.tx_lock);
641fb9987d0SSujith 	mutex_init(&priv->mutex);
642bde748a4SVivek Natarajan 	mutex_init(&priv->htc_pm_lock);
643fb9987d0SSujith 	tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
644fb9987d0SSujith 		     (unsigned long)priv);
64527876a29SSujith Manoharan 	tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet,
64673908674SSujith Manoharan 		     (unsigned long)priv);
647a236254cSSujith Manoharan 	INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work);
648bde748a4SVivek Natarajan 	INIT_WORK(&priv->ps_work, ath9k_ps_work);
64973908674SSujith Manoharan 	INIT_WORK(&priv->fatal_work, ath9k_fatal_work);
650859c3ca1SSujith Manoharan 	setup_timer(&priv->tx.cleanup_timer, ath9k_htc_tx_cleanup_timer,
651859c3ca1SSujith Manoharan 		    (unsigned long)priv);
652fb9987d0SSujith 
653fb9987d0SSujith 	/*
654fb9987d0SSujith 	 * Cache line size is used to size and align various
655fb9987d0SSujith 	 * structures used to communicate with the hardware.
656fb9987d0SSujith 	 */
657fb9987d0SSujith 	ath_read_cachesize(common, &csz);
658fb9987d0SSujith 	common->cachelsz = csz << 2; /* convert to bytes */
659fb9987d0SSujith 
660fb9987d0SSujith 	ret = ath9k_hw_init(ah);
661fb9987d0SSujith 	if (ret) {
6623800276aSJoe Perches 		ath_err(common,
6633800276aSJoe Perches 			"Unable to initialize hardware; initialization status: %d\n",
6643800276aSJoe Perches 			ret);
665fb9987d0SSujith 		goto err_hw;
666fb9987d0SSujith 	}
667fb9987d0SSujith 
668fb9987d0SSujith 	ret = ath9k_init_queues(priv);
669fb9987d0SSujith 	if (ret)
670fb9987d0SSujith 		goto err_queues;
671fb9987d0SSujith 
672832f6a18SSujith Manoharan 	for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)
673832f6a18SSujith Manoharan 		priv->cur_beacon_conf.bslot[i] = NULL;
674832f6a18SSujith Manoharan 
675f82b4bdeSRajkumar Manoharan 	ath9k_cmn_init_crypto(ah);
676fb9987d0SSujith 	ath9k_init_channels_rates(priv);
677fb9987d0SSujith 	ath9k_init_misc(priv);
678cee5341dSSujith Manoharan 	ath9k_htc_init_btcoex(priv, product);
67921cb9879SVivek Natarajan 
680fb9987d0SSujith 	return 0;
681fb9987d0SSujith 
682fb9987d0SSujith err_queues:
683fb9987d0SSujith 	ath9k_hw_deinit(ah);
684fb9987d0SSujith err_hw:
685fb9987d0SSujith 
686fb9987d0SSujith 	kfree(ah);
687fb9987d0SSujith 	priv->ah = NULL;
688fb9987d0SSujith 
689fb9987d0SSujith 	return ret;
690fb9987d0SSujith }
691fb9987d0SSujith 
692fb9987d0SSujith static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
693fb9987d0SSujith 			       struct ieee80211_hw *hw)
694fb9987d0SSujith {
695fb9987d0SSujith 	struct ath_common *common = ath9k_hw_common(priv->ah);
696fb9987d0SSujith 
697fb9987d0SSujith 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
698fb9987d0SSujith 		IEEE80211_HW_AMPDU_AGGREGATION |
699fb9987d0SSujith 		IEEE80211_HW_SPECTRUM_MGMT |
70032fbccafSSujith 		IEEE80211_HW_HAS_RATE_CONTROL |
701bde748a4SVivek Natarajan 		IEEE80211_HW_RX_INCLUDES_FCS |
702bde748a4SVivek Natarajan 		IEEE80211_HW_SUPPORTS_PS |
7037d547eb4SSujith Manoharan 		IEEE80211_HW_PS_NULLFUNC_STACK |
7048ae2e12fSRajkumar Manoharan 		IEEE80211_HW_REPORTS_TX_ACK_STATUS |
7057d547eb4SSujith Manoharan 		IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
706fb9987d0SSujith 
707fb9987d0SSujith 	hw->wiphy->interface_modes =
708fb9987d0SSujith 		BIT(NL80211_IFTYPE_STATION) |
70909d5b94dSSujith Manoharan 		BIT(NL80211_IFTYPE_ADHOC) |
71009d5b94dSSujith Manoharan 		BIT(NL80211_IFTYPE_AP) |
71109d5b94dSSujith Manoharan 		BIT(NL80211_IFTYPE_P2P_GO) |
71209d5b94dSSujith Manoharan 		BIT(NL80211_IFTYPE_P2P_CLIENT);
713fb9987d0SSujith 
714bde748a4SVivek Natarajan 	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
715bde748a4SVivek Natarajan 
71681ddbb5cSJohannes Berg 	hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN |
71781ddbb5cSJohannes Berg 			    WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
718d7d312caSAntonio Quartulli 
719fb9987d0SSujith 	hw->queues = 4;
720fb9987d0SSujith 	hw->channel_change_time = 5000;
721fb1c078eSSujith Manoharan 	hw->max_listen_interval = 1;
7223a0593efSSujith Manoharan 
723fb9987d0SSujith 	hw->vif_data_size = sizeof(struct ath9k_htc_vif);
724fb9987d0SSujith 	hw->sta_data_size = sizeof(struct ath9k_htc_sta);
725fb9987d0SSujith 
726fb9987d0SSujith 	/* tx_frame_hdr is larger than tx_mgmt_hdr anyway */
727fb9987d0SSujith 	hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) +
728fb9987d0SSujith 		sizeof(struct htc_frame_hdr) + 4;
729fb9987d0SSujith 
730d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
731fb9987d0SSujith 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
732fb9987d0SSujith 			&priv->sbands[IEEE80211_BAND_2GHZ];
733d4659912SFelix Fietkau 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
734ea46e644SSujith 		hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
735ea46e644SSujith 			&priv->sbands[IEEE80211_BAND_5GHZ];
736fb9987d0SSujith 
737fb9987d0SSujith 	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
738d4659912SFelix Fietkau 		if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
739fb9987d0SSujith 			setup_ht_cap(priv,
740fb9987d0SSujith 				     &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap);
741d4659912SFelix Fietkau 		if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
742ea46e644SSujith 			setup_ht_cap(priv,
743ea46e644SSujith 				     &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap);
744fb9987d0SSujith 	}
745fb9987d0SSujith 
746fb9987d0SSujith 	SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
747fb9987d0SSujith }
748fb9987d0SSujith 
74929bbfb24SSujith Manoharan static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv)
75029bbfb24SSujith Manoharan {
75129bbfb24SSujith Manoharan 	struct ieee80211_hw *hw = priv->hw;
75229bbfb24SSujith Manoharan 	struct wmi_fw_version cmd_rsp;
75329bbfb24SSujith Manoharan 	int ret;
75429bbfb24SSujith Manoharan 
75529bbfb24SSujith Manoharan 	memset(&cmd_rsp, 0, sizeof(cmd_rsp));
75629bbfb24SSujith Manoharan 
75729bbfb24SSujith Manoharan 	WMI_CMD(WMI_GET_FW_VERSION);
75829bbfb24SSujith Manoharan 	if (ret)
75929bbfb24SSujith Manoharan 		return -EINVAL;
76029bbfb24SSujith Manoharan 
76129bbfb24SSujith Manoharan 	priv->fw_version_major = be16_to_cpu(cmd_rsp.major);
76229bbfb24SSujith Manoharan 	priv->fw_version_minor = be16_to_cpu(cmd_rsp.minor);
76329bbfb24SSujith Manoharan 
76429bbfb24SSujith Manoharan 	snprintf(hw->wiphy->fw_version, ETHTOOL_BUSINFO_LEN, "%d.%d",
76529bbfb24SSujith Manoharan 		 priv->fw_version_major,
76629bbfb24SSujith Manoharan 		 priv->fw_version_minor);
76729bbfb24SSujith Manoharan 
76829bbfb24SSujith Manoharan 	dev_info(priv->dev, "ath9k_htc: FW Version: %d.%d\n",
76929bbfb24SSujith Manoharan 		 priv->fw_version_major,
77029bbfb24SSujith Manoharan 		 priv->fw_version_minor);
77129bbfb24SSujith Manoharan 
7723a0593efSSujith Manoharan 	/*
7733a0593efSSujith Manoharan 	 * Check if the available FW matches the driver's
7743a0593efSSujith Manoharan 	 * required version.
7753a0593efSSujith Manoharan 	 */
7763a0593efSSujith Manoharan 	if (priv->fw_version_major != MAJOR_VERSION_REQ ||
7773a0593efSSujith Manoharan 	    priv->fw_version_minor != MINOR_VERSION_REQ) {
7783a0593efSSujith Manoharan 		dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n",
7793a0593efSSujith Manoharan 			MAJOR_VERSION_REQ, MINOR_VERSION_REQ);
7803a0593efSSujith Manoharan 		return -EINVAL;
7813a0593efSSujith Manoharan 	}
7823a0593efSSujith Manoharan 
78329bbfb24SSujith Manoharan 	return 0;
78429bbfb24SSujith Manoharan }
78529bbfb24SSujith Manoharan 
78621cb9879SVivek Natarajan static int ath9k_init_device(struct ath9k_htc_priv *priv,
787fa6e15e0SRajkumar Manoharan 			     u16 devid, char *product, u32 drv_info)
788fb9987d0SSujith {
789fb9987d0SSujith 	struct ieee80211_hw *hw = priv->hw;
790fb9987d0SSujith 	struct ath_common *common;
791fb9987d0SSujith 	struct ath_hw *ah;
792fb9987d0SSujith 	int error = 0;
793fb9987d0SSujith 	struct ath_regulatory *reg;
7943e3f1d19SSujith Manoharan 	char hw_name[64];
795fb9987d0SSujith 
796fb9987d0SSujith 	/* Bring up device */
797fa6e15e0SRajkumar Manoharan 	error = ath9k_init_priv(priv, devid, product, drv_info);
798fb9987d0SSujith 	if (error != 0)
799fb9987d0SSujith 		goto err_init;
800fb9987d0SSujith 
801fb9987d0SSujith 	ah = priv->ah;
802fb9987d0SSujith 	common = ath9k_hw_common(ah);
803fb9987d0SSujith 	ath9k_set_hw_capab(priv, hw);
804fb9987d0SSujith 
80529bbfb24SSujith Manoharan 	error = ath9k_init_firmware_version(priv);
80629bbfb24SSujith Manoharan 	if (error != 0)
80729bbfb24SSujith Manoharan 		goto err_fw;
80829bbfb24SSujith Manoharan 
809fb9987d0SSujith 	/* Initialize regulatory */
810fb9987d0SSujith 	error = ath_regd_init(&common->regulatory, priv->hw->wiphy,
811fb9987d0SSujith 			      ath9k_reg_notifier);
812fb9987d0SSujith 	if (error)
813fb9987d0SSujith 		goto err_regd;
814fb9987d0SSujith 
815fb9987d0SSujith 	reg = &common->regulatory;
816fb9987d0SSujith 
817fb9987d0SSujith 	/* Setup TX */
818fb9987d0SSujith 	error = ath9k_tx_init(priv);
819fb9987d0SSujith 	if (error != 0)
820fb9987d0SSujith 		goto err_tx;
821fb9987d0SSujith 
822fb9987d0SSujith 	/* Setup RX */
823fb9987d0SSujith 	error = ath9k_rx_init(priv);
824fb9987d0SSujith 	if (error != 0)
825fb9987d0SSujith 		goto err_rx;
826fb9987d0SSujith 
827d244f21eSSujith Manoharan #ifdef CONFIG_MAC80211_LEDS
828d244f21eSSujith Manoharan 	/* must be initialized before ieee80211_register_hw */
829d244f21eSSujith Manoharan 	priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw,
830d244f21eSSujith Manoharan 		IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_htc_tpt_blink,
831d244f21eSSujith Manoharan 		ARRAY_SIZE(ath9k_htc_tpt_blink));
832d244f21eSSujith Manoharan #endif
833d244f21eSSujith Manoharan 
834fb9987d0SSujith 	/* Register with mac80211 */
835fb9987d0SSujith 	error = ieee80211_register_hw(hw);
836fb9987d0SSujith 	if (error)
837fb9987d0SSujith 		goto err_register;
838fb9987d0SSujith 
839fb9987d0SSujith 	/* Handle world regulatory */
840fb9987d0SSujith 	if (!ath_is_world_regd(reg)) {
841fb9987d0SSujith 		error = regulatory_hint(hw->wiphy, reg->alpha2);
842fb9987d0SSujith 		if (error)
843fb9987d0SSujith 			goto err_world;
844fb9987d0SSujith 	}
845fb9987d0SSujith 
846e5facc75SRajkumar Manoharan 	error = ath9k_htc_init_debug(priv->ah);
847e5facc75SRajkumar Manoharan 	if (error) {
848e5facc75SRajkumar Manoharan 		ath_err(common, "Unable to create debugfs files\n");
849e5facc75SRajkumar Manoharan 		goto err_world;
850e5facc75SRajkumar Manoharan 	}
851e5facc75SRajkumar Manoharan 
852d2182b69SJoe Perches 	ath_dbg(common, CONFIG,
853d2182b69SJoe Perches 		"WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, BE:%d, BK:%d, VI:%d, VO:%d\n",
8543e3f1d19SSujith Manoharan 		priv->wmi_cmd_ep,
8553e3f1d19SSujith Manoharan 		priv->beacon_ep,
8563e3f1d19SSujith Manoharan 		priv->cab_ep,
8573e3f1d19SSujith Manoharan 		priv->uapsd_ep,
8583e3f1d19SSujith Manoharan 		priv->mgmt_ep,
8593e3f1d19SSujith Manoharan 		priv->data_be_ep,
8603e3f1d19SSujith Manoharan 		priv->data_bk_ep,
8613e3f1d19SSujith Manoharan 		priv->data_vi_ep,
8623e3f1d19SSujith Manoharan 		priv->data_vo_ep);
8633e3f1d19SSujith Manoharan 
8643e3f1d19SSujith Manoharan 	ath9k_hw_name(priv->ah, hw_name, sizeof(hw_name));
8653e3f1d19SSujith Manoharan 	wiphy_info(hw->wiphy, "%s\n", hw_name);
8663e3f1d19SSujith Manoharan 
867fb9987d0SSujith 	ath9k_init_leds(priv);
868fb9987d0SSujith 	ath9k_start_rfkill_poll(priv);
869fb9987d0SSujith 
870fb9987d0SSujith 	return 0;
871fb9987d0SSujith 
872fb9987d0SSujith err_world:
873fb9987d0SSujith 	ieee80211_unregister_hw(hw);
874fb9987d0SSujith err_register:
875fb9987d0SSujith 	ath9k_rx_cleanup(priv);
876fb9987d0SSujith err_rx:
877fb9987d0SSujith 	ath9k_tx_cleanup(priv);
878fb9987d0SSujith err_tx:
879fb9987d0SSujith 	/* Nothing */
880fb9987d0SSujith err_regd:
88129bbfb24SSujith Manoharan 	/* Nothing */
88229bbfb24SSujith Manoharan err_fw:
883fb9987d0SSujith 	ath9k_deinit_priv(priv);
884fb9987d0SSujith err_init:
885fb9987d0SSujith 	return error;
886fb9987d0SSujith }
887fb9987d0SSujith 
888fb9987d0SSujith int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
889fa6e15e0SRajkumar Manoharan 			   u16 devid, char *product, u32 drv_info)
890fb9987d0SSujith {
891fb9987d0SSujith 	struct ieee80211_hw *hw;
892fb9987d0SSujith 	struct ath9k_htc_priv *priv;
893fb9987d0SSujith 	int ret;
894fb9987d0SSujith 
895fb9987d0SSujith 	hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops);
896fb9987d0SSujith 	if (!hw)
897fb9987d0SSujith 		return -ENOMEM;
898fb9987d0SSujith 
899fb9987d0SSujith 	priv = hw->priv;
900fb9987d0SSujith 	priv->hw = hw;
901fb9987d0SSujith 	priv->htc = htc_handle;
902fb9987d0SSujith 	priv->dev = dev;
903fb9987d0SSujith 	htc_handle->drv_priv = priv;
904fb9987d0SSujith 	SET_IEEE80211_DEV(hw, priv->dev);
905fb9987d0SSujith 
906fb9987d0SSujith 	ret = ath9k_htc_wait_for_target(priv);
907fb9987d0SSujith 	if (ret)
908fb9987d0SSujith 		goto err_free;
909fb9987d0SSujith 
910fb9987d0SSujith 	priv->wmi = ath9k_init_wmi(priv);
911fb9987d0SSujith 	if (!priv->wmi) {
912fb9987d0SSujith 		ret = -EINVAL;
913fb9987d0SSujith 		goto err_free;
914fb9987d0SSujith 	}
915fb9987d0SSujith 
916fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_htc_services(priv, devid, drv_info);
917fb9987d0SSujith 	if (ret)
918fb9987d0SSujith 		goto err_init;
919fb9987d0SSujith 
920fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_device(priv, devid, product, drv_info);
921fb9987d0SSujith 	if (ret)
922fb9987d0SSujith 		goto err_init;
923fb9987d0SSujith 
924fb9987d0SSujith 	return 0;
925fb9987d0SSujith 
926fb9987d0SSujith err_init:
927fb9987d0SSujith 	ath9k_deinit_wmi(priv);
928fb9987d0SSujith err_free:
929fb9987d0SSujith 	ieee80211_free_hw(hw);
930fb9987d0SSujith 	return ret;
931fb9987d0SSujith }
932fb9987d0SSujith 
933fb9987d0SSujith void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
934fb9987d0SSujith {
935fb9987d0SSujith 	if (htc_handle->drv_priv) {
936a3be14b7SSujith 
937a3be14b7SSujith 		/* Check if the device has been yanked out. */
938a3be14b7SSujith 		if (hotunplug)
93997dcec57SSujith Manoharan 			htc_handle->drv_priv->ah->ah_flags |= AH_UNPLUGGED;
940a3be14b7SSujith 
941fb9987d0SSujith 		ath9k_deinit_device(htc_handle->drv_priv);
942fb9987d0SSujith 		ath9k_deinit_wmi(htc_handle->drv_priv);
943fb9987d0SSujith 		ieee80211_free_hw(htc_handle->drv_priv->hw);
944fb9987d0SSujith 	}
945fb9987d0SSujith }
946fb9987d0SSujith 
947fb9987d0SSujith #ifdef CONFIG_PM
948f933ebedSSujith Manoharan 
949f933ebedSSujith Manoharan void ath9k_htc_suspend(struct htc_target *htc_handle)
950f933ebedSSujith Manoharan {
951f933ebedSSujith Manoharan 	ath9k_htc_setpower(htc_handle->drv_priv, ATH9K_PM_FULL_SLEEP);
952f933ebedSSujith Manoharan }
953f933ebedSSujith Manoharan 
954fb9987d0SSujith int ath9k_htc_resume(struct htc_target *htc_handle)
955fb9987d0SSujith {
956fa6e15e0SRajkumar Manoharan 	struct ath9k_htc_priv *priv = htc_handle->drv_priv;
957fb9987d0SSujith 	int ret;
958fb9987d0SSujith 
959fa6e15e0SRajkumar Manoharan 	ret = ath9k_htc_wait_for_target(priv);
960fb9987d0SSujith 	if (ret)
961fb9987d0SSujith 		return ret;
962fb9987d0SSujith 
963fa6e15e0SRajkumar Manoharan 	ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid,
9640b5ead91SSujith Manoharan 				      priv->ah->hw_version.usbdev);
965fb9987d0SSujith 	return ret;
966fb9987d0SSujith }
967fb9987d0SSujith #endif
968fb9987d0SSujith 
969fb9987d0SSujith static int __init ath9k_htc_init(void)
970fb9987d0SSujith {
971e5facc75SRajkumar Manoharan 	if (ath9k_hif_usb_init() < 0) {
972516304b0SJoe Perches 		pr_err("No USB devices found, driver not installed\n");
973e5facc75SRajkumar Manoharan 		return -ENODEV;
974fb9987d0SSujith 	}
975fb9987d0SSujith 
976fb9987d0SSujith 	return 0;
977fb9987d0SSujith }
978fb9987d0SSujith module_init(ath9k_htc_init);
979fb9987d0SSujith 
980fb9987d0SSujith static void __exit ath9k_htc_exit(void)
981fb9987d0SSujith {
982fb9987d0SSujith 	ath9k_hif_usb_exit();
983516304b0SJoe Perches 	pr_info("Driver unloaded\n");
984fb9987d0SSujith }
985fb9987d0SSujith module_exit(ath9k_htc_exit);
986