1 //------------------------------------------------------------------------------
2 // Copyright (c) 2004-2010 Atheros Communications Inc.
3 // All rights reserved.
4 //
5 //
6 //
7 // Permission to use, copy, modify, and/or distribute this software for any
8 // purpose with or without fee is hereby granted, provided that the above
9 // copyright notice and this permission notice appear in all copies.
10 //
11 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 //
19 //
20 //
21 // Author(s): ="Atheros"
22 //------------------------------------------------------------------------------
23 
24 #include "ar6000_drv.h"
25 #include "ieee80211_ioctl.h"
26 #include "ar6kap_common.h"
27 #include "targaddrs.h"
28 #include "a_hci.h"
29 #include "wlan_config.h"
30 
31 extern int enablerssicompensation;
32 u32 tcmdRxFreq;
33 extern unsigned int wmitimeout;
34 extern A_WAITQUEUE_HEAD arEvent;
35 extern int tspecCompliance;
36 extern int bmienable;
37 extern int loghci;
38 
39 static int
ar6000_ioctl_get_roam_tbl(struct net_device * dev,struct ifreq * rq)40 ar6000_ioctl_get_roam_tbl(struct net_device *dev, struct ifreq *rq)
41 {
42     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
43 
44     if (ar->arWmiReady == false) {
45         return -EIO;
46     }
47 
48     if(wmi_get_roam_tbl_cmd(ar->arWmi) != 0) {
49         return -EIO;
50     }
51 
52     return 0;
53 }
54 
55 static int
ar6000_ioctl_get_roam_data(struct net_device * dev,struct ifreq * rq)56 ar6000_ioctl_get_roam_data(struct net_device *dev, struct ifreq *rq)
57 {
58     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
59 
60     if (ar->arWmiReady == false) {
61         return -EIO;
62     }
63 
64 
65     /* currently assume only roam times are required */
66     if(wmi_get_roam_data_cmd(ar->arWmi, ROAM_DATA_TIME) != 0) {
67         return -EIO;
68     }
69 
70 
71     return 0;
72 }
73 
74 static int
ar6000_ioctl_set_roam_ctrl(struct net_device * dev,char * userdata)75 ar6000_ioctl_set_roam_ctrl(struct net_device *dev, char *userdata)
76 {
77     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
78     WMI_SET_ROAM_CTRL_CMD cmd;
79     u8 size = sizeof(cmd);
80 
81     if (ar->arWmiReady == false) {
82         return -EIO;
83     }
84 
85 
86     if (copy_from_user(&cmd, userdata, size)) {
87         return -EFAULT;
88     }
89 
90     if (cmd.roamCtrlType == WMI_SET_HOST_BIAS) {
91         if (cmd.info.bssBiasInfo.numBss > 1) {
92             size += (cmd.info.bssBiasInfo.numBss - 1) * sizeof(WMI_BSS_BIAS);
93         }
94     }
95 
96     if (copy_from_user(&cmd, userdata, size)) {
97         return -EFAULT;
98     }
99 
100     if(wmi_set_roam_ctrl_cmd(ar->arWmi, &cmd, size) != 0) {
101         return -EIO;
102     }
103 
104     return 0;
105 }
106 
107 static int
ar6000_ioctl_set_powersave_timers(struct net_device * dev,char * userdata)108 ar6000_ioctl_set_powersave_timers(struct net_device *dev, char *userdata)
109 {
110     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
111     WMI_POWERSAVE_TIMERS_POLICY_CMD cmd;
112     u8 size = sizeof(cmd);
113 
114     if (ar->arWmiReady == false) {
115         return -EIO;
116     }
117 
118     if (copy_from_user(&cmd, userdata, size)) {
119         return -EFAULT;
120     }
121 
122     if (copy_from_user(&cmd, userdata, size)) {
123         return -EFAULT;
124     }
125 
126     if(wmi_set_powersave_timers_cmd(ar->arWmi, &cmd, size) != 0) {
127         return -EIO;
128     }
129 
130     return 0;
131 }
132 
133 static int
ar6000_ioctl_set_qos_supp(struct net_device * dev,struct ifreq * rq)134 ar6000_ioctl_set_qos_supp(struct net_device *dev, struct ifreq *rq)
135 {
136     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
137     WMI_SET_QOS_SUPP_CMD cmd;
138     int ret;
139 
140     if ((dev->flags & IFF_UP) != IFF_UP) {
141         return -EIO;
142     }
143     if (ar->arWmiReady == false) {
144         return -EIO;
145     }
146 
147     if (copy_from_user(&cmd, (char *)((unsigned int*)rq->ifr_data + 1),
148                                 sizeof(cmd)))
149     {
150         return -EFAULT;
151     }
152 
153     ret = wmi_set_qos_supp_cmd(ar->arWmi, cmd.status);
154 
155     switch (ret) {
156         case 0:
157             return 0;
158         case A_EBUSY :
159             return -EBUSY;
160         case A_NO_MEMORY:
161             return -ENOMEM;
162         case A_EINVAL:
163         default:
164             return -EFAULT;
165     }
166 }
167 
168 static int
ar6000_ioctl_set_wmm(struct net_device * dev,struct ifreq * rq)169 ar6000_ioctl_set_wmm(struct net_device *dev, struct ifreq *rq)
170 {
171     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
172     WMI_SET_WMM_CMD cmd;
173     int ret;
174 
175     if ((dev->flags & IFF_UP) != IFF_UP) {
176         return -EIO;
177     }
178     if (ar->arWmiReady == false) {
179         return -EIO;
180     }
181 
182     if (copy_from_user(&cmd, (char *)((unsigned int*)rq->ifr_data + 1),
183                                 sizeof(cmd)))
184     {
185         return -EFAULT;
186     }
187 
188     if (cmd.status == WMI_WMM_ENABLED) {
189         ar->arWmmEnabled = true;
190     } else {
191         ar->arWmmEnabled = false;
192     }
193 
194     ret = wmi_set_wmm_cmd(ar->arWmi, cmd.status);
195 
196     switch (ret) {
197         case 0:
198             return 0;
199         case A_EBUSY :
200             return -EBUSY;
201         case A_NO_MEMORY:
202             return -ENOMEM;
203         case A_EINVAL:
204         default:
205             return -EFAULT;
206     }
207 }
208 
209 static int
ar6000_ioctl_set_txop(struct net_device * dev,struct ifreq * rq)210 ar6000_ioctl_set_txop(struct net_device *dev, struct ifreq *rq)
211 {
212     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
213     WMI_SET_WMM_TXOP_CMD cmd;
214     int ret;
215 
216     if ((dev->flags & IFF_UP) != IFF_UP) {
217         return -EIO;
218     }
219     if (ar->arWmiReady == false) {
220         return -EIO;
221     }
222 
223     if (copy_from_user(&cmd, (char *)((unsigned int*)rq->ifr_data + 1),
224                                 sizeof(cmd)))
225     {
226         return -EFAULT;
227     }
228 
229     ret = wmi_set_wmm_txop(ar->arWmi, cmd.txopEnable);
230 
231     switch (ret) {
232         case 0:
233             return 0;
234         case A_EBUSY :
235             return -EBUSY;
236         case A_NO_MEMORY:
237             return -ENOMEM;
238         case A_EINVAL:
239         default:
240             return -EFAULT;
241     }
242 }
243 
244 static int
ar6000_ioctl_get_rd(struct net_device * dev,struct ifreq * rq)245 ar6000_ioctl_get_rd(struct net_device *dev, struct ifreq *rq)
246 {
247     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
248     int ret = 0;
249 
250     if ((dev->flags & IFF_UP) != IFF_UP || ar->arWmiReady == false) {
251         return -EIO;
252     }
253 
254     if(copy_to_user((char *)((unsigned int*)rq->ifr_data + 1),
255                             &ar->arRegCode, sizeof(ar->arRegCode)))
256         ret = -EFAULT;
257 
258     return ret;
259 }
260 
261 static int
ar6000_ioctl_set_country(struct net_device * dev,struct ifreq * rq)262 ar6000_ioctl_set_country(struct net_device *dev, struct ifreq *rq)
263 {
264     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
265     WMI_AP_SET_COUNTRY_CMD cmd;
266     int ret;
267 
268     if ((dev->flags & IFF_UP) != IFF_UP) {
269         return -EIO;
270     }
271     if (ar->arWmiReady == false) {
272         return -EIO;
273     }
274 
275     if (copy_from_user(&cmd, (char *)((unsigned int*)rq->ifr_data + 1),
276                                 sizeof(cmd)))
277     {
278         return -EFAULT;
279     }
280 
281     ar->ap_profile_flag = 1; /* There is a change in profile */
282 
283     ret = wmi_set_country(ar->arWmi, cmd.countryCode);
284     memcpy(ar->ap_country_code, cmd.countryCode, 3);
285 
286     switch (ret) {
287         case 0:
288             return 0;
289         case A_EBUSY :
290             return -EBUSY;
291         case A_NO_MEMORY:
292             return -ENOMEM;
293         case A_EINVAL:
294         default:
295             return -EFAULT;
296     }
297 }
298 
299 
300 /* Get power mode command */
301 static int
ar6000_ioctl_get_power_mode(struct net_device * dev,struct ifreq * rq)302 ar6000_ioctl_get_power_mode(struct net_device *dev, struct ifreq *rq)
303 {
304     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
305     WMI_POWER_MODE_CMD power_mode;
306     int ret = 0;
307 
308     if (ar->arWmiReady == false) {
309         return -EIO;
310     }
311 
312     power_mode.powerMode = wmi_get_power_mode_cmd(ar->arWmi);
313     if (copy_to_user(rq->ifr_data, &power_mode, sizeof(WMI_POWER_MODE_CMD))) {
314         ret = -EFAULT;
315     }
316 
317     return ret;
318 }
319 
320 
321 static int
ar6000_ioctl_set_channelParams(struct net_device * dev,struct ifreq * rq)322 ar6000_ioctl_set_channelParams(struct net_device *dev, struct ifreq *rq)
323 {
324     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
325     WMI_CHANNEL_PARAMS_CMD cmd, *cmdp;
326     int ret = 0;
327 
328     if (ar->arWmiReady == false) {
329         return -EIO;
330     }
331 
332 
333     if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
334         return -EFAULT;
335     }
336 
337     if( (ar->arNextMode == AP_NETWORK) && (cmd.numChannels || cmd.scanParam) ) {
338         A_PRINTF("ERROR: Only wmode is allowed in AP mode\n");
339         return -EIO;
340     }
341 
342     if (cmd.numChannels > 1) {
343         cmdp = A_MALLOC(130);
344         if (copy_from_user(cmdp, rq->ifr_data,
345                            sizeof (*cmdp) +
346                            ((cmd.numChannels - 1) * sizeof(u16))))
347         {
348             kfree(cmdp);
349             return -EFAULT;
350         }
351     } else {
352         cmdp = &cmd;
353     }
354 
355     if ((ar->arPhyCapability == WMI_11G_CAPABILITY) &&
356         ((cmdp->phyMode == WMI_11A_MODE) || (cmdp->phyMode == WMI_11AG_MODE)))
357     {
358         ret = -EINVAL;
359     }
360 
361     if (!ret &&
362         (wmi_set_channelParams_cmd(ar->arWmi, cmdp->scanParam, cmdp->phyMode,
363                                    cmdp->numChannels, cmdp->channelList)
364          != 0))
365     {
366         ret = -EIO;
367     }
368 
369     if (cmd.numChannels > 1) {
370         kfree(cmdp);
371     }
372 
373     ar->ap_wmode = cmdp->phyMode;
374     /* Set the profile change flag to allow a commit cmd */
375     ar->ap_profile_flag = 1;
376 
377     return ret;
378 }
379 
380 
381 static int
ar6000_ioctl_set_snr_threshold(struct net_device * dev,struct ifreq * rq)382 ar6000_ioctl_set_snr_threshold(struct net_device *dev, struct ifreq *rq)
383 {
384 
385     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
386     WMI_SNR_THRESHOLD_PARAMS_CMD cmd;
387     int ret = 0;
388 
389     if (ar->arWmiReady == false) {
390         return -EIO;
391     }
392 
393     if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
394         return -EFAULT;
395     }
396 
397     if( wmi_set_snr_threshold_params(ar->arWmi, &cmd) != 0 ) {
398         ret = -EIO;
399     }
400 
401     return ret;
402 }
403 
404 static int
ar6000_ioctl_set_rssi_threshold(struct net_device * dev,struct ifreq * rq)405 ar6000_ioctl_set_rssi_threshold(struct net_device *dev, struct ifreq *rq)
406 {
407 #define SWAP_THOLD(thold1, thold2) do { \
408     USER_RSSI_THOLD tmpThold;           \
409     tmpThold.tag = thold1.tag;          \
410     tmpThold.rssi = thold1.rssi;        \
411     thold1.tag = thold2.tag;            \
412     thold1.rssi = thold2.rssi;          \
413     thold2.tag = tmpThold.tag;          \
414     thold2.rssi = tmpThold.rssi;        \
415 } while (0)
416 
417     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
418     WMI_RSSI_THRESHOLD_PARAMS_CMD cmd;
419     USER_RSSI_PARAMS rssiParams;
420     s32 i, j;
421     int ret = 0;
422 
423     if (ar->arWmiReady == false) {
424         return -EIO;
425     }
426 
427     if (copy_from_user((char *)&rssiParams, (char *)((unsigned int *)rq->ifr_data + 1), sizeof(USER_RSSI_PARAMS))) {
428         return -EFAULT;
429     }
430     cmd.weight = rssiParams.weight;
431     cmd.pollTime = rssiParams.pollTime;
432 
433     memcpy(ar->rssi_map, &rssiParams.tholds, sizeof(ar->rssi_map));
434     /*
435      *  only 6 elements, so use bubble sorting, in ascending order
436      */
437     for (i = 5; i > 0; i--) {
438         for (j = 0; j < i; j++) { /* above tholds */
439             if (ar->rssi_map[j+1].rssi < ar->rssi_map[j].rssi) {
440                 SWAP_THOLD(ar->rssi_map[j+1], ar->rssi_map[j]);
441             } else if (ar->rssi_map[j+1].rssi == ar->rssi_map[j].rssi) {
442                 return -EFAULT;
443             }
444         }
445     }
446     for (i = 11; i > 6; i--) {
447         for (j = 6; j < i; j++) { /* below tholds */
448             if (ar->rssi_map[j+1].rssi < ar->rssi_map[j].rssi) {
449                 SWAP_THOLD(ar->rssi_map[j+1], ar->rssi_map[j]);
450             } else if (ar->rssi_map[j+1].rssi == ar->rssi_map[j].rssi) {
451                 return -EFAULT;
452             }
453         }
454     }
455 
456 #ifdef DEBUG
457     for (i = 0; i < 12; i++) {
458         AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("thold[%d].tag: %d, thold[%d].rssi: %d \n",
459                 i, ar->rssi_map[i].tag, i, ar->rssi_map[i].rssi));
460     }
461 #endif
462 
463     if (enablerssicompensation) {
464         for (i = 0; i < 6; i++)
465             ar->rssi_map[i].rssi = rssi_compensation_reverse_calc(ar, ar->rssi_map[i].rssi, true);
466         for (i = 6; i < 12; i++)
467             ar->rssi_map[i].rssi = rssi_compensation_reverse_calc(ar, ar->rssi_map[i].rssi, false);
468     }
469 
470     cmd.thresholdAbove1_Val = ar->rssi_map[0].rssi;
471     cmd.thresholdAbove2_Val = ar->rssi_map[1].rssi;
472     cmd.thresholdAbove3_Val = ar->rssi_map[2].rssi;
473     cmd.thresholdAbove4_Val = ar->rssi_map[3].rssi;
474     cmd.thresholdAbove5_Val = ar->rssi_map[4].rssi;
475     cmd.thresholdAbove6_Val = ar->rssi_map[5].rssi;
476     cmd.thresholdBelow1_Val = ar->rssi_map[6].rssi;
477     cmd.thresholdBelow2_Val = ar->rssi_map[7].rssi;
478     cmd.thresholdBelow3_Val = ar->rssi_map[8].rssi;
479     cmd.thresholdBelow4_Val = ar->rssi_map[9].rssi;
480     cmd.thresholdBelow5_Val = ar->rssi_map[10].rssi;
481     cmd.thresholdBelow6_Val = ar->rssi_map[11].rssi;
482 
483     if( wmi_set_rssi_threshold_params(ar->arWmi, &cmd) != 0 ) {
484         ret = -EIO;
485     }
486 
487     return ret;
488 }
489 
490 static int
ar6000_ioctl_set_lq_threshold(struct net_device * dev,struct ifreq * rq)491 ar6000_ioctl_set_lq_threshold(struct net_device *dev, struct ifreq *rq)
492 {
493 
494     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
495     WMI_LQ_THRESHOLD_PARAMS_CMD cmd;
496     int ret = 0;
497 
498     if (ar->arWmiReady == false) {
499         return -EIO;
500     }
501 
502     if (copy_from_user(&cmd, (char *)((unsigned int *)rq->ifr_data + 1), sizeof(cmd))) {
503         return -EFAULT;
504     }
505 
506     if( wmi_set_lq_threshold_params(ar->arWmi, &cmd) != 0 ) {
507         ret = -EIO;
508     }
509 
510     return ret;
511 }
512 
513 
514 static int
ar6000_ioctl_set_probedSsid(struct net_device * dev,struct ifreq * rq)515 ar6000_ioctl_set_probedSsid(struct net_device *dev, struct ifreq *rq)
516 {
517     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
518     WMI_PROBED_SSID_CMD cmd;
519     int ret = 0;
520 
521     if (ar->arWmiReady == false) {
522         return -EIO;
523     }
524 
525     if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
526         return -EFAULT;
527     }
528 
529     if (wmi_probedSsid_cmd(ar->arWmi, cmd.entryIndex, cmd.flag, cmd.ssidLength,
530                                   cmd.ssid) != 0)
531     {
532         ret = -EIO;
533     }
534 
535     return ret;
536 }
537 
538 static int
ar6000_ioctl_set_badAp(struct net_device * dev,struct ifreq * rq)539 ar6000_ioctl_set_badAp(struct net_device *dev, struct ifreq *rq)
540 {
541     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
542     WMI_ADD_BAD_AP_CMD cmd;
543     int ret = 0;
544 
545     if (ar->arWmiReady == false) {
546         return -EIO;
547     }
548 
549 
550     if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
551         return -EFAULT;
552     }
553 
554     if (cmd.badApIndex > WMI_MAX_BAD_AP_INDEX) {
555         return -EIO;
556     }
557 
558     if (memcmp(cmd.bssid, null_mac, AR6000_ETH_ADDR_LEN) == 0) {
559         /*
560          * This is a delete badAP.
561          */
562         if (wmi_deleteBadAp_cmd(ar->arWmi, cmd.badApIndex) != 0) {
563             ret = -EIO;
564         }
565     } else {
566         if (wmi_addBadAp_cmd(ar->arWmi, cmd.badApIndex, cmd.bssid) != 0) {
567             ret = -EIO;
568         }
569     }
570 
571     return ret;
572 }
573 
574 static int
ar6000_ioctl_create_qos(struct net_device * dev,struct ifreq * rq)575 ar6000_ioctl_create_qos(struct net_device *dev, struct ifreq *rq)
576 {
577     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
578     WMI_CREATE_PSTREAM_CMD cmd;
579     int ret;
580 
581     if (ar->arWmiReady == false) {
582         return -EIO;
583     }
584 
585 
586     if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
587         return -EFAULT;
588     }
589 
590     ret = wmi_verify_tspec_params(&cmd, tspecCompliance);
591     if (ret == 0)
592         ret = wmi_create_pstream_cmd(ar->arWmi, &cmd);
593 
594     switch (ret) {
595         case 0:
596             return 0;
597         case A_EBUSY :
598             return -EBUSY;
599         case A_NO_MEMORY:
600             return -ENOMEM;
601         case A_EINVAL:
602         default:
603             return -EFAULT;
604     }
605 }
606 
607 static int
ar6000_ioctl_delete_qos(struct net_device * dev,struct ifreq * rq)608 ar6000_ioctl_delete_qos(struct net_device *dev, struct ifreq *rq)
609 {
610     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
611     WMI_DELETE_PSTREAM_CMD cmd;
612     int ret = 0;
613 
614     if (ar->arWmiReady == false) {
615         return -EIO;
616     }
617 
618     if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
619         return -EFAULT;
620     }
621 
622     ret = wmi_delete_pstream_cmd(ar->arWmi, cmd.trafficClass, cmd.tsid);
623 
624     switch (ret) {
625         case 0:
626             return 0;
627         case A_EBUSY :
628             return -EBUSY;
629         case A_NO_MEMORY:
630             return -ENOMEM;
631         case A_EINVAL:
632         default:
633             return -EFAULT;
634     }
635 }
636 
637 static int
ar6000_ioctl_get_qos_queue(struct net_device * dev,struct ifreq * rq)638 ar6000_ioctl_get_qos_queue(struct net_device *dev, struct ifreq *rq)
639 {
640     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
641     struct ar6000_queuereq qreq;
642     int ret = 0;
643 
644     if (ar->arWmiReady == false) {
645         return -EIO;
646     }
647 
648     if( copy_from_user(&qreq, rq->ifr_data,
649                   sizeof(struct ar6000_queuereq)))
650         return -EFAULT;
651 
652     qreq.activeTsids = wmi_get_mapped_qos_queue(ar->arWmi, qreq.trafficClass);
653 
654     if (copy_to_user(rq->ifr_data, &qreq,
655                  sizeof(struct ar6000_queuereq)))
656     {
657         ret = -EFAULT;
658     }
659 
660     return ret;
661 }
662 
663 #ifdef CONFIG_HOST_TCMD_SUPPORT
664 static int
ar6000_ioctl_tcmd_get_rx_report(struct net_device * dev,struct ifreq * rq,u8 * data,u32 len)665 ar6000_ioctl_tcmd_get_rx_report(struct net_device *dev,
666                                  struct ifreq *rq, u8 *data, u32 len)
667 {
668     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
669     u32 buf[4+TCMD_MAX_RATES];
670     int ret = 0;
671 
672     if (ar->bIsDestroyProgress) {
673         return -EBUSY;
674     }
675 
676     if (ar->arWmiReady == false) {
677         return -EIO;
678     }
679 
680     if (down_interruptible(&ar->arSem)) {
681         return -ERESTARTSYS;
682     }
683 
684     if (ar->bIsDestroyProgress) {
685         up(&ar->arSem);
686         return -EBUSY;
687     }
688 
689     ar->tcmdRxReport = 0;
690     if (wmi_test_cmd(ar->arWmi, data, len) != 0) {
691         up(&ar->arSem);
692         return -EIO;
693     }
694 
695     wait_event_interruptible_timeout(arEvent, ar->tcmdRxReport != 0, wmitimeout * HZ);
696 
697     if (signal_pending(current)) {
698         ret = -EINTR;
699     }
700 
701     buf[0] = ar->tcmdRxTotalPkt;
702     buf[1] = ar->tcmdRxRssi;
703     buf[2] = ar->tcmdRxcrcErrPkt;
704     buf[3] = ar->tcmdRxsecErrPkt;
705     memcpy(((u8 *)buf)+(4*sizeof(u32)), ar->tcmdRateCnt, sizeof(ar->tcmdRateCnt));
706     memcpy(((u8 *)buf)+(4*sizeof(u32))+(TCMD_MAX_RATES *sizeof(u16)), ar->tcmdRateCntShortGuard, sizeof(ar->tcmdRateCntShortGuard));
707 
708     if (!ret && copy_to_user(rq->ifr_data, buf, sizeof(buf))) {
709         ret = -EFAULT;
710     }
711 
712     up(&ar->arSem);
713 
714     return ret;
715 }
716 
717 void
ar6000_tcmd_rx_report_event(void * devt,u8 * results,int len)718 ar6000_tcmd_rx_report_event(void *devt, u8 *results, int len)
719 {
720     struct ar6_softc *ar = (struct ar6_softc *)devt;
721     TCMD_CONT_RX * rx_rep = (TCMD_CONT_RX *)results;
722 
723     if (enablerssicompensation) {
724         rx_rep->u.report.rssiInDBm = rssi_compensation_calc_tcmd(tcmdRxFreq, rx_rep->u.report.rssiInDBm,rx_rep->u.report.totalPkt);
725     }
726 
727 
728     ar->tcmdRxTotalPkt = rx_rep->u.report.totalPkt;
729     ar->tcmdRxRssi = rx_rep->u.report.rssiInDBm;
730     ar->tcmdRxcrcErrPkt = rx_rep->u.report.crcErrPkt;
731     ar->tcmdRxsecErrPkt = rx_rep->u.report.secErrPkt;
732     ar->tcmdRxReport = 1;
733     A_MEMZERO(ar->tcmdRateCnt,  sizeof(ar->tcmdRateCnt));
734     A_MEMZERO(ar->tcmdRateCntShortGuard,  sizeof(ar->tcmdRateCntShortGuard));
735     memcpy(ar->tcmdRateCnt, rx_rep->u.report.rateCnt, sizeof(ar->tcmdRateCnt));
736     memcpy(ar->tcmdRateCntShortGuard, rx_rep->u.report.rateCntShortGuard, sizeof(ar->tcmdRateCntShortGuard));
737 
738     wake_up(&arEvent);
739 }
740 #endif /* CONFIG_HOST_TCMD_SUPPORT*/
741 
742 static int
ar6000_ioctl_set_error_report_bitmask(struct net_device * dev,struct ifreq * rq)743 ar6000_ioctl_set_error_report_bitmask(struct net_device *dev, struct ifreq *rq)
744 {
745     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
746     WMI_TARGET_ERROR_REPORT_BITMASK cmd;
747     int ret = 0;
748 
749     if (ar->arWmiReady == false) {
750         return -EIO;
751     }
752 
753     if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
754         return -EFAULT;
755     }
756 
757     ret = wmi_set_error_report_bitmask(ar->arWmi, cmd.bitmask);
758 
759     return  (ret==0 ? ret : -EINVAL);
760 }
761 
762 static int
ar6000_clear_target_stats(struct net_device * dev)763 ar6000_clear_target_stats(struct net_device *dev)
764 {
765     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
766     TARGET_STATS *pStats = &ar->arTargetStats;
767     int ret = 0;
768 
769     if (ar->arWmiReady == false) {
770        return -EIO;
771     }
772     AR6000_SPIN_LOCK(&ar->arLock, 0);
773     A_MEMZERO(pStats, sizeof(TARGET_STATS));
774     AR6000_SPIN_UNLOCK(&ar->arLock, 0);
775     return ret;
776 }
777 
778 static int
ar6000_ioctl_get_target_stats(struct net_device * dev,struct ifreq * rq)779 ar6000_ioctl_get_target_stats(struct net_device *dev, struct ifreq *rq)
780 {
781     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
782     TARGET_STATS_CMD cmd;
783     TARGET_STATS *pStats = &ar->arTargetStats;
784     int ret = 0;
785 
786     if (ar->bIsDestroyProgress) {
787         return -EBUSY;
788     }
789     if (ar->arWmiReady == false) {
790         return -EIO;
791     }
792     if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
793         return -EFAULT;
794     }
795     if (down_interruptible(&ar->arSem)) {
796         return -ERESTARTSYS;
797     }
798     if (ar->bIsDestroyProgress) {
799         up(&ar->arSem);
800         return -EBUSY;
801     }
802 
803     ar->statsUpdatePending = true;
804 
805     if(wmi_get_stats_cmd(ar->arWmi) != 0) {
806         up(&ar->arSem);
807         return -EIO;
808     }
809 
810     wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
811 
812     if (signal_pending(current)) {
813         ret = -EINTR;
814     }
815 
816     if (!ret && copy_to_user(rq->ifr_data, pStats, sizeof(*pStats))) {
817         ret = -EFAULT;
818     }
819 
820     if (cmd.clearStats == 1) {
821         ret = ar6000_clear_target_stats(dev);
822     }
823 
824     up(&ar->arSem);
825 
826     return ret;
827 }
828 
829 static int
ar6000_ioctl_get_ap_stats(struct net_device * dev,struct ifreq * rq)830 ar6000_ioctl_get_ap_stats(struct net_device *dev, struct ifreq *rq)
831 {
832     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
833     u32 action; /* Allocating only the desired space on the frame. Declaring is as a WMI_AP_MODE_STAT variable results in exceeding the compiler imposed limit on the maximum frame size */
834     WMI_AP_MODE_STAT *pStats = &ar->arAPStats;
835     int ret = 0;
836 
837     if (ar->arWmiReady == false) {
838         return -EIO;
839     }
840     if (copy_from_user(&action, (char *)((unsigned int*)rq->ifr_data + 1),
841                                 sizeof(u32)))
842     {
843         return -EFAULT;
844     }
845     if (action == AP_CLEAR_STATS) {
846         u8 i;
847         AR6000_SPIN_LOCK(&ar->arLock, 0);
848         for(i = 0; i < AP_MAX_NUM_STA; i++) {
849             pStats->sta[i].tx_bytes = 0;
850             pStats->sta[i].tx_pkts = 0;
851             pStats->sta[i].tx_error = 0;
852             pStats->sta[i].tx_discard = 0;
853             pStats->sta[i].rx_bytes = 0;
854             pStats->sta[i].rx_pkts = 0;
855             pStats->sta[i].rx_error = 0;
856             pStats->sta[i].rx_discard = 0;
857         }
858         AR6000_SPIN_UNLOCK(&ar->arLock, 0);
859         return ret;
860     }
861 
862     if (down_interruptible(&ar->arSem)) {
863         return -ERESTARTSYS;
864     }
865 
866     ar->statsUpdatePending = true;
867 
868     if(wmi_get_stats_cmd(ar->arWmi) != 0) {
869         up(&ar->arSem);
870         return -EIO;
871     }
872 
873     wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
874 
875     if (signal_pending(current)) {
876         ret = -EINTR;
877     }
878 
879     if (!ret && copy_to_user(rq->ifr_data, pStats, sizeof(*pStats))) {
880         ret = -EFAULT;
881     }
882 
883     up(&ar->arSem);
884 
885     return ret;
886 }
887 
888 static int
ar6000_ioctl_set_access_params(struct net_device * dev,struct ifreq * rq)889 ar6000_ioctl_set_access_params(struct net_device *dev, struct ifreq *rq)
890 {
891     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
892     WMI_SET_ACCESS_PARAMS_CMD cmd;
893     int ret = 0;
894 
895     if (ar->arWmiReady == false) {
896         return -EIO;
897     }
898 
899     if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
900         return -EFAULT;
901     }
902 
903     if (wmi_set_access_params_cmd(ar->arWmi, cmd.ac, cmd.txop, cmd.eCWmin, cmd.eCWmax,
904                                   cmd.aifsn) == 0)
905     {
906         ret = 0;
907     } else {
908         ret = -EINVAL;
909     }
910 
911     return (ret);
912 }
913 
914 static int
ar6000_ioctl_set_disconnect_timeout(struct net_device * dev,struct ifreq * rq)915 ar6000_ioctl_set_disconnect_timeout(struct net_device *dev, struct ifreq *rq)
916 {
917     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
918     WMI_DISC_TIMEOUT_CMD cmd;
919     int ret = 0;
920 
921     if (ar->arWmiReady == false) {
922         return -EIO;
923     }
924 
925     if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
926         return -EFAULT;
927     }
928 
929     if (wmi_disctimeout_cmd(ar->arWmi, cmd.disconnectTimeout) == 0)
930     {
931         ret = 0;
932     } else {
933         ret = -EINVAL;
934     }
935 
936     return (ret);
937 }
938 
939 static int
ar6000_xioctl_set_voice_pkt_size(struct net_device * dev,char * userdata)940 ar6000_xioctl_set_voice_pkt_size(struct net_device *dev, char *userdata)
941 {
942     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
943     WMI_SET_VOICE_PKT_SIZE_CMD cmd;
944     int ret = 0;
945 
946     if (ar->arWmiReady == false) {
947         return -EIO;
948     }
949 
950     if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
951         return -EFAULT;
952     }
953 
954     if (wmi_set_voice_pkt_size_cmd(ar->arWmi, cmd.voicePktSize) == 0)
955     {
956         ret = 0;
957     } else {
958         ret = -EINVAL;
959     }
960 
961 
962     return (ret);
963 }
964 
965 static int
ar6000_xioctl_set_max_sp_len(struct net_device * dev,char * userdata)966 ar6000_xioctl_set_max_sp_len(struct net_device *dev, char *userdata)
967 {
968     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
969     WMI_SET_MAX_SP_LEN_CMD cmd;
970     int ret = 0;
971 
972     if (ar->arWmiReady == false) {
973         return -EIO;
974     }
975 
976     if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
977         return -EFAULT;
978     }
979 
980     if (wmi_set_max_sp_len_cmd(ar->arWmi, cmd.maxSPLen) == 0)
981     {
982         ret = 0;
983     } else {
984         ret = -EINVAL;
985     }
986 
987     return (ret);
988 }
989 
990 
991 static int
ar6000_xioctl_set_bt_status_cmd(struct net_device * dev,char * userdata)992 ar6000_xioctl_set_bt_status_cmd(struct net_device *dev, char *userdata)
993 {
994     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
995     WMI_SET_BT_STATUS_CMD cmd;
996     int ret = 0;
997 
998     if (ar->arWmiReady == false) {
999         return -EIO;
1000     }
1001 
1002     if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1003         return -EFAULT;
1004     }
1005 
1006     if (wmi_set_bt_status_cmd(ar->arWmi, cmd.streamType, cmd.status) == 0)
1007     {
1008         ret = 0;
1009     } else {
1010         ret = -EINVAL;
1011     }
1012 
1013     return (ret);
1014 }
1015 
1016 static int
ar6000_xioctl_set_bt_params_cmd(struct net_device * dev,char * userdata)1017 ar6000_xioctl_set_bt_params_cmd(struct net_device *dev, char *userdata)
1018 {
1019     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1020     WMI_SET_BT_PARAMS_CMD cmd;
1021     int ret = 0;
1022 
1023     if (ar->arWmiReady == false) {
1024         return -EIO;
1025     }
1026 
1027     if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1028         return -EFAULT;
1029     }
1030 
1031     if (wmi_set_bt_params_cmd(ar->arWmi, &cmd) == 0)
1032     {
1033         ret = 0;
1034     } else {
1035         ret = -EINVAL;
1036     }
1037 
1038     return (ret);
1039 }
1040 
1041 static int
ar6000_xioctl_set_btcoex_fe_ant_cmd(struct net_device * dev,char * userdata)1042 ar6000_xioctl_set_btcoex_fe_ant_cmd(struct net_device * dev, char *userdata)
1043 {
1044 	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1045 	WMI_SET_BTCOEX_FE_ANT_CMD cmd;
1046     int ret = 0;
1047 
1048 	if (ar->arWmiReady == false) {
1049 		return -EIO;
1050 	}
1051 	if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1052 		return -EFAULT;
1053 	}
1054 
1055     if (wmi_set_btcoex_fe_ant_cmd(ar->arWmi, &cmd) == 0)
1056     {
1057         ret = 0;
1058     } else {
1059         ret = -EINVAL;
1060     }
1061 
1062 	return(ret);
1063 }
1064 
1065 static int
ar6000_xioctl_set_btcoex_colocated_bt_dev_cmd(struct net_device * dev,char * userdata)1066 ar6000_xioctl_set_btcoex_colocated_bt_dev_cmd(struct net_device * dev, char *userdata)
1067 {
1068 	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1069 	WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD cmd;
1070     int ret = 0;
1071 
1072 	if (ar->arWmiReady == false) {
1073 		return -EIO;
1074 	}
1075 
1076 	if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1077 		return -EFAULT;
1078 	}
1079 
1080     if (wmi_set_btcoex_colocated_bt_dev_cmd(ar->arWmi, &cmd) == 0)
1081     {
1082         ret = 0;
1083     } else {
1084         ret = -EINVAL;
1085     }
1086 
1087 	return(ret);
1088 }
1089 
1090 static int
ar6000_xioctl_set_btcoex_btinquiry_page_config_cmd(struct net_device * dev,char * userdata)1091 ar6000_xioctl_set_btcoex_btinquiry_page_config_cmd(struct net_device * dev,  char *userdata)
1092 {
1093 	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1094 	WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD cmd;
1095     int ret = 0;
1096 
1097 	if (ar->arWmiReady == false) {
1098 		return -EIO;
1099 	}
1100 
1101 	if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1102 		return -EFAULT;
1103 	}
1104 
1105     if (wmi_set_btcoex_btinquiry_page_config_cmd(ar->arWmi, &cmd) == 0)
1106     {
1107         ret = 0;
1108     } else {
1109         ret = -EINVAL;
1110     }
1111 
1112 	return(ret);
1113 }
1114 
1115 static int
ar6000_xioctl_set_btcoex_sco_config_cmd(struct net_device * dev,char * userdata)1116 ar6000_xioctl_set_btcoex_sco_config_cmd(struct net_device * dev, char *userdata)
1117 {
1118 	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1119 	WMI_SET_BTCOEX_SCO_CONFIG_CMD cmd;
1120     int ret = 0;
1121 
1122 	if (ar->arWmiReady == false) {
1123 		return -EIO;
1124 	}
1125 
1126 	if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1127 		return -EFAULT;
1128 	}
1129 
1130     if (wmi_set_btcoex_sco_config_cmd(ar->arWmi, &cmd) == 0)
1131     {
1132         ret = 0;
1133     } else {
1134         ret = -EINVAL;
1135     }
1136 
1137 	return(ret);
1138 }
1139 
1140 static int
ar6000_xioctl_set_btcoex_a2dp_config_cmd(struct net_device * dev,char * userdata)1141 ar6000_xioctl_set_btcoex_a2dp_config_cmd(struct net_device * dev,
1142 														char *userdata)
1143 {
1144 	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1145 	WMI_SET_BTCOEX_A2DP_CONFIG_CMD cmd;
1146     int ret = 0;
1147 
1148 	if (ar->arWmiReady == false) {
1149 		return -EIO;
1150 	}
1151 
1152 	if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1153 		return -EFAULT;
1154 	}
1155 
1156     if (wmi_set_btcoex_a2dp_config_cmd(ar->arWmi, &cmd) == 0)
1157     {
1158         ret = 0;
1159     } else {
1160         ret = -EINVAL;
1161     }
1162 
1163 	return(ret);
1164 }
1165 
1166 static int
ar6000_xioctl_set_btcoex_aclcoex_config_cmd(struct net_device * dev,char * userdata)1167 ar6000_xioctl_set_btcoex_aclcoex_config_cmd(struct net_device * dev, char *userdata)
1168 {
1169 	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1170 	WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD cmd;
1171     int ret = 0;
1172 
1173 	if (ar->arWmiReady == false) {
1174 		return -EIO;
1175 	}
1176 
1177 	if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1178 		return -EFAULT;
1179 	}
1180 
1181     if (wmi_set_btcoex_aclcoex_config_cmd(ar->arWmi, &cmd) == 0)
1182     {
1183         ret = 0;
1184     } else {
1185         ret = -EINVAL;
1186     }
1187 
1188 	return(ret);
1189 }
1190 
1191 static int
ar60000_xioctl_set_btcoex_debug_cmd(struct net_device * dev,char * userdata)1192 ar60000_xioctl_set_btcoex_debug_cmd(struct net_device * dev, char *userdata)
1193 {
1194 	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1195 	WMI_SET_BTCOEX_DEBUG_CMD cmd;
1196     int ret = 0;
1197 
1198 	if (ar->arWmiReady == false) {
1199 		return -EIO;
1200 	}
1201 
1202 	if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1203 		return -EFAULT;
1204 	}
1205 
1206     if (wmi_set_btcoex_debug_cmd(ar->arWmi, &cmd) == 0)
1207     {
1208         ret = 0;
1209     } else {
1210         ret = -EINVAL;
1211     }
1212 
1213 	return(ret);
1214 }
1215 
1216 static int
ar6000_xioctl_set_btcoex_bt_operating_status_cmd(struct net_device * dev,char * userdata)1217 ar6000_xioctl_set_btcoex_bt_operating_status_cmd(struct net_device * dev, char *userdata)
1218 {
1219      struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1220      WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD cmd;
1221      int ret = 0;
1222 
1223     if (ar->arWmiReady == false) {
1224 	return -EIO;
1225     }
1226 
1227     if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1228 	return -EFAULT;
1229     }
1230 
1231     if (wmi_set_btcoex_bt_operating_status_cmd(ar->arWmi, &cmd) == 0)
1232     {
1233         ret = 0;
1234     } else {
1235         ret = -EINVAL;
1236     }
1237     return(ret);
1238 }
1239 
1240 static int
ar6000_xioctl_get_btcoex_config_cmd(struct net_device * dev,char * userdata,struct ifreq * rq)1241 ar6000_xioctl_get_btcoex_config_cmd(struct net_device * dev, char *userdata,
1242 											struct ifreq *rq)
1243 {
1244 
1245 	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1246     AR6000_BTCOEX_CONFIG btcoexConfig;
1247     WMI_BTCOEX_CONFIG_EVENT *pbtcoexConfigEv = &ar->arBtcoexConfig;
1248 
1249     int ret = 0;
1250 
1251     if (ar->bIsDestroyProgress) {
1252             return -EBUSY;
1253     }
1254     if (ar->arWmiReady == false) {
1255             return -EIO;
1256     }
1257 	if (copy_from_user(&btcoexConfig.configCmd, userdata, sizeof(AR6000_BTCOEX_CONFIG))) {
1258 		return -EFAULT;
1259 	}
1260     if (down_interruptible(&ar->arSem)) {
1261         return -ERESTARTSYS;
1262     }
1263 
1264     if (wmi_get_btcoex_config_cmd(ar->arWmi, (WMI_GET_BTCOEX_CONFIG_CMD *)&btcoexConfig.configCmd) != 0)
1265     {
1266     	up(&ar->arSem);
1267     	return -EIO;
1268     }
1269 
1270     ar->statsUpdatePending = true;
1271 
1272     wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
1273 
1274     if (signal_pending(current)) {
1275        ret = -EINTR;
1276     }
1277 
1278     if (!ret && copy_to_user(btcoexConfig.configEvent, pbtcoexConfigEv, sizeof(WMI_BTCOEX_CONFIG_EVENT))) {
1279             ret = -EFAULT;
1280     }
1281     up(&ar->arSem);
1282     return ret;
1283 }
1284 
1285 static int
ar6000_xioctl_get_btcoex_stats_cmd(struct net_device * dev,char * userdata,struct ifreq * rq)1286 ar6000_xioctl_get_btcoex_stats_cmd(struct net_device * dev, char *userdata, struct ifreq *rq)
1287 {
1288 	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1289     AR6000_BTCOEX_STATS btcoexStats;
1290     WMI_BTCOEX_STATS_EVENT *pbtcoexStats = &ar->arBtcoexStats;
1291     int ret = 0;
1292 
1293     if (ar->bIsDestroyProgress) {
1294             return -EBUSY;
1295     }
1296     if (ar->arWmiReady == false) {
1297             return -EIO;
1298     }
1299 
1300     if (down_interruptible(&ar->arSem)) {
1301         return -ERESTARTSYS;
1302     }
1303 
1304 	if (copy_from_user(&btcoexStats.statsEvent, userdata, sizeof(AR6000_BTCOEX_CONFIG))) {
1305 		return -EFAULT;
1306 	}
1307 
1308     if (wmi_get_btcoex_stats_cmd(ar->arWmi) != 0)
1309     {
1310     	up(&ar->arSem);
1311     	return -EIO;
1312     }
1313 
1314     ar->statsUpdatePending = true;
1315 
1316     wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
1317 
1318     if (signal_pending(current)) {
1319        ret = -EINTR;
1320     }
1321 
1322     if (!ret && copy_to_user(btcoexStats.statsEvent, pbtcoexStats, sizeof(WMI_BTCOEX_STATS_EVENT))) {
1323             ret = -EFAULT;
1324     }
1325 
1326 
1327     up(&ar->arSem);
1328 
1329 	return(ret);
1330 }
1331 
1332 static int
ar6000_xioctl_set_excess_tx_retry_thres_cmd(struct net_device * dev,char * userdata)1333 ar6000_xioctl_set_excess_tx_retry_thres_cmd(struct net_device * dev, char * userdata)
1334 {
1335     struct ar6_softc     *ar     = (struct ar6_softc *)ar6k_priv(dev);
1336     WMI_SET_EXCESS_TX_RETRY_THRES_CMD cmd;
1337     int ret = 0;
1338 
1339     if (ar->arWmiReady == false) {
1340         return -EIO;
1341     }
1342 
1343     if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1344         return -EFAULT;
1345     }
1346 
1347     if (wmi_set_excess_tx_retry_thres_cmd(ar->arWmi, &cmd) != 0)
1348     {
1349         ret = -EINVAL;
1350     }
1351     return(ret);
1352 }
1353 
1354 #ifdef CONFIG_HOST_GPIO_SUPPORT
1355 struct ar6000_gpio_intr_wait_cmd_s  gpio_intr_results;
1356 /* gpio_reg_results and gpio_data_available are protected by arSem */
1357 static struct ar6000_gpio_register_cmd_s gpio_reg_results;
1358 static bool gpio_data_available; /* Requested GPIO data available */
1359 static bool gpio_intr_available; /* GPIO interrupt info available */
1360 static bool gpio_ack_received;   /* GPIO ack was received */
1361 
1362 /* Host-side initialization for General Purpose I/O support */
ar6000_gpio_init(void)1363 void ar6000_gpio_init(void)
1364 {
1365     gpio_intr_available = false;
1366     gpio_data_available = false;
1367     gpio_ack_received   = false;
1368 }
1369 
1370 /*
1371  * Called when a GPIO interrupt is received from the Target.
1372  * intr_values shows which GPIO pins have interrupted.
1373  * input_values shows a recent value of GPIO pins.
1374  */
1375 void
ar6000_gpio_intr_rx(u32 intr_mask,u32 input_values)1376 ar6000_gpio_intr_rx(u32 intr_mask, u32 input_values)
1377 {
1378     gpio_intr_results.intr_mask = intr_mask;
1379     gpio_intr_results.input_values = input_values;
1380     *((volatile bool *)&gpio_intr_available) = true;
1381     wake_up(&arEvent);
1382 }
1383 
1384 /*
1385  * This is called when a response is received from the Target
1386  * for a previous or ar6000_gpio_input_get or ar6000_gpio_register_get
1387  * call.
1388  */
1389 void
ar6000_gpio_data_rx(u32 reg_id,u32 value)1390 ar6000_gpio_data_rx(u32 reg_id, u32 value)
1391 {
1392     gpio_reg_results.gpioreg_id = reg_id;
1393     gpio_reg_results.value = value;
1394     *((volatile bool *)&gpio_data_available) = true;
1395     wake_up(&arEvent);
1396 }
1397 
1398 /*
1399  * This is called when an acknowledgement is received from the Target
1400  * for a previous or ar6000_gpio_output_set or ar6000_gpio_register_set
1401  * call.
1402  */
1403 void
ar6000_gpio_ack_rx(void)1404 ar6000_gpio_ack_rx(void)
1405 {
1406     gpio_ack_received = true;
1407     wake_up(&arEvent);
1408 }
1409 
1410 int
ar6000_gpio_output_set(struct net_device * dev,u32 set_mask,u32 clear_mask,u32 enable_mask,u32 disable_mask)1411 ar6000_gpio_output_set(struct net_device *dev,
1412                        u32 set_mask,
1413                        u32 clear_mask,
1414                        u32 enable_mask,
1415                        u32 disable_mask)
1416 {
1417     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1418 
1419     gpio_ack_received = false;
1420     return wmi_gpio_output_set(ar->arWmi,
1421                 set_mask, clear_mask, enable_mask, disable_mask);
1422 }
1423 
1424 static int
ar6000_gpio_input_get(struct net_device * dev)1425 ar6000_gpio_input_get(struct net_device *dev)
1426 {
1427     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1428 
1429     *((volatile bool *)&gpio_data_available) = false;
1430     return wmi_gpio_input_get(ar->arWmi);
1431 }
1432 
1433 static int
ar6000_gpio_register_set(struct net_device * dev,u32 gpioreg_id,u32 value)1434 ar6000_gpio_register_set(struct net_device *dev,
1435                          u32 gpioreg_id,
1436                          u32 value)
1437 {
1438     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1439 
1440     gpio_ack_received = false;
1441     return wmi_gpio_register_set(ar->arWmi, gpioreg_id, value);
1442 }
1443 
1444 static int
ar6000_gpio_register_get(struct net_device * dev,u32 gpioreg_id)1445 ar6000_gpio_register_get(struct net_device *dev,
1446                          u32 gpioreg_id)
1447 {
1448     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1449 
1450     *((volatile bool *)&gpio_data_available) = false;
1451     return wmi_gpio_register_get(ar->arWmi, gpioreg_id);
1452 }
1453 
1454 static int
ar6000_gpio_intr_ack(struct net_device * dev,u32 ack_mask)1455 ar6000_gpio_intr_ack(struct net_device *dev,
1456                      u32 ack_mask)
1457 {
1458     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1459 
1460     gpio_intr_available = false;
1461     return wmi_gpio_intr_ack(ar->arWmi, ack_mask);
1462 }
1463 #endif /* CONFIG_HOST_GPIO_SUPPORT */
1464 
1465 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
1466 static struct prof_count_s prof_count_results;
1467 static bool prof_count_available; /* Requested GPIO data available */
1468 
1469 static int
prof_count_get(struct net_device * dev)1470 prof_count_get(struct net_device *dev)
1471 {
1472     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1473 
1474     *((volatile bool *)&prof_count_available) = false;
1475     return wmi_prof_count_get_cmd(ar->arWmi);
1476 }
1477 
1478 /*
1479  * This is called when a response is received from the Target
1480  * for a previous prof_count_get call.
1481  */
1482 void
prof_count_rx(u32 addr,u32 count)1483 prof_count_rx(u32 addr, u32 count)
1484 {
1485     prof_count_results.addr = addr;
1486     prof_count_results.count = count;
1487     *((volatile bool *)&prof_count_available) = true;
1488     wake_up(&arEvent);
1489 }
1490 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
1491 
1492 
1493 static int
ar6000_create_acl_data_osbuf(struct net_device * dev,u8 * userdata,void ** p_osbuf)1494 ar6000_create_acl_data_osbuf(struct net_device *dev, u8 *userdata, void **p_osbuf)
1495 {
1496     void *osbuf = NULL;
1497     u8 tmp_space[8];
1498     HCI_ACL_DATA_PKT *acl;
1499     u8 hdr_size, *datap=NULL;
1500     int ret = 0;
1501 
1502     /* ACL is in data path. There is a need to create pool
1503      * mechanism for allocating and freeing NETBUFs - ToDo later.
1504      */
1505 
1506     *p_osbuf = NULL;
1507     acl = (HCI_ACL_DATA_PKT *)tmp_space;
1508     hdr_size = sizeof(acl->hdl_and_flags) + sizeof(acl->data_len);
1509 
1510     do {
1511         if (a_copy_from_user(acl, userdata, hdr_size)) {
1512             ret = A_EFAULT;
1513             break;
1514         }
1515 
1516         osbuf = A_NETBUF_ALLOC(hdr_size + acl->data_len);
1517         if (osbuf == NULL) {
1518            ret = A_NO_MEMORY;
1519            break;
1520         }
1521         A_NETBUF_PUT(osbuf, hdr_size + acl->data_len);
1522         datap = (u8 *)A_NETBUF_DATA(osbuf);
1523 
1524         /* Real copy to osbuf */
1525         acl = (HCI_ACL_DATA_PKT *)(datap);
1526         memcpy(acl, tmp_space, hdr_size);
1527         if (a_copy_from_user(acl->data, userdata + hdr_size, acl->data_len)) {
1528             ret = A_EFAULT;
1529             break;
1530         }
1531     } while(false);
1532 
1533     if (ret == 0) {
1534         *p_osbuf = osbuf;
1535     } else {
1536         A_NETBUF_FREE(osbuf);
1537     }
1538     return ret;
1539 }
1540 
1541 
1542 
1543 int
ar6000_ioctl_ap_setparam(struct ar6_softc * ar,int param,int value)1544 ar6000_ioctl_ap_setparam(struct ar6_softc *ar, int param, int value)
1545 {
1546     int ret=0;
1547 
1548     switch(param) {
1549         case IEEE80211_PARAM_WPA:
1550             switch (value) {
1551                 case WPA_MODE_WPA1:
1552                     ar->arAuthMode = WPA_AUTH;
1553                     break;
1554                 case WPA_MODE_WPA2:
1555                     ar->arAuthMode = WPA2_AUTH;
1556                     break;
1557                 case WPA_MODE_AUTO:
1558                     ar->arAuthMode = WPA_AUTH | WPA2_AUTH;
1559                     break;
1560                 case WPA_MODE_NONE:
1561                     ar->arAuthMode = NONE_AUTH;
1562                     break;
1563             }
1564             break;
1565         case IEEE80211_PARAM_AUTHMODE:
1566             if(value == IEEE80211_AUTH_WPA_PSK) {
1567                 if (WPA_AUTH == ar->arAuthMode) {
1568                     ar->arAuthMode = WPA_PSK_AUTH;
1569                 } else if (WPA2_AUTH == ar->arAuthMode) {
1570                     ar->arAuthMode = WPA2_PSK_AUTH;
1571                 } else if ((WPA_AUTH | WPA2_AUTH) == ar->arAuthMode) {
1572                     ar->arAuthMode = WPA_PSK_AUTH | WPA2_PSK_AUTH;
1573                 } else {
1574                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Error -  Setting PSK "\
1575                         "mode when WPA param was set to %d\n",
1576                         ar->arAuthMode));
1577                     ret = -EIO;
1578                 }
1579             }
1580             break;
1581         case IEEE80211_PARAM_UCASTCIPHER:
1582             ar->arPairwiseCrypto = 0;
1583             if(value & (1<<IEEE80211_CIPHER_AES_CCM)) {
1584                 ar->arPairwiseCrypto |= AES_CRYPT;
1585             }
1586             if(value & (1<<IEEE80211_CIPHER_TKIP)) {
1587                 ar->arPairwiseCrypto |= TKIP_CRYPT;
1588             }
1589             if(!ar->arPairwiseCrypto) {
1590                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1591                            ("Error - Invalid cipher in WPA \n"));
1592                 ret = -EIO;
1593             }
1594             break;
1595         case IEEE80211_PARAM_PRIVACY:
1596             if(value == 0) {
1597                 ar->arDot11AuthMode      = OPEN_AUTH;
1598                 ar->arAuthMode           = NONE_AUTH;
1599                 ar->arPairwiseCrypto     = NONE_CRYPT;
1600                 ar->arPairwiseCryptoLen  = 0;
1601                 ar->arGroupCrypto        = NONE_CRYPT;
1602                 ar->arGroupCryptoLen     = 0;
1603             }
1604             break;
1605 #ifdef WAPI_ENABLE
1606         case IEEE80211_PARAM_WAPI:
1607             A_PRINTF("WAPI Policy: %d\n", value);
1608             ar->arDot11AuthMode      = OPEN_AUTH;
1609             ar->arAuthMode           = NONE_AUTH;
1610             if(value & 0x1) {
1611                 ar->arPairwiseCrypto     = WAPI_CRYPT;
1612                 ar->arGroupCrypto        = WAPI_CRYPT;
1613             } else {
1614                 ar->arPairwiseCrypto     = NONE_CRYPT;
1615                 ar->arGroupCrypto        = NONE_CRYPT;
1616             }
1617             break;
1618 #endif
1619     }
1620     return ret;
1621 }
1622 
1623 int
ar6000_ioctl_setparam(struct ar6_softc * ar,int param,int value)1624 ar6000_ioctl_setparam(struct ar6_softc *ar, int param, int value)
1625 {
1626     bool profChanged = false;
1627     int ret=0;
1628 
1629     if(ar->arNextMode == AP_NETWORK) {
1630         ar->ap_profile_flag = 1; /* There is a change in profile */
1631         switch (param) {
1632             case IEEE80211_PARAM_WPA:
1633             case IEEE80211_PARAM_AUTHMODE:
1634             case IEEE80211_PARAM_UCASTCIPHER:
1635             case IEEE80211_PARAM_PRIVACY:
1636             case IEEE80211_PARAM_WAPI:
1637                 ret = ar6000_ioctl_ap_setparam(ar, param, value);
1638                 return ret;
1639         }
1640     }
1641 
1642     switch (param) {
1643         case IEEE80211_PARAM_WPA:
1644             switch (value) {
1645                 case WPA_MODE_WPA1:
1646                     ar->arAuthMode = WPA_AUTH;
1647                     profChanged    = true;
1648                     break;
1649                 case WPA_MODE_WPA2:
1650                     ar->arAuthMode = WPA2_AUTH;
1651                     profChanged    = true;
1652                     break;
1653                 case WPA_MODE_NONE:
1654                     ar->arAuthMode = NONE_AUTH;
1655                     profChanged    = true;
1656                     break;
1657             }
1658             break;
1659         case IEEE80211_PARAM_AUTHMODE:
1660             switch(value) {
1661                 case IEEE80211_AUTH_WPA_PSK:
1662                     if (WPA_AUTH == ar->arAuthMode) {
1663                         ar->arAuthMode = WPA_PSK_AUTH;
1664                         profChanged    = true;
1665                     } else if (WPA2_AUTH == ar->arAuthMode) {
1666                         ar->arAuthMode = WPA2_PSK_AUTH;
1667                         profChanged    = true;
1668                     } else {
1669                         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Error -  Setting PSK "\
1670                             "mode when WPA param was set to %d\n",
1671                             ar->arAuthMode));
1672                         ret = -EIO;
1673                     }
1674                     break;
1675                 case IEEE80211_AUTH_WPA_CCKM:
1676                     if (WPA2_AUTH == ar->arAuthMode) {
1677                         ar->arAuthMode = WPA2_AUTH_CCKM;
1678                     } else {
1679                         ar->arAuthMode = WPA_AUTH_CCKM;
1680                     }
1681                     break;
1682                 default:
1683                     break;
1684             }
1685             break;
1686         case IEEE80211_PARAM_UCASTCIPHER:
1687             switch (value) {
1688                 case IEEE80211_CIPHER_AES_CCM:
1689                     ar->arPairwiseCrypto = AES_CRYPT;
1690                     profChanged          = true;
1691                     break;
1692                 case IEEE80211_CIPHER_TKIP:
1693                     ar->arPairwiseCrypto = TKIP_CRYPT;
1694                     profChanged          = true;
1695                     break;
1696                 case IEEE80211_CIPHER_WEP:
1697                     ar->arPairwiseCrypto = WEP_CRYPT;
1698                     profChanged          = true;
1699                     break;
1700                 case IEEE80211_CIPHER_NONE:
1701                     ar->arPairwiseCrypto = NONE_CRYPT;
1702                     profChanged          = true;
1703                     break;
1704             }
1705             break;
1706         case IEEE80211_PARAM_UCASTKEYLEN:
1707             if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(value)) {
1708                 ret = -EIO;
1709             } else {
1710                 ar->arPairwiseCryptoLen = value;
1711             }
1712             break;
1713         case IEEE80211_PARAM_MCASTCIPHER:
1714             switch (value) {
1715                 case IEEE80211_CIPHER_AES_CCM:
1716                     ar->arGroupCrypto = AES_CRYPT;
1717                     profChanged       = true;
1718                     break;
1719                 case IEEE80211_CIPHER_TKIP:
1720                     ar->arGroupCrypto = TKIP_CRYPT;
1721                     profChanged       = true;
1722                     break;
1723                 case IEEE80211_CIPHER_WEP:
1724                     ar->arGroupCrypto = WEP_CRYPT;
1725                     profChanged       = true;
1726                     break;
1727                 case IEEE80211_CIPHER_NONE:
1728                     ar->arGroupCrypto = NONE_CRYPT;
1729                     profChanged       = true;
1730                     break;
1731             }
1732             break;
1733         case IEEE80211_PARAM_MCASTKEYLEN:
1734             if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(value)) {
1735                 ret = -EIO;
1736             } else {
1737                 ar->arGroupCryptoLen = value;
1738             }
1739             break;
1740         case IEEE80211_PARAM_COUNTERMEASURES:
1741             if (ar->arWmiReady == false) {
1742                 return -EIO;
1743             }
1744             wmi_set_tkip_countermeasures_cmd(ar->arWmi, value);
1745             break;
1746         default:
1747             break;
1748     }
1749     if ((ar->arNextMode != AP_NETWORK) && (profChanged == true)) {
1750         /*
1751          * profile has changed.  Erase ssid to signal change
1752          */
1753         A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1754     }
1755 
1756     return ret;
1757 }
1758 
1759 int
ar6000_ioctl_setkey(struct ar6_softc * ar,struct ieee80211req_key * ik)1760 ar6000_ioctl_setkey(struct ar6_softc *ar, struct ieee80211req_key *ik)
1761 {
1762     KEY_USAGE keyUsage;
1763     int status;
1764     CRYPTO_TYPE keyType = NONE_CRYPT;
1765 
1766 #ifdef USER_KEYS
1767     ar->user_saved_keys.keyOk = false;
1768 #endif
1769     if ( (0 == memcmp(ik->ik_macaddr, null_mac, IEEE80211_ADDR_LEN)) ||
1770          (0 == memcmp(ik->ik_macaddr, bcast_mac, IEEE80211_ADDR_LEN)) ) {
1771         keyUsage = GROUP_USAGE;
1772         if(ar->arNextMode == AP_NETWORK) {
1773             memcpy(&ar->ap_mode_bkey, ik,
1774                      sizeof(struct ieee80211req_key));
1775 #ifdef WAPI_ENABLE
1776             if(ar->arPairwiseCrypto == WAPI_CRYPT) {
1777                 return ap_set_wapi_key(ar, ik);
1778             }
1779 #endif
1780         }
1781 #ifdef USER_KEYS
1782         memcpy(&ar->user_saved_keys.bcast_ik, ik,
1783                  sizeof(struct ieee80211req_key));
1784 #endif
1785     } else {
1786         keyUsage = PAIRWISE_USAGE;
1787 #ifdef USER_KEYS
1788         memcpy(&ar->user_saved_keys.ucast_ik, ik,
1789                  sizeof(struct ieee80211req_key));
1790 #endif
1791 #ifdef WAPI_ENABLE
1792         if(ar->arNextMode == AP_NETWORK) {
1793             if(ar->arPairwiseCrypto == WAPI_CRYPT) {
1794                 return ap_set_wapi_key(ar, ik);
1795             }
1796         }
1797 #endif
1798     }
1799 
1800     switch (ik->ik_type) {
1801         case IEEE80211_CIPHER_WEP:
1802             keyType = WEP_CRYPT;
1803             break;
1804         case IEEE80211_CIPHER_TKIP:
1805             keyType = TKIP_CRYPT;
1806             break;
1807         case IEEE80211_CIPHER_AES_CCM:
1808             keyType = AES_CRYPT;
1809             break;
1810         default:
1811             break;
1812     }
1813 #ifdef USER_KEYS
1814     ar->user_saved_keys.keyType = keyType;
1815 #endif
1816     if (IEEE80211_CIPHER_CCKM_KRK != ik->ik_type) {
1817         if (NONE_CRYPT == keyType) {
1818             return -EIO;
1819         }
1820 
1821         if ((WEP_CRYPT == keyType)&&(!ar->arConnected)) {
1822              int index = ik->ik_keyix;
1823 
1824             if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(ik->ik_keylen)) {
1825                 return -EIO;
1826             }
1827 
1828             A_MEMZERO(ar->arWepKeyList[index].arKey,
1829                             sizeof(ar->arWepKeyList[index].arKey));
1830             memcpy(ar->arWepKeyList[index].arKey, ik->ik_keydata, ik->ik_keylen);
1831             ar->arWepKeyList[index].arKeyLen = ik->ik_keylen;
1832 
1833             if(ik->ik_flags & IEEE80211_KEY_DEFAULT){
1834                 ar->arDefTxKeyIndex = index;
1835             }
1836 
1837             return 0;
1838         }
1839 
1840         if (((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode)) &&
1841             (GROUP_USAGE & keyUsage))
1842         {
1843             A_UNTIMEOUT(&ar->disconnect_timer);
1844         }
1845 
1846         status = wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, keyType, keyUsage,
1847                                 ik->ik_keylen, (u8 *)&ik->ik_keyrsc,
1848                                 ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr,
1849                                 SYNC_BOTH_WMIFLAG);
1850 
1851         if (status) {
1852             return -EIO;
1853         }
1854     } else {
1855         status = wmi_add_krk_cmd(ar->arWmi, ik->ik_keydata);
1856     }
1857 
1858 #ifdef USER_KEYS
1859     ar->user_saved_keys.keyOk = true;
1860 #endif
1861 
1862     return 0;
1863 }
1864 
ar6000_ioctl(struct net_device * dev,struct ifreq * rq,int cmd)1865 int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
1866 {
1867     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1868     struct hif_device *hifDevice = ar->arHifDevice;
1869     int ret = 0, param;
1870     unsigned int address = 0;
1871     unsigned int length = 0;
1872     unsigned char *buffer;
1873     char *userdata;
1874     u32 connectCtrlFlags;
1875 
1876 
1877     WMI_SET_AKMP_PARAMS_CMD  akmpParams;
1878     WMI_SET_PMKID_LIST_CMD   pmkidInfo;
1879 
1880     WMI_SET_HT_CAP_CMD htCap;
1881     WMI_SET_HT_OP_CMD htOp;
1882 
1883     /*
1884      * ioctl operations may have to wait for the Target, so we cannot hold rtnl.
1885      * Prevent the device from disappearing under us and release the lock during
1886      * the ioctl operation.
1887      */
1888     dev_hold(dev);
1889     rtnl_unlock();
1890 
1891     if (cmd == AR6000_IOCTL_EXTENDED) {
1892         /*
1893          * This allows for many more wireless ioctls than would otherwise
1894          * be available.  Applications embed the actual ioctl command in
1895          * the first word of the parameter block, and use the command
1896          * AR6000_IOCTL_EXTENDED_CMD on the ioctl call.
1897          */
1898 	if (get_user(cmd, (int *)rq->ifr_data)) {
1899 	    ret = -EFAULT;
1900 	    goto ioctl_done;
1901 	}
1902         userdata = (char *)(((unsigned int *)rq->ifr_data)+1);
1903         if(is_xioctl_allowed(ar->arNextMode, cmd) != 0) {
1904             A_PRINTF("xioctl: cmd=%d not allowed in this mode\n",cmd);
1905             ret = -EOPNOTSUPP;
1906             goto ioctl_done;
1907     }
1908     } else {
1909         int ret = is_iwioctl_allowed(ar->arNextMode, cmd);
1910         if(ret == A_ENOTSUP) {
1911             A_PRINTF("iwioctl: cmd=0x%x not allowed in this mode\n", cmd);
1912             ret = -EOPNOTSUPP;
1913             goto ioctl_done;
1914         } else if (ret == A_ERROR) {
1915             /* It is not our ioctl (out of range ioctl) */
1916             ret = -EOPNOTSUPP;
1917             goto ioctl_done;
1918         }
1919         userdata = (char *)rq->ifr_data;
1920     }
1921 
1922     if ((ar->arWlanState == WLAN_DISABLED) &&
1923         ((cmd != AR6000_XIOCTRL_WMI_SET_WLAN_STATE) &&
1924          (cmd != AR6000_XIOCTL_GET_WLAN_SLEEP_STATE) &&
1925          (cmd != AR6000_XIOCTL_DIAG_READ) &&
1926          (cmd != AR6000_XIOCTL_DIAG_WRITE) &&
1927          (cmd != AR6000_XIOCTL_SET_BT_HW_POWER_STATE) &&
1928          (cmd != AR6000_XIOCTL_GET_BT_HW_POWER_STATE) &&
1929          (cmd != AR6000_XIOCTL_ADD_AP_INTERFACE) &&
1930          (cmd != AR6000_XIOCTL_REMOVE_AP_INTERFACE) &&
1931          (cmd != AR6000_IOCTL_WMI_GETREV)))
1932     {
1933         ret = -EIO;
1934         goto ioctl_done;
1935     }
1936 
1937     ret = 0;
1938     switch(cmd)
1939     {
1940         case IEEE80211_IOCTL_SETPARAM:
1941         {
1942             int param, value;
1943             int *ptr = (int *)rq->ifr_ifru.ifru_newname;
1944             if (ar->arWmiReady == false) {
1945                 ret = -EIO;
1946             } else {
1947                 param = *ptr++;
1948                 value = *ptr;
1949                 ret = ar6000_ioctl_setparam(ar,param,value);
1950             }
1951             break;
1952         }
1953         case IEEE80211_IOCTL_SETKEY:
1954         {
1955             struct ieee80211req_key keydata;
1956             if (ar->arWmiReady == false) {
1957                 ret = -EIO;
1958             } else if (copy_from_user(&keydata, userdata,
1959                             sizeof(struct ieee80211req_key))) {
1960                 ret = -EFAULT;
1961             } else {
1962                 ar6000_ioctl_setkey(ar, &keydata);
1963             }
1964             break;
1965         }
1966         case IEEE80211_IOCTL_DELKEY:
1967         case IEEE80211_IOCTL_SETOPTIE:
1968         {
1969             //ret = -EIO;
1970             break;
1971         }
1972         case IEEE80211_IOCTL_SETMLME:
1973         {
1974             struct ieee80211req_mlme mlme;
1975             if (ar->arWmiReady == false) {
1976                 ret = -EIO;
1977             } else if (copy_from_user(&mlme, userdata,
1978                             sizeof(struct ieee80211req_mlme))) {
1979                 ret = -EFAULT;
1980             } else {
1981                 switch (mlme.im_op) {
1982                     case IEEE80211_MLME_AUTHORIZE:
1983                         A_PRINTF("setmlme AUTHORIZE %02X:%02X\n",
1984                             mlme.im_macaddr[4], mlme.im_macaddr[5]);
1985                         break;
1986                     case IEEE80211_MLME_UNAUTHORIZE:
1987                         A_PRINTF("setmlme UNAUTHORIZE %02X:%02X\n",
1988                             mlme.im_macaddr[4], mlme.im_macaddr[5]);
1989                         break;
1990                     case IEEE80211_MLME_DEAUTH:
1991                         A_PRINTF("setmlme DEAUTH %02X:%02X\n",
1992                             mlme.im_macaddr[4], mlme.im_macaddr[5]);
1993                         //remove_sta(ar, mlme.im_macaddr);
1994                         break;
1995                     case IEEE80211_MLME_DISASSOC:
1996                         A_PRINTF("setmlme DISASSOC %02X:%02X\n",
1997                             mlme.im_macaddr[4], mlme.im_macaddr[5]);
1998                         //remove_sta(ar, mlme.im_macaddr);
1999                         break;
2000                     default:
2001                         ret = 0;
2002                         goto ioctl_done;
2003                 }
2004 
2005                 wmi_ap_set_mlme(ar->arWmi, mlme.im_op, mlme.im_macaddr,
2006                                 mlme.im_reason);
2007             }
2008             break;
2009         }
2010         case IEEE80211_IOCTL_ADDPMKID:
2011         {
2012             struct ieee80211req_addpmkid  req;
2013             if (ar->arWmiReady == false) {
2014                 ret = -EIO;
2015             } else if (copy_from_user(&req, userdata, sizeof(struct ieee80211req_addpmkid))) {
2016                 ret = -EFAULT;
2017             } else {
2018                 int status;
2019 
2020                 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("Add pmkid for %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x en=%d\n",
2021                     req.pi_bssid[0], req.pi_bssid[1], req.pi_bssid[2],
2022                     req.pi_bssid[3], req.pi_bssid[4], req.pi_bssid[5],
2023                     req.pi_enable));
2024 
2025                 status = wmi_setPmkid_cmd(ar->arWmi, req.pi_bssid, req.pi_pmkid,
2026                               req.pi_enable);
2027 
2028                 if (status) {
2029                     ret = -EIO;
2030                     goto ioctl_done;
2031                 }
2032             }
2033             break;
2034         }
2035 #ifdef CONFIG_HOST_TCMD_SUPPORT
2036         case AR6000_XIOCTL_TCMD_CONT_TX:
2037             {
2038                 TCMD_CONT_TX txCmd;
2039 
2040                 if ((ar->tcmdPm == TCMD_PM_SLEEP) ||
2041                     (ar->tcmdPm == TCMD_PM_DEEPSLEEP))
2042                 {
2043                     A_PRINTF("Can NOT send tx tcmd when target is asleep! \n");
2044                     ret = -EFAULT;
2045                     goto ioctl_done;
2046                 }
2047 
2048                 if(copy_from_user(&txCmd, userdata, sizeof(TCMD_CONT_TX))) {
2049                     ret = -EFAULT;
2050                     goto ioctl_done;
2051                 } else {
2052                     wmi_test_cmd(ar->arWmi,(u8 *)&txCmd, sizeof(TCMD_CONT_TX));
2053                 }
2054             }
2055             break;
2056         case AR6000_XIOCTL_TCMD_CONT_RX:
2057             {
2058                 TCMD_CONT_RX rxCmd;
2059 
2060                 if ((ar->tcmdPm == TCMD_PM_SLEEP) ||
2061                     (ar->tcmdPm == TCMD_PM_DEEPSLEEP))
2062                 {
2063                     A_PRINTF("Can NOT send rx tcmd when target is asleep! \n");
2064                     ret = -EFAULT;
2065                     goto ioctl_done;
2066                 }
2067                 if(copy_from_user(&rxCmd, userdata, sizeof(TCMD_CONT_RX))) {
2068                     ret = -EFAULT;
2069                     goto ioctl_done;
2070                 }
2071 
2072                 switch(rxCmd.act)
2073                 {
2074                     case TCMD_CONT_RX_PROMIS:
2075                     case TCMD_CONT_RX_FILTER:
2076                     case TCMD_CONT_RX_SETMAC:
2077                     case TCMD_CONT_RX_SET_ANT_SWITCH_TABLE:
2078                          wmi_test_cmd(ar->arWmi,(u8 *)&rxCmd,
2079                                                 sizeof(TCMD_CONT_RX));
2080                          tcmdRxFreq = rxCmd.u.para.freq;
2081                          break;
2082                     case TCMD_CONT_RX_REPORT:
2083                          ar6000_ioctl_tcmd_get_rx_report(dev, rq,
2084                          (u8 *)&rxCmd, sizeof(TCMD_CONT_RX));
2085                          break;
2086                     default:
2087                          A_PRINTF("Unknown Cont Rx mode: %d\n",rxCmd.act);
2088                          ret = -EINVAL;
2089                          goto ioctl_done;
2090                 }
2091             }
2092             break;
2093         case AR6000_XIOCTL_TCMD_PM:
2094             {
2095                 TCMD_PM pmCmd;
2096 
2097                 if(copy_from_user(&pmCmd, userdata, sizeof(TCMD_PM))) {
2098                     ret = -EFAULT;
2099                     goto ioctl_done;
2100                 }
2101                 ar->tcmdPm = pmCmd.mode;
2102                 wmi_test_cmd(ar->arWmi, (u8 *)&pmCmd, sizeof(TCMD_PM));
2103             }
2104             break;
2105 #endif /* CONFIG_HOST_TCMD_SUPPORT */
2106 
2107         case AR6000_XIOCTL_BMI_DONE:
2108             if(bmienable)
2109             {
2110                 rtnl_lock(); /* ar6000_init expects to be called holding rtnl lock */
2111                 ret = ar6000_init(dev);
2112                 rtnl_unlock();
2113             }
2114             else
2115             {
2116                 ret = BMIDone(hifDevice);
2117             }
2118             break;
2119 
2120         case AR6000_XIOCTL_BMI_READ_MEMORY:
2121 	     if (get_user(address, (unsigned int *)userdata) ||
2122 		get_user(length, (unsigned int *)userdata + 1)) {
2123 		ret = -EFAULT;
2124 		break;
2125 	    }
2126 
2127             AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Read Memory (address: 0x%x, length: %d)\n",
2128                              address, length));
2129             if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) {
2130                 A_MEMZERO(buffer, length);
2131                 ret = BMIReadMemory(hifDevice, address, buffer, length);
2132                 if (copy_to_user(rq->ifr_data, buffer, length)) {
2133                     ret = -EFAULT;
2134                 }
2135                 A_FREE(buffer);
2136             } else {
2137                 ret = -ENOMEM;
2138             }
2139             break;
2140 
2141         case AR6000_XIOCTL_BMI_WRITE_MEMORY:
2142 	     if (get_user(address, (unsigned int *)userdata) ||
2143 		get_user(length, (unsigned int *)userdata + 1)) {
2144 		ret = -EFAULT;
2145 		break;
2146 	    }
2147             AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Write Memory (address: 0x%x, length: %d)\n",
2148                              address, length));
2149             if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) {
2150                 A_MEMZERO(buffer, length);
2151                 if (copy_from_user(buffer, &userdata[sizeof(address) +
2152                                    sizeof(length)], length))
2153                 {
2154                     ret = -EFAULT;
2155                 } else {
2156                     ret = BMIWriteMemory(hifDevice, address, buffer, length);
2157                 }
2158                 A_FREE(buffer);
2159             } else {
2160                 ret = -ENOMEM;
2161             }
2162             break;
2163 
2164         case AR6000_XIOCTL_BMI_TEST:
2165            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("No longer supported\n"));
2166            ret = -EOPNOTSUPP;
2167            break;
2168 
2169         case AR6000_XIOCTL_BMI_EXECUTE:
2170 	     if (get_user(address, (unsigned int *)userdata) ||
2171 		get_user(param, (unsigned int *)userdata + 1)) {
2172 		ret = -EFAULT;
2173 		break;
2174 	    }
2175             AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Execute (address: 0x%x, param: %d)\n",
2176                              address, param));
2177             ret = BMIExecute(hifDevice, address, (u32 *)&param);
2178 	    /* return value */
2179 	    if (put_user(param, (unsigned int *)rq->ifr_data)) {
2180 		ret = -EFAULT;
2181 		break;
2182 	    }
2183             break;
2184 
2185         case AR6000_XIOCTL_BMI_SET_APP_START:
2186 	    if (get_user(address, (unsigned int *)userdata)) {
2187 		ret = -EFAULT;
2188 		break;
2189 	    }
2190             AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Set App Start (address: 0x%x)\n", address));
2191             ret = BMISetAppStart(hifDevice, address);
2192             break;
2193 
2194         case AR6000_XIOCTL_BMI_READ_SOC_REGISTER:
2195 	    if (get_user(address, (unsigned int *)userdata)) {
2196 		ret = -EFAULT;
2197 		break;
2198 	    }
2199             ret = BMIReadSOCRegister(hifDevice, address, (u32 *)&param);
2200 	    /* return value */
2201 	    if (put_user(param, (unsigned int *)rq->ifr_data)) {
2202 		ret = -EFAULT;
2203 		break;
2204 	    }
2205             break;
2206 
2207         case AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER:
2208 	    if (get_user(address, (unsigned int *)userdata) ||
2209 		get_user(param, (unsigned int *)userdata + 1)) {
2210 		ret = -EFAULT;
2211 		break;
2212 	    }
2213             ret = BMIWriteSOCRegister(hifDevice, address, param);
2214             break;
2215 
2216 #ifdef HTC_RAW_INTERFACE
2217         case AR6000_XIOCTL_HTC_RAW_OPEN:
2218             ret = 0;
2219             if (!arRawIfEnabled(ar)) {
2220                 /* make sure block size is set in case the target was reset since last
2221                   * BMI phase (i.e. flashup downloads) */
2222                 ret = ar6000_set_htc_params(ar->arHifDevice,
2223                                             ar->arTargetType,
2224                                             0,  /* use default yield */
2225                                             0   /* use default number of HTC ctrl buffers */
2226                                             );
2227                 if (ret) {
2228                     break;
2229                 }
2230                 /* Terminate the BMI phase */
2231                 ret = BMIDone(hifDevice);
2232                 if (ret == 0) {
2233                     ret = ar6000_htc_raw_open(ar);
2234                 }
2235             }
2236             break;
2237 
2238         case AR6000_XIOCTL_HTC_RAW_CLOSE:
2239             if (arRawIfEnabled(ar)) {
2240                 ret = ar6000_htc_raw_close(ar);
2241                 arRawIfEnabled(ar) = false;
2242             } else {
2243                 ret = A_ERROR;
2244             }
2245             break;
2246 
2247         case AR6000_XIOCTL_HTC_RAW_READ:
2248             if (arRawIfEnabled(ar)) {
2249                 unsigned int streamID;
2250 		if (get_user(streamID, (unsigned int *)userdata) ||
2251 		    get_user(length, (unsigned int *)userdata + 1)) {
2252 		    ret = -EFAULT;
2253 		    break;
2254 		}
2255                 buffer = (unsigned char*)rq->ifr_data + sizeof(length);
2256                 ret = ar6000_htc_raw_read(ar, (HTC_RAW_STREAM_ID)streamID,
2257                                           (char*)buffer, length);
2258 		if (put_user(ret, (unsigned int *)rq->ifr_data)) {
2259 		    ret = -EFAULT;
2260 		    break;
2261 		}
2262             } else {
2263                 ret = A_ERROR;
2264             }
2265             break;
2266 
2267         case AR6000_XIOCTL_HTC_RAW_WRITE:
2268             if (arRawIfEnabled(ar)) {
2269                 unsigned int streamID;
2270 		if (get_user(streamID, (unsigned int *)userdata) ||
2271 		    get_user(length, (unsigned int *)userdata + 1)) {
2272 		    ret = -EFAULT;
2273 		    break;
2274 		}
2275                 buffer = (unsigned char*)userdata + sizeof(streamID) + sizeof(length);
2276                 ret = ar6000_htc_raw_write(ar, (HTC_RAW_STREAM_ID)streamID,
2277                                            (char*)buffer, length);
2278 		if (put_user(ret, (unsigned int *)rq->ifr_data)) {
2279 		    ret = -EFAULT;
2280 		    break;
2281 		}
2282             } else {
2283                 ret = A_ERROR;
2284             }
2285             break;
2286 #endif /* HTC_RAW_INTERFACE */
2287 
2288         case AR6000_XIOCTL_BMI_LZ_STREAM_START:
2289 	    if (get_user(address, (unsigned int *)userdata)) {
2290 		ret = -EFAULT;
2291 		break;
2292 	    }
2293             AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Start Compressed Stream (address: 0x%x)\n", address));
2294             ret = BMILZStreamStart(hifDevice, address);
2295             break;
2296 
2297         case AR6000_XIOCTL_BMI_LZ_DATA:
2298 	    if (get_user(length, (unsigned int *)userdata)) {
2299 		ret = -EFAULT;
2300 		break;
2301 	    }
2302             AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Send Compressed Data (length: %d)\n", length));
2303             if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) {
2304                 A_MEMZERO(buffer, length);
2305                 if (copy_from_user(buffer, &userdata[sizeof(length)], length))
2306                 {
2307                     ret = -EFAULT;
2308                 } else {
2309                     ret = BMILZData(hifDevice, buffer, length);
2310                 }
2311                 A_FREE(buffer);
2312             } else {
2313                 ret = -ENOMEM;
2314             }
2315             break;
2316 
2317 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
2318         /*
2319          * Optional support for Target-side profiling.
2320          * Not needed in production.
2321          */
2322 
2323         /* Configure Target-side profiling */
2324         case AR6000_XIOCTL_PROF_CFG:
2325         {
2326             u32 period;
2327             u32 nbins;
2328 	    if (get_user(period, (unsigned int *)userdata) ||
2329 		get_user(nbins, (unsigned int *)userdata + 1)) {
2330 		ret = -EFAULT;
2331 		break;
2332 	    }
2333 
2334             if (wmi_prof_cfg_cmd(ar->arWmi, period, nbins) != 0) {
2335                 ret = -EIO;
2336             }
2337 
2338             break;
2339         }
2340 
2341         /* Start a profiling bucket/bin at the specified address */
2342         case AR6000_XIOCTL_PROF_ADDR_SET:
2343         {
2344             u32 addr;
2345 	    if (get_user(addr, (unsigned int *)userdata)) {
2346 		ret = -EFAULT;
2347 		break;
2348 	    }
2349 
2350             if (wmi_prof_addr_set_cmd(ar->arWmi, addr) != 0) {
2351                 ret = -EIO;
2352             }
2353 
2354             break;
2355         }
2356 
2357         /* START Target-side profiling */
2358         case AR6000_XIOCTL_PROF_START:
2359             wmi_prof_start_cmd(ar->arWmi);
2360             break;
2361 
2362         /* STOP Target-side profiling */
2363         case AR6000_XIOCTL_PROF_STOP:
2364             wmi_prof_stop_cmd(ar->arWmi);
2365             break;
2366         case AR6000_XIOCTL_PROF_COUNT_GET:
2367         {
2368             if (ar->bIsDestroyProgress) {
2369                 ret = -EBUSY;
2370                 goto ioctl_done;
2371             }
2372             if (ar->arWmiReady == false) {
2373                 ret = -EIO;
2374                 goto ioctl_done;
2375             }
2376             if (down_interruptible(&ar->arSem)) {
2377                 ret = -ERESTARTSYS;
2378                 goto ioctl_done;
2379             }
2380             if (ar->bIsDestroyProgress) {
2381                 up(&ar->arSem);
2382                 ret = -EBUSY;
2383                 goto ioctl_done;
2384             }
2385 
2386             prof_count_available = false;
2387             ret = prof_count_get(dev);
2388             if (ret != 0) {
2389                 up(&ar->arSem);
2390                 ret = -EIO;
2391                 goto ioctl_done;
2392             }
2393 
2394             /* Wait for Target to respond. */
2395             wait_event_interruptible(arEvent, prof_count_available);
2396             if (signal_pending(current)) {
2397                 ret = -EINTR;
2398             } else {
2399                 if (copy_to_user(userdata, &prof_count_results,
2400                                  sizeof(prof_count_results)))
2401                 {
2402                     ret = -EFAULT;
2403                 }
2404             }
2405             up(&ar->arSem);
2406             break;
2407         }
2408 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
2409 
2410         case AR6000_IOCTL_WMI_GETREV:
2411         {
2412             if (copy_to_user(rq->ifr_data, &ar->arVersion,
2413                              sizeof(ar->arVersion)))
2414             {
2415                 ret = -EFAULT;
2416             }
2417             break;
2418         }
2419         case AR6000_IOCTL_WMI_SETPWR:
2420         {
2421             WMI_POWER_MODE_CMD pwrModeCmd;
2422 
2423             if (ar->arWmiReady == false) {
2424                 ret = -EIO;
2425             } else if (copy_from_user(&pwrModeCmd, userdata,
2426                                    sizeof(pwrModeCmd)))
2427             {
2428                 ret = -EFAULT;
2429             } else {
2430                 if (wmi_powermode_cmd(ar->arWmi, pwrModeCmd.powerMode)
2431                        != 0)
2432                 {
2433                     ret = -EIO;
2434                 }
2435             }
2436             break;
2437         }
2438         case AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS:
2439         {
2440             WMI_IBSS_PM_CAPS_CMD ibssPmCaps;
2441 
2442             if (ar->arWmiReady == false) {
2443                 ret = -EIO;
2444             } else if (copy_from_user(&ibssPmCaps, userdata,
2445                                    sizeof(ibssPmCaps)))
2446             {
2447                 ret = -EFAULT;
2448             } else {
2449                 if (wmi_ibsspmcaps_cmd(ar->arWmi, ibssPmCaps.power_saving, ibssPmCaps.ttl,
2450                     ibssPmCaps.atim_windows, ibssPmCaps.timeout_value) != 0)
2451                 {
2452                     ret = -EIO;
2453                 }
2454                 AR6000_SPIN_LOCK(&ar->arLock, 0);
2455                 ar->arIbssPsEnable = ibssPmCaps.power_saving;
2456                 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
2457             }
2458             break;
2459         }
2460         case AR6000_XIOCTL_WMI_SET_AP_PS:
2461         {
2462             WMI_AP_PS_CMD apPsCmd;
2463 
2464             if (ar->arWmiReady == false) {
2465                 ret = -EIO;
2466             } else if (copy_from_user(&apPsCmd, userdata,
2467                                    sizeof(apPsCmd)))
2468             {
2469                 ret = -EFAULT;
2470             } else {
2471                 if (wmi_apps_cmd(ar->arWmi, apPsCmd.psType, apPsCmd.idle_time,
2472                     apPsCmd.ps_period, apPsCmd.sleep_period) != 0)
2473                 {
2474                     ret = -EIO;
2475                 }
2476             }
2477             break;
2478         }
2479         case AR6000_IOCTL_WMI_SET_PMPARAMS:
2480         {
2481             WMI_POWER_PARAMS_CMD pmParams;
2482 
2483             if (ar->arWmiReady == false) {
2484                 ret = -EIO;
2485             } else if (copy_from_user(&pmParams, userdata,
2486                                       sizeof(pmParams)))
2487             {
2488                 ret = -EFAULT;
2489             } else {
2490                 if (wmi_pmparams_cmd(ar->arWmi, pmParams.idle_period,
2491                                      pmParams.pspoll_number,
2492                                      pmParams.dtim_policy,
2493                                      pmParams.tx_wakeup_policy,
2494                                      pmParams.num_tx_to_wakeup,
2495 #if WLAN_CONFIG_IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN
2496                                      IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN
2497 #else
2498                                      SEND_POWER_SAVE_FAIL_EVENT_ALWAYS
2499 #endif
2500                                      ) != 0)
2501                 {
2502                     ret = -EIO;
2503                 }
2504             }
2505             break;
2506         }
2507         case AR6000_IOCTL_WMI_SETSCAN:
2508         {
2509             if (ar->arWmiReady == false) {
2510                 ret = -EIO;
2511             } else if (copy_from_user(&ar->scParams, userdata,
2512                                       sizeof(ar->scParams)))
2513             {
2514                 ret = -EFAULT;
2515             } else {
2516                 if (CAN_SCAN_IN_CONNECT(ar->scParams.scanCtrlFlags)) {
2517                     ar->arSkipScan = false;
2518                 } else {
2519                     ar->arSkipScan = true;
2520                 }
2521 
2522                 if (wmi_scanparams_cmd(ar->arWmi, ar->scParams.fg_start_period,
2523                                        ar->scParams.fg_end_period,
2524                                        ar->scParams.bg_period,
2525                                        ar->scParams.minact_chdwell_time,
2526                                        ar->scParams.maxact_chdwell_time,
2527                                        ar->scParams.pas_chdwell_time,
2528                                        ar->scParams.shortScanRatio,
2529                                        ar->scParams.scanCtrlFlags,
2530                                        ar->scParams.max_dfsch_act_time,
2531                                        ar->scParams.maxact_scan_per_ssid) != 0)
2532                 {
2533                     ret = -EIO;
2534                 }
2535             }
2536             break;
2537         }
2538         case AR6000_IOCTL_WMI_SETLISTENINT:
2539         {
2540             WMI_LISTEN_INT_CMD listenCmd;
2541 
2542             if (ar->arWmiReady == false) {
2543                 ret = -EIO;
2544             } else if (copy_from_user(&listenCmd, userdata,
2545                                       sizeof(listenCmd)))
2546             {
2547                 ret = -EFAULT;
2548             } else {
2549                     if (wmi_listeninterval_cmd(ar->arWmi, listenCmd.listenInterval, listenCmd.numBeacons) != 0) {
2550                         ret = -EIO;
2551                     } else {
2552                         AR6000_SPIN_LOCK(&ar->arLock, 0);
2553                         ar->arListenIntervalT = listenCmd.listenInterval;
2554                         ar->arListenIntervalB = listenCmd.numBeacons;
2555                         AR6000_SPIN_UNLOCK(&ar->arLock, 0);
2556                     }
2557 
2558                 }
2559             break;
2560         }
2561         case AR6000_IOCTL_WMI_SET_BMISS_TIME:
2562         {
2563             WMI_BMISS_TIME_CMD bmissCmd;
2564 
2565             if (ar->arWmiReady == false) {
2566                 ret = -EIO;
2567             } else if (copy_from_user(&bmissCmd, userdata,
2568                                       sizeof(bmissCmd)))
2569             {
2570                 ret = -EFAULT;
2571             } else {
2572                 if (wmi_bmisstime_cmd(ar->arWmi, bmissCmd.bmissTime, bmissCmd.numBeacons) != 0) {
2573                     ret = -EIO;
2574                 }
2575             }
2576             break;
2577         }
2578         case AR6000_IOCTL_WMI_SETBSSFILTER:
2579         {
2580             WMI_BSS_FILTER_CMD filt;
2581 
2582             if (ar->arWmiReady == false) {
2583                 ret = -EIO;
2584             } else if (copy_from_user(&filt, userdata,
2585                                    sizeof(filt)))
2586             {
2587                 ret = -EFAULT;
2588             } else {
2589                 if (wmi_bssfilter_cmd(ar->arWmi, filt.bssFilter, filt.ieMask)
2590                         != 0) {
2591                     ret = -EIO;
2592                 } else {
2593                     ar->arUserBssFilter = filt.bssFilter;
2594                 }
2595             }
2596             break;
2597         }
2598 
2599         case AR6000_IOCTL_WMI_SET_SNRTHRESHOLD:
2600         {
2601             ret = ar6000_ioctl_set_snr_threshold(dev, rq);
2602             break;
2603         }
2604         case AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD:
2605         {
2606             ret = ar6000_ioctl_set_rssi_threshold(dev, rq);
2607             break;
2608         }
2609         case AR6000_XIOCTL_WMI_CLR_RSSISNR:
2610         {
2611             if (ar->arWmiReady == false) {
2612                 ret = -EIO;
2613             }
2614             ret = wmi_clr_rssi_snr(ar->arWmi);
2615             break;
2616         }
2617         case AR6000_XIOCTL_WMI_SET_LQTHRESHOLD:
2618         {
2619             ret = ar6000_ioctl_set_lq_threshold(dev, rq);
2620             break;
2621         }
2622         case AR6000_XIOCTL_WMI_SET_LPREAMBLE:
2623         {
2624             WMI_SET_LPREAMBLE_CMD setLpreambleCmd;
2625 
2626             if (ar->arWmiReady == false) {
2627                 ret = -EIO;
2628             } else if (copy_from_user(&setLpreambleCmd, userdata,
2629                                    sizeof(setLpreambleCmd)))
2630             {
2631                 ret = -EFAULT;
2632             } else {
2633                 if (wmi_set_lpreamble_cmd(ar->arWmi, setLpreambleCmd.status,
2634 #if WLAN_CONFIG_DONOT_IGNORE_BARKER_IN_ERP
2635                            WMI_DONOT_IGNORE_BARKER_IN_ERP
2636 #else
2637                            WMI_IGNORE_BARKER_IN_ERP
2638 #endif
2639                 ) != 0)
2640                 {
2641                     ret = -EIO;
2642                 }
2643             }
2644 
2645             break;
2646         }
2647         case AR6000_XIOCTL_WMI_SET_RTS:
2648         {
2649             WMI_SET_RTS_CMD rtsCmd;
2650             if (ar->arWmiReady == false) {
2651                 ret = -EIO;
2652             } else if (copy_from_user(&rtsCmd, userdata,
2653                                    sizeof(rtsCmd)))
2654             {
2655                 ret = -EFAULT;
2656             } else {
2657                 ar->arRTS = rtsCmd.threshold;
2658                 if (wmi_set_rts_cmd(ar->arWmi, rtsCmd.threshold)
2659                        != 0)
2660                 {
2661                     ret = -EIO;
2662                 }
2663             }
2664 
2665             break;
2666         }
2667         case AR6000_XIOCTL_WMI_SET_WMM:
2668         {
2669             ret = ar6000_ioctl_set_wmm(dev, rq);
2670             break;
2671         }
2672        case AR6000_XIOCTL_WMI_SET_QOS_SUPP:
2673         {
2674             ret = ar6000_ioctl_set_qos_supp(dev, rq);
2675             break;
2676         }
2677         case AR6000_XIOCTL_WMI_SET_TXOP:
2678         {
2679             ret = ar6000_ioctl_set_txop(dev, rq);
2680             break;
2681         }
2682         case AR6000_XIOCTL_WMI_GET_RD:
2683         {
2684             ret = ar6000_ioctl_get_rd(dev, rq);
2685             break;
2686         }
2687         case AR6000_IOCTL_WMI_SET_CHANNELPARAMS:
2688         {
2689             ret = ar6000_ioctl_set_channelParams(dev, rq);
2690             break;
2691         }
2692         case AR6000_IOCTL_WMI_SET_PROBEDSSID:
2693         {
2694             ret = ar6000_ioctl_set_probedSsid(dev, rq);
2695             break;
2696         }
2697         case AR6000_IOCTL_WMI_SET_BADAP:
2698         {
2699             ret = ar6000_ioctl_set_badAp(dev, rq);
2700             break;
2701         }
2702         case AR6000_IOCTL_WMI_CREATE_QOS:
2703         {
2704             ret = ar6000_ioctl_create_qos(dev, rq);
2705             break;
2706         }
2707         case AR6000_IOCTL_WMI_DELETE_QOS:
2708         {
2709             ret = ar6000_ioctl_delete_qos(dev, rq);
2710             break;
2711         }
2712         case AR6000_IOCTL_WMI_GET_QOS_QUEUE:
2713         {
2714             ret = ar6000_ioctl_get_qos_queue(dev, rq);
2715             break;
2716         }
2717         case AR6000_IOCTL_WMI_GET_TARGET_STATS:
2718         {
2719             ret = ar6000_ioctl_get_target_stats(dev, rq);
2720             break;
2721         }
2722         case AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK:
2723         {
2724             ret = ar6000_ioctl_set_error_report_bitmask(dev, rq);
2725             break;
2726         }
2727         case AR6000_IOCTL_WMI_SET_ASSOC_INFO:
2728         {
2729             WMI_SET_ASSOC_INFO_CMD cmd;
2730             u8 assocInfo[WMI_MAX_ASSOC_INFO_LEN];
2731 
2732             if (ar->arWmiReady == false) {
2733                 ret = -EIO;
2734 		break;
2735 	    }
2736 
2737 	    if (get_user(cmd.ieType, userdata)) {
2738 		ret = -EFAULT;
2739 		break;
2740 	    }
2741 	    if (cmd.ieType >= WMI_MAX_ASSOC_INFO_TYPE) {
2742 		ret = -EIO;
2743 		break;
2744 	    }
2745 
2746 	    if (get_user(cmd.bufferSize, userdata + 1) ||
2747 		(cmd.bufferSize > WMI_MAX_ASSOC_INFO_LEN) ||
2748 		copy_from_user(assocInfo, userdata + 2, cmd.bufferSize)) {
2749 		ret = -EFAULT;
2750 		break;
2751 	    }
2752 	    if (wmi_associnfo_cmd(ar->arWmi, cmd.ieType,
2753 				  cmd.bufferSize, assocInfo) != 0) {
2754 		ret = -EIO;
2755 		break;
2756 	    }
2757             break;
2758         }
2759         case AR6000_IOCTL_WMI_SET_ACCESS_PARAMS:
2760         {
2761             ret = ar6000_ioctl_set_access_params(dev, rq);
2762             break;
2763         }
2764         case AR6000_IOCTL_WMI_SET_DISC_TIMEOUT:
2765         {
2766             ret = ar6000_ioctl_set_disconnect_timeout(dev, rq);
2767             break;
2768         }
2769         case AR6000_XIOCTL_FORCE_TARGET_RESET:
2770         {
2771             if (ar->arHtcTarget)
2772             {
2773 //                HTCForceReset(htcTarget);
2774             }
2775             else
2776             {
2777                 AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("ar6000_ioctl cannot attempt reset.\n"));
2778             }
2779             break;
2780         }
2781         case AR6000_XIOCTL_TARGET_INFO:
2782         case AR6000_XIOCTL_CHECK_TARGET_READY: /* backwards compatibility */
2783         {
2784             /* If we made it to here, then the Target exists and is ready. */
2785 
2786             if (cmd == AR6000_XIOCTL_TARGET_INFO) {
2787                 if (copy_to_user((u32 *)rq->ifr_data, &ar->arVersion.target_ver,
2788                                  sizeof(ar->arVersion.target_ver)))
2789                 {
2790                     ret = -EFAULT;
2791                 }
2792                 if (copy_to_user(((u32 *)rq->ifr_data)+1, &ar->arTargetType,
2793                                  sizeof(ar->arTargetType)))
2794                 {
2795                     ret = -EFAULT;
2796                 }
2797             }
2798             break;
2799         }
2800         case AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS:
2801         {
2802             WMI_SET_HB_CHALLENGE_RESP_PARAMS_CMD hbparam;
2803 
2804             if (copy_from_user(&hbparam, userdata, sizeof(hbparam)))
2805             {
2806                 ret = -EFAULT;
2807             } else {
2808                 AR6000_SPIN_LOCK(&ar->arLock, 0);
2809                 /* Start a cyclic timer with the parameters provided. */
2810                 if (hbparam.frequency) {
2811                     ar->arHBChallengeResp.frequency = hbparam.frequency;
2812                 }
2813                 if (hbparam.threshold) {
2814                     ar->arHBChallengeResp.missThres = hbparam.threshold;
2815                 }
2816 
2817                 /* Delete the pending timer and start a new one */
2818                 if (timer_pending(&ar->arHBChallengeResp.timer)) {
2819                     A_UNTIMEOUT(&ar->arHBChallengeResp.timer);
2820                 }
2821                 A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0);
2822                 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
2823             }
2824             break;
2825         }
2826         case AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP:
2827         {
2828             u32 cookie;
2829 
2830             if (copy_from_user(&cookie, userdata, sizeof(cookie))) {
2831                 ret = -EFAULT;
2832                 goto ioctl_done;
2833             }
2834 
2835             /* Send the challenge on the control channel */
2836             if (wmi_get_challenge_resp_cmd(ar->arWmi, cookie, APP_HB_CHALLENGE) != 0) {
2837                 ret = -EIO;
2838                 goto ioctl_done;
2839             }
2840             break;
2841         }
2842 #ifdef USER_KEYS
2843         case AR6000_XIOCTL_USER_SETKEYS:
2844         {
2845 
2846             ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_RUN;
2847 
2848             if (copy_from_user(&ar->user_key_ctrl, userdata,
2849                                sizeof(ar->user_key_ctrl)))
2850             {
2851                 ret = -EFAULT;
2852                 goto ioctl_done;
2853             }
2854 
2855             A_PRINTF("ar6000 USER set key %x\n", ar->user_key_ctrl);
2856             break;
2857         }
2858 #endif /* USER_KEYS */
2859 
2860 #ifdef CONFIG_HOST_GPIO_SUPPORT
2861         case AR6000_XIOCTL_GPIO_OUTPUT_SET:
2862         {
2863             struct ar6000_gpio_output_set_cmd_s gpio_output_set_cmd;
2864 
2865             if (ar->bIsDestroyProgress) {
2866                 ret = -EBUSY;
2867                 goto ioctl_done;
2868             }
2869             if (ar->arWmiReady == false) {
2870                 ret = -EIO;
2871                 goto ioctl_done;
2872             }
2873             if (down_interruptible(&ar->arSem)) {
2874                 ret = -ERESTARTSYS;
2875                 goto ioctl_done;
2876             }
2877             if (ar->bIsDestroyProgress) {
2878                 up(&ar->arSem);
2879                 ret = -EBUSY;
2880                 goto ioctl_done;
2881             }
2882 
2883             if (copy_from_user(&gpio_output_set_cmd, userdata,
2884                                 sizeof(gpio_output_set_cmd)))
2885             {
2886                 ret = -EFAULT;
2887             } else {
2888                 ret = ar6000_gpio_output_set(dev,
2889                                              gpio_output_set_cmd.set_mask,
2890                                              gpio_output_set_cmd.clear_mask,
2891                                              gpio_output_set_cmd.enable_mask,
2892                                              gpio_output_set_cmd.disable_mask);
2893                 if (ret != 0) {
2894                     ret = -EIO;
2895                 }
2896             }
2897             up(&ar->arSem);
2898             break;
2899         }
2900         case AR6000_XIOCTL_GPIO_INPUT_GET:
2901         {
2902             if (ar->bIsDestroyProgress) {
2903                 ret = -EBUSY;
2904                 goto ioctl_done;
2905             }
2906             if (ar->arWmiReady == false) {
2907                 ret = -EIO;
2908                 goto ioctl_done;
2909             }
2910             if (down_interruptible(&ar->arSem)) {
2911                 ret = -ERESTARTSYS;
2912                 goto ioctl_done;
2913             }
2914             if (ar->bIsDestroyProgress) {
2915                 up(&ar->arSem);
2916                 ret = -EBUSY;
2917                 goto ioctl_done;
2918             }
2919 
2920             ret = ar6000_gpio_input_get(dev);
2921             if (ret != 0) {
2922                 up(&ar->arSem);
2923                 ret = -EIO;
2924                 goto ioctl_done;
2925             }
2926 
2927             /* Wait for Target to respond. */
2928             wait_event_interruptible(arEvent, gpio_data_available);
2929             if (signal_pending(current)) {
2930                 ret = -EINTR;
2931             } else {
2932                 A_ASSERT(gpio_reg_results.gpioreg_id == GPIO_ID_NONE);
2933 
2934                 if (copy_to_user(userdata, &gpio_reg_results.value,
2935                                  sizeof(gpio_reg_results.value)))
2936                 {
2937                     ret = -EFAULT;
2938                 }
2939             }
2940             up(&ar->arSem);
2941             break;
2942         }
2943         case AR6000_XIOCTL_GPIO_REGISTER_SET:
2944         {
2945             struct ar6000_gpio_register_cmd_s gpio_register_cmd;
2946 
2947             if (ar->bIsDestroyProgress) {
2948                 ret = -EBUSY;
2949                 goto ioctl_done;
2950             }
2951             if (ar->arWmiReady == false) {
2952                 ret = -EIO;
2953                 goto ioctl_done;
2954             }
2955             if (down_interruptible(&ar->arSem)) {
2956                 ret = -ERESTARTSYS;
2957                 goto ioctl_done;
2958             }
2959             if (ar->bIsDestroyProgress) {
2960                 up(&ar->arSem);
2961                 ret = -EBUSY;
2962                 goto ioctl_done;
2963             }
2964 
2965             if (copy_from_user(&gpio_register_cmd, userdata,
2966                                 sizeof(gpio_register_cmd)))
2967             {
2968                 ret = -EFAULT;
2969             } else {
2970                 ret = ar6000_gpio_register_set(dev,
2971                                                gpio_register_cmd.gpioreg_id,
2972                                                gpio_register_cmd.value);
2973                 if (ret != 0) {
2974                     ret = -EIO;
2975                 }
2976 
2977                 /* Wait for acknowledgement from Target */
2978                 wait_event_interruptible(arEvent, gpio_ack_received);
2979                 if (signal_pending(current)) {
2980                     ret = -EINTR;
2981                 }
2982             }
2983             up(&ar->arSem);
2984             break;
2985         }
2986         case AR6000_XIOCTL_GPIO_REGISTER_GET:
2987         {
2988             struct ar6000_gpio_register_cmd_s gpio_register_cmd;
2989 
2990             if (ar->bIsDestroyProgress) {
2991                 ret = -EBUSY;
2992                 goto ioctl_done;
2993             }
2994             if (ar->arWmiReady == false) {
2995                 ret = -EIO;
2996                 goto ioctl_done;
2997             }
2998             if (down_interruptible(&ar->arSem)) {
2999                 ret = -ERESTARTSYS;
3000                 goto ioctl_done;
3001             }
3002             if (ar->bIsDestroyProgress) {
3003                 up(&ar->arSem);
3004                 ret = -EBUSY;
3005                 goto ioctl_done;
3006             }
3007 
3008             if (copy_from_user(&gpio_register_cmd, userdata,
3009                                 sizeof(gpio_register_cmd)))
3010             {
3011                 ret = -EFAULT;
3012             } else {
3013                 ret = ar6000_gpio_register_get(dev, gpio_register_cmd.gpioreg_id);
3014                 if (ret != 0) {
3015                     up(&ar->arSem);
3016                     ret = -EIO;
3017                     goto ioctl_done;
3018                 }
3019 
3020                 /* Wait for Target to respond. */
3021                 wait_event_interruptible(arEvent, gpio_data_available);
3022                 if (signal_pending(current)) {
3023                     ret = -EINTR;
3024                 } else {
3025                     A_ASSERT(gpio_register_cmd.gpioreg_id == gpio_reg_results.gpioreg_id);
3026                     if (copy_to_user(userdata, &gpio_reg_results,
3027                                      sizeof(gpio_reg_results)))
3028                     {
3029                         ret = -EFAULT;
3030                     }
3031                 }
3032             }
3033             up(&ar->arSem);
3034             break;
3035         }
3036         case AR6000_XIOCTL_GPIO_INTR_ACK:
3037         {
3038             struct ar6000_gpio_intr_ack_cmd_s gpio_intr_ack_cmd;
3039 
3040             if (ar->bIsDestroyProgress) {
3041                 ret = -EBUSY;
3042                 goto ioctl_done;
3043             }
3044             if (ar->arWmiReady == false) {
3045                 ret = -EIO;
3046                 goto ioctl_done;
3047             }
3048             if (down_interruptible(&ar->arSem)) {
3049                 ret = -ERESTARTSYS;
3050                 goto ioctl_done;
3051             }
3052             if (ar->bIsDestroyProgress) {
3053                 up(&ar->arSem);
3054                 ret = -EBUSY;
3055                 goto ioctl_done;
3056             }
3057 
3058             if (copy_from_user(&gpio_intr_ack_cmd, userdata,
3059                                 sizeof(gpio_intr_ack_cmd)))
3060             {
3061                 ret = -EFAULT;
3062             } else {
3063                 ret = ar6000_gpio_intr_ack(dev, gpio_intr_ack_cmd.ack_mask);
3064                 if (ret != 0) {
3065                     ret = -EIO;
3066                 }
3067             }
3068             up(&ar->arSem);
3069             break;
3070         }
3071         case AR6000_XIOCTL_GPIO_INTR_WAIT:
3072         {
3073             /* Wait for Target to report an interrupt. */
3074             wait_event_interruptible(arEvent, gpio_intr_available);
3075 
3076             if (signal_pending(current)) {
3077                 ret = -EINTR;
3078             } else {
3079                 if (copy_to_user(userdata, &gpio_intr_results,
3080                                  sizeof(gpio_intr_results)))
3081                 {
3082                     ret = -EFAULT;
3083                 }
3084             }
3085             break;
3086         }
3087 #endif /* CONFIG_HOST_GPIO_SUPPORT */
3088 
3089         case AR6000_XIOCTL_DBGLOG_CFG_MODULE:
3090         {
3091             struct ar6000_dbglog_module_config_s config;
3092 
3093             if (copy_from_user(&config, userdata, sizeof(config))) {
3094                 ret = -EFAULT;
3095                 goto ioctl_done;
3096             }
3097 
3098             /* Send the challenge on the control channel */
3099             if (wmi_config_debug_module_cmd(ar->arWmi, config.mmask,
3100                                             config.tsr, config.rep,
3101                                             config.size, config.valid) != 0)
3102             {
3103                 ret = -EIO;
3104                 goto ioctl_done;
3105             }
3106             break;
3107         }
3108 
3109         case AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS:
3110         {
3111             /* Send the challenge on the control channel */
3112             if (ar6000_dbglog_get_debug_logs(ar) != 0)
3113             {
3114                 ret = -EIO;
3115                 goto ioctl_done;
3116             }
3117             break;
3118         }
3119 
3120         case AR6000_XIOCTL_SET_ADHOC_BSSID:
3121         {
3122             WMI_SET_ADHOC_BSSID_CMD adhocBssid;
3123 
3124             if (ar->arWmiReady == false) {
3125                 ret = -EIO;
3126             } else if (copy_from_user(&adhocBssid, userdata,
3127                                       sizeof(adhocBssid)))
3128             {
3129                 ret = -EFAULT;
3130             } else if (memcmp(adhocBssid.bssid, bcast_mac,
3131                                 AR6000_ETH_ADDR_LEN) == 0)
3132             {
3133                 ret = -EFAULT;
3134             } else {
3135 
3136                 memcpy(ar->arReqBssid, adhocBssid.bssid, sizeof(ar->arReqBssid));
3137         }
3138             break;
3139         }
3140 
3141         case AR6000_XIOCTL_SET_OPT_MODE:
3142         {
3143         WMI_SET_OPT_MODE_CMD optModeCmd;
3144             struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
3145 
3146             if (ar->arWmiReady == false) {
3147                 ret = -EIO;
3148             } else if (copy_from_user(&optModeCmd, userdata,
3149                                       sizeof(optModeCmd)))
3150             {
3151                 ret = -EFAULT;
3152             } else if (ar->arConnected && optModeCmd.optMode == SPECIAL_ON) {
3153                 ret = -EFAULT;
3154 
3155             } else if (wmi_set_opt_mode_cmd(ar->arWmi, optModeCmd.optMode)
3156                        != 0)
3157             {
3158                 ret = -EIO;
3159             }
3160             break;
3161         }
3162 
3163         case AR6000_XIOCTL_OPT_SEND_FRAME:
3164         {
3165             WMI_OPT_TX_FRAME_CMD optTxFrmCmd;
3166             u8 data[MAX_OPT_DATA_LEN];
3167 
3168             if (ar->arWmiReady == false) {
3169                 ret = -EIO;
3170                 break;
3171             }
3172 
3173             if (copy_from_user(&optTxFrmCmd, userdata, sizeof(optTxFrmCmd))) {
3174                 ret = -EFAULT;
3175                 break;
3176             }
3177 
3178             if (optTxFrmCmd.optIEDataLen > MAX_OPT_DATA_LEN) {
3179                 ret = -EINVAL;
3180                 break;
3181             }
3182 
3183             if (copy_from_user(data, userdata+sizeof(WMI_OPT_TX_FRAME_CMD) - 1,
3184                                    optTxFrmCmd.optIEDataLen)) {
3185                 ret = -EFAULT;
3186                 break;
3187             }
3188 
3189             ret = wmi_opt_tx_frame_cmd(ar->arWmi,
3190                                            optTxFrmCmd.frmType,
3191                                            optTxFrmCmd.dstAddr,
3192                                            optTxFrmCmd.bssid,
3193                                            optTxFrmCmd.optIEDataLen,
3194                                            data);
3195             break;
3196         }
3197         case AR6000_XIOCTL_WMI_SETRETRYLIMITS:
3198         {
3199             WMI_SET_RETRY_LIMITS_CMD setRetryParams;
3200 
3201             if (ar->arWmiReady == false) {
3202                 ret = -EIO;
3203             } else if (copy_from_user(&setRetryParams, userdata,
3204                                       sizeof(setRetryParams)))
3205             {
3206                 ret = -EFAULT;
3207             } else {
3208                 if (wmi_set_retry_limits_cmd(ar->arWmi, setRetryParams.frameType,
3209                                           setRetryParams.trafficClass,
3210                                           setRetryParams.maxRetries,
3211                                           setRetryParams.enableNotify) != 0)
3212                 {
3213                     ret = -EIO;
3214                 }
3215                 AR6000_SPIN_LOCK(&ar->arLock, 0);
3216                 ar->arMaxRetries = setRetryParams.maxRetries;
3217                 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
3218             }
3219             break;
3220         }
3221 
3222         case AR6000_XIOCTL_SET_BEACON_INTVAL:
3223         {
3224             WMI_BEACON_INT_CMD bIntvlCmd;
3225 
3226             if (ar->arWmiReady == false) {
3227                 ret = -EIO;
3228             } else if (copy_from_user(&bIntvlCmd, userdata,
3229                        sizeof(bIntvlCmd)))
3230             {
3231                 ret = -EFAULT;
3232             } else if (wmi_set_adhoc_bconIntvl_cmd(ar->arWmi, bIntvlCmd.beaconInterval)
3233                         != 0)
3234             {
3235                 ret = -EIO;
3236             }
3237             if(ret == 0) {
3238                 ar->ap_beacon_interval = bIntvlCmd.beaconInterval;
3239                 ar->ap_profile_flag = 1; /* There is a change in profile */
3240             }
3241             break;
3242         }
3243         case IEEE80211_IOCTL_SETAUTHALG:
3244         {
3245             struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
3246             struct ieee80211req_authalg req;
3247 
3248             if (ar->arWmiReady == false) {
3249                 ret = -EIO;
3250             } else if (copy_from_user(&req, userdata,
3251                        sizeof(struct ieee80211req_authalg)))
3252             {
3253                 ret = -EFAULT;
3254             } else {
3255                 if (req.auth_alg & AUTH_ALG_OPEN_SYSTEM) {
3256                     ar->arDot11AuthMode  |= OPEN_AUTH;
3257                     ar->arPairwiseCrypto  = NONE_CRYPT;
3258                     ar->arGroupCrypto     = NONE_CRYPT;
3259                 }
3260                 if (req.auth_alg & AUTH_ALG_SHARED_KEY) {
3261                     ar->arDot11AuthMode  |= SHARED_AUTH;
3262                     ar->arPairwiseCrypto  = WEP_CRYPT;
3263                     ar->arGroupCrypto     = WEP_CRYPT;
3264                     ar->arAuthMode        = NONE_AUTH;
3265                 }
3266                 if (req.auth_alg == AUTH_ALG_LEAP) {
3267                     ar->arDot11AuthMode   = LEAP_AUTH;
3268                 }
3269             }
3270             break;
3271         }
3272 
3273         case AR6000_XIOCTL_SET_VOICE_PKT_SIZE:
3274             ret = ar6000_xioctl_set_voice_pkt_size(dev, userdata);
3275             break;
3276 
3277         case AR6000_XIOCTL_SET_MAX_SP:
3278             ret = ar6000_xioctl_set_max_sp_len(dev, userdata);
3279             break;
3280 
3281         case AR6000_XIOCTL_WMI_GET_ROAM_TBL:
3282             ret = ar6000_ioctl_get_roam_tbl(dev, rq);
3283             break;
3284         case AR6000_XIOCTL_WMI_SET_ROAM_CTRL:
3285             ret = ar6000_ioctl_set_roam_ctrl(dev, userdata);
3286             break;
3287         case AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS:
3288             ret = ar6000_ioctl_set_powersave_timers(dev, userdata);
3289             break;
3290         case AR6000_XIOCTRL_WMI_GET_POWER_MODE:
3291             ret = ar6000_ioctl_get_power_mode(dev, rq);
3292             break;
3293         case AR6000_XIOCTRL_WMI_SET_WLAN_STATE:
3294         {
3295             AR6000_WLAN_STATE state;
3296 	    if (get_user(state, (unsigned int *)userdata))
3297 		ret = -EFAULT;
3298 	    else if (ar6000_set_wlan_state(ar, state) != 0)
3299                 ret = -EIO;
3300             break;
3301         }
3302         case AR6000_XIOCTL_WMI_GET_ROAM_DATA:
3303             ret = ar6000_ioctl_get_roam_data(dev, rq);
3304             break;
3305 
3306         case AR6000_XIOCTL_WMI_SET_BT_STATUS:
3307             ret = ar6000_xioctl_set_bt_status_cmd(dev, userdata);
3308             break;
3309 
3310         case AR6000_XIOCTL_WMI_SET_BT_PARAMS:
3311             ret = ar6000_xioctl_set_bt_params_cmd(dev, userdata);
3312             break;
3313 
3314 		case AR6000_XIOCTL_WMI_SET_BTCOEX_FE_ANT:
3315 			ret = ar6000_xioctl_set_btcoex_fe_ant_cmd(dev, userdata);
3316 			break;
3317 
3318 		case AR6000_XIOCTL_WMI_SET_BTCOEX_COLOCATED_BT_DEV:
3319 			ret = ar6000_xioctl_set_btcoex_colocated_bt_dev_cmd(dev, userdata);
3320 			break;
3321 
3322 		case AR6000_XIOCTL_WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG:
3323 			ret = ar6000_xioctl_set_btcoex_btinquiry_page_config_cmd(dev, userdata);
3324 			break;
3325 
3326 		case AR6000_XIOCTL_WMI_SET_BTCOEX_SCO_CONFIG:
3327 			ret = ar6000_xioctl_set_btcoex_sco_config_cmd( dev, userdata);
3328 			break;
3329 
3330 		case AR6000_XIOCTL_WMI_SET_BTCOEX_A2DP_CONFIG:
3331 			ret = ar6000_xioctl_set_btcoex_a2dp_config_cmd(dev, userdata);
3332 			break;
3333 
3334 		case AR6000_XIOCTL_WMI_SET_BTCOEX_ACLCOEX_CONFIG:
3335 			ret = ar6000_xioctl_set_btcoex_aclcoex_config_cmd(dev, userdata);
3336 			break;
3337 
3338 		case AR6000_XIOCTL_WMI_SET_BTCOEX_DEBUG:
3339 			ret = ar60000_xioctl_set_btcoex_debug_cmd(dev, userdata);
3340 			break;
3341 
3342 		case AR6000_XIOCTL_WMI_SET_BT_OPERATING_STATUS:
3343 			ret = ar6000_xioctl_set_btcoex_bt_operating_status_cmd(dev, userdata);
3344 			break;
3345 
3346 		case AR6000_XIOCTL_WMI_GET_BTCOEX_CONFIG:
3347 			ret = ar6000_xioctl_get_btcoex_config_cmd(dev, userdata, rq);
3348 			break;
3349 
3350 		case AR6000_XIOCTL_WMI_GET_BTCOEX_STATS:
3351 			ret = ar6000_xioctl_get_btcoex_stats_cmd(dev, userdata, rq);
3352 			break;
3353 
3354         case AR6000_XIOCTL_WMI_STARTSCAN:
3355         {
3356             WMI_START_SCAN_CMD setStartScanCmd, *cmdp;
3357 
3358             if (ar->arWmiReady == false) {
3359                     ret = -EIO;
3360                 } else if (copy_from_user(&setStartScanCmd, userdata,
3361                                           sizeof(setStartScanCmd)))
3362                 {
3363                     ret = -EFAULT;
3364                 } else {
3365                     if (setStartScanCmd.numChannels > 1) {
3366                         cmdp = A_MALLOC(130);
3367                         if (copy_from_user(cmdp, userdata,
3368                                            sizeof (*cmdp) +
3369                                            ((setStartScanCmd.numChannels - 1) *
3370                                            sizeof(u16))))
3371                         {
3372                             kfree(cmdp);
3373                             ret = -EFAULT;
3374                             goto ioctl_done;
3375                         }
3376                     } else {
3377                         cmdp = &setStartScanCmd;
3378                     }
3379 
3380                     if (wmi_startscan_cmd(ar->arWmi, cmdp->scanType,
3381                                           cmdp->forceFgScan,
3382                                           cmdp->isLegacy,
3383                                           cmdp->homeDwellTime,
3384                                           cmdp->forceScanInterval,
3385                                           cmdp->numChannels,
3386                                           cmdp->channelList) != 0)
3387                     {
3388                         ret = -EIO;
3389                     }
3390                 }
3391             break;
3392         }
3393         case AR6000_XIOCTL_WMI_SETFIXRATES:
3394         {
3395             WMI_FIX_RATES_CMD setFixRatesCmd;
3396             int returnStatus;
3397 
3398             if (ar->arWmiReady == false) {
3399                     ret = -EIO;
3400                 } else if (copy_from_user(&setFixRatesCmd, userdata,
3401                                           sizeof(setFixRatesCmd)))
3402                 {
3403                     ret = -EFAULT;
3404                 } else {
3405                     returnStatus = wmi_set_fixrates_cmd(ar->arWmi, setFixRatesCmd.fixRateMask);
3406                     if (returnStatus == A_EINVAL) {
3407                         ret = -EINVAL;
3408                     } else if(returnStatus != 0) {
3409                         ret = -EIO;
3410                     } else {
3411                         ar->ap_profile_flag = 1; /* There is a change in profile */
3412                     }
3413                 }
3414             break;
3415         }
3416 
3417         case AR6000_XIOCTL_WMI_GETFIXRATES:
3418         {
3419             WMI_FIX_RATES_CMD getFixRatesCmd;
3420             struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
3421             int ret = 0;
3422 
3423             if (ar->bIsDestroyProgress) {
3424                 ret = -EBUSY;
3425                 goto ioctl_done;
3426             }
3427             if (ar->arWmiReady == false) {
3428                 ret = -EIO;
3429                 goto ioctl_done;
3430             }
3431 
3432             if (down_interruptible(&ar->arSem)) {
3433                 ret = -ERESTARTSYS;
3434                 goto ioctl_done;
3435             }
3436             if (ar->bIsDestroyProgress) {
3437                 up(&ar->arSem);
3438                 ret = -EBUSY;
3439                 goto ioctl_done;
3440             }
3441             /* Used copy_from_user/copy_to_user to access user space data */
3442             if (copy_from_user(&getFixRatesCmd, userdata, sizeof(getFixRatesCmd))) {
3443                 ret = -EFAULT;
3444             } else {
3445                 ar->arRateMask = 0xFFFFFFFF;
3446 
3447                 if (wmi_get_ratemask_cmd(ar->arWmi) != 0) {
3448                     up(&ar->arSem);
3449                     ret = -EIO;
3450                     goto ioctl_done;
3451                 }
3452 
3453                 wait_event_interruptible_timeout(arEvent, ar->arRateMask != 0xFFFFFFFF, wmitimeout * HZ);
3454 
3455                 if (signal_pending(current)) {
3456                     ret = -EINTR;
3457                 }
3458 
3459                 if (!ret) {
3460                     getFixRatesCmd.fixRateMask = ar->arRateMask;
3461                 }
3462 
3463                 if(copy_to_user(userdata, &getFixRatesCmd, sizeof(getFixRatesCmd))) {
3464                    ret = -EFAULT;
3465                 }
3466 
3467                 up(&ar->arSem);
3468             }
3469             break;
3470         }
3471         case AR6000_XIOCTL_WMI_SET_AUTHMODE:
3472         {
3473             WMI_SET_AUTH_MODE_CMD setAuthMode;
3474 
3475             if (ar->arWmiReady == false) {
3476                 ret = -EIO;
3477             } else if (copy_from_user(&setAuthMode, userdata,
3478                                       sizeof(setAuthMode)))
3479             {
3480                 ret = -EFAULT;
3481             } else {
3482                 if (wmi_set_authmode_cmd(ar->arWmi, setAuthMode.mode) != 0)
3483                 {
3484                     ret = -EIO;
3485                 }
3486             }
3487             break;
3488         }
3489         case AR6000_XIOCTL_WMI_SET_REASSOCMODE:
3490         {
3491             WMI_SET_REASSOC_MODE_CMD setReassocMode;
3492 
3493             if (ar->arWmiReady == false) {
3494                 ret = -EIO;
3495             } else if (copy_from_user(&setReassocMode, userdata,
3496                                       sizeof(setReassocMode)))
3497             {
3498                 ret = -EFAULT;
3499             } else {
3500                 if (wmi_set_reassocmode_cmd(ar->arWmi, setReassocMode.mode) != 0)
3501                 {
3502                     ret = -EIO;
3503                 }
3504             }
3505             break;
3506         }
3507         case AR6000_XIOCTL_DIAG_READ:
3508         {
3509             u32 addr, data;
3510 	    if (get_user(addr, (unsigned int *)userdata)) {
3511 		ret = -EFAULT;
3512 		break;
3513 	    }
3514             addr = TARG_VTOP(ar->arTargetType, addr);
3515             if (ar6000_ReadRegDiag(ar->arHifDevice, &addr, &data) != 0) {
3516                 ret = -EIO;
3517             }
3518 	    if (put_user(data, (unsigned int *)userdata + 1)) {
3519 		ret = -EFAULT;
3520 		break;
3521 	    }
3522             break;
3523         }
3524         case AR6000_XIOCTL_DIAG_WRITE:
3525         {
3526             u32 addr, data;
3527 	    if (get_user(addr, (unsigned int *)userdata) ||
3528 		get_user(data, (unsigned int *)userdata + 1)) {
3529 		ret = -EFAULT;
3530 		break;
3531 	    }
3532             addr = TARG_VTOP(ar->arTargetType, addr);
3533             if (ar6000_WriteRegDiag(ar->arHifDevice, &addr, &data) != 0) {
3534                 ret = -EIO;
3535             }
3536             break;
3537         }
3538         case AR6000_XIOCTL_WMI_SET_KEEPALIVE:
3539         {
3540              WMI_SET_KEEPALIVE_CMD setKeepAlive;
3541              if (ar->arWmiReady == false) {
3542                  ret = -EIO;
3543                  goto ioctl_done;
3544              } else if (copy_from_user(&setKeepAlive, userdata,
3545                         sizeof(setKeepAlive))){
3546                  ret = -EFAULT;
3547              } else {
3548                  if (wmi_set_keepalive_cmd(ar->arWmi, setKeepAlive.keepaliveInterval) != 0) {
3549                      ret = -EIO;
3550                }
3551              }
3552              break;
3553         }
3554         case AR6000_XIOCTL_WMI_SET_PARAMS:
3555         {
3556              WMI_SET_PARAMS_CMD cmd;
3557              if (ar->arWmiReady == false) {
3558                  ret = -EIO;
3559                  goto ioctl_done;
3560              } else if (copy_from_user(&cmd, userdata,
3561                         sizeof(cmd))){
3562                  ret = -EFAULT;
3563              } else if (copy_from_user(&cmd, userdata,
3564                         sizeof(cmd) + cmd.length))
3565             {
3566                 ret = -EFAULT;
3567             } else {
3568                  if (wmi_set_params_cmd(ar->arWmi, cmd.opcode, cmd.length, cmd.buffer) != 0) {
3569                      ret = -EIO;
3570                }
3571              }
3572              break;
3573         }
3574         case AR6000_XIOCTL_WMI_SET_MCAST_FILTER:
3575         {
3576              WMI_SET_MCAST_FILTER_CMD cmd;
3577              if (ar->arWmiReady == false) {
3578                  ret = -EIO;
3579                  goto ioctl_done;
3580              } else if (copy_from_user(&cmd, userdata,
3581                         sizeof(cmd))){
3582                  ret = -EFAULT;
3583              } else {
3584                  if (wmi_set_mcast_filter_cmd(ar->arWmi, cmd.multicast_mac[0],
3585                                                                                      cmd.multicast_mac[1],
3586                                                                                      cmd.multicast_mac[2],
3587                                                                                      cmd.multicast_mac[3]) != 0) {
3588                      ret = -EIO;
3589                }
3590              }
3591              break;
3592         }
3593         case AR6000_XIOCTL_WMI_DEL_MCAST_FILTER:
3594         {
3595              WMI_SET_MCAST_FILTER_CMD cmd;
3596              if (ar->arWmiReady == false) {
3597                  ret = -EIO;
3598                  goto ioctl_done;
3599              } else if (copy_from_user(&cmd, userdata,
3600                         sizeof(cmd))){
3601                  ret = -EFAULT;
3602              } else {
3603                  if (wmi_del_mcast_filter_cmd(ar->arWmi, cmd.multicast_mac[0],
3604                                                                                      cmd.multicast_mac[1],
3605                                                                                      cmd.multicast_mac[2],
3606                                                                                      cmd.multicast_mac[3]) != 0) {
3607                      ret = -EIO;
3608                }
3609              }
3610              break;
3611         }
3612         case AR6000_XIOCTL_WMI_MCAST_FILTER:
3613         {
3614              WMI_MCAST_FILTER_CMD cmd;
3615              if (ar->arWmiReady == false) {
3616                  ret = -EIO;
3617                  goto ioctl_done;
3618              } else if (copy_from_user(&cmd, userdata,
3619                         sizeof(cmd))){
3620                  ret = -EFAULT;
3621              } else {
3622                  if (wmi_mcast_filter_cmd(ar->arWmi, cmd.enable)  != 0) {
3623                      ret = -EIO;
3624                }
3625              }
3626              break;
3627         }
3628         case AR6000_XIOCTL_WMI_GET_KEEPALIVE:
3629         {
3630             struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
3631             WMI_GET_KEEPALIVE_CMD getKeepAlive;
3632             int ret = 0;
3633             if (ar->bIsDestroyProgress) {
3634                 ret =-EBUSY;
3635                 goto ioctl_done;
3636             }
3637             if (ar->arWmiReady == false) {
3638                ret = -EIO;
3639                goto ioctl_done;
3640             }
3641             if (down_interruptible(&ar->arSem)) {
3642                 ret = -ERESTARTSYS;
3643                 goto ioctl_done;
3644             }
3645             if (ar->bIsDestroyProgress) {
3646                 up(&ar->arSem);
3647                 ret = -EBUSY;
3648                 goto ioctl_done;
3649             }
3650             if (copy_from_user(&getKeepAlive, userdata,sizeof(getKeepAlive))) {
3651                ret = -EFAULT;
3652             } else {
3653             getKeepAlive.keepaliveInterval = wmi_get_keepalive_cmd(ar->arWmi);
3654             ar->arKeepaliveConfigured = 0xFF;
3655             if (wmi_get_keepalive_configured(ar->arWmi) != 0){
3656                 up(&ar->arSem);
3657                 ret = -EIO;
3658                 goto ioctl_done;
3659             }
3660             wait_event_interruptible_timeout(arEvent, ar->arKeepaliveConfigured != 0xFF, wmitimeout * HZ);
3661             if (signal_pending(current)) {
3662                 ret = -EINTR;
3663             }
3664 
3665             if (!ret) {
3666                 getKeepAlive.configured = ar->arKeepaliveConfigured;
3667             }
3668             if (copy_to_user(userdata, &getKeepAlive, sizeof(getKeepAlive))) {
3669                ret = -EFAULT;
3670             }
3671             up(&ar->arSem);
3672             }
3673             break;
3674         }
3675         case AR6000_XIOCTL_WMI_SET_APPIE:
3676         {
3677             WMI_SET_APPIE_CMD appIEcmd;
3678             u8 appIeInfo[IEEE80211_APPIE_FRAME_MAX_LEN];
3679             u32 fType,ieLen;
3680 
3681             if (ar->arWmiReady == false) {
3682                 ret = -EIO;
3683                 goto ioctl_done;
3684             }
3685 	    if (get_user(fType, (u32 *)userdata)) {
3686 		ret = -EFAULT;
3687 		break;
3688 	    }
3689             appIEcmd.mgmtFrmType = fType;
3690             if (appIEcmd.mgmtFrmType >= IEEE80211_APPIE_NUM_OF_FRAME) {
3691                 ret = -EIO;
3692             } else {
3693 		if (get_user(ieLen, (u32 *)(userdata + 4))) {
3694 		    ret = -EFAULT;
3695 		    break;
3696 		}
3697                 appIEcmd.ieLen = ieLen;
3698                 A_PRINTF("WPSIE: Type-%d, Len-%d\n",appIEcmd.mgmtFrmType, appIEcmd.ieLen);
3699                 if (appIEcmd.ieLen > IEEE80211_APPIE_FRAME_MAX_LEN) {
3700                     ret = -EIO;
3701                     break;
3702                 }
3703                 if (copy_from_user(appIeInfo, userdata + 8, appIEcmd.ieLen)) {
3704                     ret = -EFAULT;
3705                 } else {
3706                     if (wmi_set_appie_cmd(ar->arWmi, appIEcmd.mgmtFrmType,
3707                                           appIEcmd.ieLen,  appIeInfo) != 0)
3708                     {
3709                         ret = -EIO;
3710                     }
3711                 }
3712             }
3713             break;
3714         }
3715         case AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER:
3716         {
3717             WMI_BSS_FILTER_CMD cmd;
3718             u32 filterType;
3719 
3720             if (copy_from_user(&filterType, userdata, sizeof(u32)))
3721             {
3722                 ret = -EFAULT;
3723                 goto ioctl_done;
3724             }
3725             if (filterType & (IEEE80211_FILTER_TYPE_BEACON |
3726                                     IEEE80211_FILTER_TYPE_PROBE_RESP))
3727             {
3728                 cmd.bssFilter = ALL_BSS_FILTER;
3729             } else {
3730                 cmd.bssFilter = NONE_BSS_FILTER;
3731             }
3732             if (wmi_bssfilter_cmd(ar->arWmi, cmd.bssFilter, 0) != 0) {
3733                 ret = -EIO;
3734             } else {
3735                 ar->arUserBssFilter = cmd.bssFilter;
3736             }
3737 
3738             AR6000_SPIN_LOCK(&ar->arLock, 0);
3739             ar->arMgmtFilter = filterType;
3740             AR6000_SPIN_UNLOCK(&ar->arLock, 0);
3741             break;
3742         }
3743         case AR6000_XIOCTL_WMI_SET_WSC_STATUS:
3744         {
3745             u32 wsc_status;
3746 
3747             if (ar->arWmiReady == false) {
3748                 ret = -EIO;
3749                 goto ioctl_done;
3750             } else if (copy_from_user(&wsc_status, userdata, sizeof(u32)))
3751             {
3752                 ret = -EFAULT;
3753                 goto ioctl_done;
3754             }
3755             if (wmi_set_wsc_status_cmd(ar->arWmi, wsc_status) != 0) {
3756                 ret = -EIO;
3757             }
3758             break;
3759         }
3760         case AR6000_XIOCTL_BMI_ROMPATCH_INSTALL:
3761         {
3762             u32 ROM_addr;
3763             u32 RAM_addr;
3764             u32 nbytes;
3765             u32 do_activate;
3766             u32 rompatch_id;
3767 
3768 	    if (get_user(ROM_addr, (u32 *)userdata) ||
3769 		get_user(RAM_addr, (u32 *)userdata + 1) ||
3770 		get_user(nbytes, (u32 *)userdata + 2) ||
3771 		get_user(do_activate, (u32 *)userdata + 3)) {
3772 		ret = -EFAULT;
3773 		break;
3774 	    }
3775             AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Install rompatch from ROM: 0x%x to RAM: 0x%x  length: %d\n",
3776                              ROM_addr, RAM_addr, nbytes));
3777             ret = BMIrompatchInstall(hifDevice, ROM_addr, RAM_addr,
3778                                         nbytes, do_activate, &rompatch_id);
3779             if (ret == 0) {
3780 		/* return value */
3781 		if (put_user(rompatch_id, (unsigned int *)rq->ifr_data)) {
3782 		    ret = -EFAULT;
3783 		    break;
3784 		}
3785             }
3786             break;
3787         }
3788 
3789         case AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL:
3790         {
3791             u32 rompatch_id;
3792 
3793 	    if (get_user(rompatch_id, (u32 *)userdata)) {
3794 		ret = -EFAULT;
3795 		break;
3796 	    }
3797             AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("UNinstall rompatch_id %d\n", rompatch_id));
3798             ret = BMIrompatchUninstall(hifDevice, rompatch_id);
3799             break;
3800         }
3801 
3802         case AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE:
3803         case AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE:
3804         {
3805             u32 rompatch_count;
3806 
3807 	    if (get_user(rompatch_count, (u32 *)userdata)) {
3808 		ret = -EFAULT;
3809 		break;
3810 	    }
3811             AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Change rompatch activation count=%d\n", rompatch_count));
3812             length = sizeof(u32) * rompatch_count;
3813             if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) {
3814                 A_MEMZERO(buffer, length);
3815                 if (copy_from_user(buffer, &userdata[sizeof(rompatch_count)], length))
3816                 {
3817                     ret = -EFAULT;
3818                 } else {
3819                     if (cmd == AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE) {
3820                         ret = BMIrompatchActivate(hifDevice, rompatch_count, (u32 *)buffer);
3821                     } else {
3822                         ret = BMIrompatchDeactivate(hifDevice, rompatch_count, (u32 *)buffer);
3823                     }
3824                 }
3825                 A_FREE(buffer);
3826             } else {
3827                 ret = -ENOMEM;
3828             }
3829 
3830             break;
3831         }
3832         case AR6000_XIOCTL_SET_IP:
3833         {
3834             WMI_SET_IP_CMD setIP;
3835 
3836             if (ar->arWmiReady == false) {
3837                 ret = -EIO;
3838             } else if (copy_from_user(&setIP, userdata,
3839                                       sizeof(setIP)))
3840             {
3841                 ret = -EFAULT;
3842             } else {
3843                 if (wmi_set_ip_cmd(ar->arWmi,
3844                                 &setIP) != 0)
3845                 {
3846                     ret = -EIO;
3847                 }
3848             }
3849             break;
3850         }
3851 
3852         case AR6000_XIOCTL_WMI_SET_HOST_SLEEP_MODE:
3853         {
3854             WMI_SET_HOST_SLEEP_MODE_CMD setHostSleepMode;
3855 
3856             if (ar->arWmiReady == false) {
3857                 ret = -EIO;
3858             } else if (copy_from_user(&setHostSleepMode, userdata,
3859                                       sizeof(setHostSleepMode)))
3860             {
3861                 ret = -EFAULT;
3862             } else {
3863                 if (wmi_set_host_sleep_mode_cmd(ar->arWmi,
3864                                 &setHostSleepMode) != 0)
3865                 {
3866                     ret = -EIO;
3867                 }
3868             }
3869             break;
3870         }
3871         case AR6000_XIOCTL_WMI_SET_WOW_MODE:
3872         {
3873             WMI_SET_WOW_MODE_CMD setWowMode;
3874 
3875             if (ar->arWmiReady == false) {
3876                 ret = -EIO;
3877             } else if (copy_from_user(&setWowMode, userdata,
3878                                       sizeof(setWowMode)))
3879             {
3880                 ret = -EFAULT;
3881             } else {
3882                 if (wmi_set_wow_mode_cmd(ar->arWmi,
3883                                 &setWowMode) != 0)
3884                 {
3885                     ret = -EIO;
3886                 }
3887             }
3888             break;
3889         }
3890         case AR6000_XIOCTL_WMI_GET_WOW_LIST:
3891         {
3892             WMI_GET_WOW_LIST_CMD getWowList;
3893 
3894             if (ar->arWmiReady == false) {
3895                 ret = -EIO;
3896             } else if (copy_from_user(&getWowList, userdata,
3897                                       sizeof(getWowList)))
3898             {
3899                 ret = -EFAULT;
3900             } else {
3901                 if (wmi_get_wow_list_cmd(ar->arWmi,
3902                                 &getWowList) != 0)
3903                 {
3904                     ret = -EIO;
3905                 }
3906             }
3907             break;
3908         }
3909         case AR6000_XIOCTL_WMI_ADD_WOW_PATTERN:
3910         {
3911 #define WOW_PATTERN_SIZE 64
3912 #define WOW_MASK_SIZE 64
3913 
3914             WMI_ADD_WOW_PATTERN_CMD cmd;
3915             u8 mask_data[WOW_PATTERN_SIZE]={0};
3916             u8 pattern_data[WOW_PATTERN_SIZE]={0};
3917 
3918             do {
3919                 if (ar->arWmiReady == false) {
3920                     ret = -EIO;
3921                     break;
3922                 }
3923                 if(copy_from_user(&cmd, userdata,
3924                             sizeof(WMI_ADD_WOW_PATTERN_CMD)))
3925                 {
3926                     ret = -EFAULT;
3927                     break;
3928                 }
3929                 if (copy_from_user(pattern_data,
3930                                       userdata + 3,
3931                                       cmd.filter_size))
3932                 {
3933                     ret = -EFAULT;
3934                     break;
3935                 }
3936                 if (copy_from_user(mask_data,
3937                                   (userdata + 3 + cmd.filter_size),
3938                                   cmd.filter_size))
3939                 {
3940                     ret = -EFAULT;
3941                     break;
3942                 }
3943                 if (wmi_add_wow_pattern_cmd(ar->arWmi,
3944                             &cmd, pattern_data, mask_data, cmd.filter_size) != 0)
3945                 {
3946                     ret = -EIO;
3947                 }
3948             } while(false);
3949 #undef WOW_PATTERN_SIZE
3950 #undef WOW_MASK_SIZE
3951             break;
3952         }
3953         case AR6000_XIOCTL_WMI_DEL_WOW_PATTERN:
3954         {
3955             WMI_DEL_WOW_PATTERN_CMD delWowPattern;
3956 
3957             if (ar->arWmiReady == false) {
3958                 ret = -EIO;
3959             } else if (copy_from_user(&delWowPattern, userdata,
3960                                       sizeof(delWowPattern)))
3961             {
3962                 ret = -EFAULT;
3963             } else {
3964                 if (wmi_del_wow_pattern_cmd(ar->arWmi,
3965                                 &delWowPattern) != 0)
3966                 {
3967                     ret = -EIO;
3968                 }
3969             }
3970             break;
3971         }
3972         case AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE:
3973             if (ar->arHtcTarget != NULL) {
3974 #ifdef ATH_DEBUG_MODULE
3975                 HTCDumpCreditStates(ar->arHtcTarget);
3976 #endif /* ATH_DEBUG_MODULE */
3977 #ifdef HTC_EP_STAT_PROFILING
3978                 {
3979                     struct htc_endpoint_stats stats;
3980                     int i;
3981 
3982                     for (i = 0; i < 5; i++) {
3983                         if (HTCGetEndpointStatistics(ar->arHtcTarget,
3984                                                      i,
3985                                                      HTC_EP_STAT_SAMPLE_AND_CLEAR,
3986                                                      &stats)) {
3987                             A_PRINTF(KERN_ALERT"------- Profiling Endpoint : %d \n", i);
3988                             A_PRINTF(KERN_ALERT"TxCreditLowIndications : %d \n", stats.TxCreditLowIndications);
3989                             A_PRINTF(KERN_ALERT"TxIssued : %d \n", stats.TxIssued);
3990                             A_PRINTF(KERN_ALERT"TxDropped: %d \n", stats.TxDropped);
3991                             A_PRINTF(KERN_ALERT"TxPacketsBundled : %d \n", stats.TxPacketsBundled);
3992                             A_PRINTF(KERN_ALERT"TxBundles : %d \n", stats.TxBundles);
3993                             A_PRINTF(KERN_ALERT"TxCreditRpts : %d \n", stats.TxCreditRpts);
3994                             A_PRINTF(KERN_ALERT"TxCreditsRptsFromRx : %d \n", stats.TxCreditRptsFromRx);
3995                             A_PRINTF(KERN_ALERT"TxCreditsRptsFromOther : %d \n", stats.TxCreditRptsFromOther);
3996                             A_PRINTF(KERN_ALERT"TxCreditsRptsFromEp0 : %d \n", stats.TxCreditRptsFromEp0);
3997                             A_PRINTF(KERN_ALERT"TxCreditsFromRx : %d \n", stats.TxCreditsFromRx);
3998                             A_PRINTF(KERN_ALERT"TxCreditsFromOther : %d \n", stats.TxCreditsFromOther);
3999                             A_PRINTF(KERN_ALERT"TxCreditsFromEp0 : %d \n", stats.TxCreditsFromEp0);
4000                             A_PRINTF(KERN_ALERT"TxCreditsConsummed : %d \n", stats.TxCreditsConsummed);
4001                             A_PRINTF(KERN_ALERT"TxCreditsReturned : %d \n", stats.TxCreditsReturned);
4002                             A_PRINTF(KERN_ALERT"RxReceived : %d \n", stats.RxReceived);
4003                             A_PRINTF(KERN_ALERT"RxPacketsBundled : %d \n", stats.RxPacketsBundled);
4004                             A_PRINTF(KERN_ALERT"RxLookAheads : %d \n", stats.RxLookAheads);
4005                             A_PRINTF(KERN_ALERT"RxBundleLookAheads : %d \n", stats.RxBundleLookAheads);
4006                             A_PRINTF(KERN_ALERT"RxBundleIndFromHdr : %d \n", stats.RxBundleIndFromHdr);
4007                             A_PRINTF(KERN_ALERT"RxAllocThreshHit : %d \n", stats.RxAllocThreshHit);
4008                             A_PRINTF(KERN_ALERT"RxAllocThreshBytes : %d \n", stats.RxAllocThreshBytes);
4009                             A_PRINTF(KERN_ALERT"---- \n");
4010 
4011                         }
4012             }
4013                 }
4014 #endif
4015             }
4016             break;
4017         case AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE:
4018             if (ar->arHtcTarget != NULL) {
4019                 struct ar6000_traffic_activity_change data;
4020 
4021                 if (copy_from_user(&data, userdata, sizeof(data)))
4022                 {
4023                     ret = -EFAULT;
4024                     goto ioctl_done;
4025                 }
4026                     /* note, this is used for testing (mbox ping testing), indicate activity
4027                      * change using the stream ID as the traffic class */
4028                 ar6000_indicate_tx_activity(ar,
4029                                             (u8)data.StreamID,
4030                                             data.Active ? true : false);
4031             }
4032             break;
4033         case AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS:
4034             if (ar->arWmiReady == false) {
4035                 ret = -EIO;
4036             } else if (copy_from_user(&connectCtrlFlags, userdata,
4037                                       sizeof(connectCtrlFlags)))
4038             {
4039                 ret = -EFAULT;
4040             } else {
4041                 ar->arConnectCtrlFlags = connectCtrlFlags;
4042             }
4043             break;
4044         case AR6000_XIOCTL_WMI_SET_AKMP_PARAMS:
4045             if (ar->arWmiReady == false) {
4046                 ret = -EIO;
4047             } else if (copy_from_user(&akmpParams, userdata,
4048                                       sizeof(WMI_SET_AKMP_PARAMS_CMD)))
4049             {
4050                 ret = -EFAULT;
4051             } else {
4052                 if (wmi_set_akmp_params_cmd(ar->arWmi, &akmpParams) != 0) {
4053                     ret = -EIO;
4054                 }
4055             }
4056             break;
4057         case AR6000_XIOCTL_WMI_SET_PMKID_LIST:
4058             if (ar->arWmiReady == false) {
4059                 ret = -EIO;
4060             } else {
4061                 if (copy_from_user(&pmkidInfo.numPMKID, userdata,
4062                                       sizeof(pmkidInfo.numPMKID)))
4063                 {
4064                     ret = -EFAULT;
4065                     break;
4066                 }
4067                 if (copy_from_user(&pmkidInfo.pmkidList,
4068                                    userdata + sizeof(pmkidInfo.numPMKID),
4069                                    pmkidInfo.numPMKID * sizeof(WMI_PMKID)))
4070                 {
4071                     ret = -EFAULT;
4072                     break;
4073                 }
4074                 if (wmi_set_pmkid_list_cmd(ar->arWmi, &pmkidInfo) != 0) {
4075                     ret = -EIO;
4076                 }
4077             }
4078             break;
4079         case AR6000_XIOCTL_WMI_GET_PMKID_LIST:
4080             if (ar->arWmiReady == false) {
4081                 ret = -EIO;
4082             } else  {
4083                 if (wmi_get_pmkid_list_cmd(ar->arWmi) != 0) {
4084                     ret = -EIO;
4085                 }
4086             }
4087             break;
4088         case AR6000_XIOCTL_WMI_ABORT_SCAN:
4089             if (ar->arWmiReady == false) {
4090                 ret = -EIO;
4091             }
4092             ret = wmi_abort_scan_cmd(ar->arWmi);
4093             break;
4094         case AR6000_XIOCTL_AP_HIDDEN_SSID:
4095         {
4096             u8 hidden_ssid;
4097             if (ar->arWmiReady == false) {
4098                 ret = -EIO;
4099             } else if (copy_from_user(&hidden_ssid, userdata, sizeof(hidden_ssid))) {
4100                 ret = -EFAULT;
4101             } else {
4102                 wmi_ap_set_hidden_ssid(ar->arWmi, hidden_ssid);
4103                 ar->ap_hidden_ssid = hidden_ssid;
4104                 ar->ap_profile_flag = 1; /* There is a change in profile */
4105             }
4106             break;
4107         }
4108         case AR6000_XIOCTL_AP_GET_STA_LIST:
4109         {
4110             if (ar->arWmiReady == false) {
4111                 ret = -EIO;
4112             } else {
4113                 u8 i;
4114                 ap_get_sta_t temp;
4115                 A_MEMZERO(&temp, sizeof(temp));
4116                 for(i=0;i<AP_MAX_NUM_STA;i++) {
4117                     memcpy(temp.sta[i].mac, ar->sta_list[i].mac, ATH_MAC_LEN);
4118                     temp.sta[i].aid = ar->sta_list[i].aid;
4119                     temp.sta[i].keymgmt = ar->sta_list[i].keymgmt;
4120                     temp.sta[i].ucipher = ar->sta_list[i].ucipher;
4121                     temp.sta[i].auth = ar->sta_list[i].auth;
4122                 }
4123                 if(copy_to_user((ap_get_sta_t *)rq->ifr_data, &temp,
4124                                  sizeof(ar->sta_list))) {
4125                     ret = -EFAULT;
4126                 }
4127             }
4128             break;
4129         }
4130         case AR6000_XIOCTL_AP_SET_NUM_STA:
4131         {
4132             u8 num_sta;
4133             if (ar->arWmiReady == false) {
4134                 ret = -EIO;
4135             } else if (copy_from_user(&num_sta, userdata, sizeof(num_sta))) {
4136                 ret = -EFAULT;
4137             } else if(num_sta > AP_MAX_NUM_STA) {
4138                 /* value out of range */
4139                 ret = -EINVAL;
4140             } else {
4141                 wmi_ap_set_num_sta(ar->arWmi, num_sta);
4142             }
4143             break;
4144         }
4145         case AR6000_XIOCTL_AP_SET_ACL_POLICY:
4146         {
4147             u8 policy;
4148             if (ar->arWmiReady == false) {
4149                 ret = -EIO;
4150             } else if (copy_from_user(&policy, userdata, sizeof(policy))) {
4151                 ret = -EFAULT;
4152             } else if(policy == ar->g_acl.policy) {
4153                 /* No change in policy */
4154             } else {
4155                 if(!(policy & AP_ACL_RETAIN_LIST_MASK)) {
4156                     /* clear ACL list */
4157                     memset(&ar->g_acl,0,sizeof(WMI_AP_ACL));
4158                 }
4159                 ar->g_acl.policy = policy;
4160                 wmi_ap_set_acl_policy(ar->arWmi, policy);
4161             }
4162             break;
4163         }
4164         case AR6000_XIOCTL_AP_SET_ACL_MAC:
4165         {
4166             WMI_AP_ACL_MAC_CMD    acl;
4167             if (ar->arWmiReady == false) {
4168                 ret = -EIO;
4169             } else if (copy_from_user(&acl, userdata, sizeof(acl))) {
4170                 ret = -EFAULT;
4171             } else {
4172                 if(acl_add_del_mac(&ar->g_acl, &acl)) {
4173                     wmi_ap_acl_mac_list(ar->arWmi, &acl);
4174                 } else {
4175                     A_PRINTF("ACL list error\n");
4176                     ret = -EIO;
4177                 }
4178             }
4179             break;
4180         }
4181         case AR6000_XIOCTL_AP_GET_ACL_LIST:
4182         {
4183             if (ar->arWmiReady == false) {
4184                 ret = -EIO;
4185             } else if(copy_to_user((WMI_AP_ACL *)rq->ifr_data, &ar->g_acl,
4186                                  sizeof(WMI_AP_ACL))) {
4187                     ret = -EFAULT;
4188             }
4189             break;
4190         }
4191         case AR6000_XIOCTL_AP_COMMIT_CONFIG:
4192         {
4193             ret = ar6000_ap_mode_profile_commit(ar);
4194             break;
4195         }
4196         case IEEE80211_IOCTL_GETWPAIE:
4197         {
4198             struct ieee80211req_wpaie wpaie;
4199             if (ar->arWmiReady == false) {
4200                 ret = -EIO;
4201             } else if (copy_from_user(&wpaie, userdata, sizeof(wpaie))) {
4202                 ret = -EFAULT;
4203             } else if (ar6000_ap_mode_get_wpa_ie(ar, &wpaie)) {
4204                 ret = -EFAULT;
4205             } else if(copy_to_user(userdata, &wpaie, sizeof(wpaie))) {
4206                 ret = -EFAULT;
4207             }
4208             break;
4209         }
4210         case AR6000_XIOCTL_AP_CONN_INACT_TIME:
4211         {
4212             u32 period;
4213             if (ar->arWmiReady == false) {
4214                 ret = -EIO;
4215             } else if (copy_from_user(&period, userdata, sizeof(period))) {
4216                 ret = -EFAULT;
4217             } else {
4218                 wmi_ap_conn_inact_time(ar->arWmi, period);
4219             }
4220             break;
4221         }
4222         case AR6000_XIOCTL_AP_PROT_SCAN_TIME:
4223         {
4224             WMI_AP_PROT_SCAN_TIME_CMD  bgscan;
4225             if (ar->arWmiReady == false) {
4226                 ret = -EIO;
4227             } else if (copy_from_user(&bgscan, userdata, sizeof(bgscan))) {
4228                 ret = -EFAULT;
4229             } else {
4230                 wmi_ap_bgscan_time(ar->arWmi, bgscan.period_min, bgscan.dwell_ms);
4231             }
4232             break;
4233         }
4234         case AR6000_XIOCTL_AP_SET_COUNTRY:
4235         {
4236             ret = ar6000_ioctl_set_country(dev, rq);
4237             break;
4238         }
4239         case AR6000_XIOCTL_AP_SET_DTIM:
4240         {
4241             WMI_AP_SET_DTIM_CMD  d;
4242             if (ar->arWmiReady == false) {
4243                 ret = -EIO;
4244             } else if (copy_from_user(&d, userdata, sizeof(d))) {
4245                 ret = -EFAULT;
4246             } else {
4247                 if(d.dtim > 0 && d.dtim < 11) {
4248                     ar->ap_dtim_period = d.dtim;
4249                     wmi_ap_set_dtim(ar->arWmi, d.dtim);
4250                     ar->ap_profile_flag = 1; /* There is a change in profile */
4251                 } else {
4252                     A_PRINTF("DTIM out of range. Valid range is [1-10]\n");
4253                     ret = -EIO;
4254                 }
4255             }
4256             break;
4257         }
4258         case AR6000_XIOCTL_WMI_TARGET_EVENT_REPORT:
4259         {
4260             WMI_SET_TARGET_EVENT_REPORT_CMD evtCfgCmd;
4261 
4262             if (ar->arWmiReady == false) {
4263                 ret = -EIO;
4264             }
4265             if (copy_from_user(&evtCfgCmd, userdata,
4266                                sizeof(evtCfgCmd))) {
4267                 ret = -EFAULT;
4268                 break;
4269             }
4270             ret = wmi_set_target_event_report_cmd(ar->arWmi, &evtCfgCmd);
4271             break;
4272         }
4273         case AR6000_XIOCTL_AP_INTRA_BSS_COMM:
4274         {
4275             u8 intra=0;
4276             if (ar->arWmiReady == false) {
4277                 ret = -EIO;
4278             } else if (copy_from_user(&intra, userdata, sizeof(intra))) {
4279                 ret = -EFAULT;
4280             } else {
4281                 ar->intra_bss = (intra?1:0);
4282             }
4283             break;
4284         }
4285         case AR6000_XIOCTL_DUMP_MODULE_DEBUG_INFO:
4286         {
4287             struct drv_debug_module_s moduleinfo;
4288 
4289             if (copy_from_user(&moduleinfo, userdata, sizeof(moduleinfo))) {
4290                 ret = -EFAULT;
4291                 break;
4292             }
4293 
4294             a_dump_module_debug_info_by_name(moduleinfo.modulename);
4295             ret = 0;
4296             break;
4297         }
4298         case AR6000_XIOCTL_MODULE_DEBUG_SET_MASK:
4299         {
4300             struct drv_debug_module_s moduleinfo;
4301 
4302             if (copy_from_user(&moduleinfo, userdata, sizeof(moduleinfo))) {
4303                 ret = -EFAULT;
4304                 break;
4305             }
4306 
4307             if (a_set_module_mask(moduleinfo.modulename, moduleinfo.mask)) {
4308                 ret = -EFAULT;
4309             }
4310 
4311             break;
4312         }
4313         case AR6000_XIOCTL_MODULE_DEBUG_GET_MASK:
4314         {
4315             struct drv_debug_module_s moduleinfo;
4316 
4317             if (copy_from_user(&moduleinfo, userdata, sizeof(moduleinfo))) {
4318                 ret = -EFAULT;
4319                 break;
4320             }
4321 
4322             if (a_get_module_mask(moduleinfo.modulename, &moduleinfo.mask)) {
4323                 ret = -EFAULT;
4324                 break;
4325             }
4326 
4327             if (copy_to_user(userdata, &moduleinfo, sizeof(moduleinfo))) {
4328                 ret = -EFAULT;
4329                 break;
4330             }
4331 
4332             break;
4333         }
4334 #ifdef ATH_AR6K_11N_SUPPORT
4335         case AR6000_XIOCTL_DUMP_RCV_AGGR_STATS:
4336         {
4337             PACKET_LOG *copy_of_pkt_log;
4338 
4339             aggr_dump_stats(ar->aggr_cntxt, &copy_of_pkt_log);
4340             if (copy_to_user(rq->ifr_data, copy_of_pkt_log, sizeof(PACKET_LOG))) {
4341                 ret = -EFAULT;
4342             }
4343             break;
4344         }
4345         case AR6000_XIOCTL_SETUP_AGGR:
4346         {
4347             WMI_ADDBA_REQ_CMD cmd;
4348 
4349             if (ar->arWmiReady == false) {
4350                 ret = -EIO;
4351             } else if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
4352                 ret = -EFAULT;
4353             } else {
4354                 wmi_setup_aggr_cmd(ar->arWmi, cmd.tid);
4355             }
4356         }
4357         break;
4358 
4359         case AR6000_XIOCTL_DELE_AGGR:
4360         {
4361             WMI_DELBA_REQ_CMD cmd;
4362 
4363             if (ar->arWmiReady == false) {
4364                 ret = -EIO;
4365             } else if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
4366                 ret = -EFAULT;
4367             } else {
4368                 wmi_delete_aggr_cmd(ar->arWmi, cmd.tid, cmd.is_sender_initiator);
4369             }
4370         }
4371         break;
4372 
4373         case AR6000_XIOCTL_ALLOW_AGGR:
4374         {
4375             WMI_ALLOW_AGGR_CMD cmd;
4376 
4377             if (ar->arWmiReady == false) {
4378                 ret = -EIO;
4379             } else if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
4380                 ret = -EFAULT;
4381             } else {
4382                 wmi_allow_aggr_cmd(ar->arWmi, cmd.tx_allow_aggr, cmd.rx_allow_aggr);
4383             }
4384         }
4385         break;
4386 
4387         case AR6000_XIOCTL_SET_HT_CAP:
4388         {
4389             if (ar->arWmiReady == false) {
4390                 ret = -EIO;
4391             } else if (copy_from_user(&htCap, userdata,
4392                                       sizeof(htCap)))
4393             {
4394                 ret = -EFAULT;
4395             } else {
4396 
4397                 if (wmi_set_ht_cap_cmd(ar->arWmi, &htCap) != 0)
4398                 {
4399                     ret = -EIO;
4400                 }
4401             }
4402             break;
4403         }
4404         case AR6000_XIOCTL_SET_HT_OP:
4405         {
4406              if (ar->arWmiReady == false) {
4407                 ret = -EIO;
4408             } else if (copy_from_user(&htOp, userdata,
4409                                       sizeof(htOp)))
4410             {
4411                  ret = -EFAULT;
4412              } else {
4413 
4414                 if (wmi_set_ht_op_cmd(ar->arWmi, htOp.sta_chan_width) != 0)
4415                 {
4416                      ret = -EIO;
4417                }
4418              }
4419              break;
4420         }
4421 #endif
4422         case AR6000_XIOCTL_ACL_DATA:
4423         {
4424             void *osbuf = NULL;
4425             if (ar->arWmiReady == false) {
4426                 ret = -EIO;
4427             } else if (ar6000_create_acl_data_osbuf(dev, (u8 *)userdata, &osbuf) != 0) {
4428                      ret = -EIO;
4429             } else {
4430                 if (wmi_data_hdr_add(ar->arWmi, osbuf, DATA_MSGTYPE, 0, WMI_DATA_HDR_DATA_TYPE_ACL,0,NULL) != 0) {
4431                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("XIOCTL_ACL_DATA - wmi_data_hdr_add failed\n"));
4432                 } else {
4433                     /* Send data buffer over HTC */
4434                     ar6000_acl_data_tx(osbuf, ar->arNetDev);
4435                 }
4436             }
4437             break;
4438         }
4439         case AR6000_XIOCTL_HCI_CMD:
4440         {
4441             char tmp_buf[512];
4442             s8 i;
4443             WMI_HCI_CMD *cmd = (WMI_HCI_CMD *)tmp_buf;
4444             u8 size;
4445 
4446             size = sizeof(cmd->cmd_buf_sz);
4447             if (ar->arWmiReady == false) {
4448                 ret = -EIO;
4449             } else if (copy_from_user(cmd, userdata, size)) {
4450                  ret = -EFAULT;
4451             } else if(copy_from_user(cmd->buf, userdata + size, cmd->cmd_buf_sz)) {
4452                     ret = -EFAULT;
4453             } else {
4454                 if (wmi_send_hci_cmd(ar->arWmi, cmd->buf, cmd->cmd_buf_sz) != 0) {
4455                      ret = -EIO;
4456                 }else if(loghci) {
4457                     A_PRINTF_LOG("HCI Command To PAL --> \n");
4458                     for(i = 0; i < cmd->cmd_buf_sz; i++) {
4459                         A_PRINTF_LOG("0x%02x ",cmd->buf[i]);
4460                         if((i % 10) == 0) {
4461                             A_PRINTF_LOG("\n");
4462                         }
4463                     }
4464                     A_PRINTF_LOG("\n");
4465                     A_PRINTF_LOG("==================================\n");
4466                 }
4467             }
4468             break;
4469         }
4470         case AR6000_XIOCTL_WLAN_CONN_PRECEDENCE:
4471         {
4472             WMI_SET_BT_WLAN_CONN_PRECEDENCE cmd;
4473             if (ar->arWmiReady == false) {
4474                 ret = -EIO;
4475             } else if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
4476                 ret = -EFAULT;
4477             } else {
4478                 if (cmd.precedence == BT_WLAN_CONN_PRECDENCE_WLAN ||
4479                             cmd.precedence == BT_WLAN_CONN_PRECDENCE_PAL) {
4480                     if ( wmi_set_wlan_conn_precedence_cmd(ar->arWmi, cmd.precedence) != 0) {
4481                         ret = -EIO;
4482                     }
4483                 } else {
4484                     ret = -EINVAL;
4485                 }
4486             }
4487             break;
4488         }
4489         case AR6000_XIOCTL_AP_GET_STAT:
4490         {
4491             ret = ar6000_ioctl_get_ap_stats(dev, rq);
4492             break;
4493         }
4494         case AR6000_XIOCTL_SET_TX_SELECT_RATES:
4495         {
4496             WMI_SET_TX_SELECT_RATES_CMD masks;
4497 
4498              if (ar->arWmiReady == false) {
4499                 ret = -EIO;
4500             } else if (copy_from_user(&masks, userdata,
4501                                       sizeof(masks)))
4502             {
4503                  ret = -EFAULT;
4504              } else {
4505 
4506                 if (wmi_set_tx_select_rates_cmd(ar->arWmi, masks.rateMasks) != 0)
4507                 {
4508                      ret = -EIO;
4509                }
4510              }
4511              break;
4512         }
4513         case AR6000_XIOCTL_AP_GET_HIDDEN_SSID:
4514         {
4515             WMI_AP_HIDDEN_SSID_CMD ssid;
4516             ssid.hidden_ssid = ar->ap_hidden_ssid;
4517 
4518             if (ar->arWmiReady == false) {
4519                 ret = -EIO;
4520             } else if(copy_to_user((WMI_AP_HIDDEN_SSID_CMD *)rq->ifr_data,
4521                                     &ssid, sizeof(WMI_AP_HIDDEN_SSID_CMD))) {
4522                     ret = -EFAULT;
4523             }
4524             break;
4525         }
4526         case AR6000_XIOCTL_AP_GET_COUNTRY:
4527         {
4528             WMI_AP_SET_COUNTRY_CMD cty;
4529             memcpy(cty.countryCode, ar->ap_country_code, 3);
4530 
4531             if (ar->arWmiReady == false) {
4532                 ret = -EIO;
4533             } else if(copy_to_user((WMI_AP_SET_COUNTRY_CMD *)rq->ifr_data,
4534                                     &cty, sizeof(WMI_AP_SET_COUNTRY_CMD))) {
4535                     ret = -EFAULT;
4536             }
4537             break;
4538         }
4539         case AR6000_XIOCTL_AP_GET_WMODE:
4540         {
4541             if (ar->arWmiReady == false) {
4542                 ret = -EIO;
4543             } else if(copy_to_user((u8 *)rq->ifr_data,
4544                                     &ar->ap_wmode, sizeof(u8))) {
4545                     ret = -EFAULT;
4546             }
4547             break;
4548         }
4549         case AR6000_XIOCTL_AP_GET_DTIM:
4550         {
4551             WMI_AP_SET_DTIM_CMD dtim;
4552             dtim.dtim = ar->ap_dtim_period;
4553 
4554             if (ar->arWmiReady == false) {
4555                 ret = -EIO;
4556             } else if(copy_to_user((WMI_AP_SET_DTIM_CMD *)rq->ifr_data,
4557                                     &dtim, sizeof(WMI_AP_SET_DTIM_CMD))) {
4558                     ret = -EFAULT;
4559             }
4560             break;
4561         }
4562         case AR6000_XIOCTL_AP_GET_BINTVL:
4563         {
4564             WMI_BEACON_INT_CMD bi;
4565             bi.beaconInterval = ar->ap_beacon_interval;
4566 
4567             if (ar->arWmiReady == false) {
4568                 ret = -EIO;
4569             } else if(copy_to_user((WMI_BEACON_INT_CMD *)rq->ifr_data,
4570                                     &bi, sizeof(WMI_BEACON_INT_CMD))) {
4571                     ret = -EFAULT;
4572             }
4573             break;
4574         }
4575         case AR6000_XIOCTL_AP_GET_RTS:
4576         {
4577             WMI_SET_RTS_CMD rts;
4578             rts.threshold = ar->arRTS;
4579 
4580             if (ar->arWmiReady == false) {
4581                 ret = -EIO;
4582             } else if(copy_to_user((WMI_SET_RTS_CMD *)rq->ifr_data,
4583                                     &rts, sizeof(WMI_SET_RTS_CMD))) {
4584                     ret = -EFAULT;
4585             }
4586             break;
4587         }
4588         case AR6000_XIOCTL_FETCH_TARGET_REGS:
4589         {
4590             u32 targregs[AR6003_FETCH_TARG_REGS_COUNT];
4591 
4592             if (ar->arTargetType == TARGET_TYPE_AR6003) {
4593                 ar6k_FetchTargetRegs(hifDevice, targregs);
4594                 if (copy_to_user((u32 *)rq->ifr_data, &targregs, sizeof(targregs)))
4595                 {
4596                     ret = -EFAULT;
4597                 }
4598             } else {
4599                 ret = -EOPNOTSUPP;
4600             }
4601             break;
4602         }
4603         case AR6000_XIOCTL_AP_SET_11BG_RATESET:
4604         {
4605             WMI_AP_SET_11BG_RATESET_CMD  rate;
4606             if (ar->arWmiReady == false) {
4607                 ret = -EIO;
4608             } else if (copy_from_user(&rate, userdata, sizeof(rate))) {
4609                 ret = -EFAULT;
4610             } else {
4611                 wmi_ap_set_rateset(ar->arWmi, rate.rateset);
4612             }
4613             break;
4614         }
4615         case AR6000_XIOCTL_GET_WLAN_SLEEP_STATE:
4616         {
4617             WMI_REPORT_SLEEP_STATE_EVENT  wmiSleepEvent ;
4618 
4619             if (ar->arWlanState == WLAN_ENABLED) {
4620                 wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_AWAKE;
4621             } else {
4622                 wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP;
4623             }
4624             rq->ifr_ifru.ifru_ivalue = ar->arWlanState; /* return value */
4625 
4626             ar6000_send_event_to_app(ar, WMI_REPORT_SLEEP_STATE_EVENTID, (u8 *)&wmiSleepEvent,
4627                                      sizeof(WMI_REPORT_SLEEP_STATE_EVENTID));
4628             break;
4629         }
4630 #ifdef CONFIG_PM
4631         case AR6000_XIOCTL_SET_BT_HW_POWER_STATE:
4632         {
4633             unsigned int state;
4634 	    if (get_user(state, (unsigned int *)userdata)) {
4635 		ret = -EFAULT;
4636 		break;
4637 	    }
4638             if (ar6000_set_bt_hw_state(ar, state)!= 0) {
4639                 ret = -EIO;
4640             }
4641         }
4642             break;
4643         case AR6000_XIOCTL_GET_BT_HW_POWER_STATE:
4644             rq->ifr_ifru.ifru_ivalue = !ar->arBTOff; /* return value */
4645             break;
4646 #endif
4647 
4648         case AR6000_XIOCTL_WMI_SET_TX_SGI_PARAM:
4649         {
4650              WMI_SET_TX_SGI_PARAM_CMD SGICmd;
4651 
4652              if (ar->arWmiReady == false) {
4653                  ret = -EIO;
4654              } else if (copy_from_user(&SGICmd, userdata,
4655                                        sizeof(SGICmd))){
4656                  ret = -EFAULT;
4657              } else{
4658                      if (wmi_SGI_cmd(ar->arWmi, SGICmd.sgiMask, SGICmd.sgiPERThreshold) != 0) {
4659                          ret = -EIO;
4660                      }
4661 
4662              }
4663              break;
4664         }
4665 
4666         case AR6000_XIOCTL_ADD_AP_INTERFACE:
4667 #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
4668         {
4669             char ap_ifname[IFNAMSIZ] = {0,};
4670             if (copy_from_user(ap_ifname, userdata, IFNAMSIZ)) {
4671                 ret = -EFAULT;
4672             } else {
4673                 if (ar6000_add_ap_interface(ar, ap_ifname) != 0) {
4674                     ret = -EIO;
4675                 }
4676             }
4677         }
4678 #else
4679             ret = -EOPNOTSUPP;
4680 #endif
4681             break;
4682         case AR6000_XIOCTL_REMOVE_AP_INTERFACE:
4683 #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
4684             if (ar6000_remove_ap_interface(ar) != 0) {
4685                 ret = -EIO;
4686             }
4687 #else
4688             ret = -EOPNOTSUPP;
4689 #endif
4690             break;
4691 
4692         case AR6000_XIOCTL_WMI_SET_EXCESS_TX_RETRY_THRES:
4693         {
4694             ret = ar6000_xioctl_set_excess_tx_retry_thres_cmd(dev, userdata);
4695             break;
4696         }
4697 
4698         default:
4699             ret = -EOPNOTSUPP;
4700     }
4701 
4702 ioctl_done:
4703     rtnl_lock(); /* restore rtnl state */
4704     dev_put(dev);
4705 
4706     return ret;
4707 }
4708 
mac_cmp_wild(u8 * mac,u8 * new_mac,u8 wild,u8 new_wild)4709 u8 mac_cmp_wild(u8 *mac, u8 *new_mac, u8 wild, u8 new_wild)
4710 {
4711     u8 i;
4712 
4713     for(i=0;i<ATH_MAC_LEN;i++) {
4714         if((wild & 1<<i) && (new_wild & 1<<i)) continue;
4715         if(mac[i] != new_mac[i]) return 1;
4716     }
4717     if((memcmp(new_mac, null_mac, 6)==0) && new_wild &&
4718         (wild != new_wild)) {
4719         return 1;
4720     }
4721 
4722     return 0;
4723 }
4724 
acl_add_del_mac(WMI_AP_ACL * a,WMI_AP_ACL_MAC_CMD * acl)4725 u8 acl_add_del_mac(WMI_AP_ACL *a, WMI_AP_ACL_MAC_CMD *acl)
4726 {
4727     s8 already_avail=-1, free_slot=-1, i;
4728 
4729     /* To check whether this mac is already there in our list */
4730     for(i=AP_ACL_SIZE-1;i>=0;i--)
4731     {
4732         if(mac_cmp_wild(a->acl_mac[i], acl->mac, a->wildcard[i],
4733             acl->wildcard)==0)
4734                 already_avail = i;
4735 
4736         if(!((1 << i) & a->index))
4737             free_slot = i;
4738     }
4739 
4740     if(acl->action == ADD_MAC_ADDR)
4741     {
4742         /* Dont add mac if it is already available */
4743         if((already_avail >= 0) || (free_slot == -1))
4744             return 0;
4745 
4746         memcpy(a->acl_mac[free_slot], acl->mac, ATH_MAC_LEN);
4747         a->index = a->index | (1 << free_slot);
4748         acl->index = free_slot;
4749         a->wildcard[free_slot] = acl->wildcard;
4750         return 1;
4751     }
4752     else if(acl->action == DEL_MAC_ADDR)
4753     {
4754         if(acl->index > AP_ACL_SIZE)
4755             return 0;
4756 
4757         if(!(a->index & (1 << acl->index)))
4758             return 0;
4759 
4760         A_MEMZERO(a->acl_mac[acl->index],ATH_MAC_LEN);
4761         a->index = a->index & ~(1 << acl->index);
4762         a->wildcard[acl->index] = 0;
4763         return 1;
4764     }
4765 
4766     return 0;
4767 }
4768