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