xref: /openbmc/linux/drivers/net/wireless/ath/ath6kl/wmi.c (revision e5090444be811ce45653969363be8fcb4c52d597)
1 /*
2  * Copyright (c) 2004-2011 Atheros Communications Inc.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <linux/ip.h>
18 #include "core.h"
19 #include "debug.h"
20 #include "testmode.h"
21 
22 static int ath6kl_wmi_sync_point(struct wmi *wmi);
23 
24 static const s32 wmi_rate_tbl[][2] = {
25 	/* {W/O SGI, with SGI} */
26 	{1000, 1000},
27 	{2000, 2000},
28 	{5500, 5500},
29 	{11000, 11000},
30 	{6000, 6000},
31 	{9000, 9000},
32 	{12000, 12000},
33 	{18000, 18000},
34 	{24000, 24000},
35 	{36000, 36000},
36 	{48000, 48000},
37 	{54000, 54000},
38 	{6500, 7200},
39 	{13000, 14400},
40 	{19500, 21700},
41 	{26000, 28900},
42 	{39000, 43300},
43 	{52000, 57800},
44 	{58500, 65000},
45 	{65000, 72200},
46 	{13500, 15000},
47 	{27000, 30000},
48 	{40500, 45000},
49 	{54000, 60000},
50 	{81000, 90000},
51 	{108000, 120000},
52 	{121500, 135000},
53 	{135000, 150000},
54 	{0, 0}
55 };
56 
57 /* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
58 static const u8 up_to_ac[] = {
59 	WMM_AC_BE,
60 	WMM_AC_BK,
61 	WMM_AC_BK,
62 	WMM_AC_BE,
63 	WMM_AC_VI,
64 	WMM_AC_VI,
65 	WMM_AC_VO,
66 	WMM_AC_VO,
67 };
68 
69 void ath6kl_wmi_set_control_ep(struct wmi *wmi, enum htc_endpoint_id ep_id)
70 {
71 	if (WARN_ON(ep_id == ENDPOINT_UNUSED || ep_id >= ENDPOINT_MAX))
72 		return;
73 
74 	wmi->ep_id = ep_id;
75 }
76 
77 enum htc_endpoint_id ath6kl_wmi_get_control_ep(struct wmi *wmi)
78 {
79 	return wmi->ep_id;
80 }
81 
82 /*  Performs DIX to 802.3 encapsulation for transmit packets.
83  *  Assumes the entire DIX header is contigous and that there is
84  *  enough room in the buffer for a 802.3 mac header and LLC+SNAP headers.
85  */
86 int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb)
87 {
88 	struct ath6kl_llc_snap_hdr *llc_hdr;
89 	struct ethhdr *eth_hdr;
90 	size_t new_len;
91 	__be16 type;
92 	u8 *datap;
93 	u16 size;
94 
95 	if (WARN_ON(skb == NULL))
96 		return -EINVAL;
97 
98 	size = sizeof(struct ath6kl_llc_snap_hdr) + sizeof(struct wmi_data_hdr);
99 	if (skb_headroom(skb) < size)
100 		return -ENOMEM;
101 
102 	eth_hdr = (struct ethhdr *) skb->data;
103 	type = eth_hdr->h_proto;
104 
105 	if (!is_ethertype(be16_to_cpu(type))) {
106 		ath6kl_dbg(ATH6KL_DBG_WMI,
107 			"%s: pkt is already in 802.3 format\n", __func__);
108 		return 0;
109 	}
110 
111 	new_len = skb->len - sizeof(*eth_hdr) + sizeof(*llc_hdr);
112 
113 	skb_push(skb, sizeof(struct ath6kl_llc_snap_hdr));
114 	datap = skb->data;
115 
116 	eth_hdr->h_proto = cpu_to_be16(new_len);
117 
118 	memcpy(datap, eth_hdr, sizeof(*eth_hdr));
119 
120 	llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap + sizeof(*eth_hdr));
121 	llc_hdr->dsap = 0xAA;
122 	llc_hdr->ssap = 0xAA;
123 	llc_hdr->cntl = 0x03;
124 	llc_hdr->org_code[0] = 0x0;
125 	llc_hdr->org_code[1] = 0x0;
126 	llc_hdr->org_code[2] = 0x0;
127 	llc_hdr->eth_type = type;
128 
129 	return 0;
130 }
131 
132 static int ath6kl_wmi_meta_add(struct wmi *wmi, struct sk_buff *skb,
133 			       u8 *version, void *tx_meta_info)
134 {
135 	struct wmi_tx_meta_v1 *v1;
136 	struct wmi_tx_meta_v2 *v2;
137 
138 	if (WARN_ON(skb == NULL || version == NULL))
139 		return -EINVAL;
140 
141 	switch (*version) {
142 	case WMI_META_VERSION_1:
143 		skb_push(skb, WMI_MAX_TX_META_SZ);
144 		v1 = (struct wmi_tx_meta_v1 *) skb->data;
145 		v1->pkt_id = 0;
146 		v1->rate_plcy_id = 0;
147 		*version = WMI_META_VERSION_1;
148 		break;
149 	case WMI_META_VERSION_2:
150 		skb_push(skb, WMI_MAX_TX_META_SZ);
151 		v2 = (struct wmi_tx_meta_v2 *) skb->data;
152 		memcpy(v2, (struct wmi_tx_meta_v2 *) tx_meta_info,
153 		       sizeof(struct wmi_tx_meta_v2));
154 		break;
155 	}
156 
157 	return 0;
158 }
159 
160 int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb,
161 			    u8 msg_type, bool more_data,
162 			    enum wmi_data_hdr_data_type data_type,
163 			    u8 meta_ver, void *tx_meta_info)
164 {
165 	struct wmi_data_hdr *data_hdr;
166 	int ret;
167 
168 	if (WARN_ON(skb == NULL))
169 		return -EINVAL;
170 
171 	if (tx_meta_info) {
172 		ret = ath6kl_wmi_meta_add(wmi, skb, &meta_ver, tx_meta_info);
173 		if (ret)
174 			return ret;
175 	}
176 
177 	skb_push(skb, sizeof(struct wmi_data_hdr));
178 
179 	data_hdr = (struct wmi_data_hdr *)skb->data;
180 	memset(data_hdr, 0, sizeof(struct wmi_data_hdr));
181 
182 	data_hdr->info = msg_type << WMI_DATA_HDR_MSG_TYPE_SHIFT;
183 	data_hdr->info |= data_type << WMI_DATA_HDR_DATA_TYPE_SHIFT;
184 
185 	if (more_data)
186 		data_hdr->info |=
187 		    WMI_DATA_HDR_MORE_MASK << WMI_DATA_HDR_MORE_SHIFT;
188 
189 	data_hdr->info2 = cpu_to_le16(meta_ver << WMI_DATA_HDR_META_SHIFT);
190 	data_hdr->info3 = 0;
191 
192 	return 0;
193 }
194 
195 static u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri)
196 {
197 	struct iphdr *ip_hdr = (struct iphdr *) pkt;
198 	u8 ip_pri;
199 
200 	/*
201 	 * Determine IPTOS priority
202 	 *
203 	 * IP-TOS - 8bits
204 	 *          : DSCP(6-bits) ECN(2-bits)
205 	 *          : DSCP - P2 P1 P0 X X X
206 	 * where (P2 P1 P0) form 802.1D
207 	 */
208 	ip_pri = ip_hdr->tos >> 5;
209 	ip_pri &= 0x7;
210 
211 	if ((layer2_pri & 0x7) > ip_pri)
212 		return (u8) layer2_pri & 0x7;
213 	else
214 		return ip_pri;
215 }
216 
217 int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, struct sk_buff *skb,
218 				       u32 layer2_priority, bool wmm_enabled,
219 				       u8 *ac)
220 {
221 	struct wmi_data_hdr *data_hdr;
222 	struct ath6kl_llc_snap_hdr *llc_hdr;
223 	struct wmi_create_pstream_cmd cmd;
224 	u32 meta_size, hdr_size;
225 	u16 ip_type = IP_ETHERTYPE;
226 	u8 stream_exist, usr_pri;
227 	u8 traffic_class = WMM_AC_BE;
228 	u8 *datap;
229 
230 	if (WARN_ON(skb == NULL))
231 		return -EINVAL;
232 
233 	datap = skb->data;
234 	data_hdr = (struct wmi_data_hdr *) datap;
235 
236 	meta_size = ((le16_to_cpu(data_hdr->info2) >> WMI_DATA_HDR_META_SHIFT) &
237 		     WMI_DATA_HDR_META_MASK) ? WMI_MAX_TX_META_SZ : 0;
238 
239 	if (!wmm_enabled) {
240 		/* If WMM is disabled all traffic goes as BE traffic */
241 		usr_pri = 0;
242 	} else {
243 		hdr_size = sizeof(struct ethhdr);
244 
245 		llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap +
246 							 sizeof(struct
247 								wmi_data_hdr) +
248 							 meta_size + hdr_size);
249 
250 		if (llc_hdr->eth_type == htons(ip_type)) {
251 			/*
252 			 * Extract the endpoint info from the TOS field
253 			 * in the IP header.
254 			 */
255 			usr_pri =
256 			   ath6kl_wmi_determine_user_priority(((u8 *) llc_hdr) +
257 					sizeof(struct ath6kl_llc_snap_hdr),
258 					layer2_priority);
259 		} else
260 			usr_pri = layer2_priority & 0x7;
261 	}
262 
263 	/* workaround for WMM S5 */
264 	if ((wmi->traffic_class == WMM_AC_VI) &&
265 	    ((usr_pri == 5) || (usr_pri == 4)))
266 		usr_pri = 1;
267 
268 	/* Convert user priority to traffic class */
269 	traffic_class = up_to_ac[usr_pri & 0x7];
270 
271 	wmi_data_hdr_set_up(data_hdr, usr_pri);
272 
273 	spin_lock_bh(&wmi->lock);
274 	stream_exist = wmi->fat_pipe_exist;
275 	spin_unlock_bh(&wmi->lock);
276 
277 	if (!(stream_exist & (1 << traffic_class))) {
278 		memset(&cmd, 0, sizeof(cmd));
279 		cmd.traffic_class = traffic_class;
280 		cmd.user_pri = usr_pri;
281 		cmd.inactivity_int =
282 			cpu_to_le32(WMI_IMPLICIT_PSTREAM_INACTIVITY_INT);
283 		/* Implicit streams are created with TSID 0xFF */
284 		cmd.tsid = WMI_IMPLICIT_PSTREAM;
285 		ath6kl_wmi_create_pstream_cmd(wmi, &cmd);
286 	}
287 
288 	*ac = traffic_class;
289 
290 	return 0;
291 }
292 
293 int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb)
294 {
295 	struct ieee80211_hdr_3addr *pwh, wh;
296 	struct ath6kl_llc_snap_hdr *llc_hdr;
297 	struct ethhdr eth_hdr;
298 	u32 hdr_size;
299 	u8 *datap;
300 	__le16 sub_type;
301 
302 	if (WARN_ON(skb == NULL))
303 		return -EINVAL;
304 
305 	datap = skb->data;
306 	pwh = (struct ieee80211_hdr_3addr *) datap;
307 
308 	sub_type = pwh->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE);
309 
310 	memcpy((u8 *) &wh, datap, sizeof(struct ieee80211_hdr_3addr));
311 
312 	/* Strip off the 802.11 header */
313 	if (sub_type == cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
314 		hdr_size = roundup(sizeof(struct ieee80211_qos_hdr),
315 				   sizeof(u32));
316 		skb_pull(skb, hdr_size);
317 	} else if (sub_type == cpu_to_le16(IEEE80211_STYPE_DATA))
318 		skb_pull(skb, sizeof(struct ieee80211_hdr_3addr));
319 
320 	datap = skb->data;
321 	llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap);
322 
323 	memset(&eth_hdr, 0, sizeof(eth_hdr));
324 	eth_hdr.h_proto = llc_hdr->eth_type;
325 
326 	switch ((le16_to_cpu(wh.frame_control)) &
327 		(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
328 	case 0:
329 		memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN);
330 		memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN);
331 		break;
332 	case IEEE80211_FCTL_TODS:
333 		memcpy(eth_hdr.h_dest, wh.addr3, ETH_ALEN);
334 		memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN);
335 		break;
336 	case IEEE80211_FCTL_FROMDS:
337 		memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN);
338 		memcpy(eth_hdr.h_source, wh.addr3, ETH_ALEN);
339 		break;
340 	case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
341 		break;
342 	}
343 
344 	skb_pull(skb, sizeof(struct ath6kl_llc_snap_hdr));
345 	skb_push(skb, sizeof(eth_hdr));
346 
347 	datap = skb->data;
348 
349 	memcpy(datap, &eth_hdr, sizeof(eth_hdr));
350 
351 	return 0;
352 }
353 
354 /*
355  * Performs 802.3 to DIX encapsulation for received packets.
356  * Assumes the entire 802.3 header is contigous.
357  */
358 int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb)
359 {
360 	struct ath6kl_llc_snap_hdr *llc_hdr;
361 	struct ethhdr eth_hdr;
362 	u8 *datap;
363 
364 	if (WARN_ON(skb == NULL))
365 		return -EINVAL;
366 
367 	datap = skb->data;
368 
369 	memcpy(&eth_hdr, datap, sizeof(eth_hdr));
370 
371 	llc_hdr = (struct ath6kl_llc_snap_hdr *) (datap + sizeof(eth_hdr));
372 	eth_hdr.h_proto = llc_hdr->eth_type;
373 
374 	skb_pull(skb, sizeof(struct ath6kl_llc_snap_hdr));
375 	datap = skb->data;
376 
377 	memcpy(datap, &eth_hdr, sizeof(eth_hdr));
378 
379 	return 0;
380 }
381 
382 static void ath6kl_wmi_convert_bssinfo_hdr2_to_hdr(struct sk_buff *skb,
383 						   u8 *datap)
384 {
385 	struct wmi_bss_info_hdr2 bih2;
386 	struct wmi_bss_info_hdr *bih;
387 
388 	memcpy(&bih2, datap, sizeof(struct wmi_bss_info_hdr2));
389 
390 	skb_push(skb, 4);
391 	bih = (struct wmi_bss_info_hdr *) skb->data;
392 
393 	bih->ch = bih2.ch;
394 	bih->frame_type = bih2.frame_type;
395 	bih->snr = bih2.snr;
396 	bih->rssi = a_cpu_to_sle16(bih2.snr - 95);
397 	bih->ie_mask = cpu_to_le32(le16_to_cpu(bih2.ie_mask));
398 	memcpy(bih->bssid, bih2.bssid, ETH_ALEN);
399 }
400 
401 static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len)
402 {
403 	struct tx_complete_msg_v1 *msg_v1;
404 	struct wmi_tx_complete_event *evt;
405 	int index;
406 	u16 size;
407 
408 	evt = (struct wmi_tx_complete_event *) datap;
409 
410 	ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n",
411 		   evt->num_msg, evt->msg_len, evt->msg_type);
412 
413 	if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_WMI))
414 		return 0;
415 
416 	for (index = 0; index < evt->num_msg; index++) {
417 		size = sizeof(struct wmi_tx_complete_event) +
418 		    (index * sizeof(struct tx_complete_msg_v1));
419 		msg_v1 = (struct tx_complete_msg_v1 *)(datap + size);
420 
421 		ath6kl_dbg(ATH6KL_DBG_WMI, "msg: %d %d %d %d\n",
422 			   msg_v1->status, msg_v1->pkt_id,
423 			   msg_v1->rate_idx, msg_v1->ack_failures);
424 	}
425 
426 	return 0;
427 }
428 
429 static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap,
430 					      int len)
431 {
432 	struct wmi_remain_on_chnl_event *ev;
433 	u32 freq;
434 	u32 dur;
435 	struct ieee80211_channel *chan;
436 	struct ath6kl *ar = wmi->parent_dev;
437 
438 	if (len < sizeof(*ev))
439 		return -EINVAL;
440 
441 	ev = (struct wmi_remain_on_chnl_event *) datap;
442 	freq = le32_to_cpu(ev->freq);
443 	dur = le32_to_cpu(ev->duration);
444 	ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: freq=%u dur=%u\n",
445 		   freq, dur);
446 	chan = ieee80211_get_channel(ar->wdev->wiphy, freq);
447 	if (!chan) {
448 		ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: Unknown channel "
449 			   "(freq=%u)\n", freq);
450 		return -EINVAL;
451 	}
452 	cfg80211_ready_on_channel(ar->net_dev, 1, chan, NL80211_CHAN_NO_HT,
453 				  dur, GFP_ATOMIC);
454 
455 	return 0;
456 }
457 
458 static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi,
459 						     u8 *datap, int len)
460 {
461 	struct wmi_cancel_remain_on_chnl_event *ev;
462 	u32 freq;
463 	u32 dur;
464 	struct ieee80211_channel *chan;
465 	struct ath6kl *ar = wmi->parent_dev;
466 
467 	if (len < sizeof(*ev))
468 		return -EINVAL;
469 
470 	ev = (struct wmi_cancel_remain_on_chnl_event *) datap;
471 	freq = le32_to_cpu(ev->freq);
472 	dur = le32_to_cpu(ev->duration);
473 	ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: freq=%u dur=%u "
474 		   "status=%u\n", freq, dur, ev->status);
475 	chan = ieee80211_get_channel(ar->wdev->wiphy, freq);
476 	if (!chan) {
477 		ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: Unknown "
478 			   "channel (freq=%u)\n", freq);
479 		return -EINVAL;
480 	}
481 	cfg80211_remain_on_channel_expired(ar->net_dev, 1, chan,
482 					   NL80211_CHAN_NO_HT, GFP_ATOMIC);
483 
484 	return 0;
485 }
486 
487 static int ath6kl_wmi_tx_status_event_rx(struct wmi *wmi, u8 *datap, int len)
488 {
489 	struct wmi_tx_status_event *ev;
490 	u32 id;
491 	struct ath6kl *ar = wmi->parent_dev;
492 
493 	if (len < sizeof(*ev))
494 		return -EINVAL;
495 
496 	ev = (struct wmi_tx_status_event *) datap;
497 	id = le32_to_cpu(ev->id);
498 	ath6kl_dbg(ATH6KL_DBG_WMI, "tx_status: id=%x ack_status=%u\n",
499 		   id, ev->ack_status);
500 	if (wmi->last_mgmt_tx_frame) {
501 		cfg80211_mgmt_tx_status(ar->net_dev, id,
502 					wmi->last_mgmt_tx_frame,
503 					wmi->last_mgmt_tx_frame_len,
504 					!!ev->ack_status, GFP_ATOMIC);
505 		kfree(wmi->last_mgmt_tx_frame);
506 		wmi->last_mgmt_tx_frame = NULL;
507 		wmi->last_mgmt_tx_frame_len = 0;
508 	}
509 
510 	return 0;
511 }
512 
513 static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len)
514 {
515 	struct wmi_p2p_rx_probe_req_event *ev;
516 	u32 freq;
517 	u16 dlen;
518 	struct ath6kl *ar = wmi->parent_dev;
519 
520 	if (len < sizeof(*ev))
521 		return -EINVAL;
522 
523 	ev = (struct wmi_p2p_rx_probe_req_event *) datap;
524 	freq = le32_to_cpu(ev->freq);
525 	dlen = le16_to_cpu(ev->len);
526 	if (datap + len < ev->data + dlen) {
527 		ath6kl_err("invalid wmi_p2p_rx_probe_req_event: "
528 			   "len=%d dlen=%u\n", len, dlen);
529 		return -EINVAL;
530 	}
531 	ath6kl_dbg(ATH6KL_DBG_WMI, "rx_probe_req: len=%u freq=%u "
532 		   "probe_req_report=%d\n",
533 		   dlen, freq, ar->probe_req_report);
534 
535 	if (ar->probe_req_report || ar->nw_type == AP_NETWORK)
536 		cfg80211_rx_mgmt(ar->net_dev, freq, ev->data, dlen, GFP_ATOMIC);
537 
538 	return 0;
539 }
540 
541 static int ath6kl_wmi_p2p_capabilities_event_rx(u8 *datap, int len)
542 {
543 	struct wmi_p2p_capabilities_event *ev;
544 	u16 dlen;
545 
546 	if (len < sizeof(*ev))
547 		return -EINVAL;
548 
549 	ev = (struct wmi_p2p_capabilities_event *) datap;
550 	dlen = le16_to_cpu(ev->len);
551 	ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_capab: len=%u\n", dlen);
552 
553 	return 0;
554 }
555 
556 static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len)
557 {
558 	struct wmi_rx_action_event *ev;
559 	u32 freq;
560 	u16 dlen;
561 	struct ath6kl *ar = wmi->parent_dev;
562 
563 	if (len < sizeof(*ev))
564 		return -EINVAL;
565 
566 	ev = (struct wmi_rx_action_event *) datap;
567 	freq = le32_to_cpu(ev->freq);
568 	dlen = le16_to_cpu(ev->len);
569 	if (datap + len < ev->data + dlen) {
570 		ath6kl_err("invalid wmi_rx_action_event: "
571 			   "len=%d dlen=%u\n", len, dlen);
572 		return -EINVAL;
573 	}
574 	ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq);
575 	cfg80211_rx_mgmt(ar->net_dev, freq, ev->data, dlen, GFP_ATOMIC);
576 
577 	return 0;
578 }
579 
580 static int ath6kl_wmi_p2p_info_event_rx(u8 *datap, int len)
581 {
582 	struct wmi_p2p_info_event *ev;
583 	u32 flags;
584 	u16 dlen;
585 
586 	if (len < sizeof(*ev))
587 		return -EINVAL;
588 
589 	ev = (struct wmi_p2p_info_event *) datap;
590 	flags = le32_to_cpu(ev->info_req_flags);
591 	dlen = le16_to_cpu(ev->len);
592 	ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: flags=%x len=%d\n", flags, dlen);
593 
594 	if (flags & P2P_FLAG_CAPABILITIES_REQ) {
595 		struct wmi_p2p_capabilities *cap;
596 		if (dlen < sizeof(*cap))
597 			return -EINVAL;
598 		cap = (struct wmi_p2p_capabilities *) ev->data;
599 		ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: GO Power Save = %d\n",
600 			   cap->go_power_save);
601 	}
602 
603 	if (flags & P2P_FLAG_MACADDR_REQ) {
604 		struct wmi_p2p_macaddr *mac;
605 		if (dlen < sizeof(*mac))
606 			return -EINVAL;
607 		mac = (struct wmi_p2p_macaddr *) ev->data;
608 		ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: MAC Address = %pM\n",
609 			   mac->mac_addr);
610 	}
611 
612 	if (flags & P2P_FLAG_HMODEL_REQ) {
613 		struct wmi_p2p_hmodel *mod;
614 		if (dlen < sizeof(*mod))
615 			return -EINVAL;
616 		mod = (struct wmi_p2p_hmodel *) ev->data;
617 		ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: P2P Model = %d (%s)\n",
618 			   mod->p2p_model,
619 			   mod->p2p_model ? "host" : "firmware");
620 	}
621 	return 0;
622 }
623 
624 static inline struct sk_buff *ath6kl_wmi_get_new_buf(u32 size)
625 {
626 	struct sk_buff *skb;
627 
628 	skb = ath6kl_buf_alloc(size);
629 	if (!skb)
630 		return NULL;
631 
632 	skb_put(skb, size);
633 	if (size)
634 		memset(skb->data, 0, size);
635 
636 	return skb;
637 }
638 
639 /* Send a "simple" wmi command -- one with no arguments */
640 static int ath6kl_wmi_simple_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id)
641 {
642 	struct sk_buff *skb;
643 	int ret;
644 
645 	skb = ath6kl_wmi_get_new_buf(0);
646 	if (!skb)
647 		return -ENOMEM;
648 
649 	ret = ath6kl_wmi_cmd_send(wmi, skb, cmd_id, NO_SYNC_WMIFLAG);
650 
651 	return ret;
652 }
653 
654 static int ath6kl_wmi_ready_event_rx(struct wmi *wmi, u8 *datap, int len)
655 {
656 	struct wmi_ready_event_2 *ev = (struct wmi_ready_event_2 *) datap;
657 
658 	if (len < sizeof(struct wmi_ready_event_2))
659 		return -EINVAL;
660 
661 	wmi->ready = true;
662 	ath6kl_ready_event(wmi->parent_dev, ev->mac_addr,
663 			   le32_to_cpu(ev->sw_version),
664 			   le32_to_cpu(ev->abi_version));
665 
666 	return 0;
667 }
668 
669 /*
670  * Mechanism to modify the roaming behavior in the firmware. The lower rssi
671  * at which the station has to roam can be passed with
672  * WMI_SET_LRSSI_SCAN_PARAMS. Subtract 96 from RSSI to get the signal level
673  * in dBm.
674  */
675 int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi)
676 {
677 	struct sk_buff *skb;
678 	struct roam_ctrl_cmd *cmd;
679 
680 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
681 	if (!skb)
682 		return -ENOMEM;
683 
684 	cmd = (struct roam_ctrl_cmd *) skb->data;
685 
686 	cmd->info.params.lrssi_scan_period = cpu_to_le16(DEF_LRSSI_SCAN_PERIOD);
687 	cmd->info.params.lrssi_scan_threshold = a_cpu_to_sle16(lrssi +
688 						       DEF_SCAN_FOR_ROAM_INTVL);
689 	cmd->info.params.lrssi_roam_threshold = a_cpu_to_sle16(lrssi);
690 	cmd->info.params.roam_rssi_floor = DEF_LRSSI_ROAM_FLOOR;
691 	cmd->roam_ctrl = WMI_SET_LRSSI_SCAN_PARAMS;
692 
693 	ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_ROAM_CTRL_CMDID, NO_SYNC_WMIFLAG);
694 
695 	return 0;
696 }
697 
698 static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len)
699 {
700 	struct wmi_connect_event *ev;
701 	u8 *pie, *peie;
702 
703 	if (len < sizeof(struct wmi_connect_event))
704 		return -EINVAL;
705 
706 	ev = (struct wmi_connect_event *) datap;
707 
708 	ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM\n",
709 		   __func__, ev->ch, ev->bssid);
710 
711 	/* Start of assoc rsp IEs */
712 	pie = ev->assoc_info + ev->beacon_ie_len +
713 	      ev->assoc_req_len + (sizeof(u16) * 3); /* capinfo, status, aid */
714 
715 	/* End of assoc rsp IEs */
716 	peie = ev->assoc_info + ev->beacon_ie_len + ev->assoc_req_len +
717 	    ev->assoc_resp_len;
718 
719 	while (pie < peie) {
720 		switch (*pie) {
721 		case WLAN_EID_VENDOR_SPECIFIC:
722 			if (pie[1] > 3 && pie[2] == 0x00 && pie[3] == 0x50 &&
723 			    pie[4] == 0xf2 && pie[5] == WMM_OUI_TYPE) {
724 				/* WMM OUT (00:50:F2) */
725 				if (pie[1] > 5
726 				    && pie[6] == WMM_PARAM_OUI_SUBTYPE)
727 					wmi->is_wmm_enabled = true;
728 			}
729 			break;
730 		}
731 
732 		if (wmi->is_wmm_enabled)
733 			break;
734 
735 		pie += pie[1] + 2;
736 	}
737 
738 	ath6kl_connect_event(wmi->parent_dev, le16_to_cpu(ev->ch), ev->bssid,
739 			     le16_to_cpu(ev->listen_intvl),
740 			     le16_to_cpu(ev->beacon_intvl),
741 			     le32_to_cpu(ev->nw_type),
742 			     ev->beacon_ie_len, ev->assoc_req_len,
743 			     ev->assoc_resp_len, ev->assoc_info);
744 
745 	return 0;
746 }
747 
748 static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len)
749 {
750 	struct wmi_disconnect_event *ev;
751 	wmi->traffic_class = 100;
752 
753 	if (len < sizeof(struct wmi_disconnect_event))
754 		return -EINVAL;
755 
756 	ev = (struct wmi_disconnect_event *) datap;
757 
758 	wmi->is_wmm_enabled = false;
759 	wmi->pair_crypto_type = NONE_CRYPT;
760 	wmi->grp_crypto_type = NONE_CRYPT;
761 
762 	ath6kl_disconnect_event(wmi->parent_dev, ev->disconn_reason,
763 				ev->bssid, ev->assoc_resp_len, ev->assoc_info,
764 				le16_to_cpu(ev->proto_reason_status));
765 
766 	return 0;
767 }
768 
769 static int ath6kl_wmi_peer_node_event_rx(struct wmi *wmi, u8 *datap, int len)
770 {
771 	struct wmi_peer_node_event *ev;
772 
773 	if (len < sizeof(struct wmi_peer_node_event))
774 		return -EINVAL;
775 
776 	ev = (struct wmi_peer_node_event *) datap;
777 
778 	if (ev->event_code == PEER_NODE_JOIN_EVENT)
779 		ath6kl_dbg(ATH6KL_DBG_WMI, "joined node with mac addr: %pM\n",
780 			   ev->peer_mac_addr);
781 	else if (ev->event_code == PEER_NODE_LEAVE_EVENT)
782 		ath6kl_dbg(ATH6KL_DBG_WMI, "left node with mac addr: %pM\n",
783 			   ev->peer_mac_addr);
784 
785 	return 0;
786 }
787 
788 static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len)
789 {
790 	struct wmi_tkip_micerr_event *ev;
791 
792 	if (len < sizeof(struct wmi_tkip_micerr_event))
793 		return -EINVAL;
794 
795 	ev = (struct wmi_tkip_micerr_event *) datap;
796 
797 	ath6kl_tkip_micerr_event(wmi->parent_dev, ev->key_id, ev->is_mcast);
798 
799 	return 0;
800 }
801 
802 static int ath6kl_wlan_parse_beacon(u8 *buf, int frame_len,
803 				    struct ath6kl_common_ie *cie)
804 {
805 	u8 *frm, *efrm;
806 	u8 elemid_ssid = false;
807 
808 	frm = buf;
809 	efrm = (u8 *) (frm + frame_len);
810 
811 	/*
812 	 * beacon/probe response frame format
813 	 *  [8] time stamp
814 	 *  [2] beacon interval
815 	 *  [2] capability information
816 	 *  [tlv] ssid
817 	 *  [tlv] supported rates
818 	 *  [tlv] country information
819 	 *  [tlv] parameter set (FH/DS)
820 	 *  [tlv] erp information
821 	 *  [tlv] extended supported rates
822 	 *  [tlv] WMM
823 	 *  [tlv] WPA or RSN
824 	 *  [tlv] Atheros Advanced Capabilities
825 	 */
826 	if ((efrm - frm) < 12)
827 		return -EINVAL;
828 
829 	memset(cie, 0, sizeof(*cie));
830 
831 	cie->ie_tstamp = frm;
832 	frm += 8;
833 	cie->ie_beaconInt = *(u16 *) frm;
834 	frm += 2;
835 	cie->ie_capInfo = *(u16 *) frm;
836 	frm += 2;
837 	cie->ie_chan = 0;
838 
839 	while (frm < efrm) {
840 		switch (*frm) {
841 		case WLAN_EID_SSID:
842 			if (!elemid_ssid) {
843 				cie->ie_ssid = frm;
844 				elemid_ssid = true;
845 			}
846 			break;
847 		case WLAN_EID_SUPP_RATES:
848 			cie->ie_rates = frm;
849 			break;
850 		case WLAN_EID_COUNTRY:
851 			cie->ie_country = frm;
852 			break;
853 		case WLAN_EID_FH_PARAMS:
854 			break;
855 		case WLAN_EID_DS_PARAMS:
856 			cie->ie_chan = frm[2];
857 			break;
858 		case WLAN_EID_TIM:
859 			cie->ie_tim = frm;
860 			break;
861 		case WLAN_EID_IBSS_PARAMS:
862 			break;
863 		case WLAN_EID_EXT_SUPP_RATES:
864 			cie->ie_xrates = frm;
865 			break;
866 		case WLAN_EID_ERP_INFO:
867 			if (frm[1] != 1)
868 				return -EINVAL;
869 
870 			cie->ie_erp = frm[2];
871 			break;
872 		case WLAN_EID_RSN:
873 			cie->ie_rsn = frm;
874 			break;
875 		case WLAN_EID_HT_CAPABILITY:
876 			cie->ie_htcap = frm;
877 			break;
878 		case WLAN_EID_HT_INFORMATION:
879 			cie->ie_htop = frm;
880 			break;
881 		case WLAN_EID_VENDOR_SPECIFIC:
882 			if (frm[1] > 3 && frm[2] == 0x00 && frm[3] == 0x50 &&
883 			    frm[4] == 0xf2) {
884 				/* OUT Type (00:50:F2) */
885 
886 				if (frm[5] == WPA_OUI_TYPE) {
887 					/* WPA OUT */
888 					cie->ie_wpa = frm;
889 				} else if (frm[5] == WMM_OUI_TYPE) {
890 					/* WMM OUT */
891 					cie->ie_wmm = frm;
892 				} else if (frm[5] == WSC_OUT_TYPE) {
893 					/* WSC OUT */
894 					cie->ie_wsc = frm;
895 				}
896 
897 			} else if (frm[1] > 3 && frm[2] == 0x00
898 				   && frm[3] == 0x03 && frm[4] == 0x7f
899 				   && frm[5] == ATH_OUI_TYPE) {
900 				/* Atheros OUI (00:03:7f) */
901 				cie->ie_ath = frm;
902 			}
903 			break;
904 		default:
905 			break;
906 		}
907 		frm += frm[1] + 2;
908 	}
909 
910 	if ((cie->ie_rates == NULL)
911 	    || (cie->ie_rates[1] > ATH6KL_RATE_MAXSIZE))
912 		return -EINVAL;
913 
914 	if ((cie->ie_ssid == NULL)
915 	    || (cie->ie_ssid[1] > IEEE80211_MAX_SSID_LEN))
916 		return -EINVAL;
917 
918 	return 0;
919 }
920 
921 static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len)
922 {
923 	struct bss *bss = NULL;
924 	struct wmi_bss_info_hdr *bih;
925 	u8 cached_ssid_len = 0;
926 	u8 cached_ssid[IEEE80211_MAX_SSID_LEN] = { 0 };
927 	u8 beacon_ssid_len = 0;
928 	u8 *buf, *ie_ssid;
929 	u8 *ni_buf;
930 	int buf_len;
931 
932 	int ret;
933 
934 	if (len <= sizeof(struct wmi_bss_info_hdr))
935 		return -EINVAL;
936 
937 	bih = (struct wmi_bss_info_hdr *) datap;
938 	bss = wlan_find_node(&wmi->parent_dev->scan_table, bih->bssid);
939 
940 	if (a_sle16_to_cpu(bih->rssi) > 0) {
941 		if (bss == NULL)
942 			return 0;
943 		else
944 			bih->rssi = a_cpu_to_sle16(bss->ni_rssi);
945 	}
946 
947 	buf = datap + sizeof(struct wmi_bss_info_hdr);
948 	len -= sizeof(struct wmi_bss_info_hdr);
949 
950 	ath6kl_dbg(ATH6KL_DBG_WMI,
951 		   "bss info evt - ch %u, rssi %02x, bssid \"%pM\"\n",
952 		   bih->ch, a_sle16_to_cpu(bih->rssi), bih->bssid);
953 
954 	if (bss != NULL) {
955 		/*
956 		 * Free up the node. We are about to allocate a new node.
957 		 * In case of hidden AP, beacon will not have ssid,
958 		 * but a directed probe response will have it,
959 		 * so cache the probe-resp-ssid if already present.
960 		 */
961 		if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE)) {
962 			ie_ssid = bss->ni_cie.ie_ssid;
963 			if (ie_ssid && (ie_ssid[1] <= IEEE80211_MAX_SSID_LEN) &&
964 			    (ie_ssid[2] != 0)) {
965 				cached_ssid_len = ie_ssid[1];
966 				memcpy(cached_ssid, ie_ssid + 2,
967 				       cached_ssid_len);
968 			}
969 		}
970 
971 		/*
972 		 * Use the current average rssi of associated AP base on
973 		 * assumption
974 		 *   1. Most os with GUI will update RSSI by
975 		 *      ath6kl_wmi_get_stats_cmd() periodically.
976 		 *   2. ath6kl_wmi_get_stats_cmd(..) will be called when calling
977 		 *      ath6kl_wmi_startscan_cmd(...)
978 		 * The average value of RSSI give end-user better feeling for
979 		 * instance value of scan result. It also sync up RSSI info
980 		 * in GUI between scan result and RSSI signal icon.
981 		 */
982 		if (memcmp(wmi->parent_dev->bssid, bih->bssid, ETH_ALEN) == 0) {
983 			bih->rssi = a_cpu_to_sle16(bss->ni_rssi);
984 			bih->snr = bss->ni_snr;
985 		}
986 
987 		wlan_node_reclaim(&wmi->parent_dev->scan_table, bss);
988 	}
989 
990 	/*
991 	 * beacon/probe response frame format
992 	 *  [8] time stamp
993 	 *  [2] beacon interval
994 	 *  [2] capability information
995 	 *  [tlv] ssid
996 	 */
997 	beacon_ssid_len = buf[SSID_IE_LEN_INDEX];
998 
999 	/*
1000 	 * If ssid is cached for this hidden AP, then change
1001 	 * buffer len accordingly.
1002 	 */
1003 	if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE) &&
1004 	    (cached_ssid_len != 0) &&
1005 	    (beacon_ssid_len == 0 || (cached_ssid_len > beacon_ssid_len &&
1006 				      buf[SSID_IE_LEN_INDEX + 1] == 0))) {
1007 
1008 		len += (cached_ssid_len - beacon_ssid_len);
1009 	}
1010 
1011 	bss = wlan_node_alloc(len);
1012 	if (!bss)
1013 		return -ENOMEM;
1014 
1015 	bss->ni_snr = bih->snr;
1016 	bss->ni_rssi = a_sle16_to_cpu(bih->rssi);
1017 
1018 	if (WARN_ON(!bss->ni_buf))
1019 		return -EINVAL;
1020 
1021 	/*
1022 	 * In case of hidden AP, beacon will not have ssid,
1023 	 * but a directed probe response will have it,
1024 	 * so place the cached-ssid(probe-resp) in the bss info.
1025 	 */
1026 	if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE) &&
1027 	    (cached_ssid_len != 0) &&
1028 	    (beacon_ssid_len == 0 || (beacon_ssid_len &&
1029 				      buf[SSID_IE_LEN_INDEX + 1] == 0))) {
1030 		ni_buf = bss->ni_buf;
1031 		buf_len = len;
1032 
1033 		/*
1034 		 * Copy the first 14 bytes:
1035 		 * time-stamp(8), beacon-interval(2),
1036 		 * cap-info(2), ssid-id(1), ssid-len(1).
1037 		 */
1038 		memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1);
1039 
1040 		ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len;
1041 		ni_buf += (SSID_IE_LEN_INDEX + 1);
1042 
1043 		buf += (SSID_IE_LEN_INDEX + 1);
1044 		buf_len -= (SSID_IE_LEN_INDEX + 1);
1045 
1046 		memcpy(ni_buf, cached_ssid, cached_ssid_len);
1047 		ni_buf += cached_ssid_len;
1048 
1049 		buf += beacon_ssid_len;
1050 		buf_len -= beacon_ssid_len;
1051 
1052 		if (cached_ssid_len > beacon_ssid_len)
1053 			buf_len -= (cached_ssid_len - beacon_ssid_len);
1054 
1055 		memcpy(ni_buf, buf, buf_len);
1056 	} else
1057 		memcpy(bss->ni_buf, buf, len);
1058 
1059 	bss->ni_framelen = len;
1060 
1061 	ret = ath6kl_wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie);
1062 	if (ret) {
1063 		wlan_node_free(bss);
1064 		return -EINVAL;
1065 	}
1066 
1067 	/*
1068 	 * Update the frequency in ie_chan, overwriting of channel number
1069 	 * which is done in ath6kl_wlan_parse_beacon
1070 	 */
1071 	bss->ni_cie.ie_chan = le16_to_cpu(bih->ch);
1072 	wlan_setup_node(&wmi->parent_dev->scan_table, bss, bih->bssid);
1073 
1074 	return 0;
1075 }
1076 
1077 static int ath6kl_wmi_opt_frame_event_rx(struct wmi *wmi, u8 *datap, int len)
1078 {
1079 	struct bss *bss;
1080 	struct wmi_opt_rx_info_hdr *bih;
1081 	u8 *buf;
1082 
1083 	if (len <= sizeof(struct wmi_opt_rx_info_hdr))
1084 		return -EINVAL;
1085 
1086 	bih = (struct wmi_opt_rx_info_hdr *) datap;
1087 	buf = datap + sizeof(struct wmi_opt_rx_info_hdr);
1088 	len -= sizeof(struct wmi_opt_rx_info_hdr);
1089 
1090 	ath6kl_dbg(ATH6KL_DBG_WMI, "opt frame event %2.2x:%2.2x\n",
1091 		   bih->bssid[4], bih->bssid[5]);
1092 
1093 	bss = wlan_find_node(&wmi->parent_dev->scan_table, bih->bssid);
1094 	if (bss != NULL) {
1095 		/* Free up the node. We are about to allocate a new node. */
1096 		wlan_node_reclaim(&wmi->parent_dev->scan_table, bss);
1097 	}
1098 
1099 	bss = wlan_node_alloc(len);
1100 	if (!bss)
1101 		return -ENOMEM;
1102 
1103 	bss->ni_snr = bih->snr;
1104 	bss->ni_cie.ie_chan = le16_to_cpu(bih->ch);
1105 
1106 	if (WARN_ON(!bss->ni_buf))
1107 		return -EINVAL;
1108 
1109 	memcpy(bss->ni_buf, buf, len);
1110 	wlan_setup_node(&wmi->parent_dev->scan_table, bss, bih->bssid);
1111 
1112 	return 0;
1113 }
1114 
1115 /* Inactivity timeout of a fatpipe(pstream) at the target */
1116 static int ath6kl_wmi_pstream_timeout_event_rx(struct wmi *wmi, u8 *datap,
1117 					       int len)
1118 {
1119 	struct wmi_pstream_timeout_event *ev;
1120 
1121 	if (len < sizeof(struct wmi_pstream_timeout_event))
1122 		return -EINVAL;
1123 
1124 	ev = (struct wmi_pstream_timeout_event *) datap;
1125 
1126 	/*
1127 	 * When the pstream (fat pipe == AC) timesout, it means there were
1128 	 * no thinStreams within this pstream & it got implicitly created
1129 	 * due to data flow on this AC. We start the inactivity timer only
1130 	 * for implicitly created pstream. Just reset the host state.
1131 	 */
1132 	spin_lock_bh(&wmi->lock);
1133 	wmi->stream_exist_for_ac[ev->traffic_class] = 0;
1134 	wmi->fat_pipe_exist &= ~(1 << ev->traffic_class);
1135 	spin_unlock_bh(&wmi->lock);
1136 
1137 	/* Indicate inactivity to driver layer for this fatpipe (pstream) */
1138 	ath6kl_indicate_tx_activity(wmi->parent_dev, ev->traffic_class, false);
1139 
1140 	return 0;
1141 }
1142 
1143 static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len)
1144 {
1145 	struct wmi_bit_rate_reply *reply;
1146 	s32 rate;
1147 	u32 sgi, index;
1148 
1149 	if (len < sizeof(struct wmi_bit_rate_reply))
1150 		return -EINVAL;
1151 
1152 	reply = (struct wmi_bit_rate_reply *) datap;
1153 
1154 	ath6kl_dbg(ATH6KL_DBG_WMI, "rateindex %d\n", reply->rate_index);
1155 
1156 	if (reply->rate_index == (s8) RATE_AUTO) {
1157 		rate = RATE_AUTO;
1158 	} else {
1159 		index = reply->rate_index & 0x7f;
1160 		sgi = (reply->rate_index & 0x80) ? 1 : 0;
1161 		rate = wmi_rate_tbl[index][sgi];
1162 	}
1163 
1164 	ath6kl_wakeup_event(wmi->parent_dev);
1165 
1166 	return 0;
1167 }
1168 
1169 static int ath6kl_wmi_tcmd_test_report_rx(struct wmi *wmi, u8 *datap, int len)
1170 {
1171 	ath6kl_tm_rx_report_event(wmi->parent_dev, datap, len);
1172 
1173 	return 0;
1174 }
1175 
1176 static int ath6kl_wmi_ratemask_reply_rx(struct wmi *wmi, u8 *datap, int len)
1177 {
1178 	if (len < sizeof(struct wmi_fix_rates_reply))
1179 		return -EINVAL;
1180 
1181 	ath6kl_wakeup_event(wmi->parent_dev);
1182 
1183 	return 0;
1184 }
1185 
1186 static int ath6kl_wmi_ch_list_reply_rx(struct wmi *wmi, u8 *datap, int len)
1187 {
1188 	if (len < sizeof(struct wmi_channel_list_reply))
1189 		return -EINVAL;
1190 
1191 	ath6kl_wakeup_event(wmi->parent_dev);
1192 
1193 	return 0;
1194 }
1195 
1196 static int ath6kl_wmi_tx_pwr_reply_rx(struct wmi *wmi, u8 *datap, int len)
1197 {
1198 	struct wmi_tx_pwr_reply *reply;
1199 
1200 	if (len < sizeof(struct wmi_tx_pwr_reply))
1201 		return -EINVAL;
1202 
1203 	reply = (struct wmi_tx_pwr_reply *) datap;
1204 	ath6kl_txpwr_rx_evt(wmi->parent_dev, reply->dbM);
1205 
1206 	return 0;
1207 }
1208 
1209 static int ath6kl_wmi_keepalive_reply_rx(struct wmi *wmi, u8 *datap, int len)
1210 {
1211 	if (len < sizeof(struct wmi_get_keepalive_cmd))
1212 		return -EINVAL;
1213 
1214 	ath6kl_wakeup_event(wmi->parent_dev);
1215 
1216 	return 0;
1217 }
1218 
1219 static int ath6kl_wmi_scan_complete_rx(struct wmi *wmi, u8 *datap, int len)
1220 {
1221 	struct wmi_scan_complete_event *ev;
1222 
1223 	ev = (struct wmi_scan_complete_event *) datap;
1224 
1225 	if (a_sle32_to_cpu(ev->status) == 0)
1226 		wlan_refresh_inactive_nodes(wmi->parent_dev);
1227 
1228 	ath6kl_scan_complete_evt(wmi->parent_dev, a_sle32_to_cpu(ev->status));
1229 	wmi->is_probe_ssid = false;
1230 
1231 	return 0;
1232 }
1233 
1234 /*
1235  * Target is reporting a programming error.  This is for
1236  * developer aid only.  Target only checks a few common violations
1237  * and it is responsibility of host to do all error checking.
1238  * Behavior of target after wmi error event is undefined.
1239  * A reset is recommended.
1240  */
1241 static int ath6kl_wmi_error_event_rx(struct wmi *wmi, u8 *datap, int len)
1242 {
1243 	const char *type = "unknown error";
1244 	struct wmi_cmd_error_event *ev;
1245 	ev = (struct wmi_cmd_error_event *) datap;
1246 
1247 	switch (ev->err_code) {
1248 	case INVALID_PARAM:
1249 		type = "invalid parameter";
1250 		break;
1251 	case ILLEGAL_STATE:
1252 		type = "invalid state";
1253 		break;
1254 	case INTERNAL_ERROR:
1255 		type = "internal error";
1256 		break;
1257 	}
1258 
1259 	ath6kl_dbg(ATH6KL_DBG_WMI, "programming error, cmd=%d %s\n",
1260 		   ev->cmd_id, type);
1261 
1262 	return 0;
1263 }
1264 
1265 static int ath6kl_wmi_stats_event_rx(struct wmi *wmi, u8 *datap, int len)
1266 {
1267 	ath6kl_tgt_stats_event(wmi->parent_dev, datap, len);
1268 
1269 	return 0;
1270 }
1271 
1272 static u8 ath6kl_wmi_get_upper_threshold(s16 rssi,
1273 					 struct sq_threshold_params *sq_thresh,
1274 					 u32 size)
1275 {
1276 	u32 index;
1277 	u8 threshold = (u8) sq_thresh->upper_threshold[size - 1];
1278 
1279 	/* The list is already in sorted order. Get the next lower value */
1280 	for (index = 0; index < size; index++) {
1281 		if (rssi < sq_thresh->upper_threshold[index]) {
1282 			threshold = (u8) sq_thresh->upper_threshold[index];
1283 			break;
1284 		}
1285 	}
1286 
1287 	return threshold;
1288 }
1289 
1290 static u8 ath6kl_wmi_get_lower_threshold(s16 rssi,
1291 					 struct sq_threshold_params *sq_thresh,
1292 					 u32 size)
1293 {
1294 	u32 index;
1295 	u8 threshold = (u8) sq_thresh->lower_threshold[size - 1];
1296 
1297 	/* The list is already in sorted order. Get the next lower value */
1298 	for (index = 0; index < size; index++) {
1299 		if (rssi > sq_thresh->lower_threshold[index]) {
1300 			threshold = (u8) sq_thresh->lower_threshold[index];
1301 			break;
1302 		}
1303 	}
1304 
1305 	return threshold;
1306 }
1307 
1308 static int ath6kl_wmi_send_rssi_threshold_params(struct wmi *wmi,
1309 			struct wmi_rssi_threshold_params_cmd *rssi_cmd)
1310 {
1311 	struct sk_buff *skb;
1312 	struct wmi_rssi_threshold_params_cmd *cmd;
1313 
1314 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1315 	if (!skb)
1316 		return -ENOMEM;
1317 
1318 	cmd = (struct wmi_rssi_threshold_params_cmd *) skb->data;
1319 	memcpy(cmd, rssi_cmd, sizeof(struct wmi_rssi_threshold_params_cmd));
1320 
1321 	return ath6kl_wmi_cmd_send(wmi, skb, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
1322 				   NO_SYNC_WMIFLAG);
1323 }
1324 
1325 static int ath6kl_wmi_rssi_threshold_event_rx(struct wmi *wmi, u8 *datap,
1326 					      int len)
1327 {
1328 	struct wmi_rssi_threshold_event *reply;
1329 	struct wmi_rssi_threshold_params_cmd cmd;
1330 	struct sq_threshold_params *sq_thresh;
1331 	enum wmi_rssi_threshold_val new_threshold;
1332 	u8 upper_rssi_threshold, lower_rssi_threshold;
1333 	s16 rssi;
1334 	int ret;
1335 
1336 	if (len < sizeof(struct wmi_rssi_threshold_event))
1337 		return -EINVAL;
1338 
1339 	reply = (struct wmi_rssi_threshold_event *) datap;
1340 	new_threshold = (enum wmi_rssi_threshold_val) reply->range;
1341 	rssi = a_sle16_to_cpu(reply->rssi);
1342 
1343 	sq_thresh = &wmi->sq_threshld[SIGNAL_QUALITY_METRICS_RSSI];
1344 
1345 	/*
1346 	 * Identify the threshold breached and communicate that to the app.
1347 	 * After that install a new set of thresholds based on the signal
1348 	 * quality reported by the target
1349 	 */
1350 	if (new_threshold) {
1351 		/* Upper threshold breached */
1352 		if (rssi < sq_thresh->upper_threshold[0]) {
1353 			ath6kl_dbg(ATH6KL_DBG_WMI,
1354 				"spurious upper rssi threshold event: %d\n",
1355 				rssi);
1356 		} else if ((rssi < sq_thresh->upper_threshold[1]) &&
1357 			   (rssi >= sq_thresh->upper_threshold[0])) {
1358 			new_threshold = WMI_RSSI_THRESHOLD1_ABOVE;
1359 		} else if ((rssi < sq_thresh->upper_threshold[2]) &&
1360 			   (rssi >= sq_thresh->upper_threshold[1])) {
1361 			new_threshold = WMI_RSSI_THRESHOLD2_ABOVE;
1362 		} else if ((rssi < sq_thresh->upper_threshold[3]) &&
1363 			   (rssi >= sq_thresh->upper_threshold[2])) {
1364 			new_threshold = WMI_RSSI_THRESHOLD3_ABOVE;
1365 		} else if ((rssi < sq_thresh->upper_threshold[4]) &&
1366 			   (rssi >= sq_thresh->upper_threshold[3])) {
1367 			new_threshold = WMI_RSSI_THRESHOLD4_ABOVE;
1368 		} else if ((rssi < sq_thresh->upper_threshold[5]) &&
1369 			   (rssi >= sq_thresh->upper_threshold[4])) {
1370 			new_threshold = WMI_RSSI_THRESHOLD5_ABOVE;
1371 		} else if (rssi >= sq_thresh->upper_threshold[5]) {
1372 			new_threshold = WMI_RSSI_THRESHOLD6_ABOVE;
1373 		}
1374 	} else {
1375 		/* Lower threshold breached */
1376 		if (rssi > sq_thresh->lower_threshold[0]) {
1377 			ath6kl_dbg(ATH6KL_DBG_WMI,
1378 				"spurious lower rssi threshold event: %d %d\n",
1379 				rssi, sq_thresh->lower_threshold[0]);
1380 		} else if ((rssi > sq_thresh->lower_threshold[1]) &&
1381 			   (rssi <= sq_thresh->lower_threshold[0])) {
1382 			new_threshold = WMI_RSSI_THRESHOLD6_BELOW;
1383 		} else if ((rssi > sq_thresh->lower_threshold[2]) &&
1384 			   (rssi <= sq_thresh->lower_threshold[1])) {
1385 			new_threshold = WMI_RSSI_THRESHOLD5_BELOW;
1386 		} else if ((rssi > sq_thresh->lower_threshold[3]) &&
1387 			   (rssi <= sq_thresh->lower_threshold[2])) {
1388 			new_threshold = WMI_RSSI_THRESHOLD4_BELOW;
1389 		} else if ((rssi > sq_thresh->lower_threshold[4]) &&
1390 			   (rssi <= sq_thresh->lower_threshold[3])) {
1391 			new_threshold = WMI_RSSI_THRESHOLD3_BELOW;
1392 		} else if ((rssi > sq_thresh->lower_threshold[5]) &&
1393 			   (rssi <= sq_thresh->lower_threshold[4])) {
1394 			new_threshold = WMI_RSSI_THRESHOLD2_BELOW;
1395 		} else if (rssi <= sq_thresh->lower_threshold[5]) {
1396 			new_threshold = WMI_RSSI_THRESHOLD1_BELOW;
1397 		}
1398 	}
1399 
1400 	/* Calculate and install the next set of thresholds */
1401 	lower_rssi_threshold = ath6kl_wmi_get_lower_threshold(rssi, sq_thresh,
1402 				       sq_thresh->lower_threshold_valid_count);
1403 	upper_rssi_threshold = ath6kl_wmi_get_upper_threshold(rssi, sq_thresh,
1404 				       sq_thresh->upper_threshold_valid_count);
1405 
1406 	/* Issue a wmi command to install the thresholds */
1407 	cmd.thresh_above1_val = a_cpu_to_sle16(upper_rssi_threshold);
1408 	cmd.thresh_below1_val = a_cpu_to_sle16(lower_rssi_threshold);
1409 	cmd.weight = sq_thresh->weight;
1410 	cmd.poll_time = cpu_to_le32(sq_thresh->polling_interval);
1411 
1412 	ret = ath6kl_wmi_send_rssi_threshold_params(wmi, &cmd);
1413 	if (ret) {
1414 		ath6kl_err("unable to configure rssi thresholds\n");
1415 		return -EIO;
1416 	}
1417 
1418 	return 0;
1419 }
1420 
1421 static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len)
1422 {
1423 	struct wmi_cac_event *reply;
1424 	struct ieee80211_tspec_ie *ts;
1425 	u16 active_tsids, tsinfo;
1426 	u8 tsid, index;
1427 	u8 ts_id;
1428 
1429 	if (len < sizeof(struct wmi_cac_event))
1430 		return -EINVAL;
1431 
1432 	reply = (struct wmi_cac_event *) datap;
1433 
1434 	if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) &&
1435 	    (reply->status_code != IEEE80211_TSPEC_STATUS_ADMISS_ACCEPTED)) {
1436 
1437 		ts = (struct ieee80211_tspec_ie *) &(reply->tspec_suggestion);
1438 		tsinfo = le16_to_cpu(ts->tsinfo);
1439 		tsid = (tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) &
1440 			IEEE80211_WMM_IE_TSPEC_TID_MASK;
1441 
1442 		ath6kl_wmi_delete_pstream_cmd(wmi, reply->ac, tsid);
1443 	} else if (reply->cac_indication == CAC_INDICATION_NO_RESP) {
1444 		/*
1445 		 * Following assumes that there is only one outstanding
1446 		 * ADDTS request when this event is received
1447 		 */
1448 		spin_lock_bh(&wmi->lock);
1449 		active_tsids = wmi->stream_exist_for_ac[reply->ac];
1450 		spin_unlock_bh(&wmi->lock);
1451 
1452 		for (index = 0; index < sizeof(active_tsids) * 8; index++) {
1453 			if ((active_tsids >> index) & 1)
1454 				break;
1455 		}
1456 		if (index < (sizeof(active_tsids) * 8))
1457 			ath6kl_wmi_delete_pstream_cmd(wmi, reply->ac, index);
1458 	}
1459 
1460 	/*
1461 	 * Clear active tsids and Add missing handling
1462 	 * for delete qos stream from AP
1463 	 */
1464 	else if (reply->cac_indication == CAC_INDICATION_DELETE) {
1465 
1466 		ts = (struct ieee80211_tspec_ie *) &(reply->tspec_suggestion);
1467 		tsinfo = le16_to_cpu(ts->tsinfo);
1468 		ts_id = ((tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) &
1469 			 IEEE80211_WMM_IE_TSPEC_TID_MASK);
1470 
1471 		spin_lock_bh(&wmi->lock);
1472 		wmi->stream_exist_for_ac[reply->ac] &= ~(1 << ts_id);
1473 		active_tsids = wmi->stream_exist_for_ac[reply->ac];
1474 		spin_unlock_bh(&wmi->lock);
1475 
1476 		/* Indicate stream inactivity to driver layer only if all tsids
1477 		 * within this AC are deleted.
1478 		 */
1479 		if (!active_tsids) {
1480 			ath6kl_indicate_tx_activity(wmi->parent_dev, reply->ac,
1481 						    false);
1482 			wmi->fat_pipe_exist &= ~(1 << reply->ac);
1483 		}
1484 	}
1485 
1486 	return 0;
1487 }
1488 
1489 static int ath6kl_wmi_send_snr_threshold_params(struct wmi *wmi,
1490 			struct wmi_snr_threshold_params_cmd *snr_cmd)
1491 {
1492 	struct sk_buff *skb;
1493 	struct wmi_snr_threshold_params_cmd *cmd;
1494 
1495 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1496 	if (!skb)
1497 		return -ENOMEM;
1498 
1499 	cmd = (struct wmi_snr_threshold_params_cmd *) skb->data;
1500 	memcpy(cmd, snr_cmd, sizeof(struct wmi_snr_threshold_params_cmd));
1501 
1502 	return ath6kl_wmi_cmd_send(wmi, skb, WMI_SNR_THRESHOLD_PARAMS_CMDID,
1503 				   NO_SYNC_WMIFLAG);
1504 }
1505 
1506 static int ath6kl_wmi_snr_threshold_event_rx(struct wmi *wmi, u8 *datap,
1507 					     int len)
1508 {
1509 	struct wmi_snr_threshold_event *reply;
1510 	struct sq_threshold_params *sq_thresh;
1511 	struct wmi_snr_threshold_params_cmd cmd;
1512 	enum wmi_snr_threshold_val new_threshold;
1513 	u8 upper_snr_threshold, lower_snr_threshold;
1514 	s16 snr;
1515 	int ret;
1516 
1517 	if (len < sizeof(struct wmi_snr_threshold_event))
1518 		return -EINVAL;
1519 
1520 	reply = (struct wmi_snr_threshold_event *) datap;
1521 
1522 	new_threshold = (enum wmi_snr_threshold_val) reply->range;
1523 	snr = reply->snr;
1524 
1525 	sq_thresh = &wmi->sq_threshld[SIGNAL_QUALITY_METRICS_SNR];
1526 
1527 	/*
1528 	 * Identify the threshold breached and communicate that to the app.
1529 	 * After that install a new set of thresholds based on the signal
1530 	 * quality reported by the target.
1531 	 */
1532 	if (new_threshold) {
1533 		/* Upper threshold breached */
1534 		if (snr < sq_thresh->upper_threshold[0]) {
1535 			ath6kl_dbg(ATH6KL_DBG_WMI,
1536 				"spurious upper snr threshold event: %d\n",
1537 				snr);
1538 		} else if ((snr < sq_thresh->upper_threshold[1]) &&
1539 			   (snr >= sq_thresh->upper_threshold[0])) {
1540 			new_threshold = WMI_SNR_THRESHOLD1_ABOVE;
1541 		} else if ((snr < sq_thresh->upper_threshold[2]) &&
1542 			   (snr >= sq_thresh->upper_threshold[1])) {
1543 			new_threshold = WMI_SNR_THRESHOLD2_ABOVE;
1544 		} else if ((snr < sq_thresh->upper_threshold[3]) &&
1545 			   (snr >= sq_thresh->upper_threshold[2])) {
1546 			new_threshold = WMI_SNR_THRESHOLD3_ABOVE;
1547 		} else if (snr >= sq_thresh->upper_threshold[3]) {
1548 			new_threshold = WMI_SNR_THRESHOLD4_ABOVE;
1549 		}
1550 	} else {
1551 		/* Lower threshold breached */
1552 		if (snr > sq_thresh->lower_threshold[0]) {
1553 			ath6kl_dbg(ATH6KL_DBG_WMI,
1554 				"spurious lower snr threshold event: %d\n",
1555 				sq_thresh->lower_threshold[0]);
1556 		} else if ((snr > sq_thresh->lower_threshold[1]) &&
1557 			   (snr <= sq_thresh->lower_threshold[0])) {
1558 			new_threshold = WMI_SNR_THRESHOLD4_BELOW;
1559 		} else if ((snr > sq_thresh->lower_threshold[2]) &&
1560 			   (snr <= sq_thresh->lower_threshold[1])) {
1561 			new_threshold = WMI_SNR_THRESHOLD3_BELOW;
1562 		} else if ((snr > sq_thresh->lower_threshold[3]) &&
1563 			   (snr <= sq_thresh->lower_threshold[2])) {
1564 			new_threshold = WMI_SNR_THRESHOLD2_BELOW;
1565 		} else if (snr <= sq_thresh->lower_threshold[3]) {
1566 			new_threshold = WMI_SNR_THRESHOLD1_BELOW;
1567 		}
1568 	}
1569 
1570 	/* Calculate and install the next set of thresholds */
1571 	lower_snr_threshold = ath6kl_wmi_get_lower_threshold(snr, sq_thresh,
1572 				       sq_thresh->lower_threshold_valid_count);
1573 	upper_snr_threshold = ath6kl_wmi_get_upper_threshold(snr, sq_thresh,
1574 				       sq_thresh->upper_threshold_valid_count);
1575 
1576 	/* Issue a wmi command to install the thresholds */
1577 	cmd.thresh_above1_val = upper_snr_threshold;
1578 	cmd.thresh_below1_val = lower_snr_threshold;
1579 	cmd.weight = sq_thresh->weight;
1580 	cmd.poll_time = cpu_to_le32(sq_thresh->polling_interval);
1581 
1582 	ath6kl_dbg(ATH6KL_DBG_WMI,
1583 		   "snr: %d, threshold: %d, lower: %d, upper: %d\n",
1584 		   snr, new_threshold,
1585 		   lower_snr_threshold, upper_snr_threshold);
1586 
1587 	ret = ath6kl_wmi_send_snr_threshold_params(wmi, &cmd);
1588 	if (ret) {
1589 		ath6kl_err("unable to configure snr threshold\n");
1590 		return -EIO;
1591 	}
1592 
1593 	return 0;
1594 }
1595 
1596 static int ath6kl_wmi_aplist_event_rx(struct wmi *wmi, u8 *datap, int len)
1597 {
1598 	u16 ap_info_entry_size;
1599 	struct wmi_aplist_event *ev = (struct wmi_aplist_event *) datap;
1600 	struct wmi_ap_info_v1 *ap_info_v1;
1601 	u8 index;
1602 
1603 	if (len < sizeof(struct wmi_aplist_event) ||
1604 	    ev->ap_list_ver != APLIST_VER1)
1605 		return -EINVAL;
1606 
1607 	ap_info_entry_size = sizeof(struct wmi_ap_info_v1);
1608 	ap_info_v1 = (struct wmi_ap_info_v1 *) ev->ap_list;
1609 
1610 	ath6kl_dbg(ATH6KL_DBG_WMI,
1611 		   "number of APs in aplist event: %d\n", ev->num_ap);
1612 
1613 	if (len < (int) (sizeof(struct wmi_aplist_event) +
1614 			 (ev->num_ap - 1) * ap_info_entry_size))
1615 		return -EINVAL;
1616 
1617 	/* AP list version 1 contents */
1618 	for (index = 0; index < ev->num_ap; index++) {
1619 		ath6kl_dbg(ATH6KL_DBG_WMI, "AP#%d BSSID %pM Channel %d\n",
1620 			   index, ap_info_v1->bssid, ap_info_v1->channel);
1621 		ap_info_v1++;
1622 	}
1623 
1624 	return 0;
1625 }
1626 
1627 int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb,
1628 			enum wmi_cmd_id cmd_id, enum wmi_sync_flag sync_flag)
1629 {
1630 	struct wmi_cmd_hdr *cmd_hdr;
1631 	enum htc_endpoint_id ep_id = wmi->ep_id;
1632 	int ret;
1633 
1634 	ath6kl_dbg(ATH6KL_DBG_WMI, "%s: cmd_id=%d\n", __func__, cmd_id);
1635 
1636 	if (WARN_ON(skb == NULL))
1637 		return -EINVAL;
1638 
1639 	if (sync_flag >= END_WMIFLAG) {
1640 		dev_kfree_skb(skb);
1641 		return -EINVAL;
1642 	}
1643 
1644 	if ((sync_flag == SYNC_BEFORE_WMIFLAG) ||
1645 	    (sync_flag == SYNC_BOTH_WMIFLAG)) {
1646 		/*
1647 		 * Make sure all data currently queued is transmitted before
1648 		 * the cmd execution.  Establish a new sync point.
1649 		 */
1650 		ath6kl_wmi_sync_point(wmi);
1651 	}
1652 
1653 	skb_push(skb, sizeof(struct wmi_cmd_hdr));
1654 
1655 	cmd_hdr = (struct wmi_cmd_hdr *) skb->data;
1656 	cmd_hdr->cmd_id = cpu_to_le16(cmd_id);
1657 	cmd_hdr->info1 = 0;	/* added for virtual interface */
1658 
1659 	/* Only for OPT_TX_CMD, use BE endpoint. */
1660 	if (cmd_id == WMI_OPT_TX_FRAME_CMDID) {
1661 		ret = ath6kl_wmi_data_hdr_add(wmi, skb, OPT_MSGTYPE,
1662 					      false, false, 0, NULL);
1663 		if (ret) {
1664 			dev_kfree_skb(skb);
1665 			return ret;
1666 		}
1667 		ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev, WMM_AC_BE);
1668 	}
1669 
1670 	ath6kl_control_tx(wmi->parent_dev, skb, ep_id);
1671 
1672 	if ((sync_flag == SYNC_AFTER_WMIFLAG) ||
1673 	    (sync_flag == SYNC_BOTH_WMIFLAG)) {
1674 		/*
1675 		 * Make sure all new data queued waits for the command to
1676 		 * execute. Establish a new sync point.
1677 		 */
1678 		ath6kl_wmi_sync_point(wmi);
1679 	}
1680 
1681 	return 0;
1682 }
1683 
1684 int ath6kl_wmi_connect_cmd(struct wmi *wmi, enum network_type nw_type,
1685 			   enum dot11_auth_mode dot11_auth_mode,
1686 			   enum auth_mode auth_mode,
1687 			   enum crypto_type pairwise_crypto,
1688 			   u8 pairwise_crypto_len,
1689 			   enum crypto_type group_crypto,
1690 			   u8 group_crypto_len, int ssid_len, u8 *ssid,
1691 			   u8 *bssid, u16 channel, u32 ctrl_flags)
1692 {
1693 	struct sk_buff *skb;
1694 	struct wmi_connect_cmd *cc;
1695 	int ret;
1696 
1697 	wmi->traffic_class = 100;
1698 
1699 	if ((pairwise_crypto == NONE_CRYPT) && (group_crypto != NONE_CRYPT))
1700 		return -EINVAL;
1701 
1702 	if ((pairwise_crypto != NONE_CRYPT) && (group_crypto == NONE_CRYPT))
1703 		return -EINVAL;
1704 
1705 	skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_connect_cmd));
1706 	if (!skb)
1707 		return -ENOMEM;
1708 
1709 	cc = (struct wmi_connect_cmd *) skb->data;
1710 
1711 	if (ssid_len)
1712 		memcpy(cc->ssid, ssid, ssid_len);
1713 
1714 	cc->ssid_len = ssid_len;
1715 	cc->nw_type = nw_type;
1716 	cc->dot11_auth_mode = dot11_auth_mode;
1717 	cc->auth_mode = auth_mode;
1718 	cc->prwise_crypto_type = pairwise_crypto;
1719 	cc->prwise_crypto_len = pairwise_crypto_len;
1720 	cc->grp_crypto_type = group_crypto;
1721 	cc->grp_crypto_len = group_crypto_len;
1722 	cc->ch = cpu_to_le16(channel);
1723 	cc->ctrl_flags = cpu_to_le32(ctrl_flags);
1724 
1725 	if (bssid != NULL)
1726 		memcpy(cc->bssid, bssid, ETH_ALEN);
1727 
1728 	wmi->pair_crypto_type = pairwise_crypto;
1729 	wmi->grp_crypto_type = group_crypto;
1730 
1731 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG);
1732 
1733 	return ret;
1734 }
1735 
1736 int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 *bssid, u16 channel)
1737 {
1738 	struct sk_buff *skb;
1739 	struct wmi_reconnect_cmd *cc;
1740 	int ret;
1741 
1742 	wmi->traffic_class = 100;
1743 
1744 	skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_reconnect_cmd));
1745 	if (!skb)
1746 		return -ENOMEM;
1747 
1748 	cc = (struct wmi_reconnect_cmd *) skb->data;
1749 	cc->channel = cpu_to_le16(channel);
1750 
1751 	if (bssid != NULL)
1752 		memcpy(cc->bssid, bssid, ETH_ALEN);
1753 
1754 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_RECONNECT_CMDID,
1755 				  NO_SYNC_WMIFLAG);
1756 
1757 	return ret;
1758 }
1759 
1760 int ath6kl_wmi_disconnect_cmd(struct wmi *wmi)
1761 {
1762 	int ret;
1763 
1764 	wmi->traffic_class = 100;
1765 
1766 	/* Disconnect command does not need to do a SYNC before. */
1767 	ret = ath6kl_wmi_simple_cmd(wmi, WMI_DISCONNECT_CMDID);
1768 
1769 	return ret;
1770 }
1771 
1772 int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type,
1773 			     u32 force_fgscan, u32 is_legacy,
1774 			     u32 home_dwell_time, u32 force_scan_interval,
1775 			     s8 num_chan, u16 *ch_list)
1776 {
1777 	struct sk_buff *skb;
1778 	struct wmi_start_scan_cmd *sc;
1779 	s8 size;
1780 	int i, ret;
1781 
1782 	size = sizeof(struct wmi_start_scan_cmd);
1783 
1784 	if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
1785 		return -EINVAL;
1786 
1787 	if (num_chan > WMI_MAX_CHANNELS)
1788 		return -EINVAL;
1789 
1790 	if (num_chan)
1791 		size += sizeof(u16) * (num_chan - 1);
1792 
1793 	skb = ath6kl_wmi_get_new_buf(size);
1794 	if (!skb)
1795 		return -ENOMEM;
1796 
1797 	sc = (struct wmi_start_scan_cmd *) skb->data;
1798 	sc->scan_type = scan_type;
1799 	sc->force_fg_scan = cpu_to_le32(force_fgscan);
1800 	sc->is_legacy = cpu_to_le32(is_legacy);
1801 	sc->home_dwell_time = cpu_to_le32(home_dwell_time);
1802 	sc->force_scan_intvl = cpu_to_le32(force_scan_interval);
1803 	sc->num_ch = num_chan;
1804 
1805 	for (i = 0; i < num_chan; i++)
1806 		sc->ch_list[i] = cpu_to_le16(ch_list[i]);
1807 
1808 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_START_SCAN_CMDID,
1809 				  NO_SYNC_WMIFLAG);
1810 
1811 	return ret;
1812 }
1813 
1814 int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u16 fg_start_sec,
1815 			      u16 fg_end_sec, u16 bg_sec,
1816 			      u16 minact_chdw_msec, u16 maxact_chdw_msec,
1817 			      u16 pas_chdw_msec, u8 short_scan_ratio,
1818 			      u8 scan_ctrl_flag, u32 max_dfsch_act_time,
1819 			      u16 maxact_scan_per_ssid)
1820 {
1821 	struct sk_buff *skb;
1822 	struct wmi_scan_params_cmd *sc;
1823 	int ret;
1824 
1825 	skb = ath6kl_wmi_get_new_buf(sizeof(*sc));
1826 	if (!skb)
1827 		return -ENOMEM;
1828 
1829 	sc = (struct wmi_scan_params_cmd *) skb->data;
1830 	sc->fg_start_period = cpu_to_le16(fg_start_sec);
1831 	sc->fg_end_period = cpu_to_le16(fg_end_sec);
1832 	sc->bg_period = cpu_to_le16(bg_sec);
1833 	sc->minact_chdwell_time = cpu_to_le16(minact_chdw_msec);
1834 	sc->maxact_chdwell_time = cpu_to_le16(maxact_chdw_msec);
1835 	sc->pas_chdwell_time = cpu_to_le16(pas_chdw_msec);
1836 	sc->short_scan_ratio = short_scan_ratio;
1837 	sc->scan_ctrl_flags = scan_ctrl_flag;
1838 	sc->max_dfsch_act_time = cpu_to_le32(max_dfsch_act_time);
1839 	sc->maxact_scan_per_ssid = cpu_to_le16(maxact_scan_per_ssid);
1840 
1841 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_SCAN_PARAMS_CMDID,
1842 				  NO_SYNC_WMIFLAG);
1843 	return ret;
1844 }
1845 
1846 int ath6kl_wmi_bssfilter_cmd(struct wmi *wmi, u8 filter, u32 ie_mask)
1847 {
1848 	struct sk_buff *skb;
1849 	struct wmi_bss_filter_cmd *cmd;
1850 	int ret;
1851 
1852 	if (filter >= LAST_BSS_FILTER)
1853 		return -EINVAL;
1854 
1855 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1856 	if (!skb)
1857 		return -ENOMEM;
1858 
1859 	cmd = (struct wmi_bss_filter_cmd *) skb->data;
1860 	cmd->bss_filter = filter;
1861 	cmd->ie_mask = cpu_to_le32(ie_mask);
1862 
1863 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_BSS_FILTER_CMDID,
1864 				  NO_SYNC_WMIFLAG);
1865 	return ret;
1866 }
1867 
1868 int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 index, u8 flag,
1869 			      u8 ssid_len, u8 *ssid)
1870 {
1871 	struct sk_buff *skb;
1872 	struct wmi_probed_ssid_cmd *cmd;
1873 	int ret;
1874 
1875 	if (index > MAX_PROBED_SSID_INDEX)
1876 		return -EINVAL;
1877 
1878 	if (ssid_len > sizeof(cmd->ssid))
1879 		return -EINVAL;
1880 
1881 	if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssid_len > 0))
1882 		return -EINVAL;
1883 
1884 	if ((flag & SPECIFIC_SSID_FLAG) && !ssid_len)
1885 		return -EINVAL;
1886 
1887 	if (flag & SPECIFIC_SSID_FLAG)
1888 		wmi->is_probe_ssid = true;
1889 
1890 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1891 	if (!skb)
1892 		return -ENOMEM;
1893 
1894 	cmd = (struct wmi_probed_ssid_cmd *) skb->data;
1895 	cmd->entry_index = index;
1896 	cmd->flag = flag;
1897 	cmd->ssid_len = ssid_len;
1898 	memcpy(cmd->ssid, ssid, ssid_len);
1899 
1900 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_PROBED_SSID_CMDID,
1901 				  NO_SYNC_WMIFLAG);
1902 	return ret;
1903 }
1904 
1905 int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u16 listen_interval,
1906 				  u16 listen_beacons)
1907 {
1908 	struct sk_buff *skb;
1909 	struct wmi_listen_int_cmd *cmd;
1910 	int ret;
1911 
1912 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1913 	if (!skb)
1914 		return -ENOMEM;
1915 
1916 	cmd = (struct wmi_listen_int_cmd *) skb->data;
1917 	cmd->listen_intvl = cpu_to_le16(listen_interval);
1918 	cmd->num_beacons = cpu_to_le16(listen_beacons);
1919 
1920 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_LISTEN_INT_CMDID,
1921 				  NO_SYNC_WMIFLAG);
1922 	return ret;
1923 }
1924 
1925 int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 pwr_mode)
1926 {
1927 	struct sk_buff *skb;
1928 	struct wmi_power_mode_cmd *cmd;
1929 	int ret;
1930 
1931 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1932 	if (!skb)
1933 		return -ENOMEM;
1934 
1935 	cmd = (struct wmi_power_mode_cmd *) skb->data;
1936 	cmd->pwr_mode = pwr_mode;
1937 	wmi->pwr_mode = pwr_mode;
1938 
1939 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_POWER_MODE_CMDID,
1940 				  NO_SYNC_WMIFLAG);
1941 	return ret;
1942 }
1943 
1944 int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u16 idle_period,
1945 			    u16 ps_poll_num, u16 dtim_policy,
1946 			    u16 tx_wakeup_policy, u16 num_tx_to_wakeup,
1947 			    u16 ps_fail_event_policy)
1948 {
1949 	struct sk_buff *skb;
1950 	struct wmi_power_params_cmd *pm;
1951 	int ret;
1952 
1953 	skb = ath6kl_wmi_get_new_buf(sizeof(*pm));
1954 	if (!skb)
1955 		return -ENOMEM;
1956 
1957 	pm = (struct wmi_power_params_cmd *)skb->data;
1958 	pm->idle_period = cpu_to_le16(idle_period);
1959 	pm->pspoll_number = cpu_to_le16(ps_poll_num);
1960 	pm->dtim_policy = cpu_to_le16(dtim_policy);
1961 	pm->tx_wakeup_policy = cpu_to_le16(tx_wakeup_policy);
1962 	pm->num_tx_to_wakeup = cpu_to_le16(num_tx_to_wakeup);
1963 	pm->ps_fail_event_policy = cpu_to_le16(ps_fail_event_policy);
1964 
1965 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_POWER_PARAMS_CMDID,
1966 				  NO_SYNC_WMIFLAG);
1967 	return ret;
1968 }
1969 
1970 int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 timeout)
1971 {
1972 	struct sk_buff *skb;
1973 	struct wmi_disc_timeout_cmd *cmd;
1974 	int ret;
1975 
1976 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1977 	if (!skb)
1978 		return -ENOMEM;
1979 
1980 	cmd = (struct wmi_disc_timeout_cmd *) skb->data;
1981 	cmd->discon_timeout = timeout;
1982 
1983 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_DISC_TIMEOUT_CMDID,
1984 				  NO_SYNC_WMIFLAG);
1985 	return ret;
1986 }
1987 
1988 int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index,
1989 			  enum crypto_type key_type,
1990 			  u8 key_usage, u8 key_len,
1991 			  u8 *key_rsc, u8 *key_material,
1992 			  u8 key_op_ctrl, u8 *mac_addr,
1993 			  enum wmi_sync_flag sync_flag)
1994 {
1995 	struct sk_buff *skb;
1996 	struct wmi_add_cipher_key_cmd *cmd;
1997 	int ret;
1998 
1999 	ath6kl_dbg(ATH6KL_DBG_WMI, "addkey cmd: key_index=%u key_type=%d "
2000 		   "key_usage=%d key_len=%d key_op_ctrl=%d\n",
2001 		   key_index, key_type, key_usage, key_len, key_op_ctrl);
2002 
2003 	if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) ||
2004 	    (key_material == NULL))
2005 		return -EINVAL;
2006 
2007 	if ((WEP_CRYPT != key_type) && (NULL == key_rsc))
2008 		return -EINVAL;
2009 
2010 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2011 	if (!skb)
2012 		return -ENOMEM;
2013 
2014 	cmd = (struct wmi_add_cipher_key_cmd *) skb->data;
2015 	cmd->key_index = key_index;
2016 	cmd->key_type = key_type;
2017 	cmd->key_usage = key_usage;
2018 	cmd->key_len = key_len;
2019 	memcpy(cmd->key, key_material, key_len);
2020 
2021 	if (key_rsc != NULL)
2022 		memcpy(cmd->key_rsc, key_rsc, sizeof(cmd->key_rsc));
2023 
2024 	cmd->key_op_ctrl = key_op_ctrl;
2025 
2026 	if (mac_addr)
2027 		memcpy(cmd->key_mac_addr, mac_addr, ETH_ALEN);
2028 
2029 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_ADD_CIPHER_KEY_CMDID,
2030 				  sync_flag);
2031 
2032 	return ret;
2033 }
2034 
2035 int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 *krk)
2036 {
2037 	struct sk_buff *skb;
2038 	struct wmi_add_krk_cmd *cmd;
2039 	int ret;
2040 
2041 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2042 	if (!skb)
2043 		return -ENOMEM;
2044 
2045 	cmd = (struct wmi_add_krk_cmd *) skb->data;
2046 	memcpy(cmd->krk, krk, WMI_KRK_LEN);
2047 
2048 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG);
2049 
2050 	return ret;
2051 }
2052 
2053 int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 key_index)
2054 {
2055 	struct sk_buff *skb;
2056 	struct wmi_delete_cipher_key_cmd *cmd;
2057 	int ret;
2058 
2059 	if (key_index > WMI_MAX_KEY_INDEX)
2060 		return -EINVAL;
2061 
2062 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2063 	if (!skb)
2064 		return -ENOMEM;
2065 
2066 	cmd = (struct wmi_delete_cipher_key_cmd *) skb->data;
2067 	cmd->key_index = key_index;
2068 
2069 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_DELETE_CIPHER_KEY_CMDID,
2070 				  NO_SYNC_WMIFLAG);
2071 
2072 	return ret;
2073 }
2074 
2075 int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, const u8 *bssid,
2076 			    const u8 *pmkid, bool set)
2077 {
2078 	struct sk_buff *skb;
2079 	struct wmi_setpmkid_cmd *cmd;
2080 	int ret;
2081 
2082 	if (bssid == NULL)
2083 		return -EINVAL;
2084 
2085 	if (set && pmkid == NULL)
2086 		return -EINVAL;
2087 
2088 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2089 	if (!skb)
2090 		return -ENOMEM;
2091 
2092 	cmd = (struct wmi_setpmkid_cmd *) skb->data;
2093 	memcpy(cmd->bssid, bssid, ETH_ALEN);
2094 	if (set) {
2095 		memcpy(cmd->pmkid, pmkid, sizeof(cmd->pmkid));
2096 		cmd->enable = PMKID_ENABLE;
2097 	} else {
2098 		memset(cmd->pmkid, 0, sizeof(cmd->pmkid));
2099 		cmd->enable = PMKID_DISABLE;
2100 	}
2101 
2102 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_PMKID_CMDID,
2103 				  NO_SYNC_WMIFLAG);
2104 
2105 	return ret;
2106 }
2107 
2108 static int ath6kl_wmi_data_sync_send(struct wmi *wmi, struct sk_buff *skb,
2109 			      enum htc_endpoint_id ep_id)
2110 {
2111 	struct wmi_data_hdr *data_hdr;
2112 	int ret;
2113 
2114 	if (WARN_ON(skb == NULL || ep_id == wmi->ep_id))
2115 		return -EINVAL;
2116 
2117 	skb_push(skb, sizeof(struct wmi_data_hdr));
2118 
2119 	data_hdr = (struct wmi_data_hdr *) skb->data;
2120 	data_hdr->info = SYNC_MSGTYPE << WMI_DATA_HDR_MSG_TYPE_SHIFT;
2121 	data_hdr->info3 = 0;
2122 
2123 	ret = ath6kl_control_tx(wmi->parent_dev, skb, ep_id);
2124 
2125 	return ret;
2126 }
2127 
2128 static int ath6kl_wmi_sync_point(struct wmi *wmi)
2129 {
2130 	struct sk_buff *skb;
2131 	struct wmi_sync_cmd *cmd;
2132 	struct wmi_data_sync_bufs data_sync_bufs[WMM_NUM_AC];
2133 	enum htc_endpoint_id ep_id;
2134 	u8 index, num_pri_streams = 0;
2135 	int ret = 0;
2136 
2137 	memset(data_sync_bufs, 0, sizeof(data_sync_bufs));
2138 
2139 	spin_lock_bh(&wmi->lock);
2140 
2141 	for (index = 0; index < WMM_NUM_AC; index++) {
2142 		if (wmi->fat_pipe_exist & (1 << index)) {
2143 			num_pri_streams++;
2144 			data_sync_bufs[num_pri_streams - 1].traffic_class =
2145 			    index;
2146 		}
2147 	}
2148 
2149 	spin_unlock_bh(&wmi->lock);
2150 
2151 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2152 	if (!skb) {
2153 		ret = -ENOMEM;
2154 		goto free_skb;
2155 	}
2156 
2157 	cmd = (struct wmi_sync_cmd *) skb->data;
2158 
2159 	/*
2160 	 * In the SYNC cmd sent on the control Ep, send a bitmap
2161 	 * of the data eps on which the Data Sync will be sent
2162 	 */
2163 	cmd->data_sync_map = wmi->fat_pipe_exist;
2164 
2165 	for (index = 0; index < num_pri_streams; index++) {
2166 		data_sync_bufs[index].skb = ath6kl_buf_alloc(0);
2167 		if (data_sync_bufs[index].skb == NULL) {
2168 			ret = -ENOMEM;
2169 			break;
2170 		}
2171 	}
2172 
2173 	/*
2174 	 * If buffer allocation for any of the dataSync fails,
2175 	 * then do not send the Synchronize cmd on the control ep
2176 	 */
2177 	if (ret)
2178 		goto free_skb;
2179 
2180 	/*
2181 	 * Send sync cmd followed by sync data messages on all
2182 	 * endpoints being used
2183 	 */
2184 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SYNCHRONIZE_CMDID,
2185 				  NO_SYNC_WMIFLAG);
2186 
2187 	if (ret)
2188 		goto free_skb;
2189 
2190 	/* cmd buffer sent, we no longer own it */
2191 	skb = NULL;
2192 
2193 	for (index = 0; index < num_pri_streams; index++) {
2194 
2195 		if (WARN_ON(!data_sync_bufs[index].skb))
2196 			break;
2197 
2198 		ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev,
2199 					       data_sync_bufs[index].
2200 					       traffic_class);
2201 		ret =
2202 		    ath6kl_wmi_data_sync_send(wmi, data_sync_bufs[index].skb,
2203 					      ep_id);
2204 
2205 		if (ret)
2206 			break;
2207 
2208 		data_sync_bufs[index].skb = NULL;
2209 	}
2210 
2211 free_skb:
2212 	/* free up any resources left over (possibly due to an error) */
2213 	if (skb)
2214 		dev_kfree_skb(skb);
2215 
2216 	for (index = 0; index < num_pri_streams; index++) {
2217 		if (data_sync_bufs[index].skb != NULL) {
2218 			dev_kfree_skb((struct sk_buff *)data_sync_bufs[index].
2219 				      skb);
2220 		}
2221 	}
2222 
2223 	return ret;
2224 }
2225 
2226 int ath6kl_wmi_create_pstream_cmd(struct wmi *wmi,
2227 				  struct wmi_create_pstream_cmd *params)
2228 {
2229 	struct sk_buff *skb;
2230 	struct wmi_create_pstream_cmd *cmd;
2231 	u8 fatpipe_exist_for_ac = 0;
2232 	s32 min_phy = 0;
2233 	s32 nominal_phy = 0;
2234 	int ret;
2235 
2236 	if (!((params->user_pri < 8) &&
2237 	      (params->user_pri <= 0x7) &&
2238 	      (up_to_ac[params->user_pri & 0x7] == params->traffic_class) &&
2239 	      (params->traffic_direc == UPLINK_TRAFFIC ||
2240 	       params->traffic_direc == DNLINK_TRAFFIC ||
2241 	       params->traffic_direc == BIDIR_TRAFFIC) &&
2242 	      (params->traffic_type == TRAFFIC_TYPE_APERIODIC ||
2243 	       params->traffic_type == TRAFFIC_TYPE_PERIODIC) &&
2244 	      (params->voice_psc_cap == DISABLE_FOR_THIS_AC ||
2245 	       params->voice_psc_cap == ENABLE_FOR_THIS_AC ||
2246 	       params->voice_psc_cap == ENABLE_FOR_ALL_AC) &&
2247 	      (params->tsid == WMI_IMPLICIT_PSTREAM ||
2248 	       params->tsid <= WMI_MAX_THINSTREAM))) {
2249 		return -EINVAL;
2250 	}
2251 
2252 	/*
2253 	 * Check nominal PHY rate is >= minimalPHY,
2254 	 * so that DUT can allow TSRS IE
2255 	 */
2256 
2257 	/* Get the physical rate (units of bps) */
2258 	min_phy = ((le32_to_cpu(params->min_phy_rate) / 1000) / 1000);
2259 
2260 	/* Check minimal phy < nominal phy rate */
2261 	if (params->nominal_phy >= min_phy) {
2262 		/* unit of 500 kbps */
2263 		nominal_phy = (params->nominal_phy * 1000) / 500;
2264 		ath6kl_dbg(ATH6KL_DBG_WMI,
2265 			   "TSRS IE enabled::MinPhy %x->NominalPhy ===> %x\n",
2266 			   min_phy, nominal_phy);
2267 
2268 		params->nominal_phy = nominal_phy;
2269 	} else {
2270 		params->nominal_phy = 0;
2271 	}
2272 
2273 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2274 	if (!skb)
2275 		return -ENOMEM;
2276 
2277 	ath6kl_dbg(ATH6KL_DBG_WMI,
2278 		   "sending create_pstream_cmd: ac=%d  tsid:%d\n",
2279 		   params->traffic_class, params->tsid);
2280 
2281 	cmd = (struct wmi_create_pstream_cmd *) skb->data;
2282 	memcpy(cmd, params, sizeof(*cmd));
2283 
2284 	/* This is an implicitly created Fat pipe */
2285 	if ((u32) params->tsid == (u32) WMI_IMPLICIT_PSTREAM) {
2286 		spin_lock_bh(&wmi->lock);
2287 		fatpipe_exist_for_ac = (wmi->fat_pipe_exist &
2288 					(1 << params->traffic_class));
2289 		wmi->fat_pipe_exist |= (1 << params->traffic_class);
2290 		spin_unlock_bh(&wmi->lock);
2291 	} else {
2292 		/* explicitly created thin stream within a fat pipe */
2293 		spin_lock_bh(&wmi->lock);
2294 		fatpipe_exist_for_ac = (wmi->fat_pipe_exist &
2295 					(1 << params->traffic_class));
2296 		wmi->stream_exist_for_ac[params->traffic_class] |=
2297 		    (1 << params->tsid);
2298 		/*
2299 		 * If a thinstream becomes active, the fat pipe automatically
2300 		 * becomes active
2301 		 */
2302 		wmi->fat_pipe_exist |= (1 << params->traffic_class);
2303 		spin_unlock_bh(&wmi->lock);
2304 	}
2305 
2306 	/*
2307 	 * Indicate activty change to driver layer only if this is the
2308 	 * first TSID to get created in this AC explicitly or an implicit
2309 	 * fat pipe is getting created.
2310 	 */
2311 	if (!fatpipe_exist_for_ac)
2312 		ath6kl_indicate_tx_activity(wmi->parent_dev,
2313 					    params->traffic_class, true);
2314 
2315 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_CREATE_PSTREAM_CMDID,
2316 				  NO_SYNC_WMIFLAG);
2317 	return ret;
2318 }
2319 
2320 int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 traffic_class, u8 tsid)
2321 {
2322 	struct sk_buff *skb;
2323 	struct wmi_delete_pstream_cmd *cmd;
2324 	u16 active_tsids = 0;
2325 	int ret;
2326 
2327 	if (traffic_class > 3) {
2328 		ath6kl_err("invalid traffic class: %d\n", traffic_class);
2329 		return -EINVAL;
2330 	}
2331 
2332 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2333 	if (!skb)
2334 		return -ENOMEM;
2335 
2336 	cmd = (struct wmi_delete_pstream_cmd *) skb->data;
2337 	cmd->traffic_class = traffic_class;
2338 	cmd->tsid = tsid;
2339 
2340 	spin_lock_bh(&wmi->lock);
2341 	active_tsids = wmi->stream_exist_for_ac[traffic_class];
2342 	spin_unlock_bh(&wmi->lock);
2343 
2344 	if (!(active_tsids & (1 << tsid))) {
2345 		dev_kfree_skb(skb);
2346 		ath6kl_dbg(ATH6KL_DBG_WMI,
2347 			   "TSID %d doesn't exist for traffic class: %d\n",
2348 			   tsid, traffic_class);
2349 		return -ENODATA;
2350 	}
2351 
2352 	ath6kl_dbg(ATH6KL_DBG_WMI,
2353 		   "sending delete_pstream_cmd: traffic class: %d tsid=%d\n",
2354 		   traffic_class, tsid);
2355 
2356 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_DELETE_PSTREAM_CMDID,
2357 				  SYNC_BEFORE_WMIFLAG);
2358 
2359 	spin_lock_bh(&wmi->lock);
2360 	wmi->stream_exist_for_ac[traffic_class] &= ~(1 << tsid);
2361 	active_tsids = wmi->stream_exist_for_ac[traffic_class];
2362 	spin_unlock_bh(&wmi->lock);
2363 
2364 	/*
2365 	 * Indicate stream inactivity to driver layer only if all tsids
2366 	 * within this AC are deleted.
2367 	 */
2368 	if (!active_tsids) {
2369 		ath6kl_indicate_tx_activity(wmi->parent_dev,
2370 					    traffic_class, false);
2371 		wmi->fat_pipe_exist &= ~(1 << traffic_class);
2372 	}
2373 
2374 	return ret;
2375 }
2376 
2377 int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd)
2378 {
2379 	struct sk_buff *skb;
2380 	struct wmi_set_ip_cmd *cmd;
2381 	int ret;
2382 
2383 	/* Multicast address are not valid */
2384 	if ((*((u8 *) &ip_cmd->ips[0]) >= 0xE0) ||
2385 	    (*((u8 *) &ip_cmd->ips[1]) >= 0xE0))
2386 		return -EINVAL;
2387 
2388 	skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_ip_cmd));
2389 	if (!skb)
2390 		return -ENOMEM;
2391 
2392 	cmd = (struct wmi_set_ip_cmd *) skb->data;
2393 	memcpy(cmd, ip_cmd, sizeof(struct wmi_set_ip_cmd));
2394 
2395 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_IP_CMDID, NO_SYNC_WMIFLAG);
2396 	return ret;
2397 }
2398 
2399 static int ath6kl_wmi_get_wow_list_event_rx(struct wmi *wmi, u8 * datap,
2400 					    int len)
2401 {
2402 	if (len < sizeof(struct wmi_get_wow_list_reply))
2403 		return -EINVAL;
2404 
2405 	return 0;
2406 }
2407 
2408 static int ath6kl_wmi_cmd_send_xtnd(struct wmi *wmi, struct sk_buff *skb,
2409 				    enum wmix_command_id cmd_id,
2410 				    enum wmi_sync_flag sync_flag)
2411 {
2412 	struct wmix_cmd_hdr *cmd_hdr;
2413 	int ret;
2414 
2415 	skb_push(skb, sizeof(struct wmix_cmd_hdr));
2416 
2417 	cmd_hdr = (struct wmix_cmd_hdr *) skb->data;
2418 	cmd_hdr->cmd_id = cpu_to_le32(cmd_id);
2419 
2420 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_EXTENSION_CMDID, sync_flag);
2421 
2422 	return ret;
2423 }
2424 
2425 int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source)
2426 {
2427 	struct sk_buff *skb;
2428 	struct wmix_hb_challenge_resp_cmd *cmd;
2429 	int ret;
2430 
2431 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2432 	if (!skb)
2433 		return -ENOMEM;
2434 
2435 	cmd = (struct wmix_hb_challenge_resp_cmd *) skb->data;
2436 	cmd->cookie = cpu_to_le32(cookie);
2437 	cmd->source = cpu_to_le32(source);
2438 
2439 	ret = ath6kl_wmi_cmd_send_xtnd(wmi, skb, WMIX_HB_CHALLENGE_RESP_CMDID,
2440 				       NO_SYNC_WMIFLAG);
2441 	return ret;
2442 }
2443 
2444 int ath6kl_wmi_config_debug_module_cmd(struct wmi *wmi, u32 valid, u32 config)
2445 {
2446 	struct ath6kl_wmix_dbglog_cfg_module_cmd *cmd;
2447 	struct sk_buff *skb;
2448 	int ret;
2449 
2450 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2451 	if (!skb)
2452 		return -ENOMEM;
2453 
2454 	cmd = (struct ath6kl_wmix_dbglog_cfg_module_cmd *) skb->data;
2455 	cmd->valid = cpu_to_le32(valid);
2456 	cmd->config = cpu_to_le32(config);
2457 
2458 	ret = ath6kl_wmi_cmd_send_xtnd(wmi, skb, WMIX_DBGLOG_CFG_MODULE_CMDID,
2459 				       NO_SYNC_WMIFLAG);
2460 	return ret;
2461 }
2462 
2463 int ath6kl_wmi_get_stats_cmd(struct wmi *wmi)
2464 {
2465 	return ath6kl_wmi_simple_cmd(wmi, WMI_GET_STATISTICS_CMDID);
2466 }
2467 
2468 int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM)
2469 {
2470 	struct sk_buff *skb;
2471 	struct wmi_set_tx_pwr_cmd *cmd;
2472 	int ret;
2473 
2474 	skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_tx_pwr_cmd));
2475 	if (!skb)
2476 		return -ENOMEM;
2477 
2478 	cmd = (struct wmi_set_tx_pwr_cmd *) skb->data;
2479 	cmd->dbM = dbM;
2480 
2481 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_TX_PWR_CMDID,
2482 				  NO_SYNC_WMIFLAG);
2483 
2484 	return ret;
2485 }
2486 
2487 int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi)
2488 {
2489 	return ath6kl_wmi_simple_cmd(wmi, WMI_GET_TX_PWR_CMDID);
2490 }
2491 
2492 int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status, u8 preamble_policy)
2493 {
2494 	struct sk_buff *skb;
2495 	struct wmi_set_lpreamble_cmd *cmd;
2496 	int ret;
2497 
2498 	skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_lpreamble_cmd));
2499 	if (!skb)
2500 		return -ENOMEM;
2501 
2502 	cmd = (struct wmi_set_lpreamble_cmd *) skb->data;
2503 	cmd->status = status;
2504 	cmd->preamble_policy = preamble_policy;
2505 
2506 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_LPREAMBLE_CMDID,
2507 				  NO_SYNC_WMIFLAG);
2508 	return ret;
2509 }
2510 
2511 int ath6kl_wmi_set_rts_cmd(struct wmi *wmi, u16 threshold)
2512 {
2513 	struct sk_buff *skb;
2514 	struct wmi_set_rts_cmd *cmd;
2515 	int ret;
2516 
2517 	skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_rts_cmd));
2518 	if (!skb)
2519 		return -ENOMEM;
2520 
2521 	cmd = (struct wmi_set_rts_cmd *) skb->data;
2522 	cmd->threshold = cpu_to_le16(threshold);
2523 
2524 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_RTS_CMDID, NO_SYNC_WMIFLAG);
2525 	return ret;
2526 }
2527 
2528 int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg)
2529 {
2530 	struct sk_buff *skb;
2531 	struct wmi_set_wmm_txop_cmd *cmd;
2532 	int ret;
2533 
2534 	if (!((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)))
2535 		return -EINVAL;
2536 
2537 	skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_wmm_txop_cmd));
2538 	if (!skb)
2539 		return -ENOMEM;
2540 
2541 	cmd = (struct wmi_set_wmm_txop_cmd *) skb->data;
2542 	cmd->txop_enable = cfg;
2543 
2544 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_WMM_TXOP_CMDID,
2545 				  NO_SYNC_WMIFLAG);
2546 	return ret;
2547 }
2548 
2549 int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl)
2550 {
2551 	struct sk_buff *skb;
2552 	struct wmi_set_keepalive_cmd *cmd;
2553 	int ret;
2554 
2555 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2556 	if (!skb)
2557 		return -ENOMEM;
2558 
2559 	cmd = (struct wmi_set_keepalive_cmd *) skb->data;
2560 	cmd->keep_alive_intvl = keep_alive_intvl;
2561 	wmi->keep_alive_intvl = keep_alive_intvl;
2562 
2563 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_KEEPALIVE_CMDID,
2564 				  NO_SYNC_WMIFLAG);
2565 	return ret;
2566 }
2567 
2568 int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len)
2569 {
2570 	struct sk_buff *skb;
2571 	int ret;
2572 
2573 	skb = ath6kl_wmi_get_new_buf(len);
2574 	if (!skb)
2575 		return -ENOMEM;
2576 
2577 	memcpy(skb->data, buf, len);
2578 
2579 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_TEST_CMDID, NO_SYNC_WMIFLAG);
2580 
2581 	return ret;
2582 }
2583 
2584 
2585 s32 ath6kl_wmi_get_rate(s8 rate_index)
2586 {
2587 	if (rate_index == RATE_AUTO)
2588 		return 0;
2589 
2590 	return wmi_rate_tbl[(u32) rate_index][0];
2591 }
2592 
2593 void ath6kl_wmi_node_return(struct wmi *wmi, struct bss *bss)
2594 {
2595 	if (bss)
2596 		wlan_node_return(&wmi->parent_dev->scan_table, bss);
2597 }
2598 
2599 struct bss *ath6kl_wmi_find_ssid_node(struct wmi *wmi, u8 * ssid,
2600 				      u32 ssid_len, bool is_wpa2,
2601 				      bool match_ssid)
2602 {
2603 	struct bss *node = NULL;
2604 
2605 	node = wlan_find_ssid_node(&wmi->parent_dev->scan_table, ssid,
2606 				  ssid_len, is_wpa2, match_ssid);
2607 	return node;
2608 }
2609 
2610 struct bss *ath6kl_wmi_find_node(struct wmi *wmi, const u8 * mac_addr)
2611 {
2612 	struct bss *ni = NULL;
2613 
2614 	ni = wlan_find_node(&wmi->parent_dev->scan_table, mac_addr);
2615 
2616 	return ni;
2617 }
2618 
2619 void ath6kl_wmi_node_free(struct wmi *wmi, const u8 * mac_addr)
2620 {
2621 	struct bss *ni = NULL;
2622 
2623 	ni = wlan_find_node(&wmi->parent_dev->scan_table, mac_addr);
2624 	if (ni != NULL)
2625 		wlan_node_reclaim(&wmi->parent_dev->scan_table, ni);
2626 
2627 	return;
2628 }
2629 
2630 static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,
2631 					      u32 len)
2632 {
2633 	struct wmi_pmkid_list_reply *reply;
2634 	u32 expected_len;
2635 
2636 	if (len < sizeof(struct wmi_pmkid_list_reply))
2637 		return -EINVAL;
2638 
2639 	reply = (struct wmi_pmkid_list_reply *)datap;
2640 	expected_len = sizeof(reply->num_pmkid) +
2641 		le32_to_cpu(reply->num_pmkid) * WMI_PMKID_LEN;
2642 
2643 	if (len < expected_len)
2644 		return -EINVAL;
2645 
2646 	return 0;
2647 }
2648 
2649 static int ath6kl_wmi_addba_req_event_rx(struct wmi *wmi, u8 *datap, int len)
2650 {
2651 	struct wmi_addba_req_event *cmd = (struct wmi_addba_req_event *) datap;
2652 
2653 	aggr_recv_addba_req_evt(wmi->parent_dev, cmd->tid,
2654 				le16_to_cpu(cmd->st_seq_no), cmd->win_sz);
2655 
2656 	return 0;
2657 }
2658 
2659 static int ath6kl_wmi_delba_req_event_rx(struct wmi *wmi, u8 *datap, int len)
2660 {
2661 	struct wmi_delba_event *cmd = (struct wmi_delba_event *) datap;
2662 
2663 	aggr_recv_delba_req_evt(wmi->parent_dev, cmd->tid);
2664 
2665 	return 0;
2666 }
2667 
2668 /*  AP mode functions */
2669 
2670 int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, struct wmi_connect_cmd *p)
2671 {
2672 	struct sk_buff *skb;
2673 	struct wmi_connect_cmd *cm;
2674 	int res;
2675 
2676 	skb = ath6kl_wmi_get_new_buf(sizeof(*cm));
2677 	if (!skb)
2678 		return -ENOMEM;
2679 
2680 	cm = (struct wmi_connect_cmd *) skb->data;
2681 	memcpy(cm, p, sizeof(*cm));
2682 
2683 	res = ath6kl_wmi_cmd_send(wmip, skb, WMI_AP_CONFIG_COMMIT_CMDID,
2684 				  NO_SYNC_WMIFLAG);
2685 	ath6kl_dbg(ATH6KL_DBG_WMI, "%s: nw_type=%u auth_mode=%u ch=%u "
2686 		   "ctrl_flags=0x%x-> res=%d\n",
2687 		   __func__, p->nw_type, p->auth_mode, le16_to_cpu(p->ch),
2688 		   le32_to_cpu(p->ctrl_flags), res);
2689 	return res;
2690 }
2691 
2692 int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 cmd, const u8 *mac, u16 reason)
2693 {
2694 	struct sk_buff *skb;
2695 	struct wmi_ap_set_mlme_cmd *cm;
2696 
2697 	skb = ath6kl_wmi_get_new_buf(sizeof(*cm));
2698 	if (!skb)
2699 		return -ENOMEM;
2700 
2701 	cm = (struct wmi_ap_set_mlme_cmd *) skb->data;
2702 	memcpy(cm->mac, mac, ETH_ALEN);
2703 	cm->reason = cpu_to_le16(reason);
2704 	cm->cmd = cmd;
2705 
2706 	return ath6kl_wmi_cmd_send(wmip, skb, WMI_AP_SET_MLME_CMDID,
2707 				   NO_SYNC_WMIFLAG);
2708 }
2709 
2710 static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len)
2711 {
2712 	struct wmi_pspoll_event *ev;
2713 
2714 	if (len < sizeof(struct wmi_pspoll_event))
2715 		return -EINVAL;
2716 
2717 	ev = (struct wmi_pspoll_event *) datap;
2718 
2719 	ath6kl_pspoll_event(wmi->parent_dev, le16_to_cpu(ev->aid));
2720 
2721 	return 0;
2722 }
2723 
2724 static int ath6kl_wmi_dtimexpiry_event_rx(struct wmi *wmi, u8 *datap, int len)
2725 {
2726 	ath6kl_dtimexpiry_event(wmi->parent_dev);
2727 
2728 	return 0;
2729 }
2730 
2731 int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag)
2732 {
2733 	struct sk_buff *skb;
2734 	struct wmi_ap_set_pvb_cmd *cmd;
2735 	int ret;
2736 
2737 	skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_ap_set_pvb_cmd));
2738 	if (!skb)
2739 		return -ENOMEM;
2740 
2741 	cmd = (struct wmi_ap_set_pvb_cmd *) skb->data;
2742 	cmd->aid = cpu_to_le16(aid);
2743 	cmd->flag = cpu_to_le32(flag);
2744 
2745 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_AP_SET_PVB_CMDID,
2746 				  NO_SYNC_WMIFLAG);
2747 
2748 	return 0;
2749 }
2750 
2751 int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_ver,
2752 				       bool rx_dot11_hdr, bool defrag_on_host)
2753 {
2754 	struct sk_buff *skb;
2755 	struct wmi_rx_frame_format_cmd *cmd;
2756 	int ret;
2757 
2758 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2759 	if (!skb)
2760 		return -ENOMEM;
2761 
2762 	cmd = (struct wmi_rx_frame_format_cmd *) skb->data;
2763 	cmd->dot11_hdr = rx_dot11_hdr ? 1 : 0;
2764 	cmd->defrag_on_host = defrag_on_host ? 1 : 0;
2765 	cmd->meta_ver = rx_meta_ver;
2766 
2767 	/* Delete the local aggr state, on host */
2768 	ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_RX_FRAME_FORMAT_CMDID,
2769 				  NO_SYNC_WMIFLAG);
2770 
2771 	return ret;
2772 }
2773 
2774 int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 mgmt_frm_type, const u8 *ie,
2775 			     u8 ie_len)
2776 {
2777 	struct sk_buff *skb;
2778 	struct wmi_set_appie_cmd *p;
2779 
2780 	skb = ath6kl_wmi_get_new_buf(sizeof(*p) + ie_len);
2781 	if (!skb)
2782 		return -ENOMEM;
2783 
2784 	ath6kl_dbg(ATH6KL_DBG_WMI, "set_appie_cmd: mgmt_frm_type=%u "
2785 		   "ie_len=%u\n", mgmt_frm_type, ie_len);
2786 	p = (struct wmi_set_appie_cmd *) skb->data;
2787 	p->mgmt_frm_type = mgmt_frm_type;
2788 	p->ie_len = ie_len;
2789 	memcpy(p->ie_info, ie, ie_len);
2790 	return ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_APPIE_CMDID,
2791 				   NO_SYNC_WMIFLAG);
2792 }
2793 
2794 int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable)
2795 {
2796 	struct sk_buff *skb;
2797 	struct wmi_disable_11b_rates_cmd *cmd;
2798 
2799 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2800 	if (!skb)
2801 		return -ENOMEM;
2802 
2803 	ath6kl_dbg(ATH6KL_DBG_WMI, "disable_11b_rates_cmd: disable=%u\n",
2804 		   disable);
2805 	cmd = (struct wmi_disable_11b_rates_cmd *) skb->data;
2806 	cmd->disable = disable ? 1 : 0;
2807 
2808 	return ath6kl_wmi_cmd_send(wmi, skb, WMI_DISABLE_11B_RATES_CMDID,
2809 				   NO_SYNC_WMIFLAG);
2810 }
2811 
2812 int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u32 freq, u32 dur)
2813 {
2814 	struct sk_buff *skb;
2815 	struct wmi_remain_on_chnl_cmd *p;
2816 
2817 	skb = ath6kl_wmi_get_new_buf(sizeof(*p));
2818 	if (!skb)
2819 		return -ENOMEM;
2820 
2821 	ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl_cmd: freq=%u dur=%u\n",
2822 		   freq, dur);
2823 	p = (struct wmi_remain_on_chnl_cmd *) skb->data;
2824 	p->freq = cpu_to_le32(freq);
2825 	p->duration = cpu_to_le32(dur);
2826 	return ath6kl_wmi_cmd_send(wmi, skb, WMI_REMAIN_ON_CHNL_CMDID,
2827 				   NO_SYNC_WMIFLAG);
2828 }
2829 
2830 int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u32 id, u32 freq, u32 wait,
2831 			       const u8 *data, u16 data_len)
2832 {
2833 	struct sk_buff *skb;
2834 	struct wmi_send_action_cmd *p;
2835 	u8 *buf;
2836 
2837 	if (wait)
2838 		return -EINVAL; /* Offload for wait not supported */
2839 
2840 	buf = kmalloc(data_len, GFP_KERNEL);
2841 	if (!buf)
2842 		return -ENOMEM;
2843 
2844 	skb = ath6kl_wmi_get_new_buf(sizeof(*p) + data_len);
2845 	if (!skb) {
2846 		kfree(buf);
2847 		return -ENOMEM;
2848 	}
2849 
2850 	kfree(wmi->last_mgmt_tx_frame);
2851 	wmi->last_mgmt_tx_frame = buf;
2852 	wmi->last_mgmt_tx_frame_len = data_len;
2853 
2854 	ath6kl_dbg(ATH6KL_DBG_WMI, "send_action_cmd: id=%u freq=%u wait=%u "
2855 		   "len=%u\n", id, freq, wait, data_len);
2856 	p = (struct wmi_send_action_cmd *) skb->data;
2857 	p->id = cpu_to_le32(id);
2858 	p->freq = cpu_to_le32(freq);
2859 	p->wait = cpu_to_le32(wait);
2860 	p->len = cpu_to_le16(data_len);
2861 	memcpy(p->data, data, data_len);
2862 	return ath6kl_wmi_cmd_send(wmi, skb, WMI_SEND_ACTION_CMDID,
2863 				   NO_SYNC_WMIFLAG);
2864 }
2865 
2866 int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u32 freq,
2867 				       const u8 *dst,
2868 				       const u8 *data, u16 data_len)
2869 {
2870 	struct sk_buff *skb;
2871 	struct wmi_p2p_probe_response_cmd *p;
2872 
2873 	skb = ath6kl_wmi_get_new_buf(sizeof(*p) + data_len);
2874 	if (!skb)
2875 		return -ENOMEM;
2876 
2877 	ath6kl_dbg(ATH6KL_DBG_WMI, "send_probe_response_cmd: freq=%u dst=%pM "
2878 		   "len=%u\n", freq, dst, data_len);
2879 	p = (struct wmi_p2p_probe_response_cmd *) skb->data;
2880 	p->freq = cpu_to_le32(freq);
2881 	memcpy(p->destination_addr, dst, ETH_ALEN);
2882 	p->len = cpu_to_le16(data_len);
2883 	memcpy(p->data, data, data_len);
2884 	return ath6kl_wmi_cmd_send(wmi, skb, WMI_SEND_PROBE_RESPONSE_CMDID,
2885 				   NO_SYNC_WMIFLAG);
2886 }
2887 
2888 int ath6kl_wmi_probe_report_req_cmd(struct wmi *wmi, bool enable)
2889 {
2890 	struct sk_buff *skb;
2891 	struct wmi_probe_req_report_cmd *p;
2892 
2893 	skb = ath6kl_wmi_get_new_buf(sizeof(*p));
2894 	if (!skb)
2895 		return -ENOMEM;
2896 
2897 	ath6kl_dbg(ATH6KL_DBG_WMI, "probe_report_req_cmd: enable=%u\n",
2898 		   enable);
2899 	p = (struct wmi_probe_req_report_cmd *) skb->data;
2900 	p->enable = enable ? 1 : 0;
2901 	return ath6kl_wmi_cmd_send(wmi, skb, WMI_PROBE_REQ_REPORT_CMDID,
2902 				   NO_SYNC_WMIFLAG);
2903 }
2904 
2905 int ath6kl_wmi_info_req_cmd(struct wmi *wmi, u32 info_req_flags)
2906 {
2907 	struct sk_buff *skb;
2908 	struct wmi_get_p2p_info *p;
2909 
2910 	skb = ath6kl_wmi_get_new_buf(sizeof(*p));
2911 	if (!skb)
2912 		return -ENOMEM;
2913 
2914 	ath6kl_dbg(ATH6KL_DBG_WMI, "info_req_cmd: flags=%x\n",
2915 		   info_req_flags);
2916 	p = (struct wmi_get_p2p_info *) skb->data;
2917 	p->info_req_flags = cpu_to_le32(info_req_flags);
2918 	return ath6kl_wmi_cmd_send(wmi, skb, WMI_GET_P2P_INFO_CMDID,
2919 				   NO_SYNC_WMIFLAG);
2920 }
2921 
2922 int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi)
2923 {
2924 	ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl_cmd\n");
2925 	return ath6kl_wmi_simple_cmd(wmi, WMI_CANCEL_REMAIN_ON_CHNL_CMDID);
2926 }
2927 
2928 static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
2929 {
2930 	struct wmix_cmd_hdr *cmd;
2931 	u32 len;
2932 	u16 id;
2933 	u8 *datap;
2934 	int ret = 0;
2935 
2936 	if (skb->len < sizeof(struct wmix_cmd_hdr)) {
2937 		ath6kl_err("bad packet 1\n");
2938 		wmi->stat.cmd_len_err++;
2939 		return -EINVAL;
2940 	}
2941 
2942 	cmd = (struct wmix_cmd_hdr *) skb->data;
2943 	id = le32_to_cpu(cmd->cmd_id);
2944 
2945 	skb_pull(skb, sizeof(struct wmix_cmd_hdr));
2946 
2947 	datap = skb->data;
2948 	len = skb->len;
2949 
2950 	switch (id) {
2951 	case WMIX_HB_CHALLENGE_RESP_EVENTID:
2952 		break;
2953 	case WMIX_DBGLOG_EVENTID:
2954 		ath6kl_debug_fwlog_event(wmi->parent_dev, datap, len);
2955 		break;
2956 	default:
2957 		ath6kl_err("unknown cmd id 0x%x\n", id);
2958 		wmi->stat.cmd_id_err++;
2959 		ret = -EINVAL;
2960 		break;
2961 	}
2962 
2963 	return ret;
2964 }
2965 
2966 /* Control Path */
2967 int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
2968 {
2969 	struct wmi_cmd_hdr *cmd;
2970 	u32 len;
2971 	u16 id;
2972 	u8 *datap;
2973 	int ret = 0;
2974 
2975 	if (WARN_ON(skb == NULL))
2976 		return -EINVAL;
2977 
2978 	if (skb->len < sizeof(struct wmi_cmd_hdr)) {
2979 		ath6kl_err("bad packet 1\n");
2980 		dev_kfree_skb(skb);
2981 		wmi->stat.cmd_len_err++;
2982 		return -EINVAL;
2983 	}
2984 
2985 	cmd = (struct wmi_cmd_hdr *) skb->data;
2986 	id = le16_to_cpu(cmd->cmd_id);
2987 
2988 	skb_pull(skb, sizeof(struct wmi_cmd_hdr));
2989 
2990 	datap = skb->data;
2991 	len = skb->len;
2992 
2993 	ath6kl_dbg(ATH6KL_DBG_WMI, "%s: wmi id: %d\n", __func__, id);
2994 	ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "msg payload ", datap, len);
2995 
2996 	switch (id) {
2997 	case WMI_GET_BITRATE_CMDID:
2998 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_BITRATE_CMDID\n");
2999 		ret = ath6kl_wmi_bitrate_reply_rx(wmi, datap, len);
3000 		break;
3001 	case WMI_GET_CHANNEL_LIST_CMDID:
3002 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_CHANNEL_LIST_CMDID\n");
3003 		ret = ath6kl_wmi_ch_list_reply_rx(wmi, datap, len);
3004 		break;
3005 	case WMI_GET_TX_PWR_CMDID:
3006 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_TX_PWR_CMDID\n");
3007 		ret = ath6kl_wmi_tx_pwr_reply_rx(wmi, datap, len);
3008 		break;
3009 	case WMI_READY_EVENTID:
3010 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_READY_EVENTID\n");
3011 		ret = ath6kl_wmi_ready_event_rx(wmi, datap, len);
3012 		break;
3013 	case WMI_CONNECT_EVENTID:
3014 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CONNECT_EVENTID\n");
3015 		ret = ath6kl_wmi_connect_event_rx(wmi, datap, len);
3016 		break;
3017 	case WMI_DISCONNECT_EVENTID:
3018 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DISCONNECT_EVENTID\n");
3019 		ret = ath6kl_wmi_disconnect_event_rx(wmi, datap, len);
3020 		break;
3021 	case WMI_PEER_NODE_EVENTID:
3022 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PEER_NODE_EVENTID\n");
3023 		ret = ath6kl_wmi_peer_node_event_rx(wmi, datap, len);
3024 		break;
3025 	case WMI_TKIP_MICERR_EVENTID:
3026 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TKIP_MICERR_EVENTID\n");
3027 		ret = ath6kl_wmi_tkip_micerr_event_rx(wmi, datap, len);
3028 		break;
3029 	case WMI_BSSINFO_EVENTID:
3030 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_BSSINFO_EVENTID\n");
3031 		ath6kl_wmi_convert_bssinfo_hdr2_to_hdr(skb, datap);
3032 		ret = ath6kl_wmi_bssinfo_event_rx(wmi, skb->data, skb->len);
3033 		break;
3034 	case WMI_REGDOMAIN_EVENTID:
3035 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REGDOMAIN_EVENTID\n");
3036 		break;
3037 	case WMI_PSTREAM_TIMEOUT_EVENTID:
3038 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSTREAM_TIMEOUT_EVENTID\n");
3039 		ret = ath6kl_wmi_pstream_timeout_event_rx(wmi, datap, len);
3040 		break;
3041 	case WMI_NEIGHBOR_REPORT_EVENTID:
3042 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_NEIGHBOR_REPORT_EVENTID\n");
3043 		break;
3044 	case WMI_SCAN_COMPLETE_EVENTID:
3045 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SCAN_COMPLETE_EVENTID\n");
3046 		ret = ath6kl_wmi_scan_complete_rx(wmi, datap, len);
3047 		break;
3048 	case WMI_CMDERROR_EVENTID:
3049 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CMDERROR_EVENTID\n");
3050 		ret = ath6kl_wmi_error_event_rx(wmi, datap, len);
3051 		break;
3052 	case WMI_REPORT_STATISTICS_EVENTID:
3053 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_STATISTICS_EVENTID\n");
3054 		ret = ath6kl_wmi_stats_event_rx(wmi, datap, len);
3055 		break;
3056 	case WMI_RSSI_THRESHOLD_EVENTID:
3057 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RSSI_THRESHOLD_EVENTID\n");
3058 		ret = ath6kl_wmi_rssi_threshold_event_rx(wmi, datap, len);
3059 		break;
3060 	case WMI_ERROR_REPORT_EVENTID:
3061 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ERROR_REPORT_EVENTID\n");
3062 		break;
3063 	case WMI_OPT_RX_FRAME_EVENTID:
3064 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_OPT_RX_FRAME_EVENTID\n");
3065 		ret = ath6kl_wmi_opt_frame_event_rx(wmi, datap, len);
3066 		break;
3067 	case WMI_REPORT_ROAM_TBL_EVENTID:
3068 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_TBL_EVENTID\n");
3069 		break;
3070 	case WMI_EXTENSION_EVENTID:
3071 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_EXTENSION_EVENTID\n");
3072 		ret = ath6kl_wmi_control_rx_xtnd(wmi, skb);
3073 		break;
3074 	case WMI_CAC_EVENTID:
3075 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CAC_EVENTID\n");
3076 		ret = ath6kl_wmi_cac_event_rx(wmi, datap, len);
3077 		break;
3078 	case WMI_CHANNEL_CHANGE_EVENTID:
3079 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CHANNEL_CHANGE_EVENTID\n");
3080 		break;
3081 	case WMI_REPORT_ROAM_DATA_EVENTID:
3082 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_DATA_EVENTID\n");
3083 		break;
3084 	case WMI_TEST_EVENTID:
3085 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TEST_EVENTID\n");
3086 		ret = ath6kl_wmi_tcmd_test_report_rx(wmi, datap, len);
3087 		break;
3088 	case WMI_GET_FIXRATES_CMDID:
3089 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_FIXRATES_CMDID\n");
3090 		ret = ath6kl_wmi_ratemask_reply_rx(wmi, datap, len);
3091 		break;
3092 	case WMI_TX_RETRY_ERR_EVENTID:
3093 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_RETRY_ERR_EVENTID\n");
3094 		break;
3095 	case WMI_SNR_THRESHOLD_EVENTID:
3096 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SNR_THRESHOLD_EVENTID\n");
3097 		ret = ath6kl_wmi_snr_threshold_event_rx(wmi, datap, len);
3098 		break;
3099 	case WMI_LQ_THRESHOLD_EVENTID:
3100 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_LQ_THRESHOLD_EVENTID\n");
3101 		break;
3102 	case WMI_APLIST_EVENTID:
3103 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_APLIST_EVENTID\n");
3104 		ret = ath6kl_wmi_aplist_event_rx(wmi, datap, len);
3105 		break;
3106 	case WMI_GET_KEEPALIVE_CMDID:
3107 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_KEEPALIVE_CMDID\n");
3108 		ret = ath6kl_wmi_keepalive_reply_rx(wmi, datap, len);
3109 		break;
3110 	case WMI_GET_WOW_LIST_EVENTID:
3111 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_WOW_LIST_EVENTID\n");
3112 		ret = ath6kl_wmi_get_wow_list_event_rx(wmi, datap, len);
3113 		break;
3114 	case WMI_GET_PMKID_LIST_EVENTID:
3115 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_PMKID_LIST_EVENTID\n");
3116 		ret = ath6kl_wmi_get_pmkid_list_event_rx(wmi, datap, len);
3117 		break;
3118 	case WMI_PSPOLL_EVENTID:
3119 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSPOLL_EVENTID\n");
3120 		ret = ath6kl_wmi_pspoll_event_rx(wmi, datap, len);
3121 		break;
3122 	case WMI_DTIMEXPIRY_EVENTID:
3123 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DTIMEXPIRY_EVENTID\n");
3124 		ret = ath6kl_wmi_dtimexpiry_event_rx(wmi, datap, len);
3125 		break;
3126 	case WMI_SET_PARAMS_REPLY_EVENTID:
3127 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SET_PARAMS_REPLY_EVENTID\n");
3128 		break;
3129 	case WMI_ADDBA_REQ_EVENTID:
3130 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_REQ_EVENTID\n");
3131 		ret = ath6kl_wmi_addba_req_event_rx(wmi, datap, len);
3132 		break;
3133 	case WMI_ADDBA_RESP_EVENTID:
3134 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_RESP_EVENTID\n");
3135 		break;
3136 	case WMI_DELBA_REQ_EVENTID:
3137 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DELBA_REQ_EVENTID\n");
3138 		ret = ath6kl_wmi_delba_req_event_rx(wmi, datap, len);
3139 		break;
3140 	case WMI_REPORT_BTCOEX_CONFIG_EVENTID:
3141 		ath6kl_dbg(ATH6KL_DBG_WMI,
3142 			   "WMI_REPORT_BTCOEX_CONFIG_EVENTID\n");
3143 		break;
3144 	case WMI_REPORT_BTCOEX_STATS_EVENTID:
3145 		ath6kl_dbg(ATH6KL_DBG_WMI,
3146 			   "WMI_REPORT_BTCOEX_STATS_EVENTID\n");
3147 		break;
3148 	case WMI_TX_COMPLETE_EVENTID:
3149 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n");
3150 		ret = ath6kl_wmi_tx_complete_event_rx(datap, len);
3151 		break;
3152 	case WMI_REMAIN_ON_CHNL_EVENTID:
3153 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n");
3154 		ret = ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len);
3155 		break;
3156 	case WMI_CANCEL_REMAIN_ON_CHNL_EVENTID:
3157 		ath6kl_dbg(ATH6KL_DBG_WMI,
3158 			   "WMI_CANCEL_REMAIN_ON_CHNL_EVENTID\n");
3159 		ret = ath6kl_wmi_cancel_remain_on_chnl_event_rx(wmi, datap,
3160 								len);
3161 		break;
3162 	case WMI_TX_STATUS_EVENTID:
3163 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_STATUS_EVENTID\n");
3164 		ret = ath6kl_wmi_tx_status_event_rx(wmi, datap, len);
3165 		break;
3166 	case WMI_RX_PROBE_REQ_EVENTID:
3167 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_PROBE_REQ_EVENTID\n");
3168 		ret = ath6kl_wmi_rx_probe_req_event_rx(wmi, datap, len);
3169 		break;
3170 	case WMI_P2P_CAPABILITIES_EVENTID:
3171 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_CAPABILITIES_EVENTID\n");
3172 		ret = ath6kl_wmi_p2p_capabilities_event_rx(datap, len);
3173 		break;
3174 	case WMI_RX_ACTION_EVENTID:
3175 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_ACTION_EVENTID\n");
3176 		ret = ath6kl_wmi_rx_action_event_rx(wmi, datap, len);
3177 		break;
3178 	case WMI_P2P_INFO_EVENTID:
3179 		ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_INFO_EVENTID\n");
3180 		ret = ath6kl_wmi_p2p_info_event_rx(datap, len);
3181 		break;
3182 	default:
3183 		ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", id);
3184 		wmi->stat.cmd_id_err++;
3185 		ret = -EINVAL;
3186 		break;
3187 	}
3188 
3189 	dev_kfree_skb(skb);
3190 
3191 	return ret;
3192 }
3193 
3194 static void ath6kl_wmi_qos_state_init(struct wmi *wmi)
3195 {
3196 	if (!wmi)
3197 		return;
3198 
3199 	spin_lock_bh(&wmi->lock);
3200 
3201 	wmi->fat_pipe_exist = 0;
3202 	memset(wmi->stream_exist_for_ac, 0, sizeof(wmi->stream_exist_for_ac));
3203 
3204 	spin_unlock_bh(&wmi->lock);
3205 }
3206 
3207 void *ath6kl_wmi_init(struct ath6kl *dev)
3208 {
3209 	struct wmi *wmi;
3210 
3211 	wmi = kzalloc(sizeof(struct wmi), GFP_KERNEL);
3212 	if (!wmi)
3213 		return NULL;
3214 
3215 	spin_lock_init(&wmi->lock);
3216 
3217 	wmi->parent_dev = dev;
3218 
3219 	ath6kl_wmi_qos_state_init(wmi);
3220 
3221 	wmi->pwr_mode = REC_POWER;
3222 	wmi->phy_mode = WMI_11G_MODE;
3223 
3224 	wmi->pair_crypto_type = NONE_CRYPT;
3225 	wmi->grp_crypto_type = NONE_CRYPT;
3226 
3227 	wmi->ht_allowed[A_BAND_24GHZ] = 1;
3228 	wmi->ht_allowed[A_BAND_5GHZ] = 1;
3229 
3230 	return wmi;
3231 }
3232 
3233 void ath6kl_wmi_shutdown(struct wmi *wmi)
3234 {
3235 	if (!wmi)
3236 		return;
3237 
3238 	kfree(wmi->last_mgmt_tx_frame);
3239 	kfree(wmi);
3240 }
3241