Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wmi.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2004-2011 Atheros Communications Inc.
3  * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <linux/ip.h>
19 #include <linux/in.h>
20 #include "core.h"
21 #include "debug.h"
22 #include "testmode.h"
23 #include "../regd.h"
24 #include "../regd_common.h"
25 
26 static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx);
27 
28 static const s32 wmi_rate_tbl[][2] = {
29  /* {W/O SGI, with SGI} */
30  {1000, 1000},
31  {2000, 2000},
32  {5500, 5500},
33  {11000, 11000},
34  {6000, 6000},
35  {9000, 9000},
36  {12000, 12000},
37  {18000, 18000},
38  {24000, 24000},
39  {36000, 36000},
40  {48000, 48000},
41  {54000, 54000},
42  {6500, 7200},
43  {13000, 14400},
44  {19500, 21700},
45  {26000, 28900},
46  {39000, 43300},
47  {52000, 57800},
48  {58500, 65000},
49  {65000, 72200},
50  {13500, 15000},
51  {27000, 30000},
52  {40500, 45000},
53  {54000, 60000},
54  {81000, 90000},
55  {108000, 120000},
56  {121500, 135000},
57  {135000, 150000},
58  {0, 0}
59 };
60 
61 /* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
62 static const u8 up_to_ac[] = {
63  WMM_AC_BE,
64  WMM_AC_BK,
65  WMM_AC_BK,
66  WMM_AC_BE,
67  WMM_AC_VI,
68  WMM_AC_VI,
69  WMM_AC_VO,
70  WMM_AC_VO,
71 };
72 
74 {
75  if (WARN_ON(ep_id == ENDPOINT_UNUSED || ep_id >= ENDPOINT_MAX))
76  return;
77 
78  wmi->ep_id = ep_id;
79 }
80 
82 {
83  return wmi->ep_id;
84 }
85 
86 struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx)
87 {
88  struct ath6kl_vif *vif, *found = NULL;
89 
90  if (WARN_ON(if_idx > (ar->vif_max - 1)))
91  return NULL;
92 
93  /* FIXME: Locking */
94  spin_lock_bh(&ar->list_lock);
95  list_for_each_entry(vif, &ar->vif_list, list) {
96  if (vif->fw_vif_idx == if_idx) {
97  found = vif;
98  break;
99  }
100  }
101  spin_unlock_bh(&ar->list_lock);
102 
103  return found;
104 }
105 
106 /* Performs DIX to 802.3 encapsulation for transmit packets.
107  * Assumes the entire DIX header is contigous and that there is
108  * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers.
109  */
110 int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb)
111 {
112  struct ath6kl_llc_snap_hdr *llc_hdr;
113  struct ethhdr *eth_hdr;
114  size_t new_len;
115  __be16 type;
116  u8 *datap;
117  u16 size;
118 
119  if (WARN_ON(skb == NULL))
120  return -EINVAL;
121 
122  size = sizeof(struct ath6kl_llc_snap_hdr) + sizeof(struct wmi_data_hdr);
123  if (skb_headroom(skb) < size)
124  return -ENOMEM;
125 
126  eth_hdr = (struct ethhdr *) skb->data;
127  type = eth_hdr->h_proto;
128 
129  if (!is_ethertype(be16_to_cpu(type))) {
130  ath6kl_dbg(ATH6KL_DBG_WMI,
131  "%s: pkt is already in 802.3 format\n", __func__);
132  return 0;
133  }
134 
135  new_len = skb->len - sizeof(*eth_hdr) + sizeof(*llc_hdr);
136 
137  skb_push(skb, sizeof(struct ath6kl_llc_snap_hdr));
138  datap = skb->data;
139 
140  eth_hdr->h_proto = cpu_to_be16(new_len);
141 
142  memcpy(datap, eth_hdr, sizeof(*eth_hdr));
143 
144  llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap + sizeof(*eth_hdr));
145  llc_hdr->dsap = 0xAA;
146  llc_hdr->ssap = 0xAA;
147  llc_hdr->cntl = 0x03;
148  llc_hdr->org_code[0] = 0x0;
149  llc_hdr->org_code[1] = 0x0;
150  llc_hdr->org_code[2] = 0x0;
151  llc_hdr->eth_type = type;
152 
153  return 0;
154 }
155 
156 static int ath6kl_wmi_meta_add(struct wmi *wmi, struct sk_buff *skb,
157  u8 *version, void *tx_meta_info)
158 {
159  struct wmi_tx_meta_v1 *v1;
160  struct wmi_tx_meta_v2 *v2;
161 
162  if (WARN_ON(skb == NULL || version == NULL))
163  return -EINVAL;
164 
165  switch (*version) {
166  case WMI_META_VERSION_1:
168  v1 = (struct wmi_tx_meta_v1 *) skb->data;
169  v1->pkt_id = 0;
170  v1->rate_plcy_id = 0;
171  *version = WMI_META_VERSION_1;
172  break;
173  case WMI_META_VERSION_2:
175  v2 = (struct wmi_tx_meta_v2 *) skb->data;
176  memcpy(v2, (struct wmi_tx_meta_v2 *) tx_meta_info,
177  sizeof(struct wmi_tx_meta_v2));
178  break;
179  }
180 
181  return 0;
182 }
183 
184 int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb,
185  u8 msg_type, u32 flags,
187  u8 meta_ver, void *tx_meta_info, u8 if_idx)
188 {
189  struct wmi_data_hdr *data_hdr;
190  int ret;
191 
192  if (WARN_ON(skb == NULL || (if_idx > wmi->parent_dev->vif_max - 1)))
193  return -EINVAL;
194 
195  if (tx_meta_info) {
196  ret = ath6kl_wmi_meta_add(wmi, skb, &meta_ver, tx_meta_info);
197  if (ret)
198  return ret;
199  }
200 
201  skb_push(skb, sizeof(struct wmi_data_hdr));
202 
203  data_hdr = (struct wmi_data_hdr *)skb->data;
204  memset(data_hdr, 0, sizeof(struct wmi_data_hdr));
205 
206  data_hdr->info = msg_type << WMI_DATA_HDR_MSG_TYPE_SHIFT;
207  data_hdr->info |= data_type << WMI_DATA_HDR_DATA_TYPE_SHIFT;
208 
209  if (flags & WMI_DATA_HDR_FLAGS_MORE)
210  data_hdr->info |= WMI_DATA_HDR_MORE;
211 
212  if (flags & WMI_DATA_HDR_FLAGS_EOSP)
213  data_hdr->info3 |= cpu_to_le16(WMI_DATA_HDR_EOSP);
214 
215  data_hdr->info2 |= cpu_to_le16(meta_ver << WMI_DATA_HDR_META_SHIFT);
216  data_hdr->info3 |= cpu_to_le16(if_idx & WMI_DATA_HDR_IF_IDX_MASK);
217 
218  return 0;
219 }
220 
222 {
223  struct iphdr *ip_hdr = (struct iphdr *) pkt;
224  u8 ip_pri;
225 
226  /*
227  * Determine IPTOS priority
228  *
229  * IP-TOS - 8bits
230  * : DSCP(6-bits) ECN(2-bits)
231  * : DSCP - P2 P1 P0 X X X
232  * where (P2 P1 P0) form 802.1D
233  */
234  ip_pri = ip_hdr->tos >> 5;
235  ip_pri &= 0x7;
236 
237  if ((layer2_pri & 0x7) > ip_pri)
238  return (u8) layer2_pri & 0x7;
239  else
240  return ip_pri;
241 }
242 
244 {
245  return up_to_ac[user_priority & 0x7];
246 }
247 
248 int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, u8 if_idx,
249  struct sk_buff *skb,
250  u32 layer2_priority, bool wmm_enabled,
251  u8 *ac)
252 {
253  struct wmi_data_hdr *data_hdr;
254  struct ath6kl_llc_snap_hdr *llc_hdr;
255  struct wmi_create_pstream_cmd cmd;
256  u32 meta_size, hdr_size;
257  u16 ip_type = IP_ETHERTYPE;
258  u8 stream_exist, usr_pri;
260  u8 *datap;
261 
262  if (WARN_ON(skb == NULL))
263  return -EINVAL;
264 
265  datap = skb->data;
266  data_hdr = (struct wmi_data_hdr *) datap;
267 
268  meta_size = ((le16_to_cpu(data_hdr->info2) >> WMI_DATA_HDR_META_SHIFT) &
270 
271  if (!wmm_enabled) {
272  /* If WMM is disabled all traffic goes as BE traffic */
273  usr_pri = 0;
274  } else {
275  hdr_size = sizeof(struct ethhdr);
276 
277  llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap +
278  sizeof(struct
279  wmi_data_hdr) +
280  meta_size + hdr_size);
281 
282  if (llc_hdr->eth_type == htons(ip_type)) {
283  /*
284  * Extract the endpoint info from the TOS field
285  * in the IP header.
286  */
287  usr_pri =
288  ath6kl_wmi_determine_user_priority(((u8 *) llc_hdr) +
289  sizeof(struct ath6kl_llc_snap_hdr),
290  layer2_priority);
291  } else
292  usr_pri = layer2_priority & 0x7;
293 
294  /*
295  * Queue the EAPOL frames in the same WMM_AC_VO queue
296  * as that of management frames.
297  */
298  if (skb->protocol == cpu_to_be16(ETH_P_PAE))
299  usr_pri = WMI_VOICE_USER_PRIORITY;
300  }
301 
302  /*
303  * workaround for WMM S5
304  *
305  * FIXME: wmi->traffic_class is always 100 so this test doesn't
306  * make sense
307  */
308  if ((wmi->traffic_class == WMM_AC_VI) &&
309  ((usr_pri == 5) || (usr_pri == 4)))
310  usr_pri = 1;
311 
312  /* Convert user priority to traffic class */
313  traffic_class = up_to_ac[usr_pri & 0x7];
314 
315  wmi_data_hdr_set_up(data_hdr, usr_pri);
316 
317  spin_lock_bh(&wmi->lock);
318  stream_exist = wmi->fat_pipe_exist;
319  spin_unlock_bh(&wmi->lock);
320 
321  if (!(stream_exist & (1 << traffic_class))) {
322  memset(&cmd, 0, sizeof(cmd));
323  cmd.traffic_class = traffic_class;
324  cmd.user_pri = usr_pri;
325  cmd.inactivity_int =
327  /* Implicit streams are created with TSID 0xFF */
329  ath6kl_wmi_create_pstream_cmd(wmi, if_idx, &cmd);
330  }
331 
332  *ac = traffic_class;
333 
334  return 0;
335 }
336 
337 int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb)
338 {
339  struct ieee80211_hdr_3addr *pwh, wh;
340  struct ath6kl_llc_snap_hdr *llc_hdr;
341  struct ethhdr eth_hdr;
342  u32 hdr_size;
343  u8 *datap;
345 
346  if (WARN_ON(skb == NULL))
347  return -EINVAL;
348 
349  datap = skb->data;
350  pwh = (struct ieee80211_hdr_3addr *) datap;
351 
353 
354  memcpy((u8 *) &wh, datap, sizeof(struct ieee80211_hdr_3addr));
355 
356  /* Strip off the 802.11 header */
357  if (sub_type == cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
358  hdr_size = roundup(sizeof(struct ieee80211_qos_hdr),
359  sizeof(u32));
360  skb_pull(skb, hdr_size);
361  } else if (sub_type == cpu_to_le16(IEEE80211_STYPE_DATA))
362  skb_pull(skb, sizeof(struct ieee80211_hdr_3addr));
363 
364  datap = skb->data;
365  llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap);
366 
367  memset(&eth_hdr, 0, sizeof(eth_hdr));
368  eth_hdr.h_proto = llc_hdr->eth_type;
369 
370  switch ((le16_to_cpu(wh.frame_control)) &
372  case 0:
373  memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN);
374  memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN);
375  break;
376  case IEEE80211_FCTL_TODS:
377  memcpy(eth_hdr.h_dest, wh.addr3, ETH_ALEN);
378  memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN);
379  break;
381  memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN);
382  memcpy(eth_hdr.h_source, wh.addr3, ETH_ALEN);
383  break;
385  break;
386  }
387 
388  skb_pull(skb, sizeof(struct ath6kl_llc_snap_hdr));
389  skb_push(skb, sizeof(eth_hdr));
390 
391  datap = skb->data;
392 
393  memcpy(datap, &eth_hdr, sizeof(eth_hdr));
394 
395  return 0;
396 }
397 
398 /*
399  * Performs 802.3 to DIX encapsulation for received packets.
400  * Assumes the entire 802.3 header is contigous.
401  */
403 {
404  struct ath6kl_llc_snap_hdr *llc_hdr;
405  struct ethhdr eth_hdr;
406  u8 *datap;
407 
408  if (WARN_ON(skb == NULL))
409  return -EINVAL;
410 
411  datap = skb->data;
412 
413  memcpy(&eth_hdr, datap, sizeof(eth_hdr));
414 
415  llc_hdr = (struct ath6kl_llc_snap_hdr *) (datap + sizeof(eth_hdr));
416  eth_hdr.h_proto = llc_hdr->eth_type;
417 
418  skb_pull(skb, sizeof(struct ath6kl_llc_snap_hdr));
419  datap = skb->data;
420 
421  memcpy(datap, &eth_hdr, sizeof(eth_hdr));
422 
423  return 0;
424 }
425 
426 static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len)
427 {
428  struct tx_complete_msg_v1 *msg_v1;
429  struct wmi_tx_complete_event *evt;
430  int index;
431  u16 size;
432 
433  evt = (struct wmi_tx_complete_event *) datap;
434 
435  ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n",
436  evt->num_msg, evt->msg_len, evt->msg_type);
437 
438  for (index = 0; index < evt->num_msg; index++) {
439  size = sizeof(struct wmi_tx_complete_event) +
440  (index * sizeof(struct tx_complete_msg_v1));
441  msg_v1 = (struct tx_complete_msg_v1 *)(datap + size);
442 
443  ath6kl_dbg(ATH6KL_DBG_WMI, "msg: %d %d %d %d\n",
444  msg_v1->status, msg_v1->pkt_id,
445  msg_v1->rate_idx, msg_v1->ack_failures);
446  }
447 
448  return 0;
449 }
450 
451 static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap,
452  int len, struct ath6kl_vif *vif)
453 {
454  struct wmi_remain_on_chnl_event *ev;
455  u32 freq;
456  u32 dur;
457  struct ieee80211_channel *chan;
458  struct ath6kl *ar = wmi->parent_dev;
459  u32 id;
460 
461  if (len < sizeof(*ev))
462  return -EINVAL;
463 
464  ev = (struct wmi_remain_on_chnl_event *) datap;
465  freq = le32_to_cpu(ev->freq);
466  dur = le32_to_cpu(ev->duration);
467  ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: freq=%u dur=%u\n",
468  freq, dur);
469  chan = ieee80211_get_channel(ar->wiphy, freq);
470  if (!chan) {
471  ath6kl_dbg(ATH6KL_DBG_WMI,
472  "remain_on_chnl: Unknown channel (freq=%u)\n",
473  freq);
474  return -EINVAL;
475  }
476  id = vif->last_roc_id;
478  dur, GFP_ATOMIC);
479 
480  return 0;
481 }
482 
483 static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi,
484  u8 *datap, int len,
485  struct ath6kl_vif *vif)
486 {
488  u32 freq;
489  u32 dur;
490  struct ieee80211_channel *chan;
491  struct ath6kl *ar = wmi->parent_dev;
492  u32 id;
493 
494  if (len < sizeof(*ev))
495  return -EINVAL;
496 
497  ev = (struct wmi_cancel_remain_on_chnl_event *) datap;
498  freq = le32_to_cpu(ev->freq);
499  dur = le32_to_cpu(ev->duration);
500  ath6kl_dbg(ATH6KL_DBG_WMI,
501  "cancel_remain_on_chnl: freq=%u dur=%u status=%u\n",
502  freq, dur, ev->status);
503  chan = ieee80211_get_channel(ar->wiphy, freq);
504  if (!chan) {
505  ath6kl_dbg(ATH6KL_DBG_WMI,
506  "cancel_remain_on_chnl: Unknown channel (freq=%u)\n",
507  freq);
508  return -EINVAL;
509  }
510  if (vif->last_cancel_roc_id &&
511  vif->last_cancel_roc_id + 1 == vif->last_roc_id)
512  id = vif->last_cancel_roc_id; /* event for cancel command */
513  else
514  id = vif->last_roc_id; /* timeout on uncanceled r-o-c */
515  vif->last_cancel_roc_id = 0;
518 
519  return 0;
520 }
521 
522 static int ath6kl_wmi_tx_status_event_rx(struct wmi *wmi, u8 *datap, int len,
523  struct ath6kl_vif *vif)
524 {
525  struct wmi_tx_status_event *ev;
526  u32 id;
527 
528  if (len < sizeof(*ev))
529  return -EINVAL;
530 
531  ev = (struct wmi_tx_status_event *) datap;
532  id = le32_to_cpu(ev->id);
533  ath6kl_dbg(ATH6KL_DBG_WMI, "tx_status: id=%x ack_status=%u\n",
534  id, ev->ack_status);
535  if (wmi->last_mgmt_tx_frame) {
536  cfg80211_mgmt_tx_status(&vif->wdev, id,
537  wmi->last_mgmt_tx_frame,
539  !!ev->ack_status, GFP_ATOMIC);
541  wmi->last_mgmt_tx_frame = NULL;
542  wmi->last_mgmt_tx_frame_len = 0;
543  }
544 
545  return 0;
546 }
547 
548 static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len,
549  struct ath6kl_vif *vif)
550 {
551  struct wmi_p2p_rx_probe_req_event *ev;
552  u32 freq;
553  u16 dlen;
554 
555  if (len < sizeof(*ev))
556  return -EINVAL;
557 
558  ev = (struct wmi_p2p_rx_probe_req_event *) datap;
559  freq = le32_to_cpu(ev->freq);
560  dlen = le16_to_cpu(ev->len);
561  if (datap + len < ev->data + dlen) {
562  ath6kl_err("invalid wmi_p2p_rx_probe_req_event: len=%d dlen=%u\n",
563  len, dlen);
564  return -EINVAL;
565  }
566  ath6kl_dbg(ATH6KL_DBG_WMI,
567  "rx_probe_req: len=%u freq=%u probe_req_report=%d\n",
568  dlen, freq, vif->probe_req_report);
569 
570  if (vif->probe_req_report || vif->nw_type == AP_NETWORK)
571  cfg80211_rx_mgmt(&vif->wdev, freq, 0,
572  ev->data, dlen, GFP_ATOMIC);
573 
574  return 0;
575 }
576 
577 static int ath6kl_wmi_p2p_capabilities_event_rx(u8 *datap, int len)
578 {
579  struct wmi_p2p_capabilities_event *ev;
580  u16 dlen;
581 
582  if (len < sizeof(*ev))
583  return -EINVAL;
584 
585  ev = (struct wmi_p2p_capabilities_event *) datap;
586  dlen = le16_to_cpu(ev->len);
587  ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_capab: len=%u\n", dlen);
588 
589  return 0;
590 }
591 
592 static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len,
593  struct ath6kl_vif *vif)
594 {
595  struct wmi_rx_action_event *ev;
596  u32 freq;
597  u16 dlen;
598 
599  if (len < sizeof(*ev))
600  return -EINVAL;
601 
602  ev = (struct wmi_rx_action_event *) datap;
603  freq = le32_to_cpu(ev->freq);
604  dlen = le16_to_cpu(ev->len);
605  if (datap + len < ev->data + dlen) {
606  ath6kl_err("invalid wmi_rx_action_event: len=%d dlen=%u\n",
607  len, dlen);
608  return -EINVAL;
609  }
610  ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq);
611  cfg80211_rx_mgmt(&vif->wdev, freq, 0,
612  ev->data, dlen, GFP_ATOMIC);
613 
614  return 0;
615 }
616 
617 static int ath6kl_wmi_p2p_info_event_rx(u8 *datap, int len)
618 {
619  struct wmi_p2p_info_event *ev;
620  u32 flags;
621  u16 dlen;
622 
623  if (len < sizeof(*ev))
624  return -EINVAL;
625 
626  ev = (struct wmi_p2p_info_event *) datap;
627  flags = le32_to_cpu(ev->info_req_flags);
628  dlen = le16_to_cpu(ev->len);
629  ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: flags=%x len=%d\n", flags, dlen);
630 
631  if (flags & P2P_FLAG_CAPABILITIES_REQ) {
632  struct wmi_p2p_capabilities *cap;
633  if (dlen < sizeof(*cap))
634  return -EINVAL;
635  cap = (struct wmi_p2p_capabilities *) ev->data;
636  ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: GO Power Save = %d\n",
637  cap->go_power_save);
638  }
639 
640  if (flags & P2P_FLAG_MACADDR_REQ) {
641  struct wmi_p2p_macaddr *mac;
642  if (dlen < sizeof(*mac))
643  return -EINVAL;
644  mac = (struct wmi_p2p_macaddr *) ev->data;
645  ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: MAC Address = %pM\n",
646  mac->mac_addr);
647  }
648 
649  if (flags & P2P_FLAG_HMODEL_REQ) {
650  struct wmi_p2p_hmodel *mod;
651  if (dlen < sizeof(*mod))
652  return -EINVAL;
653  mod = (struct wmi_p2p_hmodel *) ev->data;
654  ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: P2P Model = %d (%s)\n",
655  mod->p2p_model,
656  mod->p2p_model ? "host" : "firmware");
657  }
658  return 0;
659 }
660 
661 static inline struct sk_buff *ath6kl_wmi_get_new_buf(u32 size)
662 {
663  struct sk_buff *skb;
664 
665  skb = ath6kl_buf_alloc(size);
666  if (!skb)
667  return NULL;
668 
669  skb_put(skb, size);
670  if (size)
671  memset(skb->data, 0, size);
672 
673  return skb;
674 }
675 
676 /* Send a "simple" wmi command -- one with no arguments */
677 static int ath6kl_wmi_simple_cmd(struct wmi *wmi, u8 if_idx,
678  enum wmi_cmd_id cmd_id)
679 {
680  struct sk_buff *skb;
681  int ret;
682 
683  skb = ath6kl_wmi_get_new_buf(0);
684  if (!skb)
685  return -ENOMEM;
686 
687  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, cmd_id, NO_SYNC_WMIFLAG);
688 
689  return ret;
690 }
691 
692 static int ath6kl_wmi_ready_event_rx(struct wmi *wmi, u8 *datap, int len)
693 {
694  struct wmi_ready_event_2 *ev = (struct wmi_ready_event_2 *) datap;
695 
696  if (len < sizeof(struct wmi_ready_event_2))
697  return -EINVAL;
698 
700  le32_to_cpu(ev->sw_version),
701  le32_to_cpu(ev->abi_version), ev->phy_cap);
702 
703  return 0;
704 }
705 
706 /*
707  * Mechanism to modify the roaming behavior in the firmware. The lower rssi
708  * at which the station has to roam can be passed with
709  * WMI_SET_LRSSI_SCAN_PARAMS. Subtract 96 from RSSI to get the signal level
710  * in dBm.
711  */
712 int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi)
713 {
714  struct sk_buff *skb;
715  struct roam_ctrl_cmd *cmd;
716 
717  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
718  if (!skb)
719  return -ENOMEM;
720 
721  cmd = (struct roam_ctrl_cmd *) skb->data;
722 
723  cmd->info.params.lrssi_scan_period = cpu_to_le16(DEF_LRSSI_SCAN_PERIOD);
724  cmd->info.params.lrssi_scan_threshold = a_cpu_to_sle16(lrssi +
726  cmd->info.params.lrssi_roam_threshold = a_cpu_to_sle16(lrssi);
727  cmd->info.params.roam_rssi_floor = DEF_LRSSI_ROAM_FLOOR;
729 
732 
733  return 0;
734 }
735 
736 int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)
737 {
738  struct sk_buff *skb;
739  struct roam_ctrl_cmd *cmd;
740 
741  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
742  if (!skb)
743  return -ENOMEM;
744 
745  cmd = (struct roam_ctrl_cmd *) skb->data;
746 
747  memcpy(cmd->info.bssid, bssid, ETH_ALEN);
748  cmd->roam_ctrl = WMI_FORCE_ROAM;
749 
750  ath6kl_dbg(ATH6KL_DBG_WMI, "force roam to %pM\n", bssid);
751  return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_ROAM_CTRL_CMDID,
753 }
754 
755 int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period)
756 {
757  struct sk_buff *skb;
758  struct set_dtim_cmd *cmd;
759 
760  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
761  if (!skb)
762  return -ENOMEM;
763 
764  cmd = (struct set_dtim_cmd *) skb->data;
765 
766  cmd->dtim_period = cpu_to_le32(dtim_period);
767  return ath6kl_wmi_cmd_send(wmi, if_idx, skb,
769 }
770 
772 {
773  struct sk_buff *skb;
774  struct roam_ctrl_cmd *cmd;
775 
776  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
777  if (!skb)
778  return -ENOMEM;
779 
780  cmd = (struct roam_ctrl_cmd *) skb->data;
781 
782  cmd->info.roam_mode = mode;
784 
785  ath6kl_dbg(ATH6KL_DBG_WMI, "set roam mode %d\n", mode);
786  return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_ROAM_CTRL_CMDID,
788 }
789 
790 static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len,
791  struct ath6kl_vif *vif)
792 {
793  struct wmi_connect_event *ev;
794  u8 *pie, *peie;
795 
796  if (len < sizeof(struct wmi_connect_event))
797  return -EINVAL;
798 
799  ev = (struct wmi_connect_event *) datap;
800 
801  if (vif->nw_type == AP_NETWORK) {
802  /* AP mode start/STA connected event */
803  struct net_device *dev = vif->ndev;
804  if (memcmp(dev->dev_addr, ev->u.ap_bss.bssid, ETH_ALEN) == 0) {
805  ath6kl_dbg(ATH6KL_DBG_WMI,
806  "%s: freq %d bssid %pM (AP started)\n",
807  __func__, le16_to_cpu(ev->u.ap_bss.ch),
808  ev->u.ap_bss.bssid);
810  vif, le16_to_cpu(ev->u.ap_bss.ch));
811  } else {
812  ath6kl_dbg(ATH6KL_DBG_WMI,
813  "%s: aid %u mac_addr %pM auth=%u keymgmt=%u cipher=%u apsd_info=%u (STA connected)\n",
814  __func__, ev->u.ap_sta.aid,
815  ev->u.ap_sta.mac_addr,
816  ev->u.ap_sta.auth,
817  ev->u.ap_sta.keymgmt,
818  le16_to_cpu(ev->u.ap_sta.cipher),
819  ev->u.ap_sta.apsd_info);
820 
822  vif, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr,
823  ev->u.ap_sta.keymgmt,
824  le16_to_cpu(ev->u.ap_sta.cipher),
825  ev->u.ap_sta.auth, ev->assoc_req_len,
826  ev->assoc_info + ev->beacon_ie_len,
827  ev->u.ap_sta.apsd_info);
828  }
829  return 0;
830  }
831 
832  /* STA/IBSS mode connection event */
833 
834  ath6kl_dbg(ATH6KL_DBG_WMI,
835  "wmi event connect freq %d bssid %pM listen_intvl %d beacon_intvl %d type %d\n",
836  le16_to_cpu(ev->u.sta.ch), ev->u.sta.bssid,
837  le16_to_cpu(ev->u.sta.listen_intvl),
838  le16_to_cpu(ev->u.sta.beacon_intvl),
839  le32_to_cpu(ev->u.sta.nw_type));
840 
841  /* Start of assoc rsp IEs */
842  pie = ev->assoc_info + ev->beacon_ie_len +
843  ev->assoc_req_len + (sizeof(u16) * 3); /* capinfo, status, aid */
844 
845  /* End of assoc rsp IEs */
846  peie = ev->assoc_info + ev->beacon_ie_len + ev->assoc_req_len +
847  ev->assoc_resp_len;
848 
849  while (pie < peie) {
850  switch (*pie) {
852  if (pie[1] > 3 && pie[2] == 0x00 && pie[3] == 0x50 &&
853  pie[4] == 0xf2 && pie[5] == WMM_OUI_TYPE) {
854  /* WMM OUT (00:50:F2) */
855  if (pie[1] > 5 &&
856  pie[6] == WMM_PARAM_OUI_SUBTYPE)
857  wmi->is_wmm_enabled = true;
858  }
859  break;
860  }
861 
862  if (wmi->is_wmm_enabled)
863  break;
864 
865  pie += pie[1] + 2;
866  }
867 
868  ath6kl_connect_event(vif, le16_to_cpu(ev->u.sta.ch),
869  ev->u.sta.bssid,
870  le16_to_cpu(ev->u.sta.listen_intvl),
871  le16_to_cpu(ev->u.sta.beacon_intvl),
872  le32_to_cpu(ev->u.sta.nw_type),
873  ev->beacon_ie_len, ev->assoc_req_len,
874  ev->assoc_resp_len, ev->assoc_info);
875 
876  return 0;
877 }
878 
879 static struct country_code_to_enum_rd *
880 ath6kl_regd_find_country(u16 countryCode)
881 {
882  int i;
883 
884  for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
885  if (allCountries[i].countryCode == countryCode)
886  return &allCountries[i];
887  }
888 
889  return NULL;
890 }
891 
892 static struct reg_dmn_pair_mapping *
893 ath6kl_get_regpair(u16 regdmn)
894 {
895  int i;
896 
897  if (regdmn == NO_ENUMRD)
898  return NULL;
899 
900  for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) {
901  if (regDomainPairs[i].regDmnEnum == regdmn)
902  return &regDomainPairs[i];
903  }
904 
905  return NULL;
906 }
907 
908 static struct country_code_to_enum_rd *
909 ath6kl_regd_find_country_by_rd(u16 regdmn)
910 {
911  int i;
912 
913  for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
914  if (allCountries[i].regDmnEnum == regdmn)
915  return &allCountries[i];
916  }
917 
918  return NULL;
919 }
920 
921 static void ath6kl_wmi_regdomain_event(struct wmi *wmi, u8 *datap, int len)
922 {
923 
924  struct ath6kl_wmi_regdomain *ev;
927  char alpha2[2];
928  u32 reg_code;
929 
930  ev = (struct ath6kl_wmi_regdomain *) datap;
931  reg_code = le32_to_cpu(ev->reg_code);
932 
933  if ((reg_code >> ATH6KL_COUNTRY_RD_SHIFT) & COUNTRY_ERD_FLAG)
934  country = ath6kl_regd_find_country((u16) reg_code);
935  else if (!(((u16) reg_code & WORLD_SKU_MASK) == WORLD_SKU_PREFIX)) {
936 
937  regpair = ath6kl_get_regpair((u16) reg_code);
938  country = ath6kl_regd_find_country_by_rd((u16) reg_code);
939  ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n",
940  regpair->regDmnEnum);
941  }
942 
943  if (country && wmi->parent_dev->wiphy_registered) {
944  alpha2[0] = country->isoName[0];
945  alpha2[1] = country->isoName[1];
946 
947  regulatory_hint(wmi->parent_dev->wiphy, alpha2);
948 
949  ath6kl_dbg(ATH6KL_DBG_WMI, "Country alpha2 being used: %c%c\n",
950  alpha2[0], alpha2[1]);
951  }
952 }
953 
954 static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len,
955  struct ath6kl_vif *vif)
956 {
957  struct wmi_disconnect_event *ev;
958  wmi->traffic_class = 100;
959 
960  if (len < sizeof(struct wmi_disconnect_event))
961  return -EINVAL;
962 
963  ev = (struct wmi_disconnect_event *) datap;
964 
965  ath6kl_dbg(ATH6KL_DBG_WMI,
966  "wmi event disconnect proto_reason %d bssid %pM wmi_reason %d assoc_resp_len %d\n",
968  ev->disconn_reason, ev->assoc_resp_len);
969 
970  wmi->is_wmm_enabled = false;
971 
973  ev->bssid, ev->assoc_resp_len, ev->assoc_info,
975 
976  return 0;
977 }
978 
979 static int ath6kl_wmi_peer_node_event_rx(struct wmi *wmi, u8 *datap, int len)
980 {
981  struct wmi_peer_node_event *ev;
982 
983  if (len < sizeof(struct wmi_peer_node_event))
984  return -EINVAL;
985 
986  ev = (struct wmi_peer_node_event *) datap;
987 
988  if (ev->event_code == PEER_NODE_JOIN_EVENT)
989  ath6kl_dbg(ATH6KL_DBG_WMI, "joined node with mac addr: %pM\n",
990  ev->peer_mac_addr);
991  else if (ev->event_code == PEER_NODE_LEAVE_EVENT)
992  ath6kl_dbg(ATH6KL_DBG_WMI, "left node with mac addr: %pM\n",
993  ev->peer_mac_addr);
994 
995  return 0;
996 }
997 
998 static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len,
999  struct ath6kl_vif *vif)
1000 {
1001  struct wmi_tkip_micerr_event *ev;
1002 
1003  if (len < sizeof(struct wmi_tkip_micerr_event))
1004  return -EINVAL;
1005 
1006  ev = (struct wmi_tkip_micerr_event *) datap;
1007 
1008  ath6kl_tkip_micerr_event(vif, ev->key_id, ev->is_mcast);
1009 
1010  return 0;
1011 }
1012 
1013 void ath6kl_wmi_sscan_timer(unsigned long ptr)
1014 {
1015  struct ath6kl_vif *vif = (struct ath6kl_vif *) ptr;
1016 
1017  cfg80211_sched_scan_results(vif->ar->wiphy);
1018 }
1019 
1020 static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
1021  struct ath6kl_vif *vif)
1022 {
1023  struct wmi_bss_info_hdr2 *bih;
1024  u8 *buf;
1025  struct ieee80211_channel *channel;
1026  struct ath6kl *ar = wmi->parent_dev;
1027  struct ieee80211_mgmt *mgmt;
1028  struct cfg80211_bss *bss;
1029 
1030  if (len <= sizeof(struct wmi_bss_info_hdr2))
1031  return -EINVAL;
1032 
1033  bih = (struct wmi_bss_info_hdr2 *) datap;
1034  buf = datap + sizeof(struct wmi_bss_info_hdr2);
1035  len -= sizeof(struct wmi_bss_info_hdr2);
1036 
1037  ath6kl_dbg(ATH6KL_DBG_WMI,
1038  "bss info evt - ch %u, snr %d, rssi %d, bssid \"%pM\" "
1039  "frame_type=%d\n",
1040  bih->ch, bih->snr, bih->snr - 95, bih->bssid,
1041  bih->frame_type);
1042 
1043  if (bih->frame_type != BEACON_FTYPE &&
1044  bih->frame_type != PROBERESP_FTYPE)
1045  return 0; /* Only update BSS table for now */
1046 
1047  if (bih->frame_type == BEACON_FTYPE &&
1051  NONE_BSS_FILTER, 0);
1052  }
1053 
1054  channel = ieee80211_get_channel(ar->wiphy, le16_to_cpu(bih->ch));
1055  if (channel == NULL)
1056  return -EINVAL;
1057 
1058  if (len < 8 + 2 + 2)
1059  return -EINVAL;
1060 
1061  if (bih->frame_type == BEACON_FTYPE &&
1062  test_bit(CONNECTED, &vif->flags) &&
1063  memcmp(bih->bssid, vif->bssid, ETH_ALEN) == 0) {
1064  const u8 *tim;
1065  tim = cfg80211_find_ie(WLAN_EID_TIM, buf + 8 + 2 + 2,
1066  len - 8 - 2 - 2);
1067  if (tim && tim[1] >= 2) {
1068  vif->assoc_bss_dtim_period = tim[3];
1070  }
1071  }
1072 
1073  /*
1074  * In theory, use of cfg80211_inform_bss() would be more natural here
1075  * since we do not have the full frame. However, at least for now,
1076  * cfg80211 can only distinguish Beacon and Probe Response frames from
1077  * each other when using cfg80211_inform_bss_frame(), so let's build a
1078  * fake IEEE 802.11 header to be able to take benefit of this.
1079  */
1080  mgmt = kmalloc(24 + len, GFP_ATOMIC);
1081  if (mgmt == NULL)
1082  return -EINVAL;
1083 
1084  if (bih->frame_type == BEACON_FTYPE) {
1087  memset(mgmt->da, 0xff, ETH_ALEN);
1088  } else {
1089  struct net_device *dev = vif->ndev;
1090 
1093  memcpy(mgmt->da, dev->dev_addr, ETH_ALEN);
1094  }
1095  mgmt->duration = cpu_to_le16(0);
1096  memcpy(mgmt->sa, bih->bssid, ETH_ALEN);
1097  memcpy(mgmt->bssid, bih->bssid, ETH_ALEN);
1098  mgmt->seq_ctrl = cpu_to_le16(0);
1099 
1100  memcpy(&mgmt->u.beacon, buf, len);
1101 
1102  bss = cfg80211_inform_bss_frame(ar->wiphy, channel, mgmt,
1103  24 + len, (bih->snr - 95) * 100,
1104  GFP_ATOMIC);
1105  kfree(mgmt);
1106  if (bss == NULL)
1107  return -ENOMEM;
1108  cfg80211_put_bss(bss);
1109 
1110  /*
1111  * Firmware doesn't return any event when scheduled scan has
1112  * finished, so we need to use a timer to find out when there are
1113  * no more results.
1114  *
1115  * The timer is started from the first bss info received, otherwise
1116  * the timer would not ever fire if the scan interval is short
1117  * enough.
1118  */
1119  if (ar->state == ATH6KL_STATE_SCHED_SCAN &&
1120  !timer_pending(&vif->sched_scan_timer)) {
1121  mod_timer(&vif->sched_scan_timer, jiffies +
1123  }
1124 
1125  return 0;
1126 }
1127 
1128 /* Inactivity timeout of a fatpipe(pstream) at the target */
1129 static int ath6kl_wmi_pstream_timeout_event_rx(struct wmi *wmi, u8 *datap,
1130  int len)
1131 {
1132  struct wmi_pstream_timeout_event *ev;
1133 
1134  if (len < sizeof(struct wmi_pstream_timeout_event))
1135  return -EINVAL;
1136 
1137  ev = (struct wmi_pstream_timeout_event *) datap;
1138 
1139  /*
1140  * When the pstream (fat pipe == AC) timesout, it means there were
1141  * no thinStreams within this pstream & it got implicitly created
1142  * due to data flow on this AC. We start the inactivity timer only
1143  * for implicitly created pstream. Just reset the host state.
1144  */
1145  spin_lock_bh(&wmi->lock);
1146  wmi->stream_exist_for_ac[ev->traffic_class] = 0;
1147  wmi->fat_pipe_exist &= ~(1 << ev->traffic_class);
1148  spin_unlock_bh(&wmi->lock);
1149 
1150  /* Indicate inactivity to driver layer for this fatpipe (pstream) */
1152 
1153  return 0;
1154 }
1155 
1156 static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len)
1157 {
1158  struct wmi_bit_rate_reply *reply;
1159  s32 rate;
1160  u32 sgi, index;
1161 
1162  if (len < sizeof(struct wmi_bit_rate_reply))
1163  return -EINVAL;
1164 
1165  reply = (struct wmi_bit_rate_reply *) datap;
1166 
1167  ath6kl_dbg(ATH6KL_DBG_WMI, "rateindex %d\n", reply->rate_index);
1168 
1169  if (reply->rate_index == (s8) RATE_AUTO) {
1170  rate = RATE_AUTO;
1171  } else {
1172  index = reply->rate_index & 0x7f;
1173  sgi = (reply->rate_index & 0x80) ? 1 : 0;
1174  rate = wmi_rate_tbl[index][sgi];
1175  }
1176 
1178 
1179  return 0;
1180 }
1181 
1182 static int ath6kl_wmi_test_rx(struct wmi *wmi, u8 *datap, int len)
1183 {
1184  ath6kl_tm_rx_event(wmi->parent_dev, datap, len);
1185 
1186  return 0;
1187 }
1188 
1189 static int ath6kl_wmi_ratemask_reply_rx(struct wmi *wmi, u8 *datap, int len)
1190 {
1191  if (len < sizeof(struct wmi_fix_rates_reply))
1192  return -EINVAL;
1193 
1195 
1196  return 0;
1197 }
1198 
1199 static int ath6kl_wmi_ch_list_reply_rx(struct wmi *wmi, u8 *datap, int len)
1200 {
1201  if (len < sizeof(struct wmi_channel_list_reply))
1202  return -EINVAL;
1203 
1205 
1206  return 0;
1207 }
1208 
1209 static int ath6kl_wmi_tx_pwr_reply_rx(struct wmi *wmi, u8 *datap, int len)
1210 {
1211  struct wmi_tx_pwr_reply *reply;
1212 
1213  if (len < sizeof(struct wmi_tx_pwr_reply))
1214  return -EINVAL;
1215 
1216  reply = (struct wmi_tx_pwr_reply *) datap;
1217  ath6kl_txpwr_rx_evt(wmi->parent_dev, reply->dbM);
1218 
1219  return 0;
1220 }
1221 
1222 static int ath6kl_wmi_keepalive_reply_rx(struct wmi *wmi, u8 *datap, int len)
1223 {
1224  if (len < sizeof(struct wmi_get_keepalive_cmd))
1225  return -EINVAL;
1226 
1228 
1229  return 0;
1230 }
1231 
1232 static int ath6kl_wmi_scan_complete_rx(struct wmi *wmi, u8 *datap, int len,
1233  struct ath6kl_vif *vif)
1234 {
1235  struct wmi_scan_complete_event *ev;
1236 
1237  ev = (struct wmi_scan_complete_event *) datap;
1238 
1239  ath6kl_scan_complete_evt(vif, a_sle32_to_cpu(ev->status));
1240  wmi->is_probe_ssid = false;
1241 
1242  return 0;
1243 }
1244 
1245 static int ath6kl_wmi_neighbor_report_event_rx(struct wmi *wmi, u8 *datap,
1246  int len, struct ath6kl_vif *vif)
1247 {
1248  struct wmi_neighbor_report_event *ev;
1249  u8 i;
1250 
1251  if (len < sizeof(*ev))
1252  return -EINVAL;
1253  ev = (struct wmi_neighbor_report_event *) datap;
1254  if (sizeof(*ev) + ev->num_neighbors * sizeof(struct wmi_neighbor_info)
1255  > len) {
1256  ath6kl_dbg(ATH6KL_DBG_WMI,
1257  "truncated neighbor event (num=%d len=%d)\n",
1258  ev->num_neighbors, len);
1259  return -EINVAL;
1260  }
1261  for (i = 0; i < ev->num_neighbors; i++) {
1262  ath6kl_dbg(ATH6KL_DBG_WMI, "neighbor %d/%d - %pM 0x%x\n",
1263  i + 1, ev->num_neighbors, ev->neighbor[i].bssid,
1264  ev->neighbor[i].bss_flags);
1266  ev->neighbor[i].bssid,
1267  !!(ev->neighbor[i].bss_flags &
1269  GFP_ATOMIC);
1270  }
1271 
1272  return 0;
1273 }
1274 
1275 /*
1276  * Target is reporting a programming error. This is for
1277  * developer aid only. Target only checks a few common violations
1278  * and it is responsibility of host to do all error checking.
1279  * Behavior of target after wmi error event is undefined.
1280  * A reset is recommended.
1281  */
1282 static int ath6kl_wmi_error_event_rx(struct wmi *wmi, u8 *datap, int len)
1283 {
1284  const char *type = "unknown error";
1285  struct wmi_cmd_error_event *ev;
1286  ev = (struct wmi_cmd_error_event *) datap;
1287 
1288  switch (ev->err_code) {
1289  case INVALID_PARAM:
1290  type = "invalid parameter";
1291  break;
1292  case ILLEGAL_STATE:
1293  type = "invalid state";
1294  break;
1295  case INTERNAL_ERROR:
1296  type = "internal error";
1297  break;
1298  }
1299 
1300  ath6kl_dbg(ATH6KL_DBG_WMI, "programming error, cmd=%d %s\n",
1301  ev->cmd_id, type);
1302 
1303  return 0;
1304 }
1305 
1306 static int ath6kl_wmi_stats_event_rx(struct wmi *wmi, u8 *datap, int len,
1307  struct ath6kl_vif *vif)
1308 {
1309  ath6kl_tgt_stats_event(vif, datap, len);
1310 
1311  return 0;
1312 }
1313 
1314 static u8 ath6kl_wmi_get_upper_threshold(s16 rssi,
1315  struct sq_threshold_params *sq_thresh,
1316  u32 size)
1317 {
1318  u32 index;
1319  u8 threshold = (u8) sq_thresh->upper_threshold[size - 1];
1320 
1321  /* The list is already in sorted order. Get the next lower value */
1322  for (index = 0; index < size; index++) {
1323  if (rssi < sq_thresh->upper_threshold[index]) {
1324  threshold = (u8) sq_thresh->upper_threshold[index];
1325  break;
1326  }
1327  }
1328 
1329  return threshold;
1330 }
1331 
1332 static u8 ath6kl_wmi_get_lower_threshold(s16 rssi,
1333  struct sq_threshold_params *sq_thresh,
1334  u32 size)
1335 {
1336  u32 index;
1337  u8 threshold = (u8) sq_thresh->lower_threshold[size - 1];
1338 
1339  /* The list is already in sorted order. Get the next lower value */
1340  for (index = 0; index < size; index++) {
1341  if (rssi > sq_thresh->lower_threshold[index]) {
1342  threshold = (u8) sq_thresh->lower_threshold[index];
1343  break;
1344  }
1345  }
1346 
1347  return threshold;
1348 }
1349 
1350 static int ath6kl_wmi_send_rssi_threshold_params(struct wmi *wmi,
1351  struct wmi_rssi_threshold_params_cmd *rssi_cmd)
1352 {
1353  struct sk_buff *skb;
1355 
1356  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1357  if (!skb)
1358  return -ENOMEM;
1359 
1360  cmd = (struct wmi_rssi_threshold_params_cmd *) skb->data;
1361  memcpy(cmd, rssi_cmd, sizeof(struct wmi_rssi_threshold_params_cmd));
1362 
1364  NO_SYNC_WMIFLAG);
1365 }
1366 
1367 static int ath6kl_wmi_rssi_threshold_event_rx(struct wmi *wmi, u8 *datap,
1368  int len)
1369 {
1370  struct wmi_rssi_threshold_event *reply;
1371  struct wmi_rssi_threshold_params_cmd cmd;
1372  struct sq_threshold_params *sq_thresh;
1373  enum wmi_rssi_threshold_val new_threshold;
1374  u8 upper_rssi_threshold, lower_rssi_threshold;
1375  s16 rssi;
1376  int ret;
1377 
1378  if (len < sizeof(struct wmi_rssi_threshold_event))
1379  return -EINVAL;
1380 
1381  reply = (struct wmi_rssi_threshold_event *) datap;
1382  new_threshold = (enum wmi_rssi_threshold_val) reply->range;
1383  rssi = a_sle16_to_cpu(reply->rssi);
1384 
1385  sq_thresh = &wmi->sq_threshld[SIGNAL_QUALITY_METRICS_RSSI];
1386 
1387  /*
1388  * Identify the threshold breached and communicate that to the app.
1389  * After that install a new set of thresholds based on the signal
1390  * quality reported by the target
1391  */
1392  if (new_threshold) {
1393  /* Upper threshold breached */
1394  if (rssi < sq_thresh->upper_threshold[0]) {
1395  ath6kl_dbg(ATH6KL_DBG_WMI,
1396  "spurious upper rssi threshold event: %d\n",
1397  rssi);
1398  } else if ((rssi < sq_thresh->upper_threshold[1]) &&
1399  (rssi >= sq_thresh->upper_threshold[0])) {
1400  new_threshold = WMI_RSSI_THRESHOLD1_ABOVE;
1401  } else if ((rssi < sq_thresh->upper_threshold[2]) &&
1402  (rssi >= sq_thresh->upper_threshold[1])) {
1403  new_threshold = WMI_RSSI_THRESHOLD2_ABOVE;
1404  } else if ((rssi < sq_thresh->upper_threshold[3]) &&
1405  (rssi >= sq_thresh->upper_threshold[2])) {
1406  new_threshold = WMI_RSSI_THRESHOLD3_ABOVE;
1407  } else if ((rssi < sq_thresh->upper_threshold[4]) &&
1408  (rssi >= sq_thresh->upper_threshold[3])) {
1409  new_threshold = WMI_RSSI_THRESHOLD4_ABOVE;
1410  } else if ((rssi < sq_thresh->upper_threshold[5]) &&
1411  (rssi >= sq_thresh->upper_threshold[4])) {
1412  new_threshold = WMI_RSSI_THRESHOLD5_ABOVE;
1413  } else if (rssi >= sq_thresh->upper_threshold[5]) {
1414  new_threshold = WMI_RSSI_THRESHOLD6_ABOVE;
1415  }
1416  } else {
1417  /* Lower threshold breached */
1418  if (rssi > sq_thresh->lower_threshold[0]) {
1419  ath6kl_dbg(ATH6KL_DBG_WMI,
1420  "spurious lower rssi threshold event: %d %d\n",
1421  rssi, sq_thresh->lower_threshold[0]);
1422  } else if ((rssi > sq_thresh->lower_threshold[1]) &&
1423  (rssi <= sq_thresh->lower_threshold[0])) {
1424  new_threshold = WMI_RSSI_THRESHOLD6_BELOW;
1425  } else if ((rssi > sq_thresh->lower_threshold[2]) &&
1426  (rssi <= sq_thresh->lower_threshold[1])) {
1427  new_threshold = WMI_RSSI_THRESHOLD5_BELOW;
1428  } else if ((rssi > sq_thresh->lower_threshold[3]) &&
1429  (rssi <= sq_thresh->lower_threshold[2])) {
1430  new_threshold = WMI_RSSI_THRESHOLD4_BELOW;
1431  } else if ((rssi > sq_thresh->lower_threshold[4]) &&
1432  (rssi <= sq_thresh->lower_threshold[3])) {
1433  new_threshold = WMI_RSSI_THRESHOLD3_BELOW;
1434  } else if ((rssi > sq_thresh->lower_threshold[5]) &&
1435  (rssi <= sq_thresh->lower_threshold[4])) {
1436  new_threshold = WMI_RSSI_THRESHOLD2_BELOW;
1437  } else if (rssi <= sq_thresh->lower_threshold[5]) {
1438  new_threshold = WMI_RSSI_THRESHOLD1_BELOW;
1439  }
1440  }
1441 
1442  /* Calculate and install the next set of thresholds */
1443  lower_rssi_threshold = ath6kl_wmi_get_lower_threshold(rssi, sq_thresh,
1444  sq_thresh->lower_threshold_valid_count);
1445  upper_rssi_threshold = ath6kl_wmi_get_upper_threshold(rssi, sq_thresh,
1446  sq_thresh->upper_threshold_valid_count);
1447 
1448  /* Issue a wmi command to install the thresholds */
1449  cmd.thresh_above1_val = a_cpu_to_sle16(upper_rssi_threshold);
1450  cmd.thresh_below1_val = a_cpu_to_sle16(lower_rssi_threshold);
1451  cmd.weight = sq_thresh->weight;
1452  cmd.poll_time = cpu_to_le32(sq_thresh->polling_interval);
1453 
1454  ret = ath6kl_wmi_send_rssi_threshold_params(wmi, &cmd);
1455  if (ret) {
1456  ath6kl_err("unable to configure rssi thresholds\n");
1457  return -EIO;
1458  }
1459 
1460  return 0;
1461 }
1462 
1463 static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len,
1464  struct ath6kl_vif *vif)
1465 {
1466  struct wmi_cac_event *reply;
1467  struct ieee80211_tspec_ie *ts;
1468  u16 active_tsids, tsinfo;
1469  u8 tsid, index;
1470  u8 ts_id;
1471 
1472  if (len < sizeof(struct wmi_cac_event))
1473  return -EINVAL;
1474 
1475  reply = (struct wmi_cac_event *) datap;
1476 
1479 
1480  ts = (struct ieee80211_tspec_ie *) &(reply->tspec_suggestion);
1481  tsinfo = le16_to_cpu(ts->tsinfo);
1482  tsid = (tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) &
1484 
1486  reply->ac, tsid);
1487  } else if (reply->cac_indication == CAC_INDICATION_NO_RESP) {
1488  /*
1489  * Following assumes that there is only one outstanding
1490  * ADDTS request when this event is received
1491  */
1492  spin_lock_bh(&wmi->lock);
1493  active_tsids = wmi->stream_exist_for_ac[reply->ac];
1494  spin_unlock_bh(&wmi->lock);
1495 
1496  for (index = 0; index < sizeof(active_tsids) * 8; index++) {
1497  if ((active_tsids >> index) & 1)
1498  break;
1499  }
1500  if (index < (sizeof(active_tsids) * 8))
1502  reply->ac, index);
1503  }
1504 
1505  /*
1506  * Clear active tsids and Add missing handling
1507  * for delete qos stream from AP
1508  */
1509  else if (reply->cac_indication == CAC_INDICATION_DELETE) {
1510 
1511  ts = (struct ieee80211_tspec_ie *) &(reply->tspec_suggestion);
1512  tsinfo = le16_to_cpu(ts->tsinfo);
1513  ts_id = ((tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) &
1515 
1516  spin_lock_bh(&wmi->lock);
1517  wmi->stream_exist_for_ac[reply->ac] &= ~(1 << ts_id);
1518  active_tsids = wmi->stream_exist_for_ac[reply->ac];
1519  spin_unlock_bh(&wmi->lock);
1520 
1521  /* Indicate stream inactivity to driver layer only if all tsids
1522  * within this AC are deleted.
1523  */
1524  if (!active_tsids) {
1526  false);
1527  wmi->fat_pipe_exist &= ~(1 << reply->ac);
1528  }
1529  }
1530 
1531  return 0;
1532 }
1533 
1534 static int ath6kl_wmi_send_snr_threshold_params(struct wmi *wmi,
1535  struct wmi_snr_threshold_params_cmd *snr_cmd)
1536 {
1537  struct sk_buff *skb;
1539 
1540  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1541  if (!skb)
1542  return -ENOMEM;
1543 
1544  cmd = (struct wmi_snr_threshold_params_cmd *) skb->data;
1545  memcpy(cmd, snr_cmd, sizeof(struct wmi_snr_threshold_params_cmd));
1546 
1548  NO_SYNC_WMIFLAG);
1549 }
1550 
1551 static int ath6kl_wmi_snr_threshold_event_rx(struct wmi *wmi, u8 *datap,
1552  int len)
1553 {
1554  struct wmi_snr_threshold_event *reply;
1555  struct sq_threshold_params *sq_thresh;
1556  struct wmi_snr_threshold_params_cmd cmd;
1557  enum wmi_snr_threshold_val new_threshold;
1558  u8 upper_snr_threshold, lower_snr_threshold;
1559  s16 snr;
1560  int ret;
1561 
1562  if (len < sizeof(struct wmi_snr_threshold_event))
1563  return -EINVAL;
1564 
1565  reply = (struct wmi_snr_threshold_event *) datap;
1566 
1567  new_threshold = (enum wmi_snr_threshold_val) reply->range;
1568  snr = reply->snr;
1569 
1570  sq_thresh = &wmi->sq_threshld[SIGNAL_QUALITY_METRICS_SNR];
1571 
1572  /*
1573  * Identify the threshold breached and communicate that to the app.
1574  * After that install a new set of thresholds based on the signal
1575  * quality reported by the target.
1576  */
1577  if (new_threshold) {
1578  /* Upper threshold breached */
1579  if (snr < sq_thresh->upper_threshold[0]) {
1580  ath6kl_dbg(ATH6KL_DBG_WMI,
1581  "spurious upper snr threshold event: %d\n",
1582  snr);
1583  } else if ((snr < sq_thresh->upper_threshold[1]) &&
1584  (snr >= sq_thresh->upper_threshold[0])) {
1585  new_threshold = WMI_SNR_THRESHOLD1_ABOVE;
1586  } else if ((snr < sq_thresh->upper_threshold[2]) &&
1587  (snr >= sq_thresh->upper_threshold[1])) {
1588  new_threshold = WMI_SNR_THRESHOLD2_ABOVE;
1589  } else if ((snr < sq_thresh->upper_threshold[3]) &&
1590  (snr >= sq_thresh->upper_threshold[2])) {
1591  new_threshold = WMI_SNR_THRESHOLD3_ABOVE;
1592  } else if (snr >= sq_thresh->upper_threshold[3]) {
1593  new_threshold = WMI_SNR_THRESHOLD4_ABOVE;
1594  }
1595  } else {
1596  /* Lower threshold breached */
1597  if (snr > sq_thresh->lower_threshold[0]) {
1598  ath6kl_dbg(ATH6KL_DBG_WMI,
1599  "spurious lower snr threshold event: %d\n",
1600  sq_thresh->lower_threshold[0]);
1601  } else if ((snr > sq_thresh->lower_threshold[1]) &&
1602  (snr <= sq_thresh->lower_threshold[0])) {
1603  new_threshold = WMI_SNR_THRESHOLD4_BELOW;
1604  } else if ((snr > sq_thresh->lower_threshold[2]) &&
1605  (snr <= sq_thresh->lower_threshold[1])) {
1606  new_threshold = WMI_SNR_THRESHOLD3_BELOW;
1607  } else if ((snr > sq_thresh->lower_threshold[3]) &&
1608  (snr <= sq_thresh->lower_threshold[2])) {
1609  new_threshold = WMI_SNR_THRESHOLD2_BELOW;
1610  } else if (snr <= sq_thresh->lower_threshold[3]) {
1611  new_threshold = WMI_SNR_THRESHOLD1_BELOW;
1612  }
1613  }
1614 
1615  /* Calculate and install the next set of thresholds */
1616  lower_snr_threshold = ath6kl_wmi_get_lower_threshold(snr, sq_thresh,
1617  sq_thresh->lower_threshold_valid_count);
1618  upper_snr_threshold = ath6kl_wmi_get_upper_threshold(snr, sq_thresh,
1619  sq_thresh->upper_threshold_valid_count);
1620 
1621  /* Issue a wmi command to install the thresholds */
1622  cmd.thresh_above1_val = upper_snr_threshold;
1623  cmd.thresh_below1_val = lower_snr_threshold;
1624  cmd.weight = sq_thresh->weight;
1625  cmd.poll_time = cpu_to_le32(sq_thresh->polling_interval);
1626 
1627  ath6kl_dbg(ATH6KL_DBG_WMI,
1628  "snr: %d, threshold: %d, lower: %d, upper: %d\n",
1629  snr, new_threshold,
1630  lower_snr_threshold, upper_snr_threshold);
1631 
1632  ret = ath6kl_wmi_send_snr_threshold_params(wmi, &cmd);
1633  if (ret) {
1634  ath6kl_err("unable to configure snr threshold\n");
1635  return -EIO;
1636  }
1637 
1638  return 0;
1639 }
1640 
1641 static int ath6kl_wmi_aplist_event_rx(struct wmi *wmi, u8 *datap, int len)
1642 {
1643  u16 ap_info_entry_size;
1644  struct wmi_aplist_event *ev = (struct wmi_aplist_event *) datap;
1645  struct wmi_ap_info_v1 *ap_info_v1;
1646  u8 index;
1647 
1648  if (len < sizeof(struct wmi_aplist_event) ||
1649  ev->ap_list_ver != APLIST_VER1)
1650  return -EINVAL;
1651 
1652  ap_info_entry_size = sizeof(struct wmi_ap_info_v1);
1653  ap_info_v1 = (struct wmi_ap_info_v1 *) ev->ap_list;
1654 
1655  ath6kl_dbg(ATH6KL_DBG_WMI,
1656  "number of APs in aplist event: %d\n", ev->num_ap);
1657 
1658  if (len < (int) (sizeof(struct wmi_aplist_event) +
1659  (ev->num_ap - 1) * ap_info_entry_size))
1660  return -EINVAL;
1661 
1662  /* AP list version 1 contents */
1663  for (index = 0; index < ev->num_ap; index++) {
1664  ath6kl_dbg(ATH6KL_DBG_WMI, "AP#%d BSSID %pM Channel %d\n",
1665  index, ap_info_v1->bssid, ap_info_v1->channel);
1666  ap_info_v1++;
1667  }
1668 
1669  return 0;
1670 }
1671 
1672 int ath6kl_wmi_cmd_send(struct wmi *wmi, u8 if_idx, struct sk_buff *skb,
1673  enum wmi_cmd_id cmd_id, enum wmi_sync_flag sync_flag)
1674 {
1675  struct wmi_cmd_hdr *cmd_hdr;
1676  enum htc_endpoint_id ep_id = wmi->ep_id;
1677  int ret;
1678  u16 info1;
1679 
1680  if (WARN_ON(skb == NULL || (if_idx > (wmi->parent_dev->vif_max - 1))))
1681  return -EINVAL;
1682 
1683  ath6kl_dbg(ATH6KL_DBG_WMI, "wmi tx id %d len %d flag %d\n",
1684  cmd_id, skb->len, sync_flag);
1685  ath6kl_dbg_dump(ATH6KL_DBG_WMI_DUMP, NULL, "wmi tx ",
1686  skb->data, skb->len);
1687 
1688  if (sync_flag >= END_WMIFLAG) {
1689  dev_kfree_skb(skb);
1690  return -EINVAL;
1691  }
1692 
1693  if ((sync_flag == SYNC_BEFORE_WMIFLAG) ||
1694  (sync_flag == SYNC_BOTH_WMIFLAG)) {
1695  /*
1696  * Make sure all data currently queued is transmitted before
1697  * the cmd execution. Establish a new sync point.
1698  */
1699  ath6kl_wmi_sync_point(wmi, if_idx);
1700  }
1701 
1702  skb_push(skb, sizeof(struct wmi_cmd_hdr));
1703 
1704  cmd_hdr = (struct wmi_cmd_hdr *) skb->data;
1705  cmd_hdr->cmd_id = cpu_to_le16(cmd_id);
1706  info1 = if_idx & WMI_CMD_HDR_IF_ID_MASK;
1707  cmd_hdr->info1 = cpu_to_le16(info1);
1708 
1709  /* Only for OPT_TX_CMD, use BE endpoint. */
1710  if (cmd_id == WMI_OPT_TX_FRAME_CMDID) {
1711  ret = ath6kl_wmi_data_hdr_add(wmi, skb, OPT_MSGTYPE,
1712  false, false, 0, NULL, if_idx);
1713  if (ret) {
1714  dev_kfree_skb(skb);
1715  return ret;
1716  }
1718  }
1719 
1720  ath6kl_control_tx(wmi->parent_dev, skb, ep_id);
1721 
1722  if ((sync_flag == SYNC_AFTER_WMIFLAG) ||
1723  (sync_flag == SYNC_BOTH_WMIFLAG)) {
1724  /*
1725  * Make sure all new data queued waits for the command to
1726  * execute. Establish a new sync point.
1727  */
1728  ath6kl_wmi_sync_point(wmi, if_idx);
1729  }
1730 
1731  return 0;
1732 }
1733 
1734 int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx,
1735  enum network_type nw_type,
1737  enum auth_mode auth_mode,
1738  enum crypto_type pairwise_crypto,
1739  u8 pairwise_crypto_len,
1740  enum crypto_type group_crypto,
1741  u8 group_crypto_len, int ssid_len, u8 *ssid,
1742  u8 *bssid, u16 channel, u32 ctrl_flags,
1743  u8 nw_subtype)
1744 {
1745  struct sk_buff *skb;
1746  struct wmi_connect_cmd *cc;
1747  int ret;
1748 
1749  ath6kl_dbg(ATH6KL_DBG_WMI,
1750  "wmi connect bssid %pM freq %d flags 0x%x ssid_len %d "
1751  "type %d dot11_auth %d auth %d pairwise %d group %d\n",
1752  bssid, channel, ctrl_flags, ssid_len, nw_type,
1753  dot11_auth_mode, auth_mode, pairwise_crypto, group_crypto);
1754  ath6kl_dbg_dump(ATH6KL_DBG_WMI, NULL, "ssid ", ssid, ssid_len);
1755 
1756  wmi->traffic_class = 100;
1757 
1758  if ((pairwise_crypto == NONE_CRYPT) && (group_crypto != NONE_CRYPT))
1759  return -EINVAL;
1760 
1761  if ((pairwise_crypto != NONE_CRYPT) && (group_crypto == NONE_CRYPT))
1762  return -EINVAL;
1763 
1764  skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_connect_cmd));
1765  if (!skb)
1766  return -ENOMEM;
1767 
1768  cc = (struct wmi_connect_cmd *) skb->data;
1769 
1770  if (ssid_len)
1771  memcpy(cc->ssid, ssid, ssid_len);
1772 
1773  cc->ssid_len = ssid_len;
1774  cc->nw_type = nw_type;
1776  cc->auth_mode = auth_mode;
1777  cc->prwise_crypto_type = pairwise_crypto;
1778  cc->prwise_crypto_len = pairwise_crypto_len;
1779  cc->grp_crypto_type = group_crypto;
1780  cc->grp_crypto_len = group_crypto_len;
1781  cc->ch = cpu_to_le16(channel);
1782  cc->ctrl_flags = cpu_to_le32(ctrl_flags);
1783  cc->nw_subtype = nw_subtype;
1784 
1785  if (bssid != NULL)
1786  memcpy(cc->bssid, bssid, ETH_ALEN);
1787 
1788  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_CONNECT_CMDID,
1789  NO_SYNC_WMIFLAG);
1790 
1791  return ret;
1792 }
1793 
1794 int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 if_idx, u8 *bssid,
1795  u16 channel)
1796 {
1797  struct sk_buff *skb;
1798  struct wmi_reconnect_cmd *cc;
1799  int ret;
1800 
1801  ath6kl_dbg(ATH6KL_DBG_WMI, "wmi reconnect bssid %pM freq %d\n",
1802  bssid, channel);
1803 
1804  wmi->traffic_class = 100;
1805 
1806  skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_reconnect_cmd));
1807  if (!skb)
1808  return -ENOMEM;
1809 
1810  cc = (struct wmi_reconnect_cmd *) skb->data;
1811  cc->channel = cpu_to_le16(channel);
1812 
1813  if (bssid != NULL)
1814  memcpy(cc->bssid, bssid, ETH_ALEN);
1815 
1816  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_RECONNECT_CMDID,
1817  NO_SYNC_WMIFLAG);
1818 
1819  return ret;
1820 }
1821 
1822 int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx)
1823 {
1824  int ret;
1825 
1826  ath6kl_dbg(ATH6KL_DBG_WMI, "wmi disconnect\n");
1827 
1828  wmi->traffic_class = 100;
1829 
1830  /* Disconnect command does not need to do a SYNC before. */
1831  ret = ath6kl_wmi_simple_cmd(wmi, if_idx, WMI_DISCONNECT_CMDID);
1832 
1833  return ret;
1834 }
1835 
1836 int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
1837  enum wmi_scan_type scan_type,
1838  u32 force_fgscan, u32 is_legacy,
1839  u32 home_dwell_time, u32 force_scan_interval,
1840  s8 num_chan, u16 *ch_list, u32 no_cck, u32 *rates)
1841 {
1842  struct ieee80211_supported_band *sband;
1843  struct sk_buff *skb;
1844  struct wmi_begin_scan_cmd *sc;
1845  s8 size, *supp_rates;
1846  int i, band, ret;
1847  struct ath6kl *ar = wmi->parent_dev;
1848  int num_rates;
1849  u32 ratemask;
1850 
1851  size = sizeof(struct wmi_begin_scan_cmd);
1852 
1853  if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
1854  return -EINVAL;
1855 
1856  if (num_chan > WMI_MAX_CHANNELS)
1857  return -EINVAL;
1858 
1859  if (num_chan)
1860  size += sizeof(u16) * (num_chan - 1);
1861 
1862  skb = ath6kl_wmi_get_new_buf(size);
1863  if (!skb)
1864  return -ENOMEM;
1865 
1866  sc = (struct wmi_begin_scan_cmd *) skb->data;
1867  sc->scan_type = scan_type;
1868  sc->force_fg_scan = cpu_to_le32(force_fgscan);
1869  sc->is_legacy = cpu_to_le32(is_legacy);
1870  sc->home_dwell_time = cpu_to_le32(home_dwell_time);
1871  sc->force_scan_intvl = cpu_to_le32(force_scan_interval);
1872  sc->no_cck = cpu_to_le32(no_cck);
1873  sc->num_ch = num_chan;
1874 
1875  for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1876  sband = ar->wiphy->bands[band];
1877 
1878  if (!sband)
1879  continue;
1880 
1881  ratemask = rates[band];
1882  supp_rates = sc->supp_rates[band].rates;
1883  num_rates = 0;
1884 
1885  for (i = 0; i < sband->n_bitrates; i++) {
1886  if ((BIT(i) & ratemask) == 0)
1887  continue; /* skip rate */
1888  supp_rates[num_rates++] =
1889  (u8) (sband->bitrates[i].bitrate / 5);
1890  }
1891  sc->supp_rates[band].nrates = num_rates;
1892  }
1893 
1894  for (i = 0; i < num_chan; i++)
1895  sc->ch_list[i] = cpu_to_le16(ch_list[i]);
1896 
1897  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_BEGIN_SCAN_CMDID,
1898  NO_SYNC_WMIFLAG);
1899 
1900  return ret;
1901 }
1902 
1903 /* ath6kl_wmi_start_scan_cmd is to be deprecated. Use
1904  * ath6kl_wmi_begin_scan_cmd instead. The new function supports P2P
1905  * mgmt operations using station interface.
1906  */
1907 int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
1908  enum wmi_scan_type scan_type,
1909  u32 force_fgscan, u32 is_legacy,
1910  u32 home_dwell_time, u32 force_scan_interval,
1911  s8 num_chan, u16 *ch_list)
1912 {
1913  struct sk_buff *skb;
1914  struct wmi_start_scan_cmd *sc;
1915  s8 size;
1916  int i, ret;
1917 
1918  size = sizeof(struct wmi_start_scan_cmd);
1919 
1920  if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
1921  return -EINVAL;
1922 
1923  if (num_chan > WMI_MAX_CHANNELS)
1924  return -EINVAL;
1925 
1926  if (num_chan)
1927  size += sizeof(u16) * (num_chan - 1);
1928 
1929  skb = ath6kl_wmi_get_new_buf(size);
1930  if (!skb)
1931  return -ENOMEM;
1932 
1933  sc = (struct wmi_start_scan_cmd *) skb->data;
1934  sc->scan_type = scan_type;
1935  sc->force_fg_scan = cpu_to_le32(force_fgscan);
1936  sc->is_legacy = cpu_to_le32(is_legacy);
1937  sc->home_dwell_time = cpu_to_le32(home_dwell_time);
1938  sc->force_scan_intvl = cpu_to_le32(force_scan_interval);
1939  sc->num_ch = num_chan;
1940 
1941  for (i = 0; i < num_chan; i++)
1942  sc->ch_list[i] = cpu_to_le16(ch_list[i]);
1943 
1944  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_START_SCAN_CMDID,
1945  NO_SYNC_WMIFLAG);
1946 
1947  return ret;
1948 }
1949 
1950 int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u8 if_idx,
1951  u16 fg_start_sec,
1952  u16 fg_end_sec, u16 bg_sec,
1953  u16 minact_chdw_msec, u16 maxact_chdw_msec,
1954  u16 pas_chdw_msec, u8 short_scan_ratio,
1955  u8 scan_ctrl_flag, u32 max_dfsch_act_time,
1956  u16 maxact_scan_per_ssid)
1957 {
1958  struct sk_buff *skb;
1959  struct wmi_scan_params_cmd *sc;
1960  int ret;
1961 
1962  skb = ath6kl_wmi_get_new_buf(sizeof(*sc));
1963  if (!skb)
1964  return -ENOMEM;
1965 
1966  sc = (struct wmi_scan_params_cmd *) skb->data;
1967  sc->fg_start_period = cpu_to_le16(fg_start_sec);
1968  sc->fg_end_period = cpu_to_le16(fg_end_sec);
1969  sc->bg_period = cpu_to_le16(bg_sec);
1970  sc->minact_chdwell_time = cpu_to_le16(minact_chdw_msec);
1971  sc->maxact_chdwell_time = cpu_to_le16(maxact_chdw_msec);
1972  sc->pas_chdwell_time = cpu_to_le16(pas_chdw_msec);
1974  sc->scan_ctrl_flags = scan_ctrl_flag;
1975  sc->max_dfsch_act_time = cpu_to_le32(max_dfsch_act_time);
1976  sc->maxact_scan_per_ssid = cpu_to_le16(maxact_scan_per_ssid);
1977 
1978  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_SCAN_PARAMS_CMDID,
1979  NO_SYNC_WMIFLAG);
1980  return ret;
1981 }
1982 
1983 int ath6kl_wmi_bssfilter_cmd(struct wmi *wmi, u8 if_idx, u8 filter, u32 ie_mask)
1984 {
1985  struct sk_buff *skb;
1986  struct wmi_bss_filter_cmd *cmd;
1987  int ret;
1988 
1989  if (filter >= LAST_BSS_FILTER)
1990  return -EINVAL;
1991 
1992  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1993  if (!skb)
1994  return -ENOMEM;
1995 
1996  cmd = (struct wmi_bss_filter_cmd *) skb->data;
1997  cmd->bss_filter = filter;
1998  cmd->ie_mask = cpu_to_le32(ie_mask);
1999 
2000  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_BSS_FILTER_CMDID,
2001  NO_SYNC_WMIFLAG);
2002  return ret;
2003 }
2004 
2005 int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag,
2006  u8 ssid_len, u8 *ssid)
2007 {
2008  struct sk_buff *skb;
2009  struct wmi_probed_ssid_cmd *cmd;
2010  int ret;
2011 
2012  if (index >= MAX_PROBED_SSIDS)
2013  return -EINVAL;
2014 
2015  if (ssid_len > sizeof(cmd->ssid))
2016  return -EINVAL;
2017 
2018  if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssid_len > 0))
2019  return -EINVAL;
2020 
2021  if ((flag & SPECIFIC_SSID_FLAG) && !ssid_len)
2022  return -EINVAL;
2023 
2024  if (flag & SPECIFIC_SSID_FLAG)
2025  wmi->is_probe_ssid = true;
2026 
2027  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2028  if (!skb)
2029  return -ENOMEM;
2030 
2031  cmd = (struct wmi_probed_ssid_cmd *) skb->data;
2032  cmd->entry_index = index;
2033  cmd->flag = flag;
2034  cmd->ssid_len = ssid_len;
2035  memcpy(cmd->ssid, ssid, ssid_len);
2036 
2037  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_PROBED_SSID_CMDID,
2038  NO_SYNC_WMIFLAG);
2039  return ret;
2040 }
2041 
2042 int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u8 if_idx,
2044  u16 listen_beacons)
2045 {
2046  struct sk_buff *skb;
2047  struct wmi_listen_int_cmd *cmd;
2048  int ret;
2049 
2050  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2051  if (!skb)
2052  return -ENOMEM;
2053 
2054  cmd = (struct wmi_listen_int_cmd *) skb->data;
2055  cmd->listen_intvl = cpu_to_le16(listen_interval);
2056  cmd->num_beacons = cpu_to_le16(listen_beacons);
2057 
2058  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_LISTEN_INT_CMDID,
2059  NO_SYNC_WMIFLAG);
2060  return ret;
2061 }
2062 
2063 int ath6kl_wmi_bmisstime_cmd(struct wmi *wmi, u8 if_idx,
2064  u16 bmiss_time, u16 num_beacons)
2065 {
2066  struct sk_buff *skb;
2067  struct wmi_bmiss_time_cmd *cmd;
2068  int ret;
2069 
2070  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2071  if (!skb)
2072  return -ENOMEM;
2073 
2074  cmd = (struct wmi_bmiss_time_cmd *) skb->data;
2075  cmd->bmiss_time = cpu_to_le16(bmiss_time);
2076  cmd->num_beacons = cpu_to_le16(num_beacons);
2077 
2078  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_BMISS_TIME_CMDID,
2079  NO_SYNC_WMIFLAG);
2080  return ret;
2081 }
2082 
2083 int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 if_idx, u8 pwr_mode)
2084 {
2085  struct sk_buff *skb;
2086  struct wmi_power_mode_cmd *cmd;
2087  int ret;
2088 
2089  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2090  if (!skb)
2091  return -ENOMEM;
2092 
2093  cmd = (struct wmi_power_mode_cmd *) skb->data;
2094  cmd->pwr_mode = pwr_mode;
2095  wmi->pwr_mode = pwr_mode;
2096 
2097  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_POWER_MODE_CMDID,
2098  NO_SYNC_WMIFLAG);
2099  return ret;
2100 }
2101 
2102 int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u8 if_idx, u16 idle_period,
2103  u16 ps_poll_num, u16 dtim_policy,
2104  u16 tx_wakeup_policy, u16 num_tx_to_wakeup,
2105  u16 ps_fail_event_policy)
2106 {
2107  struct sk_buff *skb;
2108  struct wmi_power_params_cmd *pm;
2109  int ret;
2110 
2111  skb = ath6kl_wmi_get_new_buf(sizeof(*pm));
2112  if (!skb)
2113  return -ENOMEM;
2114 
2115  pm = (struct wmi_power_params_cmd *)skb->data;
2116  pm->idle_period = cpu_to_le16(idle_period);
2117  pm->pspoll_number = cpu_to_le16(ps_poll_num);
2118  pm->dtim_policy = cpu_to_le16(dtim_policy);
2119  pm->tx_wakeup_policy = cpu_to_le16(tx_wakeup_policy);
2120  pm->num_tx_to_wakeup = cpu_to_le16(num_tx_to_wakeup);
2121  pm->ps_fail_event_policy = cpu_to_le16(ps_fail_event_policy);
2122 
2123  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_POWER_PARAMS_CMDID,
2124  NO_SYNC_WMIFLAG);
2125  return ret;
2126 }
2127 
2128 int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 if_idx, u8 timeout)
2129 {
2130  struct sk_buff *skb;
2131  struct wmi_disc_timeout_cmd *cmd;
2132  int ret;
2133 
2134  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2135  if (!skb)
2136  return -ENOMEM;
2137 
2138  cmd = (struct wmi_disc_timeout_cmd *) skb->data;
2139  cmd->discon_timeout = timeout;
2140 
2141  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_DISC_TIMEOUT_CMDID,
2142  NO_SYNC_WMIFLAG);
2143 
2144  if (ret == 0)
2145  ath6kl_debug_set_disconnect_timeout(wmi->parent_dev, timeout);
2146 
2147  return ret;
2148 }
2149 
2150 int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index,
2151  enum crypto_type key_type,
2153  u8 *key_rsc, unsigned int key_rsc_len,
2154  u8 *key_material,
2155  u8 key_op_ctrl, u8 *mac_addr,
2156  enum wmi_sync_flag sync_flag)
2157 {
2158  struct sk_buff *skb;
2159  struct wmi_add_cipher_key_cmd *cmd;
2160  int ret;
2161 
2162  ath6kl_dbg(ATH6KL_DBG_WMI,
2163  "addkey cmd: key_index=%u key_type=%d key_usage=%d key_len=%d key_op_ctrl=%d\n",
2164  key_index, key_type, key_usage, key_len, key_op_ctrl);
2165 
2166  if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) ||
2167  (key_material == NULL) || key_rsc_len > 8)
2168  return -EINVAL;
2169 
2170  if ((WEP_CRYPT != key_type) && (NULL == key_rsc))
2171  return -EINVAL;
2172 
2173  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2174  if (!skb)
2175  return -ENOMEM;
2176 
2177  cmd = (struct wmi_add_cipher_key_cmd *) skb->data;
2178  cmd->key_index = key_index;
2179  cmd->key_type = key_type;
2180  cmd->key_usage = key_usage;
2181  cmd->key_len = key_len;
2182  memcpy(cmd->key, key_material, key_len);
2183 
2184  if (key_rsc != NULL)
2185  memcpy(cmd->key_rsc, key_rsc, key_rsc_len);
2186 
2187  cmd->key_op_ctrl = key_op_ctrl;
2188 
2189  if (mac_addr)
2190  memcpy(cmd->key_mac_addr, mac_addr, ETH_ALEN);
2191 
2192  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_ADD_CIPHER_KEY_CMDID,
2193  sync_flag);
2194 
2195  return ret;
2196 }
2197 
2198 int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk)
2199 {
2200  struct sk_buff *skb;
2201  struct wmi_add_krk_cmd *cmd;
2202  int ret;
2203 
2204  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2205  if (!skb)
2206  return -ENOMEM;
2207 
2208  cmd = (struct wmi_add_krk_cmd *) skb->data;
2209  memcpy(cmd->krk, krk, WMI_KRK_LEN);
2210 
2211  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_ADD_KRK_CMDID,
2212  NO_SYNC_WMIFLAG);
2213 
2214  return ret;
2215 }
2216 
2217 int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index)
2218 {
2219  struct sk_buff *skb;
2221  int ret;
2222 
2223  if (key_index > WMI_MAX_KEY_INDEX)
2224  return -EINVAL;
2225 
2226  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2227  if (!skb)
2228  return -ENOMEM;
2229 
2230  cmd = (struct wmi_delete_cipher_key_cmd *) skb->data;
2231  cmd->key_index = key_index;
2232 
2233  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_DELETE_CIPHER_KEY_CMDID,
2234  NO_SYNC_WMIFLAG);
2235 
2236  return ret;
2237 }
2238 
2239 int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, u8 if_idx, const u8 *bssid,
2240  const u8 *pmkid, bool set)
2241 {
2242  struct sk_buff *skb;
2243  struct wmi_setpmkid_cmd *cmd;
2244  int ret;
2245 
2246  if (bssid == NULL)
2247  return -EINVAL;
2248 
2249  if (set && pmkid == NULL)
2250  return -EINVAL;
2251 
2252  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2253  if (!skb)
2254  return -ENOMEM;
2255 
2256  cmd = (struct wmi_setpmkid_cmd *) skb->data;
2257  memcpy(cmd->bssid, bssid, ETH_ALEN);
2258  if (set) {
2259  memcpy(cmd->pmkid, pmkid, sizeof(cmd->pmkid));
2260  cmd->enable = PMKID_ENABLE;
2261  } else {
2262  memset(cmd->pmkid, 0, sizeof(cmd->pmkid));
2263  cmd->enable = PMKID_DISABLE;
2264  }
2265 
2266  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_PMKID_CMDID,
2267  NO_SYNC_WMIFLAG);
2268 
2269  return ret;
2270 }
2271 
2272 static int ath6kl_wmi_data_sync_send(struct wmi *wmi, struct sk_buff *skb,
2273  enum htc_endpoint_id ep_id, u8 if_idx)
2274 {
2275  struct wmi_data_hdr *data_hdr;
2276  int ret;
2277 
2278  if (WARN_ON(skb == NULL || ep_id == wmi->ep_id))
2279  return -EINVAL;
2280 
2281  skb_push(skb, sizeof(struct wmi_data_hdr));
2282 
2283  data_hdr = (struct wmi_data_hdr *) skb->data;
2285  data_hdr->info3 = cpu_to_le16(if_idx & WMI_DATA_HDR_IF_IDX_MASK);
2286 
2287  ret = ath6kl_control_tx(wmi->parent_dev, skb, ep_id);
2288 
2289  return ret;
2290 }
2291 
2292 static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
2293 {
2294  struct sk_buff *skb;
2295  struct wmi_sync_cmd *cmd;
2296  struct wmi_data_sync_bufs data_sync_bufs[WMM_NUM_AC];
2297  enum htc_endpoint_id ep_id;
2298  u8 index, num_pri_streams = 0;
2299  int ret = 0;
2300 
2301  memset(data_sync_bufs, 0, sizeof(data_sync_bufs));
2302 
2303  spin_lock_bh(&wmi->lock);
2304 
2305  for (index = 0; index < WMM_NUM_AC; index++) {
2306  if (wmi->fat_pipe_exist & (1 << index)) {
2307  num_pri_streams++;
2308  data_sync_bufs[num_pri_streams - 1].traffic_class =
2309  index;
2310  }
2311  }
2312 
2313  spin_unlock_bh(&wmi->lock);
2314 
2315  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2316  if (!skb) {
2317  ret = -ENOMEM;
2318  goto free_skb;
2319  }
2320 
2321  cmd = (struct wmi_sync_cmd *) skb->data;
2322 
2323  /*
2324  * In the SYNC cmd sent on the control Ep, send a bitmap
2325  * of the data eps on which the Data Sync will be sent
2326  */
2327  cmd->data_sync_map = wmi->fat_pipe_exist;
2328 
2329  for (index = 0; index < num_pri_streams; index++) {
2330  data_sync_bufs[index].skb = ath6kl_buf_alloc(0);
2331  if (data_sync_bufs[index].skb == NULL) {
2332  ret = -ENOMEM;
2333  break;
2334  }
2335  }
2336 
2337  /*
2338  * If buffer allocation for any of the dataSync fails,
2339  * then do not send the Synchronize cmd on the control ep
2340  */
2341  if (ret)
2342  goto free_skb;
2343 
2344  /*
2345  * Send sync cmd followed by sync data messages on all
2346  * endpoints being used
2347  */
2348  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SYNCHRONIZE_CMDID,
2349  NO_SYNC_WMIFLAG);
2350 
2351  if (ret)
2352  goto free_skb;
2353 
2354  /* cmd buffer sent, we no longer own it */
2355  skb = NULL;
2356 
2357  for (index = 0; index < num_pri_streams; index++) {
2358 
2359  if (WARN_ON(!data_sync_bufs[index].skb))
2360  break;
2361 
2362  ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev,
2363  data_sync_bufs[index].
2364  traffic_class);
2365  ret =
2366  ath6kl_wmi_data_sync_send(wmi, data_sync_bufs[index].skb,
2367  ep_id, if_idx);
2368 
2369  if (ret)
2370  break;
2371 
2372  data_sync_bufs[index].skb = NULL;
2373  }
2374 
2375 free_skb:
2376  /* free up any resources left over (possibly due to an error) */
2377  if (skb)
2378  dev_kfree_skb(skb);
2379 
2380  for (index = 0; index < num_pri_streams; index++) {
2381  if (data_sync_bufs[index].skb != NULL) {
2382  dev_kfree_skb((struct sk_buff *)data_sync_bufs[index].
2383  skb);
2384  }
2385  }
2386 
2387  return ret;
2388 }
2389 
2390 int ath6kl_wmi_create_pstream_cmd(struct wmi *wmi, u8 if_idx,
2392 {
2393  struct sk_buff *skb;
2394  struct wmi_create_pstream_cmd *cmd;
2395  u8 fatpipe_exist_for_ac = 0;
2396  s32 min_phy = 0;
2397  s32 nominal_phy = 0;
2398  int ret;
2399 
2400  if (!((params->user_pri < 8) &&
2401  (params->user_pri <= 0x7) &&
2402  (up_to_ac[params->user_pri & 0x7] == params->traffic_class) &&
2403  (params->traffic_direc == UPLINK_TRAFFIC ||
2404  params->traffic_direc == DNLINK_TRAFFIC ||
2405  params->traffic_direc == BIDIR_TRAFFIC) &&
2406  (params->traffic_type == TRAFFIC_TYPE_APERIODIC ||
2407  params->traffic_type == TRAFFIC_TYPE_PERIODIC) &&
2408  (params->voice_psc_cap == DISABLE_FOR_THIS_AC ||
2409  params->voice_psc_cap == ENABLE_FOR_THIS_AC ||
2410  params->voice_psc_cap == ENABLE_FOR_ALL_AC) &&
2411  (params->tsid == WMI_IMPLICIT_PSTREAM ||
2412  params->tsid <= WMI_MAX_THINSTREAM))) {
2413  return -EINVAL;
2414  }
2415 
2416  /*
2417  * Check nominal PHY rate is >= minimalPHY,
2418  * so that DUT can allow TSRS IE
2419  */
2420 
2421  /* Get the physical rate (units of bps) */
2422  min_phy = ((le32_to_cpu(params->min_phy_rate) / 1000) / 1000);
2423 
2424  /* Check minimal phy < nominal phy rate */
2425  if (params->nominal_phy >= min_phy) {
2426  /* unit of 500 kbps */
2427  nominal_phy = (params->nominal_phy * 1000) / 500;
2428  ath6kl_dbg(ATH6KL_DBG_WMI,
2429  "TSRS IE enabled::MinPhy %x->NominalPhy ===> %x\n",
2430  min_phy, nominal_phy);
2431 
2432  params->nominal_phy = nominal_phy;
2433  } else {
2434  params->nominal_phy = 0;
2435  }
2436 
2437  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2438  if (!skb)
2439  return -ENOMEM;
2440 
2441  ath6kl_dbg(ATH6KL_DBG_WMI,
2442  "sending create_pstream_cmd: ac=%d tsid:%d\n",
2443  params->traffic_class, params->tsid);
2444 
2445  cmd = (struct wmi_create_pstream_cmd *) skb->data;
2446  memcpy(cmd, params, sizeof(*cmd));
2447 
2448  /* This is an implicitly created Fat pipe */
2449  if ((u32) params->tsid == (u32) WMI_IMPLICIT_PSTREAM) {
2450  spin_lock_bh(&wmi->lock);
2451  fatpipe_exist_for_ac = (wmi->fat_pipe_exist &
2452  (1 << params->traffic_class));
2453  wmi->fat_pipe_exist |= (1 << params->traffic_class);
2454  spin_unlock_bh(&wmi->lock);
2455  } else {
2456  /* explicitly created thin stream within a fat pipe */
2457  spin_lock_bh(&wmi->lock);
2458  fatpipe_exist_for_ac = (wmi->fat_pipe_exist &
2459  (1 << params->traffic_class));
2460  wmi->stream_exist_for_ac[params->traffic_class] |=
2461  (1 << params->tsid);
2462  /*
2463  * If a thinstream becomes active, the fat pipe automatically
2464  * becomes active
2465  */
2466  wmi->fat_pipe_exist |= (1 << params->traffic_class);
2467  spin_unlock_bh(&wmi->lock);
2468  }
2469 
2470  /*
2471  * Indicate activty change to driver layer only if this is the
2472  * first TSID to get created in this AC explicitly or an implicit
2473  * fat pipe is getting created.
2474  */
2475  if (!fatpipe_exist_for_ac)
2477  params->traffic_class, true);
2478 
2479  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_CREATE_PSTREAM_CMDID,
2480  NO_SYNC_WMIFLAG);
2481  return ret;
2482 }
2483 
2484 int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 if_idx, u8 traffic_class,
2485  u8 tsid)
2486 {
2487  struct sk_buff *skb;
2488  struct wmi_delete_pstream_cmd *cmd;
2489  u16 active_tsids = 0;
2490  int ret;
2491 
2492  if (traffic_class > 3) {
2493  ath6kl_err("invalid traffic class: %d\n", traffic_class);
2494  return -EINVAL;
2495  }
2496 
2497  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2498  if (!skb)
2499  return -ENOMEM;
2500 
2501  cmd = (struct wmi_delete_pstream_cmd *) skb->data;
2502  cmd->traffic_class = traffic_class;
2503  cmd->tsid = tsid;
2504 
2505  spin_lock_bh(&wmi->lock);
2506  active_tsids = wmi->stream_exist_for_ac[traffic_class];
2507  spin_unlock_bh(&wmi->lock);
2508 
2509  if (!(active_tsids & (1 << tsid))) {
2510  dev_kfree_skb(skb);
2511  ath6kl_dbg(ATH6KL_DBG_WMI,
2512  "TSID %d doesn't exist for traffic class: %d\n",
2513  tsid, traffic_class);
2514  return -ENODATA;
2515  }
2516 
2517  ath6kl_dbg(ATH6KL_DBG_WMI,
2518  "sending delete_pstream_cmd: traffic class: %d tsid=%d\n",
2519  traffic_class, tsid);
2520 
2521  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_DELETE_PSTREAM_CMDID,
2523 
2524  spin_lock_bh(&wmi->lock);
2525  wmi->stream_exist_for_ac[traffic_class] &= ~(1 << tsid);
2526  active_tsids = wmi->stream_exist_for_ac[traffic_class];
2527  spin_unlock_bh(&wmi->lock);
2528 
2529  /*
2530  * Indicate stream inactivity to driver layer only if all tsids
2531  * within this AC are deleted.
2532  */
2533  if (!active_tsids) {
2535  traffic_class, false);
2536  wmi->fat_pipe_exist &= ~(1 << traffic_class);
2537  }
2538 
2539  return ret;
2540 }
2541 
2542 int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
2543  __be32 ips0, __be32 ips1)
2544 {
2545  struct sk_buff *skb;
2546  struct wmi_set_ip_cmd *cmd;
2547  int ret;
2548 
2549  /* Multicast address are not valid */
2550  if (ipv4_is_multicast(ips0) ||
2551  ipv4_is_multicast(ips1))
2552  return -EINVAL;
2553 
2554  skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_ip_cmd));
2555  if (!skb)
2556  return -ENOMEM;
2557 
2558  cmd = (struct wmi_set_ip_cmd *) skb->data;
2559  cmd->ips[0] = ips0;
2560  cmd->ips[1] = ips1;
2561 
2562  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_IP_CMDID,
2563  NO_SYNC_WMIFLAG);
2564  return ret;
2565 }
2566 
2567 static void ath6kl_wmi_relinquish_implicit_pstream_credits(struct wmi *wmi)
2568 {
2569  u16 active_tsids;
2570  u8 stream_exist;
2571  int i;
2572 
2573  /*
2574  * Relinquish credits from all implicitly created pstreams
2575  * since when we go to sleep. If user created explicit
2576  * thinstreams exists with in a fatpipe leave them intact
2577  * for the user to delete.
2578  */
2579  spin_lock_bh(&wmi->lock);
2580  stream_exist = wmi->fat_pipe_exist;
2581  spin_unlock_bh(&wmi->lock);
2582 
2583  for (i = 0; i < WMM_NUM_AC; i++) {
2584  if (stream_exist & (1 << i)) {
2585 
2586  /*
2587  * FIXME: Is this lock & unlock inside
2588  * for loop correct? may need rework.
2589  */
2590  spin_lock_bh(&wmi->lock);
2591  active_tsids = wmi->stream_exist_for_ac[i];
2592  spin_unlock_bh(&wmi->lock);
2593 
2594  /*
2595  * If there are no user created thin streams
2596  * delete the fatpipe
2597  */
2598  if (!active_tsids) {
2599  stream_exist &= ~(1 << i);
2600  /*
2601  * Indicate inactivity to driver layer for
2602  * this fatpipe (pstream)
2603  */
2605  i, false);
2606  }
2607  }
2608  }
2609 
2610  /* FIXME: Can we do this assignment without locking ? */
2611  spin_lock_bh(&wmi->lock);
2612  wmi->fat_pipe_exist = stream_exist;
2613  spin_unlock_bh(&wmi->lock);
2614 }
2615 
2616 static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
2617  const struct cfg80211_bitrate_mask *mask)
2618 {
2619  struct sk_buff *skb;
2620  int ret, mode, band;
2621  u64 mcsrate, ratemask[IEEE80211_NUM_BANDS];
2623 
2624  memset(&ratemask, 0, sizeof(ratemask));
2625  for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
2626  /* copy legacy rate mask */
2627  ratemask[band] = mask->control[band].legacy;
2628  if (band == IEEE80211_BAND_5GHZ)
2629  ratemask[band] =
2630  mask->control[band].legacy << 4;
2631 
2632  /* copy mcs rate mask */
2633  mcsrate = mask->control[band].mcs[1];
2634  mcsrate <<= 8;
2635  mcsrate |= mask->control[band].mcs[0];
2636  ratemask[band] |= mcsrate << 12;
2637  ratemask[band] |= mcsrate << 28;
2638  }
2639 
2640  ath6kl_dbg(ATH6KL_DBG_WMI,
2641  "Ratemask 64 bit: 2.4:%llx 5:%llx\n",
2642  ratemask[0], ratemask[1]);
2643 
2644  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
2645  if (!skb)
2646  return -ENOMEM;
2647 
2648  cmd = (struct wmi_set_tx_select_rates64_cmd *) skb->data;
2649  for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) {
2650  /* A mode operate in 5GHZ band */
2651  if (mode == WMI_RATES_MODE_11A ||
2652  mode == WMI_RATES_MODE_11A_HT20 ||
2653  mode == WMI_RATES_MODE_11A_HT40)
2654  band = IEEE80211_BAND_5GHZ;
2655  else
2656  band = IEEE80211_BAND_2GHZ;
2657  cmd->ratemask[mode] = cpu_to_le64(ratemask[band]);
2658  }
2659 
2660  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
2662  NO_SYNC_WMIFLAG);
2663  return ret;
2664 }
2665 
2666 static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
2667  const struct cfg80211_bitrate_mask *mask)
2668 {
2669  struct sk_buff *skb;
2670  int ret, mode, band;
2671  u32 mcsrate, ratemask[IEEE80211_NUM_BANDS];
2673 
2674  memset(&ratemask, 0, sizeof(ratemask));
2675  for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
2676  /* copy legacy rate mask */
2677  ratemask[band] = mask->control[band].legacy;
2678  if (band == IEEE80211_BAND_5GHZ)
2679  ratemask[band] =
2680  mask->control[band].legacy << 4;
2681 
2682  /* copy mcs rate mask */
2683  mcsrate = mask->control[band].mcs[0];
2684  ratemask[band] |= mcsrate << 12;
2685  ratemask[band] |= mcsrate << 20;
2686  }
2687 
2688  ath6kl_dbg(ATH6KL_DBG_WMI,
2689  "Ratemask 32 bit: 2.4:%x 5:%x\n",
2690  ratemask[0], ratemask[1]);
2691 
2692  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
2693  if (!skb)
2694  return -ENOMEM;
2695 
2696  cmd = (struct wmi_set_tx_select_rates32_cmd *) skb->data;
2697  for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) {
2698  /* A mode operate in 5GHZ band */
2699  if (mode == WMI_RATES_MODE_11A ||
2700  mode == WMI_RATES_MODE_11A_HT20 ||
2701  mode == WMI_RATES_MODE_11A_HT40)
2702  band = IEEE80211_BAND_5GHZ;
2703  else
2704  band = IEEE80211_BAND_2GHZ;
2705  cmd->ratemask[mode] = cpu_to_le32(ratemask[band]);
2706  }
2707 
2708  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
2710  NO_SYNC_WMIFLAG);
2711  return ret;
2712 }
2713 
2714 int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
2715  const struct cfg80211_bitrate_mask *mask)
2716 {
2717  struct ath6kl *ar = wmi->parent_dev;
2718 
2719  if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES)
2720  return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
2721  else
2722  return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
2723 }
2724 
2725 int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
2726  enum ath6kl_host_mode host_mode)
2727 {
2728  struct sk_buff *skb;
2730  int ret;
2731 
2732  if ((host_mode != ATH6KL_HOST_MODE_ASLEEP) &&
2733  (host_mode != ATH6KL_HOST_MODE_AWAKE)) {
2734  ath6kl_err("invalid host sleep mode: %d\n", host_mode);
2735  return -EINVAL;
2736  }
2737 
2738  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2739  if (!skb)
2740  return -ENOMEM;
2741 
2742  cmd = (struct wmi_set_host_sleep_mode_cmd *) skb->data;
2743 
2744  if (host_mode == ATH6KL_HOST_MODE_ASLEEP) {
2745  ath6kl_wmi_relinquish_implicit_pstream_credits(wmi);
2746  cmd->asleep = cpu_to_le32(1);
2747  } else
2748  cmd->awake = cpu_to_le32(1);
2749 
2750  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
2752  NO_SYNC_WMIFLAG);
2753  return ret;
2754 }
2755 
2756 /* This command has zero length payload */
2757 static int ath6kl_wmi_host_sleep_mode_cmd_prcd_evt_rx(struct wmi *wmi,
2758  struct ath6kl_vif *vif)
2759 {
2760  struct ath6kl *ar = wmi->parent_dev;
2761 
2763  wake_up(&ar->event_wq);
2764 
2765  return 0;
2766 }
2767 
2768 int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
2769  enum ath6kl_wow_mode wow_mode,
2770  u32 filter, u16 host_req_delay)
2771 {
2772  struct sk_buff *skb;
2773  struct wmi_set_wow_mode_cmd *cmd;
2774  int ret;
2775 
2776  if ((wow_mode != ATH6KL_WOW_MODE_ENABLE) &&
2777  wow_mode != ATH6KL_WOW_MODE_DISABLE) {
2778  ath6kl_err("invalid wow mode: %d\n", wow_mode);
2779  return -EINVAL;
2780  }
2781 
2782  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2783  if (!skb)
2784  return -ENOMEM;
2785 
2786  cmd = (struct wmi_set_wow_mode_cmd *) skb->data;
2787  cmd->enable_wow = cpu_to_le32(wow_mode);
2788  cmd->filter = cpu_to_le32(filter);
2789  cmd->host_req_delay = cpu_to_le16(host_req_delay);
2790 
2791  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_WOW_MODE_CMDID,
2792  NO_SYNC_WMIFLAG);
2793  return ret;
2794 }
2795 
2796 int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
2797  u8 list_id, u8 filter_size,
2798  u8 filter_offset, const u8 *filter,
2799  const u8 *mask)
2800 {
2801  struct sk_buff *skb;
2802  struct wmi_add_wow_pattern_cmd *cmd;
2803  u16 size;
2804  u8 *filter_mask;
2805  int ret;
2806 
2807  /*
2808  * Allocate additional memory in the buffer to hold
2809  * filter and mask value, which is twice of filter_size.
2810  */
2811  size = sizeof(*cmd) + (2 * filter_size);
2812 
2813  skb = ath6kl_wmi_get_new_buf(size);
2814  if (!skb)
2815  return -ENOMEM;
2816 
2817  cmd = (struct wmi_add_wow_pattern_cmd *) skb->data;
2818  cmd->filter_list_id = list_id;
2819  cmd->filter_size = filter_size;
2820  cmd->filter_offset = filter_offset;
2821 
2822  memcpy(cmd->filter, filter, filter_size);
2823 
2824  filter_mask = (u8 *) (cmd->filter + filter_size);
2825  memcpy(filter_mask, mask, filter_size);
2826 
2827  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_ADD_WOW_PATTERN_CMDID,
2828  NO_SYNC_WMIFLAG);
2829 
2830  return ret;
2831 }
2832 
2833 int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
2834  u16 list_id, u16 filter_id)
2835 {
2836  struct sk_buff *skb;
2837  struct wmi_del_wow_pattern_cmd *cmd;
2838  int ret;
2839 
2840  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2841  if (!skb)
2842  return -ENOMEM;
2843 
2844  cmd = (struct wmi_del_wow_pattern_cmd *) skb->data;
2845  cmd->filter_list_id = cpu_to_le16(list_id);
2846  cmd->filter_id = cpu_to_le16(filter_id);
2847 
2848  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_DEL_WOW_PATTERN_CMDID,
2849  NO_SYNC_WMIFLAG);
2850  return ret;
2851 }
2852 
2853 static int ath6kl_wmi_cmd_send_xtnd(struct wmi *wmi, struct sk_buff *skb,
2854  enum wmix_command_id cmd_id,
2855  enum wmi_sync_flag sync_flag)
2856 {
2857  struct wmix_cmd_hdr *cmd_hdr;
2858  int ret;
2859 
2860  skb_push(skb, sizeof(struct wmix_cmd_hdr));
2861 
2862  cmd_hdr = (struct wmix_cmd_hdr *) skb->data;
2863  cmd_hdr->cmd_id = cpu_to_le32(cmd_id);
2864 
2865  ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_EXTENSION_CMDID, sync_flag);
2866 
2867  return ret;
2868 }
2869 
2871 {
2872  struct sk_buff *skb;
2874  int ret;
2875 
2876  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2877  if (!skb)
2878  return -ENOMEM;
2879 
2880  cmd = (struct wmix_hb_challenge_resp_cmd *) skb->data;
2881  cmd->cookie = cpu_to_le32(cookie);
2882  cmd->source = cpu_to_le32(source);
2883 
2884  ret = ath6kl_wmi_cmd_send_xtnd(wmi, skb, WMIX_HB_CHALLENGE_RESP_CMDID,
2885  NO_SYNC_WMIFLAG);
2886  return ret;
2887 }
2888 
2890 {
2892  struct sk_buff *skb;
2893  int ret;
2894 
2895  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2896  if (!skb)
2897  return -ENOMEM;
2898 
2899  cmd = (struct ath6kl_wmix_dbglog_cfg_module_cmd *) skb->data;
2900  cmd->valid = cpu_to_le32(valid);
2901  cmd->config = cpu_to_le32(config);
2902 
2903  ret = ath6kl_wmi_cmd_send_xtnd(wmi, skb, WMIX_DBGLOG_CFG_MODULE_CMDID,
2904  NO_SYNC_WMIFLAG);
2905  return ret;
2906 }
2907 
2908 int ath6kl_wmi_get_stats_cmd(struct wmi *wmi, u8 if_idx)
2909 {
2910  return ath6kl_wmi_simple_cmd(wmi, if_idx, WMI_GET_STATISTICS_CMDID);
2911 }
2912 
2913 int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 if_idx, u8 dbM)
2914 {
2915  struct sk_buff *skb;
2916  struct wmi_set_tx_pwr_cmd *cmd;
2917  int ret;
2918 
2919  skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_tx_pwr_cmd));
2920  if (!skb)
2921  return -ENOMEM;
2922 
2923  cmd = (struct wmi_set_tx_pwr_cmd *) skb->data;
2924  cmd->dbM = dbM;
2925 
2926  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_TX_PWR_CMDID,
2927  NO_SYNC_WMIFLAG);
2928 
2929  return ret;
2930 }
2931 
2932 int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi, u8 if_idx)
2933 {
2934  return ath6kl_wmi_simple_cmd(wmi, if_idx, WMI_GET_TX_PWR_CMDID);
2935 }
2936 
2937 int ath6kl_wmi_get_roam_tbl_cmd(struct wmi *wmi)
2938 {
2939  return ath6kl_wmi_simple_cmd(wmi, 0, WMI_GET_ROAM_TBL_CMDID);
2940 }
2941 
2942 int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 if_idx, u8 status,
2943  u8 preamble_policy)
2944 {
2945  struct sk_buff *skb;
2946  struct wmi_set_lpreamble_cmd *cmd;
2947  int ret;
2948 
2949  skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_lpreamble_cmd));
2950  if (!skb)
2951  return -ENOMEM;
2952 
2953  cmd = (struct wmi_set_lpreamble_cmd *) skb->data;
2954  cmd->status = status;
2955  cmd->preamble_policy = preamble_policy;
2956 
2957  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_LPREAMBLE_CMDID,
2958  NO_SYNC_WMIFLAG);
2959  return ret;
2960 }
2961 
2962 int ath6kl_wmi_set_rts_cmd(struct wmi *wmi, u16 threshold)
2963 {
2964  struct sk_buff *skb;
2965  struct wmi_set_rts_cmd *cmd;
2966  int ret;
2967 
2968  skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_rts_cmd));
2969  if (!skb)
2970  return -ENOMEM;
2971 
2972  cmd = (struct wmi_set_rts_cmd *) skb->data;
2973  cmd->threshold = cpu_to_le16(threshold);
2974 
2975  ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_RTS_CMDID,
2976  NO_SYNC_WMIFLAG);
2977  return ret;
2978 }
2979 
2980 int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, u8 if_idx, enum wmi_txop_cfg cfg)
2981 {
2982  struct sk_buff *skb;
2983  struct wmi_set_wmm_txop_cmd *cmd;
2984  int ret;
2985 
2986  if (!((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)))
2987  return -EINVAL;
2988 
2989  skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_wmm_txop_cmd));
2990  if (!skb)
2991  return -ENOMEM;
2992 
2993  cmd = (struct wmi_set_wmm_txop_cmd *) skb->data;
2994  cmd->txop_enable = cfg;
2995 
2996  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_WMM_TXOP_CMDID,
2997  NO_SYNC_WMIFLAG);
2998  return ret;
2999 }
3000 
3001 int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx,
3002  u8 keep_alive_intvl)
3003 {
3004  struct sk_buff *skb;
3005  struct wmi_set_keepalive_cmd *cmd;
3006  int ret;
3007 
3008  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
3009  if (!skb)
3010  return -ENOMEM;
3011 
3012  cmd = (struct wmi_set_keepalive_cmd *) skb->data;
3013  cmd->keep_alive_intvl = keep_alive_intvl;
3014 
3015  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_KEEPALIVE_CMDID,
3016  NO_SYNC_WMIFLAG);
3017 
3018  if (ret == 0)
3019  ath6kl_debug_set_keepalive(wmi->parent_dev, keep_alive_intvl);
3020 
3021  return ret;
3022 }
3023 
3024 int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx,
3025  enum ieee80211_band band,
3026  struct ath6kl_htcap *htcap)
3027 {
3028  struct sk_buff *skb;
3029  struct wmi_set_htcap_cmd *cmd;
3030 
3031  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
3032  if (!skb)
3033  return -ENOMEM;
3034 
3035  cmd = (struct wmi_set_htcap_cmd *) skb->data;
3036 
3037  /*
3038  * NOTE: Band in firmware matches enum ieee80211_band, it is unlikely
3039  * this will be changed in firmware. If at all there is any change in
3040  * band value, the host needs to be fixed.
3041  */
3042  cmd->band = band;
3043  cmd->ht_enable = !!htcap->ht_enable;
3044  cmd->ht20_sgi = !!(htcap->cap_info & IEEE80211_HT_CAP_SGI_20);
3045  cmd->ht40_supported =
3047  cmd->ht40_sgi = !!(htcap->cap_info & IEEE80211_HT_CAP_SGI_40);
3048  cmd->intolerant_40mhz =
3050  cmd->max_ampdu_len_exp = htcap->ampdu_factor;
3051 
3052  ath6kl_dbg(ATH6KL_DBG_WMI,
3053  "Set htcap: band:%d ht_enable:%d 40mhz:%d sgi_20mhz:%d sgi_40mhz:%d 40mhz_intolerant:%d ampdu_len_exp:%d\n",
3054  cmd->band, cmd->ht_enable, cmd->ht40_supported,
3055  cmd->ht20_sgi, cmd->ht40_sgi, cmd->intolerant_40mhz,
3056  cmd->max_ampdu_len_exp);
3057  return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_HT_CAP_CMDID,
3058  NO_SYNC_WMIFLAG);
3059 }
3060 
3061 int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len)
3062 {
3063  struct sk_buff *skb;
3064  int ret;
3065 
3066  skb = ath6kl_wmi_get_new_buf(len);
3067  if (!skb)
3068  return -ENOMEM;
3069 
3070  memcpy(skb->data, buf, len);
3071 
3072  ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_TEST_CMDID, NO_SYNC_WMIFLAG);
3073 
3074  return ret;
3075 }
3076 
3077 int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on)
3078 {
3079  struct sk_buff *skb;
3080  struct wmi_mcast_filter_cmd *cmd;
3081  int ret;
3082 
3083  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
3084  if (!skb)
3085  return -ENOMEM;
3086 
3087  cmd = (struct wmi_mcast_filter_cmd *) skb->data;
3088  cmd->mcast_all_enable = mc_all_on;
3089 
3090  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_MCAST_FILTER_CMDID,
3091  NO_SYNC_WMIFLAG);
3092  return ret;
3093 }
3094 
3095 int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
3096  u8 *filter, bool add_filter)
3097 {
3098  struct sk_buff *skb;
3100  int ret;
3101 
3102  if ((filter[0] != 0x33 || filter[1] != 0x33) &&
3103  (filter[0] != 0x01 || filter[1] != 0x00 ||
3104  filter[2] != 0x5e || filter[3] > 0x7f)) {
3105  ath6kl_warn("invalid multicast filter address\n");
3106  return -EINVAL;
3107  }
3108 
3109  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
3110  if (!skb)
3111  return -ENOMEM;
3112 
3113  cmd = (struct wmi_mcast_filter_add_del_cmd *) skb->data;
3115  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
3116  add_filter ? WMI_SET_MCAST_FILTER_CMDID :
3118  NO_SYNC_WMIFLAG);
3119 
3120  return ret;
3121 }
3122 
3123 int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enhance)
3124 {
3125  struct sk_buff *skb;
3127  int ret;
3128 
3129  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
3130  if (!skb)
3131  return -ENOMEM;
3132 
3133  cmd = (struct wmi_sta_bmiss_enhance_cmd *) skb->data;
3134  cmd->enable = enhance ? 1 : 0;
3135 
3136  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
3138  NO_SYNC_WMIFLAG);
3139  return ret;
3140 }
3141 
3143 {
3144  if (rate_index == RATE_AUTO)
3145  return 0;
3146 
3147  return wmi_rate_tbl[(u32) rate_index][0];
3148 }
3149 
3150 static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,
3151  u32 len)
3152 {
3153  struct wmi_pmkid_list_reply *reply;
3154  u32 expected_len;
3155 
3156  if (len < sizeof(struct wmi_pmkid_list_reply))
3157  return -EINVAL;
3158 
3159  reply = (struct wmi_pmkid_list_reply *)datap;
3160  expected_len = sizeof(reply->num_pmkid) +
3162 
3163  if (len < expected_len)
3164  return -EINVAL;
3165 
3166  return 0;
3167 }
3168 
3169 static int ath6kl_wmi_addba_req_event_rx(struct wmi *wmi, u8 *datap, int len,
3170  struct ath6kl_vif *vif)
3171 {
3172  struct wmi_addba_req_event *cmd = (struct wmi_addba_req_event *) datap;
3173 
3174  aggr_recv_addba_req_evt(vif, cmd->tid,
3175  le16_to_cpu(cmd->st_seq_no), cmd->win_sz);
3176 
3177  return 0;
3178 }
3179 
3180 static int ath6kl_wmi_delba_req_event_rx(struct wmi *wmi, u8 *datap, int len,
3181  struct ath6kl_vif *vif)
3182 {
3183  struct wmi_delba_event *cmd = (struct wmi_delba_event *) datap;
3184 
3185  aggr_recv_delba_req_evt(vif, cmd->tid);
3186 
3187  return 0;
3188 }
3189 
3190 /* AP mode functions */
3191 
3192 int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx,
3193  struct wmi_connect_cmd *p)
3194 {
3195  struct sk_buff *skb;
3196  struct wmi_connect_cmd *cm;
3197  int res;
3198 
3199  skb = ath6kl_wmi_get_new_buf(sizeof(*cm));
3200  if (!skb)
3201  return -ENOMEM;
3202 
3203  cm = (struct wmi_connect_cmd *) skb->data;
3204  memcpy(cm, p, sizeof(*cm));
3205 
3206  res = ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_CONFIG_COMMIT_CMDID,
3207  NO_SYNC_WMIFLAG);
3208  ath6kl_dbg(ATH6KL_DBG_WMI,
3209  "%s: nw_type=%u auth_mode=%u ch=%u ctrl_flags=0x%x-> res=%d\n",
3210  __func__, p->nw_type, p->auth_mode, le16_to_cpu(p->ch),
3211  le32_to_cpu(p->ctrl_flags), res);
3212  return res;
3213 }
3214 
3215 int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 if_idx, u8 cmd, const u8 *mac,
3216  u16 reason)
3217 {
3218  struct sk_buff *skb;
3219  struct wmi_ap_set_mlme_cmd *cm;
3220 
3221  skb = ath6kl_wmi_get_new_buf(sizeof(*cm));
3222  if (!skb)
3223  return -ENOMEM;
3224 
3225  cm = (struct wmi_ap_set_mlme_cmd *) skb->data;
3226  memcpy(cm->mac, mac, ETH_ALEN);
3227  cm->reason = cpu_to_le16(reason);
3228  cm->cmd = cmd;
3229 
3230  ath6kl_dbg(ATH6KL_DBG_WMI, "ap_set_mlme: cmd=%d reason=%d\n", cm->cmd,
3231  cm->reason);
3232 
3233  return ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_SET_MLME_CMDID,
3234  NO_SYNC_WMIFLAG);
3235 }
3236 
3237 int ath6kl_wmi_ap_hidden_ssid(struct wmi *wmi, u8 if_idx, bool enable)
3238 {
3239  struct sk_buff *skb;
3240  struct wmi_ap_hidden_ssid_cmd *cmd;
3241 
3242  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
3243  if (!skb)
3244  return -ENOMEM;
3245 
3246  cmd = (struct wmi_ap_hidden_ssid_cmd *) skb->data;
3247  cmd->hidden_ssid = enable ? 1 : 0;
3248 
3249  return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_AP_HIDDEN_SSID_CMDID,
3250  NO_SYNC_WMIFLAG);
3251 }
3252 
3253 /* This command will be used to enable/disable AP uAPSD feature */
3254 int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable)
3255 {
3256  struct wmi_ap_set_apsd_cmd *cmd;
3257  struct sk_buff *skb;
3258 
3259  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
3260  if (!skb)
3261  return -ENOMEM;
3262 
3263  cmd = (struct wmi_ap_set_apsd_cmd *)skb->data;
3264  cmd->enable = enable;
3265 
3266  return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_AP_SET_APSD_CMDID,
3267  NO_SYNC_WMIFLAG);
3268 }
3269 
3270 int ath6kl_wmi_set_apsd_bfrd_traf(struct wmi *wmi, u8 if_idx,
3271  u16 aid, u16 bitmap, u32 flags)
3272 {
3274  struct sk_buff *skb;
3275 
3276  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
3277  if (!skb)
3278  return -ENOMEM;
3279 
3280  cmd = (struct wmi_ap_apsd_buffered_traffic_cmd *)skb->data;
3281  cmd->aid = cpu_to_le16(aid);
3282  cmd->bitmap = cpu_to_le16(bitmap);
3283  cmd->flags = cpu_to_le32(flags);
3284 
3285  return ath6kl_wmi_cmd_send(wmi, if_idx, skb,
3287  NO_SYNC_WMIFLAG);
3288 }
3289 
3290 static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len,
3291  struct ath6kl_vif *vif)
3292 {
3293  struct wmi_pspoll_event *ev;
3294 
3295  if (len < sizeof(struct wmi_pspoll_event))
3296  return -EINVAL;
3297 
3298  ev = (struct wmi_pspoll_event *) datap;
3299 
3300  ath6kl_pspoll_event(vif, le16_to_cpu(ev->aid));
3301 
3302  return 0;
3303 }
3304 
3305 static int ath6kl_wmi_dtimexpiry_event_rx(struct wmi *wmi, u8 *datap, int len,
3306  struct ath6kl_vif *vif)
3307 {
3309 
3310  return 0;
3311 }
3312 
3313 int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u8 if_idx, u16 aid,
3314  bool flag)
3315 {
3316  struct sk_buff *skb;
3317  struct wmi_ap_set_pvb_cmd *cmd;
3318  int ret;
3319 
3320  skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_ap_set_pvb_cmd));
3321  if (!skb)
3322  return -ENOMEM;
3323 
3324  cmd = (struct wmi_ap_set_pvb_cmd *) skb->data;
3325  cmd->aid = cpu_to_le16(aid);
3326  cmd->rsvd = cpu_to_le16(0);
3327  cmd->flag = cpu_to_le32(flag);
3328 
3329  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_AP_SET_PVB_CMDID,
3330  NO_SYNC_WMIFLAG);
3331 
3332  return 0;
3333 }
3334 
3335 int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 if_idx,
3336  u8 rx_meta_ver,
3337  bool rx_dot11_hdr, bool defrag_on_host)
3338 {
3339  struct sk_buff *skb;
3340  struct wmi_rx_frame_format_cmd *cmd;
3341  int ret;
3342 
3343  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
3344  if (!skb)
3345  return -ENOMEM;
3346 
3347  cmd = (struct wmi_rx_frame_format_cmd *) skb->data;
3348  cmd->dot11_hdr = rx_dot11_hdr ? 1 : 0;
3349  cmd->defrag_on_host = defrag_on_host ? 1 : 0;
3350  cmd->meta_ver = rx_meta_ver;
3351 
3352  /* Delete the local aggr state, on host */
3353  ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_RX_FRAME_FORMAT_CMDID,
3354  NO_SYNC_WMIFLAG);
3355 
3356  return ret;
3357 }
3358 
3359 int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type,
3360  const u8 *ie, u8 ie_len)
3361 {
3362  struct sk_buff *skb;
3363  struct wmi_set_appie_cmd *p;
3364 
3365  skb = ath6kl_wmi_get_new_buf(sizeof(*p) + ie_len);
3366  if (!skb)
3367  return -ENOMEM;
3368 
3369  ath6kl_dbg(ATH6KL_DBG_WMI,
3370  "set_appie_cmd: mgmt_frm_type=%u ie_len=%u\n",
3371  mgmt_frm_type, ie_len);
3372  p = (struct wmi_set_appie_cmd *) skb->data;
3373  p->mgmt_frm_type = mgmt_frm_type;
3374  p->ie_len = ie_len;
3375 
3376  if (ie != NULL && ie_len > 0)
3377  memcpy(p->ie_info, ie, ie_len);
3378 
3379  return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_APPIE_CMDID,
3380  NO_SYNC_WMIFLAG);
3381 }
3382 
3383 int ath6kl_wmi_set_ie_cmd(struct wmi *wmi, u8 if_idx, u8 ie_id, u8 ie_field,
3384  const u8 *ie_info, u8 ie_len)
3385 {
3386  struct sk_buff *skb;
3387  struct wmi_set_ie_cmd *p;
3388 
3389  skb = ath6kl_wmi_get_new_buf(sizeof(*p) + ie_len);
3390  if (!skb)
3391  return -ENOMEM;
3392 
3393  ath6kl_dbg(ATH6KL_DBG_WMI, "set_ie_cmd: ie_id=%u ie_ie_field=%u ie_len=%u\n",
3394  ie_id, ie_field, ie_len);
3395  p = (struct wmi_set_ie_cmd *) skb->data;
3396  p->ie_id = ie_id;
3397  p->ie_field = ie_field;
3398  p->ie_len = ie_len;
3399  if (ie_info && ie_len > 0)
3400  memcpy(p->ie_info, ie_info, ie_len);
3401 
3402  return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_IE_CMDID,
3403  NO_SYNC_WMIFLAG);
3404 }
3405 
3406 int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable)
3407 {
3408  struct sk_buff *skb;
3410 
3411  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
3412  if (!skb)
3413  return -ENOMEM;
3414 
3415  ath6kl_dbg(ATH6KL_DBG_WMI, "disable_11b_rates_cmd: disable=%u\n",
3416  disable);
3417  cmd = (struct wmi_disable_11b_rates_cmd *) skb->data;
3418  cmd->disable = disable ? 1 : 0;
3419 
3421  NO_SYNC_WMIFLAG);
3422 }
3423 
3424 int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx, u32 freq, u32 dur)
3425 {
3426  struct sk_buff *skb;
3427  struct wmi_remain_on_chnl_cmd *p;
3428 
3429  skb = ath6kl_wmi_get_new_buf(sizeof(*p));
3430  if (!skb)
3431  return -ENOMEM;
3432 
3433  ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl_cmd: freq=%u dur=%u\n",
3434  freq, dur);
3435  p = (struct wmi_remain_on_chnl_cmd *) skb->data;
3436  p->freq = cpu_to_le32(freq);
3437  p->duration = cpu_to_le32(dur);
3438  return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_REMAIN_ON_CHNL_CMDID,
3439  NO_SYNC_WMIFLAG);
3440 }
3441 
3442 /* ath6kl_wmi_send_action_cmd is to be deprecated. Use
3443  * ath6kl_wmi_send_mgmt_cmd instead. The new function supports P2P
3444  * mgmt operations using station interface.
3445  */
3446 static int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id,
3447  u32 freq, u32 wait, const u8 *data,
3448  u16 data_len)
3449 {
3450  struct sk_buff *skb;
3451  struct wmi_send_action_cmd *p;
3452  u8 *buf;
3453 
3454  if (wait)
3455  return -EINVAL; /* Offload for wait not supported */
3456 
3457  buf = kmalloc(data_len, GFP_KERNEL);
3458  if (!buf)
3459  return -ENOMEM;
3460 
3461  skb = ath6kl_wmi_get_new_buf(sizeof(*p) + data_len);
3462  if (!skb) {
3463  kfree(buf);
3464  return -ENOMEM;
3465  }
3466 
3467  kfree(wmi->last_mgmt_tx_frame);
3468  memcpy(buf, data, data_len);
3469  wmi->last_mgmt_tx_frame = buf;
3471 
3472  ath6kl_dbg(ATH6KL_DBG_WMI,
3473  "send_action_cmd: id=%u freq=%u wait=%u len=%u\n",
3474  id, freq, wait, data_len);
3475  p = (struct wmi_send_action_cmd *) skb->data;
3476  p->id = cpu_to_le32(id);
3477  p->freq = cpu_to_le32(freq);
3478  p->wait = cpu_to_le32(wait);
3479  p->len = cpu_to_le16(data_len);
3480  memcpy(p->data, data, data_len);
3481  return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SEND_ACTION_CMDID,
3482  NO_SYNC_WMIFLAG);
3483 }
3484 
3485 static int __ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id,
3486  u32 freq, u32 wait, const u8 *data,
3487  u16 data_len, u32 no_cck)
3488 {
3489  struct sk_buff *skb;
3490  struct wmi_send_mgmt_cmd *p;
3491  u8 *buf;
3492 
3493  if (wait)
3494  return -EINVAL; /* Offload for wait not supported */
3495 
3496  buf = kmalloc(data_len, GFP_KERNEL);
3497  if (!buf)
3498  return -ENOMEM;
3499 
3500  skb = ath6kl_wmi_get_new_buf(sizeof(*p) + data_len);
3501  if (!skb) {
3502  kfree(buf);
3503  return -ENOMEM;
3504  }
3505 
3506  kfree(wmi->last_mgmt_tx_frame);
3507  memcpy(buf, data, data_len);
3508  wmi->last_mgmt_tx_frame = buf;
3510 
3511  ath6kl_dbg(ATH6KL_DBG_WMI,
3512  "send_action_cmd: id=%u freq=%u wait=%u len=%u\n",
3513  id, freq, wait, data_len);
3514  p = (struct wmi_send_mgmt_cmd *) skb->data;
3515  p->id = cpu_to_le32(id);
3516  p->freq = cpu_to_le32(freq);
3517  p->wait = cpu_to_le32(wait);
3518  p->no_cck = cpu_to_le32(no_cck);
3519  p->len = cpu_to_le16(data_len);
3520  memcpy(p->data, data, data_len);
3521  return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SEND_MGMT_CMDID,
3522  NO_SYNC_WMIFLAG);
3523 }
3524 
3525 int ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
3526  u32 wait, const u8 *data, u16 data_len,
3527  u32 no_cck)
3528 {
3529  int status;
3530  struct ath6kl *ar = wmi->parent_dev;
3531 
3533  ar->fw_capabilities)) {
3534  /*
3535  * If capable of doing P2P mgmt operations using
3536  * station interface, send additional information like
3537  * supported rates to advertise and xmit rates for
3538  * probe requests
3539  */
3540  status = __ath6kl_wmi_send_mgmt_cmd(ar->wmi, if_idx, id, freq,
3541  wait, data, data_len,
3542  no_cck);
3543  } else {
3544  status = ath6kl_wmi_send_action_cmd(ar->wmi, if_idx, id, freq,
3545  wait, data, data_len);
3546  }
3547 
3548  return status;
3549 }
3550 
3551 int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq,
3552  const u8 *dst, const u8 *data,
3553  u16 data_len)
3554 {
3555  struct sk_buff *skb;
3556  struct wmi_p2p_probe_response_cmd *p;
3557  size_t cmd_len = sizeof(*p) + data_len;
3558 
3559  if (data_len == 0)
3560  cmd_len++; /* work around target minimum length requirement */
3561 
3562  skb = ath6kl_wmi_get_new_buf(cmd_len);
3563  if (!skb)
3564  return -ENOMEM;
3565 
3566  ath6kl_dbg(ATH6KL_DBG_WMI,
3567  "send_probe_response_cmd: freq=%u dst=%pM len=%u\n",
3568  freq, dst, data_len);
3569  p = (struct wmi_p2p_probe_response_cmd *) skb->data;
3570  p->freq = cpu_to_le32(freq);
3571  memcpy(p->destination_addr, dst, ETH_ALEN);
3572  p->len = cpu_to_le16(data_len);
3573  memcpy(p->data, data, data_len);
3574  return ath6kl_wmi_cmd_send(wmi, if_idx, skb,
3576  NO_SYNC_WMIFLAG);
3577 }
3578 
3579 int ath6kl_wmi_probe_report_req_cmd(struct wmi *wmi, u8 if_idx, bool enable)
3580 {
3581  struct sk_buff *skb;
3582  struct wmi_probe_req_report_cmd *p;
3583 
3584  skb = ath6kl_wmi_get_new_buf(sizeof(*p));
3585  if (!skb)
3586  return -ENOMEM;
3587 
3588  ath6kl_dbg(ATH6KL_DBG_WMI, "probe_report_req_cmd: enable=%u\n",
3589  enable);
3590  p = (struct wmi_probe_req_report_cmd *) skb->data;
3591  p->enable = enable ? 1 : 0;
3592  return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_PROBE_REQ_REPORT_CMDID,
3593  NO_SYNC_WMIFLAG);
3594 }
3595 
3596 int ath6kl_wmi_info_req_cmd(struct wmi *wmi, u8 if_idx, u32 info_req_flags)
3597 {
3598  struct sk_buff *skb;
3599  struct wmi_get_p2p_info *p;
3600 
3601  skb = ath6kl_wmi_get_new_buf(sizeof(*p));
3602  if (!skb)
3603  return -ENOMEM;
3604 
3605  ath6kl_dbg(ATH6KL_DBG_WMI, "info_req_cmd: flags=%x\n",
3606  info_req_flags);
3607  p = (struct wmi_get_p2p_info *) skb->data;
3608  p->info_req_flags = cpu_to_le32(info_req_flags);
3609  return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_GET_P2P_INFO_CMDID,
3610  NO_SYNC_WMIFLAG);
3611 }
3612 
3613 int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx)
3614 {
3615  ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl_cmd\n");
3616  return ath6kl_wmi_simple_cmd(wmi, if_idx,
3618 }
3619 
3620 int ath6kl_wmi_set_inact_period(struct wmi *wmi, u8 if_idx, int inact_timeout)
3621 {
3622  struct sk_buff *skb;
3623  struct wmi_set_inact_period_cmd *cmd;
3624 
3625  skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
3626  if (!skb)
3627  return -ENOMEM;
3628 
3629  cmd = (struct wmi_set_inact_period_cmd *) skb->data;
3630  cmd->inact_period = cpu_to_le32(inact_timeout);
3631  cmd->num_null_func = 0;
3632 
3633  return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_AP_CONN_INACT_CMDID,
3634  NO_SYNC_WMIFLAG);
3635 }
3636 
3637 static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
3638 {
3639  struct wmix_cmd_hdr *cmd;
3640  u32 len;
3641  u16 id;
3642  u8 *datap;
3643  int ret = 0;
3644 
3645  if (skb->len < sizeof(struct wmix_cmd_hdr)) {
3646  ath6kl_err("bad packet 1\n");
3647  return -EINVAL;
3648  }
3649 
3650  cmd = (struct wmix_cmd_hdr *) skb->data;
3651  id = le32_to_cpu(cmd->cmd_id);
3652 
3653  skb_pull(skb, sizeof(struct wmix_cmd_hdr));
3654 
3655  datap = skb->data;
3656  len = skb->len;
3657 
3658  switch (id) {
3660  ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event hb challenge resp\n");
3661  break;
3662  case WMIX_DBGLOG_EVENTID:
3663  ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event dbglog len %d\n", len);
3664  ath6kl_debug_fwlog_event(wmi->parent_dev, datap, len);
3665  break;
3666  default:
3667  ath6kl_warn("unknown cmd id 0x%x\n", id);
3668  ret = -EINVAL;
3669  break;
3670  }
3671 
3672  return ret;
3673 }
3674 
3675 static int ath6kl_wmi_roam_tbl_event_rx(struct wmi *wmi, u8 *datap, int len)
3676 {
3677  return ath6kl_debug_roam_tbl_event(wmi->parent_dev, datap, len);
3678 }
3679 
3680 /* Process interface specific wmi events, caller would free the datap */
3681 static int ath6kl_wmi_proc_events_vif(struct wmi *wmi, u16 if_idx, u16 cmd_id,
3682  u8 *datap, u32 len)
3683 {
3684  struct ath6kl_vif *vif;
3685 
3686  vif = ath6kl_get_vif_by_index(wmi->parent_dev, if_idx);
3687  if (!vif) {
3688  ath6kl_dbg(ATH6KL_DBG_WMI,
3689  "Wmi event for unavailable vif, vif_index:%d\n",
3690  if_idx);
3691  return -EINVAL;
3692  }
3693 
3694  switch (cmd_id) {
3695  case WMI_CONNECT_EVENTID:
3696  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CONNECT_EVENTID\n");
3697  return ath6kl_wmi_connect_event_rx(wmi, datap, len, vif);
3699  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DISCONNECT_EVENTID\n");
3700  return ath6kl_wmi_disconnect_event_rx(wmi, datap, len, vif);
3702  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TKIP_MICERR_EVENTID\n");
3703  return ath6kl_wmi_tkip_micerr_event_rx(wmi, datap, len, vif);
3704  case WMI_BSSINFO_EVENTID:
3705  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_BSSINFO_EVENTID\n");
3706  return ath6kl_wmi_bssinfo_event_rx(wmi, datap, len, vif);
3708  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_NEIGHBOR_REPORT_EVENTID\n");
3709  return ath6kl_wmi_neighbor_report_event_rx(wmi, datap, len,
3710  vif);
3712  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SCAN_COMPLETE_EVENTID\n");
3713  return ath6kl_wmi_scan_complete_rx(wmi, datap, len, vif);
3715  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_STATISTICS_EVENTID\n");
3716  return ath6kl_wmi_stats_event_rx(wmi, datap, len, vif);
3717  case WMI_CAC_EVENTID:
3718  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CAC_EVENTID\n");
3719  return ath6kl_wmi_cac_event_rx(wmi, datap, len, vif);
3720  case WMI_PSPOLL_EVENTID:
3721  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSPOLL_EVENTID\n");
3722  return ath6kl_wmi_pspoll_event_rx(wmi, datap, len, vif);
3724  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DTIMEXPIRY_EVENTID\n");
3725  return ath6kl_wmi_dtimexpiry_event_rx(wmi, datap, len, vif);
3726  case WMI_ADDBA_REQ_EVENTID:
3727  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_REQ_EVENTID\n");
3728  return ath6kl_wmi_addba_req_event_rx(wmi, datap, len, vif);
3729  case WMI_DELBA_REQ_EVENTID:
3730  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DELBA_REQ_EVENTID\n");
3731  return ath6kl_wmi_delba_req_event_rx(wmi, datap, len, vif);
3733  ath6kl_dbg(ATH6KL_DBG_WMI,
3734  "WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID");
3735  return ath6kl_wmi_host_sleep_mode_cmd_prcd_evt_rx(wmi, vif);
3737  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n");
3738  return ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len, vif);
3740  ath6kl_dbg(ATH6KL_DBG_WMI,
3741  "WMI_CANCEL_REMAIN_ON_CHNL_EVENTID\n");
3742  return ath6kl_wmi_cancel_remain_on_chnl_event_rx(wmi, datap,
3743  len, vif);
3744  case WMI_TX_STATUS_EVENTID:
3745  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_STATUS_EVENTID\n");
3746  return ath6kl_wmi_tx_status_event_rx(wmi, datap, len, vif);
3748  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_PROBE_REQ_EVENTID\n");
3749  return ath6kl_wmi_rx_probe_req_event_rx(wmi, datap, len, vif);
3750  case WMI_RX_ACTION_EVENTID:
3751  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_ACTION_EVENTID\n");
3752  return ath6kl_wmi_rx_action_event_rx(wmi, datap, len, vif);
3753  default:
3754  ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", cmd_id);
3755  return -EINVAL;
3756  }
3757 
3758  return 0;
3759 }
3760 
3761 static int ath6kl_wmi_proc_events(struct wmi *wmi, struct sk_buff *skb)
3762 {
3763  struct wmi_cmd_hdr *cmd;
3764  int ret = 0;
3765  u32 len;
3766  u16 id;
3767  u8 if_idx;
3768  u8 *datap;
3769 
3770  cmd = (struct wmi_cmd_hdr *) skb->data;
3771  id = le16_to_cpu(cmd->cmd_id);
3772  if_idx = le16_to_cpu(cmd->info1) & WMI_CMD_HDR_IF_ID_MASK;
3773 
3774  skb_pull(skb, sizeof(struct wmi_cmd_hdr));
3775  datap = skb->data;
3776  len = skb->len;
3777 
3778  ath6kl_dbg(ATH6KL_DBG_WMI, "wmi rx id %d len %d\n", id, len);
3779  ath6kl_dbg_dump(ATH6KL_DBG_WMI_DUMP, NULL, "wmi rx ",
3780  datap, len);
3781 
3782  switch (id) {
3783  case WMI_GET_BITRATE_CMDID:
3784  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_BITRATE_CMDID\n");
3785  ret = ath6kl_wmi_bitrate_reply_rx(wmi, datap, len);
3786  break;
3788  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_CHANNEL_LIST_CMDID\n");
3789  ret = ath6kl_wmi_ch_list_reply_rx(wmi, datap, len);
3790  break;
3791  case WMI_GET_TX_PWR_CMDID:
3792  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_TX_PWR_CMDID\n");
3793  ret = ath6kl_wmi_tx_pwr_reply_rx(wmi, datap, len);
3794  break;
3795  case WMI_READY_EVENTID:
3796  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_READY_EVENTID\n");
3797  ret = ath6kl_wmi_ready_event_rx(wmi, datap, len);
3798  break;
3799  case WMI_PEER_NODE_EVENTID:
3800  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PEER_NODE_EVENTID\n");
3801  ret = ath6kl_wmi_peer_node_event_rx(wmi, datap, len);
3802  break;
3803  case WMI_REGDOMAIN_EVENTID:
3804  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REGDOMAIN_EVENTID\n");
3805  ath6kl_wmi_regdomain_event(wmi, datap, len);
3806  break;
3808  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSTREAM_TIMEOUT_EVENTID\n");
3809  ret = ath6kl_wmi_pstream_timeout_event_rx(wmi, datap, len);
3810  break;
3811  case WMI_CMDERROR_EVENTID:
3812  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CMDERROR_EVENTID\n");
3813  ret = ath6kl_wmi_error_event_rx(wmi, datap, len);
3814  break;
3816  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RSSI_THRESHOLD_EVENTID\n");
3817  ret = ath6kl_wmi_rssi_threshold_event_rx(wmi, datap, len);
3818  break;
3820  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ERROR_REPORT_EVENTID\n");
3821  break;
3823  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_OPT_RX_FRAME_EVENTID\n");
3824  /* this event has been deprecated */
3825  break;
3827  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_TBL_EVENTID\n");
3828  ret = ath6kl_wmi_roam_tbl_event_rx(wmi, datap, len);
3829  break;
3830  case WMI_EXTENSION_EVENTID:
3831  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_EXTENSION_EVENTID\n");
3832  ret = ath6kl_wmi_control_rx_xtnd(wmi, skb);
3833  break;
3835  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CHANNEL_CHANGE_EVENTID\n");
3836  break;
3838  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_DATA_EVENTID\n");
3839  break;
3840  case WMI_TEST_EVENTID:
3841  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TEST_EVENTID\n");
3842  ret = ath6kl_wmi_test_rx(wmi, datap, len);
3843  break;
3845  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_FIXRATES_CMDID\n");
3846  ret = ath6kl_wmi_ratemask_reply_rx(wmi, datap, len);
3847  break;
3849  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_RETRY_ERR_EVENTID\n");
3850  break;
3852  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SNR_THRESHOLD_EVENTID\n");
3853  ret = ath6kl_wmi_snr_threshold_event_rx(wmi, datap, len);
3854  break;
3856  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_LQ_THRESHOLD_EVENTID\n");
3857  break;
3858  case WMI_APLIST_EVENTID:
3859  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_APLIST_EVENTID\n");
3860  ret = ath6kl_wmi_aplist_event_rx(wmi, datap, len);
3861  break;
3863  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_KEEPALIVE_CMDID\n");
3864  ret = ath6kl_wmi_keepalive_reply_rx(wmi, datap, len);
3865  break;
3867  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_WOW_LIST_EVENTID\n");
3868  break;
3870  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_PMKID_LIST_EVENTID\n");
3871  ret = ath6kl_wmi_get_pmkid_list_event_rx(wmi, datap, len);
3872  break;
3874  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SET_PARAMS_REPLY_EVENTID\n");
3875  break;
3877  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_RESP_EVENTID\n");
3878  break;
3880  ath6kl_dbg(ATH6KL_DBG_WMI,
3881  "WMI_REPORT_BTCOEX_CONFIG_EVENTID\n");
3882  break;
3884  ath6kl_dbg(ATH6KL_DBG_WMI,
3885  "WMI_REPORT_BTCOEX_STATS_EVENTID\n");
3886  break;
3888  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n");
3889  ret = ath6kl_wmi_tx_complete_event_rx(datap, len);
3890  break;
3892  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_CAPABILITIES_EVENTID\n");
3893  ret = ath6kl_wmi_p2p_capabilities_event_rx(datap, len);
3894  break;
3895  case WMI_P2P_INFO_EVENTID:
3896  ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_INFO_EVENTID\n");
3897  ret = ath6kl_wmi_p2p_info_event_rx(datap, len);
3898  break;
3899  default:
3900  /* may be the event is interface specific */
3901  ret = ath6kl_wmi_proc_events_vif(wmi, if_idx, id, datap, len);
3902  break;
3903  }
3904 
3905  dev_kfree_skb(skb);
3906  return ret;
3907 }
3908 
3909 /* Control Path */
3910 int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
3911 {
3912  if (WARN_ON(skb == NULL))
3913  return -EINVAL;
3914 
3915  if (skb->len < sizeof(struct wmi_cmd_hdr)) {
3916  ath6kl_err("bad packet 1\n");
3917  dev_kfree_skb(skb);
3918  return -EINVAL;
3919  }
3920 
3921  return ath6kl_wmi_proc_events(wmi, skb);
3922 }
3923 
3924 void ath6kl_wmi_reset(struct wmi *wmi)
3925 {
3926  spin_lock_bh(&wmi->lock);
3927 
3928  wmi->fat_pipe_exist = 0;
3929  memset(wmi->stream_exist_for_ac, 0, sizeof(wmi->stream_exist_for_ac));
3930 
3931  spin_unlock_bh(&wmi->lock);
3932 }
3933 
3934 void *ath6kl_wmi_init(struct ath6kl *dev)
3935 {
3936  struct wmi *wmi;
3937 
3938  wmi = kzalloc(sizeof(struct wmi), GFP_KERNEL);
3939  if (!wmi)
3940  return NULL;
3941 
3942  spin_lock_init(&wmi->lock);
3943 
3944  wmi->parent_dev = dev;
3945 
3946  wmi->pwr_mode = REC_POWER;
3947 
3948  ath6kl_wmi_reset(wmi);
3949 
3950  return wmi;
3951 }
3952 
3953 void ath6kl_wmi_shutdown(struct wmi *wmi)
3954 {
3955  if (!wmi)
3956  return;
3957 
3958  kfree(wmi->last_mgmt_tx_frame);
3959  kfree(wmi);
3960 }