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