xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlinux/moal_ioctl.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /** @file moal_ioctl.c
2  *
3  * @brief This file contains ioctl function to MLAN
4  *
5  *
6  * Copyright 2008-2022 NXP
7  *
8  * This software file (the File) is distributed by NXP
9  * under the terms of the GNU General Public License Version 2, June 1991
10  * (the License).  You may use, redistribute and/or modify the 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_eth_ioctl.h"
30 #ifdef SDIO
31 #include "moal_sdio.h"
32 #endif
33 #ifdef USB
34 #include "moal_usb.h"
35 #endif
36 #ifdef UAP_SUPPORT
37 #include "moal_uap.h"
38 #endif
39 
40 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
41 #include "moal_cfg80211.h"
42 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
43 #include "moal_cfg80211_util.h"
44 #endif
45 #endif
46 
47 /********************************************************
48 			Local Variables
49 ********************************************************/
50 #define MRVL_TLV_HEADER_SIZE 4
51 /* NXP Channel config TLV ID */
52 #define MRVL_CHANNELCONFIG_TLV_ID (0x0100 + 0x2a) /* 0x012a */
53 
54 typedef struct _hostcmd_header {
55 	/** Command Header : Command */
56 	t_u16 command;
57 	/** Command Header : Size */
58 	t_u16 size;
59 	/** Command Header : Sequence number */
60 	t_u16 seq_num;
61 	/** Command Header : Result */
62 	t_u16 result;
63 	/** Command action */
64 	t_u16 action;
65 } hostcmd_header, *phostcmd_header;
66 
67 /** Region code mapping */
68 typedef struct _region_code_mapping_t {
69 	/** Region */
70 	t_u8 region[COUNTRY_CODE_LEN];
71 	/** Code */
72 	t_u8 code;
73 } region_code_mapping_t;
74 
75 #define EU_REGION_CODE 0x30
76 
77 /** Region code mapping table */
78 static region_code_mapping_t region_code_mapping[] = {
79 	{"00", 0x00}, /* World       */
80 	{"US", 0x10}, /* US FCC      */
81 	{"CA", 0x20}, /* IC Canada   */
82 	{"SG", 0x10}, /* Singapore   */
83 	{"EU", 0x30}, /* ETSI        */
84 	{"AU", 0x30}, /* Australia   */
85 	{"KR", 0x30}, /* Republic Of Korea */
86 	{"JP", 0x40}, /* Japan       */
87 	{"CN", 0x50}, /* China       */
88 	{"BR", 0x09}, /* Brazil      */
89 	{"RU", 0x0f}, /* Russia      */
90 	{"IN", 0x06}, /* India       */
91 	{"MY", 0x06}, /* Malaysia    */
92 	{"MX", 0x07}, /* Mexico    */
93 	{"NE", 0x30}, /* New Zeland  */
94 };
95 
96 /** EEPROM Region code mapping table */
97 static region_code_mapping_t hw_region_code_mapping[] = {
98 	{"00 ", 0x00}, /* World       */
99 	{"US ", 0x10}, /* US FCC      */
100 	{"CA ", 0x20}, /* IC Canada   */
101 	{"KR ", 0x30}, /* Korea       */
102 	{"CN ", 0x50}, /* China       */
103 	{"ES ", 0x31}, /* Spain       */
104 	{"FR ", 0x32}, /* France      */
105 	{"JP ", 0x40}, /* Japan       */
106 	{"JP ", 0x41}, /* Japan       */
107 };
108 
109 /** Country code for ETSI */
110 static t_u8 eu_country_code_table[][COUNTRY_CODE_LEN] = {
111 	"AL", "AD", "AT", "AU", "BE", "BA", "BG", "HR", "CY", "CZ", "DK", "EE",
112 	"FI", "FR", "MK", "DE", "GR", "HU", "IS", "IE", "IT", "LV", "LI", "LT",
113 	"LU", "MT", "MD", "MC", "ME", "NL", "NO", "PL", "RO", "SM", "RS", "SI",
114 	"SK", "ES", "SE", "CH", "TR", "UA", "UK", "GB", "NE", "NZ", "DZ", "AO",
115 	"AM", "AW", "BH", "BD", "BT", "BO", "BQ", "BW", "VG", "BF", "BI", "KH",
116 	"CL", "KM", "CG", "CD", "CW", "EG", "FO", "GF", "PF", "GE", "GI", "GP",
117 	"HK", "IN", "ID", "IM", "IL", "JE", "KE", "XK", "KW", "LA", "LR", "MW",
118 	"MV", "MQ", "MR", "YT", "MA", "MZ", "MM", "NA", "NC", "NG", "OM", "PS",
119 	"PT", "QA", "RW", "RE", "BL", "MF", "VC", "SA", "SC", "ZA", "SZ", "SY",
120 	"TZ", "TG", "TN", "AE", "VA", "EH", "YE", "ZM", "ZW"};
121 
122 /********************************************************
123 			Global Variables
124 ********************************************************/
125 
126 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
127 #ifdef UAP_SUPPORT
128 /** Network device handlers for uAP */
129 extern const struct net_device_ops woal_uap_netdev_ops;
130 #endif
131 #ifdef STA_SUPPORT
132 /** Network device handlers for STA */
133 extern const struct net_device_ops woal_netdev_ops;
134 #endif
135 #endif
136 
137 /********************************************************
138 			Local Functions
139 ********************************************************/
140 /**
141  *  @brief This function converts region string to region code
142  *
143  *  @param country_code     Region string
144  *
145  *  @return                 Region code
146  */
woal_is_country_code_supported(t_u8 * country_code)147 static t_bool woal_is_country_code_supported(t_u8 *country_code)
148 {
149 	t_u8 i;
150 	ENTER();
151 
152 	for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
153 		if (!memcmp(country_code, region_code_mapping[i].region,
154 			    COUNTRY_CODE_LEN - 1)) {
155 			PRINTM(MIOCTL,
156 			       "found country code in region_code table\n");
157 			LEAVE();
158 			return MTRUE;
159 		}
160 	}
161 
162 	LEAVE();
163 	return MFALSE;
164 }
165 /**
166  *  @brief This function converts region string to region code
167  *
168  *  @param region_string    Region string
169  *
170  *  @return                 Region code
171  */
region_string_2_region_code(char * region_string)172 static t_u8 region_string_2_region_code(char *region_string)
173 {
174 	t_u8 i;
175 
176 	ENTER();
177 	for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
178 		if (!memcmp(region_string, region_code_mapping[i].region,
179 			    strlen(region_string))) {
180 			LEAVE();
181 			return region_code_mapping[i].code;
182 		}
183 	}
184 
185 	/* If still not found, look for code in EU country code table */
186 	for (i = 0; i < ARRAY_SIZE(eu_country_code_table); i++) {
187 		if (!memcmp(region_string, eu_country_code_table[i],
188 			    COUNTRY_CODE_LEN - 1)) {
189 			PRINTM(MIOCTL, "found region code=%d in EU table\n",
190 			       EU_REGION_CODE);
191 			LEAVE();
192 			return EU_REGION_CODE;
193 		}
194 	}
195 
196 	/* Default is US */
197 	LEAVE();
198 	return region_code_mapping[0].code;
199 }
200 
201 /**
202  *  @brief This function converts region string to region code
203  *
204  *  @param country_code     Region string
205  *
206  *  @return                 Region code
207  */
woal_is_etsi_country(t_u8 * country_code)208 t_bool woal_is_etsi_country(t_u8 *country_code)
209 {
210 	t_u8 i;
211 	ENTER();
212 
213 	for (i = 0; i < ARRAY_SIZE(eu_country_code_table); i++) {
214 		if (!memcmp(country_code, eu_country_code_table[i],
215 			    COUNTRY_CODE_LEN - 1)) {
216 			PRINTM(MIOCTL, "found region code=%d in EU table\n",
217 			       EU_REGION_CODE);
218 			LEAVE();
219 			return MTRUE;
220 		}
221 	}
222 
223 	LEAVE();
224 	return MFALSE;
225 }
226 
227 /**
228  *  @brief This function converts region string to region code
229  *
230  *  @param region_code      region code
231  *
232  *  @return                 Region string or NULL
233  */
region_code_2_string(t_u8 region_code)234 char *region_code_2_string(t_u8 region_code)
235 {
236 	t_u8 i;
237 
238 	ENTER();
239 	for (i = 0; i < ARRAY_SIZE(hw_region_code_mapping); i++) {
240 		if (hw_region_code_mapping[i].code == region_code) {
241 			LEAVE();
242 			return hw_region_code_mapping[i].region;
243 		}
244 	}
245 	LEAVE();
246 	return NULL;
247 }
248 
woal_is_valid_alpha2(char * alpha2)249 t_u8 woal_is_valid_alpha2(char *alpha2)
250 {
251 	if (!alpha2 || strlen(alpha2) < 2)
252 		return MFALSE;
253 	if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
254 		return MTRUE;
255 	return MFALSE;
256 }
257 
258 /**
259  * @brief Get second channel offset
260  *
261  * @param priv         A pointer to moal_private structure
262  * @param chan             channel num
263  * @return                second channel offset
264  */
woal_get_second_channel_offset(moal_private * priv,int chan)265 t_u8 woal_get_second_channel_offset(moal_private *priv, int chan)
266 {
267 	t_u8 chan2Offset = SEC_CHAN_NONE;
268 	mlan_bss_info bss_info;
269 
270 	/* Special Case: 20Mhz-only Channel */
271 	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
272 	if (bss_info.region_code != COUNTRY_CODE_US && chan == 165)
273 		return chan2Offset;
274 
275 	switch (chan) {
276 	case 36:
277 	case 44:
278 	case 52:
279 	case 60:
280 	case 100:
281 	case 108:
282 	case 116:
283 	case 124:
284 	case 132:
285 	case 140:
286 	case 149:
287 	case 157:
288 	case 165:
289 	case 173:
290 		chan2Offset = SEC_CHAN_ABOVE;
291 		break;
292 	case 40:
293 	case 48:
294 	case 56:
295 	case 64:
296 	case 104:
297 	case 112:
298 	case 120:
299 	case 128:
300 	case 136:
301 	case 144:
302 	case 153:
303 	case 161:
304 	case 169:
305 	case 177:
306 		chan2Offset = SEC_CHAN_BELOW;
307 		break;
308 	}
309 	return chan2Offset;
310 }
311 
312 /**
313  *  @brief Copy mc address to the mlist
314  *
315  *  @param mlist    A pointer to mlan_multicast_list structure
316  *  @param mac      mc address
317  *
318  *  @return         N/A
319  */
woal_copy_mc_addr(mlan_multicast_list * mlist,mlan_802_11_mac_addr mac)320 static inline void woal_copy_mc_addr(mlan_multicast_list *mlist,
321 				     mlan_802_11_mac_addr mac)
322 {
323 	t_u32 i = 0;
324 	for (i = 0; i < mlist->num_multicast_addr; i++) {
325 		if (!memcmp(&mlist->mac_list[i], mac, ETH_ALEN))
326 			return;
327 	}
328 	if (mlist->num_multicast_addr < MLAN_MAX_MULTICAST_LIST_SIZE)
329 		moal_memcpy_ext(NULL,
330 				&mlist->mac_list[mlist->num_multicast_addr],
331 				mac, ETH_ALEN, sizeof(mlan_802_11_mac_addr));
332 	mlist->num_multicast_addr++;
333 	return;
334 }
335 
336 /**
337  *  @brief Copy multicast table
338  *
339  *  @param mlist    A pointer to mlan_multicast_list structure
340  *  @param dev      A pointer to net_device structure
341  *
342  *  @return         Number of multicast addresses
343  */
woal_copy_mcast_addr(mlan_multicast_list * mlist,struct net_device * dev)344 static inline int woal_copy_mcast_addr(mlan_multicast_list *mlist,
345 				       struct net_device *dev)
346 {
347 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
348 	struct dev_mc_list *mcptr = dev->mc_list;
349 	int i = 0;
350 #else
351 	struct netdev_hw_addr *mcptr = NULL;
352 #endif /* < 2.6.35 */
353 
354 	ENTER();
355 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
356 	for (i = 0; i < dev->mc_count && mcptr; i++) {
357 		woal_copy_mc_addr(mlist, mcptr->dmi_addr);
358 		mcptr = mcptr->next;
359 	}
360 #else
361 	netdev_for_each_mc_addr (mcptr, dev)
362 		woal_copy_mc_addr(mlist, mcptr->addr);
363 #endif /* < 2.6.35 */
364 	LEAVE();
365 	return mlist->num_multicast_addr;
366 }
367 
368 /**
369  *  @brief copy mc list from all the active interface
370  *
371  *  @param handle  A pointer to moal_handle
372  *  @param mlist  A pointer to multicast list
373  *
374  *  @return       total_mc_count
375  */
woal_copy_all_mc_list(moal_handle * handle,mlan_multicast_list * mlist)376 static int woal_copy_all_mc_list(moal_handle *handle,
377 				 mlan_multicast_list *mlist)
378 {
379 	int i;
380 	moal_private *priv = NULL;
381 #ifdef STA_SUPPORT
382 	int mc_count = 0;
383 #endif
384 	ENTER();
385 	for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) {
386 #ifdef STA_SUPPORT
387 		if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA) {
388 			if (handle->priv[i]->media_connected == MTRUE) {
389 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
390 				mc_count = priv->netdev->mc_count;
391 #else
392 				mc_count = netdev_mc_count(priv->netdev);
393 #endif
394 				if (mc_count)
395 					woal_copy_mcast_addr(mlist,
396 							     priv->netdev);
397 			}
398 		}
399 #endif
400 	}
401 	PRINTM(MIOCTL, "total mc_count=%d\n", mlist->num_multicast_addr);
402 	LEAVE();
403 	return mlist->num_multicast_addr;
404 }
405 
406 /**
407  *  @brief Fill in wait queue
408  *
409  *  @param priv         A pointer to moal_private structure
410  *  @param wait         A pointer to wait_queue structure
411  *  @param wait_option  Wait option
412  *
413  *  @return             N/A
414  */
woal_fill_wait_queue(moal_private * priv,wait_queue * wait,t_u8 wait_option)415 static inline void woal_fill_wait_queue(moal_private *priv, wait_queue *wait,
416 					t_u8 wait_option)
417 {
418 	ENTER();
419 	wait->start_time = jiffies;
420 	wait->condition = MFALSE;
421 	wait->wait_timeout = MFALSE;
422 	switch (wait_option) {
423 	case MOAL_NO_WAIT:
424 		break;
425 	case MOAL_IOCTL_WAIT:
426 		init_waitqueue_head(&wait->wait);
427 		break;
428 	case MOAL_IOCTL_WAIT_TIMEOUT:
429 		init_waitqueue_head(&wait->wait);
430 		wait->wait_timeout = MTRUE;
431 		break;
432 	}
433 	LEAVE();
434 	return;
435 }
436 
437 /**
438  *  @brief Wait mlan ioctl complete
439  *
440  *  @param priv         A pointer to moal_private structure
441  *  @param req          A pointer to mlan_ioctl_req structure
442  *  @param wait_option  Wait option
443  *
444  *  @return             N/A
445  */
woal_wait_ioctl_complete(moal_private * priv,mlan_ioctl_req * req,t_u8 wait_option)446 static inline mlan_status woal_wait_ioctl_complete(moal_private *priv,
447 						   mlan_ioctl_req *req,
448 						   t_u8 wait_option)
449 {
450 	mlan_status status;
451 	wait_queue *wait = (wait_queue *)req->reserved_1;
452 	unsigned long flags;
453 
454 	ENTER();
455 
456 	priv->phandle->ioctl_timeout = MFALSE;
457 
458 	switch (wait_option) {
459 	case MOAL_NO_WAIT:
460 		break;
461 	case MOAL_IOCTL_WAIT:
462 		while (wait_event_interruptible_exclusive(
463 			       wait->wait, wait->condition) == -ERESTARTSYS &&
464 		       wait->retry < MAX_RETRY_CNT) {
465 			wait->retry++;
466 		}
467 		break;
468 	case MOAL_IOCTL_WAIT_TIMEOUT:
469 		wait_event_timeout(wait->wait, wait->condition,
470 				   MOAL_IOCTL_TIMEOUT);
471 		break;
472 	}
473 	spin_lock_irqsave(&priv->phandle->driver_lock, flags);
474 	if (wait->condition == MFALSE) {
475 		if (wait_option == MOAL_IOCTL_WAIT_TIMEOUT) {
476 			priv->phandle->ioctl_timeout = MTRUE;
477 			PRINTM(MMSG,
478 			       "wlan: IOCTL timeout %p id=0x%x, sub_id=0x%x, wait_option=%d, action=%d\n",
479 			       req, req->req_id, (*(t_u32 *)req->pbuf),
480 			       wait_option, (int)req->action);
481 		} else {
482 			PRINTM(MMSG,
483 			       "wlan: IOCTL by signal %p id=0x%x, sub_id=0x%x, wait_option=%d, action=%d\n",
484 			       req, req->req_id, (*(t_u32 *)req->pbuf),
485 			       wait_option, (int)req->action);
486 		}
487 		req->reserved_1 = 0;
488 		status = MLAN_STATUS_PENDING;
489 	} else {
490 		status = wait->status;
491 	}
492 	spin_unlock_irqrestore(&priv->phandle->driver_lock, flags);
493 
494 	LEAVE();
495 	return status;
496 }
497 
498 /**
499  *  @brief CAC period block cmd handler
500  *
501  *  @param priv     A pointer to moal_private structure
502  *  @param req      A pointer to mlan_ioctl_req buffer
503  *
504  *  @return         MTRUE/MFALSE
505  */
woal_cac_period_block_cmd(moal_private * priv,pmlan_ioctl_req req)506 static inline t_bool woal_cac_period_block_cmd(moal_private *priv,
507 					       pmlan_ioctl_req req)
508 {
509 	mlan_status ret = MFALSE;
510 	t_u32 sub_command;
511 
512 	ENTER();
513 	if (req == NULL || req->pbuf == NULL)
514 		goto done;
515 
516 	sub_command = *(t_u32 *)req->pbuf;
517 
518 	switch (req->req_id) {
519 	case MLAN_IOCTL_SCAN:
520 		if (sub_command == MLAN_OID_SCAN_NORMAL ||
521 		    sub_command == MLAN_OID_SCAN_SPECIFIC_SSID ||
522 		    sub_command == MLAN_OID_SCAN_USER_CONFIG)
523 			ret = MTRUE;
524 		break;
525 	case MLAN_IOCTL_BSS:
526 		if (sub_command == MLAN_OID_BSS_STOP ||
527 		    sub_command == MLAN_OID_BSS_CHANNEL
528 		    /* sub_command == MLAN_OID_BSS_ROLE */)
529 			ret = MTRUE;
530 #ifdef UAP_SUPPORT
531 		else if (sub_command == MLAN_OID_UAP_BSS_CONFIG) {
532 			mlan_ds_bss *bss = (mlan_ds_bss *)req->pbuf;
533 			if (bss->param.bss_config.channel)
534 				ret = MTRUE;
535 			else
536 				ret = MFALSE;
537 		}
538 #endif
539 		break;
540 	case MLAN_IOCTL_RADIO_CFG:
541 		if (sub_command == MLAN_OID_BAND_CFG ||
542 		    sub_command == MLAN_OID_REMAIN_CHAN_CFG)
543 			ret = MTRUE;
544 		break;
545 	case MLAN_IOCTL_SNMP_MIB:
546 		if (sub_command == MLAN_OID_SNMP_MIB_DOT11D)
547 			ret = MTRUE;
548 #if defined(UAP_SUPPORT)
549 		if (sub_command == MLAN_OID_SNMP_MIB_DOT11H)
550 			ret = MTRUE;
551 #endif
552 		break;
553 	case MLAN_IOCTL_11D_CFG:
554 #ifdef STA_SUPPORT
555 		if (sub_command == MLAN_OID_11D_CFG_ENABLE)
556 			ret = MTRUE;
557 #endif
558 #ifdef UAP_SUPPORT
559 		if (sub_command == MLAN_OID_11D_DOMAIN_INFO)
560 			ret = MTRUE;
561 #endif
562 		if (sub_command == MLAN_OID_11D_DOMAIN_INFO_EXT)
563 			ret = MTRUE;
564 		break;
565 	case MLAN_IOCTL_MISC_CFG:
566 		if (sub_command == MLAN_OID_MISC_REGION)
567 			ret = MTRUE;
568 		if (sub_command == MLAN_OID_MISC_HOST_CMD) {
569 			phostcmd_header phostcmd;
570 			t_u8 *ptlv_buf;
571 			t_u16 tag, length;
572 
573 			phostcmd =
574 				(phostcmd_header)((pmlan_ds_misc_cfg)req->pbuf)
575 					->param.hostcmd.cmd;
576 			ptlv_buf = (t_u8 *)phostcmd + sizeof(hostcmd_header);
577 			if (phostcmd->action == MLAN_ACT_SET) {
578 				while (ptlv_buf <
579 				       (t_u8 *)phostcmd + phostcmd->size) {
580 					tag = *(t_u16 *)ptlv_buf;
581 					length = *(t_u16 *)(ptlv_buf + 2);
582 					/* Check Blocking TLV here, should add
583 					 * more... */
584 					if (tag == MRVL_CHANNELCONFIG_TLV_ID) {
585 						ret = MTRUE;
586 						break;
587 					}
588 					ptlv_buf +=
589 						(length + MRVL_TLV_HEADER_SIZE);
590 				}
591 			}
592 		}
593 		break;
594 	case MLAN_IOCTL_11H_CFG:
595 		/* Prevent execute more than once */
596 		if (sub_command == MLAN_OID_11H_CHANNEL_CHECK)
597 			ret = MTRUE;
598 		break;
599 	default:
600 		ret = MFALSE;
601 		break;
602 	}
603 
604 done:
605 	LEAVE();
606 	return ret;
607 }
608 
609 /********************************************************
610 			Global Functions
611 ********************************************************/
612 
613 /**
614  *  @brief Send ioctl request to MLAN
615  *
616  *  @param priv          A pointer to moal_private structure
617  *  @param req           A pointer to mlan_ioctl_req buffer
618  *  @param wait_option   Wait option (MOAL_WAIT or MOAL_NO_WAIT)
619  *
620  *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
621  *                          -- success, otherwise fail
622  */
woal_request_ioctl(moal_private * priv,mlan_ioctl_req * req,t_u8 wait_option)623 mlan_status woal_request_ioctl(moal_private *priv, mlan_ioctl_req *req,
624 			       t_u8 wait_option)
625 {
626 	wait_queue *wait = NULL;
627 	mlan_status status;
628 	unsigned long flags;
629 	t_u32 sub_command = 0;
630 
631 	ENTER();
632 
633 	if (!priv || !priv->phandle || !priv->phandle->pmlan_adapter || !req) {
634 		PRINTM(MINFO,
635 		       "priv or priv->phandle or priv->phandle->pmlan_adapter or req is null\n");
636 		LEAVE();
637 		return MLAN_STATUS_FAILURE;
638 	}
639 
640 	sub_command = *(t_u32 *)req->pbuf;
641 
642 	if (sub_command != MLAN_OID_GET_DEBUG_INFO &&
643 	    sub_command != MLAN_OID_MISC_WARM_RESET) {
644 		if (priv->phandle->surprise_removed == MTRUE ||
645 		    priv->phandle->driver_status) {
646 			PRINTM(MCMND,
647 			       "IOCTL is not allowed while the device is not present or hang\n");
648 			LEAVE();
649 			return MLAN_STATUS_FAILURE;
650 		}
651 		if (priv->phandle->is_suspended == MTRUE) {
652 			PRINTM(MCMND, "IOCTL is not allowed while suspended\n");
653 			LEAVE();
654 			return MLAN_STATUS_FAILURE;
655 		}
656 #ifdef MFG_CMD_SUPPORT
657 		if (mfg_mode && sub_command != MLAN_OID_MISC_HOST_CMD) {
658 			PRINTM(MCMND, "Only HOST_CMD allowed in MFG mode\n");
659 			LEAVE();
660 			return MLAN_STATUS_FAILURE;
661 		}
662 #endif
663 	}
664 	/* For MLAN_OID_MISC_HOST_CMD, action is 0, "action set" is checked
665 	 * later */
666 	if ((req->action == MLAN_ACT_SET || req->action == 0) &&
667 	    priv->phandle->cac_period == MTRUE) {
668 		/* CAC checking period left to complete jiffies */
669 		long cac_left_jiffies;
670 
671 		/* cac_left_jiffies will be negative if and only if
672 		 * event MLAN_EVENT_ID_DRV_MEAS_REPORT recieved from FW
673 		 * after CAC measure period ends,
674 		 * usually this could be considered as a FW bug
675 		 */
676 		cac_left_jiffies =
677 			priv->phandle->cac_timer_jiffies -
678 			(jiffies - priv->phandle->meas_start_jiffies);
679 		if (priv->phandle->cac_period_jiffies) {
680 			cac_left_jiffies =
681 				priv->phandle->cac_period_jiffies -
682 				(jiffies - priv->phandle->meas_start_jiffies);
683 		}
684 		if (priv->phandle->cac_restart)
685 			cac_left_jiffies = DEF_CAC_DWELL_TIME * HZ / 1000;
686 		if (cac_left_jiffies < 0) {
687 			/* Avoid driver hang in FW died during CAC measure
688 			 * period */
689 			priv->phandle->cac_period = MFALSE;
690 			PRINTM(MERROR,
691 			       "CAC measure period spends longer than scheduled time "
692 			       "or meas done event never received\n");
693 			status = MLAN_STATUS_FAILURE;
694 #ifdef UAP_SUPPORT
695 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
696 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
697 			if (priv->uap_host_based &&
698 			    moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
699 				woal_cfg80211_dfs_vendor_event(
700 					priv, event_dfs_cac_aborted,
701 					&priv->chan);
702 #endif
703 #endif
704 #endif
705 
706 			goto done;
707 		}
708 
709 		/* Check BSS START first */
710 		if (sub_command == MLAN_OID_BSS_START) {
711 			mlan_ds_bss *bss;
712 			bss = (mlan_ds_bss *)req->pbuf;
713 			/*
714 			 * Bss delay start after channel report received,
715 			 * not block the driver by delay executing. This is
716 			 * because a BSS_START cmd is always executed right
717 			 * after channel check issued.
718 			 */
719 			if (priv->phandle->delay_bss_start == MFALSE) {
720 				PRINTM(MMSG,
721 				       "Received BSS Start command during CAC period, delay executing %ld seconds\n",
722 				       cac_left_jiffies / HZ);
723 				priv->phandle->delay_bss_start = MTRUE;
724 				moal_memcpy_ext(
725 					priv->phandle,
726 					&priv->phandle->delay_ssid_bssid,
727 					&bss->param.ssid_bssid,
728 					sizeof(mlan_ssid_bssid),
729 					sizeof(mlan_ssid_bssid));
730 				/* TODO: return success to allow the half below
731 				 * of routines of which calling BSS start to
732 				 * execute
733 				 */
734 				status = MLAN_STATUS_SUCCESS;
735 				goto done;
736 			} else {
737 				/* TODO: not blocking it, just return failure */
738 				PRINTM(MMSG,
739 				       "Only one BSS Start command allowed for delay executing!\n");
740 				status = MLAN_STATUS_FAILURE;
741 				goto done;
742 			}
743 		}
744 		if (woal_cac_period_block_cmd(priv, req)) {
745 			priv->phandle->meas_wait_q_woken = MFALSE;
746 			PRINTM(MMSG,
747 			       "CAC check is on going... Blocking Command %ld seconds\n",
748 			       cac_left_jiffies / HZ);
749 			/* blocking timeout set to 1.5 * CAC checking period
750 			 * left time */
751 			wait_event_interruptible_timeout(
752 				priv->phandle->meas_wait_q,
753 				priv->phandle->meas_wait_q_woken,
754 				cac_left_jiffies * 3 / 2);
755 		}
756 	}
757 #ifdef UAP_CFG80211
758 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
759 	else if (priv->phandle->is_cac_timer_set &&
760 		 (req->action == MLAN_ACT_SET || req->action == 0)) {
761 		if (woal_cac_period_block_cmd(priv, req)) {
762 			PRINTM(MMSG,
763 			       "CAC check is on going... Blocking Command\n");
764 			status = MLAN_STATUS_FAILURE;
765 			goto done;
766 		}
767 	}
768 #endif
769 #endif
770 	else if (priv->phandle->cac_period) {
771 		PRINTM(MINFO, "Operation during CAC check period.\n");
772 	}
773 	wait = (wait_queue *)req->reserved_1;
774 	req->bss_index = priv->bss_index;
775 	if (wait_option)
776 		woal_fill_wait_queue(priv, wait, wait_option);
777 	else
778 		req->reserved_1 = 0;
779 
780 	/* Call MLAN ioctl handle */
781 	atomic_inc(&priv->phandle->ioctl_pending);
782 	spin_lock_irqsave(&priv->phandle->ioctl_lock, flags);
783 	status = mlan_ioctl(priv->phandle->pmlan_adapter, req);
784 	spin_unlock_irqrestore(&priv->phandle->ioctl_lock, flags);
785 	switch (status) {
786 	case MLAN_STATUS_PENDING:
787 		if (wait_option == MOAL_NO_WAIT)
788 			PRINTM(MIOCTL, "IOCTL MOAL_NO_WAIT: %p\n", req);
789 		else
790 			PRINTM(MIOCTL,
791 			       "IOCTL pending: %p id=0x%x, sub_id=0x%x wait_option=%d, action=%d\n",
792 			       req, req->req_id, (*(t_u32 *)req->pbuf),
793 			       wait_option, (int)req->action);
794 		/* Status pending, wake up main process */
795 		queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
796 
797 		/* Wait for completion */
798 		if (wait_option)
799 			status = woal_wait_ioctl_complete(priv, req,
800 							  wait_option);
801 		break;
802 	case MLAN_STATUS_SUCCESS:
803 	case MLAN_STATUS_FAILURE:
804 	case MLAN_STATUS_RESOURCE:
805 		if (req)
806 			PRINTM(MIOCTL,
807 			       "IOCTL: %p id=0x%x, sub_id=0x%x wait_option=%d, action=%d status=%d\n",
808 			       req, req->req_id, (*(t_u32 *)req->pbuf),
809 			       wait_option, (int)req->action, status);
810 		atomic_dec(&priv->phandle->ioctl_pending);
811 		break;
812 	default:
813 		atomic_dec(&priv->phandle->ioctl_pending);
814 		break;
815 	}
816 
817 done:
818 	LEAVE();
819 	return status;
820 }
821 
822 /**
823  *  @brief Send set MAC address request to MLAN
824  *
825  *  @param priv   A pointer to moal_private structure
826  *  @param wait_option wait option
827  *
828  *  @return       MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
829  *                  -- success, otherwise fail
830  */
woal_request_set_mac_address(moal_private * priv,t_u8 wait_option)831 mlan_status woal_request_set_mac_address(moal_private *priv, t_u8 wait_option)
832 {
833 	mlan_ioctl_req *req = NULL;
834 	mlan_ds_bss *bss = NULL;
835 	mlan_status status;
836 	ENTER();
837 
838 	/* Allocate an IOCTL request buffer */
839 	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
840 	if (req == NULL) {
841 		status = MLAN_STATUS_FAILURE;
842 		goto done;
843 	}
844 
845 	/* Fill request buffer */
846 	bss = (mlan_ds_bss *)req->pbuf;
847 	bss->sub_command = MLAN_OID_BSS_MAC_ADDR;
848 	moal_memcpy_ext(priv->phandle, &bss->param.mac_addr, priv->current_addr,
849 			sizeof(mlan_802_11_mac_addr),
850 			sizeof(mlan_802_11_mac_addr));
851 	req->req_id = MLAN_IOCTL_BSS;
852 	req->action = MLAN_ACT_SET;
853 
854 	/* Send IOCTL request to MLAN */
855 	status = woal_request_ioctl(priv, req, wait_option);
856 	if (status == MLAN_STATUS_FAILURE) {
857 		PRINTM(MERROR,
858 		       "set mac address failed! status=%d, error_code=0x%x\n",
859 		       status, req->status_code);
860 	} else {
861 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)
862 		eth_hw_addr_set(priv->netdev, priv->current_addr);
863 #else
864 		moal_memcpy_ext(priv->phandle, priv->netdev->dev_addr,
865 				priv->current_addr, ETH_ALEN, ETH_ALEN);
866 #endif
867 		HEXDUMP("priv->MacAddr:", priv->current_addr, ETH_ALEN);
868 	}
869 done:
870 	if (status != MLAN_STATUS_PENDING)
871 		kfree(req);
872 	LEAVE();
873 	return status;
874 }
875 
876 /**
877  *  @brief Send multicast list request to MLAN
878  *
879  *  @param priv   A pointer to moal_private structure
880  *  @param dev    A pointer to net_device structure
881  *
882  *  @return       N/A
883  */
woal_request_set_multicast_list(moal_private * priv,struct net_device * dev)884 void woal_request_set_multicast_list(moal_private *priv, struct net_device *dev)
885 {
886 	mlan_ioctl_req *req = NULL;
887 	mlan_ds_bss *bss = NULL;
888 	mlan_status status;
889 	int mc_count = 0;
890 
891 	ENTER();
892 
893 	/* Allocate an IOCTL request buffer */
894 	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
895 	if (req == NULL) {
896 		PRINTM(MERROR, "%s:Fail to allocate ioctl req buffer\n",
897 		       __func__);
898 		goto done;
899 	}
900 
901 	/* Fill request buffer */
902 	bss = (mlan_ds_bss *)req->pbuf;
903 	bss->sub_command = MLAN_OID_BSS_MULTICAST_LIST;
904 	req->req_id = MLAN_IOCTL_BSS;
905 	req->action = MLAN_ACT_SET;
906 	if (dev->flags & IFF_PROMISC) {
907 		bss->param.multicast_list.mode = MLAN_PROMISC_MODE;
908 	} else if (dev->flags & IFF_ALLMULTI) {
909 		bss->param.multicast_list.mode = MLAN_ALL_MULTI_MODE;
910 	} else {
911 		bss->param.multicast_list.mode = MLAN_MULTICAST_MODE;
912 		mc_count = woal_copy_all_mc_list(priv->phandle,
913 						 &bss->param.multicast_list);
914 		if (mc_count > MLAN_MAX_MULTICAST_LIST_SIZE)
915 			bss->param.multicast_list.mode = MLAN_ALL_MULTI_MODE;
916 	}
917 	PRINTM(MCMND, "%s set multicast_list\n", dev->name);
918 	/* Send IOCTL request to MLAN */
919 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
920 	if (status != MLAN_STATUS_PENDING)
921 		kfree(req);
922 done:
923 	LEAVE();
924 	return;
925 }
926 
927 /**
928  *  @brief Send deauth command to MLAN
929  *
930  *  @param priv          A pointer to moal_private structure
931  *  @param wait_option          Wait option
932  *  @param mac           MAC address to deauthenticate
933  *  @param reason code   reason code to deauthenticate
934  *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
935  * otherwise fail
936  */
woal_disconnect(moal_private * priv,t_u8 wait_option,t_u8 * mac,t_u16 reason_code)937 mlan_status woal_disconnect(moal_private *priv, t_u8 wait_option, t_u8 *mac,
938 			    t_u16 reason_code)
939 {
940 	mlan_ioctl_req *req = NULL;
941 	mlan_ds_bss *bss = NULL;
942 	mlan_status status;
943 
944 	ENTER();
945 
946 	/* Allocate an IOCTL request buffer */
947 	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
948 	if (req == NULL) {
949 		status = MLAN_STATUS_FAILURE;
950 		goto done;
951 	}
952 
953 	/* Fill request buffer */
954 	bss = (mlan_ds_bss *)req->pbuf;
955 	bss->sub_command = MLAN_OID_BSS_STOP;
956 	if (mac)
957 		moal_memcpy_ext(priv->phandle,
958 				&bss->param.deauth_param.mac_addr, mac,
959 				sizeof(mlan_802_11_mac_addr),
960 				sizeof(bss->param.deauth_param.mac_addr));
961 	bss->param.deauth_param.reason_code = reason_code;
962 	req->req_id = MLAN_IOCTL_BSS;
963 	req->action = MLAN_ACT_SET;
964 
965 	/* Send IOCTL request to MLAN */
966 	status = woal_request_ioctl(priv, req, wait_option);
967 
968 done:
969 	if (status != MLAN_STATUS_PENDING)
970 		kfree(req);
971 #ifdef REASSOCIATION
972 	priv->reassoc_required = MFALSE;
973 #endif /* REASSOCIATION */
974 	priv->auto_assoc_priv.drv_assoc.status = MFALSE;
975 	priv->auto_assoc_priv.drv_reconnect.status = MFALSE;
976 	LEAVE();
977 	return status;
978 }
979 
980 #if defined(UAP_SUPPORT)
981 /**
982  * @brief               Get non-global oper class
983  *
984  * @param priv          Pointer to moal_private structure
985  * @param bw            bandwidth
986  * @param channel       channel
987  * @param oper_class    pointer to oper_class
988 
989  *  @return             non-global operclass
990  */
woal_priv_get_nonglobal_operclass_by_bw_channel(moal_private * priv,t_u8 bandwidth,t_u8 channel,t_u8 * oper_class)991 int woal_priv_get_nonglobal_operclass_by_bw_channel(moal_private *priv,
992 						    t_u8 bandwidth,
993 						    t_u8 channel,
994 						    t_u8 *oper_class)
995 {
996 	int ret = 0;
997 	mlan_ioctl_req *ioctl_req = NULL;
998 	mlan_ds_misc_cfg *misc = NULL;
999 	mlan_status status = MLAN_STATUS_SUCCESS;
1000 
1001 	ENTER();
1002 
1003 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1004 	if (ioctl_req == NULL) {
1005 		ret = -ENOMEM;
1006 		goto done;
1007 	}
1008 
1009 	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
1010 	misc->sub_command = MLAN_OID_MISC_OPER_CLASS;
1011 	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
1012 	ioctl_req->action = MLAN_ACT_GET;
1013 	misc->param.bw_chan_oper.bandwidth = bandwidth;
1014 	misc->param.bw_chan_oper.channel = channel;
1015 
1016 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1017 	if (status != MLAN_STATUS_SUCCESS) {
1018 		ret = -EFAULT;
1019 		goto done;
1020 	}
1021 	*oper_class = misc->param.bw_chan_oper.oper_class;
1022 
1023 done:
1024 	if (status != MLAN_STATUS_PENDING)
1025 		kfree(ioctl_req);
1026 
1027 	LEAVE();
1028 	return ret;
1029 }
1030 #endif
1031 
1032 /**
1033  *  @brief Send bss_start command to MLAN
1034  *
1035  *  @param priv          A pointer to moal_private structure
1036  *  @param wait_option          Wait option
1037  *  @param ssid_bssid    A point to mlan_ssid_bssid structure
1038  *
1039  *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
1040  * otherwise fail
1041  */
woal_bss_start(moal_private * priv,t_u8 wait_option,mlan_ssid_bssid * ssid_bssid)1042 mlan_status woal_bss_start(moal_private *priv, t_u8 wait_option,
1043 			   mlan_ssid_bssid *ssid_bssid)
1044 {
1045 	mlan_ioctl_req *req = NULL;
1046 	mlan_ds_bss *bss = NULL;
1047 	mlan_status status;
1048 
1049 	ENTER();
1050 
1051 	/* Stop the O.S. TX queue When we are roaming */
1052 	woal_stop_queue(priv->netdev);
1053 	if (priv->media_connected == MFALSE) {
1054 		if (netif_carrier_ok(priv->netdev))
1055 			netif_carrier_off(priv->netdev);
1056 	}
1057 
1058 	/* Allocate an IOCTL request buffer */
1059 	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
1060 	if (req == NULL) {
1061 		status = MLAN_STATUS_FAILURE;
1062 		goto done;
1063 	}
1064 
1065 	/* Fill request buffer */
1066 	bss = (mlan_ds_bss *)req->pbuf;
1067 	bss->sub_command = MLAN_OID_BSS_START;
1068 	if (ssid_bssid)
1069 		moal_memcpy_ext(priv->phandle, &bss->param.ssid_bssid,
1070 				ssid_bssid, sizeof(mlan_ssid_bssid),
1071 				sizeof(mlan_ssid_bssid));
1072 	req->req_id = MLAN_IOCTL_BSS;
1073 	req->action = MLAN_ACT_SET;
1074 
1075 	/* Send IOCTL request to MLAN */
1076 	status = woal_request_ioctl(priv, req, wait_option);
1077 	if (ssid_bssid)
1078 		moal_memcpy_ext(priv->phandle, ssid_bssid,
1079 				&bss->param.ssid_bssid, sizeof(mlan_ssid_bssid),
1080 				sizeof(mlan_ssid_bssid));
1081 #ifdef STA_CFG80211
1082 #ifdef STA_SUPPORT
1083 	priv->assoc_status = req->status_code;
1084 #endif
1085 #endif
1086 done:
1087 	if (status != MLAN_STATUS_PENDING)
1088 		kfree(req);
1089 	LEAVE();
1090 	return status;
1091 }
1092 
1093 /**
1094  *  @brief Get BSS info
1095  *
1096  *  @param priv                 A pointer to moal_private structure
1097  *  @param wait_option          Wait option
1098  *  @param bss_info             A pointer to mlan_bss_info structure
1099  *
1100  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
1101  * success, otherwise fail
1102  */
woal_get_bss_info(moal_private * priv,t_u8 wait_option,mlan_bss_info * bss_info)1103 mlan_status woal_get_bss_info(moal_private *priv, t_u8 wait_option,
1104 			      mlan_bss_info *bss_info)
1105 {
1106 	mlan_ioctl_req *req = NULL;
1107 	mlan_ds_get_info *info = NULL;
1108 	mlan_status status = MLAN_STATUS_SUCCESS;
1109 	ENTER();
1110 
1111 	/* Allocate an IOCTL request buffer */
1112 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
1113 	if (req == NULL) {
1114 		PRINTM(MERROR,
1115 		       "Fail to allocate the buffer for get bss_info\n");
1116 		status = MLAN_STATUS_FAILURE;
1117 		goto done;
1118 	}
1119 
1120 	/* Fill request buffer */
1121 	info = (mlan_ds_get_info *)req->pbuf;
1122 	info->sub_command = MLAN_OID_GET_BSS_INFO;
1123 	req->req_id = MLAN_IOCTL_GET_INFO;
1124 	req->action = MLAN_ACT_GET;
1125 
1126 	/* Send IOCTL request to MLAN */
1127 	status = woal_request_ioctl(priv, req, wait_option);
1128 	if (status == MLAN_STATUS_SUCCESS) {
1129 		if (bss_info)
1130 			moal_memcpy_ext(priv->phandle, bss_info,
1131 					&info->param.bss_info,
1132 					sizeof(mlan_bss_info),
1133 					sizeof(mlan_bss_info));
1134 	}
1135 done:
1136 	if (status != MLAN_STATUS_PENDING)
1137 		kfree(req);
1138 	LEAVE();
1139 	return status;
1140 }
1141 
1142 /**
1143  *  @brief Set/Get generic IE
1144  *
1145  *  @param priv         A pointer to moal_private structure
1146  *  @param action       Action set or get
1147  *  @param ie           Information element
1148  *  @param ie_len       Length of the IE
1149  *  @param wait_option  wait option
1150  *
1151  *  @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
1152  */
woal_set_get_gen_ie(moal_private * priv,t_u32 action,t_u8 * ie,int * ie_len,t_u8 wait_option)1153 mlan_status woal_set_get_gen_ie(moal_private *priv, t_u32 action, t_u8 *ie,
1154 				int *ie_len, t_u8 wait_option)
1155 {
1156 	mlan_status ret = MLAN_STATUS_SUCCESS;
1157 	mlan_ds_misc_cfg *misc = NULL;
1158 	mlan_ioctl_req *req = NULL;
1159 
1160 	ENTER();
1161 
1162 	if ((action == MLAN_ACT_GET) && (ie == NULL || ie_len == NULL)) {
1163 		ret = MLAN_STATUS_FAILURE;
1164 		goto done;
1165 	}
1166 
1167 	if (action == MLAN_ACT_SET && *ie_len > MAX_IE_SIZE) {
1168 		ret = MLAN_STATUS_FAILURE;
1169 		goto done;
1170 	}
1171 
1172 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1173 	if (req == NULL) {
1174 		ret = MLAN_STATUS_FAILURE;
1175 		goto done;
1176 	}
1177 
1178 	misc = (mlan_ds_misc_cfg *)req->pbuf;
1179 	misc->sub_command = MLAN_OID_MISC_GEN_IE;
1180 	req->req_id = MLAN_IOCTL_MISC_CFG;
1181 	req->action = action;
1182 	misc->param.gen_ie.type = MLAN_IE_TYPE_GEN_IE;
1183 
1184 	if (action == MLAN_ACT_SET) {
1185 		misc->param.gen_ie.len = *ie_len;
1186 		if (*ie_len)
1187 			moal_memcpy_ext(priv->phandle,
1188 					misc->param.gen_ie.ie_data, ie, *ie_len,
1189 					MAX_IE_SIZE);
1190 	}
1191 
1192 	ret = woal_request_ioctl(priv, req, wait_option);
1193 	if (ret != MLAN_STATUS_SUCCESS)
1194 		goto done;
1195 
1196 	if (action == MLAN_ACT_GET) {
1197 		*ie_len = misc->param.gen_ie.len;
1198 		if (*ie_len)
1199 			moal_memcpy_ext(priv->phandle, ie,
1200 					misc->param.gen_ie.ie_data, *ie_len,
1201 					*ie_len);
1202 	}
1203 
1204 done:
1205 	if (ret != MLAN_STATUS_PENDING)
1206 		kfree(req);
1207 	LEAVE();
1208 	return ret;
1209 }
1210 
1211 #ifdef STA_SUPPORT
1212 /**
1213  *  @brief Set/Get retry count
1214  *
1215  *  @param priv                 A pointer to moal_private structure
1216  *  @param action               Action set or get
1217  *  @param wait_option          Wait option
1218  *  @param value                Retry value
1219  *
1220  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
1221  * success, otherwise fail
1222  */
woal_set_get_retry(moal_private * priv,t_u32 action,t_u8 wait_option,int * value)1223 mlan_status woal_set_get_retry(moal_private *priv, t_u32 action,
1224 			       t_u8 wait_option, int *value)
1225 {
1226 	mlan_ioctl_req *req = NULL;
1227 	mlan_ds_snmp_mib *mib = NULL;
1228 	mlan_status ret = MLAN_STATUS_SUCCESS;
1229 
1230 	ENTER();
1231 
1232 	/* Allocate an IOCTL request buffer */
1233 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
1234 	if (req == NULL) {
1235 		ret = MLAN_STATUS_FAILURE;
1236 		goto done;
1237 	}
1238 
1239 	/* Fill request buffer */
1240 	mib = (mlan_ds_snmp_mib *)req->pbuf;
1241 	mib->sub_command = MLAN_OID_SNMP_MIB_RETRY_COUNT;
1242 	req->req_id = MLAN_IOCTL_SNMP_MIB;
1243 	req->action = action;
1244 
1245 	if (action == MLAN_ACT_SET) {
1246 		if (*value < MLAN_TX_RETRY_MIN || *value > MLAN_TX_RETRY_MAX) {
1247 			ret = MLAN_STATUS_FAILURE;
1248 			goto done;
1249 		}
1250 		mib->param.retry_count = *value;
1251 	}
1252 
1253 	/* Send IOCTL request to MLAN */
1254 	ret = woal_request_ioctl(priv, req, wait_option);
1255 	if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
1256 		*value = mib->param.retry_count;
1257 #ifdef STA_CFG80211
1258 	/* If set is invoked from other than iw i.e iwconfig,
1259 	 * wiphy retry count should be updated as well */
1260 	if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext) &&
1261 	    priv->wdev && priv->wdev->wiphy &&
1262 	    (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1263 	    (action == MLAN_ACT_SET)) {
1264 		priv->wdev->wiphy->retry_long = (t_u8)*value;
1265 		priv->wdev->wiphy->retry_short = (t_u8)*value;
1266 	}
1267 #endif
1268 
1269 done:
1270 	if (ret != MLAN_STATUS_PENDING)
1271 		kfree(req);
1272 	LEAVE();
1273 	return ret;
1274 }
1275 
1276 /**
1277  * @brief Performs pre-warm-reset
1278  *
1279  * @param priv         A pointer to moal_private structure
1280  *
1281  * @return         0 if successful else negative value
1282  */
woal_pre_warmreset(moal_private * priv)1283 int woal_pre_warmreset(moal_private *priv)
1284 {
1285 	moal_handle *handle = priv->phandle;
1286 	int ret = 0;
1287 	int intf_num;
1288 #ifdef WIFI_DIRECT_SUPPORT
1289 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
1290 #if defined(STA_WEXT) || defined(UAP_WEXT)
1291 	t_u8 bss_role = MLAN_BSS_ROLE_STA;
1292 #endif
1293 #endif
1294 #endif /* WIFI_DIRECT_SUPPORT */
1295 
1296 	ENTER();
1297 #ifdef USB
1298 #ifdef CONFIG_USB_SUSPEND
1299 	if (IS_USB(handle->card_type) && handle->is_suspended &&
1300 	    woal_exit_usb_suspend(handle)) {
1301 		PRINTM(MERROR, "Failed to resume the suspended device\n");
1302 		LEAVE();
1303 		return -EFAULT;
1304 	}
1305 #endif /* CONFIG_USB_SUSPEND */
1306 #endif
1307 	woal_cancel_cac_block(priv);
1308 	/* Reset all interfaces */
1309 	woal_reset_intf(priv, MOAL_IOCTL_WAIT, MTRUE);
1310 	/* Initialize private structures */
1311 	for (intf_num = 0; intf_num < handle->priv_num; intf_num++) {
1312 		woal_init_priv(handle->priv[intf_num], MOAL_IOCTL_WAIT);
1313 #ifdef WIFI_DIRECT_SUPPORT
1314 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
1315 #if defined(STA_WEXT) || defined(UAP_WEXT)
1316 		if ((handle->priv[intf_num]->bss_type ==
1317 		     MLAN_BSS_TYPE_WIFIDIRECT) &&
1318 		    (GET_BSS_ROLE(handle->priv[intf_num]) ==
1319 		     MLAN_BSS_ROLE_UAP)) {
1320 			if (MLAN_STATUS_SUCCESS !=
1321 			    woal_bss_role_cfg(handle->priv[intf_num],
1322 					      MLAN_ACT_SET, MOAL_IOCTL_WAIT,
1323 					      &bss_role)) {
1324 				ret = -EFAULT;
1325 				goto done;
1326 			}
1327 		}
1328 #endif /* STA_WEXT || UAP_WEXT */
1329 #endif /* STA_SUPPORT && UAP_SUPPORT */
1330 #endif /* WIFI_DIRECT_SUPPORT */
1331 	}
1332 	woal_shutdown_fw(priv, MOAL_IOCTL_WAIT);
1333 #ifdef WIFI_DIRECT_SUPPORT
1334 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
1335 #if defined(STA_WEXT) || defined(UAP_WEXT)
1336 done:
1337 #endif /* STA_WEXT || UAP_WEXT */
1338 #endif /* STA_SUPPORT && UAP_SUPPORT */
1339 #endif /* WIFI_DIRECT_SUPPORT */
1340 	LEAVE();
1341 	return ret;
1342 }
1343 
1344 /**
1345  * @brief warm reset
1346  *
1347  * @param priv         A pointer to moal_private structure
1348  *
1349  * @return        0 success, otherwise failure
1350  */
woal_warmreset(moal_private * priv)1351 int woal_warmreset(moal_private *priv)
1352 {
1353 	moal_handle *handle = priv->phandle;
1354 	mlan_ioctl_req *req = NULL;
1355 	mlan_ds_misc_cfg *misc = NULL;
1356 	mlan_status status = MLAN_STATUS_SUCCESS;
1357 	int ret = 0;
1358 	int intf_num;
1359 
1360 	/* Restart the firmware */
1361 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1362 	if (req) {
1363 		misc = (mlan_ds_misc_cfg *)req->pbuf;
1364 		misc->sub_command = MLAN_OID_MISC_WARM_RESET;
1365 		misc->param.fw_reload = MTRUE;
1366 		req->req_id = MLAN_IOCTL_MISC_CFG;
1367 		req->action = MLAN_ACT_SET;
1368 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1369 		if (status != MLAN_STATUS_SUCCESS) {
1370 			PRINTM(MERROR, "warm reset failure!\n");
1371 			ret = -EFAULT;
1372 			if (status != MLAN_STATUS_PENDING)
1373 				kfree(req);
1374 			goto done;
1375 		}
1376 		kfree(req);
1377 	}
1378 #ifdef USB
1379 	if (IS_USB(handle->card_type) && handle->params.usb_aggr == 1) {
1380 		/* Enable USB aggregation in FW */
1381 		if (woal_usb_aggr_init(handle)) {
1382 			PRINTM(MERROR, "usb aggr init fail\n");
1383 			ret = -EFAULT;
1384 			goto done;
1385 		}
1386 	}
1387 #endif
1388 
1389 	if (moal_extflg_isset(handle, EXT_AGGR_CTRL)) {
1390 		/* Enable aggregation in FW */
1391 		if (woal_init_aggr_ctrl(handle, MOAL_IOCTL_WAIT)) {
1392 			PRINTM(MERROR, "Fail to init aggr ctrl\n");
1393 			ret = -EFAULT;
1394 			goto done;
1395 		}
1396 	}
1397 
1398 	/* Enable interfaces */
1399 	for (intf_num = 0; intf_num < handle->priv_num; intf_num++) {
1400 		netif_device_attach(handle->priv[intf_num]->netdev);
1401 		woal_start_queue(handle->priv[intf_num]->netdev);
1402 	}
1403 done:
1404 	LEAVE();
1405 	return ret;
1406 }
1407 
1408 /**
1409  *  @brief Set/Get RTS threshold
1410  *
1411  *  @param priv                 A pointer to moal_private structure
1412  *  @param action               Action set or get
1413  *  @param wait_option          Wait option
1414  *  @param value                RTS threshold value
1415  *
1416  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
1417  * success, otherwise fail
1418  */
woal_set_get_rts(moal_private * priv,t_u32 action,t_u8 wait_option,int * value)1419 mlan_status woal_set_get_rts(moal_private *priv, t_u32 action, t_u8 wait_option,
1420 			     int *value)
1421 {
1422 	mlan_ioctl_req *req = NULL;
1423 	mlan_ds_snmp_mib *mib = NULL;
1424 	mlan_status ret = MLAN_STATUS_SUCCESS;
1425 
1426 	ENTER();
1427 
1428 	/* Allocate an IOCTL request buffer */
1429 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
1430 	if (req == NULL) {
1431 		ret = MLAN_STATUS_FAILURE;
1432 		goto done;
1433 	}
1434 
1435 	/* Fill request buffer */
1436 	mib = (mlan_ds_snmp_mib *)req->pbuf;
1437 	mib->sub_command = MLAN_OID_SNMP_MIB_RTS_THRESHOLD;
1438 	req->req_id = MLAN_IOCTL_SNMP_MIB;
1439 	req->action = action;
1440 
1441 	if (action == MLAN_ACT_SET) {
1442 		if (*value < MLAN_RTS_MIN_VALUE ||
1443 		    *value > MLAN_RTS_MAX_VALUE) {
1444 			ret = MLAN_STATUS_FAILURE;
1445 			goto done;
1446 		}
1447 		mib->param.rts_threshold = *value;
1448 	}
1449 
1450 	/* Send IOCTL request to MLAN */
1451 	ret = woal_request_ioctl(priv, req, wait_option);
1452 	if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
1453 		*value = mib->param.rts_threshold;
1454 #ifdef STA_CFG80211
1455 	/* If set is invoked from other than iw i.e iwconfig,
1456 	 * wiphy RTS threshold should be updated as well */
1457 	if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext) &&
1458 	    priv->wdev && priv->wdev->wiphy &&
1459 	    (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1460 	    (action == MLAN_ACT_SET))
1461 		priv->wdev->wiphy->rts_threshold = *value;
1462 #endif
1463 
1464 done:
1465 	if (ret != MLAN_STATUS_PENDING)
1466 		kfree(req);
1467 	LEAVE();
1468 	return ret;
1469 }
1470 
1471 /**
1472  *  @brief Set/Get Fragment threshold
1473  *
1474  *  @param priv                 A pointer to moal_private structure
1475  *  @param action               Action set or get
1476  *  @param wait_option          Wait option
1477  *  @param value                Fragment threshold value
1478  *
1479  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
1480  * success, otherwise fail
1481  */
woal_set_get_frag(moal_private * priv,t_u32 action,t_u8 wait_option,int * value)1482 mlan_status woal_set_get_frag(moal_private *priv, t_u32 action,
1483 			      t_u8 wait_option, int *value)
1484 {
1485 	mlan_ioctl_req *req = NULL;
1486 	mlan_ds_snmp_mib *mib = NULL;
1487 	mlan_status ret = MLAN_STATUS_SUCCESS;
1488 
1489 	ENTER();
1490 
1491 	/* Allocate an IOCTL request buffer */
1492 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
1493 	if (req == NULL) {
1494 		ret = MLAN_STATUS_FAILURE;
1495 		goto done;
1496 	}
1497 
1498 	/* Fill request buffer */
1499 	mib = (mlan_ds_snmp_mib *)req->pbuf;
1500 	mib->sub_command = MLAN_OID_SNMP_MIB_FRAG_THRESHOLD;
1501 	req->req_id = MLAN_IOCTL_SNMP_MIB;
1502 	req->action = action;
1503 
1504 	if (action == MLAN_ACT_SET) {
1505 		if (*value < MLAN_FRAG_MIN_VALUE ||
1506 		    *value > MLAN_FRAG_MAX_VALUE) {
1507 			ret = MLAN_STATUS_FAILURE;
1508 			goto done;
1509 		}
1510 		mib->param.frag_threshold = *value;
1511 	}
1512 
1513 	/* Send IOCTL request to MLAN */
1514 	ret = woal_request_ioctl(priv, req, wait_option);
1515 	if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
1516 		*value = mib->param.frag_threshold;
1517 #ifdef STA_CFG80211
1518 	/* If set is invoked from other than iw i.e iwconfig,
1519 	 * wiphy fragment threshold should be updated as well */
1520 	if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext) &&
1521 	    priv->wdev && priv->wdev->wiphy &&
1522 	    (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1523 	    (action == MLAN_ACT_SET))
1524 		priv->wdev->wiphy->frag_threshold = *value;
1525 #endif
1526 
1527 done:
1528 	if (ret != MLAN_STATUS_PENDING)
1529 		kfree(req);
1530 	LEAVE();
1531 	return ret;
1532 }
1533 
1534 /**
1535  *  @brief Set/Get TX power
1536  *
1537  *  @param priv                 A pointer to moal_private structure
1538  *  @param action               Action set or get
1539  *  @param power_cfg            A pinter to mlan_power_cfg_t structure
1540  *
1541  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
1542  * success, otherwise fail
1543  */
woal_set_get_tx_power(moal_private * priv,t_u32 action,mlan_power_cfg_t * power_cfg)1544 mlan_status woal_set_get_tx_power(moal_private *priv, t_u32 action,
1545 				  mlan_power_cfg_t *power_cfg)
1546 {
1547 	mlan_ds_power_cfg *pcfg = NULL;
1548 	mlan_ioctl_req *req = NULL;
1549 	mlan_status ret = MLAN_STATUS_SUCCESS;
1550 	ENTER();
1551 
1552 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_power_cfg));
1553 	if (req == NULL) {
1554 		ret = MLAN_STATUS_FAILURE;
1555 		goto done;
1556 	}
1557 	pcfg = (mlan_ds_power_cfg *)req->pbuf;
1558 	pcfg->sub_command = MLAN_OID_POWER_CFG;
1559 	req->req_id = MLAN_IOCTL_POWER_CFG;
1560 	req->action = action;
1561 	if (action == MLAN_ACT_SET && power_cfg)
1562 		moal_memcpy_ext(priv->phandle, &pcfg->param.power_cfg,
1563 				power_cfg, sizeof(mlan_power_cfg_t),
1564 				sizeof(mlan_power_cfg_t));
1565 
1566 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1567 	if (ret != MLAN_STATUS_SUCCESS)
1568 		goto done;
1569 
1570 	if (ret == MLAN_STATUS_SUCCESS && power_cfg)
1571 		moal_memcpy_ext(priv->phandle, power_cfg,
1572 				&pcfg->param.power_cfg,
1573 				sizeof(mlan_power_cfg_t),
1574 				sizeof(mlan_power_cfg_t));
1575 
1576 done:
1577 	if (ret != MLAN_STATUS_PENDING)
1578 		kfree(req);
1579 	LEAVE();
1580 	return ret;
1581 }
1582 
1583 /**
1584  *  @brief Set/Get IEEE power management
1585  *
1586  *  @param priv                 A pointer to moal_private structure
1587  *  @param action               Action set or get
1588  *  @param disabled             A pointer to disabled flag
1589  *  @param power_type           IEEE power type
1590  *  @param wait_option          wait option
1591  *
1592  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
1593  */
woal_set_get_power_mgmt(moal_private * priv,t_u32 action,int * disabled,int power_type,t_u8 wait_option)1594 mlan_status woal_set_get_power_mgmt(moal_private *priv, t_u32 action,
1595 				    int *disabled, int power_type,
1596 				    t_u8 wait_option)
1597 {
1598 	mlan_status ret = MLAN_STATUS_SUCCESS;
1599 	mlan_ioctl_req *req = NULL;
1600 	mlan_ds_pm_cfg *pm_cfg = NULL;
1601 
1602 	ENTER();
1603 
1604 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
1605 	if (req == NULL) {
1606 		ret = MLAN_STATUS_FAILURE;
1607 		goto done;
1608 	}
1609 	pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
1610 	pm_cfg->sub_command = MLAN_OID_PM_CFG_IEEE_PS;
1611 	req->req_id = MLAN_IOCTL_PM_CFG;
1612 	req->action = action;
1613 
1614 	if (action == MLAN_ACT_SET) {
1615 		PRINTM(MINFO, "PS_MODE set power disabled=%d power type=%#x\n",
1616 		       *disabled, power_type);
1617 		if (*disabled)
1618 			pm_cfg->param.ps_mode = 0;
1619 		else {
1620 			/* Check not support case only (vwrq->disabled == FALSE)
1621 			 */
1622 			if ((power_type & MW_POWER_TYPE) == MW_POWER_TIMEOUT) {
1623 				PRINTM(MERROR,
1624 				       "Setting power timeout is not supported\n");
1625 				ret = MLAN_STATUS_FAILURE;
1626 				goto done;
1627 			} else if ((power_type & MW_POWER_TYPE) ==
1628 				   MW_POWER_PERIOD) {
1629 				PRINTM(MERROR,
1630 				       "Setting power period is not supported\n");
1631 				ret = MLAN_STATUS_FAILURE;
1632 				goto done;
1633 			}
1634 			pm_cfg->param.ps_mode = 1;
1635 		}
1636 	}
1637 
1638 	ret = woal_request_ioctl(priv, req, wait_option);
1639 	if (ret != MLAN_STATUS_SUCCESS)
1640 		goto done;
1641 
1642 	if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
1643 		*disabled = pm_cfg->param.ps_mode;
1644 
1645 #ifdef STA_CFG80211
1646 	/* If set is invoked from other than iw i.e iwconfig,
1647 	 * wiphy IEEE power save mode should be updated */
1648 	if (IS_STA_CFG80211(priv->phandle->params.cfg80211_wext) &&
1649 	    priv->wdev && (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1650 	    (action == MLAN_ACT_SET)) {
1651 		if (*disabled)
1652 			priv->wdev->ps = MFALSE;
1653 		else
1654 			priv->wdev->ps = MTRUE;
1655 	}
1656 #endif
1657 
1658 done:
1659 	if (ret != MLAN_STATUS_PENDING)
1660 		kfree(req);
1661 	LEAVE();
1662 	return ret;
1663 }
1664 
1665 /**
1666  * @brief Set Country Code
1667  *
1668  * @param priv     A pointer to moal_private structure
1669  * @param region   A pointer to region string
1670  *
1671  * @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise
1672  * fail
1673  */
woal_set_countrycode(moal_private * priv,char * country)1674 static int woal_set_countrycode(moal_private *priv, char *country)
1675 {
1676 	int ret = 0;
1677 	mlan_ioctl_req *req = NULL;
1678 	mlan_ds_misc_cfg *pcfg_misc = NULL;
1679 	mlan_ds_misc_country_code *country_code = NULL;
1680 	mlan_status status = MLAN_STATUS_SUCCESS;
1681 
1682 	ENTER();
1683 
1684 	/* Allocate an IOCTL request buffer */
1685 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1686 	if (req == NULL) {
1687 		ret = -ENOMEM;
1688 		goto done;
1689 	}
1690 
1691 	/* Fill request buffer */
1692 	pcfg_misc = (mlan_ds_misc_cfg *)req->pbuf;
1693 	country_code = &pcfg_misc->param.country_code;
1694 	pcfg_misc->sub_command = MLAN_OID_MISC_COUNTRY_CODE;
1695 	req->req_id = MLAN_IOCTL_MISC_CFG;
1696 
1697 	memset(country_code->country_code, 0, COUNTRY_CODE_LEN);
1698 	moal_memcpy_ext(priv->phandle, country_code->country_code, country,
1699 			COUNTRY_CODE_LEN - 1, COUNTRY_CODE_LEN - 1);
1700 	req->action = MLAN_ACT_SET;
1701 
1702 	/* Send IOCTL request to MLAN */
1703 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1704 	if (status != MLAN_STATUS_SUCCESS) {
1705 		ret = -EFAULT;
1706 		goto done;
1707 	}
1708 done:
1709 	if (status != MLAN_STATUS_PENDING)
1710 		kfree(req);
1711 
1712 	LEAVE();
1713 	return ret;
1714 }
1715 
1716 /**
1717  * @brief Set region code
1718  *
1719  * @param priv     A pointer to moal_private structure
1720  * @param region   A pointer to region string
1721  *
1722  * @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise
1723  * fail
1724  */
woal_set_region_code(moal_private * priv,char * region)1725 mlan_status woal_set_region_code(moal_private *priv, char *region)
1726 {
1727 	mlan_status ret = MLAN_STATUS_SUCCESS;
1728 	mlan_ds_misc_cfg *cfg = NULL;
1729 	mlan_ioctl_req *req = NULL;
1730 
1731 	ENTER();
1732 	if (woal_is_country_code_supported(region))
1733 		return woal_set_countrycode(priv, region);
1734 
1735 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1736 	if (req == NULL) {
1737 		ret = MLAN_STATUS_FAILURE;
1738 		goto done;
1739 	}
1740 	cfg = (mlan_ds_misc_cfg *)req->pbuf;
1741 	cfg->sub_command = MLAN_OID_MISC_REGION;
1742 	req->req_id = MLAN_IOCTL_MISC_CFG;
1743 	req->action = MLAN_ACT_SET;
1744 	cfg->param.region_code = region_string_2_region_code(region);
1745 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1746 
1747 done:
1748 	if (ret != MLAN_STATUS_PENDING)
1749 		kfree(req);
1750 	LEAVE();
1751 	return ret;
1752 }
1753 
1754 /**
1755  *  @brief Set/Get data rate
1756  *
1757  *  @param priv                 A pointer to moal_private structure
1758  *  @param action               Action set or get
1759  *  @param datarate             A pointer to mlan_rate_cfg_t structure
1760  *
1761  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
1762  */
woal_set_get_data_rate(moal_private * priv,t_u8 action,mlan_rate_cfg_t * datarate)1763 mlan_status woal_set_get_data_rate(moal_private *priv, t_u8 action,
1764 				   mlan_rate_cfg_t *datarate)
1765 {
1766 	mlan_status ret = MLAN_STATUS_SUCCESS;
1767 	mlan_ds_rate *rate = NULL;
1768 	mlan_ioctl_req *req = NULL;
1769 
1770 	ENTER();
1771 
1772 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
1773 	if (req == NULL) {
1774 		ret = MLAN_STATUS_FAILURE;
1775 		goto done;
1776 	}
1777 
1778 	rate = (mlan_ds_rate *)req->pbuf;
1779 	rate->param.rate_cfg.rate_type = MLAN_RATE_VALUE;
1780 	rate->sub_command = MLAN_OID_RATE_CFG;
1781 	req->req_id = MLAN_IOCTL_RATE;
1782 	req->action = action;
1783 
1784 	if (datarate && (action == MLAN_ACT_SET))
1785 		moal_memcpy_ext(priv->phandle, &rate->param.rate_cfg, datarate,
1786 				sizeof(mlan_rate_cfg_t),
1787 				sizeof(mlan_rate_cfg_t));
1788 
1789 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1790 	if (ret == MLAN_STATUS_SUCCESS && datarate && action == MLAN_ACT_GET)
1791 		moal_memcpy_ext(priv->phandle, datarate, &rate->param.rate_cfg,
1792 				sizeof(mlan_rate_cfg_t),
1793 				sizeof(mlan_rate_cfg_t));
1794 
1795 done:
1796 	if (ret != MLAN_STATUS_PENDING)
1797 		kfree(req);
1798 	LEAVE();
1799 	return ret;
1800 }
1801 
1802 /**
1803  *  @brief Get assoc_resp buffer
1804  *
1805  *  @param priv                 A pointer to moal_private structure
1806  *  @param assoc_rsp            A pointer to mlan_ds_misc_assoc_rsp structure
1807  *  @param wait_option          wait option
1808  *
1809  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
1810  */
woal_get_assoc_rsp(moal_private * priv,mlan_ds_misc_assoc_rsp * assoc_rsp,t_u8 wait_option)1811 mlan_status woal_get_assoc_rsp(moal_private *priv,
1812 			       mlan_ds_misc_assoc_rsp *assoc_rsp,
1813 			       t_u8 wait_option)
1814 {
1815 	mlan_status ret = MLAN_STATUS_SUCCESS;
1816 	mlan_ds_misc_cfg *misc = NULL;
1817 	mlan_ioctl_req *req = NULL;
1818 
1819 	ENTER();
1820 
1821 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1822 	if (req == NULL) {
1823 		PRINTM(MERROR, "Fail to allocate buffer for get assoc resp\n");
1824 		ret = MLAN_STATUS_FAILURE;
1825 		goto done;
1826 	}
1827 
1828 	req->req_id = MLAN_IOCTL_MISC_CFG;
1829 	misc = (pmlan_ds_misc_cfg)req->pbuf;
1830 	misc->sub_command = MLAN_OID_MISC_ASSOC_RSP;
1831 	req->action = MLAN_ACT_GET;
1832 
1833 	ret = woal_request_ioctl(priv, req, wait_option);
1834 	if (ret == MLAN_STATUS_SUCCESS && assoc_rsp)
1835 		moal_memcpy_ext(priv->phandle, assoc_rsp,
1836 				&misc->param.assoc_resp,
1837 				sizeof(mlan_ds_misc_assoc_rsp),
1838 				sizeof(mlan_ds_misc_assoc_rsp));
1839 
1840 done:
1841 	if (ret != MLAN_STATUS_PENDING)
1842 		kfree(req);
1843 	LEAVE();
1844 	return ret;
1845 }
1846 
1847 /**
1848  *  @brief Get assoc_req IEs buffer
1849  *
1850  *  @param priv                 A pointer to moal_private structure
1851  *  @param assoc_rsp            A pointer to mlan_ds_misc_assoc_rsp structure
1852  *  @param wait_option          wait option
1853  *
1854  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
1855  */
woal_get_assoc_req(moal_private * priv,mlan_ds_misc_assoc_req * assoc_req,t_u8 wait_option)1856 mlan_status woal_get_assoc_req(moal_private *priv,
1857 			       mlan_ds_misc_assoc_req *assoc_req,
1858 			       t_u8 wait_option)
1859 {
1860 	mlan_status ret = MLAN_STATUS_SUCCESS;
1861 	mlan_ds_misc_cfg *misc = NULL;
1862 	mlan_ioctl_req *req = NULL;
1863 
1864 	ENTER();
1865 
1866 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1867 	if (req == NULL) {
1868 		PRINTM(MERROR,
1869 		       "Fail to allocate buffer for get assoc request\n");
1870 		ret = MLAN_STATUS_FAILURE;
1871 		goto done;
1872 	}
1873 
1874 	req->req_id = MLAN_IOCTL_MISC_CFG;
1875 	misc = (pmlan_ds_misc_cfg)req->pbuf;
1876 	misc->sub_command = MLAN_OID_MISC_ASSOC_REQ;
1877 	req->action = MLAN_ACT_GET;
1878 
1879 	ret = woal_request_ioctl(priv, req, wait_option);
1880 	if (ret == MLAN_STATUS_SUCCESS && assoc_req)
1881 		moal_memcpy_ext(priv->phandle, assoc_req,
1882 				&misc->param.assoc_req,
1883 				sizeof(mlan_ds_misc_assoc_req),
1884 				sizeof(mlan_ds_misc_assoc_req));
1885 
1886 done:
1887 	if (ret != MLAN_STATUS_PENDING)
1888 		kfree(req);
1889 	LEAVE();
1890 	return ret;
1891 }
1892 
1893 #endif
1894 
1895 /**
1896  *  @brief Send get FW info request to MLAN
1897  *
1898  *  @param priv             A pointer to moal_private structure
1899  *  @param wait_option      Wait option
1900  *  @param fw_info          FW information
1901  *
1902  *  @return                 MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
1903  * otherwise fail
1904  */
woal_request_get_fw_info(moal_private * priv,t_u8 wait_option,mlan_fw_info * fw_info)1905 mlan_status woal_request_get_fw_info(moal_private *priv, t_u8 wait_option,
1906 				     mlan_fw_info *fw_info)
1907 {
1908 	mlan_ioctl_req *req = NULL;
1909 	mlan_ds_get_info *info;
1910 	mlan_status status;
1911 	ENTER();
1912 	memset(priv->current_addr, 0xff, ETH_ALEN);
1913 
1914 	/* Allocate an IOCTL request buffer */
1915 	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(
1916 		sizeof(mlan_ds_get_info));
1917 	if (req == NULL) {
1918 		status = MLAN_STATUS_FAILURE;
1919 		goto done;
1920 	}
1921 
1922 	/* Fill request buffer */
1923 	info = (mlan_ds_get_info *)req->pbuf;
1924 	req->req_id = MLAN_IOCTL_GET_INFO;
1925 	req->action = MLAN_ACT_GET;
1926 	info->sub_command = MLAN_OID_GET_FW_INFO;
1927 
1928 	/* Send IOCTL request to MLAN */
1929 	status = woal_request_ioctl(priv, req, wait_option);
1930 	if (status == MLAN_STATUS_SUCCESS) {
1931 		priv->phandle->fw_release_number = info->param.fw_info.fw_ver;
1932 		priv->phandle->fw_hotfix_version =
1933 			info->param.fw_info.hotfix_version;
1934 		priv->phandle->fw_ecsa_enable = info->param.fw_info.ecsa_enable;
1935 		priv->phandle->fw_bands = info->param.fw_info.fw_bands;
1936 		priv->phandle->fw_getlog_enable =
1937 			info->param.fw_info.getlog_enable;
1938 		priv->phandle->fw_roaming_support =
1939 			info->param.fw_info.fw_roaming_support;
1940 		if (priv->current_addr[0] == 0xff)
1941 			moal_memcpy_ext(priv->phandle, priv->current_addr,
1942 					&info->param.fw_info.mac_addr,
1943 					sizeof(mlan_802_11_mac_addr), ETH_ALEN);
1944 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)
1945 		eth_hw_addr_set(priv->netdev, priv->current_addr);
1946 #else
1947 		moal_memcpy_ext(priv->phandle, priv->netdev->dev_addr,
1948 				priv->current_addr, ETH_ALEN, ETH_ALEN);
1949 #endif
1950 		if (fw_info)
1951 			moal_memcpy_ext(priv->phandle, fw_info,
1952 					&info->param.fw_info,
1953 					sizeof(mlan_fw_info),
1954 					sizeof(mlan_fw_info));
1955 		DBG_HEXDUMP(MCMD_D, "mac", priv->current_addr, 6);
1956 	} else
1957 		PRINTM(MERROR,
1958 		       "get fw info failed! status=%d, error_code=0x%x\n",
1959 		       status, req->status_code);
1960 done:
1961 	if (status != MLAN_STATUS_PENDING)
1962 		kfree(req);
1963 	LEAVE();
1964 	return status;
1965 }
1966 
1967 /**
1968  *  @brief Get current channel of active interface
1969  *
1970  *  @param priv        A pointer to moal_private
1971  *  @param channel 	   A pointer to chan_band_info structure
1972  *
1973  *  @return            MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1974  */
woal_get_active_intf_channel(moal_private * priv,chan_band_info * channel)1975 mlan_status woal_get_active_intf_channel(moal_private *priv,
1976 					 chan_band_info *channel)
1977 {
1978 	moal_handle *handle = priv->phandle;
1979 	int i;
1980 	for (i = 0; i < handle->priv_num; i++) {
1981 #ifdef STA_SUPPORT
1982 		if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA) {
1983 			if (handle->priv[i]->media_connected == MTRUE)
1984 				return woal_get_sta_channel(handle->priv[i],
1985 							    MOAL_IOCTL_WAIT,
1986 							    channel);
1987 		}
1988 #endif
1989 #ifdef UAP_SUPPORT
1990 		if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_UAP) {
1991 			if (handle->priv[i]->bss_started == MTRUE)
1992 				return woal_set_get_ap_channel(handle->priv[i],
1993 							       MLAN_ACT_GET,
1994 							       MOAL_IOCTL_WAIT,
1995 							       channel);
1996 		}
1997 #endif
1998 	}
1999 	return MLAN_STATUS_FAILURE;
2000 }
2001 
2002 #ifdef STA_SUPPORT
2003 /**
2004  *  @brief Send get ext cap info request to MLAN
2005  *
2006  *  @param priv             A pointer to moal_private structure
2007  *  @param buf              data buffer
2008  *  @param len              data buffer length
2009  *
2010  *  @return                 number of bytes of extended capability -- success,
2011  * otherwise error
2012  */
woal_request_extcap(moal_private * priv,t_u8 * buf,t_u8 len)2013 int woal_request_extcap(moal_private *priv, t_u8 *buf, t_u8 len)
2014 {
2015 	int ret = 0;
2016 	mlan_ioctl_req *req = NULL;
2017 	mlan_ds_misc_cfg *cfg = NULL;
2018 	mlan_status status = MLAN_STATUS_SUCCESS;
2019 
2020 	ENTER();
2021 	if (buf == NULL || len <= 0 || len < sizeof(ExtCap_t)) {
2022 		ret = -EINVAL;
2023 		goto out;
2024 	}
2025 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2026 	if (req == NULL) {
2027 		ret = -ENOMEM;
2028 		goto out;
2029 	}
2030 	cfg = (mlan_ds_misc_cfg *)req->pbuf;
2031 	cfg->sub_command = MLAN_OID_MISC_EXT_CAP_CFG;
2032 	req->req_id = MLAN_IOCTL_MISC_CFG;
2033 	req->action = MLAN_ACT_GET;
2034 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2035 	if (status != MLAN_STATUS_SUCCESS) {
2036 		ret = -EFAULT;
2037 		goto out;
2038 	}
2039 	memset(buf, 0, len);
2040 	moal_memcpy_ext(priv->phandle, buf, &cfg->param.ext_cap,
2041 			sizeof(ExtCap_t), len);
2042 	ret = sizeof(ExtCap_t);
2043 out:
2044 	if (status != MLAN_STATUS_PENDING)
2045 		kfree(req);
2046 	LEAVE();
2047 	return ret;
2048 }
2049 #endif
2050 
2051 /**
2052  *  @brief Get debug info
2053  *
2054  *  @param priv                 A pointer to moal_private structure
2055  *  @param wait_option          Wait option
2056  *  @param debug_info           A pointer to mlan_debug_info structure
2057  *
2058  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
2059  * success, otherwise fail
2060  */
woal_get_debug_info(moal_private * priv,t_u8 wait_option,mlan_debug_info * debug_info)2061 mlan_status woal_get_debug_info(moal_private *priv, t_u8 wait_option,
2062 				mlan_debug_info *debug_info)
2063 {
2064 	mlan_ioctl_req *req = NULL;
2065 	mlan_ds_get_info *info = NULL;
2066 	mlan_status status = MLAN_STATUS_SUCCESS;
2067 	ENTER();
2068 
2069 	/* Allocate an IOCTL request buffer */
2070 	req = woal_alloc_mlan_ioctl_req(sizeof(t_u32) +
2071 					sizeof(mlan_debug_info));
2072 	if (req == NULL) {
2073 		status = MLAN_STATUS_FAILURE;
2074 		goto done;
2075 	}
2076 
2077 	/* Fill request buffer */
2078 	info = (mlan_ds_get_info *)req->pbuf;
2079 	info->sub_command = MLAN_OID_GET_DEBUG_INFO;
2080 	req->req_id = MLAN_IOCTL_GET_INFO;
2081 	req->action = MLAN_ACT_GET;
2082 
2083 	/* Send IOCTL request to MLAN */
2084 	status = woal_request_ioctl(priv, req, wait_option);
2085 	if (status == MLAN_STATUS_SUCCESS) {
2086 		if (debug_info) {
2087 			moal_memcpy_ext(priv->phandle, debug_info,
2088 					&info->param.debug_info,
2089 					sizeof(mlan_debug_info),
2090 					sizeof(mlan_debug_info));
2091 		}
2092 	}
2093 done:
2094 	if (status != MLAN_STATUS_PENDING)
2095 		kfree(req);
2096 	LEAVE();
2097 	return status;
2098 }
2099 
2100 #if defined(STA_WEXT) || defined(UAP_WEXT)
2101 /**
2102  *  @brief host command ioctl function
2103  *
2104  *  @param priv     A pointer to moal_private structure
2105  *  @param wrq      A pointer to iwreq structure
2106  *  @return         0 --success, otherwise fail
2107  */
woal_host_command(moal_private * priv,struct iwreq * wrq)2108 int woal_host_command(moal_private *priv, struct iwreq *wrq)
2109 {
2110 	HostCmd_Header cmd_header;
2111 	int ret = 0;
2112 	mlan_ds_misc_cfg *misc = NULL;
2113 	mlan_ioctl_req *req = NULL;
2114 	mlan_status status = MLAN_STATUS_SUCCESS;
2115 
2116 	ENTER();
2117 
2118 	/* Sanity check */
2119 	if (wrq->u.data.pointer == NULL) {
2120 		PRINTM(MERROR, "hostcmd IOCTL corrupt data\n");
2121 		ret = -EINVAL;
2122 		goto done;
2123 	}
2124 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2125 	if (req == NULL) {
2126 		ret = -ENOMEM;
2127 		goto done;
2128 	}
2129 	misc = (mlan_ds_misc_cfg *)req->pbuf;
2130 	memset(&cmd_header, 0, sizeof(cmd_header));
2131 
2132 	/* get command header */
2133 	if (copy_from_user(&cmd_header, wrq->u.data.pointer,
2134 			   sizeof(HostCmd_Header))) {
2135 		PRINTM(MERROR, "copy from user failed: Host command header\n");
2136 		ret = -EFAULT;
2137 		goto done;
2138 	}
2139 	misc->param.hostcmd.len = woal_le16_to_cpu(cmd_header.size);
2140 
2141 	PRINTM(MINFO, "Host command len = %u\n", misc->param.hostcmd.len);
2142 
2143 	if (!misc->param.hostcmd.len ||
2144 	    misc->param.hostcmd.len > MRVDRV_SIZE_OF_CMD_BUFFER) {
2145 		PRINTM(MERROR, "Invalid data buffer length\n");
2146 		ret = -EINVAL;
2147 		goto done;
2148 	}
2149 
2150 	/* get the whole command from user */
2151 	if (copy_from_user(misc->param.hostcmd.cmd, wrq->u.data.pointer,
2152 			   woal_le16_to_cpu(cmd_header.size))) {
2153 		PRINTM(MERROR, "copy from user failed\n");
2154 		ret = -EFAULT;
2155 		goto done;
2156 	}
2157 	misc->sub_command = MLAN_OID_MISC_HOST_CMD;
2158 	req->req_id = MLAN_IOCTL_MISC_CFG;
2159 
2160 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2161 	if (status != MLAN_STATUS_SUCCESS) {
2162 		ret = -EFAULT;
2163 		goto done;
2164 	}
2165 	if (copy_to_user(wrq->u.data.pointer, (t_u8 *)misc->param.hostcmd.cmd,
2166 			 misc->param.hostcmd.len)) {
2167 		ret = -EFAULT;
2168 		goto done;
2169 	}
2170 	wrq->u.data.length = misc->param.hostcmd.len;
2171 done:
2172 	if (status != MLAN_STATUS_PENDING)
2173 		kfree(req);
2174 	LEAVE();
2175 	return ret;
2176 }
2177 #endif
2178 
2179 #if defined(WIFI_DIRECT_SUPPORT) || defined(UAP_SUPPORT)
2180 /**
2181  *  @brief host command ioctl function
2182  *
2183  *  @param dev      A pointer to net_device structure
2184  *  @param req      A pointer to ifreq structure
2185  *  @return         0 --success, otherwise fail
2186  */
2187 /*********  format of ifr_data *************/
2188 /*    buf_len + Hostcmd_body               */
2189 /*    buf_len: 4 bytes                     */
2190 /*             the length of the buf which */
2191 /*             can be used to return data  */
2192 /*             to application              */
2193 /*    Hostcmd_body                         */
2194 /*******************************************/
woal_hostcmd_ioctl(struct net_device * dev,struct ifreq * req)2195 int woal_hostcmd_ioctl(struct net_device *dev, struct ifreq *req)
2196 {
2197 	moal_private *priv = (moal_private *)netdev_priv(dev);
2198 	t_u32 buf_len = 0;
2199 	HostCmd_Header cmd_header;
2200 	int ret = 0;
2201 	mlan_ds_misc_cfg *misc = NULL;
2202 	mlan_ioctl_req *ioctl_req = NULL;
2203 	mlan_status status = MLAN_STATUS_SUCCESS;
2204 
2205 	ENTER();
2206 
2207 	/* Sanity check */
2208 	if (req->ifr_data == NULL) {
2209 		PRINTM(MERROR, "uap_hostcmd_ioctl() corrupt data\n");
2210 		ret = -EFAULT;
2211 		goto done;
2212 	}
2213 
2214 	if (copy_from_user(&buf_len, req->ifr_data, sizeof(buf_len))) {
2215 		PRINTM(MERROR, "Copy from user failed\n");
2216 		ret = -EFAULT;
2217 		goto done;
2218 	}
2219 
2220 	memset(&cmd_header, 0, sizeof(cmd_header));
2221 
2222 	/* get command header */
2223 	if (copy_from_user(&cmd_header, req->ifr_data + sizeof(buf_len),
2224 			   sizeof(HostCmd_Header))) {
2225 		PRINTM(MERROR, "Copy from user failed\n");
2226 		ret = -EFAULT;
2227 		goto done;
2228 	}
2229 
2230 	PRINTM(MINFO, "Host command len = %d\n",
2231 	       woal_le16_to_cpu(cmd_header.size));
2232 
2233 	if (woal_le16_to_cpu(cmd_header.size) > MRVDRV_SIZE_OF_CMD_BUFFER) {
2234 		ret = -EINVAL;
2235 		goto done;
2236 	}
2237 
2238 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2239 	if (ioctl_req == NULL) {
2240 		ret = -ENOMEM;
2241 		goto done;
2242 	}
2243 	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
2244 
2245 	misc->param.hostcmd.len = woal_le16_to_cpu(cmd_header.size);
2246 
2247 	/* get the whole command from user */
2248 	if (copy_from_user(misc->param.hostcmd.cmd,
2249 			   req->ifr_data + sizeof(buf_len),
2250 			   misc->param.hostcmd.len)) {
2251 		PRINTM(MERROR, "copy from user failed\n");
2252 		ret = -EFAULT;
2253 		goto done;
2254 	}
2255 	misc->sub_command = MLAN_OID_MISC_HOST_CMD;
2256 	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
2257 
2258 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2259 	if (status != MLAN_STATUS_SUCCESS) {
2260 		ret = -EFAULT;
2261 		goto done;
2262 	}
2263 	if (misc->param.hostcmd.len > buf_len) {
2264 		PRINTM(MERROR,
2265 		       "buf_len is too small, resp_len=%d, buf_len=%d\n",
2266 		       (int)misc->param.hostcmd.len, (int)buf_len);
2267 		ret = -EFAULT;
2268 		goto done;
2269 	}
2270 	if (copy_to_user(req->ifr_data + sizeof(buf_len),
2271 			 (t_u8 *)misc->param.hostcmd.cmd,
2272 			 misc->param.hostcmd.len)) {
2273 		ret = -EFAULT;
2274 		goto done;
2275 	}
2276 done:
2277 	if (status != MLAN_STATUS_PENDING)
2278 		kfree(ioctl_req);
2279 	LEAVE();
2280 	return ret;
2281 }
2282 #endif
2283 
2284 /**
2285  *  @brief CUSTOM_IE ioctl handler
2286  *
2287  *  @param dev      A pointer to net_device structure
2288  *  @param req      A pointer to ifreq structure
2289  *  @return         0 --success, otherwise fail
2290  */
woal_custom_ie_ioctl(struct net_device * dev,struct ifreq * req)2291 int woal_custom_ie_ioctl(struct net_device *dev, struct ifreq *req)
2292 {
2293 	moal_private *priv = (moal_private *)netdev_priv(dev);
2294 	mlan_ioctl_req *ioctl_req = NULL;
2295 	mlan_ds_misc_cfg *misc = NULL;
2296 	mlan_ds_misc_custom_ie *pcustom_ie = NULL;
2297 	int ret = 0;
2298 	mlan_status status = MLAN_STATUS_SUCCESS;
2299 	gfp_t flag;
2300 
2301 	ENTER();
2302 
2303 	/* Sanity check */
2304 	if (req->ifr_data == NULL) {
2305 		PRINTM(MERROR, "woal_custom_ie_ioctl() corrupt data\n");
2306 		ret = -EFAULT;
2307 		goto done;
2308 	}
2309 
2310 	flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
2311 	pcustom_ie = kzalloc(sizeof(mlan_ds_misc_custom_ie), flag);
2312 	if (!pcustom_ie) {
2313 		ret = -ENOMEM;
2314 		goto done;
2315 	}
2316 
2317 	if (copy_from_user(pcustom_ie, req->ifr_data,
2318 			   sizeof(mlan_ds_misc_custom_ie))) {
2319 		PRINTM(MERROR, "Copy from user failed\n");
2320 		ret = -EFAULT;
2321 		goto done;
2322 	}
2323 
2324 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2325 	if (ioctl_req == NULL) {
2326 		ret = -ENOMEM;
2327 		goto done;
2328 	}
2329 
2330 	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
2331 	misc->sub_command = MLAN_OID_MISC_CUSTOM_IE;
2332 	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
2333 	if ((pcustom_ie->len == 0) ||
2334 	    (pcustom_ie->len == sizeof(pcustom_ie->ie_data_list[0].ie_index)))
2335 		ioctl_req->action = MLAN_ACT_GET;
2336 	else
2337 		ioctl_req->action = MLAN_ACT_SET;
2338 
2339 	moal_memcpy_ext(priv->phandle, &misc->param.cust_ie, pcustom_ie,
2340 			sizeof(mlan_ds_misc_custom_ie),
2341 			sizeof(mlan_ds_misc_custom_ie));
2342 
2343 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2344 	if (status != MLAN_STATUS_SUCCESS) {
2345 		ret = -EFAULT;
2346 		goto done;
2347 	}
2348 
2349 	if (ioctl_req->action == MLAN_ACT_GET) {
2350 		if (copy_to_user(req->ifr_data, &misc->param.cust_ie,
2351 				 sizeof(mlan_ds_misc_custom_ie))) {
2352 			PRINTM(MERROR, "Copy to user failed!\n");
2353 			ret = -EFAULT;
2354 			goto done;
2355 		}
2356 	} else if (ioctl_req->status_code == MLAN_ERROR_IOCTL_FAIL) {
2357 		/* send a separate error code to indicate error from driver */
2358 		ret = EFAULT;
2359 	}
2360 
2361 done:
2362 	if (status != MLAN_STATUS_PENDING)
2363 		kfree(ioctl_req);
2364 	kfree(pcustom_ie);
2365 	LEAVE();
2366 	return ret;
2367 }
2368 
2369 /**
2370  *  @brief send raw data packet ioctl function
2371  *
2372  *  @param dev      A pointer to net_device structure
2373  *  @param req      A pointer to ifreq structure
2374  *  @return         0 --success, otherwise fail
2375  */
woal_send_host_packet(struct net_device * dev,struct ifreq * req)2376 int woal_send_host_packet(struct net_device *dev, struct ifreq *req)
2377 {
2378 	moal_private *priv = (moal_private *)netdev_priv(dev);
2379 	t_u32 packet_len = 0;
2380 	int ret = 0;
2381 	pmlan_buffer pmbuf = NULL;
2382 	mlan_status status;
2383 
2384 	ENTER();
2385 
2386 	if (!priv || !priv->phandle) {
2387 		PRINTM(MERROR, "priv or handle is NULL\n");
2388 		ret = -EFAULT;
2389 		goto done;
2390 	}
2391 
2392 	/* Sanity check */
2393 	if (req->ifr_data == NULL) {
2394 		PRINTM(MERROR, "woal_send_host_packet() corrupt data\n");
2395 		ret = -EFAULT;
2396 		goto done;
2397 	}
2398 
2399 	if (copy_from_user(&packet_len, req->ifr_data, sizeof(packet_len))) {
2400 		PRINTM(MERROR, "Copy from user failed\n");
2401 		ret = -EFAULT;
2402 		goto done;
2403 	}
2404 #define PACKET_HEADER_LEN 8
2405 #define MV_ETH_FRAME_LEN 1514
2406 	if (packet_len > MV_ETH_FRAME_LEN) {
2407 		PRINTM(MERROR, "Invalid packet length %d\n", packet_len);
2408 		ret = -EFAULT;
2409 		goto done;
2410 	}
2411 	pmbuf = woal_alloc_mlan_buffer(
2412 		priv->phandle, (int)(MLAN_MIN_DATA_HEADER_LEN +
2413 				     (int)packet_len + PACKET_HEADER_LEN));
2414 	if (!pmbuf) {
2415 		PRINTM(MERROR, "Fail to allocate mlan_buffer\n");
2416 		ret = -ENOMEM;
2417 		goto done;
2418 	}
2419 	pmbuf->data_offset = MLAN_MIN_DATA_HEADER_LEN;
2420 
2421 	/* get whole packet and header */
2422 	if (copy_from_user(pmbuf->pbuf + pmbuf->data_offset,
2423 			   req->ifr_data + sizeof(packet_len),
2424 			   PACKET_HEADER_LEN + packet_len)) {
2425 		PRINTM(MERROR, "Copy from user failed\n");
2426 		ret = -EFAULT;
2427 		woal_free_mlan_buffer(priv->phandle, pmbuf);
2428 		goto done;
2429 	}
2430 	pmbuf->data_len = PACKET_HEADER_LEN + packet_len;
2431 	pmbuf->buf_type = MLAN_BUF_TYPE_RAW_DATA;
2432 	pmbuf->bss_index = priv->bss_index;
2433 
2434 	status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf);
2435 	switch (status) {
2436 	case MLAN_STATUS_PENDING:
2437 		atomic_inc(&priv->phandle->tx_pending);
2438 		queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
2439 		break;
2440 	case MLAN_STATUS_SUCCESS:
2441 		woal_free_mlan_buffer(priv->phandle, pmbuf);
2442 		break;
2443 	case MLAN_STATUS_FAILURE:
2444 	default:
2445 		woal_free_mlan_buffer(priv->phandle, pmbuf);
2446 		ret = -EFAULT;
2447 		break;
2448 	}
2449 done:
2450 	LEAVE();
2451 	return ret;
2452 }
2453 
2454 #if defined(UAP_WEXT)
2455 /**
2456  *  @brief Set/Get CUSTOM_IE ioctl handler
2457  *
2458  *  @param priv         A pointer to moal_private structure
2459  *  @param mask         Mask to set or clear from caller
2460  *  @param ie           IE buffer to set for beacon
2461  *  @param ie_len       Length of the IE
2462  *
2463  *  @return         0 --success, otherwise fail
2464  */
woal_set_get_custom_ie(moal_private * priv,t_u16 mask,t_u8 * ie,int ie_len)2465 int woal_set_get_custom_ie(moal_private *priv, t_u16 mask, t_u8 *ie, int ie_len)
2466 {
2467 	mlan_ioctl_req *ioctl_req = NULL;
2468 	mlan_ds_misc_cfg *misc = NULL;
2469 	mlan_ds_misc_custom_ie *misc_ie = NULL;
2470 	int ret = 0;
2471 	custom_ie *pcust_bcn_ie = NULL;
2472 	mlan_status status = MLAN_STATUS_SUCCESS;
2473 
2474 	ENTER();
2475 
2476 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2477 	if (ioctl_req == NULL) {
2478 		LEAVE();
2479 		return -ENOMEM;
2480 	}
2481 
2482 	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
2483 	misc->sub_command = MLAN_OID_MISC_CUSTOM_IE;
2484 	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
2485 	ioctl_req->action = MLAN_ACT_SET;
2486 	misc_ie = &misc->param.cust_ie;
2487 
2488 	misc_ie->type = TLV_TYPE_MGMT_IE;
2489 	misc_ie->len = (sizeof(custom_ie) - MAX_IE_SIZE) + ie_len;
2490 	pcust_bcn_ie = misc_ie->ie_data_list;
2491 	pcust_bcn_ie->ie_index = 0xffff;
2492 	pcust_bcn_ie->mgmt_subtype_mask = mask;
2493 	pcust_bcn_ie->ie_length = ie_len;
2494 	moal_memcpy_ext(priv->phandle, pcust_bcn_ie->ie_buffer, ie, ie_len,
2495 			MAX_IE_SIZE);
2496 
2497 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2498 	if (status != MLAN_STATUS_SUCCESS)
2499 		ret = -EFAULT;
2500 
2501 	if (status != MLAN_STATUS_PENDING)
2502 		kfree(ioctl_req);
2503 	LEAVE();
2504 	return ret;
2505 }
2506 #endif /* defined(HOST_TXRX_MGMT_FRAME) && defined(UAP_WEXT) */
2507 
2508 /**
2509  *  @brief TDLS configuration ioctl handler
2510  *
2511  *  @param dev      A pointer to net_device structure
2512  *  @param req      A pointer to ifreq structure
2513  *  @return         0 --success, otherwise fail
2514  */
woal_tdls_config_ioctl(struct net_device * dev,struct ifreq * req)2515 int woal_tdls_config_ioctl(struct net_device *dev, struct ifreq *req)
2516 {
2517 	moal_private *priv = (moal_private *)netdev_priv(dev);
2518 	mlan_ioctl_req *ioctl_req = NULL;
2519 	mlan_ds_misc_cfg *misc = NULL;
2520 	mlan_ds_misc_tdls_config *tdls_data = NULL;
2521 	int ret = 0;
2522 	mlan_status status = MLAN_STATUS_SUCCESS;
2523 	gfp_t flag;
2524 
2525 	ENTER();
2526 
2527 	/* Sanity check */
2528 	if (req->ifr_data == NULL) {
2529 		PRINTM(MERROR, "woal_tdls_config_ioctl() corrupt data\n");
2530 		ret = -EFAULT;
2531 		goto done;
2532 	}
2533 	flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
2534 	tdls_data = kzalloc(sizeof(mlan_ds_misc_tdls_config), flag);
2535 	if (!tdls_data) {
2536 		ret = -ENOMEM;
2537 		goto done;
2538 	}
2539 
2540 	if (copy_from_user(tdls_data, req->ifr_data,
2541 			   sizeof(mlan_ds_misc_tdls_config))) {
2542 		PRINTM(MERROR, "Copy from user failed\n");
2543 		ret = -EFAULT;
2544 		goto done;
2545 	}
2546 
2547 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2548 	if (ioctl_req == NULL) {
2549 		ret = -ENOMEM;
2550 		goto done;
2551 	}
2552 
2553 	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
2554 	misc->sub_command = MLAN_OID_MISC_TDLS_CONFIG;
2555 	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
2556 	if (tdls_data->tdls_action == WLAN_TDLS_DISCOVERY_REQ ||
2557 	    tdls_data->tdls_action == WLAN_TDLS_LINK_STATUS)
2558 		ioctl_req->action = MLAN_ACT_GET;
2559 	else
2560 		ioctl_req->action = MLAN_ACT_SET;
2561 
2562 	moal_memcpy_ext(priv->phandle, &misc->param.tdls_config, tdls_data,
2563 			sizeof(mlan_ds_misc_tdls_config),
2564 			sizeof(mlan_ds_misc_tdls_config));
2565 
2566 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2567 	if (status != MLAN_STATUS_SUCCESS) {
2568 		ret = -EFAULT;
2569 		goto done;
2570 	}
2571 
2572 	if (tdls_data->tdls_action == WLAN_TDLS_DISCOVERY_REQ ||
2573 	    tdls_data->tdls_action == WLAN_TDLS_LINK_STATUS) {
2574 		if (copy_to_user(req->ifr_data, &misc->param.tdls_config,
2575 				 sizeof(mlan_ds_misc_tdls_config))) {
2576 			PRINTM(MERROR, "Copy to user failed!\n");
2577 			ret = -EFAULT;
2578 			goto done;
2579 		}
2580 	}
2581 
2582 done:
2583 	if (status != MLAN_STATUS_PENDING)
2584 		kfree(ioctl_req);
2585 	kfree(tdls_data);
2586 	LEAVE();
2587 	return ret;
2588 }
2589 
2590 /**
2591  *  @brief ioctl function get BSS type
2592  *
2593  *  @param dev      A pointer to net_device structure
2594  *  @param req      A pointer to ifreq structure
2595  *  @return         0 --success, otherwise fail
2596  */
woal_get_bss_type(struct net_device * dev,struct ifreq * req)2597 int woal_get_bss_type(struct net_device *dev, struct ifreq *req)
2598 {
2599 	int ret = 0;
2600 	moal_private *priv = (moal_private *)netdev_priv(dev);
2601 	int bss_type;
2602 
2603 	ENTER();
2604 
2605 	bss_type = (int)priv->bss_type;
2606 	if (copy_to_user(req->ifr_data, &bss_type, sizeof(int))) {
2607 		PRINTM(MINFO, "Copy to user failed!\n");
2608 		ret = -EFAULT;
2609 	}
2610 
2611 	LEAVE();
2612 	return ret;
2613 }
2614 
2615 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
2616 /**
2617  * @brief Swithces BSS role of interface
2618  *
2619  * @param priv          A pointer to moal_private structure
2620  * @param action        Action: set or get
2621  * @param wait_option   Wait option (MOAL_WAIT or MOAL_NO_WAIT)
2622  * @param bss_role      A pointer to bss role
2623  *
2624  * @return         0 --success, otherwise fail
2625  */
woal_bss_role_cfg(moal_private * priv,t_u8 action,t_u8 wait_option,t_u8 * bss_role)2626 mlan_status woal_bss_role_cfg(moal_private *priv, t_u8 action, t_u8 wait_option,
2627 			      t_u8 *bss_role)
2628 {
2629 	int ret = 0;
2630 	mlan_ds_bss *bss = NULL;
2631 	mlan_ioctl_req *req = NULL;
2632 	struct net_device *dev = priv->netdev;
2633 	mlan_status status = MLAN_STATUS_SUCCESS;
2634 
2635 	ENTER();
2636 
2637 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
2638 	if (req == NULL) {
2639 		ret = -ENOMEM;
2640 		goto done;
2641 	}
2642 	bss = (mlan_ds_bss *)req->pbuf;
2643 	bss->sub_command = MLAN_OID_BSS_ROLE;
2644 	req->req_id = MLAN_IOCTL_BSS;
2645 	req->action = action;
2646 	if (action == MLAN_ACT_SET) {
2647 		if (priv->bss_role == *bss_role) {
2648 			PRINTM(MWARN, "BSS is in desired role already\n");
2649 			goto done;
2650 		} else {
2651 			bss->param.bss_role = *bss_role;
2652 		}
2653 	}
2654 	status = woal_request_ioctl(priv, req, wait_option);
2655 	if (status != MLAN_STATUS_SUCCESS) {
2656 		ret = -EFAULT;
2657 		goto done;
2658 	}
2659 
2660 	if (action == MLAN_ACT_GET) {
2661 		*bss_role = bss->param.bss_role;
2662 	} else {
2663 		/* Update moal_private */
2664 		priv->bss_role = *bss_role;
2665 		if (priv->bss_type == MLAN_BSS_TYPE_UAP)
2666 			priv->bss_type = MLAN_BSS_TYPE_STA;
2667 		else if (priv->bss_type == MLAN_BSS_TYPE_STA)
2668 			priv->bss_type = MLAN_BSS_TYPE_UAP;
2669 
2670 		if (*bss_role == MLAN_BSS_ROLE_UAP) {
2671 			/* Switch: STA -> uAP */
2672 			/* Setup the OS Interface to our functions */
2673 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
2674 			dev->do_ioctl = woal_uap_do_ioctl;
2675 			dev->set_multicast_list = woal_uap_set_multicast_list;
2676 #else
2677 			dev->netdev_ops = &woal_uap_netdev_ops;
2678 #endif
2679 #ifdef UAP_WEXT
2680 			if (IS_UAP_WEXT(priv->phandle->params.cfg80211_wext)) {
2681 #if WIRELESS_EXT < 21
2682 				dev->get_wireless_stats =
2683 					woal_get_uap_wireless_stats;
2684 #endif
2685 				dev->wireless_handlers =
2686 					(struct iw_handler_def
2687 						 *)&woal_uap_handler_def;
2688 			}
2689 #endif /* UAP_WEXT */
2690 		} else if (*bss_role == MLAN_BSS_ROLE_STA) {
2691 			/* Switch: uAP -> STA */
2692 			/* Setup the OS Interface to our functions */
2693 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
2694 			dev->do_ioctl = woal_do_ioctl;
2695 			dev->set_multicast_list = woal_set_multicast_list;
2696 #else
2697 			dev->netdev_ops = &woal_netdev_ops;
2698 #endif
2699 #ifdef STA_WEXT
2700 			if (IS_STA_WEXT(priv->phandle->params.cfg80211_wext)) {
2701 #if WIRELESS_EXT < 21
2702 				dev->get_wireless_stats =
2703 					woal_get_wireless_stats;
2704 #endif
2705 				dev->wireless_handlers =
2706 					(struct iw_handler_def
2707 						 *)&woal_handler_def;
2708 			}
2709 #endif /* STA_WEXT */
2710 		}
2711 	}
2712 
2713 done:
2714 	if (status != MLAN_STATUS_PENDING)
2715 		kfree(req);
2716 	LEAVE();
2717 	return ret;
2718 }
2719 
2720 #if defined(STA_WEXT) || defined(UAP_WEXT)
2721 /**
2722  * @brief Set/Get BSS role
2723  *
2724  * @param priv     A pointer to moal_private structure
2725  * @param wrq      A pointer to iwreq structure
2726  *
2727  * @return         0 --success, otherwise fail
2728  */
woal_set_get_bss_role(moal_private * priv,struct iwreq * wrq)2729 int woal_set_get_bss_role(moal_private *priv, struct iwreq *wrq)
2730 {
2731 	int ret = 0;
2732 	int bss_role = 0;
2733 	t_u8 action = MLAN_ACT_GET;
2734 
2735 	ENTER();
2736 
2737 	if (wrq->u.data.length) {
2738 		if (copy_from_user(&bss_role, wrq->u.data.pointer,
2739 				   sizeof(int))) {
2740 			PRINTM(MERROR, "Copy from user failed\n");
2741 			ret = -EFAULT;
2742 			goto done;
2743 		}
2744 		if ((bss_role != MLAN_BSS_ROLE_STA &&
2745 		     bss_role != MLAN_BSS_ROLE_UAP)
2746 #ifdef WIFI_DIRECT_SUPPORT
2747 		    || (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT)
2748 #endif
2749 		) {
2750 			PRINTM(MWARN, "Invalid BSS role\n");
2751 			ret = -EINVAL;
2752 			goto done;
2753 		}
2754 		if (bss_role == (int)GET_BSS_ROLE(priv)) {
2755 			PRINTM(MWARN, "Already BSS is in desired role\n");
2756 			ret = -EINVAL;
2757 			goto done;
2758 		}
2759 		action = MLAN_ACT_SET;
2760 		/* Reset interface */
2761 		if (MLAN_STATUS_SUCCESS !=
2762 		    woal_reset_intf(priv, MOAL_IOCTL_WAIT, MFALSE)) {
2763 			PRINTM(MERROR, "%s: reset_intf failed \n", __func__);
2764 			ret = -EFAULT;
2765 			goto done;
2766 		}
2767 	}
2768 
2769 	if (MLAN_STATUS_SUCCESS != woal_bss_role_cfg(priv, action,
2770 						     MOAL_IOCTL_WAIT,
2771 						     (t_u8 *)&bss_role)) {
2772 		ret = -EFAULT;
2773 		goto done;
2774 	}
2775 
2776 	if (!wrq->u.data.length) {
2777 		if (copy_to_user(wrq->u.data.pointer, &bss_role, sizeof(int))) {
2778 			ret = -EFAULT;
2779 			goto done;
2780 		}
2781 		wrq->u.data.length = 1;
2782 	} else {
2783 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
2784 		if (IS_STA_OR_UAP_CFG80211(priv->phandle->params.cfg80211_wext))
2785 			woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_WAIT);
2786 #endif
2787 		/* Initialize private structures */
2788 		woal_init_priv(priv, MOAL_IOCTL_WAIT);
2789 
2790 		/* Enable interfaces */
2791 		netif_device_attach(priv->netdev);
2792 		woal_start_queue(priv->netdev);
2793 	}
2794 
2795 done:
2796 	LEAVE();
2797 	return ret;
2798 }
2799 #endif /* STA_WEXT || UAP_WEXT */
2800 #endif /* STA_SUPPORT && UAP_SUPPORT */
2801 
2802 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
2803 /**
2804  *  @brief Enable IPv6 Router Advertisement offload
2805  *
2806  *  @param handle  A pointer to moal_handle structure
2807  *  @param enable  enable or disable
2808  *
2809  *  @return        MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise
2810  * fail
2811  */
woal_set_ipv6_ra_offload(moal_handle * handle,t_u8 enable)2812 static mlan_status woal_set_ipv6_ra_offload(moal_handle *handle, t_u8 enable)
2813 {
2814 	mlan_status ret = MLAN_STATUS_SUCCESS;
2815 	moal_private *priv = NULL;
2816 	mlan_ds_misc_cfg *misc = NULL;
2817 	mlan_ioctl_req *req = NULL;
2818 	mlan_ds_misc_ipv6_ra_offload *ipv6_ra;
2819 	int i = 0;
2820 
2821 	ENTER();
2822 
2823 	for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) {
2824 		if (priv->ipv6_addr_configured)
2825 			break;
2826 	}
2827 
2828 	if (!priv || !priv->ipv6_addr_configured) {
2829 		PRINTM(MIOCTL, "No IPv6 address configured\n");
2830 		goto done;
2831 	}
2832 
2833 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2834 	if (req == NULL) {
2835 		PRINTM(MIOCTL, "IOCTL req allocated failed!\n");
2836 		ret = MLAN_STATUS_FAILURE;
2837 		goto done;
2838 	}
2839 	misc = (mlan_ds_misc_cfg *)req->pbuf;
2840 	misc->sub_command = MLAN_OID_MISC_IPV6_RA_OFFLOAD;
2841 	req->req_id = MLAN_IOCTL_MISC_CFG;
2842 	req->action = MLAN_ACT_SET;
2843 	ipv6_ra = &misc->param.ipv6_ra_offload;
2844 	ipv6_ra->enable = enable;
2845 	moal_memcpy_ext(priv->phandle, ipv6_ra->ipv6_addr, priv->ipv6_addr, 16,
2846 			sizeof(ipv6_ra->ipv6_addr));
2847 	ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_STA), req,
2848 				 MOAL_NO_WAIT);
2849 	if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
2850 		PRINTM(MIOCTL, "Set IPv6 RA offload failed\n");
2851 
2852 done:
2853 	if (ret != MLAN_STATUS_PENDING && req != NULL)
2854 		kfree(req);
2855 	LEAVE();
2856 	return ret;
2857 }
2858 #endif
2859 
woal_set_wake_on_mdns(moal_handle * handle,t_u8 enable)2860 static mlan_status woal_set_wake_on_mdns(moal_handle *handle, t_u8 enable)
2861 {
2862 	mlan_status ret = MLAN_STATUS_SUCCESS;
2863 	mlan_ds_misc_cfg *misc = NULL;
2864 	mlan_ioctl_req *req = NULL;
2865 	mlan_ds_misc_mef_flt_cfg *mef_cfg = NULL;
2866 	mef_entry_t *entry = NULL;
2867 	mef_filter_t *filter = NULL;
2868 
2869 	ENTER();
2870 
2871 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2872 	if (req == NULL) {
2873 		PRINTM(MIOCTL, "IOCTL req allocated failed!\n");
2874 		ret = MLAN_STATUS_FAILURE;
2875 		goto done;
2876 	}
2877 	misc = (mlan_ds_misc_cfg *)req->pbuf;
2878 	misc->sub_command = MLAN_OID_MISC_MEF_FLT_CFG;
2879 	req->req_id = MLAN_IOCTL_MISC_CFG;
2880 	req->action = MLAN_ACT_SET;
2881 
2882 	mef_cfg = (mlan_ds_misc_mef_flt_cfg *)(&misc->param.mef_flt_cfg);
2883 	mef_cfg->mef_act_type = MEF_ACT_WOWLAN;
2884 	mef_cfg->criteria = MBIT(3);
2885 
2886 	entry = (mef_entry_t *)&mef_cfg->mef_entry;
2887 	entry->mode = MBIT(0);
2888 	entry->action = 3;
2889 
2890 	filter = (mef_filter_t *)entry->filter_item;
2891 	filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | FILLING_OFFSET |
2892 			     FILLING_BYTE_SEQ);
2893 	filter->type = TYPE_BYTE_EQ;
2894 	filter->repeat = 1;
2895 	filter->offset = 20;
2896 	filter->num_byte_seq = 2;
2897 	moal_memcpy_ext(handle, filter->byte_seq, "\x08\x00", 2,
2898 			sizeof(filter->byte_seq));
2899 	entry->rpn[1] = RPN_TYPE_AND;
2900 
2901 	filter++;
2902 	filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | FILLING_OFFSET |
2903 			     FILLING_BYTE_SEQ);
2904 	filter->type = TYPE_BYTE_EQ;
2905 	filter->repeat = 1;
2906 	filter->offset = 38;
2907 	filter->num_bytes = 4;
2908 	moal_memcpy_ext(handle, filter->byte_seq, "\xe0\x00\x00\xfb", 4,
2909 			sizeof(filter->byte_seq));
2910 	entry->rpn[2] = RPN_TYPE_AND;
2911 	filter++;
2912 	filter->fill_flag = (FILLING_TYPE | FILLING_PATTERN | FILLING_OFFSET |
2913 			     FILLING_NUM_BYTES);
2914 	filter->type = TYPE_BYTE_EQ + 1;
2915 	filter->pattern = 17;
2916 	filter->offset = 31;
2917 	filter->num_bytes = 1;
2918 	entry->rpn[3] = RPN_TYPE_AND;
2919 	filter++;
2920 	filter->fill_flag = (FILLING_TYPE | FILLING_PATTERN | FILLING_OFFSET |
2921 			     FILLING_NUM_BYTES);
2922 	filter->type = TYPE_BYTE_EQ + 1;
2923 	filter->pattern = 5353;
2924 	filter->offset = 44;
2925 	filter->num_bytes = 2;
2926 	filter++;
2927 	entry->filter_num = 4;
2928 	if (enable) {
2929 		mef_cfg->op_code = MLAN_OP_ADD_MDNS;
2930 	} else {
2931 		mef_cfg->op_code = MLAN_IPADDR_OP_IP_REMOVE;
2932 	}
2933 	ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), req,
2934 				 MOAL_NO_WAIT);
2935 	if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
2936 		PRINTM(MIOCTL, "Set Mdns wake up failed! ret=%d\n", ret);
2937 done:
2938 	if (ret != MLAN_STATUS_PENDING)
2939 		kfree(req);
2940 	LEAVE();
2941 	return ret;
2942 }
2943 
2944 /**
2945  *  @brief Enable IPv6 Neighbor Solicitation offload
2946  *
2947  *  @param handle  A pointer to moal_handle structure
2948  *  @param enable  enable or disable mef entry
2949  *
2950  *  @return        MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise
2951  * fail
2952  */
woal_set_ipv6_ns_offload(moal_handle * handle,t_u8 enable)2953 static mlan_status woal_set_ipv6_ns_offload(moal_handle *handle, t_u8 enable)
2954 {
2955 	mlan_status ret = MLAN_STATUS_SUCCESS;
2956 	mlan_ds_misc_cfg *misc = NULL;
2957 	mlan_ioctl_req *req = NULL;
2958 	mlan_ds_misc_mef_flt_cfg *mef_cfg = NULL;
2959 	mef_entry_t *entry = NULL;
2960 	mef_filter_t *filter = NULL;
2961 
2962 	ENTER();
2963 
2964 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2965 	if (req == NULL) {
2966 		PRINTM(MIOCTL, "IOCTL req allocated failed!\n");
2967 		ret = MLAN_STATUS_FAILURE;
2968 		goto done;
2969 	}
2970 	misc = (mlan_ds_misc_cfg *)req->pbuf;
2971 	misc->sub_command = MLAN_OID_MISC_MEF_FLT_CFG;
2972 	req->req_id = MLAN_IOCTL_MISC_CFG;
2973 	req->action = MLAN_ACT_SET;
2974 
2975 	mef_cfg = (mlan_ds_misc_mef_flt_cfg *)(&misc->param.mef_flt_cfg);
2976 	mef_cfg->mef_act_type = MEF_ACT_IPV6_NS;
2977 	mef_cfg->criteria = (MBIT(1) | MBIT(3));
2978 
2979 	entry = (mef_entry_t *)&mef_cfg->mef_entry;
2980 	entry->mode = MBIT(0);
2981 	entry->action = 0x40;
2982 	filter = (mef_filter_t *)entry->filter_item;
2983 	filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | FILLING_OFFSET |
2984 			     FILLING_BYTE_SEQ);
2985 	filter->type = TYPE_BYTE_EQ;
2986 	filter->repeat = 1;
2987 	filter->offset = 20;
2988 	filter->num_byte_seq = 2;
2989 	moal_memcpy_ext(handle, filter->byte_seq, "\x86\xdd", 2,
2990 			sizeof(filter->byte_seq));
2991 	entry->rpn[1] = RPN_TYPE_AND;
2992 
2993 	filter++;
2994 	filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | FILLING_OFFSET |
2995 			     FILLING_BYTE_SEQ);
2996 	filter->type = TYPE_BYTE_EQ;
2997 	filter->repeat = 1;
2998 	filter->offset = 62;
2999 	filter->num_byte_seq = 1;
3000 	moal_memcpy_ext(handle, filter->byte_seq, "\x87", 1,
3001 			sizeof(filter->byte_seq));
3002 	entry->filter_num = 2;
3003 	if (enable) {
3004 		mef_cfg->op_code = MLAN_OP_ADD_IPV6_NS;
3005 	} else {
3006 		mef_cfg->op_code = MLAN_IPADDR_OP_IP_REMOVE;
3007 	}
3008 	ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), req,
3009 				 MOAL_NO_WAIT);
3010 	if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
3011 		PRINTM(MIOCTL, "Set ipv6 ns offload failed! ret=%d\n", ret);
3012 
3013 done:
3014 	if (ret != MLAN_STATUS_PENDING)
3015 		kfree(req);
3016 	LEAVE();
3017 	return ret;
3018 }
3019 
3020 /**
3021  *  @brief Set auto arp resp
3022  *
3023  *  @param handle         A pointer to moal_handle structure
3024  *  @param enable         enable/disable
3025  *
3026  *  @return               MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
3027  * otherwise fail
3028  */
woal_set_auto_arp(moal_handle * handle,t_u8 enable)3029 static mlan_status woal_set_auto_arp(moal_handle *handle, t_u8 enable)
3030 {
3031 	mlan_status ret = MLAN_STATUS_SUCCESS;
3032 	int i = 0;
3033 	moal_private *priv = NULL;
3034 	mlan_ds_misc_cfg *misc = NULL;
3035 	mlan_ioctl_req *req = NULL;
3036 	mlan_ds_misc_ipaddr_cfg ipaddr_cfg;
3037 
3038 	ENTER();
3039 
3040 	memset(&ipaddr_cfg, 0, sizeof(ipaddr_cfg));
3041 	for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) {
3042 		if (priv && priv->ip_addr_type != IPADDR_TYPE_NONE) {
3043 			moal_memcpy_ext(
3044 				handle,
3045 				ipaddr_cfg.ip_addr[ipaddr_cfg.ip_addr_num],
3046 				priv->ip_addr, IPADDR_LEN, IPADDR_LEN);
3047 			ipaddr_cfg.ip_addr_num++;
3048 		}
3049 	}
3050 	if (ipaddr_cfg.ip_addr_num == 0) {
3051 		PRINTM(MIOCTL, "No IP addr configured.\n");
3052 		goto done;
3053 	}
3054 
3055 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3056 	if (req == NULL) {
3057 		PRINTM(MIOCTL, "IOCTL req allocated failed!\n");
3058 		ret = MLAN_STATUS_FAILURE;
3059 		goto done;
3060 	}
3061 	misc = (mlan_ds_misc_cfg *)req->pbuf;
3062 	misc->sub_command = MLAN_OID_MISC_IP_ADDR;
3063 	req->req_id = MLAN_IOCTL_MISC_CFG;
3064 	req->action = MLAN_ACT_SET;
3065 	moal_memcpy_ext(handle, &misc->param.ipaddr_cfg, &ipaddr_cfg,
3066 			sizeof(ipaddr_cfg), sizeof(misc->param.ipaddr_cfg));
3067 	if (enable) {
3068 		misc->param.ipaddr_cfg.op_code = MLAN_IPADDR_OP_ARP_FILTER |
3069 						 MLAN_IPADDR_OP_AUTO_ARP_RESP;
3070 		misc->param.ipaddr_cfg.ip_addr_type = IPADDR_TYPE_IPV4;
3071 	} else {
3072 		/** remove ip */
3073 		misc->param.ipaddr_cfg.op_code = MLAN_IPADDR_OP_IP_REMOVE;
3074 	}
3075 	ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), req,
3076 				 MOAL_NO_WAIT);
3077 	if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
3078 		PRINTM(MIOCTL, "Set auto arp IOCTL failed!\n");
3079 done:
3080 	if (ret != MLAN_STATUS_PENDING)
3081 		kfree(req);
3082 	LEAVE();
3083 	return ret;
3084 }
3085 
3086 /**
3087  *  @brief Set auto arp resp with enhancement method
3088  *
3089  *  @param handle         A pointer to moal_handle structure
3090  *  @param enable         enable/disable
3091  *
3092  *  @return               MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
3093  * otherwise fail
3094  */
woal_set_auto_arp_ext(moal_handle * handle,t_u8 enable)3095 mlan_status woal_set_auto_arp_ext(moal_handle *handle, t_u8 enable)
3096 {
3097 	mlan_status ret = MLAN_STATUS_SUCCESS;
3098 	int i = 0, ip_addr_num = 0;
3099 	moal_private *priv = NULL;
3100 	mlan_ds_misc_cfg *misc = NULL;
3101 	mlan_ioctl_req *req = NULL;
3102 	mlan_ds_misc_mef_flt_cfg *mef_cfg = NULL;
3103 	mef_entry_t *entry = NULL;
3104 	mef_filter_t *filter = NULL;
3105 	t_u8 ip_addr[MAX_IPADDR][IPADDR_LEN];
3106 
3107 	ENTER();
3108 
3109 	memset(&mef_cfg, 0, sizeof(mef_cfg));
3110 	for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) {
3111 		if (priv && priv->ip_addr_type != IPADDR_TYPE_NONE) {
3112 			moal_memcpy_ext(handle, ip_addr[ip_addr_num],
3113 					priv->ip_addr, IPADDR_LEN, IPADDR_LEN);
3114 			ip_addr_num++;
3115 		}
3116 	}
3117 	if (ip_addr_num == 0) {
3118 		PRINTM(MIOCTL, "No IP addr configured.\n");
3119 		goto done;
3120 	}
3121 
3122 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3123 	if (req == NULL) {
3124 		PRINTM(MIOCTL, "IOCTL req allocated failed!\n");
3125 		ret = MLAN_STATUS_FAILURE;
3126 		goto done;
3127 	}
3128 	misc = (mlan_ds_misc_cfg *)req->pbuf;
3129 	misc->sub_command = MLAN_OID_MISC_MEF_FLT_CFG;
3130 	req->req_id = MLAN_IOCTL_MISC_CFG;
3131 	req->action = MLAN_ACT_SET;
3132 
3133 	mef_cfg = (mlan_ds_misc_mef_flt_cfg *)(&(misc->param.mef_flt_cfg));
3134 	mef_cfg->mef_act_type = MEF_ACT_AUTOARP;
3135 	mef_cfg->criteria = (MBIT(0) | MBIT(1));
3136 
3137 	entry = (mef_entry_t *)&mef_cfg->mef_entry;
3138 	entry->mode = MBIT(0);
3139 	entry->action = 0x10;
3140 
3141 	filter = (mef_filter_t *)(entry->filter_item);
3142 	filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | FILLING_OFFSET |
3143 			     FILLING_BYTE_SEQ);
3144 	filter->type = TYPE_BYTE_EQ;
3145 	filter->repeat = 1;
3146 	filter->offset = 20;
3147 	filter->num_byte_seq = 2;
3148 	moal_memcpy_ext(handle, filter->byte_seq, "\x08\x06", 2,
3149 			sizeof(filter->byte_seq));
3150 	entry->rpn[1] = RPN_TYPE_AND;
3151 
3152 	for (i = 0; i < ip_addr_num; i++) {
3153 		filter++;
3154 		filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT |
3155 				     FILLING_OFFSET | FILLING_BYTE_SEQ);
3156 		filter->type = TYPE_BYTE_EQ;
3157 		filter->repeat = 1;
3158 		filter->offset = 46;
3159 		filter->num_byte_seq = 4;
3160 		moal_memcpy_ext(handle, filter->byte_seq, &ip_addr[i],
3161 				sizeof(t_u32), sizeof(filter->byte_seq));
3162 		if (i > 1)
3163 			entry->rpn[i] = RPN_TYPE_OR;
3164 	}
3165 	entry->filter_num = ip_addr_num + 1;
3166 
3167 	if (enable)
3168 		mef_cfg->op_code = MLAN_IPADDR_OP_ARP_FILTER |
3169 				   MLAN_IPADDR_OP_AUTO_ARP_RESP;
3170 	else
3171 		/** remove ip */
3172 		mef_cfg->op_code = MLAN_IPADDR_OP_IP_REMOVE;
3173 	ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), req,
3174 				 MOAL_NO_WAIT);
3175 	if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
3176 		PRINTM(MIOCTL, "Set auto arp IOCTL failed!\n");
3177 done:
3178 	if (ret != MLAN_STATUS_PENDING)
3179 		kfree(req);
3180 	LEAVE();
3181 	return ret;
3182 }
3183 
3184 /**
3185  *  @brief Set/Get DTIM period
3186  *
3187  *  @param priv                 A pointer to moal_private structure
3188  *  @param action               Action set or get
3189  *  @param wait_option          Wait option
3190  *  @param value                DTIM period
3191  *
3192  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
3193  * success, otherwise fail
3194  */
woal_set_get_dtim_period(moal_private * priv,t_u32 action,t_u8 wait_option,t_u8 * value)3195 mlan_status woal_set_get_dtim_period(moal_private *priv, t_u32 action,
3196 				     t_u8 wait_option, t_u8 *value)
3197 {
3198 	mlan_ioctl_req *req = NULL;
3199 	mlan_ds_snmp_mib *mib = NULL;
3200 	mlan_status ret = MLAN_STATUS_SUCCESS;
3201 
3202 	ENTER();
3203 
3204 	/* Allocate an IOCTL request buffer */
3205 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
3206 	if (req == NULL) {
3207 		ret = MLAN_STATUS_FAILURE;
3208 		goto done;
3209 	}
3210 
3211 	/* Fill request buffer */
3212 	mib = (mlan_ds_snmp_mib *)req->pbuf;
3213 	mib->sub_command = MLAN_OID_SNMP_MIB_DTIM_PERIOD;
3214 	req->req_id = MLAN_IOCTL_SNMP_MIB;
3215 	req->action = action;
3216 
3217 	if (action == MLAN_ACT_SET)
3218 		mib->param.dtim_period = *value;
3219 
3220 	/* Send IOCTL request to MLAN */
3221 	ret = woal_request_ioctl(priv, req, wait_option);
3222 	if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
3223 		*value = (t_u8)mib->param.dtim_period;
3224 
3225 done:
3226 	if (ret != MLAN_STATUS_PENDING)
3227 		kfree(req);
3228 	LEAVE();
3229 	return ret;
3230 }
3231 
3232 /**
3233  *  @brief Get Host Sleep parameters
3234  *
3235  *  @param priv         A pointer to moal_private structure
3236  *  @param action       Action: set or get
3237  *  @param wait_option  Wait option (MOAL_WAIT or MOAL_NO_WAIT)
3238  *  @param hscfg        A pointer to mlan_ds_hs_cfg structure
3239  *
3240  *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
3241  * otherwise fail
3242  */
woal_set_get_hs_params(moal_private * priv,t_u16 action,t_u8 wait_option,mlan_ds_hs_cfg * hscfg)3243 mlan_status woal_set_get_hs_params(moal_private *priv, t_u16 action,
3244 				   t_u8 wait_option, mlan_ds_hs_cfg *hscfg)
3245 {
3246 	mlan_status ret = MLAN_STATUS_SUCCESS;
3247 	mlan_ds_pm_cfg *pmcfg = NULL;
3248 	mlan_ioctl_req *req = NULL;
3249 
3250 	ENTER();
3251 
3252 	/* Allocate an IOCTL request buffer */
3253 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
3254 	if (req == NULL) {
3255 		ret = MLAN_STATUS_FAILURE;
3256 		goto done;
3257 	}
3258 
3259 	/* Fill request buffer */
3260 	pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
3261 	pmcfg->sub_command = MLAN_OID_PM_CFG_HS_CFG;
3262 	req->req_id = MLAN_IOCTL_PM_CFG;
3263 	req->action = action;
3264 	if (action == MLAN_ACT_SET)
3265 		moal_memcpy_ext(priv->phandle, &pmcfg->param.hs_cfg, hscfg,
3266 				sizeof(mlan_ds_hs_cfg), sizeof(mlan_ds_hs_cfg));
3267 
3268 	/* Send IOCTL request to MLAN */
3269 	ret = woal_request_ioctl(priv, req, wait_option);
3270 	if (ret == MLAN_STATUS_SUCCESS) {
3271 		if (hscfg && action == MLAN_ACT_GET) {
3272 			moal_memcpy_ext(priv->phandle, hscfg,
3273 					&pmcfg->param.hs_cfg,
3274 					sizeof(mlan_ds_hs_cfg),
3275 					sizeof(mlan_ds_hs_cfg));
3276 		}
3277 	}
3278 done:
3279 	if (ret != MLAN_STATUS_PENDING)
3280 		kfree(req);
3281 	LEAVE();
3282 	return ret;
3283 }
3284 
3285 /**
3286  *  @brief Get wakeup reason
3287  *
3288  *  @param priv         A pointer to moal_private structure
3289  *  @param wakeup_reason        A pointer to mlan_ds_hs_wakeup_reason  structure
3290  *
3291  *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
3292  * otherwise fail
3293  */
woal_get_wakeup_reason(moal_private * priv,mlan_ds_hs_wakeup_reason * wakeup_reason)3294 mlan_status woal_get_wakeup_reason(moal_private *priv,
3295 				   mlan_ds_hs_wakeup_reason *wakeup_reason)
3296 {
3297 	mlan_status ret = MLAN_STATUS_SUCCESS;
3298 	mlan_ds_pm_cfg *pmcfg = NULL;
3299 	mlan_ioctl_req *req = NULL;
3300 
3301 	ENTER();
3302 
3303 	/* Allocate an IOCTL request buffer */
3304 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
3305 	if (req == NULL) {
3306 		ret = -ENOMEM;
3307 		goto done;
3308 	}
3309 
3310 	/* Fill request buffer */
3311 	pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
3312 	pmcfg->sub_command = MLAN_OID_PM_HS_WAKEUP_REASON;
3313 	req->req_id = MLAN_IOCTL_PM_CFG;
3314 	req->action = MLAN_ACT_GET;
3315 
3316 	/* Send IOCTL request to MLAN */
3317 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT_TIMEOUT);
3318 	if (ret == MLAN_STATUS_SUCCESS) {
3319 		wakeup_reason->hs_wakeup_reason =
3320 			pmcfg->param.wakeup_reason.hs_wakeup_reason;
3321 	}
3322 done:
3323 	if (ret != MLAN_STATUS_PENDING)
3324 		kfree(req);
3325 	LEAVE();
3326 	return ret;
3327 }
3328 
3329 /**
3330  *  @brief Set or Get wowlan config
3331  *
3332  *  @param priv         A pointer to moal_private structure
3333  *  @param action       Action: action to config wowlan
3334  *  @param wait_option  Wait option (MOAL_WAIT or MOAL_NO_WAIT)
3335  *  @param mefcfg        A pointer to mlan_ds_misc_mef_flt_cfg structure
3336  *
3337  *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
3338  */
woal_set_get_wowlan_config(moal_private * priv,t_u16 action,t_u8 wait_option,mlan_ds_misc_mef_flt_cfg * mefcfg)3339 mlan_status woal_set_get_wowlan_config(moal_private *priv, t_u16 action,
3340 				       t_u8 wait_option,
3341 				       mlan_ds_misc_mef_flt_cfg *mefcfg)
3342 {
3343 	mlan_status ret = MLAN_STATUS_SUCCESS;
3344 	mlan_ds_misc_cfg *misccfg = NULL;
3345 	mlan_ioctl_req *req = NULL;
3346 
3347 	ENTER();
3348 
3349 	/** Allocate an IOCTL request buffer*/
3350 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3351 	if (req == NULL) {
3352 		ret = -ENOMEM;
3353 		goto done;
3354 	}
3355 	/** Fill request buffer */
3356 	misccfg = (mlan_ds_misc_cfg *)req->pbuf;
3357 	misccfg->sub_command = MLAN_OID_MISC_MEF_FLT_CFG;
3358 	req->req_id = MLAN_IOCTL_MISC_CFG;
3359 	req->action = action;
3360 	moal_memcpy_ext(priv->phandle, &misccfg->param.mef_flt_cfg, mefcfg,
3361 			sizeof(mlan_ds_misc_mef_flt_cfg),
3362 			sizeof(mlan_ds_misc_mef_flt_cfg));
3363 	/* Send IOCTL request to MLAN */
3364 	ret = woal_request_ioctl(priv, req, wait_option);
3365 	if (ret == MLAN_STATUS_SUCCESS) {
3366 		if (mefcfg && action == MLAN_ACT_GET) {
3367 			moal_memcpy_ext(priv->phandle, mefcfg,
3368 					&misccfg->param.mef_flt_cfg,
3369 					sizeof(mlan_ds_misc_mef_flt_cfg),
3370 					sizeof(mlan_ds_misc_mef_flt_cfg));
3371 		}
3372 	}
3373 	if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
3374 		PRINTM(MIOCTL, "Set Get wowlan IOCTL failed!\n");
3375 done:
3376 	if (ret != MLAN_STATUS_PENDING)
3377 		kfree(req);
3378 	LEAVE();
3379 	return ret;
3380 }
3381 
3382 /**
3383  *  @brief Cancel Host Sleep configuration
3384  *
3385  *  @param priv             A pointer to moal_private structure
3386  *  @param wait_option      wait option
3387  *
3388  *  @return                 MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING,
3389  *                              or MLAN_STATUS_FAILURE
3390  */
woal_cancel_hs(moal_private * priv,t_u8 wait_option)3391 mlan_status woal_cancel_hs(moal_private *priv, t_u8 wait_option)
3392 {
3393 #ifdef STA_CFG80211
3394 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
3395 	moal_handle *handle = NULL;
3396 #endif
3397 #endif
3398 	mlan_status ret = MLAN_STATUS_SUCCESS;
3399 	mlan_ds_hs_cfg hscfg;
3400 #ifdef STA_CFG80211
3401 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
3402 	int i;
3403 #endif
3404 #endif
3405 	ENTER();
3406 
3407 	if (!priv) {
3408 		LEAVE();
3409 		return MLAN_STATUS_FAILURE;
3410 	}
3411 	/* Cancel Host Sleep */
3412 	hscfg.conditions = HOST_SLEEP_CFG_CANCEL;
3413 	hscfg.is_invoke_hostcmd = MTRUE;
3414 	ret = woal_set_get_hs_params(priv, MLAN_ACT_SET, wait_option, &hscfg);
3415 	if (ret != MLAN_STATUS_SUCCESS) {
3416 		PRINTM(MERROR, "%s: woal_set_get_hs_params failed \n",
3417 		       __func__);
3418 		LEAVE();
3419 		return ret;
3420 	}
3421 	if (moal_extflg_isset(priv->phandle, EXT_ROAMOFFLOAD_IN_HS)) {
3422 		/*Disable firmware roaming*/
3423 		woal_enable_fw_roaming(priv, 0);
3424 	}
3425 	if (priv->phandle->fw_roam_enable == ROAM_OFFLOAD_WITH_BSSID ||
3426 	    priv->phandle->fw_roam_enable == ROAM_OFFLOAD_WITH_SSID ||
3427 	    priv->phandle->fw_roam_enable == AUTO_RECONNECT)
3428 		woal_config_fw_roaming(priv, ROAM_OFFLOAD_RESUME_CFG, NULL);
3429 #ifdef STA_CFG80211
3430 	if (priv->phandle->fw_roam_enable == AUTO_RECONNECT)
3431 		woal_set_clear_pmk(priv, MLAN_ACT_CLEAR);
3432 #endif
3433 
3434 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
3435 #if IS_ENABLED(CONFIG_IPV6)
3436 	if (priv->phandle->hs_auto_arp) {
3437 		PRINTM(MIOCTL, "Cancel Host Sleep... remove ipv6 offload\n");
3438 		/** Set ipv6 router advertisement message offload */
3439 		woal_set_ipv6_ra_offload(priv->phandle, MFALSE);
3440 	}
3441 	/** Set Neighbor Solitation message offload */
3442 	woal_set_ipv6_ns_offload(priv->phandle, MFALSE);
3443 #endif
3444 #endif
3445 
3446 	if (priv->phandle->hs_auto_arp) {
3447 		PRINTM(MIOCTL, "Cancel Host Sleep... remove Mdns wake up\n");
3448 		/** Set ipv6 router advertisement message offload */
3449 		woal_set_wake_on_mdns(priv->phandle, MFALSE);
3450 	}
3451 
3452 	if (priv->phandle->hs_auto_arp) {
3453 		PRINTM(MIOCTL, "Cancel Host Sleep... remove FW auto arp\n");
3454 		/* remove auto arp from FW */
3455 		woal_set_auto_arp(priv->phandle, MFALSE);
3456 		/* remove auto arp from FW */
3457 		woal_set_auto_arp_ext(priv->phandle, MFALSE);
3458 	}
3459 
3460 #ifdef STA_CFG80211
3461 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
3462 	handle = priv->phandle;
3463 	if (GTK_REKEY_OFFLOAD_SUSPEND == handle->params.gtk_rekey_offload) {
3464 		PRINTM(MIOCTL,
3465 		       "Cancel Host Sleep... clear gtk rekey offload of FW\n");
3466 		for (i = 0; i < handle->priv_num; i++) {
3467 			if (handle->priv[i] &&
3468 			    handle->priv[i]->gtk_data_ready) {
3469 				PRINTM(MCMND, "clear GTK in resume\n");
3470 				if (MLAN_STATUS_SUCCESS !=
3471 				    woal_set_rekey_data(handle->priv[i], NULL,
3472 							MLAN_ACT_CLEAR,
3473 							wait_option))
3474 					PRINTM(MERROR,
3475 					       "%s: clear GTK in resume failed \n",
3476 					       __func__);
3477 			}
3478 		}
3479 	}
3480 #endif
3481 #endif
3482 
3483 	LEAVE();
3484 	return ret;
3485 }
3486 
3487 /**  @brief This function config fw roaming parameters
3488  *
3489  *  @param priv     A Pointer to the moal_private structure
3490  *  @return         MTRUE or MFALSE
3491  */
woal_set_fw_roaming_params(moal_private * priv)3492 static int woal_set_fw_roaming_params(moal_private *priv)
3493 {
3494 	int ret = 0;
3495 	mlan_status status = MLAN_STATUS_SUCCESS;
3496 	mlan_ioctl_req *req = NULL;
3497 	mlan_ds_sec_cfg *sec = NULL;
3498 	woal_roam_offload_cfg roam_offload_cfg;
3499 #ifdef STA_CFG80211
3500 	t_u8 zero[MLAN_MAX_KEY_LENGTH] = {0};
3501 #endif
3502 
3503 	/*Enable fw roaming*/
3504 	woal_config_fw_roaming(priv, ROAM_OFFLOAD_ENABLE, NULL);
3505 	/*Download fw roaming parameters*/
3506 	woal_config_fw_roaming(priv, ROAM_OFFLOAD_PARAM_CFG,
3507 			       &priv->phandle->fw_roam_params);
3508 
3509 	/*Download userset passphrase key and current connection's PMK*/
3510 #ifdef STA_CFG80211
3511 	if (!priv->phandle->fw_roam_params.userset_passphrase) {
3512 		woal_set_clear_pmk(priv, MLAN_ACT_SET);
3513 		goto done;
3514 	}
3515 #endif
3516 
3517 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
3518 	if (req == NULL) {
3519 		ret = -ENOMEM;
3520 		goto done;
3521 	}
3522 
3523 	req->req_id = MLAN_IOCTL_SEC_CFG;
3524 	sec = (mlan_ds_sec_cfg *)req->pbuf;
3525 	sec->sub_command = MLAN_OID_SEC_CFG_PASSPHRASE;
3526 	sec->multi_passphrase = 1;
3527 	req->action = MLAN_ACT_SET;
3528 
3529 	/*Copy user set passphrase*/
3530 	moal_memcpy_ext(priv->phandle, (char *)sec->param.roam_passphrase,
3531 			(char *)priv->phandle->ssid_passphrase,
3532 			MAX_SEC_SSID_NUM * sizeof(mlan_ds_passphrase),
3533 			MAX_SEC_SSID_NUM * sizeof(mlan_ds_passphrase));
3534 	roam_offload_cfg.userset_passphrase =
3535 		priv->phandle->fw_roam_params.userset_passphrase;
3536 #ifdef STA_CFG80211
3537 	if (memcmp(priv->pmk.pmk, zero, MLAN_MAX_KEY_LENGTH)) {
3538 		/*Download current connection PMK*/
3539 		if (priv->pmk_saved) {
3540 			woal_set_clear_pmk(priv, MLAN_ACT_SET);
3541 			priv->pmk_saved = false;
3542 		}
3543 	}
3544 #endif
3545 	/*Set userset to mlan adapter*/
3546 	woal_config_fw_roaming(priv, ROAM_OFFLOAD_ENABLE, &roam_offload_cfg);
3547 
3548 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3549 	if (status != MLAN_STATUS_SUCCESS) {
3550 		ret = -EFAULT;
3551 		goto done;
3552 	}
3553 done:
3554 	if (status != MLAN_STATUS_PENDING)
3555 		kfree(req);
3556 	LEAVE();
3557 	return ret;
3558 }
3559 
3560 /**  @brief This function enable/disable fw roaming
3561  *
3562  *  @param priv     A Pointer to the moal_private structure
3563  *  @param enable   Enable/disable fw roaming
3564  *  @return         MTRUE or MFALSE
3565  */
woal_enable_fw_roaming(moal_private * priv,int data)3566 int woal_enable_fw_roaming(moal_private *priv, int data)
3567 {
3568 	mlan_ioctl_req *ioctl_req = NULL;
3569 	mlan_ds_misc_cfg *misc = NULL;
3570 	mlan_ds_misc_roam_offload *roam = NULL;
3571 	mlan_status status = MLAN_STATUS_SUCCESS;
3572 	int ret = 0;
3573 
3574 	ENTER();
3575 
3576 	if (!priv || !priv->phandle) {
3577 		PRINTM(MERROR, "priv or handle is null\n");
3578 		ret = -EFAULT;
3579 		goto done;
3580 	}
3581 
3582 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3583 	if (ioctl_req == NULL) {
3584 		ret = -ENOMEM;
3585 		goto done;
3586 	}
3587 
3588 	if (!data && !priv->phandle->fw_roam_enable) {
3589 		PRINTM(MIOCTL, "Fw roaming already disabled\n");
3590 		goto done;
3591 	}
3592 
3593 	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
3594 	misc->sub_command = MLAN_OID_MISC_ROAM_OFFLOAD;
3595 	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
3596 
3597 	roam = (mlan_ds_misc_roam_offload *)&misc->param.roam_offload;
3598 	roam->aplist.ap_num = 0;
3599 	/* SET operation */
3600 	ioctl_req->action = MLAN_ACT_SET;
3601 	roam->enable = data;
3602 	roam->config_mode = ROAM_OFFLOAD_ENABLE;
3603 
3604 	if (moal_extflg_isset(priv->phandle, EXT_ROAMOFFLOAD_IN_HS) && data) {
3605 		priv->phandle->fw_roam_enable = data;
3606 		goto done;
3607 	}
3608 
3609 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
3610 	if (status != MLAN_STATUS_SUCCESS) {
3611 		ret = -EFAULT;
3612 		goto done;
3613 	}
3614 	priv->phandle->fw_roam_enable = data;
3615 	if (!data) {
3616 		memset((char *)&priv->phandle->fw_roam_params, 0,
3617 		       sizeof(woal_roam_offload_cfg));
3618 		memset((char *)&priv->phandle->ssid_passphrase, 0,
3619 		       MAX_SEC_SSID_NUM * sizeof(mlan_ds_passphrase));
3620 	}
3621 #ifdef STA_CFG80211
3622 	else if (priv->media_connected && priv->pmk_saved) {
3623 		woal_set_clear_pmk(priv, MLAN_ACT_SET);
3624 		priv->pmk_saved = false;
3625 	}
3626 #endif
3627 done:
3628 	if (status != MLAN_STATUS_PENDING)
3629 		kfree(ioctl_req);
3630 
3631 	LEAVE();
3632 	return ret;
3633 }
3634 
3635 /**  @brief This function enables the host sleep
3636  *
3637  *  @param priv     A Pointer to the moal_private structure
3638  *  @return         MTRUE or MFALSE
3639  */
woal_enable_hs(moal_private * priv)3640 int woal_enable_hs(moal_private *priv)
3641 {
3642 	mlan_ds_hs_cfg hscfg;
3643 	moal_handle *handle = NULL;
3644 	int hs_actived = MFALSE;
3645 	int timeout = 0;
3646 	int i;
3647 #ifdef SDIO_SUSPEND_RESUME
3648 	mlan_ds_ps_info pm_info;
3649 #endif
3650 	pmlan_ds_misc_keep_alive keep_alive = NULL;
3651 	t_u8 media_connected = MFALSE;
3652 
3653 	ENTER();
3654 
3655 	if (priv == NULL) {
3656 		PRINTM(MERROR, "Invalid priv\n");
3657 		goto done;
3658 	}
3659 	handle = priv->phandle;
3660 	if (handle->hs_activated == MTRUE) {
3661 		PRINTM(MIOCTL, "HS Already actived\n");
3662 		hs_actived = MTRUE;
3663 		goto done;
3664 	}
3665 	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
3666 		if (handle->priv[i] &&
3667 		    (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA)) {
3668 			if (moal_extflg_isset(handle,
3669 					      EXT_DISCONNECT_ON_SUSPEND) &&
3670 			    handle->priv[i]->media_connected == MTRUE) {
3671 				PRINTM(MIOCTL, "disconnect on suspend\n");
3672 				woal_disconnect(handle->priv[i], MOAL_NO_WAIT,
3673 						NULL, DEF_DEAUTH_REASON_CODE);
3674 			}
3675 		}
3676 		if (handle->priv[i]) {
3677 			PRINTM(MIOCTL, "woal_delba_all on priv[%d]\n", i);
3678 			woal_delba_all(handle->priv[i], MOAL_NO_WAIT);
3679 		}
3680 	}
3681 
3682 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
3683 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
3684 	if (priv->phandle->is_remain_timer_set) {
3685 		woal_cancel_timer(&priv->phandle->remain_timer);
3686 		woal_remain_timer_func(priv->phandle);
3687 	}
3688 	/* cancel pending remain on channel */
3689 	if (priv->phandle->remain_on_channel) {
3690 		t_u8 channel_status;
3691 		moal_private *remain_priv =
3692 			priv->phandle->priv[priv->phandle->remain_bss_index];
3693 		if (remain_priv) {
3694 			woal_cfg80211_remain_on_channel_cfg(remain_priv,
3695 							    MOAL_NO_WAIT, MTRUE,
3696 							    &channel_status,
3697 							    NULL, 0, 0);
3698 			if (priv->phandle->cookie) {
3699 				cfg80211_remain_on_channel_expired(
3700 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
3701 					remain_priv->netdev,
3702 #else
3703 					remain_priv->wdev,
3704 #endif
3705 					priv->phandle->cookie,
3706 					&priv->phandle->chan,
3707 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
3708 					priv->phandle->channel_type,
3709 #endif
3710 					GFP_ATOMIC);
3711 				priv->phandle->cookie = 0;
3712 			}
3713 		}
3714 		priv->phandle->remain_on_channel = MFALSE;
3715 	}
3716 #endif
3717 #endif
3718 
3719 #ifdef STA_SUPPORT
3720 	woal_reconfig_bgscan(priv->phandle);
3721 #endif
3722 
3723 	if (moal_extflg_isset(priv->phandle, EXT_ROAMOFFLOAD_IN_HS) &&
3724 	    handle->fw_roam_enable) {
3725 		woal_set_fw_roaming_params(priv);
3726 	}
3727 	if (handle->fw_roam_enable == ROAM_OFFLOAD_WITH_BSSID ||
3728 	    handle->fw_roam_enable == ROAM_OFFLOAD_WITH_SSID ||
3729 	    handle->fw_roam_enable == AUTO_RECONNECT) {
3730 		woal_config_fw_roaming(priv, ROAM_OFFLOAD_SUSPEND_CFG, NULL);
3731 #ifdef STA_CFG80211
3732 		if (priv->phandle->fw_roam_enable == AUTO_RECONNECT)
3733 			woal_set_clear_pmk(priv, MLAN_ACT_SET);
3734 #endif
3735 	}
3736 	media_connected = woal_check_media_connected(handle);
3737 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
3738 #if IS_ENABLED(CONFIG_IPV6)
3739 	if (handle->hs_auto_arp && media_connected) {
3740 		PRINTM(MIOCTL, "Host Sleep enabled... set ipv6 offload\n");
3741 		/** Set ipv6 router advertisement message offload */
3742 		woal_set_ipv6_ra_offload(handle, MTRUE);
3743 		/** Set Neighbor Solitation message offload */
3744 		woal_set_ipv6_ns_offload(handle, MTRUE);
3745 	}
3746 #endif
3747 #endif
3748 
3749 	if (handle->hs_auto_arp) {
3750 		PRINTM(MIOCTL, "Host Sleep enabled... set mdns wake up\n");
3751 		/**MDNS wake up**/
3752 		woal_set_wake_on_mdns(handle, MTRUE);
3753 	}
3754 
3755 	if (handle->hs_auto_arp && media_connected) {
3756 		PRINTM(MIOCTL, "Host Sleep enabled... set FW auto arp\n");
3757 		/* Set auto arp response configuration to Fw */
3758 		woal_set_auto_arp(handle, MTRUE);
3759 		/* Set auto arp response configuration to Fw */
3760 		woal_set_auto_arp_ext(handle, MTRUE);
3761 	}
3762 
3763 #ifdef STA_CFG80211
3764 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
3765 	if (GTK_REKEY_OFFLOAD_SUSPEND == handle->params.gtk_rekey_offload) {
3766 		PRINTM(MIOCTL,
3767 		       "Host Sleep enabled... set gtk rekey offload to FW\n");
3768 		for (i = 0; i < handle->priv_num; i++) {
3769 			if (handle->priv[i] &&
3770 			    handle->priv[i]->gtk_data_ready) {
3771 				PRINTM(MCMND, "set GTK before suspend\n");
3772 				if (MLAN_STATUS_SUCCESS !=
3773 				    woal_set_rekey_data(
3774 					    handle->priv[i],
3775 					    &handle->priv[i]->gtk_rekey_data,
3776 					    MLAN_ACT_SET, MOAL_NO_WAIT))
3777 					PRINTM(MERROR,
3778 					       "%s: set GTR before suspend failed \n",
3779 					       __func__);
3780 			}
3781 		}
3782 	}
3783 #endif
3784 #endif
3785 
3786 	for (i = 0; i < MAX_KEEP_ALIVE_ID; i++) {
3787 		keep_alive = &handle->keep_alive[i];
3788 		if (keep_alive && keep_alive->cached && keep_alive->enable) {
3789 			keep_alive->cached = false;
3790 			woal_start_mkeep_alive(
3791 				woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
3792 				keep_alive->mkeep_alive_id, keep_alive->packet,
3793 				keep_alive->pkt_len, keep_alive->src_mac,
3794 				keep_alive->dst_mac, keep_alive->send_interval,
3795 				keep_alive->retry_interval,
3796 				keep_alive->retry_count);
3797 			keep_alive->pkt_len = 0;
3798 			memset(keep_alive->packet, 0, MKEEP_ALIVE_IP_PKT_MAX);
3799 		}
3800 	}
3801 	/* Enable Host Sleep */
3802 	handle->hs_activate_wait_q_woken = MFALSE;
3803 	memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg));
3804 	hscfg.is_invoke_hostcmd = MTRUE;
3805 	if (woal_set_get_hs_params(priv, MLAN_ACT_SET, MOAL_NO_WAIT, &hscfg) ==
3806 	    MLAN_STATUS_FAILURE) {
3807 		PRINTM(MIOCTL, "IOCTL request HS enable failed\n");
3808 		goto done;
3809 	}
3810 	timeout = wait_event_timeout(handle->hs_activate_wait_q,
3811 				     handle->hs_activate_wait_q_woken,
3812 				     HS_ACTIVE_TIMEOUT);
3813 #ifdef SDIO_MMC
3814 	if (IS_SD(handle->card_type)) {
3815 		sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
3816 	}
3817 #endif
3818 
3819 #ifdef SDIO_SUSPEND_RESUME
3820 	memset(&pm_info, 0, sizeof(mlan_ds_ps_info));
3821 #endif
3822 	if ((handle->hs_activated == MTRUE) ||
3823 	    (handle->is_suspended == MTRUE)) {
3824 		PRINTM(MCMND, "suspend success! force=%u skip=%u\n",
3825 		       handle->hs_force_count, handle->hs_skip_count);
3826 		hs_actived = MTRUE;
3827 	}
3828 #ifdef SDIO_SUSPEND_RESUME
3829 	else if (IS_SD(handle->card_type)) {
3830 		handle->suspend_fail = MTRUE;
3831 		woal_get_pm_info(priv, &pm_info);
3832 		if (pm_info.is_suspend_allowed == MTRUE) {
3833 #ifdef MMC_PM_FUNC_SUSPENDED
3834 			woal_wlan_is_suspended(priv->phandle);
3835 #endif
3836 			handle->hs_force_count++;
3837 			PRINTM(MCMND, "suspend allowed! force=%u skip=%u\n",
3838 			       handle->hs_force_count, handle->hs_skip_count);
3839 			hs_actived = MTRUE;
3840 		}
3841 	}
3842 #endif /* SDIO_SUSPEND_RESUME*/
3843 #ifdef SDIO_MMC
3844 	if (IS_SD(handle->card_type)) {
3845 		sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
3846 	}
3847 #endif
3848 	if (hs_actived != MTRUE) {
3849 		handle->hs_skip_count++;
3850 #ifdef SDIO_SUSPEND_RESUME
3851 		if (IS_SD(handle->card_type)) {
3852 			PRINTM(MCMND,
3853 			       "suspend skipped! timeout=%d allow=%d force=%u skip=%u\n",
3854 			       timeout, (int)pm_info.is_suspend_allowed,
3855 			       handle->hs_force_count, handle->hs_skip_count);
3856 		}
3857 #else
3858 		PRINTM(MCMND, "suspend skipped! timeout=%d skip=%u\n", timeout,
3859 		       handle->hs_skip_count);
3860 #endif
3861 		woal_cancel_hs(priv, MOAL_NO_WAIT);
3862 	}
3863 done:
3864 	LEAVE();
3865 	return hs_actived;
3866 }
3867 
3868 #ifdef CONFIG_PROC_FS
3869 /**
3870  *  @brief This function send soft_reset command to firmware
3871  *
3872  *  @param handle   A pointer to moal_handle structure
3873  *  @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING on success,
3874  *                      otherwise failure code
3875  */
woal_request_soft_reset(moal_handle * handle)3876 mlan_status woal_request_soft_reset(moal_handle *handle)
3877 {
3878 	mlan_status ret = MLAN_STATUS_SUCCESS;
3879 	mlan_ioctl_req *req = NULL;
3880 	mlan_ds_misc_cfg *misc = NULL;
3881 
3882 	ENTER();
3883 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3884 	if (req) {
3885 		misc = (mlan_ds_misc_cfg *)req->pbuf;
3886 		misc->sub_command = MLAN_OID_MISC_SOFT_RESET;
3887 		req->req_id = MLAN_IOCTL_MISC_CFG;
3888 		req->action = MLAN_ACT_SET;
3889 		ret = woal_request_ioctl(woal_get_priv(handle,
3890 						       MLAN_BSS_ROLE_ANY),
3891 					 req, MOAL_IOCTL_WAIT);
3892 	}
3893 
3894 	handle->surprise_removed = MTRUE;
3895 	woal_sched_timeout(5);
3896 	if (ret != MLAN_STATUS_PENDING)
3897 		kfree(req);
3898 	LEAVE();
3899 	return ret;
3900 }
3901 #endif /* CONFIG_PROC_FS */
3902 
3903 /**
3904  *  @brief Set wapi enable
3905  *
3906  *  @param priv                 A pointer to moal_private structure
3907  *  @param wait_option          Wait option
3908  *  @param enable               MTRUE or MFALSE
3909  *
3910  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
3911  * success, otherwise fail
3912  */
woal_set_wapi_enable(moal_private * priv,t_u8 wait_option,t_u32 enable)3913 mlan_status woal_set_wapi_enable(moal_private *priv, t_u8 wait_option,
3914 				 t_u32 enable)
3915 {
3916 	mlan_ioctl_req *req = NULL;
3917 	mlan_ds_sec_cfg *sec = NULL;
3918 	mlan_status status = MLAN_STATUS_SUCCESS;
3919 	ENTER();
3920 
3921 	/* Allocate an IOCTL request buffer */
3922 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
3923 	if (req == NULL) {
3924 		status = MLAN_STATUS_FAILURE;
3925 		goto done;
3926 	}
3927 
3928 	/* Fill request buffer */
3929 	sec = (mlan_ds_sec_cfg *)req->pbuf;
3930 	sec->sub_command = MLAN_OID_SEC_CFG_WAPI_ENABLED;
3931 	req->req_id = MLAN_IOCTL_SEC_CFG;
3932 	req->action = MLAN_ACT_SET;
3933 	sec->param.wapi_enabled = enable;
3934 
3935 	/* Send IOCTL request to MLAN */
3936 	status = woal_request_ioctl(priv, req, wait_option);
3937 done:
3938 	if (status != MLAN_STATUS_PENDING)
3939 		kfree(req);
3940 	LEAVE();
3941 	return status;
3942 }
3943 
3944 /**
3945  *  @brief Get version
3946  *
3947  *  @param handle       A pointer to moal_handle structure
3948  *  @param version      A pointer to version buffer
3949  *  @param max_len      max length of version buffer
3950  *
3951  *  @return             N/A
3952  */
woal_get_version(moal_handle * handle,char * version,int max_len)3953 void woal_get_version(moal_handle *handle, char *version, int max_len)
3954 {
3955 	t_u8 hotfix_ver = 0;
3956 	union {
3957 		t_u32 l;
3958 		t_u8 c[4];
3959 	} ver;
3960 	char fw_ver[32];
3961 
3962 	ENTER();
3963 
3964 	hotfix_ver = handle->fw_hotfix_version;
3965 	ver.l = handle->fw_release_number;
3966 
3967 	if (hotfix_ver) {
3968 		snprintf(fw_ver, sizeof(fw_ver), "%u.%u.%u.p%u.%u", ver.c[2],
3969 			 ver.c[1], ver.c[0], ver.c[3], hotfix_ver);
3970 
3971 	} else {
3972 		snprintf(fw_ver, sizeof(fw_ver), "%u.%u.%u.p%u", ver.c[2],
3973 			 ver.c[1], ver.c[0], ver.c[3]);
3974 	}
3975 
3976 	snprintf(version, max_len, handle->driver_version, fw_ver);
3977 
3978 	LEAVE();
3979 }
3980 
3981 #if defined(STA_WEXT) || defined(UAP_WEXT)
3982 /**
3983  *  @brief Get Driver Version
3984  *
3985  *  @param priv         A pointer to moal_private structure
3986  *  @param req          A pointer to ifreq structure
3987  *
3988  *  @return             0 --success, otherwise fail
3989  */
woal_get_driver_version(moal_private * priv,struct ifreq * req)3990 int woal_get_driver_version(moal_private *priv, struct ifreq *req)
3991 {
3992 	struct iwreq *wrq = (struct iwreq *)req;
3993 	int len;
3994 	char buf[MLAN_MAX_VER_STR_LEN];
3995 	ENTER();
3996 
3997 	woal_get_version(priv->phandle, buf, sizeof(buf) - 1);
3998 
3999 	len = strlen(buf);
4000 	if (wrq->u.data.pointer) {
4001 		if (copy_to_user(wrq->u.data.pointer, buf, len)) {
4002 			PRINTM(MERROR, "Copy to user failed\n");
4003 			LEAVE();
4004 			return -EFAULT;
4005 		}
4006 		wrq->u.data.length = len;
4007 	}
4008 	PRINTM(MINFO, "MOAL VERSION: %s\n", buf);
4009 	LEAVE();
4010 	return 0;
4011 }
4012 
4013 /**
4014  *  @brief Get extended driver version
4015  *
4016  *  @param priv         A pointer to moal_private structure
4017  *  @param ireq         A pointer to ifreq structure
4018  *
4019  *  @return             0 --success, otherwise fail
4020  */
woal_get_driver_verext(moal_private * priv,struct ifreq * ireq)4021 int woal_get_driver_verext(moal_private *priv, struct ifreq *ireq)
4022 {
4023 	struct iwreq *wrq = (struct iwreq *)ireq;
4024 	mlan_ds_get_info *info = NULL;
4025 	mlan_ioctl_req *req = NULL;
4026 	int ret = 0;
4027 	mlan_status status = MLAN_STATUS_SUCCESS;
4028 
4029 	ENTER();
4030 
4031 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
4032 	if (req == NULL) {
4033 		LEAVE();
4034 		return -ENOMEM;
4035 	}
4036 
4037 	info = (mlan_ds_get_info *)req->pbuf;
4038 	info->sub_command = MLAN_OID_GET_VER_EXT;
4039 	req->req_id = MLAN_IOCTL_GET_INFO;
4040 	req->action = MLAN_ACT_GET;
4041 
4042 	if (!wrq->u.data.flags) {
4043 		info->param.ver_ext.version_str_sel =
4044 			*((int *)(wrq->u.name + SUBCMD_OFFSET));
4045 	} else {
4046 		if (copy_from_user(
4047 			    &info->param.ver_ext.version_str_sel,
4048 			    wrq->u.data.pointer,
4049 			    sizeof(info->param.ver_ext.version_str_sel))) {
4050 			PRINTM(MERROR, "Copy from user failed\n");
4051 			ret = -EFAULT;
4052 			goto done;
4053 		} else {
4054 			if (((t_s32)(info->param.ver_ext.version_str_sel)) <
4055 			    0) {
4056 				PRINTM(MERROR, "Invalid arguments!\n");
4057 				ret = -EINVAL;
4058 				goto done;
4059 			}
4060 		}
4061 	}
4062 
4063 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4064 	if (status != MLAN_STATUS_SUCCESS) {
4065 		ret = -EFAULT;
4066 		goto done;
4067 	}
4068 
4069 	if (wrq->u.data.pointer) {
4070 		if (copy_to_user(wrq->u.data.pointer,
4071 				 info->param.ver_ext.version_str,
4072 				 strlen(info->param.ver_ext.version_str))) {
4073 			PRINTM(MERROR, "Copy to user failed\n");
4074 			ret = -EFAULT;
4075 			goto done;
4076 		}
4077 		wrq->u.data.length = strlen(info->param.ver_ext.version_str);
4078 	}
4079 
4080 	PRINTM(MINFO, "MOAL EXTENDED VERSION: %s\n",
4081 	       info->param.ver_ext.version_str);
4082 done:
4083 	if (status != MLAN_STATUS_PENDING)
4084 		kfree(req);
4085 
4086 	LEAVE();
4087 	return ret;
4088 }
4089 #endif
4090 
4091 #ifdef DEBUG_LEVEL1
4092 /**
4093  *  @brief Set driver debug bit masks to mlan in order to enhance performance
4094  *
4095  *  @param priv         A pointer to moal_private structure
4096  *  @param drv_dbg       Driver debug level
4097  *
4098  *  @return             0 --success, otherwise fail
4099  */
woal_set_drvdbg(moal_private * priv,t_u32 drv_dbg)4100 int woal_set_drvdbg(moal_private *priv, t_u32 drv_dbg)
4101 {
4102 	mlan_ioctl_req *req = NULL;
4103 	mlan_ds_misc_cfg *misc = NULL;
4104 	int ret = 0;
4105 
4106 	ENTER();
4107 
4108 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
4109 	if (req == NULL) {
4110 		LEAVE();
4111 		return -ENOMEM;
4112 	}
4113 
4114 	misc = (mlan_ds_misc_cfg *)req->pbuf;
4115 	misc->sub_command = MLAN_OID_MISC_DRVDBG;
4116 	req->req_id = MLAN_IOCTL_MISC_CFG;
4117 	req->action = MLAN_ACT_SET;
4118 	misc->param.drvdbg = drv_dbg;
4119 
4120 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4121 
4122 	if (ret != MLAN_STATUS_PENDING)
4123 		kfree(req);
4124 
4125 	LEAVE();
4126 	return ret;
4127 }
4128 #endif
4129 
4130 /**
4131  *  @brief Mgmt frame forward registration
4132  *
4133  *  @param priv         A pointer to moal_private structure
4134  *  @param action       Action: set or get
4135  *  @param pmgmt_subtype_mask   A Pointer to mgmt frame subtype mask
4136  *  @param wait_option  wait option (MOAL_WAIT or MOAL_NO_WAIT)
4137  *
4138  *  @return             0 --success, otherwise fail
4139  */
woal_reg_rx_mgmt_ind(moal_private * priv,t_u16 action,t_u32 * pmgmt_subtype_mask,t_u8 wait_option)4140 int woal_reg_rx_mgmt_ind(moal_private *priv, t_u16 action,
4141 			 t_u32 *pmgmt_subtype_mask, t_u8 wait_option)
4142 {
4143 	mlan_ioctl_req *req = NULL;
4144 	mlan_ds_misc_cfg *misc = NULL;
4145 	int ret = 0;
4146 
4147 	ENTER();
4148 
4149 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
4150 	if (req == NULL) {
4151 		LEAVE();
4152 		return -ENOMEM;
4153 	}
4154 
4155 	misc = (mlan_ds_misc_cfg *)req->pbuf;
4156 	misc->sub_command = MLAN_OID_MISC_RX_MGMT_IND;
4157 	req->req_id = MLAN_IOCTL_MISC_CFG;
4158 	req->action = action;
4159 	misc->param.mgmt_subtype_mask = *pmgmt_subtype_mask;
4160 	if (req->action == MLAN_ACT_SET)
4161 		moal_memcpy_ext(priv->phandle, &misc->param.mgmt_subtype_mask,
4162 				pmgmt_subtype_mask,
4163 				sizeof(misc->param.mgmt_subtype_mask),
4164 				sizeof(misc->param.mgmt_subtype_mask));
4165 
4166 	ret = woal_request_ioctl(priv, req, wait_option);
4167 
4168 	if (req->action == MLAN_ACT_GET)
4169 		moal_memcpy_ext(priv->phandle, pmgmt_subtype_mask,
4170 				&misc->param.mgmt_subtype_mask,
4171 				sizeof(misc->param.mgmt_subtype_mask),
4172 				sizeof(misc->param.mgmt_subtype_mask));
4173 
4174 	if (ret != MLAN_STATUS_PENDING)
4175 		kfree(req);
4176 
4177 	LEAVE();
4178 	return ret;
4179 }
4180 
4181 /**
4182  *  @brief Set/Get Transmit beamforming capabilities
4183  *
4184  *  @param priv     A pointer to moal_private structure
4185  *  @param action       Action: set or get
4186  *  @param tx_bf_cap    A pointer to tx_buf_cap buffer
4187  *
4188  *  @return         MLAN_STATUS_SUCCESS -- success, otherwise fail
4189  */
woal_set_get_tx_bf_cap(moal_private * priv,t_u16 action,t_u32 * tx_bf_cap)4190 mlan_status woal_set_get_tx_bf_cap(moal_private *priv, t_u16 action,
4191 				   t_u32 *tx_bf_cap)
4192 {
4193 	mlan_ioctl_req *req = NULL;
4194 	mlan_ds_11n_cfg *bf_cfg = NULL;
4195 	mlan_status ret = MLAN_STATUS_SUCCESS;
4196 
4197 	ENTER();
4198 
4199 	if (!tx_bf_cap) {
4200 		ret = MLAN_STATUS_FAILURE;
4201 		goto done;
4202 	}
4203 	/* Allocate an IOCTL request buffer */
4204 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
4205 	if (req == NULL) {
4206 		ret = MLAN_STATUS_FAILURE;
4207 		goto done;
4208 	}
4209 
4210 	/* Fill request buffer */
4211 	bf_cfg = (mlan_ds_11n_cfg *)req->pbuf;
4212 	req->req_id = MLAN_IOCTL_11N_CFG;
4213 	bf_cfg->sub_command = MLAN_OID_11N_CFG_TX_BF_CAP;
4214 	req->action = action;
4215 	if (action == MLAN_ACT_SET)
4216 		bf_cfg->param.tx_bf_cap = *tx_bf_cap;
4217 
4218 	/* Send IOCTL request to MLAN */
4219 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4220 	if (ret != MLAN_STATUS_SUCCESS) {
4221 		goto done;
4222 	}
4223 
4224 	if (action == MLAN_ACT_GET)
4225 		*tx_bf_cap = bf_cfg->param.tx_bf_cap;
4226 
4227 done:
4228 	if (ret != MLAN_STATUS_PENDING)
4229 		kfree(req);
4230 	LEAVE();
4231 	return ret;
4232 }
4233 
4234 /**
4235  *  @brief Set/Get Transmit beamforming configuration
4236  *
4237  *  @param priv         A pointer to moal_private structure
4238  *  @param action       Action: set or get
4239  *  @param tx_bf_cfg    A pointer to tx_bf_cfg structure
4240  *
4241  *  @return         MLAN_STATUS_SUCCESS -- success, otherwise fail
4242  */
woal_set_get_tx_bf_cfg(moal_private * priv,t_u16 action,mlan_ds_11n_tx_bf_cfg * tx_bf_cfg)4243 mlan_status woal_set_get_tx_bf_cfg(moal_private *priv, t_u16 action,
4244 				   mlan_ds_11n_tx_bf_cfg *tx_bf_cfg)
4245 {
4246 	mlan_status ret = MLAN_STATUS_SUCCESS;
4247 	mlan_ioctl_req *req = NULL;
4248 	mlan_ds_11n_cfg *bf_cfg = NULL;
4249 
4250 	ENTER();
4251 
4252 	/* Sanity test */
4253 	if (tx_bf_cfg == NULL) {
4254 		ret = MLAN_STATUS_FAILURE;
4255 		goto done;
4256 	}
4257 
4258 	/* Allocate an IOCTL request buffer */
4259 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
4260 	if (req == NULL) {
4261 		ret = MLAN_STATUS_FAILURE;
4262 		goto done;
4263 	}
4264 
4265 	/* Fill request buffer */
4266 	bf_cfg = (mlan_ds_11n_cfg *)req->pbuf;
4267 	req->req_id = MLAN_IOCTL_11N_CFG;
4268 	bf_cfg->sub_command = MLAN_OID_11N_CFG_TX_BF_CFG;
4269 
4270 	req->action = action;
4271 	moal_memcpy_ext(priv->phandle, &bf_cfg->param.tx_bf, tx_bf_cfg,
4272 			sizeof(mlan_ds_11n_tx_bf_cfg),
4273 			sizeof(mlan_ds_11n_tx_bf_cfg));
4274 
4275 	/* Send IOCTL request to MLAN */
4276 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4277 	if (ret != MLAN_STATUS_SUCCESS)
4278 		goto done;
4279 
4280 	if (action == MLAN_ACT_GET)
4281 		moal_memcpy_ext(priv->phandle, tx_bf_cfg, &bf_cfg->param.tx_bf,
4282 				sizeof(mlan_ds_11n_tx_bf_cfg),
4283 				sizeof(mlan_ds_11n_tx_bf_cfg));
4284 
4285 done:
4286 	if (ret != MLAN_STATUS_PENDING)
4287 		kfree(req);
4288 	LEAVE();
4289 	return ret;
4290 }
4291 
4292 /**
4293  *  @brief Handle ioctl resp
4294  *
4295  *  @param priv     Pointer to moal_private structure
4296  *  @param req      Pointer to mlan_ioctl_req structure
4297  *
4298  *  @return         N/A
4299  */
woal_process_ioctl_resp(moal_private * priv,mlan_ioctl_req * req)4300 void woal_process_ioctl_resp(moal_private *priv, mlan_ioctl_req *req)
4301 {
4302 	int cfg80211_wext;
4303 
4304 	ENTER();
4305 
4306 	if (priv == NULL) {
4307 		LEAVE();
4308 		return;
4309 	}
4310 	cfg80211_wext = priv->phandle->params.cfg80211_wext;
4311 	switch (req->req_id) {
4312 	case MLAN_IOCTL_GET_INFO:
4313 #ifdef STA_WEXT
4314 #ifdef STA_SUPPORT
4315 		if (IS_STA_WEXT(cfg80211_wext) &&
4316 		    GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
4317 			woal_ioctl_get_info_resp(priv,
4318 						 (mlan_ds_get_info *)req->pbuf);
4319 #endif
4320 #endif
4321 #ifdef UAP_WEXT
4322 #ifdef UAP_SUPPORT
4323 		if (IS_UAP_WEXT(cfg80211_wext) &&
4324 		    GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
4325 			woal_ioctl_get_uap_info_resp(
4326 				priv, (mlan_ds_get_info *)req->pbuf);
4327 #endif
4328 #endif
4329 		break;
4330 #ifdef STA_WEXT
4331 #ifdef STA_SUPPORT
4332 	case MLAN_IOCTL_BSS:
4333 		if (IS_STA_WEXT(cfg80211_wext) &&
4334 		    GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
4335 			woal_ioctl_get_bss_resp(priv, (mlan_ds_bss *)req->pbuf);
4336 		break;
4337 #endif
4338 #endif
4339 	case MLAN_IOCTL_MISC_CFG:
4340 		woal_ioctl_get_misc_conf(priv, (mlan_ds_misc_cfg *)req->pbuf);
4341 	default:
4342 		break;
4343 	}
4344 
4345 	LEAVE();
4346 	return;
4347 }
4348 
4349 /**
4350  *  @brief Get PM info
4351  *
4352  *  @param priv                 A pointer to moal_private structure
4353  *  @param pm_info              A pointer to mlan_ds_ps_info structure
4354  *
4355  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
4356  * success, otherwise fail
4357  */
woal_get_pm_info(moal_private * priv,mlan_ds_ps_info * pm_info)4358 mlan_status woal_get_pm_info(moal_private *priv, mlan_ds_ps_info *pm_info)
4359 {
4360 	mlan_status ret = MLAN_STATUS_SUCCESS;
4361 	mlan_ds_pm_cfg *pmcfg = NULL;
4362 	mlan_ioctl_req *req = NULL;
4363 
4364 	ENTER();
4365 
4366 	/* Allocate an IOCTL request buffer */
4367 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
4368 	if (req == NULL) {
4369 		PRINTM(MERROR, "Fail to alloc mlan_ds_pm_cfg buffer\n");
4370 		ret = MLAN_STATUS_FAILURE;
4371 		goto done;
4372 	}
4373 
4374 	/* Fill request buffer */
4375 	pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
4376 	pmcfg->sub_command = MLAN_OID_PM_INFO;
4377 	req->req_id = MLAN_IOCTL_PM_CFG;
4378 	req->action = MLAN_ACT_GET;
4379 
4380 	/* Send IOCTL request to MLAN */
4381 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4382 	if (ret == MLAN_STATUS_SUCCESS) {
4383 		if (pm_info) {
4384 			moal_memcpy_ext(priv->phandle, pm_info,
4385 					&pmcfg->param.ps_info,
4386 					sizeof(mlan_ds_ps_info),
4387 					sizeof(mlan_ds_ps_info));
4388 		}
4389 	}
4390 done:
4391 	if (ret != MLAN_STATUS_PENDING)
4392 		kfree(req);
4393 	LEAVE();
4394 	return ret;
4395 }
4396 
4397 /**
4398  *  @brief Get Deep Sleep
4399  *
4400  *  @param priv      Pointer to the moal_private driver data struct
4401  *  @param data      Pointer to return deep_sleep setting
4402  *
4403  *  @return          0 --success, otherwise fail
4404  */
woal_get_deep_sleep(moal_private * priv,t_u32 * data)4405 int woal_get_deep_sleep(moal_private *priv, t_u32 *data)
4406 {
4407 	int ret = 0;
4408 	mlan_ioctl_req *req = NULL;
4409 	mlan_ds_pm_cfg *pm = NULL;
4410 	mlan_status status = MLAN_STATUS_SUCCESS;
4411 
4412 	ENTER();
4413 
4414 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
4415 	if (req == NULL) {
4416 		LEAVE();
4417 		return -ENOMEM;
4418 	}
4419 	pm = (mlan_ds_pm_cfg *)req->pbuf;
4420 	pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP;
4421 	req->req_id = MLAN_IOCTL_PM_CFG;
4422 
4423 	req->action = MLAN_ACT_GET;
4424 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4425 	if (status != MLAN_STATUS_SUCCESS) {
4426 		ret = -EFAULT;
4427 		goto done;
4428 	}
4429 	*data = pm->param.auto_deep_sleep.auto_ds;
4430 	*(data + 1) = pm->param.auto_deep_sleep.idletime;
4431 
4432 done:
4433 	if (status != MLAN_STATUS_PENDING)
4434 		kfree(req);
4435 	LEAVE();
4436 	return ret;
4437 }
4438 
4439 /**
4440  *  @brief Set Deep Sleep
4441  *
4442  *  @param priv         Pointer to the moal_private driver data struct
4443  *  @param wait_option  wait option
4444  *  @param bdeep_sleep  TRUE--enalbe deepsleep, FALSE--disable deepsleep
4445  *  @param idletime     Idle time for optimized PS API
4446  *
4447  *  @return             0 --success, otherwise fail
4448  */
woal_set_deep_sleep(moal_private * priv,t_u8 wait_option,BOOLEAN bdeep_sleep,t_u16 idletime)4449 int woal_set_deep_sleep(moal_private *priv, t_u8 wait_option,
4450 			BOOLEAN bdeep_sleep, t_u16 idletime)
4451 {
4452 	int ret = 0;
4453 	mlan_ioctl_req *req = NULL;
4454 	mlan_ds_pm_cfg *pm = NULL;
4455 
4456 	ENTER();
4457 
4458 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
4459 	if (req == NULL) {
4460 		LEAVE();
4461 		return -ENOMEM;
4462 	}
4463 	pm = (mlan_ds_pm_cfg *)req->pbuf;
4464 	pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP;
4465 	req->req_id = MLAN_IOCTL_PM_CFG;
4466 
4467 	req->action = MLAN_ACT_SET;
4468 	if (bdeep_sleep == MTRUE) {
4469 		PRINTM(MIOCTL, "Deep Sleep: sleep\n");
4470 		pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_ON;
4471 		if (idletime)
4472 			pm->param.auto_deep_sleep.idletime = idletime;
4473 		ret = woal_request_ioctl(priv, req, wait_option);
4474 		if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING) {
4475 			ret = -EFAULT;
4476 			goto done;
4477 		}
4478 	} else {
4479 		PRINTM(MIOCTL, "%lu : Deep Sleep: wakeup\n", jiffies);
4480 		pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_OFF;
4481 		ret = woal_request_ioctl(priv, req, wait_option);
4482 		if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING) {
4483 			ret = -EFAULT;
4484 			goto done;
4485 		}
4486 	}
4487 done:
4488 	if (ret != MLAN_STATUS_PENDING)
4489 		kfree(req);
4490 	LEAVE();
4491 	return ret;
4492 }
4493 
4494 /**
4495  *  @brief Cancel CAC period block
4496  *
4497  *  @param priv         A pointer to moal_private structure
4498  *
4499  *  @return         N/A
4500  */
woal_cancel_cac_block(moal_private * priv)4501 void woal_cancel_cac_block(moal_private *priv)
4502 {
4503 	ENTER();
4504 	/* if during CAC period, wake up wait queue */
4505 	if (priv->phandle->cac_period == MTRUE) {
4506 		priv->phandle->cac_period = MFALSE;
4507 		/* Make sure Chan Report is cancelled */
4508 		if (woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT))
4509 			PRINTM(MERROR,
4510 			       "%s: Cancelling CAC chan report in FW failed \n",
4511 			       __func__);
4512 		priv->phandle->meas_start_jiffies = 0;
4513 		if (priv->phandle->delay_bss_start == MTRUE)
4514 			priv->phandle->delay_bss_start = MFALSE;
4515 		if (priv->phandle->meas_wait_q_woken == MFALSE) {
4516 			priv->phandle->meas_wait_q_woken = MTRUE;
4517 			wake_up_interruptible(&priv->phandle->meas_wait_q);
4518 		}
4519 #ifdef UAP_SUPPORT
4520 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
4521 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
4522 		if (priv->uap_host_based &&
4523 		    moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
4524 			woal_cfg80211_dfs_vendor_event(
4525 				priv, event_dfs_cac_aborted, &priv->chan);
4526 #endif
4527 #endif
4528 #endif
4529 	}
4530 	LEAVE();
4531 }
4532 
4533 /** MEAS report timeout value in seconds */
4534 
4535 /**
4536  *  @brief Issue MLAN_OID_11H_CHANNEL_CHECK ioctl
4537  *
4538  *  @param priv     Pointer to the moal_private driver data struct
4539  *  @param wait_option wait option
4540  *
4541  *  @return         0 --success, otherwise fail
4542  */
woal_11h_channel_check_ioctl(moal_private * priv,t_u8 wait_option)4543 int woal_11h_channel_check_ioctl(moal_private *priv, t_u8 wait_option)
4544 {
4545 	int ret = 0;
4546 	mlan_ioctl_req *req = NULL;
4547 	mlan_ds_11h_cfg *ds_11hcfg = NULL;
4548 	mlan_status status = MLAN_STATUS_SUCCESS;
4549 
4550 	ENTER();
4551 
4552 #ifdef UAP_SUPPORT
4553 	if (priv->skip_cac) {
4554 		LEAVE();
4555 		return ret;
4556 	}
4557 #endif
4558 
4559 	/* Skip sending request/report query when DFS_REPEATER_MODE is on. This
4560 	 * would get rid of CAC timers before starting BSSes in
4561 	 * DFS_REPEATER_MODE
4562 	 */
4563 	if (priv->phandle->dfs_repeater_mode) {
4564 		LEAVE();
4565 		return ret;
4566 	}
4567 
4568 	if (woal_is_any_interface_active(priv->phandle)) {
4569 	}
4570 
4571 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
4572 	if (req == NULL) {
4573 		ret = -ENOMEM;
4574 		goto done;
4575 	}
4576 	ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
4577 
4578 	ds_11hcfg->sub_command = MLAN_OID_11H_CHANNEL_CHECK;
4579 	ds_11hcfg->param.chan_rpt_req.host_based = MFALSE;
4580 	req->req_id = MLAN_IOCTL_11H_CFG;
4581 	req->action = MLAN_ACT_SET;
4582 	/* Send Channel Check command and wait until the report is ready */
4583 	status = woal_request_ioctl(priv, req, wait_option);
4584 	if (status != MLAN_STATUS_SUCCESS) {
4585 		goto done;
4586 	}
4587 
4588 	/* set flag from here */
4589 	priv->phandle->cac_period = MTRUE;
4590 	priv->phandle->meas_start_jiffies = jiffies;
4591 	priv->phandle->cac_timer_jiffies =
4592 		ds_11hcfg->param.chan_rpt_req.millisec_dwell_time * HZ / 1000;
4593 
4594 #ifdef UAP_SUPPORT
4595 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
4596 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
4597 	if (priv->uap_host_based &&
4598 	    moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
4599 		woal_cfg80211_dfs_vendor_event(priv, event_dfs_cac_started,
4600 					       &priv->chan);
4601 #endif
4602 #endif
4603 #endif
4604 done:
4605 	if (status != MLAN_STATUS_PENDING)
4606 		kfree(req);
4607 	LEAVE();
4608 	return ret;
4609 }
4610 
4611 /**
4612  *  @brief Issue MLAN_OID_11H_CHAN_REPORT_REQUEST ioctl to cancel dozer
4613  *
4614  *  @param priv     Pointer to the moal_private driver data struct
4615  *  @param wait_option wait option
4616  *
4617  *  @return         0 --success, otherwise fail
4618  */
woal_11h_cancel_chan_report_ioctl(moal_private * priv,t_u8 wait_option)4619 int woal_11h_cancel_chan_report_ioctl(moal_private *priv, t_u8 wait_option)
4620 {
4621 	int ret = 0;
4622 	mlan_ioctl_req *req = NULL;
4623 	mlan_ds_11h_cfg *ds_11hcfg = NULL;
4624 	mlan_status status = MLAN_STATUS_SUCCESS;
4625 
4626 	ENTER();
4627 	PRINTM(MCMND, "wlan: woal_11h_cancel_chan_report\n");
4628 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
4629 	if (req == NULL) {
4630 		ret = -ENOMEM;
4631 		goto done;
4632 	}
4633 	ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
4634 
4635 	ds_11hcfg->sub_command = MLAN_OID_11H_CHAN_REPORT_REQUEST;
4636 	req->req_id = MLAN_IOCTL_11H_CFG;
4637 	req->action = MLAN_ACT_SET;
4638 	ds_11hcfg->param.chan_rpt_req.millisec_dwell_time = 0;
4639 	/* Send Channel Check command and wait until the report is ready */
4640 	status = woal_request_ioctl(priv, req, wait_option);
4641 	if (status != MLAN_STATUS_SUCCESS) {
4642 		ret = -EFAULT;
4643 		goto done;
4644 	}
4645 
4646 done:
4647 	if (status != MLAN_STATUS_PENDING)
4648 		kfree(req);
4649 	LEAVE();
4650 	return ret;
4651 }
4652 
4653 /**
4654  *  @brief set remain channel
4655  *
4656  *  @param priv         A pointer to moal_private structure
4657  *  @param wait_option  Wait option
4658  *  @param pchan        A pointer to mlan_ds_remain_chan structure
4659  *
4660  *  @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
4661  */
woal_set_remain_channel_ioctl(moal_private * priv,t_u8 wait_option,mlan_ds_remain_chan * pchan)4662 mlan_status woal_set_remain_channel_ioctl(moal_private *priv, t_u8 wait_option,
4663 					  mlan_ds_remain_chan *pchan)
4664 {
4665 	mlan_status ret = MLAN_STATUS_SUCCESS;
4666 	mlan_ioctl_req *req = NULL;
4667 	mlan_ds_radio_cfg *radio_cfg = NULL;
4668 
4669 	ENTER();
4670 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
4671 	if (req == NULL) {
4672 		ret = MLAN_STATUS_FAILURE;
4673 		goto done;
4674 	}
4675 	radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
4676 	radio_cfg->sub_command = MLAN_OID_REMAIN_CHAN_CFG;
4677 	req->req_id = MLAN_IOCTL_RADIO_CFG;
4678 
4679 	req->action = MLAN_ACT_SET;
4680 	moal_memcpy_ext(priv->phandle, &radio_cfg->param.remain_chan, pchan,
4681 			sizeof(mlan_ds_remain_chan),
4682 			sizeof(mlan_ds_remain_chan));
4683 	ret = woal_request_ioctl(priv, req, wait_option);
4684 	if (ret == MLAN_STATUS_SUCCESS) {
4685 		moal_memcpy_ext(priv->phandle, pchan,
4686 				&radio_cfg->param.remain_chan,
4687 				sizeof(mlan_ds_remain_chan),
4688 				sizeof(mlan_ds_remain_chan));
4689 		PRINTM(MCMND,
4690 		       "Remain_chan_cfg: remove=%d, channel=%d, remain_period=%d\n",
4691 		       pchan->remove, pchan->channel, pchan->remain_period);
4692 	}
4693 done:
4694 	if (ret != MLAN_STATUS_PENDING)
4695 		kfree(req);
4696 	LEAVE();
4697 	return ret;
4698 }
4699 
4700 #ifdef WIFI_DIRECT_SUPPORT
4701 /**
4702  *  @brief set/get wifi direct mode
4703  *
4704  *  @param priv         A pointer to moal_private structure
4705  *  @param action       set or get
4706  *  @param mode         A pointer to wifi direct mode
4707  *
4708  *  @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
4709  */
woal_wifi_direct_mode_cfg(moal_private * priv,t_u16 action,t_u16 * mode)4710 mlan_status woal_wifi_direct_mode_cfg(moal_private *priv, t_u16 action,
4711 				      t_u16 *mode)
4712 {
4713 	mlan_status ret = MLAN_STATUS_SUCCESS;
4714 	mlan_ioctl_req *req = NULL;
4715 	mlan_ds_bss *bss = NULL;
4716 
4717 	ENTER();
4718 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4719 	if (req == NULL) {
4720 		ret = MLAN_STATUS_FAILURE;
4721 		goto done;
4722 	}
4723 	bss = (mlan_ds_bss *)req->pbuf;
4724 	bss->sub_command = MLAN_OID_WIFI_DIRECT_MODE;
4725 	req->req_id = MLAN_IOCTL_BSS;
4726 
4727 	req->action = action;
4728 	if (action == MLAN_ACT_SET)
4729 		bss->param.wfd_mode = *mode;
4730 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4731 	if (ret == MLAN_STATUS_SUCCESS) {
4732 		*mode = bss->param.wfd_mode;
4733 		PRINTM(MIOCTL, "ACT=%d, wifi_direct_mode=%d\n", action, *mode);
4734 	}
4735 done:
4736 	if (ret != MLAN_STATUS_PENDING)
4737 		kfree(req);
4738 	LEAVE();
4739 	return ret;
4740 }
4741 
4742 /**
4743  *  @brief Set p2p config
4744  *
4745  *  @param priv         A pointer to moal_private structure
4746  *  @param action       Action set or get
4747  *  @param p2p_config   A pointer to  mlan_ds_wifi_direct_config structure
4748  *
4749  *  @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
4750  */
woal_p2p_config(moal_private * priv,t_u32 action,mlan_ds_wifi_direct_config * p2p_config)4751 mlan_status woal_p2p_config(moal_private *priv, t_u32 action,
4752 			    mlan_ds_wifi_direct_config *p2p_config)
4753 {
4754 	mlan_status ret = MLAN_STATUS_SUCCESS;
4755 	mlan_ioctl_req *req = NULL;
4756 	mlan_ds_misc_cfg *misc_cfg = NULL;
4757 
4758 	ENTER();
4759 	if (!p2p_config) {
4760 		LEAVE();
4761 		return MLAN_STATUS_FAILURE;
4762 	}
4763 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
4764 	if (req == NULL) {
4765 		ret = MLAN_STATUS_FAILURE;
4766 		goto done;
4767 	}
4768 	misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
4769 	misc_cfg->sub_command = MLAN_OID_MISC_WIFI_DIRECT_CONFIG;
4770 	req->req_id = MLAN_IOCTL_MISC_CFG;
4771 	req->action = action;
4772 	moal_memcpy_ext(priv->phandle, &misc_cfg->param.p2p_config, p2p_config,
4773 			sizeof(mlan_ds_wifi_direct_config),
4774 			sizeof(mlan_ds_wifi_direct_config));
4775 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4776 	if (ret == MLAN_STATUS_SUCCESS) {
4777 		if (action == MLAN_ACT_GET)
4778 			moal_memcpy_ext(priv->phandle, p2p_config,
4779 					&misc_cfg->param.p2p_config,
4780 					sizeof(mlan_ds_wifi_direct_config),
4781 					sizeof(mlan_ds_wifi_direct_config));
4782 	}
4783 done:
4784 	if (ret != MLAN_STATUS_PENDING)
4785 		kfree(req);
4786 	LEAVE();
4787 	return ret;
4788 }
4789 #endif /* WIFI_DIRECT_SUPPORT */
4790 
4791 #ifdef STA_SUPPORT
4792 /**
4793  *  @brief Get STA Channel Info
4794  *
4795  *  @param priv             A pointer to moal_private structure
4796  *  @param wait_option      Wait option
4797  *  @param channel          A pointer to channel info
4798  *
4799  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
4800  * success, otherwise fail
4801  */
woal_get_sta_channel(moal_private * priv,t_u8 wait_option,chan_band_info * channel)4802 mlan_status woal_get_sta_channel(moal_private *priv, t_u8 wait_option,
4803 				 chan_band_info *channel)
4804 {
4805 	mlan_ioctl_req *req = NULL;
4806 	mlan_ds_bss *bss = NULL;
4807 	mlan_status status = MLAN_STATUS_SUCCESS;
4808 	ENTER();
4809 
4810 	/* Allocate an IOCTL request buffer */
4811 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4812 	if (req == NULL) {
4813 		PRINTM(MERROR, "woal_get_sta_channel req alloc fail\n");
4814 		status = MLAN_STATUS_FAILURE;
4815 		goto done;
4816 	}
4817 
4818 	/* Fill request buffer */
4819 	bss = (mlan_ds_bss *)req->pbuf;
4820 	bss->sub_command = MLAN_OID_BSS_CHAN_INFO;
4821 	req->req_id = MLAN_IOCTL_BSS;
4822 	req->action = MLAN_ACT_GET;
4823 
4824 	/* Send IOCTL request to MLAN */
4825 	status = woal_request_ioctl(priv, req, wait_option);
4826 	if (status == MLAN_STATUS_SUCCESS && channel)
4827 		moal_memcpy_ext(priv->phandle, channel,
4828 				&(bss->param.sta_channel),
4829 				sizeof(chan_band_info), sizeof(chan_band_info));
4830 
4831 done:
4832 	if (status != MLAN_STATUS_PENDING)
4833 		kfree(req);
4834 	LEAVE();
4835 	return status;
4836 }
4837 
4838 /**
4839  *  @brief Get RSSI info
4840  *
4841  *  @param priv         A pointer to moal_private structure
4842  *  @param wait_option  Wait option
4843  *  @param signal       A pointer tp mlan_ds_get_signal structure
4844  *
4845  *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
4846  * otherwise fail
4847  */
woal_get_signal_info(moal_private * priv,t_u8 wait_option,mlan_ds_get_signal * signal)4848 mlan_status woal_get_signal_info(moal_private *priv, t_u8 wait_option,
4849 				 mlan_ds_get_signal *signal)
4850 {
4851 	mlan_ds_get_info *info = NULL;
4852 	mlan_ioctl_req *req = NULL;
4853 	mlan_status status = MLAN_STATUS_SUCCESS;
4854 
4855 	ENTER();
4856 
4857 	/* Allocate an IOCTL request buffer */
4858 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
4859 	if (req == NULL) {
4860 		status = MLAN_STATUS_FAILURE;
4861 		goto done;
4862 	}
4863 
4864 	/* Fill request buffer */
4865 	info = (mlan_ds_get_info *)req->pbuf;
4866 	info->sub_command = MLAN_OID_GET_SIGNAL;
4867 	info->param.signal.selector = ALL_RSSI_INFO_MASK;
4868 	req->req_id = MLAN_IOCTL_GET_INFO;
4869 	req->action = MLAN_ACT_GET;
4870 
4871 	/* Send IOCTL request to MLAN */
4872 	status = woal_request_ioctl(priv, req, wait_option);
4873 	if (status == MLAN_STATUS_SUCCESS) {
4874 		if (signal)
4875 			moal_memcpy_ext(priv->phandle, signal,
4876 					&info->param.signal,
4877 					sizeof(mlan_ds_get_signal),
4878 					sizeof(mlan_ds_get_signal));
4879 #ifdef STA_WEXT
4880 		if (IS_STA_WEXT(priv->phandle->params.cfg80211_wext)) {
4881 			if (info->param.signal.selector & BCN_RSSI_AVG_MASK)
4882 				priv->w_stats.qual.level =
4883 					info->param.signal.bcn_rssi_avg;
4884 			if (info->param.signal.selector & BCN_NF_AVG_MASK)
4885 				priv->w_stats.qual.noise =
4886 					info->param.signal.bcn_nf_avg;
4887 		}
4888 #endif
4889 	}
4890 done:
4891 	if (status != MLAN_STATUS_PENDING)
4892 		kfree(req);
4893 	LEAVE();
4894 	return status;
4895 }
4896 
4897 /**
4898  *  @brief Get scan table
4899  *
4900  *  @param priv         A pointer to moal_private structure
4901  *  @param wait_option  Wait option
4902  *  @param scan_resp    A pointer to mlan_scan_resp structure
4903  *
4904  *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
4905  * otherwise fail
4906  */
woal_get_scan_table(moal_private * priv,t_u8 wait_option,mlan_scan_resp * scan_resp)4907 mlan_status woal_get_scan_table(moal_private *priv, t_u8 wait_option,
4908 				mlan_scan_resp *scan_resp)
4909 {
4910 	mlan_ioctl_req *req = NULL;
4911 	mlan_ds_scan *scan = NULL;
4912 	mlan_status status = MLAN_STATUS_SUCCESS;
4913 	ENTER();
4914 
4915 	if (!scan_resp) {
4916 		LEAVE();
4917 		return MLAN_STATUS_FAILURE;
4918 	}
4919 
4920 	/* Allocate an IOCTL request buffer */
4921 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
4922 	if (req == NULL) {
4923 		status = MLAN_STATUS_FAILURE;
4924 		goto done;
4925 	}
4926 
4927 	/* Fill request buffer */
4928 	scan = (mlan_ds_scan *)req->pbuf;
4929 	scan->sub_command = MLAN_OID_SCAN_NORMAL;
4930 	req->req_id = MLAN_IOCTL_SCAN;
4931 	req->action = MLAN_ACT_GET;
4932 	moal_memcpy_ext(priv->phandle, (void *)&scan->param.scan_resp,
4933 			(void *)scan_resp, sizeof(mlan_scan_resp),
4934 			sizeof(mlan_scan_resp));
4935 
4936 	/* Send IOCTL request to MLAN */
4937 	status = woal_request_ioctl(priv, req, wait_option);
4938 	if (status == MLAN_STATUS_SUCCESS) {
4939 		if (scan_resp) {
4940 			moal_memcpy_ext(priv->phandle, scan_resp,
4941 					&scan->param.scan_resp,
4942 					sizeof(mlan_scan_resp),
4943 					sizeof(mlan_scan_resp));
4944 		}
4945 	}
4946 
4947 done:
4948 	if (status != MLAN_STATUS_PENDING)
4949 		kfree(req);
4950 	LEAVE();
4951 	return status;
4952 }
4953 
4954 /**
4955  *  @brief Request a scan
4956  *
4957  *  @param priv                 A pointer to moal_private structure
4958  *  @param wait_option          Wait option
4959  *  @param req_ssid             A pointer to mlan_802_11_ssid structure
4960  *
4961  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
4962  */
woal_request_scan(moal_private * priv,t_u8 wait_option,mlan_802_11_ssid * req_ssid)4963 mlan_status woal_request_scan(moal_private *priv, t_u8 wait_option,
4964 			      mlan_802_11_ssid *req_ssid)
4965 {
4966 	mlan_status ret = MLAN_STATUS_SUCCESS;
4967 	moal_handle *handle = priv->phandle;
4968 	mlan_ioctl_req *ioctl_req = NULL;
4969 	mlan_ds_scan *scan = NULL;
4970 	mlan_status status = MLAN_STATUS_SUCCESS;
4971 	ENTER();
4972 
4973 	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->async_sem)) {
4974 		PRINTM(MERROR, "Acquire semaphore error, request_scan\n");
4975 		LEAVE();
4976 		return MLAN_STATUS_FAILURE;
4977 	}
4978 	handle->scan_pending_on_block = MTRUE;
4979 	handle->scan_priv = priv;
4980 
4981 	/* Allocate an IOCTL request buffer */
4982 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
4983 	if (ioctl_req == NULL) {
4984 		ret = MLAN_STATUS_FAILURE;
4985 		goto done;
4986 	}
4987 
4988 	scan = (mlan_ds_scan *)ioctl_req->pbuf;
4989 
4990 	if (req_ssid && req_ssid->ssid_len != 0) {
4991 		/* Specific SSID scan */
4992 		ioctl_req->req_id = MLAN_IOCTL_SCAN;
4993 		ioctl_req->action = MLAN_ACT_SET;
4994 
4995 		scan->sub_command = MLAN_OID_SCAN_SPECIFIC_SSID;
4996 
4997 		moal_memcpy_ext(handle, scan->param.scan_req.scan_ssid.ssid,
4998 				req_ssid->ssid, req_ssid->ssid_len,
4999 				MLAN_MAX_SSID_LENGTH);
5000 		scan->param.scan_req.scan_ssid.ssid_len =
5001 			MIN(MLAN_MAX_SSID_LENGTH, req_ssid->ssid_len);
5002 	} else {
5003 		/* Normal scan */
5004 		ioctl_req->req_id = MLAN_IOCTL_SCAN;
5005 		ioctl_req->action = MLAN_ACT_SET;
5006 
5007 		scan->sub_command = MLAN_OID_SCAN_NORMAL;
5008 	}
5009 	/* Send IOCTL request to MLAN */
5010 	status = woal_request_ioctl(priv, ioctl_req, wait_option);
5011 
5012 	if (status == MLAN_STATUS_FAILURE) {
5013 		ret = MLAN_STATUS_FAILURE;
5014 		goto done;
5015 	}
5016 done:
5017 	if (status != MLAN_STATUS_PENDING)
5018 		kfree(ioctl_req);
5019 
5020 	if (ret == MLAN_STATUS_FAILURE) {
5021 		handle->scan_pending_on_block = MFALSE;
5022 		handle->scan_priv = NULL;
5023 		MOAL_REL_SEMAPHORE(&handle->async_sem);
5024 	}
5025 	LEAVE();
5026 	return ret;
5027 }
5028 
5029 /**
5030  *  @brief Change Adhoc Channel
5031  *
5032  *  @param priv         A pointer to moal_private structure
5033  *  @param channel      The channel to be set.
5034  *  @param wait_option  wait_option
5035  *
5036  *  @return             MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail
5037  */
woal_change_adhoc_chan(moal_private * priv,int channel,t_u8 wait_option)5038 mlan_status woal_change_adhoc_chan(moal_private *priv, int channel,
5039 				   t_u8 wait_option)
5040 {
5041 	mlan_status ret = MLAN_STATUS_SUCCESS;
5042 	mlan_bss_info bss_info;
5043 	mlan_ds_bss *bss = NULL;
5044 	mlan_ioctl_req *req = NULL;
5045 
5046 	ENTER();
5047 
5048 	memset(&bss_info, 0, sizeof(bss_info));
5049 
5050 	/* Get BSS information */
5051 	if (MLAN_STATUS_SUCCESS !=
5052 	    woal_get_bss_info(priv, wait_option, &bss_info)) {
5053 		ret = MLAN_STATUS_FAILURE;
5054 		goto done;
5055 	}
5056 	if (bss_info.bss_mode == MLAN_BSS_MODE_INFRA) {
5057 		ret = MLAN_STATUS_SUCCESS;
5058 		goto done;
5059 	}
5060 
5061 	/* Allocate an IOCTL request buffer */
5062 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
5063 	if (req == NULL) {
5064 		ret = MLAN_STATUS_FAILURE;
5065 		goto done;
5066 	}
5067 
5068 	/* Get current channel */
5069 	bss = (mlan_ds_bss *)req->pbuf;
5070 	bss->sub_command = MLAN_OID_IBSS_CHANNEL;
5071 	req->req_id = MLAN_IOCTL_BSS;
5072 	req->action = MLAN_ACT_GET;
5073 
5074 	/* Send IOCTL request to MLAN */
5075 	ret = woal_request_ioctl(priv, req, wait_option);
5076 	if (ret != MLAN_STATUS_SUCCESS)
5077 		goto done;
5078 
5079 	if (bss->param.bss_chan.channel == (unsigned int)channel) {
5080 		ret = MLAN_STATUS_SUCCESS;
5081 		goto done;
5082 	}
5083 	PRINTM(MINFO, "Updating Channel from %d to %d\n",
5084 	       (int)bss->param.bss_chan.channel, channel);
5085 
5086 	if (bss_info.media_connected != MTRUE) {
5087 		ret = MLAN_STATUS_SUCCESS;
5088 		goto done;
5089 	}
5090 
5091 	/* Do disonnect*/
5092 	bss->sub_command = MLAN_OID_BSS_STOP;
5093 	memset((t_u8 *)&bss->param.bssid, 0, ETH_ALEN);
5094 
5095 	/* Send IOCTL request to MLAN */
5096 	ret = woal_request_ioctl(priv, req, wait_option);
5097 	if (ret != MLAN_STATUS_SUCCESS)
5098 		goto done;
5099 
5100 	/* Do specific SSID scanning */
5101 	if (MLAN_STATUS_SUCCESS !=
5102 	    woal_request_scan(priv, wait_option, &bss_info.ssid)) {
5103 		ret = MLAN_STATUS_FAILURE;
5104 		goto done;
5105 	}
5106 	/* Start/Join Adhoc network */
5107 	bss->sub_command = MLAN_OID_BSS_START;
5108 	memset(&bss->param.ssid_bssid, 0, sizeof(mlan_ssid_bssid));
5109 	moal_memcpy_ext(priv->phandle, &bss->param.ssid_bssid.ssid,
5110 			&bss_info.ssid, sizeof(mlan_802_11_ssid),
5111 			sizeof(mlan_802_11_ssid));
5112 
5113 	/* Send IOCTL request to MLAN */
5114 	ret = woal_request_ioctl(priv, req, wait_option);
5115 
5116 done:
5117 	if (ret != MLAN_STATUS_PENDING)
5118 		kfree(req);
5119 	LEAVE();
5120 	return ret;
5121 }
5122 
5123 /**
5124  *  @brief Find the best network to associate
5125  *
5126  *  @param priv             A pointer to moal_private structure
5127  *  @param wait_option      Wait option
5128  *  @param ssid_bssid       A pointer to mlan_ssid_bssid structure
5129  *
5130  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5131  * success, otherwise fail
5132  */
woal_find_best_network(moal_private * priv,t_u8 wait_option,mlan_ssid_bssid * ssid_bssid)5133 mlan_status woal_find_best_network(moal_private *priv, t_u8 wait_option,
5134 				   mlan_ssid_bssid *ssid_bssid)
5135 {
5136 	mlan_ioctl_req *req = NULL;
5137 	mlan_ds_bss *bss = NULL;
5138 	mlan_status ret = MLAN_STATUS_SUCCESS;
5139 
5140 	ENTER();
5141 
5142 	if (!ssid_bssid) {
5143 		ret = MLAN_STATUS_FAILURE;
5144 		goto done;
5145 	}
5146 
5147 	/* Allocate an IOCTL request buffer */
5148 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
5149 	if (req == NULL) {
5150 		ret = MLAN_STATUS_FAILURE;
5151 		goto done;
5152 	}
5153 
5154 	/* Fill request buffer */
5155 	bss = (mlan_ds_bss *)req->pbuf;
5156 	req->req_id = MLAN_IOCTL_BSS;
5157 	req->action = MLAN_ACT_GET;
5158 	bss->sub_command = MLAN_OID_BSS_FIND_BSS;
5159 
5160 	moal_memcpy_ext(priv->phandle, &bss->param.ssid_bssid, ssid_bssid,
5161 			sizeof(mlan_ssid_bssid), sizeof(mlan_ssid_bssid));
5162 
5163 	/* Send IOCTL request to MLAN */
5164 	ret = woal_request_ioctl(priv, req, wait_option);
5165 	if (ret == MLAN_STATUS_SUCCESS) {
5166 		moal_memcpy_ext(priv->phandle, ssid_bssid,
5167 				&bss->param.ssid_bssid, sizeof(mlan_ssid_bssid),
5168 				sizeof(mlan_ssid_bssid));
5169 		PRINTM(MINFO, "Find network: ssid=%s, " MACSTR ", idx=%d\n",
5170 		       ssid_bssid->ssid.ssid,
5171 		       MAC2STR((t_u8 *)&ssid_bssid->bssid),
5172 		       (int)ssid_bssid->idx);
5173 	}
5174 
5175 done:
5176 	if (ret != MLAN_STATUS_PENDING)
5177 		kfree(req);
5178 	LEAVE();
5179 	return ret;
5180 }
5181 
5182 /**
5183  *  @brief Find the best network to associate
5184  *
5185  *  @param priv             A pointer to moal_private structure
5186  *  @param bssid       		A pointer to bssid
5187  *
5188  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5189  * success, otherwise fail
5190  */
woal_find_bssid(moal_private * priv,mlan_802_11_mac_addr bssid)5191 mlan_status woal_find_bssid(moal_private *priv, mlan_802_11_mac_addr bssid)
5192 {
5193 	mlan_ioctl_req *req = NULL;
5194 	mlan_ds_bss *bss = NULL;
5195 	mlan_status ret = MLAN_STATUS_SUCCESS;
5196 
5197 	ENTER();
5198 	/* Allocate an IOCTL request buffer */
5199 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
5200 	if (req == NULL) {
5201 		ret = MLAN_STATUS_FAILURE;
5202 		goto done;
5203 	}
5204 
5205 	/* Fill request buffer */
5206 	bss = (mlan_ds_bss *)req->pbuf;
5207 	req->req_id = MLAN_IOCTL_BSS;
5208 	req->action = MLAN_ACT_GET;
5209 	bss->sub_command = MLAN_OID_BSS_FIND_BSSID;
5210 
5211 	moal_memcpy_ext(priv->phandle, &bss->param.bssid, bssid,
5212 			sizeof(mlan_802_11_mac_addr),
5213 			sizeof(mlan_802_11_mac_addr));
5214 
5215 	/* Send IOCTL request to MLAN */
5216 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5217 done:
5218 	if (ret != MLAN_STATUS_PENDING)
5219 		kfree(req);
5220 	LEAVE();
5221 	return ret;
5222 }
5223 
5224 /**
5225  *  @brief Check if AP channel is valid for STA Region
5226  *
5227  *  @param priv             A pointer to moal_private structure
5228  *  @param wait_option      Wait option
5229  *  @param ssid_bssid       A pointer to mlan_ssid_bssid structure
5230  *
5231  *  @return                 MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
5232  * otherwise fail
5233  */
woal_11d_check_ap_channel(moal_private * priv,t_u8 wait_option,mlan_ssid_bssid * ssid_bssid)5234 mlan_status woal_11d_check_ap_channel(moal_private *priv, t_u8 wait_option,
5235 				      mlan_ssid_bssid *ssid_bssid)
5236 {
5237 	mlan_ioctl_req *req = NULL;
5238 	mlan_ds_bss *bss = NULL;
5239 	mlan_status ret = MLAN_STATUS_SUCCESS;
5240 
5241 	ENTER();
5242 
5243 	if (!ssid_bssid) {
5244 		ret = MLAN_STATUS_FAILURE;
5245 		goto done;
5246 	}
5247 
5248 	/* Allocate an IOCTL request buffer */
5249 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
5250 	if (req == NULL) {
5251 		ret = MLAN_STATUS_FAILURE;
5252 		goto done;
5253 	}
5254 
5255 	/* Fill request buffer */
5256 	bss = (mlan_ds_bss *)req->pbuf;
5257 	req->req_id = MLAN_IOCTL_BSS;
5258 	req->action = MLAN_ACT_GET;
5259 	bss->sub_command = MLAN_OID_BSS_11D_CHECK_CHANNEL;
5260 
5261 	moal_memcpy_ext(priv->phandle, &bss->param.ssid_bssid, ssid_bssid,
5262 			sizeof(mlan_ssid_bssid), sizeof(mlan_ssid_bssid));
5263 
5264 	PRINTM(MINFO, "ssid=%s, " MACSTR ", idx=%d\n", ssid_bssid->ssid.ssid,
5265 	       MAC2STR((t_u8 *)&ssid_bssid->bssid), (int)ssid_bssid->idx);
5266 
5267 	/* Send IOCTL request to MLAN */
5268 	ret = woal_request_ioctl(priv, req, wait_option);
5269 
5270 done:
5271 	if (ret != MLAN_STATUS_PENDING)
5272 		kfree(req);
5273 	LEAVE();
5274 	return ret;
5275 }
5276 
5277 /**
5278  *  @brief Get authentication mode
5279  *
5280  *  @param priv             A pointer to moal_private structure
5281  *  @param wait_option      Wait option
5282  *  @param auth_mode        A pointer to authentication mode
5283  *
5284  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5285  * success, otherwise fail
5286  */
woal_get_auth_mode(moal_private * priv,t_u8 wait_option,t_u32 * auth_mode)5287 mlan_status woal_get_auth_mode(moal_private *priv, t_u8 wait_option,
5288 			       t_u32 *auth_mode)
5289 {
5290 	mlan_ioctl_req *req = NULL;
5291 	mlan_ds_sec_cfg *sec = NULL;
5292 	mlan_status status = MLAN_STATUS_SUCCESS;
5293 	ENTER();
5294 
5295 	/* Allocate an IOCTL request buffer */
5296 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
5297 	if (req == NULL) {
5298 		status = MLAN_STATUS_FAILURE;
5299 		goto done;
5300 	}
5301 
5302 	/* Fill request buffer */
5303 	sec = (mlan_ds_sec_cfg *)req->pbuf;
5304 	sec->sub_command = MLAN_OID_SEC_CFG_AUTH_MODE;
5305 	req->req_id = MLAN_IOCTL_SEC_CFG;
5306 	req->action = MLAN_ACT_GET;
5307 
5308 	/* Send IOCTL request to MLAN */
5309 	status = woal_request_ioctl(priv, req, wait_option);
5310 	if (status == MLAN_STATUS_SUCCESS && auth_mode)
5311 		*auth_mode = sec->param.auth_mode;
5312 done:
5313 	if (status != MLAN_STATUS_PENDING)
5314 		kfree(req);
5315 	LEAVE();
5316 	return status;
5317 }
5318 
5319 /**
5320  *  @brief Get encrypt mode
5321  *
5322  *  @param priv                 A pointer to moal_private structure
5323  *  @param wait_option          Wait option
5324  *  @param encrypt_mode         A pointer to encrypt mode
5325  *
5326  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5327  * success, otherwise fail
5328  */
woal_get_encrypt_mode(moal_private * priv,t_u8 wait_option,t_u32 * encrypt_mode)5329 mlan_status woal_get_encrypt_mode(moal_private *priv, t_u8 wait_option,
5330 				  t_u32 *encrypt_mode)
5331 {
5332 	mlan_ioctl_req *req = NULL;
5333 	mlan_ds_sec_cfg *sec = NULL;
5334 	mlan_status status = MLAN_STATUS_SUCCESS;
5335 
5336 	ENTER();
5337 
5338 	/* Allocate an IOCTL request buffer */
5339 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
5340 	if (req == NULL) {
5341 		status = MLAN_STATUS_FAILURE;
5342 		goto done;
5343 	}
5344 
5345 	/* Fill request buffer */
5346 	sec = (mlan_ds_sec_cfg *)req->pbuf;
5347 	sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_MODE;
5348 	req->req_id = MLAN_IOCTL_SEC_CFG;
5349 	req->action = MLAN_ACT_GET;
5350 
5351 	/* Send IOCTL request to MLAN */
5352 	status = woal_request_ioctl(priv, req, wait_option);
5353 	if (status == MLAN_STATUS_SUCCESS && encrypt_mode)
5354 		*encrypt_mode = sec->param.encrypt_mode;
5355 done:
5356 	if (status != MLAN_STATUS_PENDING)
5357 		kfree(req);
5358 	LEAVE();
5359 	return status;
5360 }
5361 
5362 /**
5363  *  @brief Get WPA enable
5364  *
5365  *  @param priv             A pointer to moal_private structure
5366  *  @param wait_option      Wait option
5367  *  @param enable           A pointer to wpa enable status
5368  *
5369  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5370  * success, otherwise fail
5371  */
woal_get_wpa_enable(moal_private * priv,t_u8 wait_option,t_u32 * enable)5372 mlan_status woal_get_wpa_enable(moal_private *priv, t_u8 wait_option,
5373 				t_u32 *enable)
5374 {
5375 	mlan_ioctl_req *req = NULL;
5376 	mlan_ds_sec_cfg *sec = NULL;
5377 	mlan_status status = MLAN_STATUS_SUCCESS;
5378 
5379 	ENTER();
5380 
5381 	/* Allocate an IOCTL request buffer */
5382 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
5383 	if (req == NULL) {
5384 		status = MLAN_STATUS_FAILURE;
5385 		goto done;
5386 	}
5387 
5388 	/* Fill request buffer */
5389 	sec = (mlan_ds_sec_cfg *)req->pbuf;
5390 	sec->sub_command = MLAN_OID_SEC_CFG_WPA_ENABLED;
5391 	req->req_id = MLAN_IOCTL_SEC_CFG;
5392 	req->action = MLAN_ACT_GET;
5393 
5394 	/* Send IOCTL request to MLAN */
5395 	status = woal_request_ioctl(priv, req, wait_option);
5396 	if (status == MLAN_STATUS_SUCCESS && enable)
5397 		*enable = sec->param.wpa_enabled;
5398 done:
5399 	if (status != MLAN_STATUS_PENDING)
5400 		kfree(req);
5401 	LEAVE();
5402 	return status;
5403 }
5404 
5405 /**
5406  *  @brief Set authentication mode
5407  *
5408  *  @param priv             A pointer to moal_private structure
5409  *  @param wait_option      Wait option
5410  *  @param auth_mode        Authentication mode
5411  *
5412  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5413  * success, otherwise fail
5414  */
woal_set_auth_mode(moal_private * priv,t_u8 wait_option,t_u32 auth_mode)5415 mlan_status woal_set_auth_mode(moal_private *priv, t_u8 wait_option,
5416 			       t_u32 auth_mode)
5417 {
5418 	mlan_ioctl_req *req = NULL;
5419 	mlan_ds_sec_cfg *sec = NULL;
5420 	mlan_status status = MLAN_STATUS_SUCCESS;
5421 	ENTER();
5422 
5423 	/* Allocate an IOCTL request buffer */
5424 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
5425 	if (req == NULL) {
5426 		status = MLAN_STATUS_FAILURE;
5427 		goto done;
5428 	}
5429 
5430 	/* Fill request buffer */
5431 	sec = (mlan_ds_sec_cfg *)req->pbuf;
5432 	sec->sub_command = MLAN_OID_SEC_CFG_AUTH_MODE;
5433 	req->req_id = MLAN_IOCTL_SEC_CFG;
5434 	req->action = MLAN_ACT_SET;
5435 	sec->param.auth_mode = auth_mode;
5436 
5437 	/* Send IOCTL request to MLAN */
5438 	status = woal_request_ioctl(priv, req, wait_option);
5439 done:
5440 	if (status != MLAN_STATUS_PENDING)
5441 		kfree(req);
5442 	LEAVE();
5443 	return status;
5444 }
5445 
5446 /**
5447  *  @brief Set encrypt mode
5448  *
5449  *  @param priv                 A pointer to moal_private structure
5450  *  @param wait_option          Wait option
5451  *  @param encrypt_mode         Encryption mode
5452  *
5453  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5454  * success, otherwise fail
5455  */
woal_set_encrypt_mode(moal_private * priv,t_u8 wait_option,t_u32 encrypt_mode)5456 mlan_status woal_set_encrypt_mode(moal_private *priv, t_u8 wait_option,
5457 				  t_u32 encrypt_mode)
5458 {
5459 	mlan_ioctl_req *req = NULL;
5460 	mlan_ds_sec_cfg *sec = NULL;
5461 	mlan_status status = MLAN_STATUS_SUCCESS;
5462 	ENTER();
5463 
5464 	/* Allocate an IOCTL request buffer */
5465 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
5466 	if (req == NULL) {
5467 		status = MLAN_STATUS_FAILURE;
5468 		goto done;
5469 	}
5470 
5471 	/* Fill request buffer */
5472 	sec = (mlan_ds_sec_cfg *)req->pbuf;
5473 	sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_MODE;
5474 	req->req_id = MLAN_IOCTL_SEC_CFG;
5475 	req->action = MLAN_ACT_SET;
5476 	sec->param.encrypt_mode = encrypt_mode;
5477 
5478 	/* Send IOCTL request to MLAN */
5479 	status = woal_request_ioctl(priv, req, wait_option);
5480 done:
5481 	if (status != MLAN_STATUS_PENDING)
5482 		kfree(req);
5483 	LEAVE();
5484 	return status;
5485 }
5486 
5487 /**
5488  *  @brief Set wpa enable
5489  *
5490  *  @param priv                 A pointer to moal_private structure
5491  *  @param wait_option          Wait option
5492  *  @param enable               MTRUE or MFALSE
5493  *
5494  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5495  * success, otherwise fail
5496  */
woal_set_wpa_enable(moal_private * priv,t_u8 wait_option,t_u32 enable)5497 mlan_status woal_set_wpa_enable(moal_private *priv, t_u8 wait_option,
5498 				t_u32 enable)
5499 {
5500 	mlan_ioctl_req *req = NULL;
5501 	mlan_ds_sec_cfg *sec = NULL;
5502 	mlan_status status = MLAN_STATUS_SUCCESS;
5503 	ENTER();
5504 
5505 	/* Allocate an IOCTL request buffer */
5506 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
5507 	if (req == NULL) {
5508 		status = MLAN_STATUS_FAILURE;
5509 		goto done;
5510 	}
5511 
5512 	/* Fill request buffer */
5513 	sec = (mlan_ds_sec_cfg *)req->pbuf;
5514 	sec->sub_command = MLAN_OID_SEC_CFG_WPA_ENABLED;
5515 	req->req_id = MLAN_IOCTL_SEC_CFG;
5516 	req->action = MLAN_ACT_SET;
5517 	sec->param.wpa_enabled = enable;
5518 
5519 	/* Send IOCTL request to MLAN */
5520 	status = woal_request_ioctl(priv, req, wait_option);
5521 done:
5522 	if (status != MLAN_STATUS_PENDING)
5523 		kfree(req);
5524 	LEAVE();
5525 	return status;
5526 }
5527 
5528 /**
5529  *  @brief enable wep key
5530  *
5531  *  @param priv                 A pointer to moal_private structure
5532  *  @param wait_option          Wait option
5533  *
5534  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --
5535  * success, otherwise fail
5536  */
woal_enable_wep_key(moal_private * priv,t_u8 wait_option)5537 mlan_status woal_enable_wep_key(moal_private *priv, t_u8 wait_option)
5538 {
5539 	mlan_ioctl_req *req = NULL;
5540 	mlan_ds_sec_cfg *sec = NULL;
5541 	mlan_status status = MLAN_STATUS_SUCCESS;
5542 	ENTER();
5543 
5544 	/* Allocate an IOCTL request buffer */
5545 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
5546 	if (req == NULL) {
5547 		status = MLAN_STATUS_FAILURE;
5548 		goto done;
5549 	}
5550 
5551 	/* Fill request buffer */
5552 	sec = (mlan_ds_sec_cfg *)req->pbuf;
5553 	sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
5554 	req->req_id = MLAN_IOCTL_SEC_CFG;
5555 	req->action = MLAN_ACT_SET;
5556 	sec->param.encrypt_key.key_disable = MFALSE;
5557 	sec->param.encrypt_key.key_index = MLAN_KEY_INDEX_DEFAULT;
5558 	sec->param.encrypt_key.is_current_wep_key = MTRUE;
5559 
5560 	/* Send IOCTL request to MLAN */
5561 	status = woal_request_ioctl(priv, req, wait_option);
5562 done:
5563 	if (status != MLAN_STATUS_PENDING)
5564 		kfree(req);
5565 	LEAVE();
5566 	return status;
5567 }
5568 
5569 /**
5570  *  @brief Request user scan
5571  *
5572  *  @param priv                 A pointer to moal_private structure
5573  *  @param wait_option          Wait option
5574  *  @param scan_cfg             A pointer to wlan_user_scan_config structure
5575  *
5576  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5577  */
woal_request_userscan(moal_private * priv,t_u8 wait_option,wlan_user_scan_cfg * scan_cfg)5578 mlan_status woal_request_userscan(moal_private *priv, t_u8 wait_option,
5579 				  wlan_user_scan_cfg *scan_cfg)
5580 {
5581 	mlan_status ret = MLAN_STATUS_SUCCESS;
5582 	mlan_ioctl_req *ioctl_req = NULL;
5583 	mlan_ds_scan *scan = NULL;
5584 	mlan_status status = MLAN_STATUS_SUCCESS;
5585 	moal_handle *handle = priv->phandle;
5586 	ENTER();
5587 
5588 	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->async_sem)) {
5589 		PRINTM(MERROR, "Acquire semaphore error, request_scan\n");
5590 		LEAVE();
5591 		return MLAN_STATUS_FAILURE;
5592 	}
5593 	handle->scan_pending_on_block = MTRUE;
5594 	handle->scan_priv = priv;
5595 
5596 	/* Allocate an IOCTL request buffer */
5597 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan) +
5598 					      sizeof(wlan_user_scan_cfg));
5599 	if (ioctl_req == NULL) {
5600 		ret = MLAN_STATUS_FAILURE;
5601 		goto done;
5602 	}
5603 
5604 	scan = (mlan_ds_scan *)ioctl_req->pbuf;
5605 	scan->sub_command = MLAN_OID_SCAN_USER_CONFIG;
5606 	ioctl_req->req_id = MLAN_IOCTL_SCAN;
5607 	ioctl_req->action = MLAN_ACT_SET;
5608 	moal_memcpy_ext(handle, scan->param.user_scan.scan_cfg_buf, scan_cfg,
5609 			sizeof(wlan_user_scan_cfg), sizeof(wlan_user_scan_cfg));
5610 	/* Send IOCTL request to MLAN */
5611 	status = woal_request_ioctl(priv, ioctl_req, wait_option);
5612 	if (status == MLAN_STATUS_FAILURE) {
5613 		ret = MLAN_STATUS_FAILURE;
5614 		goto done;
5615 	}
5616 
5617 done:
5618 	if (status != MLAN_STATUS_PENDING)
5619 		kfree(ioctl_req);
5620 	else if (wait_option != MOAL_NO_WAIT) {
5621 		PRINTM(MMSG, "scan interrupted by Signal, Cancel it...");
5622 		woal_cancel_scan(priv, MOAL_IOCTL_WAIT_TIMEOUT);
5623 	}
5624 	if (ret == MLAN_STATUS_FAILURE) {
5625 		handle->scan_pending_on_block = MFALSE;
5626 		handle->scan_priv = NULL;
5627 		MOAL_REL_SEMAPHORE(&handle->async_sem);
5628 	}
5629 	LEAVE();
5630 	return ret;
5631 }
5632 
5633 /**
5634  *  @brief woal_get_scan_config
5635  *
5636  *  @param priv                 A pointer to moal_private structure
5637  *  @param scan_cfg             A pointer to scan_cfg structure
5638  *
5639  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5640  */
woal_get_scan_config(moal_private * priv,mlan_scan_cfg * scan_cfg)5641 mlan_status woal_get_scan_config(moal_private *priv, mlan_scan_cfg *scan_cfg)
5642 {
5643 	mlan_status ret = MLAN_STATUS_SUCCESS;
5644 	mlan_ds_scan *scan = NULL;
5645 	mlan_ioctl_req *req = NULL;
5646 
5647 	ENTER();
5648 
5649 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
5650 	if (req == NULL) {
5651 		ret = MLAN_STATUS_FAILURE;
5652 		goto done;
5653 	}
5654 	scan = (mlan_ds_scan *)req->pbuf;
5655 	scan->sub_command = MLAN_OID_SCAN_CONFIG;
5656 	req->req_id = MLAN_IOCTL_SCAN;
5657 	req->action = MLAN_ACT_GET;
5658 	memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
5659 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5660 	if (ret == MLAN_STATUS_SUCCESS && scan_cfg)
5661 		moal_memcpy_ext(priv->phandle, scan_cfg, &scan->param.scan_cfg,
5662 				sizeof(mlan_scan_cfg), sizeof(mlan_scan_cfg));
5663 
5664 done:
5665 	if (ret != MLAN_STATUS_PENDING)
5666 		kfree(req);
5667 	LEAVE();
5668 	return ret;
5669 }
5670 
5671 /**
5672  *  @brief set scan time
5673  *
5674  *  @param priv                 A pointer to moal_private structure
5675  *  @param active_scan_time     Active scan time
5676  *  @param passive_scan_time    Passive scan time
5677  *  @param specific_scan_time   Specific scan time
5678  *
5679  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5680  */
woal_set_scan_time(moal_private * priv,t_u16 active_scan_time,t_u16 passive_scan_time,t_u16 specific_scan_time)5681 mlan_status woal_set_scan_time(moal_private *priv, t_u16 active_scan_time,
5682 			       t_u16 passive_scan_time,
5683 			       t_u16 specific_scan_time)
5684 {
5685 	mlan_status ret = MLAN_STATUS_SUCCESS;
5686 	mlan_ds_scan *scan = NULL;
5687 	mlan_ioctl_req *req = NULL;
5688 	mlan_scan_cfg scan_cfg;
5689 
5690 	ENTER();
5691 
5692 	memset(&scan_cfg, 0, sizeof(scan_cfg));
5693 	if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) {
5694 		ret = MLAN_STATUS_FAILURE;
5695 		goto done;
5696 	}
5697 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
5698 	if (req == NULL) {
5699 		ret = MLAN_STATUS_FAILURE;
5700 		goto done;
5701 	}
5702 	scan = (mlan_ds_scan *)req->pbuf;
5703 	scan->sub_command = MLAN_OID_SCAN_CONFIG;
5704 	req->req_id = MLAN_IOCTL_SCAN;
5705 	req->action = MLAN_ACT_SET;
5706 	memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
5707 	scan_cfg.scan_time.active_scan_time = active_scan_time;
5708 	scan_cfg.scan_time.specific_scan_time = specific_scan_time;
5709 	scan_cfg.scan_time.passive_scan_time = passive_scan_time;
5710 	PRINTM(MIOCTL, "Set specific=%d, active=%d, passive=%d\n",
5711 	       (int)active_scan_time, (int)passive_scan_time,
5712 	       (int)specific_scan_time);
5713 	moal_memcpy_ext(priv->phandle, &scan->param.scan_cfg, &scan_cfg,
5714 			sizeof(mlan_scan_cfg), sizeof(mlan_scan_cfg));
5715 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5716 
5717 done:
5718 	if (ret != MLAN_STATUS_PENDING)
5719 		kfree(req);
5720 	LEAVE();
5721 	return ret;
5722 }
5723 
5724 /**
5725  *  @brief request scan
5726  *
5727  *  @param priv                 A pointer to moal_private structure
5728  *  @param scan_cfg             A pointer to wlan_user_scan_cfg structure
5729  *
5730  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5731  */
woal_do_scan(moal_private * priv,wlan_user_scan_cfg * scan_cfg)5732 mlan_status woal_do_scan(moal_private *priv, wlan_user_scan_cfg *scan_cfg)
5733 {
5734 	mlan_status ret = MLAN_STATUS_SUCCESS;
5735 	moal_handle *handle = priv->phandle;
5736 
5737 	ENTER();
5738 	if (handle->scan_pending_on_block == MTRUE) {
5739 		PRINTM(MINFO, "scan already in processing...\n");
5740 		LEAVE();
5741 		return ret;
5742 	}
5743 #ifdef REASSOCIATION
5744 	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->reassoc_sem)) {
5745 		PRINTM(MERROR, "Acquire semaphore error, woal_do_combo_scan\n");
5746 		LEAVE();
5747 		return -EBUSY;
5748 	}
5749 #endif /* REASSOCIATION */
5750 	priv->report_scan_result = MTRUE;
5751 
5752 	if (!scan_cfg)
5753 		ret = woal_request_scan(priv, MOAL_NO_WAIT, NULL);
5754 	else
5755 		ret = woal_request_userscan(priv, MOAL_NO_WAIT, scan_cfg);
5756 
5757 #ifdef REASSOCIATION
5758 	MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
5759 #endif
5760 	LEAVE();
5761 	return ret;
5762 }
5763 
5764 /**
5765  *  @brief Cancel pending scan
5766  *
5767  *  @param priv                 A pointer to moal_private structure
5768  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5769  */
woal_cancel_scan(moal_private * priv,t_u8 wait_option)5770 mlan_status woal_cancel_scan(moal_private *priv, t_u8 wait_option)
5771 {
5772 	mlan_ioctl_req *req = NULL;
5773 	mlan_status ret = MLAN_STATUS_SUCCESS;
5774 	moal_handle *handle = priv->phandle;
5775 	moal_private *scan_priv = handle->scan_priv;
5776 #ifdef STA_CFG80211
5777 	unsigned long flags;
5778 #endif
5779 	/* If scan is in process, cancel the scan command */
5780 	if (!handle->scan_pending_on_block || !scan_priv)
5781 		return ret;
5782 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
5783 	if (req == NULL) {
5784 		ret = MLAN_STATUS_FAILURE;
5785 		goto done;
5786 	}
5787 	req->req_id = MLAN_IOCTL_SCAN;
5788 	req->action = MLAN_ACT_SET;
5789 	((mlan_ds_scan *)req->pbuf)->sub_command = MLAN_OID_SCAN_CANCEL;
5790 	ret = woal_request_ioctl(scan_priv, req, wait_option);
5791 	handle->scan_pending_on_block = MFALSE;
5792 	MOAL_REL_SEMAPHORE(&handle->async_sem);
5793 #ifdef STA_CFG80211
5794 	spin_lock_irqsave(&handle->scan_req_lock, flags);
5795 	if (IS_STA_CFG80211(handle->params.cfg80211_wext) &&
5796 	    handle->scan_request) {
5797 		cancel_delayed_work(&handle->scan_timeout_work);
5798 		/** some supplicant can not handle SCAN abort event */
5799 		if (scan_priv->bss_type == MLAN_BSS_TYPE_STA)
5800 			woal_cfg80211_scan_done(handle->scan_request, MTRUE);
5801 		else
5802 			woal_cfg80211_scan_done(handle->scan_request, MFALSE);
5803 		handle->scan_request = NULL;
5804 	}
5805 	spin_unlock_irqrestore(&handle->scan_req_lock, flags);
5806 #endif
5807 	/* add 10ms delay, incase firmware delay 0x7f event after scan cancel
5808 	 * command response */
5809 	woal_sched_timeout(10);
5810 	handle->scan_priv = NULL;
5811 done:
5812 	if (ret != MLAN_STATUS_PENDING)
5813 		kfree(req);
5814 	return ret;
5815 }
5816 
5817 /**
5818  *  @brief find ssid in scan_table
5819  *
5820  *  @param priv         A pointer to moal_private
5821  *  @param ssid_bssid   A pointer to mlan_ssid_bssid structure
5822  *
5823  *
5824  *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
5825  */
woal_find_essid(moal_private * priv,mlan_ssid_bssid * ssid_bssid,t_u8 wait_option)5826 int woal_find_essid(moal_private *priv, mlan_ssid_bssid *ssid_bssid,
5827 		    t_u8 wait_option)
5828 {
5829 	int ret = 0;
5830 	mlan_scan_resp scan_resp;
5831 	wifi_timeval t;
5832 	ENTER();
5833 
5834 	if (MLAN_STATUS_SUCCESS !=
5835 	    woal_get_scan_table(priv, wait_option, &scan_resp)) {
5836 		LEAVE();
5837 		return MLAN_STATUS_FAILURE;
5838 	}
5839 #ifdef STA_CFG80211
5840 	if (priv->ft_pre_connect || priv->ft_ie_len) {
5841 		/** skip check the scan age out */
5842 		ret = woal_find_best_network(priv, wait_option, ssid_bssid);
5843 		LEAVE();
5844 		return ret;
5845 	}
5846 #endif
5847 	woal_get_monotonic_time(&t);
5848 /** scan result timeout value */
5849 #define SCAN_RESULT_AGEOUT 10
5850 	if (t.time_sec > (scan_resp.age_in_secs + SCAN_RESULT_AGEOUT)) {
5851 		LEAVE();
5852 		return MLAN_STATUS_FAILURE;
5853 	}
5854 	ret = woal_find_best_network(priv, wait_option, ssid_bssid);
5855 	LEAVE();
5856 	return ret;
5857 }
5858 
5859 /**
5860  * @brief                    auto reconnection configure
5861  *
5862  * @param priv               Pointer to moal_private structure
5863  * @param cfg_mode           configure mode
5864  * @param roam_offload_cfg   Pointer to woal_roam_offload_cfg structure
5865  *
5866  *  @return                  0-success, negative for failure.
5867  */
woal_config_fw_roaming(moal_private * priv,t_u8 cfg_mode,woal_roam_offload_cfg * roam_offload_cfg)5868 int woal_config_fw_roaming(moal_private *priv, t_u8 cfg_mode,
5869 			   woal_roam_offload_cfg *roam_offload_cfg)
5870 {
5871 	mlan_ioctl_req *ioctl_req = NULL;
5872 	mlan_ds_misc_cfg *misc = NULL;
5873 	mlan_ds_misc_roam_offload *roam = NULL;
5874 	mlan_status status = MLAN_STATUS_SUCCESS;
5875 	int ret = 0;
5876 
5877 	ENTER();
5878 
5879 	if (!priv || !priv->phandle) {
5880 		PRINTM(MERROR, "priv or handle is null\n");
5881 		ret = -EFAULT;
5882 		goto done;
5883 	}
5884 
5885 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
5886 	if (ioctl_req == NULL) {
5887 		ret = -ENOMEM;
5888 		goto done;
5889 	}
5890 
5891 	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
5892 	misc->sub_command = MLAN_OID_MISC_ROAM_OFFLOAD;
5893 	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
5894 
5895 	roam = (mlan_ds_misc_roam_offload *)&misc->param.roam_offload;
5896 	roam->aplist.ap_num = 0;
5897 	ioctl_req->action = MLAN_ACT_SET;
5898 	roam->enable = priv->phandle->fw_roam_enable;
5899 	roam->config_mode = cfg_mode;
5900 
5901 	if ((roam->config_mode == ROAM_OFFLOAD_ENABLE) && roam_offload_cfg) {
5902 		roam->userset_passphrase = roam_offload_cfg->userset_passphrase;
5903 		if (roam->userset_passphrase)
5904 			roam->enable = 0;
5905 	}
5906 	if (roam->config_mode == ROAM_OFFLOAD_PARAM_CFG) {
5907 		moal_memcpy_ext(priv->phandle, (t_u8 *)&roam->bssid_reconnect,
5908 				(t_u8 *)&roam_offload_cfg->bssid,
5909 				MLAN_MAC_ADDR_LENGTH,
5910 				sizeof(roam->bssid_reconnect));
5911 		if (roam_offload_cfg->ssid_list.ssid_num) {
5912 			moal_memcpy_ext(priv->phandle, (t_u8 *)&roam->ssid_list,
5913 					(t_u8 *)&roam_offload_cfg->ssid_list,
5914 					sizeof(mlan_ds_misc_ssid_list),
5915 					sizeof(mlan_ds_misc_ssid_list));
5916 		}
5917 		if (roam_offload_cfg->black_list.ap_num) {
5918 			moal_memcpy_ext(
5919 				priv->phandle, (t_u8 *)&roam->black_list,
5920 				(t_u8 *)&roam_offload_cfg->black_list,
5921 				sizeof(mlan_ds_misc_roam_offload_aplist),
5922 				sizeof(mlan_ds_misc_roam_offload_aplist));
5923 		}
5924 		roam->trigger_condition = roam_offload_cfg->trigger_condition;
5925 		roam->retry_count = roam_offload_cfg->retry_count;
5926 		if (roam_offload_cfg->rssi_param_set_flag) {
5927 			roam->para_rssi.set_flag = 1;
5928 			roam->para_rssi.max_rssi = roam_offload_cfg->max_rssi;
5929 			roam->para_rssi.min_rssi = roam_offload_cfg->min_rssi;
5930 			roam->para_rssi.step_rssi = roam_offload_cfg->step_rssi;
5931 		}
5932 		if (roam_offload_cfg->band_rssi_flag) {
5933 			roam->band_rssi_flag = roam_offload_cfg->band_rssi_flag;
5934 			moal_memcpy_ext(priv->phandle, (t_u8 *)&roam->band_rssi,
5935 					(t_u8 *)&roam_offload_cfg->band_rssi,
5936 					sizeof(mlan_ds_misc_band_rssi),
5937 					sizeof(mlan_ds_misc_band_rssi));
5938 		}
5939 		if (roam_offload_cfg->bgscan_set_flag) {
5940 			roam->bgscan_set_flag =
5941 				roam_offload_cfg->bgscan_set_flag;
5942 			moal_memcpy_ext(priv->phandle,
5943 					(t_u8 *)&roam->bgscan_cfg,
5944 					(t_u8 *)&roam_offload_cfg->bgscan_cfg,
5945 					sizeof(mlan_ds_misc_bgscan_cfg),
5946 					sizeof(mlan_ds_misc_bgscan_cfg));
5947 		}
5948 		if (roam_offload_cfg->ees_param_set_flag) {
5949 			roam->ees_param_set_flag =
5950 				roam_offload_cfg->ees_param_set_flag;
5951 			moal_memcpy_ext(priv->phandle, (t_u8 *)&roam->ees_cfg,
5952 					(t_u8 *)&roam_offload_cfg->ees_cfg,
5953 					sizeof(mlan_ds_misc_ees_cfg),
5954 					sizeof(mlan_ds_misc_ees_cfg));
5955 		}
5956 		roam->bcn_miss_threshold = roam_offload_cfg->bcn_miss_threshold;
5957 		roam->pre_bcn_miss_threshold =
5958 			roam_offload_cfg->pre_bcn_miss_threshold;
5959 		roam->repeat_count = roam_offload_cfg->repeat_count;
5960 	}
5961 	if (roam->config_mode == ROAM_OFFLOAD_SUSPEND_CFG) {
5962 		moal_memcpy_ext(priv->phandle, roam->bssid_reconnect,
5963 				priv->phandle->auto_reconnect_bssid,
5964 				MLAN_MAC_ADDR_LENGTH,
5965 				sizeof(roam->bssid_reconnect));
5966 		roam->ssid_list.ssid_num = 1;
5967 		moal_memcpy_ext(
5968 			priv->phandle, (t_u8 *)&roam->ssid_list.ssids[0].ssid,
5969 			(t_u8 *)&priv->phandle->auto_reconnect_ssid.ssid,
5970 			priv->phandle->auto_reconnect_ssid.ssid_len,
5971 			MLAN_MAX_SSID_LENGTH);
5972 		roam->retry_count = priv->phandle->auto_reconnect_retry_count;
5973 	}
5974 
5975 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
5976 	if (status != MLAN_STATUS_SUCCESS) {
5977 		ret = -EFAULT;
5978 		goto done;
5979 	}
5980 
5981 done:
5982 	if (status != MLAN_STATUS_PENDING)
5983 		kfree(ioctl_req);
5984 
5985 	LEAVE();
5986 	return ret;
5987 }
5988 
5989 /**
5990  *  @brief Request user scan
5991  *
5992  *  @param priv                 A pointer to moal_private structure
5993  *  @param wait_option          Wait option
5994  *  @param scan_cfg             A pointer to wlan_bgscan_cfg structure
5995  *
5996  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5997  */
woal_request_bgscan(moal_private * priv,t_u8 wait_option,wlan_bgscan_cfg * scan_cfg)5998 mlan_status woal_request_bgscan(moal_private *priv, t_u8 wait_option,
5999 				wlan_bgscan_cfg *scan_cfg)
6000 {
6001 	mlan_status ret = MLAN_STATUS_SUCCESS;
6002 	mlan_ioctl_req *ioctl_req = NULL;
6003 	mlan_ds_scan *scan = NULL;
6004 	mlan_status status = MLAN_STATUS_SUCCESS;
6005 	ENTER();
6006 
6007 	/* Allocate an IOCTL request buffer */
6008 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan) +
6009 					      sizeof(wlan_bgscan_cfg));
6010 	if (ioctl_req == NULL) {
6011 		ret = MLAN_STATUS_FAILURE;
6012 		goto done;
6013 	}
6014 
6015 	scan = (mlan_ds_scan *)ioctl_req->pbuf;
6016 	scan->sub_command = MLAN_OID_SCAN_BGSCAN_CONFIG;
6017 	ioctl_req->req_id = MLAN_IOCTL_SCAN;
6018 	ioctl_req->action = MLAN_ACT_SET;
6019 	moal_memcpy_ext(priv->phandle, scan->param.user_scan.scan_cfg_buf,
6020 			scan_cfg, sizeof(wlan_bgscan_cfg),
6021 			sizeof(wlan_bgscan_cfg));
6022 
6023 	/* Send IOCTL request to MLAN */
6024 	status = woal_request_ioctl(priv, ioctl_req, wait_option);
6025 	if (status == MLAN_STATUS_FAILURE) {
6026 		ret = MLAN_STATUS_FAILURE;
6027 		goto done;
6028 	}
6029 done:
6030 	if (status != MLAN_STATUS_PENDING)
6031 		kfree(ioctl_req);
6032 	LEAVE();
6033 	return ret;
6034 }
6035 
6036 /**
6037  *  @brief set bgscan config
6038  *
6039  *  @param priv                 A pointer to moal_private structure
6040  *  @param buf                  A pointer to scan command buf
6041  *  @param length               buf length
6042  *
6043  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
6044  */
woal_set_bg_scan(moal_private * priv,char * buf,int length)6045 mlan_status woal_set_bg_scan(moal_private *priv, char *buf, int length)
6046 {
6047 	t_u8 *ptr = buf + strlen("BGSCAN-CONFIG") + 1;
6048 	int buf_left = length - (strlen("BGSCAN-CONFIG") + 1);
6049 	int band = 0;
6050 	int num_ssid = 0;
6051 	int ssid_len = 0;
6052 	mlan_status ret = MLAN_STATUS_FAILURE;
6053 
6054 	ENTER();
6055 	memset(&priv->scan_cfg, 0, sizeof(priv->scan_cfg));
6056 	priv->scan_cfg.report_condition =
6057 		BG_SCAN_SSID_MATCH | BG_SCAN_WAIT_ALL_CHAN_DONE;
6058 	while (buf_left >= 2) {
6059 		switch (*ptr) {
6060 		case WEXT_CSCAN_SSID_SECTION:
6061 			ssid_len = *(ptr + 1);
6062 			if ((buf_left < (ssid_len + 2)) ||
6063 			    (ssid_len > MLAN_MAX_SSID_LENGTH)) {
6064 				PRINTM(MERROR,
6065 				       "Invalid ssid, buf_left=%d, ssid_len=%d\n",
6066 				       buf_left, ssid_len);
6067 				buf_left = 0;
6068 				break;
6069 			}
6070 			if (ssid_len &&
6071 			    (num_ssid < (MRVDRV_MAX_SSID_LIST_LENGTH - 1))) {
6072 				strncpy(priv->scan_cfg.ssid_list[num_ssid].ssid,
6073 					ptr + 2, ssid_len);
6074 				priv->scan_cfg.ssid_list[num_ssid].max_len = 0;
6075 				PRINTM(MIOCTL, "BG scan: ssid=%s\n",
6076 				       priv->scan_cfg.ssid_list[num_ssid].ssid);
6077 				num_ssid++;
6078 			}
6079 			buf_left -= ssid_len + 2;
6080 			ptr += ssid_len + 2;
6081 			break;
6082 		case WEXT_BGSCAN_RSSI_SECTION:
6083 			priv->scan_cfg.report_condition =
6084 				BG_SCAN_SSID_RSSI_MATCH |
6085 				BG_SCAN_WAIT_ALL_CHAN_DONE;
6086 			priv->scan_cfg.rssi_threshold = ptr[1];
6087 			PRINTM(MIOCTL, "BG scan: rssi_threshold=%d\n",
6088 			       (int)priv->scan_cfg.rssi_threshold);
6089 			ptr += 2;
6090 			buf_left -= 2;
6091 			break;
6092 		case WEXT_BGSCAN_REPEAT_SECTION:
6093 			priv->scan_cfg.repeat_count = (t_u16)ptr[1];
6094 			PRINTM(MIOCTL, "BG scan: repeat_count=%d\n",
6095 			       (int)priv->scan_cfg.repeat_count);
6096 			ptr += 2;
6097 			buf_left -= 2;
6098 			break;
6099 		case WEXT_BGSCAN_INTERVAL_SECTION:
6100 			if (buf_left < 3) {
6101 				PRINTM(MERROR,
6102 				       "Invalid scan_interval, buf_left=%d\n",
6103 				       buf_left);
6104 				buf_left = 0;
6105 				break;
6106 			}
6107 			priv->scan_cfg.scan_interval =
6108 				(ptr[2] << 8 | ptr[1]) * 1000;
6109 			PRINTM(MIOCTL, "BG scan: scan_interval=%d\n",
6110 			       (int)priv->scan_cfg.scan_interval);
6111 			ptr += 3;
6112 			buf_left -= 3;
6113 			break;
6114 		default:
6115 			buf_left = 0;
6116 			break;
6117 		}
6118 	}
6119 	/** set bgscan when ssid_num > 0 */
6120 	if (num_ssid) {
6121 		if (MLAN_STATUS_SUCCESS != woal_get_band(priv, &band)) {
6122 			ret = MLAN_STATUS_FAILURE;
6123 			goto done;
6124 		}
6125 		switch (band) {
6126 		case WIFI_FREQUENCY_BAND_2GHZ:
6127 			priv->scan_cfg.chan_list[0].radio_type =
6128 				0 | BAND_SPECIFIED;
6129 			break;
6130 		case WIFI_FREQUENCY_BAND_5GHZ:
6131 			priv->scan_cfg.chan_list[0].radio_type =
6132 				1 | BAND_SPECIFIED;
6133 			break;
6134 		default:
6135 			break;
6136 		}
6137 		priv->scan_cfg.bss_type = MLAN_BSS_MODE_INFRA;
6138 		priv->scan_cfg.action = BG_SCAN_ACT_SET;
6139 		priv->scan_cfg.enable = MTRUE;
6140 		moal_memcpy_ext(priv->phandle, priv->scan_cfg.random_mac,
6141 				priv->random_mac, ETH_ALEN,
6142 				sizeof(priv->scan_cfg.random_mac));
6143 		ret = woal_request_bgscan(priv, MOAL_IOCTL_WAIT,
6144 					  &priv->scan_cfg);
6145 	}
6146 done:
6147 	LEAVE();
6148 	return ret;
6149 }
6150 
6151 #ifdef STA_CFG80211
6152 /**
6153  *  @brief set bgscan and new rssi_low_threshold
6154  *
6155  *  @param priv                 A pointer to moal_private structure
6156  *  @param set_rssi             flag for set rssi_low_threshold
6157  *
6158  *  @return                     N/A
6159  */
woal_config_bgscan_and_rssi(moal_private * priv,t_u8 set_rssi)6160 void woal_config_bgscan_and_rssi(moal_private *priv, t_u8 set_rssi)
6161 {
6162 	char rssi_low[11];
6163 	mlan_bss_info bss_info;
6164 	int band = 0;
6165 
6166 	ENTER();
6167 	if (!priv->rssi_low) {
6168 		LEAVE();
6169 		return;
6170 	}
6171 	memset(&bss_info, 0, sizeof(bss_info));
6172 	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
6173 	if (!bss_info.media_connected) {
6174 		PRINTM(MIOCTL, "We already lost connection\n");
6175 		LEAVE();
6176 		return;
6177 	}
6178 	memset(&priv->scan_cfg, 0, sizeof(priv->scan_cfg));
6179 	strncpy(priv->scan_cfg.ssid_list[0].ssid, bss_info.ssid.ssid,
6180 		bss_info.ssid.ssid_len);
6181 	priv->scan_cfg.ssid_list[0].max_len = 0;
6182 
6183 	priv->scan_cfg.report_condition =
6184 		BG_SCAN_SSID_RSSI_MATCH | BG_SCAN_WAIT_ALL_CHAN_DONE;
6185 	priv->scan_cfg.rssi_threshold = priv->rssi_low - RSSI_HYSTERESIS;
6186 	priv->scan_cfg.repeat_count = DEF_REPEAT_COUNT;
6187 	priv->scan_cfg.scan_interval = MIN_BGSCAN_INTERVAL;
6188 	if (MLAN_STATUS_SUCCESS != woal_get_band(priv, &band)) {
6189 		PRINTM(MERROR, "woal get band fail\n");
6190 		LEAVE();
6191 		return;
6192 	}
6193 	switch (band) {
6194 	case WIFI_FREQUENCY_BAND_2GHZ:
6195 		priv->scan_cfg.chan_list[0].radio_type = 0 | BAND_SPECIFIED;
6196 		break;
6197 	case WIFI_FREQUENCY_BAND_5GHZ:
6198 		priv->scan_cfg.chan_list[0].radio_type = 1 | BAND_SPECIFIED;
6199 		break;
6200 	default:
6201 		break;
6202 	}
6203 	priv->scan_cfg.bss_type = MLAN_BSS_MODE_INFRA;
6204 	priv->scan_cfg.action = BG_SCAN_ACT_SET;
6205 	priv->scan_cfg.enable = MTRUE;
6206 	moal_memcpy_ext(priv->phandle, priv->scan_cfg.random_mac,
6207 			priv->random_mac, ETH_ALEN,
6208 			sizeof(priv->scan_cfg.random_mac));
6209 	if (MLAN_STATUS_FAILURE ==
6210 	    woal_request_bgscan(priv, MOAL_NO_WAIT, &priv->scan_cfg)) {
6211 		PRINTM(MERROR, "request bgscan fail\n");
6212 		LEAVE();
6213 		return;
6214 	}
6215 	if (set_rssi &&
6216 	    ((priv->rssi_low + RSSI_HYSTERESIS) <= LOWEST_RSSI_THRESHOLD)) {
6217 		priv->rssi_low += RSSI_HYSTERESIS;
6218 		snprintf(rssi_low, sizeof(rssi_low), "%d", priv->rssi_low);
6219 		if (MLAN_STATUS_FAILURE ==
6220 		    woal_set_rssi_low_threshold(priv, rssi_low, MOAL_NO_WAIT))
6221 			PRINTM(MERROR, "set_rssi_low_threshold fail\n");
6222 	}
6223 	LEAVE();
6224 }
6225 #endif
6226 
6227 /**
6228  *  @brief stop bg scan
6229  *
6230  *  @param priv                 A pointer to moal_private structure
6231  *  @param wait_option          wait option
6232  *
6233  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
6234  */
woal_stop_bg_scan(moal_private * priv,t_u8 wait_option)6235 mlan_status woal_stop_bg_scan(moal_private *priv, t_u8 wait_option)
6236 {
6237 	wlan_bgscan_cfg scan_cfg;
6238 	mlan_status ret = MLAN_STATUS_SUCCESS;
6239 	ENTER();
6240 
6241 	memset(&scan_cfg, 0, sizeof(scan_cfg));
6242 	scan_cfg.action = BG_SCAN_ACT_SET;
6243 	scan_cfg.enable = MFALSE;
6244 	ret = woal_request_bgscan(priv, wait_option, &scan_cfg);
6245 
6246 	LEAVE();
6247 	return ret;
6248 }
6249 
6250 /**
6251  *  @brief set bgscan config
6252  *
6253  *  @param handle               A pointer to moal_handle structure
6254  *
6255  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
6256  */
woal_reconfig_bgscan(moal_handle * handle)6257 void woal_reconfig_bgscan(moal_handle *handle)
6258 {
6259 	int i;
6260 	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
6261 		if (handle->priv[i] &&
6262 		    (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA)) {
6263 			if (handle->priv[i]->bg_scan_start &&
6264 			    handle->priv[i]->bg_scan_reported) {
6265 				PRINTM(MIOCTL, "Reconfig BGSCAN\n");
6266 				woal_request_bgscan(handle->priv[i],
6267 						    MOAL_NO_WAIT,
6268 						    &handle->priv[i]->scan_cfg);
6269 				handle->priv[i]->bg_scan_reported = MFALSE;
6270 			}
6271 		}
6272 	}
6273 }
6274 
6275 /**
6276  *  @brief set rssi low threshold
6277  *
6278  *  @param priv                 A pointer to moal_private structure
6279  *  @param rssi                 A pointer to low rssi
6280  *  @param wait_option          Wait option
6281  *
6282  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
6283  */
woal_set_rssi_low_threshold(moal_private * priv,char * rssi,t_u8 wait_option)6284 mlan_status woal_set_rssi_low_threshold(moal_private *priv, char *rssi,
6285 					t_u8 wait_option)
6286 {
6287 	mlan_status ret = MLAN_STATUS_SUCCESS;
6288 	mlan_ioctl_req *req = NULL;
6289 	mlan_ds_misc_cfg *misc = NULL;
6290 	int low_rssi = 0;
6291 
6292 	ENTER();
6293 	if (priv->media_connected == MFALSE)
6294 		goto done;
6295 
6296 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
6297 	if (req == NULL) {
6298 		ret = MLAN_STATUS_FAILURE;
6299 		goto done;
6300 	}
6301 	misc = (mlan_ds_misc_cfg *)req->pbuf;
6302 	req->req_id = MLAN_IOCTL_MISC_CFG;
6303 	misc->sub_command = MLAN_OID_MISC_SUBSCRIBE_EVENT;
6304 	req->action = MLAN_ACT_SET;
6305 	misc->param.subscribe_event.evt_action = SUBSCRIBE_EVT_ACT_BITWISE_SET;
6306 	misc->param.subscribe_event.evt_bitmap = SUBSCRIBE_EVT_RSSI_LOW;
6307 	misc->param.subscribe_event.evt_bitmap |= SUBSCRIBE_EVT_PRE_BEACON_LOST;
6308 	misc->param.subscribe_event.pre_beacon_miss = DEFAULT_PRE_BEACON_MISS;
6309 
6310 	if (MLAN_STATUS_SUCCESS != woal_atoi(&low_rssi, rssi)) {
6311 		ret = MLAN_STATUS_FAILURE;
6312 		goto done;
6313 	}
6314 #ifdef STA_CFG80211
6315 	priv->mrvl_rssi_low = low_rssi;
6316 #endif
6317 	misc->param.subscribe_event.low_rssi = low_rssi;
6318 	misc->param.subscribe_event.low_rssi_freq = 0;
6319 	ret = woal_request_ioctl(priv, req, wait_option);
6320 	if (ret == MLAN_STATUS_FAILURE) {
6321 		PRINTM(MERROR, "request set rssi_low_threshold fail!\n");
6322 		goto done;
6323 	}
6324 done:
6325 	if (ret != MLAN_STATUS_PENDING)
6326 		kfree(req);
6327 	LEAVE();
6328 	return ret;
6329 }
6330 
6331 #if defined(STA_CFG80211)
6332 /**
6333  *  @brief set rssi low threshold
6334  *
6335  *  @param priv                 A pointer to moal_private structure
6336  *  @param event_id             event id.
6337  *  @param wait_option          wait option
6338  *
6339  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
6340  */
woal_set_rssi_threshold(moal_private * priv,t_u32 event_id,t_u8 wait_option)6341 mlan_status woal_set_rssi_threshold(moal_private *priv, t_u32 event_id,
6342 				    t_u8 wait_option)
6343 {
6344 	mlan_status ret = MLAN_STATUS_SUCCESS;
6345 	mlan_ioctl_req *req = NULL;
6346 	mlan_ds_misc_cfg *misc = NULL;
6347 
6348 	ENTER();
6349 	if (priv->media_connected == MFALSE)
6350 		goto done;
6351 	if (priv->mrvl_rssi_low || !priv->cqm_rssi_thold)
6352 		goto done;
6353 	if (event_id == MLAN_EVENT_ID_FW_BCN_RSSI_LOW) {
6354 		if (priv->last_rssi_low < 100)
6355 			priv->last_rssi_low += priv->cqm_rssi_hyst;
6356 		priv->last_rssi_high = abs(priv->cqm_rssi_high_thold);
6357 	} else if (event_id == MLAN_EVENT_ID_FW_BCN_RSSI_HIGH) {
6358 		priv->last_rssi_low = abs(priv->cqm_rssi_thold);
6359 		if (priv->last_rssi_high > priv->cqm_rssi_hyst)
6360 			priv->last_rssi_high -= priv->cqm_rssi_hyst;
6361 	} else {
6362 		priv->last_rssi_low = abs(priv->cqm_rssi_thold);
6363 		priv->last_rssi_high = abs(priv->cqm_rssi_high_thold);
6364 	}
6365 
6366 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
6367 	if (req == NULL) {
6368 		ret = -ENOMEM;
6369 		goto done;
6370 	}
6371 	misc = (mlan_ds_misc_cfg *)req->pbuf;
6372 	req->req_id = MLAN_IOCTL_MISC_CFG;
6373 	misc->sub_command = MLAN_OID_MISC_SUBSCRIBE_EVENT;
6374 	req->action = MLAN_ACT_SET;
6375 	if (!event_id && !priv->cqm_rssi_thold && !priv->cqm_rssi_hyst)
6376 		misc->param.subscribe_event.evt_action =
6377 			SUBSCRIBE_EVT_ACT_BITWISE_CLR;
6378 	else
6379 		misc->param.subscribe_event.evt_action =
6380 			SUBSCRIBE_EVT_ACT_BITWISE_SET;
6381 	misc->param.subscribe_event.evt_bitmap =
6382 		SUBSCRIBE_EVT_RSSI_LOW | SUBSCRIBE_EVT_RSSI_HIGH;
6383 	misc->param.subscribe_event.low_rssi_freq = 0;
6384 	misc->param.subscribe_event.low_rssi = priv->last_rssi_low;
6385 	misc->param.subscribe_event.high_rssi_freq = 0;
6386 	misc->param.subscribe_event.high_rssi = priv->last_rssi_high;
6387 	PRINTM(MIOCTL, "rssi_low=%d, rssi_high=%d action=%d\n",
6388 	       (int)priv->last_rssi_low, (int)priv->last_rssi_high,
6389 	       misc->param.subscribe_event.evt_action);
6390 	ret = woal_request_ioctl(priv, req, wait_option);
6391 done:
6392 	if (ret != MLAN_STATUS_PENDING)
6393 		kfree(req);
6394 	LEAVE();
6395 	return ret;
6396 }
6397 #endif
6398 
6399 /**
6400  *  @brief  Get power mode
6401  *
6402  *  @param priv                 A pointer to moal_private structure
6403  *  @param powermode            A pointer to powermode buf
6404  *
6405  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
6406  */
woal_get_powermode(moal_private * priv,int * powermode)6407 mlan_status woal_get_powermode(moal_private *priv, int *powermode)
6408 {
6409 	mlan_status ret = MLAN_STATUS_SUCCESS;
6410 	int ps_mode;
6411 
6412 	ENTER();
6413 
6414 	if (MLAN_STATUS_SUCCESS != woal_set_get_power_mgmt(priv, MLAN_ACT_GET,
6415 							   &ps_mode, 0,
6416 							   MOAL_IOCTL_WAIT)) {
6417 		ret = MLAN_STATUS_FAILURE;
6418 		goto done;
6419 	}
6420 
6421 	if (ps_mode)
6422 		*powermode = MFALSE;
6423 	else
6424 		*powermode = MTRUE;
6425 
6426 done:
6427 	LEAVE();
6428 	return ret;
6429 }
6430 
6431 /**
6432  *  @brief set scan type
6433  *
6434  *  @param priv                 A pointer to moal_private structure
6435  *  @param scan_type            MLAN_SCAN_TYPE_ACTIVE/MLAN_SCAN_TYPE_PASSIVE
6436  *
6437  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
6438  */
woal_set_scan_type(moal_private * priv,t_u32 scan_type)6439 mlan_status woal_set_scan_type(moal_private *priv, t_u32 scan_type)
6440 {
6441 	mlan_status ret = MLAN_STATUS_SUCCESS;
6442 	mlan_ds_scan *scan = NULL;
6443 	mlan_ioctl_req *req = NULL;
6444 	mlan_scan_cfg scan_cfg;
6445 
6446 	ENTER();
6447 	memset(&scan_cfg, 0, sizeof(scan_cfg));
6448 	if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) {
6449 		ret = MLAN_STATUS_FAILURE;
6450 		goto done;
6451 	}
6452 
6453 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
6454 	if (req == NULL) {
6455 		ret = MLAN_STATUS_FAILURE;
6456 		goto done;
6457 	}
6458 	scan = (mlan_ds_scan *)req->pbuf;
6459 	scan->sub_command = MLAN_OID_SCAN_CONFIG;
6460 	req->req_id = MLAN_IOCTL_SCAN;
6461 	req->action = MLAN_ACT_SET;
6462 	memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
6463 	scan_cfg.scan_type = scan_type;
6464 	PRINTM(MIOCTL, "Set scan_type=%d\n", (int)scan_type);
6465 	moal_memcpy_ext(priv->phandle, &scan->param.scan_cfg, &scan_cfg,
6466 			sizeof(mlan_scan_cfg), sizeof(mlan_scan_cfg));
6467 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6468 
6469 done:
6470 	if (ret != MLAN_STATUS_PENDING)
6471 		kfree(req);
6472 	LEAVE();
6473 	return ret;
6474 }
6475 
6476 /**
6477  *  @brief enable/disable ext_scan
6478  *
6479  *  @param priv                 A pointer to moal_private structure
6480  *  @param enable               MTRUE -- enable, MFALSE --disable
6481  *
6482  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
6483  */
woal_enable_ext_scan(moal_private * priv,t_u8 enable)6484 mlan_status woal_enable_ext_scan(moal_private *priv, t_u8 enable)
6485 {
6486 	mlan_status ret = MLAN_STATUS_SUCCESS;
6487 	mlan_ds_scan *scan = NULL;
6488 	mlan_ioctl_req *req = NULL;
6489 	mlan_scan_cfg scan_cfg;
6490 
6491 	ENTER();
6492 	memset(&scan_cfg, 0, sizeof(scan_cfg));
6493 	if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) {
6494 		ret = MLAN_STATUS_FAILURE;
6495 		goto done;
6496 	}
6497 
6498 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
6499 	if (req == NULL) {
6500 		ret = MLAN_STATUS_FAILURE;
6501 		goto done;
6502 	}
6503 	scan = (mlan_ds_scan *)req->pbuf;
6504 	scan->sub_command = MLAN_OID_SCAN_CONFIG;
6505 	req->req_id = MLAN_IOCTL_SCAN;
6506 	req->action = MLAN_ACT_SET;
6507 	memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
6508 	scan_cfg.ext_scan = enable;
6509 	PRINTM(MIOCTL, "Set ext_scan=%d\n", (int)enable);
6510 	moal_memcpy_ext(priv->phandle, &scan->param.scan_cfg, &scan_cfg,
6511 			sizeof(mlan_scan_cfg), sizeof(mlan_scan_cfg));
6512 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6513 
6514 done:
6515 	if (ret != MLAN_STATUS_PENDING)
6516 		kfree(req);
6517 	LEAVE();
6518 	return ret;
6519 }
6520 
6521 /**
6522  *  @brief set power mode
6523  *
6524  *  @param priv                 A pointer to moal_private structure
6525  *  @param powermode            A pointer to powermode string.
6526  *
6527  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
6528  */
woal_set_powermode(moal_private * priv,char * powermode)6529 mlan_status woal_set_powermode(moal_private *priv, char *powermode)
6530 {
6531 	mlan_status ret = MLAN_STATUS_SUCCESS;
6532 	int disabled;
6533 
6534 	ENTER();
6535 
6536 	if (*powermode == '1') {
6537 		PRINTM(MIOCTL, "Disable power save\n");
6538 		disabled = 1;
6539 	} else if (*powermode == '0') {
6540 		PRINTM(MIOCTL, "Enable power save\n");
6541 		disabled = 0;
6542 	} else {
6543 		PRINTM(MERROR, "unsupported power mode\n");
6544 		ret = MLAN_STATUS_FAILURE;
6545 		goto done;
6546 	}
6547 
6548 	if (MLAN_STATUS_SUCCESS != woal_set_get_power_mgmt(priv, MLAN_ACT_SET,
6549 							   &disabled, 0,
6550 							   MOAL_IOCTL_WAIT))
6551 		ret = MLAN_STATUS_FAILURE;
6552 
6553 done:
6554 	LEAVE();
6555 	return ret;
6556 }
6557 
6558 /**
6559  *  @brief set combo scan
6560  *
6561  *  @param priv                 A pointer to moal_private structure
6562  *  @param buf                  A pointer to scan command buf
6563  *  @param length               buf length
6564  *
6565  *  @return                     0 -- success, otherwise fail
6566  */
woal_set_combo_scan(moal_private * priv,char * buf,int length)6567 int woal_set_combo_scan(moal_private *priv, char *buf, int length)
6568 {
6569 	int ret = 0;
6570 	wlan_user_scan_cfg *scan_cfg;
6571 	t_u8 *ptr = buf + WEXT_CSCAN_HEADER_SIZE;
6572 	int buf_left = length - WEXT_CSCAN_HEADER_SIZE;
6573 	int num_ssid = 0;
6574 	int num_chan = 0;
6575 	int ssid_len = 0;
6576 	int i = 0;
6577 	t_u16 passive_scan_time = 0;
6578 	t_u16 specific_scan_time = 0;
6579 
6580 	ENTER();
6581 
6582 	scan_cfg = (wlan_user_scan_cfg *)kmalloc(sizeof(wlan_user_scan_cfg),
6583 						 GFP_KERNEL);
6584 	if (!scan_cfg) {
6585 		PRINTM(MERROR, "Malloc buffer failed\n");
6586 		LEAVE();
6587 		return -ENOMEM;
6588 	}
6589 
6590 	memset(scan_cfg, 0, sizeof(wlan_user_scan_cfg));
6591 	while (buf_left >= 2) {
6592 		switch (*ptr) {
6593 		case WEXT_CSCAN_SSID_SECTION:
6594 			ssid_len = *(ptr + 1);
6595 			if ((buf_left < (ssid_len + 2)) ||
6596 			    (ssid_len > MLAN_MAX_SSID_LENGTH)) {
6597 				PRINTM(MERROR,
6598 				       "Invalid ssid, buf_left=%d, ssid_len=%d\n",
6599 				       buf_left, ssid_len);
6600 				buf_left = 0;
6601 				break;
6602 			}
6603 			if (ssid_len &&
6604 			    (num_ssid < (MRVDRV_MAX_SSID_LIST_LENGTH - 1))) {
6605 				strncpy(scan_cfg->ssid_list[num_ssid].ssid,
6606 					ptr + 2, ssid_len);
6607 				scan_cfg->ssid_list[num_ssid].max_len = 0;
6608 				PRINTM(MIOCTL, "Combo scan: ssid=%s\n",
6609 				       scan_cfg->ssid_list[num_ssid].ssid);
6610 				num_ssid++;
6611 			}
6612 			buf_left -= ssid_len + 2;
6613 			ptr += ssid_len + 2;
6614 			break;
6615 		case WEXT_CSCAN_CHANNEL_SECTION:
6616 			num_chan = ptr[1];
6617 			if ((buf_left < (num_chan + 2)) ||
6618 			    (num_chan > WLAN_USER_SCAN_CHAN_MAX)) {
6619 				PRINTM(MERROR,
6620 				       "Invalid channel list, buf_left=%d, num_chan=%d\n",
6621 				       buf_left, num_chan);
6622 				buf_left = 0;
6623 				break;
6624 			}
6625 			for (i = 0; i < num_chan; i++) {
6626 				scan_cfg->chan_list[i].chan_number = ptr[2 + i];
6627 				PRINTM(MIOCTL, "Combo scan: chan=%d\n",
6628 				       scan_cfg->chan_list[i].chan_number);
6629 			}
6630 			buf_left -= 2 + num_chan;
6631 			ptr += 2 + num_chan;
6632 			break;
6633 		case WEXT_CSCAN_PASV_DWELL_SECTION:
6634 			if (buf_left < 3) {
6635 				PRINTM(MERROR,
6636 				       "Invalid PASV_DWELL_SECTION, buf_left=%d\n",
6637 				       buf_left);
6638 				buf_left = 0;
6639 				break;
6640 			}
6641 			passive_scan_time = ptr[2] << 8 | ptr[1];
6642 			ptr += 3;
6643 			buf_left -= 3;
6644 			break;
6645 		case WEXT_CSCAN_HOME_DWELL_SECTION:
6646 			if (buf_left < 3) {
6647 				PRINTM(MERROR,
6648 				       "Invalid HOME_DWELL_SECTION, buf_left=%d\n",
6649 				       buf_left);
6650 				buf_left = 0;
6651 				break;
6652 			}
6653 			specific_scan_time = ptr[2] << 8 | ptr[1];
6654 			ptr += 3;
6655 			buf_left -= 3;
6656 			break;
6657 		default:
6658 			buf_left = 0;
6659 			break;
6660 		}
6661 	}
6662 	if (passive_scan_time || specific_scan_time) {
6663 		PRINTM(MIOCTL,
6664 		       "Set passive_scan_time=%d specific_scan_time=%d\n",
6665 		       passive_scan_time, specific_scan_time);
6666 		if (MLAN_STATUS_FAILURE ==
6667 		    woal_set_scan_time(priv, 0, passive_scan_time,
6668 				       specific_scan_time)) {
6669 			ret = -EFAULT;
6670 			goto done;
6671 		}
6672 	}
6673 	if (num_ssid || num_chan) {
6674 		if (num_ssid) {
6675 			/* Add broadcast scan to ssid_list */
6676 			scan_cfg->ssid_list[num_ssid].max_len = 0xff;
6677 			if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
6678 				woal_set_scan_type(priv, MLAN_SCAN_TYPE_ACTIVE);
6679 		}
6680 		if (MLAN_STATUS_FAILURE == woal_do_scan(priv, scan_cfg))
6681 			ret = -EFAULT;
6682 		if (num_ssid && (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE))
6683 			woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE);
6684 	} else {
6685 		/* request broadcast scan */
6686 		if (MLAN_STATUS_FAILURE == woal_do_scan(priv, NULL))
6687 			ret = -EFAULT;
6688 	}
6689 done:
6690 	kfree(scan_cfg);
6691 	LEAVE();
6692 	return ret;
6693 }
6694 
6695 /**
6696  *  @brief  Get band
6697  *
6698  *  @param priv                 A pointer to moal_private structure
6699  *  @param band                 A pointer to band buf
6700  *
6701  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
6702  */
woal_get_band(moal_private * priv,int * band)6703 mlan_status woal_get_band(moal_private *priv, int *band)
6704 {
6705 	mlan_status ret = MLAN_STATUS_SUCCESS;
6706 	mlan_ioctl_req *req = NULL;
6707 	mlan_ds_radio_cfg *radio_cfg = NULL;
6708 	int support_band = 0;
6709 
6710 	ENTER();
6711 
6712 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
6713 	if (req == NULL) {
6714 		ret = MLAN_STATUS_FAILURE;
6715 		goto done;
6716 	}
6717 	radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
6718 	radio_cfg->sub_command = MLAN_OID_BAND_CFG;
6719 	req->req_id = MLAN_IOCTL_RADIO_CFG;
6720 	/* Get config_bands, adhoc_start_band and adhoc_channel values from MLAN
6721 	 */
6722 	req->action = MLAN_ACT_GET;
6723 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6724 	if (ret != MLAN_STATUS_SUCCESS)
6725 		goto done;
6726 
6727 	if (radio_cfg->param.band_cfg.config_bands &
6728 	    (BAND_B | BAND_G | BAND_GN))
6729 		support_band |= WIFI_FREQUENCY_BAND_2GHZ;
6730 	if (radio_cfg->param.band_cfg.config_bands & (BAND_A | BAND_AN))
6731 		support_band |= WIFI_FREQUENCY_BAND_5GHZ;
6732 	*band = support_band;
6733 	if (support_band == WIFI_FREQUENCY_ALL_BAND)
6734 		*band = WIFI_FREQUENCY_BAND_AUTO;
6735 done:
6736 	if (ret != MLAN_STATUS_PENDING)
6737 		kfree(req);
6738 	LEAVE();
6739 	return ret;
6740 }
6741 
6742 /**
6743  *  @brief set band
6744  *
6745  *  @param priv             A pointer to moal_private structure
6746  *  @param pband            A pointer to band string.
6747  *
6748  *  @return                 MLAN_STATUS_SUCCESS -- success, otherwise fail
6749  */
woal_set_band(moal_private * priv,char * pband)6750 mlan_status woal_set_band(moal_private *priv, char *pband)
6751 {
6752 	mlan_status ret = MLAN_STATUS_SUCCESS;
6753 	int band = 0;
6754 	mlan_ioctl_req *req = NULL;
6755 	mlan_ds_radio_cfg *radio_cfg = NULL;
6756 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
6757 	int cfg80211_wext = priv->phandle->params.cfg80211_wext;
6758 #endif
6759 
6760 	ENTER();
6761 	if (priv->media_connected == MTRUE) {
6762 		PRINTM(MERROR, "Set band is not allowed in connected state\n");
6763 		ret = MLAN_STATUS_FAILURE;
6764 		goto done;
6765 	}
6766 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
6767 	if (req == NULL) {
6768 		ret = MLAN_STATUS_FAILURE;
6769 		goto done;
6770 	}
6771 	radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
6772 	radio_cfg->sub_command = MLAN_OID_BAND_CFG;
6773 	req->req_id = MLAN_IOCTL_RADIO_CFG;
6774 
6775 	/* Get fw supported values from MLAN */
6776 	req->action = MLAN_ACT_GET;
6777 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6778 	if (ret != MLAN_STATUS_SUCCESS)
6779 		goto done;
6780 
6781 	if (*pband == '0') {
6782 		PRINTM(MIOCTL, "Set band to AUTO\n");
6783 		band = radio_cfg->param.band_cfg.fw_bands;
6784 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
6785 		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev &&
6786 		    priv->wdev->wiphy) {
6787 			if (radio_cfg->param.band_cfg.fw_bands & BAND_A)
6788 				priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ] =
6789 					&cfg80211_band_5ghz;
6790 			priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ] =
6791 				&cfg80211_band_2ghz;
6792 		}
6793 #endif
6794 	} else if (*pband == '1') {
6795 		PRINTM(MIOCTL, "Set band to 5G\n");
6796 		if (!(radio_cfg->param.band_cfg.fw_bands & BAND_A)) {
6797 			PRINTM(MERROR, "Don't support 5G band\n");
6798 			ret = MLAN_STATUS_FAILURE;
6799 			goto done;
6800 		}
6801 		band = BAND_A;
6802 		if (radio_cfg->param.band_cfg.fw_bands & BAND_AN)
6803 			band |= BAND_AN;
6804 		if (radio_cfg->param.band_cfg.fw_bands & BAND_AAC)
6805 			band |= BAND_AAC;
6806 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
6807 		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev &&
6808 		    priv->wdev->wiphy) {
6809 			priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ] =
6810 				&cfg80211_band_5ghz;
6811 			priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
6812 		}
6813 #endif
6814 	} else if (*pband == '2') {
6815 		PRINTM(MIOCTL, "Set band to 2G\n");
6816 		band = BAND_B | BAND_G;
6817 		band |= BAND_GN;
6818 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
6819 		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev &&
6820 		    priv->wdev->wiphy) {
6821 			priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
6822 			priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ] =
6823 				&cfg80211_band_2ghz;
6824 		}
6825 #endif
6826 	} else {
6827 		PRINTM(MERROR, "unsupported band\n");
6828 		ret = MLAN_STATUS_FAILURE;
6829 		goto done;
6830 	}
6831 	/* Set config_bands to MLAN */
6832 	req->action = MLAN_ACT_SET;
6833 	memset(&radio_cfg->param.band_cfg, 0, sizeof(mlan_ds_band_cfg));
6834 	radio_cfg->param.band_cfg.config_bands = band;
6835 	radio_cfg->param.band_cfg.adhoc_start_band = band;
6836 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6837 
6838 done:
6839 	if (ret != MLAN_STATUS_PENDING)
6840 		kfree(req);
6841 	LEAVE();
6842 	return ret;
6843 }
6844 
6845 /**
6846  *  @brief Add RX Filter
6847  *
6848  *  @param priv                 A pointer to moal_private structure
6849  *  @param rxfilter             A pointer to rxfilter string.
6850  *
6851  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
6852  */
woal_add_rxfilter(moal_private * priv,char * rxfilter)6853 mlan_status woal_add_rxfilter(moal_private *priv, char *rxfilter)
6854 {
6855 	mlan_status ret = MLAN_STATUS_SUCCESS;
6856 	ENTER();
6857 	/*  Android command:
6858 	    "DRIVER RXFILTER-ADD 0"
6859 	    "DRIVER RXFILTER-ADD 1"
6860 	    "DRIVER RXFILTER-ADD 3" */
6861 	if (*rxfilter == '0') {
6862 		PRINTM(MIOCTL, "Add IPV4 multicast filter\n");
6863 		priv->rx_filter |= RX_FILTER_IPV4_MULTICAST;
6864 	} else if (*rxfilter == '1') {
6865 		PRINTM(MIOCTL, "Add broadcast filter\n");
6866 		priv->rx_filter |= RX_FILTER_BROADCAST;
6867 	} else if (*rxfilter == '2') {
6868 		PRINTM(MIOCTL, "Add unicast filter\n");
6869 		priv->rx_filter |= RX_FILTER_UNICAST;
6870 	} else if (*rxfilter == '3') {
6871 		PRINTM(MIOCTL, "Add IPV6 multicast fitler\n");
6872 		priv->rx_filter |= RX_FILTER_IPV6_MULTICAST;
6873 	} else {
6874 		PRINTM(MERROR, "unsupported rx fitler\n");
6875 		ret = MLAN_STATUS_FAILURE;
6876 		goto done;
6877 	}
6878 done:
6879 	LEAVE();
6880 	return ret;
6881 }
6882 
6883 /**
6884  *  @brief Remove RX Filter
6885  *
6886  *  @param priv                 A pointer to moal_private structure
6887  *  @param rxfilter             A pointer to rxfilter string.
6888  *
6889  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
6890  */
woal_remove_rxfilter(moal_private * priv,char * rxfilter)6891 mlan_status woal_remove_rxfilter(moal_private *priv, char *rxfilter)
6892 {
6893 	mlan_status ret = MLAN_STATUS_SUCCESS;
6894 	ENTER();
6895 	if (*rxfilter == '0') {
6896 		PRINTM(MIOCTL, "Remove IPV4 multicast filter\n");
6897 		priv->rx_filter &= ~RX_FILTER_IPV4_MULTICAST;
6898 	} else if (*rxfilter == '1') {
6899 		PRINTM(MIOCTL, "Remove broadcast filter\n");
6900 		priv->rx_filter &= ~RX_FILTER_BROADCAST;
6901 	} else if (*rxfilter == '2') {
6902 		PRINTM(MIOCTL, "Remove unicast filter\n");
6903 		priv->rx_filter &= ~RX_FILTER_UNICAST;
6904 	} else if (*rxfilter == '3') {
6905 		PRINTM(MIOCTL, "Remove IPV6 multicast fitler\n");
6906 		priv->rx_filter &= ~RX_FILTER_IPV6_MULTICAST;
6907 	} else {
6908 		PRINTM(MERROR, "unsupported rx fitler\n");
6909 		ret = MLAN_STATUS_FAILURE;
6910 		goto done;
6911 	}
6912 done:
6913 	LEAVE();
6914 	return ret;
6915 }
6916 
6917 /**
6918  * @brief Set/Get WMM IE QoS configuration
6919  *
6920  * @param priv     A pointer to moal_private structure
6921  *  @param action  Action set or get
6922  * @param qos_cfg  A pointer to QoS configuration structure
6923  *
6924  * @return         MLAN_STATUS_SUCCESS -- success, otherwise fail
6925  */
woal_priv_qos_cfg(moal_private * priv,t_u32 action,char * qos_cfg)6926 mlan_status woal_priv_qos_cfg(moal_private *priv, t_u32 action, char *qos_cfg)
6927 {
6928 	mlan_status ret = MLAN_STATUS_SUCCESS;
6929 	mlan_ds_wmm_cfg *cfg = NULL;
6930 	mlan_ioctl_req *req = NULL;
6931 	int qosinfo = 0;
6932 
6933 	ENTER();
6934 
6935 	if (qos_cfg == NULL) {
6936 		PRINTM(MERROR, "QOS info buffer is null\n");
6937 		return MLAN_STATUS_FAILURE;
6938 	}
6939 	if ((action == MLAN_ACT_SET) &&
6940 	    (MLAN_STATUS_SUCCESS != woal_atoi(&qosinfo, qos_cfg))) {
6941 		ret = MLAN_STATUS_FAILURE;
6942 		goto done;
6943 	}
6944 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
6945 	if (req == NULL) {
6946 		ret = MLAN_STATUS_FAILURE;
6947 		goto done;
6948 	}
6949 	cfg = (mlan_ds_wmm_cfg *)req->pbuf;
6950 	cfg->sub_command = MLAN_OID_WMM_CFG_QOS;
6951 	req->req_id = MLAN_IOCTL_WMM_CFG;
6952 	req->action = action;
6953 	if (action == MLAN_ACT_SET) {
6954 		cfg->param.qos_cfg = (t_u8)qosinfo;
6955 		PRINTM(MIOCTL, "set qosinfo=%d\n", qosinfo);
6956 	}
6957 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6958 
6959 	if (action == MLAN_ACT_GET)
6960 		*qos_cfg = cfg->param.qos_cfg;
6961 done:
6962 	if (ret != MLAN_STATUS_PENDING)
6963 		kfree(req);
6964 	LEAVE();
6965 	return ret;
6966 }
6967 
6968 /**
6969  * @brief Set sleep period
6970  *
6971  * @param priv     A pointer to moal_private structure
6972  * @param psleeppd A pointer to sleep period configuration structure
6973  *
6974  * @return         MLAN_STATUS_SUCCESS -- success, otherwise fail
6975  */
woal_set_sleeppd(moal_private * priv,char * psleeppd)6976 mlan_status woal_set_sleeppd(moal_private *priv, char *psleeppd)
6977 {
6978 	mlan_status ret = MLAN_STATUS_SUCCESS;
6979 	mlan_ds_pm_cfg *pm_cfg = NULL;
6980 	mlan_ioctl_req *req = NULL;
6981 	int sleeppd = 0;
6982 
6983 	ENTER();
6984 
6985 	if (MLAN_STATUS_SUCCESS != woal_atoi(&sleeppd, psleeppd)) {
6986 		ret = MLAN_STATUS_FAILURE;
6987 		goto done;
6988 	}
6989 	PRINTM(MIOCTL, "set sleeppd=%d\n", sleeppd);
6990 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
6991 	if (req == NULL) {
6992 		ret = MLAN_STATUS_FAILURE;
6993 		goto done;
6994 	}
6995 	pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
6996 	pm_cfg->sub_command = MLAN_OID_PM_CFG_SLEEP_PD;
6997 	req->req_id = MLAN_IOCTL_PM_CFG;
6998 	if ((sleeppd <= MAX_SLEEP_PERIOD && sleeppd >= MIN_SLEEP_PERIOD) ||
6999 	    (sleeppd == 0) || (sleeppd == SLEEP_PERIOD_RESERVED_FF)) {
7000 		req->action = MLAN_ACT_SET;
7001 		pm_cfg->param.sleep_period = sleeppd;
7002 	} else {
7003 		ret = MLAN_STATUS_FAILURE;
7004 		goto done;
7005 	}
7006 
7007 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
7008 
7009 done:
7010 	if (ret != MLAN_STATUS_PENDING)
7011 		kfree(req);
7012 	LEAVE();
7013 	return ret;
7014 }
7015 
7016 /**
7017  * @brief  Set scan period function
7018  *
7019  * @param priv      A pointer to moal_private structure
7020  * @param buf       A pointer to scan command buf
7021  * @param length    buf length
7022  *
7023  * @return          MLAN_STATUS_SUCCESS -- success, otherwise fail
7024  */
woal_set_scan_cfg(moal_private * priv,char * buf,int length)7025 int woal_set_scan_cfg(moal_private *priv, char *buf, int length)
7026 {
7027 	mlan_status ret = MLAN_STATUS_SUCCESS;
7028 	t_u8 *ptr = buf + NL80211_SCANCFG_HEADER_SIZE;
7029 	int buf_left = length - NL80211_SCANCFG_HEADER_SIZE;
7030 	t_u16 active_scan_time = 0;
7031 	t_u16 passive_scan_time = 0;
7032 	t_u16 specific_scan_time = 0;
7033 
7034 	ENTER();
7035 	while (buf_left >= 2) {
7036 		switch (*ptr) {
7037 		case NL80211_SCANCFG_ACTV_DWELL_SECTION:
7038 			if (buf_left < 3) {
7039 				PRINTM(MERROR,
7040 				       "Invalid ACTV_DWELL_SECTION, buf_left=%d\n",
7041 				       buf_left);
7042 				buf_left = 0;
7043 				break;
7044 			}
7045 			active_scan_time = ptr[2] << 8 | ptr[1];
7046 			ptr += 3;
7047 			buf_left -= 3;
7048 			break;
7049 		case NL80211_SCANCFG_PASV_DWELL_SECTION:
7050 			if (buf_left < 3) {
7051 				PRINTM(MERROR,
7052 				       "Invalid PASV_DWELL_SECTION, buf_left=%d\n",
7053 				       buf_left);
7054 				buf_left = 0;
7055 				break;
7056 			}
7057 			passive_scan_time = ptr[2] << 8 | ptr[1];
7058 			ptr += 3;
7059 			buf_left -= 3;
7060 			break;
7061 		case NL80211_SCANCFG_SPCF_DWELL_SECTION:
7062 			if (buf_left < 3) {
7063 				PRINTM(MERROR,
7064 				       "Invalid SPCF_DWELL_SECTION, buf_left=%d\n",
7065 				       buf_left);
7066 				buf_left = 0;
7067 				break;
7068 			}
7069 			specific_scan_time = ptr[2] << 8 | ptr[1];
7070 			ptr += 3;
7071 			buf_left -= 3;
7072 			break;
7073 		default:
7074 			buf_left = 0;
7075 			break;
7076 		}
7077 	}
7078 
7079 	if (active_scan_time || passive_scan_time || specific_scan_time) {
7080 		PRINTM(MIOCTL,
7081 		       "Set active_scan_time= %d passive_scan_time=%d specific_scan_time=%d\n",
7082 		       active_scan_time, passive_scan_time, specific_scan_time);
7083 		if (MLAN_STATUS_FAILURE ==
7084 		    woal_set_scan_time(priv, active_scan_time,
7085 				       passive_scan_time, specific_scan_time)) {
7086 			ret = -EFAULT;
7087 		}
7088 	}
7089 
7090 	LEAVE();
7091 	return ret;
7092 }
7093 
7094 /**
7095  *  @brief Set Radio On/OFF
7096  *
7097  *  @param priv                 A pointer to moal_private structure
7098  *  @param option               Radio Option
7099  *
7100  *  @return                     0 --success, otherwise fail
7101  */
woal_set_radio(moal_private * priv,t_u8 option)7102 int woal_set_radio(moal_private *priv, t_u8 option)
7103 {
7104 	int ret = 0;
7105 	mlan_ds_radio_cfg *radio = NULL;
7106 	mlan_ioctl_req *req = NULL;
7107 	mlan_status status = MLAN_STATUS_SUCCESS;
7108 	ENTER();
7109 	if ((option != 0) && (option != 1)) {
7110 		ret = -EINVAL;
7111 		goto done;
7112 	}
7113 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
7114 	if (req == NULL) {
7115 		ret = -ENOMEM;
7116 		goto done;
7117 	}
7118 	radio = (mlan_ds_radio_cfg *)req->pbuf;
7119 	radio->sub_command = MLAN_OID_RADIO_CTRL;
7120 	req->req_id = MLAN_IOCTL_RADIO_CFG;
7121 	req->action = MLAN_ACT_SET;
7122 	radio->param.radio_on_off = option;
7123 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
7124 	if (status != MLAN_STATUS_SUCCESS)
7125 		ret = -EFAULT;
7126 
7127 done:
7128 	if (status != MLAN_STATUS_PENDING)
7129 		kfree(req);
7130 	LEAVE();
7131 	return ret;
7132 }
7133 
7134 #endif /* STA_SUPPORT */
7135 
7136 #ifdef USB
7137 /**
7138  * @brief Initialize USB packet aggregation control
7139  *
7140  * @param handle    A pointer to moal_private structure
7141  *
7142  * @return          MLAN_STATUS_SUCCESS -- success, otherwise fail
7143  */
woal_usb_aggr_init(moal_handle * handle)7144 mlan_status woal_usb_aggr_init(moal_handle *handle)
7145 {
7146 	mlan_status ret = MLAN_STATUS_SUCCESS;
7147 	moal_private *priv = NULL;
7148 	mlan_ioctl_req *req = NULL;
7149 	mlan_ds_misc_cfg *pcfg_misc = NULL;
7150 	mlan_ds_misc_usb_aggr_ctrl *aggr_param = NULL;
7151 	t_u8 usb_aggr_enable;
7152 	struct usb_card_rec *cardp = NULL;
7153 	int i = 0, resubmit_urbs = 0;
7154 
7155 	ENTER();
7156 
7157 	if (!handle) {
7158 		PRINTM(MERROR, "Handle is null\n");
7159 		LEAVE();
7160 		return MLAN_STATUS_FAILURE;
7161 	}
7162 	priv = woal_get_priv(handle, MLAN_BSS_ROLE_STA);
7163 	if (!priv) {
7164 		PRINTM(MERROR, "STA priv is null\n");
7165 		ret = MLAN_STATUS_FAILURE;
7166 		goto done;
7167 	}
7168 	if (handle->card == NULL) {
7169 		PRINTM(MERROR, "Card is null in %s()\n", __func__);
7170 		ret = MLAN_STATUS_FAILURE;
7171 		goto done;
7172 	}
7173 	cardp = (struct usb_card_rec *)handle->card;
7174 
7175 	/* Check module parameter */
7176 	if (handle->params.usb_aggr == 0 || handle->params.usb_aggr == 2) {
7177 		usb_aggr_enable = MFALSE;
7178 	} else if (handle->params.usb_aggr == 1) {
7179 		usb_aggr_enable = MTRUE;
7180 	} else {
7181 		PRINTM(MWARN,
7182 		       "Invalid module param (usb_aggr) value %d, "
7183 		       "using MLAN default\n",
7184 		       handle->params.usb_aggr);
7185 		handle->params.usb_aggr = 0;
7186 		usb_aggr_enable = MFALSE;
7187 	}
7188 
7189 	/* Allocate an IOCTL request buffer */
7190 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
7191 	if (req == NULL) {
7192 		ret = MLAN_STATUS_FAILURE;
7193 		goto done;
7194 	}
7195 
7196 	/* Fill request buffer */
7197 	pcfg_misc = (mlan_ds_misc_cfg *)req->pbuf;
7198 	pcfg_misc->sub_command = MLAN_OID_MISC_USB_AGGR_CTRL;
7199 	req->req_id = MLAN_IOCTL_MISC_CFG;
7200 	req->action = MLAN_ACT_SET;
7201 
7202 	aggr_param = &pcfg_misc->param.usb_aggr_params;
7203 	/* Initialize TX aggr default values */
7204 	aggr_param->tx_aggr_ctrl.enable = usb_aggr_enable;
7205 	aggr_param->tx_aggr_ctrl.aggr_mode = MLAN_USB_AGGR_MODE_NUM;
7206 	aggr_param->tx_aggr_ctrl.aggr_align =
7207 		MAX(handle->params.max_tx_buf, MLAN_USB_TX_AGGR_ALIGN);
7208 	aggr_param->tx_aggr_ctrl.aggr_max = MLAN_USB_TX_MAX_AGGR_NUM;
7209 	aggr_param->tx_aggr_ctrl.aggr_tmo =
7210 		MLAN_USB_TX_AGGR_TIMEOUT_MSEC * 1000;
7211 
7212 	/* Initialize RX deaggr default values */
7213 	aggr_param->rx_deaggr_ctrl.enable = usb_aggr_enable;
7214 	aggr_param->rx_deaggr_ctrl.aggr_mode = MLAN_USB_AGGR_MODE_NUM;
7215 	aggr_param->rx_deaggr_ctrl.aggr_align = MLAN_USB_RX_ALIGN_SIZE;
7216 	aggr_param->rx_deaggr_ctrl.aggr_max = MLAN_USB_RX_MAX_AGGR_NUM;
7217 	aggr_param->rx_deaggr_ctrl.aggr_tmo = MLAN_USB_RX_DEAGGR_TIMEOUT_USEC;
7218 
7219 	/* Do not fail driver init due to command failure */
7220 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
7221 	/* Disable the feature if FW return failure/unsupported */
7222 	if (req->status_code)
7223 		cardp->tx_aggr_ctrl.enable = MFALSE;
7224 	else
7225 		moal_memcpy_ext(handle, &cardp->tx_aggr_ctrl,
7226 				&aggr_param->tx_aggr_ctrl,
7227 				sizeof(usb_aggr_ctrl_cfg),
7228 				sizeof(usb_aggr_ctrl_cfg));
7229 
7230 	if (req->status_code) {
7231 		/* Disable the feature if FW return failure/unsupported */
7232 		cardp->rx_deaggr_ctrl.enable = MFALSE;
7233 	} else {
7234 		/* Default is disable, resubmit URBs only for enable */
7235 		if (cardp->rx_deaggr_ctrl.enable != usb_aggr_enable)
7236 			resubmit_urbs = 1;
7237 	}
7238 	if (resubmit_urbs) {
7239 		/* Indicate resubmition from here */
7240 		cardp->resubmit_urbs = 1;
7241 		/* Rx SG feature is disabled due to FW failure/unsupported,
7242 		 * kill the URBs, they will be resubmitted after saving the
7243 		 * parameters to USB card */
7244 		if (atomic_read(&cardp->rx_data_urb_pending)) {
7245 			for (i = 0; i < MVUSB_RX_DATA_URB; i++) {
7246 				if (cardp->rx_data_list[i].urb) {
7247 					usb_kill_urb(
7248 						cardp->rx_data_list[i].urb);
7249 					usb_init_urb(
7250 						cardp->rx_data_list[i].urb);
7251 				}
7252 			}
7253 		}
7254 
7255 		/* Default is disable, update only for enable case */
7256 		moal_memcpy_ext(handle, &cardp->rx_deaggr_ctrl,
7257 				&aggr_param->rx_deaggr_ctrl,
7258 				sizeof(usb_aggr_ctrl_cfg),
7259 				sizeof(usb_aggr_ctrl_cfg));
7260 
7261 		/* Ensure the next data URBs will use the modified parameters */
7262 		if (!atomic_read(&cardp->rx_data_urb_pending)) {
7263 			/* Submit multiple Rx data URBs */
7264 			woal_usb_submit_rx_data_urbs(handle);
7265 		}
7266 		cardp->resubmit_urbs = 0;
7267 	}
7268 
7269 done:
7270 	if (ret != MLAN_STATUS_PENDING)
7271 		kfree(req);
7272 	LEAVE();
7273 	return ret;
7274 }
7275 #endif
7276 
7277 /**
7278  *  @brief Set hotspot configuration value to mlan layer
7279  *
7280  *  @param priv         A pointer to moal_private structure
7281  *  @param wait_option  wait option
7282  *  @param hotspotcfg   Hotspot configuration value
7283  *
7284  *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
7285  * otherwise fail
7286  */
woal_set_hotspotcfg(moal_private * priv,t_u8 wait_option,t_u32 hotspotcfg)7287 mlan_status woal_set_hotspotcfg(moal_private *priv, t_u8 wait_option,
7288 				t_u32 hotspotcfg)
7289 {
7290 	mlan_status ret = MLAN_STATUS_SUCCESS;
7291 	mlan_ioctl_req *req = NULL;
7292 	mlan_ds_misc_cfg *cfg = NULL;
7293 
7294 	ENTER();
7295 
7296 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
7297 	if (req == NULL) {
7298 		ret = MLAN_STATUS_FAILURE;
7299 		goto done;
7300 	}
7301 
7302 	cfg = (mlan_ds_misc_cfg *)req->pbuf;
7303 	cfg->param.hotspot_cfg = hotspotcfg;
7304 	req->action = MLAN_ACT_SET;
7305 
7306 	cfg->sub_command = MLAN_OID_MISC_HOTSPOT_CFG;
7307 	req->req_id = MLAN_IOCTL_MISC_CFG;
7308 
7309 	ret = woal_request_ioctl(priv, req, wait_option);
7310 	if (ret != MLAN_STATUS_SUCCESS)
7311 		goto done;
7312 
7313 done:
7314 	if (ret != MLAN_STATUS_PENDING)
7315 		kfree(req);
7316 	LEAVE();
7317 	return ret;
7318 }
7319 
7320 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
7321 /**
7322  * @brief               Set/Get network monitor configurations
7323  *
7324  * @param priv          Pointer to moal_private structure
7325  * @param wait_option  wait option
7326  * @param enable	    Enable/Disable
7327  * @param filter	    Filter flag - Management/Control/Data
7328  * @param band_chan_cfg           Network monitor band channel config
7329  *
7330  * @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
7331  */
woal_set_net_monitor(moal_private * priv,t_u8 wait_option,t_u8 enable,t_u8 filter,netmon_band_chan_cfg * band_chan_cfg)7332 mlan_status woal_set_net_monitor(moal_private *priv, t_u8 wait_option,
7333 				 t_u8 enable, t_u8 filter,
7334 				 netmon_band_chan_cfg *band_chan_cfg)
7335 {
7336 	mlan_status ret = MLAN_STATUS_SUCCESS;
7337 	mlan_ioctl_req *req = NULL;
7338 	mlan_ds_misc_cfg *misc = NULL;
7339 	mlan_ds_misc_net_monitor *net_mon = NULL;
7340 	mlan_status status = MLAN_STATUS_SUCCESS;
7341 
7342 	ENTER();
7343 
7344 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
7345 	if (req == NULL) {
7346 		ret = MLAN_STATUS_FAILURE;
7347 		goto done;
7348 	}
7349 	misc = (mlan_ds_misc_cfg *)req->pbuf;
7350 	net_mon = (mlan_ds_misc_net_monitor *)&misc->param.net_mon;
7351 	misc->sub_command = MLAN_OID_MISC_NET_MONITOR;
7352 	req->req_id = MLAN_IOCTL_MISC_CFG;
7353 	req->action = MLAN_ACT_SET;
7354 	net_mon->enable_net_mon = enable;
7355 	if (net_mon->enable_net_mon) {
7356 		net_mon->filter_flag = filter;
7357 		if (net_mon->enable_net_mon == CHANNEL_SPEC_SNIFFER_MODE) {
7358 			net_mon->band = band_chan_cfg->band;
7359 			net_mon->channel = band_chan_cfg->channel;
7360 			net_mon->chan_bandwidth = band_chan_cfg->chan_bandwidth;
7361 		}
7362 	}
7363 
7364 	status = woal_request_ioctl(priv, req, wait_option);
7365 	if (status != MLAN_STATUS_SUCCESS) {
7366 		ret = MLAN_STATUS_FAILURE;
7367 		goto done;
7368 	}
7369 
7370 done:
7371 	if (status != MLAN_STATUS_PENDING)
7372 		kfree(req);
7373 
7374 	LEAVE();
7375 	return ret;
7376 }
7377 #endif
7378 
7379 /**
7380  *  @brief Send delelte all BA command to MLAN
7381  *
7382  *  @param priv          A pointer to moal_private structure
7383  *  @param wait_option          Wait option
7384  *
7385  *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
7386  * otherwise fail
7387  */
woal_delba_all(moal_private * priv,t_u8 wait_option)7388 mlan_status woal_delba_all(moal_private *priv, t_u8 wait_option)
7389 {
7390 	mlan_ioctl_req *req = NULL;
7391 	mlan_ds_11n_cfg *cfg_11n = NULL;
7392 	mlan_ds_11n_delba *del_ba = NULL;
7393 	t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0};
7394 	mlan_status status = MLAN_STATUS_SUCCESS;
7395 	int ret = 0;
7396 
7397 	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(
7398 		sizeof(mlan_ds_11n_cfg));
7399 	if (req == NULL) {
7400 		ret = -ENOMEM;
7401 		goto done;
7402 	}
7403 	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
7404 	req->req_id = MLAN_IOCTL_11N_CFG;
7405 	cfg_11n->sub_command = MLAN_OID_11N_CFG_DELBA;
7406 
7407 	del_ba = &cfg_11n->param.del_ba;
7408 	memset(del_ba, 0, sizeof(mlan_ds_11n_delba));
7409 	del_ba->direction = DELBA_RX | DELBA_TX;
7410 	del_ba->tid = DELBA_ALL_TIDS;
7411 	moal_memcpy_ext(priv->phandle, del_ba->peer_mac_addr, zero_mac,
7412 			ETH_ALEN, sizeof(del_ba->peer_mac_addr));
7413 
7414 	status = woal_request_ioctl(priv, req, wait_option);
7415 
7416 	if (status != MLAN_STATUS_SUCCESS) {
7417 		ret = -EFAULT;
7418 		goto done;
7419 	}
7420 
7421 done:
7422 	if (status != MLAN_STATUS_PENDING)
7423 		kfree(req);
7424 	LEAVE();
7425 	return ret;
7426 }
7427 
7428 /**
7429  *  @brief Send 11d enable/disable command to firmware.
7430  *
7431  *  @param priv             A pointer to moal_private structure
7432  *  @param wait_option      Wait option
7433  *  @param enable           Enable/Disable 11d
7434  *
7435  *  @return                 MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
7436  * otherwise fail
7437  */
woal_set_11d(moal_private * priv,t_u8 wait_option,t_u8 enable)7438 mlan_status woal_set_11d(moal_private *priv, t_u8 wait_option, t_u8 enable)
7439 {
7440 	mlan_ioctl_req *req = NULL;
7441 	mlan_ds_snmp_mib *snmp = NULL;
7442 	mlan_status ret = MLAN_STATUS_SUCCESS;
7443 
7444 	ENTER();
7445 
7446 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
7447 	if (req == NULL) {
7448 		LEAVE();
7449 		return -ENOMEM;
7450 	}
7451 
7452 	req->action = MLAN_ACT_SET;
7453 	req->req_id = MLAN_IOCTL_SNMP_MIB;
7454 
7455 	snmp = (mlan_ds_snmp_mib *)req->pbuf;
7456 	snmp->sub_command = MLAN_OID_SNMP_MIB_DOT11D;
7457 	snmp->param.oid_value = enable;
7458 
7459 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
7460 	if (ret != MLAN_STATUS_PENDING)
7461 		kfree(req);
7462 
7463 	LEAVE();
7464 	return ret;
7465 }
7466 
7467 /**
7468  *  @brief Handle miscellaneous ioctls for asynchronous command response
7469  *
7470  *  @param priv     Pointer to moal_private structure
7471  *  @param info     Pointer to mlan_ds_misc_cfg structure
7472  *
7473  *  @return         N/A
7474  */
woal_ioctl_get_misc_conf(moal_private * priv,mlan_ds_misc_cfg * info)7475 void woal_ioctl_get_misc_conf(moal_private *priv, mlan_ds_misc_cfg *info)
7476 {
7477 	ENTER();
7478 	switch (info->sub_command) {
7479 	default:
7480 		break;
7481 	}
7482 }
7483 
7484 #ifdef CONFIG_PROC_FS
7485 #define RADIO_MODE_STR_LEN 20
7486 #define TX_PWR_STR_LEN 20
7487 #define TX_CONT_STR_LEN 50
7488 #define TX_FRAME_STR_LEN 200
7489 #define HE_TB_TX_STR_LEN 30
7490 
7491 /*
7492  *  @brief Parse mfg cmd radio mode string
7493  *
7494  *  @param s        A pointer to user buffer
7495  *  @param len      Length of user buffer
7496  *  @param d        A pointer to mfg_cmd_generic_cfg struct
7497  *  @return         0 on success, -EINVAL otherwise
7498  */
parse_radio_mode_string(const char * s,size_t len,struct mfg_cmd_generic_cfg * d)7499 static int parse_radio_mode_string(const char *s, size_t len,
7500 				   struct mfg_cmd_generic_cfg *d)
7501 {
7502 	int ret = MLAN_STATUS_SUCCESS;
7503 	char *string = NULL;
7504 	char *tmp = NULL;
7505 	char *pos = NULL;
7506 	gfp_t flag;
7507 
7508 	ENTER();
7509 	if (!s || !d) {
7510 		LEAVE();
7511 		return -EINVAL;
7512 	}
7513 	flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
7514 	string = kzalloc(RADIO_MODE_STR_LEN, flag);
7515 	if (string == NULL) {
7516 		LEAVE();
7517 		return -ENOMEM;
7518 	}
7519 
7520 	moal_memcpy_ext(NULL, string, s + strlen("radio_mode="),
7521 			len - strlen("radio_mode="), RADIO_MODE_STR_LEN - 1);
7522 
7523 	tmp = string;
7524 	string = strstrip(string);
7525 
7526 	/* radio mode index 0 */
7527 	pos = strsep(&string, " \t");
7528 	if (pos)
7529 		d->data1 = (t_u32)woal_string_to_number(pos);
7530 
7531 	/* radio mode index 1 */
7532 	pos = strsep(&string, " \t");
7533 	if (pos)
7534 		d->data2 = (t_u32)woal_string_to_number(pos);
7535 
7536 	if ((d->data1 > 14) || (d->data2 > 14))
7537 		ret = -EINVAL;
7538 
7539 	kfree(tmp);
7540 	LEAVE();
7541 	return ret;
7542 }
7543 
7544 /*
7545  *  @brief PoweLevelToDUT11Bits
7546  *
7547  *  @param Pwr		A user txpwr values of type int
7548  *  @param PowerLevel	A Pointer of uint32 type for converted txpwr vals
7549  *  @return		nothing just exit
7550  */
7551 
PoweLevelToDUT11Bits(int Pwr,t_u32 * PowerLevel)7552 static void PoweLevelToDUT11Bits(int Pwr, t_u32 *PowerLevel)
7553 {
7554 	int Z = 0;
7555 
7556 	if ((Pwr > 64) || (Pwr < -64))
7557 		return;
7558 
7559 	Z = (int)(Pwr * 16);
7560 	if (Z < 0) {
7561 		Z = Z + (1 << 11);
7562 	}
7563 	(*PowerLevel) = (t_u32)Z;
7564 
7565 	return;
7566 }
7567 
7568 /*
7569  *  @brief Parse mfg cmd tx pwr string
7570  *
7571  *  @param handle   A pointer to moal_handle structure
7572  *  @param s        A pointer to user buffer
7573  *  @param len      Length of user buffer
7574  *  @param d        A pointer to mfg_cmd_generic_cfg struct
7575  *  @return         0 on success, -EINVAL otherwise
7576  */
7577 
parse_tx_pwr_string(moal_handle * handle,const char * s,size_t len,struct mfg_cmd_generic_cfg * d)7578 static int parse_tx_pwr_string(moal_handle *handle, const char *s, size_t len,
7579 			       struct mfg_cmd_generic_cfg *d)
7580 {
7581 	int ret = MLAN_STATUS_SUCCESS;
7582 	char *string = NULL;
7583 	char *tmp = NULL;
7584 	char *pos = NULL;
7585 	gfp_t flag;
7586 	t_u32 tx_pwr_converted = 0xffffffff;
7587 	int tx_pwr_local = 0;
7588 	t_u8 fc_card = MFALSE;
7589 
7590 	ENTER();
7591 	if (!s || !d) {
7592 		LEAVE();
7593 		return -EINVAL;
7594 	}
7595 #ifdef SD9177
7596 	if (IS_SD9177(handle->card_type))
7597 		fc_card = MTRUE;
7598 #endif
7599 	flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
7600 	string = kzalloc(TX_PWR_STR_LEN, flag);
7601 	if (string == NULL) {
7602 		LEAVE();
7603 		return -ENOMEM;
7604 	}
7605 
7606 	moal_memcpy_ext(NULL, string, s + strlen("tx_power="),
7607 			len - strlen("tx_power="), TX_PWR_STR_LEN - 1);
7608 
7609 	tmp = string;
7610 	string = strstrip(string);
7611 
7612 	/* tx power value */
7613 	pos = strsep(&string, " \t");
7614 	if (fc_card && pos) {
7615 		/* for sd9177 we need to convert user power vals including -ve
7616 		 * vals as per labtool */
7617 		tx_pwr_local = woal_string_to_number(pos);
7618 		PoweLevelToDUT11Bits(tx_pwr_local, &tx_pwr_converted);
7619 		d->data1 = tx_pwr_converted;
7620 	} else if (pos) {
7621 		d->data1 = (t_u32)woal_string_to_number(pos);
7622 	}
7623 	/* modulation */
7624 	pos = strsep(&string, " \t");
7625 	if (pos)
7626 		d->data2 = (t_u32)woal_string_to_number(pos);
7627 
7628 	/* path id */
7629 	pos = strsep(&string, " \t");
7630 	if (pos)
7631 		d->data3 = (t_u32)woal_string_to_number(pos);
7632 
7633 	if (((!fc_card) && (d->data1 > 24)) || (d->data2 > 2))
7634 		ret = -EINVAL;
7635 
7636 	kfree(tmp);
7637 	LEAVE();
7638 	return ret;
7639 }
7640 /*
7641  *  @brief Parse mfg cmd tx cont string
7642  *
7643  *  @param s        A pointer to user buffer
7644  *  @param len      Length of user buffer
7645  *  @param d        A pointer to mfg_cmd_tx_cont struct
7646  *  @return         0 on success, -EINVAL otherwise
7647  */
parse_tx_cont_string(const char * s,size_t len,struct mfg_cmd_tx_cont * d)7648 static int parse_tx_cont_string(const char *s, size_t len,
7649 				struct mfg_cmd_tx_cont *d)
7650 {
7651 	int ret = MLAN_STATUS_SUCCESS;
7652 	char *string = NULL;
7653 	char *tmp = NULL;
7654 	char *pos = NULL;
7655 	gfp_t flag;
7656 
7657 	ENTER();
7658 	if (!s || !d) {
7659 		LEAVE();
7660 		return -EINVAL;
7661 	}
7662 	flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
7663 	string = kzalloc(TX_CONT_STR_LEN, flag);
7664 	if (string == NULL) {
7665 		LEAVE();
7666 		return -ENOMEM;
7667 	}
7668 
7669 	moal_memcpy_ext(NULL, string, s + strlen("tx_continuous="),
7670 			len - strlen("tx_continuous="), TX_CONT_STR_LEN - 1);
7671 
7672 	tmp = string;
7673 	string = strstrip(string);
7674 
7675 	pos = strsep(&string, " \t");
7676 	if (pos)
7677 		d->enable_tx = (t_u32)woal_string_to_number(pos);
7678 
7679 	pos = strsep(&string, " \t");
7680 	if (pos)
7681 		d->cw_mode = (t_u32)woal_string_to_number(pos);
7682 
7683 	if (d->enable_tx == MFALSE)
7684 		goto done;
7685 
7686 	pos = strsep(&string, " \t");
7687 	if (pos)
7688 		d->payload_pattern = (t_u32)woal_string_to_number(pos);
7689 
7690 	pos = strsep(&string, " \t");
7691 	if (pos)
7692 		d->cs_mode = (t_u32)woal_string_to_number(pos);
7693 
7694 	pos = strsep(&string, " \t");
7695 	if (pos)
7696 		d->act_sub_ch = (t_u32)woal_string_to_number(pos);
7697 
7698 	pos = strsep(&string, " \t");
7699 	if (pos)
7700 		d->tx_rate = (t_u32)woal_string_to_number(pos);
7701 
7702 	if ((d->enable_tx > 1) || (d->cw_mode > 1) || (d->cs_mode > 1) ||
7703 	    (d->act_sub_ch == 2 || d->act_sub_ch > 3))
7704 		ret = -EINVAL;
7705 done:
7706 	kfree(tmp);
7707 	LEAVE();
7708 	return ret;
7709 }
7710 
7711 /*
7712  *  @brief Parse mfg cmd tx frame string
7713  *
7714  *  @param s        A pointer to user buffer
7715  *  @param len      Length of user buffer
7716  *  @param d        A pointer to mfg_cmd_tx_frame2 struct
7717  *  @return         0 on success, -EINVAL otherwise
7718  */
parse_tx_frame_string(const char * s,size_t len,struct mfg_cmd_tx_frame2 * d)7719 static int parse_tx_frame_string(const char *s, size_t len,
7720 				 struct mfg_cmd_tx_frame2 *d)
7721 {
7722 	int ret = MLAN_STATUS_SUCCESS;
7723 	char *string = NULL;
7724 	char *tmp = NULL;
7725 	char *pos = NULL;
7726 	int i;
7727 	gfp_t flag;
7728 
7729 	ENTER();
7730 	if (!s || !d) {
7731 		LEAVE();
7732 		return -EINVAL;
7733 	}
7734 	flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
7735 	string = kzalloc(TX_FRAME_STR_LEN, flag);
7736 	if (string == NULL)
7737 		return -ENOMEM;
7738 
7739 	moal_memcpy_ext(NULL, string, s + strlen("tx_frame="),
7740 			len - strlen("tx_frame="), TX_FRAME_STR_LEN - 1);
7741 
7742 	tmp = string;
7743 	string = strstrip(string);
7744 
7745 	pos = strsep(&string, " \t");
7746 	if (pos)
7747 		d->enable = (t_u32)woal_string_to_number(pos);
7748 
7749 	if (d->enable == MFALSE)
7750 		goto done;
7751 
7752 	pos = strsep(&string, " \t");
7753 	if (pos)
7754 		d->data_rate = (t_u32)woal_string_to_number(pos);
7755 
7756 	pos = strsep(&string, " \t");
7757 	if (pos)
7758 		d->frame_pattern = (t_u32)woal_string_to_number(pos);
7759 
7760 	pos = strsep(&string, " \t");
7761 	if (pos)
7762 		d->frame_length = (t_u32)woal_string_to_number(pos);
7763 
7764 	pos = strsep(&string, " \t");
7765 	if (pos)
7766 		d->adjust_burst_sifs = (t_u16)woal_string_to_number(pos);
7767 
7768 	pos = strsep(&string, " \t");
7769 	if (pos)
7770 		d->burst_sifs_in_us = (t_u32)woal_string_to_number(pos);
7771 
7772 	pos = strsep(&string, " \t");
7773 	if (pos)
7774 		d->short_preamble = (t_u32)woal_string_to_number(pos);
7775 
7776 	pos = strsep(&string, " \t");
7777 	if (pos)
7778 		d->act_sub_ch = (t_u32)woal_string_to_number(pos);
7779 
7780 	pos = strsep(&string, " \t");
7781 	if (pos)
7782 		d->short_gi = (t_u32)woal_string_to_number(pos);
7783 
7784 	pos = strsep(&string, " \t");
7785 	if (pos)
7786 		d->adv_coding = (t_u32)woal_string_to_number(pos);
7787 
7788 	pos = strsep(&string, " \t");
7789 	if (pos)
7790 		d->tx_bf = (t_u32)woal_string_to_number(pos);
7791 
7792 	pos = strsep(&string, " \t");
7793 	if (pos)
7794 		d->gf_mode = (t_u32)woal_string_to_number(pos);
7795 
7796 	pos = strsep(&string, " \t");
7797 	if (pos)
7798 		d->stbc = (t_u32)woal_string_to_number(pos);
7799 
7800 	pos = strsep(&string, " \t");
7801 	if (pos)
7802 		d->NumPkt = (t_u32)woal_string_to_number(pos);
7803 
7804 	pos = strsep(&string, " \t");
7805 	if (pos)
7806 		d->MaxPE = (t_u32)woal_string_to_number(pos);
7807 
7808 	pos = strsep(&string, " \t");
7809 	if (pos)
7810 		d->BeamChange = (t_u32)woal_string_to_number(pos);
7811 
7812 	pos = strsep(&string, " \t");
7813 	if (pos)
7814 		d->Dcm = (t_u32)woal_string_to_number(pos);
7815 
7816 	pos = strsep(&string, " \t");
7817 	if (pos)
7818 		d->Doppler = (t_u32)woal_string_to_number(pos);
7819 
7820 	pos = strsep(&string, " \t");
7821 	if (pos)
7822 		d->MidP = (t_u32)woal_string_to_number(pos);
7823 
7824 	pos = strsep(&string, " \t");
7825 	if (pos)
7826 		d->QNum = (t_u32)woal_string_to_number(pos);
7827 
7828 	pos = strsep(&string, " \t");
7829 	if (pos) {
7830 		for (i = 0; i < ETH_ALEN; i++) {
7831 			pos = strsep(&string, ":");
7832 			if (pos)
7833 				d->bssid[i] = woal_atox(pos);
7834 		}
7835 	}
7836 
7837 	if ((d->enable > 1) || (d->frame_length == 0) ||
7838 	    (d->adjust_burst_sifs > 1) || (d->burst_sifs_in_us > 255) ||
7839 	    (d->short_preamble > 1) ||
7840 	    (d->act_sub_ch == 2 || d->act_sub_ch > 3) || (d->short_gi > 1) ||
7841 	    (d->adv_coding > 1) || (d->tx_bf > 1) || (d->gf_mode > 1) ||
7842 	    (d->stbc > 1))
7843 		ret = -EINVAL;
7844 done:
7845 	kfree(tmp);
7846 	LEAVE();
7847 	return ret;
7848 }
7849 
7850 /*
7851  *  @brief Parse mfg cmd HE TB Tx string
7852  *
7853  *  @param s        A pointer to user buffer
7854  *  @param len      Length of user buffer
7855  *  @param d        A pointer to mfg_Cmd_HE_TBTx_t struct
7856  *  @return         0 on success, -EINVAL otherwise
7857  */
parse_he_tb_tx_string(const char * s,size_t len,struct mfg_Cmd_HE_TBTx_t * d)7858 static int parse_he_tb_tx_string(const char *s, size_t len,
7859 				 struct mfg_Cmd_HE_TBTx_t *d)
7860 {
7861 	int ret = MLAN_STATUS_SUCCESS;
7862 	char *string = NULL;
7863 	char *pos = NULL;
7864 	gfp_t flag;
7865 
7866 	ENTER();
7867 	if (!s || !d) {
7868 		LEAVE();
7869 		return -EINVAL;
7870 	}
7871 	flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
7872 	string = kzalloc(HE_TB_TX_STR_LEN, flag);
7873 	if (string == NULL)
7874 		return -ENOMEM;
7875 
7876 	moal_memcpy_ext(NULL, string, s + strlen("he_tb_tx="),
7877 			len - strlen("he_tb_tx="), HE_TB_TX_STR_LEN - 1);
7878 
7879 	pos = strsep(&string, " \t");
7880 	if (pos)
7881 		d->enable = (t_u32)woal_string_to_number(pos);
7882 
7883 	if (d->enable == MFALSE)
7884 		goto done;
7885 	pos = strsep(&string, " \t");
7886 	if (pos)
7887 		d->qnum = (t_u32)woal_string_to_number(pos);
7888 
7889 	pos = strsep(&string, " \t");
7890 	if (pos)
7891 		d->aid = (t_u32)woal_string_to_number(pos);
7892 
7893 	pos = strsep(&string, " \t");
7894 	if (pos)
7895 		d->axq_mu_timer = (t_u32)woal_string_to_number(pos);
7896 
7897 	pos = strsep(&string, " \t");
7898 	if (pos)
7899 		d->tx_power = (t_u16)woal_string_to_number(pos);
7900 
7901 	if (d->enable > 1)
7902 		ret = -EINVAL;
7903 
7904 done:
7905 	kfree(string);
7906 	LEAVE();
7907 	return ret;
7908 }
7909 /*
7910  *  @brief This function enables/disables RF test mode in firmware
7911  *
7912  *  @param handle   A pointer to moal_handle structure
7913  *  @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING on success,
7914  *                  otherwise failure code
7915  */
woal_process_rf_test_mode(moal_handle * handle,t_u32 mode)7916 mlan_status woal_process_rf_test_mode(moal_handle *handle, t_u32 mode)
7917 {
7918 	mlan_status ret = MLAN_STATUS_FAILURE;
7919 	mlan_ioctl_req *req = NULL;
7920 	mlan_ds_misc_cfg *misc = NULL;
7921 	t_u32 flag = 0;
7922 
7923 	ENTER();
7924 #ifdef MFG_CMD_SUPPORT
7925 	if (mfg_mode) {
7926 		LEAVE();
7927 		return ret;
7928 	}
7929 #endif
7930 	if (mode != MFG_CMD_SET_TEST_MODE && mode != MFG_CMD_UNSET_TEST_MODE) {
7931 		LEAVE();
7932 		return ret;
7933 	}
7934 
7935 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
7936 	if (req) {
7937 		misc = (mlan_ds_misc_cfg *)req->pbuf;
7938 		misc->sub_command = MLAN_OID_MISC_RF_TEST_GENERIC;
7939 		req->req_id = MLAN_IOCTL_MISC_CFG;
7940 		req->action = MLAN_ACT_SET;
7941 		if (mode == MFG_CMD_SET_TEST_MODE)
7942 			misc->param.mfg_generic_cfg.mfg_cmd =
7943 				MFG_CMD_SET_TEST_MODE;
7944 		ret = woal_request_ioctl(woal_get_priv(handle,
7945 						       MLAN_BSS_ROLE_ANY),
7946 					 req, MOAL_IOCTL_WAIT);
7947 	}
7948 
7949 	if (ret == MLAN_STATUS_SUCCESS && mode == MFG_CMD_SET_TEST_MODE &&
7950 	    handle->rf_data == NULL) {
7951 		flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC :
7952 							  GFP_KERNEL;
7953 		/* Allocate memory to hold RF test mode data */
7954 		handle->rf_data =
7955 			kzalloc(sizeof(struct rf_test_mode_data), flag);
7956 		if (!handle->rf_data)
7957 			PRINTM(MERROR,
7958 			       "Couldn't allocate memory for RF test mode\n");
7959 		handle->rf_test_mode = MTRUE;
7960 		if (handle->rf_data) {
7961 			/* antenna is set to 1 by default */
7962 			handle->rf_data->tx_antenna = 1;
7963 			handle->rf_data->rx_antenna = 1;
7964 		}
7965 	} else if (mode == MFG_CMD_UNSET_TEST_MODE) {
7966 		if (handle->rf_data) {
7967 			/* Free RF test mode data memory */
7968 			kfree(handle->rf_data);
7969 			handle->rf_data = NULL;
7970 		}
7971 		handle->rf_test_mode = MFALSE;
7972 	}
7973 	if (ret != MLAN_STATUS_PENDING)
7974 		kfree(req);
7975 	LEAVE();
7976 	return ret;
7977 }
7978 
7979 /**
7980  *  @brief This function sends RF test mode command in firmware
7981  *
7982  *  @param handle   A pointer to moal_handle structure
7983  *  @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING on success,
7984  *                      otherwise failure code
7985  */
woal_process_rf_test_mode_cmd(moal_handle * handle,t_u32 cmd,const char * buffer,size_t len,t_u32 action,t_u32 val)7986 mlan_status woal_process_rf_test_mode_cmd(moal_handle *handle, t_u32 cmd,
7987 					  const char *buffer, size_t len,
7988 					  t_u32 action, t_u32 val)
7989 {
7990 	mlan_status ret = MLAN_STATUS_FAILURE;
7991 	mlan_ioctl_req *req = NULL;
7992 	mlan_ds_misc_cfg *misc = NULL;
7993 	int err = MFALSE;
7994 	int i;
7995 
7996 	ENTER();
7997 
7998 	if (!handle->rf_test_mode || !handle->rf_data)
7999 		goto done;
8000 
8001 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
8002 	if (!req)
8003 		goto done;
8004 
8005 	misc = (mlan_ds_misc_cfg *)req->pbuf;
8006 	req->req_id = MLAN_IOCTL_MISC_CFG;
8007 	misc->sub_command = MLAN_OID_MISC_RF_TEST_GENERIC;
8008 	req->action = action;
8009 
8010 	switch (cmd) {
8011 	case MFG_CMD_TX_ANT:
8012 		if (val != 1 && val != 2 && val != 3)
8013 			err = MTRUE;
8014 		break;
8015 	case MFG_CMD_RX_ANT:
8016 		if (val != 1 && val != 2 && val != 3)
8017 			err = MTRUE;
8018 		break;
8019 	case MFG_CMD_RF_BAND_AG:
8020 		if (val != 0 && val != 1)
8021 			err = MTRUE;
8022 		break;
8023 	case MFG_CMD_RF_CHANNELBW:
8024 		if (val != 0 && val != 1 &&
8025 		    (val != 4 ||
8026 		     (val == 4 && handle->rf_data->band == BAND_2GHZ)))
8027 			err = MTRUE;
8028 		break;
8029 	case MFG_CMD_RF_CHAN:
8030 		break;
8031 	case MFG_CMD_CLR_RX_ERR:
8032 		break;
8033 	case MFG_CMD_RADIO_MODE_CFG:
8034 		if (parse_radio_mode_string(buffer, len,
8035 					    &misc->param.mfg_generic_cfg))
8036 			err = MTRUE;
8037 		break;
8038 	case MFG_CMD_RFPWR:
8039 		if (parse_tx_pwr_string(handle, buffer, len,
8040 					&misc->param.mfg_generic_cfg))
8041 			err = MTRUE;
8042 		break;
8043 	case MFG_CMD_TX_CONT:
8044 		misc->sub_command = MLAN_OID_MISC_RF_TEST_TX_CONT;
8045 		if (parse_tx_cont_string(buffer, len, &misc->param.mfg_tx_cont))
8046 			err = MTRUE;
8047 		break;
8048 	case MFG_CMD_TX_FRAME:
8049 		misc->sub_command = MLAN_OID_MISC_RF_TEST_TX_FRAME;
8050 		if (parse_tx_frame_string(buffer, len,
8051 					  &misc->param.mfg_tx_frame2))
8052 			err = MTRUE;
8053 		break;
8054 	case MFG_CMD_CONFIG_MAC_HE_TB_TX:
8055 		misc->sub_command = MLAN_OID_MISC_RF_TEST_HE_POWER;
8056 		if (parse_he_tb_tx_string(buffer, len,
8057 					  &misc->param.mfg_he_power))
8058 			err = MTRUE;
8059 		break;
8060 	default:
8061 		err = MTRUE;
8062 	}
8063 
8064 	if (!err) {
8065 		misc->param.mfg_generic_cfg.mfg_cmd = (t_u32)cmd;
8066 		if (cmd != MFG_CMD_RFPWR &&
8067 		    misc->sub_command == MLAN_OID_MISC_RF_TEST_GENERIC)
8068 			misc->param.mfg_generic_cfg.data1 = val;
8069 
8070 		ret = woal_request_ioctl(woal_get_priv(handle,
8071 						       MLAN_BSS_ROLE_ANY),
8072 					 req, MOAL_IOCTL_WAIT);
8073 	}
8074 	if (ret != MLAN_STATUS_SUCCESS)
8075 		goto done;
8076 
8077 	switch (cmd) {
8078 	case MFG_CMD_TX_ANT:
8079 		handle->rf_data->tx_antenna = misc->param.mfg_generic_cfg.data1;
8080 		break;
8081 	case MFG_CMD_RX_ANT:
8082 		handle->rf_data->rx_antenna = misc->param.mfg_generic_cfg.data1;
8083 		break;
8084 	case MFG_CMD_RADIO_MODE_CFG:
8085 		handle->rf_data->radio_mode[0] =
8086 			misc->param.mfg_generic_cfg.data1;
8087 		handle->rf_data->radio_mode[1] =
8088 			misc->param.mfg_generic_cfg.data2;
8089 		break;
8090 	case MFG_CMD_RF_BAND_AG:
8091 		handle->rf_data->band = misc->param.mfg_generic_cfg.data1;
8092 		/* set fw default bw and channel config on band change */
8093 		handle->rf_data->bandwidth = CHANNEL_BW_20MHZ;
8094 		if (handle->rf_data->band == BAND_2GHZ)
8095 			handle->rf_data->channel = 6;
8096 		else if (handle->rf_data->band == BAND_5GHZ)
8097 			handle->rf_data->channel = 36;
8098 		break;
8099 	case MFG_CMD_RF_CHANNELBW:
8100 		handle->rf_data->bandwidth = misc->param.mfg_generic_cfg.data1;
8101 		break;
8102 	case MFG_CMD_RF_CHAN:
8103 		handle->rf_data->channel = misc->param.mfg_generic_cfg.data1;
8104 		break;
8105 	case MFG_CMD_CLR_RX_ERR:
8106 		handle->rf_data->rx_tot_pkt_count =
8107 			misc->param.mfg_generic_cfg.data1;
8108 		handle->rf_data->rx_mcast_bcast_pkt_count =
8109 			misc->param.mfg_generic_cfg.data2;
8110 		handle->rf_data->rx_pkt_fcs_err_count =
8111 			misc->param.mfg_generic_cfg.data3;
8112 		break;
8113 	case MFG_CMD_RFPWR:
8114 		handle->rf_data->tx_power_data[0] =
8115 			misc->param.mfg_generic_cfg.data1;
8116 		handle->rf_data->tx_power_data[1] =
8117 			misc->param.mfg_generic_cfg.data2;
8118 		handle->rf_data->tx_power_data[2] =
8119 			misc->param.mfg_generic_cfg.data3;
8120 		break;
8121 	case MFG_CMD_TX_CONT:
8122 		handle->rf_data->tx_cont_data[0] =
8123 			misc->param.mfg_tx_cont.enable_tx;
8124 		handle->rf_data->tx_cont_data[1] =
8125 			misc->param.mfg_tx_cont.cw_mode;
8126 		handle->rf_data->tx_cont_data[2] =
8127 			misc->param.mfg_tx_cont.payload_pattern;
8128 		handle->rf_data->tx_cont_data[3] =
8129 			misc->param.mfg_tx_cont.cs_mode;
8130 		handle->rf_data->tx_cont_data[4] =
8131 			misc->param.mfg_tx_cont.act_sub_ch;
8132 		handle->rf_data->tx_cont_data[5] =
8133 			misc->param.mfg_tx_cont.tx_rate;
8134 		break;
8135 	case MFG_CMD_TX_FRAME:
8136 		handle->rf_data->tx_frame_data[0] =
8137 			misc->param.mfg_tx_frame2.enable;
8138 		handle->rf_data->tx_frame_data[1] =
8139 			misc->param.mfg_tx_frame2.data_rate;
8140 		handle->rf_data->tx_frame_data[2] =
8141 			misc->param.mfg_tx_frame2.frame_pattern;
8142 		handle->rf_data->tx_frame_data[3] =
8143 			misc->param.mfg_tx_frame2.frame_length;
8144 		handle->rf_data->tx_frame_data[4] =
8145 			misc->param.mfg_tx_frame2.adjust_burst_sifs;
8146 		handle->rf_data->tx_frame_data[5] =
8147 			misc->param.mfg_tx_frame2.burst_sifs_in_us;
8148 		handle->rf_data->tx_frame_data[6] =
8149 			misc->param.mfg_tx_frame2.short_preamble;
8150 		handle->rf_data->tx_frame_data[7] =
8151 			misc->param.mfg_tx_frame2.act_sub_ch;
8152 		handle->rf_data->tx_frame_data[8] =
8153 			misc->param.mfg_tx_frame2.short_gi;
8154 		handle->rf_data->tx_frame_data[9] =
8155 			misc->param.mfg_tx_frame2.adv_coding;
8156 		handle->rf_data->tx_frame_data[10] =
8157 			misc->param.mfg_tx_frame2.tx_bf;
8158 		handle->rf_data->tx_frame_data[11] =
8159 			misc->param.mfg_tx_frame2.gf_mode;
8160 		handle->rf_data->tx_frame_data[12] =
8161 			misc->param.mfg_tx_frame2.stbc;
8162 		handle->rf_data->tx_frame_data[13] =
8163 			misc->param.mfg_tx_frame2.NumPkt;
8164 		handle->rf_data->tx_frame_data[14] =
8165 			misc->param.mfg_tx_frame2.MaxPE;
8166 		handle->rf_data->tx_frame_data[15] =
8167 			misc->param.mfg_tx_frame2.BeamChange;
8168 		handle->rf_data->tx_frame_data[16] =
8169 			misc->param.mfg_tx_frame2.Dcm;
8170 		handle->rf_data->tx_frame_data[17] =
8171 			misc->param.mfg_tx_frame2.Doppler;
8172 		handle->rf_data->tx_frame_data[18] =
8173 			misc->param.mfg_tx_frame2.MidP;
8174 		handle->rf_data->tx_frame_data[19] =
8175 			misc->param.mfg_tx_frame2.QNum;
8176 		for (i = 0; i < ETH_ALEN; i++) {
8177 			handle->rf_data->bssid[i] =
8178 				misc->param.mfg_tx_frame2.bssid[i];
8179 		}
8180 		break;
8181 	case MFG_CMD_CONFIG_MAC_HE_TB_TX:
8182 		handle->rf_data->he_tb_tx[0] = misc->param.mfg_he_power.enable;
8183 		handle->rf_data->he_tb_tx[1] = misc->param.mfg_he_power.qnum;
8184 		handle->rf_data->he_tb_tx[2] = misc->param.mfg_he_power.aid;
8185 		handle->rf_data->he_tb_tx[3] =
8186 			misc->param.mfg_he_power.axq_mu_timer;
8187 		handle->rf_data->he_tb_tx[4] =
8188 			misc->param.mfg_he_power.tx_power;
8189 		break;
8190 	}
8191 done:
8192 	if (err || ret != MLAN_STATUS_PENDING)
8193 		kfree(req);
8194 
8195 	LEAVE();
8196 	return ret;
8197 }
8198 #endif /* RF_TEST_MODE */
8199