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