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