blob: 0daa201c6ccabc59be3f6eca3d636ab370d2d961 [file] [log] [blame]
Vipin Mehta30295c82010-09-01 12:06:33 -07001//------------------------------------------------------------------------------
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;
Joe Perchese1ce2a32011-02-02 14:05:51 -080032u32 tcmdRxFreq;
Vipin Mehta30295c82010-09-01 12:06:33 -070033extern unsigned int wmitimeout;
34extern A_WAITQUEUE_HEAD arEvent;
35extern int tspecCompliance;
36extern int bmienable;
Vipin Mehta30295c82010-09-01 12:06:33 -070037extern int loghci;
38
39static int
40ar6000_ioctl_get_roam_tbl(struct net_device *dev, struct ifreq *rq)
41{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -070042 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -070043
Joe Perches1071a132011-02-02 14:05:47 -080044 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -070045 return -EIO;
46 }
47
Joe Perches4f69cef2011-02-02 14:05:57 -080048 if(wmi_get_roam_tbl_cmd(ar->arWmi) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -070049 return -EIO;
50 }
51
52 return 0;
53}
54
55static int
56ar6000_ioctl_get_roam_data(struct net_device *dev, struct ifreq *rq)
57{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -070058 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -070059
Joe Perches1071a132011-02-02 14:05:47 -080060 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -070061 return -EIO;
62 }
63
64
65 /* currently assume only roam times are required */
Joe Perches4f69cef2011-02-02 14:05:57 -080066 if(wmi_get_roam_data_cmd(ar->arWmi, ROAM_DATA_TIME) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -070067 return -EIO;
68 }
69
70
71 return 0;
72}
73
74static int
75ar6000_ioctl_set_roam_ctrl(struct net_device *dev, char *userdata)
76{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -070077 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -070078 WMI_SET_ROAM_CTRL_CMD cmd;
Joe Perchesab3655d2011-02-02 14:05:49 -080079 u8 size = sizeof(cmd);
Vipin Mehta30295c82010-09-01 12:06:33 -070080
Joe Perches1071a132011-02-02 14:05:47 -080081 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -070082 return -EIO;
83 }
84
85
86 if (copy_from_user(&cmd, userdata, size)) {
87 return -EFAULT;
88 }
89
90 if (cmd.roamCtrlType == WMI_SET_HOST_BIAS) {
91 if (cmd.info.bssBiasInfo.numBss > 1) {
92 size += (cmd.info.bssBiasInfo.numBss - 1) * sizeof(WMI_BSS_BIAS);
93 }
94 }
95
96 if (copy_from_user(&cmd, userdata, size)) {
97 return -EFAULT;
98 }
99
Joe Perches4f69cef2011-02-02 14:05:57 -0800100 if(wmi_set_roam_ctrl_cmd(ar->arWmi, &cmd, size) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700101 return -EIO;
102 }
103
104 return 0;
105}
106
107static int
108ar6000_ioctl_set_powersave_timers(struct net_device *dev, char *userdata)
109{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700110 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700111 WMI_POWERSAVE_TIMERS_POLICY_CMD cmd;
Joe Perchesab3655d2011-02-02 14:05:49 -0800112 u8 size = sizeof(cmd);
Vipin Mehta30295c82010-09-01 12:06:33 -0700113
Joe Perches1071a132011-02-02 14:05:47 -0800114 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700115 return -EIO;
116 }
117
118 if (copy_from_user(&cmd, userdata, size)) {
119 return -EFAULT;
120 }
121
122 if (copy_from_user(&cmd, userdata, size)) {
123 return -EFAULT;
124 }
125
Joe Perches4f69cef2011-02-02 14:05:57 -0800126 if(wmi_set_powersave_timers_cmd(ar->arWmi, &cmd, size) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700127 return -EIO;
128 }
129
130 return 0;
131}
132
133static int
134ar6000_ioctl_set_qos_supp(struct net_device *dev, struct ifreq *rq)
135{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700136 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700137 WMI_SET_QOS_SUPP_CMD cmd;
Joe Perches1f4c34b2011-01-27 20:04:19 -0800138 int ret;
Vipin Mehta30295c82010-09-01 12:06:33 -0700139
140 if ((dev->flags & IFF_UP) != IFF_UP) {
141 return -EIO;
142 }
Joe Perches1071a132011-02-02 14:05:47 -0800143 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700144 return -EIO;
145 }
146
147 if (copy_from_user(&cmd, (char *)((unsigned int*)rq->ifr_data + 1),
148 sizeof(cmd)))
149 {
150 return -EFAULT;
151 }
152
153 ret = wmi_set_qos_supp_cmd(ar->arWmi, cmd.status);
154
155 switch (ret) {
Joe Perches4f69cef2011-02-02 14:05:57 -0800156 case 0:
Vipin Mehta30295c82010-09-01 12:06:33 -0700157 return 0;
158 case A_EBUSY :
159 return -EBUSY;
160 case A_NO_MEMORY:
161 return -ENOMEM;
162 case A_EINVAL:
163 default:
164 return -EFAULT;
165 }
166}
167
168static int
169ar6000_ioctl_set_wmm(struct net_device *dev, struct ifreq *rq)
170{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700171 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700172 WMI_SET_WMM_CMD cmd;
Joe Perches1f4c34b2011-01-27 20:04:19 -0800173 int ret;
Vipin Mehta30295c82010-09-01 12:06:33 -0700174
175 if ((dev->flags & IFF_UP) != IFF_UP) {
176 return -EIO;
177 }
Joe Perches1071a132011-02-02 14:05:47 -0800178 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700179 return -EIO;
180 }
181
182 if (copy_from_user(&cmd, (char *)((unsigned int*)rq->ifr_data + 1),
183 sizeof(cmd)))
184 {
185 return -EFAULT;
186 }
187
188 if (cmd.status == WMI_WMM_ENABLED) {
Joe Perches1071a132011-02-02 14:05:47 -0800189 ar->arWmmEnabled = true;
Vipin Mehta30295c82010-09-01 12:06:33 -0700190 } else {
Joe Perches1071a132011-02-02 14:05:47 -0800191 ar->arWmmEnabled = false;
Vipin Mehta30295c82010-09-01 12:06:33 -0700192 }
193
194 ret = wmi_set_wmm_cmd(ar->arWmi, cmd.status);
195
196 switch (ret) {
Joe Perches4f69cef2011-02-02 14:05:57 -0800197 case 0:
Vipin Mehta30295c82010-09-01 12:06:33 -0700198 return 0;
199 case A_EBUSY :
200 return -EBUSY;
201 case A_NO_MEMORY:
202 return -ENOMEM;
203 case A_EINVAL:
204 default:
205 return -EFAULT;
206 }
207}
208
209static int
210ar6000_ioctl_set_txop(struct net_device *dev, struct ifreq *rq)
211{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700212 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700213 WMI_SET_WMM_TXOP_CMD cmd;
Joe Perches1f4c34b2011-01-27 20:04:19 -0800214 int ret;
Vipin Mehta30295c82010-09-01 12:06:33 -0700215
216 if ((dev->flags & IFF_UP) != IFF_UP) {
217 return -EIO;
218 }
Joe Perches1071a132011-02-02 14:05:47 -0800219 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700220 return -EIO;
221 }
222
223 if (copy_from_user(&cmd, (char *)((unsigned int*)rq->ifr_data + 1),
224 sizeof(cmd)))
225 {
226 return -EFAULT;
227 }
228
229 ret = wmi_set_wmm_txop(ar->arWmi, cmd.txopEnable);
230
231 switch (ret) {
Joe Perches4f69cef2011-02-02 14:05:57 -0800232 case 0:
Vipin Mehta30295c82010-09-01 12:06:33 -0700233 return 0;
234 case A_EBUSY :
235 return -EBUSY;
236 case A_NO_MEMORY:
237 return -ENOMEM;
238 case A_EINVAL:
239 default:
240 return -EFAULT;
241 }
242}
243
244static int
245ar6000_ioctl_get_rd(struct net_device *dev, struct ifreq *rq)
246{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700247 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Joe Perches1f4c34b2011-01-27 20:04:19 -0800248 int ret = 0;
Vipin Mehta30295c82010-09-01 12:06:33 -0700249
Joe Perches1071a132011-02-02 14:05:47 -0800250 if ((dev->flags & IFF_UP) != IFF_UP || ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700251 return -EIO;
252 }
253
254 if(copy_to_user((char *)((unsigned int*)rq->ifr_data + 1),
255 &ar->arRegCode, sizeof(ar->arRegCode)))
256 ret = -EFAULT;
257
258 return ret;
259}
260
261static int
262ar6000_ioctl_set_country(struct net_device *dev, struct ifreq *rq)
263{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700264 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700265 WMI_AP_SET_COUNTRY_CMD cmd;
Joe Perches1f4c34b2011-01-27 20:04:19 -0800266 int ret;
Vipin Mehta30295c82010-09-01 12:06:33 -0700267
268 if ((dev->flags & IFF_UP) != IFF_UP) {
269 return -EIO;
270 }
Joe Perches1071a132011-02-02 14:05:47 -0800271 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700272 return -EIO;
273 }
274
275 if (copy_from_user(&cmd, (char *)((unsigned int*)rq->ifr_data + 1),
276 sizeof(cmd)))
277 {
278 return -EFAULT;
279 }
280
281 ar->ap_profile_flag = 1; /* There is a change in profile */
282
283 ret = wmi_set_country(ar->arWmi, cmd.countryCode);
Luis R. Rodriguez05209262011-03-10 18:55:29 -0800284 memcpy(ar->ap_country_code, cmd.countryCode, 3);
Vipin Mehta30295c82010-09-01 12:06:33 -0700285
286 switch (ret) {
Joe Perches4f69cef2011-02-02 14:05:57 -0800287 case 0:
Vipin Mehta30295c82010-09-01 12:06:33 -0700288 return 0;
289 case A_EBUSY :
290 return -EBUSY;
291 case A_NO_MEMORY:
292 return -ENOMEM;
293 case A_EINVAL:
294 default:
295 return -EFAULT;
296 }
297}
298
299
300/* Get power mode command */
301static int
302ar6000_ioctl_get_power_mode(struct net_device *dev, struct ifreq *rq)
303{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700304 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700305 WMI_POWER_MODE_CMD power_mode;
306 int ret = 0;
307
Joe Perches1071a132011-02-02 14:05:47 -0800308 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700309 return -EIO;
310 }
311
312 power_mode.powerMode = wmi_get_power_mode_cmd(ar->arWmi);
313 if (copy_to_user(rq->ifr_data, &power_mode, sizeof(WMI_POWER_MODE_CMD))) {
314 ret = -EFAULT;
315 }
316
317 return ret;
318}
319
320
321static int
322ar6000_ioctl_set_channelParams(struct net_device *dev, struct ifreq *rq)
323{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700324 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700325 WMI_CHANNEL_PARAMS_CMD cmd, *cmdp;
326 int ret = 0;
327
Joe Perches1071a132011-02-02 14:05:47 -0800328 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700329 return -EIO;
330 }
331
332
333 if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
334 return -EFAULT;
335 }
336
337 if( (ar->arNextMode == AP_NETWORK) && (cmd.numChannels || cmd.scanParam) ) {
338 A_PRINTF("ERROR: Only wmode is allowed in AP mode\n");
339 return -EIO;
340 }
341
342 if (cmd.numChannels > 1) {
343 cmdp = A_MALLOC(130);
344 if (copy_from_user(cmdp, rq->ifr_data,
345 sizeof (*cmdp) +
Joe Perches4853ac02011-02-02 14:05:50 -0800346 ((cmd.numChannels - 1) * sizeof(u16))))
Vipin Mehta30295c82010-09-01 12:06:33 -0700347 {
348 kfree(cmdp);
349 return -EFAULT;
350 }
351 } else {
352 cmdp = &cmd;
353 }
354
355 if ((ar->arPhyCapability == WMI_11G_CAPABILITY) &&
356 ((cmdp->phyMode == WMI_11A_MODE) || (cmdp->phyMode == WMI_11AG_MODE)))
357 {
358 ret = -EINVAL;
359 }
360
361 if (!ret &&
362 (wmi_set_channelParams_cmd(ar->arWmi, cmdp->scanParam, cmdp->phyMode,
363 cmdp->numChannels, cmdp->channelList)
Joe Perches4f69cef2011-02-02 14:05:57 -0800364 != 0))
Vipin Mehta30295c82010-09-01 12:06:33 -0700365 {
366 ret = -EIO;
367 }
368
369 if (cmd.numChannels > 1) {
370 kfree(cmdp);
371 }
372
373 ar->ap_wmode = cmdp->phyMode;
374 /* Set the profile change flag to allow a commit cmd */
375 ar->ap_profile_flag = 1;
376
377 return ret;
378}
379
380
381static int
382ar6000_ioctl_set_snr_threshold(struct net_device *dev, struct ifreq *rq)
383{
384
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700385 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700386 WMI_SNR_THRESHOLD_PARAMS_CMD cmd;
387 int ret = 0;
388
Joe Perches1071a132011-02-02 14:05:47 -0800389 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700390 return -EIO;
391 }
392
393 if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
394 return -EFAULT;
395 }
396
Joe Perches4f69cef2011-02-02 14:05:57 -0800397 if( wmi_set_snr_threshold_params(ar->arWmi, &cmd) != 0 ) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700398 ret = -EIO;
399 }
400
401 return ret;
402}
403
404static int
405ar6000_ioctl_set_rssi_threshold(struct net_device *dev, struct ifreq *rq)
406{
407#define SWAP_THOLD(thold1, thold2) do { \
408 USER_RSSI_THOLD tmpThold; \
409 tmpThold.tag = thold1.tag; \
410 tmpThold.rssi = thold1.rssi; \
411 thold1.tag = thold2.tag; \
412 thold1.rssi = thold2.rssi; \
413 thold2.tag = tmpThold.tag; \
414 thold2.rssi = tmpThold.rssi; \
415} while (0)
416
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700417 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700418 WMI_RSSI_THRESHOLD_PARAMS_CMD cmd;
419 USER_RSSI_PARAMS rssiParams;
Joe Perchesf68057e2011-02-02 14:05:55 -0800420 s32 i, j;
Vipin Mehta30295c82010-09-01 12:06:33 -0700421 int ret = 0;
422
Joe Perches1071a132011-02-02 14:05:47 -0800423 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700424 return -EIO;
425 }
426
427 if (copy_from_user((char *)&rssiParams, (char *)((unsigned int *)rq->ifr_data + 1), sizeof(USER_RSSI_PARAMS))) {
428 return -EFAULT;
429 }
430 cmd.weight = rssiParams.weight;
431 cmd.pollTime = rssiParams.pollTime;
432
Luis R. Rodriguez05209262011-03-10 18:55:29 -0800433 memcpy(ar->rssi_map, &rssiParams.tholds, sizeof(ar->rssi_map));
Vipin Mehta30295c82010-09-01 12:06:33 -0700434 /*
435 * only 6 elements, so use bubble sorting, in ascending order
436 */
437 for (i = 5; i > 0; i--) {
438 for (j = 0; j < i; j++) { /* above tholds */
439 if (ar->rssi_map[j+1].rssi < ar->rssi_map[j].rssi) {
440 SWAP_THOLD(ar->rssi_map[j+1], ar->rssi_map[j]);
441 } else if (ar->rssi_map[j+1].rssi == ar->rssi_map[j].rssi) {
Ralph Loader3ec60802011-01-21 19:27:53 +1300442 return -EFAULT;
Vipin Mehta30295c82010-09-01 12:06:33 -0700443 }
444 }
445 }
446 for (i = 11; i > 6; i--) {
447 for (j = 6; j < i; j++) { /* below tholds */
448 if (ar->rssi_map[j+1].rssi < ar->rssi_map[j].rssi) {
449 SWAP_THOLD(ar->rssi_map[j+1], ar->rssi_map[j]);
450 } else if (ar->rssi_map[j+1].rssi == ar->rssi_map[j].rssi) {
Ralph Loader3ec60802011-01-21 19:27:53 +1300451 return -EFAULT;
Vipin Mehta30295c82010-09-01 12:06:33 -0700452 }
453 }
454 }
455
456#ifdef DEBUG
457 for (i = 0; i < 12; i++) {
458 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("thold[%d].tag: %d, thold[%d].rssi: %d \n",
459 i, ar->rssi_map[i].tag, i, ar->rssi_map[i].rssi));
460 }
461#endif
462
463 if (enablerssicompensation) {
464 for (i = 0; i < 6; i++)
Joe Perches1071a132011-02-02 14:05:47 -0800465 ar->rssi_map[i].rssi = rssi_compensation_reverse_calc(ar, ar->rssi_map[i].rssi, true);
Vipin Mehta30295c82010-09-01 12:06:33 -0700466 for (i = 6; i < 12; i++)
Joe Perches1071a132011-02-02 14:05:47 -0800467 ar->rssi_map[i].rssi = rssi_compensation_reverse_calc(ar, ar->rssi_map[i].rssi, false);
Vipin Mehta30295c82010-09-01 12:06:33 -0700468 }
469
470 cmd.thresholdAbove1_Val = ar->rssi_map[0].rssi;
471 cmd.thresholdAbove2_Val = ar->rssi_map[1].rssi;
472 cmd.thresholdAbove3_Val = ar->rssi_map[2].rssi;
473 cmd.thresholdAbove4_Val = ar->rssi_map[3].rssi;
474 cmd.thresholdAbove5_Val = ar->rssi_map[4].rssi;
475 cmd.thresholdAbove6_Val = ar->rssi_map[5].rssi;
476 cmd.thresholdBelow1_Val = ar->rssi_map[6].rssi;
477 cmd.thresholdBelow2_Val = ar->rssi_map[7].rssi;
478 cmd.thresholdBelow3_Val = ar->rssi_map[8].rssi;
479 cmd.thresholdBelow4_Val = ar->rssi_map[9].rssi;
480 cmd.thresholdBelow5_Val = ar->rssi_map[10].rssi;
481 cmd.thresholdBelow6_Val = ar->rssi_map[11].rssi;
482
Joe Perches4f69cef2011-02-02 14:05:57 -0800483 if( wmi_set_rssi_threshold_params(ar->arWmi, &cmd) != 0 ) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700484 ret = -EIO;
485 }
486
487 return ret;
488}
489
490static int
491ar6000_ioctl_set_lq_threshold(struct net_device *dev, struct ifreq *rq)
492{
493
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700494 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700495 WMI_LQ_THRESHOLD_PARAMS_CMD cmd;
496 int ret = 0;
497
Joe Perches1071a132011-02-02 14:05:47 -0800498 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700499 return -EIO;
500 }
501
502 if (copy_from_user(&cmd, (char *)((unsigned int *)rq->ifr_data + 1), sizeof(cmd))) {
503 return -EFAULT;
504 }
505
Joe Perches4f69cef2011-02-02 14:05:57 -0800506 if( wmi_set_lq_threshold_params(ar->arWmi, &cmd) != 0 ) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700507 ret = -EIO;
508 }
509
510 return ret;
511}
512
513
514static int
515ar6000_ioctl_set_probedSsid(struct net_device *dev, struct ifreq *rq)
516{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700517 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700518 WMI_PROBED_SSID_CMD cmd;
519 int ret = 0;
520
Joe Perches1071a132011-02-02 14:05:47 -0800521 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700522 return -EIO;
523 }
524
525 if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
526 return -EFAULT;
527 }
528
529 if (wmi_probedSsid_cmd(ar->arWmi, cmd.entryIndex, cmd.flag, cmd.ssidLength,
Joe Perches4f69cef2011-02-02 14:05:57 -0800530 cmd.ssid) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -0700531 {
532 ret = -EIO;
533 }
534
535 return ret;
536}
537
538static int
539ar6000_ioctl_set_badAp(struct net_device *dev, struct ifreq *rq)
540{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700541 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700542 WMI_ADD_BAD_AP_CMD cmd;
543 int ret = 0;
544
Joe Perches1071a132011-02-02 14:05:47 -0800545 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700546 return -EIO;
547 }
548
549
550 if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
551 return -EFAULT;
552 }
553
554 if (cmd.badApIndex > WMI_MAX_BAD_AP_INDEX) {
555 return -EIO;
556 }
557
Luis R. Rodriguez395e1ca2011-03-10 18:55:30 -0800558 if (memcmp(cmd.bssid, null_mac, AR6000_ETH_ADDR_LEN) == 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700559 /*
560 * This is a delete badAP.
561 */
Joe Perches4f69cef2011-02-02 14:05:57 -0800562 if (wmi_deleteBadAp_cmd(ar->arWmi, cmd.badApIndex) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700563 ret = -EIO;
564 }
565 } else {
Joe Perches4f69cef2011-02-02 14:05:57 -0800566 if (wmi_addBadAp_cmd(ar->arWmi, cmd.badApIndex, cmd.bssid) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700567 ret = -EIO;
568 }
569 }
570
571 return ret;
572}
573
574static int
575ar6000_ioctl_create_qos(struct net_device *dev, struct ifreq *rq)
576{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700577 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700578 WMI_CREATE_PSTREAM_CMD cmd;
Joe Perches1f4c34b2011-01-27 20:04:19 -0800579 int ret;
Vipin Mehta30295c82010-09-01 12:06:33 -0700580
Joe Perches1071a132011-02-02 14:05:47 -0800581 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700582 return -EIO;
583 }
584
585
586 if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
587 return -EFAULT;
588 }
589
590 ret = wmi_verify_tspec_params(&cmd, tspecCompliance);
Joe Perches4f69cef2011-02-02 14:05:57 -0800591 if (ret == 0)
Vipin Mehta30295c82010-09-01 12:06:33 -0700592 ret = wmi_create_pstream_cmd(ar->arWmi, &cmd);
593
594 switch (ret) {
Joe Perches4f69cef2011-02-02 14:05:57 -0800595 case 0:
Vipin Mehta30295c82010-09-01 12:06:33 -0700596 return 0;
597 case A_EBUSY :
598 return -EBUSY;
599 case A_NO_MEMORY:
600 return -ENOMEM;
601 case A_EINVAL:
602 default:
603 return -EFAULT;
604 }
605}
606
607static int
608ar6000_ioctl_delete_qos(struct net_device *dev, struct ifreq *rq)
609{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700610 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700611 WMI_DELETE_PSTREAM_CMD cmd;
612 int ret = 0;
613
Joe Perches1071a132011-02-02 14:05:47 -0800614 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700615 return -EIO;
616 }
617
618 if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
619 return -EFAULT;
620 }
621
622 ret = wmi_delete_pstream_cmd(ar->arWmi, cmd.trafficClass, cmd.tsid);
623
624 switch (ret) {
Joe Perches4f69cef2011-02-02 14:05:57 -0800625 case 0:
Vipin Mehta30295c82010-09-01 12:06:33 -0700626 return 0;
627 case A_EBUSY :
628 return -EBUSY;
629 case A_NO_MEMORY:
630 return -ENOMEM;
631 case A_EINVAL:
632 default:
633 return -EFAULT;
634 }
635}
636
637static int
638ar6000_ioctl_get_qos_queue(struct net_device *dev, struct ifreq *rq)
639{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700640 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700641 struct ar6000_queuereq qreq;
642 int ret = 0;
643
Joe Perches1071a132011-02-02 14:05:47 -0800644 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700645 return -EIO;
646 }
647
648 if( copy_from_user(&qreq, rq->ifr_data,
649 sizeof(struct ar6000_queuereq)))
650 return -EFAULT;
651
652 qreq.activeTsids = wmi_get_mapped_qos_queue(ar->arWmi, qreq.trafficClass);
653
654 if (copy_to_user(rq->ifr_data, &qreq,
655 sizeof(struct ar6000_queuereq)))
656 {
657 ret = -EFAULT;
658 }
659
660 return ret;
661}
662
663#ifdef CONFIG_HOST_TCMD_SUPPORT
Joe Perches1f4c34b2011-01-27 20:04:19 -0800664static int
Vipin Mehta30295c82010-09-01 12:06:33 -0700665ar6000_ioctl_tcmd_get_rx_report(struct net_device *dev,
Joe Perchese1ce2a32011-02-02 14:05:51 -0800666 struct ifreq *rq, u8 *data, u32 len)
Vipin Mehta30295c82010-09-01 12:06:33 -0700667{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700668 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Joe Perchese1ce2a32011-02-02 14:05:51 -0800669 u32 buf[4+TCMD_MAX_RATES];
Vipin Mehta30295c82010-09-01 12:06:33 -0700670 int ret = 0;
671
672 if (ar->bIsDestroyProgress) {
673 return -EBUSY;
674 }
675
Joe Perches1071a132011-02-02 14:05:47 -0800676 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700677 return -EIO;
678 }
679
680 if (down_interruptible(&ar->arSem)) {
681 return -ERESTARTSYS;
682 }
683
684 if (ar->bIsDestroyProgress) {
685 up(&ar->arSem);
686 return -EBUSY;
687 }
688
689 ar->tcmdRxReport = 0;
Joe Perches4f69cef2011-02-02 14:05:57 -0800690 if (wmi_test_cmd(ar->arWmi, data, len) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700691 up(&ar->arSem);
692 return -EIO;
693 }
694
695 wait_event_interruptible_timeout(arEvent, ar->tcmdRxReport != 0, wmitimeout * HZ);
696
697 if (signal_pending(current)) {
698 ret = -EINTR;
699 }
700
701 buf[0] = ar->tcmdRxTotalPkt;
702 buf[1] = ar->tcmdRxRssi;
703 buf[2] = ar->tcmdRxcrcErrPkt;
704 buf[3] = ar->tcmdRxsecErrPkt;
Luis R. Rodriguezd8cb3162011-03-10 18:55:31 -0800705 memcpy(((u8 *)buf)+(4*sizeof(u32)), ar->tcmdRateCnt, sizeof(ar->tcmdRateCnt));
706 memcpy(((u8 *)buf)+(4*sizeof(u32))+(TCMD_MAX_RATES *sizeof(u16)), ar->tcmdRateCntShortGuard, sizeof(ar->tcmdRateCntShortGuard));
Vipin Mehta30295c82010-09-01 12:06:33 -0700707
708 if (!ret && copy_to_user(rq->ifr_data, buf, sizeof(buf))) {
709 ret = -EFAULT;
710 }
711
712 up(&ar->arSem);
713
714 return ret;
715}
716
717void
Joe Perchesab3655d2011-02-02 14:05:49 -0800718ar6000_tcmd_rx_report_event(void *devt, u8 *results, int len)
Vipin Mehta30295c82010-09-01 12:06:33 -0700719{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700720 struct ar6_softc *ar = (struct ar6_softc *)devt;
Vipin Mehta30295c82010-09-01 12:06:33 -0700721 TCMD_CONT_RX * rx_rep = (TCMD_CONT_RX *)results;
722
723 if (enablerssicompensation) {
724 rx_rep->u.report.rssiInDBm = rssi_compensation_calc_tcmd(tcmdRxFreq, rx_rep->u.report.rssiInDBm,rx_rep->u.report.totalPkt);
725 }
726
727
728 ar->tcmdRxTotalPkt = rx_rep->u.report.totalPkt;
729 ar->tcmdRxRssi = rx_rep->u.report.rssiInDBm;
730 ar->tcmdRxcrcErrPkt = rx_rep->u.report.crcErrPkt;
731 ar->tcmdRxsecErrPkt = rx_rep->u.report.secErrPkt;
732 ar->tcmdRxReport = 1;
733 A_MEMZERO(ar->tcmdRateCnt, sizeof(ar->tcmdRateCnt));
734 A_MEMZERO(ar->tcmdRateCntShortGuard, sizeof(ar->tcmdRateCntShortGuard));
Luis R. Rodriguez05209262011-03-10 18:55:29 -0800735 memcpy(ar->tcmdRateCnt, rx_rep->u.report.rateCnt, sizeof(ar->tcmdRateCnt));
736 memcpy(ar->tcmdRateCntShortGuard, rx_rep->u.report.rateCntShortGuard, sizeof(ar->tcmdRateCntShortGuard));
Vipin Mehta30295c82010-09-01 12:06:33 -0700737
738 wake_up(&arEvent);
739}
740#endif /* CONFIG_HOST_TCMD_SUPPORT*/
741
742static int
743ar6000_ioctl_set_error_report_bitmask(struct net_device *dev, struct ifreq *rq)
744{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700745 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700746 WMI_TARGET_ERROR_REPORT_BITMASK cmd;
747 int ret = 0;
748
Joe Perches1071a132011-02-02 14:05:47 -0800749 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700750 return -EIO;
751 }
752
753 if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
754 return -EFAULT;
755 }
756
757 ret = wmi_set_error_report_bitmask(ar->arWmi, cmd.bitmask);
758
759 return (ret==0 ? ret : -EINVAL);
760}
761
762static int
763ar6000_clear_target_stats(struct net_device *dev)
764{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700765 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700766 TARGET_STATS *pStats = &ar->arTargetStats;
767 int ret = 0;
768
Joe Perches1071a132011-02-02 14:05:47 -0800769 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700770 return -EIO;
771 }
772 AR6000_SPIN_LOCK(&ar->arLock, 0);
773 A_MEMZERO(pStats, sizeof(TARGET_STATS));
774 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
775 return ret;
776}
777
778static int
779ar6000_ioctl_get_target_stats(struct net_device *dev, struct ifreq *rq)
780{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700781 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700782 TARGET_STATS_CMD cmd;
783 TARGET_STATS *pStats = &ar->arTargetStats;
784 int ret = 0;
785
786 if (ar->bIsDestroyProgress) {
787 return -EBUSY;
788 }
Joe Perches1071a132011-02-02 14:05:47 -0800789 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700790 return -EIO;
791 }
792 if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
793 return -EFAULT;
794 }
795 if (down_interruptible(&ar->arSem)) {
796 return -ERESTARTSYS;
797 }
798 if (ar->bIsDestroyProgress) {
799 up(&ar->arSem);
800 return -EBUSY;
801 }
802
Joe Perches1071a132011-02-02 14:05:47 -0800803 ar->statsUpdatePending = true;
Vipin Mehta30295c82010-09-01 12:06:33 -0700804
Joe Perches4f69cef2011-02-02 14:05:57 -0800805 if(wmi_get_stats_cmd(ar->arWmi) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700806 up(&ar->arSem);
807 return -EIO;
808 }
809
Joe Perches1071a132011-02-02 14:05:47 -0800810 wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
Vipin Mehta30295c82010-09-01 12:06:33 -0700811
812 if (signal_pending(current)) {
813 ret = -EINTR;
814 }
815
816 if (!ret && copy_to_user(rq->ifr_data, pStats, sizeof(*pStats))) {
817 ret = -EFAULT;
818 }
819
820 if (cmd.clearStats == 1) {
821 ret = ar6000_clear_target_stats(dev);
822 }
823
824 up(&ar->arSem);
825
826 return ret;
827}
828
829static int
830ar6000_ioctl_get_ap_stats(struct net_device *dev, struct ifreq *rq)
831{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700832 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Joe Perchese1ce2a32011-02-02 14:05:51 -0800833 u32 action; /* Allocating only the desired space on the frame. Declaring is as a WMI_AP_MODE_STAT variable results in exceeding the compiler imposed limit on the maximum frame size */
Vipin Mehta30295c82010-09-01 12:06:33 -0700834 WMI_AP_MODE_STAT *pStats = &ar->arAPStats;
835 int ret = 0;
836
Joe Perches1071a132011-02-02 14:05:47 -0800837 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700838 return -EIO;
839 }
840 if (copy_from_user(&action, (char *)((unsigned int*)rq->ifr_data + 1),
Joe Perchese1ce2a32011-02-02 14:05:51 -0800841 sizeof(u32)))
Vipin Mehta30295c82010-09-01 12:06:33 -0700842 {
843 return -EFAULT;
844 }
845 if (action == AP_CLEAR_STATS) {
Joe Perchesab3655d2011-02-02 14:05:49 -0800846 u8 i;
Vipin Mehta30295c82010-09-01 12:06:33 -0700847 AR6000_SPIN_LOCK(&ar->arLock, 0);
848 for(i = 0; i < AP_MAX_NUM_STA; i++) {
849 pStats->sta[i].tx_bytes = 0;
850 pStats->sta[i].tx_pkts = 0;
851 pStats->sta[i].tx_error = 0;
852 pStats->sta[i].tx_discard = 0;
853 pStats->sta[i].rx_bytes = 0;
854 pStats->sta[i].rx_pkts = 0;
855 pStats->sta[i].rx_error = 0;
856 pStats->sta[i].rx_discard = 0;
857 }
858 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
859 return ret;
860 }
861
862 if (down_interruptible(&ar->arSem)) {
863 return -ERESTARTSYS;
864 }
865
Joe Perches1071a132011-02-02 14:05:47 -0800866 ar->statsUpdatePending = true;
Vipin Mehta30295c82010-09-01 12:06:33 -0700867
Joe Perches4f69cef2011-02-02 14:05:57 -0800868 if(wmi_get_stats_cmd(ar->arWmi) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700869 up(&ar->arSem);
870 return -EIO;
871 }
872
Joe Perches1071a132011-02-02 14:05:47 -0800873 wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
Vipin Mehta30295c82010-09-01 12:06:33 -0700874
875 if (signal_pending(current)) {
876 ret = -EINTR;
877 }
878
879 if (!ret && copy_to_user(rq->ifr_data, pStats, sizeof(*pStats))) {
880 ret = -EFAULT;
881 }
882
883 up(&ar->arSem);
884
885 return ret;
886}
887
888static int
889ar6000_ioctl_set_access_params(struct net_device *dev, struct ifreq *rq)
890{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700891 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700892 WMI_SET_ACCESS_PARAMS_CMD cmd;
893 int ret = 0;
894
Joe Perches1071a132011-02-02 14:05:47 -0800895 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700896 return -EIO;
897 }
898
899 if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
900 return -EFAULT;
901 }
902
903 if (wmi_set_access_params_cmd(ar->arWmi, cmd.ac, cmd.txop, cmd.eCWmin, cmd.eCWmax,
Joe Perches4f69cef2011-02-02 14:05:57 -0800904 cmd.aifsn) == 0)
Vipin Mehta30295c82010-09-01 12:06:33 -0700905 {
906 ret = 0;
907 } else {
908 ret = -EINVAL;
909 }
910
911 return (ret);
912}
913
914static int
915ar6000_ioctl_set_disconnect_timeout(struct net_device *dev, struct ifreq *rq)
916{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700917 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700918 WMI_DISC_TIMEOUT_CMD cmd;
919 int ret = 0;
920
Joe Perches1071a132011-02-02 14:05:47 -0800921 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700922 return -EIO;
923 }
924
925 if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
926 return -EFAULT;
927 }
928
Joe Perches4f69cef2011-02-02 14:05:57 -0800929 if (wmi_disctimeout_cmd(ar->arWmi, cmd.disconnectTimeout) == 0)
Vipin Mehta30295c82010-09-01 12:06:33 -0700930 {
931 ret = 0;
932 } else {
933 ret = -EINVAL;
934 }
935
936 return (ret);
937}
938
939static int
Joe Perches4c42080f2011-02-02 14:05:48 -0800940ar6000_xioctl_set_voice_pkt_size(struct net_device *dev, char *userdata)
Vipin Mehta30295c82010-09-01 12:06:33 -0700941{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700942 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700943 WMI_SET_VOICE_PKT_SIZE_CMD cmd;
944 int ret = 0;
945
Joe Perches1071a132011-02-02 14:05:47 -0800946 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700947 return -EIO;
948 }
949
950 if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
951 return -EFAULT;
952 }
953
Joe Perches4f69cef2011-02-02 14:05:57 -0800954 if (wmi_set_voice_pkt_size_cmd(ar->arWmi, cmd.voicePktSize) == 0)
Vipin Mehta30295c82010-09-01 12:06:33 -0700955 {
956 ret = 0;
957 } else {
958 ret = -EINVAL;
959 }
960
961
962 return (ret);
963}
964
965static int
Joe Perches4c42080f2011-02-02 14:05:48 -0800966ar6000_xioctl_set_max_sp_len(struct net_device *dev, char *userdata)
Vipin Mehta30295c82010-09-01 12:06:33 -0700967{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700968 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700969 WMI_SET_MAX_SP_LEN_CMD cmd;
970 int ret = 0;
971
Joe Perches1071a132011-02-02 14:05:47 -0800972 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700973 return -EIO;
974 }
975
976 if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
977 return -EFAULT;
978 }
979
Joe Perches4f69cef2011-02-02 14:05:57 -0800980 if (wmi_set_max_sp_len_cmd(ar->arWmi, cmd.maxSPLen) == 0)
Vipin Mehta30295c82010-09-01 12:06:33 -0700981 {
982 ret = 0;
983 } else {
984 ret = -EINVAL;
985 }
986
987 return (ret);
988}
989
990
991static int
Joe Perches4c42080f2011-02-02 14:05:48 -0800992ar6000_xioctl_set_bt_status_cmd(struct net_device *dev, char *userdata)
Vipin Mehta30295c82010-09-01 12:06:33 -0700993{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -0700994 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -0700995 WMI_SET_BT_STATUS_CMD cmd;
996 int ret = 0;
997
Joe Perches1071a132011-02-02 14:05:47 -0800998 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -0700999 return -EIO;
1000 }
1001
1002 if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1003 return -EFAULT;
1004 }
1005
Joe Perches4f69cef2011-02-02 14:05:57 -08001006 if (wmi_set_bt_status_cmd(ar->arWmi, cmd.streamType, cmd.status) == 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07001007 {
1008 ret = 0;
1009 } else {
1010 ret = -EINVAL;
1011 }
1012
1013 return (ret);
1014}
1015
1016static int
Joe Perches4c42080f2011-02-02 14:05:48 -08001017ar6000_xioctl_set_bt_params_cmd(struct net_device *dev, char *userdata)
Vipin Mehta30295c82010-09-01 12:06:33 -07001018{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001019 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001020 WMI_SET_BT_PARAMS_CMD cmd;
1021 int ret = 0;
1022
Joe Perches1071a132011-02-02 14:05:47 -08001023 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001024 return -EIO;
1025 }
1026
1027 if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1028 return -EFAULT;
1029 }
1030
Joe Perches4f69cef2011-02-02 14:05:57 -08001031 if (wmi_set_bt_params_cmd(ar->arWmi, &cmd) == 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07001032 {
1033 ret = 0;
1034 } else {
1035 ret = -EINVAL;
1036 }
1037
1038 return (ret);
1039}
1040
1041static int
Joe Perches4c42080f2011-02-02 14:05:48 -08001042ar6000_xioctl_set_btcoex_fe_ant_cmd(struct net_device * dev, char *userdata)
Vipin Mehta30295c82010-09-01 12:06:33 -07001043{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001044 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001045 WMI_SET_BTCOEX_FE_ANT_CMD cmd;
1046 int ret = 0;
1047
Joe Perches1071a132011-02-02 14:05:47 -08001048 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001049 return -EIO;
1050 }
1051 if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1052 return -EFAULT;
1053 }
1054
Joe Perches4f69cef2011-02-02 14:05:57 -08001055 if (wmi_set_btcoex_fe_ant_cmd(ar->arWmi, &cmd) == 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07001056 {
1057 ret = 0;
1058 } else {
1059 ret = -EINVAL;
1060 }
1061
1062 return(ret);
1063}
1064
1065static int
Joe Perches4c42080f2011-02-02 14:05:48 -08001066ar6000_xioctl_set_btcoex_colocated_bt_dev_cmd(struct net_device * dev, char *userdata)
Vipin Mehta30295c82010-09-01 12:06:33 -07001067{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001068 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001069 WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD cmd;
1070 int ret = 0;
1071
Joe Perches1071a132011-02-02 14:05:47 -08001072 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001073 return -EIO;
1074 }
1075
1076 if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1077 return -EFAULT;
1078 }
1079
Joe Perches4f69cef2011-02-02 14:05:57 -08001080 if (wmi_set_btcoex_colocated_bt_dev_cmd(ar->arWmi, &cmd) == 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07001081 {
1082 ret = 0;
1083 } else {
1084 ret = -EINVAL;
1085 }
1086
1087 return(ret);
1088}
1089
1090static int
Joe Perches4c42080f2011-02-02 14:05:48 -08001091ar6000_xioctl_set_btcoex_btinquiry_page_config_cmd(struct net_device * dev, char *userdata)
Vipin Mehta30295c82010-09-01 12:06:33 -07001092{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001093 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001094 WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD cmd;
1095 int ret = 0;
1096
Joe Perches1071a132011-02-02 14:05:47 -08001097 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001098 return -EIO;
1099 }
1100
1101 if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1102 return -EFAULT;
1103 }
1104
Joe Perches4f69cef2011-02-02 14:05:57 -08001105 if (wmi_set_btcoex_btinquiry_page_config_cmd(ar->arWmi, &cmd) == 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07001106 {
1107 ret = 0;
1108 } else {
1109 ret = -EINVAL;
1110 }
1111
1112 return(ret);
1113}
1114
1115static int
Joe Perches4c42080f2011-02-02 14:05:48 -08001116ar6000_xioctl_set_btcoex_sco_config_cmd(struct net_device * dev, char *userdata)
Vipin Mehta30295c82010-09-01 12:06:33 -07001117{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001118 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001119 WMI_SET_BTCOEX_SCO_CONFIG_CMD cmd;
1120 int ret = 0;
1121
Joe Perches1071a132011-02-02 14:05:47 -08001122 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001123 return -EIO;
1124 }
1125
1126 if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1127 return -EFAULT;
1128 }
1129
Joe Perches4f69cef2011-02-02 14:05:57 -08001130 if (wmi_set_btcoex_sco_config_cmd(ar->arWmi, &cmd) == 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07001131 {
1132 ret = 0;
1133 } else {
1134 ret = -EINVAL;
1135 }
1136
1137 return(ret);
1138}
1139
1140static int
1141ar6000_xioctl_set_btcoex_a2dp_config_cmd(struct net_device * dev,
Joe Perches4c42080f2011-02-02 14:05:48 -08001142 char *userdata)
Vipin Mehta30295c82010-09-01 12:06:33 -07001143{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001144 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001145 WMI_SET_BTCOEX_A2DP_CONFIG_CMD cmd;
1146 int ret = 0;
1147
Joe Perches1071a132011-02-02 14:05:47 -08001148 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001149 return -EIO;
1150 }
1151
1152 if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1153 return -EFAULT;
1154 }
1155
Joe Perches4f69cef2011-02-02 14:05:57 -08001156 if (wmi_set_btcoex_a2dp_config_cmd(ar->arWmi, &cmd) == 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07001157 {
1158 ret = 0;
1159 } else {
1160 ret = -EINVAL;
1161 }
1162
1163 return(ret);
1164}
1165
1166static int
Joe Perches4c42080f2011-02-02 14:05:48 -08001167ar6000_xioctl_set_btcoex_aclcoex_config_cmd(struct net_device * dev, char *userdata)
Vipin Mehta30295c82010-09-01 12:06:33 -07001168{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001169 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001170 WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD cmd;
1171 int ret = 0;
1172
Joe Perches1071a132011-02-02 14:05:47 -08001173 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001174 return -EIO;
1175 }
1176
1177 if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1178 return -EFAULT;
1179 }
1180
Joe Perches4f69cef2011-02-02 14:05:57 -08001181 if (wmi_set_btcoex_aclcoex_config_cmd(ar->arWmi, &cmd) == 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07001182 {
1183 ret = 0;
1184 } else {
1185 ret = -EINVAL;
1186 }
1187
1188 return(ret);
1189}
1190
1191static int
Joe Perches4c42080f2011-02-02 14:05:48 -08001192ar60000_xioctl_set_btcoex_debug_cmd(struct net_device * dev, char *userdata)
Vipin Mehta30295c82010-09-01 12:06:33 -07001193{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001194 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001195 WMI_SET_BTCOEX_DEBUG_CMD cmd;
1196 int ret = 0;
1197
Joe Perches1071a132011-02-02 14:05:47 -08001198 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001199 return -EIO;
1200 }
1201
1202 if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1203 return -EFAULT;
1204 }
1205
Joe Perches4f69cef2011-02-02 14:05:57 -08001206 if (wmi_set_btcoex_debug_cmd(ar->arWmi, &cmd) == 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07001207 {
1208 ret = 0;
1209 } else {
1210 ret = -EINVAL;
1211 }
1212
1213 return(ret);
1214}
1215
1216static int
Joe Perches4c42080f2011-02-02 14:05:48 -08001217ar6000_xioctl_set_btcoex_bt_operating_status_cmd(struct net_device * dev, char *userdata)
Vipin Mehta30295c82010-09-01 12:06:33 -07001218{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001219 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001220 WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD cmd;
1221 int ret = 0;
1222
Joe Perches1071a132011-02-02 14:05:47 -08001223 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001224 return -EIO;
1225 }
1226
1227 if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1228 return -EFAULT;
1229 }
1230
Joe Perches4f69cef2011-02-02 14:05:57 -08001231 if (wmi_set_btcoex_bt_operating_status_cmd(ar->arWmi, &cmd) == 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07001232 {
1233 ret = 0;
1234 } else {
1235 ret = -EINVAL;
1236 }
1237 return(ret);
1238}
1239
1240static int
Joe Perches4c42080f2011-02-02 14:05:48 -08001241ar6000_xioctl_get_btcoex_config_cmd(struct net_device * dev, char *userdata,
Vipin Mehta30295c82010-09-01 12:06:33 -07001242 struct ifreq *rq)
1243{
1244
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001245 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001246 AR6000_BTCOEX_CONFIG btcoexConfig;
1247 WMI_BTCOEX_CONFIG_EVENT *pbtcoexConfigEv = &ar->arBtcoexConfig;
1248
1249 int ret = 0;
1250
1251 if (ar->bIsDestroyProgress) {
1252 return -EBUSY;
1253 }
Joe Perches1071a132011-02-02 14:05:47 -08001254 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001255 return -EIO;
1256 }
1257 if (copy_from_user(&btcoexConfig.configCmd, userdata, sizeof(AR6000_BTCOEX_CONFIG))) {
1258 return -EFAULT;
1259 }
1260 if (down_interruptible(&ar->arSem)) {
1261 return -ERESTARTSYS;
1262 }
1263
Joe Perches4f69cef2011-02-02 14:05:57 -08001264 if (wmi_get_btcoex_config_cmd(ar->arWmi, (WMI_GET_BTCOEX_CONFIG_CMD *)&btcoexConfig.configCmd) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07001265 {
1266 up(&ar->arSem);
1267 return -EIO;
1268 }
1269
Joe Perches1071a132011-02-02 14:05:47 -08001270 ar->statsUpdatePending = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001271
Joe Perches1071a132011-02-02 14:05:47 -08001272 wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
Vipin Mehta30295c82010-09-01 12:06:33 -07001273
1274 if (signal_pending(current)) {
1275 ret = -EINTR;
1276 }
1277
1278 if (!ret && copy_to_user(btcoexConfig.configEvent, pbtcoexConfigEv, sizeof(WMI_BTCOEX_CONFIG_EVENT))) {
1279 ret = -EFAULT;
1280 }
1281 up(&ar->arSem);
1282 return ret;
1283}
1284
1285static int
Joe Perches4c42080f2011-02-02 14:05:48 -08001286ar6000_xioctl_get_btcoex_stats_cmd(struct net_device * dev, char *userdata, struct ifreq *rq)
Vipin Mehta30295c82010-09-01 12:06:33 -07001287{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001288 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001289 AR6000_BTCOEX_STATS btcoexStats;
1290 WMI_BTCOEX_STATS_EVENT *pbtcoexStats = &ar->arBtcoexStats;
1291 int ret = 0;
1292
1293 if (ar->bIsDestroyProgress) {
1294 return -EBUSY;
1295 }
Joe Perches1071a132011-02-02 14:05:47 -08001296 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001297 return -EIO;
1298 }
1299
1300 if (down_interruptible(&ar->arSem)) {
1301 return -ERESTARTSYS;
1302 }
1303
1304 if (copy_from_user(&btcoexStats.statsEvent, userdata, sizeof(AR6000_BTCOEX_CONFIG))) {
1305 return -EFAULT;
1306 }
1307
Joe Perches4f69cef2011-02-02 14:05:57 -08001308 if (wmi_get_btcoex_stats_cmd(ar->arWmi) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07001309 {
1310 up(&ar->arSem);
1311 return -EIO;
1312 }
1313
Joe Perches1071a132011-02-02 14:05:47 -08001314 ar->statsUpdatePending = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001315
Joe Perches1071a132011-02-02 14:05:47 -08001316 wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
Vipin Mehta30295c82010-09-01 12:06:33 -07001317
1318 if (signal_pending(current)) {
1319 ret = -EINTR;
1320 }
1321
1322 if (!ret && copy_to_user(btcoexStats.statsEvent, pbtcoexStats, sizeof(WMI_BTCOEX_STATS_EVENT))) {
1323 ret = -EFAULT;
1324 }
1325
1326
1327 up(&ar->arSem);
1328
1329 return(ret);
1330}
1331
Vipin Mehta711a1bc2011-02-18 13:13:11 -08001332static int
1333ar6000_xioctl_set_excess_tx_retry_thres_cmd(struct net_device * dev, char * userdata)
1334{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001335 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta711a1bc2011-02-18 13:13:11 -08001336 WMI_SET_EXCESS_TX_RETRY_THRES_CMD cmd;
1337 int ret = 0;
1338
1339 if (ar->arWmiReady == false) {
1340 return -EIO;
1341 }
1342
1343 if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
1344 return -EFAULT;
1345 }
1346
1347 if (wmi_set_excess_tx_retry_thres_cmd(ar->arWmi, &cmd) != 0)
1348 {
1349 ret = -EINVAL;
1350 }
1351 return(ret);
1352}
1353
Vipin Mehta30295c82010-09-01 12:06:33 -07001354#ifdef CONFIG_HOST_GPIO_SUPPORT
1355struct ar6000_gpio_intr_wait_cmd_s gpio_intr_results;
1356/* gpio_reg_results and gpio_data_available are protected by arSem */
1357static struct ar6000_gpio_register_cmd_s gpio_reg_results;
Joe Perches1071a132011-02-02 14:05:47 -08001358static bool gpio_data_available; /* Requested GPIO data available */
1359static bool gpio_intr_available; /* GPIO interrupt info available */
1360static bool gpio_ack_received; /* GPIO ack was received */
Vipin Mehta30295c82010-09-01 12:06:33 -07001361
1362/* Host-side initialization for General Purpose I/O support */
1363void ar6000_gpio_init(void)
1364{
Joe Perches1071a132011-02-02 14:05:47 -08001365 gpio_intr_available = false;
1366 gpio_data_available = false;
1367 gpio_ack_received = false;
Vipin Mehta30295c82010-09-01 12:06:33 -07001368}
1369
1370/*
1371 * Called when a GPIO interrupt is received from the Target.
1372 * intr_values shows which GPIO pins have interrupted.
1373 * input_values shows a recent value of GPIO pins.
1374 */
1375void
Joe Perchese1ce2a32011-02-02 14:05:51 -08001376ar6000_gpio_intr_rx(u32 intr_mask, u32 input_values)
Vipin Mehta30295c82010-09-01 12:06:33 -07001377{
1378 gpio_intr_results.intr_mask = intr_mask;
1379 gpio_intr_results.input_values = input_values;
Joe Perches1071a132011-02-02 14:05:47 -08001380 *((volatile bool *)&gpio_intr_available) = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001381 wake_up(&arEvent);
1382}
1383
1384/*
1385 * This is called when a response is received from the Target
1386 * for a previous or ar6000_gpio_input_get or ar6000_gpio_register_get
1387 * call.
1388 */
1389void
Joe Perchese1ce2a32011-02-02 14:05:51 -08001390ar6000_gpio_data_rx(u32 reg_id, u32 value)
Vipin Mehta30295c82010-09-01 12:06:33 -07001391{
1392 gpio_reg_results.gpioreg_id = reg_id;
1393 gpio_reg_results.value = value;
Joe Perches1071a132011-02-02 14:05:47 -08001394 *((volatile bool *)&gpio_data_available) = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001395 wake_up(&arEvent);
1396}
1397
1398/*
1399 * This is called when an acknowledgement is received from the Target
1400 * for a previous or ar6000_gpio_output_set or ar6000_gpio_register_set
1401 * call.
1402 */
1403void
1404ar6000_gpio_ack_rx(void)
1405{
Joe Perches1071a132011-02-02 14:05:47 -08001406 gpio_ack_received = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001407 wake_up(&arEvent);
1408}
1409
Joe Perches1f4c34b2011-01-27 20:04:19 -08001410int
Vipin Mehta30295c82010-09-01 12:06:33 -07001411ar6000_gpio_output_set(struct net_device *dev,
Joe Perchese1ce2a32011-02-02 14:05:51 -08001412 u32 set_mask,
1413 u32 clear_mask,
1414 u32 enable_mask,
1415 u32 disable_mask)
Vipin Mehta30295c82010-09-01 12:06:33 -07001416{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001417 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001418
Joe Perches1071a132011-02-02 14:05:47 -08001419 gpio_ack_received = false;
Vipin Mehta30295c82010-09-01 12:06:33 -07001420 return wmi_gpio_output_set(ar->arWmi,
1421 set_mask, clear_mask, enable_mask, disable_mask);
1422}
1423
Joe Perches1f4c34b2011-01-27 20:04:19 -08001424static int
Vipin Mehta30295c82010-09-01 12:06:33 -07001425ar6000_gpio_input_get(struct net_device *dev)
1426{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001427 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001428
Joe Perches1071a132011-02-02 14:05:47 -08001429 *((volatile bool *)&gpio_data_available) = false;
Vipin Mehta30295c82010-09-01 12:06:33 -07001430 return wmi_gpio_input_get(ar->arWmi);
1431}
1432
Joe Perches1f4c34b2011-01-27 20:04:19 -08001433static int
Vipin Mehta30295c82010-09-01 12:06:33 -07001434ar6000_gpio_register_set(struct net_device *dev,
Joe Perchese1ce2a32011-02-02 14:05:51 -08001435 u32 gpioreg_id,
1436 u32 value)
Vipin Mehta30295c82010-09-01 12:06:33 -07001437{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001438 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001439
Joe Perches1071a132011-02-02 14:05:47 -08001440 gpio_ack_received = false;
Vipin Mehta30295c82010-09-01 12:06:33 -07001441 return wmi_gpio_register_set(ar->arWmi, gpioreg_id, value);
1442}
1443
Joe Perches1f4c34b2011-01-27 20:04:19 -08001444static int
Vipin Mehta30295c82010-09-01 12:06:33 -07001445ar6000_gpio_register_get(struct net_device *dev,
Joe Perchese1ce2a32011-02-02 14:05:51 -08001446 u32 gpioreg_id)
Vipin Mehta30295c82010-09-01 12:06:33 -07001447{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001448 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001449
Joe Perches1071a132011-02-02 14:05:47 -08001450 *((volatile bool *)&gpio_data_available) = false;
Vipin Mehta30295c82010-09-01 12:06:33 -07001451 return wmi_gpio_register_get(ar->arWmi, gpioreg_id);
1452}
1453
Joe Perches1f4c34b2011-01-27 20:04:19 -08001454static int
Vipin Mehta30295c82010-09-01 12:06:33 -07001455ar6000_gpio_intr_ack(struct net_device *dev,
Joe Perchese1ce2a32011-02-02 14:05:51 -08001456 u32 ack_mask)
Vipin Mehta30295c82010-09-01 12:06:33 -07001457{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001458 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001459
Joe Perches1071a132011-02-02 14:05:47 -08001460 gpio_intr_available = false;
Vipin Mehta30295c82010-09-01 12:06:33 -07001461 return wmi_gpio_intr_ack(ar->arWmi, ack_mask);
1462}
1463#endif /* CONFIG_HOST_GPIO_SUPPORT */
1464
1465#if defined(CONFIG_TARGET_PROFILE_SUPPORT)
1466static struct prof_count_s prof_count_results;
Joe Perches1071a132011-02-02 14:05:47 -08001467static bool prof_count_available; /* Requested GPIO data available */
Vipin Mehta30295c82010-09-01 12:06:33 -07001468
Joe Perches1f4c34b2011-01-27 20:04:19 -08001469static int
Vipin Mehta30295c82010-09-01 12:06:33 -07001470prof_count_get(struct net_device *dev)
1471{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001472 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07001473
Joe Perches1071a132011-02-02 14:05:47 -08001474 *((volatile bool *)&prof_count_available) = false;
Vipin Mehta30295c82010-09-01 12:06:33 -07001475 return wmi_prof_count_get_cmd(ar->arWmi);
1476}
1477
1478/*
1479 * This is called when a response is received from the Target
1480 * for a previous prof_count_get call.
1481 */
1482void
Joe Perchese1ce2a32011-02-02 14:05:51 -08001483prof_count_rx(u32 addr, u32 count)
Vipin Mehta30295c82010-09-01 12:06:33 -07001484{
1485 prof_count_results.addr = addr;
1486 prof_count_results.count = count;
Joe Perches1071a132011-02-02 14:05:47 -08001487 *((volatile bool *)&prof_count_available) = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001488 wake_up(&arEvent);
1489}
1490#endif /* CONFIG_TARGET_PROFILE_SUPPORT */
1491
1492
Joe Perches1f4c34b2011-01-27 20:04:19 -08001493static int
Joe Perchesab3655d2011-02-02 14:05:49 -08001494ar6000_create_acl_data_osbuf(struct net_device *dev, u8 *userdata, void **p_osbuf)
Vipin Mehta30295c82010-09-01 12:06:33 -07001495{
1496 void *osbuf = NULL;
Joe Perchesab3655d2011-02-02 14:05:49 -08001497 u8 tmp_space[8];
Vipin Mehta30295c82010-09-01 12:06:33 -07001498 HCI_ACL_DATA_PKT *acl;
Joe Perchesab3655d2011-02-02 14:05:49 -08001499 u8 hdr_size, *datap=NULL;
Joe Perches4f69cef2011-02-02 14:05:57 -08001500 int ret = 0;
Vipin Mehta30295c82010-09-01 12:06:33 -07001501
1502 /* ACL is in data path. There is a need to create pool
1503 * mechanism for allocating and freeing NETBUFs - ToDo later.
1504 */
1505
1506 *p_osbuf = NULL;
1507 acl = (HCI_ACL_DATA_PKT *)tmp_space;
1508 hdr_size = sizeof(acl->hdl_and_flags) + sizeof(acl->data_len);
1509
1510 do {
1511 if (a_copy_from_user(acl, userdata, hdr_size)) {
1512 ret = A_EFAULT;
1513 break;
1514 }
1515
1516 osbuf = A_NETBUF_ALLOC(hdr_size + acl->data_len);
1517 if (osbuf == NULL) {
1518 ret = A_NO_MEMORY;
1519 break;
1520 }
1521 A_NETBUF_PUT(osbuf, hdr_size + acl->data_len);
Joe Perchesab3655d2011-02-02 14:05:49 -08001522 datap = (u8 *)A_NETBUF_DATA(osbuf);
Vipin Mehta30295c82010-09-01 12:06:33 -07001523
1524 /* Real copy to osbuf */
1525 acl = (HCI_ACL_DATA_PKT *)(datap);
Luis R. Rodriguez05209262011-03-10 18:55:29 -08001526 memcpy(acl, tmp_space, hdr_size);
Vipin Mehta30295c82010-09-01 12:06:33 -07001527 if (a_copy_from_user(acl->data, userdata + hdr_size, acl->data_len)) {
1528 ret = A_EFAULT;
1529 break;
1530 }
Joe Perches1071a132011-02-02 14:05:47 -08001531 } while(false);
Vipin Mehta30295c82010-09-01 12:06:33 -07001532
Joe Perches4f69cef2011-02-02 14:05:57 -08001533 if (ret == 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001534 *p_osbuf = osbuf;
1535 } else {
1536 A_NETBUF_FREE(osbuf);
1537 }
1538 return ret;
1539}
1540
1541
1542
1543int
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001544ar6000_ioctl_ap_setparam(struct ar6_softc *ar, int param, int value)
Vipin Mehta30295c82010-09-01 12:06:33 -07001545{
1546 int ret=0;
1547
1548 switch(param) {
1549 case IEEE80211_PARAM_WPA:
1550 switch (value) {
1551 case WPA_MODE_WPA1:
1552 ar->arAuthMode = WPA_AUTH;
1553 break;
1554 case WPA_MODE_WPA2:
1555 ar->arAuthMode = WPA2_AUTH;
1556 break;
1557 case WPA_MODE_AUTO:
1558 ar->arAuthMode = WPA_AUTH | WPA2_AUTH;
1559 break;
1560 case WPA_MODE_NONE:
1561 ar->arAuthMode = NONE_AUTH;
1562 break;
1563 }
1564 break;
1565 case IEEE80211_PARAM_AUTHMODE:
1566 if(value == IEEE80211_AUTH_WPA_PSK) {
1567 if (WPA_AUTH == ar->arAuthMode) {
1568 ar->arAuthMode = WPA_PSK_AUTH;
1569 } else if (WPA2_AUTH == ar->arAuthMode) {
1570 ar->arAuthMode = WPA2_PSK_AUTH;
1571 } else if ((WPA_AUTH | WPA2_AUTH) == ar->arAuthMode) {
1572 ar->arAuthMode = WPA_PSK_AUTH | WPA2_PSK_AUTH;
1573 } else {
1574 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Error - Setting PSK "\
1575 "mode when WPA param was set to %d\n",
1576 ar->arAuthMode));
1577 ret = -EIO;
1578 }
1579 }
1580 break;
1581 case IEEE80211_PARAM_UCASTCIPHER:
1582 ar->arPairwiseCrypto = 0;
1583 if(value & (1<<IEEE80211_CIPHER_AES_CCM)) {
1584 ar->arPairwiseCrypto |= AES_CRYPT;
1585 }
1586 if(value & (1<<IEEE80211_CIPHER_TKIP)) {
1587 ar->arPairwiseCrypto |= TKIP_CRYPT;
1588 }
1589 if(!ar->arPairwiseCrypto) {
1590 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1591 ("Error - Invalid cipher in WPA \n"));
1592 ret = -EIO;
1593 }
1594 break;
1595 case IEEE80211_PARAM_PRIVACY:
1596 if(value == 0) {
1597 ar->arDot11AuthMode = OPEN_AUTH;
1598 ar->arAuthMode = NONE_AUTH;
1599 ar->arPairwiseCrypto = NONE_CRYPT;
1600 ar->arPairwiseCryptoLen = 0;
1601 ar->arGroupCrypto = NONE_CRYPT;
1602 ar->arGroupCryptoLen = 0;
1603 }
1604 break;
1605#ifdef WAPI_ENABLE
1606 case IEEE80211_PARAM_WAPI:
1607 A_PRINTF("WAPI Policy: %d\n", value);
1608 ar->arDot11AuthMode = OPEN_AUTH;
1609 ar->arAuthMode = NONE_AUTH;
1610 if(value & 0x1) {
1611 ar->arPairwiseCrypto = WAPI_CRYPT;
1612 ar->arGroupCrypto = WAPI_CRYPT;
1613 } else {
1614 ar->arPairwiseCrypto = NONE_CRYPT;
1615 ar->arGroupCrypto = NONE_CRYPT;
1616 }
1617 break;
1618#endif
1619 }
1620 return ret;
1621}
1622
1623int
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001624ar6000_ioctl_setparam(struct ar6_softc *ar, int param, int value)
Vipin Mehta30295c82010-09-01 12:06:33 -07001625{
Joe Perches1071a132011-02-02 14:05:47 -08001626 bool profChanged = false;
Vipin Mehta30295c82010-09-01 12:06:33 -07001627 int ret=0;
1628
1629 if(ar->arNextMode == AP_NETWORK) {
1630 ar->ap_profile_flag = 1; /* There is a change in profile */
1631 switch (param) {
1632 case IEEE80211_PARAM_WPA:
1633 case IEEE80211_PARAM_AUTHMODE:
1634 case IEEE80211_PARAM_UCASTCIPHER:
1635 case IEEE80211_PARAM_PRIVACY:
1636 case IEEE80211_PARAM_WAPI:
1637 ret = ar6000_ioctl_ap_setparam(ar, param, value);
1638 return ret;
1639 }
1640 }
1641
1642 switch (param) {
1643 case IEEE80211_PARAM_WPA:
1644 switch (value) {
1645 case WPA_MODE_WPA1:
1646 ar->arAuthMode = WPA_AUTH;
Joe Perches1071a132011-02-02 14:05:47 -08001647 profChanged = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001648 break;
1649 case WPA_MODE_WPA2:
1650 ar->arAuthMode = WPA2_AUTH;
Joe Perches1071a132011-02-02 14:05:47 -08001651 profChanged = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001652 break;
1653 case WPA_MODE_NONE:
1654 ar->arAuthMode = NONE_AUTH;
Joe Perches1071a132011-02-02 14:05:47 -08001655 profChanged = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001656 break;
1657 }
1658 break;
1659 case IEEE80211_PARAM_AUTHMODE:
1660 switch(value) {
1661 case IEEE80211_AUTH_WPA_PSK:
1662 if (WPA_AUTH == ar->arAuthMode) {
1663 ar->arAuthMode = WPA_PSK_AUTH;
Joe Perches1071a132011-02-02 14:05:47 -08001664 profChanged = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001665 } else if (WPA2_AUTH == ar->arAuthMode) {
1666 ar->arAuthMode = WPA2_PSK_AUTH;
Joe Perches1071a132011-02-02 14:05:47 -08001667 profChanged = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001668 } else {
1669 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Error - Setting PSK "\
1670 "mode when WPA param was set to %d\n",
1671 ar->arAuthMode));
1672 ret = -EIO;
1673 }
1674 break;
1675 case IEEE80211_AUTH_WPA_CCKM:
1676 if (WPA2_AUTH == ar->arAuthMode) {
1677 ar->arAuthMode = WPA2_AUTH_CCKM;
1678 } else {
1679 ar->arAuthMode = WPA_AUTH_CCKM;
1680 }
1681 break;
1682 default:
1683 break;
1684 }
1685 break;
1686 case IEEE80211_PARAM_UCASTCIPHER:
1687 switch (value) {
1688 case IEEE80211_CIPHER_AES_CCM:
1689 ar->arPairwiseCrypto = AES_CRYPT;
Joe Perches1071a132011-02-02 14:05:47 -08001690 profChanged = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001691 break;
1692 case IEEE80211_CIPHER_TKIP:
1693 ar->arPairwiseCrypto = TKIP_CRYPT;
Joe Perches1071a132011-02-02 14:05:47 -08001694 profChanged = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001695 break;
1696 case IEEE80211_CIPHER_WEP:
1697 ar->arPairwiseCrypto = WEP_CRYPT;
Joe Perches1071a132011-02-02 14:05:47 -08001698 profChanged = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001699 break;
1700 case IEEE80211_CIPHER_NONE:
1701 ar->arPairwiseCrypto = NONE_CRYPT;
Joe Perches1071a132011-02-02 14:05:47 -08001702 profChanged = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001703 break;
1704 }
1705 break;
1706 case IEEE80211_PARAM_UCASTKEYLEN:
1707 if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(value)) {
1708 ret = -EIO;
1709 } else {
1710 ar->arPairwiseCryptoLen = value;
1711 }
1712 break;
1713 case IEEE80211_PARAM_MCASTCIPHER:
1714 switch (value) {
1715 case IEEE80211_CIPHER_AES_CCM:
1716 ar->arGroupCrypto = AES_CRYPT;
Joe Perches1071a132011-02-02 14:05:47 -08001717 profChanged = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001718 break;
1719 case IEEE80211_CIPHER_TKIP:
1720 ar->arGroupCrypto = TKIP_CRYPT;
Joe Perches1071a132011-02-02 14:05:47 -08001721 profChanged = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001722 break;
1723 case IEEE80211_CIPHER_WEP:
1724 ar->arGroupCrypto = WEP_CRYPT;
Joe Perches1071a132011-02-02 14:05:47 -08001725 profChanged = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001726 break;
1727 case IEEE80211_CIPHER_NONE:
1728 ar->arGroupCrypto = NONE_CRYPT;
Joe Perches1071a132011-02-02 14:05:47 -08001729 profChanged = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001730 break;
1731 }
1732 break;
1733 case IEEE80211_PARAM_MCASTKEYLEN:
1734 if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(value)) {
1735 ret = -EIO;
1736 } else {
1737 ar->arGroupCryptoLen = value;
1738 }
1739 break;
1740 case IEEE80211_PARAM_COUNTERMEASURES:
Joe Perches1071a132011-02-02 14:05:47 -08001741 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001742 return -EIO;
1743 }
1744 wmi_set_tkip_countermeasures_cmd(ar->arWmi, value);
1745 break;
1746 default:
1747 break;
1748 }
Joe Perches1071a132011-02-02 14:05:47 -08001749 if ((ar->arNextMode != AP_NETWORK) && (profChanged == true)) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001750 /*
1751 * profile has changed. Erase ssid to signal change
1752 */
1753 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1754 }
1755
1756 return ret;
1757}
1758
1759int
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001760ar6000_ioctl_setkey(struct ar6_softc *ar, struct ieee80211req_key *ik)
Vipin Mehta30295c82010-09-01 12:06:33 -07001761{
1762 KEY_USAGE keyUsage;
Joe Perches1f4c34b2011-01-27 20:04:19 -08001763 int status;
Vipin Mehta30295c82010-09-01 12:06:33 -07001764 CRYPTO_TYPE keyType = NONE_CRYPT;
1765
1766#ifdef USER_KEYS
Joe Perches1071a132011-02-02 14:05:47 -08001767 ar->user_saved_keys.keyOk = false;
Vipin Mehta30295c82010-09-01 12:06:33 -07001768#endif
1769 if ( (0 == memcmp(ik->ik_macaddr, null_mac, IEEE80211_ADDR_LEN)) ||
1770 (0 == memcmp(ik->ik_macaddr, bcast_mac, IEEE80211_ADDR_LEN)) ) {
1771 keyUsage = GROUP_USAGE;
1772 if(ar->arNextMode == AP_NETWORK) {
Luis R. Rodriguez05209262011-03-10 18:55:29 -08001773 memcpy(&ar->ap_mode_bkey, ik,
Vipin Mehta30295c82010-09-01 12:06:33 -07001774 sizeof(struct ieee80211req_key));
1775#ifdef WAPI_ENABLE
1776 if(ar->arPairwiseCrypto == WAPI_CRYPT) {
1777 return ap_set_wapi_key(ar, ik);
1778 }
1779#endif
1780 }
1781#ifdef USER_KEYS
Luis R. Rodriguez05209262011-03-10 18:55:29 -08001782 memcpy(&ar->user_saved_keys.bcast_ik, ik,
Vipin Mehta30295c82010-09-01 12:06:33 -07001783 sizeof(struct ieee80211req_key));
1784#endif
1785 } else {
1786 keyUsage = PAIRWISE_USAGE;
1787#ifdef USER_KEYS
Luis R. Rodriguez05209262011-03-10 18:55:29 -08001788 memcpy(&ar->user_saved_keys.ucast_ik, ik,
Vipin Mehta30295c82010-09-01 12:06:33 -07001789 sizeof(struct ieee80211req_key));
1790#endif
1791#ifdef WAPI_ENABLE
1792 if(ar->arNextMode == AP_NETWORK) {
1793 if(ar->arPairwiseCrypto == WAPI_CRYPT) {
1794 return ap_set_wapi_key(ar, ik);
1795 }
1796 }
1797#endif
1798 }
1799
1800 switch (ik->ik_type) {
1801 case IEEE80211_CIPHER_WEP:
1802 keyType = WEP_CRYPT;
1803 break;
1804 case IEEE80211_CIPHER_TKIP:
1805 keyType = TKIP_CRYPT;
1806 break;
1807 case IEEE80211_CIPHER_AES_CCM:
1808 keyType = AES_CRYPT;
1809 break;
1810 default:
1811 break;
1812 }
1813#ifdef USER_KEYS
1814 ar->user_saved_keys.keyType = keyType;
1815#endif
1816 if (IEEE80211_CIPHER_CCKM_KRK != ik->ik_type) {
1817 if (NONE_CRYPT == keyType) {
1818 return -EIO;
1819 }
1820
1821 if ((WEP_CRYPT == keyType)&&(!ar->arConnected)) {
1822 int index = ik->ik_keyix;
1823
1824 if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(ik->ik_keylen)) {
1825 return -EIO;
1826 }
1827
1828 A_MEMZERO(ar->arWepKeyList[index].arKey,
1829 sizeof(ar->arWepKeyList[index].arKey));
Luis R. Rodriguez05209262011-03-10 18:55:29 -08001830 memcpy(ar->arWepKeyList[index].arKey, ik->ik_keydata, ik->ik_keylen);
Vipin Mehta30295c82010-09-01 12:06:33 -07001831 ar->arWepKeyList[index].arKeyLen = ik->ik_keylen;
1832
1833 if(ik->ik_flags & IEEE80211_KEY_DEFAULT){
1834 ar->arDefTxKeyIndex = index;
1835 }
1836
1837 return 0;
1838 }
1839
1840 if (((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode)) &&
1841 (GROUP_USAGE & keyUsage))
1842 {
1843 A_UNTIMEOUT(&ar->disconnect_timer);
1844 }
1845
1846 status = wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, keyType, keyUsage,
Joe Perchesab3655d2011-02-02 14:05:49 -08001847 ik->ik_keylen, (u8 *)&ik->ik_keyrsc,
Vipin Mehta30295c82010-09-01 12:06:33 -07001848 ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr,
1849 SYNC_BOTH_WMIFLAG);
1850
Joe Perchesa1d46522011-02-02 14:05:56 -08001851 if (status) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001852 return -EIO;
1853 }
1854 } else {
1855 status = wmi_add_krk_cmd(ar->arWmi, ik->ik_keydata);
1856 }
1857
1858#ifdef USER_KEYS
Joe Perches1071a132011-02-02 14:05:47 -08001859 ar->user_saved_keys.keyOk = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07001860#endif
1861
1862 return 0;
1863}
1864
1865int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
1866{
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07001867 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Luis R. Rodriguez9dabb722011-03-14 10:59:12 -07001868 struct hif_device *hifDevice = ar->arHifDevice;
Vipin Mehta30295c82010-09-01 12:06:33 -07001869 int ret = 0, param;
1870 unsigned int address = 0;
1871 unsigned int length = 0;
1872 unsigned char *buffer;
1873 char *userdata;
Joe Perchese1ce2a32011-02-02 14:05:51 -08001874 u32 connectCtrlFlags;
Vipin Mehta30295c82010-09-01 12:06:33 -07001875
1876
1877 WMI_SET_AKMP_PARAMS_CMD akmpParams;
1878 WMI_SET_PMKID_LIST_CMD pmkidInfo;
1879
1880 WMI_SET_HT_CAP_CMD htCap;
1881 WMI_SET_HT_OP_CMD htOp;
1882
1883 /*
1884 * ioctl operations may have to wait for the Target, so we cannot hold rtnl.
1885 * Prevent the device from disappearing under us and release the lock during
1886 * the ioctl operation.
1887 */
1888 dev_hold(dev);
1889 rtnl_unlock();
1890
1891 if (cmd == AR6000_IOCTL_EXTENDED) {
1892 /*
1893 * This allows for many more wireless ioctls than would otherwise
1894 * be available. Applications embed the actual ioctl command in
1895 * the first word of the parameter block, and use the command
1896 * AR6000_IOCTL_EXTENDED_CMD on the ioctl call.
1897 */
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04001898 if (get_user(cmd, (int *)rq->ifr_data)) {
1899 ret = -EFAULT;
1900 goto ioctl_done;
1901 }
Vipin Mehta30295c82010-09-01 12:06:33 -07001902 userdata = (char *)(((unsigned int *)rq->ifr_data)+1);
Joe Perches4f69cef2011-02-02 14:05:57 -08001903 if(is_xioctl_allowed(ar->arNextMode, cmd) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001904 A_PRINTF("xioctl: cmd=%d not allowed in this mode\n",cmd);
1905 ret = -EOPNOTSUPP;
1906 goto ioctl_done;
1907 }
1908 } else {
Joe Perches1f4c34b2011-01-27 20:04:19 -08001909 int ret = is_iwioctl_allowed(ar->arNextMode, cmd);
Vipin Mehta30295c82010-09-01 12:06:33 -07001910 if(ret == A_ENOTSUP) {
1911 A_PRINTF("iwioctl: cmd=0x%x not allowed in this mode\n", cmd);
1912 ret = -EOPNOTSUPP;
1913 goto ioctl_done;
1914 } else if (ret == A_ERROR) {
1915 /* It is not our ioctl (out of range ioctl) */
1916 ret = -EOPNOTSUPP;
1917 goto ioctl_done;
1918 }
1919 userdata = (char *)rq->ifr_data;
1920 }
1921
1922 if ((ar->arWlanState == WLAN_DISABLED) &&
1923 ((cmd != AR6000_XIOCTRL_WMI_SET_WLAN_STATE) &&
1924 (cmd != AR6000_XIOCTL_GET_WLAN_SLEEP_STATE) &&
1925 (cmd != AR6000_XIOCTL_DIAG_READ) &&
1926 (cmd != AR6000_XIOCTL_DIAG_WRITE) &&
1927 (cmd != AR6000_XIOCTL_SET_BT_HW_POWER_STATE) &&
1928 (cmd != AR6000_XIOCTL_GET_BT_HW_POWER_STATE) &&
1929 (cmd != AR6000_XIOCTL_ADD_AP_INTERFACE) &&
1930 (cmd != AR6000_XIOCTL_REMOVE_AP_INTERFACE) &&
1931 (cmd != AR6000_IOCTL_WMI_GETREV)))
1932 {
1933 ret = -EIO;
1934 goto ioctl_done;
1935 }
1936
1937 ret = 0;
1938 switch(cmd)
1939 {
1940 case IEEE80211_IOCTL_SETPARAM:
1941 {
1942 int param, value;
1943 int *ptr = (int *)rq->ifr_ifru.ifru_newname;
Joe Perches1071a132011-02-02 14:05:47 -08001944 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001945 ret = -EIO;
1946 } else {
1947 param = *ptr++;
1948 value = *ptr;
1949 ret = ar6000_ioctl_setparam(ar,param,value);
1950 }
1951 break;
1952 }
1953 case IEEE80211_IOCTL_SETKEY:
1954 {
1955 struct ieee80211req_key keydata;
Joe Perches1071a132011-02-02 14:05:47 -08001956 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001957 ret = -EIO;
1958 } else if (copy_from_user(&keydata, userdata,
1959 sizeof(struct ieee80211req_key))) {
1960 ret = -EFAULT;
1961 } else {
1962 ar6000_ioctl_setkey(ar, &keydata);
1963 }
1964 break;
1965 }
1966 case IEEE80211_IOCTL_DELKEY:
1967 case IEEE80211_IOCTL_SETOPTIE:
1968 {
1969 //ret = -EIO;
1970 break;
1971 }
1972 case IEEE80211_IOCTL_SETMLME:
1973 {
1974 struct ieee80211req_mlme mlme;
Joe Perches1071a132011-02-02 14:05:47 -08001975 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07001976 ret = -EIO;
1977 } else if (copy_from_user(&mlme, userdata,
1978 sizeof(struct ieee80211req_mlme))) {
1979 ret = -EFAULT;
1980 } else {
1981 switch (mlme.im_op) {
1982 case IEEE80211_MLME_AUTHORIZE:
1983 A_PRINTF("setmlme AUTHORIZE %02X:%02X\n",
1984 mlme.im_macaddr[4], mlme.im_macaddr[5]);
1985 break;
1986 case IEEE80211_MLME_UNAUTHORIZE:
1987 A_PRINTF("setmlme UNAUTHORIZE %02X:%02X\n",
1988 mlme.im_macaddr[4], mlme.im_macaddr[5]);
1989 break;
1990 case IEEE80211_MLME_DEAUTH:
1991 A_PRINTF("setmlme DEAUTH %02X:%02X\n",
1992 mlme.im_macaddr[4], mlme.im_macaddr[5]);
1993 //remove_sta(ar, mlme.im_macaddr);
1994 break;
1995 case IEEE80211_MLME_DISASSOC:
1996 A_PRINTF("setmlme DISASSOC %02X:%02X\n",
1997 mlme.im_macaddr[4], mlme.im_macaddr[5]);
1998 //remove_sta(ar, mlme.im_macaddr);
1999 break;
2000 default:
2001 ret = 0;
2002 goto ioctl_done;
2003 }
2004
2005 wmi_ap_set_mlme(ar->arWmi, mlme.im_op, mlme.im_macaddr,
2006 mlme.im_reason);
2007 }
2008 break;
2009 }
2010 case IEEE80211_IOCTL_ADDPMKID:
2011 {
2012 struct ieee80211req_addpmkid req;
Joe Perches1071a132011-02-02 14:05:47 -08002013 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002014 ret = -EIO;
2015 } else if (copy_from_user(&req, userdata, sizeof(struct ieee80211req_addpmkid))) {
2016 ret = -EFAULT;
2017 } else {
Joe Perches1f4c34b2011-01-27 20:04:19 -08002018 int status;
Vipin Mehta30295c82010-09-01 12:06:33 -07002019
2020 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("Add pmkid for %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x en=%d\n",
2021 req.pi_bssid[0], req.pi_bssid[1], req.pi_bssid[2],
2022 req.pi_bssid[3], req.pi_bssid[4], req.pi_bssid[5],
2023 req.pi_enable));
2024
2025 status = wmi_setPmkid_cmd(ar->arWmi, req.pi_bssid, req.pi_pmkid,
2026 req.pi_enable);
2027
Joe Perchesa1d46522011-02-02 14:05:56 -08002028 if (status) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002029 ret = -EIO;
2030 goto ioctl_done;
2031 }
2032 }
2033 break;
2034 }
2035#ifdef CONFIG_HOST_TCMD_SUPPORT
2036 case AR6000_XIOCTL_TCMD_CONT_TX:
2037 {
2038 TCMD_CONT_TX txCmd;
2039
2040 if ((ar->tcmdPm == TCMD_PM_SLEEP) ||
2041 (ar->tcmdPm == TCMD_PM_DEEPSLEEP))
2042 {
2043 A_PRINTF("Can NOT send tx tcmd when target is asleep! \n");
2044 ret = -EFAULT;
2045 goto ioctl_done;
2046 }
2047
2048 if(copy_from_user(&txCmd, userdata, sizeof(TCMD_CONT_TX))) {
2049 ret = -EFAULT;
2050 goto ioctl_done;
2051 } else {
Joe Perchesab3655d2011-02-02 14:05:49 -08002052 wmi_test_cmd(ar->arWmi,(u8 *)&txCmd, sizeof(TCMD_CONT_TX));
Vipin Mehta30295c82010-09-01 12:06:33 -07002053 }
2054 }
2055 break;
2056 case AR6000_XIOCTL_TCMD_CONT_RX:
2057 {
2058 TCMD_CONT_RX rxCmd;
2059
2060 if ((ar->tcmdPm == TCMD_PM_SLEEP) ||
2061 (ar->tcmdPm == TCMD_PM_DEEPSLEEP))
2062 {
2063 A_PRINTF("Can NOT send rx tcmd when target is asleep! \n");
2064 ret = -EFAULT;
2065 goto ioctl_done;
2066 }
2067 if(copy_from_user(&rxCmd, userdata, sizeof(TCMD_CONT_RX))) {
2068 ret = -EFAULT;
2069 goto ioctl_done;
2070 }
2071
2072 switch(rxCmd.act)
2073 {
2074 case TCMD_CONT_RX_PROMIS:
2075 case TCMD_CONT_RX_FILTER:
2076 case TCMD_CONT_RX_SETMAC:
2077 case TCMD_CONT_RX_SET_ANT_SWITCH_TABLE:
Joe Perchesab3655d2011-02-02 14:05:49 -08002078 wmi_test_cmd(ar->arWmi,(u8 *)&rxCmd,
Vipin Mehta30295c82010-09-01 12:06:33 -07002079 sizeof(TCMD_CONT_RX));
2080 tcmdRxFreq = rxCmd.u.para.freq;
2081 break;
2082 case TCMD_CONT_RX_REPORT:
2083 ar6000_ioctl_tcmd_get_rx_report(dev, rq,
Joe Perchesab3655d2011-02-02 14:05:49 -08002084 (u8 *)&rxCmd, sizeof(TCMD_CONT_RX));
Vipin Mehta30295c82010-09-01 12:06:33 -07002085 break;
2086 default:
2087 A_PRINTF("Unknown Cont Rx mode: %d\n",rxCmd.act);
2088 ret = -EINVAL;
2089 goto ioctl_done;
2090 }
2091 }
2092 break;
2093 case AR6000_XIOCTL_TCMD_PM:
2094 {
2095 TCMD_PM pmCmd;
2096
2097 if(copy_from_user(&pmCmd, userdata, sizeof(TCMD_PM))) {
2098 ret = -EFAULT;
2099 goto ioctl_done;
2100 }
2101 ar->tcmdPm = pmCmd.mode;
Joe Perchesab3655d2011-02-02 14:05:49 -08002102 wmi_test_cmd(ar->arWmi, (u8 *)&pmCmd, sizeof(TCMD_PM));
Vipin Mehta30295c82010-09-01 12:06:33 -07002103 }
2104 break;
2105#endif /* CONFIG_HOST_TCMD_SUPPORT */
2106
2107 case AR6000_XIOCTL_BMI_DONE:
2108 if(bmienable)
2109 {
2110 rtnl_lock(); /* ar6000_init expects to be called holding rtnl lock */
2111 ret = ar6000_init(dev);
2112 rtnl_unlock();
2113 }
2114 else
2115 {
2116 ret = BMIDone(hifDevice);
2117 }
2118 break;
2119
2120 case AR6000_XIOCTL_BMI_READ_MEMORY:
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002121 if (get_user(address, (unsigned int *)userdata) ||
2122 get_user(length, (unsigned int *)userdata + 1)) {
2123 ret = -EFAULT;
2124 break;
2125 }
2126
Vipin Mehta30295c82010-09-01 12:06:33 -07002127 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Read Memory (address: 0x%x, length: %d)\n",
2128 address, length));
2129 if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) {
2130 A_MEMZERO(buffer, length);
2131 ret = BMIReadMemory(hifDevice, address, buffer, length);
2132 if (copy_to_user(rq->ifr_data, buffer, length)) {
2133 ret = -EFAULT;
2134 }
2135 A_FREE(buffer);
2136 } else {
2137 ret = -ENOMEM;
2138 }
2139 break;
2140
2141 case AR6000_XIOCTL_BMI_WRITE_MEMORY:
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002142 if (get_user(address, (unsigned int *)userdata) ||
2143 get_user(length, (unsigned int *)userdata + 1)) {
2144 ret = -EFAULT;
2145 break;
2146 }
Vipin Mehta30295c82010-09-01 12:06:33 -07002147 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Write Memory (address: 0x%x, length: %d)\n",
2148 address, length));
2149 if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) {
2150 A_MEMZERO(buffer, length);
2151 if (copy_from_user(buffer, &userdata[sizeof(address) +
2152 sizeof(length)], length))
2153 {
2154 ret = -EFAULT;
2155 } else {
2156 ret = BMIWriteMemory(hifDevice, address, buffer, length);
2157 }
2158 A_FREE(buffer);
2159 } else {
2160 ret = -ENOMEM;
2161 }
2162 break;
2163
2164 case AR6000_XIOCTL_BMI_TEST:
2165 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("No longer supported\n"));
2166 ret = -EOPNOTSUPP;
2167 break;
2168
2169 case AR6000_XIOCTL_BMI_EXECUTE:
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002170 if (get_user(address, (unsigned int *)userdata) ||
2171 get_user(param, (unsigned int *)userdata + 1)) {
2172 ret = -EFAULT;
2173 break;
2174 }
Vipin Mehta30295c82010-09-01 12:06:33 -07002175 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Execute (address: 0x%x, param: %d)\n",
2176 address, param));
Joe Perchese1ce2a32011-02-02 14:05:51 -08002177 ret = BMIExecute(hifDevice, address, (u32 *)&param);
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002178 /* return value */
2179 if (put_user(param, (unsigned int *)rq->ifr_data)) {
2180 ret = -EFAULT;
2181 break;
2182 }
Vipin Mehta30295c82010-09-01 12:06:33 -07002183 break;
2184
2185 case AR6000_XIOCTL_BMI_SET_APP_START:
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002186 if (get_user(address, (unsigned int *)userdata)) {
2187 ret = -EFAULT;
2188 break;
2189 }
Vipin Mehta30295c82010-09-01 12:06:33 -07002190 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Set App Start (address: 0x%x)\n", address));
2191 ret = BMISetAppStart(hifDevice, address);
2192 break;
2193
2194 case AR6000_XIOCTL_BMI_READ_SOC_REGISTER:
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002195 if (get_user(address, (unsigned int *)userdata)) {
2196 ret = -EFAULT;
2197 break;
2198 }
Joe Perchese1ce2a32011-02-02 14:05:51 -08002199 ret = BMIReadSOCRegister(hifDevice, address, (u32 *)&param);
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002200 /* return value */
2201 if (put_user(param, (unsigned int *)rq->ifr_data)) {
2202 ret = -EFAULT;
2203 break;
2204 }
Vipin Mehta30295c82010-09-01 12:06:33 -07002205 break;
2206
2207 case AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER:
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002208 if (get_user(address, (unsigned int *)userdata) ||
2209 get_user(param, (unsigned int *)userdata + 1)) {
2210 ret = -EFAULT;
2211 break;
2212 }
Vipin Mehta30295c82010-09-01 12:06:33 -07002213 ret = BMIWriteSOCRegister(hifDevice, address, param);
2214 break;
2215
2216#ifdef HTC_RAW_INTERFACE
2217 case AR6000_XIOCTL_HTC_RAW_OPEN:
Joe Perches4f69cef2011-02-02 14:05:57 -08002218 ret = 0;
Vipin Mehta30295c82010-09-01 12:06:33 -07002219 if (!arRawIfEnabled(ar)) {
2220 /* make sure block size is set in case the target was reset since last
2221 * BMI phase (i.e. flashup downloads) */
2222 ret = ar6000_set_htc_params(ar->arHifDevice,
2223 ar->arTargetType,
2224 0, /* use default yield */
2225 0 /* use default number of HTC ctrl buffers */
2226 );
Joe Perches391bb212011-01-27 20:04:21 -08002227 if (ret) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002228 break;
2229 }
2230 /* Terminate the BMI phase */
2231 ret = BMIDone(hifDevice);
Joe Perches4f69cef2011-02-02 14:05:57 -08002232 if (ret == 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002233 ret = ar6000_htc_raw_open(ar);
2234 }
2235 }
2236 break;
2237
2238 case AR6000_XIOCTL_HTC_RAW_CLOSE:
2239 if (arRawIfEnabled(ar)) {
2240 ret = ar6000_htc_raw_close(ar);
Joe Perches1071a132011-02-02 14:05:47 -08002241 arRawIfEnabled(ar) = false;
Vipin Mehta30295c82010-09-01 12:06:33 -07002242 } else {
2243 ret = A_ERROR;
2244 }
2245 break;
2246
2247 case AR6000_XIOCTL_HTC_RAW_READ:
2248 if (arRawIfEnabled(ar)) {
2249 unsigned int streamID;
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002250 if (get_user(streamID, (unsigned int *)userdata) ||
2251 get_user(length, (unsigned int *)userdata + 1)) {
2252 ret = -EFAULT;
2253 break;
2254 }
Vipin Mehta30295c82010-09-01 12:06:33 -07002255 buffer = (unsigned char*)rq->ifr_data + sizeof(length);
2256 ret = ar6000_htc_raw_read(ar, (HTC_RAW_STREAM_ID)streamID,
2257 (char*)buffer, length);
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002258 if (put_user(ret, (unsigned int *)rq->ifr_data)) {
2259 ret = -EFAULT;
2260 break;
2261 }
Vipin Mehta30295c82010-09-01 12:06:33 -07002262 } else {
2263 ret = A_ERROR;
2264 }
2265 break;
2266
2267 case AR6000_XIOCTL_HTC_RAW_WRITE:
2268 if (arRawIfEnabled(ar)) {
2269 unsigned int streamID;
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002270 if (get_user(streamID, (unsigned int *)userdata) ||
2271 get_user(length, (unsigned int *)userdata + 1)) {
2272 ret = -EFAULT;
2273 break;
2274 }
Vipin Mehta30295c82010-09-01 12:06:33 -07002275 buffer = (unsigned char*)userdata + sizeof(streamID) + sizeof(length);
2276 ret = ar6000_htc_raw_write(ar, (HTC_RAW_STREAM_ID)streamID,
2277 (char*)buffer, length);
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002278 if (put_user(ret, (unsigned int *)rq->ifr_data)) {
2279 ret = -EFAULT;
2280 break;
2281 }
Vipin Mehta30295c82010-09-01 12:06:33 -07002282 } else {
2283 ret = A_ERROR;
2284 }
2285 break;
2286#endif /* HTC_RAW_INTERFACE */
2287
2288 case AR6000_XIOCTL_BMI_LZ_STREAM_START:
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002289 if (get_user(address, (unsigned int *)userdata)) {
2290 ret = -EFAULT;
2291 break;
2292 }
Vipin Mehta30295c82010-09-01 12:06:33 -07002293 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Start Compressed Stream (address: 0x%x)\n", address));
2294 ret = BMILZStreamStart(hifDevice, address);
2295 break;
2296
2297 case AR6000_XIOCTL_BMI_LZ_DATA:
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002298 if (get_user(length, (unsigned int *)userdata)) {
2299 ret = -EFAULT;
2300 break;
2301 }
Vipin Mehta30295c82010-09-01 12:06:33 -07002302 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Send Compressed Data (length: %d)\n", length));
2303 if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) {
2304 A_MEMZERO(buffer, length);
2305 if (copy_from_user(buffer, &userdata[sizeof(length)], length))
2306 {
2307 ret = -EFAULT;
2308 } else {
2309 ret = BMILZData(hifDevice, buffer, length);
2310 }
2311 A_FREE(buffer);
2312 } else {
2313 ret = -ENOMEM;
2314 }
2315 break;
2316
2317#if defined(CONFIG_TARGET_PROFILE_SUPPORT)
2318 /*
2319 * Optional support for Target-side profiling.
2320 * Not needed in production.
2321 */
2322
2323 /* Configure Target-side profiling */
2324 case AR6000_XIOCTL_PROF_CFG:
2325 {
Joe Perchese1ce2a32011-02-02 14:05:51 -08002326 u32 period;
2327 u32 nbins;
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002328 if (get_user(period, (unsigned int *)userdata) ||
2329 get_user(nbins, (unsigned int *)userdata + 1)) {
2330 ret = -EFAULT;
2331 break;
2332 }
Vipin Mehta30295c82010-09-01 12:06:33 -07002333
Joe Perches4f69cef2011-02-02 14:05:57 -08002334 if (wmi_prof_cfg_cmd(ar->arWmi, period, nbins) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002335 ret = -EIO;
2336 }
2337
2338 break;
2339 }
2340
2341 /* Start a profiling bucket/bin at the specified address */
2342 case AR6000_XIOCTL_PROF_ADDR_SET:
2343 {
Joe Perchese1ce2a32011-02-02 14:05:51 -08002344 u32 addr;
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002345 if (get_user(addr, (unsigned int *)userdata)) {
2346 ret = -EFAULT;
2347 break;
2348 }
Vipin Mehta30295c82010-09-01 12:06:33 -07002349
Joe Perches4f69cef2011-02-02 14:05:57 -08002350 if (wmi_prof_addr_set_cmd(ar->arWmi, addr) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002351 ret = -EIO;
2352 }
2353
2354 break;
2355 }
2356
2357 /* START Target-side profiling */
2358 case AR6000_XIOCTL_PROF_START:
2359 wmi_prof_start_cmd(ar->arWmi);
2360 break;
2361
2362 /* STOP Target-side profiling */
2363 case AR6000_XIOCTL_PROF_STOP:
2364 wmi_prof_stop_cmd(ar->arWmi);
2365 break;
2366 case AR6000_XIOCTL_PROF_COUNT_GET:
2367 {
2368 if (ar->bIsDestroyProgress) {
2369 ret = -EBUSY;
2370 goto ioctl_done;
2371 }
Joe Perches1071a132011-02-02 14:05:47 -08002372 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002373 ret = -EIO;
2374 goto ioctl_done;
2375 }
2376 if (down_interruptible(&ar->arSem)) {
2377 ret = -ERESTARTSYS;
2378 goto ioctl_done;
2379 }
2380 if (ar->bIsDestroyProgress) {
2381 up(&ar->arSem);
2382 ret = -EBUSY;
2383 goto ioctl_done;
2384 }
2385
Joe Perches1071a132011-02-02 14:05:47 -08002386 prof_count_available = false;
Vipin Mehta30295c82010-09-01 12:06:33 -07002387 ret = prof_count_get(dev);
Joe Perches4f69cef2011-02-02 14:05:57 -08002388 if (ret != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002389 up(&ar->arSem);
2390 ret = -EIO;
2391 goto ioctl_done;
2392 }
2393
2394 /* Wait for Target to respond. */
2395 wait_event_interruptible(arEvent, prof_count_available);
2396 if (signal_pending(current)) {
2397 ret = -EINTR;
2398 } else {
2399 if (copy_to_user(userdata, &prof_count_results,
2400 sizeof(prof_count_results)))
2401 {
2402 ret = -EFAULT;
2403 }
2404 }
2405 up(&ar->arSem);
2406 break;
2407 }
2408#endif /* CONFIG_TARGET_PROFILE_SUPPORT */
2409
2410 case AR6000_IOCTL_WMI_GETREV:
2411 {
2412 if (copy_to_user(rq->ifr_data, &ar->arVersion,
2413 sizeof(ar->arVersion)))
2414 {
2415 ret = -EFAULT;
2416 }
2417 break;
2418 }
2419 case AR6000_IOCTL_WMI_SETPWR:
2420 {
2421 WMI_POWER_MODE_CMD pwrModeCmd;
2422
Joe Perches1071a132011-02-02 14:05:47 -08002423 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002424 ret = -EIO;
2425 } else if (copy_from_user(&pwrModeCmd, userdata,
2426 sizeof(pwrModeCmd)))
2427 {
2428 ret = -EFAULT;
2429 } else {
2430 if (wmi_powermode_cmd(ar->arWmi, pwrModeCmd.powerMode)
Joe Perches4f69cef2011-02-02 14:05:57 -08002431 != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07002432 {
2433 ret = -EIO;
2434 }
2435 }
2436 break;
2437 }
2438 case AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS:
2439 {
2440 WMI_IBSS_PM_CAPS_CMD ibssPmCaps;
2441
Joe Perches1071a132011-02-02 14:05:47 -08002442 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002443 ret = -EIO;
2444 } else if (copy_from_user(&ibssPmCaps, userdata,
2445 sizeof(ibssPmCaps)))
2446 {
2447 ret = -EFAULT;
2448 } else {
2449 if (wmi_ibsspmcaps_cmd(ar->arWmi, ibssPmCaps.power_saving, ibssPmCaps.ttl,
Joe Perches4f69cef2011-02-02 14:05:57 -08002450 ibssPmCaps.atim_windows, ibssPmCaps.timeout_value) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07002451 {
2452 ret = -EIO;
2453 }
2454 AR6000_SPIN_LOCK(&ar->arLock, 0);
2455 ar->arIbssPsEnable = ibssPmCaps.power_saving;
2456 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
2457 }
2458 break;
2459 }
2460 case AR6000_XIOCTL_WMI_SET_AP_PS:
2461 {
2462 WMI_AP_PS_CMD apPsCmd;
2463
Joe Perches1071a132011-02-02 14:05:47 -08002464 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002465 ret = -EIO;
2466 } else if (copy_from_user(&apPsCmd, userdata,
2467 sizeof(apPsCmd)))
2468 {
2469 ret = -EFAULT;
2470 } else {
2471 if (wmi_apps_cmd(ar->arWmi, apPsCmd.psType, apPsCmd.idle_time,
Joe Perches4f69cef2011-02-02 14:05:57 -08002472 apPsCmd.ps_period, apPsCmd.sleep_period) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07002473 {
2474 ret = -EIO;
2475 }
2476 }
2477 break;
2478 }
2479 case AR6000_IOCTL_WMI_SET_PMPARAMS:
2480 {
2481 WMI_POWER_PARAMS_CMD pmParams;
2482
Joe Perches1071a132011-02-02 14:05:47 -08002483 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002484 ret = -EIO;
2485 } else if (copy_from_user(&pmParams, userdata,
2486 sizeof(pmParams)))
2487 {
2488 ret = -EFAULT;
2489 } else {
2490 if (wmi_pmparams_cmd(ar->arWmi, pmParams.idle_period,
2491 pmParams.pspoll_number,
2492 pmParams.dtim_policy,
2493 pmParams.tx_wakeup_policy,
2494 pmParams.num_tx_to_wakeup,
2495#if WLAN_CONFIG_IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN
2496 IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN
2497#else
2498 SEND_POWER_SAVE_FAIL_EVENT_ALWAYS
2499#endif
Joe Perches4f69cef2011-02-02 14:05:57 -08002500 ) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07002501 {
2502 ret = -EIO;
2503 }
2504 }
2505 break;
2506 }
2507 case AR6000_IOCTL_WMI_SETSCAN:
2508 {
Joe Perches1071a132011-02-02 14:05:47 -08002509 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002510 ret = -EIO;
2511 } else if (copy_from_user(&ar->scParams, userdata,
2512 sizeof(ar->scParams)))
2513 {
2514 ret = -EFAULT;
2515 } else {
2516 if (CAN_SCAN_IN_CONNECT(ar->scParams.scanCtrlFlags)) {
Joe Perches1071a132011-02-02 14:05:47 -08002517 ar->arSkipScan = false;
Vipin Mehta30295c82010-09-01 12:06:33 -07002518 } else {
Joe Perches1071a132011-02-02 14:05:47 -08002519 ar->arSkipScan = true;
Vipin Mehta30295c82010-09-01 12:06:33 -07002520 }
2521
2522 if (wmi_scanparams_cmd(ar->arWmi, ar->scParams.fg_start_period,
2523 ar->scParams.fg_end_period,
2524 ar->scParams.bg_period,
2525 ar->scParams.minact_chdwell_time,
2526 ar->scParams.maxact_chdwell_time,
2527 ar->scParams.pas_chdwell_time,
2528 ar->scParams.shortScanRatio,
2529 ar->scParams.scanCtrlFlags,
2530 ar->scParams.max_dfsch_act_time,
Joe Perches4f69cef2011-02-02 14:05:57 -08002531 ar->scParams.maxact_scan_per_ssid) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07002532 {
2533 ret = -EIO;
2534 }
2535 }
2536 break;
2537 }
2538 case AR6000_IOCTL_WMI_SETLISTENINT:
2539 {
2540 WMI_LISTEN_INT_CMD listenCmd;
2541
Joe Perches1071a132011-02-02 14:05:47 -08002542 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002543 ret = -EIO;
2544 } else if (copy_from_user(&listenCmd, userdata,
2545 sizeof(listenCmd)))
2546 {
2547 ret = -EFAULT;
2548 } else {
Joe Perches4f69cef2011-02-02 14:05:57 -08002549 if (wmi_listeninterval_cmd(ar->arWmi, listenCmd.listenInterval, listenCmd.numBeacons) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002550 ret = -EIO;
2551 } else {
2552 AR6000_SPIN_LOCK(&ar->arLock, 0);
2553 ar->arListenIntervalT = listenCmd.listenInterval;
2554 ar->arListenIntervalB = listenCmd.numBeacons;
2555 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
2556 }
2557
2558 }
2559 break;
2560 }
2561 case AR6000_IOCTL_WMI_SET_BMISS_TIME:
2562 {
2563 WMI_BMISS_TIME_CMD bmissCmd;
2564
Joe Perches1071a132011-02-02 14:05:47 -08002565 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002566 ret = -EIO;
2567 } else if (copy_from_user(&bmissCmd, userdata,
2568 sizeof(bmissCmd)))
2569 {
2570 ret = -EFAULT;
2571 } else {
Joe Perches4f69cef2011-02-02 14:05:57 -08002572 if (wmi_bmisstime_cmd(ar->arWmi, bmissCmd.bmissTime, bmissCmd.numBeacons) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002573 ret = -EIO;
2574 }
2575 }
2576 break;
2577 }
2578 case AR6000_IOCTL_WMI_SETBSSFILTER:
2579 {
2580 WMI_BSS_FILTER_CMD filt;
2581
Joe Perches1071a132011-02-02 14:05:47 -08002582 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002583 ret = -EIO;
2584 } else if (copy_from_user(&filt, userdata,
2585 sizeof(filt)))
2586 {
2587 ret = -EFAULT;
2588 } else {
2589 if (wmi_bssfilter_cmd(ar->arWmi, filt.bssFilter, filt.ieMask)
Joe Perches4f69cef2011-02-02 14:05:57 -08002590 != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002591 ret = -EIO;
2592 } else {
Vipin Mehta9ea979d2011-02-18 13:13:13 -08002593 ar->arUserBssFilter = filt.bssFilter;
Vipin Mehta30295c82010-09-01 12:06:33 -07002594 }
2595 }
2596 break;
2597 }
2598
2599 case AR6000_IOCTL_WMI_SET_SNRTHRESHOLD:
2600 {
2601 ret = ar6000_ioctl_set_snr_threshold(dev, rq);
2602 break;
2603 }
2604 case AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD:
2605 {
2606 ret = ar6000_ioctl_set_rssi_threshold(dev, rq);
2607 break;
2608 }
2609 case AR6000_XIOCTL_WMI_CLR_RSSISNR:
2610 {
Joe Perches1071a132011-02-02 14:05:47 -08002611 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002612 ret = -EIO;
2613 }
2614 ret = wmi_clr_rssi_snr(ar->arWmi);
2615 break;
2616 }
2617 case AR6000_XIOCTL_WMI_SET_LQTHRESHOLD:
2618 {
2619 ret = ar6000_ioctl_set_lq_threshold(dev, rq);
2620 break;
2621 }
2622 case AR6000_XIOCTL_WMI_SET_LPREAMBLE:
2623 {
2624 WMI_SET_LPREAMBLE_CMD setLpreambleCmd;
2625
Joe Perches1071a132011-02-02 14:05:47 -08002626 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002627 ret = -EIO;
2628 } else if (copy_from_user(&setLpreambleCmd, userdata,
2629 sizeof(setLpreambleCmd)))
2630 {
2631 ret = -EFAULT;
2632 } else {
2633 if (wmi_set_lpreamble_cmd(ar->arWmi, setLpreambleCmd.status,
2634#if WLAN_CONFIG_DONOT_IGNORE_BARKER_IN_ERP
2635 WMI_DONOT_IGNORE_BARKER_IN_ERP
2636#else
2637 WMI_IGNORE_BARKER_IN_ERP
2638#endif
Joe Perches4f69cef2011-02-02 14:05:57 -08002639 ) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07002640 {
2641 ret = -EIO;
2642 }
2643 }
2644
2645 break;
2646 }
2647 case AR6000_XIOCTL_WMI_SET_RTS:
2648 {
2649 WMI_SET_RTS_CMD rtsCmd;
Joe Perches1071a132011-02-02 14:05:47 -08002650 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002651 ret = -EIO;
2652 } else if (copy_from_user(&rtsCmd, userdata,
2653 sizeof(rtsCmd)))
2654 {
2655 ret = -EFAULT;
2656 } else {
2657 ar->arRTS = rtsCmd.threshold;
2658 if (wmi_set_rts_cmd(ar->arWmi, rtsCmd.threshold)
Joe Perches4f69cef2011-02-02 14:05:57 -08002659 != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07002660 {
2661 ret = -EIO;
2662 }
2663 }
2664
2665 break;
2666 }
2667 case AR6000_XIOCTL_WMI_SET_WMM:
2668 {
2669 ret = ar6000_ioctl_set_wmm(dev, rq);
2670 break;
2671 }
2672 case AR6000_XIOCTL_WMI_SET_QOS_SUPP:
2673 {
2674 ret = ar6000_ioctl_set_qos_supp(dev, rq);
2675 break;
2676 }
2677 case AR6000_XIOCTL_WMI_SET_TXOP:
2678 {
2679 ret = ar6000_ioctl_set_txop(dev, rq);
2680 break;
2681 }
2682 case AR6000_XIOCTL_WMI_GET_RD:
2683 {
2684 ret = ar6000_ioctl_get_rd(dev, rq);
2685 break;
2686 }
2687 case AR6000_IOCTL_WMI_SET_CHANNELPARAMS:
2688 {
2689 ret = ar6000_ioctl_set_channelParams(dev, rq);
2690 break;
2691 }
2692 case AR6000_IOCTL_WMI_SET_PROBEDSSID:
2693 {
2694 ret = ar6000_ioctl_set_probedSsid(dev, rq);
2695 break;
2696 }
2697 case AR6000_IOCTL_WMI_SET_BADAP:
2698 {
2699 ret = ar6000_ioctl_set_badAp(dev, rq);
2700 break;
2701 }
2702 case AR6000_IOCTL_WMI_CREATE_QOS:
2703 {
2704 ret = ar6000_ioctl_create_qos(dev, rq);
2705 break;
2706 }
2707 case AR6000_IOCTL_WMI_DELETE_QOS:
2708 {
2709 ret = ar6000_ioctl_delete_qos(dev, rq);
2710 break;
2711 }
2712 case AR6000_IOCTL_WMI_GET_QOS_QUEUE:
2713 {
2714 ret = ar6000_ioctl_get_qos_queue(dev, rq);
2715 break;
2716 }
2717 case AR6000_IOCTL_WMI_GET_TARGET_STATS:
2718 {
2719 ret = ar6000_ioctl_get_target_stats(dev, rq);
2720 break;
2721 }
2722 case AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK:
2723 {
2724 ret = ar6000_ioctl_set_error_report_bitmask(dev, rq);
2725 break;
2726 }
2727 case AR6000_IOCTL_WMI_SET_ASSOC_INFO:
2728 {
2729 WMI_SET_ASSOC_INFO_CMD cmd;
Joe Perchesab3655d2011-02-02 14:05:49 -08002730 u8 assocInfo[WMI_MAX_ASSOC_INFO_LEN];
Vipin Mehta30295c82010-09-01 12:06:33 -07002731
Joe Perches1071a132011-02-02 14:05:47 -08002732 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002733 ret = -EIO;
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002734 break;
2735 }
2736
Vipin Mehtab6c78752010-09-07 17:06:50 -07002737 if (get_user(cmd.ieType, userdata)) {
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002738 ret = -EFAULT;
2739 break;
2740 }
2741 if (cmd.ieType >= WMI_MAX_ASSOC_INFO_TYPE) {
2742 ret = -EIO;
2743 break;
2744 }
2745
2746 if (get_user(cmd.bufferSize, userdata + 1) ||
2747 (cmd.bufferSize > WMI_MAX_ASSOC_INFO_LEN) ||
2748 copy_from_user(assocInfo, userdata + 2, cmd.bufferSize)) {
2749 ret = -EFAULT;
2750 break;
2751 }
2752 if (wmi_associnfo_cmd(ar->arWmi, cmd.ieType,
Joe Perches4f69cef2011-02-02 14:05:57 -08002753 cmd.bufferSize, assocInfo) != 0) {
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04002754 ret = -EIO;
2755 break;
2756 }
Vipin Mehta30295c82010-09-01 12:06:33 -07002757 break;
2758 }
2759 case AR6000_IOCTL_WMI_SET_ACCESS_PARAMS:
2760 {
2761 ret = ar6000_ioctl_set_access_params(dev, rq);
2762 break;
2763 }
2764 case AR6000_IOCTL_WMI_SET_DISC_TIMEOUT:
2765 {
2766 ret = ar6000_ioctl_set_disconnect_timeout(dev, rq);
2767 break;
2768 }
2769 case AR6000_XIOCTL_FORCE_TARGET_RESET:
2770 {
2771 if (ar->arHtcTarget)
2772 {
2773// HTCForceReset(htcTarget);
2774 }
2775 else
2776 {
2777 AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("ar6000_ioctl cannot attempt reset.\n"));
2778 }
2779 break;
2780 }
2781 case AR6000_XIOCTL_TARGET_INFO:
2782 case AR6000_XIOCTL_CHECK_TARGET_READY: /* backwards compatibility */
2783 {
2784 /* If we made it to here, then the Target exists and is ready. */
2785
2786 if (cmd == AR6000_XIOCTL_TARGET_INFO) {
Joe Perchese1ce2a32011-02-02 14:05:51 -08002787 if (copy_to_user((u32 *)rq->ifr_data, &ar->arVersion.target_ver,
Vipin Mehta30295c82010-09-01 12:06:33 -07002788 sizeof(ar->arVersion.target_ver)))
2789 {
2790 ret = -EFAULT;
2791 }
Joe Perchese1ce2a32011-02-02 14:05:51 -08002792 if (copy_to_user(((u32 *)rq->ifr_data)+1, &ar->arTargetType,
Vipin Mehta30295c82010-09-01 12:06:33 -07002793 sizeof(ar->arTargetType)))
2794 {
2795 ret = -EFAULT;
2796 }
2797 }
2798 break;
2799 }
2800 case AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS:
2801 {
2802 WMI_SET_HB_CHALLENGE_RESP_PARAMS_CMD hbparam;
2803
2804 if (copy_from_user(&hbparam, userdata, sizeof(hbparam)))
2805 {
2806 ret = -EFAULT;
2807 } else {
2808 AR6000_SPIN_LOCK(&ar->arLock, 0);
2809 /* Start a cyclic timer with the parameters provided. */
2810 if (hbparam.frequency) {
2811 ar->arHBChallengeResp.frequency = hbparam.frequency;
2812 }
2813 if (hbparam.threshold) {
2814 ar->arHBChallengeResp.missThres = hbparam.threshold;
2815 }
2816
2817 /* Delete the pending timer and start a new one */
2818 if (timer_pending(&ar->arHBChallengeResp.timer)) {
2819 A_UNTIMEOUT(&ar->arHBChallengeResp.timer);
2820 }
2821 A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0);
2822 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
2823 }
2824 break;
2825 }
2826 case AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP:
2827 {
Joe Perchese1ce2a32011-02-02 14:05:51 -08002828 u32 cookie;
Vipin Mehta30295c82010-09-01 12:06:33 -07002829
2830 if (copy_from_user(&cookie, userdata, sizeof(cookie))) {
2831 ret = -EFAULT;
2832 goto ioctl_done;
2833 }
2834
2835 /* Send the challenge on the control channel */
Joe Perches4f69cef2011-02-02 14:05:57 -08002836 if (wmi_get_challenge_resp_cmd(ar->arWmi, cookie, APP_HB_CHALLENGE) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002837 ret = -EIO;
2838 goto ioctl_done;
2839 }
2840 break;
2841 }
2842#ifdef USER_KEYS
2843 case AR6000_XIOCTL_USER_SETKEYS:
2844 {
2845
2846 ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_RUN;
2847
2848 if (copy_from_user(&ar->user_key_ctrl, userdata,
2849 sizeof(ar->user_key_ctrl)))
2850 {
2851 ret = -EFAULT;
2852 goto ioctl_done;
2853 }
2854
2855 A_PRINTF("ar6000 USER set key %x\n", ar->user_key_ctrl);
2856 break;
2857 }
2858#endif /* USER_KEYS */
2859
2860#ifdef CONFIG_HOST_GPIO_SUPPORT
2861 case AR6000_XIOCTL_GPIO_OUTPUT_SET:
2862 {
2863 struct ar6000_gpio_output_set_cmd_s gpio_output_set_cmd;
2864
2865 if (ar->bIsDestroyProgress) {
2866 ret = -EBUSY;
2867 goto ioctl_done;
2868 }
Joe Perches1071a132011-02-02 14:05:47 -08002869 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002870 ret = -EIO;
2871 goto ioctl_done;
2872 }
2873 if (down_interruptible(&ar->arSem)) {
2874 ret = -ERESTARTSYS;
2875 goto ioctl_done;
2876 }
2877 if (ar->bIsDestroyProgress) {
2878 up(&ar->arSem);
2879 ret = -EBUSY;
2880 goto ioctl_done;
2881 }
2882
2883 if (copy_from_user(&gpio_output_set_cmd, userdata,
2884 sizeof(gpio_output_set_cmd)))
2885 {
2886 ret = -EFAULT;
2887 } else {
2888 ret = ar6000_gpio_output_set(dev,
2889 gpio_output_set_cmd.set_mask,
2890 gpio_output_set_cmd.clear_mask,
2891 gpio_output_set_cmd.enable_mask,
2892 gpio_output_set_cmd.disable_mask);
Joe Perches4f69cef2011-02-02 14:05:57 -08002893 if (ret != 0) {
Ralph Loader3ec60802011-01-21 19:27:53 +13002894 ret = -EIO;
Vipin Mehta30295c82010-09-01 12:06:33 -07002895 }
2896 }
2897 up(&ar->arSem);
2898 break;
2899 }
2900 case AR6000_XIOCTL_GPIO_INPUT_GET:
2901 {
2902 if (ar->bIsDestroyProgress) {
2903 ret = -EBUSY;
2904 goto ioctl_done;
2905 }
Joe Perches1071a132011-02-02 14:05:47 -08002906 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002907 ret = -EIO;
2908 goto ioctl_done;
2909 }
2910 if (down_interruptible(&ar->arSem)) {
2911 ret = -ERESTARTSYS;
2912 goto ioctl_done;
2913 }
2914 if (ar->bIsDestroyProgress) {
2915 up(&ar->arSem);
2916 ret = -EBUSY;
2917 goto ioctl_done;
2918 }
2919
2920 ret = ar6000_gpio_input_get(dev);
Joe Perches4f69cef2011-02-02 14:05:57 -08002921 if (ret != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002922 up(&ar->arSem);
2923 ret = -EIO;
2924 goto ioctl_done;
2925 }
2926
2927 /* Wait for Target to respond. */
2928 wait_event_interruptible(arEvent, gpio_data_available);
2929 if (signal_pending(current)) {
2930 ret = -EINTR;
2931 } else {
2932 A_ASSERT(gpio_reg_results.gpioreg_id == GPIO_ID_NONE);
2933
2934 if (copy_to_user(userdata, &gpio_reg_results.value,
2935 sizeof(gpio_reg_results.value)))
2936 {
2937 ret = -EFAULT;
2938 }
2939 }
2940 up(&ar->arSem);
2941 break;
2942 }
2943 case AR6000_XIOCTL_GPIO_REGISTER_SET:
2944 {
2945 struct ar6000_gpio_register_cmd_s gpio_register_cmd;
2946
2947 if (ar->bIsDestroyProgress) {
2948 ret = -EBUSY;
2949 goto ioctl_done;
2950 }
Joe Perches1071a132011-02-02 14:05:47 -08002951 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002952 ret = -EIO;
2953 goto ioctl_done;
2954 }
2955 if (down_interruptible(&ar->arSem)) {
2956 ret = -ERESTARTSYS;
2957 goto ioctl_done;
2958 }
2959 if (ar->bIsDestroyProgress) {
2960 up(&ar->arSem);
2961 ret = -EBUSY;
2962 goto ioctl_done;
2963 }
2964
2965 if (copy_from_user(&gpio_register_cmd, userdata,
2966 sizeof(gpio_register_cmd)))
2967 {
2968 ret = -EFAULT;
2969 } else {
2970 ret = ar6000_gpio_register_set(dev,
2971 gpio_register_cmd.gpioreg_id,
2972 gpio_register_cmd.value);
Joe Perches4f69cef2011-02-02 14:05:57 -08002973 if (ret != 0) {
Ralph Loader3ec60802011-01-21 19:27:53 +13002974 ret = -EIO;
Vipin Mehta30295c82010-09-01 12:06:33 -07002975 }
2976
2977 /* Wait for acknowledgement from Target */
2978 wait_event_interruptible(arEvent, gpio_ack_received);
2979 if (signal_pending(current)) {
2980 ret = -EINTR;
2981 }
2982 }
2983 up(&ar->arSem);
2984 break;
2985 }
2986 case AR6000_XIOCTL_GPIO_REGISTER_GET:
2987 {
2988 struct ar6000_gpio_register_cmd_s gpio_register_cmd;
2989
2990 if (ar->bIsDestroyProgress) {
2991 ret = -EBUSY;
2992 goto ioctl_done;
2993 }
Joe Perches1071a132011-02-02 14:05:47 -08002994 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07002995 ret = -EIO;
2996 goto ioctl_done;
2997 }
2998 if (down_interruptible(&ar->arSem)) {
2999 ret = -ERESTARTSYS;
3000 goto ioctl_done;
3001 }
3002 if (ar->bIsDestroyProgress) {
3003 up(&ar->arSem);
3004 ret = -EBUSY;
3005 goto ioctl_done;
3006 }
3007
3008 if (copy_from_user(&gpio_register_cmd, userdata,
3009 sizeof(gpio_register_cmd)))
3010 {
3011 ret = -EFAULT;
3012 } else {
3013 ret = ar6000_gpio_register_get(dev, gpio_register_cmd.gpioreg_id);
Joe Perches4f69cef2011-02-02 14:05:57 -08003014 if (ret != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003015 up(&ar->arSem);
3016 ret = -EIO;
3017 goto ioctl_done;
3018 }
3019
3020 /* Wait for Target to respond. */
3021 wait_event_interruptible(arEvent, gpio_data_available);
3022 if (signal_pending(current)) {
3023 ret = -EINTR;
3024 } else {
3025 A_ASSERT(gpio_register_cmd.gpioreg_id == gpio_reg_results.gpioreg_id);
3026 if (copy_to_user(userdata, &gpio_reg_results,
3027 sizeof(gpio_reg_results)))
3028 {
3029 ret = -EFAULT;
3030 }
3031 }
3032 }
3033 up(&ar->arSem);
3034 break;
3035 }
3036 case AR6000_XIOCTL_GPIO_INTR_ACK:
3037 {
3038 struct ar6000_gpio_intr_ack_cmd_s gpio_intr_ack_cmd;
3039
3040 if (ar->bIsDestroyProgress) {
3041 ret = -EBUSY;
3042 goto ioctl_done;
3043 }
Joe Perches1071a132011-02-02 14:05:47 -08003044 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003045 ret = -EIO;
3046 goto ioctl_done;
3047 }
3048 if (down_interruptible(&ar->arSem)) {
3049 ret = -ERESTARTSYS;
3050 goto ioctl_done;
3051 }
3052 if (ar->bIsDestroyProgress) {
3053 up(&ar->arSem);
3054 ret = -EBUSY;
3055 goto ioctl_done;
3056 }
3057
3058 if (copy_from_user(&gpio_intr_ack_cmd, userdata,
3059 sizeof(gpio_intr_ack_cmd)))
3060 {
3061 ret = -EFAULT;
3062 } else {
3063 ret = ar6000_gpio_intr_ack(dev, gpio_intr_ack_cmd.ack_mask);
Joe Perches4f69cef2011-02-02 14:05:57 -08003064 if (ret != 0) {
Ralph Loader3ec60802011-01-21 19:27:53 +13003065 ret = -EIO;
Vipin Mehta30295c82010-09-01 12:06:33 -07003066 }
3067 }
3068 up(&ar->arSem);
3069 break;
3070 }
3071 case AR6000_XIOCTL_GPIO_INTR_WAIT:
3072 {
3073 /* Wait for Target to report an interrupt. */
3074 wait_event_interruptible(arEvent, gpio_intr_available);
3075
3076 if (signal_pending(current)) {
3077 ret = -EINTR;
3078 } else {
3079 if (copy_to_user(userdata, &gpio_intr_results,
3080 sizeof(gpio_intr_results)))
3081 {
3082 ret = -EFAULT;
3083 }
3084 }
3085 break;
3086 }
3087#endif /* CONFIG_HOST_GPIO_SUPPORT */
3088
3089 case AR6000_XIOCTL_DBGLOG_CFG_MODULE:
3090 {
3091 struct ar6000_dbglog_module_config_s config;
3092
3093 if (copy_from_user(&config, userdata, sizeof(config))) {
3094 ret = -EFAULT;
3095 goto ioctl_done;
3096 }
3097
3098 /* Send the challenge on the control channel */
3099 if (wmi_config_debug_module_cmd(ar->arWmi, config.mmask,
3100 config.tsr, config.rep,
Joe Perches4f69cef2011-02-02 14:05:57 -08003101 config.size, config.valid) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07003102 {
3103 ret = -EIO;
3104 goto ioctl_done;
3105 }
3106 break;
3107 }
3108
3109 case AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS:
3110 {
3111 /* Send the challenge on the control channel */
Joe Perches4f69cef2011-02-02 14:05:57 -08003112 if (ar6000_dbglog_get_debug_logs(ar) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07003113 {
3114 ret = -EIO;
3115 goto ioctl_done;
3116 }
3117 break;
3118 }
3119
3120 case AR6000_XIOCTL_SET_ADHOC_BSSID:
3121 {
3122 WMI_SET_ADHOC_BSSID_CMD adhocBssid;
3123
Joe Perches1071a132011-02-02 14:05:47 -08003124 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003125 ret = -EIO;
3126 } else if (copy_from_user(&adhocBssid, userdata,
3127 sizeof(adhocBssid)))
3128 {
3129 ret = -EFAULT;
Luis R. Rodriguez395e1ca2011-03-10 18:55:30 -08003130 } else if (memcmp(adhocBssid.bssid, bcast_mac,
Vipin Mehta30295c82010-09-01 12:06:33 -07003131 AR6000_ETH_ADDR_LEN) == 0)
3132 {
3133 ret = -EFAULT;
3134 } else {
3135
Luis R. Rodriguez05209262011-03-10 18:55:29 -08003136 memcpy(ar->arReqBssid, adhocBssid.bssid, sizeof(ar->arReqBssid));
Vipin Mehta30295c82010-09-01 12:06:33 -07003137 }
3138 break;
3139 }
3140
3141 case AR6000_XIOCTL_SET_OPT_MODE:
3142 {
3143 WMI_SET_OPT_MODE_CMD optModeCmd;
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07003144 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07003145
Joe Perches1071a132011-02-02 14:05:47 -08003146 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003147 ret = -EIO;
3148 } else if (copy_from_user(&optModeCmd, userdata,
3149 sizeof(optModeCmd)))
3150 {
3151 ret = -EFAULT;
3152 } else if (ar->arConnected && optModeCmd.optMode == SPECIAL_ON) {
3153 ret = -EFAULT;
3154
3155 } else if (wmi_set_opt_mode_cmd(ar->arWmi, optModeCmd.optMode)
Joe Perches4f69cef2011-02-02 14:05:57 -08003156 != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07003157 {
3158 ret = -EIO;
3159 }
3160 break;
3161 }
3162
3163 case AR6000_XIOCTL_OPT_SEND_FRAME:
3164 {
Dan Carpenter253804a2011-02-20 15:49:08 +03003165 WMI_OPT_TX_FRAME_CMD optTxFrmCmd;
Joe Perchesab3655d2011-02-02 14:05:49 -08003166 u8 data[MAX_OPT_DATA_LEN];
Vipin Mehta30295c82010-09-01 12:06:33 -07003167
Joe Perches1071a132011-02-02 14:05:47 -08003168 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003169 ret = -EIO;
Dan Carpenter253804a2011-02-20 15:49:08 +03003170 break;
3171 }
3172
3173 if (copy_from_user(&optTxFrmCmd, userdata, sizeof(optTxFrmCmd))) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003174 ret = -EFAULT;
Dan Carpenter253804a2011-02-20 15:49:08 +03003175 break;
3176 }
3177
Dan Carpenter5b6567e2011-02-20 15:49:53 +03003178 if (optTxFrmCmd.optIEDataLen > MAX_OPT_DATA_LEN) {
3179 ret = -EINVAL;
3180 break;
3181 }
3182
Dan Carpenter253804a2011-02-20 15:49:08 +03003183 if (copy_from_user(data, userdata+sizeof(WMI_OPT_TX_FRAME_CMD) - 1,
3184 optTxFrmCmd.optIEDataLen)) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003185 ret = -EFAULT;
Dan Carpenter253804a2011-02-20 15:49:08 +03003186 break;
3187 }
3188
3189 ret = wmi_opt_tx_frame_cmd(ar->arWmi,
Vipin Mehta30295c82010-09-01 12:06:33 -07003190 optTxFrmCmd.frmType,
3191 optTxFrmCmd.dstAddr,
3192 optTxFrmCmd.bssid,
3193 optTxFrmCmd.optIEDataLen,
3194 data);
Vipin Mehta30295c82010-09-01 12:06:33 -07003195 break;
3196 }
3197 case AR6000_XIOCTL_WMI_SETRETRYLIMITS:
3198 {
3199 WMI_SET_RETRY_LIMITS_CMD setRetryParams;
3200
Joe Perches1071a132011-02-02 14:05:47 -08003201 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003202 ret = -EIO;
3203 } else if (copy_from_user(&setRetryParams, userdata,
3204 sizeof(setRetryParams)))
3205 {
3206 ret = -EFAULT;
3207 } else {
3208 if (wmi_set_retry_limits_cmd(ar->arWmi, setRetryParams.frameType,
3209 setRetryParams.trafficClass,
3210 setRetryParams.maxRetries,
Joe Perches4f69cef2011-02-02 14:05:57 -08003211 setRetryParams.enableNotify) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07003212 {
3213 ret = -EIO;
3214 }
3215 AR6000_SPIN_LOCK(&ar->arLock, 0);
3216 ar->arMaxRetries = setRetryParams.maxRetries;
3217 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
3218 }
3219 break;
3220 }
3221
3222 case AR6000_XIOCTL_SET_BEACON_INTVAL:
3223 {
3224 WMI_BEACON_INT_CMD bIntvlCmd;
3225
Joe Perches1071a132011-02-02 14:05:47 -08003226 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003227 ret = -EIO;
3228 } else if (copy_from_user(&bIntvlCmd, userdata,
3229 sizeof(bIntvlCmd)))
3230 {
3231 ret = -EFAULT;
3232 } else if (wmi_set_adhoc_bconIntvl_cmd(ar->arWmi, bIntvlCmd.beaconInterval)
Joe Perches4f69cef2011-02-02 14:05:57 -08003233 != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07003234 {
3235 ret = -EIO;
3236 }
3237 if(ret == 0) {
3238 ar->ap_beacon_interval = bIntvlCmd.beaconInterval;
3239 ar->ap_profile_flag = 1; /* There is a change in profile */
3240 }
3241 break;
3242 }
3243 case IEEE80211_IOCTL_SETAUTHALG:
3244 {
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07003245 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07003246 struct ieee80211req_authalg req;
3247
Joe Perches1071a132011-02-02 14:05:47 -08003248 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003249 ret = -EIO;
3250 } else if (copy_from_user(&req, userdata,
3251 sizeof(struct ieee80211req_authalg)))
3252 {
3253 ret = -EFAULT;
3254 } else {
3255 if (req.auth_alg & AUTH_ALG_OPEN_SYSTEM) {
3256 ar->arDot11AuthMode |= OPEN_AUTH;
3257 ar->arPairwiseCrypto = NONE_CRYPT;
3258 ar->arGroupCrypto = NONE_CRYPT;
3259 }
3260 if (req.auth_alg & AUTH_ALG_SHARED_KEY) {
3261 ar->arDot11AuthMode |= SHARED_AUTH;
3262 ar->arPairwiseCrypto = WEP_CRYPT;
3263 ar->arGroupCrypto = WEP_CRYPT;
3264 ar->arAuthMode = NONE_AUTH;
3265 }
3266 if (req.auth_alg == AUTH_ALG_LEAP) {
3267 ar->arDot11AuthMode = LEAP_AUTH;
3268 }
3269 }
3270 break;
3271 }
3272
3273 case AR6000_XIOCTL_SET_VOICE_PKT_SIZE:
3274 ret = ar6000_xioctl_set_voice_pkt_size(dev, userdata);
3275 break;
3276
3277 case AR6000_XIOCTL_SET_MAX_SP:
3278 ret = ar6000_xioctl_set_max_sp_len(dev, userdata);
3279 break;
3280
3281 case AR6000_XIOCTL_WMI_GET_ROAM_TBL:
3282 ret = ar6000_ioctl_get_roam_tbl(dev, rq);
3283 break;
3284 case AR6000_XIOCTL_WMI_SET_ROAM_CTRL:
3285 ret = ar6000_ioctl_set_roam_ctrl(dev, userdata);
3286 break;
3287 case AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS:
3288 ret = ar6000_ioctl_set_powersave_timers(dev, userdata);
3289 break;
3290 case AR6000_XIOCTRL_WMI_GET_POWER_MODE:
3291 ret = ar6000_ioctl_get_power_mode(dev, rq);
3292 break;
3293 case AR6000_XIOCTRL_WMI_SET_WLAN_STATE:
3294 {
3295 AR6000_WLAN_STATE state;
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04003296 if (get_user(state, (unsigned int *)userdata))
3297 ret = -EFAULT;
Joe Perches4f69cef2011-02-02 14:05:57 -08003298 else if (ar6000_set_wlan_state(ar, state) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07003299 ret = -EIO;
Vipin Mehta30295c82010-09-01 12:06:33 -07003300 break;
3301 }
3302 case AR6000_XIOCTL_WMI_GET_ROAM_DATA:
3303 ret = ar6000_ioctl_get_roam_data(dev, rq);
3304 break;
3305
3306 case AR6000_XIOCTL_WMI_SET_BT_STATUS:
3307 ret = ar6000_xioctl_set_bt_status_cmd(dev, userdata);
3308 break;
3309
3310 case AR6000_XIOCTL_WMI_SET_BT_PARAMS:
3311 ret = ar6000_xioctl_set_bt_params_cmd(dev, userdata);
3312 break;
3313
3314 case AR6000_XIOCTL_WMI_SET_BTCOEX_FE_ANT:
3315 ret = ar6000_xioctl_set_btcoex_fe_ant_cmd(dev, userdata);
3316 break;
3317
3318 case AR6000_XIOCTL_WMI_SET_BTCOEX_COLOCATED_BT_DEV:
3319 ret = ar6000_xioctl_set_btcoex_colocated_bt_dev_cmd(dev, userdata);
3320 break;
3321
3322 case AR6000_XIOCTL_WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG:
3323 ret = ar6000_xioctl_set_btcoex_btinquiry_page_config_cmd(dev, userdata);
3324 break;
3325
3326 case AR6000_XIOCTL_WMI_SET_BTCOEX_SCO_CONFIG:
3327 ret = ar6000_xioctl_set_btcoex_sco_config_cmd( dev, userdata);
3328 break;
3329
3330 case AR6000_XIOCTL_WMI_SET_BTCOEX_A2DP_CONFIG:
3331 ret = ar6000_xioctl_set_btcoex_a2dp_config_cmd(dev, userdata);
3332 break;
3333
3334 case AR6000_XIOCTL_WMI_SET_BTCOEX_ACLCOEX_CONFIG:
3335 ret = ar6000_xioctl_set_btcoex_aclcoex_config_cmd(dev, userdata);
3336 break;
3337
3338 case AR6000_XIOCTL_WMI_SET_BTCOEX_DEBUG:
3339 ret = ar60000_xioctl_set_btcoex_debug_cmd(dev, userdata);
3340 break;
3341
3342 case AR6000_XIOCTL_WMI_SET_BT_OPERATING_STATUS:
3343 ret = ar6000_xioctl_set_btcoex_bt_operating_status_cmd(dev, userdata);
3344 break;
3345
3346 case AR6000_XIOCTL_WMI_GET_BTCOEX_CONFIG:
3347 ret = ar6000_xioctl_get_btcoex_config_cmd(dev, userdata, rq);
3348 break;
3349
3350 case AR6000_XIOCTL_WMI_GET_BTCOEX_STATS:
3351 ret = ar6000_xioctl_get_btcoex_stats_cmd(dev, userdata, rq);
3352 break;
3353
3354 case AR6000_XIOCTL_WMI_STARTSCAN:
3355 {
3356 WMI_START_SCAN_CMD setStartScanCmd, *cmdp;
3357
Joe Perches1071a132011-02-02 14:05:47 -08003358 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003359 ret = -EIO;
3360 } else if (copy_from_user(&setStartScanCmd, userdata,
3361 sizeof(setStartScanCmd)))
3362 {
3363 ret = -EFAULT;
3364 } else {
3365 if (setStartScanCmd.numChannels > 1) {
3366 cmdp = A_MALLOC(130);
3367 if (copy_from_user(cmdp, userdata,
3368 sizeof (*cmdp) +
3369 ((setStartScanCmd.numChannels - 1) *
Joe Perches4853ac02011-02-02 14:05:50 -08003370 sizeof(u16))))
Vipin Mehta30295c82010-09-01 12:06:33 -07003371 {
3372 kfree(cmdp);
3373 ret = -EFAULT;
3374 goto ioctl_done;
3375 }
3376 } else {
3377 cmdp = &setStartScanCmd;
3378 }
3379
3380 if (wmi_startscan_cmd(ar->arWmi, cmdp->scanType,
3381 cmdp->forceFgScan,
3382 cmdp->isLegacy,
3383 cmdp->homeDwellTime,
3384 cmdp->forceScanInterval,
3385 cmdp->numChannels,
Joe Perches4f69cef2011-02-02 14:05:57 -08003386 cmdp->channelList) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07003387 {
3388 ret = -EIO;
3389 }
3390 }
3391 break;
3392 }
3393 case AR6000_XIOCTL_WMI_SETFIXRATES:
3394 {
3395 WMI_FIX_RATES_CMD setFixRatesCmd;
Joe Perches1f4c34b2011-01-27 20:04:19 -08003396 int returnStatus;
Vipin Mehta30295c82010-09-01 12:06:33 -07003397
Joe Perches1071a132011-02-02 14:05:47 -08003398 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003399 ret = -EIO;
3400 } else if (copy_from_user(&setFixRatesCmd, userdata,
3401 sizeof(setFixRatesCmd)))
3402 {
3403 ret = -EFAULT;
3404 } else {
3405 returnStatus = wmi_set_fixrates_cmd(ar->arWmi, setFixRatesCmd.fixRateMask);
3406 if (returnStatus == A_EINVAL) {
3407 ret = -EINVAL;
Joe Perches4f69cef2011-02-02 14:05:57 -08003408 } else if(returnStatus != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003409 ret = -EIO;
3410 } else {
3411 ar->ap_profile_flag = 1; /* There is a change in profile */
3412 }
3413 }
3414 break;
3415 }
3416
3417 case AR6000_XIOCTL_WMI_GETFIXRATES:
3418 {
3419 WMI_FIX_RATES_CMD getFixRatesCmd;
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07003420 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07003421 int ret = 0;
3422
3423 if (ar->bIsDestroyProgress) {
3424 ret = -EBUSY;
3425 goto ioctl_done;
3426 }
Joe Perches1071a132011-02-02 14:05:47 -08003427 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003428 ret = -EIO;
3429 goto ioctl_done;
3430 }
3431
3432 if (down_interruptible(&ar->arSem)) {
3433 ret = -ERESTARTSYS;
3434 goto ioctl_done;
3435 }
3436 if (ar->bIsDestroyProgress) {
3437 up(&ar->arSem);
3438 ret = -EBUSY;
3439 goto ioctl_done;
3440 }
3441 /* Used copy_from_user/copy_to_user to access user space data */
3442 if (copy_from_user(&getFixRatesCmd, userdata, sizeof(getFixRatesCmd))) {
3443 ret = -EFAULT;
3444 } else {
3445 ar->arRateMask = 0xFFFFFFFF;
3446
Joe Perches4f69cef2011-02-02 14:05:57 -08003447 if (wmi_get_ratemask_cmd(ar->arWmi) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003448 up(&ar->arSem);
3449 ret = -EIO;
3450 goto ioctl_done;
3451 }
3452
3453 wait_event_interruptible_timeout(arEvent, ar->arRateMask != 0xFFFFFFFF, wmitimeout * HZ);
3454
3455 if (signal_pending(current)) {
3456 ret = -EINTR;
3457 }
3458
3459 if (!ret) {
3460 getFixRatesCmd.fixRateMask = ar->arRateMask;
3461 }
3462
3463 if(copy_to_user(userdata, &getFixRatesCmd, sizeof(getFixRatesCmd))) {
3464 ret = -EFAULT;
3465 }
3466
3467 up(&ar->arSem);
3468 }
3469 break;
3470 }
3471 case AR6000_XIOCTL_WMI_SET_AUTHMODE:
3472 {
3473 WMI_SET_AUTH_MODE_CMD setAuthMode;
3474
Joe Perches1071a132011-02-02 14:05:47 -08003475 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003476 ret = -EIO;
3477 } else if (copy_from_user(&setAuthMode, userdata,
3478 sizeof(setAuthMode)))
3479 {
3480 ret = -EFAULT;
3481 } else {
Joe Perches4f69cef2011-02-02 14:05:57 -08003482 if (wmi_set_authmode_cmd(ar->arWmi, setAuthMode.mode) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07003483 {
3484 ret = -EIO;
3485 }
3486 }
3487 break;
3488 }
3489 case AR6000_XIOCTL_WMI_SET_REASSOCMODE:
3490 {
3491 WMI_SET_REASSOC_MODE_CMD setReassocMode;
3492
Joe Perches1071a132011-02-02 14:05:47 -08003493 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003494 ret = -EIO;
3495 } else if (copy_from_user(&setReassocMode, userdata,
3496 sizeof(setReassocMode)))
3497 {
3498 ret = -EFAULT;
3499 } else {
Joe Perches4f69cef2011-02-02 14:05:57 -08003500 if (wmi_set_reassocmode_cmd(ar->arWmi, setReassocMode.mode) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07003501 {
3502 ret = -EIO;
3503 }
3504 }
3505 break;
3506 }
3507 case AR6000_XIOCTL_DIAG_READ:
3508 {
Joe Perchese1ce2a32011-02-02 14:05:51 -08003509 u32 addr, data;
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04003510 if (get_user(addr, (unsigned int *)userdata)) {
3511 ret = -EFAULT;
3512 break;
3513 }
Vipin Mehta30295c82010-09-01 12:06:33 -07003514 addr = TARG_VTOP(ar->arTargetType, addr);
Joe Perches4f69cef2011-02-02 14:05:57 -08003515 if (ar6000_ReadRegDiag(ar->arHifDevice, &addr, &data) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003516 ret = -EIO;
3517 }
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04003518 if (put_user(data, (unsigned int *)userdata + 1)) {
3519 ret = -EFAULT;
3520 break;
3521 }
Vipin Mehta30295c82010-09-01 12:06:33 -07003522 break;
3523 }
3524 case AR6000_XIOCTL_DIAG_WRITE:
3525 {
Joe Perchese1ce2a32011-02-02 14:05:51 -08003526 u32 addr, data;
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04003527 if (get_user(addr, (unsigned int *)userdata) ||
3528 get_user(data, (unsigned int *)userdata + 1)) {
3529 ret = -EFAULT;
3530 break;
3531 }
Vipin Mehta30295c82010-09-01 12:06:33 -07003532 addr = TARG_VTOP(ar->arTargetType, addr);
Joe Perches4f69cef2011-02-02 14:05:57 -08003533 if (ar6000_WriteRegDiag(ar->arHifDevice, &addr, &data) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003534 ret = -EIO;
3535 }
3536 break;
3537 }
3538 case AR6000_XIOCTL_WMI_SET_KEEPALIVE:
3539 {
3540 WMI_SET_KEEPALIVE_CMD setKeepAlive;
Joe Perches1071a132011-02-02 14:05:47 -08003541 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003542 ret = -EIO;
3543 goto ioctl_done;
3544 } else if (copy_from_user(&setKeepAlive, userdata,
3545 sizeof(setKeepAlive))){
3546 ret = -EFAULT;
3547 } else {
Joe Perches4f69cef2011-02-02 14:05:57 -08003548 if (wmi_set_keepalive_cmd(ar->arWmi, setKeepAlive.keepaliveInterval) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003549 ret = -EIO;
3550 }
3551 }
3552 break;
3553 }
3554 case AR6000_XIOCTL_WMI_SET_PARAMS:
3555 {
3556 WMI_SET_PARAMS_CMD cmd;
Joe Perches1071a132011-02-02 14:05:47 -08003557 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003558 ret = -EIO;
3559 goto ioctl_done;
3560 } else if (copy_from_user(&cmd, userdata,
3561 sizeof(cmd))){
3562 ret = -EFAULT;
3563 } else if (copy_from_user(&cmd, userdata,
3564 sizeof(cmd) + cmd.length))
3565 {
3566 ret = -EFAULT;
3567 } else {
Joe Perches4f69cef2011-02-02 14:05:57 -08003568 if (wmi_set_params_cmd(ar->arWmi, cmd.opcode, cmd.length, cmd.buffer) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003569 ret = -EIO;
3570 }
3571 }
3572 break;
3573 }
3574 case AR6000_XIOCTL_WMI_SET_MCAST_FILTER:
3575 {
3576 WMI_SET_MCAST_FILTER_CMD cmd;
Joe Perches1071a132011-02-02 14:05:47 -08003577 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003578 ret = -EIO;
3579 goto ioctl_done;
3580 } else if (copy_from_user(&cmd, userdata,
3581 sizeof(cmd))){
3582 ret = -EFAULT;
3583 } else {
3584 if (wmi_set_mcast_filter_cmd(ar->arWmi, cmd.multicast_mac[0],
3585 cmd.multicast_mac[1],
3586 cmd.multicast_mac[2],
Joe Perches4f69cef2011-02-02 14:05:57 -08003587 cmd.multicast_mac[3]) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003588 ret = -EIO;
3589 }
3590 }
3591 break;
3592 }
3593 case AR6000_XIOCTL_WMI_DEL_MCAST_FILTER:
3594 {
3595 WMI_SET_MCAST_FILTER_CMD cmd;
Joe Perches1071a132011-02-02 14:05:47 -08003596 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003597 ret = -EIO;
3598 goto ioctl_done;
3599 } else if (copy_from_user(&cmd, userdata,
3600 sizeof(cmd))){
3601 ret = -EFAULT;
3602 } else {
3603 if (wmi_del_mcast_filter_cmd(ar->arWmi, cmd.multicast_mac[0],
3604 cmd.multicast_mac[1],
3605 cmd.multicast_mac[2],
Joe Perches4f69cef2011-02-02 14:05:57 -08003606 cmd.multicast_mac[3]) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003607 ret = -EIO;
3608 }
3609 }
3610 break;
3611 }
3612 case AR6000_XIOCTL_WMI_MCAST_FILTER:
3613 {
3614 WMI_MCAST_FILTER_CMD cmd;
Joe Perches1071a132011-02-02 14:05:47 -08003615 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003616 ret = -EIO;
3617 goto ioctl_done;
3618 } else if (copy_from_user(&cmd, userdata,
3619 sizeof(cmd))){
3620 ret = -EFAULT;
3621 } else {
Joe Perches4f69cef2011-02-02 14:05:57 -08003622 if (wmi_mcast_filter_cmd(ar->arWmi, cmd.enable) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003623 ret = -EIO;
3624 }
3625 }
3626 break;
3627 }
3628 case AR6000_XIOCTL_WMI_GET_KEEPALIVE:
3629 {
Luis R. Rodrigueza71f0bf2011-03-14 10:59:11 -07003630 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
Vipin Mehta30295c82010-09-01 12:06:33 -07003631 WMI_GET_KEEPALIVE_CMD getKeepAlive;
3632 int ret = 0;
3633 if (ar->bIsDestroyProgress) {
3634 ret =-EBUSY;
3635 goto ioctl_done;
3636 }
Joe Perches1071a132011-02-02 14:05:47 -08003637 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003638 ret = -EIO;
3639 goto ioctl_done;
3640 }
3641 if (down_interruptible(&ar->arSem)) {
3642 ret = -ERESTARTSYS;
3643 goto ioctl_done;
3644 }
3645 if (ar->bIsDestroyProgress) {
3646 up(&ar->arSem);
3647 ret = -EBUSY;
3648 goto ioctl_done;
3649 }
3650 if (copy_from_user(&getKeepAlive, userdata,sizeof(getKeepAlive))) {
3651 ret = -EFAULT;
3652 } else {
3653 getKeepAlive.keepaliveInterval = wmi_get_keepalive_cmd(ar->arWmi);
3654 ar->arKeepaliveConfigured = 0xFF;
Joe Perches4f69cef2011-02-02 14:05:57 -08003655 if (wmi_get_keepalive_configured(ar->arWmi) != 0){
Vipin Mehta30295c82010-09-01 12:06:33 -07003656 up(&ar->arSem);
3657 ret = -EIO;
3658 goto ioctl_done;
3659 }
3660 wait_event_interruptible_timeout(arEvent, ar->arKeepaliveConfigured != 0xFF, wmitimeout * HZ);
3661 if (signal_pending(current)) {
3662 ret = -EINTR;
3663 }
3664
3665 if (!ret) {
3666 getKeepAlive.configured = ar->arKeepaliveConfigured;
3667 }
3668 if (copy_to_user(userdata, &getKeepAlive, sizeof(getKeepAlive))) {
3669 ret = -EFAULT;
3670 }
3671 up(&ar->arSem);
3672 }
3673 break;
3674 }
3675 case AR6000_XIOCTL_WMI_SET_APPIE:
3676 {
3677 WMI_SET_APPIE_CMD appIEcmd;
Joe Perchesab3655d2011-02-02 14:05:49 -08003678 u8 appIeInfo[IEEE80211_APPIE_FRAME_MAX_LEN];
Joe Perchese1ce2a32011-02-02 14:05:51 -08003679 u32 fType,ieLen;
Vipin Mehta30295c82010-09-01 12:06:33 -07003680
Joe Perches1071a132011-02-02 14:05:47 -08003681 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003682 ret = -EIO;
3683 goto ioctl_done;
3684 }
Joe Perchese1ce2a32011-02-02 14:05:51 -08003685 if (get_user(fType, (u32 *)userdata)) {
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04003686 ret = -EFAULT;
3687 break;
3688 }
Vipin Mehta30295c82010-09-01 12:06:33 -07003689 appIEcmd.mgmtFrmType = fType;
3690 if (appIEcmd.mgmtFrmType >= IEEE80211_APPIE_NUM_OF_FRAME) {
3691 ret = -EIO;
3692 } else {
Joe Perchese1ce2a32011-02-02 14:05:51 -08003693 if (get_user(ieLen, (u32 *)(userdata + 4))) {
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04003694 ret = -EFAULT;
3695 break;
3696 }
Vipin Mehta30295c82010-09-01 12:06:33 -07003697 appIEcmd.ieLen = ieLen;
3698 A_PRINTF("WPSIE: Type-%d, Len-%d\n",appIEcmd.mgmtFrmType, appIEcmd.ieLen);
3699 if (appIEcmd.ieLen > IEEE80211_APPIE_FRAME_MAX_LEN) {
3700 ret = -EIO;
3701 break;
3702 }
3703 if (copy_from_user(appIeInfo, userdata + 8, appIEcmd.ieLen)) {
3704 ret = -EFAULT;
3705 } else {
3706 if (wmi_set_appie_cmd(ar->arWmi, appIEcmd.mgmtFrmType,
Joe Perches4f69cef2011-02-02 14:05:57 -08003707 appIEcmd.ieLen, appIeInfo) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07003708 {
3709 ret = -EIO;
3710 }
3711 }
3712 }
3713 break;
3714 }
3715 case AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER:
3716 {
3717 WMI_BSS_FILTER_CMD cmd;
Joe Perchese1ce2a32011-02-02 14:05:51 -08003718 u32 filterType;
Vipin Mehta30295c82010-09-01 12:06:33 -07003719
Joe Perchese1ce2a32011-02-02 14:05:51 -08003720 if (copy_from_user(&filterType, userdata, sizeof(u32)))
Vipin Mehta30295c82010-09-01 12:06:33 -07003721 {
3722 ret = -EFAULT;
3723 goto ioctl_done;
3724 }
3725 if (filterType & (IEEE80211_FILTER_TYPE_BEACON |
3726 IEEE80211_FILTER_TYPE_PROBE_RESP))
3727 {
3728 cmd.bssFilter = ALL_BSS_FILTER;
3729 } else {
3730 cmd.bssFilter = NONE_BSS_FILTER;
3731 }
Joe Perches4f69cef2011-02-02 14:05:57 -08003732 if (wmi_bssfilter_cmd(ar->arWmi, cmd.bssFilter, 0) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003733 ret = -EIO;
3734 } else {
3735 ar->arUserBssFilter = cmd.bssFilter;
3736 }
3737
3738 AR6000_SPIN_LOCK(&ar->arLock, 0);
3739 ar->arMgmtFilter = filterType;
3740 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
3741 break;
3742 }
3743 case AR6000_XIOCTL_WMI_SET_WSC_STATUS:
3744 {
Joe Perchese1ce2a32011-02-02 14:05:51 -08003745 u32 wsc_status;
Vipin Mehta30295c82010-09-01 12:06:33 -07003746
Joe Perches1071a132011-02-02 14:05:47 -08003747 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003748 ret = -EIO;
3749 goto ioctl_done;
Joe Perchese1ce2a32011-02-02 14:05:51 -08003750 } else if (copy_from_user(&wsc_status, userdata, sizeof(u32)))
Vipin Mehta30295c82010-09-01 12:06:33 -07003751 {
3752 ret = -EFAULT;
3753 goto ioctl_done;
3754 }
Joe Perches4f69cef2011-02-02 14:05:57 -08003755 if (wmi_set_wsc_status_cmd(ar->arWmi, wsc_status) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003756 ret = -EIO;
3757 }
3758 break;
3759 }
3760 case AR6000_XIOCTL_BMI_ROMPATCH_INSTALL:
3761 {
Joe Perchese1ce2a32011-02-02 14:05:51 -08003762 u32 ROM_addr;
3763 u32 RAM_addr;
3764 u32 nbytes;
3765 u32 do_activate;
3766 u32 rompatch_id;
Vipin Mehta30295c82010-09-01 12:06:33 -07003767
Joe Perchese1ce2a32011-02-02 14:05:51 -08003768 if (get_user(ROM_addr, (u32 *)userdata) ||
3769 get_user(RAM_addr, (u32 *)userdata + 1) ||
3770 get_user(nbytes, (u32 *)userdata + 2) ||
3771 get_user(do_activate, (u32 *)userdata + 3)) {
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04003772 ret = -EFAULT;
3773 break;
3774 }
Vipin Mehta30295c82010-09-01 12:06:33 -07003775 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Install rompatch from ROM: 0x%x to RAM: 0x%x length: %d\n",
3776 ROM_addr, RAM_addr, nbytes));
3777 ret = BMIrompatchInstall(hifDevice, ROM_addr, RAM_addr,
3778 nbytes, do_activate, &rompatch_id);
Joe Perches4f69cef2011-02-02 14:05:57 -08003779 if (ret == 0) {
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04003780 /* return value */
3781 if (put_user(rompatch_id, (unsigned int *)rq->ifr_data)) {
3782 ret = -EFAULT;
3783 break;
3784 }
Vipin Mehta30295c82010-09-01 12:06:33 -07003785 }
3786 break;
3787 }
3788
3789 case AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL:
3790 {
Joe Perchese1ce2a32011-02-02 14:05:51 -08003791 u32 rompatch_id;
Vipin Mehta30295c82010-09-01 12:06:33 -07003792
Joe Perchese1ce2a32011-02-02 14:05:51 -08003793 if (get_user(rompatch_id, (u32 *)userdata)) {
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04003794 ret = -EFAULT;
3795 break;
3796 }
Vipin Mehta30295c82010-09-01 12:06:33 -07003797 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("UNinstall rompatch_id %d\n", rompatch_id));
3798 ret = BMIrompatchUninstall(hifDevice, rompatch_id);
3799 break;
3800 }
3801
3802 case AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE:
3803 case AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE:
3804 {
Joe Perchese1ce2a32011-02-02 14:05:51 -08003805 u32 rompatch_count;
Vipin Mehta30295c82010-09-01 12:06:33 -07003806
Joe Perchese1ce2a32011-02-02 14:05:51 -08003807 if (get_user(rompatch_count, (u32 *)userdata)) {
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04003808 ret = -EFAULT;
3809 break;
3810 }
Vipin Mehta30295c82010-09-01 12:06:33 -07003811 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Change rompatch activation count=%d\n", rompatch_count));
Joe Perchese1ce2a32011-02-02 14:05:51 -08003812 length = sizeof(u32) * rompatch_count;
Vipin Mehta30295c82010-09-01 12:06:33 -07003813 if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) {
3814 A_MEMZERO(buffer, length);
3815 if (copy_from_user(buffer, &userdata[sizeof(rompatch_count)], length))
3816 {
3817 ret = -EFAULT;
3818 } else {
3819 if (cmd == AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE) {
Joe Perchese1ce2a32011-02-02 14:05:51 -08003820 ret = BMIrompatchActivate(hifDevice, rompatch_count, (u32 *)buffer);
Vipin Mehta30295c82010-09-01 12:06:33 -07003821 } else {
Joe Perchese1ce2a32011-02-02 14:05:51 -08003822 ret = BMIrompatchDeactivate(hifDevice, rompatch_count, (u32 *)buffer);
Vipin Mehta30295c82010-09-01 12:06:33 -07003823 }
3824 }
3825 A_FREE(buffer);
3826 } else {
3827 ret = -ENOMEM;
3828 }
3829
3830 break;
3831 }
3832 case AR6000_XIOCTL_SET_IP:
3833 {
3834 WMI_SET_IP_CMD setIP;
3835
Joe Perches1071a132011-02-02 14:05:47 -08003836 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003837 ret = -EIO;
3838 } else if (copy_from_user(&setIP, userdata,
3839 sizeof(setIP)))
3840 {
3841 ret = -EFAULT;
3842 } else {
3843 if (wmi_set_ip_cmd(ar->arWmi,
Joe Perches4f69cef2011-02-02 14:05:57 -08003844 &setIP) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07003845 {
3846 ret = -EIO;
3847 }
3848 }
3849 break;
3850 }
3851
3852 case AR6000_XIOCTL_WMI_SET_HOST_SLEEP_MODE:
3853 {
3854 WMI_SET_HOST_SLEEP_MODE_CMD setHostSleepMode;
3855
Joe Perches1071a132011-02-02 14:05:47 -08003856 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003857 ret = -EIO;
3858 } else if (copy_from_user(&setHostSleepMode, userdata,
3859 sizeof(setHostSleepMode)))
3860 {
3861 ret = -EFAULT;
3862 } else {
3863 if (wmi_set_host_sleep_mode_cmd(ar->arWmi,
Joe Perches4f69cef2011-02-02 14:05:57 -08003864 &setHostSleepMode) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07003865 {
3866 ret = -EIO;
3867 }
3868 }
3869 break;
3870 }
3871 case AR6000_XIOCTL_WMI_SET_WOW_MODE:
3872 {
3873 WMI_SET_WOW_MODE_CMD setWowMode;
3874
Joe Perches1071a132011-02-02 14:05:47 -08003875 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003876 ret = -EIO;
3877 } else if (copy_from_user(&setWowMode, userdata,
3878 sizeof(setWowMode)))
3879 {
3880 ret = -EFAULT;
3881 } else {
3882 if (wmi_set_wow_mode_cmd(ar->arWmi,
Joe Perches4f69cef2011-02-02 14:05:57 -08003883 &setWowMode) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07003884 {
3885 ret = -EIO;
3886 }
3887 }
3888 break;
3889 }
3890 case AR6000_XIOCTL_WMI_GET_WOW_LIST:
3891 {
3892 WMI_GET_WOW_LIST_CMD getWowList;
3893
Joe Perches1071a132011-02-02 14:05:47 -08003894 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003895 ret = -EIO;
3896 } else if (copy_from_user(&getWowList, userdata,
3897 sizeof(getWowList)))
3898 {
3899 ret = -EFAULT;
3900 } else {
3901 if (wmi_get_wow_list_cmd(ar->arWmi,
Joe Perches4f69cef2011-02-02 14:05:57 -08003902 &getWowList) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07003903 {
3904 ret = -EIO;
3905 }
3906 }
3907 break;
3908 }
3909 case AR6000_XIOCTL_WMI_ADD_WOW_PATTERN:
3910 {
3911#define WOW_PATTERN_SIZE 64
3912#define WOW_MASK_SIZE 64
3913
3914 WMI_ADD_WOW_PATTERN_CMD cmd;
Joe Perchesab3655d2011-02-02 14:05:49 -08003915 u8 mask_data[WOW_PATTERN_SIZE]={0};
3916 u8 pattern_data[WOW_PATTERN_SIZE]={0};
Vipin Mehta30295c82010-09-01 12:06:33 -07003917
3918 do {
Joe Perches1071a132011-02-02 14:05:47 -08003919 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003920 ret = -EIO;
3921 break;
3922 }
3923 if(copy_from_user(&cmd, userdata,
3924 sizeof(WMI_ADD_WOW_PATTERN_CMD)))
3925 {
3926 ret = -EFAULT;
3927 break;
3928 }
3929 if (copy_from_user(pattern_data,
3930 userdata + 3,
3931 cmd.filter_size))
3932 {
3933 ret = -EFAULT;
3934 break;
3935 }
3936 if (copy_from_user(mask_data,
3937 (userdata + 3 + cmd.filter_size),
3938 cmd.filter_size))
3939 {
3940 ret = -EFAULT;
3941 break;
3942 }
3943 if (wmi_add_wow_pattern_cmd(ar->arWmi,
Joe Perches4f69cef2011-02-02 14:05:57 -08003944 &cmd, pattern_data, mask_data, cmd.filter_size) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07003945 {
3946 ret = -EIO;
3947 }
Joe Perches1071a132011-02-02 14:05:47 -08003948 } while(false);
Vipin Mehta30295c82010-09-01 12:06:33 -07003949#undef WOW_PATTERN_SIZE
3950#undef WOW_MASK_SIZE
3951 break;
3952 }
3953 case AR6000_XIOCTL_WMI_DEL_WOW_PATTERN:
3954 {
3955 WMI_DEL_WOW_PATTERN_CMD delWowPattern;
3956
Joe Perches1071a132011-02-02 14:05:47 -08003957 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07003958 ret = -EIO;
3959 } else if (copy_from_user(&delWowPattern, userdata,
3960 sizeof(delWowPattern)))
3961 {
3962 ret = -EFAULT;
3963 } else {
3964 if (wmi_del_wow_pattern_cmd(ar->arWmi,
Joe Perches4f69cef2011-02-02 14:05:57 -08003965 &delWowPattern) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07003966 {
3967 ret = -EIO;
3968 }
3969 }
3970 break;
3971 }
3972 case AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE:
3973 if (ar->arHtcTarget != NULL) {
3974#ifdef ATH_DEBUG_MODULE
3975 HTCDumpCreditStates(ar->arHtcTarget);
3976#endif /* ATH_DEBUG_MODULE */
3977#ifdef HTC_EP_STAT_PROFILING
3978 {
Luis R. Rodriguez84efc7f2011-03-14 10:58:53 -07003979 struct htc_endpoint_stats stats;
Vipin Mehta30295c82010-09-01 12:06:33 -07003980 int i;
3981
3982 for (i = 0; i < 5; i++) {
3983 if (HTCGetEndpointStatistics(ar->arHtcTarget,
3984 i,
3985 HTC_EP_STAT_SAMPLE_AND_CLEAR,
3986 &stats)) {
3987 A_PRINTF(KERN_ALERT"------- Profiling Endpoint : %d \n", i);
3988 A_PRINTF(KERN_ALERT"TxCreditLowIndications : %d \n", stats.TxCreditLowIndications);
3989 A_PRINTF(KERN_ALERT"TxIssued : %d \n", stats.TxIssued);
3990 A_PRINTF(KERN_ALERT"TxDropped: %d \n", stats.TxDropped);
3991 A_PRINTF(KERN_ALERT"TxPacketsBundled : %d \n", stats.TxPacketsBundled);
3992 A_PRINTF(KERN_ALERT"TxBundles : %d \n", stats.TxBundles);
3993 A_PRINTF(KERN_ALERT"TxCreditRpts : %d \n", stats.TxCreditRpts);
3994 A_PRINTF(KERN_ALERT"TxCreditsRptsFromRx : %d \n", stats.TxCreditRptsFromRx);
3995 A_PRINTF(KERN_ALERT"TxCreditsRptsFromOther : %d \n", stats.TxCreditRptsFromOther);
3996 A_PRINTF(KERN_ALERT"TxCreditsRptsFromEp0 : %d \n", stats.TxCreditRptsFromEp0);
3997 A_PRINTF(KERN_ALERT"TxCreditsFromRx : %d \n", stats.TxCreditsFromRx);
3998 A_PRINTF(KERN_ALERT"TxCreditsFromOther : %d \n", stats.TxCreditsFromOther);
3999 A_PRINTF(KERN_ALERT"TxCreditsFromEp0 : %d \n", stats.TxCreditsFromEp0);
4000 A_PRINTF(KERN_ALERT"TxCreditsConsummed : %d \n", stats.TxCreditsConsummed);
4001 A_PRINTF(KERN_ALERT"TxCreditsReturned : %d \n", stats.TxCreditsReturned);
4002 A_PRINTF(KERN_ALERT"RxReceived : %d \n", stats.RxReceived);
4003 A_PRINTF(KERN_ALERT"RxPacketsBundled : %d \n", stats.RxPacketsBundled);
4004 A_PRINTF(KERN_ALERT"RxLookAheads : %d \n", stats.RxLookAheads);
4005 A_PRINTF(KERN_ALERT"RxBundleLookAheads : %d \n", stats.RxBundleLookAheads);
4006 A_PRINTF(KERN_ALERT"RxBundleIndFromHdr : %d \n", stats.RxBundleIndFromHdr);
4007 A_PRINTF(KERN_ALERT"RxAllocThreshHit : %d \n", stats.RxAllocThreshHit);
4008 A_PRINTF(KERN_ALERT"RxAllocThreshBytes : %d \n", stats.RxAllocThreshBytes);
4009 A_PRINTF(KERN_ALERT"---- \n");
4010
4011 }
4012 }
4013 }
4014#endif
4015 }
4016 break;
4017 case AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE:
4018 if (ar->arHtcTarget != NULL) {
4019 struct ar6000_traffic_activity_change data;
4020
4021 if (copy_from_user(&data, userdata, sizeof(data)))
4022 {
4023 ret = -EFAULT;
4024 goto ioctl_done;
4025 }
4026 /* note, this is used for testing (mbox ping testing), indicate activity
4027 * change using the stream ID as the traffic class */
4028 ar6000_indicate_tx_activity(ar,
Joe Perchesab3655d2011-02-02 14:05:49 -08004029 (u8)data.StreamID,
Joe Perches1071a132011-02-02 14:05:47 -08004030 data.Active ? true : false);
Vipin Mehta30295c82010-09-01 12:06:33 -07004031 }
4032 break;
4033 case AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS:
Joe Perches1071a132011-02-02 14:05:47 -08004034 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004035 ret = -EIO;
4036 } else if (copy_from_user(&connectCtrlFlags, userdata,
4037 sizeof(connectCtrlFlags)))
4038 {
4039 ret = -EFAULT;
4040 } else {
4041 ar->arConnectCtrlFlags = connectCtrlFlags;
4042 }
4043 break;
4044 case AR6000_XIOCTL_WMI_SET_AKMP_PARAMS:
Joe Perches1071a132011-02-02 14:05:47 -08004045 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004046 ret = -EIO;
4047 } else if (copy_from_user(&akmpParams, userdata,
4048 sizeof(WMI_SET_AKMP_PARAMS_CMD)))
4049 {
4050 ret = -EFAULT;
4051 } else {
Joe Perches4f69cef2011-02-02 14:05:57 -08004052 if (wmi_set_akmp_params_cmd(ar->arWmi, &akmpParams) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004053 ret = -EIO;
4054 }
4055 }
4056 break;
4057 case AR6000_XIOCTL_WMI_SET_PMKID_LIST:
Joe Perches1071a132011-02-02 14:05:47 -08004058 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004059 ret = -EIO;
4060 } else {
4061 if (copy_from_user(&pmkidInfo.numPMKID, userdata,
4062 sizeof(pmkidInfo.numPMKID)))
4063 {
4064 ret = -EFAULT;
4065 break;
4066 }
4067 if (copy_from_user(&pmkidInfo.pmkidList,
4068 userdata + sizeof(pmkidInfo.numPMKID),
4069 pmkidInfo.numPMKID * sizeof(WMI_PMKID)))
4070 {
4071 ret = -EFAULT;
4072 break;
4073 }
Joe Perches4f69cef2011-02-02 14:05:57 -08004074 if (wmi_set_pmkid_list_cmd(ar->arWmi, &pmkidInfo) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004075 ret = -EIO;
4076 }
4077 }
4078 break;
4079 case AR6000_XIOCTL_WMI_GET_PMKID_LIST:
Joe Perches1071a132011-02-02 14:05:47 -08004080 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004081 ret = -EIO;
4082 } else {
Joe Perches4f69cef2011-02-02 14:05:57 -08004083 if (wmi_get_pmkid_list_cmd(ar->arWmi) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004084 ret = -EIO;
4085 }
4086 }
4087 break;
4088 case AR6000_XIOCTL_WMI_ABORT_SCAN:
Joe Perches1071a132011-02-02 14:05:47 -08004089 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004090 ret = -EIO;
4091 }
4092 ret = wmi_abort_scan_cmd(ar->arWmi);
4093 break;
4094 case AR6000_XIOCTL_AP_HIDDEN_SSID:
4095 {
Joe Perchesab3655d2011-02-02 14:05:49 -08004096 u8 hidden_ssid;
Joe Perches1071a132011-02-02 14:05:47 -08004097 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004098 ret = -EIO;
4099 } else if (copy_from_user(&hidden_ssid, userdata, sizeof(hidden_ssid))) {
4100 ret = -EFAULT;
4101 } else {
4102 wmi_ap_set_hidden_ssid(ar->arWmi, hidden_ssid);
4103 ar->ap_hidden_ssid = hidden_ssid;
4104 ar->ap_profile_flag = 1; /* There is a change in profile */
4105 }
4106 break;
4107 }
4108 case AR6000_XIOCTL_AP_GET_STA_LIST:
4109 {
Joe Perches1071a132011-02-02 14:05:47 -08004110 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004111 ret = -EIO;
4112 } else {
Joe Perchesab3655d2011-02-02 14:05:49 -08004113 u8 i;
Vipin Mehta30295c82010-09-01 12:06:33 -07004114 ap_get_sta_t temp;
4115 A_MEMZERO(&temp, sizeof(temp));
4116 for(i=0;i<AP_MAX_NUM_STA;i++) {
Luis R. Rodriguez05209262011-03-10 18:55:29 -08004117 memcpy(temp.sta[i].mac, ar->sta_list[i].mac, ATH_MAC_LEN);
Vipin Mehta30295c82010-09-01 12:06:33 -07004118 temp.sta[i].aid = ar->sta_list[i].aid;
4119 temp.sta[i].keymgmt = ar->sta_list[i].keymgmt;
4120 temp.sta[i].ucipher = ar->sta_list[i].ucipher;
4121 temp.sta[i].auth = ar->sta_list[i].auth;
4122 }
4123 if(copy_to_user((ap_get_sta_t *)rq->ifr_data, &temp,
4124 sizeof(ar->sta_list))) {
4125 ret = -EFAULT;
4126 }
4127 }
4128 break;
4129 }
4130 case AR6000_XIOCTL_AP_SET_NUM_STA:
4131 {
Joe Perchesab3655d2011-02-02 14:05:49 -08004132 u8 num_sta;
Joe Perches1071a132011-02-02 14:05:47 -08004133 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004134 ret = -EIO;
4135 } else if (copy_from_user(&num_sta, userdata, sizeof(num_sta))) {
4136 ret = -EFAULT;
4137 } else if(num_sta > AP_MAX_NUM_STA) {
4138 /* value out of range */
4139 ret = -EINVAL;
4140 } else {
4141 wmi_ap_set_num_sta(ar->arWmi, num_sta);
4142 }
4143 break;
4144 }
4145 case AR6000_XIOCTL_AP_SET_ACL_POLICY:
4146 {
Joe Perchesab3655d2011-02-02 14:05:49 -08004147 u8 policy;
Joe Perches1071a132011-02-02 14:05:47 -08004148 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004149 ret = -EIO;
4150 } else if (copy_from_user(&policy, userdata, sizeof(policy))) {
4151 ret = -EFAULT;
4152 } else if(policy == ar->g_acl.policy) {
4153 /* No change in policy */
4154 } else {
4155 if(!(policy & AP_ACL_RETAIN_LIST_MASK)) {
4156 /* clear ACL list */
4157 memset(&ar->g_acl,0,sizeof(WMI_AP_ACL));
4158 }
4159 ar->g_acl.policy = policy;
4160 wmi_ap_set_acl_policy(ar->arWmi, policy);
4161 }
4162 break;
4163 }
4164 case AR6000_XIOCTL_AP_SET_ACL_MAC:
4165 {
4166 WMI_AP_ACL_MAC_CMD acl;
Joe Perches1071a132011-02-02 14:05:47 -08004167 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004168 ret = -EIO;
4169 } else if (copy_from_user(&acl, userdata, sizeof(acl))) {
4170 ret = -EFAULT;
4171 } else {
4172 if(acl_add_del_mac(&ar->g_acl, &acl)) {
4173 wmi_ap_acl_mac_list(ar->arWmi, &acl);
4174 } else {
4175 A_PRINTF("ACL list error\n");
4176 ret = -EIO;
4177 }
4178 }
4179 break;
4180 }
4181 case AR6000_XIOCTL_AP_GET_ACL_LIST:
4182 {
Joe Perches1071a132011-02-02 14:05:47 -08004183 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004184 ret = -EIO;
4185 } else if(copy_to_user((WMI_AP_ACL *)rq->ifr_data, &ar->g_acl,
4186 sizeof(WMI_AP_ACL))) {
4187 ret = -EFAULT;
4188 }
4189 break;
4190 }
4191 case AR6000_XIOCTL_AP_COMMIT_CONFIG:
4192 {
4193 ret = ar6000_ap_mode_profile_commit(ar);
4194 break;
4195 }
4196 case IEEE80211_IOCTL_GETWPAIE:
4197 {
4198 struct ieee80211req_wpaie wpaie;
Joe Perches1071a132011-02-02 14:05:47 -08004199 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004200 ret = -EIO;
4201 } else if (copy_from_user(&wpaie, userdata, sizeof(wpaie))) {
4202 ret = -EFAULT;
4203 } else if (ar6000_ap_mode_get_wpa_ie(ar, &wpaie)) {
4204 ret = -EFAULT;
4205 } else if(copy_to_user(userdata, &wpaie, sizeof(wpaie))) {
4206 ret = -EFAULT;
4207 }
4208 break;
4209 }
4210 case AR6000_XIOCTL_AP_CONN_INACT_TIME:
4211 {
Joe Perchese1ce2a32011-02-02 14:05:51 -08004212 u32 period;
Joe Perches1071a132011-02-02 14:05:47 -08004213 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004214 ret = -EIO;
4215 } else if (copy_from_user(&period, userdata, sizeof(period))) {
4216 ret = -EFAULT;
4217 } else {
4218 wmi_ap_conn_inact_time(ar->arWmi, period);
4219 }
4220 break;
4221 }
4222 case AR6000_XIOCTL_AP_PROT_SCAN_TIME:
4223 {
4224 WMI_AP_PROT_SCAN_TIME_CMD bgscan;
Joe Perches1071a132011-02-02 14:05:47 -08004225 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004226 ret = -EIO;
4227 } else if (copy_from_user(&bgscan, userdata, sizeof(bgscan))) {
4228 ret = -EFAULT;
4229 } else {
4230 wmi_ap_bgscan_time(ar->arWmi, bgscan.period_min, bgscan.dwell_ms);
4231 }
4232 break;
4233 }
4234 case AR6000_XIOCTL_AP_SET_COUNTRY:
4235 {
4236 ret = ar6000_ioctl_set_country(dev, rq);
4237 break;
4238 }
4239 case AR6000_XIOCTL_AP_SET_DTIM:
4240 {
4241 WMI_AP_SET_DTIM_CMD d;
Joe Perches1071a132011-02-02 14:05:47 -08004242 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004243 ret = -EIO;
4244 } else if (copy_from_user(&d, userdata, sizeof(d))) {
4245 ret = -EFAULT;
4246 } else {
4247 if(d.dtim > 0 && d.dtim < 11) {
4248 ar->ap_dtim_period = d.dtim;
4249 wmi_ap_set_dtim(ar->arWmi, d.dtim);
4250 ar->ap_profile_flag = 1; /* There is a change in profile */
4251 } else {
4252 A_PRINTF("DTIM out of range. Valid range is [1-10]\n");
4253 ret = -EIO;
4254 }
4255 }
4256 break;
4257 }
4258 case AR6000_XIOCTL_WMI_TARGET_EVENT_REPORT:
4259 {
4260 WMI_SET_TARGET_EVENT_REPORT_CMD evtCfgCmd;
4261
Joe Perches1071a132011-02-02 14:05:47 -08004262 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004263 ret = -EIO;
4264 }
4265 if (copy_from_user(&evtCfgCmd, userdata,
4266 sizeof(evtCfgCmd))) {
4267 ret = -EFAULT;
4268 break;
4269 }
4270 ret = wmi_set_target_event_report_cmd(ar->arWmi, &evtCfgCmd);
4271 break;
4272 }
4273 case AR6000_XIOCTL_AP_INTRA_BSS_COMM:
4274 {
Joe Perchesab3655d2011-02-02 14:05:49 -08004275 u8 intra=0;
Joe Perches1071a132011-02-02 14:05:47 -08004276 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004277 ret = -EIO;
4278 } else if (copy_from_user(&intra, userdata, sizeof(intra))) {
4279 ret = -EFAULT;
4280 } else {
4281 ar->intra_bss = (intra?1:0);
4282 }
4283 break;
4284 }
4285 case AR6000_XIOCTL_DUMP_MODULE_DEBUG_INFO:
4286 {
4287 struct drv_debug_module_s moduleinfo;
4288
4289 if (copy_from_user(&moduleinfo, userdata, sizeof(moduleinfo))) {
4290 ret = -EFAULT;
4291 break;
4292 }
4293
4294 a_dump_module_debug_info_by_name(moduleinfo.modulename);
4295 ret = 0;
4296 break;
4297 }
4298 case AR6000_XIOCTL_MODULE_DEBUG_SET_MASK:
4299 {
4300 struct drv_debug_module_s moduleinfo;
4301
4302 if (copy_from_user(&moduleinfo, userdata, sizeof(moduleinfo))) {
4303 ret = -EFAULT;
4304 break;
4305 }
4306
Joe Perches391bb212011-01-27 20:04:21 -08004307 if (a_set_module_mask(moduleinfo.modulename, moduleinfo.mask)) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004308 ret = -EFAULT;
4309 }
4310
4311 break;
4312 }
4313 case AR6000_XIOCTL_MODULE_DEBUG_GET_MASK:
4314 {
4315 struct drv_debug_module_s moduleinfo;
4316
4317 if (copy_from_user(&moduleinfo, userdata, sizeof(moduleinfo))) {
4318 ret = -EFAULT;
4319 break;
4320 }
4321
Joe Perches391bb212011-01-27 20:04:21 -08004322 if (a_get_module_mask(moduleinfo.modulename, &moduleinfo.mask)) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004323 ret = -EFAULT;
4324 break;
4325 }
4326
4327 if (copy_to_user(userdata, &moduleinfo, sizeof(moduleinfo))) {
4328 ret = -EFAULT;
4329 break;
4330 }
4331
4332 break;
4333 }
4334#ifdef ATH_AR6K_11N_SUPPORT
4335 case AR6000_XIOCTL_DUMP_RCV_AGGR_STATS:
4336 {
4337 PACKET_LOG *copy_of_pkt_log;
4338
4339 aggr_dump_stats(ar->aggr_cntxt, &copy_of_pkt_log);
4340 if (copy_to_user(rq->ifr_data, copy_of_pkt_log, sizeof(PACKET_LOG))) {
4341 ret = -EFAULT;
4342 }
4343 break;
4344 }
4345 case AR6000_XIOCTL_SETUP_AGGR:
4346 {
4347 WMI_ADDBA_REQ_CMD cmd;
4348
Joe Perches1071a132011-02-02 14:05:47 -08004349 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004350 ret = -EIO;
4351 } else if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
4352 ret = -EFAULT;
4353 } else {
4354 wmi_setup_aggr_cmd(ar->arWmi, cmd.tid);
4355 }
4356 }
4357 break;
4358
4359 case AR6000_XIOCTL_DELE_AGGR:
4360 {
4361 WMI_DELBA_REQ_CMD cmd;
4362
Joe Perches1071a132011-02-02 14:05:47 -08004363 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004364 ret = -EIO;
4365 } else if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
4366 ret = -EFAULT;
4367 } else {
4368 wmi_delete_aggr_cmd(ar->arWmi, cmd.tid, cmd.is_sender_initiator);
4369 }
4370 }
4371 break;
4372
4373 case AR6000_XIOCTL_ALLOW_AGGR:
4374 {
4375 WMI_ALLOW_AGGR_CMD cmd;
4376
Joe Perches1071a132011-02-02 14:05:47 -08004377 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004378 ret = -EIO;
4379 } else if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
4380 ret = -EFAULT;
4381 } else {
4382 wmi_allow_aggr_cmd(ar->arWmi, cmd.tx_allow_aggr, cmd.rx_allow_aggr);
4383 }
4384 }
4385 break;
4386
4387 case AR6000_XIOCTL_SET_HT_CAP:
4388 {
Joe Perches1071a132011-02-02 14:05:47 -08004389 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004390 ret = -EIO;
4391 } else if (copy_from_user(&htCap, userdata,
4392 sizeof(htCap)))
4393 {
4394 ret = -EFAULT;
4395 } else {
4396
Joe Perches4f69cef2011-02-02 14:05:57 -08004397 if (wmi_set_ht_cap_cmd(ar->arWmi, &htCap) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07004398 {
4399 ret = -EIO;
4400 }
4401 }
4402 break;
4403 }
4404 case AR6000_XIOCTL_SET_HT_OP:
4405 {
Joe Perches1071a132011-02-02 14:05:47 -08004406 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004407 ret = -EIO;
4408 } else if (copy_from_user(&htOp, userdata,
4409 sizeof(htOp)))
4410 {
4411 ret = -EFAULT;
4412 } else {
4413
Joe Perches4f69cef2011-02-02 14:05:57 -08004414 if (wmi_set_ht_op_cmd(ar->arWmi, htOp.sta_chan_width) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07004415 {
4416 ret = -EIO;
4417 }
4418 }
4419 break;
4420 }
4421#endif
4422 case AR6000_XIOCTL_ACL_DATA:
4423 {
4424 void *osbuf = NULL;
Joe Perches1071a132011-02-02 14:05:47 -08004425 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004426 ret = -EIO;
Joe Perches4f69cef2011-02-02 14:05:57 -08004427 } else if (ar6000_create_acl_data_osbuf(dev, (u8 *)userdata, &osbuf) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004428 ret = -EIO;
4429 } else {
Joe Perches4f69cef2011-02-02 14:05:57 -08004430 if (wmi_data_hdr_add(ar->arWmi, osbuf, DATA_MSGTYPE, 0, WMI_DATA_HDR_DATA_TYPE_ACL,0,NULL) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004431 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("XIOCTL_ACL_DATA - wmi_data_hdr_add failed\n"));
4432 } else {
4433 /* Send data buffer over HTC */
4434 ar6000_acl_data_tx(osbuf, ar->arNetDev);
4435 }
4436 }
4437 break;
4438 }
4439 case AR6000_XIOCTL_HCI_CMD:
4440 {
4441 char tmp_buf[512];
Joe Perchesf2ab1272011-02-02 14:05:53 -08004442 s8 i;
Vipin Mehta30295c82010-09-01 12:06:33 -07004443 WMI_HCI_CMD *cmd = (WMI_HCI_CMD *)tmp_buf;
Joe Perchesab3655d2011-02-02 14:05:49 -08004444 u8 size;
Vipin Mehta30295c82010-09-01 12:06:33 -07004445
4446 size = sizeof(cmd->cmd_buf_sz);
Joe Perches1071a132011-02-02 14:05:47 -08004447 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004448 ret = -EIO;
4449 } else if (copy_from_user(cmd, userdata, size)) {
4450 ret = -EFAULT;
4451 } else if(copy_from_user(cmd->buf, userdata + size, cmd->cmd_buf_sz)) {
4452 ret = -EFAULT;
4453 } else {
Joe Perches4f69cef2011-02-02 14:05:57 -08004454 if (wmi_send_hci_cmd(ar->arWmi, cmd->buf, cmd->cmd_buf_sz) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004455 ret = -EIO;
4456 }else if(loghci) {
4457 A_PRINTF_LOG("HCI Command To PAL --> \n");
4458 for(i = 0; i < cmd->cmd_buf_sz; i++) {
4459 A_PRINTF_LOG("0x%02x ",cmd->buf[i]);
4460 if((i % 10) == 0) {
4461 A_PRINTF_LOG("\n");
4462 }
4463 }
4464 A_PRINTF_LOG("\n");
4465 A_PRINTF_LOG("==================================\n");
4466 }
4467 }
4468 break;
4469 }
4470 case AR6000_XIOCTL_WLAN_CONN_PRECEDENCE:
4471 {
4472 WMI_SET_BT_WLAN_CONN_PRECEDENCE cmd;
Joe Perches1071a132011-02-02 14:05:47 -08004473 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004474 ret = -EIO;
4475 } else if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
4476 ret = -EFAULT;
4477 } else {
4478 if (cmd.precedence == BT_WLAN_CONN_PRECDENCE_WLAN ||
4479 cmd.precedence == BT_WLAN_CONN_PRECDENCE_PAL) {
Joe Perches4f69cef2011-02-02 14:05:57 -08004480 if ( wmi_set_wlan_conn_precedence_cmd(ar->arWmi, cmd.precedence) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004481 ret = -EIO;
4482 }
4483 } else {
4484 ret = -EINVAL;
4485 }
4486 }
4487 break;
4488 }
4489 case AR6000_XIOCTL_AP_GET_STAT:
4490 {
4491 ret = ar6000_ioctl_get_ap_stats(dev, rq);
4492 break;
4493 }
4494 case AR6000_XIOCTL_SET_TX_SELECT_RATES:
4495 {
4496 WMI_SET_TX_SELECT_RATES_CMD masks;
4497
Joe Perches1071a132011-02-02 14:05:47 -08004498 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004499 ret = -EIO;
4500 } else if (copy_from_user(&masks, userdata,
4501 sizeof(masks)))
4502 {
4503 ret = -EFAULT;
4504 } else {
4505
Joe Perches4f69cef2011-02-02 14:05:57 -08004506 if (wmi_set_tx_select_rates_cmd(ar->arWmi, masks.rateMasks) != 0)
Vipin Mehta30295c82010-09-01 12:06:33 -07004507 {
4508 ret = -EIO;
4509 }
4510 }
4511 break;
4512 }
4513 case AR6000_XIOCTL_AP_GET_HIDDEN_SSID:
4514 {
4515 WMI_AP_HIDDEN_SSID_CMD ssid;
4516 ssid.hidden_ssid = ar->ap_hidden_ssid;
4517
Joe Perches1071a132011-02-02 14:05:47 -08004518 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004519 ret = -EIO;
4520 } else if(copy_to_user((WMI_AP_HIDDEN_SSID_CMD *)rq->ifr_data,
4521 &ssid, sizeof(WMI_AP_HIDDEN_SSID_CMD))) {
4522 ret = -EFAULT;
4523 }
4524 break;
4525 }
4526 case AR6000_XIOCTL_AP_GET_COUNTRY:
4527 {
4528 WMI_AP_SET_COUNTRY_CMD cty;
Luis R. Rodriguez05209262011-03-10 18:55:29 -08004529 memcpy(cty.countryCode, ar->ap_country_code, 3);
Vipin Mehta30295c82010-09-01 12:06:33 -07004530
Joe Perches1071a132011-02-02 14:05:47 -08004531 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004532 ret = -EIO;
4533 } else if(copy_to_user((WMI_AP_SET_COUNTRY_CMD *)rq->ifr_data,
4534 &cty, sizeof(WMI_AP_SET_COUNTRY_CMD))) {
4535 ret = -EFAULT;
4536 }
4537 break;
4538 }
4539 case AR6000_XIOCTL_AP_GET_WMODE:
4540 {
Joe Perches1071a132011-02-02 14:05:47 -08004541 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004542 ret = -EIO;
Joe Perchesab3655d2011-02-02 14:05:49 -08004543 } else if(copy_to_user((u8 *)rq->ifr_data,
4544 &ar->ap_wmode, sizeof(u8))) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004545 ret = -EFAULT;
4546 }
4547 break;
4548 }
4549 case AR6000_XIOCTL_AP_GET_DTIM:
4550 {
4551 WMI_AP_SET_DTIM_CMD dtim;
4552 dtim.dtim = ar->ap_dtim_period;
4553
Joe Perches1071a132011-02-02 14:05:47 -08004554 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004555 ret = -EIO;
4556 } else if(copy_to_user((WMI_AP_SET_DTIM_CMD *)rq->ifr_data,
4557 &dtim, sizeof(WMI_AP_SET_DTIM_CMD))) {
4558 ret = -EFAULT;
4559 }
4560 break;
4561 }
4562 case AR6000_XIOCTL_AP_GET_BINTVL:
4563 {
4564 WMI_BEACON_INT_CMD bi;
4565 bi.beaconInterval = ar->ap_beacon_interval;
4566
Joe Perches1071a132011-02-02 14:05:47 -08004567 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004568 ret = -EIO;
4569 } else if(copy_to_user((WMI_BEACON_INT_CMD *)rq->ifr_data,
4570 &bi, sizeof(WMI_BEACON_INT_CMD))) {
4571 ret = -EFAULT;
4572 }
4573 break;
4574 }
4575 case AR6000_XIOCTL_AP_GET_RTS:
4576 {
4577 WMI_SET_RTS_CMD rts;
4578 rts.threshold = ar->arRTS;
4579
Joe Perches1071a132011-02-02 14:05:47 -08004580 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004581 ret = -EIO;
4582 } else if(copy_to_user((WMI_SET_RTS_CMD *)rq->ifr_data,
4583 &rts, sizeof(WMI_SET_RTS_CMD))) {
4584 ret = -EFAULT;
4585 }
4586 break;
4587 }
4588 case AR6000_XIOCTL_FETCH_TARGET_REGS:
4589 {
Joe Perchese1ce2a32011-02-02 14:05:51 -08004590 u32 targregs[AR6003_FETCH_TARG_REGS_COUNT];
Vipin Mehta30295c82010-09-01 12:06:33 -07004591
4592 if (ar->arTargetType == TARGET_TYPE_AR6003) {
4593 ar6k_FetchTargetRegs(hifDevice, targregs);
Joe Perchese1ce2a32011-02-02 14:05:51 -08004594 if (copy_to_user((u32 *)rq->ifr_data, &targregs, sizeof(targregs)))
Vipin Mehta30295c82010-09-01 12:06:33 -07004595 {
4596 ret = -EFAULT;
4597 }
4598 } else {
4599 ret = -EOPNOTSUPP;
4600 }
4601 break;
4602 }
4603 case AR6000_XIOCTL_AP_SET_11BG_RATESET:
4604 {
4605 WMI_AP_SET_11BG_RATESET_CMD rate;
Joe Perches1071a132011-02-02 14:05:47 -08004606 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004607 ret = -EIO;
4608 } else if (copy_from_user(&rate, userdata, sizeof(rate))) {
4609 ret = -EFAULT;
4610 } else {
4611 wmi_ap_set_rateset(ar->arWmi, rate.rateset);
4612 }
4613 break;
4614 }
4615 case AR6000_XIOCTL_GET_WLAN_SLEEP_STATE:
4616 {
4617 WMI_REPORT_SLEEP_STATE_EVENT wmiSleepEvent ;
4618
4619 if (ar->arWlanState == WLAN_ENABLED) {
4620 wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_AWAKE;
4621 } else {
4622 wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP;
4623 }
4624 rq->ifr_ifru.ifru_ivalue = ar->arWlanState; /* return value */
4625
Joe Perchesab3655d2011-02-02 14:05:49 -08004626 ar6000_send_event_to_app(ar, WMI_REPORT_SLEEP_STATE_EVENTID, (u8 *)&wmiSleepEvent,
Vipin Mehta30295c82010-09-01 12:06:33 -07004627 sizeof(WMI_REPORT_SLEEP_STATE_EVENTID));
4628 break;
4629 }
4630#ifdef CONFIG_PM
4631 case AR6000_XIOCTL_SET_BT_HW_POWER_STATE:
4632 {
4633 unsigned int state;
Vasiliy Kulikovec53d612010-09-05 22:32:29 +04004634 if (get_user(state, (unsigned int *)userdata)) {
4635 ret = -EFAULT;
4636 break;
4637 }
Joe Perches4f69cef2011-02-02 14:05:57 -08004638 if (ar6000_set_bt_hw_state(ar, state)!= 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004639 ret = -EIO;
4640 }
4641 }
4642 break;
4643 case AR6000_XIOCTL_GET_BT_HW_POWER_STATE:
4644 rq->ifr_ifru.ifru_ivalue = !ar->arBTOff; /* return value */
4645 break;
4646#endif
4647
4648 case AR6000_XIOCTL_WMI_SET_TX_SGI_PARAM:
4649 {
4650 WMI_SET_TX_SGI_PARAM_CMD SGICmd;
4651
Joe Perches1071a132011-02-02 14:05:47 -08004652 if (ar->arWmiReady == false) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004653 ret = -EIO;
4654 } else if (copy_from_user(&SGICmd, userdata,
4655 sizeof(SGICmd))){
4656 ret = -EFAULT;
4657 } else{
Joe Perches4f69cef2011-02-02 14:05:57 -08004658 if (wmi_SGI_cmd(ar->arWmi, SGICmd.sgiMask, SGICmd.sgiPERThreshold) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004659 ret = -EIO;
4660 }
4661
4662 }
4663 break;
4664 }
4665
4666 case AR6000_XIOCTL_ADD_AP_INTERFACE:
4667#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
4668 {
4669 char ap_ifname[IFNAMSIZ] = {0,};
4670 if (copy_from_user(ap_ifname, userdata, IFNAMSIZ)) {
4671 ret = -EFAULT;
4672 } else {
Joe Perches4f69cef2011-02-02 14:05:57 -08004673 if (ar6000_add_ap_interface(ar, ap_ifname) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004674 ret = -EIO;
4675 }
4676 }
4677 }
4678#else
4679 ret = -EOPNOTSUPP;
4680#endif
4681 break;
4682 case AR6000_XIOCTL_REMOVE_AP_INTERFACE:
4683#ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
Joe Perches4f69cef2011-02-02 14:05:57 -08004684 if (ar6000_remove_ap_interface(ar) != 0) {
Vipin Mehta30295c82010-09-01 12:06:33 -07004685 ret = -EIO;
4686 }
4687#else
4688 ret = -EOPNOTSUPP;
4689#endif
4690 break;
4691
Vipin Mehta711a1bc2011-02-18 13:13:11 -08004692 case AR6000_XIOCTL_WMI_SET_EXCESS_TX_RETRY_THRES:
4693 {
4694 ret = ar6000_xioctl_set_excess_tx_retry_thres_cmd(dev, userdata);
4695 break;
4696 }
4697
Vipin Mehta30295c82010-09-01 12:06:33 -07004698 default:
4699 ret = -EOPNOTSUPP;
4700 }
4701
4702ioctl_done:
4703 rtnl_lock(); /* restore rtnl state */
4704 dev_put(dev);
4705
4706 return ret;
4707}
4708
Joe Perchesab3655d2011-02-02 14:05:49 -08004709u8 mac_cmp_wild(u8 *mac, u8 *new_mac, u8 wild, u8 new_wild)
Vipin Mehta30295c82010-09-01 12:06:33 -07004710{
Joe Perchesab3655d2011-02-02 14:05:49 -08004711 u8 i;
Vipin Mehta30295c82010-09-01 12:06:33 -07004712
4713 for(i=0;i<ATH_MAC_LEN;i++) {
4714 if((wild & 1<<i) && (new_wild & 1<<i)) continue;
4715 if(mac[i] != new_mac[i]) return 1;
4716 }
Luis R. Rodriguez395e1ca2011-03-10 18:55:30 -08004717 if((memcmp(new_mac, null_mac, 6)==0) && new_wild &&
Vipin Mehta30295c82010-09-01 12:06:33 -07004718 (wild != new_wild)) {
4719 return 1;
4720 }
4721
4722 return 0;
4723}
4724
Joe Perchesab3655d2011-02-02 14:05:49 -08004725u8 acl_add_del_mac(WMI_AP_ACL *a, WMI_AP_ACL_MAC_CMD *acl)
Vipin Mehta30295c82010-09-01 12:06:33 -07004726{
Joe Perchesf2ab1272011-02-02 14:05:53 -08004727 s8 already_avail=-1, free_slot=-1, i;
Vipin Mehta30295c82010-09-01 12:06:33 -07004728
4729 /* To check whether this mac is already there in our list */
4730 for(i=AP_ACL_SIZE-1;i>=0;i--)
4731 {
4732 if(mac_cmp_wild(a->acl_mac[i], acl->mac, a->wildcard[i],
4733 acl->wildcard)==0)
4734 already_avail = i;
4735
4736 if(!((1 << i) & a->index))
4737 free_slot = i;
4738 }
4739
4740 if(acl->action == ADD_MAC_ADDR)
4741 {
4742 /* Dont add mac if it is already available */
4743 if((already_avail >= 0) || (free_slot == -1))
4744 return 0;
4745
Luis R. Rodriguez05209262011-03-10 18:55:29 -08004746 memcpy(a->acl_mac[free_slot], acl->mac, ATH_MAC_LEN);
Vipin Mehta30295c82010-09-01 12:06:33 -07004747 a->index = a->index | (1 << free_slot);
4748 acl->index = free_slot;
4749 a->wildcard[free_slot] = acl->wildcard;
4750 return 1;
4751 }
4752 else if(acl->action == DEL_MAC_ADDR)
4753 {
4754 if(acl->index > AP_ACL_SIZE)
4755 return 0;
4756
4757 if(!(a->index & (1 << acl->index)))
4758 return 0;
4759
4760 A_MEMZERO(a->acl_mac[acl->index],ATH_MAC_LEN);
4761 a->index = a->index & ~(1 << acl->index);
4762 a->wildcard[acl->index] = 0;
4763 return 1;
4764 }
4765
4766 return 0;
4767}