1 /** @file moal_uap.c
2 *
3 * @brief This file contains the major functions in UAP
4 * driver.
5 *
6 *
7 * Copyright 2008-2022 NXP
8 *
9 * This software file (the File) is distributed by NXP
10 * under the terms of the GNU General Public License Version 2, June 1991
11 * (the License). You may use, redistribute and/or modify the File in
12 * accordance with the terms and conditions of the License, a copy of which
13 * is available by writing to the Free Software Foundation, Inc.,
14 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
15 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
16 *
17 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
19 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
20 * this warranty disclaimer.
21 *
22 */
23
24 /********************************************************
25 Change log:
26 10/21/2008: initial version
27 ********************************************************/
28
29 #include "moal_main.h"
30 #include "moal_uap.h"
31 #ifdef SDIO
32 #include "moal_sdio.h"
33 #endif /* SDIO */
34 #include "moal_eth_ioctl.h"
35 #if defined(STA_CFG80211) && defined(UAP_CFG80211)
36 #include "moal_cfg80211.h"
37 #endif
38
39 /********************************************************
40 Local Variables
41 ********************************************************/
42
43 /********************************************************
44 Global Variables
45 ********************************************************/
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 */
woal_uap_addba_param(struct net_device * dev,struct ifreq * req)56 static int woal_uap_addba_param(struct net_device *dev, struct ifreq *req)
57 {
58 moal_private *priv = (moal_private *)netdev_priv(dev);
59 mlan_ioctl_req *ioctl_req = NULL;
60 mlan_ds_11n_cfg *cfg_11n = NULL;
61 uap_addba_param param;
62 int ret = 0;
63 mlan_status status = MLAN_STATUS_SUCCESS;
64
65 ENTER();
66 memset(¶m, 0, sizeof(param));
67
68 /* Sanity check */
69 if (req->ifr_data == NULL) {
70 PRINTM(MERROR, "uap_addba_param() corrupt data\n");
71 ret = -EFAULT;
72 goto done;
73 }
74 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
75 PRINTM(MERROR, "Copy from user failed\n");
76 ret = -EFAULT;
77 goto done;
78 }
79 PRINTM(MIOCTL,
80 "addba param: action=%d, timeout=%d, txwinsize=%d, rxwinsize=%d txamsdu=%d rxamsdu=%d\n",
81 (int)param.action, (int)param.timeout, (int)param.txwinsize,
82 (int)param.rxwinsize, (int)param.txamsdu, (int)param.rxamsdu);
83 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
84 if (ioctl_req == NULL) {
85 LEAVE();
86 return -ENOMEM;
87 }
88 cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
89 cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_PARAM;
90 ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
91
92 if (!param.action)
93 /* Get addba param from MLAN */
94 ioctl_req->action = MLAN_ACT_GET;
95 else {
96 /* Set addba param in MLAN */
97 ioctl_req->action = MLAN_ACT_SET;
98 cfg_11n->param.addba_param.timeout = param.timeout;
99 cfg_11n->param.addba_param.txwinsize = param.txwinsize;
100 cfg_11n->param.addba_param.rxwinsize = param.rxwinsize;
101 cfg_11n->param.addba_param.txamsdu = param.txamsdu;
102 cfg_11n->param.addba_param.rxamsdu = param.rxamsdu;
103 }
104 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
105 if (status != MLAN_STATUS_SUCCESS) {
106 ret = -EFAULT;
107 goto done;
108 }
109 param.timeout = cfg_11n->param.addba_param.timeout;
110 param.txwinsize = cfg_11n->param.addba_param.txwinsize;
111 param.rxwinsize = cfg_11n->param.addba_param.rxwinsize;
112 param.txamsdu = cfg_11n->param.addba_param.txamsdu;
113 param.rxamsdu = cfg_11n->param.addba_param.rxamsdu;
114
115 /* Copy to user */
116 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
117 PRINTM(MERROR, "Copy to user failed!\n");
118 ret = -EFAULT;
119 goto done;
120 }
121 done:
122 if (status != MLAN_STATUS_PENDING)
123 kfree(ioctl_req);
124 LEAVE();
125 return ret;
126 }
127
128 /**
129 * @brief uap aggr priority tbl
130 *
131 * @param dev A pointer to net_device structure
132 * @param req A pointer to ifreq structure
133 * @return 0 --success, otherwise fail
134 */
woal_uap_aggr_priotbl(struct net_device * dev,struct ifreq * req)135 static int woal_uap_aggr_priotbl(struct net_device *dev, struct ifreq *req)
136 {
137 moal_private *priv = (moal_private *)netdev_priv(dev);
138 mlan_ioctl_req *ioctl_req = NULL;
139 mlan_ds_11n_cfg *cfg_11n = NULL;
140 uap_aggr_prio_tbl param;
141 int ret = 0;
142 int i = 0;
143 mlan_status status = MLAN_STATUS_SUCCESS;
144
145 ENTER();
146 memset(¶m, 0, sizeof(param));
147
148 /* Sanity check */
149 if (req->ifr_data == NULL) {
150 PRINTM(MERROR, "woal_uap_aggr_priotbl() corrupt data\n");
151 ret = -EFAULT;
152 goto done;
153 }
154 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
155 PRINTM(MERROR, "Copy from user failed\n");
156 ret = -EFAULT;
157 goto done;
158 }
159 DBG_HEXDUMP(MCMD_D, "aggr_prio_tbl", (t_u8 *)¶m, sizeof(param));
160
161 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
162 if (ioctl_req == NULL) {
163 LEAVE();
164 return -ENOMEM;
165 }
166 cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
167 cfg_11n->sub_command = MLAN_OID_11N_CFG_AGGR_PRIO_TBL;
168 ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
169
170 if (!param.action) {
171 /* Get aggr_prio_tbl from MLAN */
172 ioctl_req->action = MLAN_ACT_GET;
173 } else {
174 /* Set aggr_prio_tbl in MLAN */
175 ioctl_req->action = MLAN_ACT_SET;
176 for (i = 0; i < MAX_NUM_TID; i++) {
177 cfg_11n->param.aggr_prio_tbl.ampdu[i] = param.ampdu[i];
178 cfg_11n->param.aggr_prio_tbl.amsdu[i] = param.amsdu[i];
179 }
180 }
181 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
182 if (status != MLAN_STATUS_SUCCESS) {
183 ret = -EFAULT;
184 goto done;
185 }
186 for (i = 0; i < MAX_NUM_TID; i++) {
187 param.ampdu[i] = cfg_11n->param.aggr_prio_tbl.ampdu[i];
188 param.amsdu[i] = cfg_11n->param.aggr_prio_tbl.amsdu[i];
189 }
190 /* Copy to user */
191 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
192 PRINTM(MERROR, "Copy to user failed!\n");
193 ret = -EFAULT;
194 goto done;
195 }
196 done:
197 if (status != MLAN_STATUS_PENDING)
198 kfree(ioctl_req);
199 LEAVE();
200 return ret;
201 }
202
203 /**
204 * @brief uap addba reject tbl
205 *
206 * @param dev A pointer to net_device structure
207 * @param req A pointer to ifreq structure
208 * @return 0 --success, otherwise fail
209 */
woal_uap_addba_reject(struct net_device * dev,struct ifreq * req)210 static int woal_uap_addba_reject(struct net_device *dev, struct ifreq *req)
211 {
212 moal_private *priv = (moal_private *)netdev_priv(dev);
213 mlan_ioctl_req *ioctl_req = NULL;
214 mlan_ds_11n_cfg *cfg_11n = NULL;
215 addba_reject_para param;
216 int ret = 0;
217 int i = 0;
218 mlan_status status = MLAN_STATUS_SUCCESS;
219
220 ENTER();
221 memset(¶m, 0, sizeof(param));
222
223 /* Sanity check */
224 if (req->ifr_data == NULL) {
225 PRINTM(MERROR, "woal_uap_addba_reject() corrupt data\n");
226 ret = -EFAULT;
227 goto done;
228 }
229 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
230 PRINTM(MERROR, "Copy from user failed\n");
231 ret = -EFAULT;
232 goto done;
233 }
234 DBG_HEXDUMP(MCMD_D, "addba_reject tbl", (t_u8 *)¶m, sizeof(param));
235
236 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
237 if (ioctl_req == NULL) {
238 LEAVE();
239 return -ENOMEM;
240 }
241 cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
242 cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_REJECT;
243 ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
244
245 if (!param.action) {
246 /* Get addba_reject tbl from MLAN */
247 ioctl_req->action = MLAN_ACT_GET;
248 } else {
249 /* Set addba_reject tbl in MLAN */
250 ioctl_req->action = MLAN_ACT_SET;
251 for (i = 0; i < MAX_NUM_TID; i++)
252 cfg_11n->param.addba_reject[i] = param.addba_reject[i];
253 }
254 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
255 if (status != MLAN_STATUS_SUCCESS) {
256 ret = -EFAULT;
257 goto done;
258 }
259 for (i = 0; i < MAX_NUM_TID; i++)
260 param.addba_reject[i] = cfg_11n->param.addba_reject[i];
261 /* Copy to user */
262 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
263 PRINTM(MERROR, "Copy to user failed!\n");
264 ret = -EFAULT;
265 goto done;
266 }
267 done:
268 if (status != MLAN_STATUS_PENDING)
269 kfree(ioctl_req);
270 LEAVE();
271 return ret;
272 }
273
274 /**
275 * @brief uap get_fw_info handler
276 *
277 * @param dev A pointer to net_device structure
278 * @param req A pointer to ifreq structure
279 * @return 0 --success, otherwise fail
280 */
woal_uap_get_fw_info(struct net_device * dev,struct ifreq * req)281 static int woal_uap_get_fw_info(struct net_device *dev, struct ifreq *req)
282 {
283 moal_private *priv = (moal_private *)netdev_priv(dev);
284 uap_fw_info fw;
285 mlan_fw_info fw_info;
286 int ret = 0;
287
288 ENTER();
289 memset(&fw, 0, sizeof(fw));
290 memset(&fw_info, 0, sizeof(fw_info));
291
292 /* Sanity check */
293 if (req->ifr_data == NULL) {
294 PRINTM(MERROR, "woal_uap_get_fw_info() corrupt data\n");
295 ret = -EFAULT;
296 goto done;
297 }
298 if (copy_from_user(&fw, req->ifr_data, sizeof(fw))) {
299 PRINTM(MERROR, "Copy from user failed\n");
300 ret = -EFAULT;
301 goto done;
302 }
303 if (MLAN_STATUS_SUCCESS !=
304 woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info)) {
305 ret = -EFAULT;
306 goto done;
307 }
308 fw.fw_release_number = fw_info.fw_ver;
309 fw.hw_dev_mcs_support = fw_info.hw_dev_mcs_support;
310 fw.fw_bands = fw_info.fw_bands;
311 fw.region_code = fw_info.region_code;
312 fw.hw_dot_11n_dev_cap = fw_info.hw_dot_11n_dev_cap;
313 /* Copy to user */
314 if (copy_to_user(req->ifr_data, &fw, sizeof(fw))) {
315 PRINTM(MERROR, "Copy to user failed!\n");
316 ret = -EFAULT;
317 goto done;
318 }
319 done:
320 LEAVE();
321 return ret;
322 }
323
324 /**
325 * @brief configure deep sleep
326 *
327 * @param dev A pointer to net_device structure
328 * @param req A pointer to ifreq structure
329 * @return 0 --success, otherwise fail
330 */
woal_uap_deep_sleep(struct net_device * dev,struct ifreq * req)331 static int woal_uap_deep_sleep(struct net_device *dev, struct ifreq *req)
332 {
333 moal_private *priv = (moal_private *)netdev_priv(dev);
334 mlan_ioctl_req *ioctl_req = NULL;
335 mlan_ds_pm_cfg *pm = NULL;
336 deep_sleep_para param;
337 int ret = 0;
338 mlan_status status = MLAN_STATUS_SUCCESS;
339
340 ENTER();
341 memset(¶m, 0, sizeof(param));
342
343 /* Sanity check */
344 if (req->ifr_data == NULL) {
345 PRINTM(MERROR, "woal_uap_deep_sleep() corrupt data\n");
346 ret = -EFAULT;
347 goto done;
348 }
349 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
350 PRINTM(MERROR, "Copy from user failed\n");
351 ret = -EFAULT;
352 goto done;
353 }
354 DBG_HEXDUMP(MCMD_D, "deep_sleep_para", (t_u8 *)¶m, sizeof(param));
355
356 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
357 if (ioctl_req == NULL) {
358 LEAVE();
359 return -ENOMEM;
360 }
361 pm = (mlan_ds_pm_cfg *)ioctl_req->pbuf;
362 pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP;
363 ioctl_req->req_id = MLAN_IOCTL_PM_CFG;
364
365 if (!param.action) {
366 /* Get deep_sleep status from MLAN */
367 ioctl_req->action = MLAN_ACT_GET;
368 } else {
369 /* Set deep_sleep in MLAN */
370 ioctl_req->action = MLAN_ACT_SET;
371 if (param.deep_sleep == MTRUE) {
372 pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_ON;
373 pm->param.auto_deep_sleep.idletime = param.idle_time;
374 } else {
375 pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_OFF;
376 }
377 }
378 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
379 if (status != MLAN_STATUS_SUCCESS) {
380 ret = -EFAULT;
381 goto done;
382 }
383 if (pm->param.auto_deep_sleep.auto_ds == DEEP_SLEEP_ON)
384 param.deep_sleep = MTRUE;
385 else
386 param.deep_sleep = MFALSE;
387 param.idle_time = pm->param.auto_deep_sleep.idletime;
388 /* Copy to user */
389 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
390 PRINTM(MERROR, "Copy to user failed!\n");
391 ret = -EFAULT;
392 goto done;
393 }
394 done:
395 if (status != MLAN_STATUS_PENDING)
396 kfree(ioctl_req);
397 LEAVE();
398 return ret;
399 }
400
401 /**
402 * @brief configure band steering
403 *
404 * @param dev A pointer to net_device structure
405 * @param req A pointer to ifreq structure
406 * @return 0 --success, otherwise fail
407 */
woal_uap_band_steer(struct net_device * dev,struct ifreq * req)408 static int woal_uap_band_steer(struct net_device *dev, struct ifreq *req)
409 {
410 moal_private *priv = (moal_private *)netdev_priv(dev);
411 mlan_ioctl_req *ioctl_req = NULL;
412 mlan_ds_misc_cfg *pm = NULL;
413 band_steer_para param;
414 int ret = 0;
415 mlan_status status = MLAN_STATUS_SUCCESS;
416 ENTER();
417 memset(¶m, 0, sizeof(param));
418
419 /* Sanity check */
420 if (req->ifr_data == NULL) {
421 PRINTM(MERROR, "woal_uap_band_steer() corrupt data\n");
422 ret = -EFAULT;
423 goto done;
424 }
425 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
426 PRINTM(MERROR, "Copy from user failed\n");
427 ret = -EFAULT;
428 goto done;
429 }
430 DBG_HEXDUMP(MCMD_D, "band_steer_para", (t_u8 *)¶m, sizeof(param));
431
432 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_band_steer_cfg));
433 if (ioctl_req == NULL) {
434 LEAVE();
435 return -ENOMEM;
436 }
437 pm = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
438 pm->sub_command = MLAN_OID_MISC_BAND_STEERING;
439 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
440
441 pm->param.band_steer_cfg.action = param.action;
442 pm->param.band_steer_cfg.block_2g_prb_req = param.block_2g_prb_req;
443 pm->param.band_steer_cfg.state = param.state;
444 pm->param.band_steer_cfg.max_btm_req_allowed =
445 param.max_btm_req_allowed;
446
447 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
448 if (status != MLAN_STATUS_SUCCESS) {
449 ret = -EFAULT;
450 goto done;
451 }
452
453 param.action = pm->param.band_steer_cfg.action;
454 param.block_2g_prb_req = pm->param.band_steer_cfg.block_2g_prb_req;
455 param.state = pm->param.band_steer_cfg.state;
456 param.max_btm_req_allowed =
457 pm->param.band_steer_cfg.max_btm_req_allowed;
458
459 /* Copy to user */
460 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
461 PRINTM(MERROR, "Copy to user failed!\n");
462 ret = -EFAULT;
463 goto done;
464 }
465 done:
466 if (status != MLAN_STATUS_PENDING)
467 kfree(ioctl_req);
468 LEAVE();
469 return ret;
470 }
471
472 /**
473 * @brief configure beacon stuck detect mechanism
474 *
475 * @param dev A pointer to net_device structure
476 * @param req A pointer to ifreq structure
477 * @return 0 --success, otherwise fail
478 */
woal_uap_beacon_stuck(struct net_device * dev,struct ifreq * req)479 static int woal_uap_beacon_stuck(struct net_device *dev, struct ifreq *req)
480 {
481 moal_private *priv = (moal_private *)netdev_priv(dev);
482 mlan_ioctl_req *ioctl_req = NULL;
483 mlan_ds_misc_cfg *pm = NULL;
484 beacon_stuck_detect_para param;
485 int ret = 0;
486 mlan_status status = MLAN_STATUS_SUCCESS;
487
488 ENTER();
489
490 memset(¶m, 0, sizeof(param));
491
492 /* Sanity check */
493 if (req->ifr_data == NULL) {
494 PRINTM(MERROR, "woal_uap_beacon_stuck() corrupt data\n");
495 ret = -EFAULT;
496 goto done;
497 }
498
499 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
500 PRINTM(MERROR, "Copy from user failed\n");
501 ret = -EFAULT;
502 goto done;
503 }
504
505 DBG_HEXDUMP(MCMD_D, "beacon_stuck_detect_para", (t_u8 *)¶m,
506 sizeof(param));
507
508 ioctl_req = woal_alloc_mlan_ioctl_req(
509 sizeof(mlan_ds_beacon_stuck_param_cfg));
510 if (ioctl_req == NULL) {
511 LEAVE();
512 return -ENOMEM;
513 }
514
515 pm = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
516 pm->sub_command = MLAN_OID_MISC_BEACON_STUCK;
517 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
518
519 pm->param.beacon_stuck_cfg.action = param.action;
520 pm->param.beacon_stuck_cfg.beacon_stuck_detect_count =
521 param.beacon_stuck_detect_count;
522 pm->param.beacon_stuck_cfg.recovery_confirm_count =
523 param.recovery_confirm_count;
524
525 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
526
527 if (status != MLAN_STATUS_SUCCESS) {
528 ret = -EFAULT;
529 goto done;
530 }
531
532 param.action = pm->param.beacon_stuck_cfg.action;
533 param.beacon_stuck_detect_count =
534 pm->param.beacon_stuck_cfg.beacon_stuck_detect_count;
535 param.recovery_confirm_count =
536 pm->param.beacon_stuck_cfg.recovery_confirm_count;
537
538 /* Copy to user */
539 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
540 PRINTM(MERROR, "Copy to user failed!\n");
541 ret = -EFAULT;
542 goto done;
543 }
544
545 done:
546 if (status != MLAN_STATUS_PENDING)
547 kfree(ioctl_req);
548
549 LEAVE();
550
551 return ret;
552 }
553
554 /**
555 * @brief configure tx_pause settings
556 *
557 * @param dev A pointer to net_device structure
558 * @param req A pointer to ifreq structure
559 * @return 0 --success, otherwise fail
560 */
woal_uap_txdatapause(struct net_device * dev,struct ifreq * req)561 static int woal_uap_txdatapause(struct net_device *dev, struct ifreq *req)
562 {
563 moal_private *priv = (moal_private *)netdev_priv(dev);
564 mlan_ioctl_req *ioctl_req = NULL;
565 mlan_ds_misc_cfg *misc = NULL;
566 tx_data_pause_para param;
567 int ret = 0;
568 mlan_status status = MLAN_STATUS_SUCCESS;
569
570 ENTER();
571 memset(¶m, 0, sizeof(param));
572
573 /* Sanity check */
574 if (req->ifr_data == NULL) {
575 PRINTM(MERROR, "woal_uap_txdatapause corrupt data\n");
576 ret = -EFAULT;
577 goto done;
578 }
579 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
580 PRINTM(MERROR, "Copy from user failed\n");
581 ret = -EFAULT;
582 goto done;
583 }
584 DBG_HEXDUMP(MCMD_D, "tx_data_pause_para", (t_u8 *)¶m,
585 sizeof(param));
586
587 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
588 if (ioctl_req == NULL) {
589 LEAVE();
590 return -ENOMEM;
591 }
592 misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
593 misc->sub_command = MLAN_OID_MISC_TX_DATAPAUSE;
594 ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
595
596 if (!param.action) {
597 /* Get Tx data pause status from MLAN */
598 ioctl_req->action = MLAN_ACT_GET;
599 } else {
600 /* Set Tx data pause in MLAN */
601 ioctl_req->action = MLAN_ACT_SET;
602 misc->param.tx_datapause.tx_pause = param.txpause;
603 misc->param.tx_datapause.tx_buf_cnt = param.txbufcnt;
604 }
605 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
606 if (status != MLAN_STATUS_SUCCESS) {
607 ret = -EFAULT;
608 goto done;
609 }
610
611 param.txpause = misc->param.tx_datapause.tx_pause;
612 param.txbufcnt = misc->param.tx_datapause.tx_buf_cnt;
613
614 /* Copy to user */
615 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
616 PRINTM(MERROR, "Copy to user failed!\n");
617 ret = -EFAULT;
618 goto done;
619 }
620 done:
621 if (status != MLAN_STATUS_PENDING)
622 kfree(ioctl_req);
623 LEAVE();
624 return ret;
625 }
626
627 #ifdef SDIO
628 /**
629 * @brief uap sdcmd52rw ioctl handler
630 *
631 * @param dev A pointer to net_device structure
632 * @param req A pointer to ifreq structure
633 * @return 0 --success, otherwise fail
634 */
woal_uap_sdcmd52_rw(struct net_device * dev,struct ifreq * req)635 static int woal_uap_sdcmd52_rw(struct net_device *dev, struct ifreq *req)
636 {
637 moal_private *priv = (moal_private *)netdev_priv(dev);
638 sdcmd52_para param;
639 t_u8 func, data = 0;
640 int ret = 0, reg;
641
642 ENTER();
643 memset(¶m, 0, sizeof(param));
644
645 /* Sanity check */
646 if (req->ifr_data == NULL) {
647 PRINTM(MERROR, "woal_uap_sdcmd52_rw() corrupt data\n");
648 ret = -EFAULT;
649 goto done;
650 }
651 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
652 PRINTM(MERROR, "Copy from user failed\n");
653 ret = -EFAULT;
654 goto done;
655 }
656
657 func = (t_u8)param.cmd52_params[0];
658 reg = (t_u32)param.cmd52_params[1];
659
660 if (!param.action) {
661 PRINTM(MINFO, "Cmd52 read, func=%d, reg=0x%08X\n", func, reg);
662 #ifdef SDIO_MMC
663 sdio_claim_host(
664 ((struct sdio_mmc_card *)priv->phandle->card)->func);
665 if (func)
666 data = sdio_readb(
667 ((struct sdio_mmc_card *)priv->phandle->card)
668 ->func,
669 reg, &ret);
670 else
671 data = sdio_f0_readb(
672 ((struct sdio_mmc_card *)priv->phandle->card)
673 ->func,
674 reg, &ret);
675 sdio_release_host(
676 ((struct sdio_mmc_card *)priv->phandle->card)->func);
677 if (ret) {
678 PRINTM(MERROR,
679 "sdio_readb: reading register 0x%X failed\n",
680 reg);
681 goto done;
682 }
683 #else
684 if (sdio_read_ioreg(priv->phandle->card, func, reg, &data) <
685 0) {
686 PRINTM(MERROR,
687 "sdio_read_ioreg: reading register 0x%X failed\n",
688 reg);
689 ret = MLAN_STATUS_FAILURE;
690 goto done;
691 }
692 #endif
693 param.cmd52_params[2] = data;
694 } else {
695 data = (t_u8)param.cmd52_params[2];
696 PRINTM(MINFO, "Cmd52 write, func=%d, reg=0x%08X, data=0x%02X\n",
697 func, reg, data);
698 #ifdef SDIO_MMC
699 sdio_claim_host(
700 ((struct sdio_mmc_card *)priv->phandle->card)->func);
701 if (func)
702 sdio_writeb(
703 ((struct sdio_mmc_card *)priv->phandle->card)
704 ->func,
705 data, reg, &ret);
706 else
707 sdio_f0_writeb(
708 ((struct sdio_mmc_card *)priv->phandle->card)
709 ->func,
710 data, reg, &ret);
711 sdio_release_host(
712 ((struct sdio_mmc_card *)priv->phandle->card)->func);
713 if (ret) {
714 PRINTM(MERROR,
715 "sdio_writeb: writing register 0x%X failed\n",
716 reg);
717 goto done;
718 }
719 #else
720 if (sdio_write_ioreg(priv->phandle->card, func, reg, data) <
721 0) {
722 PRINTM(MERROR,
723 "sdio_write_ioreg: writing register 0x%X failed\n",
724 reg);
725 ret = MLAN_STATUS_FAILURE;
726 goto done;
727 }
728 #endif
729 }
730 /* Copy to user */
731 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
732 PRINTM(MERROR, "Copy to user failed!\n");
733 ret = -EFAULT;
734 }
735 done:
736 LEAVE();
737 return ret;
738 }
739 #endif
740
741 /**
742 * @brief enable/disable 11h
743 *
744 * @param enable MTRUE/MFALSE
745 * @return 0 --success, otherwise fail
746 */
woal_uap_11h_ctrl(moal_private * priv,t_u32 enable)747 int woal_uap_11h_ctrl(moal_private *priv, t_u32 enable)
748 {
749 mlan_ioctl_req *ioctl_req = NULL;
750 mlan_ds_snmp_mib *snmp = NULL;
751 int ret = 0;
752 mlan_status status = MLAN_STATUS_SUCCESS;
753 ENTER();
754 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
755 if (ioctl_req == NULL) {
756 LEAVE();
757 return -ENOMEM;
758 }
759 snmp = (mlan_ds_snmp_mib *)ioctl_req->pbuf;
760 ioctl_req->req_id = MLAN_IOCTL_SNMP_MIB;
761 snmp->sub_command = MLAN_OID_SNMP_MIB_DOT11H;
762 snmp->param.oid_value = enable;
763 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
764 if (status != MLAN_STATUS_SUCCESS) {
765 ret = -EFAULT;
766 goto done;
767 }
768 done:
769 if (status != MLAN_STATUS_PENDING)
770 kfree(ioctl_req);
771 LEAVE();
772 return ret;
773 }
774
775 /**
776 * @brief configure snmp mib
777 *
778 * @param dev A pointer to net_device structure
779 * @param req A pointer to ifreq structure
780 * @return 0 --success, otherwise fail
781 */
woal_uap_snmp_mib(struct net_device * dev,struct ifreq * req)782 static int woal_uap_snmp_mib(struct net_device *dev, struct ifreq *req)
783 {
784 moal_private *priv = (moal_private *)netdev_priv(dev);
785 mlan_ioctl_req *ioctl_req = NULL;
786 mlan_ds_snmp_mib *snmp = NULL;
787 snmp_mib_para param;
788 t_u8 value[MAX_SNMP_VALUE_SIZE];
789 int ret = 0;
790 mlan_status status = MLAN_STATUS_SUCCESS;
791
792 ENTER();
793 memset(¶m, 0, sizeof(param));
794 memset(value, 0, MAX_SNMP_VALUE_SIZE);
795
796 /* Sanity check */
797 if (req->ifr_data == NULL) {
798 PRINTM(MERROR, "woal_uap_snmp_mib() corrupt data\n");
799 ret = -EFAULT;
800 goto done;
801 }
802
803 /* Copy from user */
804 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
805 PRINTM(MERROR, "Copy from user failed\n");
806 ret = -EFAULT;
807 goto done;
808 }
809 DBG_HEXDUMP(MCMD_D, "snmp_mib_para", (t_u8 *)¶m, sizeof(param));
810 if (param.action) {
811 if (copy_from_user(value, req->ifr_data + sizeof(param),
812 MIN(param.oid_val_len,
813 MAX_SNMP_VALUE_SIZE))) {
814 PRINTM(MERROR, "Copy from user failed\n");
815 ret = -EFAULT;
816 goto done;
817 }
818 DBG_HEXDUMP(MCMD_D, "snmp_mib_para value", value,
819 MIN(param.oid_val_len, sizeof(t_u32)));
820 }
821
822 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
823 if (ioctl_req == NULL) {
824 LEAVE();
825 return -ENOMEM;
826 }
827 snmp = (mlan_ds_snmp_mib *)ioctl_req->pbuf;
828 ioctl_req->req_id = MLAN_IOCTL_SNMP_MIB;
829 switch (param.oid) {
830 case OID_80211D_ENABLE:
831 snmp->sub_command = MLAN_OID_SNMP_MIB_DOT11D;
832 break;
833 case OID_80211H_ENABLE:
834 snmp->sub_command = MLAN_OID_SNMP_MIB_DOT11H;
835 break;
836 default:
837 ret = -EINVAL;
838 PRINTM(MERROR, "%s: Unsupported SNMP_MIB OID (%d).\n", __func__,
839 param.oid);
840 goto done;
841 }
842
843 if (!param.action) {
844 /* Get mib value from MLAN */
845 ioctl_req->action = MLAN_ACT_GET;
846 } else {
847 /* Set mib value to MLAN */
848 ioctl_req->action = MLAN_ACT_SET;
849 snmp->param.oid_value = *(t_u32 *)value;
850 }
851 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
852 if (status != MLAN_STATUS_SUCCESS) {
853 ret = -EFAULT;
854 goto done;
855 }
856
857 /* Copy to user */
858 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
859 PRINTM(MERROR, "Copy to user failed!\n");
860 ret = -EFAULT;
861 goto done;
862 }
863 if (!param.action) { /* GET */
864 if (copy_to_user(req->ifr_data + sizeof(param),
865 &snmp->param.oid_value,
866 MIN(param.oid_val_len, sizeof(t_u32)))) {
867 PRINTM(MERROR, "Copy from user failed\n");
868 ret = -EFAULT;
869 goto done;
870 }
871 }
872
873 done:
874 if (status != MLAN_STATUS_PENDING)
875 kfree(ioctl_req);
876 LEAVE();
877 return ret;
878 }
879
880 /**
881 * @brief configure domain info
882 *
883 * @param dev A pointer to net_device structure
884 * @param req A pointer to ifreq structure
885 * @return 0 --success, otherwise fail
886 */
woal_uap_domain_info(struct net_device * dev,struct ifreq * req)887 static int woal_uap_domain_info(struct net_device *dev, struct ifreq *req)
888 {
889 moal_private *priv = (moal_private *)netdev_priv(dev);
890 mlan_ioctl_req *ioctl_req = NULL;
891 mlan_ds_11d_cfg *cfg11d = NULL;
892 domain_info_para param;
893 t_u8 tlv[MAX_DOMAIN_TLV_LEN + MAX_REG_DOMAIN_TLV_LEN];
894 t_u16 tlv_data_len = 0;
895 int ret = 0;
896 mlan_status status = MLAN_STATUS_SUCCESS;
897
898 ENTER();
899 memset(¶m, 0, sizeof(param));
900 memset(tlv, 0, MAX_DOMAIN_TLV_LEN + MAX_REG_DOMAIN_TLV_LEN);
901
902 /* Sanity check */
903 if (req->ifr_data == NULL) {
904 PRINTM(MERROR, "woal_uap_domain_info() corrupt data\n");
905 ret = -EFAULT;
906 goto done;
907 }
908
909 /* Copy from user */
910 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
911 PRINTM(MERROR, "Copy from user failed\n");
912 ret = -EFAULT;
913 goto done;
914 }
915 DBG_HEXDUMP(MCMD_D, "domain_info_para", (t_u8 *)¶m, sizeof(param));
916 if (param.action) {
917 /* get tlv header */
918 if (copy_from_user(tlv, req->ifr_data + sizeof(param),
919 TLV_HEADER_LEN)) {
920 PRINTM(MERROR, "Copy from user failed\n");
921 ret = -EFAULT;
922 goto done;
923 }
924 tlv_data_len = ((t_u16 *)(tlv))[1];
925 tlv_data_len += MAX_REG_DOMAIN_TLV_LEN;
926 if ((TLV_HEADER_LEN + tlv_data_len) > (int)sizeof(tlv)) {
927 PRINTM(MERROR, "TLV buffer is overflowed");
928 ret = -EINVAL;
929 goto done;
930 }
931 /* get full tlv */
932 if (copy_from_user(tlv, req->ifr_data + sizeof(param),
933 TLV_HEADER_LEN + tlv_data_len)) {
934 PRINTM(MERROR, "Copy from user failed\n");
935 ret = -EFAULT;
936 goto done;
937 }
938 DBG_HEXDUMP(MCMD_D, "domain_info_para tlv", tlv,
939 TLV_HEADER_LEN + tlv_data_len);
940 }
941
942 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11d_cfg));
943 if (ioctl_req == NULL) {
944 LEAVE();
945 return -ENOMEM;
946 }
947 cfg11d = (mlan_ds_11d_cfg *)ioctl_req->pbuf;
948 ioctl_req->req_id = MLAN_IOCTL_11D_CFG;
949 cfg11d->sub_command = MLAN_OID_11D_DOMAIN_INFO;
950
951 if (!param.action) {
952 /* Get mib value from MLAN */
953 ioctl_req->action = MLAN_ACT_GET;
954 } else {
955 /* Set mib value to MLAN */
956 ioctl_req->action = MLAN_ACT_SET;
957 moal_memcpy_ext(priv->phandle, cfg11d->param.domain_tlv, tlv,
958 TLV_HEADER_LEN + tlv_data_len,
959 sizeof(cfg11d->param.domain_tlv));
960 }
961 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
962 if (status != MLAN_STATUS_SUCCESS) {
963 ret = -EFAULT;
964 goto done;
965 }
966
967 /* Copy to user */
968 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
969 PRINTM(MERROR, "Copy to user failed!\n");
970 ret = -EFAULT;
971 goto done;
972 }
973 if (!param.action) { /* GET */
974 tlv_data_len = ((t_u16 *)(cfg11d->param.domain_tlv))[1];
975 if (copy_to_user(req->ifr_data + sizeof(param),
976 &cfg11d->param.domain_tlv,
977 TLV_HEADER_LEN + tlv_data_len)) {
978 PRINTM(MERROR, "Copy from user failed\n");
979 ret = -EFAULT;
980 goto done;
981 }
982 }
983
984 done:
985 if (status != MLAN_STATUS_PENDING)
986 kfree(ioctl_req);
987 LEAVE();
988 return ret;
989 }
990
991 /**
992 * @brief configure dfs testing settings
993 *
994 * @param dev A pointer to net_device structure
995 * @param req A pointer to ifreq structure
996 * @return 0 --success, otherwise fail
997 */
woal_uap_dfs_testing(struct net_device * dev,struct ifreq * req)998 static int woal_uap_dfs_testing(struct net_device *dev, struct ifreq *req)
999 {
1000 moal_private *priv = (moal_private *)netdev_priv(dev);
1001 mlan_ioctl_req *ioctl_req = NULL;
1002 mlan_ds_11h_cfg *cfg11h = NULL;
1003 dfs_testing_para param;
1004 int ret = 0;
1005 mlan_status status = MLAN_STATUS_SUCCESS;
1006
1007 ENTER();
1008 memset(¶m, 0, sizeof(param));
1009
1010 /* Sanity check */
1011 if (req->ifr_data == NULL) {
1012 PRINTM(MERROR, "woal_uap_dfs_testing() corrupt data\n");
1013 ret = -EFAULT;
1014 goto done;
1015 }
1016
1017 /* Copy from user */
1018 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
1019 PRINTM(MERROR, "Copy from user failed\n");
1020 ret = -EFAULT;
1021 goto done;
1022 }
1023 DBG_HEXDUMP(MCMD_D, "dfs_testing_para", (t_u8 *)¶m, sizeof(param));
1024
1025 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
1026 if (ioctl_req == NULL) {
1027 LEAVE();
1028 return -ENOMEM;
1029 }
1030 cfg11h = (mlan_ds_11h_cfg *)ioctl_req->pbuf;
1031 ioctl_req->req_id = MLAN_IOCTL_11H_CFG;
1032 cfg11h->sub_command = MLAN_OID_11H_DFS_TESTING;
1033
1034 if (!param.action) {
1035 /* Get mib value from MLAN */
1036 ioctl_req->action = MLAN_ACT_GET;
1037 } else {
1038 /* Set mib value to MLAN */
1039 ioctl_req->action = MLAN_ACT_SET;
1040 cfg11h->param.dfs_testing.usr_cac_period_msec =
1041 param.usr_cac_period * 1000;
1042 cfg11h->param.dfs_testing.usr_nop_period_sec =
1043 param.usr_nop_period;
1044 cfg11h->param.dfs_testing.usr_no_chan_change =
1045 param.no_chan_change;
1046 cfg11h->param.dfs_testing.usr_fixed_new_chan =
1047 param.fixed_new_chan;
1048 cfg11h->param.dfs_testing.usr_cac_restart = param.cac_restart;
1049 priv->phandle->cac_restart = param.cac_restart;
1050 priv->phandle->cac_period_jiffies = param.usr_cac_period * HZ;
1051 priv->user_cac_period_msec =
1052 cfg11h->param.dfs_testing.usr_cac_period_msec;
1053 }
1054 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1055 if (status != MLAN_STATUS_SUCCESS) {
1056 ret = -EFAULT;
1057 goto done;
1058 }
1059
1060 if (!param.action) { /* GET */
1061 param.usr_cac_period =
1062 cfg11h->param.dfs_testing.usr_cac_period_msec / 1000;
1063 param.usr_nop_period =
1064 cfg11h->param.dfs_testing.usr_nop_period_sec;
1065 param.no_chan_change =
1066 cfg11h->param.dfs_testing.usr_no_chan_change;
1067 param.fixed_new_chan =
1068 cfg11h->param.dfs_testing.usr_fixed_new_chan;
1069 param.cac_restart = cfg11h->param.dfs_testing.usr_cac_restart;
1070 }
1071 /* Copy to user */
1072 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
1073 PRINTM(MERROR, "Copy to user failed!\n");
1074 ret = -EFAULT;
1075 goto done;
1076 }
1077
1078 done:
1079 if (status != MLAN_STATUS_PENDING)
1080 kfree(ioctl_req);
1081 LEAVE();
1082 return ret;
1083 }
1084
1085 /**
1086 * @brief uap channel NOP status check ioctl handler
1087 *
1088 * @param priv A pointer to moal_private structure
1089 * @param wait_option Wait option
1090 * @param data BSS control type
1091 * @return 0 --success, otherwise fail
1092 */
woal_uap_get_channel_nop_info(moal_private * priv,t_u8 wait_option,mlan_ds_11h_chan_nop_info * ch_info)1093 int woal_uap_get_channel_nop_info(moal_private *priv, t_u8 wait_option,
1094 mlan_ds_11h_chan_nop_info *ch_info)
1095 {
1096 mlan_ioctl_req *req = NULL;
1097 mlan_ds_11h_cfg *ds_11hcfg = NULL;
1098
1099 int ret = 0;
1100 mlan_status status = MLAN_STATUS_SUCCESS;
1101
1102 ENTER();
1103
1104 if (!ch_info) {
1105 PRINTM(MERROR, "Invalid chan_info\n");
1106 LEAVE();
1107 return -EFAULT;
1108 }
1109 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
1110 if (req == NULL) {
1111 ret = -ENOMEM;
1112 goto done;
1113 }
1114
1115 req->req_id = MLAN_IOCTL_11H_CFG;
1116 req->action = MLAN_ACT_GET;
1117
1118 ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
1119 ds_11hcfg->sub_command = MLAN_OID_11H_CHAN_NOP_INFO;
1120 moal_memcpy_ext(priv->phandle, &ds_11hcfg->param.ch_nop_info, ch_info,
1121 sizeof(mlan_ds_11h_chan_nop_info),
1122 sizeof(ds_11hcfg->param.ch_nop_info));
1123 status = woal_request_ioctl(priv, req, wait_option);
1124 if (status == MLAN_STATUS_FAILURE) {
1125 ret = -EFAULT;
1126 goto done;
1127 }
1128 moal_memcpy_ext(priv->phandle, ch_info, &ds_11hcfg->param.ch_nop_info,
1129 sizeof(mlan_ds_11h_chan_nop_info),
1130 sizeof(mlan_ds_11h_chan_nop_info));
1131
1132 done:
1133 if (status != MLAN_STATUS_PENDING)
1134 kfree(req);
1135 LEAVE();
1136 return ret;
1137 }
1138
1139 /**
1140 * @brief configure channel switch count
1141 *
1142 * @param dev A pointer to net_device structure
1143 * @param req A pointer to ifreq structure
1144 * @return 0 --success, otherwise fail
1145 */
woal_uap_chan_switch_count_cfg(struct net_device * dev,struct ifreq * req)1146 static int woal_uap_chan_switch_count_cfg(struct net_device *dev,
1147 struct ifreq *req)
1148 {
1149 moal_private *priv = (moal_private *)netdev_priv(dev);
1150 mlan_ioctl_req *ioctl_req = NULL;
1151 mlan_ds_11h_cfg *cfg11h = NULL;
1152 cscount_cfg_t param;
1153 int ret = 0;
1154 mlan_status status = MLAN_STATUS_SUCCESS;
1155
1156 ENTER();
1157 memset(¶m, 0, sizeof(param));
1158
1159 /* Sanity check */
1160 if (req->ifr_data == NULL) {
1161 PRINTM(MERROR, "%s corrupt data\n", __func__);
1162 ret = -EFAULT;
1163 goto done;
1164 }
1165
1166 /* Copy from user */
1167 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
1168 PRINTM(MERROR, "Copy from user failed\n");
1169 ret = -EFAULT;
1170 goto done;
1171 }
1172 DBG_HEXDUMP(MCMD_D, "cscount_cfg_t", (t_u8 *)¶m, sizeof(param));
1173
1174 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
1175 if (ioctl_req == NULL) {
1176 LEAVE();
1177 return -ENOMEM;
1178 }
1179 cfg11h = (mlan_ds_11h_cfg *)ioctl_req->pbuf;
1180 ioctl_req->req_id = MLAN_IOCTL_11H_CFG;
1181 cfg11h->sub_command = MLAN_OID_11H_CHAN_SWITCH_COUNT;
1182
1183 if (!param.action) {
1184 /* Get mib value from MLAN */
1185 ioctl_req->action = MLAN_ACT_GET;
1186 } else {
1187 /* Set mib value to MLAN */
1188 ioctl_req->action = MLAN_ACT_SET;
1189 cfg11h->param.cs_count = param.cs_count;
1190 }
1191 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1192 if (status != MLAN_STATUS_SUCCESS) {
1193 ret = -EFAULT;
1194 goto done;
1195 }
1196
1197 if (!param.action) { /* GET */
1198 param.cs_count = cfg11h->param.cs_count;
1199 }
1200 /* Copy to user */
1201 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
1202 PRINTM(MERROR, "Copy to user failed!\n");
1203 ret = -EFAULT;
1204 goto done;
1205 }
1206
1207 done:
1208 if (status != MLAN_STATUS_PENDING)
1209 kfree(ioctl_req);
1210 LEAVE();
1211 return ret;
1212 }
1213
1214 /**
1215 * @brief Configure TX beamforming support
1216 *
1217 * @param dev A pointer to net_device structure
1218 * @param req A pointer to ifreq structure
1219 * @return 0 --success, otherwise fail
1220 */
woal_uap_tx_bf_cfg(struct net_device * dev,struct ifreq * req)1221 static int woal_uap_tx_bf_cfg(struct net_device *dev, struct ifreq *req)
1222 {
1223 int ret = 0;
1224 moal_private *priv = (moal_private *)netdev_priv(dev);
1225 mlan_ds_11n_tx_bf_cfg bf_cfg;
1226 tx_bf_cfg_para_hdr param;
1227 t_u16 action = 0;
1228
1229 ENTER();
1230
1231 memset(¶m, 0, sizeof(param));
1232 memset(&bf_cfg, 0, sizeof(bf_cfg));
1233
1234 /* Sanity check */
1235 if (req->ifr_data == NULL) {
1236 PRINTM(MERROR, "woal_uap_tx_bf_cfg corrupt data\n");
1237 ret = -EFAULT;
1238 goto done;
1239 }
1240 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
1241 PRINTM(MERROR, "Copy from user failed\n");
1242 ret = -EFAULT;
1243 goto done;
1244 }
1245 if (!param.action)
1246 /* Get BF configurations */
1247 action = MLAN_ACT_GET;
1248 else
1249 /* Set BF configurations */
1250 action = MLAN_ACT_SET;
1251 if (copy_from_user(&bf_cfg, req->ifr_data + sizeof(tx_bf_cfg_para_hdr),
1252 sizeof(bf_cfg))) {
1253 PRINTM(MERROR, "Copy from user failed\n");
1254 ret = -EFAULT;
1255 goto done;
1256 }
1257 DBG_HEXDUMP(MCMD_D, "bf_cfg", (t_u8 *)&bf_cfg, sizeof(bf_cfg));
1258
1259 if (MLAN_STATUS_SUCCESS !=
1260 woal_set_get_tx_bf_cfg(priv, action, &bf_cfg)) {
1261 ret = -EFAULT;
1262 goto done;
1263 }
1264
1265 /* Copy to user */
1266 if (copy_to_user(req->ifr_data + sizeof(tx_bf_cfg_para_hdr), &bf_cfg,
1267 sizeof(bf_cfg))) {
1268 PRINTM(MERROR, "Copy to user failed!\n");
1269 ret = -EFAULT;
1270 goto done;
1271 }
1272
1273 done:
1274 LEAVE();
1275 return ret;
1276 }
1277
1278 /**
1279 * @brief Set/Get 11n configurations
1280 *
1281 * @param dev A pointer to net_device structure
1282 * @param req A pointer to ifreq structure
1283 * @return 0 --success, otherwise fail
1284 */
woal_uap_ht_tx_cfg(struct net_device * dev,struct ifreq * req)1285 static int woal_uap_ht_tx_cfg(struct net_device *dev, struct ifreq *req)
1286 {
1287 int ret = 0;
1288 moal_private *priv = (moal_private *)netdev_priv(dev);
1289 mlan_ds_11n_cfg *cfg_11n = NULL;
1290 mlan_ds_11n_tx_cfg httx_cfg;
1291 mlan_ioctl_req *ioctl_req = NULL;
1292 ht_tx_cfg_para_hdr param;
1293 mlan_status status = MLAN_STATUS_SUCCESS;
1294
1295 ENTER();
1296
1297 memset(¶m, 0, sizeof(ht_tx_cfg_para_hdr));
1298 memset(&httx_cfg, 0, sizeof(mlan_ds_11n_tx_cfg));
1299
1300 /* Sanity check */
1301 if (req->ifr_data == NULL) {
1302 PRINTM(MERROR, "woal_uap_ht_tx_cfg corrupt data\n");
1303 ret = -EFAULT;
1304 goto done;
1305 }
1306 if (copy_from_user(¶m, req->ifr_data, sizeof(ht_tx_cfg_para_hdr))) {
1307 PRINTM(MERROR, "Copy from user failed\n");
1308 ret = -EFAULT;
1309 goto done;
1310 }
1311 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
1312 if (ioctl_req == NULL) {
1313 ret = -ENOMEM;
1314 goto done;
1315 }
1316 cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
1317 cfg_11n->sub_command = MLAN_OID_11N_CFG_TX;
1318 ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
1319 if (copy_from_user(&httx_cfg,
1320 req->ifr_data + sizeof(ht_tx_cfg_para_hdr),
1321 sizeof(mlan_ds_11n_tx_cfg))) {
1322 PRINTM(MERROR, "Copy from user failed\n");
1323 ret = -EFAULT;
1324 goto done;
1325 }
1326 if (!param.action) {
1327 /* Get 11n tx parameters from MLAN */
1328 ioctl_req->action = MLAN_ACT_GET;
1329 } else {
1330 /* Set HT Tx configurations */
1331 cfg_11n->param.tx_cfg.httxcap = httx_cfg.httxcap;
1332 PRINTM(MINFO, "SET: httxcap:0x%x\n", httx_cfg.httxcap);
1333 /* Update 11n tx parameters in MLAN */
1334 ioctl_req->action = MLAN_ACT_SET;
1335 }
1336 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1337 if (status != MLAN_STATUS_SUCCESS) {
1338 ret = -EFAULT;
1339 goto done;
1340 }
1341 if (ioctl_req->action == MLAN_ACT_GET) {
1342 httx_cfg.httxcap = cfg_11n->param.tx_cfg.httxcap;
1343 PRINTM(MINFO, "GET: httxcap:0x%x\n", httx_cfg.httxcap);
1344 }
1345 /* Copy to user */
1346 if (copy_to_user(req->ifr_data + sizeof(ht_tx_cfg_para_hdr), &httx_cfg,
1347 sizeof(mlan_ds_11n_tx_cfg))) {
1348 PRINTM(MERROR, "Copy to user failed!\n");
1349 ret = -EFAULT;
1350 goto done;
1351 }
1352 done:
1353 if (status != MLAN_STATUS_PENDING)
1354 kfree(ioctl_req);
1355 LEAVE();
1356 return ret;
1357 }
1358
1359 /**
1360 * @brief Set/Get Set/Get 11AC configurations
1361 *
1362 * @param dev A pointer to net_device structure
1363 * @param req A pointer to ifreq structure
1364 * @return 0 --success, otherwise fail
1365 */
woal_uap_vht_cfg(struct net_device * dev,struct ifreq * req)1366 static int woal_uap_vht_cfg(struct net_device *dev, struct ifreq *req)
1367 {
1368 moal_private *priv = (moal_private *)netdev_priv(dev);
1369 int ret = 0, resbuf_len = 0;
1370 mlan_ds_11ac_cfg *cfg_11ac = NULL;
1371 mlan_ioctl_req *ioctl_req = NULL;
1372 mlan_ds_11ac_vht_cfg *vhtcfg = NULL, vht_cfg;
1373 t_u8 *respbuf = NULL;
1374 vht_cfg_para_hdr param;
1375 mlan_status status = MLAN_STATUS_SUCCESS;
1376 #define CMD_RESPBUF_LEN 2048
1377 gfp_t flag;
1378
1379 ENTER();
1380
1381 memset(¶m, 0, sizeof(vht_cfg_para_hdr));
1382
1383 flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
1384 respbuf = kzalloc(CMD_RESPBUF_LEN, flag);
1385 if (!respbuf) {
1386 ret = -ENOMEM;
1387 goto done;
1388 }
1389
1390 /* Sanity check */
1391 if (req->ifr_data == NULL) {
1392 PRINTM(MERROR, "woal_uap_ht_tx_cfg corrupt data\n");
1393 ret = -EFAULT;
1394 goto done;
1395 }
1396 if (copy_from_user(¶m, req->ifr_data, sizeof(vht_cfg_para_hdr))) {
1397 PRINTM(MERROR, "Copy from user failed\n");
1398 ret = -EFAULT;
1399 goto done;
1400 }
1401
1402 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11ac_cfg));
1403 if (ioctl_req == NULL) {
1404 ret = -ENOMEM;
1405 goto done;
1406 }
1407 cfg_11ac = (mlan_ds_11ac_cfg *)ioctl_req->pbuf;
1408 cfg_11ac->sub_command = MLAN_OID_11AC_VHT_CFG;
1409 ioctl_req->req_id = MLAN_IOCTL_11AC_CFG;
1410 if (copy_from_user(&vht_cfg, req->ifr_data + sizeof(vht_cfg_para_hdr),
1411 sizeof(mlan_ds_11ac_vht_cfg))) {
1412 PRINTM(MERROR, "Copy from user failed\n");
1413 ret = -EFAULT;
1414 goto done;
1415 }
1416 if (vht_cfg.band == BAND_SELECT_BOTH) {
1417 cfg_11ac->param.vht_cfg.band = (BAND_SELECT_BG | BAND_SELECT_A);
1418 } else {
1419 cfg_11ac->param.vht_cfg.band = vht_cfg.band;
1420 }
1421 if (!param.action) {
1422 /* GET operation */
1423 if (vht_cfg.band == BAND_SELECT_BOTH) {
1424 /* if get both bands, get BG first */
1425 cfg_11ac->param.vht_cfg.band = BAND_SELECT_BG;
1426 }
1427 PRINTM(MINFO, "GET: vhtcfg band: 0x%x\n",
1428 cfg_11ac->param.vht_cfg.band);
1429 if (priv->bss_role == MLAN_BSS_ROLE_UAP)
1430 cfg_11ac->param.vht_cfg.txrx = MLAN_RADIO_RX;
1431 else
1432 cfg_11ac->param.vht_cfg.txrx = vht_cfg.txrx;
1433 PRINTM(MINFO, "GET: vhtcfg txrx: 0x%x\n",
1434 cfg_11ac->param.vht_cfg.txrx);
1435 ioctl_req->action = MLAN_ACT_GET;
1436 } else {
1437 /* Band */
1438 if (vht_cfg.band == BAND_SELECT_BOTH)
1439 cfg_11ac->param.vht_cfg.band =
1440 (BAND_SELECT_BG | BAND_SELECT_A);
1441 else
1442 cfg_11ac->param.vht_cfg.band = vht_cfg.band;
1443 PRINTM(MINFO, "SET: vhtcfg band: 0x%x\n",
1444 cfg_11ac->param.vht_cfg.band);
1445 /* Tx/Rx */
1446 cfg_11ac->param.vht_cfg.txrx = vht_cfg.txrx;
1447 PRINTM(MINFO, "SET: vhtcfg txrx: 0x%x\n",
1448 cfg_11ac->param.vht_cfg.txrx);
1449 /* BW cfg */
1450 cfg_11ac->param.vht_cfg.bwcfg = vht_cfg.bwcfg;
1451 PRINTM(MINFO, "SET: vhtcfg bw cfg:0x%x\n",
1452 cfg_11ac->param.vht_cfg.bwcfg);
1453
1454 cfg_11ac->param.vht_cfg.vht_cap_info = vht_cfg.vht_cap_info;
1455 PRINTM(MINFO, "SET: vhtcfg vht_cap_info:0x%x\n",
1456 cfg_11ac->param.vht_cfg.vht_cap_info);
1457 cfg_11ac->param.vht_cfg.vht_tx_mcs = vht_cfg.vht_tx_mcs;
1458 cfg_11ac->param.vht_cfg.vht_rx_mcs = vht_cfg.vht_rx_mcs;
1459 /* Update 11AC parameters in MLAN */
1460 ioctl_req->action = MLAN_ACT_SET;
1461 }
1462 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1463 if (status != MLAN_STATUS_SUCCESS) {
1464 ret = -EFAULT;
1465 goto done;
1466 }
1467
1468 /* number of vhtcfg entries */
1469 *respbuf = 1;
1470 vhtcfg = (mlan_ds_11ac_vht_cfg *)(respbuf + 1);
1471 moal_memcpy_ext(priv->phandle, vhtcfg, &cfg_11ac->param.vht_cfg,
1472 sizeof(mlan_ds_11ac_vht_cfg),
1473 sizeof(mlan_ds_11ac_vht_cfg));
1474 resbuf_len = 1 + sizeof(mlan_ds_11ac_vht_cfg);
1475
1476 if ((ioctl_req->action == MLAN_ACT_GET) &&
1477 (vht_cfg.band == BAND_SELECT_BOTH)) {
1478 cfg_11ac->param.vht_cfg.band = BAND_SELECT_A;
1479 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1480 if (status != MLAN_STATUS_SUCCESS) {
1481 ret = -EFAULT;
1482 goto done;
1483 }
1484 /* number of vhtcfg entries */
1485 *respbuf = 2;
1486 vhtcfg++;
1487 moal_memcpy_ext(priv->phandle, vhtcfg, &cfg_11ac->param.vht_cfg,
1488 sizeof(mlan_ds_11ac_vht_cfg),
1489 sizeof(mlan_ds_11ac_vht_cfg));
1490 resbuf_len += sizeof(mlan_ds_11ac_vht_cfg);
1491 }
1492 if (ioctl_req->action == MLAN_ACT_GET) {
1493 if (copy_to_user(req->ifr_data, respbuf, resbuf_len)) {
1494 PRINTM(MERROR, "Copy to user failed\n");
1495 ret = -EFAULT;
1496 }
1497 }
1498 done:
1499 if (status != MLAN_STATUS_PENDING)
1500 kfree(ioctl_req);
1501 if (respbuf)
1502 kfree(respbuf);
1503 LEAVE();
1504 return ret;
1505 }
1506
1507 /**
1508 * @brief uap hs_cfg ioctl handler
1509 *
1510 * @param dev A pointer to net_device structure
1511 * @param req A pointer to ifreq structure
1512 * @return 0 --success, otherwise fail
1513 */
woal_uap_hs_cfg(struct net_device * dev,struct ifreq * req,BOOLEAN invoke_hostcmd)1514 static int woal_uap_hs_cfg(struct net_device *dev, struct ifreq *req,
1515 BOOLEAN invoke_hostcmd)
1516 {
1517 moal_private *priv = (moal_private *)netdev_priv(dev);
1518 mlan_ds_hs_cfg hscfg;
1519 ds_hs_cfg hs_cfg;
1520 mlan_bss_info bss_info;
1521 t_u16 action;
1522 int ret = 0;
1523
1524 ENTER();
1525
1526 memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg));
1527 memset(&hs_cfg, 0, sizeof(ds_hs_cfg));
1528
1529 /* Sanity check */
1530 if (req->ifr_data == NULL) {
1531 PRINTM(MERROR, "uap_hs_cfg() corrupt data\n");
1532 ret = -EFAULT;
1533 goto done;
1534 }
1535 if (copy_from_user(&hs_cfg, req->ifr_data, sizeof(ds_hs_cfg))) {
1536 PRINTM(MERROR, "Copy from user failed\n");
1537 ret = -EFAULT;
1538 goto done;
1539 }
1540
1541 PRINTM(MIOCTL,
1542 "ioctl hscfg: flags=0x%x condition=0x%x gpio=%d gap=0x%x\n",
1543 hs_cfg.flags, hs_cfg.conditions, (int)hs_cfg.gpio, hs_cfg.gap);
1544
1545 /* HS config is blocked if HS is already activated */
1546 if ((hs_cfg.flags & HS_CFG_FLAG_CONDITION) &&
1547 (hs_cfg.conditions != HOST_SLEEP_CFG_CANCEL ||
1548 invoke_hostcmd == MFALSE)) {
1549 memset(&bss_info, 0, sizeof(bss_info));
1550 woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
1551 if (bss_info.is_hs_configured) {
1552 PRINTM(MERROR, "HS already configured\n");
1553 ret = -EFAULT;
1554 goto done;
1555 }
1556 }
1557
1558 if (hs_cfg.flags & HS_CFG_FLAG_SET) {
1559 action = MLAN_ACT_SET;
1560 if (hs_cfg.flags != HS_CFG_FLAG_ALL) {
1561 woal_set_get_hs_params(priv, MLAN_ACT_GET,
1562 MOAL_IOCTL_WAIT, &hscfg);
1563 }
1564 if (hs_cfg.flags & HS_CFG_FLAG_CONDITION)
1565 hscfg.conditions = hs_cfg.conditions;
1566 if (hs_cfg.flags & HS_CFG_FLAG_GPIO)
1567 hscfg.gpio = hs_cfg.gpio;
1568 if (hs_cfg.flags & HS_CFG_FLAG_GAP)
1569 hscfg.gap = hs_cfg.gap;
1570
1571 if (invoke_hostcmd == MTRUE) {
1572 /* Issue IOCTL to set up parameters */
1573 hscfg.is_invoke_hostcmd = MFALSE;
1574 if (MLAN_STATUS_SUCCESS !=
1575 woal_set_get_hs_params(priv, action,
1576 MOAL_IOCTL_WAIT, &hscfg)) {
1577 ret = -EFAULT;
1578 goto done;
1579 }
1580 }
1581 } else {
1582 action = MLAN_ACT_GET;
1583 }
1584
1585 /* Issue IOCTL to invoke hostcmd */
1586 hscfg.is_invoke_hostcmd = invoke_hostcmd;
1587 if (MLAN_STATUS_SUCCESS !=
1588 woal_set_get_hs_params(priv, action, MOAL_IOCTL_WAIT, &hscfg)) {
1589 ret = -EFAULT;
1590 goto done;
1591 }
1592 if (!(hs_cfg.flags & HS_CFG_FLAG_SET)) {
1593 hs_cfg.flags = HS_CFG_FLAG_CONDITION | HS_CFG_FLAG_GPIO |
1594 HS_CFG_FLAG_GAP;
1595 hs_cfg.conditions = hscfg.conditions;
1596 hs_cfg.gpio = hscfg.gpio;
1597 hs_cfg.gap = hscfg.gap;
1598 /* Copy to user */
1599 if (copy_to_user(req->ifr_data, &hs_cfg, sizeof(ds_hs_cfg))) {
1600 PRINTM(MERROR, "Copy to user failed!\n");
1601 ret = -EFAULT;
1602 goto done;
1603 }
1604 }
1605
1606 done:
1607 LEAVE();
1608 return ret;
1609 }
1610
1611 /**
1612 * @brief Set Host Sleep parameters
1613 *
1614 * @param priv A pointer to moal_private structure
1615 * @param wrq A pointer to iwreq structure
1616 *
1617 * @return 0 --success, otherwise fail
1618 */
woal_uap_hs_set_para(struct net_device * dev,struct ifreq * req)1619 static int woal_uap_hs_set_para(struct net_device *dev, struct ifreq *req)
1620 {
1621 int ret = 0;
1622
1623 ENTER();
1624
1625 if (req->ifr_data != NULL) {
1626 ret = woal_uap_hs_cfg(dev, req, MFALSE);
1627 goto done;
1628 } else {
1629 PRINTM(MERROR, "Invalid data\n");
1630 ret = -EINVAL;
1631 goto done;
1632 }
1633 done:
1634 LEAVE();
1635 return ret;
1636 }
1637
1638 /**
1639 * @brief uap mgmt_frame_control ioctl handler
1640 *
1641 * @param dev A pointer to net_device structure
1642 * @param req A pointer to ifreq structure
1643 * @return 0 --success, otherwise fail
1644 */
woal_uap_mgmt_frame_control(struct net_device * dev,struct ifreq * req)1645 static int woal_uap_mgmt_frame_control(struct net_device *dev,
1646 struct ifreq *req)
1647 {
1648 moal_private *priv = (moal_private *)netdev_priv(dev);
1649 int ret = 0;
1650 t_u16 action = 0;
1651 mgmt_frame_ctrl param;
1652 mlan_uap_bss_param *sys_config = NULL;
1653
1654 ENTER();
1655
1656 /* Sanity check */
1657 if (req->ifr_data == NULL) {
1658 PRINTM(MERROR, "uap_mgmt_frame_ctrl() corrupt data\n");
1659 ret = -EFAULT;
1660 goto done;
1661 }
1662
1663 /* Get user data */
1664 if (copy_from_user(¶m, req->ifr_data, sizeof(param))) {
1665 PRINTM(MERROR, "Copy from user failed\n");
1666 ret = -EFAULT;
1667 goto done;
1668 }
1669 sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
1670 if (!sys_config) {
1671 PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
1672 ret = -EFAULT;
1673 goto done;
1674 }
1675
1676 if (param.action)
1677 action = MLAN_ACT_SET;
1678 else
1679 action = MLAN_ACT_GET;
1680 if (action == MLAN_ACT_SET) {
1681 /* Initialize the invalid values so that the correct
1682 values below are downloaded to firmware */
1683 woal_set_sys_config_invalid_data(sys_config);
1684 sys_config->mgmt_ie_passthru_mask = param.mask;
1685 }
1686
1687 if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, action,
1688 MOAL_IOCTL_WAIT,
1689 sys_config)) {
1690 ret = -EFAULT;
1691 goto done;
1692 }
1693
1694 if (action == MLAN_ACT_GET) {
1695 param.mask = sys_config->mgmt_ie_passthru_mask;
1696 if (copy_to_user(req->ifr_data, ¶m, sizeof(param))) {
1697 PRINTM(MERROR, "Copy to user failed\n");
1698 ret = -EFAULT;
1699 }
1700 }
1701 done:
1702 kfree(sys_config);
1703 LEAVE();
1704 return ret;
1705 }
1706
1707 /**
1708 * @brief Set/Get tx rate
1709 *
1710 * @param dev A pointer to net_device structure
1711 * @param req A pointer to ifreq structure
1712 *
1713 * @return 0 --success, otherwise fail
1714 */
woal_uap_tx_rate_cfg(struct net_device * dev,struct ifreq * req)1715 static int woal_uap_tx_rate_cfg(struct net_device *dev, struct ifreq *req)
1716 {
1717 moal_private *priv = (moal_private *)netdev_priv(dev);
1718 int ret = 0, i = 0;
1719 mlan_ds_rate *rate = NULL;
1720 mlan_ioctl_req *mreq = NULL;
1721 tx_rate_cfg_t tx_rate_config;
1722 mlan_status status = MLAN_STATUS_SUCCESS;
1723
1724 ENTER();
1725
1726 /* Sanity check */
1727 if (req->ifr_data == NULL) {
1728 PRINTM(MERROR, "uap_tx_rate_cfg() corrupt data\n");
1729 ret = -EFAULT;
1730 goto done;
1731 }
1732
1733 memset(&tx_rate_config, 0, sizeof(tx_rate_cfg_t));
1734 /* Get user data */
1735 if (copy_from_user(&tx_rate_config, req->ifr_data,
1736 sizeof(tx_rate_cfg_t))) {
1737 PRINTM(MERROR, "Copy from user failed\n");
1738 ret = -EFAULT;
1739 goto done;
1740 }
1741
1742 mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
1743 if (mreq == NULL) {
1744 ret = -ENOMEM;
1745 goto done;
1746 }
1747 rate = (mlan_ds_rate *)mreq->pbuf;
1748 rate->param.rate_cfg.rate_type = MLAN_RATE_INDEX;
1749 rate->sub_command = MLAN_OID_RATE_CFG;
1750 mreq->req_id = MLAN_IOCTL_RATE;
1751 if (!(tx_rate_config.action))
1752 mreq->action = MLAN_ACT_GET;
1753 else {
1754 if ((tx_rate_config.user_data_cnt <= 0) ||
1755 (tx_rate_config.user_data_cnt > 4)) {
1756 PRINTM(MERROR, "Invalid user_data_cnt\n");
1757 ret = -EINVAL;
1758 goto done;
1759 }
1760
1761 mreq->action = MLAN_ACT_SET;
1762 if (tx_rate_config.rate_format == AUTO_RATE)
1763 rate->param.rate_cfg.is_rate_auto = 1;
1764 else {
1765 if ((tx_rate_config.rate_format < 0) ||
1766 (tx_rate_config.rate < 0)) {
1767 PRINTM(MERROR,
1768 "Invalid format or rate selection\n");
1769 ret = -EINVAL;
1770 goto done;
1771 }
1772 /* rate_format sanity check */
1773 if ((tx_rate_config.rate_format >
1774 MLAN_RATE_FORMAT_HE)) {
1775 PRINTM(MERROR, "Invalid format selection\n");
1776 ret = -EINVAL;
1777 goto done;
1778 }
1779 rate->param.rate_cfg.rate_format =
1780 tx_rate_config.rate_format;
1781
1782 /* rate sanity check */
1783 if (tx_rate_config.user_data_cnt >= 2) {
1784 if (((tx_rate_config.rate_format ==
1785 MLAN_RATE_FORMAT_LG) &&
1786 (tx_rate_config.rate >
1787 MLAN_RATE_INDEX_OFDM7)) ||
1788 ((tx_rate_config.rate_format ==
1789 MLAN_RATE_FORMAT_HT) &&
1790 (tx_rate_config.rate != 32) &&
1791 (tx_rate_config.rate > 15)) ||
1792 ((tx_rate_config.rate_format ==
1793 MLAN_RATE_FORMAT_VHT) &&
1794 (tx_rate_config.rate >
1795 MLAN_RATE_INDEX_MCS9)) ||
1796 ((tx_rate_config.rate_format ==
1797 MLAN_RATE_FORMAT_HE) &&
1798 (tx_rate_config.rate >
1799 MLAN_RATE_INDEX_MCS11))) {
1800 PRINTM(MERROR,
1801 "Invalid rate selection\n");
1802 ret = -EINVAL;
1803 goto done;
1804 }
1805 rate->param.rate_cfg.rate = tx_rate_config.rate;
1806 }
1807
1808 /* nss sanity check */
1809 if ((tx_rate_config.rate_format == 2) ||
1810 (tx_rate_config.rate_format == 3)) {
1811 if ((tx_rate_config.nss < 1) ||
1812 (tx_rate_config.nss > 2)) {
1813 PRINTM(MERROR,
1814 "Invalid nss selection %d\n",
1815 tx_rate_config.nss);
1816 ret = -EINVAL;
1817 goto done;
1818 }
1819 rate->param.rate_cfg.nss = tx_rate_config.nss;
1820 }
1821 if (tx_rate_config.user_data_cnt <= 3)
1822 rate->param.rate_cfg.rate_setting = 0xffff;
1823 else
1824 rate->param.rate_cfg.rate_setting =
1825 tx_rate_config.rate_setting;
1826 }
1827 }
1828
1829 status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
1830 if (status != MLAN_STATUS_SUCCESS) {
1831 ret = -EFAULT;
1832 goto done;
1833 }
1834 if (tx_rate_config.action) {
1835 priv->rate_index = tx_rate_config.action;
1836 } else {
1837 if (rate->param.rate_cfg.is_rate_auto)
1838 tx_rate_config.rate_format = AUTO_RATE;
1839 else {
1840 /* fixed rate */
1841 tx_rate_config.rate_format =
1842 rate->param.rate_cfg.rate_format;
1843 tx_rate_config.rate = rate->param.rate_cfg.rate;
1844 if (rate->param.rate_cfg.rate_format ==
1845 MLAN_RATE_FORMAT_VHT ||
1846 rate->param.rate_cfg.rate_format ==
1847 MLAN_RATE_FORMAT_HE)
1848 tx_rate_config.nss = rate->param.rate_cfg.nss;
1849 tx_rate_config.rate_setting =
1850 rate->param.rate_cfg.rate_setting;
1851 }
1852 for (i = 0; i < MAX_BITMAP_RATES_SIZE; i++) {
1853 tx_rate_config.bitmap_rates[i] =
1854 rate->param.rate_cfg.bitmap_rates[i];
1855 }
1856
1857 if (copy_to_user(req->ifr_data, &tx_rate_config,
1858 sizeof(tx_rate_cfg_t))) {
1859 PRINTM(MERROR, "Copy to user failed\n");
1860 ret = -EFAULT;
1861 }
1862 }
1863 done:
1864 if (status != MLAN_STATUS_PENDING)
1865 kfree(mreq);
1866 LEAVE();
1867 return ret;
1868 }
1869
1870 /**
1871 * @brief Set/Get RF antenna mode
1872 *
1873 * @param dev A pointer to net_device structure
1874 * @param req A pointer to ifreq structure
1875 *
1876 * @return 0 --success, otherwise fail
1877 */
woal_uap_antenna_cfg(struct net_device * dev,struct ifreq * req)1878 static int woal_uap_antenna_cfg(struct net_device *dev, struct ifreq *req)
1879 {
1880 moal_private *priv = (moal_private *)netdev_priv(dev);
1881 int ret = 0;
1882 mlan_ds_radio_cfg *radio = NULL;
1883 mlan_ioctl_req *mreq = NULL;
1884 ant_cfg_t antenna_config;
1885 mlan_status status = MLAN_STATUS_SUCCESS;
1886
1887 ENTER();
1888
1889 /* Sanity check */
1890 if (req->ifr_data == NULL) {
1891 PRINTM(MERROR, "uap_antenna_cfg() corrupt data\n");
1892 ret = -EFAULT;
1893 goto done;
1894 }
1895
1896 memset(&antenna_config, 0, sizeof(ant_cfg_t));
1897 /* Get user data */
1898 if (copy_from_user(&antenna_config, req->ifr_data, sizeof(ant_cfg_t))) {
1899 PRINTM(MERROR, "Copy from user failed\n");
1900 ret = -EFAULT;
1901 goto done;
1902 }
1903 mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
1904 if (mreq == NULL) {
1905 ret = -ENOMEM;
1906 goto done;
1907 }
1908 radio = (mlan_ds_radio_cfg *)mreq->pbuf;
1909 radio->sub_command = MLAN_OID_ANT_CFG;
1910 mreq->req_id = MLAN_IOCTL_RADIO_CFG;
1911 if (!(antenna_config.action))
1912 mreq->action = MLAN_ACT_GET;
1913 else {
1914 mreq->action = MLAN_ACT_SET;
1915 radio->param.ant_cfg.tx_antenna = antenna_config.tx_mode;
1916 radio->param.ant_cfg.rx_antenna = antenna_config.rx_mode;
1917 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
1918 if (IS_CARD9098(priv->phandle->card_type) ||
1919 IS_CARD9097(priv->phandle->card_type)) {
1920 if (IS_STA_CFG80211(
1921 priv->phandle->params.cfg80211_wext))
1922 woal_cfg80211_notify_antcfg(
1923 priv, priv->phandle->wiphy, radio);
1924 }
1925 #endif
1926 }
1927
1928 status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
1929 if (status != MLAN_STATUS_SUCCESS) {
1930 ret = -EFAULT;
1931 goto done;
1932 }
1933 if (mreq->action == MLAN_ACT_GET) {
1934 antenna_config.tx_mode = radio->param.ant_cfg.tx_antenna;
1935 antenna_config.rx_mode = radio->param.ant_cfg.rx_antenna;
1936 if (copy_to_user(req->ifr_data, &antenna_config,
1937 sizeof(ant_cfg_t))) {
1938 PRINTM(MERROR, "Copy to user failed\n");
1939 ret = -EFAULT;
1940 }
1941 }
1942 done:
1943 if (status != MLAN_STATUS_PENDING)
1944 kfree(mreq);
1945 LEAVE();
1946 return ret;
1947 }
1948
1949 /**
1950 * @brief Set/Get HT stream configurations
1951 *
1952 * @param dev A pointer to net_device structure
1953 * @param req A pointer to ifreq structure
1954 *
1955 * @return 0 --success, otherwise fail
1956 */
woal_uap_htstream_cfg(struct net_device * dev,struct ifreq * req)1957 static int woal_uap_htstream_cfg(struct net_device *dev, struct ifreq *req)
1958 {
1959 moal_private *priv = (moal_private *)netdev_priv(dev);
1960 int ret = 0;
1961 mlan_ds_11n_cfg *cfg = NULL;
1962 mlan_ioctl_req *ioctl_req = NULL;
1963 htstream_cfg_t htstream_cfg;
1964 mlan_status status = MLAN_STATUS_SUCCESS;
1965
1966 ENTER();
1967
1968 memset(&htstream_cfg, 0, sizeof(htstream_cfg_t));
1969
1970 /* Sanity check */
1971 if (req->ifr_data == NULL) {
1972 PRINTM(MERROR, "woal_uap_htstream_cfg corrupt data\n");
1973 ret = -EFAULT;
1974 goto done;
1975 }
1976 if (copy_from_user(&htstream_cfg, req->ifr_data,
1977 sizeof(htstream_cfg_t))) {
1978 PRINTM(MERROR, "Copy from user failed\n");
1979 ret = -EFAULT;
1980 goto done;
1981 }
1982 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
1983 if (ioctl_req == NULL) {
1984 ret = -ENOMEM;
1985 goto done;
1986 }
1987 cfg = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
1988 cfg->sub_command = MLAN_OID_11N_CFG_STREAM_CFG;
1989 ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
1990
1991 if (!htstream_cfg.action) {
1992 /* Get operation */
1993 ioctl_req->action = MLAN_ACT_GET;
1994 } else {
1995 /* Update HT stream parameter in MLAN */
1996 ioctl_req->action = MLAN_ACT_SET;
1997 /* Set HT Stream configuration */
1998 cfg->param.stream_cfg = htstream_cfg.stream_cfg;
1999 PRINTM(MINFO, "SET: htstream_cfg:0x%x\n",
2000 cfg->param.stream_cfg);
2001 }
2002 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2003 if (status != MLAN_STATUS_SUCCESS) {
2004 ret = -EFAULT;
2005 goto done;
2006 }
2007 /* Copy to user */
2008 if (ioctl_req->action == MLAN_ACT_GET) {
2009 PRINTM(MINFO, "GET: htstream_cfg:0x%x\n",
2010 htstream_cfg.stream_cfg);
2011 htstream_cfg.stream_cfg = cfg->param.stream_cfg;
2012 if (copy_to_user(req->ifr_data, &htstream_cfg,
2013 sizeof(htstream_cfg_t))) {
2014 PRINTM(MERROR, "Copy to user failed!\n");
2015 ret = -EFAULT;
2016 goto done;
2017 }
2018 }
2019 done:
2020 if (status != MLAN_STATUS_PENDING)
2021 kfree(ioctl_req);
2022 LEAVE();
2023 return ret;
2024 }
2025
2026 /**
2027 * @brief Get DFS_REPEATER mode
2028 *
2029 * @param dev A pointer to net_device structure
2030 * @param req A pointer to ifreq structure
2031 *
2032 * @return 0 --success, otherwise fail
2033 */
woal_uap_dfs_repeater(struct net_device * dev,struct ifreq * req)2034 static int woal_uap_dfs_repeater(struct net_device *dev, struct ifreq *req)
2035 {
2036 moal_private *priv = (moal_private *)netdev_priv(dev);
2037 int ret = 0;
2038 dfs_repeater_mode param;
2039 mlan_ds_misc_cfg *misc = NULL;
2040 mlan_ioctl_req *mreq = NULL;
2041 mlan_status status = MLAN_STATUS_SUCCESS;
2042
2043 ENTER();
2044
2045 /* Sanity check */
2046 if (req->ifr_data == NULL) {
2047 PRINTM(MERROR, "uap_antenna_cfg() corrupt data\n");
2048 ret = -EFAULT;
2049 goto done;
2050 }
2051
2052 memset(¶m, 0, sizeof(dfs_repeater_mode));
2053 /* Get user data */
2054 if (copy_from_user(¶m, req->ifr_data, sizeof(dfs_repeater_mode))) {
2055 PRINTM(MERROR, "Copy from user failed\n");
2056 ret = -EFAULT;
2057 goto done;
2058 }
2059 mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2060 if (mreq == NULL) {
2061 ret = -ENOMEM;
2062 goto done;
2063 }
2064 misc = (mlan_ds_misc_cfg *)mreq->pbuf;
2065 misc->sub_command = MLAN_OID_MISC_DFS_REAPTER_MODE;
2066 mreq->req_id = MLAN_IOCTL_MISC_CFG;
2067 mreq->action = MLAN_ACT_GET;
2068
2069 status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
2070 if (status != MLAN_STATUS_SUCCESS) {
2071 ret = -EFAULT;
2072 goto done;
2073 }
2074 param.mode = misc->param.dfs_repeater.mode;
2075
2076 if (copy_to_user(req->ifr_data, ¶m, sizeof(dfs_repeater_mode))) {
2077 PRINTM(MERROR, "Copy to user failed\n");
2078 ret = -EFAULT;
2079 }
2080 done:
2081 if (status != MLAN_STATUS_PENDING)
2082 kfree(mreq);
2083 LEAVE();
2084 return ret;
2085 }
2086
2087 /**
2088 * @brief Issue MLAN_OID_11H_CHAN_REPORT_REQUEST ioctl to cancel dozer
2089 *
2090 * @param priv Pointer to the moal_private driver data struct
2091 * @param action MLAN_ACT_SET/MLAN_ACT_GET
2092 * @param
2093 *
2094 * @return 0 --success, otherwise fail
2095 */
woal_11h_chan_dfs_state(moal_private * priv,t_u8 action,mlan_ds_11h_chan_dfs_state * ch_dfs_state)2096 int woal_11h_chan_dfs_state(moal_private *priv, t_u8 action,
2097 mlan_ds_11h_chan_dfs_state *ch_dfs_state)
2098 {
2099 int ret = 0;
2100 mlan_ioctl_req *req = NULL;
2101 mlan_ds_11h_cfg *ds_11hcfg = NULL;
2102 mlan_status status = MLAN_STATUS_SUCCESS;
2103 #ifdef UAP_CFG80211
2104 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2105 int cfg80211_wext = priv->phandle->params.cfg80211_wext;
2106 #endif
2107 #endif
2108
2109 ENTER();
2110 #ifdef UAP_CFG80211
2111 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2112 if (action == MLAN_ACT_GET) {
2113 if (IS_UAP_CFG80211(cfg80211_wext)) {
2114 ret = woal_get_wiphy_chan_dfs_state(
2115 priv->phandle->wiphy, ch_dfs_state);
2116 if (!ret) {
2117 LEAVE();
2118 return ret;
2119 }
2120 }
2121 }
2122 #endif
2123 #endif
2124 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
2125 if (req == NULL) {
2126 ret = -ENOMEM;
2127 goto done;
2128 }
2129 ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
2130
2131 ds_11hcfg->sub_command = MLAN_OID_11H_CHAN_DFS_STATE;
2132 req->req_id = MLAN_IOCTL_11H_CFG;
2133 req->action = action;
2134 moal_memcpy_ext(priv->phandle, &ds_11hcfg->param.ch_dfs_state,
2135 ch_dfs_state, sizeof(mlan_ds_11h_chan_dfs_state),
2136 sizeof(ds_11hcfg->param.ch_dfs_state));
2137 /* Send Channel Check command and wait until the report is ready */
2138 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2139 if (status != MLAN_STATUS_SUCCESS) {
2140 ret = -EFAULT;
2141 goto done;
2142 }
2143 moal_memcpy_ext(priv->phandle, ch_dfs_state,
2144 &ds_11hcfg->param.ch_dfs_state,
2145 sizeof(mlan_ds_11h_chan_dfs_state),
2146 sizeof(mlan_ds_11h_chan_dfs_state));
2147 done:
2148 if (status != MLAN_STATUS_PENDING)
2149 kfree(req);
2150 LEAVE();
2151 return ret;
2152 }
2153
2154 /**
2155 * @brief find all bonded channel.
2156 *
2157 * @param pri_chan primary channel
2158 * @param bw channel bandwidth
2159 * @param ch_dfs_state a pointer to mlan_ds_11h_chan_dfs_state array
2160 *
2161 * @return number of channel
2162 */
woal_uap_get_dfs_chan(t_u8 pri_chan,t_u8 bw,mlan_ds_11h_chan_dfs_state * ch_dfs_state)2163 static int woal_uap_get_dfs_chan(t_u8 pri_chan, t_u8 bw,
2164 mlan_ds_11h_chan_dfs_state *ch_dfs_state)
2165 {
2166 int ht40_plus[] = {52, 60, 100, 108, 116, 124, 132, 140};
2167 int ht40_minus[] = {56, 64, 104, 112, 120, 128, 136, 144};
2168 int vht80_dfs[4][4] = {{52, 56, 60, 64},
2169 {100, 104, 108, 112},
2170 {116, 120, 124, 128},
2171 {132, 136, 140, 144}};
2172 t_u8 find = false;
2173 int i, j;
2174 t_u8 sec_chan = 0;
2175 mlan_ds_11h_chan_dfs_state *pos = ch_dfs_state;
2176 t_u8 n_chan = 1;
2177
2178 if (bw == CHAN_BW_20MHZ) {
2179 pos->channel = pri_chan;
2180 } else if (bw == CHAN_BW_40MHZ) {
2181 pos->channel = pri_chan;
2182 pos++;
2183 for (i = 0; i < (sizeof(ht40_minus) / sizeof(int)); i++) {
2184 if (pri_chan == (t_u8)ht40_plus[i]) {
2185 sec_chan = pri_chan + 4;
2186 n_chan = 2;
2187 break;
2188 }
2189 }
2190 for (i = 0; i < (sizeof(ht40_minus) / sizeof(int)); i++) {
2191 if (pri_chan == (t_u8)ht40_minus[i]) {
2192 sec_chan = pri_chan - 4;
2193 n_chan = 2;
2194 break;
2195 }
2196 }
2197 pos->channel = sec_chan;
2198 } else if (bw == CHAN_BW_80MHZ) {
2199 for (i = 0; i < 4; i++) {
2200 for (j = 0; j < 4; j++) {
2201 if (pri_chan == (t_u8)vht80_dfs[i][j]) {
2202 find = true;
2203 break;
2204 }
2205 }
2206 if (find)
2207 break;
2208 }
2209 if (find) {
2210 n_chan = 4;
2211 for (j = 0; j < n_chan; j++) {
2212 pos->channel = (t_u8)vht80_dfs[i][j];
2213 pos++;
2214 }
2215 }
2216 }
2217 return n_chan;
2218 }
2219
2220 #ifdef UAP_CFG80211
2221 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2222 /**
2223 * @brief update channel dfs state to all wiphy
2224 *
2225 * @param channel given radar channel
2226 * @param bandwidth channel's bandwidth
2227 * @param dfs_state dfs_state
2228 *
2229 * @return N/A
2230 */
woal_update_channels_dfs_state(moal_private * priv,t_u8 channel,t_u8 bandwidth,t_u8 dfs_state)2231 void woal_update_channels_dfs_state(moal_private *priv, t_u8 channel,
2232 t_u8 bandwidth, t_u8 dfs_state)
2233 {
2234 mlan_ds_11h_chan_dfs_state ch_dfs_state[4];
2235 int cfg80211_wext = priv->phandle->params.cfg80211_wext;
2236 t_u8 n_chan;
2237 int i;
2238 ENTER();
2239 memset(ch_dfs_state, 0, sizeof(ch_dfs_state));
2240 n_chan = woal_uap_get_dfs_chan(channel, bandwidth, &ch_dfs_state[0]);
2241 if (IS_UAP_CFG80211(cfg80211_wext)) {
2242 for (i = 0; i < n_chan; i++) {
2243 woal_update_channel_dfs_state(ch_dfs_state[i].channel,
2244 dfs_state);
2245 }
2246 }
2247 LEAVE();
2248 return;
2249 }
2250 #endif
2251 #endif
2252
2253 /**
2254 * @brief skip cac on specific channel
2255 * @and Wext
2256 *
2257 * @param dev A pointer to net_device structure
2258 * @param req A pointer to ifreq structure
2259 *
2260 * @return 0 --success, otherwise fail
2261 */
woal_uap_skip_cac(struct net_device * dev,struct ifreq * req)2262 static int woal_uap_skip_cac(struct net_device *dev, struct ifreq *req)
2263 {
2264 int ret = 0;
2265 skip_cac_para param;
2266 moal_private *priv = (moal_private *)netdev_priv(dev);
2267 #ifdef UAP_CFG80211
2268 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2269 int cfg80211_wext = priv->phandle->params.cfg80211_wext;
2270 #endif
2271 #endif
2272 dfs_state_t dfs_state;
2273 mlan_ds_11h_chan_dfs_state ch_dfs_state[4];
2274 t_u8 n_chan;
2275 int i = 0;
2276 ENTER();
2277
2278 /* Sanity check */
2279 if (req->ifr_data == NULL) {
2280 PRINTM(MERROR, "skip_dfs_cac() corrupt data\n");
2281 ret = -EFAULT;
2282 goto done;
2283 }
2284 memset(¶m, 0, sizeof(skip_cac_para));
2285 /* Get user data */
2286 if (copy_from_user(¶m, req->ifr_data, sizeof(skip_cac_para))) {
2287 PRINTM(MERROR, "Copy from user failed\n");
2288 ret = -EFAULT;
2289 goto done;
2290 }
2291 if (param.skip_cac)
2292 dfs_state = DFS_AVAILABLE;
2293 else
2294 dfs_state = DFS_USABLE;
2295 memset(&ch_dfs_state, 0, sizeof(ch_dfs_state));
2296 n_chan = woal_uap_get_dfs_chan(param.channel, param.bw,
2297 &ch_dfs_state[0]);
2298 for (i = 0; i < n_chan; i++) {
2299 if (woal_11h_chan_dfs_state(priv, MLAN_ACT_GET,
2300 &ch_dfs_state[i]))
2301 PRINTM(MERROR, "Get DFS state for chan:%d failed\n",
2302 ch_dfs_state[i].channel);
2303 }
2304 for (i = 0; i < n_chan; i++) {
2305 if (param.skip_cac && ch_dfs_state[i].dfs_state == DFS_USABLE)
2306 PRINTM(MMSG,
2307 "DFS: Requst skip cac on the channel %d which hasn't do CAC before!\n",
2308 ch_dfs_state[i].channel);
2309 ch_dfs_state[i].dfs_state = dfs_state;
2310 if (woal_11h_chan_dfs_state(priv, MLAN_ACT_SET,
2311 &ch_dfs_state[i]))
2312 PRINTM(MERROR, "Set DFS state for chan:%d failed\n",
2313 ch_dfs_state[i].channel);
2314 else
2315 PRINTM(MCMND, "DFS: Skip CAC on chan %d %d\n",
2316 ch_dfs_state[i].channel, param.skip_cac);
2317 }
2318 #ifdef UAP_CFG80211
2319 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2320 if (IS_UAP_CFG80211(cfg80211_wext)) {
2321 for (i = 0; i < n_chan; i++) {
2322 if (param.skip_cac)
2323 woal_update_channel_dfs_state(
2324 ch_dfs_state[i].channel, DFS_AVAILABLE);
2325 else
2326 woal_update_channel_dfs_state(
2327 ch_dfs_state[i].channel, DFS_USABLE);
2328 }
2329 }
2330 #endif
2331 #endif
2332 done:
2333 LEAVE();
2334 return ret;
2335 }
2336
2337 /**
2338 * @brief Get DFS_REPEATER mode
2339 *
2340 * @param dev A pointer to net_device structure
2341 * @param req A pointer to ifreq structure
2342 *
2343 * @return 0 --success, otherwise fail
2344 */
woal_uap_cac_timer_status(struct net_device * dev,struct ifreq * req)2345 static int woal_uap_cac_timer_status(struct net_device *dev, struct ifreq *req)
2346 {
2347 moal_private *priv = (moal_private *)netdev_priv(dev);
2348 int ret = 0;
2349 cac_timer_status param;
2350 mlan_status status = MLAN_STATUS_SUCCESS;
2351
2352 ENTER();
2353
2354 /* Sanity check */
2355 if (req->ifr_data == NULL) {
2356 PRINTM(MERROR, "uap_antenna_cfg() corrupt data\n");
2357 ret = -EFAULT;
2358 goto done;
2359 }
2360
2361 memset(¶m, 0, sizeof(cac_timer_status));
2362
2363 /* Get user data */
2364 if (copy_from_user(¶m, req->ifr_data, sizeof(cac_timer_status))) {
2365 PRINTM(MERROR, "Copy from user failed\n");
2366 ret = -EFAULT;
2367 goto done;
2368 }
2369
2370 /* Currently default action is get */
2371 param.mode = 0;
2372
2373 if (priv->phandle->cac_period == MTRUE) {
2374 long cac_left_jiffies;
2375
2376 cac_left_jiffies =
2377 MEAS_REPORT_TIME -
2378 (jiffies - priv->phandle->meas_start_jiffies);
2379
2380 /* cac_left_jiffies would be negative if timer has already
2381 * elapsed. positive if timer is still yet to lapsed
2382 */
2383 if (cac_left_jiffies > 0)
2384 param.mode = (t_u32)cac_left_jiffies / HZ;
2385 }
2386
2387 if (copy_to_user(req->ifr_data, ¶m, sizeof(cac_timer_status))) {
2388 PRINTM(MERROR, "Copy to user failed\n");
2389 ret = -EFAULT;
2390 }
2391 done:
2392 if (status != MLAN_STATUS_PENDING)
2393 LEAVE();
2394 return ret;
2395 }
2396
2397 /**
2398 * @brief set/get uap operation control
2399 *
2400 * @param dev A pointer to net_device structure
2401 * @param req A pointer to ifreq structure
2402 *
2403 * @return 0 --success, otherwise fail
2404 */
woal_uap_operation_ctrl(struct net_device * dev,struct ifreq * req)2405 static int woal_uap_operation_ctrl(struct net_device *dev, struct ifreq *req)
2406 {
2407 int ret = 0;
2408 moal_private *priv = (moal_private *)netdev_priv(dev);
2409 mlan_uap_oper_ctrl uap_oper;
2410 uap_oper_para_hdr param;
2411 mlan_ds_bss *bss = NULL;
2412 mlan_ioctl_req *ioctl_req = NULL;
2413 mlan_status status = MLAN_STATUS_SUCCESS;
2414
2415 ENTER();
2416
2417 memset(¶m, 0, sizeof(uap_oper_para_hdr));
2418 memset(&uap_oper, 0, sizeof(mlan_uap_oper_ctrl));
2419
2420 /* Sanity check */
2421 if (req->ifr_data == NULL) {
2422 PRINTM(MERROR, "woal_uap_operation_ctrl corrupt data\n");
2423 ret = -EFAULT;
2424 goto done;
2425 }
2426 if (copy_from_user(¶m, req->ifr_data, sizeof(uap_oper_para_hdr))) {
2427 PRINTM(MERROR, "Copy from user failed\n");
2428 ret = -EFAULT;
2429 goto done;
2430 }
2431 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
2432 if (ioctl_req == NULL) {
2433 ret = MLAN_STATUS_FAILURE;
2434 goto done;
2435 }
2436
2437 bss = (mlan_ds_bss *)ioctl_req->pbuf;
2438 bss->sub_command = MLAN_OID_UAP_OPER_CTRL;
2439 ioctl_req->req_id = MLAN_IOCTL_BSS;
2440 if (copy_from_user(&uap_oper, req->ifr_data + sizeof(uap_oper_para_hdr),
2441 sizeof(mlan_uap_oper_ctrl))) {
2442 PRINTM(MERROR, "Copy from user failed\n");
2443 ret = -EFAULT;
2444 goto done;
2445 }
2446 if (!param.action) {
2447 /* Get uap operation control parameters from FW */
2448 ioctl_req->action = MLAN_ACT_GET;
2449 } else {
2450 /* Set uap operation control configurations */
2451 ioctl_req->action = MLAN_ACT_SET;
2452 bss->param.ap_oper_ctrl.ctrl_value = uap_oper.ctrl_value;
2453 if (uap_oper.ctrl_value == 2)
2454 bss->param.ap_oper_ctrl.chan_opt = uap_oper.chan_opt;
2455 if (uap_oper.chan_opt == 3) {
2456 bss->param.ap_oper_ctrl.band_cfg = uap_oper.band_cfg;
2457 bss->param.ap_oper_ctrl.channel = uap_oper.channel;
2458 }
2459 }
2460 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2461 if (status != MLAN_STATUS_SUCCESS) {
2462 ret = -EFAULT;
2463 goto done;
2464 }
2465
2466 /* Copy to user */
2467 if (copy_to_user(req->ifr_data + sizeof(uap_oper_para_hdr),
2468 &bss->param.ap_oper_ctrl,
2469 sizeof(mlan_uap_oper_ctrl))) {
2470 PRINTM(MERROR, "Copy to user failed!\n");
2471 ret = -EFAULT;
2472 goto done;
2473 }
2474 done:
2475 if (status != MLAN_STATUS_PENDING)
2476 kfree(ioctl_req);
2477 LEAVE();
2478 return ret;
2479 }
2480
2481 /**
2482 * @brief uap ioctl handler
2483 *
2484 * @param dev A pointer to net_device structure
2485 * @param req A pointer to ifreq structure
2486 * @return 0 --success, otherwise fail
2487 */
woal_uap_ioctl(struct net_device * dev,struct ifreq * req)2488 static int woal_uap_ioctl(struct net_device *dev, struct ifreq *req)
2489 {
2490 int ret = 0;
2491 t_u32 subcmd = 0;
2492 ENTER();
2493 /* Sanity check */
2494 if (req->ifr_data == NULL) {
2495 PRINTM(MERROR, "uap_ioctl() corrupt data\n");
2496 ret = -EFAULT;
2497 goto done;
2498 }
2499 if (copy_from_user(&subcmd, req->ifr_data, sizeof(subcmd))) {
2500 PRINTM(MERROR, "Copy from user failed\n");
2501 ret = -EFAULT;
2502 goto done;
2503 }
2504
2505 PRINTM(MIOCTL, "ioctl subcmd=%d\n", (int)subcmd);
2506 switch (subcmd) {
2507 case UAP_ADDBA_PARA:
2508 ret = woal_uap_addba_param(dev, req);
2509 break;
2510 case UAP_AGGR_PRIOTBL:
2511 ret = woal_uap_aggr_priotbl(dev, req);
2512 break;
2513 case UAP_ADDBA_REJECT:
2514 ret = woal_uap_addba_reject(dev, req);
2515 break;
2516 case UAP_FW_INFO:
2517 ret = woal_uap_get_fw_info(dev, req);
2518 break;
2519 case UAP_DEEP_SLEEP:
2520 ret = woal_uap_deep_sleep(dev, req);
2521 break;
2522 case UAP_TX_DATA_PAUSE:
2523 ret = woal_uap_txdatapause(dev, req);
2524 break;
2525 #ifdef SDIO
2526 case UAP_SDCMD52_RW:
2527 ret = woal_uap_sdcmd52_rw(dev, req);
2528 break;
2529 #endif
2530 case UAP_SNMP_MIB:
2531 ret = woal_uap_snmp_mib(dev, req);
2532 break;
2533 case UAP_DFS_TESTING:
2534 ret = woal_uap_dfs_testing(dev, req);
2535 break;
2536 case UAP_CHAN_SWITCH_COUNT_CFG:
2537 ret = woal_uap_chan_switch_count_cfg(dev, req);
2538 break;
2539 case UAP_DOMAIN_INFO:
2540 ret = woal_uap_domain_info(dev, req);
2541 break;
2542 case UAP_TX_BF_CFG:
2543 ret = woal_uap_tx_bf_cfg(dev, req);
2544 break;
2545 case UAP_HT_TX_CFG:
2546 ret = woal_uap_ht_tx_cfg(dev, req);
2547 break;
2548 case UAP_VHT_CFG:
2549 ret = woal_uap_vht_cfg(dev, req);
2550 break;
2551 case UAP_HS_CFG:
2552 ret = woal_uap_hs_cfg(dev, req, MTRUE);
2553 break;
2554 case UAP_HS_SET_PARA:
2555 ret = woal_uap_hs_set_para(dev, req);
2556 break;
2557 case UAP_MGMT_FRAME_CONTROL:
2558 ret = woal_uap_mgmt_frame_control(dev, req);
2559 break;
2560 case UAP_TX_RATE_CFG:
2561 ret = woal_uap_tx_rate_cfg(dev, req);
2562 break;
2563 case UAP_ANTENNA_CFG:
2564 ret = woal_uap_antenna_cfg(dev, req);
2565 break;
2566 case UAP_HT_STREAM_CFG:
2567 ret = woal_uap_htstream_cfg(dev, req);
2568 break;
2569 case UAP_DFS_REPEATER_MODE:
2570 ret = woal_uap_dfs_repeater(dev, req);
2571 break;
2572 case UAP_CAC_TIMER_STATUS:
2573 ret = woal_uap_cac_timer_status(dev, req);
2574 break;
2575 case UAP_SKIP_CAC:
2576 ret = woal_uap_skip_cac(dev, req);
2577 break;
2578 case UAP_OPERATION_CTRL:
2579 ret = woal_uap_operation_ctrl(dev, req);
2580 break;
2581 case UAP_BAND_STEER:
2582 ret = woal_uap_band_steer(dev, req);
2583 break;
2584 case UAP_BEACON_STUCK_DETECT:
2585 ret = woal_uap_beacon_stuck(dev, req);
2586 break;
2587 default:
2588 break;
2589 }
2590 done:
2591 LEAVE();
2592 return ret;
2593 }
2594
2595 /**
2596 * @brief uap station deauth ioctl handler
2597 *
2598 * @param dev A pointer to net_device structure
2599 * @param req A pointer to ifreq structure
2600 * @return 0 --success, otherwise fail
2601 */
woal_uap_sta_deauth_ioctl(struct net_device * dev,struct ifreq * req)2602 static int woal_uap_sta_deauth_ioctl(struct net_device *dev, struct ifreq *req)
2603 {
2604 moal_private *priv = (moal_private *)netdev_priv(dev);
2605 mlan_ioctl_req *ioctl_req = NULL;
2606 mlan_ds_bss *bss = NULL;
2607 mlan_deauth_param deauth_param;
2608 int ret = 0;
2609 mlan_status status = MLAN_STATUS_SUCCESS;
2610
2611 ENTER();
2612
2613 memset(&deauth_param, 0, sizeof(mlan_deauth_param));
2614 /* Sanity check */
2615 if (req->ifr_data == NULL) {
2616 PRINTM(MERROR, "uap_sta_deauth_ioctl() corrupt data\n");
2617 ret = -EFAULT;
2618 goto done;
2619 }
2620 if (copy_from_user(&deauth_param, req->ifr_data,
2621 sizeof(mlan_deauth_param))) {
2622 PRINTM(MERROR, "Copy from user failed\n");
2623 ret = -EFAULT;
2624 goto done;
2625 }
2626
2627 PRINTM(MIOCTL, "ioctl deauth station: " MACSTR ", reason=%d\n",
2628 MAC2STR(deauth_param.mac_addr), deauth_param.reason_code);
2629
2630 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
2631 if (ioctl_req == NULL) {
2632 ret = -ENOMEM;
2633 goto done;
2634 }
2635 bss = (mlan_ds_bss *)ioctl_req->pbuf;
2636
2637 bss->sub_command = MLAN_OID_UAP_DEAUTH_STA;
2638 ioctl_req->req_id = MLAN_IOCTL_BSS;
2639 ioctl_req->action = MLAN_ACT_SET;
2640
2641 moal_memcpy_ext(priv->phandle, &bss->param.deauth_param, &deauth_param,
2642 sizeof(mlan_deauth_param),
2643 sizeof(bss->param.deauth_param));
2644 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2645 if (status != MLAN_STATUS_SUCCESS) {
2646 ret = -EFAULT;
2647 if (copy_to_user(req->ifr_data, &ioctl_req->status_code,
2648 sizeof(t_u32)))
2649 PRINTM(MERROR, "Copy to user failed!\n");
2650 goto done;
2651 }
2652
2653 done:
2654 if (status != MLAN_STATUS_PENDING)
2655 kfree(ioctl_req);
2656 LEAVE();
2657 return ret;
2658 }
2659
2660 /**
2661 * @brief Set/Get radio
2662 *
2663 * @param dev A pointer to net_device structure
2664 * @param req A pointer to ifreq structure
2665 *
2666 * @return 0 --success, otherwise fail
2667 */
woal_uap_radio_ctl(struct net_device * dev,struct ifreq * req)2668 static int woal_uap_radio_ctl(struct net_device *dev, struct ifreq *req)
2669 {
2670 moal_private *priv = (moal_private *)netdev_priv(dev);
2671 int ret = 0;
2672 mlan_ds_radio_cfg *radio = NULL;
2673 mlan_ioctl_req *mreq = NULL;
2674 int data[2] = {0, 0};
2675 mlan_bss_info bss_info;
2676 mlan_status status = MLAN_STATUS_SUCCESS;
2677
2678 ENTER();
2679
2680 /* Sanity check */
2681 if (req->ifr_data == NULL) {
2682 PRINTM(MERROR, "uap_radio_ctl() corrupt data\n");
2683 ret = -EFAULT;
2684 goto done;
2685 }
2686
2687 /* Get user data */
2688 if (copy_from_user(&data, req->ifr_data, sizeof(data))) {
2689 PRINTM(MERROR, "Copy from user failed\n");
2690 ret = -EFAULT;
2691 goto done;
2692 }
2693
2694 if (data[0]) {
2695 mreq = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
2696 if (mreq == NULL) {
2697 ret = -ENOMEM;
2698 goto done;
2699 }
2700 radio = (mlan_ds_radio_cfg *)mreq->pbuf;
2701 radio->sub_command = MLAN_OID_RADIO_CTRL;
2702 mreq->req_id = MLAN_IOCTL_RADIO_CFG;
2703 mreq->action = MLAN_ACT_SET;
2704 radio->param.radio_on_off = (t_u32)data[1];
2705 status = woal_request_ioctl(priv, mreq, MOAL_IOCTL_WAIT);
2706 if (status != MLAN_STATUS_SUCCESS)
2707 ret = -EFAULT;
2708 if (status != MLAN_STATUS_PENDING)
2709 kfree(mreq);
2710 } else {
2711 /* Get radio status */
2712 memset(&bss_info, 0, sizeof(bss_info));
2713 woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
2714
2715 data[1] = bss_info.radio_on;
2716 if (copy_to_user(req->ifr_data, data, sizeof(data))) {
2717 PRINTM(MERROR, "Copy to user failed\n");
2718 ret = -EFAULT;
2719 }
2720 }
2721 done:
2722 LEAVE();
2723 return ret;
2724 }
2725
2726 /**
2727 * @brief uap bss control ioctl handler
2728 *
2729 * @param dev A pointer to net_device structure
2730 * @param req A pointer to ifreq structure
2731 * @return 0 --success, otherwise fail
2732 */
woal_uap_bss_ctrl_ioctl(struct net_device * dev,struct ifreq * req)2733 static int woal_uap_bss_ctrl_ioctl(struct net_device *dev, struct ifreq *req)
2734 {
2735 moal_private *priv = (moal_private *)netdev_priv(dev);
2736 int ret = 0, data = 0;
2737
2738 ENTER();
2739
2740 /* Sanity check */
2741 if (req->ifr_data == NULL) {
2742 PRINTM(MERROR, "uap_bss_ctrl() corrupt data\n");
2743 ret = -EFAULT;
2744 goto done;
2745 }
2746 if (copy_from_user(&data, req->ifr_data, sizeof(data))) {
2747 PRINTM(MERROR, "Copy from user failed\n");
2748 ret = -EFAULT;
2749 goto done;
2750 }
2751
2752 ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, data);
2753
2754 done:
2755 LEAVE();
2756 return ret;
2757 }
2758
2759 /**
2760 * @brief uap report mic error ioctl handler
2761 *
2762 * @param dev A pointer to net_device structure
2763 * @param req A pointer to ifreq structure
2764 * @return 0 --success, otherwise fail
2765 */
woal_uap_report_mic_ioctl(struct net_device * dev,struct ifreq * req)2766 static int woal_uap_report_mic_ioctl(struct net_device *dev, struct ifreq *req)
2767 {
2768 moal_private *priv = (moal_private *)netdev_priv(dev);
2769 mlan_ioctl_req *ioctl_req = NULL;
2770 mlan_ds_sec_cfg *sec = NULL;
2771 t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH];
2772 int ret = 0;
2773 mlan_status status = MLAN_STATUS_SUCCESS;
2774
2775 ENTER();
2776
2777 memset(mac_addr, 0, MLAN_MAC_ADDR_LENGTH);
2778 /* Sanity check */
2779 if (req->ifr_data == NULL) {
2780 PRINTM(MERROR, "uap_report_mic_ioctl() corrupt data\n");
2781 ret = -EFAULT;
2782 goto done;
2783 }
2784 if (copy_from_user(mac_addr, req->ifr_data, MLAN_MAC_ADDR_LENGTH)) {
2785 PRINTM(MERROR, "Copy from user failed\n");
2786 ret = -EFAULT;
2787 goto done;
2788 }
2789
2790 PRINTM(MINFO, "ioctl report mic err station: " MACSTR "\n",
2791 MAC2STR(mac_addr));
2792
2793 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
2794 if (ioctl_req == NULL) {
2795 ret = -ENOMEM;
2796 goto done;
2797 }
2798
2799 sec = (mlan_ds_sec_cfg *)ioctl_req->pbuf;
2800 sec->sub_command = MLAN_OID_SEC_CFG_REPORT_MIC_ERR;
2801 ioctl_req->req_id = MLAN_IOCTL_SEC_CFG;
2802 ioctl_req->action = MLAN_ACT_SET;
2803 moal_memcpy_ext(priv->phandle, sec->param.sta_mac, mac_addr,
2804 MLAN_MAC_ADDR_LENGTH, sizeof(sec->param.sta_mac));
2805
2806 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2807 if (status != MLAN_STATUS_SUCCESS) {
2808 ret = -EFAULT;
2809 goto done;
2810 }
2811
2812 done:
2813 if (status != MLAN_STATUS_PENDING)
2814 kfree(ioctl_req);
2815 LEAVE();
2816 return ret;
2817 }
2818
2819 /**
2820 * @brief uap set key ioctl handler
2821 *
2822 * @param dev A pointer to net_device structure
2823 * @param req A pointer to ifreq structure
2824 * @return 0 --success, otherwise fail
2825 */
woal_uap_set_key_ioctl(struct net_device * dev,struct ifreq * req)2826 static int woal_uap_set_key_ioctl(struct net_device *dev, struct ifreq *req)
2827 {
2828 moal_private *priv = (moal_private *)netdev_priv(dev);
2829 mlan_ioctl_req *ioctl_req = NULL;
2830 mlan_ds_sec_cfg *sec = NULL;
2831 encrypt_key key;
2832 int ret = 0;
2833 t_u8 bcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2834 mlan_status status = MLAN_STATUS_SUCCESS;
2835
2836 ENTER();
2837
2838 memset(&key, 0, sizeof(encrypt_key));
2839 /* Sanity check */
2840 if (req->ifr_data == NULL) {
2841 PRINTM(MERROR, "uap_set_key_ioctl() corrupt data\n");
2842 ret = -EFAULT;
2843 goto done;
2844 }
2845 if (copy_from_user(&key, req->ifr_data, sizeof(encrypt_key))) {
2846 PRINTM(MERROR, "Copy from user failed\n");
2847 ret = -EFAULT;
2848 goto done;
2849 }
2850
2851 PRINTM(MIOCTL,
2852 "ioctl report set key: " MACSTR " key_index=%d, key_len=%d \n",
2853 MAC2STR(key.mac_addr), (int)key.key_index, (int)key.key_len);
2854
2855 if ((key.key_len > MLAN_MAX_KEY_LENGTH) || (key.key_index > 3)) {
2856 ret = -EINVAL;
2857 goto done;
2858 }
2859
2860 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
2861 if (ioctl_req == NULL) {
2862 ret = -ENOMEM;
2863 goto done;
2864 }
2865
2866 sec = (mlan_ds_sec_cfg *)ioctl_req->pbuf;
2867 sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY,
2868 ioctl_req->req_id = MLAN_IOCTL_SEC_CFG;
2869 ioctl_req->action = MLAN_ACT_SET;
2870
2871 moal_memcpy_ext(priv->phandle, sec->param.encrypt_key.mac_addr,
2872 key.mac_addr, MLAN_MAC_ADDR_LENGTH,
2873 sizeof(sec->param.encrypt_key.mac_addr));
2874 sec->param.encrypt_key.key_index = key.key_index;
2875 sec->param.encrypt_key.key_len = key.key_len;
2876 moal_memcpy_ext(priv->phandle, sec->param.encrypt_key.key_material,
2877 key.key_material, key.key_len,
2878 sizeof(sec->param.encrypt_key.key_material));
2879 if (0 == memcmp(sec->param.encrypt_key.mac_addr, bcast_addr, ETH_ALEN))
2880 sec->param.encrypt_key.key_flags = KEY_FLAG_GROUP_KEY;
2881 else
2882 sec->param.encrypt_key.key_flags = KEY_FLAG_SET_TX_KEY;
2883
2884 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2885 if (status != MLAN_STATUS_SUCCESS) {
2886 ret = -EFAULT;
2887 goto done;
2888 }
2889 done:
2890 if (status != MLAN_STATUS_PENDING)
2891 kfree(ioctl_req);
2892 LEAVE();
2893 return ret;
2894 }
2895
2896 /**
2897 * @brief Set/Get uap power mode
2898 *
2899 * @param priv A pointer to moal_private structure
2900 * @param action Action set or get
2901 * @param ps_mgmt A pointer to mlan_ds_ps_mgmt structure
2902 *
2903 * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
2904 */
woal_set_get_uap_power_mode(moal_private * priv,t_u32 action,mlan_ds_ps_mgmt * ps_mgmt)2905 mlan_status woal_set_get_uap_power_mode(moal_private *priv, t_u32 action,
2906 mlan_ds_ps_mgmt *ps_mgmt)
2907 {
2908 mlan_ioctl_req *ioctl_req = NULL;
2909 mlan_ds_pm_cfg *pm_cfg = NULL;
2910 mlan_status status = MLAN_STATUS_SUCCESS;
2911
2912 ENTER();
2913 if (!ps_mgmt) {
2914 LEAVE();
2915 return MLAN_STATUS_FAILURE;
2916 }
2917
2918 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
2919 if (ioctl_req == NULL) {
2920 LEAVE();
2921 return MLAN_STATUS_FAILURE;
2922 }
2923 pm_cfg = (mlan_ds_pm_cfg *)ioctl_req->pbuf;
2924 pm_cfg->sub_command = MLAN_OID_PM_CFG_PS_MODE;
2925 ioctl_req->req_id = MLAN_IOCTL_PM_CFG;
2926 ioctl_req->action = action;
2927 if (action == MLAN_ACT_SET)
2928 moal_memcpy_ext(priv->phandle, &pm_cfg->param.ps_mgmt, ps_mgmt,
2929 sizeof(mlan_ds_ps_mgmt),
2930 sizeof(pm_cfg->param.ps_mgmt));
2931 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2932 if (status == MLAN_STATUS_SUCCESS) {
2933 if (action == MLAN_ACT_GET)
2934 moal_memcpy_ext(priv->phandle, ps_mgmt,
2935 &pm_cfg->param.ps_mgmt,
2936 sizeof(mlan_ds_ps_mgmt),
2937 sizeof(mlan_ds_ps_mgmt));
2938 }
2939 if (status != MLAN_STATUS_PENDING)
2940 kfree(ioctl_req);
2941 LEAVE();
2942 return status;
2943 }
2944
2945 /**
2946 * @brief uap power mode ioctl handler
2947 *
2948 * @param dev A pointer to net_device structure
2949 * @param req A pointer to ifreq structure
2950 * @return 0 --success, otherwise fail
2951 */
woal_uap_power_mode_ioctl(struct net_device * dev,struct ifreq * req)2952 static int woal_uap_power_mode_ioctl(struct net_device *dev, struct ifreq *req)
2953 {
2954 moal_private *priv = (moal_private *)netdev_priv(dev);
2955 mlan_ioctl_req *ioctl_req = NULL;
2956 mlan_ds_pm_cfg *pm_cfg = NULL;
2957 mlan_ds_ps_mgmt ps_mgmt;
2958 int ret = 0;
2959 mlan_status status = MLAN_STATUS_SUCCESS;
2960
2961 ENTER();
2962
2963 memset(&ps_mgmt, 0, sizeof(mlan_ds_ps_mgmt));
2964
2965 /* Sanity check */
2966 if (req->ifr_data == NULL) {
2967 PRINTM(MERROR, "uap_power_mode_ioctl() corrupt data\n");
2968 ret = -EFAULT;
2969 goto done;
2970 }
2971 if (copy_from_user(&ps_mgmt, req->ifr_data, sizeof(mlan_ds_ps_mgmt))) {
2972 PRINTM(MERROR, "Copy from user failed\n");
2973 ret = -EFAULT;
2974 goto done;
2975 }
2976 if (priv->bss_type != MLAN_BSS_TYPE_UAP) {
2977 PRINTM(MERROR, "Invlaid BSS_TYPE for UAP power mode command\n");
2978 ret = -EFAULT;
2979 goto done;
2980 }
2981 PRINTM(MIOCTL,
2982 "ioctl power: flag=0x%x ps_mode=%d ctrl_bitmap=%d min_sleep=%d max_sleep=%d "
2983 "inact_to=%d min_awake=%d max_awake=%d\n",
2984 ps_mgmt.flags, (int)ps_mgmt.ps_mode,
2985 (int)ps_mgmt.sleep_param.ctrl_bitmap,
2986 (int)ps_mgmt.sleep_param.min_sleep,
2987 (int)ps_mgmt.sleep_param.max_sleep,
2988 (int)ps_mgmt.inact_param.inactivity_to,
2989 (int)ps_mgmt.inact_param.min_awake,
2990 (int)ps_mgmt.inact_param.max_awake);
2991
2992 if (ps_mgmt.flags & ~(PS_FLAG_PS_MODE | PS_FLAG_SLEEP_PARAM |
2993 PS_FLAG_INACT_SLEEP_PARAM)) {
2994 PRINTM(MERROR, "Invalid parameter: flags = 0x%x\n",
2995 ps_mgmt.flags);
2996 ret = -EINVAL;
2997 goto done;
2998 }
2999
3000 if (ps_mgmt.ps_mode > PS_MODE_INACTIVITY) {
3001 PRINTM(MERROR, "Invalid parameter: ps_mode = %d\n",
3002 (int)ps_mgmt.flags);
3003 ret = -EINVAL;
3004 goto done;
3005 }
3006
3007 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
3008 if (ioctl_req == NULL) {
3009 ret = -ENOMEM;
3010 goto done;
3011 }
3012 pm_cfg = (mlan_ds_pm_cfg *)ioctl_req->pbuf;
3013 pm_cfg->sub_command = MLAN_OID_PM_CFG_PS_MODE;
3014 ioctl_req->req_id = MLAN_IOCTL_PM_CFG;
3015 if (ps_mgmt.flags) {
3016 ioctl_req->action = MLAN_ACT_SET;
3017 moal_memcpy_ext(priv->phandle, &pm_cfg->param.ps_mgmt, &ps_mgmt,
3018 sizeof(mlan_ds_ps_mgmt),
3019 sizeof(pm_cfg->param.ps_mgmt));
3020 } else {
3021 ioctl_req->action = MLAN_ACT_GET;
3022 }
3023
3024 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
3025 if (status != MLAN_STATUS_SUCCESS) {
3026 ret = -EFAULT;
3027 if (copy_to_user(req->ifr_data, &ioctl_req->status_code,
3028 sizeof(t_u32)))
3029 PRINTM(MERROR, "Copy to user failed!\n");
3030 goto done;
3031 }
3032 if (!ps_mgmt.flags) {
3033 /* Copy to user */
3034 if (copy_to_user(req->ifr_data, &pm_cfg->param.ps_mgmt,
3035 sizeof(mlan_ds_ps_mgmt))) {
3036 PRINTM(MERROR, "Copy to user failed!\n");
3037 ret = -EFAULT;
3038 goto done;
3039 }
3040 }
3041 done:
3042 if (status != MLAN_STATUS_PENDING)
3043 kfree(ioctl_req);
3044 LEAVE();
3045 return ret;
3046 }
3047
3048 /**
3049 * @brief uap BSS config ioctl handler
3050 *
3051 * @param dev A pointer to net_device structure
3052 * @param req A pointer to ifreq structure
3053 * @return 0 --success, otherwise fail
3054 */
woal_uap_bss_cfg_ioctl(struct net_device * dev,struct ifreq * req)3055 static int woal_uap_bss_cfg_ioctl(struct net_device *dev, struct ifreq *req)
3056 {
3057 moal_private *priv = (moal_private *)netdev_priv(dev);
3058 int ret = 0;
3059 mlan_ds_bss *bss = NULL;
3060 mlan_ioctl_req *ioctl_req = NULL;
3061 int offset = 0;
3062 t_u32 action = 0;
3063 mlan_status status = MLAN_STATUS_SUCCESS;
3064
3065 ENTER();
3066
3067 /* Sanity check */
3068 if (req->ifr_data == NULL) {
3069 PRINTM(MERROR, "uap_bss_cfg_ioctl() corrupt data\n");
3070 ret = -EFAULT;
3071 goto done;
3072 }
3073
3074 /* Get action */
3075 if (copy_from_user(&action, req->ifr_data + offset, sizeof(action))) {
3076 PRINTM(MERROR, "Copy from user failed\n");
3077 ret = -EFAULT;
3078 goto done;
3079 }
3080 offset += sizeof(action);
3081
3082 /* Allocate an IOCTL request buffer */
3083 ioctl_req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(
3084 sizeof(mlan_ds_bss));
3085 if (ioctl_req == NULL) {
3086 ret = -ENOMEM;
3087 goto done;
3088 }
3089
3090 bss = (mlan_ds_bss *)ioctl_req->pbuf;
3091 bss->sub_command = MLAN_OID_UAP_BSS_CONFIG;
3092 ioctl_req->req_id = MLAN_IOCTL_BSS;
3093 if (action == 1)
3094 ioctl_req->action = MLAN_ACT_SET;
3095 else
3096 ioctl_req->action = MLAN_ACT_GET;
3097
3098 if (ioctl_req->action == MLAN_ACT_SET) {
3099 /* Get the BSS config from user */
3100 if (copy_from_user(&bss->param.bss_config,
3101 req->ifr_data + offset,
3102 sizeof(mlan_uap_bss_param))) {
3103 PRINTM(MERROR, "Copy from user failed\n");
3104 ret = -EFAULT;
3105 goto done;
3106 }
3107 }
3108
3109 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
3110 if (status != MLAN_STATUS_SUCCESS) {
3111 ret = -EFAULT;
3112 goto done;
3113 }
3114
3115 if (ioctl_req->action == MLAN_ACT_GET) {
3116 offset = sizeof(action);
3117
3118 /* Copy to user : BSS config */
3119 if (copy_to_user(req->ifr_data + offset, &bss->param.bss_config,
3120 sizeof(mlan_uap_bss_param))) {
3121 PRINTM(MERROR, "Copy to user failed!\n");
3122 ret = -EFAULT;
3123 goto done;
3124 }
3125 }
3126 done:
3127 if (status != MLAN_STATUS_PENDING)
3128 kfree(ioctl_req);
3129 LEAVE();
3130 return ret;
3131 }
3132
3133 /**
3134 * @brief uap get station list handler
3135 *
3136 * @param dev A pointer to net_device structure
3137 * @param req A pointer to ifreq structure
3138 * @return 0 --success, otherwise fail
3139 */
woal_uap_get_sta_list_ioctl(struct net_device * dev,struct ifreq * req)3140 static int woal_uap_get_sta_list_ioctl(struct net_device *dev,
3141 struct ifreq *req)
3142 {
3143 moal_private *priv = (moal_private *)netdev_priv(dev);
3144 int ret = 0;
3145 mlan_ds_get_info *info = NULL;
3146 mlan_ioctl_req *ioctl_req = NULL;
3147 mlan_status status = MLAN_STATUS_SUCCESS;
3148
3149 ENTER();
3150
3151 /* Sanity check */
3152 if (req->ifr_data == NULL) {
3153 PRINTM(MERROR, "uap_get_sta_list_ioctl() corrupt data\n");
3154 ret = -EFAULT;
3155 goto done;
3156 }
3157
3158 /* Allocate an IOCTL request buffer */
3159 ioctl_req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(
3160 sizeof(mlan_ds_get_info));
3161 if (ioctl_req == NULL) {
3162 ret = -ENOMEM;
3163 goto done;
3164 }
3165
3166 info = (mlan_ds_get_info *)ioctl_req->pbuf;
3167 info->sub_command = MLAN_OID_UAP_STA_LIST;
3168 ioctl_req->req_id = MLAN_IOCTL_GET_INFO;
3169 ioctl_req->action = MLAN_ACT_GET;
3170
3171 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
3172 if (status != MLAN_STATUS_SUCCESS) {
3173 ret = -EFAULT;
3174 goto done;
3175 }
3176
3177 if (ioctl_req->action == MLAN_ACT_GET) {
3178 /* Copy to user : sta_list */
3179 if (copy_to_user(req->ifr_data, &info->param.sta_list,
3180 ioctl_req->data_read_written)) {
3181 PRINTM(MERROR, "Copy to user failed!\n");
3182 ret = -EFAULT;
3183 goto done;
3184 }
3185 }
3186 done:
3187 if (status != MLAN_STATUS_PENDING)
3188 kfree(ioctl_req);
3189 LEAVE();
3190 return ret;
3191 }
3192
3193 /**
3194 * @brief uAP set WAPI key ioctl
3195 *
3196 * @param priv A pointer to moal_private structure
3197 * @param msg A pointer to wapi_msg structure
3198 *
3199 * @return 0 --success, otherwise fail
3200 */
woal_uap_set_wapi_key_ioctl(moal_private * priv,wapi_msg * msg)3201 static int woal_uap_set_wapi_key_ioctl(moal_private *priv, wapi_msg *msg)
3202 {
3203 mlan_ioctl_req *req = NULL;
3204 mlan_ds_sec_cfg *sec = NULL;
3205 int ret = 0;
3206 wapi_key_msg *key_msg = NULL;
3207 t_u8 bcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
3208 mlan_status status = MLAN_STATUS_SUCCESS;
3209
3210 ENTER();
3211 if (msg->msg_len != sizeof(wapi_key_msg)) {
3212 ret = -EINVAL;
3213 goto done;
3214 }
3215 key_msg = (wapi_key_msg *)msg->msg;
3216
3217 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
3218 if (req == NULL) {
3219 ret = -ENOMEM;
3220 goto done;
3221 }
3222 sec = (mlan_ds_sec_cfg *)req->pbuf;
3223 sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
3224 req->req_id = MLAN_IOCTL_SEC_CFG;
3225 req->action = MLAN_ACT_SET;
3226
3227 sec->param.encrypt_key.is_wapi_key = MTRUE;
3228 sec->param.encrypt_key.key_len = MLAN_MAX_KEY_LENGTH;
3229 moal_memcpy_ext(priv->phandle, sec->param.encrypt_key.mac_addr,
3230 key_msg->mac_addr, ETH_ALEN,
3231 sizeof(sec->param.encrypt_key.mac_addr));
3232 sec->param.encrypt_key.key_index = key_msg->key_id;
3233 if (0 == memcmp(key_msg->mac_addr, bcast_addr, ETH_ALEN))
3234 sec->param.encrypt_key.key_flags = KEY_FLAG_GROUP_KEY;
3235 else
3236 sec->param.encrypt_key.key_flags = KEY_FLAG_SET_TX_KEY;
3237 moal_memcpy_ext(priv->phandle, sec->param.encrypt_key.key_material,
3238 key_msg->key, sec->param.encrypt_key.key_len,
3239 sizeof(sec->param.encrypt_key.key_material));
3240
3241 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3242 if (status != MLAN_STATUS_SUCCESS)
3243 ret = -EFAULT;
3244 done:
3245 if (status != MLAN_STATUS_PENDING)
3246 kfree(req);
3247 LEAVE();
3248 return ret;
3249 }
3250
3251 /**
3252 * @brief Enable/Disable wapi in firmware
3253 *
3254 * @param priv A pointer to moal_private structure
3255 * @param enable MTRUE/MFALSE
3256 *
3257 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
3258 * otherwise fail
3259 */
woal_enable_wapi(moal_private * priv,t_u8 enable)3260 static mlan_status woal_enable_wapi(moal_private *priv, t_u8 enable)
3261 {
3262 mlan_ioctl_req *req = NULL;
3263 mlan_ds_bss *bss = NULL;
3264 mlan_status status;
3265
3266 ENTER();
3267
3268 /* Allocate an IOCTL request buffer */
3269 req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
3270 if (req == NULL) {
3271 status = MLAN_STATUS_FAILURE;
3272 goto done;
3273 }
3274
3275 /* Fill request buffer */
3276 bss = (mlan_ds_bss *)req->pbuf;
3277 bss->sub_command = MLAN_OID_UAP_BSS_CONFIG;
3278 req->req_id = MLAN_IOCTL_BSS;
3279 req->action = MLAN_ACT_GET;
3280
3281 /* Send IOCTL request to MLAN */
3282 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3283 if (status != MLAN_STATUS_SUCCESS) {
3284 PRINTM(MERROR,
3285 "Get AP setting failed! status=%d, error_code=0x%x\n",
3286 status, req->status_code);
3287 }
3288
3289 /* Change AP default setting */
3290 req->action = MLAN_ACT_SET;
3291 if (enable == MFALSE) {
3292 bss->param.bss_config.auth_mode = MLAN_AUTH_MODE_OPEN;
3293 bss->param.bss_config.protocol = PROTOCOL_NO_SECURITY;
3294 } else {
3295 bss->param.bss_config.auth_mode = MLAN_AUTH_MODE_OPEN;
3296 bss->param.bss_config.protocol = PROTOCOL_WAPI;
3297 }
3298
3299 /* Send IOCTL request to MLAN */
3300 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3301 if (status != MLAN_STATUS_SUCCESS) {
3302 PRINTM(MERROR,
3303 "Set AP setting failed! status=%d, error_code=0x%x\n",
3304 status, req->status_code);
3305 }
3306 if (enable) {
3307 if (woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START))
3308 PRINTM(MERROR, "%s: uap bss start failed \n", __func__);
3309 }
3310 done:
3311 if (status != MLAN_STATUS_PENDING)
3312 kfree(req);
3313 LEAVE();
3314 return status;
3315 }
3316
3317 /**
3318 * @brief uAP set WAPI flag ioctl
3319 *
3320 * @param priv A pointer to moal_private structure
3321 * @param msg A pointer to wapi_msg structure
3322 *
3323 * @return 0 --success, otherwise fail
3324 */
woal_uap_set_wapi_flag_ioctl(moal_private * priv,wapi_msg * msg)3325 static int woal_uap_set_wapi_flag_ioctl(moal_private *priv, wapi_msg *msg)
3326 {
3327 t_u8 wapi_psk_ie[] = {0x44, 0x14, 0x01, 0x00, 0x01, 0x00, 0x00, 0x14,
3328 0x72, 0x02, 0x01, 0x00, 0x00, 0x14, 0x72, 0x01,
3329 0x00, 0x14, 0x72, 0x01, 0x00, 0x00};
3330 t_u8 wapi_cert_ie[] = {0x44, 0x14, 0x01, 0x00, 0x01, 0x00, 0x00, 0x14,
3331 0x72, 0x01, 0x01, 0x00, 0x00, 0x14, 0x72, 0x01,
3332 0x00, 0x14, 0x72, 0x01, 0x00, 0x00};
3333 mlan_ds_misc_cfg *misc = NULL;
3334 mlan_ioctl_req *req = NULL;
3335 int ret = 0;
3336 mlan_status status = MLAN_STATUS_SUCCESS;
3337
3338 ENTER();
3339
3340 if (woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP)) {
3341 PRINTM(MERROR, "%s: uap bss stop failed \n", __func__);
3342 ret = -EFAULT;
3343 goto done;
3344 }
3345
3346 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3347 if (req == NULL) {
3348 ret = -ENOMEM;
3349 goto done;
3350 }
3351 misc = (mlan_ds_misc_cfg *)req->pbuf;
3352 misc->sub_command = MLAN_OID_MISC_GEN_IE;
3353 req->req_id = MLAN_IOCTL_MISC_CFG;
3354 req->action = MLAN_ACT_SET;
3355
3356 misc->param.gen_ie.type = MLAN_IE_TYPE_GEN_IE;
3357 misc->param.gen_ie.len = sizeof(wapi_psk_ie);
3358 if (msg->msg[0] & WAPI_MODE_PSK) {
3359 moal_memcpy_ext(priv->phandle, misc->param.gen_ie.ie_data,
3360 wapi_psk_ie, misc->param.gen_ie.len,
3361 sizeof(misc->param.gen_ie.ie_data));
3362 } else if (msg->msg[0] & WAPI_MODE_CERT) {
3363 moal_memcpy_ext(priv->phandle, misc->param.gen_ie.ie_data,
3364 wapi_cert_ie, misc->param.gen_ie.len,
3365 sizeof(misc->param.gen_ie.ie_data));
3366 } else if (msg->msg[0] == 0) {
3367 /* disable WAPI in driver */
3368 if (MLAN_STATUS_SUCCESS !=
3369 woal_set_wapi_enable(priv, MOAL_IOCTL_WAIT, 0))
3370 ret = -EFAULT;
3371 woal_enable_wapi(priv, MFALSE);
3372 goto done;
3373 } else {
3374 ret = -EINVAL;
3375 goto done;
3376 }
3377 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3378 if (status != MLAN_STATUS_SUCCESS) {
3379 ret = -EFAULT;
3380 goto done;
3381 }
3382 woal_enable_wapi(priv, MTRUE);
3383 done:
3384 if ((status != MLAN_STATUS_PENDING) && req)
3385 kfree(req);
3386 LEAVE();
3387 return ret;
3388 }
3389
3390 /**
3391 * @brief set wapi ioctl function
3392 *
3393 * @param dev A pointer to net_device structure
3394 * @param req A pointer to ifreq structure
3395 * @return 0 --success, otherwise fail
3396 */
woal_uap_set_wapi(struct net_device * dev,struct ifreq * req)3397 static int woal_uap_set_wapi(struct net_device *dev, struct ifreq *req)
3398 {
3399 moal_private *priv = (moal_private *)netdev_priv(dev);
3400 wapi_msg msg;
3401 int ret = 0;
3402
3403 ENTER();
3404
3405 /* Sanity check */
3406 if (req->ifr_data == NULL) {
3407 PRINTM(MERROR, "uap_set_wapi() corrupt data\n");
3408 ret = -EFAULT;
3409 goto done;
3410 }
3411
3412 memset(&msg, 0, sizeof(msg));
3413
3414 if (copy_from_user(&msg, req->ifr_data, sizeof(msg))) {
3415 PRINTM(MERROR, "Copy from user failed\n");
3416 ret = -EFAULT;
3417 goto done;
3418 }
3419
3420 PRINTM(MIOCTL, "set wapi msg_type = %d, msg_len=%d\n", msg.msg_type,
3421 msg.msg_len);
3422 DBG_HEXDUMP(MCMD_D, "wapi msg", msg.msg,
3423 MIN(msg.msg_len, sizeof(msg.msg)));
3424
3425 switch (msg.msg_type) {
3426 case P80211_PACKET_WAPIFLAG:
3427 ret = woal_uap_set_wapi_flag_ioctl(priv, &msg);
3428 break;
3429 case P80211_PACKET_SETKEY:
3430 ret = woal_uap_set_wapi_key_ioctl(priv, &msg);
3431 break;
3432 default:
3433 ret = -EOPNOTSUPP;
3434 break;
3435 }
3436 done:
3437 LEAVE();
3438 return ret;
3439 }
3440
3441 /********************************************************
3442 Global Functions
3443 ********************************************************/
3444 /**
3445 * @brief Initialize the members of mlan_uap_bss_param
3446 * which are uploaded from firmware
3447 *
3448 * @param priv A pointer to moal_private structure
3449 * @param sys_cfg A pointer to mlan_uap_bss_param structure
3450 * @param wait_option Wait option
3451 *
3452 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3453 */
woal_uap_get_bss_param(moal_private * priv,mlan_uap_bss_param * sys_cfg,t_u8 wait_option)3454 static mlan_status woal_uap_get_bss_param(moal_private *priv,
3455 mlan_uap_bss_param *sys_cfg,
3456 t_u8 wait_option)
3457 {
3458 mlan_ds_bss *info = NULL;
3459 mlan_ioctl_req *req = NULL;
3460 mlan_status status = MLAN_STATUS_SUCCESS;
3461
3462 ENTER();
3463
3464 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
3465 if (req == NULL) {
3466 LEAVE();
3467 return MLAN_STATUS_FAILURE;
3468 }
3469
3470 info = (mlan_ds_bss *)req->pbuf;
3471 info->sub_command = MLAN_OID_UAP_BSS_CONFIG;
3472 req->req_id = MLAN_IOCTL_BSS;
3473 req->action = MLAN_ACT_GET;
3474
3475 status = woal_request_ioctl(priv, req, wait_option);
3476 if (status != MLAN_STATUS_SUCCESS) {
3477 PRINTM(MERROR, "Get bss info failed!\n");
3478 status = MLAN_STATUS_FAILURE;
3479 goto done;
3480 }
3481 moal_memcpy_ext(priv->phandle, sys_cfg, &info->param.bss_config,
3482 sizeof(mlan_uap_bss_param), sizeof(mlan_uap_bss_param));
3483
3484 done:
3485 if (status != MLAN_STATUS_PENDING)
3486 kfree(req);
3487 LEAVE();
3488 return status;
3489 }
3490
3491 /**
3492 * @brief Set uap httxcfg
3493 *
3494 * @param priv A pointer to moal_private structure
3495 * @param band_cfg Band cfg
3496 * @param en Enabled/Disabled
3497 *
3498 * @return 0 --success, otherwise fail
3499 */
woal_set_uap_ht_tx_cfg(moal_private * priv,Band_Config_t bandcfg,t_u16 ht_cap,t_u8 en)3500 int woal_set_uap_ht_tx_cfg(moal_private *priv, Band_Config_t bandcfg,
3501 t_u16 ht_cap, t_u8 en)
3502 {
3503 int ret = 0;
3504 mlan_ds_11n_cfg *cfg_11n = NULL;
3505 mlan_ioctl_req *ioctl_req = NULL;
3506 mlan_status status = MLAN_STATUS_SUCCESS;
3507
3508 ENTER();
3509
3510 ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
3511 if (ioctl_req == NULL) {
3512 ret = -ENOMEM;
3513 goto done;
3514 }
3515 cfg_11n = (mlan_ds_11n_cfg *)ioctl_req->pbuf;
3516 cfg_11n->sub_command = MLAN_OID_11N_CFG_TX;
3517 ioctl_req->req_id = MLAN_IOCTL_11N_CFG;
3518
3519 /* Set HT Tx configurations */
3520 if (bandcfg.chanBand == BAND_2GHZ) {
3521 if (en)
3522 cfg_11n->param.tx_cfg.httxcap = ht_cap;
3523 else
3524 cfg_11n->param.tx_cfg.httxcap = 0;
3525 cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_BG;
3526 } else if (bandcfg.chanBand == BAND_5GHZ) {
3527 if (en)
3528 cfg_11n->param.tx_cfg.httxcap = ht_cap;
3529 else
3530 cfg_11n->param.tx_cfg.httxcap = 0;
3531 cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_A;
3532 }
3533 PRINTM(MCMND, "SET: httxcap=0x%x band:0x%x\n",
3534 cfg_11n->param.tx_cfg.httxcap, cfg_11n->param.tx_cfg.misc_cfg);
3535 /* Update 11n tx parameters in MLAN */
3536 ioctl_req->action = MLAN_ACT_SET;
3537 status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
3538 if (status != MLAN_STATUS_SUCCESS) {
3539 ret = -EFAULT;
3540 goto done;
3541 }
3542 done:
3543 if (status != MLAN_STATUS_PENDING)
3544 kfree(ioctl_req);
3545 LEAVE();
3546 return ret;
3547 }
3548
3549 /**
3550 * @brief Set 11n status based on the configured security mode
3551 *
3552 * @param priv A pointer to moal_private structure
3553 * @param sys_cfg A pointer to mlan_uap_bss_param structure
3554 * @param action MLAN_ACT_DISABLE or MLAN_ACT_ENABLE
3555 *
3556 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3557 */
woal_uap_set_11n_status(moal_private * priv,mlan_uap_bss_param * sys_cfg,t_u8 action)3558 mlan_status woal_uap_set_11n_status(moal_private *priv,
3559 mlan_uap_bss_param *sys_cfg, t_u8 action)
3560 {
3561 mlan_status status = MLAN_STATUS_SUCCESS;
3562 mlan_fw_info fw_info;
3563
3564 ENTER();
3565 memset(&fw_info, 0, sizeof(mlan_fw_info));
3566 if (action == MLAN_ACT_DISABLE) {
3567 if ((sys_cfg->supported_mcs_set[0] == 0) &&
3568 (sys_cfg->supported_mcs_set[4] == 0) &&
3569 (sys_cfg->supported_mcs_set[1] == 0)) {
3570 goto done;
3571 } else {
3572 sys_cfg->supported_mcs_set[0] = 0;
3573 sys_cfg->supported_mcs_set[4] = 0;
3574 sys_cfg->supported_mcs_set[1] = 0;
3575 }
3576 }
3577
3578 if (action == MLAN_ACT_ENABLE) {
3579 woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
3580 sys_cfg->supported_mcs_set[0] = 0xFF;
3581 if (sys_cfg->bandcfg.chan2Offset)
3582 sys_cfg->supported_mcs_set[4] = 0x01;
3583 else
3584 sys_cfg->supported_mcs_set[4] = 0x0;
3585 if (fw_info.usr_dev_mcs_support == HT_STREAM_MODE_2X2)
3586 sys_cfg->supported_mcs_set[1] = 0xFF;
3587 else
3588 sys_cfg->supported_mcs_set[1] = 0;
3589 }
3590
3591 done:
3592 LEAVE();
3593 return status;
3594 }
3595
3596 #define VHT_CAP_11AC_MASK 0x007fffff
3597
3598 /**
3599 * @brief enable/disable 11AC
3600 *
3601 * @param priv A pointer to moal_private structure
3602 * @param action MLAN_ACT_DISABLE or MLAN_ACT_ENABLE
3603 * @param vht20_40 Enable VHT 20 MHz or 40 MHz band
3604 * @param vhtcap_ie A pointer to vht capability IE
3605 *
3606 * @return 0--success, otherwise failure
3607 */
woal_uap_set_11ac_status(moal_private * priv,t_u8 action,t_u8 vht20_40,IEEEtypes_VHTCap_t * vhtcap_ie)3608 int woal_uap_set_11ac_status(moal_private *priv, t_u8 action, t_u8 vht20_40,
3609 IEEEtypes_VHTCap_t *vhtcap_ie)
3610 {
3611 mlan_ioctl_req *req = NULL;
3612 mlan_ds_11ac_cfg *cfg_11ac = NULL;
3613 mlan_fw_info fw_info;
3614 int ret = 0;
3615 mlan_status status = MLAN_STATUS_SUCCESS;
3616
3617 ENTER();
3618
3619 memset(&fw_info, 0, sizeof(mlan_fw_info));
3620 woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
3621
3622 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11ac_cfg));
3623 if (req == NULL) {
3624 ret = -ENOMEM;
3625 goto done;
3626 }
3627
3628 cfg_11ac = (mlan_ds_11ac_cfg *)req->pbuf;
3629 cfg_11ac->sub_command = MLAN_OID_11AC_VHT_CFG;
3630 req->req_id = MLAN_IOCTL_11AC_CFG;
3631 req->action = MLAN_ACT_SET;
3632
3633 cfg_11ac->param.vht_cfg.band = BAND_SELECT_A;
3634 cfg_11ac->param.vht_cfg.txrx = MLAN_RADIO_TXRX;
3635
3636 /*
3637 * p2p GO (negotiation or auto GO) cases, wpa_supplicant will download
3638 * invalid vht capability with value 0 in beacon parameters, so for p2p
3639 * GO case (vht_cap_info = 0), driver will use hardware 11ac vht
3640 * capability value instead of up layer value.
3641 */
3642 if (vhtcap_ie && vhtcap_ie->vht_cap.vht_cap_info != 0) {
3643 cfg_11ac->param.vht_cfg.vht_cap_info =
3644 woal_le32_to_cpu(vhtcap_ie->vht_cap.vht_cap_info);
3645 /** todo mcs configuration */
3646 } else {
3647 cfg_11ac->param.vht_cfg.vht_cap_info =
3648 fw_info.usr_dot_11ac_dev_cap_a;
3649 }
3650 if (action == MLAN_ACT_DISABLE) {
3651 cfg_11ac->param.vht_cfg.bwcfg = MFALSE;
3652 cfg_11ac->param.vht_cfg.vht_cap_info &= ~VHT_CAP_11AC_MASK;
3653 cfg_11ac->param.vht_cfg.vht_rx_mcs =
3654 cfg_11ac->param.vht_cfg.vht_tx_mcs = 0xffff;
3655 cfg_11ac->param.vht_cfg.skip_usr_11ac_mcs_cfg = MTRUE;
3656 } else {
3657 if (vht20_40)
3658 cfg_11ac->param.vht_cfg.bwcfg = MFALSE;
3659 else
3660 cfg_11ac->param.vht_cfg.bwcfg = MTRUE;
3661 cfg_11ac->param.vht_cfg.vht_cap_info &=
3662 ~DEFALUT_11AC_CAP_BEAMFORMING_RESET_MASK;
3663 cfg_11ac->param.vht_cfg.vht_tx_mcs =
3664 fw_info.usr_dot_11ac_mcs_support >> 16;
3665 cfg_11ac->param.vht_cfg.vht_rx_mcs =
3666 fw_info.usr_dot_11ac_mcs_support & 0xffff;
3667 cfg_11ac->param.vht_cfg.skip_usr_11ac_mcs_cfg = MTRUE;
3668 }
3669 PRINTM(MCMND,
3670 "Uap:11ac=%d vht_cap_info=0x%x, vht_tx_mcs=0x%x, vht_rx_mcs=0x%x\n",
3671 action, cfg_11ac->param.vht_cfg.vht_cap_info,
3672 cfg_11ac->param.vht_cfg.vht_tx_mcs,
3673 cfg_11ac->param.vht_cfg.vht_rx_mcs);
3674
3675 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3676 if (status != MLAN_STATUS_SUCCESS) {
3677 ret = -EFAULT;
3678 goto done;
3679 }
3680 done:
3681 if (status != MLAN_STATUS_PENDING)
3682 kfree(req);
3683 LEAVE();
3684 return ret;
3685 }
3686
3687 /**
3688 * @brief Get/Set 11ax cfg
3689 *
3690 * @param priv A pointer to moal_private structure
3691 * @param action MLAN_ACT_SET or MLAN_ACT_GET
3692 * @param he_cfg a pointer to mlan_ds_11ax_he_cfg
3693 *
3694 * @return 0--success, otherwise failure
3695 */
woal_11ax_cfg(moal_private * priv,t_u8 action,mlan_ds_11ax_he_cfg * he_cfg)3696 int woal_11ax_cfg(moal_private *priv, t_u8 action, mlan_ds_11ax_he_cfg *he_cfg)
3697 {
3698 int ret = 0;
3699 mlan_status status = MLAN_STATUS_SUCCESS;
3700 mlan_ioctl_req *req = NULL;
3701 mlan_ds_11ax_cfg *cfg_11ax = NULL;
3702 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11ax_cfg));
3703 if (req == NULL) {
3704 ret = -ENOMEM;
3705 goto done;
3706 }
3707 cfg_11ax = (mlan_ds_11ax_cfg *)req->pbuf;
3708 cfg_11ax->sub_command = MLAN_OID_11AX_HE_CFG;
3709 req->req_id = MLAN_IOCTL_11AX_CFG;
3710 req->action = action;
3711 moal_memcpy_ext(priv->phandle, &cfg_11ax->param.he_cfg, he_cfg,
3712 sizeof(mlan_ds_11ax_he_cfg),
3713 sizeof(mlan_ds_11ax_he_cfg));
3714 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3715 if (status != MLAN_STATUS_SUCCESS) {
3716 ret = -EFAULT;
3717 goto done;
3718 }
3719 moal_memcpy_ext(priv->phandle, he_cfg, &cfg_11ax->param.he_cfg,
3720 sizeof(mlan_ds_11ax_he_cfg),
3721 sizeof(mlan_ds_11ax_he_cfg));
3722 done:
3723 if (status != MLAN_STATUS_PENDING)
3724 kfree(req);
3725 LEAVE();
3726 return ret;
3727 }
3728
3729 /**
3730 * @brief enable/disable 11AX
3731 *
3732 * @param priv A pointer to moal_private structure
3733 * @param action MLAN_ACT_DISABLE or MLAN_ACT_ENABLE
3734 * @param band band config
3735 * @param hecap_ie
3736 *
3737 * @return 0--success, otherwise failure
3738 */
woal_uap_set_11ax_status(moal_private * priv,t_u8 action,t_u8 band,IEEEtypes_HECap_t * hecap_ie)3739 int woal_uap_set_11ax_status(moal_private *priv, t_u8 action, t_u8 band,
3740 IEEEtypes_HECap_t *hecap_ie)
3741 {
3742 mlan_fw_info fw_info;
3743 int ret = 0;
3744 mlan_ds_11ax_he_cfg he_cfg;
3745 ENTER();
3746
3747 memset(&fw_info, 0, sizeof(mlan_fw_info));
3748 woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
3749 if ((band == BAND_5GHZ && !(fw_info.fw_bands & BAND_AAX)) ||
3750 (band == BAND_2GHZ && !(fw_info.fw_bands & BAND_GAX))) {
3751 PRINTM(MERROR, "fw doesn't support 11ax\n");
3752 ret = -EFAULT;
3753 goto done;
3754 }
3755 memset(&he_cfg, 0, sizeof(he_cfg));
3756 if (band == BAND_5GHZ)
3757 he_cfg.band = MBIT(1);
3758 else if (band == BAND_2GHZ)
3759 he_cfg.band = MBIT(0);
3760 else {
3761 PRINTM(MERROR, "Invalid band!\n");
3762 ret = -EFAULT;
3763 goto done;
3764 }
3765 if (woal_11ax_cfg(priv, MLAN_ACT_GET, &he_cfg)) {
3766 PRINTM(MERROR, "Fail to get 11ax cfg!\n");
3767 ret = -EFAULT;
3768 goto done;
3769 }
3770 if (hecap_ie) {
3771 DBG_HEXDUMP(MCMD_D, "hecap_ie", (t_u8 *)hecap_ie,
3772 hecap_ie->ieee_hdr.len +
3773 sizeof(IEEEtypes_Header_t));
3774 he_cfg.he_cap.id = hecap_ie->ieee_hdr.element_id;
3775 he_cfg.he_cap.len = hecap_ie->ieee_hdr.len;
3776 moal_memcpy_ext(priv->phandle, &he_cfg.he_cap.ext_id,
3777 &hecap_ie->ext_id, he_cfg.he_cap.len,
3778 he_cfg.he_cap.len);
3779 }
3780 #define HE_MAC_CAP_TWT_REQ_SUPPORT MBIT(1)
3781 /* uap mode clear TWT request bit */
3782 he_cfg.he_cap.he_mac_cap[0] &= ~HE_MAC_CAP_TWT_REQ_SUPPORT;
3783
3784 if (action == MLAN_ACT_DISABLE) {
3785 if (he_cfg.he_cap.len &&
3786 (he_cfg.he_cap.ext_id == HE_CAPABILITY)) {
3787 memset(he_cfg.he_cap.he_txrx_mcs_support, 0xff,
3788 sizeof(he_cfg.he_cap.he_txrx_mcs_support));
3789 } else {
3790 PRINTM(MCMND, "11ax already disabled\n");
3791 goto done;
3792 }
3793 }
3794 DBG_HEXDUMP(MCMD_D, "HE_CFG ", (t_u8 *)&he_cfg, sizeof(he_cfg));
3795 ret = woal_11ax_cfg(priv, MLAN_ACT_SET, &he_cfg);
3796 done:
3797 LEAVE();
3798 return ret;
3799 }
3800
3801 /**
3802 * @brief Parse AP configuration from ASCII string
3803 *
3804 * @param priv A pointer to moal_private structure
3805 * @param ap_cfg A pointer to mlan_uap_bss_param structure
3806 * @param buf A pointer to user data
3807 *
3808 * @return 0 --success, otherwise fail
3809 */
woal_uap_ap_cfg_parse_data(moal_private * priv,mlan_uap_bss_param * ap_cfg,char * buf)3810 static int woal_uap_ap_cfg_parse_data(moal_private *priv,
3811 mlan_uap_bss_param *ap_cfg, char *buf)
3812 {
3813 int ret = 0, atoi_ret;
3814 int set_sec = 0, set_key = 0, set_chan = 0;
3815 int set_preamble = 0, set_scb = 0, set_ssid = 0;
3816 char *begin = buf, *value = NULL, *opt = NULL;
3817
3818 ENTER();
3819
3820 while (begin) {
3821 value = woal_strsep(&begin, ',', '/');
3822 opt = woal_strsep(&value, '=', '/');
3823 if (opt && !strncmp(opt, "END", strlen("END"))) {
3824 if (!ap_cfg->ssid.ssid_len) {
3825 PRINTM(MERROR,
3826 "Minimum option required is SSID\n");
3827 ret = -EINVAL;
3828 goto done;
3829 }
3830 PRINTM(MINFO, "Parsing terminated by string END\n");
3831 break;
3832 }
3833 if (!opt || !value || !value[0]) {
3834 PRINTM(MERROR, "Invalid option\n");
3835 ret = -EINVAL;
3836 goto done;
3837 } else if (!strncmp(opt, "ASCII_CMD", strlen("ASCII_CMD"))) {
3838 if (strncmp(value, "AP_CFG", strlen("AP_CFG"))) {
3839 PRINTM(MERROR,
3840 "ASCII_CMD: %s not matched with AP_CFG\n",
3841 value);
3842 ret = -EFAULT;
3843 goto done;
3844 }
3845 value = woal_strsep(&begin, ',', '/');
3846 opt = woal_strsep(&value, '=', '/');
3847 if (!opt || !value || !value[0]) {
3848 PRINTM(MERROR,
3849 "Minimum option required is SSID\n");
3850 ret = -EINVAL;
3851 goto done;
3852 } else if (!strncmp(opt, "SSID", strlen("SSID"))) {
3853 if (set_ssid) {
3854 PRINTM(MWARN,
3855 "Skipping SSID, found again!\n");
3856 continue;
3857 }
3858 if (strlen(value) >= MLAN_MAX_SSID_LENGTH) {
3859 PRINTM(MERROR,
3860 "SSID length exceeds max length\n");
3861 ret = -EFAULT;
3862 goto done;
3863 }
3864 ap_cfg->ssid.ssid_len = strlen(value);
3865 strncpy((char *)ap_cfg->ssid.ssid, value,
3866 MIN(MLAN_MAX_SSID_LENGTH - 1,
3867 strlen(value)));
3868 PRINTM(MINFO, "ssid=%s, len=%d\n",
3869 ap_cfg->ssid.ssid,
3870 (int)ap_cfg->ssid.ssid_len);
3871 set_ssid = 1;
3872 } else {
3873 PRINTM(MERROR,
3874 "AP_CFG: Invalid option %s, expect SSID\n",
3875 opt);
3876 ret = -EINVAL;
3877 goto done;
3878 }
3879 } else if (!strncmp(opt, "SEC", strlen("SEC"))) {
3880 if (set_sec) {
3881 PRINTM(MWARN, "Skipping SEC, found again!\n");
3882 continue;
3883 }
3884 if (!strnicmp(value, "open", strlen("open"))) {
3885 ap_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
3886 if (set_key)
3887 ap_cfg->wpa_cfg.length = 0;
3888 ap_cfg->key_mgmt = KEY_MGMT_NONE;
3889 ap_cfg->protocol = PROTOCOL_NO_SECURITY;
3890 } else if (!strnicmp(value, "wpa2-psk",
3891 strlen("wpa2-psk"))) {
3892 ap_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
3893 ap_cfg->protocol = PROTOCOL_WPA2;
3894 ap_cfg->key_mgmt = KEY_MGMT_PSK;
3895 ap_cfg->wpa_cfg.pairwise_cipher_wpa =
3896 CIPHER_AES_CCMP;
3897 ap_cfg->wpa_cfg.pairwise_cipher_wpa2 =
3898 CIPHER_AES_CCMP;
3899 ap_cfg->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
3900 } else if (!strnicmp(value, "wpa-psk",
3901 strlen("wpa-psk"))) {
3902 ap_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
3903 ap_cfg->protocol = PROTOCOL_WPA;
3904 ap_cfg->key_mgmt = KEY_MGMT_PSK;
3905 ap_cfg->wpa_cfg.pairwise_cipher_wpa =
3906 CIPHER_TKIP;
3907 ap_cfg->wpa_cfg.group_cipher = CIPHER_TKIP;
3908 } else if (!strnicmp(value, "wep128",
3909 strlen("wep128"))) {
3910 ap_cfg->auth_mode = MLAN_AUTH_MODE_OPEN;
3911 if (set_key)
3912 ap_cfg->wpa_cfg.length = 0;
3913 ap_cfg->key_mgmt = KEY_MGMT_NONE;
3914 ap_cfg->protocol = PROTOCOL_STATIC_WEP;
3915 } else {
3916 PRINTM(MERROR,
3917 "AP_CFG: Invalid value=%s for %s\n",
3918 value, opt);
3919 ret = -EFAULT;
3920 goto done;
3921 }
3922 set_sec = 1;
3923 } else if (!strncmp(opt, "KEY", strlen("KEY"))) {
3924 if (set_key) {
3925 PRINTM(MWARN, "Skipping KEY, found again!\n");
3926 continue;
3927 }
3928 if (set_sec &&
3929 ap_cfg->protocol == PROTOCOL_STATIC_WEP) {
3930 if (strlen(value) != MAX_WEP_KEY_SIZE) {
3931 PRINTM(MERROR,
3932 "Invalid WEP KEY length\n");
3933 ret = -EFAULT;
3934 goto done;
3935 }
3936 ap_cfg->wep_cfg.key0.key_index = 0;
3937 ap_cfg->wep_cfg.key0.is_default = 1;
3938 ap_cfg->wep_cfg.key0.length = strlen(value);
3939 moal_memcpy_ext(
3940 priv->phandle, ap_cfg->wep_cfg.key0.key,
3941 value, strlen(value),
3942 sizeof(ap_cfg->wep_cfg.key0.key));
3943 set_key = 1;
3944 continue;
3945 }
3946 if (set_sec && ap_cfg->protocol != PROTOCOL_WPA2 &&
3947 ap_cfg->protocol != PROTOCOL_WPA) {
3948 PRINTM(MWARN,
3949 "Warning! No KEY for open mode\n");
3950 set_key = 1;
3951 continue;
3952 }
3953 if (strlen(value) < MLAN_MIN_PASSPHRASE_LENGTH ||
3954 strlen(value) > MLAN_PMK_HEXSTR_LENGTH) {
3955 PRINTM(MERROR, "Invalid PSK/PMK length\n");
3956 ret = -EINVAL;
3957 goto done;
3958 }
3959 ap_cfg->wpa_cfg.length = strlen(value);
3960 moal_memcpy_ext(priv->phandle,
3961 ap_cfg->wpa_cfg.passphrase, value,
3962 strlen(value),
3963 sizeof(ap_cfg->wpa_cfg.passphrase));
3964 set_key = 1;
3965 } else if (!strncmp(opt, "CHANNEL", strlen("CHANNEL"))) {
3966 if (set_chan) {
3967 PRINTM(MWARN,
3968 "Skipping CHANNEL, found again!\n");
3969 continue;
3970 }
3971 if (woal_atoi(&atoi_ret, value)) {
3972 ret = -EINVAL;
3973 goto done;
3974 }
3975 if (atoi_ret < 1 || atoi_ret > MLAN_MAX_CHANNEL) {
3976 PRINTM(MERROR,
3977 "AP_CFG: Channel must be between 1 and %d"
3978 "(both included)\n",
3979 MLAN_MAX_CHANNEL);
3980 ret = -EINVAL;
3981 goto done;
3982 }
3983 ap_cfg->channel = atoi_ret;
3984 set_chan = 1;
3985 } else if (!strncmp(opt, "PREAMBLE", strlen("PREAMBLE"))) {
3986 if (set_preamble) {
3987 PRINTM(MWARN,
3988 "Skipping PREAMBLE, found again!\n");
3989 continue;
3990 }
3991 if (woal_atoi(&atoi_ret, value)) {
3992 ret = -EINVAL;
3993 goto done;
3994 }
3995 /* This is a READ only value from FW, so we
3996 * can not set this and pass it successfully */
3997 set_preamble = 1;
3998 } else if (!strncmp(opt, "MAX_SCB", strlen("MAX_SCB"))) {
3999 if (set_scb) {
4000 PRINTM(MWARN,
4001 "Skipping MAX_SCB, found again!\n");
4002 continue;
4003 }
4004 if (woal_atoi(&atoi_ret, value)) {
4005 ret = -EINVAL;
4006 goto done;
4007 }
4008 if (atoi_ret < 1 || atoi_ret > MAX_STA_COUNT) {
4009 PRINTM(MERROR,
4010 "AP_CFG: MAX_SCB must be between 1 to %d "
4011 "(both included)\n",
4012 MAX_STA_COUNT);
4013 ret = -EINVAL;
4014 goto done;
4015 }
4016 ap_cfg->max_sta_count = (t_u16)atoi_ret;
4017 set_scb = 1;
4018 } else {
4019 PRINTM(MERROR, "Invalid option %s\n", opt);
4020 ret = -EINVAL;
4021 goto done;
4022 }
4023 }
4024
4025 done:
4026 LEAVE();
4027 return ret;
4028 }
4029
4030 /**
4031 * @brief Set AP configuration
4032 *
4033 * @param priv A pointer to moal_private structure
4034 * @param data A pointer to user data
4035 * @param len Length of buf
4036 *
4037 * @return 0 --success, otherwise fail
4038 */
woal_uap_set_ap_cfg(moal_private * priv,t_u8 * data,int len)4039 int woal_uap_set_ap_cfg(moal_private *priv, t_u8 *data, int len)
4040 {
4041 int ret = 0;
4042 static char buf[MAX_BUF_LEN];
4043 mlan_uap_bss_param *sys_config = NULL;
4044 int restart = 0;
4045
4046 ENTER();
4047
4048 #define MIN_AP_CFG_CMD_LEN 16 /* strlen("ASCII_CMD=AP_CFG") */
4049 if ((len - 1) <= MIN_AP_CFG_CMD_LEN) {
4050 PRINTM(MERROR, "Invalid length of command\n");
4051 ret = -EINVAL;
4052 goto done;
4053 }
4054 sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
4055 if (!sys_config) {
4056 PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
4057 ret = -EFAULT;
4058 goto done;
4059 }
4060 memset(buf, 0, MAX_BUF_LEN);
4061 moal_memcpy_ext(priv->phandle, buf, data, len, sizeof(buf) - 1);
4062
4063 /* Initialize the uap bss values which are uploaded from firmware */
4064 woal_uap_get_bss_param(priv, sys_config, MOAL_IOCTL_WAIT);
4065
4066 /* Setting the default values */
4067 sys_config->channel = 6;
4068 sys_config->preamble_type = 0;
4069
4070 ret = woal_uap_ap_cfg_parse_data(priv, sys_config, buf);
4071 if (ret)
4072 goto done;
4073
4074 /* If BSS already started stop it first and restart
4075 * after changing the setting */
4076 if (priv->bss_started == MTRUE) {
4077 ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP);
4078 if (ret)
4079 goto done;
4080 restart = 1;
4081 }
4082
4083 /* If the security mode is configured as WEP or WPA-PSK,
4084 * it will disable 11n automatically, and if configured as
4085 * open(off) or wpa2-psk, it will automatically enable 11n */
4086 if ((sys_config->protocol == PROTOCOL_STATIC_WEP) ||
4087 (sys_config->protocol == PROTOCOL_WPA)) {
4088 if (MLAN_STATUS_SUCCESS !=
4089 woal_uap_set_11n_status(priv, sys_config,
4090 MLAN_ACT_DISABLE)) {
4091 ret = -EFAULT;
4092 goto done;
4093 }
4094 } else {
4095 if (MLAN_STATUS_SUCCESS !=
4096 woal_uap_set_11n_status(priv, sys_config,
4097 MLAN_ACT_ENABLE)) {
4098 ret = -EFAULT;
4099 goto done;
4100 }
4101 }
4102
4103 if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET,
4104 MOAL_IOCTL_WAIT,
4105 sys_config)) {
4106 ret = -EFAULT;
4107 goto done;
4108 }
4109
4110 /* Start the BSS after successful configuration */
4111 if (restart)
4112 ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START);
4113
4114 done:
4115 kfree(sys_config);
4116 LEAVE();
4117 return ret;
4118 }
4119
4120 /**
4121 * @brief Set/Get ap scan channel list
4122 *
4123 * @param priv A pointer to moal_private structure
4124 * @param action MLAN_ACT_SET or MLAN_ACT_GET
4125 * @param scan_channels A pointer to mlan_uap_scan_channels structure
4126 *
4127 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4128 */
4129 static mlan_status
woal_set_get_ap_scan_channels(moal_private * priv,t_u16 action,mlan_uap_scan_channels * scan_channels)4130 woal_set_get_ap_scan_channels(moal_private *priv, t_u16 action,
4131 mlan_uap_scan_channels *scan_channels)
4132 {
4133 mlan_status ret = MLAN_STATUS_SUCCESS;
4134 mlan_ds_bss *bss = NULL;
4135 mlan_ioctl_req *req = NULL;
4136
4137 ENTER();
4138
4139 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4140 if (req == NULL) {
4141 ret = MLAN_STATUS_FAILURE;
4142 goto done;
4143 }
4144
4145 bss = (mlan_ds_bss *)req->pbuf;
4146 bss->sub_command = MLAN_OID_UAP_SCAN_CHANNELS;
4147 req->req_id = MLAN_IOCTL_BSS;
4148 req->action = action;
4149
4150 moal_memcpy_ext(priv->phandle, &bss->param.ap_scan_channels,
4151 scan_channels, sizeof(mlan_uap_scan_channels),
4152 sizeof(bss->param.ap_scan_channels));
4153
4154 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4155 if (ret != MLAN_STATUS_SUCCESS)
4156 goto done;
4157 if (action == MLAN_ACT_GET)
4158 moal_memcpy_ext(priv->phandle, scan_channels,
4159 &bss->param.ap_scan_channels,
4160 sizeof(mlan_uap_scan_channels),
4161 sizeof(mlan_uap_scan_channels));
4162
4163 done:
4164 if (ret != MLAN_STATUS_PENDING)
4165 kfree(req);
4166 LEAVE();
4167 return ret;
4168 }
4169
4170 /**
4171 * @brief Set/Get uap channel
4172 *
4173 * @param priv A pointer to moal_private structure
4174 * @param action MLAN_ACT_SET or MLAN_ACT_GET
4175 * @param wait_option wait option
4176 * @param uap_channel A pointer to mlan_uap_channel structure
4177 *
4178 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4179 */
woal_set_get_ap_channel(moal_private * priv,t_u16 action,t_u8 wait_option,chan_band_info * uap_channel)4180 mlan_status woal_set_get_ap_channel(moal_private *priv, t_u16 action,
4181 t_u8 wait_option,
4182 chan_band_info *uap_channel)
4183 {
4184 mlan_status ret = MLAN_STATUS_SUCCESS;
4185 mlan_ds_bss *bss = NULL;
4186 mlan_ioctl_req *req = NULL;
4187
4188 ENTER();
4189
4190 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4191 if (req == NULL) {
4192 ret = MLAN_STATUS_FAILURE;
4193 goto done;
4194 }
4195
4196 bss = (mlan_ds_bss *)req->pbuf;
4197 bss->sub_command = MLAN_OID_UAP_CHANNEL;
4198 req->req_id = MLAN_IOCTL_BSS;
4199 req->action = action;
4200
4201 moal_memcpy_ext(priv->phandle, &bss->param.ap_channel, uap_channel,
4202 sizeof(chan_band_info), sizeof(bss->param.ap_channel));
4203 ret = woal_request_ioctl(priv, req, wait_option);
4204 if (ret != MLAN_STATUS_SUCCESS)
4205 goto done;
4206 if (action == MLAN_ACT_GET)
4207 moal_memcpy_ext(priv->phandle, uap_channel,
4208 &bss->param.ap_channel, sizeof(chan_band_info),
4209 sizeof(chan_band_info));
4210
4211 done:
4212 if (ret != MLAN_STATUS_PENDING)
4213 kfree(req);
4214 LEAVE();
4215 return ret;
4216 }
4217
4218 /**
4219 * @brief start ACS scan
4220 *
4221 * @param priv A pointer to moal_private structure
4222 * @param action MLAN_ACT_SET or MLAN_ACT_GET
4223 *
4224 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4225 */
woal_start_acs_scan(moal_private * priv)4226 static mlan_status woal_start_acs_scan(moal_private *priv)
4227 {
4228 mlan_status ret = MLAN_STATUS_SUCCESS;
4229 mlan_ds_bss *bss = NULL;
4230 mlan_ioctl_req *req = NULL;
4231
4232 ENTER();
4233
4234 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4235 if (req == NULL) {
4236 ret = MLAN_STATUS_FAILURE;
4237 goto done;
4238 }
4239
4240 bss = (mlan_ds_bss *)req->pbuf;
4241 bss->sub_command = MLAN_OID_UAP_ACS_SCAN;
4242 req->req_id = MLAN_IOCTL_BSS;
4243 req->action = MLAN_ACT_SET;
4244
4245 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4246 if (ret != MLAN_STATUS_SUCCESS)
4247 goto done;
4248 PRINTM(MIOCTL,
4249 "ACS scan done: bandcfg:[chanBand=0x%x chanWidth=0x%x chan2Offset=0x%x scanMode=0x%x], channel=%d\n",
4250 bss->param.ap_acs_scan.bandcfg.chanBand,
4251 bss->param.ap_acs_scan.bandcfg.chanWidth,
4252 bss->param.ap_acs_scan.bandcfg.chan2Offset,
4253 bss->param.ap_acs_scan.bandcfg.scanMode,
4254 bss->param.ap_acs_scan.chan);
4255 done:
4256 if (ret != MLAN_STATUS_PENDING)
4257 kfree(req);
4258 LEAVE();
4259 return ret;
4260 }
4261
4262 /**
4263 * @brie check if we need do ACS scan
4264 *
4265 * @param priv A pointer to moal_private structure
4266 *
4267 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4268 */
woal_do_acs_check(moal_private * priv)4269 static mlan_status woal_do_acs_check(moal_private *priv)
4270 {
4271 mlan_status ret = MLAN_STATUS_SUCCESS;
4272 mlan_uap_bss_param *sys_config = NULL;
4273 mlan_uap_scan_channels *scan_channels = NULL;
4274 chan_band_info uap_channel;
4275 ENTER();
4276
4277 sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
4278 if (!sys_config) {
4279 PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
4280 LEAVE();
4281 return MLAN_STATUS_FAILURE;
4282 }
4283
4284 if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET,
4285 MOAL_IOCTL_WAIT,
4286 sys_config)) {
4287 PRINTM(MERROR, "Fail to get sys config data\n");
4288 kfree(sys_config);
4289 LEAVE();
4290 return MLAN_STATUS_FAILURE;
4291 }
4292 if (!(sys_config->bandcfg.scanMode == SCAN_MODE_ACS)) {
4293 kfree(sys_config);
4294 LEAVE();
4295 return ret;
4296 }
4297 scan_channels = kzalloc(sizeof(mlan_uap_scan_channels), GFP_ATOMIC);
4298 if (scan_channels == NULL) {
4299 PRINTM(MERROR, "Fail to alloc scan channels buffer\n");
4300 kfree(sys_config);
4301 LEAVE();
4302 return MLAN_STATUS_FAILURE;
4303 }
4304 scan_channels->remove_nop_channel = MTRUE;
4305 if (MLAN_STATUS_SUCCESS !=
4306 woal_set_get_ap_scan_channels(priv, MLAN_ACT_GET, scan_channels)) {
4307 PRINTM(MERROR, "Fail to get scan channels\n");
4308 goto done;
4309 }
4310
4311 if (scan_channels->num_remvoed_channel && scan_channels->num_of_chan) {
4312 scan_channels->remove_nop_channel = 0;
4313 /** set back new channel list after remove nop channels */
4314 if (MLAN_STATUS_SUCCESS !=
4315 woal_set_get_ap_scan_channels(priv, MLAN_ACT_SET,
4316 scan_channels)) {
4317 PRINTM(MERROR, "Fail to get scan channels\n");
4318 goto done;
4319 }
4320 }
4321 if (scan_channels->num_of_chan)
4322 ret = woal_start_acs_scan(priv);
4323 else
4324 ret = MLAN_STATUS_FAILURE;
4325 /** set to default channel 6 when 5G ACS is configured */
4326 if ((ret != MLAN_STATUS_SUCCESS) &&
4327 (sys_config->bandcfg.chanBand == BAND_5GHZ)) {
4328 memset(&uap_channel, 0, sizeof(uap_channel));
4329 uap_channel.bandcfg.chanBand = DEFAULT_UAP_BAND;
4330 uap_channel.channel = DEFAULT_UAP_CHANNEL;
4331 ret = woal_set_get_ap_channel(priv, MLAN_ACT_SET,
4332 MOAL_IOCTL_WAIT, &uap_channel);
4333 }
4334 done:
4335 kfree(scan_channels);
4336 kfree(sys_config);
4337 LEAVE();
4338 return ret;
4339 }
4340
4341 /**
4342 * @brief uap BSS control ioctl handler
4343 *
4344 * @param priv A pointer to moal_private structure
4345 * @param wait_option Wait option
4346 * @param data BSS control type
4347 * @return 0 --success, otherwise fail
4348 */
woal_uap_bss_ctrl(moal_private * priv,t_u8 wait_option,int data)4349 int woal_uap_bss_ctrl(moal_private *priv, t_u8 wait_option, int data)
4350 {
4351 mlan_ioctl_req *req = NULL;
4352 mlan_ds_bss *bss = NULL;
4353 int ret = 0;
4354 mlan_status status = MLAN_STATUS_SUCCESS;
4355
4356 ENTER();
4357
4358 PRINTM(MIOCTL, "ioctl bss ctrl=%d\n", data);
4359
4360 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4361 if (req == NULL) {
4362 ret = -ENOMEM;
4363 goto done;
4364 }
4365 bss = (mlan_ds_bss *)req->pbuf;
4366 switch (data) {
4367 case UAP_BSS_START:
4368 if (priv->bss_started == MTRUE) {
4369 PRINTM(MWARN, "Warning: BSS already started!\n");
4370 /* goto done; */
4371 } else if (!priv->uap_host_based
4372 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
4373 || moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD)
4374 #endif
4375 ) {
4376 status = woal_do_acs_check(priv);
4377 if (status)
4378 PRINTM(MMSG, "woal_do_acs_check fails\n");
4379 /* about to start bss: issue channel check */
4380 status = woal_11h_channel_check_ioctl(priv,
4381 MOAL_IOCTL_WAIT);
4382 if (status) {
4383 PRINTM(MMSG, "11h channel check fails\n");
4384 status = MLAN_STATUS_FAILURE;
4385 ret = -1;
4386 goto done;
4387 }
4388 }
4389 bss->sub_command = MLAN_OID_BSS_START;
4390 if (priv->uap_host_based) {
4391 bss->param.host_based |= UAP_FLAG_HOST_BASED;
4392 #ifdef UAP_CFG80211
4393 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
4394 if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME))
4395 bss->param.host_based |= UAP_FLAG_HOST_MLME;
4396 #endif
4397 #endif
4398 }
4399 break;
4400 case UAP_BSS_STOP:
4401 if (priv->bss_started == MFALSE) {
4402 PRINTM(MWARN, "Warning: BSS already stopped!\n");
4403 /* This is a situation where CAC it started and BSS
4404 * start is dealyed and before CAC timer expires BSS
4405 * stop is triggered.
4406 *
4407 * Do not skip sending the BSS_STOP command since there
4408 * are many routines triggered on BSS_STOP command
4409 * response.
4410 */
4411 woal_cancel_cac_block(priv);
4412 }
4413 bss->sub_command = MLAN_OID_BSS_STOP;
4414 break;
4415 case UAP_BSS_RESET:
4416 bss->sub_command = MLAN_OID_UAP_BSS_RESET;
4417 woal_cancel_cac_block(priv);
4418 break;
4419 default:
4420 PRINTM(MMSG, "We don't support this uap_bss_ctrl cmd %d\n",
4421 data);
4422 ret = -EFAULT;
4423 goto done;
4424 }
4425 req->req_id = MLAN_IOCTL_BSS;
4426 req->action = MLAN_ACT_SET;
4427
4428 status = woal_request_ioctl(priv, req, wait_option);
4429 if (status == MLAN_STATUS_FAILURE) {
4430 ret = -EFAULT;
4431 goto done;
4432 }
4433 if (data == UAP_BSS_STOP || data == UAP_BSS_RESET) {
4434 priv->bss_started = MFALSE;
4435 woal_stop_queue(priv->netdev);
4436 if (netif_carrier_ok(priv->netdev))
4437 netif_carrier_off(priv->netdev);
4438 if (data == UAP_BSS_RESET) {
4439 if (MLAN_STATUS_FAILURE ==
4440 woal_request_set_mac_address(priv, wait_option))
4441 PRINTM(MERROR,
4442 "Fail to set mac address after UAP_BSS_RESET\n");
4443 }
4444 woal_flush_tcp_sess_queue(priv);
4445 }
4446 done:
4447 if (status != MLAN_STATUS_PENDING)
4448 kfree(req);
4449 LEAVE();
4450 return ret;
4451 }
4452
4453 /**
4454 * @brief This function sets multicast addresses to firmware
4455 *
4456 * @param dev A pointer to net_device structure
4457 * @return N/A
4458 */
woal_uap_set_multicast_list(struct net_device * dev)4459 void woal_uap_set_multicast_list(struct net_device *dev)
4460 {
4461 ENTER();
4462
4463 LEAVE();
4464 }
4465
4466 /**
4467 * @brief ioctl function - entry point
4468 *
4469 * @param dev A pointer to net_device structure
4470 * @param req A pointer to ifreq structure
4471 * @param cmd Command
4472 *
4473 * @return 0 --success, otherwise fail
4474 */
4475 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
woal_uap_do_ioctl(struct net_device * dev,struct ifreq * req,void __user * data,int cmd)4476 int woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req,
4477 void __user *data, int cmd)
4478 #else
4479 int woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
4480 #endif
4481 {
4482 int ret = 0;
4483 ENTER();
4484
4485 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
4486 if (in_compat_syscall()) /* not implemented yet */
4487 return -EOPNOTSUPP;
4488 #endif
4489
4490 switch (cmd) {
4491 case WOAL_ANDROID_DEF_CMD:
4492 /** android default ioctl ID is SIOCDEVPRIVATE + 1 */
4493 ret = woal_android_priv_cmd(dev, req);
4494 break;
4495 case UAP_IOCTL_CMD:
4496 ret = woal_uap_ioctl(dev, req);
4497 break;
4498 case UAP_POWER_MODE:
4499 ret = woal_uap_power_mode_ioctl(dev, req);
4500 break;
4501 case UAP_BSS_CTRL:
4502 ret = woal_uap_bss_ctrl_ioctl(dev, req);
4503 break;
4504 case UAP_WAPI_MSG:
4505 ret = woal_uap_set_wapi(dev, req);
4506 break;
4507 case UAP_BSS_CONFIG:
4508 ret = woal_uap_bss_cfg_ioctl(dev, req);
4509 break;
4510 case UAP_STA_DEAUTH:
4511 ret = woal_uap_sta_deauth_ioctl(dev, req);
4512 break;
4513 case UAP_RADIO_CTL:
4514 ret = woal_uap_radio_ctl(dev, req);
4515 break;
4516 case UAP_REPORT_MIC_ERR:
4517 ret = woal_uap_report_mic_ioctl(dev, req);
4518 break;
4519 case UAP_SET_KEY:
4520 ret = woal_uap_set_key_ioctl(dev, req);
4521 break;
4522 case UAPHOSTPKTINJECT:
4523 ret = woal_send_host_packet(dev, req);
4524 break;
4525 case UAP_GET_STA_LIST:
4526 ret = woal_uap_get_sta_list_ioctl(dev, req);
4527 break;
4528 case UAP_CUSTOM_IE:
4529 ret = woal_custom_ie_ioctl(dev, req);
4530 break;
4531 case UAP_GET_BSS_TYPE:
4532 ret = woal_get_bss_type(dev, req);
4533 break;
4534 case WOAL_ANDROID_PRIV_CMD:
4535 ret = woal_android_priv_cmd(dev, req);
4536 break;
4537 default:
4538 #ifdef UAP_WEXT
4539 ret = woal_uap_do_priv_ioctl(dev, req, cmd);
4540 #else
4541 ret = -EOPNOTSUPP;
4542 #endif
4543 break;
4544 }
4545
4546 LEAVE();
4547 return ret;
4548 }
4549
4550 #ifdef CONFIG_PROC_FS
4551 /**
4552 * @brief Get version
4553 *
4554 * @param priv A pointer to moal_private structure
4555 * @param version A pointer to version buffer
4556 * @param max_len max length of version buffer
4557 *
4558 * @return N/A
4559 */
woal_uap_get_version(moal_private * priv,char * version,int max_len)4560 void woal_uap_get_version(moal_private *priv, char *version, int max_len)
4561 {
4562 mlan_ds_get_info *info = NULL;
4563 mlan_ioctl_req *req = NULL;
4564 mlan_status status = MLAN_STATUS_SUCCESS;
4565
4566 ENTER();
4567
4568 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
4569 if (req == NULL) {
4570 LEAVE();
4571 return;
4572 }
4573
4574 info = (mlan_ds_get_info *)req->pbuf;
4575 info->sub_command = MLAN_OID_GET_VER_EXT;
4576 req->req_id = MLAN_IOCTL_GET_INFO;
4577 req->action = MLAN_ACT_GET;
4578
4579 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4580 if (status == MLAN_STATUS_SUCCESS) {
4581 PRINTM(MINFO, "MOAL UAP VERSION: %s\n",
4582 info->param.ver_ext.version_str);
4583 snprintf(version, max_len, priv->phandle->driver_version,
4584 info->param.ver_ext.version_str);
4585 }
4586
4587 if (status != MLAN_STATUS_PENDING)
4588 kfree(req);
4589 LEAVE();
4590 return;
4591 }
4592 #endif
4593
4594 /**
4595 * @brief Get uap statistics
4596 *
4597 * @param priv A pointer to moal_private structure
4598 * @param wait_option Wait option
4599 * @param ustats A pointer to mlan_ds_uap_stats structure
4600 *
4601 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
4602 * success, otherwise fail
4603 */
woal_uap_get_stats(moal_private * priv,t_u8 wait_option,mlan_ds_uap_stats * ustats)4604 mlan_status woal_uap_get_stats(moal_private *priv, t_u8 wait_option,
4605 mlan_ds_uap_stats *ustats)
4606 {
4607 mlan_ds_get_info *info = NULL;
4608 mlan_ioctl_req *req = NULL;
4609 mlan_status status = MLAN_STATUS_SUCCESS;
4610
4611 ENTER();
4612
4613 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
4614 if (req == NULL) {
4615 LEAVE();
4616 return MLAN_STATUS_FAILURE;
4617 }
4618
4619 info = (mlan_ds_get_info *)req->pbuf;
4620 info->sub_command = MLAN_OID_GET_STATS;
4621 req->req_id = MLAN_IOCTL_GET_INFO;
4622 req->action = MLAN_ACT_GET;
4623
4624 status = woal_request_ioctl(priv, req, wait_option);
4625 if (status == MLAN_STATUS_SUCCESS) {
4626 if (ustats)
4627 moal_memcpy_ext(priv->phandle, ustats,
4628 &info->param.ustats,
4629 sizeof(mlan_ds_uap_stats),
4630 sizeof(mlan_ds_uap_stats));
4631 #ifdef UAP_WEXT
4632 priv->w_stats.discard.fragment =
4633 info->param.ustats.fcs_error_count;
4634 priv->w_stats.discard.retries = info->param.ustats.retry_count;
4635 priv->w_stats.discard.misc =
4636 info->param.ustats.ack_failure_count;
4637 #endif
4638 }
4639
4640 if (status != MLAN_STATUS_PENDING)
4641 kfree(req);
4642 LEAVE();
4643 return status;
4644 }
4645
4646 /**
4647 * @brief Set/Get system configuration parameters
4648 *
4649 * @param priv A pointer to moal_private structure
4650 * @param action MLAN_ACT_SET or MLAN_ACT_GET
4651 * @param ap_wmm_para A pointer to wmm_parameter_t structure
4652 *
4653 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4654 */
woal_set_get_ap_wmm_para(moal_private * priv,t_u16 action,wmm_parameter_t * ap_wmm_para)4655 mlan_status woal_set_get_ap_wmm_para(moal_private *priv, t_u16 action,
4656 wmm_parameter_t *ap_wmm_para)
4657 {
4658 mlan_status ret = MLAN_STATUS_SUCCESS;
4659 mlan_ds_bss *bss = NULL;
4660 mlan_ioctl_req *req = NULL;
4661
4662 ENTER();
4663
4664 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4665 if (req == NULL) {
4666 ret = MLAN_STATUS_FAILURE;
4667 goto done;
4668 }
4669
4670 bss = (mlan_ds_bss *)req->pbuf;
4671 bss->sub_command = MLAN_OID_UAP_CFG_WMM_PARAM;
4672 req->req_id = MLAN_IOCTL_BSS;
4673 req->action = action;
4674
4675 if (action == MLAN_ACT_SET)
4676 moal_memcpy_ext(priv->phandle, &bss->param.ap_wmm_para,
4677 ap_wmm_para, sizeof(wmm_parameter_t),
4678 sizeof(bss->param.ap_wmm_para));
4679
4680 ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4681 if (ret != MLAN_STATUS_SUCCESS)
4682 goto done;
4683 if (bss->param.ap_wmm_para.reserved != MLAN_STATUS_COMPLETE) {
4684 ret = MLAN_STATUS_FAILURE;
4685 goto done;
4686 }
4687 if (action == MLAN_ACT_GET)
4688 moal_memcpy_ext(priv->phandle, ap_wmm_para,
4689 &bss->param.ap_wmm_para,
4690 sizeof(wmm_parameter_t),
4691 sizeof(wmm_parameter_t));
4692
4693 done:
4694 if (ret != MLAN_STATUS_PENDING)
4695 kfree(req);
4696 LEAVE();
4697 return ret;
4698 }
4699
4700 /**
4701 * @brief Set/Get system configuration parameters
4702 *
4703 * @param priv A pointer to moal_private structure
4704 * @param action MLAN_ACT_SET or MLAN_ACT_GET
4705 * @param wait_option Wait option
4706 * @param sys_cfg A pointer to mlan_uap_bss_param structure
4707 *
4708 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4709 */
woal_set_get_sys_config(moal_private * priv,t_u16 action,t_u8 wait_option,mlan_uap_bss_param * sys_cfg)4710 mlan_status woal_set_get_sys_config(moal_private *priv, t_u16 action,
4711 t_u8 wait_option,
4712 mlan_uap_bss_param *sys_cfg)
4713 {
4714 mlan_status ret = MLAN_STATUS_SUCCESS;
4715 mlan_ds_bss *bss = NULL;
4716 mlan_ioctl_req *req = NULL;
4717
4718 ENTER();
4719
4720 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4721 if (req == NULL) {
4722 ret = MLAN_STATUS_FAILURE;
4723 goto done;
4724 }
4725
4726 bss = (mlan_ds_bss *)req->pbuf;
4727 bss->sub_command = MLAN_OID_UAP_BSS_CONFIG;
4728 req->req_id = MLAN_IOCTL_BSS;
4729 req->action = action;
4730
4731 if (action == MLAN_ACT_SET)
4732 moal_memcpy_ext(priv->phandle, &bss->param.bss_config, sys_cfg,
4733 sizeof(mlan_uap_bss_param),
4734 sizeof(bss->param.bss_config));
4735
4736 ret = woal_request_ioctl(priv, req, wait_option);
4737 if (ret != MLAN_STATUS_SUCCESS)
4738 goto done;
4739
4740 if (action == MLAN_ACT_GET)
4741 moal_memcpy_ext(priv->phandle, sys_cfg, &bss->param.bss_config,
4742 sizeof(mlan_uap_bss_param),
4743 sizeof(mlan_uap_bss_param));
4744
4745 done:
4746 if (ret != MLAN_STATUS_PENDING)
4747 kfree(req);
4748 LEAVE();
4749 return ret;
4750 }
4751
4752 /**
4753 * @brief Set invalid data for each member of mlan_uap_bss_param
4754 * structure
4755 *
4756 * @param config A pointer to mlan_uap_bss_param structure
4757 *
4758 * @return N/A
4759 */
woal_set_sys_config_invalid_data(mlan_uap_bss_param * config)4760 void woal_set_sys_config_invalid_data(mlan_uap_bss_param *config)
4761 {
4762 ENTER();
4763
4764 memset(config, 0, sizeof(mlan_uap_bss_param));
4765 config->bcast_ssid_ctl = 0x7F;
4766 config->radio_ctl = 0x7F;
4767 config->dtim_period = 0x7F;
4768 config->beacon_period = 0x7FFF;
4769 config->tx_data_rate = 0x7FFF;
4770 config->mcbc_data_rate = 0x7FFF;
4771 config->tx_power_level = 0x7F;
4772 config->tx_antenna = 0x7F;
4773 config->rx_antenna = 0x7F;
4774 config->pkt_forward_ctl = 0x7F;
4775 config->max_sta_count = 0x7FFF;
4776 config->auth_mode = 0x7F;
4777 config->sta_ageout_timer = 0x7FFFFFFF;
4778 config->pairwise_update_timeout = 0x7FFFFFFF;
4779 config->pwk_retries = 0x7FFFFFFF;
4780 config->groupwise_update_timeout = 0x7FFFFFFF;
4781 config->gwk_retries = 0x7FFFFFFF;
4782 config->mgmt_ie_passthru_mask = 0x7FFFFFFF;
4783 config->ps_sta_ageout_timer = 0x7FFFFFFF;
4784 config->rts_threshold = 0x7FFF;
4785 config->frag_threshold = 0x7FFF;
4786 config->retry_limit = 0x7FFF;
4787 config->filter.filter_mode = 0x7FFF;
4788 config->filter.mac_count = 0x7FFF;
4789 config->wpa_cfg.rsn_protection = 0x7F;
4790 config->wpa_cfg.gk_rekey_time = 0x7FFFFFFF;
4791 config->enable_2040coex = 0x7F;
4792 config->wmm_para.qos_info = 0x7F;
4793
4794 LEAVE();
4795 }
4796