1 /** @file moal_uap.c
2 *
3 * @brief This file contains the major functions in UAP
4 * driver.
5 *
6 * Copyright (C) 2008-2017, Marvell International Ltd.
7 *
8 * This software file (the "File") is distributed by Marvell International
9 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
10 * (the "License"). You may use, redistribute and/or modify this File in
11 * accordance with the terms and conditions of the License, a copy of which
12 * is available by writing to the Free Software Foundation, Inc.,
13 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15 *
16 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
19 * this warranty disclaimer.
20 *
21 */
22
23 /********************************************************
24 Change log:
25 10/21/2008: initial version
26 ********************************************************/
27
28 #include "moal_main.h"
29 #include "moal_uap.h"
30 #include "moal_sdio.h"
31 #include "moal_eth_ioctl.h"
32 #if defined(STA_CFG80211) && defined(UAP_CFG80211)
33 #include "moal_cfg80211.h"
34 #endif
35
36 /********************************************************
37 Local Variables
38 ********************************************************/
39
40 /********************************************************
41 Global Variables
42 ********************************************************/
43 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
44 extern int dfs_offload;
45 #endif
46 /********************************************************
47 Local Functions
48 ********************************************************/
49 /**
50 * @brief uap addba parameter handler
51 *
52 * @param dev A pointer to net_device structure
53 * @param req A pointer to ifreq structure
54 * @return 0 --success, otherwise fail
55 */
56 static int
woal_uap_addba_param(struct net_device * dev,struct ifreq * req)57 woal_uap_addba_param(struct net_device *dev, struct ifreq *req)
58 {
59 moal_private *priv = (moal_private *)netdev_priv(dev);
60 mlan_ioctl_req *ioctl_req = NULL;
61 mlan_ds_11n_cfg *cfg_11n = NULL;
62 addba_param param;
63 int ret = 0;
64 mlan_status status = MLAN_STATUS_SUCCESS;
65
66 ENTER();
67 memset(¶m, 0, sizeof(param));
68
69 /* Sanity check */
70 if (req->ifr_data == NULL) {
71 PRINTM(MERROR, "uap_addba_param() corrupt data\n");
72 ret = -EFAULT;
73 goto done;
74 }
75 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
76 PRINTM(MERROR, "Copy from user failed\n");
77 ret = -EFAULT;
78 goto done;
79 }
80 PRINTM(MIOCTL,
81 "addba param: action=%d, timeout=%d, txwinsize=%d, rxwinsize=%d txamsdu=%d rxamsdu=%d\n",
82 (int)param.action, (int)param.timeout, (int)param.txwinsize,
83 (int)param.rxwinsize, (int)param.txamsdu, (int)param.rxamsdu);
84 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
85 if (ioctl_req == NULL) {
86 LEAVE();
87 return -ENOMEM;
88 }
89 cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
90 cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_PARAM;
91 ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
92
93 if (!param.action)
94 /* Get addba param from MLAN */
95 ioctl_req->action = MLAN_ACT_GET;
96 else {
97 /* Set addba param in MLAN */
98 ioctl_req->action = MLAN_ACT_SET;
99 cfg_11n->param.addba_param.timeout = param.timeout;
100 cfg_11n->param.addba_param.txwinsize = param.txwinsize;
101 cfg_11n->param.addba_param.rxwinsize = param.rxwinsize;
102 cfg_11n->param.addba_param.txamsdu = param.txamsdu;
103 cfg_11n->param.addba_param.rxamsdu = param.rxamsdu;
104 }
105 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
106 if (status != MLAN_STATUS_SUCCESS) {
107 ret = -EFAULT;
108 goto done;
109 }
110 param.timeout = cfg_11n->param.addba_param.timeout;
111 param.txwinsize = cfg_11n->param.addba_param.txwinsize;
112 param.rxwinsize = cfg_11n->param.addba_param.rxwinsize;
113 param.txamsdu = cfg_11n->param.addba_param.txamsdu;
114 param.rxamsdu = cfg_11n->param.addba_param.rxamsdu;
115
116 /* Copy to user */
117 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
118 PRINTM(MERROR, "Copy to user failed!\n");
119 ret = -EFAULT;
120 goto done;
121 }
122 done:
123 if (status != MLAN_STATUS_PENDING)
124 kfree(ioctl_req);
125 LEAVE();
126 return ret;
127 }
128
129 /**
130 * @brief uap aggr priority tbl
131 *
132 * @param dev A pointer to net_device structure
133 * @param req A pointer to ifreq structure
134 * @return 0 --success, otherwise fail
135 */
136 static int
woal_uap_aggr_priotbl(struct net_device * dev,struct ifreq * req)137 woal_uap_aggr_priotbl(struct net_device *dev, struct ifreq *req)
138 {
139 moal_private *priv = (moal_private *)netdev_priv(dev);
140 mlan_ioctl_req *ioctl_req = NULL;
141 mlan_ds_11n_cfg *cfg_11n = NULL;
142 aggr_prio_tbl param;
143 int ret = 0;
144 int i = 0;
145 mlan_status status = MLAN_STATUS_SUCCESS;
146
147 ENTER();
148 memset(¶m, 0, sizeof(param));
149
150 /* Sanity check */
151 if (req->ifr_data == NULL) {
152 PRINTM(MERROR, "woal_uap_aggr_priotbl() corrupt data\n");
153 ret = -EFAULT;
154 goto done;
155 }
156 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
157 PRINTM(MERROR, "Copy from user failed\n");
158 ret = -EFAULT;
159 goto done;
160 }
161 DBG_HEXDUMP(MCMD_D, "aggr_prio_tbl", (t_u8 *)¶m, sizeof(param));
162
163 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
164 if (ioctl_req == NULL) {
165 LEAVE();
166 return -ENOMEM;
167 }
168 cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
169 cfg_11n->sub_command = MLAN_OID_11N_CFG_AGGR_PRIO_TBL;
170 ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
171
172 if (!param.action) {
173 /* Get aggr_prio_tbl from MLAN */
174 ioctl_req->action = MLAN_ACT_GET;
175 } else {
176 /* Set aggr_prio_tbl in MLAN */
177 ioctl_req->action = MLAN_ACT_SET;
178 for (i = 0; i < MAX_NUM_TID; i++) {
179 cfg_11n->param.aggr_prio_tbl.ampdu[i] = param.ampdu[i];
180 cfg_11n->param.aggr_prio_tbl.amsdu[i] = param.amsdu[i];
181 }
182 }
183 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
184 if (status != MLAN_STATUS_SUCCESS) {
185 ret = -EFAULT;
186 goto done;
187 }
188 for (i = 0; i < MAX_NUM_TID; i++) {
189 param.ampdu[i] = cfg_11n->param.aggr_prio_tbl.ampdu[i];
190 param.amsdu[i] = cfg_11n->param.aggr_prio_tbl.amsdu[i];
191 }
192 /* Copy to user */
193 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
194 PRINTM(MERROR, "Copy to user failed!\n");
195 ret = -EFAULT;
196 goto done;
197 }
198 done:
199 if (status != MLAN_STATUS_PENDING)
200 kfree(ioctl_req);
201 LEAVE();
202 return ret;
203 }
204
205 /**
206 * @brief uap addba reject tbl
207 *
208 * @param dev A pointer to net_device structure
209 * @param req A pointer to ifreq structure
210 * @return 0 --success, otherwise fail
211 */
212 static int
woal_uap_addba_reject(struct net_device * dev,struct ifreq * req)213 woal_uap_addba_reject(struct net_device *dev, struct ifreq *req)
214 {
215 moal_private *priv = (moal_private *)netdev_priv(dev);
216 mlan_ioctl_req *ioctl_req = NULL;
217 mlan_ds_11n_cfg *cfg_11n = NULL;
218 addba_reject_para param;
219 int ret = 0;
220 int i = 0;
221 mlan_status status = MLAN_STATUS_SUCCESS;
222
223 ENTER();
224 memset(¶m, 0, sizeof(param));
225
226 /* Sanity check */
227 if (req->ifr_data == NULL) {
228 PRINTM(MERROR, "woal_uap_addba_reject() corrupt data\n");
229 ret = -EFAULT;
230 goto done;
231 }
232 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
233 PRINTM(MERROR, "Copy from user failed\n");
234 ret = -EFAULT;
235 goto done;
236 }
237 DBG_HEXDUMP(MCMD_D, "addba_reject tbl", (t_u8 *)¶m, sizeof(param));
238
239 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
240 if (ioctl_req == NULL) {
241 LEAVE();
242 return -ENOMEM;
243 }
244 cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
245 cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_REJECT;
246 ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
247
248 if (!param.action) {
249 /* Get addba_reject tbl from MLAN */
250 ioctl_req->action = MLAN_ACT_GET;
251 } else {
252 /* Set addba_reject tbl in MLAN */
253 ioctl_req->action = MLAN_ACT_SET;
254 for (i = 0; i < MAX_NUM_TID; i++)
255 cfg_11n->param.addba_reject[i] = param.addba_reject[i];
256 }
257 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
258 if (status != MLAN_STATUS_SUCCESS) {
259 ret = -EFAULT;
260 goto done;
261 }
262 for (i = 0; i < MAX_NUM_TID; i++)
263 param.addba_reject[i] = cfg_11n->param.addba_reject[i];
264 /* Copy to user */
265 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
266 PRINTM(MERROR, "Copy to user failed!\n");
267 ret = -EFAULT;
268 goto done;
269 }
270 done:
271 if (status != MLAN_STATUS_PENDING)
272 kfree(ioctl_req);
273 LEAVE();
274 return ret;
275 }
276
277 /**
278 * @brief uap get_fw_info handler
279 *
280 * @param dev A pointer to net_device structure
281 * @param req A pointer to ifreq structure
282 * @return 0 --success, otherwise fail
283 */
284 static int
woal_uap_get_fw_info(struct net_device * dev,struct ifreq * req)285 woal_uap_get_fw_info(struct net_device *dev, struct ifreq *req)
286 {
287 moal_private *priv = (moal_private *)netdev_priv(dev);
288 fw_info fw;
289 mlan_fw_info fw_info;
290 int ret = 0;
291
292 ENTER();
293 memset(&fw, 0, sizeof(fw));
294 memset(&fw_info, 0, sizeof(fw_info));
295
296 /* Sanity check */
297 if (req->ifr_data == NULL) {
298 PRINTM(MERROR, "woal_uap_get_fw_info() corrupt data\n");
299 ret = -EFAULT;
300 goto done;
301 }
302 if (copy_from_user(&fw, req->ifr_data, sizeof(fw))) {
303 PRINTM(MERROR, "Copy from user failed\n");
304 ret = -EFAULT;
305 goto done;
306 }
307 if (MLAN_STATUS_SUCCESS !=
308 woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info)) {
309 ret = -EFAULT;
310 goto done;
311 }
312 fw.fw_release_number = fw_info.fw_ver;
313 fw.hw_dev_mcs_support = fw_info.hw_dev_mcs_support;
314 fw.fw_bands = fw_info.fw_bands;
315 fw.region_code = fw_info.region_code;
316 fw.hw_dot_11n_dev_cap = fw_info.hw_dot_11n_dev_cap;
317 /* Copy to user */
318 if (copy_to_user(req->ifr_data, &fw, sizeof(fw))) {
319 PRINTM(MERROR, "Copy to user failed!\n");
320 ret = -EFAULT;
321 goto done;
322 }
323 done:
324 LEAVE();
325 return ret;
326 }
327
328 /**
329 * @brief configure deep sleep
330 *
331 * @param dev A pointer to net_device structure
332 * @param req A pointer to ifreq structure
333 * @return 0 --success, otherwise fail
334 */
335 static int
woal_uap_deep_sleep(struct net_device * dev,struct ifreq * req)336 woal_uap_deep_sleep(struct net_device *dev, struct ifreq *req)
337 {
338 moal_private *priv = (moal_private *)netdev_priv(dev);
339 mlan_ioctl_req *ioctl_req = NULL;
340 mlan_ds_pm_cfg *pm = NULL;
341 deep_sleep_para param;
342 int ret = 0;
343 mlan_status status = MLAN_STATUS_SUCCESS;
344
345 ENTER();
346 memset(¶m, 0, sizeof(param));
347
348 /* Sanity check */
349 if (req->ifr_data == NULL) {
350 PRINTM(MERROR, "woal_uap_deep_sleep() corrupt data\n");
351 ret = -EFAULT;
352 goto done;
353 }
354 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
355 PRINTM(MERROR, "Copy from user failed\n");
356 ret = -EFAULT;
357 goto done;
358 }
359 DBG_HEXDUMP(MCMD_D, "deep_sleep_para", (t_u8 *)¶m, sizeof(param));
360
361 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
362 if (ioctl_req == NULL) {
363 LEAVE();
364 return -ENOMEM;
365 }
366 pm = (mlan_ds_pm_cfg *)ioctl_req->pbuf;
367 pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP;
368 ioctl_req->req_id = MLAN_IOCTL_PM_CFG;
369
370 if (!param.action) {
371 /* Get deep_sleep status from MLAN */
372 ioctl_req->action = MLAN_ACT_GET;
373 } else {
374 /* Set deep_sleep in MLAN */
375 ioctl_req->action = MLAN_ACT_SET;
376 if (param.deep_sleep == MTRUE) {
377 pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_ON;
378 pm->param.auto_deep_sleep.idletime = param.idle_time;
379 } else {
380 pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_OFF;
381 }
382 }
383 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
384 if (status != MLAN_STATUS_SUCCESS) {
385 ret = -EFAULT;
386 goto done;
387 }
388 if (pm->param.auto_deep_sleep.auto_ds == DEEP_SLEEP_ON)
389 param.deep_sleep = MTRUE;
390 else
391 param.deep_sleep = MFALSE;
392 param.idle_time = pm->param.auto_deep_sleep.idletime;
393 /* Copy to user */
394 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
395 PRINTM(MERROR, "Copy to user failed!\n");
396 ret = -EFAULT;
397 goto done;
398 }
399 done:
400 if (status != MLAN_STATUS_PENDING)
401 kfree(ioctl_req);
402 LEAVE();
403 return ret;
404 }
405
406 /**
407 * @brief configure tx_pause settings
408 *
409 * @param dev A pointer to net_device structure
410 * @param req A pointer to ifreq structure
411 * @return 0 --success, otherwise fail
412 */
413 static int
woal_uap_txdatapause(struct net_device * dev,struct ifreq * req)414 woal_uap_txdatapause(struct net_device *dev, struct ifreq *req)
415 {
416 moal_private *priv = (moal_private *)netdev_priv(dev);
417 mlan_ioctl_req *ioctl_req = NULL;
418 mlan_ds_misc_cfg *misc = NULL;
419 tx_data_pause_para param;
420 int ret = 0;
421 mlan_status status = MLAN_STATUS_SUCCESS;
422
423 ENTER();
424 memset(¶m, 0, sizeof(param));
425
426 /* Sanity check */
427 if (req->ifr_data == NULL) {
428 PRINTM(MERROR, "woal_uap_txdatapause corrupt data\n");
429 ret = -EFAULT;
430 goto done;
431 }
432 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
433 PRINTM(MERROR, "Copy from user failed\n");
434 ret = -EFAULT;
435 goto done;
436 }
437 DBG_HEXDUMP(MCMD_D, "tx_data_pause_para", (t_u8 *)¶m,
438 sizeof(param));
439
440 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
441 if (ioctl_req == NULL) {
442 LEAVE();
443 return -ENOMEM;
444 }
445 misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
446 misc->sub_command = MLAN_OID_MISC_TX_DATAPAUSE;
447 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
448
449 if (!param.action) {
450 /* Get Tx data pause status from MLAN */
451 ioctl_req->action = MLAN_ACT_GET;
452 } else {
453 /* Set Tx data pause in MLAN */
454 ioctl_req->action = MLAN_ACT_SET;
455 misc->param.tx_datapause.tx_pause = param.txpause;
456 misc->param.tx_datapause.tx_buf_cnt = param.txbufcnt;
457 }
458 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
459 if (status != MLAN_STATUS_SUCCESS) {
460 ret = -EFAULT;
461 goto done;
462 }
463
464 param.txpause = misc->param.tx_datapause.tx_pause;
465 param.txbufcnt = misc->param.tx_datapause.tx_buf_cnt;
466
467 /* Copy to user */
468 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
469 PRINTM(MERROR, "Copy to user failed!\n");
470 ret = -EFAULT;
471 goto done;
472 }
473 done:
474 if (status != MLAN_STATUS_PENDING)
475 kfree(ioctl_req);
476 LEAVE();
477 return ret;
478 }
479
480 /**
481 * @brief uap sdcmd52rw ioctl handler
482 *
483 * @param dev A pointer to net_device structure
484 * @param req A pointer to ifreq structure
485 * @return 0 --success, otherwise fail
486 */
487 static int
woal_uap_sdcmd52_rw(struct net_device * dev,struct ifreq * req)488 woal_uap_sdcmd52_rw(struct net_device *dev, struct ifreq *req)
489 {
490 moal_private *priv = (moal_private *)netdev_priv(dev);
491 sdcmd52_para param;
492 t_u8 func, data = 0;
493 int ret = 0, reg;
494
495 ENTER();
496 memset(¶m, 0, sizeof(param));
497
498 /* Sanity check */
499 if (req->ifr_data == NULL) {
500 PRINTM(MERROR, "woal_uap_sdcmd52_rw() corrupt data\n");
501 ret = -EFAULT;
502 goto done;
503 }
504 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
505 PRINTM(MERROR, "Copy from user failed\n");
506 ret = -EFAULT;
507 goto done;
508 }
509
510 func = (t_u8)param.cmd52_params[0];
511 reg = (t_u32)param.cmd52_params[1];
512
513 if (!param.action) {
514 PRINTM(MINFO, "Cmd52 read, func=%d, reg=0x%08X\n", func, reg);
515 sdio_claim_host(((struct sdio_mmc_card *)priv->phandle->card)->
516 func);
517 if (func)
518 data = sdio_readb(((struct sdio_mmc_card *)priv->
519 phandle->card)->func, reg, &ret);
520 else
521 data = sdio_f0_readb(((struct sdio_mmc_card *)priv->
522 phandle->card)->func, reg, &ret);
523 sdio_release_host(((struct sdio_mmc_card *)priv->phandle->
524 card)->func);
525 if (ret) {
526 PRINTM(MERROR,
527 "sdio_readb: reading register 0x%X failed\n",
528 reg);
529 goto done;
530 }
531 param.cmd52_params[2] = data;
532 } else {
533 data = (t_u8)param.cmd52_params[2];
534 PRINTM(MINFO, "Cmd52 write, func=%d, reg=0x%08X, data=0x%02X\n",
535 func, reg, data);
536 sdio_claim_host(((struct sdio_mmc_card *)priv->phandle->card)->
537 func);
538 if (func)
539 sdio_writeb(((struct sdio_mmc_card *)priv->phandle->
540 card)->func, data, reg, &ret);
541 else
542 sdio_f0_writeb(((struct sdio_mmc_card *)priv->phandle->
543 card)->func, data, reg, &ret);
544 sdio_release_host(((struct sdio_mmc_card *)priv->phandle->
545 card)->func);
546 if (ret) {
547 PRINTM(MERROR,
548 "sdio_writeb: writing register 0x%X failed\n",
549 reg);
550 goto done;
551 }
552 }
553 /* Copy to user */
554 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
555 PRINTM(MERROR, "Copy to user failed!\n");
556 ret = -EFAULT;
557 }
558 done:
559 LEAVE();
560 return ret;
561 }
562
563 /**
564 * @brief configure snmp mib
565 *
566 * @param dev A pointer to net_device structure
567 * @param req A pointer to ifreq structure
568 * @return 0 --success, otherwise fail
569 */
570 static int
woal_uap_snmp_mib(struct net_device * dev,struct ifreq * req)571 woal_uap_snmp_mib(struct net_device *dev, struct ifreq *req)
572 {
573 moal_private *priv = (moal_private *)netdev_priv(dev);
574 mlan_ioctl_req *ioctl_req = NULL;
575 mlan_ds_snmp_mib *snmp = NULL;
576 snmp_mib_para param;
577 t_u8 value[MAX_SNMP_VALUE_SIZE];
578 int ret = 0;
579 mlan_status status = MLAN_STATUS_SUCCESS;
580
581 ENTER();
582 memset(¶m, 0, sizeof(param));
583 memset(value, 0, MAX_SNMP_VALUE_SIZE);
584
585 /* Sanity check */
586 if (req->ifr_data == NULL) {
587 PRINTM(MERROR, "woal_uap_snmp_mib() corrupt data\n");
588 ret = -EFAULT;
589 goto done;
590 }
591
592 /* Copy from user */
593 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
594 PRINTM(MERROR, "Copy from user failed\n");
595 ret = -EFAULT;
596 goto done;
597 }
598 DBG_HEXDUMP(MCMD_D, "snmp_mib_para", (t_u8 *)¶m, sizeof(param));
599 if (param.action) {
600 if (copy_from_user(value, req->ifr_data + sizeof(param),
601 MIN(param.oid_val_len,
602 MAX_SNMP_VALUE_SIZE))) {
603 PRINTM(MERROR, "Copy from user failed\n");
604 ret = -EFAULT;
605 goto done;
606 }
607 DBG_HEXDUMP(MCMD_D, "snmp_mib_para value", value,
608 MIN(param.oid_val_len, sizeof(t_u32)));
609 }
610
611 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
612 if (ioctl_req == NULL) {
613 LEAVE();
614 return -ENOMEM;
615 }
616 snmp = (mlan_ds_snmp_mib *)ioctl_req->pbuf;
617 ioctl_req->req_id = MLAN_IOCTL_SNMP_MIB;
618 switch (param.oid) {
619 case OID_80211D_ENABLE:
620 snmp->sub_command = MLAN_OID_SNMP_MIB_DOT11D;
621 break;
622 case OID_80211H_ENABLE:
623 snmp->sub_command = MLAN_OID_SNMP_MIB_DOT11H;
624 break;
625 default:
626 PRINTM(MERROR, "%s: Unsupported SNMP_MIB OID (%d).\n", __func__,
627 param.oid);
628 goto done;
629 }
630
631 if (!param.action) {
632 /* Get mib value from MLAN */
633 ioctl_req->action = MLAN_ACT_GET;
634 } else {
635 /* Set mib value to MLAN */
636 ioctl_req->action = MLAN_ACT_SET;
637 snmp->param.oid_value = *(t_u32 *)value;
638 }
639 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
640 if (status != MLAN_STATUS_SUCCESS) {
641 ret = -EFAULT;
642 goto done;
643 }
644
645 /* Copy to user */
646 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
647 PRINTM(MERROR, "Copy to user failed!\n");
648 ret = -EFAULT;
649 goto done;
650 }
651 if (!param.action) { /* GET */
652 if (copy_to_user
653 (req->ifr_data + sizeof(param), &snmp->param.oid_value,
654 MIN(param.oid_val_len, sizeof(t_u32)))) {
655 PRINTM(MERROR, "Copy from user failed\n");
656 ret = -EFAULT;
657 goto done;
658 }
659 }
660
661 done:
662 if (status != MLAN_STATUS_PENDING)
663 kfree(ioctl_req);
664 LEAVE();
665 return ret;
666 }
667
668 /**
669 * @brief configure domain info
670 *
671 * @param dev A pointer to net_device structure
672 * @param req A pointer to ifreq structure
673 * @return 0 --success, otherwise fail
674 */
675 static int
woal_uap_domain_info(struct net_device * dev,struct ifreq * req)676 woal_uap_domain_info(struct net_device *dev, struct ifreq *req)
677 {
678 moal_private *priv = (moal_private *)netdev_priv(dev);
679 mlan_ioctl_req *ioctl_req = NULL;
680 mlan_ds_11d_cfg *cfg11d = NULL;
681 domain_info_para param;
682 t_u8 tlv[MAX_DOMAIN_TLV_LEN];
683 t_u16 tlv_data_len = 0;
684 int ret = 0;
685 mlan_status status = MLAN_STATUS_SUCCESS;
686
687 ENTER();
688 memset(¶m, 0, sizeof(param));
689 memset(tlv, 0, MAX_DOMAIN_TLV_LEN);
690
691 /* Sanity check */
692 if (req->ifr_data == NULL) {
693 PRINTM(MERROR, "woal_uap_domain_info() corrupt data\n");
694 ret = -EFAULT;
695 goto done;
696 }
697
698 /* Copy from user */
699 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
700 PRINTM(MERROR, "Copy from user failed\n");
701 ret = -EFAULT;
702 goto done;
703 }
704 DBG_HEXDUMP(MCMD_D, "domain_info_para", (t_u8 *)¶m, sizeof(param));
705 if (param.action) {
706 /* get tlv header */
707 if (copy_from_user
708 (tlv, req->ifr_data + sizeof(param), TLV_HEADER_LEN)) {
709 PRINTM(MERROR, "Copy from user failed\n");
710 ret = -EFAULT;
711 goto done;
712 }
713 tlv_data_len = ((t_u16 *)(tlv))[1];
714 if ((TLV_HEADER_LEN + tlv_data_len) > sizeof(tlv)) {
715 PRINTM(MERROR, "TLV buffer is overflowed");
716 ret = -EINVAL;
717 goto done;
718 }
719 /* get full tlv */
720 if (copy_from_user(tlv, req->ifr_data + sizeof(param),
721 TLV_HEADER_LEN + tlv_data_len)) {
722 PRINTM(MERROR, "Copy from user failed\n");
723 ret = -EFAULT;
724 goto done;
725 }
726 DBG_HEXDUMP(MCMD_D, "domain_info_para tlv", tlv,
727 TLV_HEADER_LEN + tlv_data_len);
728 }
729
730 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11d_cfg));
731 if (ioctl_req == NULL) {
732 LEAVE();
733 return -ENOMEM;
734 }
735 cfg11d = (mlan_ds_11d_cfg *)ioctl_req->pbuf;
736 ioctl_req->req_id = MLAN_IOCTL_11D_CFG;
737 cfg11d->sub_command = MLAN_OID_11D_DOMAIN_INFO;
738
739 if (!param.action) {
740 /* Get mib value from MLAN */
741 ioctl_req->action = MLAN_ACT_GET;
742 } else {
743 /* Set mib value to MLAN */
744 ioctl_req->action = MLAN_ACT_SET;
745 memcpy(cfg11d->param.domain_tlv, tlv,
746 MIN(MAX_IE_SIZE, (TLV_HEADER_LEN + tlv_data_len)));
747 }
748 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
749 if (status != MLAN_STATUS_SUCCESS) {
750 ret = -EFAULT;
751 goto done;
752 }
753
754 /* Copy to user */
755 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
756 PRINTM(MERROR, "Copy to user failed!\n");
757 ret = -EFAULT;
758 goto done;
759 }
760 if (!param.action) { /* GET */
761 tlv_data_len = ((t_u16 *)(cfg11d->param.domain_tlv))[1];
762 if (copy_to_user
763 (req->ifr_data + sizeof(param), &cfg11d->param.domain_tlv,
764 TLV_HEADER_LEN + tlv_data_len)) {
765 PRINTM(MERROR, "Copy from user failed\n");
766 ret = -EFAULT;
767 goto done;
768 }
769 }
770
771 done:
772 if (status != MLAN_STATUS_PENDING)
773 kfree(ioctl_req);
774 LEAVE();
775 return ret;
776 }
777
778 #if defined(DFS_TESTING_SUPPORT)
779 /**
780 * @brief configure dfs testing settings
781 *
782 * @param dev A pointer to net_device structure
783 * @param req A pointer to ifreq structure
784 * @return 0 --success, otherwise fail
785 */
786 static int
woal_uap_dfs_testing(struct net_device * dev,struct ifreq * req)787 woal_uap_dfs_testing(struct net_device *dev, struct ifreq *req)
788 {
789 moal_private *priv = (moal_private *)netdev_priv(dev);
790 mlan_ioctl_req *ioctl_req = NULL;
791 mlan_ds_11h_cfg *cfg11h = NULL;
792 dfs_testing_para param;
793 int ret = 0;
794 mlan_status status = MLAN_STATUS_SUCCESS;
795
796 ENTER();
797 memset(¶m, 0, sizeof(param));
798
799 /* Sanity check */
800 if (req->ifr_data == NULL) {
801 PRINTM(MERROR, "woal_uap_dfs_testing() corrupt data\n");
802 ret = -EFAULT;
803 goto done;
804 }
805
806 /* Copy from user */
807 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
808 PRINTM(MERROR, "Copy from user failed\n");
809 ret = -EFAULT;
810 goto done;
811 }
812 DBG_HEXDUMP(MCMD_D, "dfs_testing_para", (t_u8 *)¶m, sizeof(param));
813
814 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
815 if (ioctl_req == NULL) {
816 LEAVE();
817 return -ENOMEM;
818 }
819 cfg11h = (mlan_ds_11h_cfg *)ioctl_req->pbuf;
820 ioctl_req->req_id = MLAN_IOCTL_11H_CFG;
821 cfg11h->sub_command = MLAN_OID_11H_DFS_TESTING;
822
823 if (!param.action) {
824 /* Get mib value from MLAN */
825 ioctl_req->action = MLAN_ACT_GET;
826 } else {
827 /* Set mib value to MLAN */
828 ioctl_req->action = MLAN_ACT_SET;
829 cfg11h->param.dfs_testing.usr_cac_period_msec =
830 param.usr_cac_period;
831 cfg11h->param.dfs_testing.usr_nop_period_sec =
832 param.usr_nop_period;
833 cfg11h->param.dfs_testing.usr_no_chan_change =
834 param.no_chan_change;
835 cfg11h->param.dfs_testing.usr_fixed_new_chan =
836 param.fixed_new_chan;
837 priv->phandle->cac_period_jiffies =
838 param.usr_cac_period * HZ / 1000;
839 priv->user_cac_period_msec =
840 cfg11h->param.dfs_testing.usr_cac_period_msec;
841 }
842 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
843 if (status != MLAN_STATUS_SUCCESS) {
844 ret = -EFAULT;
845 goto done;
846 }
847
848 if (!param.action) { /* GET */
849 param.usr_cac_period =
850 cfg11h->param.dfs_testing.usr_cac_period_msec;
851 param.usr_nop_period =
852 cfg11h->param.dfs_testing.usr_nop_period_sec;
853 param.no_chan_change =
854 cfg11h->param.dfs_testing.usr_no_chan_change;
855 param.fixed_new_chan =
856 cfg11h->param.dfs_testing.usr_fixed_new_chan;
857 }
858 /* Copy to user */
859 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
860 PRINTM(MERROR, "Copy to user failed!\n");
861 ret = -EFAULT;
862 goto done;
863 }
864
865 done:
866 if (status != MLAN_STATUS_PENDING)
867 kfree(ioctl_req);
868 LEAVE();
869 return ret;
870 }
871
872 #ifdef UAP_CFG80211
873 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
874 /**
875 * @brief uap channel NOP status check ioctl handler
876 *
877 * @param priv A pointer to moal_private structure
878 * @param wait_option Wait option
879 * @param data BSS control type
880 * @return 0 --success, otherwise fail
881 */
882 int
woal_uap_get_channel_nop_info(moal_private * priv,t_u8 wait_option,mlan_ds_11h_chan_nop_info * ch_info)883 woal_uap_get_channel_nop_info(moal_private *priv, t_u8 wait_option,
884 mlan_ds_11h_chan_nop_info * ch_info)
885 {
886 mlan_ioctl_req *req = NULL;
887 mlan_ds_11h_cfg *ds_11hcfg = NULL;
888
889 int ret = 0;
890 mlan_status status = MLAN_STATUS_SUCCESS;
891
892 ENTER();
893
894 if (!ch_info) {
895 PRINTM(MERROR, "Invalid chan_info\n");
896 LEAVE();
897 return -EFAULT;
898 }
899 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
900 if (req == NULL) {
901 ret = -ENOMEM;
902 goto done;
903 }
904
905 req->req_id = MLAN_IOCTL_11H_CFG;
906 req->action = MLAN_ACT_GET;
907
908 ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
909 ds_11hcfg->sub_command = MLAN_OID_11H_CHAN_NOP_INFO;
910 memcpy(&ds_11hcfg->param.ch_nop_info, ch_info,
911 sizeof(mlan_ds_11h_chan_nop_info));
912 status = woal_request_ioctl(priv, req, wait_option);
913 if (status == MLAN_STATUS_FAILURE) {
914 ret = -EFAULT;
915 goto done;
916 }
917 memcpy(ch_info, &ds_11hcfg->param.ch_nop_info,
918 sizeof(mlan_ds_11h_chan_nop_info));
919
920 done:
921 if (status != MLAN_STATUS_PENDING)
922 kfree(req);
923 LEAVE();
924 return ret;
925 }
926 #endif
927 #endif
928 #endif
929
930 /**
931 * @brief configure channel switch count
932 *
933 * @param dev A pointer to net_device structure
934 * @param req A pointer to ifreq structure
935 * @return 0 --success, otherwise fail
936 */
937 static int
woal_uap_chan_switch_count_cfg(struct net_device * dev,struct ifreq * req)938 woal_uap_chan_switch_count_cfg(struct net_device *dev, struct ifreq *req)
939 {
940 moal_private *priv = (moal_private *)netdev_priv(dev);
941 mlan_ioctl_req *ioctl_req = NULL;
942 mlan_ds_11h_cfg *cfg11h = NULL;
943 cscount_cfg_t param;
944 int ret = 0;
945 mlan_status status = MLAN_STATUS_SUCCESS;
946
947 ENTER();
948 memset(¶m, 0, sizeof(param));
949
950 /* Sanity check */
951 if (req->ifr_data == NULL) {
952 PRINTM(MERROR, "%s corrupt data\n", __func__);
953 ret = -EFAULT;
954 goto done;
955 }
956
957 /* Copy from user */
958 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
959 PRINTM(MERROR, "Copy from user failed\n");
960 ret = -EFAULT;
961 goto done;
962 }
963 DBG_HEXDUMP(MCMD_D, "cscount_cfg_t", (t_u8 *)¶m, sizeof(param));
964
965 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
966 if (ioctl_req == NULL) {
967 LEAVE();
968 return -ENOMEM;
969 }
970 cfg11h = (mlan_ds_11h_cfg *)ioctl_req->pbuf;
971 ioctl_req->req_id = MLAN_IOCTL_11H_CFG;
972 cfg11h->sub_command = MLAN_OID_11H_CHAN_SWITCH_COUNT;
973
974 if (!param.action) {
975 /* Get mib value from MLAN */
976 ioctl_req->action = MLAN_ACT_GET;
977 } else {
978 /* Set mib value to MLAN */
979 ioctl_req->action = MLAN_ACT_SET;
980 cfg11h->param.cs_count = param.cs_count;
981 }
982 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
983 if (status != MLAN_STATUS_SUCCESS) {
984 ret = -EFAULT;
985 goto done;
986 }
987
988 if (!param.action) { /* GET */
989 param.cs_count = cfg11h->param.cs_count;
990 }
991 /* Copy to user */
992 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
993 PRINTM(MERROR, "Copy to user failed!\n");
994 ret = -EFAULT;
995 goto done;
996 }
997
998 done:
999 if (status != MLAN_STATUS_PENDING)
1000 kfree(ioctl_req);
1001 LEAVE();
1002 return ret;
1003 }
1004
1005 /**
1006 * @brief Configure TX beamforming support
1007 *
1008 * @param dev A pointer to net_device structure
1009 * @param req A pointer to ifreq structure
1010 * @return 0 --success, otherwise fail
1011 */
1012 static int
woal_uap_tx_bf_cfg(struct net_device * dev,struct ifreq * req)1013 woal_uap_tx_bf_cfg(struct net_device *dev, struct ifreq *req)
1014 {
1015 int ret = 0;
1016 moal_private *priv = (moal_private *)netdev_priv(dev);
1017 mlan_ds_11n_tx_bf_cfg bf_cfg;
1018 tx_bf_cfg_para_hdr param;
1019 t_u16 action = 0;
1020
1021 ENTER();
1022
1023 memset(¶m, 0, sizeof(param));
1024 memset(&bf_cfg, 0, sizeof(bf_cfg));
1025
1026 /* Sanity check */
1027 if (req->ifr_data == NULL) {
1028 PRINTM(MERROR, "woal_uap_tx_bf_cfg corrupt data\n");
1029 ret = -EFAULT;
1030 goto done;
1031 }
1032 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
1033 PRINTM(MERROR, "Copy from user failed\n");
1034 ret = -EFAULT;
1035 goto done;
1036 }
1037 if (!param.action)
1038 /* Get BF configurations */
1039 action = MLAN_ACT_GET;
1040 else
1041 /* Set BF configurations */
1042 action = MLAN_ACT_SET;
1043 if (copy_from_user(&bf_cfg, req->ifr_data + sizeof(tx_bf_cfg_para_hdr),
1044 sizeof(bf_cfg))) {
1045 PRINTM(MERROR, "Copy from user failed\n");
1046 ret = -EFAULT;
1047 goto done;
1048 }
1049 DBG_HEXDUMP(MCMD_D, "bf_cfg", (t_u8 *)&bf_cfg, sizeof(bf_cfg));
1050
1051 if (MLAN_STATUS_SUCCESS !=
1052 woal_set_get_tx_bf_cfg(priv, action, &bf_cfg)) {
1053 ret = -EFAULT;
1054 goto done;
1055 }
1056
1057 /* Copy to user */
1058 if (copy_to_user(req->ifr_data + sizeof(tx_bf_cfg_para_hdr),
1059 &bf_cfg, sizeof(bf_cfg))) {
1060 PRINTM(MERROR, "Copy to user failed!\n");
1061 ret = -EFAULT;
1062 goto done;
1063 }
1064
1065 done:
1066 LEAVE();
1067 return ret;
1068 }
1069
1070 /**
1071 * @brief Set/Get 11n configurations
1072 *
1073 * @param dev A pointer to net_device structure
1074 * @param req A pointer to ifreq structure
1075 * @return 0 --success, otherwise fail
1076 */
1077 static int
woal_uap_ht_tx_cfg(struct net_device * dev,struct ifreq * req)1078 woal_uap_ht_tx_cfg(struct net_device *dev, struct ifreq *req)
1079 {
1080 int ret = 0;
1081 moal_private *priv = (moal_private *)netdev_priv(dev);
1082 mlan_ds_11n_cfg *cfg_11n = NULL;
1083 mlan_ds_11n_tx_cfg httx_cfg;
1084 mlan_ioctl_req *ioctl_req = NULL;
1085 ht_tx_cfg_para_hdr param;
1086 mlan_status status = MLAN_STATUS_SUCCESS;
1087
1088 ENTER();
1089
1090 memset(¶m, 0, sizeof(ht_tx_cfg_para_hdr));
1091 memset(&httx_cfg, 0, sizeof(mlan_ds_11n_tx_cfg));
1092
1093 /* Sanity check */
1094 if (req->ifr_data == NULL) {
1095 PRINTM(MERROR, "woal_uap_ht_tx_cfg corrupt data\n");
1096 ret = -EFAULT;
1097 goto done;
1098 }
1099 if (copy_from_user(¶m, req->ifr_data, sizeof(ht_tx_cfg_para_hdr))) {
1100 PRINTM(MERROR, "Copy from user failed\n");
1101 ret = -EFAULT;
1102 goto done;
1103 }
1104 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
1105 if (ioctl_req == NULL) {
1106 ret = -ENOMEM;
1107 goto done;
1108 }
1109 cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
1110 cfg_11n->sub_command = MLAN_OID_11N_CFG_TX;
1111 ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
1112 if (copy_from_user
1113 (&httx_cfg, req->ifr_data + sizeof(ht_tx_cfg_para_hdr),
1114 sizeof(mlan_ds_11n_tx_cfg))) {
1115 PRINTM(MERROR, "Copy from user failed\n");
1116 ret = -EFAULT;
1117 goto done;
1118 }
1119 if (!param.action) {
1120 /* Get 11n tx parameters from MLAN */
1121 ioctl_req->action = MLAN_ACT_GET;
1122 cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_BG;
1123 } else {
1124 /* Set HT Tx configurations */
1125 cfg_11n->param.tx_cfg.httxcap = httx_cfg.httxcap;
1126 PRINTM(MINFO, "SET: httxcap:0x%x\n", httx_cfg.httxcap);
1127 cfg_11n->param.tx_cfg.misc_cfg = httx_cfg.misc_cfg;
1128 PRINTM(MINFO, "SET: httxcap band:0x%x\n", httx_cfg.misc_cfg);
1129 /* Update 11n tx parameters in MLAN */
1130 ioctl_req->action = MLAN_ACT_SET;
1131 }
1132 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1133 if (status != MLAN_STATUS_SUCCESS) {
1134 ret = -EFAULT;
1135 goto done;
1136 }
1137 if (ioctl_req->action == MLAN_ACT_GET) {
1138 httx_cfg.httxcap = cfg_11n->param.tx_cfg.httxcap;
1139 PRINTM(MINFO, "GET: httxcap:0x%x\n", httx_cfg.httxcap);
1140 cfg_11n->param.tx_cfg.httxcap = 0;
1141 cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_A;
1142 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1143 if (status != MLAN_STATUS_SUCCESS) {
1144 ret = -EFAULT;
1145 goto done;
1146 }
1147 httx_cfg.misc_cfg = cfg_11n->param.tx_cfg.httxcap;
1148 PRINTM(MINFO, "GET: httxcap for 5GHz:0x%x\n",
1149 httx_cfg.misc_cfg);
1150 }
1151 /* Copy to user */
1152 if (copy_to_user(req->ifr_data + sizeof(ht_tx_cfg_para_hdr),
1153 &httx_cfg, sizeof(mlan_ds_11n_tx_cfg))) {
1154 PRINTM(MERROR, "Copy to user failed!\n");
1155 ret = -EFAULT;
1156 goto done;
1157 }
1158 done:
1159 if (status != MLAN_STATUS_PENDING)
1160 kfree(ioctl_req);
1161 LEAVE();
1162 return ret;
1163 }
1164
1165 /**
1166 * @brief uap hs_cfg ioctl handler
1167 *
1168 * @param dev A pointer to net_device structure
1169 * @param req A pointer to ifreq structure
1170 * @invoke_hostcmd Argument
1171 *
1172 * @return 0 --success, otherwise fail
1173 */
1174 static int
woal_uap_hs_cfg(struct net_device * dev,struct ifreq * req,BOOLEAN invoke_hostcmd)1175 woal_uap_hs_cfg(struct net_device *dev, struct ifreq *req,
1176 BOOLEAN invoke_hostcmd)
1177 {
1178 moal_private *priv = (moal_private *)netdev_priv(dev);
1179 mlan_ds_hs_cfg hscfg;
1180 ds_hs_cfg hs_cfg;
1181 mlan_bss_info bss_info;
1182 t_u16 action;
1183 int ret = 0;
1184
1185 ENTER();
1186
1187 memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg));
1188 memset(&hs_cfg, 0, sizeof(ds_hs_cfg));
1189
1190 /* Sanity check */
1191 if (req->ifr_data == NULL) {
1192 PRINTM(MERROR, "uap_hs_cfg() corrupt data\n");
1193 ret = -EFAULT;
1194 goto done;
1195 }
1196 if (copy_from_user(&hs_cfg, req->ifr_data, sizeof(ds_hs_cfg))) {
1197 PRINTM(MERROR, "Copy from user failed\n");
1198 ret = -EFAULT;
1199 goto done;
1200 }
1201
1202 PRINTM(MIOCTL,
1203 "ioctl hscfg: flags=0x%x condition=0x%x gpio=%d gap=0x%x\n",
1204 hs_cfg.flags, hs_cfg.conditions, (int)hs_cfg.gpio, hs_cfg.gap);
1205
1206 /* HS config is blocked if HS is already activated */
1207 if ((hs_cfg.flags & HS_CFG_FLAG_CONDITION) &&
1208 (hs_cfg.conditions != HOST_SLEEP_CFG_CANCEL ||
1209 invoke_hostcmd == MFALSE)) {
1210 memset(&bss_info, 0, sizeof(bss_info));
1211 woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
1212 if (bss_info.is_hs_configured) {
1213 PRINTM(MERROR, "HS already configured\n");
1214 ret = -EFAULT;
1215 goto done;
1216 }
1217 }
1218
1219 if (hs_cfg.flags & HS_CFG_FLAG_SET) {
1220 action = MLAN_ACT_SET;
1221 if (hs_cfg.flags != HS_CFG_FLAG_ALL) {
1222 woal_set_get_hs_params(priv, MLAN_ACT_GET,
1223 MOAL_IOCTL_WAIT, &hscfg);
1224 }
1225 if (hs_cfg.flags & HS_CFG_FLAG_CONDITION)
1226 hscfg.conditions = hs_cfg.conditions;
1227 if (hs_cfg.flags & HS_CFG_FLAG_GPIO)
1228 hscfg.gpio = hs_cfg.gpio;
1229 if (hs_cfg.flags & HS_CFG_FLAG_GAP)
1230 hscfg.gap = hs_cfg.gap;
1231
1232 if (invoke_hostcmd == MTRUE) {
1233 /* Issue IOCTL to set up parameters */
1234 hscfg.is_invoke_hostcmd = MFALSE;
1235 if (MLAN_STATUS_SUCCESS !=
1236 woal_set_get_hs_params(priv, action,
1237 MOAL_IOCTL_WAIT, &hscfg)) {
1238 ret = -EFAULT;
1239 goto done;
1240 }
1241 }
1242 } else {
1243 action = MLAN_ACT_GET;
1244 }
1245
1246 /* Issue IOCTL to invoke hostcmd */
1247 hscfg.is_invoke_hostcmd = invoke_hostcmd;
1248 if (MLAN_STATUS_SUCCESS !=
1249 woal_set_get_hs_params(priv, action, MOAL_IOCTL_WAIT, &hscfg)) {
1250 ret = -EFAULT;
1251 goto done;
1252 }
1253 if (!(hs_cfg.flags & HS_CFG_FLAG_SET)) {
1254 hs_cfg.flags =
1255 HS_CFG_FLAG_CONDITION | HS_CFG_FLAG_GPIO |
1256 HS_CFG_FLAG_GAP;
1257 hs_cfg.conditions = hscfg.conditions;
1258 hs_cfg.gpio = hscfg.gpio;
1259 hs_cfg.gap = hscfg.gap;
1260 /* Copy to user */
1261 if (copy_to_user(req->ifr_data, &hs_cfg, sizeof(ds_hs_cfg))) {
1262 PRINTM(MERROR, "Copy to user failed!\n");
1263 ret = -EFAULT;
1264 goto done;
1265 }
1266 }
1267
1268 done:
1269 LEAVE();
1270 return ret;
1271 }
1272
1273 /**
1274 * @brief Set Host Sleep parameters
1275 *
1276 * @param dev A pointer to net_device structure
1277 * @param req A pointer to ifreq structure
1278 *
1279 * @return 0 --success, otherwise fail
1280 */
1281 static int
woal_uap_hs_set_para(struct net_device * dev,struct ifreq * req)1282 woal_uap_hs_set_para(struct net_device *dev, struct ifreq *req)
1283 {
1284 int ret = 0;
1285
1286 ENTER();
1287
1288 if (req->ifr_data != NULL) {
1289 ret = woal_uap_hs_cfg(dev, req, MFALSE);
1290 goto done;
1291 } else {
1292 PRINTM(MERROR, "Invalid data\n");
1293 ret = -EINVAL;
1294 goto done;
1295 }
1296 done:
1297 LEAVE();
1298 return ret;
1299 }
1300
1301 /**
1302 * @brief uap mgmt_frame_control ioctl handler
1303 *
1304 * @param dev A pointer to net_device structure
1305 * @param req A pointer to ifreq structure
1306 * @return 0 --success, otherwise fail
1307 */
1308 static int
woal_uap_mgmt_frame_control(struct net_device * dev,struct ifreq * req)1309 woal_uap_mgmt_frame_control(struct net_device *dev, struct ifreq *req)
1310 {
1311 moal_private *priv = (moal_private *)netdev_priv(dev);
1312 int ret = 0;
1313 t_u16 action = 0;
1314 mgmt_frame_ctrl param;
1315 mlan_uap_bss_param *sys_config = NULL;
1316
1317 ENTER();
1318
1319 /* Sanity check */
1320 if (req->ifr_data == NULL) {
1321 PRINTM(MERROR, "uap_mgmt_frame_ctrl() corrupt data\n");
1322 ret = -EFAULT;
1323 goto done;
1324 }
1325
1326 /* Get user data */
1327 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
1328 PRINTM(MERROR, "Copy from user failed\n");
1329 ret = -EFAULT;
1330 goto done;
1331 }
1332 sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
1333 if (!sys_config) {
1334 PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
1335 ret = -EFAULT;
1336 goto done;
1337 }
1338
1339 if (param.action)
1340 action = MLAN_ACT_SET;
1341 else
1342 action = MLAN_ACT_GET;
1343 if (action == MLAN_ACT_SET) {
1344 /* Initialize the invalid values so that the correct
1345 values below are downloaded to firmware */
1346 woal_set_sys_config_invalid_data(sys_config);
1347 sys_config->mgmt_ie_passthru_mask = param.mask;
1348 }
1349
1350 if (MLAN_STATUS_SUCCESS !=
1351 woal_set_get_sys_config(priv, action, MOAL_IOCTL_WAIT,
1352 sys_config)) {
1353 ret = -EFAULT;
1354 goto done;
1355 }
1356
1357 if (action == MLAN_ACT_GET) {
1358 param.mask = sys_config->mgmt_ie_passthru_mask;
1359 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
1360 PRINTM(MERROR, "Copy to user failed\n");
1361 ret = -EFAULT;
1362 }
1363 }
1364 done:
1365 kfree(sys_config);
1366 LEAVE();
1367 return ret;
1368 }
1369
1370 /**
1371 * @brief Set/Get tx rate
1372 *
1373 * @param dev A pointer to net_device structure
1374 * @param req A pointer to ifreq structure
1375 *
1376 * @return 0 --success, otherwise fail
1377 */
1378 static int
woal_uap_tx_rate_cfg(struct net_device * dev,struct ifreq * req)1379 woal_uap_tx_rate_cfg(struct net_device *dev, struct ifreq *req)
1380 {
1381 moal_private *priv = (moal_private *)netdev_priv(dev);
1382 int ret = 0, i = 0;
1383 mlan_ds_rate *rate = NULL;
1384 mlan_ioctl_req *mreq = NULL;
1385 tx_rate_cfg_t tx_rate_config;
1386 mlan_status status = MLAN_STATUS_SUCCESS;
1387
1388 ENTER();
1389
1390 /* Sanity check */
1391 if (req->ifr_data == NULL) {
1392 PRINTM(MERROR, "uap_tx_rate_cfg() corrupt data\n");
1393 ret = -EFAULT;
1394 goto done;
1395 }
1396
1397 memset(&tx_rate_config, 0, sizeof(tx_rate_cfg_t));
1398 /* Get user data */
1399 if (copy_from_user
1400 (&tx_rate_config, req->ifr_data, sizeof(tx_rate_cfg_t))) {
1401 PRINTM(MERROR, "Copy from user failed\n");
1402 ret = -EFAULT;
1403 goto done;
1404 }
1405
1406 mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
1407 if (mreq == NULL) {
1408 ret = -ENOMEM;
1409 goto done;
1410 }
1411 rate = (mlan_ds_rate *)mreq->pbuf;
1412 rate->param.rate_cfg.rate_type = MLAN_RATE_INDEX;
1413 rate->sub_command = MLAN_OID_RATE_CFG;
1414 mreq->req_id = MLAN_IOCTL_RATE;
1415 if (!(tx_rate_config.action))
1416 mreq->action = MLAN_ACT_GET;
1417 else {
1418 if ((tx_rate_config.user_data_cnt <= 0) ||
1419 (tx_rate_config.user_data_cnt > 3)) {
1420 PRINTM(MERROR, "Invalid user_data_cnt\n");
1421 ret = -EINVAL;
1422 goto done;
1423 }
1424
1425 mreq->action = MLAN_ACT_SET;
1426 if (tx_rate_config.rate_format == AUTO_RATE)
1427 rate->param.rate_cfg.is_rate_auto = 1;
1428 else {
1429 if ((tx_rate_config.rate_format < 0) ||
1430 (tx_rate_config.rate < 0)) {
1431 PRINTM(MERROR,
1432 "Invalid format or rate selection\n");
1433 ret = -EINVAL;
1434 goto done;
1435 }
1436 /* rate_format sanity check */
1437 if ((tx_rate_config.rate_format > MLAN_RATE_FORMAT_HT)
1438 ) {
1439 PRINTM(MERROR, "Invalid format selection\n");
1440 ret = -EINVAL;
1441 goto done;
1442 }
1443 rate->param.rate_cfg.rate_format =
1444 tx_rate_config.rate_format;
1445
1446 /* rate sanity check */
1447 if (tx_rate_config.user_data_cnt >= 2) {
1448 if (((tx_rate_config.rate_format ==
1449 MLAN_RATE_FORMAT_LG) &&
1450 (tx_rate_config.rate >
1451 MLAN_RATE_INDEX_OFDM7))
1452 ||
1453 ((tx_rate_config.rate_format ==
1454 MLAN_RATE_FORMAT_HT) &&
1455 (tx_rate_config.rate != 32) &&
1456 (tx_rate_config.rate > 7)
1457 )
1458 ) {
1459 PRINTM(MERROR,
1460 "Invalid rate selection\n");
1461 ret = -EINVAL;
1462 goto done;
1463 }
1464 rate->param.rate_cfg.rate = tx_rate_config.rate;
1465 }
1466
1467 /* nss sanity check */
1468 }
1469 }
1470
1471 status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
1472 if (status != MLAN_STATUS_SUCCESS) {
1473 ret = -EFAULT;
1474 goto done;
1475 }
1476 if (tx_rate_config.action) {
1477 priv->rate_index = tx_rate_config.action;
1478 } else {
1479 if (rate->param.rate_cfg.is_rate_auto)
1480 tx_rate_config.rate_format = AUTO_RATE;
1481 else {
1482 /* fixed rate */
1483 tx_rate_config.rate_format =
1484 rate->param.rate_cfg.rate_format;
1485 tx_rate_config.rate = rate->param.rate_cfg.rate;
1486 }
1487 for (i = 0; i < MAX_BITMAP_RATES_SIZE; i++) {
1488 tx_rate_config.bitmap_rates[i] =
1489 rate->param.rate_cfg.bitmap_rates[i];
1490 }
1491
1492 if (copy_to_user
1493 (req->ifr_data, &tx_rate_config, sizeof(tx_rate_cfg_t))) {
1494 PRINTM(MERROR, "Copy to user failed\n");
1495 ret = -EFAULT;
1496 }
1497 }
1498 done:
1499 if (status != MLAN_STATUS_PENDING)
1500 kfree(mreq);
1501 LEAVE();
1502 return ret;
1503 }
1504
1505 /**
1506 * @brief Get DFS_REPEATER mode
1507 *
1508 * @param dev A pointer to net_device structure
1509 * @param req A pointer to ifreq structure
1510 *
1511 * @return 0 --success, otherwise fail
1512 */
1513 static int
woal_uap_dfs_repeater(struct net_device * dev,struct ifreq * req)1514 woal_uap_dfs_repeater(struct net_device *dev, struct ifreq *req)
1515 {
1516 moal_private *priv = (moal_private *)netdev_priv(dev);
1517 int ret = 0;
1518 dfs_repeater_mode param;
1519 mlan_ds_misc_cfg *misc = NULL;
1520 mlan_ioctl_req *mreq = NULL;
1521 mlan_status status = MLAN_STATUS_SUCCESS;
1522
1523 ENTER();
1524
1525 /* Sanity check */
1526 if (req->ifr_data == NULL) {
1527 PRINTM(MERROR, "uap_antenna_cfg() corrupt data\n");
1528 ret = -EFAULT;
1529 goto done;
1530 }
1531
1532 memset(¶m, 0, sizeof(dfs_repeater_mode));
1533 /* Get user data */
1534 if (copy_from_user(¶m, req->ifr_data, sizeof(dfs_repeater_mode))) {
1535 PRINTM(MERROR, "Copy from user failed\n");
1536 ret = -EFAULT;
1537 goto done;
1538 }
1539 mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1540 if (mreq == NULL) {
1541 ret = -ENOMEM;
1542 goto done;
1543 }
1544 misc = (mlan_ds_misc_cfg *)mreq->pbuf;
1545 misc->sub_command = MLAN_OID_MISC_DFS_REAPTER_MODE;
1546 mreq->req_id = MLAN_IOCTL_MISC_CFG;
1547 mreq->action = MLAN_ACT_GET;
1548
1549 status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
1550 if (status != MLAN_STATUS_SUCCESS) {
1551 ret = -EFAULT;
1552 goto done;
1553 }
1554 param.mode = misc->param.dfs_repeater.mode;
1555
1556 if (copy_to_user(req->ifr_data, ¶m, sizeof(dfs_repeater_mode))) {
1557 PRINTM(MERROR, "Copy to user failed\n");
1558 ret = -EFAULT;
1559 }
1560 done:
1561 if (status != MLAN_STATUS_PENDING)
1562 kfree(mreq);
1563 LEAVE();
1564 return ret;
1565 }
1566
1567 /**
1568 * @brief Set/Get skip CAC mode
1569 *
1570 * @param dev A pointer to net_device structure
1571 * @param req A pointer to ifreq structure
1572 *
1573 * @return 0 --success, otherwise fail
1574 */
1575 static int
woal_uap_skip_cac(struct net_device * dev,struct ifreq * req)1576 woal_uap_skip_cac(struct net_device *dev, struct ifreq *req)
1577 {
1578 moal_private *priv = (moal_private *)netdev_priv(dev);
1579 int ret = 0;
1580 skip_cac_para param;
1581
1582 ENTER();
1583
1584 /* Sanity check */
1585 if (req->ifr_data == NULL) {
1586 PRINTM(MERROR, "skip_cac() corrupt data\n");
1587 ret = -EFAULT;
1588 goto done;
1589 }
1590
1591 memset(¶m, 0, sizeof(skip_cac_para));
1592
1593 /* Get user data */
1594 if (copy_from_user(¶m, req->ifr_data, sizeof(skip_cac_para))) {
1595 PRINTM(MERROR, "Copy from user failed\n");
1596 ret = -EFAULT;
1597 goto done;
1598 }
1599
1600 /* Currently default action is get */
1601 if (param.action == 0) {
1602 param.skip_cac = (t_u16)priv->skip_cac;
1603 } else {
1604 priv->skip_cac = param.skip_cac;
1605 }
1606
1607 if (copy_to_user(req->ifr_data, ¶m, sizeof(skip_cac_para))) {
1608 PRINTM(MERROR, "Copy to user failed\n");
1609 ret = -EFAULT;
1610 }
1611 done:
1612
1613 LEAVE();
1614 return ret;
1615 }
1616
1617 /**
1618 * @brief Get DFS_REPEATER mode
1619 *
1620 * @param dev A pointer to net_device structure
1621 * @param req A pointer to ifreq structure
1622 *
1623 * @return 0 --success, otherwise fail
1624 */
1625 static int
woal_uap_cac_timer_status(struct net_device * dev,struct ifreq * req)1626 woal_uap_cac_timer_status(struct net_device *dev, struct ifreq *req)
1627 {
1628 moal_private *priv = (moal_private *)netdev_priv(dev);
1629 int ret = 0;
1630 cac_timer_status param;
1631 mlan_status status = MLAN_STATUS_SUCCESS;
1632
1633 ENTER();
1634
1635 /* Sanity check */
1636 if (req->ifr_data == NULL) {
1637 PRINTM(MERROR, "uap_antenna_cfg() corrupt data\n");
1638 ret = -EFAULT;
1639 goto done;
1640 }
1641
1642 memset(¶m, 0, sizeof(cac_timer_status));
1643
1644 /* Get user data */
1645 if (copy_from_user(¶m, req->ifr_data, sizeof(cac_timer_status))) {
1646 PRINTM(MERROR, "Copy from user failed\n");
1647 ret = -EFAULT;
1648 goto done;
1649 }
1650
1651 /* Currently default action is get */
1652 param.mode = 0;
1653
1654 if (priv->phandle->cac_period == MTRUE) {
1655 long cac_left_jiffies;
1656
1657 cac_left_jiffies = MEAS_REPORT_TIME -
1658 (jiffies - priv->phandle->meas_start_jiffies);
1659
1660 /* cac_left_jiffies would be negative if timer has already elapsed.
1661 * positive if timer is still yet to lapsed
1662 */
1663 if (cac_left_jiffies > 0)
1664 param.mode = (t_u32)cac_left_jiffies / HZ;
1665 }
1666
1667 if (copy_to_user(req->ifr_data, ¶m, sizeof(cac_timer_status))) {
1668 PRINTM(MERROR, "Copy to user failed\n");
1669 ret = -EFAULT;
1670 }
1671 done:
1672 if (status != MLAN_STATUS_PENDING)
1673 LEAVE();
1674 return ret;
1675 }
1676
1677 /**
1678 * @brief set/get uap operation control
1679 *
1680 * @param dev A pointer to net_device structure
1681 * @param req A pointer to ifreq structure
1682 *
1683 * @return 0 --success, otherwise fail
1684 */
1685 static int
woal_uap_operation_ctrl(struct net_device * dev,struct ifreq * req)1686 woal_uap_operation_ctrl(struct net_device *dev, struct ifreq *req)
1687 {
1688 int ret = 0;
1689 moal_private *priv = (moal_private *)netdev_priv(dev);
1690 mlan_uap_oper_ctrl uap_oper;
1691 uap_oper_para_hdr param;
1692 mlan_ds_bss *bss = NULL;
1693 mlan_ioctl_req *ioctl_req = NULL;
1694 mlan_status status = MLAN_STATUS_SUCCESS;
1695
1696 ENTER();
1697
1698 memset(¶m, 0, sizeof(uap_oper_para_hdr));
1699 memset(&uap_oper, 0, sizeof(mlan_uap_oper_ctrl));
1700
1701 /* Sanity check */
1702 if (req->ifr_data == NULL) {
1703 PRINTM(MERROR, "woal_uap_operation_ctrl corrupt data\n");
1704 ret = -EFAULT;
1705 goto done;
1706 }
1707 if (copy_from_user(¶m, req->ifr_data, sizeof(uap_oper_para_hdr))) {
1708 PRINTM(MERROR, "Copy from user failed\n");
1709 ret = -EFAULT;
1710 goto done;
1711 }
1712 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
1713 if (ioctl_req == NULL) {
1714 ret = MLAN_STATUS_FAILURE;
1715 goto done;
1716 }
1717
1718 bss = (mlan_ds_bss *)ioctl_req->pbuf;
1719 bss->sub_command = MLAN_OID_UAP_OPER_CTRL;
1720 ioctl_req->req_id = MLAN_IOCTL_BSS;
1721 if (copy_from_user(&uap_oper, req->ifr_data + sizeof(uap_oper_para_hdr),
1722 sizeof(mlan_uap_oper_ctrl))) {
1723 PRINTM(MERROR, "Copy from user failed\n");
1724 ret = -EFAULT;
1725 goto done;
1726 }
1727 if (!param.action) {
1728 /* Get uap operation control parameters from FW */
1729 ioctl_req->action = MLAN_ACT_GET;
1730 } else {
1731 /* Set uap operation control configurations */
1732 ioctl_req->action = MLAN_ACT_SET;
1733 bss->param.ap_oper_ctrl.ctrl_value = uap_oper.ctrl_value;
1734 if (uap_oper.ctrl_value == 2)
1735 bss->param.ap_oper_ctrl.chan_opt = uap_oper.chan_opt;
1736 if (uap_oper.chan_opt == 3) {
1737 bss->param.ap_oper_ctrl.band_cfg = uap_oper.band_cfg;
1738 bss->param.ap_oper_ctrl.channel = uap_oper.channel;
1739 }
1740
1741 }
1742 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1743 if (status != MLAN_STATUS_SUCCESS) {
1744 ret = -EFAULT;
1745 goto done;
1746 }
1747
1748 /* Copy to user */
1749 if (copy_to_user(req->ifr_data + sizeof(uap_oper_para_hdr),
1750 &bss->param.ap_oper_ctrl,
1751 sizeof(mlan_uap_oper_ctrl))) {
1752 PRINTM(MERROR, "Copy to user failed!\n");
1753 ret = -EFAULT;
1754 goto done;
1755 }
1756 done:
1757 if (status != MLAN_STATUS_PENDING)
1758 kfree(ioctl_req);
1759 LEAVE();
1760 return ret;
1761 }
1762
1763 /**
1764 * @brief uap ioctl handler
1765 *
1766 * @param dev A pointer to net_device structure
1767 * @param req A pointer to ifreq structure
1768 * @return 0 --success, otherwise fail
1769 */
1770 static int
woal_uap_ioctl(struct net_device * dev,struct ifreq * req)1771 woal_uap_ioctl(struct net_device *dev, struct ifreq *req)
1772 {
1773 int ret = 0;
1774 t_u32 subcmd = 0;
1775 ENTER();
1776 /* Sanity check */
1777 if (req->ifr_data == NULL) {
1778 PRINTM(MERROR, "uap_ioctl() corrupt data\n");
1779 ret = -EFAULT;
1780 goto done;
1781 }
1782 if (copy_from_user(&subcmd, req->ifr_data, sizeof(subcmd))) {
1783 PRINTM(MERROR, "Copy from user failed\n");
1784 ret = -EFAULT;
1785 goto done;
1786 }
1787
1788 PRINTM(MIOCTL, "ioctl subcmd=%d\n", (int)subcmd);
1789 switch (subcmd) {
1790 case UAP_ADDBA_PARA:
1791 ret = woal_uap_addba_param(dev, req);
1792 break;
1793 case UAP_AGGR_PRIOTBL:
1794 ret = woal_uap_aggr_priotbl(dev, req);
1795 break;
1796 case UAP_ADDBA_REJECT:
1797 ret = woal_uap_addba_reject(dev, req);
1798 break;
1799 case UAP_FW_INFO:
1800 ret = woal_uap_get_fw_info(dev, req);
1801 break;
1802 case UAP_DEEP_SLEEP:
1803 ret = woal_uap_deep_sleep(dev, req);
1804 break;
1805 case UAP_TX_DATA_PAUSE:
1806 ret = woal_uap_txdatapause(dev, req);
1807 break;
1808 case UAP_SDCMD52_RW:
1809 ret = woal_uap_sdcmd52_rw(dev, req);
1810 break;
1811 case UAP_SNMP_MIB:
1812 ret = woal_uap_snmp_mib(dev, req);
1813 break;
1814 #ifdef DFS_TESTING_SUPPORT
1815 case UAP_DFS_TESTING:
1816 ret = woal_uap_dfs_testing(dev, req);
1817 break;
1818 #endif
1819 case UAP_CHAN_SWITCH_COUNT_CFG:
1820 ret = woal_uap_chan_switch_count_cfg(dev, req);
1821 break;
1822 case UAP_DOMAIN_INFO:
1823 ret = woal_uap_domain_info(dev, req);
1824 break;
1825 case UAP_TX_BF_CFG:
1826 ret = woal_uap_tx_bf_cfg(dev, req);
1827 break;
1828 case UAP_HT_TX_CFG:
1829 ret = woal_uap_ht_tx_cfg(dev, req);
1830 break;
1831 case UAP_HS_CFG:
1832 ret = woal_uap_hs_cfg(dev, req, MTRUE);
1833 break;
1834 case UAP_HS_SET_PARA:
1835 ret = woal_uap_hs_set_para(dev, req);
1836 break;
1837 case UAP_MGMT_FRAME_CONTROL:
1838 ret = woal_uap_mgmt_frame_control(dev, req);
1839 break;
1840 case UAP_TX_RATE_CFG:
1841 ret = woal_uap_tx_rate_cfg(dev, req);
1842 break;
1843 case UAP_DFS_REPEATER_MODE:
1844 ret = woal_uap_dfs_repeater(dev, req);
1845 break;
1846 case UAP_CAC_TIMER_STATUS:
1847 ret = woal_uap_cac_timer_status(dev, req);
1848 break;
1849 case UAP_SKIP_CAC:
1850 ret = woal_uap_skip_cac(dev, req);
1851 break;
1852 case UAP_OPERATION_CTRL:
1853 ret = woal_uap_operation_ctrl(dev, req);
1854 break;
1855 default:
1856 break;
1857 }
1858 done:
1859 LEAVE();
1860 return ret;
1861 }
1862
1863 /**
1864 * @brief uap station deauth ioctl handler
1865 *
1866 * @param dev A pointer to net_device structure
1867 * @param req A pointer to ifreq structure
1868 * @return 0 --success, otherwise fail
1869 */
1870 static int
woal_uap_sta_deauth_ioctl(struct net_device * dev,struct ifreq * req)1871 woal_uap_sta_deauth_ioctl(struct net_device *dev, struct ifreq *req)
1872 {
1873 moal_private *priv = (moal_private *)netdev_priv(dev);
1874 mlan_ioctl_req *ioctl_req = NULL;
1875 mlan_ds_bss *bss = NULL;
1876 mlan_deauth_param deauth_param;
1877 int ret = 0;
1878 mlan_status status = MLAN_STATUS_SUCCESS;
1879
1880 ENTER();
1881
1882 memset(&deauth_param, 0, sizeof(mlan_deauth_param));
1883 /* Sanity check */
1884 if (req->ifr_data == NULL) {
1885 PRINTM(MERROR, "uap_sta_deauth_ioctl() corrupt data\n");
1886 ret = -EFAULT;
1887 goto done;
1888 }
1889 if (copy_from_user
1890 (&deauth_param, req->ifr_data, sizeof(mlan_deauth_param))) {
1891 PRINTM(MERROR, "Copy from user failed\n");
1892 ret = -EFAULT;
1893 goto done;
1894 }
1895
1896 PRINTM(MIOCTL, "ioctl deauth station: " MACSTR ", reason=%d\n",
1897 MAC2STR(deauth_param.mac_addr), deauth_param.reason_code);
1898
1899 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
1900 if (ioctl_req == NULL) {
1901 ret = -ENOMEM;
1902 goto done;
1903 }
1904 bss = (mlan_ds_bss *)ioctl_req->pbuf;
1905
1906 bss->sub_command = MLAN_OID_UAP_DEAUTH_STA;
1907 ioctl_req->req_id = MLAN_IOCTL_BSS;
1908 ioctl_req->action = MLAN_ACT_SET;
1909
1910 memcpy(&bss->param.deauth_param, &deauth_param,
1911 sizeof(mlan_deauth_param));
1912 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1913 if (status != MLAN_STATUS_SUCCESS) {
1914 ret = -EFAULT;
1915 if (copy_to_user
1916 (req->ifr_data, &ioctl_req->status_code, sizeof(t_u32)))
1917 PRINTM(MERROR, "Copy to user failed!\n");
1918 goto done;
1919 }
1920
1921 done:
1922 if (status != MLAN_STATUS_PENDING)
1923 kfree(ioctl_req);
1924 LEAVE();
1925 return ret;
1926 }
1927
1928 /**
1929 * @brief Set/Get radio
1930 *
1931 * @param dev A pointer to net_device structure
1932 * @param req A pointer to ifreq structure
1933 *
1934 * @return 0 --success, otherwise fail
1935 */
1936 static int
woal_uap_radio_ctl(struct net_device * dev,struct ifreq * req)1937 woal_uap_radio_ctl(struct net_device *dev, struct ifreq *req)
1938 {
1939 moal_private *priv = (moal_private *)netdev_priv(dev);
1940 int ret = 0;
1941 mlan_ds_radio_cfg *radio = NULL;
1942 mlan_ioctl_req *mreq = NULL;
1943 int data[2] = { 0, 0 };
1944 mlan_bss_info bss_info;
1945 mlan_status status = MLAN_STATUS_SUCCESS;
1946
1947 ENTER();
1948
1949 /* Sanity check */
1950 if (req->ifr_data == NULL) {
1951 PRINTM(MERROR, "uap_radio_ctl() corrupt data\n");
1952 ret = -EFAULT;
1953 goto done;
1954 }
1955
1956 /* Get user data */
1957 if (copy_from_user(&data, req->ifr_data, sizeof(data))) {
1958 PRINTM(MERROR, "Copy from user failed\n");
1959 ret = -EFAULT;
1960 goto done;
1961 }
1962
1963 if (data[0]) {
1964 mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
1965 if (mreq == NULL) {
1966 ret = -ENOMEM;
1967 goto done;
1968 }
1969 radio = (mlan_ds_radio_cfg *)mreq->pbuf;
1970 radio->sub_command = MLAN_OID_RADIO_CTRL;
1971 mreq->req_id = MLAN_IOCTL_RADIO_CFG;
1972 mreq->action = MLAN_ACT_SET;
1973 radio->param.radio_on_off = (t_u32)data[1];
1974 status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
1975 if (status != MLAN_STATUS_SUCCESS)
1976 ret = -EFAULT;
1977 if (status != MLAN_STATUS_PENDING)
1978 kfree(mreq);
1979 } else {
1980 /* Get radio status */
1981 memset(&bss_info, 0, sizeof(bss_info));
1982 woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
1983
1984 data[1] = bss_info.radio_on;
1985 if (copy_to_user(req->ifr_data, data, sizeof(data))) {
1986 PRINTM(MERROR, "Copy to user failed\n");
1987 ret = -EFAULT;
1988 }
1989 }
1990 done:
1991 LEAVE();
1992 return ret;
1993 }
1994
1995 /**
1996 * @brief uap bss control ioctl handler
1997 *
1998 * @param dev A pointer to net_device structure
1999 * @param req A pointer to ifreq structure
2000 * @return 0 --success, otherwise fail
2001 */
2002 static int
woal_uap_bss_ctrl_ioctl(struct net_device * dev,struct ifreq * req)2003 woal_uap_bss_ctrl_ioctl(struct net_device *dev, struct ifreq *req)
2004 {
2005 moal_private *priv = (moal_private *)netdev_priv(dev);
2006 int ret = 0, data = 0;
2007
2008 ENTER();
2009
2010 /* Sanity check */
2011 if (req->ifr_data == NULL) {
2012 PRINTM(MERROR, "uap_bss_ctrl() corrupt data\n");
2013 ret = -EFAULT;
2014 goto done;
2015 }
2016 if (copy_from_user(&data, req->ifr_data, sizeof(data))) {
2017 PRINTM(MERROR, "Copy from user failed\n");
2018 ret = -EFAULT;
2019 goto done;
2020 }
2021
2022 ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, data);
2023
2024 done:
2025 LEAVE();
2026 return ret;
2027 }
2028
2029 /**
2030 * @brief Set/Get uap power mode
2031 *
2032 * @param priv A pointer to moal_private structure
2033 * @param action Action set or get
2034 * @param ps_mgmt A pointer to mlan_ds_ps_mgmt structure
2035 *
2036 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
2037 */
2038 int
woal_set_get_uap_power_mode(moal_private * priv,t_u32 action,mlan_ds_ps_mgmt * ps_mgmt)2039 woal_set_get_uap_power_mode(moal_private *priv, t_u32 action,
2040 mlan_ds_ps_mgmt *ps_mgmt)
2041 {
2042 mlan_ioctl_req *ioctl_req = NULL;
2043 mlan_ds_pm_cfg *pm_cfg = NULL;
2044 mlan_status status = MLAN_STATUS_SUCCESS;
2045
2046 ENTER();
2047 if (!ps_mgmt) {
2048 LEAVE();
2049 return MLAN_STATUS_FAILURE;
2050 }
2051
2052 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
2053 if (ioctl_req == NULL) {
2054 LEAVE();
2055 return MLAN_STATUS_FAILURE;
2056 }
2057 pm_cfg = (mlan_ds_pm_cfg *)ioctl_req->pbuf;
2058 pm_cfg->sub_command = MLAN_OID_PM_CFG_PS_MODE;
2059 ioctl_req->req_id = MLAN_IOCTL_PM_CFG;
2060 ioctl_req->action = action;
2061 if (action == MLAN_ACT_SET)
2062 memcpy(&pm_cfg->param.ps_mgmt, ps_mgmt,
2063 sizeof(mlan_ds_ps_mgmt));
2064 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2065 if (status == MLAN_STATUS_SUCCESS) {
2066 if (action == MLAN_ACT_GET)
2067 memcpy(ps_mgmt, &pm_cfg->param.ps_mgmt,
2068 sizeof(mlan_ds_ps_mgmt));
2069 }
2070 if (status != MLAN_STATUS_PENDING)
2071 kfree(ioctl_req);
2072 LEAVE();
2073 return status;
2074 }
2075
2076 /**
2077 * @brief uap power mode ioctl handler
2078 *
2079 * @param dev A pointer to net_device structure
2080 * @param req A pointer to ifreq structure
2081 * @return 0 --success, otherwise fail
2082 */
2083 static int
woal_uap_power_mode_ioctl(struct net_device * dev,struct ifreq * req)2084 woal_uap_power_mode_ioctl(struct net_device *dev, struct ifreq *req)
2085 {
2086 moal_private *priv = (moal_private *)netdev_priv(dev);
2087 mlan_ioctl_req *ioctl_req = NULL;
2088 mlan_ds_pm_cfg *pm_cfg = NULL;
2089 mlan_ds_ps_mgmt ps_mgmt;
2090 int ret = 0;
2091 mlan_status status = MLAN_STATUS_SUCCESS;
2092
2093 ENTER();
2094
2095 memset(&ps_mgmt, 0, sizeof(mlan_ds_ps_mgmt));
2096
2097 /* Sanity check */
2098 if (req->ifr_data == NULL) {
2099 PRINTM(MERROR, "uap_power_mode_ioctl() corrupt data\n");
2100 ret = -EFAULT;
2101 goto done;
2102 }
2103 if (copy_from_user(&ps_mgmt, req->ifr_data, sizeof(mlan_ds_ps_mgmt))) {
2104 PRINTM(MERROR, "Copy from user failed\n");
2105 ret = -EFAULT;
2106 goto done;
2107 }
2108
2109 PRINTM(MIOCTL,
2110 "ioctl power: flag=0x%x ps_mode=%d ctrl_bitmap=%d min_sleep=%d max_sleep=%d "
2111 "inact_to=%d min_awake=%d max_awake=%d\n", ps_mgmt.flags,
2112 (int)ps_mgmt.ps_mode, (int)ps_mgmt.sleep_param.ctrl_bitmap,
2113 (int)ps_mgmt.sleep_param.min_sleep,
2114 (int)ps_mgmt.sleep_param.max_sleep,
2115 (int)ps_mgmt.inact_param.inactivity_to,
2116 (int)ps_mgmt.inact_param.min_awake,
2117 (int)ps_mgmt.inact_param.max_awake);
2118
2119 if (ps_mgmt.
2120 flags & ~(PS_FLAG_PS_MODE | PS_FLAG_SLEEP_PARAM |
2121 PS_FLAG_INACT_SLEEP_PARAM)) {
2122 PRINTM(MERROR, "Invalid parameter: flags = 0x%x\n",
2123 ps_mgmt.flags);
2124 ret = -EINVAL;
2125 goto done;
2126 }
2127
2128 if (ps_mgmt.ps_mode > PS_MODE_INACTIVITY) {
2129 PRINTM(MERROR, "Invalid parameter: ps_mode = %d\n",
2130 (int)ps_mgmt.flags);
2131 ret = -EINVAL;
2132 goto done;
2133 }
2134
2135 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
2136 if (ioctl_req == NULL) {
2137 ret = -ENOMEM;
2138 goto done;
2139 }
2140 pm_cfg = (mlan_ds_pm_cfg *)ioctl_req->pbuf;
2141 pm_cfg->sub_command = MLAN_OID_PM_CFG_PS_MODE;
2142 ioctl_req->req_id = MLAN_IOCTL_PM_CFG;
2143 if (ps_mgmt.flags) {
2144 ioctl_req->action = MLAN_ACT_SET;
2145 memcpy(&pm_cfg->param.ps_mgmt, &ps_mgmt,
2146 sizeof(mlan_ds_ps_mgmt));
2147 } else {
2148 ioctl_req->action = MLAN_ACT_GET;
2149 }
2150
2151 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2152 if (status != MLAN_STATUS_SUCCESS) {
2153 ret = -EFAULT;
2154 if (copy_to_user
2155 (req->ifr_data, &ioctl_req->status_code, sizeof(t_u32)))
2156 PRINTM(MERROR, "Copy to user failed!\n");
2157 goto done;
2158 }
2159 if (!ps_mgmt.flags) {
2160 /* Copy to user */
2161 if (copy_to_user
2162 (req->ifr_data, &pm_cfg->param.ps_mgmt,
2163 sizeof(mlan_ds_ps_mgmt))) {
2164 PRINTM(MERROR, "Copy to user failed!\n");
2165 ret = -EFAULT;
2166 goto done;
2167 }
2168 }
2169 done:
2170 if (status != MLAN_STATUS_PENDING)
2171 kfree(ioctl_req);
2172 LEAVE();
2173 return ret;
2174 }
2175
2176 /**
2177 * @brief uap BSS config ioctl handler
2178 *
2179 * @param dev A pointer to net_device structure
2180 * @param req A pointer to ifreq structure
2181 * @return 0 --success, otherwise fail
2182 */
2183 static int
woal_uap_bss_cfg_ioctl(struct net_device * dev,struct ifreq * req)2184 woal_uap_bss_cfg_ioctl(struct net_device *dev, struct ifreq *req)
2185 {
2186 moal_private *priv = (moal_private *)netdev_priv(dev);
2187 int ret = 0;
2188 mlan_ds_bss *bss = NULL;
2189 mlan_ioctl_req *ioctl_req = NULL;
2190 int offset = 0;
2191 t_u32 action = 0;
2192 mlan_status status = MLAN_STATUS_SUCCESS;
2193
2194 ENTER();
2195
2196 /* Sanity check */
2197 if (req->ifr_data == NULL) {
2198 PRINTM(MERROR, "uap_bss_cfg_ioctl() corrupt data\n");
2199 ret = -EFAULT;
2200 goto done;
2201 }
2202
2203 /* Get action */
2204 if (copy_from_user(&action, req->ifr_data + offset, sizeof(action))) {
2205 PRINTM(MERROR, "Copy from user failed\n");
2206 ret = -EFAULT;
2207 goto done;
2208 }
2209 offset += sizeof(action);
2210
2211 /* Allocate an IOCTL request buffer */
2212 ioctl_req =
2213 (mlan_ioctl_req *)
2214 woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
2215 if (ioctl_req == NULL) {
2216 ret = -ENOMEM;
2217 goto done;
2218 }
2219
2220 bss = (mlan_ds_bss *)ioctl_req->pbuf;
2221 bss->sub_command = MLAN_OID_UAP_BSS_CONFIG;
2222 ioctl_req->req_id = MLAN_IOCTL_BSS;
2223 if (action == 1)
2224 ioctl_req->action = MLAN_ACT_SET;
2225 else
2226 ioctl_req->action = MLAN_ACT_GET;
2227
2228 if (ioctl_req->action == MLAN_ACT_SET) {
2229 /* Get the BSS config from user */
2230 if (copy_from_user
2231 (&bss->param.bss_config, req->ifr_data + offset,
2232 sizeof(mlan_uap_bss_param))) {
2233 PRINTM(MERROR, "Copy from user failed\n");
2234 ret = -EFAULT;
2235 goto done;
2236 }
2237 }
2238
2239 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2240 if (status != MLAN_STATUS_SUCCESS) {
2241 ret = -EFAULT;
2242 goto done;
2243 }
2244
2245 if (ioctl_req->action == MLAN_ACT_GET) {
2246 offset = sizeof(action);
2247
2248 /* Copy to user : BSS config */
2249 if (copy_to_user
2250 (req->ifr_data + offset, &bss->param.bss_config,
2251 sizeof(mlan_uap_bss_param))) {
2252 PRINTM(MERROR, "Copy to user failed!\n");
2253 ret = -EFAULT;
2254 goto done;
2255 }
2256 }
2257 done:
2258 if (status != MLAN_STATUS_PENDING)
2259 kfree(ioctl_req);
2260 LEAVE();
2261 return ret;
2262 }
2263
2264 /**
2265 * @brief uap get station list handler
2266 *
2267 * @param dev A pointer to net_device structure
2268 * @param req A pointer to ifreq structure
2269 * @return 0 --success, otherwise fail
2270 */
2271 static int
woal_uap_get_sta_list_ioctl(struct net_device * dev,struct ifreq * req)2272 woal_uap_get_sta_list_ioctl(struct net_device *dev, struct ifreq *req)
2273 {
2274 moal_private *priv = (moal_private *)netdev_priv(dev);
2275 int ret = 0;
2276 mlan_ds_get_info *info = NULL;
2277 mlan_ioctl_req *ioctl_req = NULL;
2278 mlan_status status = MLAN_STATUS_SUCCESS;
2279
2280 ENTER();
2281
2282 /* Sanity check */
2283 if (req->ifr_data == NULL) {
2284 PRINTM(MERROR, "uap_get_sta_list_ioctl() corrupt data\n");
2285 ret = -EFAULT;
2286 goto done;
2287 }
2288
2289 /* Allocate an IOCTL request buffer */
2290 ioctl_req =
2291 (mlan_ioctl_req *)
2292 woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
2293 if (ioctl_req == NULL) {
2294 ret = -ENOMEM;
2295 goto done;
2296 }
2297
2298 info = (mlan_ds_get_info *)ioctl_req->pbuf;
2299 info->sub_command = MLAN_OID_UAP_STA_LIST;
2300 ioctl_req->req_id = MLAN_IOCTL_GET_INFO;
2301 ioctl_req->action = MLAN_ACT_GET;
2302
2303 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2304 if (status != MLAN_STATUS_SUCCESS) {
2305 ret = -EFAULT;
2306 goto done;
2307 }
2308
2309 if (ioctl_req->action == MLAN_ACT_GET) {
2310 /* Copy to user : sta_list */
2311 if (copy_to_user
2312 (req->ifr_data, &info->param.sta_list,
2313 sizeof(mlan_ds_sta_list))) {
2314 PRINTM(MERROR, "Copy to user failed!\n");
2315 ret = -EFAULT;
2316 goto done;
2317 }
2318 }
2319 done:
2320 if (status != MLAN_STATUS_PENDING)
2321 kfree(ioctl_req);
2322 LEAVE();
2323 return ret;
2324 }
2325
2326 /**
2327 * @brief uAP set WAPI key ioctl
2328 *
2329 * @param priv A pointer to moal_private structure
2330 * @param msg A pointer to wapi_msg structure
2331 *
2332 * @return 0 --success, otherwise fail
2333 */
2334 static int
woal_uap_set_wapi_key_ioctl(moal_private * priv,wapi_msg * msg)2335 woal_uap_set_wapi_key_ioctl(moal_private *priv, wapi_msg *msg)
2336 {
2337 mlan_ioctl_req *req = NULL;
2338 mlan_ds_sec_cfg *sec = NULL;
2339 int ret = 0;
2340 wapi_key_msg *key_msg = NULL;
2341 t_u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2342 mlan_status status = MLAN_STATUS_SUCCESS;
2343
2344 ENTER();
2345 if (msg->msg_len != sizeof(wapi_key_msg)) {
2346 ret = -EINVAL;
2347 goto done;
2348 }
2349 key_msg = (wapi_key_msg *)msg->msg;
2350
2351 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
2352 if (req == NULL) {
2353 ret = -ENOMEM;
2354 goto done;
2355 }
2356 sec = (mlan_ds_sec_cfg *)req->pbuf;
2357 sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
2358 req->req_id = MLAN_IOCTL_SEC_CFG;
2359 req->action = MLAN_ACT_SET;
2360
2361 sec->param.encrypt_key.is_wapi_key = MTRUE;
2362 sec->param.encrypt_key.key_len = MLAN_MAX_KEY_LENGTH;
2363 memcpy(sec->param.encrypt_key.mac_addr, key_msg->mac_addr, ETH_ALEN);
2364 sec->param.encrypt_key.key_index = key_msg->key_id;
2365 if (0 == memcmp(key_msg->mac_addr, bcast_addr, ETH_ALEN))
2366 sec->param.encrypt_key.key_flags = KEY_FLAG_GROUP_KEY;
2367 else
2368 sec->param.encrypt_key.key_flags = KEY_FLAG_SET_TX_KEY;
2369 memcpy(sec->param.encrypt_key.key_material, key_msg->key,
2370 sec->param.encrypt_key.key_len);
2371
2372 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2373 if (status != MLAN_STATUS_SUCCESS)
2374 ret = -EFAULT;
2375 done:
2376 if (status != MLAN_STATUS_PENDING)
2377 kfree(req);
2378 LEAVE();
2379 return ret;
2380 }
2381
2382 /**
2383 * @brief Enable/Disable wapi in firmware
2384 *
2385 * @param priv A pointer to moal_private structure
2386 * @param enable MTRUE/MFALSE
2387 *
2388 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
2389 */
2390 static mlan_status
woal_enable_wapi(moal_private * priv,t_u8 enable)2391 woal_enable_wapi(moal_private *priv, t_u8 enable)
2392 {
2393 mlan_ioctl_req *req = NULL;
2394 mlan_ds_bss *bss = NULL;
2395 mlan_status status;
2396
2397 ENTER();
2398
2399 /* Allocate an IOCTL request buffer */
2400 req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
2401 if (req == NULL) {
2402 status = MLAN_STATUS_FAILURE;
2403 goto done;
2404 }
2405
2406 /* Fill request buffer */
2407 bss = (mlan_ds_bss *)req->pbuf;
2408 bss->sub_command = MLAN_OID_UAP_BSS_CONFIG;
2409 req->req_id = MLAN_IOCTL_BSS;
2410 req->action = MLAN_ACT_GET;
2411
2412 /* Send IOCTL request to MLAN */
2413 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2414 if (status != MLAN_STATUS_SUCCESS) {
2415 PRINTM(MERROR,
2416 "Get AP setting failed! status=%d, error_code=0x%x\n",
2417 status, req->status_code);
2418 }
2419
2420 /* Change AP default setting */
2421 req->action = MLAN_ACT_SET;
2422 if (enable == MFALSE) {
2423 bss->param.bss_config.auth_mode = MLAN_AUTH_MODE_OPEN;
2424 bss->param.bss_config.protocol = PROTOCOL_NO_SECURITY;
2425 } else {
2426 bss->param.bss_config.auth_mode = MLAN_AUTH_MODE_OPEN;
2427 bss->param.bss_config.protocol = PROTOCOL_WAPI;
2428 }
2429
2430 /* Send IOCTL request to MLAN */
2431 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2432 if (status != MLAN_STATUS_SUCCESS) {
2433 PRINTM(MERROR,
2434 "Set AP setting failed! status=%d, error_code=0x%x\n",
2435 status, req->status_code);
2436 }
2437 if (enable)
2438 woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START);
2439 done:
2440 if (status != MLAN_STATUS_PENDING)
2441 kfree(req);
2442 LEAVE();
2443 return status;
2444 }
2445
2446 /**
2447 * @brief uAP set WAPI flag ioctl
2448 *
2449 * @param priv A pointer to moal_private structure
2450 * @param msg A pointer to wapi_msg structure
2451 *
2452 * @return 0 --success, otherwise fail
2453 */
2454 static int
woal_uap_set_wapi_flag_ioctl(moal_private * priv,wapi_msg * msg)2455 woal_uap_set_wapi_flag_ioctl(moal_private *priv, wapi_msg *msg)
2456 {
2457 t_u8 wapi_psk_ie[] = {
2458 0x44, 0x14, 0x01, 0x00,
2459 0x01, 0x00, 0x00, 0x14,
2460 0x72, 0x02, 0x01, 0x00,
2461 0x00, 0x14, 0x72, 0x01,
2462 0x00, 0x14, 0x72, 0x01,
2463 0x00, 0x00
2464 };
2465 t_u8 wapi_cert_ie[] = {
2466 0x44, 0x14, 0x01, 0x00,
2467 0x01, 0x00, 0x00, 0x14,
2468 0x72, 0x01, 0x01, 0x00,
2469 0x00, 0x14, 0x72, 0x01,
2470 0x00, 0x14, 0x72, 0x01,
2471 0x00, 0x00
2472 };
2473 mlan_ds_misc_cfg *misc = NULL;
2474 mlan_ioctl_req *req = NULL;
2475 int ret = 0;
2476 mlan_status status = MLAN_STATUS_SUCCESS;
2477
2478 ENTER();
2479
2480 woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP);
2481
2482 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2483 if (req == NULL) {
2484 ret = -ENOMEM;
2485 goto done;
2486 }
2487 misc = (mlan_ds_misc_cfg *)req->pbuf;
2488 misc->sub_command = MLAN_OID_MISC_GEN_IE;
2489 req->req_id = MLAN_IOCTL_MISC_CFG;
2490 req->action = MLAN_ACT_SET;
2491
2492 misc->param.gen_ie.type = MLAN_IE_TYPE_GEN_IE;
2493 misc->param.gen_ie.len = sizeof(wapi_psk_ie);
2494 if (msg->msg[0] & WAPI_MODE_PSK) {
2495 memcpy(misc->param.gen_ie.ie_data, wapi_psk_ie,
2496 misc->param.gen_ie.len);
2497 } else if (msg->msg[0] & WAPI_MODE_CERT) {
2498 memcpy(misc->param.gen_ie.ie_data, wapi_cert_ie,
2499 misc->param.gen_ie.len);
2500 } else if (msg->msg[0] == 0) {
2501 /* disable WAPI in driver */
2502 if (MLAN_STATUS_SUCCESS !=
2503 woal_set_wapi_enable(priv, MOAL_IOCTL_WAIT, 0))
2504 ret = -EFAULT;
2505 woal_enable_wapi(priv, MFALSE);
2506 goto done;
2507 } else {
2508 ret = -EINVAL;
2509 goto done;
2510 }
2511 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2512 if (status != MLAN_STATUS_SUCCESS) {
2513 ret = -EFAULT;
2514 goto done;
2515 }
2516 woal_enable_wapi(priv, MTRUE);
2517 done:
2518 if (status != MLAN_STATUS_PENDING)
2519 kfree(req);
2520 LEAVE();
2521 return ret;
2522 }
2523
2524 /**
2525 * @brief set wapi ioctl function
2526 *
2527 * @param dev A pointer to net_device structure
2528 * @param req A pointer to ifreq structure
2529 * @return 0 --success, otherwise fail
2530 */
2531 static int
woal_uap_set_wapi(struct net_device * dev,struct ifreq * req)2532 woal_uap_set_wapi(struct net_device *dev, struct ifreq *req)
2533 {
2534 moal_private *priv = (moal_private *)netdev_priv(dev);
2535 wapi_msg msg;
2536 int ret = 0;
2537
2538 ENTER();
2539
2540 /* Sanity check */
2541 if (req->ifr_data == NULL) {
2542 PRINTM(MERROR, "uap_set_wapi() corrupt data\n");
2543 ret = -EFAULT;
2544 goto done;
2545 }
2546
2547 memset(&msg, 0, sizeof(msg));
2548
2549 if (copy_from_user(&msg, req->ifr_data, sizeof(msg))) {
2550 PRINTM(MERROR, "Copy from user failed\n");
2551 ret = -EFAULT;
2552 goto done;
2553 }
2554
2555 PRINTM(MIOCTL, "set wapi msg_type = %d, msg_len=%d\n", msg.msg_type,
2556 msg.msg_len);
2557 DBG_HEXDUMP(MCMD_D, "wapi msg", msg.msg,
2558 MIN(msg.msg_len, sizeof(msg.msg)));
2559
2560 switch (msg.msg_type) {
2561 case P80211_PACKET_WAPIFLAG:
2562 ret = woal_uap_set_wapi_flag_ioctl(priv, &msg);
2563 break;
2564 case P80211_PACKET_SETKEY:
2565 ret = woal_uap_set_wapi_key_ioctl(priv, &msg);
2566 break;
2567 default:
2568 ret = -EOPNOTSUPP;
2569 break;
2570 }
2571 done:
2572 LEAVE();
2573 return ret;
2574 }
2575
2576 /********************************************************
2577 Global Functions
2578 ********************************************************/
2579 /**
2580 * @brief Initialize the members of mlan_uap_bss_param
2581 * which are uploaded from firmware
2582 *
2583 * @param priv A pointer to moal_private structure
2584 * @param sys_cfg A pointer to mlan_uap_bss_param structure
2585 * @param wait_option Wait option
2586 *
2587 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2588 */
2589 mlan_status
woal_uap_get_bss_param(moal_private * priv,mlan_uap_bss_param * sys_cfg,t_u8 wait_option)2590 woal_uap_get_bss_param(moal_private *priv, mlan_uap_bss_param *sys_cfg,
2591 t_u8 wait_option)
2592 {
2593 mlan_ds_bss *info = NULL;
2594 mlan_ioctl_req *req = NULL;
2595 mlan_status status = MLAN_STATUS_SUCCESS;
2596
2597 ENTER();
2598
2599 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
2600 if (req == NULL) {
2601 LEAVE();
2602 return MLAN_STATUS_FAILURE;
2603 }
2604
2605 info = (mlan_ds_bss *)req->pbuf;
2606 info->sub_command = MLAN_OID_UAP_BSS_CONFIG;
2607 req->req_id = MLAN_IOCTL_BSS;
2608 req->action = MLAN_ACT_GET;
2609
2610 status = woal_request_ioctl(priv, req, wait_option);
2611 if (status != MLAN_STATUS_SUCCESS) {
2612 PRINTM(MERROR, "Get bss info failed!\n");
2613 status = MLAN_STATUS_FAILURE;
2614 goto done;
2615 }
2616 memcpy(sys_cfg, &info->param.bss_config, sizeof(mlan_uap_bss_param));
2617
2618 done:
2619 if (status != MLAN_STATUS_PENDING)
2620 kfree(req);
2621 LEAVE();
2622 return status;
2623 }
2624
2625 /**
2626 * @brief Set uap httxcfg
2627 *
2628 * @param priv A pointer to moal_private structure
2629 * @param band_cfg Band cfg
2630 * @param en Enabled/Disabled
2631 *
2632 * @return 0 --success, otherwise fail
2633 */
2634 int
woal_set_uap_ht_tx_cfg(moal_private * priv,Band_Config_t bandcfg,t_u8 en)2635 woal_set_uap_ht_tx_cfg(moal_private *priv, Band_Config_t bandcfg, t_u8 en)
2636 {
2637 int ret = 0;
2638 mlan_ds_11n_cfg *cfg_11n = NULL;
2639 mlan_ioctl_req *ioctl_req = NULL;
2640 mlan_status status = MLAN_STATUS_SUCCESS;
2641
2642 ENTER();
2643
2644 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
2645 if (ioctl_req == NULL) {
2646 ret = -ENOMEM;
2647 goto done;
2648 }
2649 cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
2650 cfg_11n->sub_command = MLAN_OID_11N_CFG_TX;
2651 ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
2652
2653 /* Set HT Tx configurations */
2654 if (bandcfg.chanBand == BAND_2GHZ) {
2655 if (en)
2656 cfg_11n->param.tx_cfg.httxcap = 0x20;
2657 else
2658 cfg_11n->param.tx_cfg.httxcap = 0;
2659 cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_BG;
2660 } else if (bandcfg.chanBand == BAND_5GHZ) {
2661 if (en)
2662 cfg_11n->param.tx_cfg.httxcap = 0x6f;
2663 else
2664 cfg_11n->param.tx_cfg.httxcap = 0;
2665 cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_A;
2666 }
2667 PRINTM(MCMND, "SET: httxcap=0x%x band:0x%x\n",
2668 cfg_11n->param.tx_cfg.httxcap, cfg_11n->param.tx_cfg.misc_cfg);
2669 /* Update 11n tx parameters in MLAN */
2670 ioctl_req->action = MLAN_ACT_SET;
2671 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2672 if (status != MLAN_STATUS_SUCCESS) {
2673 ret = -EFAULT;
2674 goto done;
2675 }
2676 done:
2677 if (status != MLAN_STATUS_PENDING)
2678 kfree(ioctl_req);
2679 LEAVE();
2680 return ret;
2681 }
2682
2683 /**
2684 * @brief Set 11n status based on the configured security mode
2685 *
2686 * @param priv A pointer to moal_private structure
2687 * @param sys_cfg A pointer to mlan_uap_bss_param structure
2688 * @param action MLAN_ACT_DISABLE or MLAN_ACT_ENABLE
2689 *
2690 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2691 */
2692 mlan_status
woal_uap_set_11n_status(moal_private * priv,mlan_uap_bss_param * sys_cfg,t_u8 action)2693 woal_uap_set_11n_status(moal_private *priv, mlan_uap_bss_param *sys_cfg,
2694 t_u8 action)
2695 {
2696 mlan_status status = MLAN_STATUS_SUCCESS;
2697 mlan_fw_info fw_info;
2698
2699 ENTER();
2700 if (action == MLAN_ACT_DISABLE) {
2701 if ((sys_cfg->supported_mcs_set[0] == 0)
2702 && (sys_cfg->supported_mcs_set[4] == 0)
2703 ) {
2704 goto done;
2705 } else {
2706 sys_cfg->supported_mcs_set[0] = 0;
2707 sys_cfg->supported_mcs_set[4] = 0;
2708 }
2709 }
2710
2711 if (action == MLAN_ACT_ENABLE) {
2712 woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
2713 sys_cfg->supported_mcs_set[0] = 0xFF;
2714 sys_cfg->supported_mcs_set[4] = 0x01;
2715 }
2716
2717 done:
2718 LEAVE();
2719 return status;
2720 }
2721
2722 /**
2723 * @brief Parse AP configuration from ASCII string
2724 *
2725 * @param ap_cfg A pointer to mlan_uap_bss_param structure
2726 * @param buf A pointer to user data
2727 *
2728 * @return 0 --success, otherwise fail
2729 */
2730 int
woal_uap_ap_cfg_parse_data(mlan_uap_bss_param * ap_cfg,char * buf)2731 woal_uap_ap_cfg_parse_data(mlan_uap_bss_param *ap_cfg, char *buf)
2732 {
2733 int ret = 0, atoi_ret;
2734 int set_sec = 0, set_key = 0, set_chan = 0;
2735 int set_preamble = 0, set_scb = 0, set_ssid = 0;
2736 char *begin = buf, *value = NULL, *opt = NULL;
2737
2738 ENTER();
2739
2740 while (begin) {
2741 value = woal_strsep(&begin, ',', '/');
2742 opt = woal_strsep(&value, '=', '/');
2743 if (opt && !strncmp(opt, "END", strlen("END"))) {
2744 if (!ap_cfg->ssid.ssid_len) {
2745 PRINTM(MERROR,
2746 "Minimum option required is SSID\n");
2747 ret = -EINVAL;
2748 goto done;
2749 }
2750 PRINTM(MINFO, "Parsing terminated by string END\n");
2751 break;
2752 }
2753 if (!opt || !value || !value[0]) {
2754 PRINTM(MERROR, "Invalid option\n");
2755 ret = -EINVAL;
2756 goto done;
2757 } else if (!strncmp(opt, "ASCII_CMD", strlen("ASCII_CMD"))) {
2758 if (strncmp(value, "AP_CFG", strlen("AP_CFG"))) {
2759 PRINTM(MERROR,
2760 "ASCII_CMD: %s not matched with AP_CFG\n",
2761 value);
2762 ret = -EFAULT;
2763 goto done;
2764 }
2765 value = woal_strsep(&begin, ',', '/');
2766 opt = woal_strsep(&value, '=', '/');
2767 if (!opt || !value || !value[0]) {
2768 PRINTM(MERROR,
2769 "Minimum option required is SSID\n");
2770 ret = -EINVAL;
2771 goto done;
2772 } else if (!strncmp(opt, "SSID", strlen("SSID"))) {
2773 if (set_ssid) {
2774 PRINTM(MWARN,
2775 "Skipping SSID, found again!\n");
2776 continue;
2777 }
2778 if (strlen(value) >= MLAN_MAX_SSID_LENGTH) {
2779 PRINTM(MERROR,
2780 "SSID length exceeds max length\n");
2781 ret = -EFAULT;
2782 goto done;
2783 }
2784 ap_cfg->ssid.ssid_len = strlen(value);
2785 strncpy((char *)ap_cfg->ssid.ssid, value,
2786 MIN(MLAN_MAX_SSID_LENGTH - 1,
2787 strlen(value)));
2788 PRINTM(MINFO, "ssid=%s, len=%d\n",
2789 ap_cfg->ssid.ssid,
2790 (int)ap_cfg->ssid.ssid_len);
2791 set_ssid = 1;
2792 } else {
2793 PRINTM(MERROR,
2794 "AP_CFG: Invalid option %s, expect SSID\n",
2795 opt);
2796 ret = -EINVAL;
2797 goto done;
2798 }
2799 } else if (!strncmp(opt, "SEC", strlen("SEC"))) {
2800 if (set_sec) {
2801 PRINTM(MWARN, "Skipping SEC, found again!\n");
2802 continue;
2803 }
2804 if (!strnicmp(value, "open", strlen("open"))) {
2805 ap_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
2806 if (set_key)
2807 ap_cfg->wpa_cfg.length = 0;
2808 ap_cfg->key_mgmt = KEY_MGMT_NONE;
2809 ap_cfg->protocol = PROTOCOL_NO_SECURITY;
2810 } else if (!strnicmp
2811 (value, "wpa2-psk", strlen("wpa2-psk"))) {
2812 ap_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
2813 ap_cfg->protocol = PROTOCOL_WPA2;
2814 ap_cfg->key_mgmt = KEY_MGMT_PSK;
2815 ap_cfg->wpa_cfg.pairwise_cipher_wpa =
2816 CIPHER_AES_CCMP;
2817 ap_cfg->wpa_cfg.pairwise_cipher_wpa2 =
2818 CIPHER_AES_CCMP;
2819 ap_cfg->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
2820 } else if (!strnicmp
2821 (value, "wpa-psk", strlen("wpa-psk"))) {
2822 ap_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
2823 ap_cfg->protocol = PROTOCOL_WPA;
2824 ap_cfg->key_mgmt = KEY_MGMT_PSK;
2825 ap_cfg->wpa_cfg.pairwise_cipher_wpa =
2826 CIPHER_TKIP;
2827 ap_cfg->wpa_cfg.group_cipher = CIPHER_TKIP;
2828 } else if (!strnicmp(value, "wep128", strlen("wep128"))) {
2829 ap_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
2830 if (set_key)
2831 ap_cfg->wpa_cfg.length = 0;
2832 ap_cfg->key_mgmt = KEY_MGMT_NONE;
2833 ap_cfg->protocol = PROTOCOL_STATIC_WEP;
2834 } else {
2835 PRINTM(MERROR,
2836 "AP_CFG: Invalid value=%s for %s\n",
2837 value, opt);
2838 ret = -EFAULT;
2839 goto done;
2840 }
2841 set_sec = 1;
2842 } else if (!strncmp(opt, "KEY", strlen("KEY"))) {
2843 if (set_key) {
2844 PRINTM(MWARN, "Skipping KEY, found again!\n");
2845 continue;
2846 }
2847 if (set_sec && ap_cfg->protocol == PROTOCOL_STATIC_WEP) {
2848 if (strlen(value) != MAX_WEP_KEY_SIZE) {
2849 PRINTM(MERROR,
2850 "Invalid WEP KEY length\n");
2851 ret = -EFAULT;
2852 goto done;
2853 }
2854 ap_cfg->wep_cfg.key0.key_index = 0;
2855 ap_cfg->wep_cfg.key0.is_default = 1;
2856 ap_cfg->wep_cfg.key0.length = strlen(value);
2857 memcpy(ap_cfg->wep_cfg.key0.key, value,
2858 MIN(sizeof(ap_cfg->wep_cfg.key0.key),
2859 strlen(value)));
2860 set_key = 1;
2861 continue;
2862 }
2863 if (set_sec && ap_cfg->protocol != PROTOCOL_WPA2
2864 && ap_cfg->protocol != PROTOCOL_WPA) {
2865 PRINTM(MWARN,
2866 "Warning! No KEY for open mode\n");
2867 set_key = 1;
2868 continue;
2869 }
2870 if (strlen(value) < MLAN_MIN_PASSPHRASE_LENGTH ||
2871 strlen(value) > MLAN_PMK_HEXSTR_LENGTH) {
2872 PRINTM(MERROR, "Invalid PSK/PMK length\n");
2873 ret = -EINVAL;
2874 goto done;
2875 }
2876 ap_cfg->wpa_cfg.length = strlen(value);
2877 memcpy(ap_cfg->wpa_cfg.passphrase, value,
2878 MIN(sizeof(ap_cfg->wpa_cfg.passphrase),
2879 strlen(value)));
2880 set_key = 1;
2881 } else if (!strncmp(opt, "CHANNEL", strlen("CHANNEL"))) {
2882 if (set_chan) {
2883 PRINTM(MWARN,
2884 "Skipping CHANNEL, found again!\n");
2885 continue;
2886 }
2887 if (woal_atoi(&atoi_ret, value)) {
2888 ret = -EINVAL;
2889 goto done;
2890 }
2891 if (atoi_ret < 1 || atoi_ret > MLAN_MAX_CHANNEL) {
2892 PRINTM(MERROR,
2893 "AP_CFG: Channel must be between 1 and %d"
2894 "(both included)\n", MLAN_MAX_CHANNEL);
2895 ret = -EINVAL;
2896 goto done;
2897 }
2898 ap_cfg->channel = atoi_ret;
2899 set_chan = 1;
2900 } else if (!strncmp(opt, "PREAMBLE", strlen("PREAMBLE"))) {
2901 if (set_preamble) {
2902 PRINTM(MWARN,
2903 "Skipping PREAMBLE, found again!\n");
2904 continue;
2905 }
2906 if (woal_atoi(&atoi_ret, value)) {
2907 ret = -EINVAL;
2908 goto done;
2909 }
2910 /* This is a READ only value from FW, so we
2911 * can not set this and pass it successfully */
2912 set_preamble = 1;
2913 } else if (!strncmp(opt, "MAX_SCB", strlen("MAX_SCB"))) {
2914 if (set_scb) {
2915 PRINTM(MWARN,
2916 "Skipping MAX_SCB, found again!\n");
2917 continue;
2918 }
2919 if (woal_atoi(&atoi_ret, value)) {
2920 ret = -EINVAL;
2921 goto done;
2922 }
2923 if (atoi_ret < 1 || atoi_ret > MAX_STA_COUNT) {
2924 PRINTM(MERROR,
2925 "AP_CFG: MAX_SCB must be between 1 to %d "
2926 "(both included)\n", MAX_STA_COUNT);
2927 ret = -EINVAL;
2928 goto done;
2929 }
2930 ap_cfg->max_sta_count = (t_u16)atoi_ret;
2931 set_scb = 1;
2932 } else {
2933 PRINTM(MERROR, "Invalid option %s\n", opt);
2934 ret = -EINVAL;
2935 goto done;
2936 }
2937 }
2938
2939 done:
2940 LEAVE();
2941 return ret;
2942 }
2943
2944 /**
2945 * @brief Set AP configuration
2946 *
2947 * @param priv A pointer to moal_private structure
2948 * @param data A pointer to user data
2949 * @param len Length of buf
2950 *
2951 * @return 0 --success, otherwise fail
2952 */
2953 int
woal_uap_set_ap_cfg(moal_private * priv,t_u8 * data,int len)2954 woal_uap_set_ap_cfg(moal_private *priv, t_u8 *data, int len)
2955 {
2956 int ret = 0;
2957 static char buf[MAX_BUF_LEN];
2958 mlan_uap_bss_param *sys_config = NULL;
2959 int restart = 0;
2960
2961 ENTER();
2962
2963 #define MIN_AP_CFG_CMD_LEN 16 /* strlen("ASCII_CMD=AP_CFG") */
2964 if ((len - 1) <= MIN_AP_CFG_CMD_LEN) {
2965 PRINTM(MERROR, "Invalid length of command\n");
2966 ret = -EINVAL;
2967 goto done;
2968 }
2969 sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
2970 if (!sys_config) {
2971 PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
2972 ret = -EFAULT;
2973 goto done;
2974 }
2975
2976 memset(buf, 0, MAX_BUF_LEN);
2977 memcpy(buf, data, MIN(len, (sizeof(buf) - 1)));
2978
2979 /* Initialize the uap bss values which are uploaded from firmware */
2980 woal_uap_get_bss_param(priv, sys_config, MOAL_IOCTL_WAIT);
2981
2982 /* Setting the default values */
2983 sys_config->channel = 6;
2984 sys_config->preamble_type = 0;
2985
2986 ret = woal_uap_ap_cfg_parse_data(sys_config, buf);
2987 if (ret)
2988 goto done;
2989
2990 /* If BSS already started stop it first and restart
2991 * after changing the setting */
2992 if (priv->bss_started == MTRUE) {
2993 ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP);
2994 if (ret)
2995 goto done;
2996 restart = 1;
2997 }
2998
2999 /* If the security mode is configured as WEP or WPA-PSK,
3000 * it will disable 11n automatically, and if configured as
3001 * open(off) or wpa2-psk, it will automatically enable 11n */
3002 if ((sys_config->protocol == PROTOCOL_STATIC_WEP)
3003 || (sys_config->protocol == PROTOCOL_WPA)) {
3004 if (MLAN_STATUS_SUCCESS !=
3005 woal_uap_set_11n_status(priv, sys_config,
3006 MLAN_ACT_DISABLE)) {
3007 ret = -EFAULT;
3008 goto done;
3009 }
3010 } else {
3011 if (MLAN_STATUS_SUCCESS !=
3012 woal_uap_set_11n_status(priv, sys_config,
3013 MLAN_ACT_ENABLE)) {
3014 ret = -EFAULT;
3015 goto done;
3016 }
3017 }
3018
3019 if (MLAN_STATUS_SUCCESS !=
3020 woal_set_get_sys_config(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT,
3021 sys_config)) {
3022 ret = -EFAULT;
3023 goto done;
3024 }
3025
3026 /* Start the BSS after successful configuration */
3027 if (restart)
3028 ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START);
3029
3030 done:
3031 kfree(sys_config);
3032 LEAVE();
3033 return ret;
3034 }
3035
3036 /**
3037 * @brief Set/Get ap scan channel list
3038 *
3039 * @param priv A pointer to moal_private structure
3040 * @param action MLAN_ACT_SET or MLAN_ACT_GET
3041 * @param scan_channels A pointer to mlan_uap_scan_channels structure
3042 *
3043 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3044 */
3045 mlan_status
woal_set_get_ap_scan_channels(moal_private * priv,t_u16 action,mlan_uap_scan_channels * scan_channels)3046 woal_set_get_ap_scan_channels(moal_private *priv, t_u16 action,
3047 mlan_uap_scan_channels * scan_channels)
3048 {
3049 mlan_status ret = MLAN_STATUS_SUCCESS;
3050 mlan_ds_bss *bss = NULL;
3051 mlan_ioctl_req *req = NULL;
3052
3053 ENTER();
3054
3055 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
3056 if (req == NULL) {
3057 ret = MLAN_STATUS_FAILURE;
3058 goto done;
3059 }
3060
3061 bss = (mlan_ds_bss *)req->pbuf;
3062 bss->sub_command = MLAN_OID_UAP_SCAN_CHANNELS;
3063 req->req_id = MLAN_IOCTL_BSS;
3064 req->action = action;
3065
3066 memcpy(&bss->param.ap_scan_channels, scan_channels,
3067 sizeof(mlan_uap_scan_channels));
3068
3069 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3070 if (ret != MLAN_STATUS_SUCCESS)
3071 goto done;
3072 if (action == MLAN_ACT_GET)
3073 memcpy(scan_channels, &bss->param.ap_scan_channels,
3074 sizeof(mlan_uap_scan_channels));
3075
3076 done:
3077 if (ret != MLAN_STATUS_PENDING)
3078 kfree(req);
3079 LEAVE();
3080 return ret;
3081 }
3082
3083 /**
3084 * @brief Set/Get uap channel
3085 *
3086 * @param priv A pointer to moal_private structure
3087 * @param action MLAN_ACT_SET or MLAN_ACT_GET
3088 * @param wait_option wait option
3089 * @param uap_channel A pointer to mlan_uap_channel structure
3090 *
3091 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3092 */
3093 mlan_status
woal_set_get_ap_channel(moal_private * priv,t_u16 action,t_u8 wait_option,chan_band_info * uap_channel)3094 woal_set_get_ap_channel(moal_private *priv, t_u16 action, t_u8 wait_option,
3095 chan_band_info * uap_channel)
3096 {
3097 mlan_status ret = MLAN_STATUS_SUCCESS;
3098 mlan_ds_bss *bss = NULL;
3099 mlan_ioctl_req *req = NULL;
3100
3101 ENTER();
3102
3103 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
3104 if (req == NULL) {
3105 ret = MLAN_STATUS_FAILURE;
3106 goto done;
3107 }
3108
3109 bss = (mlan_ds_bss *)req->pbuf;
3110 bss->sub_command = MLAN_OID_UAP_CHANNEL;
3111 req->req_id = MLAN_IOCTL_BSS;
3112 req->action = action;
3113
3114 memcpy(&bss->param.ap_channel, uap_channel, sizeof(chan_band_info));
3115 ret = woal_request_ioctl(priv, req, wait_option);
3116 if (ret != MLAN_STATUS_SUCCESS)
3117 goto done;
3118 if (action == MLAN_ACT_GET)
3119 memcpy(uap_channel, &bss->param.ap_channel,
3120 sizeof(chan_band_info));
3121
3122 done:
3123 if (ret != MLAN_STATUS_PENDING)
3124 kfree(req);
3125 LEAVE();
3126 return ret;
3127 }
3128
3129 /**
3130 * @brief uap BSS control ioctl handler
3131 *
3132 * @param priv A pointer to moal_private structure
3133 * @param wait_option Wait option
3134 * @param data BSS control type
3135 * @return 0 --success, otherwise fail
3136 */
3137 int
woal_uap_bss_ctrl(moal_private * priv,t_u8 wait_option,int data)3138 woal_uap_bss_ctrl(moal_private *priv, t_u8 wait_option, int data)
3139 {
3140 mlan_ioctl_req *req = NULL;
3141 mlan_ds_bss *bss = NULL;
3142 int ret = 0;
3143 mlan_status status = MLAN_STATUS_SUCCESS;
3144
3145 ENTER();
3146
3147 PRINTM(MIOCTL, "ioctl bss ctrl=%d\n", data);
3148 if ((data != UAP_BSS_START) && (data != UAP_BSS_STOP) &&
3149 (data != UAP_BSS_RESET)) {
3150 PRINTM(MERROR, "Invalid parameter: %d\n", data);
3151 ret = -EINVAL;
3152 goto done;
3153 }
3154 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
3155 if (req == NULL) {
3156 ret = -ENOMEM;
3157 goto done;
3158 }
3159 bss = (mlan_ds_bss *)req->pbuf;
3160 switch (data) {
3161 case UAP_BSS_START:
3162 if (priv->bss_started == MTRUE) {
3163 PRINTM(MWARN, "Warning: BSS already started!\n");
3164 /* goto done; */
3165 } else if (!priv->uap_host_based
3166 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
3167 || dfs_offload
3168 #endif
3169 ) {
3170 /* about to start bss: issue channel check */
3171 woal_11h_channel_check_ioctl(priv, MOAL_IOCTL_WAIT);
3172 }
3173 bss->sub_command = MLAN_OID_BSS_START;
3174 bss->param.host_based = priv->uap_host_based;
3175 break;
3176 case UAP_BSS_STOP:
3177 if (priv->bss_started == MFALSE) {
3178 PRINTM(MWARN, "Warning: BSS already stopped!\n");
3179 /* This is a situation where CAC it started and BSS start is dealyed
3180 * and before CAC timer expires BSS stop is triggered.
3181 *
3182 * Do not skip sending the BSS_STOP command since there are many
3183 * routines triggered on BSS_STOP command response.
3184 */
3185 woal_cancel_cac_block(priv);
3186 }
3187 bss->sub_command = MLAN_OID_BSS_STOP;
3188 break;
3189 case UAP_BSS_RESET:
3190 bss->sub_command = MLAN_OID_UAP_BSS_RESET;
3191 woal_cancel_cac_block(priv);
3192 break;
3193 }
3194 req->req_id = MLAN_IOCTL_BSS;
3195 req->action = MLAN_ACT_SET;
3196
3197 status = woal_request_ioctl(priv, req, wait_option);
3198 if (status == MLAN_STATUS_FAILURE) {
3199 ret = -EFAULT;
3200 goto done;
3201 }
3202 if (data == UAP_BSS_STOP || data == UAP_BSS_RESET) {
3203 priv->bss_started = MFALSE;
3204 woal_stop_queue(priv->netdev);
3205 if (netif_carrier_ok(priv->netdev))
3206 netif_carrier_off(priv->netdev);
3207 woal_flush_tcp_sess_queue(priv);
3208 }
3209 done:
3210 if (status != MLAN_STATUS_PENDING)
3211 kfree(req);
3212 LEAVE();
3213 return ret;
3214 }
3215
3216 /**
3217 * @brief This function sets multicast addresses to firmware
3218 *
3219 * @param dev A pointer to net_device structure
3220 * @return N/A
3221 */
3222 void
woal_uap_set_multicast_list(struct net_device * dev)3223 woal_uap_set_multicast_list(struct net_device *dev)
3224 {
3225 ENTER();
3226
3227 LEAVE();
3228 }
3229
3230 /**
3231 * @brief ioctl function - entry point
3232 *
3233 * @param dev A pointer to net_device structure
3234 * @param req A pointer to ifreq structure
3235 * @param cmd Command
3236 *
3237 * @return 0 --success, otherwise fail
3238 */
3239 int
woal_uap_do_ioctl(struct net_device * dev,struct ifreq * req,int cmd)3240 woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
3241 {
3242 int ret = 0;
3243 ENTER();
3244 PRINTM(MIOCTL, "uap_do_ioctl: ioctl cmd = 0x%x\n", cmd);
3245 switch (cmd) {
3246 case WOAL_ANDROID_DEF_CMD:
3247 /** android default ioctl ID is SIOCDEVPRIVATE + 1 */
3248 ret = woal_android_priv_cmd(dev, req);
3249 break;
3250 case UAP_IOCTL_CMD:
3251 ret = woal_uap_ioctl(dev, req);
3252 break;
3253 case UAP_POWER_MODE:
3254 ret = woal_uap_power_mode_ioctl(dev, req);
3255 break;
3256 case UAP_BSS_CTRL:
3257 ret = woal_uap_bss_ctrl_ioctl(dev, req);
3258 break;
3259 case UAP_WAPI_MSG:
3260 ret = woal_uap_set_wapi(dev, req);
3261 break;
3262 case UAP_BSS_CONFIG:
3263 ret = woal_uap_bss_cfg_ioctl(dev, req);
3264 break;
3265 case UAP_STA_DEAUTH:
3266 ret = woal_uap_sta_deauth_ioctl(dev, req);
3267 break;
3268 case UAP_RADIO_CTL:
3269 ret = woal_uap_radio_ctl(dev, req);
3270 break;
3271 case UAPHOSTPKTINJECT:
3272 ret = woal_send_host_packet(dev, req);
3273 break;
3274 case UAP_GET_STA_LIST:
3275 ret = woal_uap_get_sta_list_ioctl(dev, req);
3276 break;
3277 case UAP_CUSTOM_IE:
3278 ret = woal_custom_ie_ioctl(dev, req);
3279 break;
3280 case UAP_GET_BSS_TYPE:
3281 ret = woal_get_bss_type(dev, req);
3282 break;
3283 case WOAL_ANDROID_PRIV_CMD:
3284 ret = woal_android_priv_cmd(dev, req);
3285 break;
3286 default:
3287 #ifdef UAP_WEXT
3288 ret = woal_uap_do_priv_ioctl(dev, req, cmd);
3289 #else
3290 ret = -EOPNOTSUPP;
3291 #endif
3292 break;
3293 }
3294
3295 LEAVE();
3296 return ret;
3297 }
3298
3299 #ifdef CONFIG_PROC_FS
3300 /**
3301 * @brief Get version
3302 *
3303 * @param priv A pointer to moal_private structure
3304 * @param version A pointer to version buffer
3305 * @param max_len max length of version buffer
3306 *
3307 * @return N/A
3308 */
3309 void
woal_uap_get_version(moal_private * priv,char * version,int max_len)3310 woal_uap_get_version(moal_private *priv, char *version, int max_len)
3311 {
3312 mlan_ds_get_info *info = NULL;
3313 mlan_ioctl_req *req = NULL;
3314 mlan_status status = MLAN_STATUS_SUCCESS;
3315
3316 ENTER();
3317
3318 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
3319 if (req == NULL) {
3320 LEAVE();
3321 return;
3322 }
3323
3324 info = (mlan_ds_get_info *)req->pbuf;
3325 info->sub_command = MLAN_OID_GET_VER_EXT;
3326 req->req_id = MLAN_IOCTL_GET_INFO;
3327 req->action = MLAN_ACT_GET;
3328
3329 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3330 if (status == MLAN_STATUS_SUCCESS) {
3331 PRINTM(MINFO, "MOAL UAP VERSION: %s\n",
3332 info->param.ver_ext.version_str);
3333 snprintf(version, max_len, priv->phandle->driver_version,
3334 info->param.ver_ext.version_str);
3335 }
3336
3337 if (status != MLAN_STATUS_PENDING)
3338 kfree(req);
3339 LEAVE();
3340 return;
3341 }
3342 #endif
3343
3344 /**
3345 * @brief Get uap statistics
3346 *
3347 * @param priv A pointer to moal_private structure
3348 * @param wait_option Wait option
3349 * @param ustats A pointer to mlan_ds_uap_stats structure
3350 *
3351 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
3352 */
3353 mlan_status
woal_uap_get_stats(moal_private * priv,t_u8 wait_option,mlan_ds_uap_stats * ustats)3354 woal_uap_get_stats(moal_private *priv, t_u8 wait_option,
3355 mlan_ds_uap_stats *ustats)
3356 {
3357 mlan_ds_get_info *info = NULL;
3358 mlan_ioctl_req *req = NULL;
3359 mlan_status status = MLAN_STATUS_SUCCESS;
3360
3361 ENTER();
3362
3363 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
3364 if (req == NULL) {
3365 LEAVE();
3366 return MLAN_STATUS_FAILURE;
3367 }
3368
3369 info = (mlan_ds_get_info *)req->pbuf;
3370 info->sub_command = MLAN_OID_GET_STATS;
3371 req->req_id = MLAN_IOCTL_GET_INFO;
3372 req->action = MLAN_ACT_GET;
3373
3374 status = woal_request_ioctl(priv, req, wait_option);
3375 if (status == MLAN_STATUS_SUCCESS) {
3376 if (ustats)
3377 memcpy(ustats, &info->param.ustats,
3378 sizeof(mlan_ds_uap_stats));
3379 #ifdef UAP_WEXT
3380 priv->w_stats.discard.fragment =
3381 info->param.ustats.fcs_error_count;
3382 priv->w_stats.discard.retries = info->param.ustats.retry_count;
3383 priv->w_stats.discard.misc =
3384 info->param.ustats.ack_failure_count;
3385 #endif
3386 }
3387
3388 if (status != MLAN_STATUS_PENDING)
3389 kfree(req);
3390 LEAVE();
3391 return status;
3392 }
3393
3394 /**
3395 * @brief Set/Get system configuration parameters
3396 *
3397 * @param priv A pointer to moal_private structure
3398 * @param action MLAN_ACT_SET or MLAN_ACT_GET
3399 * @param ap_wmm_para A pointer to wmm_parameter_t structure
3400 *
3401 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3402 */
3403 mlan_status
woal_set_get_ap_wmm_para(moal_private * priv,t_u16 action,wmm_parameter_t * ap_wmm_para)3404 woal_set_get_ap_wmm_para(moal_private *priv, t_u16 action,
3405 wmm_parameter_t *ap_wmm_para)
3406 {
3407 mlan_status ret = MLAN_STATUS_SUCCESS;
3408 mlan_ds_bss *bss = NULL;
3409 mlan_ioctl_req *req = NULL;
3410
3411 ENTER();
3412
3413 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
3414 if (req == NULL) {
3415 ret = MLAN_STATUS_FAILURE;
3416 goto done;
3417 }
3418
3419 bss = (mlan_ds_bss *)req->pbuf;
3420 bss->sub_command = MLAN_OID_UAP_CFG_WMM_PARAM;
3421 req->req_id = MLAN_IOCTL_BSS;
3422 req->action = action;
3423
3424 if (action == MLAN_ACT_SET)
3425 memcpy(&bss->param.ap_wmm_para, ap_wmm_para,
3426 sizeof(wmm_parameter_t));
3427
3428 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3429 if (ret != MLAN_STATUS_SUCCESS)
3430 goto done;
3431 if (bss->param.ap_wmm_para.reserved != MLAN_STATUS_COMPLETE) {
3432 ret = MLAN_STATUS_FAILURE;
3433 goto done;
3434 }
3435 if (action == MLAN_ACT_GET)
3436 memcpy(ap_wmm_para, &bss->param.ap_wmm_para,
3437 sizeof(wmm_parameter_t));
3438
3439 done:
3440 if (ret != MLAN_STATUS_PENDING)
3441 kfree(req);
3442 LEAVE();
3443 return ret;
3444 }
3445
3446 /**
3447 * @brief Set/Get system configuration parameters
3448 *
3449 * @param priv A pointer to moal_private structure
3450 * @param action MLAN_ACT_SET or MLAN_ACT_GET
3451 * @param wait_option Wait option
3452 * @param sys_cfg A pointer to mlan_uap_bss_param structure
3453 *
3454 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3455 */
3456 mlan_status
woal_set_get_sys_config(moal_private * priv,t_u16 action,t_u8 wait_option,mlan_uap_bss_param * sys_cfg)3457 woal_set_get_sys_config(moal_private *priv, t_u16 action, t_u8 wait_option,
3458 mlan_uap_bss_param *sys_cfg)
3459 {
3460 mlan_status ret = MLAN_STATUS_SUCCESS;
3461 mlan_ds_bss *bss = NULL;
3462 mlan_ioctl_req *req = NULL;
3463
3464 ENTER();
3465
3466 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
3467 if (req == NULL) {
3468 ret = MLAN_STATUS_FAILURE;
3469 goto done;
3470 }
3471
3472 bss = (mlan_ds_bss *)req->pbuf;
3473 bss->sub_command = MLAN_OID_UAP_BSS_CONFIG;
3474 req->req_id = MLAN_IOCTL_BSS;
3475 req->action = action;
3476
3477 if (action == MLAN_ACT_SET)
3478 memcpy(&bss->param.bss_config, sys_cfg,
3479 sizeof(mlan_uap_bss_param));
3480
3481 ret = woal_request_ioctl(priv, req, wait_option);
3482 if (ret != MLAN_STATUS_SUCCESS)
3483 goto done;
3484
3485 if (action == MLAN_ACT_GET)
3486 memcpy(sys_cfg, &bss->param.bss_config,
3487 sizeof(mlan_uap_bss_param));
3488
3489 done:
3490 if (ret != MLAN_STATUS_PENDING)
3491 kfree(req);
3492 LEAVE();
3493 return ret;
3494 }
3495
3496 /**
3497 * @brief Set invalid data for each member of mlan_uap_bss_param
3498 * structure
3499 *
3500 * @param config A pointer to mlan_uap_bss_param structure
3501 *
3502 * @return N/A
3503 */
3504 void
woal_set_sys_config_invalid_data(mlan_uap_bss_param * config)3505 woal_set_sys_config_invalid_data(mlan_uap_bss_param *config)
3506 {
3507 ENTER();
3508
3509 memset(config, 0, sizeof(mlan_uap_bss_param));
3510 config->bcast_ssid_ctl = 0x7F;
3511 config->radio_ctl = 0x7F;
3512 config->dtim_period = 0x7F;
3513 config->beacon_period = 0x7FFF;
3514 config->tx_data_rate = 0x7FFF;
3515 config->mcbc_data_rate = 0x7FFF;
3516 config->tx_power_level = 0x7F;
3517 config->tx_antenna = 0x7F;
3518 config->rx_antenna = 0x7F;
3519 config->pkt_forward_ctl = 0x7F;
3520 config->max_sta_count = 0x7FFF;
3521 config->auth_mode = 0x7F;
3522 config->sta_ageout_timer = 0x7FFFFFFF;
3523 config->pairwise_update_timeout = 0x7FFFFFFF;
3524 config->pwk_retries = 0x7FFFFFFF;
3525 config->groupwise_update_timeout = 0x7FFFFFFF;
3526 config->gwk_retries = 0x7FFFFFFF;
3527 config->mgmt_ie_passthru_mask = 0x7FFFFFFF;
3528 config->ps_sta_ageout_timer = 0x7FFFFFFF;
3529 config->rts_threshold = 0x7FFF;
3530 config->frag_threshold = 0x7FFF;
3531 config->retry_limit = 0x7FFF;
3532 config->filter.filter_mode = 0x7FFF;
3533 config->filter.mac_count = 0x7FFF;
3534 config->wpa_cfg.rsn_protection = 0x7F;
3535 config->wpa_cfg.gk_rekey_time = 0x7FFFFFFF;
3536 config->enable_2040coex = 0x7F;
3537 config->wmm_para.qos_info = 0x7F;
3538
3539 LEAVE();
3540 }
3541