xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/mvl88w8977/mlinux/moal_ioctl.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /** @file moal_ioctl.c
2   *
3   * @brief This file contains ioctl function to MLAN
4   *
5   * Copyright (C) 2008-2017, Marvell International Ltd.
6   *
7   * This software file (the "File") is distributed by Marvell International
8   * Ltd. under the terms of the GNU General Public License Version 2, June 1991
9   * (the "License").  You may use, redistribute and/or modify this File in
10   * accordance with the terms and conditions of the License, a copy of which
11   * is available by writing to the Free Software Foundation, Inc.,
12   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
13   * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
14   *
15   * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
16   * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
17   * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
18   * this warranty disclaimer.
19   *
20   */
21 
22 /********************************************************
23 Change log:
24     10/21/2008: initial version
25 ********************************************************/
26 
27 #include    "moal_main.h"
28 #include    "moal_eth_ioctl.h"
29 #include    "moal_sdio.h"
30 #ifdef UAP_SUPPORT
31 #include    "moal_uap.h"
32 #endif
33 
34 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
35 #include "moal_cfg80211.h"
36 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
37 #include "moal_cfgvendor.h"
38 #endif
39 #endif
40 
41 /********************************************************
42 			Local Variables
43 ********************************************************/
44 #define MRVL_TLV_HEADER_SIZE            4
45 /* Marvell Channel config TLV ID */
46 #define MRVL_CHANNELCONFIG_TLV_ID       (0x0100 + 0x2a)	/* 0x012a */
47 
48 typedef struct _hostcmd_header {
49     /** Command Header : Command */
50 	t_u16 command;
51     /** Command Header : Size */
52 	t_u16 size;
53     /** Command Header : Sequence number */
54 	t_u16 seq_num;
55     /** Command Header : Result */
56 	t_u16 result;
57     /** Command action */
58 	t_u16 action;
59 } hostcmd_header, *phostcmd_header;
60 
61 /** Region code mapping */
62 typedef struct _region_code_mapping_t {
63     /** Region */
64 	t_u8 region[COUNTRY_CODE_LEN];
65     /** Code */
66 	t_u8 code;
67 } region_code_mapping_t;
68 
69 #define EU_REGION_CODE 0x30
70 
71 /** Region code mapping table */
72 static region_code_mapping_t region_code_mapping[] = {
73 	{"US ", 0x10},		/* US FCC            */
74 	{"CA ", 0x20},		/* IC Canada         */
75 	{"SG ", 0x10},		/* Singapore         */
76 	{"EU ", 0x30},		/* ETSI              */
77 	{"AU ", 0x30},		/* Australia         */
78 	{"KR ", 0x30},		/* Republic Of Korea */
79 	{"CN ", 0x50},		/* China             */
80 	{"JP ", 0xFF},		/* Japan special     */
81 };
82 
83 /** EEPROM Region code mapping table */
84 static region_code_mapping_t hw_region_code_mapping[] = {
85 	{"US ", 0x10},		/* US FCC      */
86 	{"CA ", 0x20},		/* IC Canada   */
87 	{"KR ", 0x30},		/* Korea       */
88 	{"CN ", 0x50},		/* China       */
89 	{"ES ", 0x31},		/* Spain       */
90 	{"FR ", 0x32},		/* France      */
91 	{"JP ", 0x40},		/* Japan       */
92 	{"JP ", 0x41},		/* Japan       */
93 };
94 
95 /** Country code for ETSI */
96 static t_u8 eu_country_code_table[][COUNTRY_CODE_LEN] = {
97 	"AL", "AD", "AT", "AU", "BY", "BE", "BA", "BG", "HR", "CY",
98 	"CZ", "DK", "EE", "FI", "FR", "MK", "DE", "GR", "HU", "IS",
99 	"IE", "IT", "KR", "LV", "LI", "LT", "LU", "MT", "MD", "MC",
100 	"ME", "NL", "NO", "PL", "RO", "RU", "SM", "RS", "SI", "SK",
101 	"ES", "SE", "CH", "TR", "UA", "UK", "GB"
102 };
103 
104 /********************************************************
105 			Global Variables
106 ********************************************************/
107 
108 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
109 #ifdef UAP_SUPPORT
110 /** Network device handlers for uAP */
111 extern const struct net_device_ops woal_uap_netdev_ops;
112 #endif
113 #ifdef STA_SUPPORT
114 /** Network device handlers for STA */
115 extern const struct net_device_ops woal_netdev_ops;
116 #endif
117 #endif
118 extern int cfg80211_wext;
119 int disconnect_on_suspend;
120 
121 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
122 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
123 extern int dfs_offload;
124 #endif
125 #endif
126 
127 extern int roamoffload_in_hs;
128 
129 /** gtk rekey offload mode */
130 extern int gtk_rekey_offload;
131 
132 /********************************************************
133 			Local Functions
134 ********************************************************/
135 /**
136  *  @brief This function converts region string to region code
137  *
138  *  @param region_string    Region string
139  *
140  *  @return                 Region code
141  */
142 t_u8
region_string_2_region_code(char * region_string)143 region_string_2_region_code(char *region_string)
144 {
145 	t_u8 i;
146 
147 	ENTER();
148 	for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
149 		if (!memcmp(region_string,
150 			    region_code_mapping[i].region,
151 			    strlen(region_string))) {
152 			LEAVE();
153 			return region_code_mapping[i].code;
154 		}
155 	}
156 
157 	/* If still not found, look for code in EU country code table */
158 	for (i = 0; i < ARRAY_SIZE(eu_country_code_table); i++) {
159 		if (!memcmp(region_string, eu_country_code_table[i],
160 			    COUNTRY_CODE_LEN - 1)) {
161 			PRINTM(MIOCTL, "found region code=%d in EU table\n",
162 			       EU_REGION_CODE);
163 			LEAVE();
164 			return EU_REGION_CODE;
165 		}
166 	}
167 
168 	/* Default is US */
169 	LEAVE();
170 	return region_code_mapping[0].code;
171 }
172 
173 /**
174  *  @brief This function converts region string to region code
175  *
176  *  @param country_code     Region string
177  *
178  *  @return                 Region code
179  */
180 t_bool
woal_is_etsi_country(t_u8 * country_code)181 woal_is_etsi_country(t_u8 *country_code)
182 {
183 
184 	t_u8 i;
185 	ENTER();
186 
187 	for (i = 0; i < ARRAY_SIZE(eu_country_code_table); i++) {
188 		if (!memcmp(country_code, eu_country_code_table[i],
189 			    COUNTRY_CODE_LEN - 1)) {
190 			PRINTM(MIOCTL, "found region code=%d in EU table\n",
191 			       EU_REGION_CODE);
192 			LEAVE();
193 			return MTRUE;
194 		}
195 	}
196 
197 	LEAVE();
198 	return MFALSE;
199 }
200 
201 /**
202  *  @brief This function converts region string to region code
203  *
204  *  @param region_code      region code
205  *
206  *  @return                 Region string or NULL
207  */
208 char *
region_code_2_string(t_u8 region_code)209 region_code_2_string(t_u8 region_code)
210 {
211 	t_u8 i;
212 
213 	ENTER();
214 	for (i = 0; i < ARRAY_SIZE(hw_region_code_mapping); i++) {
215 		if (hw_region_code_mapping[i].code == region_code) {
216 			LEAVE();
217 			return hw_region_code_mapping[i].region;
218 		}
219 	}
220 	LEAVE();
221 	return NULL;
222 }
223 
224 t_u8
woal_is_valid_alpha2(char * alpha2)225 woal_is_valid_alpha2(char *alpha2)
226 {
227 	if (!alpha2 || strlen(alpha2) < 2)
228 		return MFALSE;
229 	if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
230 		return MTRUE;
231 	return MFALSE;
232 }
233 
234 /**
235  *  @brief Copy mc address to the mlist
236  *
237  *  @param mlist    A pointer to mlan_multicast_list structure
238  *  @param mac      mc address
239  *
240  *  @return         N/A
241  */
242 static inline void
woal_copy_mc_addr(mlan_multicast_list * mlist,mlan_802_11_mac_addr mac)243 woal_copy_mc_addr(mlan_multicast_list *mlist, mlan_802_11_mac_addr mac)
244 {
245 	int i = 0;
246 	for (i = 0; i < mlist->num_multicast_addr; i++) {
247 		if (!memcmp(&mlist->mac_list[i], mac, ETH_ALEN))
248 			return;
249 	}
250 	if (mlist->num_multicast_addr < MLAN_MAX_MULTICAST_LIST_SIZE)
251 		memcpy(&mlist->mac_list[mlist->num_multicast_addr], mac,
252 		       ETH_ALEN);
253 	mlist->num_multicast_addr++;
254 	return;
255 }
256 
257 /**
258  *  @brief Copy multicast table
259  *
260  *  @param mlist    A pointer to mlan_multicast_list structure
261  *  @param dev      A pointer to net_device structure
262  *
263  *  @return         Number of multicast addresses
264  */
265 static inline int
woal_copy_mcast_addr(mlan_multicast_list * mlist,struct net_device * dev)266 woal_copy_mcast_addr(mlan_multicast_list *mlist, struct net_device *dev)
267 {
268 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
269 	struct dev_mc_list *mcptr = dev->mc_list;
270 	int i = 0;
271 #else
272 	struct netdev_hw_addr *mcptr = NULL;
273 #endif /* < 2.6.35 */
274 
275 	ENTER();
276 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
277 	for (i = 0; i < dev->mc_count && mcptr; i++) {
278 		woal_copy_mc_addr(mlist, mcptr->dmi_addr);
279 		mcptr = mcptr->next;
280 	}
281 #else
282 	netdev_for_each_mc_addr(mcptr, dev)
283 		woal_copy_mc_addr(mlist, mcptr->addr);
284 #endif /* < 2.6.35 */
285 	LEAVE();
286 	return mlist->num_multicast_addr;
287 }
288 
289 /**
290  *  @brief copy mc list from all the active interface
291  *
292  *  @param handle  A pointer to moal_handle
293  *  @param mlist  A pointer to multicast list
294  *
295  *  @return       total_mc_count
296  */
297 static int
woal_copy_all_mc_list(moal_handle * handle,mlan_multicast_list * mlist)298 woal_copy_all_mc_list(moal_handle *handle, mlan_multicast_list *mlist)
299 {
300 	int i;
301 	moal_private *priv = NULL;
302 #ifdef STA_SUPPORT
303 	int mc_count = 0;
304 #endif
305 	ENTER();
306 	for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) {
307 #ifdef STA_SUPPORT
308 		if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA) {
309 			if (handle->priv[i]->media_connected == MTRUE) {
310 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
311 				mc_count = priv->netdev->mc_count;
312 #else
313 				mc_count = netdev_mc_count(priv->netdev);
314 #endif
315 				if (mc_count)
316 					woal_copy_mcast_addr(mlist,
317 							     priv->netdev);
318 			}
319 		}
320 #endif
321 	}
322 	PRINTM(MIOCTL, "total mc_count=%d\n", mlist->num_multicast_addr);
323 	LEAVE();
324 	return mlist->num_multicast_addr;
325 }
326 
327 /**
328  *  @brief Fill in wait queue
329  *
330  *  @param priv         A pointer to moal_private structure
331  *  @param wait         A pointer to wait_queue structure
332  *  @param wait_option  Wait option
333  *
334  *  @return             N/A
335  */
336 static inline void
woal_fill_wait_queue(moal_private * priv,wait_queue * wait,t_u8 wait_option)337 woal_fill_wait_queue(moal_private *priv, wait_queue *wait, t_u8 wait_option)
338 {
339 	ENTER();
340 	wait->start_time = jiffies;
341 	wait->condition = MFALSE;
342 	wait->wait_timeout = MFALSE;
343 	switch (wait_option) {
344 	case MOAL_NO_WAIT:
345 		break;
346 	case MOAL_IOCTL_WAIT:
347 		init_waitqueue_head(&wait->wait);
348 		break;
349 	case MOAL_IOCTL_WAIT_TIMEOUT:
350 		init_waitqueue_head(&wait->wait);
351 		wait->wait_timeout = MTRUE;
352 		break;
353 	}
354 	LEAVE();
355 	return;
356 }
357 
358 /**
359  *  @brief Wait mlan ioctl complete
360  *
361  *  @param priv         A pointer to moal_private structure
362  *  @param req          A pointer to mlan_ioctl_req structure
363  *  @param wait_option  Wait option
364  *
365  *  @return             N/A
366  */
367 static inline mlan_status
woal_wait_ioctl_complete(moal_private * priv,mlan_ioctl_req * req,t_u8 wait_option)368 woal_wait_ioctl_complete(moal_private *priv, mlan_ioctl_req *req,
369 			 t_u8 wait_option)
370 {
371 	mlan_status status;
372 	wait_queue *wait = (wait_queue *)req->reserved_1;
373 	unsigned long flags;
374 
375 	ENTER();
376 
377 	priv->phandle->ioctl_timeout = MFALSE;
378 
379 	switch (wait_option) {
380 	case MOAL_NO_WAIT:
381 		break;
382 	case MOAL_IOCTL_WAIT:
383 		while (wait_event_interruptible_exclusive
384 		       (wait->wait, wait->condition)
385 		       == -ERESTARTSYS && wait->retry < MAX_RETRY_CNT) {
386 			wait->retry++;
387 		}
388 		break;
389 	case MOAL_IOCTL_WAIT_TIMEOUT:
390 		wait_event_timeout(wait->wait, wait->condition,
391 				   MOAL_IOCTL_TIMEOUT);
392 		break;
393 	}
394 	spin_lock_irqsave(&priv->phandle->driver_lock, flags);
395 	if (wait->condition == MFALSE) {
396 		if (wait_option == MOAL_IOCTL_WAIT_TIMEOUT) {
397 			priv->phandle->ioctl_timeout = MTRUE;
398 			PRINTM(MMSG,
399 			       "wlan: IOCTL timeout %p id=0x%x, sub_id=0x%x, wait_option=%d, action=%d\n",
400 			       req, req->req_id, (*(t_u32 *)req->pbuf),
401 			       wait_option, (int)req->action);
402 		} else {
403 			PRINTM(MMSG,
404 			       "wlan: IOCTL by signal %p id=0x%x, sub_id=0x%x, wait_option=%d, action=%d\n",
405 			       req, req->req_id, (*(t_u32 *)req->pbuf),
406 			       wait_option, (int)req->action);
407 		}
408 		req->reserved_1 = 0;
409 		status = MLAN_STATUS_PENDING;
410 	} else {
411 		status = wait->status;
412 	}
413 	spin_unlock_irqrestore(&priv->phandle->driver_lock, flags);
414 
415 	LEAVE();
416 	return status;
417 }
418 
419 /**
420  *  @brief CAC period block cmd handler
421  *
422  *  @param priv     A pointer to moal_private structure
423  *  @param req      A pointer to mlan_ioctl_req buffer
424  *
425  *  @return         MTRUE/MFALSE
426  */
427 static inline t_bool
woal_cac_period_block_cmd(moal_private * priv,pmlan_ioctl_req req)428 woal_cac_period_block_cmd(moal_private *priv, pmlan_ioctl_req req)
429 {
430 	mlan_status ret = MFALSE;
431 	t_u32 sub_command;
432 
433 	ENTER();
434 	if (req == NULL || req->pbuf == NULL)
435 		goto done;
436 
437 	sub_command = *(t_u32 *)req->pbuf;
438 
439 	switch (req->req_id) {
440 	case MLAN_IOCTL_SCAN:
441 		if (sub_command == MLAN_OID_SCAN_NORMAL ||
442 		    sub_command == MLAN_OID_SCAN_SPECIFIC_SSID ||
443 		    sub_command == MLAN_OID_SCAN_USER_CONFIG)
444 			ret = MTRUE;
445 		break;
446 	case MLAN_IOCTL_BSS:
447 		if (sub_command == MLAN_OID_BSS_STOP ||
448 		    sub_command == MLAN_OID_BSS_CHANNEL
449 		    /* sub_command == MLAN_OID_BSS_ROLE */ )
450 			ret = MTRUE;
451 #ifdef UAP_SUPPORT
452 		else if (sub_command == MLAN_OID_UAP_BSS_CONFIG) {
453 			mlan_ds_bss *bss = (mlan_ds_bss *)req->pbuf;
454 			if (bss->param.bss_config.channel)
455 				ret = MTRUE;
456 			else
457 				ret = MFALSE;
458 		}
459 #endif
460 		break;
461 	case MLAN_IOCTL_RADIO_CFG:
462 		if (sub_command == MLAN_OID_BAND_CFG)
463 			ret = MTRUE;
464 		break;
465 	case MLAN_IOCTL_SNMP_MIB:
466 		if (sub_command == MLAN_OID_SNMP_MIB_DOT11D)
467 			ret = MTRUE;
468 #if defined(UAP_SUPPORT)
469 		if (sub_command == MLAN_OID_SNMP_MIB_DOT11H)
470 			ret = MTRUE;
471 #endif
472 		break;
473 	case MLAN_IOCTL_11D_CFG:
474 #ifdef STA_SUPPORT
475 		if (sub_command == MLAN_OID_11D_CFG_ENABLE)
476 			ret = MTRUE;
477 #endif
478 		if (sub_command == MLAN_OID_11D_DOMAIN_INFO)
479 			ret = MTRUE;
480 		break;
481 	case MLAN_IOCTL_MISC_CFG:
482 		if (sub_command == MLAN_OID_MISC_REGION)
483 			ret = MTRUE;
484 		if (sub_command == MLAN_OID_MISC_HOST_CMD) {
485 			phostcmd_header phostcmd;
486 			t_u8 *ptlv_buf;
487 			t_u16 tag, length;
488 
489 			phostcmd =
490 				(phostcmd_header)((pmlan_ds_misc_cfg)req->
491 						  pbuf)->param.hostcmd.cmd;
492 			ptlv_buf = (t_u8 *)phostcmd + sizeof(hostcmd_header);
493 			if (phostcmd->action == MLAN_ACT_SET) {
494 				while (ptlv_buf <
495 				       (t_u8 *)phostcmd + phostcmd->size) {
496 					tag = *(t_u16 *)ptlv_buf;
497 					length = *(t_u16 *)(ptlv_buf + 2);
498 					/* Check Blocking TLV here, should add more... */
499 					if (tag == MRVL_CHANNELCONFIG_TLV_ID) {
500 						ret = MTRUE;
501 						break;
502 					}
503 					ptlv_buf +=
504 						(length + MRVL_TLV_HEADER_SIZE);
505 				}
506 			}
507 		}
508 		break;
509 	case MLAN_IOCTL_11H_CFG:
510 		/* Prevent execute more than once */
511 		if (sub_command == MLAN_OID_11H_CHANNEL_CHECK)
512 			ret = MTRUE;
513 		break;
514 	default:
515 		ret = MFALSE;
516 		break;
517 	}
518 
519 done:
520 	LEAVE();
521 	return ret;
522 }
523 
524 /********************************************************
525 			Global Functions
526 ********************************************************/
527 
528 /**
529  *  @brief Send ioctl request to MLAN
530  *
531  *  @param priv          A pointer to moal_private structure
532  *  @param req           A pointer to mlan_ioctl_req buffer
533  *  @param wait_option   Wait option (MOAL_IOCTL_WAIT or MOAL_NO_WAIT)
534  *
535  *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
536  *                          -- success, otherwise fail
537  */
538 mlan_status
woal_request_ioctl(moal_private * priv,mlan_ioctl_req * req,t_u8 wait_option)539 woal_request_ioctl(moal_private *priv, mlan_ioctl_req *req, t_u8 wait_option)
540 {
541 	wait_queue *wait = NULL;
542 	mlan_status status;
543 	unsigned long flags;
544 	t_u32 sub_command = *(t_u32 *)req->pbuf;
545 
546 	ENTER();
547 
548 	if (!priv) {
549 		LEAVE();
550 		return MLAN_STATUS_FAILURE;
551 	}
552 	if (sub_command != MLAN_OID_GET_DEBUG_INFO) {
553 		if (priv->phandle->surprise_removed == MTRUE ||
554 		    priv->phandle->driver_state) {
555 			PRINTM(MERROR,
556 			       "IOCTL is not allowed while the device is not present or hang\n");
557 			LEAVE();
558 			return MLAN_STATUS_FAILURE;
559 		}
560 #if defined(SDIO_SUSPEND_RESUME)
561 		if (priv->phandle->is_suspended == MTRUE) {
562 			PRINTM(MERROR,
563 			       "IOCTL is not allowed while suspended\n");
564 			LEAVE();
565 			return MLAN_STATUS_FAILURE;
566 		}
567 #endif
568 	}
569 	/* For MLAN_OID_MISC_HOST_CMD, action is 0, "action set" is checked later */
570 	if ((req->action == MLAN_ACT_SET || req->action == 0) &&
571 	    priv->phandle->cac_period == MTRUE) {
572 
573 		/* CAC checking period left to complete jiffies */
574 		long cac_left_jiffies;
575 
576 		/* cac_left_jiffies will be negative if and only if
577 		 * event MLAN_EVENT_ID_DRV_MEAS_REPORT recieved from FW
578 		 * after CAC measure period ends,
579 		 * usually this could be considered as a FW bug
580 		 */
581 		cac_left_jiffies = priv->phandle->cac_timer_jiffies -
582 			(jiffies - priv->phandle->meas_start_jiffies);
583 #ifdef DFS_TESTING_SUPPORT
584 		if (priv->phandle->cac_period_jiffies) {
585 			cac_left_jiffies = priv->phandle->cac_period_jiffies -
586 				(jiffies - priv->phandle->meas_start_jiffies);
587 		}
588 #endif
589 		if (cac_left_jiffies < 0) {
590 			/* Avoid driver hang in FW died during CAC measure period */
591 			priv->phandle->cac_period = MFALSE;
592 			PRINTM(MERROR,
593 			       "CAC measure period spends longer than scheduled time "
594 			       "or meas done event never received\n");
595 			status = MLAN_STATUS_FAILURE;
596 #ifdef UAP_SUPPORT
597 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
598 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
599 			if (priv->uap_host_based && dfs_offload)
600 				woal_cfg80211_dfs_vendor_event(priv,
601 							       event_dfs_cac_aborted,
602 							       &priv->chan);
603 #endif
604 #endif
605 #endif
606 
607 			goto done;
608 		}
609 
610 		/* Check BSS START first */
611 		if (sub_command == MLAN_OID_BSS_START) {
612 			mlan_ds_bss *bss;
613 			bss = (mlan_ds_bss *)req->pbuf;
614 			/*
615 			 * Bss delay start after channel report received,
616 			 * not block the driver by delay executing. This is
617 			 * because a BSS_START cmd is always executed right
618 			 * after channel check issued.
619 			 */
620 			if (priv->phandle->delay_bss_start == MFALSE) {
621 				PRINTM(MMSG,
622 				       "Received BSS Start command during CAC period, delay executing %ld seconds\n",
623 				       cac_left_jiffies / HZ);
624 				priv->phandle->delay_bss_start = MTRUE;
625 				memcpy(&priv->phandle->delay_ssid_bssid,
626 				       &bss->param.ssid_bssid,
627 				       sizeof(mlan_ssid_bssid));
628 				/* TODO: return success to allow the half below of routines
629 				 * of which calling BSS start to execute
630 				 */
631 				status = MLAN_STATUS_SUCCESS;
632 				goto done;
633 			} else {
634 				/* TODO: not blocking it, just return failure */
635 				PRINTM(MMSG,
636 				       "Only one BSS Start command allowed for delay executing!\n");
637 				status = MLAN_STATUS_FAILURE;
638 				goto done;
639 			}
640 		}
641 		if (woal_cac_period_block_cmd(priv, req)) {
642 			priv->phandle->meas_wait_q_woken = MFALSE;
643 			PRINTM(MMSG,
644 			       "CAC check is on going... Blocking Command %ld seconds\n",
645 			       cac_left_jiffies / HZ);
646 			/* blocking timeout set to 1.5 * CAC checking period left time */
647 			wait_event_interruptible_timeout(priv->phandle->
648 							 meas_wait_q,
649 							 priv->phandle->
650 							 meas_wait_q_woken,
651 							 cac_left_jiffies * 3 /
652 							 2);
653 		}
654 	}
655 #ifdef UAP_CFG80211
656 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
657 	else if (priv->phandle->is_cac_timer_set &&
658 		 (req->action == MLAN_ACT_SET || req->action == 0)) {
659 		if (woal_cac_period_block_cmd(priv, req)) {
660 			PRINTM(MMSG,
661 			       "CAC check is on going... Blocking Command\n");
662 			status = MLAN_STATUS_FAILURE;
663 			goto done;
664 		}
665 	}
666 #endif
667 #endif
668 	else if (priv->phandle->cac_period) {
669 		PRINTM(MINFO, "Operation during CAC check period.\n");
670 	}
671 	wait = (wait_queue *)req->reserved_1;
672 	req->bss_index = priv->bss_index;
673 	if (wait_option)
674 		woal_fill_wait_queue(priv, wait, wait_option);
675 	else
676 		req->reserved_1 = 0;
677 
678 	/* Call MLAN ioctl handle */
679 	atomic_inc(&priv->phandle->ioctl_pending);
680 	spin_lock_irqsave(&priv->phandle->ioctl_lock, flags);
681 	status = mlan_ioctl(priv->phandle->pmlan_adapter, req);
682 	spin_unlock_irqrestore(&priv->phandle->ioctl_lock, flags);
683 	switch (status) {
684 	case MLAN_STATUS_PENDING:
685 		if (wait_option == MOAL_NO_WAIT)
686 			PRINTM(MIOCTL, "IOCTL MOAL_NO_WAIT: %p\n", req);
687 		else
688 			PRINTM(MIOCTL,
689 			       "IOCTL pending: %p id=0x%x, sub_id=0x%x wait_option=%d, action=%d\n",
690 			       req, req->req_id, (*(t_u32 *)req->pbuf),
691 			       wait_option, (int)req->action);
692 		/* Status pending, wake up main process */
693 		queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
694 
695 		/* Wait for completion */
696 		if (wait_option)
697 			status = woal_wait_ioctl_complete(priv, req,
698 							  wait_option);
699 		break;
700 	case MLAN_STATUS_SUCCESS:
701 	case MLAN_STATUS_FAILURE:
702 	case MLAN_STATUS_RESOURCE:
703 		PRINTM(MIOCTL,
704 		       "IOCTL: %p id=0x%x, sub_id=0x%x wait_option=%d, action=%d status=%d\n",
705 		       req, req->req_id, (*(t_u32 *)req->pbuf), wait_option,
706 		       (int)req->action, status);
707 		atomic_dec(&priv->phandle->ioctl_pending);
708 		break;
709 	default:
710 		atomic_dec(&priv->phandle->ioctl_pending);
711 		break;
712 	}
713 
714 done:
715 	LEAVE();
716 	return status;
717 }
718 
719 /**
720  *  @brief Send set MAC address request to MLAN
721  *
722  *  @param priv   A pointer to moal_private structure
723  *
724  *  @return       MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
725  *                  -- success, otherwise fail
726  */
727 mlan_status
woal_request_set_mac_address(moal_private * priv)728 woal_request_set_mac_address(moal_private *priv)
729 {
730 	mlan_ioctl_req *req = NULL;
731 	mlan_ds_bss *bss = NULL;
732 	mlan_status status;
733 	ENTER();
734 
735 	/* Allocate an IOCTL request buffer */
736 	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
737 	if (req == NULL) {
738 		status = MLAN_STATUS_FAILURE;
739 		goto done;
740 	}
741 
742 	/* Fill request buffer */
743 	bss = (mlan_ds_bss *)req->pbuf;
744 	bss->sub_command = MLAN_OID_BSS_MAC_ADDR;
745 	memcpy(&bss->param.mac_addr, priv->current_addr,
746 	       sizeof(mlan_802_11_mac_addr));
747 	req->req_id = MLAN_IOCTL_BSS;
748 	req->action = MLAN_ACT_SET;
749 
750 	/* Send IOCTL request to MLAN */
751 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
752 	if (status == MLAN_STATUS_SUCCESS) {
753 		memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN);
754 		HEXDUMP("priv->MacAddr:", priv->current_addr, ETH_ALEN);
755 	} else {
756 		PRINTM(MERROR,
757 		       "set mac address failed! status=%d, error_code=0x%x\n",
758 		       status, req->status_code);
759 	}
760 done:
761 	if (status != MLAN_STATUS_PENDING)
762 		kfree(req);
763 	LEAVE();
764 	return status;
765 }
766 
767 /**
768  *  @brief Send multicast list request to MLAN
769  *
770  *  @param priv   A pointer to moal_private structure
771  *  @param dev    A pointer to net_device structure
772  *
773  *  @return       N/A
774  */
775 void
woal_request_set_multicast_list(moal_private * priv,struct net_device * dev)776 woal_request_set_multicast_list(moal_private *priv, struct net_device *dev)
777 {
778 	mlan_ioctl_req *req = NULL;
779 	mlan_ds_bss *bss = NULL;
780 	mlan_status status;
781 	int mc_count = 0;
782 
783 	ENTER();
784 
785 	/* Allocate an IOCTL request buffer */
786 	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
787 	if (req == NULL) {
788 		PRINTM(MERROR, "%s:Fail to allocate ioctl req buffer\n",
789 		       __func__);
790 		goto done;
791 	}
792 
793 	/* Fill request buffer */
794 	bss = (mlan_ds_bss *)req->pbuf;
795 	bss->sub_command = MLAN_OID_BSS_MULTICAST_LIST;
796 	req->req_id = MLAN_IOCTL_BSS;
797 	req->action = MLAN_ACT_SET;
798 	if (dev->flags & IFF_PROMISC) {
799 		bss->param.multicast_list.mode = MLAN_PROMISC_MODE;
800 	} else if (dev->flags & IFF_ALLMULTI) {
801 		bss->param.multicast_list.mode = MLAN_ALL_MULTI_MODE;
802 	} else {
803 		bss->param.multicast_list.mode = MLAN_MULTICAST_MODE;
804 		mc_count =
805 			woal_copy_all_mc_list(priv->phandle,
806 					      &bss->param.multicast_list);
807 		if (mc_count > MLAN_MAX_MULTICAST_LIST_SIZE)
808 			bss->param.multicast_list.mode = MLAN_ALL_MULTI_MODE;
809 	}
810 
811 	/* Send IOCTL request to MLAN */
812 	status = woal_request_ioctl(priv, req, MOAL_NO_WAIT);
813 	if (status != MLAN_STATUS_PENDING)
814 		kfree(req);
815 done:
816 	LEAVE();
817 	return;
818 }
819 
820 /**
821  *  @brief Send deauth command to MLAN
822  *
823  *  @param priv          A pointer to moal_private structure
824  *  @param wait_option          Wait option
825  *  @param mac           MAC address to deauthenticate
826  *  @param reason_code   reason code to deauthenticate
827  *
828  *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
829  */
830 mlan_status
woal_disconnect(moal_private * priv,t_u8 wait_option,t_u8 * mac,t_u16 reason_code)831 woal_disconnect(moal_private *priv, t_u8 wait_option, t_u8 *mac,
832 		t_u16 reason_code)
833 {
834 	mlan_ioctl_req *req = NULL;
835 	mlan_ds_bss *bss = NULL;
836 	mlan_status status;
837 
838 	ENTER();
839 
840 	/* Allocate an IOCTL request buffer */
841 	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
842 	if (req == NULL) {
843 		status = MLAN_STATUS_FAILURE;
844 		goto done;
845 	}
846 
847 	/* Fill request buffer */
848 	bss = (mlan_ds_bss *)req->pbuf;
849 	bss->sub_command = MLAN_OID_BSS_STOP;
850 	if (mac)
851 		memcpy(&bss->param.deauth_param.mac_addr, mac,
852 		       sizeof(mlan_802_11_mac_addr));
853 	bss->param.deauth_param.reason_code = reason_code;
854 	req->req_id = MLAN_IOCTL_BSS;
855 	req->action = MLAN_ACT_SET;
856 
857 	/* Send IOCTL request to MLAN */
858 	status = woal_request_ioctl(priv, req, wait_option);
859 
860 done:
861 	if (status != MLAN_STATUS_PENDING)
862 		kfree(req);
863 #ifdef REASSOCIATION
864 	priv->reassoc_required = MFALSE;
865 #endif /* REASSOCIATION */
866 	LEAVE();
867 	return status;
868 }
869 
870 /**
871  *  @brief Send bss_start command to MLAN
872  *
873  *  @param priv          A pointer to moal_private structure
874  *  @param wait_option          Wait option
875  *  @param ssid_bssid    A point to mlan_ssid_bssid structure
876  *
877  *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
878  */
879 mlan_status
woal_bss_start(moal_private * priv,t_u8 wait_option,mlan_ssid_bssid * ssid_bssid)880 woal_bss_start(moal_private *priv, t_u8 wait_option,
881 	       mlan_ssid_bssid *ssid_bssid)
882 {
883 	mlan_ioctl_req *req = NULL;
884 	mlan_ds_bss *bss = NULL;
885 	mlan_status status;
886 
887 	ENTER();
888 
889 	/* Stop the O.S. TX queue When we are roaming */
890 	woal_stop_queue(priv->netdev);
891 	if (priv->media_connected == MFALSE) {
892 		if (netif_carrier_ok(priv->netdev))
893 			netif_carrier_off(priv->netdev);
894 	}
895 
896 	/* Allocate an IOCTL request buffer */
897 	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
898 	if (req == NULL) {
899 		status = MLAN_STATUS_FAILURE;
900 		goto done;
901 	}
902 
903 	/* Fill request buffer */
904 	bss = (mlan_ds_bss *)req->pbuf;
905 	bss->sub_command = MLAN_OID_BSS_START;
906 	if (ssid_bssid)
907 		memcpy(&bss->param.ssid_bssid, ssid_bssid,
908 		       sizeof(mlan_ssid_bssid));
909 	req->req_id = MLAN_IOCTL_BSS;
910 	req->action = MLAN_ACT_SET;
911 
912 	/* Send IOCTL request to MLAN */
913 	status = woal_request_ioctl(priv, req, wait_option);
914 #ifdef STA_CFG80211
915 #ifdef STA_SUPPORT
916 	priv->assoc_status = req->status_code;
917 #endif
918 #endif
919 done:
920 	if (status != MLAN_STATUS_PENDING)
921 		kfree(req);
922 	LEAVE();
923 	return status;
924 }
925 
926 /**
927  *  @brief Get BSS info
928  *
929  *  @param priv                 A pointer to moal_private structure
930  *  @param wait_option          Wait option
931  *  @param bss_info             A pointer to mlan_bss_info structure
932  *
933  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
934  */
935 mlan_status
woal_get_bss_info(moal_private * priv,t_u8 wait_option,mlan_bss_info * bss_info)936 woal_get_bss_info(moal_private *priv, t_u8 wait_option, mlan_bss_info *bss_info)
937 {
938 	mlan_ioctl_req *req = NULL;
939 	mlan_ds_get_info *info = NULL;
940 	mlan_status status = MLAN_STATUS_SUCCESS;
941 	ENTER();
942 
943 	/* Allocate an IOCTL request buffer */
944 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
945 	if (req == NULL) {
946 		PRINTM(MERROR,
947 		       "Fail to allocate the buffer for get bss_info\n");
948 		status = MLAN_STATUS_FAILURE;
949 		goto done;
950 	}
951 
952 	/* Fill request buffer */
953 	info = (mlan_ds_get_info *)req->pbuf;
954 	info->sub_command = MLAN_OID_GET_BSS_INFO;
955 	req->req_id = MLAN_IOCTL_GET_INFO;
956 	req->action = MLAN_ACT_GET;
957 
958 	/* Send IOCTL request to MLAN */
959 	status = woal_request_ioctl(priv, req, wait_option);
960 	if (status == MLAN_STATUS_SUCCESS) {
961 		if (bss_info)
962 			memcpy(bss_info, &info->param.bss_info,
963 			       sizeof(mlan_bss_info));
964 	}
965 done:
966 	if (status != MLAN_STATUS_PENDING)
967 		kfree(req);
968 	LEAVE();
969 	return status;
970 }
971 
972 /**
973  *  @brief Set/Get generic IE
974  *
975  *  @param priv         A pointer to moal_private structure
976  *  @param action       Action set or get
977  *  @param ie           Information element
978  *  @param ie_len       Length of the IE
979  *  @param wait_option  wait option
980  *
981  *  @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
982  */
983 mlan_status
woal_set_get_gen_ie(moal_private * priv,t_u32 action,t_u8 * ie,int * ie_len,t_u8 wait_option)984 woal_set_get_gen_ie(moal_private *priv, t_u32 action,
985 		    t_u8 *ie, int *ie_len, t_u8 wait_option)
986 {
987 	mlan_status ret = MLAN_STATUS_SUCCESS;
988 	mlan_ds_misc_cfg *misc = NULL;
989 	mlan_ioctl_req *req = NULL;
990 
991 	ENTER();
992 
993 	if ((action == MLAN_ACT_GET) && (ie == NULL || ie_len == NULL)) {
994 		ret = MLAN_STATUS_FAILURE;
995 		goto done;
996 	}
997 
998 	if (action == MLAN_ACT_SET && *ie_len > MAX_IE_SIZE) {
999 		ret = MLAN_STATUS_FAILURE;
1000 		goto done;
1001 	}
1002 
1003 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1004 	if (req == NULL) {
1005 		ret = MLAN_STATUS_FAILURE;
1006 		goto done;
1007 	}
1008 
1009 	misc = (mlan_ds_misc_cfg *)req->pbuf;
1010 	misc->sub_command = MLAN_OID_MISC_GEN_IE;
1011 	req->req_id = MLAN_IOCTL_MISC_CFG;
1012 	req->action = action;
1013 	misc->param.gen_ie.type = MLAN_IE_TYPE_GEN_IE;
1014 
1015 	if (action == MLAN_ACT_SET) {
1016 		misc->param.gen_ie.len = *ie_len;
1017 		if (*ie_len)
1018 			memcpy(misc->param.gen_ie.ie_data, ie, *ie_len);
1019 	}
1020 
1021 	ret = woal_request_ioctl(priv, req, wait_option);
1022 	if (ret != MLAN_STATUS_SUCCESS)
1023 		goto done;
1024 
1025 	if (action == MLAN_ACT_GET) {
1026 		*ie_len = misc->param.gen_ie.len;
1027 		if (*ie_len)
1028 			memcpy(ie, misc->param.gen_ie.ie_data, *ie_len);
1029 	}
1030 
1031 done:
1032 	if (ret != MLAN_STATUS_PENDING)
1033 		kfree(req);
1034 	LEAVE();
1035 	return ret;
1036 }
1037 
1038 #ifdef STA_SUPPORT
1039 /**
1040  *  @brief Set/Get retry count
1041  *
1042  *  @param priv                 A pointer to moal_private structure
1043  *  @param action               Action set or get
1044  *  @param wait_option          Wait option
1045  *  @param value                Retry value
1046  *
1047  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
1048  */
1049 mlan_status
woal_set_get_retry(moal_private * priv,t_u32 action,t_u8 wait_option,int * value)1050 woal_set_get_retry(moal_private *priv, t_u32 action,
1051 		   t_u8 wait_option, int *value)
1052 {
1053 	mlan_ioctl_req *req = NULL;
1054 	mlan_ds_snmp_mib *mib = NULL;
1055 	mlan_status ret = MLAN_STATUS_SUCCESS;
1056 	ENTER();
1057 
1058 	/* Allocate an IOCTL request buffer */
1059 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
1060 	if (req == NULL) {
1061 		ret = MLAN_STATUS_FAILURE;
1062 		goto done;
1063 	}
1064 
1065 	/* Fill request buffer */
1066 	mib = (mlan_ds_snmp_mib *)req->pbuf;
1067 	mib->sub_command = MLAN_OID_SNMP_MIB_RETRY_COUNT;
1068 	req->req_id = MLAN_IOCTL_SNMP_MIB;
1069 	req->action = action;
1070 
1071 	if (action == MLAN_ACT_SET) {
1072 		if (*value < MLAN_TX_RETRY_MIN || *value > MLAN_TX_RETRY_MAX) {
1073 			ret = MLAN_STATUS_FAILURE;
1074 			goto done;
1075 		}
1076 		mib->param.retry_count = *value;
1077 	}
1078 
1079 	/* Send IOCTL request to MLAN */
1080 	ret = woal_request_ioctl(priv, req, wait_option);
1081 	if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
1082 		*value = mib->param.retry_count;
1083 #ifdef STA_CFG80211
1084 	/* If set is invoked from other than iw i.e iwconfig,
1085 	 * wiphy retry count should be updated as well */
1086 	if (IS_STA_CFG80211(cfg80211_wext) && priv->wdev && priv->wdev->wiphy &&
1087 	    (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1088 	    (action == MLAN_ACT_SET)) {
1089 		priv->wdev->wiphy->retry_long = (t_u8)*value;
1090 		priv->wdev->wiphy->retry_short = (t_u8)*value;
1091 	}
1092 #endif
1093 
1094 done:
1095 	if (ret != MLAN_STATUS_PENDING)
1096 		kfree(req);
1097 	LEAVE();
1098 	return ret;
1099 }
1100 
1101 /**
1102  *  @brief Set/Get RTS threshold
1103  *
1104  *  @param priv                 A pointer to moal_private structure
1105  *  @param action               Action set or get
1106  *  @param wait_option          Wait option
1107  *  @param value                RTS threshold value
1108  *
1109  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
1110  */
1111 mlan_status
woal_set_get_rts(moal_private * priv,t_u32 action,t_u8 wait_option,int * value)1112 woal_set_get_rts(moal_private *priv, t_u32 action, t_u8 wait_option, int *value)
1113 {
1114 	mlan_ioctl_req *req = NULL;
1115 	mlan_ds_snmp_mib *mib = NULL;
1116 	mlan_status ret = MLAN_STATUS_SUCCESS;
1117 	ENTER();
1118 
1119 	/* Allocate an IOCTL request buffer */
1120 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
1121 	if (req == NULL) {
1122 		ret = MLAN_STATUS_FAILURE;
1123 		goto done;
1124 	}
1125 
1126 	/* Fill request buffer */
1127 	mib = (mlan_ds_snmp_mib *)req->pbuf;
1128 	mib->sub_command = MLAN_OID_SNMP_MIB_RTS_THRESHOLD;
1129 	req->req_id = MLAN_IOCTL_SNMP_MIB;
1130 	req->action = action;
1131 
1132 	if (action == MLAN_ACT_SET) {
1133 		if (*value < MLAN_RTS_MIN_VALUE || *value > MLAN_RTS_MAX_VALUE) {
1134 			ret = MLAN_STATUS_FAILURE;
1135 			goto done;
1136 		}
1137 		mib->param.rts_threshold = *value;
1138 	}
1139 
1140 	/* Send IOCTL request to MLAN */
1141 	ret = woal_request_ioctl(priv, req, wait_option);
1142 	if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
1143 		*value = mib->param.rts_threshold;
1144 #ifdef STA_CFG80211
1145 	/* If set is invoked from other than iw i.e iwconfig,
1146 	 * wiphy RTS threshold should be updated as well */
1147 	if (IS_STA_CFG80211(cfg80211_wext) && priv->wdev && priv->wdev->wiphy &&
1148 	    (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1149 	    (action == MLAN_ACT_SET))
1150 		priv->wdev->wiphy->rts_threshold = *value;
1151 #endif
1152 
1153 done:
1154 	if (ret != MLAN_STATUS_PENDING)
1155 		kfree(req);
1156 	LEAVE();
1157 	return ret;
1158 }
1159 
1160 /**
1161  *  @brief Set/Get Fragment threshold
1162  *
1163  *  @param priv                 A pointer to moal_private structure
1164  *  @param action               Action set or get
1165  *  @param wait_option          Wait option
1166  *  @param value                Fragment threshold value
1167  *
1168  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
1169  */
1170 mlan_status
woal_set_get_frag(moal_private * priv,t_u32 action,t_u8 wait_option,int * value)1171 woal_set_get_frag(moal_private *priv, t_u32 action,
1172 		  t_u8 wait_option, int *value)
1173 {
1174 	mlan_ioctl_req *req = NULL;
1175 	mlan_ds_snmp_mib *mib = NULL;
1176 	mlan_status ret = MLAN_STATUS_SUCCESS;
1177 	ENTER();
1178 
1179 	/* Allocate an IOCTL request buffer */
1180 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
1181 	if (req == NULL) {
1182 		ret = MLAN_STATUS_FAILURE;
1183 		goto done;
1184 	}
1185 
1186 	/* Fill request buffer */
1187 	mib = (mlan_ds_snmp_mib *)req->pbuf;
1188 	mib->sub_command = MLAN_OID_SNMP_MIB_FRAG_THRESHOLD;
1189 	req->req_id = MLAN_IOCTL_SNMP_MIB;
1190 	req->action = action;
1191 
1192 	if (action == MLAN_ACT_SET) {
1193 		if (*value < MLAN_FRAG_MIN_VALUE ||
1194 		    *value > MLAN_FRAG_MAX_VALUE) {
1195 			ret = MLAN_STATUS_FAILURE;
1196 			goto done;
1197 		}
1198 		mib->param.frag_threshold = *value;
1199 	}
1200 
1201 	/* Send IOCTL request to MLAN */
1202 	ret = woal_request_ioctl(priv, req, wait_option);
1203 	if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
1204 		*value = mib->param.frag_threshold;
1205 #ifdef STA_CFG80211
1206 	/* If set is invoked from other than iw i.e iwconfig,
1207 	 * wiphy fragment threshold should be updated as well */
1208 	if (IS_STA_CFG80211(cfg80211_wext) && priv->wdev && priv->wdev->wiphy &&
1209 	    (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1210 	    (action == MLAN_ACT_SET))
1211 		priv->wdev->wiphy->frag_threshold = *value;
1212 #endif
1213 
1214 done:
1215 	if (ret != MLAN_STATUS_PENDING)
1216 		kfree(req);
1217 	LEAVE();
1218 	return ret;
1219 }
1220 
1221 /**
1222  *  @brief Set/Get TX power
1223  *
1224  *  @param priv                 A pointer to moal_private structure
1225  *  @param action               Action set or get
1226  *  @param power_cfg            A pinter to mlan_power_cfg_t structure
1227  *
1228  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
1229  */
1230 mlan_status
woal_set_get_tx_power(moal_private * priv,t_u32 action,mlan_power_cfg_t * power_cfg)1231 woal_set_get_tx_power(moal_private *priv,
1232 		      t_u32 action, mlan_power_cfg_t *power_cfg)
1233 {
1234 	mlan_ds_power_cfg *pcfg = NULL;
1235 	mlan_ioctl_req *req = NULL;
1236 	mlan_status ret = MLAN_STATUS_SUCCESS;
1237 	ENTER();
1238 
1239 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_power_cfg));
1240 	if (req == NULL) {
1241 		ret = MLAN_STATUS_FAILURE;
1242 		goto done;
1243 	}
1244 	pcfg = (mlan_ds_power_cfg *)req->pbuf;
1245 	pcfg->sub_command = MLAN_OID_POWER_CFG;
1246 	req->req_id = MLAN_IOCTL_POWER_CFG;
1247 	req->action = action;
1248 	if (action == MLAN_ACT_SET && power_cfg)
1249 		memcpy(&pcfg->param.power_cfg, power_cfg,
1250 		       sizeof(mlan_power_cfg_t));
1251 
1252 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1253 	if (ret != MLAN_STATUS_SUCCESS)
1254 		goto done;
1255 
1256 	if (ret == MLAN_STATUS_SUCCESS && power_cfg)
1257 		memcpy(power_cfg, &pcfg->param.power_cfg,
1258 		       sizeof(mlan_power_cfg_t));
1259 
1260 done:
1261 	if (ret != MLAN_STATUS_PENDING)
1262 		kfree(req);
1263 	LEAVE();
1264 	return ret;
1265 }
1266 
1267 /**
1268  *  @brief Set/Get IEEE power management
1269  *
1270  *  @param priv                 A pointer to moal_private structure
1271  *  @param action               Action set or get
1272  *  @param disabled             A pointer to disabled flag
1273  *  @param power_type           IEEE power type
1274  *  @param wait_option          wait option
1275  *
1276  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
1277  */
1278 mlan_status
woal_set_get_power_mgmt(moal_private * priv,t_u32 action,int * disabled,int power_type,t_u8 wait_option)1279 woal_set_get_power_mgmt(moal_private *priv,
1280 			t_u32 action, int *disabled, int power_type,
1281 			t_u8 wait_option)
1282 {
1283 	mlan_status ret = MLAN_STATUS_SUCCESS;
1284 	mlan_ioctl_req *req = NULL;
1285 	mlan_ds_pm_cfg *pm_cfg = NULL;
1286 
1287 	ENTER();
1288 
1289 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
1290 	if (req == NULL) {
1291 		ret = MLAN_STATUS_FAILURE;
1292 		goto done;
1293 	}
1294 	pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
1295 	pm_cfg->sub_command = MLAN_OID_PM_CFG_IEEE_PS;
1296 	req->req_id = MLAN_IOCTL_PM_CFG;
1297 	req->action = action;
1298 
1299 	if (action == MLAN_ACT_SET) {
1300 		PRINTM(MINFO, "PS_MODE set power disabled=%d power type=%#x\n",
1301 		       *disabled, power_type);
1302 		if (*disabled)
1303 			pm_cfg->param.ps_mode = 0;
1304 		else {
1305 			/* Check not support case only (vwrq->disabled == FALSE) */
1306 			if ((power_type & MW_POWER_TYPE) == MW_POWER_TIMEOUT) {
1307 				PRINTM(MERROR,
1308 				       "Setting power timeout is not supported\n");
1309 				ret = MLAN_STATUS_FAILURE;
1310 				goto done;
1311 			} else if ((power_type & MW_POWER_TYPE) ==
1312 				   MW_POWER_PERIOD) {
1313 				PRINTM(MERROR,
1314 				       "Setting power period is not supported\n");
1315 				ret = MLAN_STATUS_FAILURE;
1316 				goto done;
1317 			}
1318 			pm_cfg->param.ps_mode = 1;
1319 		}
1320 	}
1321 
1322 	ret = woal_request_ioctl(priv, req, wait_option);
1323 	if (ret != MLAN_STATUS_SUCCESS)
1324 		goto done;
1325 
1326 	if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
1327 		*disabled = pm_cfg->param.ps_mode;
1328 
1329 #ifdef STA_CFG80211
1330 	/* If set is invoked from other than iw i.e iwconfig,
1331 	 * wiphy IEEE power save mode should be updated */
1332 	if (IS_STA_CFG80211(cfg80211_wext) && priv->wdev &&
1333 	    (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
1334 	    (action == MLAN_ACT_SET)) {
1335 		if (*disabled)
1336 			priv->wdev->ps = MFALSE;
1337 		else
1338 			priv->wdev->ps = MTRUE;
1339 	}
1340 #endif
1341 
1342 done:
1343 	if (ret != MLAN_STATUS_PENDING)
1344 		kfree(req);
1345 	LEAVE();
1346 	return ret;
1347 }
1348 
1349 /**
1350  * @brief Set region code
1351  *
1352  * @param priv     A pointer to moal_private structure
1353  * @param region   A pointer to region string
1354  *
1355  * @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
1356  */
1357 mlan_status
woal_set_region_code(moal_private * priv,char * region)1358 woal_set_region_code(moal_private *priv, char *region)
1359 {
1360 	mlan_status ret = MLAN_STATUS_SUCCESS;
1361 	mlan_ds_misc_cfg *cfg = NULL;
1362 	mlan_ioctl_req *req = NULL;
1363 
1364 	ENTER();
1365 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1366 	if (req == NULL) {
1367 		ret = MLAN_STATUS_FAILURE;
1368 		goto done;
1369 	}
1370 	cfg = (mlan_ds_misc_cfg *)req->pbuf;
1371 	cfg->sub_command = MLAN_OID_MISC_REGION;
1372 	req->req_id = MLAN_IOCTL_MISC_CFG;
1373 	req->action = MLAN_ACT_SET;
1374 	cfg->param.region_code = region_string_2_region_code(region);
1375 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1376 
1377 done:
1378 	if (ret != MLAN_STATUS_PENDING)
1379 		kfree(req);
1380 	LEAVE();
1381 	return ret;
1382 }
1383 
1384 /**
1385  *  @brief Set/Get data rate
1386  *
1387  *  @param priv                 A pointer to moal_private structure
1388  *  @param action               Action set or get
1389  *  @param datarate             A pointer to mlan_rate_cfg_t structure
1390  *
1391  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
1392  */
1393 mlan_status
woal_set_get_data_rate(moal_private * priv,t_u8 action,mlan_rate_cfg_t * datarate)1394 woal_set_get_data_rate(moal_private *priv,
1395 		       t_u8 action, mlan_rate_cfg_t *datarate)
1396 {
1397 	mlan_status ret = MLAN_STATUS_SUCCESS;
1398 	mlan_ds_rate *rate = NULL;
1399 	mlan_ioctl_req *req = NULL;
1400 
1401 	ENTER();
1402 
1403 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
1404 	if (req == NULL) {
1405 		ret = MLAN_STATUS_FAILURE;
1406 		goto done;
1407 	}
1408 
1409 	rate = (mlan_ds_rate *)req->pbuf;
1410 	rate->param.rate_cfg.rate_type = MLAN_RATE_VALUE;
1411 	rate->sub_command = MLAN_OID_RATE_CFG;
1412 	req->req_id = MLAN_IOCTL_RATE;
1413 	req->action = action;
1414 
1415 	if (datarate && (action == MLAN_ACT_SET))
1416 		memcpy(&rate->param.rate_cfg, datarate,
1417 		       sizeof(mlan_rate_cfg_t));
1418 
1419 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1420 	if (ret == MLAN_STATUS_SUCCESS && datarate && action == MLAN_ACT_GET)
1421 		memcpy(datarate, &rate->param.rate_cfg,
1422 		       sizeof(mlan_rate_cfg_t));
1423 
1424 done:
1425 	if (ret != MLAN_STATUS_PENDING)
1426 		kfree(req);
1427 	LEAVE();
1428 	return ret;
1429 }
1430 
1431 /**
1432  *  @brief Get assoc_resp buffer
1433  *
1434  *  @param priv                 A pointer to moal_private structure
1435  *  @param assoc_rsp            A pointer to mlan_ds_misc_assoc_rsp structure
1436  *  @param wait_option          wait option
1437  *
1438  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
1439  */
1440 mlan_status
woal_get_assoc_rsp(moal_private * priv,mlan_ds_misc_assoc_rsp * assoc_rsp,t_u8 wait_option)1441 woal_get_assoc_rsp(moal_private *priv, mlan_ds_misc_assoc_rsp *assoc_rsp,
1442 		   t_u8 wait_option)
1443 {
1444 	mlan_status ret = MLAN_STATUS_SUCCESS;
1445 	mlan_ds_misc_cfg *misc = NULL;
1446 	mlan_ioctl_req *req = NULL;
1447 
1448 	ENTER();
1449 
1450 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1451 	if (req == NULL) {
1452 		PRINTM(MERROR, "Fail to allocate buffer for get assoc resp\n");
1453 		ret = MLAN_STATUS_FAILURE;
1454 		goto done;
1455 	}
1456 
1457 	req->req_id = MLAN_IOCTL_MISC_CFG;
1458 	misc = (pmlan_ds_misc_cfg)req->pbuf;
1459 	misc->sub_command = MLAN_OID_MISC_ASSOC_RSP;
1460 	req->action = MLAN_ACT_GET;
1461 
1462 	ret = woal_request_ioctl(priv, req, wait_option);
1463 	if (ret == MLAN_STATUS_SUCCESS && assoc_rsp)
1464 		memcpy(assoc_rsp, &misc->param.assoc_resp,
1465 		       sizeof(mlan_ds_misc_assoc_rsp));
1466 
1467 done:
1468 	if (ret != MLAN_STATUS_PENDING)
1469 		kfree(req);
1470 	LEAVE();
1471 	return ret;
1472 }
1473 #endif
1474 
1475 /**
1476  *  @brief Send get FW info request to MLAN
1477  *
1478  *  @param priv             A pointer to moal_private structure
1479  *  @param wait_option      Wait option
1480  *  @param fw_info          FW information
1481  *
1482  *  @return                 MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
1483  */
1484 mlan_status
woal_request_get_fw_info(moal_private * priv,t_u8 wait_option,mlan_fw_info * fw_info)1485 woal_request_get_fw_info(moal_private *priv, t_u8 wait_option,
1486 			 mlan_fw_info *fw_info)
1487 {
1488 	mlan_ioctl_req *req = NULL;
1489 	mlan_ds_get_info *info;
1490 	mlan_status status;
1491 	ENTER();
1492 	memset(priv->current_addr, 0xff, ETH_ALEN);
1493 
1494 	/* Allocate an IOCTL request buffer */
1495 	req = (mlan_ioctl_req *)
1496 		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
1497 	if (req == NULL) {
1498 		status = MLAN_STATUS_FAILURE;
1499 		goto done;
1500 	}
1501 
1502 	/* Fill request buffer */
1503 	info = (mlan_ds_get_info *)req->pbuf;
1504 	req->req_id = MLAN_IOCTL_GET_INFO;
1505 	req->action = MLAN_ACT_GET;
1506 	info->sub_command = MLAN_OID_GET_FW_INFO;
1507 
1508 	/* Send IOCTL request to MLAN */
1509 	status = woal_request_ioctl(priv, req, wait_option);
1510 	if (status == MLAN_STATUS_SUCCESS) {
1511 		priv->phandle->fw_release_number = info->param.fw_info.fw_ver;
1512 		priv->phandle->fw_ecsa_enable = info->param.fw_info.ecsa_enable;
1513 		priv->phandle->fw_getlog_enable =
1514 			info->param.fw_info.getlog_enable;
1515 		priv->phandle->fw_roaming_support =
1516 			info->param.fw_info.fw_roaming_support;
1517 		if (priv->current_addr[0] == 0xff)
1518 			memcpy(priv->current_addr,
1519 			       &info->param.fw_info.mac_addr,
1520 			       sizeof(mlan_802_11_mac_addr));
1521 		memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN);
1522 		if (fw_info)
1523 			memcpy(fw_info, &info->param.fw_info,
1524 			       sizeof(mlan_fw_info));
1525 		DBG_HEXDUMP(MCMD_D, "mac", priv->current_addr, 6);
1526 	} else
1527 		PRINTM(MERROR,
1528 		       "get fw info failed! status=%d, error_code=0x%x\n",
1529 		       status, req->status_code);
1530 done:
1531 	if (status != MLAN_STATUS_PENDING)
1532 		kfree(req);
1533 	LEAVE();
1534 	return status;
1535 }
1536 
1537 #ifdef STA_SUPPORT
1538 /**
1539  *  @brief Send get ext cap info request to MLAN
1540  *
1541  *  @param priv             A pointer to moal_private structure
1542  *  @param buf              data buffer
1543  *  @param len              data buffer length
1544  *
1545  *  @return                 number of bytes of extended capability -- success, otherwise error
1546  */
1547 int
woal_request_extcap(moal_private * priv,t_u8 * buf,t_u8 len)1548 woal_request_extcap(moal_private *priv, t_u8 *buf, t_u8 len)
1549 {
1550 	int ret = 0;
1551 	mlan_ioctl_req *req = NULL;
1552 	mlan_ds_misc_cfg *cfg = NULL;
1553 	mlan_status status = MLAN_STATUS_SUCCESS;
1554 
1555 	ENTER();
1556 	if (buf == NULL || len <= 0 || len < sizeof(ExtCap_t)) {
1557 		ret = -EINVAL;
1558 		goto out;
1559 	}
1560 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1561 	if (req == NULL) {
1562 		ret = -ENOMEM;
1563 		goto out;
1564 	}
1565 	cfg = (mlan_ds_misc_cfg *)req->pbuf;
1566 	cfg->sub_command = MLAN_OID_MISC_EXT_CAP_CFG;
1567 	req->req_id = MLAN_IOCTL_MISC_CFG;
1568 	req->action = MLAN_ACT_GET;
1569 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1570 	if (status != MLAN_STATUS_SUCCESS) {
1571 		ret = -EFAULT;
1572 		goto out;
1573 	}
1574 	memset(buf, 0, len);
1575 	memcpy(buf, &cfg->param.ext_cap, sizeof(ExtCap_t));
1576 	ret = sizeof(ExtCap_t);
1577 out:
1578 	if (status != MLAN_STATUS_PENDING)
1579 		kfree(req);
1580 	LEAVE();
1581 	return ret;
1582 }
1583 #endif
1584 
1585 #ifdef PROC_DEBUG
1586 /**
1587  *  @brief Get debug info
1588  *
1589  *  @param priv                 A pointer to moal_private structure
1590  *  @param wait_option          Wait option
1591  *  @param debug_info           A pointer to mlan_debug_info structure
1592  *
1593  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
1594  */
1595 mlan_status
woal_get_debug_info(moal_private * priv,t_u8 wait_option,mlan_debug_info * debug_info)1596 woal_get_debug_info(moal_private *priv, t_u8 wait_option,
1597 		    mlan_debug_info *debug_info)
1598 {
1599 	int ret = 0;
1600 	mlan_ioctl_req *req = NULL;
1601 	mlan_ds_get_info *info = NULL;
1602 	mlan_status status = MLAN_STATUS_SUCCESS;
1603 	ENTER();
1604 
1605 	/* Allocate an IOCTL request buffer */
1606 	req = woal_alloc_mlan_ioctl_req(sizeof(t_u32) +
1607 					sizeof(mlan_debug_info));
1608 	if (req == NULL) {
1609 		ret = -ENOMEM;
1610 		goto done;
1611 	}
1612 
1613 	/* Fill request buffer */
1614 	info = (mlan_ds_get_info *)req->pbuf;
1615 	info->sub_command = MLAN_OID_GET_DEBUG_INFO;
1616 	req->req_id = MLAN_IOCTL_GET_INFO;
1617 	req->action = MLAN_ACT_GET;
1618 
1619 	/* Send IOCTL request to MLAN */
1620 	status = woal_request_ioctl(priv, req, wait_option);
1621 	if (status == MLAN_STATUS_SUCCESS) {
1622 		if (debug_info) {
1623 			memcpy(debug_info, &info->param.debug_info,
1624 			       sizeof(mlan_debug_info));
1625 		}
1626 	}
1627 done:
1628 	if (status != MLAN_STATUS_PENDING)
1629 		kfree(req);
1630 	LEAVE();
1631 	return status;
1632 }
1633 #endif /* PROC_DEBUG */
1634 
1635 #if defined(STA_WEXT) || defined(UAP_WEXT)
1636 /**
1637  *  @brief host command ioctl function
1638  *
1639  *  @param priv     A pointer to moal_private structure
1640  *  @param wrq      A pointer to iwreq structure
1641  *  @return         0 --success, otherwise fail
1642  */
1643 int
woal_host_command(moal_private * priv,struct iwreq * wrq)1644 woal_host_command(moal_private *priv, struct iwreq *wrq)
1645 {
1646 	HostCmd_Header cmd_header;
1647 	int ret = 0;
1648 	mlan_ds_misc_cfg *misc = NULL;
1649 	mlan_ioctl_req *req = NULL;
1650 	mlan_status status = MLAN_STATUS_SUCCESS;
1651 
1652 	ENTER();
1653 
1654 	/* Sanity check */
1655 	if (wrq->u.data.pointer == NULL) {
1656 		PRINTM(MERROR, "hostcmd IOCTL corrupt data\n");
1657 		ret = -EINVAL;
1658 		goto done;
1659 	}
1660 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1661 	if (req == NULL) {
1662 		ret = -ENOMEM;
1663 		goto done;
1664 	}
1665 	misc = (mlan_ds_misc_cfg *)req->pbuf;
1666 	memset(&cmd_header, 0, sizeof(cmd_header));
1667 
1668 	/* get command header */
1669 	if (copy_from_user
1670 	    (&cmd_header, wrq->u.data.pointer, sizeof(HostCmd_Header))) {
1671 		PRINTM(MERROR, "copy from user failed: Host command header\n");
1672 		ret = -EFAULT;
1673 		goto done;
1674 	}
1675 	misc->param.hostcmd.len = woal_le16_to_cpu(cmd_header.size);
1676 
1677 	PRINTM(MINFO, "Host command len = %u\n", misc->param.hostcmd.len);
1678 
1679 	if (!misc->param.hostcmd.len ||
1680 	    misc->param.hostcmd.len > MLAN_SIZE_OF_CMD_BUFFER) {
1681 		PRINTM(MERROR, "Invalid data buffer length\n");
1682 		ret = -EINVAL;
1683 		goto done;
1684 	}
1685 
1686 	/* get the whole command from user */
1687 	if (copy_from_user
1688 	    (misc->param.hostcmd.cmd, wrq->u.data.pointer,
1689 	     woal_le16_to_cpu(cmd_header.size))) {
1690 		PRINTM(MERROR, "copy from user failed\n");
1691 		ret = -EFAULT;
1692 		goto done;
1693 	}
1694 	misc->sub_command = MLAN_OID_MISC_HOST_CMD;
1695 	req->req_id = MLAN_IOCTL_MISC_CFG;
1696 
1697 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1698 	if (status != MLAN_STATUS_SUCCESS) {
1699 		ret = -EFAULT;
1700 		goto done;
1701 	}
1702 	if (copy_to_user
1703 	    (wrq->u.data.pointer, (t_u8 *)misc->param.hostcmd.cmd,
1704 	     misc->param.hostcmd.len)) {
1705 		ret = -EFAULT;
1706 		goto done;
1707 	}
1708 	wrq->u.data.length = misc->param.hostcmd.len;
1709 done:
1710 	if (status != MLAN_STATUS_PENDING)
1711 		kfree(req);
1712 	LEAVE();
1713 	return ret;
1714 }
1715 #endif
1716 
1717 #if defined(WIFI_DIRECT_SUPPORT) || defined(UAP_SUPPORT)
1718 /**
1719  *  @brief host command ioctl function
1720  *
1721  *  @param dev      A pointer to net_device structure
1722  *  @param req      A pointer to ifreq structure
1723  *  @return         0 --success, otherwise fail
1724  */
1725 /*********  format of ifr_data *************/
1726 /*    buf_len + Hostcmd_body               */
1727 /*    buf_len: 4 bytes                     */
1728 /*             the length of the buf which */
1729 /*             can be used to return data  */
1730 /*             to application              */
1731 /*    Hostcmd_body                         */
1732 /*******************************************/
1733 int
woal_hostcmd_ioctl(struct net_device * dev,struct ifreq * req)1734 woal_hostcmd_ioctl(struct net_device *dev, struct ifreq *req)
1735 {
1736 	moal_private *priv = (moal_private *)netdev_priv(dev);
1737 	t_u32 buf_len = 0;
1738 	HostCmd_Header cmd_header;
1739 	int ret = 0;
1740 	mlan_ds_misc_cfg *misc = NULL;
1741 	mlan_ioctl_req *ioctl_req = NULL;
1742 	mlan_status status = MLAN_STATUS_SUCCESS;
1743 
1744 	ENTER();
1745 
1746 	/* Sanity check */
1747 	if (req->ifr_data == NULL) {
1748 		PRINTM(MERROR, "uap_hostcmd_ioctl() corrupt data\n");
1749 		ret = -EFAULT;
1750 		goto done;
1751 	}
1752 
1753 	if (copy_from_user(&buf_len, req->ifr_data, sizeof(buf_len))) {
1754 		PRINTM(MERROR, "Copy from user failed\n");
1755 		ret = -EFAULT;
1756 		goto done;
1757 	}
1758 
1759 	memset(&cmd_header, 0, sizeof(cmd_header));
1760 
1761 	/* get command header */
1762 	if (copy_from_user
1763 	    (&cmd_header, req->ifr_data + sizeof(buf_len),
1764 	     sizeof(HostCmd_Header))) {
1765 		PRINTM(MERROR, "Copy from user failed\n");
1766 		ret = -EFAULT;
1767 		goto done;
1768 	}
1769 
1770 	PRINTM(MINFO, "Host command len = %d\n",
1771 	       woal_le16_to_cpu(cmd_header.size));
1772 
1773 	if (woal_le16_to_cpu(cmd_header.size) > MLAN_SIZE_OF_CMD_BUFFER) {
1774 		ret = -EINVAL;
1775 		goto done;
1776 	}
1777 
1778 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1779 	if (ioctl_req == NULL) {
1780 		ret = -ENOMEM;
1781 		goto done;
1782 	}
1783 	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
1784 
1785 	misc->param.hostcmd.len = woal_le16_to_cpu(cmd_header.size);
1786 
1787 	/* get the whole command from user */
1788 	if (copy_from_user
1789 	    (misc->param.hostcmd.cmd, req->ifr_data + sizeof(buf_len),
1790 	     misc->param.hostcmd.len)) {
1791 		PRINTM(MERROR, "copy from user failed\n");
1792 		ret = -EFAULT;
1793 		goto done;
1794 	}
1795 	misc->sub_command = MLAN_OID_MISC_HOST_CMD;
1796 	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
1797 
1798 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1799 	if (status != MLAN_STATUS_SUCCESS) {
1800 		ret = -EFAULT;
1801 		goto done;
1802 	}
1803 	if (misc->param.hostcmd.len > buf_len) {
1804 		PRINTM(MERROR,
1805 		       "buf_len is too small, resp_len=%d, buf_len=%d\n",
1806 		       (int)misc->param.hostcmd.len, (int)buf_len);
1807 		ret = -EFAULT;
1808 		goto done;
1809 	}
1810 	if (copy_to_user
1811 	    (req->ifr_data + sizeof(buf_len), (t_u8 *)misc->param.hostcmd.cmd,
1812 	     misc->param.hostcmd.len)) {
1813 		ret = -EFAULT;
1814 		goto done;
1815 	}
1816 done:
1817 	if (status != MLAN_STATUS_PENDING)
1818 		kfree(ioctl_req);
1819 	LEAVE();
1820 	return ret;
1821 }
1822 #endif
1823 
1824 /**
1825  *  @brief CUSTOM_IE ioctl handler
1826  *
1827  *  @param dev      A pointer to net_device structure
1828  *  @param req      A pointer to ifreq structure
1829  *  @return         0 --success, otherwise fail
1830  */
1831 int
woal_custom_ie_ioctl(struct net_device * dev,struct ifreq * req)1832 woal_custom_ie_ioctl(struct net_device *dev, struct ifreq *req)
1833 {
1834 	moal_private *priv = (moal_private *)netdev_priv(dev);
1835 	mlan_ioctl_req *ioctl_req = NULL;
1836 	mlan_ds_misc_cfg *misc = NULL;
1837 	mlan_ds_misc_custom_ie *custom_ie = NULL;
1838 	int ret = 0;
1839 	mlan_status status = MLAN_STATUS_SUCCESS;
1840 	gfp_t flag;
1841 
1842 	ENTER();
1843 
1844 	/* Sanity check */
1845 	if (req->ifr_data == NULL) {
1846 		PRINTM(MERROR, "woal_custom_ie_ioctl() corrupt data\n");
1847 		ret = -EFAULT;
1848 		goto done;
1849 	}
1850 
1851 	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
1852 	custom_ie = kzalloc(sizeof(mlan_ds_misc_custom_ie), flag);
1853 	if (!custom_ie) {
1854 		ret = -ENOMEM;
1855 		goto done;
1856 	}
1857 
1858 	if (copy_from_user
1859 	    (custom_ie, req->ifr_data, sizeof(mlan_ds_misc_custom_ie))) {
1860 		PRINTM(MERROR, "Copy from user failed\n");
1861 		ret = -EFAULT;
1862 		goto done;
1863 	}
1864 
1865 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1866 	if (ioctl_req == NULL) {
1867 		ret = -ENOMEM;
1868 		goto done;
1869 	}
1870 
1871 	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
1872 	misc->sub_command = MLAN_OID_MISC_CUSTOM_IE;
1873 	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
1874 	if ((custom_ie->len == 0)||(custom_ie->len ==
1875 				    sizeof(custom_ie->ie_data_list[0].
1876 					   ie_index)))
1877 		ioctl_req->action = MLAN_ACT_GET;
1878 	else
1879 		ioctl_req->action = MLAN_ACT_SET;
1880 
1881 	memcpy(&misc->param.cust_ie, custom_ie, sizeof(mlan_ds_misc_custom_ie));
1882 
1883 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
1884 	if (status != MLAN_STATUS_SUCCESS) {
1885 		ret = -EFAULT;
1886 		goto done;
1887 	}
1888 
1889 	if (ioctl_req->action == MLAN_ACT_GET) {
1890 		if (copy_to_user
1891 		    (req->ifr_data, &misc->param.cust_ie,
1892 		     sizeof(mlan_ds_misc_custom_ie))) {
1893 			PRINTM(MERROR, "Copy to user failed!\n");
1894 			ret = -EFAULT;
1895 			goto done;
1896 		}
1897 	} else if (ioctl_req->status_code == MLAN_ERROR_IOCTL_FAIL) {
1898 		/* send a separate error code to indicate error from driver */
1899 		ret = EFAULT;
1900 	}
1901 
1902 done:
1903 	if (status != MLAN_STATUS_PENDING)
1904 		kfree(ioctl_req);
1905 	kfree(custom_ie);
1906 	LEAVE();
1907 	return ret;
1908 }
1909 
1910 /**
1911  *  @brief send raw data packet ioctl function
1912  *
1913  *  @param dev      A pointer to net_device structure
1914  *  @param req      A pointer to ifreq structure
1915  *  @return         0 --success, otherwise fail
1916  */
1917 int
woal_send_host_packet(struct net_device * dev,struct ifreq * req)1918 woal_send_host_packet(struct net_device *dev, struct ifreq *req)
1919 {
1920 	moal_private *priv = (moal_private *)netdev_priv(dev);
1921 	t_u32 packet_len = 0;
1922 	int ret = 0;
1923 	pmlan_buffer pmbuf = NULL;
1924 	mlan_status status;
1925 	IEEEtypes_ActionCategory_e *action_cat;
1926 	t_u8 *action;
1927 	struct tx_status_info *tx_info = NULL;
1928 	struct sk_buff *skb = NULL;
1929 	unsigned long flags;
1930 	struct ieee80211_mgmt *mgmt_frame;
1931 
1932 	ENTER();
1933 
1934 	if (!priv || !priv->phandle) {
1935 		PRINTM(MERROR, "priv or handle is NULL\n");
1936 		ret = -EFAULT;
1937 		goto done;
1938 	}
1939 
1940 	/* Sanity check */
1941 	if (req->ifr_data == NULL) {
1942 		PRINTM(MERROR, "woal_send_host_packet() corrupt data\n");
1943 		ret = -EFAULT;
1944 		goto done;
1945 	}
1946 
1947 	if (copy_from_user(&packet_len, req->ifr_data, sizeof(packet_len))) {
1948 		PRINTM(MERROR, "Copy from user failed\n");
1949 		ret = -EFAULT;
1950 		goto done;
1951 	}
1952 #define PACKET_HEADER_LEN        8
1953 #define MV_ETH_FRAME_LEN      1514
1954 	if (packet_len > MV_ETH_FRAME_LEN) {
1955 		PRINTM(MERROR, "Invalid packet length %d\n", packet_len);
1956 		ret = -EFAULT;
1957 		goto done;
1958 	}
1959 	pmbuf = woal_alloc_mlan_buffer(priv->phandle,
1960 				       (int)(MLAN_MIN_DATA_HEADER_LEN +
1961 					     (int)packet_len +
1962 					     PACKET_HEADER_LEN));
1963 	if (!pmbuf) {
1964 		PRINTM(MERROR, "Fail to allocate mlan_buffer\n");
1965 		ret = -ENOMEM;
1966 		goto done;
1967 	}
1968 	pmbuf->data_offset = MLAN_MIN_DATA_HEADER_LEN;
1969 
1970 	/* get whole packet and header */
1971 	if (copy_from_user
1972 	    (pmbuf->pbuf + pmbuf->data_offset,
1973 	     req->ifr_data + sizeof(packet_len),
1974 	     PACKET_HEADER_LEN + packet_len)) {
1975 		PRINTM(MERROR, "Copy from user failed\n");
1976 		ret = -EFAULT;
1977 		woal_free_mlan_buffer(priv->phandle, pmbuf);
1978 		goto done;
1979 	}
1980 	pmbuf->data_len = PACKET_HEADER_LEN + packet_len;
1981 	pmbuf->buf_type = MLAN_BUF_TYPE_RAW_DATA;
1982 	pmbuf->bss_index = priv->bss_index;
1983 	action_cat =
1984 		(IEEEtypes_ActionCategory_e *)&pmbuf->pbuf[pmbuf->data_offset +
1985 							   MLAN_ACTION_FRAME_CATEGORY_OFFSET];
1986 	action = &pmbuf->pbuf[pmbuf->data_offset +
1987 			      MLAN_ACTION_FRAME_ACTION_OFFSET];
1988 
1989 	if (*action_cat == IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM &&
1990 	    *action == 0x1) {
1991 		pmbuf->flags |= MLAN_BUF_FLAG_TX_STATUS;
1992 		if (!priv->tx_seq_num)
1993 			priv->tx_seq_num++;
1994 		pmbuf->tx_seq_num = priv->tx_seq_num++;
1995 		tx_info = kzalloc(sizeof(struct tx_status_info), GFP_ATOMIC);
1996 		if (tx_info) {
1997 			skb = alloc_skb(pmbuf->data_len, GFP_ATOMIC);
1998 			if (skb) {
1999 				mgmt_frame = (struct ieee80211_mgmt *)skb->data;
2000 				//Copy DA,SA and BSSID feilds.
2001 				memcpy(mgmt_frame->da,
2002 				       &pmbuf->pbuf[pmbuf->data_offset + 14],
2003 				       3 * MLAN_MAC_ADDR_LENGTH);
2004 				//Copy packet data starting from category feild
2005 				memcpy(&mgmt_frame->u.action.category,
2006 				       action_cat,
2007 				       packet_len -
2008 				       MLAN_ACTION_FRAME_CATEGORY_OFFSET);
2009 				/* frame_ctrl+duration+DA+SA+BSSID+seq_ctrl = 24 Bytes */
2010 				/*category+action+dt+status = 4Bytes */
2011 				skb_put(skb,
2012 					24 + 4 + packet_len -
2013 					MLAN_ACTION_FRAME_CATEGORY_OFFSET);
2014 				spin_lock_irqsave(&priv->tx_stat_lock, flags);
2015 				tx_info->tx_skb = skb;
2016 				tx_info->tx_seq_num = pmbuf->tx_seq_num;
2017 				tx_info->tx_cookie = 0;
2018 				INIT_LIST_HEAD(&tx_info->link);
2019 				list_add_tail(&tx_info->link,
2020 					      &priv->tx_stat_queue);
2021 				spin_unlock_irqrestore(&priv->tx_stat_lock,
2022 						       flags);
2023 			} else {
2024 				kfree(tx_info);
2025 				tx_info = NULL;
2026 			}
2027 		}
2028 	}
2029 
2030 	status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf);
2031 	switch (status) {
2032 	case MLAN_STATUS_PENDING:
2033 		atomic_inc(&priv->phandle->tx_pending);
2034 		queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
2035 		break;
2036 	case MLAN_STATUS_SUCCESS:
2037 		woal_free_mlan_buffer(priv->phandle, pmbuf);
2038 		break;
2039 	case MLAN_STATUS_FAILURE:
2040 	default:
2041 		woal_free_mlan_buffer(priv->phandle, pmbuf);
2042 		ret = -EFAULT;
2043 		break;
2044 	}
2045 done:
2046 	LEAVE();
2047 	return ret;
2048 }
2049 
2050 #if defined(UAP_WEXT)
2051 /**
2052  *  @brief Set/Get CUSTOM_IE ioctl handler
2053  *
2054  *  @param priv         A pointer to moal_private structure
2055  *  @param mask         Mask to set or clear from caller
2056  *  @param ie           IE buffer to set for beacon
2057  *  @param ie_len       Length of the IE
2058  *
2059  *  @return         0 --success, otherwise fail
2060  */
2061 int
woal_set_get_custom_ie(moal_private * priv,t_u16 mask,t_u8 * ie,int ie_len)2062 woal_set_get_custom_ie(moal_private *priv, t_u16 mask, t_u8 *ie, int ie_len)
2063 {
2064 	mlan_ioctl_req *ioctl_req = NULL;
2065 	mlan_ds_misc_cfg *misc = NULL;
2066 	mlan_ds_misc_custom_ie *misc_ie = NULL;
2067 	int ret = 0;
2068 	custom_ie *pcust_bcn_ie = NULL;
2069 	mlan_status status = MLAN_STATUS_SUCCESS;
2070 
2071 	ENTER();
2072 
2073 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2074 	if (ioctl_req == NULL) {
2075 		LEAVE();
2076 		return -ENOMEM;
2077 	}
2078 
2079 	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
2080 	misc->sub_command = MLAN_OID_MISC_CUSTOM_IE;
2081 	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
2082 	ioctl_req->action = MLAN_ACT_SET;
2083 	misc_ie = &misc->param.cust_ie;
2084 
2085 	misc_ie->type = TLV_TYPE_MGMT_IE;
2086 	misc_ie->len = (sizeof(custom_ie) - MAX_IE_SIZE) + ie_len;
2087 	pcust_bcn_ie = misc_ie->ie_data_list;
2088 	pcust_bcn_ie->ie_index = 0xffff;
2089 	pcust_bcn_ie->mgmt_subtype_mask = mask;
2090 	pcust_bcn_ie->ie_length = ie_len;
2091 	memcpy(pcust_bcn_ie->ie_buffer, ie, ie_len);
2092 
2093 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2094 	if (status != MLAN_STATUS_SUCCESS)
2095 		ret = -EFAULT;
2096 
2097 	if (status != MLAN_STATUS_PENDING)
2098 		kfree(ioctl_req);
2099 	LEAVE();
2100 	return ret;
2101 }
2102 #endif /* defined(HOST_TXRX_MGMT_FRAME) && defined(UAP_WEXT) */
2103 
2104 /**
2105  *  @brief TDLS configuration ioctl handler
2106  *
2107  *  @param dev      A pointer to net_device structure
2108  *  @param req      A pointer to ifreq structure
2109  *  @return         0 --success, otherwise fail
2110  */
2111 int
woal_tdls_config_ioctl(struct net_device * dev,struct ifreq * req)2112 woal_tdls_config_ioctl(struct net_device *dev, struct ifreq *req)
2113 {
2114 	moal_private *priv = (moal_private *)netdev_priv(dev);
2115 	mlan_ioctl_req *ioctl_req = NULL;
2116 	mlan_ds_misc_cfg *misc = NULL;
2117 	mlan_ds_misc_tdls_config *tdls_data = NULL;
2118 	int ret = 0;
2119 	mlan_status status = MLAN_STATUS_SUCCESS;
2120 	gfp_t flag;
2121 
2122 	ENTER();
2123 
2124 	/* Sanity check */
2125 	if (req->ifr_data == NULL) {
2126 		PRINTM(MERROR, "woal_tdls_config_ioctl() corrupt data\n");
2127 		ret = -EFAULT;
2128 		goto done;
2129 	}
2130 	flag = (in_atomic() || irqs_disabled())? GFP_ATOMIC : GFP_KERNEL;
2131 	tdls_data = kzalloc(sizeof(mlan_ds_misc_tdls_config), flag);
2132 	if (!tdls_data) {
2133 		ret = -ENOMEM;
2134 		goto done;
2135 	}
2136 
2137 	if (copy_from_user
2138 	    (tdls_data, req->ifr_data, sizeof(mlan_ds_misc_tdls_config))) {
2139 		PRINTM(MERROR, "Copy from user failed\n");
2140 		ret = -EFAULT;
2141 		goto done;
2142 	}
2143 
2144 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2145 	if (ioctl_req == NULL) {
2146 		ret = -ENOMEM;
2147 		goto done;
2148 	}
2149 
2150 	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
2151 	misc->sub_command = MLAN_OID_MISC_TDLS_CONFIG;
2152 	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
2153 	if (tdls_data->tdls_action == WLAN_TDLS_DISCOVERY_REQ
2154 	    || tdls_data->tdls_action == WLAN_TDLS_LINK_STATUS)
2155 		ioctl_req->action = MLAN_ACT_GET;
2156 	else
2157 		ioctl_req->action = MLAN_ACT_SET;
2158 
2159 	memcpy(&misc->param.tdls_config, tdls_data,
2160 	       sizeof(mlan_ds_misc_tdls_config));
2161 
2162 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2163 	if (status != MLAN_STATUS_SUCCESS) {
2164 		ret = -EFAULT;
2165 		goto done;
2166 	}
2167 
2168 	if (tdls_data->tdls_action == WLAN_TDLS_DISCOVERY_REQ
2169 	    || tdls_data->tdls_action == WLAN_TDLS_LINK_STATUS) {
2170 		if (copy_to_user(req->ifr_data, &misc->param.tdls_config,
2171 				 sizeof(mlan_ds_misc_tdls_config))) {
2172 			PRINTM(MERROR, "Copy to user failed!\n");
2173 			ret = -EFAULT;
2174 			goto done;
2175 		}
2176 	}
2177 
2178 done:
2179 	if (status != MLAN_STATUS_PENDING)
2180 		kfree(ioctl_req);
2181 	kfree(tdls_data);
2182 	LEAVE();
2183 	return ret;
2184 }
2185 
2186 /**
2187  *  @brief ioctl function get BSS type
2188  *
2189  *  @param dev      A pointer to net_device structure
2190  *  @param req      A pointer to ifreq structure
2191  *  @return         0 --success, otherwise fail
2192  */
2193 int
woal_get_bss_type(struct net_device * dev,struct ifreq * req)2194 woal_get_bss_type(struct net_device *dev, struct ifreq *req)
2195 {
2196 	int ret = 0;
2197 	moal_private *priv = (moal_private *)netdev_priv(dev);
2198 	int bss_type;
2199 
2200 	ENTER();
2201 
2202 	bss_type = (int)priv->bss_type;
2203 	if (copy_to_user(req->ifr_data, &bss_type, sizeof(int))) {
2204 		PRINTM(MINFO, "Copy to user failed!\n");
2205 		ret = -EFAULT;
2206 	}
2207 
2208 	LEAVE();
2209 	return ret;
2210 }
2211 
2212 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
2213 /**
2214  * @brief Swithces BSS role of interface
2215  *
2216  * @param priv          A pointer to moal_private structure
2217  * @param action        Action: set or get
2218  * @param wait_option   Wait option (MOAL_IOCTL_WAIT or MOAL_NO_WAIT)
2219  * @param bss_role      A pointer to bss role
2220  *
2221  * @return         0 --success, otherwise fail
2222  */
2223 mlan_status
woal_bss_role_cfg(moal_private * priv,t_u8 action,t_u8 wait_option,t_u8 * bss_role)2224 woal_bss_role_cfg(moal_private *priv, t_u8 action,
2225 		  t_u8 wait_option, t_u8 *bss_role)
2226 {
2227 	int ret = 0;
2228 	mlan_ds_bss *bss = NULL;
2229 	mlan_ioctl_req *req = NULL;
2230 	struct net_device *dev = priv->netdev;
2231 	mlan_status status = MLAN_STATUS_SUCCESS;
2232 
2233 	ENTER();
2234 
2235 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
2236 	if (req == NULL) {
2237 		ret = -ENOMEM;
2238 		goto done;
2239 	}
2240 	bss = (mlan_ds_bss *)req->pbuf;
2241 	bss->sub_command = MLAN_OID_BSS_ROLE;
2242 	req->req_id = MLAN_IOCTL_BSS;
2243 	req->action = action;
2244 	if (action == MLAN_ACT_SET) {
2245 		if (priv->bss_role == *bss_role) {
2246 			PRINTM(MWARN, "BSS is in desired role already\n");
2247 			goto done;
2248 		} else {
2249 			bss->param.bss_role = *bss_role;
2250 		}
2251 	}
2252 	status = woal_request_ioctl(priv, req, wait_option);
2253 	if (status != MLAN_STATUS_SUCCESS) {
2254 		ret = -EFAULT;
2255 		goto done;
2256 	}
2257 
2258 	if (action == MLAN_ACT_GET) {
2259 		*bss_role = bss->param.bss_role;
2260 	} else {
2261 		/* Update moal_private */
2262 		priv->bss_role = *bss_role;
2263 		if (priv->bss_type == MLAN_BSS_TYPE_UAP)
2264 			priv->bss_type = MLAN_BSS_TYPE_STA;
2265 		else if (priv->bss_type == MLAN_BSS_TYPE_STA)
2266 			priv->bss_type = MLAN_BSS_TYPE_UAP;
2267 
2268 		if (*bss_role == MLAN_BSS_ROLE_UAP) {
2269 			/* Switch: STA -> uAP */
2270 			/* Setup the OS Interface to our functions */
2271 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
2272 			dev->do_ioctl = woal_uap_do_ioctl;
2273 			dev->set_multicast_list = woal_uap_set_multicast_list;
2274 #else
2275 			dev->netdev_ops = &woal_uap_netdev_ops;
2276 #endif
2277 #ifdef UAP_WEXT
2278 			if (IS_UAP_WEXT(cfg80211_wext)) {
2279 #if WIRELESS_EXT < 21
2280 				dev->get_wireless_stats =
2281 					woal_get_uap_wireless_stats;
2282 #endif
2283 				dev->wireless_handlers =
2284 					(struct iw_handler_def *)
2285 					&woal_uap_handler_def;
2286 			}
2287 #endif /* UAP_WEXT */
2288 		} else if (*bss_role == MLAN_BSS_ROLE_STA) {
2289 			/* Switch: uAP -> STA */
2290 			/* Setup the OS Interface to our functions */
2291 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29)
2292 			dev->do_ioctl = woal_do_ioctl;
2293 			dev->set_multicast_list = woal_set_multicast_list;
2294 #else
2295 			dev->netdev_ops = &woal_netdev_ops;
2296 #endif
2297 #ifdef STA_WEXT
2298 			if (IS_STA_WEXT(cfg80211_wext)) {
2299 #if WIRELESS_EXT < 21
2300 				dev->get_wireless_stats =
2301 					woal_get_wireless_stats;
2302 #endif
2303 				dev->wireless_handlers =
2304 					(struct iw_handler_def *)
2305 					&woal_handler_def;
2306 			}
2307 #endif /* STA_WEXT */
2308 		}
2309 	}
2310 
2311 done:
2312 	if (status != MLAN_STATUS_PENDING)
2313 		kfree(req);
2314 	LEAVE();
2315 	return ret;
2316 }
2317 
2318 #if defined(STA_WEXT) || defined(UAP_WEXT)
2319 /**
2320  * @brief Set/Get BSS role
2321  *
2322  * @param priv     A pointer to moal_private structure
2323  * @param wrq      A pointer to iwreq structure
2324  *
2325  * @return         0 --success, otherwise fail
2326  */
2327 int
woal_set_get_bss_role(moal_private * priv,struct iwreq * wrq)2328 woal_set_get_bss_role(moal_private *priv, struct iwreq *wrq)
2329 {
2330 	int ret = 0;
2331 	int bss_role = 0;
2332 	t_u8 action = MLAN_ACT_GET;
2333 
2334 	ENTER();
2335 
2336 	if (wrq->u.data.length) {
2337 		if (copy_from_user(&bss_role, wrq->u.data.pointer, sizeof(int))) {
2338 			PRINTM(MERROR, "Copy from user failed\n");
2339 			ret = -EFAULT;
2340 			goto done;
2341 		}
2342 		if ((bss_role != MLAN_BSS_ROLE_STA &&
2343 		     bss_role != MLAN_BSS_ROLE_UAP)
2344 #if defined(WIFI_DIRECT_SUPPORT)
2345 		    || (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT)
2346 #endif
2347 			) {
2348 			PRINTM(MWARN, "Invalid BSS role\n");
2349 			ret = -EINVAL;
2350 			goto done;
2351 		}
2352 		if (bss_role == GET_BSS_ROLE(priv)) {
2353 			PRINTM(MWARN, "Already BSS is in desired role\n");
2354 			ret = -EINVAL;
2355 			goto done;
2356 		}
2357 		action = MLAN_ACT_SET;
2358 		/* Reset interface */
2359 		woal_reset_intf(priv, MOAL_IOCTL_WAIT, MFALSE);
2360 	}
2361 
2362 	if (MLAN_STATUS_SUCCESS != woal_bss_role_cfg(priv,
2363 						     action, MOAL_IOCTL_WAIT,
2364 						     (t_u8 *)&bss_role)) {
2365 		ret = -EFAULT;
2366 		goto done;
2367 	}
2368 
2369 	if (!wrq->u.data.length) {
2370 		if (copy_to_user(wrq->u.data.pointer, &bss_role, sizeof(int))) {
2371 			ret = -EFAULT;
2372 			goto done;
2373 		}
2374 		wrq->u.data.length = 1;
2375 	} else {
2376 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
2377 		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext))
2378 			woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_WAIT);
2379 #endif
2380 		/* Initialize private structures */
2381 		woal_init_priv(priv, MOAL_IOCTL_WAIT);
2382 
2383 		/* Enable interfaces */
2384 		netif_device_attach(priv->netdev);
2385 		woal_start_queue(priv->netdev);
2386 	}
2387 
2388 done:
2389 	LEAVE();
2390 	return ret;
2391 }
2392 #endif /* STA_WEXT || UAP_WEXT */
2393 #endif /* STA_SUPPORT && UAP_SUPPORT */
2394 
2395 #if defined(SDIO_SUSPEND_RESUME)
2396 /**
2397  *  @brief Set auto arp resp
2398  *
2399  *  @param handle         A pointer to moal_handle structure
2400  *  @param enable         enable/disable
2401  *
2402  *  @return               MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
2403  */
2404 static mlan_status
woal_set_auto_arp(moal_handle * handle,t_u8 enable)2405 woal_set_auto_arp(moal_handle *handle, t_u8 enable)
2406 {
2407 	mlan_status ret = MLAN_STATUS_SUCCESS;
2408 	int i = 0;
2409 	moal_private *priv = NULL;
2410 	mlan_ds_misc_cfg *misc = NULL;
2411 	mlan_ioctl_req *req = NULL;
2412 	mlan_ds_misc_ipaddr_cfg ipaddr_cfg;
2413 
2414 	ENTER();
2415 
2416 	memset(&ipaddr_cfg, 0, sizeof(ipaddr_cfg));
2417 	for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) {
2418 		if (priv && priv->ip_addr_type != IPADDR_TYPE_NONE) {
2419 			memcpy(ipaddr_cfg.ip_addr[ipaddr_cfg.ip_addr_num],
2420 			       priv->ip_addr, IPADDR_LEN);
2421 			ipaddr_cfg.ip_addr_num++;
2422 		}
2423 	}
2424 	if (ipaddr_cfg.ip_addr_num == 0) {
2425 		PRINTM(MIOCTL, "No IP addr configured.\n");
2426 		goto done;
2427 	}
2428 
2429 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2430 	if (req == NULL) {
2431 		PRINTM(MIOCTL, "IOCTL req allocated failed!\n");
2432 		ret = MLAN_STATUS_FAILURE;
2433 		goto done;
2434 	}
2435 	misc = (mlan_ds_misc_cfg *)req->pbuf;
2436 	misc->sub_command = MLAN_OID_MISC_IP_ADDR;
2437 	req->req_id = MLAN_IOCTL_MISC_CFG;
2438 	req->action = MLAN_ACT_SET;
2439 	memcpy(&misc->param.ipaddr_cfg, &ipaddr_cfg, sizeof(ipaddr_cfg));
2440 	if (enable) {
2441 		misc->param.ipaddr_cfg.op_code = MLAN_IPADDR_OP_ARP_FILTER |
2442 			MLAN_IPADDR_OP_AUTO_ARP_RESP;
2443 		misc->param.ipaddr_cfg.ip_addr_type = IPADDR_TYPE_IPV4;
2444 	} else {
2445 	/** remove ip */
2446 		misc->param.ipaddr_cfg.op_code = MLAN_IPADDR_OP_IP_REMOVE;
2447 	}
2448 	ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), req,
2449 				 MOAL_NO_WAIT);
2450 	if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING)
2451 		PRINTM(MIOCTL, "Set auto arp IOCTL failed!\n");
2452 done:
2453 	if (ret != MLAN_STATUS_PENDING)
2454 		kfree(req);
2455 	LEAVE();
2456 	return ret;
2457 }
2458 
2459 #endif
2460 
2461 /**
2462  *  @brief Set/Get DTIM period
2463  *
2464  *  @param priv                 A pointer to moal_private structure
2465  *  @param action               Action set or get
2466  *  @param wait_option          Wait option
2467  *  @param value                DTIM period
2468  *
2469  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
2470  */
2471 mlan_status
woal_set_get_dtim_period(moal_private * priv,t_u32 action,t_u8 wait_option,t_u8 * value)2472 woal_set_get_dtim_period(moal_private *priv,
2473 			 t_u32 action, t_u8 wait_option, t_u8 *value)
2474 {
2475 	mlan_ioctl_req *req = NULL;
2476 	mlan_ds_snmp_mib *mib = NULL;
2477 	mlan_status ret = MLAN_STATUS_SUCCESS;
2478 
2479 	ENTER();
2480 
2481 	/* Allocate an IOCTL request buffer */
2482 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
2483 	if (req == NULL) {
2484 		ret = MLAN_STATUS_FAILURE;
2485 		goto done;
2486 	}
2487 
2488 	/* Fill request buffer */
2489 	mib = (mlan_ds_snmp_mib *)req->pbuf;
2490 	mib->sub_command = MLAN_OID_SNMP_MIB_DTIM_PERIOD;
2491 	req->req_id = MLAN_IOCTL_SNMP_MIB;
2492 	req->action = action;
2493 
2494 	if (action == MLAN_ACT_SET)
2495 		mib->param.dtim_period = *value;
2496 
2497 	/* Send IOCTL request to MLAN */
2498 	ret = woal_request_ioctl(priv, req, wait_option);
2499 	if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET)
2500 		*value = (t_u8)mib->param.dtim_period;
2501 
2502 done:
2503 	if (ret != MLAN_STATUS_PENDING)
2504 		kfree(req);
2505 	LEAVE();
2506 	return ret;
2507 }
2508 
2509 /**
2510  *  @brief Get Host Sleep parameters
2511  *
2512  *  @param priv         A pointer to moal_private structure
2513  *  @param action       Action: set or get
2514  *  @param wait_option  Wait option (MOAL_IOCTL_WAIT or MOAL_NO_WAIT)
2515  *  @param hscfg        A pointer to mlan_ds_hs_cfg structure
2516  *
2517  *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
2518  */
2519 mlan_status
woal_set_get_hs_params(moal_private * priv,t_u16 action,t_u8 wait_option,mlan_ds_hs_cfg * hscfg)2520 woal_set_get_hs_params(moal_private *priv, t_u16 action, t_u8 wait_option,
2521 		       mlan_ds_hs_cfg *hscfg)
2522 {
2523 	mlan_status ret = MLAN_STATUS_SUCCESS;
2524 	mlan_ds_pm_cfg *pmcfg = NULL;
2525 	mlan_ioctl_req *req = NULL;
2526 
2527 	ENTER();
2528 
2529 	/* Allocate an IOCTL request buffer */
2530 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
2531 	if (req == NULL) {
2532 		ret = -ENOMEM;
2533 		goto done;
2534 	}
2535 
2536 	/* Fill request buffer */
2537 	pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
2538 	pmcfg->sub_command = MLAN_OID_PM_CFG_HS_CFG;
2539 	req->req_id = MLAN_IOCTL_PM_CFG;
2540 	req->action = action;
2541 	if (action == MLAN_ACT_SET)
2542 		memcpy(&pmcfg->param.hs_cfg, hscfg, sizeof(mlan_ds_hs_cfg));
2543 
2544 	/* Send IOCTL request to MLAN */
2545 	ret = woal_request_ioctl(priv, req, wait_option);
2546 	if (ret == MLAN_STATUS_SUCCESS) {
2547 		if (hscfg && action == MLAN_ACT_GET) {
2548 			memcpy(hscfg, &pmcfg->param.hs_cfg,
2549 			       sizeof(mlan_ds_hs_cfg));
2550 		}
2551 	}
2552 done:
2553 	if (ret != MLAN_STATUS_PENDING)
2554 		kfree(req);
2555 	LEAVE();
2556 	return ret;
2557 }
2558 
2559 /**
2560  *  @brief Get wakeup reason
2561  *
2562  *  @param priv         A pointer to moal_private structure
2563  *  @param wakeup_reason        A pointer to mlan_ds_hs_wakeup_reason  structure
2564  *
2565  *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
2566  */
2567 mlan_status
woal_get_wakeup_reason(moal_private * priv,mlan_ds_hs_wakeup_reason * wakeup_reason)2568 woal_get_wakeup_reason(moal_private *priv,
2569 		       mlan_ds_hs_wakeup_reason *wakeup_reason)
2570 {
2571 	mlan_status ret = MLAN_STATUS_SUCCESS;
2572 	mlan_ds_pm_cfg *pmcfg = NULL;
2573 	mlan_ioctl_req *req = NULL;
2574 
2575 	ENTER();
2576 
2577 	/* Allocate an IOCTL request buffer */
2578 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
2579 	if (req == NULL) {
2580 		ret = -ENOMEM;
2581 		goto done;
2582 	}
2583 
2584 	/* Fill request buffer */
2585 	pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
2586 	pmcfg->sub_command = MLAN_OID_PM_HS_WAKEUP_REASON;
2587 	req->req_id = MLAN_IOCTL_PM_CFG;
2588 	req->action = MLAN_ACT_GET;
2589 
2590 	/* Send IOCTL request to MLAN */
2591 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2592 	if (ret == MLAN_STATUS_SUCCESS) {
2593 		wakeup_reason->hs_wakeup_reason =
2594 			pmcfg->param.wakeup_reason.hs_wakeup_reason;
2595 	}
2596 done:
2597 	if (ret != MLAN_STATUS_PENDING)
2598 		kfree(req);
2599 	LEAVE();
2600 	return ret;
2601 }
2602 
2603 /**
2604  *  @brief Cancel Host Sleep configuration
2605  *
2606  *  @param priv             A pointer to moal_private structure
2607  *  @param wait_option      wait option
2608  *
2609  *  @return                 MLAN_STATUS_SUCCESS, MLAN_STATUS_PENDING,
2610  *                              or MLAN_STATUS_FAILURE
2611  */
2612 mlan_status
woal_cancel_hs(moal_private * priv,t_u8 wait_option)2613 woal_cancel_hs(moal_private *priv, t_u8 wait_option)
2614 {
2615 	moal_handle *handle = NULL;
2616 	mlan_status ret = MLAN_STATUS_SUCCESS;
2617 	mlan_ds_hs_cfg hscfg;
2618 	int i;
2619 	ENTER();
2620 
2621 	if (!priv) {
2622 		LEAVE();
2623 		return MLAN_STATUS_FAILURE;
2624 	}
2625 	handle = priv->phandle;
2626 	/* Cancel Host Sleep */
2627 
2628 	hscfg.conditions = HOST_SLEEP_CFG_CANCEL;
2629 	hscfg.is_invoke_hostcmd = MTRUE;
2630 	ret = woal_set_get_hs_params(priv, MLAN_ACT_SET, wait_option, &hscfg);
2631 
2632 	if (roamoffload_in_hs) {
2633 		/*Disable firmware roaming */
2634 		woal_enable_fw_roaming(priv, 0);
2635 	}
2636 	if (handle->fw_roam_enable == ROAM_OFFLOAD_WITH_BSSID ||
2637 	    handle->fw_roam_enable == ROAM_OFFLOAD_WITH_SSID ||
2638 	    handle->fw_roam_enable == AUTO_RECONNECT)
2639 		woal_config_fw_roaming(priv, ROAM_OFFLOAD_RESUME_CFG, NULL);
2640 	if (handle->fw_roam_enable == AUTO_RECONNECT)
2641 		woal_set_clear_pmk(priv, MLAN_ACT_CLEAR);
2642 
2643 #if defined(SDIO_SUSPEND_RESUME)
2644 	if (priv->phandle->hs_auto_arp) {
2645 		PRINTM(MIOCTL, "Cancel Host Sleep... remove FW auto arp\n");
2646 		/* remove auto arp from FW */
2647 		woal_set_auto_arp(priv->phandle, MFALSE);
2648 	}
2649 #endif
2650 
2651 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
2652 	if (GTK_REKEY_OFFLOAD_SUSPEND == gtk_rekey_offload) {
2653 		PRINTM(MIOCTL,
2654 		       "Cancel Host Sleep... clear gtk rekey offload of FW\n");
2655 		for (i = 0; i < handle->priv_num; i++) {
2656 			if (handle->priv[i] && handle->priv[i]->gtk_data_ready) {
2657 				PRINTM(MCMND, "clear GTK in resume\n");
2658 				woal_set_rekey_data(handle->priv[i], NULL,
2659 						    MLAN_ACT_CLEAR);
2660 			}
2661 		}
2662 	}
2663 #endif
2664 
2665 	LEAVE();
2666 	return ret;
2667 }
2668 
2669 /**  @brief This function config fw roaming parameters
2670  *
2671  *  @param priv     A Pointer to the moal_private structure
2672  *  @return         MTRUE or MFALSE
2673  */
2674 int
woal_set_fw_roaming_params(moal_private * priv)2675 woal_set_fw_roaming_params(moal_private *priv)
2676 {
2677 	int ret = 0;
2678 	mlan_status status = MLAN_STATUS_SUCCESS;
2679 	mlan_ioctl_req *req = NULL;
2680 	mlan_ds_sec_cfg *sec = NULL;
2681 	woal_roam_offload_cfg roam_offload_cfg;
2682 	t_u8 zero[MLAN_MAX_KEY_LENGTH] = { 0 };
2683 
2684 	/*Enable fw roaming */
2685 	woal_config_fw_roaming(priv, ROAM_OFFLOAD_ENABLE, NULL);
2686 	/*Download fw roaming parameters */
2687 	woal_config_fw_roaming(priv, ROAM_OFFLOAD_PARAM_CFG,
2688 			       &priv->phandle->fw_roam_params);
2689 
2690 	/*Download userset passphrase key and current connection's PMK */
2691 	if (!priv->phandle->fw_roam_params.userset_passphrase) {
2692 		woal_set_clear_pmk(priv, MLAN_ACT_SET);
2693 		goto done;
2694 	}
2695 
2696 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
2697 	if (req == NULL) {
2698 		ret = -ENOMEM;
2699 		goto done;
2700 	}
2701 
2702 	req->req_id = MLAN_IOCTL_SEC_CFG;
2703 	sec = (mlan_ds_sec_cfg *)req->pbuf;
2704 	sec->sub_command = MLAN_OID_SEC_CFG_PASSPHRASE;
2705 	sec->multi_passphrase = 1;
2706 	req->action = MLAN_ACT_SET;
2707 
2708 	/*Copy user set passphrase */
2709 	memcpy((char *)sec->param.roam_passphrase,
2710 	       (char *)priv->phandle->ssid_passphrase,
2711 	       MAX_SEC_SSID_NUM * sizeof(mlan_ds_passphrase));
2712 	roam_offload_cfg.userset_passphrase =
2713 		priv->phandle->fw_roam_params.userset_passphrase;
2714 
2715 	if (memcmp(priv->pmk.pmk, zero, MLAN_MAX_KEY_LENGTH)) {
2716 		/*Download current connection PMK */
2717 		if (priv->pmk_saved) {
2718 			woal_set_clear_pmk(priv, MLAN_ACT_SET);
2719 			priv->pmk_saved = false;
2720 		}
2721 	}
2722 
2723 	/*Set userset to mlan adapter */
2724 	woal_config_fw_roaming(priv, ROAM_OFFLOAD_ENABLE, &roam_offload_cfg);
2725 
2726 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2727 	if (status != MLAN_STATUS_SUCCESS) {
2728 		ret = -EFAULT;
2729 		goto done;
2730 	}
2731 	if (ret)
2732 		goto done;
2733 done:
2734 	if (status != MLAN_STATUS_PENDING)
2735 		kfree(req);
2736 	LEAVE();
2737 	return ret;
2738 }
2739 
2740 /**  @brief This function enable/disable fw roaming
2741  *
2742  *  @param priv     A Pointer to the moal_private structure
2743  *  @param enable   Enable/disable fw roaming
2744  *  @return         MTRUE or MFALSE
2745  */
2746 int
woal_enable_fw_roaming(moal_private * priv,int data)2747 woal_enable_fw_roaming(moal_private *priv, int data)
2748 {
2749 	mlan_ioctl_req *ioctl_req = NULL;
2750 	mlan_ds_misc_cfg *misc = NULL;
2751 	mlan_ds_misc_roam_offload *roam = NULL;
2752 	mlan_status status = MLAN_STATUS_SUCCESS;
2753 	int ret = 0;
2754 
2755 	ENTER();
2756 
2757 	if (!priv || !priv->phandle) {
2758 		PRINTM(MERROR, "priv or handle is null\n");
2759 		ret = -EFAULT;
2760 		goto done;
2761 	}
2762 
2763 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2764 	if (ioctl_req == NULL) {
2765 		ret = -ENOMEM;
2766 		goto done;
2767 	}
2768 
2769 	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
2770 	misc->sub_command = MLAN_OID_MISC_ROAM_OFFLOAD;
2771 	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
2772 
2773 	roam = (mlan_ds_misc_roam_offload *) & misc->param.roam_offload;
2774 	roam->aplist.ap_num = 0;
2775 	/* SET operation */
2776 	ioctl_req->action = MLAN_ACT_SET;
2777 	roam->enable = data;
2778 	roam->config_mode = ROAM_OFFLOAD_ENABLE;
2779 
2780 	if (roamoffload_in_hs && data) {
2781 		priv->phandle->fw_roam_enable = data;
2782 		goto done;
2783 	}
2784 
2785 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2786 	if (status != MLAN_STATUS_SUCCESS) {
2787 		ret = -EFAULT;
2788 		goto done;
2789 	}
2790 	priv->phandle->fw_roam_enable = data;
2791 	if (!data) {
2792 		memset((char *)&priv->phandle->fw_roam_params, 0,
2793 		       sizeof(woal_roam_offload_cfg));
2794 		memset((char *)&priv->phandle->ssid_passphrase, 0,
2795 		       MAX_SEC_SSID_NUM * sizeof(mlan_ds_passphrase));
2796 	} else if (priv->media_connected && priv->pmk_saved) {
2797 		woal_set_clear_pmk(priv, MLAN_ACT_SET);
2798 		priv->pmk_saved = false;
2799 	}
2800 
2801 done:
2802 	if (status != MLAN_STATUS_PENDING)
2803 		kfree(ioctl_req);
2804 
2805 	LEAVE();
2806 	return ret;
2807 }
2808 
2809 #if defined(SDIO_SUSPEND_RESUME)
2810 /**  @brief This function enables the host sleep
2811  *
2812  *  @param priv     A Pointer to the moal_private structure
2813  *  @return         MTRUE or MFALSE
2814  */
2815 int
woal_enable_hs(moal_private * priv)2816 woal_enable_hs(moal_private *priv)
2817 {
2818 	mlan_ds_hs_cfg hscfg;
2819 	moal_handle *handle = NULL;
2820 	int hs_actived = MFALSE;
2821 	int timeout = 0;
2822 	int i;
2823 #ifdef SDIO_SUSPEND_RESUME
2824 	mlan_ds_ps_info pm_info;
2825 #endif
2826 
2827 	ENTER();
2828 
2829 	if (priv == NULL) {
2830 		PRINTM(MERROR, "Invalid priv\n");
2831 		goto done;
2832 	}
2833 	handle = priv->phandle;
2834 	if (handle->hs_activated == MTRUE) {
2835 		PRINTM(MIOCTL, "HS Already actived\n");
2836 		hs_actived = MTRUE;
2837 		goto done;
2838 	}
2839 	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
2840 		if (handle->priv[i] &&
2841 		    (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA)) {
2842 			if (disconnect_on_suspend &&
2843 			    handle->priv[i]->media_connected == MTRUE) {
2844 				PRINTM(MIOCTL, "disconnect on suspend\n");
2845 				woal_disconnect(handle->priv[i], MOAL_NO_WAIT,
2846 						NULL, DEF_DEAUTH_REASON_CODE);
2847 			}
2848 		}
2849 		if (handle->priv[i]) {
2850 			PRINTM(MIOCTL, "woal_delba_all on priv[%d]\n", i);
2851 			woal_delba_all(handle->priv[i], MOAL_IOCTL_WAIT);
2852 		}
2853 	}
2854 
2855 #if defined(STA_CFG80211) && defined(UAP_CFG80211)
2856 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
2857 
2858 	if (priv->phandle->is_remain_timer_set) {
2859 		woal_cancel_timer(&priv->phandle->remain_timer);
2860 		woal_remain_timer_func(priv->phandle);
2861 	}
2862 	/* cancel pending remain on channel */
2863 	if (priv->phandle->remain_on_channel) {
2864 		t_u8 channel_status;
2865 		moal_private *remain_priv =
2866 			priv->phandle->priv[priv->phandle->remain_bss_index];
2867 		if (remain_priv) {
2868 			woal_cfg80211_remain_on_channel_cfg(remain_priv,
2869 							    MOAL_NO_WAIT, MTRUE,
2870 							    &channel_status,
2871 							    NULL, 0, 0);
2872 			if (priv->phandle->cookie) {
2873 				cfg80211_remain_on_channel_expired(
2874 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
2875 									  remain_priv->
2876 									  netdev,
2877 #else
2878 									  remain_priv->
2879 									  wdev,
2880 #endif
2881 									  priv->
2882 									  phandle->
2883 									  cookie,
2884 									  &priv->
2885 									  phandle->
2886 									  chan,
2887 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
2888 									  priv->
2889 									  phandle->
2890 									  channel_type,
2891 #endif
2892 									  GFP_ATOMIC);
2893 				priv->phandle->cookie = 0;
2894 			}
2895 		}
2896 		priv->phandle->remain_on_channel = MFALSE;
2897 	}
2898 #endif
2899 #endif
2900 
2901 #ifdef STA_SUPPORT
2902 	woal_reconfig_bgscan(priv->phandle);
2903 #endif
2904 
2905 	if (roamoffload_in_hs) {
2906 		woal_set_fw_roaming_params(priv);
2907 	}
2908 	if (handle->fw_roam_enable == ROAM_OFFLOAD_WITH_BSSID ||
2909 	    handle->fw_roam_enable == ROAM_OFFLOAD_WITH_SSID ||
2910 	    handle->fw_roam_enable == AUTO_RECONNECT) {
2911 		woal_config_fw_roaming(priv, ROAM_OFFLOAD_SUSPEND_CFG, NULL);
2912 		if (priv->phandle->fw_roam_enable == AUTO_RECONNECT)
2913 			woal_set_clear_pmk(priv, MLAN_ACT_SET);
2914 	}
2915 
2916 	if (handle->hs_auto_arp) {
2917 		PRINTM(MIOCTL, "Host Sleep enabled... set FW auto arp\n");
2918 		/* Set auto arp response configuration to Fw */
2919 		woal_set_auto_arp(handle, MTRUE);
2920 	}
2921 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
2922 	if (GTK_REKEY_OFFLOAD_SUSPEND == gtk_rekey_offload) {
2923 		PRINTM(MIOCTL,
2924 		       "Host Sleep enabled... set gtk rekey offload to FW\n");
2925 		for (i = 0; i < handle->priv_num; i++) {
2926 			if (handle->priv[i] && handle->priv[i]->gtk_data_ready) {
2927 				PRINTM(MCMND, "set GTK before suspend\n");
2928 				woal_set_rekey_data(handle->priv[i],
2929 						    &handle->priv[i]->
2930 						    gtk_rekey_data,
2931 						    MLAN_ACT_SET);
2932 			}
2933 		}
2934 	}
2935 #endif
2936 
2937 	/* Enable Host Sleep */
2938 	handle->hs_activate_wait_q_woken = MFALSE;
2939 	memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg));
2940 	hscfg.is_invoke_hostcmd = MTRUE;
2941 	if (woal_set_get_hs_params(priv, MLAN_ACT_SET, MOAL_NO_WAIT, &hscfg) ==
2942 	    MLAN_STATUS_FAILURE) {
2943 		PRINTM(MIOCTL, "IOCTL request HS enable failed\n");
2944 		goto done;
2945 	}
2946 	timeout = wait_event_interruptible_timeout(handle->hs_activate_wait_q,
2947 						   handle->
2948 						   hs_activate_wait_q_woken,
2949 						   HS_ACTIVE_TIMEOUT);
2950 	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
2951 	if ((handle->hs_activated == MTRUE) || (handle->is_suspended == MTRUE)) {
2952 		PRINTM(MCMND, "suspend success! force=%u skip=%u\n",
2953 		       handle->hs_force_count, handle->hs_skip_count);
2954 		hs_actived = MTRUE;
2955 	}
2956 #ifdef SDIO_SUSPEND_RESUME
2957 	else {
2958 		handle->suspend_fail = MTRUE;
2959 		woal_get_pm_info(priv, &pm_info);
2960 		if (pm_info.is_suspend_allowed == MTRUE) {
2961 #ifdef MMC_PM_FUNC_SUSPENDED
2962 			woal_wlan_is_suspended(priv->phandle);
2963 #endif
2964 			handle->hs_force_count++;
2965 			PRINTM(MCMND, "suspend allowed! force=%u skip=%u\n",
2966 			       handle->hs_force_count, handle->hs_skip_count);
2967 			hs_actived = MTRUE;
2968 		}
2969 	}
2970 #endif /* SDIO_SUSPEND_RESUME */
2971 	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
2972 	if (hs_actived != MTRUE) {
2973 		handle->hs_skip_count++;
2974 #ifdef SDIO_SUSPEND_RESUME
2975 		PRINTM(MCMND,
2976 		       "suspend skipped! timeout=%d allow=%d force=%u skip=%u\n",
2977 		       timeout, (int)pm_info.is_suspend_allowed,
2978 		       handle->hs_force_count, handle->hs_skip_count);
2979 #else
2980 		PRINTM(MCMND, "suspend skipped! timeout=%d skip=%u\n",
2981 		       timeout, handle->hs_skip_count);
2982 #endif
2983 		woal_cancel_hs(priv, MOAL_NO_WAIT);
2984 	}
2985 done:
2986 	LEAVE();
2987 	return hs_actived;
2988 }
2989 #endif
2990 
2991 #ifdef CONFIG_PROC_FS
2992 /**
2993  *  @brief This function send soft_reset command to firmware
2994  *
2995  *  @param handle   A pointer to moal_handle structure
2996  *  @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING on success,
2997  *                      otherwise failure code
2998  */
2999 mlan_status
woal_request_soft_reset(moal_handle * handle)3000 woal_request_soft_reset(moal_handle *handle)
3001 {
3002 	mlan_status ret = MLAN_STATUS_SUCCESS;
3003 	mlan_ioctl_req *req = NULL;
3004 	mlan_ds_misc_cfg *misc = NULL;
3005 
3006 	ENTER();
3007 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3008 	if (req) {
3009 		misc = (mlan_ds_misc_cfg *)req->pbuf;
3010 		misc->sub_command = MLAN_OID_MISC_SOFT_RESET;
3011 		req->req_id = MLAN_IOCTL_MISC_CFG;
3012 		req->action = MLAN_ACT_SET;
3013 		ret = woal_request_ioctl(woal_get_priv
3014 					 (handle, MLAN_BSS_ROLE_ANY), req,
3015 					 MOAL_IOCTL_WAIT);
3016 	}
3017 
3018 	handle->surprise_removed = MTRUE;
3019 	woal_sched_timeout(5);
3020 	if (ret != MLAN_STATUS_PENDING)
3021 		kfree(req);
3022 	LEAVE();
3023 	return ret;
3024 }
3025 #endif /* CONFIG_PROC_FS */
3026 
3027 /**
3028  *  @brief Set wapi enable
3029  *
3030  *  @param priv                 A pointer to moal_private structure
3031  *  @param wait_option          Wait option
3032  *  @param enable               MTRUE or MFALSE
3033  *
3034  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
3035  */
3036 mlan_status
woal_set_wapi_enable(moal_private * priv,t_u8 wait_option,t_u32 enable)3037 woal_set_wapi_enable(moal_private *priv, t_u8 wait_option, t_u32 enable)
3038 {
3039 	int ret = 0;
3040 	mlan_ioctl_req *req = NULL;
3041 	mlan_ds_sec_cfg *sec = NULL;
3042 	mlan_status status = MLAN_STATUS_SUCCESS;
3043 	ENTER();
3044 
3045 	/* Allocate an IOCTL request buffer */
3046 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
3047 	if (req == NULL) {
3048 		ret = -ENOMEM;
3049 		goto done;
3050 	}
3051 
3052 	/* Fill request buffer */
3053 	sec = (mlan_ds_sec_cfg *)req->pbuf;
3054 	sec->sub_command = MLAN_OID_SEC_CFG_WAPI_ENABLED;
3055 	req->req_id = MLAN_IOCTL_SEC_CFG;
3056 	req->action = MLAN_ACT_SET;
3057 	sec->param.wapi_enabled = enable;
3058 
3059 	/* Send IOCTL request to MLAN */
3060 	status = woal_request_ioctl(priv, req, wait_option);
3061 done:
3062 	if (status != MLAN_STATUS_PENDING)
3063 		kfree(req);
3064 	LEAVE();
3065 	return status;
3066 }
3067 
3068 /**
3069  *  @brief Get version
3070  *
3071  *  @param handle       A pointer to moal_handle structure
3072  *  @param version      A pointer to version buffer
3073  *  @param max_len      max length of version buffer
3074  *
3075  *  @return             N/A
3076  */
3077 void
woal_get_version(moal_handle * handle,char * version,int max_len)3078 woal_get_version(moal_handle *handle, char *version, int max_len)
3079 {
3080 	union {
3081 		t_u32 l;
3082 		t_u8 c[4];
3083 	} ver;
3084 	char fw_ver[32];
3085 
3086 	ENTER();
3087 
3088 	ver.l = handle->fw_release_number;
3089 	snprintf(fw_ver, sizeof(fw_ver), "%u.%u.%u.p%u",
3090 		 ver.c[2], ver.c[1], ver.c[0], ver.c[3]);
3091 
3092 	snprintf(version, max_len, handle->driver_version, fw_ver);
3093 
3094 	LEAVE();
3095 }
3096 
3097 #if defined(STA_WEXT) || defined(UAP_WEXT)
3098 /**
3099  *  @brief Get Driver Version
3100  *
3101  *  @param priv         A pointer to moal_private structure
3102  *  @param req          A pointer to ifreq structure
3103  *
3104  *  @return             0 --success, otherwise fail
3105  */
3106 int
woal_get_driver_version(moal_private * priv,struct ifreq * req)3107 woal_get_driver_version(moal_private *priv, struct ifreq *req)
3108 {
3109 	struct iwreq *wrq = (struct iwreq *)req;
3110 	int len;
3111 	char buf[MLAN_MAX_VER_STR_LEN];
3112 	ENTER();
3113 
3114 	woal_get_version(priv->phandle, buf, sizeof(buf) - 1);
3115 
3116 	len = strlen(buf);
3117 	if (wrq->u.data.pointer) {
3118 		if (copy_to_user(wrq->u.data.pointer, buf, len)) {
3119 			PRINTM(MERROR, "Copy to user failed\n");
3120 			LEAVE();
3121 			return -EFAULT;
3122 		}
3123 		wrq->u.data.length = len;
3124 	}
3125 	PRINTM(MINFO, "MOAL VERSION: %s\n", buf);
3126 	LEAVE();
3127 	return 0;
3128 }
3129 
3130 /**
3131  *  @brief Get extended driver version
3132  *
3133  *  @param priv         A pointer to moal_private structure
3134  *  @param ireq         A pointer to ifreq structure
3135  *
3136  *  @return             0 --success, otherwise fail
3137  */
3138 int
woal_get_driver_verext(moal_private * priv,struct ifreq * ireq)3139 woal_get_driver_verext(moal_private *priv, struct ifreq *ireq)
3140 {
3141 	struct iwreq *wrq = (struct iwreq *)ireq;
3142 	mlan_ds_get_info *info = NULL;
3143 	mlan_ioctl_req *req = NULL;
3144 	int ret = 0;
3145 	mlan_status status = MLAN_STATUS_SUCCESS;
3146 
3147 	ENTER();
3148 
3149 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
3150 	if (req == NULL) {
3151 		LEAVE();
3152 		return -ENOMEM;
3153 	}
3154 
3155 	info = (mlan_ds_get_info *)req->pbuf;
3156 	info->sub_command = MLAN_OID_GET_VER_EXT;
3157 	req->req_id = MLAN_IOCTL_GET_INFO;
3158 	req->action = MLAN_ACT_GET;
3159 
3160 	if (!wrq->u.data.flags) {
3161 		info->param.ver_ext.version_str_sel =
3162 			*((int *)(wrq->u.name + SUBCMD_OFFSET));
3163 	} else {
3164 		if (copy_from_user
3165 		    (&info->param.ver_ext.version_str_sel, wrq->u.data.pointer,
3166 		     sizeof(info->param.ver_ext.version_str_sel))) {
3167 			PRINTM(MERROR, "Copy from user failed\n");
3168 			ret = -EFAULT;
3169 			goto done;
3170 		} else {
3171 			if (((t_s32)(info->param.ver_ext.version_str_sel)) < 0) {
3172 				PRINTM(MERROR, "Invalid arguments!\n");
3173 				ret = -EINVAL;
3174 				goto done;
3175 			}
3176 		}
3177 	}
3178 
3179 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3180 	if (status != MLAN_STATUS_SUCCESS) {
3181 		ret = -EFAULT;
3182 		goto done;
3183 	}
3184 
3185 	if (wrq->u.data.pointer) {
3186 		if (copy_to_user
3187 		    (wrq->u.data.pointer, info->param.ver_ext.version_str,
3188 		     strlen(info->param.ver_ext.version_str))) {
3189 			PRINTM(MERROR, "Copy to user failed\n");
3190 			ret = -EFAULT;
3191 			goto done;
3192 		}
3193 		wrq->u.data.length = strlen(info->param.ver_ext.version_str);
3194 	}
3195 
3196 	PRINTM(MINFO, "MOAL EXTENDED VERSION: %s\n",
3197 	       info->param.ver_ext.version_str);
3198 done:
3199 	if (status != MLAN_STATUS_PENDING)
3200 		kfree(req);
3201 
3202 	LEAVE();
3203 	return ret;
3204 }
3205 #endif
3206 
3207 #ifdef DEBUG_LEVEL1
3208 /**
3209  *  @brief Set driver debug bit masks to mlan in order to enhance performance
3210  *
3211  *  @param priv         A pointer to moal_private structure
3212  *  @param drvdbg       Driver debug level
3213  *
3214  *  @return             0 --success, otherwise fail
3215  */
3216 int
woal_set_drvdbg(moal_private * priv,t_u32 drvdbg)3217 woal_set_drvdbg(moal_private *priv, t_u32 drvdbg)
3218 {
3219 	mlan_ioctl_req *req = NULL;
3220 	mlan_ds_misc_cfg *misc = NULL;
3221 	int ret = 0;
3222 
3223 	ENTER();
3224 
3225 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3226 	if (req == NULL) {
3227 		LEAVE();
3228 		return -ENOMEM;
3229 	}
3230 
3231 	misc = (mlan_ds_misc_cfg *)req->pbuf;
3232 	misc->sub_command = MLAN_OID_MISC_DRVDBG;
3233 	req->req_id = MLAN_IOCTL_MISC_CFG;
3234 	req->action = MLAN_ACT_SET;
3235 	misc->param.drvdbg = drvdbg;
3236 
3237 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3238 
3239 	if (ret != MLAN_STATUS_PENDING)
3240 		kfree(req);
3241 
3242 	LEAVE();
3243 	return ret;
3244 }
3245 #endif
3246 
3247 /**
3248  *  @brief Mgmt frame forward registration
3249  *
3250  *  @param priv         A pointer to moal_private structure
3251  *  @param action       Action: set or get
3252  *  @param pmgmt_subtype_mask   A Pointer to mgmt frame subtype mask
3253  *  @param wait_option  wait option (MOAL_IOCTL_WAIT or MOAL_NO_WAIT)
3254  *
3255  *  @return             0 --success, otherwise fail
3256  */
3257 int
woal_reg_rx_mgmt_ind(moal_private * priv,t_u16 action,t_u32 * pmgmt_subtype_mask,t_u8 wait_option)3258 woal_reg_rx_mgmt_ind(moal_private *priv, t_u16 action,
3259 		     t_u32 *pmgmt_subtype_mask, t_u8 wait_option)
3260 {
3261 	mlan_ioctl_req *req = NULL;
3262 	mlan_ds_misc_cfg *misc = NULL;
3263 	int ret = 0;
3264 
3265 	ENTER();
3266 
3267 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3268 	if (req == NULL) {
3269 		LEAVE();
3270 		return -ENOMEM;
3271 	}
3272 
3273 	misc = (mlan_ds_misc_cfg *)req->pbuf;
3274 	misc->sub_command = MLAN_OID_MISC_RX_MGMT_IND;
3275 	req->req_id = MLAN_IOCTL_MISC_CFG;
3276 	req->action = action;
3277 	misc->param.mgmt_subtype_mask = *pmgmt_subtype_mask;
3278 	if (req->action == MLAN_ACT_SET)
3279 		memcpy(&misc->param.mgmt_subtype_mask,
3280 		       pmgmt_subtype_mask,
3281 		       sizeof(misc->param.mgmt_subtype_mask));
3282 
3283 	ret = woal_request_ioctl(priv, req, wait_option);
3284 
3285 	if (req->action == MLAN_ACT_GET)
3286 		memcpy(pmgmt_subtype_mask, &misc->param.mgmt_subtype_mask,
3287 		       sizeof(misc->param.mgmt_subtype_mask));
3288 
3289 	if (ret != MLAN_STATUS_PENDING)
3290 		kfree(req);
3291 
3292 	LEAVE();
3293 	return ret;
3294 }
3295 
3296 /**
3297  *  @brief Set/Get Transmit beamforming capabilities
3298  *
3299  *  @param priv     A pointer to moal_private structure
3300  *  @param action       Action: set or get
3301  *  @param tx_bf_cap    A pointer to tx_buf_cap buffer
3302  *
3303  *  @return         MLAN_STATUS_SUCCESS -- success, otherwise fail
3304  */
3305 mlan_status
woal_set_get_tx_bf_cap(moal_private * priv,t_u16 action,t_u32 * tx_bf_cap)3306 woal_set_get_tx_bf_cap(moal_private *priv, t_u16 action, t_u32 *tx_bf_cap)
3307 {
3308 	mlan_ioctl_req *req = NULL;
3309 	mlan_ds_11n_cfg *bf_cfg = NULL;
3310 	mlan_status ret = MLAN_STATUS_SUCCESS;
3311 
3312 	ENTER();
3313 
3314 	if (!tx_bf_cap) {
3315 		ret = MLAN_STATUS_FAILURE;
3316 		goto done;
3317 	}
3318 	/* Allocate an IOCTL request buffer */
3319 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
3320 	if (req == NULL) {
3321 		ret = MLAN_STATUS_FAILURE;
3322 		goto done;
3323 	}
3324 
3325 	/* Fill request buffer */
3326 	bf_cfg = (mlan_ds_11n_cfg *)req->pbuf;
3327 	req->req_id = MLAN_IOCTL_11N_CFG;
3328 	bf_cfg->sub_command = MLAN_OID_11N_CFG_TX_BF_CAP;
3329 	req->action = action;
3330 	if (action == MLAN_ACT_SET)
3331 		bf_cfg->param.tx_bf_cap = *tx_bf_cap;
3332 
3333 	/* Send IOCTL request to MLAN */
3334 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3335 	if (ret != MLAN_STATUS_SUCCESS) {
3336 		goto done;
3337 	}
3338 
3339 	if (action == MLAN_ACT_GET)
3340 		*tx_bf_cap = bf_cfg->param.tx_bf_cap;
3341 
3342 done:
3343 	if (ret != MLAN_STATUS_PENDING)
3344 		kfree(req);
3345 	LEAVE();
3346 	return ret;
3347 }
3348 
3349 /**
3350  *  @brief Set/Get Transmit beamforming configuration
3351  *
3352  *  @param priv         A pointer to moal_private structure
3353  *  @param action       Action: set or get
3354  *  @param tx_bf_cfg    A pointer to tx_bf_cfg structure
3355  *
3356  *  @return         MLAN_STATUS_SUCCESS -- success, otherwise fail
3357  */
3358 mlan_status
woal_set_get_tx_bf_cfg(moal_private * priv,t_u16 action,mlan_ds_11n_tx_bf_cfg * tx_bf_cfg)3359 woal_set_get_tx_bf_cfg(moal_private *priv, t_u16 action,
3360 		       mlan_ds_11n_tx_bf_cfg *tx_bf_cfg)
3361 {
3362 	mlan_status ret = MLAN_STATUS_SUCCESS;
3363 	mlan_ioctl_req *req = NULL;
3364 	mlan_ds_11n_cfg *bf_cfg = NULL;
3365 
3366 	ENTER();
3367 
3368 	/* Sanity test */
3369 	if (tx_bf_cfg == NULL) {
3370 		ret = MLAN_STATUS_FAILURE;
3371 		goto done;
3372 	}
3373 
3374 	/* Allocate an IOCTL request buffer */
3375 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
3376 	if (req == NULL) {
3377 		ret = MLAN_STATUS_FAILURE;
3378 		goto done;
3379 	}
3380 
3381 	/* Fill request buffer */
3382 	bf_cfg = (mlan_ds_11n_cfg *)req->pbuf;
3383 	req->req_id = MLAN_IOCTL_11N_CFG;
3384 	bf_cfg->sub_command = MLAN_OID_11N_CFG_TX_BF_CFG;
3385 
3386 	req->action = action;
3387 	memcpy(&bf_cfg->param.tx_bf, tx_bf_cfg, sizeof(mlan_ds_11n_tx_bf_cfg));
3388 
3389 	/* Send IOCTL request to MLAN */
3390 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3391 	if (ret != MLAN_STATUS_SUCCESS)
3392 		goto done;
3393 
3394 	if (action == MLAN_ACT_GET)
3395 		memcpy(tx_bf_cfg, &bf_cfg->param.tx_bf,
3396 		       sizeof(mlan_ds_11n_tx_bf_cfg));
3397 
3398 done:
3399 	if (ret != MLAN_STATUS_PENDING)
3400 		kfree(req);
3401 	LEAVE();
3402 	return ret;
3403 }
3404 
3405 /**
3406  *  @brief Handle ioctl resp
3407  *
3408  *  @param priv     Pointer to moal_private structure
3409  *  @param req      Pointer to mlan_ioctl_req structure
3410  *
3411  *  @return         N/A
3412  */
3413 void
woal_process_ioctl_resp(moal_private * priv,mlan_ioctl_req * req)3414 woal_process_ioctl_resp(moal_private *priv, mlan_ioctl_req *req)
3415 {
3416 	ENTER();
3417 
3418 	if (priv == NULL) {
3419 		LEAVE();
3420 		return;
3421 	}
3422 	switch (req->req_id) {
3423 	case MLAN_IOCTL_GET_INFO:
3424 #ifdef STA_WEXT
3425 #ifdef STA_SUPPORT
3426 		if (IS_STA_WEXT(cfg80211_wext) &&
3427 		    GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
3428 			woal_ioctl_get_info_resp(priv,
3429 						 (mlan_ds_get_info *)req->pbuf);
3430 #endif
3431 #endif
3432 #ifdef UAP_WEXT
3433 #ifdef UAP_SUPPORT
3434 		if (IS_UAP_WEXT(cfg80211_wext) &&
3435 		    GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
3436 			woal_ioctl_get_uap_info_resp(priv,
3437 						     (mlan_ds_get_info *)req->
3438 						     pbuf);
3439 #endif
3440 #endif
3441 		break;
3442 #ifdef STA_WEXT
3443 #ifdef STA_SUPPORT
3444 	case MLAN_IOCTL_BSS:
3445 		if (IS_STA_WEXT(cfg80211_wext) &&
3446 		    GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
3447 			woal_ioctl_get_bss_resp(priv, (mlan_ds_bss *)req->pbuf);
3448 		break;
3449 #endif
3450 #endif
3451 	case MLAN_IOCTL_MISC_CFG:
3452 		woal_ioctl_get_misc_conf(priv, (mlan_ds_misc_cfg *)req->pbuf);
3453 	default:
3454 		break;
3455 	}
3456 
3457 	LEAVE();
3458 	return;
3459 }
3460 
3461 /**
3462  *  @brief Get PM info
3463  *
3464  *  @param priv                 A pointer to moal_private structure
3465  *  @param pm_info              A pointer to mlan_ds_ps_info structure
3466  *
3467  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
3468  */
3469 mlan_status
woal_get_pm_info(moal_private * priv,mlan_ds_ps_info * pm_info)3470 woal_get_pm_info(moal_private *priv, mlan_ds_ps_info *pm_info)
3471 {
3472 	mlan_status ret = MLAN_STATUS_SUCCESS;
3473 	mlan_ds_pm_cfg *pmcfg = NULL;
3474 	mlan_ioctl_req *req = NULL;
3475 
3476 	ENTER();
3477 
3478 	/* Allocate an IOCTL request buffer */
3479 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
3480 	if (req == NULL) {
3481 		PRINTM(MERROR, "Fail to alloc mlan_ds_pm_cfg buffer\n");
3482 		ret = MLAN_STATUS_FAILURE;
3483 		goto done;
3484 	}
3485 
3486 	/* Fill request buffer */
3487 	pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
3488 	pmcfg->sub_command = MLAN_OID_PM_INFO;
3489 	req->req_id = MLAN_IOCTL_PM_CFG;
3490 	req->action = MLAN_ACT_GET;
3491 
3492 	/* Send IOCTL request to MLAN */
3493 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3494 	if (ret == MLAN_STATUS_SUCCESS) {
3495 		if (pm_info) {
3496 			memcpy(pm_info, &pmcfg->param.ps_info,
3497 			       sizeof(mlan_ds_ps_info));
3498 		}
3499 	}
3500 done:
3501 	if (ret != MLAN_STATUS_PENDING)
3502 		kfree(req);
3503 	LEAVE();
3504 	return ret;
3505 }
3506 
3507 /**
3508  *  @brief Get Deep Sleep
3509  *
3510  *  @param priv      Pointer to the moal_private driver data struct
3511  *  @param data      Pointer to return deep_sleep setting
3512  *
3513  *  @return          0 --success, otherwise fail
3514  */
3515 int
woal_get_deep_sleep(moal_private * priv,t_u32 * data)3516 woal_get_deep_sleep(moal_private *priv, t_u32 *data)
3517 {
3518 	int ret = 0;
3519 	mlan_ioctl_req *req = NULL;
3520 	mlan_ds_pm_cfg *pm = NULL;
3521 	mlan_status status = MLAN_STATUS_SUCCESS;
3522 
3523 	ENTER();
3524 
3525 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
3526 	if (req == NULL) {
3527 		LEAVE();
3528 		return -ENOMEM;
3529 	}
3530 	pm = (mlan_ds_pm_cfg *)req->pbuf;
3531 	pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP;
3532 	req->req_id = MLAN_IOCTL_PM_CFG;
3533 
3534 	req->action = MLAN_ACT_GET;
3535 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3536 	if (status != MLAN_STATUS_SUCCESS) {
3537 		ret = -EFAULT;
3538 		goto done;
3539 	}
3540 	*data = pm->param.auto_deep_sleep.auto_ds;
3541 	*(data + 1) = pm->param.auto_deep_sleep.idletime;
3542 
3543 done:
3544 	if (status != MLAN_STATUS_PENDING)
3545 		kfree(req);
3546 	LEAVE();
3547 	return ret;
3548 }
3549 
3550 /**
3551  *  @brief Set Deep Sleep
3552  *
3553  *  @param priv         Pointer to the moal_private driver data struct
3554  *  @param wait_option  wait option
3555  *  @param bdeep_sleep  TRUE--enalbe deepsleep, FALSE--disable deepsleep
3556  *  @param idletime     Idle time for optimized PS API
3557  *
3558  *  @return             0 --success, otherwise fail
3559  */
3560 int
woal_set_deep_sleep(moal_private * priv,t_u8 wait_option,BOOLEAN bdeep_sleep,t_u16 idletime)3561 woal_set_deep_sleep(moal_private *priv, t_u8 wait_option, BOOLEAN bdeep_sleep,
3562 		    t_u16 idletime)
3563 {
3564 	int ret = 0;
3565 	mlan_ioctl_req *req = NULL;
3566 	mlan_ds_pm_cfg *pm = NULL;
3567 
3568 	ENTER();
3569 
3570 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
3571 	if (req == NULL) {
3572 		LEAVE();
3573 		return -ENOMEM;
3574 	}
3575 	pm = (mlan_ds_pm_cfg *)req->pbuf;
3576 	pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP;
3577 	req->req_id = MLAN_IOCTL_PM_CFG;
3578 
3579 	req->action = MLAN_ACT_SET;
3580 	if (bdeep_sleep == MTRUE) {
3581 		PRINTM(MIOCTL, "Deep Sleep: sleep\n");
3582 		pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_ON;
3583 		if (idletime)
3584 			pm->param.auto_deep_sleep.idletime = idletime;
3585 		ret = woal_request_ioctl(priv, req, wait_option);
3586 		if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING) {
3587 			ret = -EFAULT;
3588 			goto done;
3589 		}
3590 	} else {
3591 		PRINTM(MIOCTL, "%lu : Deep Sleep: wakeup\n", jiffies);
3592 		pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_OFF;
3593 		ret = woal_request_ioctl(priv, req, wait_option);
3594 		if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING) {
3595 			ret = -EFAULT;
3596 			goto done;
3597 		}
3598 	}
3599 done:
3600 	if (ret != MLAN_STATUS_PENDING)
3601 		kfree(req);
3602 	LEAVE();
3603 	return ret;
3604 }
3605 
3606 /**
3607  *  @brief Cancel CAC period block
3608  *
3609  *  @param priv     A pointer to moal_private structure
3610  *
3611  *  @return         N/A
3612  */
3613 void
woal_cancel_cac_block(moal_private * priv)3614 woal_cancel_cac_block(moal_private *priv)
3615 {
3616 	ENTER();
3617 	/* if during CAC period, wake up wait queue */
3618 	if (priv->phandle->cac_period == MTRUE) {
3619 		priv->phandle->cac_period = MFALSE;
3620 		/* Make sure Chan Report is cancelled */
3621 		woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT);
3622 		priv->phandle->meas_start_jiffies = 0;
3623 		if (priv->phandle->delay_bss_start == MTRUE)
3624 			priv->phandle->delay_bss_start = MFALSE;
3625 		if (priv->phandle->meas_wait_q_woken == MFALSE) {
3626 			priv->phandle->meas_wait_q_woken = MTRUE;
3627 			wake_up_interruptible(&priv->phandle->meas_wait_q);
3628 		}
3629 #ifdef UAP_SUPPORT
3630 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
3631 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
3632 		if (priv->uap_host_based && dfs_offload)
3633 			woal_cfg80211_dfs_vendor_event(priv,
3634 						       event_dfs_cac_aborted,
3635 						       &priv->chan);
3636 #endif
3637 #endif
3638 #endif
3639 	}
3640 	LEAVE();
3641 }
3642 
3643 /** MEAS report timeout value in seconds */
3644 
3645 /**
3646  *  @brief Issue MLAN_OID_11H_CHANNEL_CHECK ioctl
3647  *
3648  *  @param priv     Pointer to the moal_private driver data struct
3649  *  @param wait_option wait option
3650  *
3651  *  @return         0 --success, otherwise fail
3652  */
3653 int
woal_11h_channel_check_ioctl(moal_private * priv,t_u8 wait_option)3654 woal_11h_channel_check_ioctl(moal_private *priv, t_u8 wait_option)
3655 {
3656 	int ret = 0;
3657 	mlan_ioctl_req *req = NULL;
3658 	mlan_ds_11h_cfg *ds_11hcfg = NULL;
3659 	mlan_status status = MLAN_STATUS_SUCCESS;
3660 
3661 	ENTER();
3662 
3663 	if (priv->skip_cac) {
3664 		LEAVE();
3665 		return status;
3666 	}
3667 
3668 	/* Skip sending request/report query when DFS_REPEATER_MODE is on. This
3669 	 * would get rid of CAC timers before starting BSSes in DFS_REPEATER_MODE
3670 	 */
3671 	if (priv->phandle->dfs_repeater_mode) {
3672 		LEAVE();
3673 		return status;
3674 	}
3675 
3676 	if (woal_is_any_interface_active(priv->phandle)) {
3677 		/* When any other interface is active
3678 		 * Get rid of CAC timer when drcs is disabled */
3679 		t_u16 enable = 0;
3680 		ret = woal_mc_policy_cfg(priv, &enable, wait_option,
3681 					 MLAN_ACT_GET);
3682 		if (!enable) {
3683 			LEAVE();
3684 			return status;
3685 		}
3686 	}
3687 
3688 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
3689 	if (req == NULL) {
3690 		ret = -ENOMEM;
3691 		goto done;
3692 	}
3693 	ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
3694 
3695 	ds_11hcfg->sub_command = MLAN_OID_11H_CHANNEL_CHECK;
3696 	ds_11hcfg->param.chan_rpt_req.host_based = MFALSE;
3697 	req->req_id = MLAN_IOCTL_11H_CFG;
3698 	req->action = MLAN_ACT_SET;
3699 	/* Send Channel Check command and wait until the report is ready */
3700 	status = woal_request_ioctl(priv, req, wait_option);
3701 	if (status != MLAN_STATUS_SUCCESS) {
3702 		ret = -EFAULT;
3703 		goto done;
3704 	}
3705 
3706 	/* set flag from here */
3707 	priv->phandle->cac_period = MTRUE;
3708 	priv->phandle->meas_start_jiffies = jiffies;
3709 	priv->phandle->cac_timer_jiffies =
3710 		ds_11hcfg->param.chan_rpt_req.millisec_dwell_time * HZ / 1000;
3711 #ifdef UAP_SUPPORT
3712 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
3713 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
3714 	if (priv->uap_host_based && dfs_offload)
3715 		woal_cfg80211_dfs_vendor_event(priv, event_dfs_cac_started,
3716 					       &priv->chan);
3717 #endif
3718 #endif
3719 #endif
3720 done:
3721 	if (status != MLAN_STATUS_PENDING)
3722 		kfree(req);
3723 	LEAVE();
3724 	return ret;
3725 }
3726 
3727 /**
3728  *  @brief Issue MLAN_OID_11H_CHAN_REPORT_REQUEST ioctl to cancel dozer
3729  *
3730  *  @param priv     Pointer to the moal_private driver data struct
3731  *  @param wait_option wait option
3732  *
3733  *  @return         0 --success, otherwise fail
3734  */
3735 int
woal_11h_cancel_chan_report_ioctl(moal_private * priv,t_u8 wait_option)3736 woal_11h_cancel_chan_report_ioctl(moal_private *priv, t_u8 wait_option)
3737 {
3738 	int ret = 0;
3739 	mlan_ioctl_req *req = NULL;
3740 	mlan_ds_11h_cfg *ds_11hcfg = NULL;
3741 	mlan_status status = MLAN_STATUS_SUCCESS;
3742 
3743 	ENTER();
3744 
3745 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
3746 	if (req == NULL) {
3747 		ret = -ENOMEM;
3748 		goto done;
3749 	}
3750 	ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
3751 
3752 	ds_11hcfg->sub_command = MLAN_OID_11H_CHAN_REPORT_REQUEST;
3753 	req->req_id = MLAN_IOCTL_11H_CFG;
3754 	req->action = MLAN_ACT_SET;
3755 	ds_11hcfg->param.chan_rpt_req.millisec_dwell_time = 0;
3756 	/* Send Channel Check command and wait until the report is ready */
3757 	status = woal_request_ioctl(priv, req, wait_option);
3758 	if (status != MLAN_STATUS_SUCCESS) {
3759 		ret = -EFAULT;
3760 		goto done;
3761 	}
3762 
3763 done:
3764 	if (status != MLAN_STATUS_PENDING)
3765 		kfree(req);
3766 	LEAVE();
3767 	return ret;
3768 }
3769 
3770 /**
3771  *  @brief set remain channel
3772  *
3773  *  @param priv         A pointer to moal_private structure
3774  *  @param wait_option  Wait option
3775  *  @param pchan        A pointer to mlan_ds_remain_chan structure
3776  *
3777  *  @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
3778  */
3779 mlan_status
woal_set_remain_channel_ioctl(moal_private * priv,t_u8 wait_option,mlan_ds_remain_chan * pchan)3780 woal_set_remain_channel_ioctl(moal_private *priv, t_u8 wait_option,
3781 			      mlan_ds_remain_chan *pchan)
3782 {
3783 	mlan_status ret = MLAN_STATUS_SUCCESS;
3784 	mlan_ioctl_req *req = NULL;
3785 	mlan_ds_radio_cfg *radio_cfg = NULL;
3786 
3787 	ENTER();
3788 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
3789 	if (req == NULL) {
3790 		ret = MLAN_STATUS_FAILURE;
3791 		goto done;
3792 	}
3793 	radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
3794 	radio_cfg->sub_command = MLAN_OID_REMAIN_CHAN_CFG;
3795 	req->req_id = MLAN_IOCTL_RADIO_CFG;
3796 
3797 	req->action = MLAN_ACT_SET;
3798 	memcpy(&radio_cfg->param.remain_chan, pchan,
3799 	       sizeof(mlan_ds_remain_chan));
3800 	ret = woal_request_ioctl(priv, req, wait_option);
3801 	if (ret == MLAN_STATUS_SUCCESS) {
3802 		memcpy(pchan, &radio_cfg->param.remain_chan,
3803 		       sizeof(mlan_ds_remain_chan));
3804 	}
3805 done:
3806 	if (ret != MLAN_STATUS_PENDING)
3807 		kfree(req);
3808 	LEAVE();
3809 	return ret;
3810 }
3811 
3812 #if defined(WIFI_DIRECT_SUPPORT)
3813 /**
3814  *  @brief set/get wifi direct mode
3815  *
3816  *  @param priv         A pointer to moal_private structure
3817  *  @param action       set or get
3818  *  @param mode         A pointer to wifi direct mode
3819  *
3820  *  @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
3821  */
3822 mlan_status
woal_wifi_direct_mode_cfg(moal_private * priv,t_u16 action,t_u16 * mode)3823 woal_wifi_direct_mode_cfg(moal_private *priv, t_u16 action, t_u16 *mode)
3824 {
3825 	mlan_status ret = MLAN_STATUS_SUCCESS;
3826 	mlan_ioctl_req *req = NULL;
3827 	mlan_ds_bss *bss = NULL;
3828 
3829 	ENTER();
3830 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
3831 	if (req == NULL) {
3832 		ret = MLAN_STATUS_FAILURE;
3833 		goto done;
3834 	}
3835 	bss = (mlan_ds_bss *)req->pbuf;
3836 	bss->sub_command = MLAN_OID_WIFI_DIRECT_MODE;
3837 	req->req_id = MLAN_IOCTL_BSS;
3838 
3839 	req->action = action;
3840 	if (action == MLAN_ACT_SET)
3841 		bss->param.wfd_mode = *mode;
3842 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3843 	if (ret == MLAN_STATUS_SUCCESS) {
3844 		*mode = bss->param.wfd_mode;
3845 		PRINTM(MIOCTL, "ACT=%d, wifi_direct_mode=%d\n", action, *mode);
3846 	}
3847 done:
3848 	if (ret != MLAN_STATUS_PENDING)
3849 		kfree(req);
3850 	LEAVE();
3851 	return ret;
3852 }
3853 
3854 /**
3855  *  @brief Set p2p config
3856  *
3857  *  @param priv         A pointer to moal_private structure
3858  *  @param action       Action set or get
3859  *  @param p2p_config   A pointer to  mlan_ds_wifi_direct_config structure
3860  *
3861  *  @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
3862  */
3863 mlan_status
woal_p2p_config(moal_private * priv,t_u32 action,mlan_ds_wifi_direct_config * p2p_config)3864 woal_p2p_config(moal_private *priv, t_u32 action,
3865 		mlan_ds_wifi_direct_config *p2p_config)
3866 {
3867 	mlan_status ret = MLAN_STATUS_SUCCESS;
3868 	mlan_ioctl_req *req = NULL;
3869 	mlan_ds_misc_cfg *misc_cfg = NULL;
3870 
3871 	ENTER();
3872 	if (!p2p_config) {
3873 		LEAVE();
3874 		return MLAN_STATUS_FAILURE;
3875 	}
3876 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3877 	if (req == NULL) {
3878 		ret = MLAN_STATUS_FAILURE;
3879 		goto done;
3880 	}
3881 	misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
3882 	misc_cfg->sub_command = MLAN_OID_MISC_WIFI_DIRECT_CONFIG;
3883 	req->req_id = MLAN_IOCTL_MISC_CFG;
3884 	req->action = action;
3885 	memcpy(&misc_cfg->param.p2p_config, p2p_config,
3886 	       sizeof(mlan_ds_wifi_direct_config));
3887 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3888 	if (ret == MLAN_STATUS_SUCCESS) {
3889 		if (action == MLAN_ACT_GET)
3890 			memcpy(p2p_config, &misc_cfg->param.p2p_config,
3891 			       sizeof(mlan_ds_wifi_direct_config));
3892 	}
3893 done:
3894 	if (ret != MLAN_STATUS_PENDING)
3895 		kfree(req);
3896 	LEAVE();
3897 	return ret;
3898 }
3899 #endif /* WIFI_DIRECT_SUPPORT */
3900 
3901 #ifdef STA_SUPPORT
3902 /**
3903  *  @brief Get STA Channel Info
3904  *
3905  *  @param priv             A pointer to moal_private structure
3906  *  @param wait_option      Wait option
3907  *  @param channel          A pointer to channel info
3908  *
3909  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
3910  */
3911 mlan_status
woal_get_sta_channel(moal_private * priv,t_u8 wait_option,chan_band_info * channel)3912 woal_get_sta_channel(moal_private *priv, t_u8 wait_option,
3913 		     chan_band_info * channel)
3914 {
3915 	int ret = 0;
3916 	mlan_ioctl_req *req = NULL;
3917 	mlan_ds_bss *bss = 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_bss));
3923 	if (req == NULL) {
3924 		PRINTM(MERROR, "woal_get_sta_channel req alloc fail\n");
3925 		ret = MLAN_STATUS_FAILURE;
3926 		goto done;
3927 	}
3928 
3929 	/* Fill request buffer */
3930 	bss = (mlan_ds_bss *)req->pbuf;
3931 	bss->sub_command = MLAN_OID_BSS_CHAN_INFO;
3932 	req->req_id = MLAN_IOCTL_BSS;
3933 	req->action = MLAN_ACT_GET;
3934 
3935 	/* Send IOCTL request to MLAN */
3936 	status = woal_request_ioctl(priv, req, wait_option);
3937 	if (status == MLAN_STATUS_SUCCESS && channel)
3938 		memcpy(channel, &(bss->param.sta_channel), sizeof(*channel));
3939 
3940 done:
3941 	if (status != MLAN_STATUS_PENDING)
3942 		kfree(req);
3943 	LEAVE();
3944 	return status;
3945 }
3946 
3947 /**
3948  *  @brief Get RSSI info
3949  *
3950  *  @param priv         A pointer to moal_private structure
3951  *  @param wait_option  Wait option
3952  *  @param signal       A pointer tp mlan_ds_get_signal structure
3953  *
3954  *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
3955  */
3956 mlan_status
woal_get_signal_info(moal_private * priv,t_u8 wait_option,mlan_ds_get_signal * signal)3957 woal_get_signal_info(moal_private *priv, t_u8 wait_option,
3958 		     mlan_ds_get_signal *signal)
3959 {
3960 	int ret = 0;
3961 	mlan_ds_get_info *info = NULL;
3962 	mlan_ioctl_req *req = NULL;
3963 	mlan_status status = MLAN_STATUS_SUCCESS;
3964 	ENTER();
3965 
3966 	/* Allocate an IOCTL request buffer */
3967 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info));
3968 	if (req == NULL) {
3969 		ret = -ENOMEM;
3970 		goto done;
3971 	}
3972 
3973 	/* Fill request buffer */
3974 	info = (mlan_ds_get_info *)req->pbuf;
3975 	info->sub_command = MLAN_OID_GET_SIGNAL;
3976 	info->param.signal.selector = ALL_RSSI_INFO_MASK;
3977 	req->req_id = MLAN_IOCTL_GET_INFO;
3978 	req->action = MLAN_ACT_GET;
3979 
3980 	/* Send IOCTL request to MLAN */
3981 	status = woal_request_ioctl(priv, req, wait_option);
3982 	if (status == MLAN_STATUS_SUCCESS) {
3983 		if (signal)
3984 			memcpy(signal, &info->param.signal,
3985 			       sizeof(mlan_ds_get_signal));
3986 #ifdef STA_WEXT
3987 		if (IS_STA_WEXT(cfg80211_wext)) {
3988 			if (info->param.signal.selector & BCN_RSSI_AVG_MASK)
3989 				priv->w_stats.qual.level =
3990 					info->param.signal.bcn_rssi_avg;
3991 			if (info->param.signal.selector & BCN_NF_AVG_MASK)
3992 				priv->w_stats.qual.noise =
3993 					info->param.signal.bcn_nf_avg;
3994 		}
3995 #endif
3996 	}
3997 done:
3998 	if (status != MLAN_STATUS_PENDING)
3999 		kfree(req);
4000 	LEAVE();
4001 	return status;
4002 }
4003 
4004 /**
4005  *  @brief Get scan table
4006  *
4007  *  @param priv         A pointer to moal_private structure
4008  *  @param wait_option  Wait option
4009  *  @param scan_resp    A pointer to mlan_scan_resp structure
4010  *
4011  *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4012  */
4013 mlan_status
woal_get_scan_table(moal_private * priv,t_u8 wait_option,mlan_scan_resp * scan_resp)4014 woal_get_scan_table(moal_private *priv, t_u8 wait_option,
4015 		    mlan_scan_resp *scan_resp)
4016 {
4017 	int ret = 0;
4018 	mlan_ioctl_req *req = NULL;
4019 	mlan_ds_scan *scan = NULL;
4020 	mlan_status status = MLAN_STATUS_SUCCESS;
4021 	ENTER();
4022 
4023 	if (!scan_resp) {
4024 		LEAVE();
4025 		return MLAN_STATUS_FAILURE;
4026 	}
4027 
4028 	/* Allocate an IOCTL request buffer */
4029 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
4030 	if (req == NULL) {
4031 		ret = -ENOMEM;
4032 		goto done;
4033 	}
4034 
4035 	/* Fill request buffer */
4036 	scan = (mlan_ds_scan *)req->pbuf;
4037 	scan->sub_command = MLAN_OID_SCAN_NORMAL;
4038 	req->req_id = MLAN_IOCTL_SCAN;
4039 	req->action = MLAN_ACT_GET;
4040 	memcpy((void *)&scan->param.scan_resp, (void *)scan_resp,
4041 	       sizeof(mlan_scan_resp));
4042 
4043 	/* Send IOCTL request to MLAN */
4044 	status = woal_request_ioctl(priv, req, wait_option);
4045 	if (status == MLAN_STATUS_SUCCESS) {
4046 		if (scan_resp) {
4047 			memcpy(scan_resp, &scan->param.scan_resp,
4048 			       sizeof(mlan_scan_resp));
4049 		}
4050 	}
4051 
4052 done:
4053 	if (status != MLAN_STATUS_PENDING)
4054 		kfree(req);
4055 	LEAVE();
4056 	return status;
4057 }
4058 
4059 /**
4060  *  @brief Request a scan
4061  *
4062  *  @param priv                 A pointer to moal_private structure
4063  *  @param wait_option          Wait option
4064  *  @param req_ssid             A pointer to mlan_802_11_ssid structure
4065  *
4066  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
4067  */
4068 mlan_status
woal_request_scan(moal_private * priv,t_u8 wait_option,mlan_802_11_ssid * req_ssid)4069 woal_request_scan(moal_private *priv,
4070 		  t_u8 wait_option, mlan_802_11_ssid *req_ssid)
4071 {
4072 	mlan_status ret = MLAN_STATUS_SUCCESS;
4073 	moal_handle *handle = priv->phandle;
4074 	mlan_ioctl_req *ioctl_req = NULL;
4075 	mlan_ds_scan *scan = NULL;
4076 	mlan_status status = MLAN_STATUS_SUCCESS;
4077 	ENTER();
4078 
4079 	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->async_sem)) {
4080 		PRINTM(MERROR, "Acquire semaphore error, request_scan\n");
4081 		LEAVE();
4082 		return MLAN_STATUS_FAILURE;
4083 	}
4084 	handle->scan_pending_on_block = MTRUE;
4085 	handle->scan_priv = priv;
4086 
4087 	/* Allocate an IOCTL request buffer */
4088 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
4089 	if (ioctl_req == NULL) {
4090 		ret = MLAN_STATUS_FAILURE;
4091 		goto done;
4092 	}
4093 
4094 	scan = (mlan_ds_scan *)ioctl_req->pbuf;
4095 
4096 	if (req_ssid && req_ssid->ssid_len != 0) {
4097 		/* Specific SSID scan */
4098 		ioctl_req->req_id = MLAN_IOCTL_SCAN;
4099 		ioctl_req->action = MLAN_ACT_SET;
4100 
4101 		scan->sub_command = MLAN_OID_SCAN_SPECIFIC_SSID;
4102 
4103 		memcpy(scan->param.scan_req.scan_ssid.ssid,
4104 		       req_ssid->ssid,
4105 		       MIN(MLAN_MAX_SSID_LENGTH, req_ssid->ssid_len));
4106 		scan->param.scan_req.scan_ssid.ssid_len =
4107 			MIN(MLAN_MAX_SSID_LENGTH, req_ssid->ssid_len);
4108 	} else {
4109 		/* Normal scan */
4110 		ioctl_req->req_id = MLAN_IOCTL_SCAN;
4111 		ioctl_req->action = MLAN_ACT_SET;
4112 
4113 		scan->sub_command = MLAN_OID_SCAN_NORMAL;
4114 	}
4115 	/* Send IOCTL request to MLAN */
4116 	status = woal_request_ioctl(priv, ioctl_req, wait_option);
4117 
4118 	if (status == MLAN_STATUS_FAILURE) {
4119 		ret = MLAN_STATUS_FAILURE;
4120 		goto done;
4121 	}
4122 done:
4123 	if (status != MLAN_STATUS_PENDING)
4124 		kfree(ioctl_req);
4125 
4126 	if (ret == MLAN_STATUS_FAILURE) {
4127 		handle->scan_pending_on_block = MFALSE;
4128 		handle->scan_priv = NULL;
4129 		MOAL_REL_SEMAPHORE(&handle->async_sem);
4130 	}
4131 	LEAVE();
4132 	return ret;
4133 }
4134 
4135 /**
4136  *  @brief Change Adhoc Channel
4137  *
4138  *  @param priv         A pointer to moal_private structure
4139  *  @param channel      The channel to be set.
4140  *  @param wait_option  wait_option
4141  *
4142  *  @return             MLAN_STATUS_SUCCESS--success, MLAN_STATUS_FAILURE--fail
4143  */
4144 mlan_status
woal_change_adhoc_chan(moal_private * priv,int channel,t_u8 wait_option)4145 woal_change_adhoc_chan(moal_private *priv, int channel, t_u8 wait_option)
4146 {
4147 	mlan_status ret = MLAN_STATUS_SUCCESS;
4148 	mlan_bss_info bss_info;
4149 	mlan_ds_bss *bss = NULL;
4150 	mlan_ioctl_req *req = NULL;
4151 
4152 	ENTER();
4153 
4154 	memset(&bss_info, 0, sizeof(bss_info));
4155 
4156 	/* Get BSS information */
4157 	if (MLAN_STATUS_SUCCESS !=
4158 	    woal_get_bss_info(priv, wait_option, &bss_info)) {
4159 		ret = MLAN_STATUS_FAILURE;
4160 		goto done;
4161 	}
4162 	if (bss_info.bss_mode == MLAN_BSS_MODE_INFRA) {
4163 		ret = MLAN_STATUS_SUCCESS;
4164 		goto done;
4165 	}
4166 
4167 	/* Allocate an IOCTL request buffer */
4168 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4169 	if (req == NULL) {
4170 		ret = MLAN_STATUS_FAILURE;
4171 		goto done;
4172 	}
4173 
4174 	/* Get current channel */
4175 	bss = (mlan_ds_bss *)req->pbuf;
4176 	bss->sub_command = MLAN_OID_IBSS_CHANNEL;
4177 	req->req_id = MLAN_IOCTL_BSS;
4178 	req->action = MLAN_ACT_GET;
4179 
4180 	/* Send IOCTL request to MLAN */
4181 	ret = woal_request_ioctl(priv, req, wait_option);
4182 	if (ret != MLAN_STATUS_SUCCESS)
4183 		goto done;
4184 
4185 	if (bss->param.bss_chan.channel == (unsigned int)channel) {
4186 		ret = MLAN_STATUS_SUCCESS;
4187 		goto done;
4188 	}
4189 	PRINTM(MINFO, "Updating Channel from %d to %d\n",
4190 	       (int)bss->param.bss_chan.channel, channel);
4191 
4192 	if (bss_info.media_connected != MTRUE) {
4193 		ret = MLAN_STATUS_SUCCESS;
4194 		goto done;
4195 	}
4196 
4197 	/* Do disonnect */
4198 	bss->sub_command = MLAN_OID_BSS_STOP;
4199 	memset((t_u8 *)&bss->param.bssid, 0, ETH_ALEN);
4200 
4201 	/* Send IOCTL request to MLAN */
4202 	ret = woal_request_ioctl(priv, req, wait_option);
4203 	if (ret != MLAN_STATUS_SUCCESS)
4204 		goto done;
4205 
4206 	/* Do specific SSID scanning */
4207 	if (MLAN_STATUS_SUCCESS !=
4208 	    woal_request_scan(priv, wait_option, &bss_info.ssid)) {
4209 		ret = MLAN_STATUS_FAILURE;
4210 		goto done;
4211 	}
4212 	/* Start/Join Adhoc network */
4213 	bss->sub_command = MLAN_OID_BSS_START;
4214 	memset(&bss->param.ssid_bssid, 0, sizeof(mlan_ssid_bssid));
4215 	memcpy(&bss->param.ssid_bssid.ssid, &bss_info.ssid,
4216 	       sizeof(mlan_802_11_ssid));
4217 
4218 	/* Send IOCTL request to MLAN */
4219 	ret = woal_request_ioctl(priv, req, wait_option);
4220 
4221 done:
4222 	if (ret != MLAN_STATUS_PENDING)
4223 		kfree(req);
4224 	LEAVE();
4225 	return ret;
4226 }
4227 
4228 /**
4229  *  @brief Find the best network to associate
4230  *
4231  *  @param priv             A pointer to moal_private structure
4232  *  @param wait_option      Wait option
4233  *  @param ssid_bssid       A pointer to mlan_ssid_bssid structure
4234  *
4235  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4236  */
4237 mlan_status
woal_find_best_network(moal_private * priv,t_u8 wait_option,mlan_ssid_bssid * ssid_bssid)4238 woal_find_best_network(moal_private *priv, t_u8 wait_option,
4239 		       mlan_ssid_bssid *ssid_bssid)
4240 {
4241 	mlan_ioctl_req *req = NULL;
4242 	mlan_ds_bss *bss = NULL;
4243 	mlan_status ret = MLAN_STATUS_SUCCESS;
4244 	t_u8 *mac = 0;
4245 
4246 	ENTER();
4247 
4248 	if (!ssid_bssid) {
4249 		ret = MLAN_STATUS_FAILURE;
4250 		goto done;
4251 	}
4252 
4253 	/* Allocate an IOCTL request buffer */
4254 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4255 	if (req == NULL) {
4256 		ret = MLAN_STATUS_FAILURE;
4257 		goto done;
4258 	}
4259 
4260 	/* Fill request buffer */
4261 	bss = (mlan_ds_bss *)req->pbuf;
4262 	req->req_id = MLAN_IOCTL_BSS;
4263 	req->action = MLAN_ACT_GET;
4264 	bss->sub_command = MLAN_OID_BSS_FIND_BSS;
4265 
4266 	memcpy(&bss->param.ssid_bssid, ssid_bssid, sizeof(mlan_ssid_bssid));
4267 
4268 	/* Send IOCTL request to MLAN */
4269 	ret = woal_request_ioctl(priv, req, wait_option);
4270 	if (ret == MLAN_STATUS_SUCCESS) {
4271 		memcpy(ssid_bssid, &bss->param.ssid_bssid,
4272 		       sizeof(mlan_ssid_bssid));
4273 		mac = (t_u8 *)&ssid_bssid->bssid;
4274 		PRINTM(MINFO, "Find network: ssid=%s, " MACSTR ", idx=%d\n",
4275 		       ssid_bssid->ssid.ssid, MAC2STR(mac),
4276 		       (int)ssid_bssid->idx);
4277 	}
4278 
4279 done:
4280 	if (ret != MLAN_STATUS_PENDING)
4281 		kfree(req);
4282 	LEAVE();
4283 	return ret;
4284 }
4285 
4286 /**
4287  *  @brief Check if AP channel is valid for STA Region
4288  *
4289  *  @param priv             A pointer to moal_private structure
4290  *  @param wait_option      Wait option
4291  *  @param ssid_bssid       A pointer to mlan_ssid_bssid structure
4292  *
4293  *  @return                 MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4294  */
4295 mlan_status
woal_11d_check_ap_channel(moal_private * priv,t_u8 wait_option,mlan_ssid_bssid * ssid_bssid)4296 woal_11d_check_ap_channel(moal_private *priv, t_u8 wait_option,
4297 			  mlan_ssid_bssid *ssid_bssid)
4298 {
4299 	mlan_ioctl_req *req = NULL;
4300 	mlan_ds_bss *bss = NULL;
4301 	mlan_status ret = MLAN_STATUS_SUCCESS;
4302 	t_u8 *mac = 0;
4303 
4304 	ENTER();
4305 
4306 	if (!ssid_bssid) {
4307 		ret = MLAN_STATUS_FAILURE;
4308 		goto done;
4309 	}
4310 
4311 	/* Allocate an IOCTL request buffer */
4312 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
4313 	if (req == NULL) {
4314 		ret = MLAN_STATUS_FAILURE;
4315 		goto done;
4316 	}
4317 
4318 	/* Fill request buffer */
4319 	bss = (mlan_ds_bss *)req->pbuf;
4320 	req->req_id = MLAN_IOCTL_BSS;
4321 	req->action = MLAN_ACT_GET;
4322 	bss->sub_command = MLAN_OID_BSS_11D_CHECK_CHANNEL;
4323 
4324 	memcpy(&bss->param.ssid_bssid, ssid_bssid, sizeof(mlan_ssid_bssid));
4325 
4326 	mac = (t_u8 *)&ssid_bssid->bssid;
4327 	PRINTM(MINFO, "ssid=%s, " MACSTR ", idx=%d\n",
4328 	       ssid_bssid->ssid.ssid, MAC2STR(mac), (int)ssid_bssid->idx);
4329 
4330 	/* Send IOCTL request to MLAN */
4331 	ret = woal_request_ioctl(priv, req, wait_option);
4332 
4333 done:
4334 	if (ret != MLAN_STATUS_PENDING)
4335 		kfree(req);
4336 	LEAVE();
4337 	return ret;
4338 }
4339 
4340 /**
4341  *  @brief Get authentication mode
4342  *
4343  *  @param priv             A pointer to moal_private structure
4344  *  @param wait_option      Wait option
4345  *  @param auth_mode        A pointer to authentication mode
4346  *
4347  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4348  */
4349 mlan_status
woal_get_auth_mode(moal_private * priv,t_u8 wait_option,t_u32 * auth_mode)4350 woal_get_auth_mode(moal_private *priv, t_u8 wait_option, t_u32 *auth_mode)
4351 {
4352 	int ret = 0;
4353 	mlan_ioctl_req *req = NULL;
4354 	mlan_ds_sec_cfg *sec = NULL;
4355 	mlan_status status = MLAN_STATUS_SUCCESS;
4356 	ENTER();
4357 
4358 	/* Allocate an IOCTL request buffer */
4359 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
4360 	if (req == NULL) {
4361 		ret = -ENOMEM;
4362 		goto done;
4363 	}
4364 
4365 	/* Fill request buffer */
4366 	sec = (mlan_ds_sec_cfg *)req->pbuf;
4367 	sec->sub_command = MLAN_OID_SEC_CFG_AUTH_MODE;
4368 	req->req_id = MLAN_IOCTL_SEC_CFG;
4369 	req->action = MLAN_ACT_GET;
4370 
4371 	/* Send IOCTL request to MLAN */
4372 	status = woal_request_ioctl(priv, req, wait_option);
4373 	if (status == MLAN_STATUS_SUCCESS && auth_mode)
4374 		*auth_mode = sec->param.auth_mode;
4375 done:
4376 	if (status != MLAN_STATUS_PENDING)
4377 		kfree(req);
4378 	LEAVE();
4379 	return status;
4380 }
4381 
4382 /**
4383  *  @brief Get encrypt mode
4384  *
4385  *  @param priv                 A pointer to moal_private structure
4386  *  @param wait_option          Wait option
4387  *  @param encrypt_mode         A pointer to encrypt mode
4388  *
4389  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4390  */
4391 mlan_status
woal_get_encrypt_mode(moal_private * priv,t_u8 wait_option,t_u32 * encrypt_mode)4392 woal_get_encrypt_mode(moal_private *priv, t_u8 wait_option, t_u32 *encrypt_mode)
4393 {
4394 	int ret = 0;
4395 	mlan_ioctl_req *req = NULL;
4396 	mlan_ds_sec_cfg *sec = NULL;
4397 	mlan_status status = MLAN_STATUS_SUCCESS;
4398 
4399 	ENTER();
4400 
4401 	/* Allocate an IOCTL request buffer */
4402 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
4403 	if (req == NULL) {
4404 		ret = -ENOMEM;
4405 		goto done;
4406 	}
4407 
4408 	/* Fill request buffer */
4409 	sec = (mlan_ds_sec_cfg *)req->pbuf;
4410 	sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_MODE;
4411 	req->req_id = MLAN_IOCTL_SEC_CFG;
4412 	req->action = MLAN_ACT_GET;
4413 
4414 	/* Send IOCTL request to MLAN */
4415 	status = woal_request_ioctl(priv, req, wait_option);
4416 	if (status == MLAN_STATUS_SUCCESS && encrypt_mode)
4417 		*encrypt_mode = sec->param.encrypt_mode;
4418 done:
4419 	if (status != MLAN_STATUS_PENDING)
4420 		kfree(req);
4421 	LEAVE();
4422 	return status;
4423 }
4424 
4425 /**
4426  *  @brief Get WPA enable
4427  *
4428  *  @param priv             A pointer to moal_private structure
4429  *  @param wait_option      Wait option
4430  *  @param enable           A pointer to wpa enable status
4431  *
4432  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4433  */
4434 mlan_status
woal_get_wpa_enable(moal_private * priv,t_u8 wait_option,t_u32 * enable)4435 woal_get_wpa_enable(moal_private *priv, t_u8 wait_option, t_u32 *enable)
4436 {
4437 	int ret = 0;
4438 	mlan_ioctl_req *req = NULL;
4439 	mlan_ds_sec_cfg *sec = NULL;
4440 	mlan_status status = MLAN_STATUS_SUCCESS;
4441 
4442 	ENTER();
4443 
4444 	/* Allocate an IOCTL request buffer */
4445 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
4446 	if (req == NULL) {
4447 		ret = -ENOMEM;
4448 		goto done;
4449 	}
4450 
4451 	/* Fill request buffer */
4452 	sec = (mlan_ds_sec_cfg *)req->pbuf;
4453 	sec->sub_command = MLAN_OID_SEC_CFG_WPA_ENABLED;
4454 	req->req_id = MLAN_IOCTL_SEC_CFG;
4455 	req->action = MLAN_ACT_GET;
4456 
4457 	/* Send IOCTL request to MLAN */
4458 	status = woal_request_ioctl(priv, req, wait_option);
4459 	if (status == MLAN_STATUS_SUCCESS && enable)
4460 		*enable = sec->param.wpa_enabled;
4461 done:
4462 	if (status != MLAN_STATUS_PENDING)
4463 		kfree(req);
4464 	LEAVE();
4465 	return status;
4466 }
4467 
4468 /**
4469  *  @brief Set authentication mode
4470  *
4471  *  @param priv             A pointer to moal_private structure
4472  *  @param wait_option      Wait option
4473  *  @param auth_mode        Authentication mode
4474  *
4475  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4476  */
4477 mlan_status
woal_set_auth_mode(moal_private * priv,t_u8 wait_option,t_u32 auth_mode)4478 woal_set_auth_mode(moal_private *priv, t_u8 wait_option, t_u32 auth_mode)
4479 {
4480 	int ret = 0;
4481 	mlan_ioctl_req *req = NULL;
4482 	mlan_ds_sec_cfg *sec = NULL;
4483 	mlan_status status = MLAN_STATUS_SUCCESS;
4484 	ENTER();
4485 
4486 	/* Allocate an IOCTL request buffer */
4487 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
4488 	if (req == NULL) {
4489 		ret = -ENOMEM;
4490 		goto done;
4491 	}
4492 
4493 	/* Fill request buffer */
4494 	sec = (mlan_ds_sec_cfg *)req->pbuf;
4495 	sec->sub_command = MLAN_OID_SEC_CFG_AUTH_MODE;
4496 	req->req_id = MLAN_IOCTL_SEC_CFG;
4497 	req->action = MLAN_ACT_SET;
4498 	sec->param.auth_mode = auth_mode;
4499 
4500 	/* Send IOCTL request to MLAN */
4501 	status = woal_request_ioctl(priv, req, wait_option);
4502 done:
4503 	if (status != MLAN_STATUS_PENDING)
4504 		kfree(req);
4505 	LEAVE();
4506 	return status;
4507 }
4508 
4509 /**
4510  *  @brief Set encrypt mode
4511  *
4512  *  @param priv                 A pointer to moal_private structure
4513  *  @param wait_option          Wait option
4514  *  @param encrypt_mode         Encryption mode
4515  *
4516  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4517  */
4518 mlan_status
woal_set_encrypt_mode(moal_private * priv,t_u8 wait_option,t_u32 encrypt_mode)4519 woal_set_encrypt_mode(moal_private *priv, t_u8 wait_option, t_u32 encrypt_mode)
4520 {
4521 	int ret = 0;
4522 	mlan_ioctl_req *req = NULL;
4523 	mlan_ds_sec_cfg *sec = NULL;
4524 	mlan_status status = MLAN_STATUS_SUCCESS;
4525 	ENTER();
4526 
4527 	/* Allocate an IOCTL request buffer */
4528 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
4529 	if (req == NULL) {
4530 		ret = -ENOMEM;
4531 		goto done;
4532 	}
4533 
4534 	/* Fill request buffer */
4535 	sec = (mlan_ds_sec_cfg *)req->pbuf;
4536 	sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_MODE;
4537 	req->req_id = MLAN_IOCTL_SEC_CFG;
4538 	req->action = MLAN_ACT_SET;
4539 	sec->param.encrypt_mode = encrypt_mode;
4540 
4541 	/* Send IOCTL request to MLAN */
4542 	status = woal_request_ioctl(priv, req, wait_option);
4543 done:
4544 	if (status != MLAN_STATUS_PENDING)
4545 		kfree(req);
4546 	LEAVE();
4547 	return status;
4548 }
4549 
4550 /**
4551  *  @brief Set wpa enable
4552  *
4553  *  @param priv                 A pointer to moal_private structure
4554  *  @param wait_option          Wait option
4555  *  @param enable               MTRUE or MFALSE
4556  *
4557  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4558  */
4559 mlan_status
woal_set_wpa_enable(moal_private * priv,t_u8 wait_option,t_u32 enable)4560 woal_set_wpa_enable(moal_private *priv, t_u8 wait_option, t_u32 enable)
4561 {
4562 	int ret = 0;
4563 	mlan_ioctl_req *req = NULL;
4564 	mlan_ds_sec_cfg *sec = NULL;
4565 	mlan_status status = MLAN_STATUS_SUCCESS;
4566 	ENTER();
4567 
4568 	/* Allocate an IOCTL request buffer */
4569 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
4570 	if (req == NULL) {
4571 		ret = -ENOMEM;
4572 		goto done;
4573 	}
4574 
4575 	/* Fill request buffer */
4576 	sec = (mlan_ds_sec_cfg *)req->pbuf;
4577 	sec->sub_command = MLAN_OID_SEC_CFG_WPA_ENABLED;
4578 	req->req_id = MLAN_IOCTL_SEC_CFG;
4579 	req->action = MLAN_ACT_SET;
4580 	sec->param.wpa_enabled = enable;
4581 
4582 	/* Send IOCTL request to MLAN */
4583 	status = woal_request_ioctl(priv, req, wait_option);
4584 done:
4585 	if (status != MLAN_STATUS_PENDING)
4586 		kfree(req);
4587 	LEAVE();
4588 	return status;
4589 }
4590 
4591 /**
4592  *  @brief enable wep key
4593  *
4594  *  @param priv                 A pointer to moal_private structure
4595  *  @param wait_option          Wait option
4596  *
4597  *  @return                     MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
4598  */
4599 mlan_status
woal_enable_wep_key(moal_private * priv,t_u8 wait_option)4600 woal_enable_wep_key(moal_private *priv, t_u8 wait_option)
4601 {
4602 	int ret = 0;
4603 	mlan_ioctl_req *req = NULL;
4604 	mlan_ds_sec_cfg *sec = NULL;
4605 	mlan_status status = MLAN_STATUS_SUCCESS;
4606 	ENTER();
4607 
4608 	/* Allocate an IOCTL request buffer */
4609 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
4610 	if (req == NULL) {
4611 		ret = -ENOMEM;
4612 		goto done;
4613 	}
4614 
4615 	/* Fill request buffer */
4616 	sec = (mlan_ds_sec_cfg *)req->pbuf;
4617 	sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
4618 	req->req_id = MLAN_IOCTL_SEC_CFG;
4619 	req->action = MLAN_ACT_SET;
4620 	sec->param.encrypt_key.key_disable = MFALSE;
4621 	sec->param.encrypt_key.key_index = MLAN_KEY_INDEX_DEFAULT;
4622 	sec->param.encrypt_key.is_current_wep_key = MTRUE;
4623 
4624 	/* Send IOCTL request to MLAN */
4625 	status = woal_request_ioctl(priv, req, wait_option);
4626 done:
4627 	if (status != MLAN_STATUS_PENDING)
4628 		kfree(req);
4629 	LEAVE();
4630 	return status;
4631 }
4632 
4633 /**
4634  *  @brief Request user scan
4635  *
4636  *  @param priv                 A pointer to moal_private structure
4637  *  @param wait_option          Wait option
4638  *  @param scan_cfg             A pointer to wlan_user_scan_config structure
4639  *
4640  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
4641  */
4642 mlan_status
woal_request_userscan(moal_private * priv,t_u8 wait_option,wlan_user_scan_cfg * scan_cfg)4643 woal_request_userscan(moal_private *priv,
4644 		      t_u8 wait_option, wlan_user_scan_cfg *scan_cfg)
4645 {
4646 	mlan_status ret = MLAN_STATUS_SUCCESS;
4647 	mlan_ioctl_req *ioctl_req = NULL;
4648 	mlan_ds_scan *scan = NULL;
4649 	mlan_status status = MLAN_STATUS_SUCCESS;
4650 	moal_handle *handle = priv->phandle;
4651 	ENTER();
4652 
4653 	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->async_sem)) {
4654 		PRINTM(MERROR, "Acquire semaphore error, request_scan\n");
4655 		LEAVE();
4656 		return MLAN_STATUS_FAILURE;
4657 	}
4658 	handle->scan_pending_on_block = MTRUE;
4659 	handle->scan_priv = priv;
4660 
4661 	/* Allocate an IOCTL request buffer */
4662 	ioctl_req =
4663 		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan) +
4664 					  sizeof(wlan_user_scan_cfg));
4665 	if (ioctl_req == NULL) {
4666 		ret = MLAN_STATUS_FAILURE;
4667 		goto done;
4668 	}
4669 
4670 	scan = (mlan_ds_scan *)ioctl_req->pbuf;
4671 	scan->sub_command = MLAN_OID_SCAN_USER_CONFIG;
4672 	ioctl_req->req_id = MLAN_IOCTL_SCAN;
4673 	ioctl_req->action = MLAN_ACT_SET;
4674 	memcpy(scan->param.user_scan.scan_cfg_buf, scan_cfg,
4675 	       sizeof(wlan_user_scan_cfg));
4676 	/* Send IOCTL request to MLAN */
4677 	status = woal_request_ioctl(priv, ioctl_req, wait_option);
4678 	if (status == MLAN_STATUS_FAILURE) {
4679 		ret = MLAN_STATUS_FAILURE;
4680 		goto done;
4681 	}
4682 
4683 done:
4684 	if (status != MLAN_STATUS_PENDING)
4685 		kfree(ioctl_req);
4686 
4687 	if (ret == MLAN_STATUS_FAILURE) {
4688 		handle->scan_pending_on_block = MFALSE;
4689 		handle->scan_priv = NULL;
4690 		MOAL_REL_SEMAPHORE(&handle->async_sem);
4691 	}
4692 	LEAVE();
4693 	return ret;
4694 }
4695 
4696 /**
4697  *  @brief woal_get_scan_config
4698  *
4699  *  @param priv                 A pointer to moal_private structure
4700  *  @param scan_cfg             A pointer to scan_cfg structure
4701  *
4702  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
4703  */
4704 mlan_status
woal_get_scan_config(moal_private * priv,mlan_scan_cfg * scan_cfg)4705 woal_get_scan_config(moal_private *priv, mlan_scan_cfg *scan_cfg)
4706 {
4707 	mlan_status ret = MLAN_STATUS_SUCCESS;
4708 	mlan_ds_scan *scan = NULL;
4709 	mlan_ioctl_req *req = NULL;
4710 
4711 	ENTER();
4712 
4713 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
4714 	if (req == NULL) {
4715 		ret = MLAN_STATUS_FAILURE;
4716 		goto done;
4717 	}
4718 	scan = (mlan_ds_scan *)req->pbuf;
4719 	scan->sub_command = MLAN_OID_SCAN_CONFIG;
4720 	req->req_id = MLAN_IOCTL_SCAN;
4721 	req->action = MLAN_ACT_GET;
4722 	memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
4723 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4724 	if (ret == MLAN_STATUS_SUCCESS && scan_cfg)
4725 		memcpy(scan_cfg, &scan->param.scan_cfg, sizeof(mlan_scan_cfg));
4726 
4727 done:
4728 	if (ret != MLAN_STATUS_PENDING)
4729 		kfree(req);
4730 	LEAVE();
4731 	return ret;
4732 }
4733 
4734 /**
4735  *  @brief set scan time
4736  *
4737  *  @param priv                 A pointer to moal_private structure
4738  *  @param active_scan_time     Active scan time
4739  *  @param passive_scan_time    Passive scan time
4740  *  @param specific_scan_time   Specific scan time
4741  *
4742  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
4743  */
4744 mlan_status
woal_set_scan_time(moal_private * priv,t_u16 active_scan_time,t_u16 passive_scan_time,t_u16 specific_scan_time)4745 woal_set_scan_time(moal_private *priv, t_u16 active_scan_time,
4746 		   t_u16 passive_scan_time, t_u16 specific_scan_time)
4747 {
4748 	mlan_status ret = MLAN_STATUS_SUCCESS;
4749 	mlan_ds_scan *scan = NULL;
4750 	mlan_ioctl_req *req = NULL;
4751 	mlan_scan_cfg scan_cfg;
4752 
4753 	ENTER();
4754 
4755 	memset(&scan_cfg, 0, sizeof(scan_cfg));
4756 	if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) {
4757 		ret = MLAN_STATUS_FAILURE;
4758 		goto done;
4759 	}
4760 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
4761 	if (req == NULL) {
4762 		ret = MLAN_STATUS_FAILURE;
4763 		goto done;
4764 	}
4765 	scan = (mlan_ds_scan *)req->pbuf;
4766 	scan->sub_command = MLAN_OID_SCAN_CONFIG;
4767 	req->req_id = MLAN_IOCTL_SCAN;
4768 	req->action = MLAN_ACT_SET;
4769 	memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
4770 	scan_cfg.scan_time.active_scan_time = active_scan_time;
4771 	scan_cfg.scan_time.specific_scan_time = specific_scan_time;
4772 	scan_cfg.scan_time.passive_scan_time = passive_scan_time;
4773 	PRINTM(MIOCTL, "Set specific=%d, active=%d, passive=%d\n",
4774 	       (int)active_scan_time, (int)passive_scan_time,
4775 	       (int)specific_scan_time);
4776 	memcpy(&scan->param.scan_cfg, &scan_cfg, sizeof(mlan_scan_cfg));
4777 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4778 
4779 done:
4780 	if (ret != MLAN_STATUS_PENDING)
4781 		kfree(req);
4782 	LEAVE();
4783 	return ret;
4784 }
4785 
4786 /**
4787  *  @brief request scan
4788  *
4789  *  @param priv                 A pointer to moal_private structure
4790  *  @param scan_cfg             A pointer to wlan_user_scan_cfg structure
4791  *
4792  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
4793  */
4794 mlan_status
woal_do_scan(moal_private * priv,wlan_user_scan_cfg * scan_cfg)4795 woal_do_scan(moal_private *priv, wlan_user_scan_cfg *scan_cfg)
4796 {
4797 	mlan_status ret = MLAN_STATUS_SUCCESS;
4798 	moal_handle *handle = priv->phandle;
4799 
4800 	ENTER();
4801 	if (handle->scan_pending_on_block == MTRUE) {
4802 		PRINTM(MINFO, "scan already in processing...\n");
4803 		LEAVE();
4804 		return ret;
4805 	}
4806 #ifdef REASSOCIATION
4807 	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->reassoc_sem)) {
4808 		PRINTM(MERROR, "Acquire semaphore error, woal_do_combo_scan\n");
4809 		LEAVE();
4810 		return -EBUSY;
4811 	}
4812 #endif /* REASSOCIATION */
4813 	priv->report_scan_result = MTRUE;
4814 
4815 	if (!scan_cfg)
4816 		ret = woal_request_scan(priv, MOAL_NO_WAIT, NULL);
4817 	else
4818 		ret = woal_request_userscan(priv, MOAL_NO_WAIT, scan_cfg);
4819 
4820 #ifdef REASSOCIATION
4821 	MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
4822 #endif
4823 	LEAVE();
4824 	return ret;
4825 }
4826 
4827 /**
4828  *  @brief Cancel pending scan
4829  *
4830  *  @param priv                 A pointer to moal_private structure
4831  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
4832  */
4833 mlan_status
woal_cancel_scan(moal_private * priv,t_u8 wait_option)4834 woal_cancel_scan(moal_private *priv, t_u8 wait_option)
4835 {
4836 	mlan_ioctl_req *req = NULL;
4837 	mlan_status ret = MLAN_STATUS_SUCCESS;
4838 	moal_handle *handle = priv->phandle;
4839 	moal_private *scan_priv = handle->scan_priv;
4840 #ifdef STA_CFG80211
4841 	unsigned long flags;
4842 #endif
4843 
4844 	/* If scan is in process, cancel the scan command */
4845 	if (!handle->scan_pending_on_block || !scan_priv)
4846 		return ret;
4847 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
4848 	if (req == NULL) {
4849 		ret = MLAN_STATUS_FAILURE;
4850 		goto done;
4851 	}
4852 	req->req_id = MLAN_IOCTL_SCAN;
4853 	req->action = MLAN_ACT_SET;
4854 	((mlan_ds_scan *)req->pbuf)->sub_command = MLAN_OID_SCAN_CANCEL;
4855 	ret = woal_request_ioctl(scan_priv, req, wait_option);
4856 	handle->scan_pending_on_block = MFALSE;
4857 	MOAL_REL_SEMAPHORE(&handle->async_sem);
4858 #ifdef STA_CFG80211
4859 	spin_lock_irqsave(&handle->scan_req_lock, flags);
4860 	if (IS_STA_CFG80211(cfg80211_wext) && handle->scan_request) {
4861 	    /** some supplicant can not handle SCAN abort event */
4862 		if (scan_priv->bss_type == MLAN_BSS_TYPE_STA)
4863 			woal_cfg80211_scan_done(handle->scan_request, MTRUE);
4864 		else
4865 			woal_cfg80211_scan_done(handle->scan_request, MFALSE);
4866 		handle->scan_request = NULL;
4867 	}
4868 	spin_unlock_irqrestore(&handle->scan_req_lock, flags);
4869 #endif
4870 	/* add 10ms delay, incase firmware delay 0x7f event after scan cancel command response */
4871 	woal_sched_timeout(10);
4872 	handle->scan_priv = NULL;
4873 done:
4874 	if (ret != MLAN_STATUS_PENDING)
4875 		kfree(req);
4876 	return ret;
4877 }
4878 
4879 /**
4880  *  @brief find ssid in scan_table
4881  *
4882  *  @param priv         A pointer to moal_private
4883  *  @param ssid_bssid   A pointer to mlan_ssid_bssid structure
4884  *
4885  *
4886  *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_FAILURE
4887  */
4888 int
woal_find_essid(moal_private * priv,mlan_ssid_bssid * ssid_bssid,t_u8 wait_option)4889 woal_find_essid(moal_private *priv, mlan_ssid_bssid *ssid_bssid,
4890 		t_u8 wait_option)
4891 {
4892 	int ret = 0;
4893 	mlan_scan_resp scan_resp;
4894 	struct timeval t;
4895 	ENTER();
4896 
4897 	if (MLAN_STATUS_SUCCESS !=
4898 	    woal_get_scan_table(priv, wait_option, &scan_resp)) {
4899 		LEAVE();
4900 		return MLAN_STATUS_FAILURE;
4901 	}
4902 #ifdef STA_CFG80211
4903 	if (priv->ft_pre_connect) {
4904 	/** skip check the scan age out */
4905 		ret = woal_find_best_network(priv, wait_option, ssid_bssid);
4906 		LEAVE();
4907 		return ret;
4908 	}
4909 #endif
4910 	do_gettimeofday(&t);
4911 /** scan result timeout value */
4912 #define SCAN_RESULT_AGEOUT      10
4913 	if (t.tv_sec > (scan_resp.age_in_secs + SCAN_RESULT_AGEOUT)) {
4914 		LEAVE();
4915 		return MLAN_STATUS_FAILURE;
4916 	}
4917 	ret = woal_find_best_network(priv, wait_option, ssid_bssid);
4918 	LEAVE();
4919 	return ret;
4920 }
4921 
4922 /**
4923  * @brief                    auto reconnection configure
4924  *
4925  * @param priv               Pointer to moal_private structure
4926  * @param cfg_mode           configure mode
4927  * @param roam_offload_cfg   Pointer to woal_roam_offload_cfg structure
4928  *
4929  *  @return                  Number of bytes written, negative for failure.
4930  */
4931 mlan_status
woal_config_fw_roaming(moal_private * priv,t_u8 cfg_mode,woal_roam_offload_cfg * roam_offload_cfg)4932 woal_config_fw_roaming(moal_private *priv, t_u8 cfg_mode,
4933 		       woal_roam_offload_cfg * roam_offload_cfg)
4934 {
4935 	mlan_ioctl_req *ioctl_req = NULL;
4936 	mlan_ds_misc_cfg *misc = NULL;
4937 	mlan_ds_misc_roam_offload *roam = NULL;
4938 	mlan_status status = MLAN_STATUS_SUCCESS;
4939 	int ret = 0;
4940 
4941 	ENTER();
4942 
4943 	if (!priv || !priv->phandle) {
4944 		PRINTM(MERROR, "priv or handle is null\n");
4945 		ret = -EFAULT;
4946 		goto done;
4947 	}
4948 
4949 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
4950 	if (ioctl_req == NULL) {
4951 		ret = -ENOMEM;
4952 		goto done;
4953 	}
4954 
4955 	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
4956 	misc->sub_command = MLAN_OID_MISC_ROAM_OFFLOAD;
4957 	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
4958 
4959 	roam = (mlan_ds_misc_roam_offload *) & misc->param.roam_offload;
4960 	roam->aplist.ap_num = 0;
4961 	ioctl_req->action = MLAN_ACT_SET;
4962 	roam->enable = priv->phandle->fw_roam_enable;
4963 	roam->config_mode = cfg_mode;
4964 
4965 	if ((roam->config_mode == ROAM_OFFLOAD_ENABLE) && roam_offload_cfg) {
4966 		roam->userset_passphrase = roam_offload_cfg->userset_passphrase;
4967 		if (roam->userset_passphrase)
4968 			roam->enable = 0;
4969 	}
4970 	if (roam->config_mode == ROAM_OFFLOAD_PARAM_CFG) {
4971 		memcpy((t_u8 *)&roam->bssid_reconnect,
4972 		       (t_u8 *)&roam_offload_cfg->bssid, MLAN_MAC_ADDR_LENGTH);
4973 		if (roam_offload_cfg->ssid_list.ssid_num) {
4974 			memcpy((t_u8 *)&roam->ssid_list,
4975 			       (t_u8 *)&roam_offload_cfg->ssid_list,
4976 			       sizeof(mlan_ds_misc_ssid_list));
4977 		}
4978 		if (roam_offload_cfg->black_list.ap_num) {
4979 			memcpy((t_u8 *)&roam->black_list,
4980 			       (t_u8 *)&roam_offload_cfg->black_list,
4981 			       sizeof(mlan_ds_misc_roam_offload_aplist));
4982 		}
4983 		roam->trigger_condition = roam_offload_cfg->trigger_condition;
4984 		roam->retry_count = roam_offload_cfg->retry_count;
4985 		if (roam_offload_cfg->rssi_param_set_flag) {
4986 			roam->para_rssi.set_flag = 1;
4987 			roam->para_rssi.max_rssi = roam_offload_cfg->max_rssi;
4988 			roam->para_rssi.min_rssi = roam_offload_cfg->min_rssi;
4989 			roam->para_rssi.step_rssi = roam_offload_cfg->step_rssi;
4990 		}
4991 		if (roam_offload_cfg->band_rssi_flag) {
4992 			roam->band_rssi_flag = roam_offload_cfg->band_rssi_flag;
4993 			memcpy((t_u8 *)&roam->band_rssi,
4994 			       (t_u8 *)&roam_offload_cfg->band_rssi,
4995 			       sizeof(mlan_ds_misc_band_rssi));
4996 		}
4997 		if (roam_offload_cfg->bgscan_set_flag) {
4998 			roam->bgscan_set_flag =
4999 				roam_offload_cfg->bgscan_set_flag;
5000 			memcpy((t_u8 *)&roam->bgscan_cfg,
5001 			       (t_u8 *)&roam_offload_cfg->bgscan_cfg,
5002 			       sizeof(mlan_ds_misc_bgscan_cfg));
5003 		}
5004 		if (roam_offload_cfg->ees_param_set_flag) {
5005 			roam->ees_param_set_flag =
5006 				roam_offload_cfg->ees_param_set_flag;
5007 			memcpy((t_u8 *)&roam->ees_cfg,
5008 			       (t_u8 *)&roam_offload_cfg->ees_cfg,
5009 			       sizeof(mlan_ds_misc_ees_cfg));
5010 		}
5011 		roam->bcn_miss_threshold = roam_offload_cfg->bcn_miss_threshold;
5012 		roam->pre_bcn_miss_threshold =
5013 			roam_offload_cfg->pre_bcn_miss_threshold;
5014 		roam->repeat_count = roam_offload_cfg->repeat_count;
5015 	}
5016 	if (roam->config_mode == ROAM_OFFLOAD_SUSPEND_CFG) {
5017 		memcpy(roam->bssid_reconnect,
5018 		       priv->phandle->auto_reconnect_bssid,
5019 		       MLAN_MAC_ADDR_LENGTH);
5020 		roam->ssid_list.ssid_num = 1;
5021 		memcpy((t_u8 *)&roam->ssid_list.ssids[0].ssid,
5022 		       (t_u8 *)&priv->phandle->auto_reconnect_ssid.ssid,
5023 		       priv->phandle->auto_reconnect_ssid.ssid_len);
5024 
5025 		roam->retry_count = priv->phandle->auto_reconnect_retry_count;
5026 	}
5027 
5028 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
5029 	if (status != MLAN_STATUS_SUCCESS) {
5030 		ret = -EFAULT;
5031 		goto done;
5032 	}
5033 
5034 done:
5035 	if (status != MLAN_STATUS_PENDING)
5036 		kfree(ioctl_req);
5037 
5038 	LEAVE();
5039 	return ret;
5040 }
5041 
5042 /**
5043  *  @brief Request user scan
5044  *
5045  *  @param priv                 A pointer to moal_private structure
5046  *  @param wait_option          Wait option
5047  *  @param scan_cfg             A pointer to wlan_bgscan_cfg structure
5048  *
5049  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5050  */
5051 mlan_status
woal_request_bgscan(moal_private * priv,t_u8 wait_option,wlan_bgscan_cfg * scan_cfg)5052 woal_request_bgscan(moal_private *priv,
5053 		    t_u8 wait_option, wlan_bgscan_cfg *scan_cfg)
5054 {
5055 	mlan_status ret = MLAN_STATUS_SUCCESS;
5056 	mlan_ioctl_req *ioctl_req = NULL;
5057 	mlan_ds_scan *scan = NULL;
5058 	mlan_status status = MLAN_STATUS_SUCCESS;
5059 	ENTER();
5060 
5061 	/* Allocate an IOCTL request buffer */
5062 	ioctl_req =
5063 		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan) +
5064 					  sizeof(wlan_bgscan_cfg));
5065 	if (ioctl_req == NULL) {
5066 		ret = MLAN_STATUS_FAILURE;
5067 		goto done;
5068 	}
5069 
5070 	scan = (mlan_ds_scan *)ioctl_req->pbuf;
5071 	scan->sub_command = MLAN_OID_SCAN_BGSCAN_CONFIG;
5072 	ioctl_req->req_id = MLAN_IOCTL_SCAN;
5073 	ioctl_req->action = MLAN_ACT_SET;
5074 	memcpy(scan->param.user_scan.scan_cfg_buf, scan_cfg,
5075 	       sizeof(wlan_bgscan_cfg));
5076 
5077 	/* Send IOCTL request to MLAN */
5078 	status = woal_request_ioctl(priv, ioctl_req, wait_option);
5079 	if (status == MLAN_STATUS_FAILURE) {
5080 		ret = MLAN_STATUS_FAILURE;
5081 		goto done;
5082 	}
5083 done:
5084 	if (status != MLAN_STATUS_PENDING)
5085 		kfree(ioctl_req);
5086 	LEAVE();
5087 	return ret;
5088 }
5089 
5090 /**
5091  *  @brief set bgscan config
5092  *
5093  *  @param priv                 A pointer to moal_private structure
5094  *  @param buf                  A pointer to scan command buf
5095  *  @param length               buf length
5096  *
5097  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5098  */
5099 mlan_status
woal_set_bg_scan(moal_private * priv,char * buf,int length)5100 woal_set_bg_scan(moal_private *priv, char *buf, int length)
5101 {
5102 	t_u8 *ptr = buf + strlen("BGSCAN-CONFIG") + 1;
5103 	int buf_left = length - (strlen("BGSCAN-CONFIG") + 1);
5104 	int band = 0;
5105 	int num_ssid = 0;
5106 	int ssid_len = 0;
5107 	mlan_status ret = MLAN_STATUS_FAILURE;
5108 
5109 	ENTER();
5110 	memset(&priv->scan_cfg, 0, sizeof(priv->scan_cfg));
5111 	priv->scan_cfg.report_condition =
5112 		BG_SCAN_SSID_MATCH | BG_SCAN_WAIT_ALL_CHAN_DONE;
5113 	while (buf_left >= 2) {
5114 		switch (*ptr) {
5115 		case WEXT_CSCAN_SSID_SECTION:
5116 			ssid_len = *(ptr + 1);
5117 			if ((buf_left < (ssid_len + 2)) ||
5118 			    (ssid_len > MLAN_MAX_SSID_LENGTH)) {
5119 				PRINTM(MERROR,
5120 				       "Invalid ssid, buf_left=%d, ssid_len=%d\n",
5121 				       buf_left, ssid_len);
5122 				buf_left = 0;
5123 				break;
5124 			}
5125 			if (ssid_len &&
5126 			    (num_ssid < (MRVDRV_MAX_SSID_LIST_LENGTH - 1))) {
5127 				strncpy(priv->scan_cfg.ssid_list[num_ssid].ssid,
5128 					ptr + 2, ssid_len);
5129 				priv->scan_cfg.ssid_list[num_ssid].max_len = 0;
5130 				PRINTM(MIOCTL, "BG scan: ssid=%s\n",
5131 				       priv->scan_cfg.ssid_list[num_ssid].ssid);
5132 				num_ssid++;
5133 			}
5134 			buf_left -= ssid_len + 2;
5135 			ptr += ssid_len + 2;
5136 			break;
5137 		case WEXT_BGSCAN_RSSI_SECTION:
5138 			priv->scan_cfg.report_condition =
5139 				BG_SCAN_SSID_RSSI_MATCH |
5140 				BG_SCAN_WAIT_ALL_CHAN_DONE;
5141 			priv->scan_cfg.rssi_threshold = ptr[1];
5142 			PRINTM(MIOCTL, "BG scan: rssi_threshold=%d\n",
5143 			       (int)priv->scan_cfg.rssi_threshold);
5144 			ptr += 2;
5145 			buf_left -= 2;
5146 			break;
5147 		case WEXT_BGSCAN_REPEAT_SECTION:
5148 			priv->scan_cfg.repeat_count = (t_u16)ptr[1];
5149 			PRINTM(MIOCTL, "BG scan: repeat_count=%d\n",
5150 			       (int)priv->scan_cfg.repeat_count);
5151 			ptr += 2;
5152 			buf_left -= 2;
5153 			break;
5154 		case WEXT_BGSCAN_INTERVAL_SECTION:
5155 			if (buf_left < 3) {
5156 				PRINTM(MERROR,
5157 				       "Invalid scan_interval, buf_left=%d\n",
5158 				       buf_left);
5159 				buf_left = 0;
5160 				break;
5161 			}
5162 			priv->scan_cfg.scan_interval =
5163 				(ptr[2] << 8 | ptr[1]) * 1000;
5164 			PRINTM(MIOCTL, "BG scan: scan_interval=%d\n",
5165 			       (int)priv->scan_cfg.scan_interval);
5166 			ptr += 3;
5167 			buf_left -= 3;
5168 			break;
5169 		default:
5170 			buf_left = 0;
5171 			break;
5172 		}
5173 	}
5174     /** set bgscan when ssid_num > 0 */
5175 	if (num_ssid) {
5176 		if (MLAN_STATUS_SUCCESS != woal_get_band(priv, &band)) {
5177 			ret = MLAN_STATUS_FAILURE;
5178 			goto done;
5179 		}
5180 		switch (band) {
5181 		case WIFI_FREQUENCY_BAND_2GHZ:
5182 			priv->scan_cfg.chan_list[0].radio_type =
5183 				0 | BAND_SPECIFIED;
5184 			break;
5185 		case WIFI_FREQUENCY_BAND_5GHZ:
5186 			priv->scan_cfg.chan_list[0].radio_type =
5187 				1 | BAND_SPECIFIED;
5188 			break;
5189 		default:
5190 			break;
5191 		}
5192 		priv->scan_cfg.bss_type = MLAN_BSS_MODE_INFRA;
5193 		priv->scan_cfg.action = BG_SCAN_ACT_SET;
5194 		priv->scan_cfg.enable = MTRUE;
5195 		ret = woal_request_bgscan(priv, MOAL_IOCTL_WAIT,
5196 					  &priv->scan_cfg);
5197 	}
5198 done:
5199 	LEAVE();
5200 	return ret;
5201 }
5202 
5203 #ifdef STA_CFG80211
5204 /**
5205  *  @brief set bgscan and new rssi_low_threshold
5206  *
5207  *  @param priv                 A pointer to moal_private structure
5208  *  @param set_rssi             flag for set rssi_low_threshold
5209  *
5210  *  @return                     N/A
5211  */
5212 void
woal_config_bgscan_and_rssi(moal_private * priv,t_u8 set_rssi)5213 woal_config_bgscan_and_rssi(moal_private *priv, t_u8 set_rssi)
5214 {
5215 	char rssi_low[11];
5216 	mlan_bss_info bss_info;
5217 	int band = 0;
5218 
5219 	ENTER();
5220 	memset(&bss_info, 0, sizeof(bss_info));
5221 	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
5222 	if (!bss_info.media_connected) {
5223 		PRINTM(MIOCTL, "We already lost connection\n");
5224 		LEAVE();
5225 		return;
5226 	}
5227 	memset(&priv->scan_cfg, 0, sizeof(priv->scan_cfg));
5228 	strncpy(priv->scan_cfg.ssid_list[0].ssid, bss_info.ssid.ssid,
5229 		bss_info.ssid.ssid_len);
5230 	priv->scan_cfg.ssid_list[0].max_len = 0;
5231 
5232 	priv->scan_cfg.report_condition =
5233 		BG_SCAN_SSID_RSSI_MATCH | BG_SCAN_WAIT_ALL_CHAN_DONE;
5234 	priv->scan_cfg.rssi_threshold = priv->rssi_low - RSSI_HYSTERESIS;
5235 	priv->scan_cfg.repeat_count = DEF_REPEAT_COUNT;
5236 	priv->scan_cfg.scan_interval = MIN_BGSCAN_INTERVAL;
5237 	woal_get_band(priv, &band);
5238 	switch (band) {
5239 	case WIFI_FREQUENCY_BAND_2GHZ:
5240 		priv->scan_cfg.chan_list[0].radio_type = 0 | BAND_SPECIFIED;
5241 		break;
5242 	case WIFI_FREQUENCY_BAND_5GHZ:
5243 		priv->scan_cfg.chan_list[0].radio_type = 1 | BAND_SPECIFIED;
5244 		break;
5245 	default:
5246 		break;
5247 	}
5248 	priv->scan_cfg.bss_type = MLAN_BSS_MODE_INFRA;
5249 	priv->scan_cfg.action = BG_SCAN_ACT_SET;
5250 	priv->scan_cfg.enable = MTRUE;
5251 	woal_request_bgscan(priv, MOAL_NO_WAIT, &priv->scan_cfg);
5252 	if (set_rssi &&
5253 	    ((priv->rssi_low + RSSI_HYSTERESIS) <= LOWEST_RSSI_THRESHOLD)) {
5254 		priv->rssi_low += RSSI_HYSTERESIS;
5255 		sprintf(rssi_low, "%d", priv->rssi_low);
5256 		woal_set_rssi_low_threshold(priv, rssi_low, MOAL_NO_WAIT);
5257 	}
5258 	LEAVE();
5259 }
5260 #endif
5261 
5262 /**
5263  *  @brief stop bg scan
5264  *
5265  *  @param priv                 A pointer to moal_private structure
5266  *  @param wait_option          wait option
5267  *
5268  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5269  */
5270 mlan_status
woal_stop_bg_scan(moal_private * priv,t_u8 wait_option)5271 woal_stop_bg_scan(moal_private *priv, t_u8 wait_option)
5272 {
5273 	wlan_bgscan_cfg scan_cfg;
5274 	mlan_status ret = MLAN_STATUS_SUCCESS;
5275 	ENTER();
5276 
5277 	memset(&scan_cfg, 0, sizeof(scan_cfg));
5278 	scan_cfg.action = BG_SCAN_ACT_SET;
5279 	scan_cfg.enable = MFALSE;
5280 	ret = woal_request_bgscan(priv, wait_option, &scan_cfg);
5281 
5282 	LEAVE();
5283 	return ret;
5284 }
5285 
5286 /**
5287  *  @brief set bgscan config
5288  *
5289  *  @param handle               A pointer to moal_handle structure
5290  *
5291  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5292  */
5293 void
woal_reconfig_bgscan(moal_handle * handle)5294 woal_reconfig_bgscan(moal_handle *handle)
5295 {
5296 	int i;
5297 	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
5298 		if (handle->priv[i] &&
5299 		    (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA)) {
5300 			if (handle->priv[i]->bg_scan_start &&
5301 			    handle->priv[i]->bg_scan_reported) {
5302 				PRINTM(MIOCTL, "Reconfig BGSCAN\n");
5303 				woal_request_bgscan(handle->priv[i],
5304 						    MOAL_NO_WAIT,
5305 						    &handle->priv[i]->scan_cfg);
5306 				handle->priv[i]->bg_scan_reported = MFALSE;
5307 			}
5308 		}
5309 	}
5310 }
5311 
5312 /**
5313  *  @brief set rssi low threshold
5314  *
5315  *  @param priv                 A pointer to moal_private structure
5316  *  @param rssi                 A pointer to low rssi
5317  *  @param wait_option          Wait option
5318  *
5319  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5320  */
5321 mlan_status
woal_set_rssi_low_threshold(moal_private * priv,char * rssi,t_u8 wait_option)5322 woal_set_rssi_low_threshold(moal_private *priv, char *rssi, t_u8 wait_option)
5323 {
5324 	mlan_status ret = MLAN_STATUS_SUCCESS;
5325 	mlan_ioctl_req *req = NULL;
5326 	mlan_ds_misc_cfg *misc = NULL;
5327 	int low_rssi = 0;
5328 
5329 	ENTER();
5330 	if (priv->media_connected == MFALSE)
5331 		goto done;
5332 
5333 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
5334 	if (req == NULL) {
5335 		ret = MLAN_STATUS_FAILURE;
5336 		goto done;
5337 	}
5338 	misc = (mlan_ds_misc_cfg *)req->pbuf;
5339 	req->req_id = MLAN_IOCTL_MISC_CFG;
5340 	misc->sub_command = MLAN_OID_MISC_SUBSCRIBE_EVENT;
5341 	req->action = MLAN_ACT_SET;
5342 	misc->param.subscribe_event.evt_action = SUBSCRIBE_EVT_ACT_BITWISE_SET;
5343 	misc->param.subscribe_event.evt_bitmap = SUBSCRIBE_EVT_RSSI_LOW;
5344 	misc->param.subscribe_event.evt_bitmap |= SUBSCRIBE_EVT_PRE_BEACON_LOST;
5345 	misc->param.subscribe_event.pre_beacon_miss = DEFAULT_PRE_BEACON_MISS;
5346 
5347 	if (MLAN_STATUS_SUCCESS != woal_atoi(&low_rssi, rssi)) {
5348 		ret = MLAN_STATUS_FAILURE;
5349 		goto done;
5350 	}
5351 #ifdef STA_CFG80211
5352 	priv->mrvl_rssi_low = low_rssi;
5353 #endif
5354 	misc->param.subscribe_event.low_rssi = low_rssi;
5355 	misc->param.subscribe_event.low_rssi_freq = 0;
5356 	ret = woal_request_ioctl(priv, req, wait_option);
5357 	if (ret == MLAN_STATUS_FAILURE) {
5358 		PRINTM(MERROR, "request set rssi_low_threshold fail!\n");
5359 		goto done;
5360 	}
5361 done:
5362 	if (ret != MLAN_STATUS_PENDING)
5363 		kfree(req);
5364 	LEAVE();
5365 	return ret;
5366 }
5367 
5368 #if defined(STA_CFG80211)
5369 /**
5370  *  @brief set rssi low threshold
5371  *
5372  *  @param priv                 A pointer to moal_private structure
5373  *  @param event_id             event id.
5374  *  @param wait_option          wait option
5375  *
5376  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5377  */
5378 mlan_status
woal_set_rssi_threshold(moal_private * priv,t_u32 event_id,t_u8 wait_option)5379 woal_set_rssi_threshold(moal_private *priv, t_u32 event_id, t_u8 wait_option)
5380 {
5381 	mlan_status ret = MLAN_STATUS_SUCCESS;
5382 	mlan_ioctl_req *req = NULL;
5383 	mlan_ds_misc_cfg *misc = NULL;
5384 
5385 	ENTER();
5386 	if (priv->media_connected == MFALSE)
5387 		goto done;
5388 	if (priv->mrvl_rssi_low)
5389 		goto done;
5390 	if (event_id == MLAN_EVENT_ID_FW_BCN_RSSI_LOW) {
5391 		if (priv->last_rssi_low < 100)
5392 			priv->last_rssi_low += priv->cqm_rssi_hyst;
5393 		priv->last_rssi_high = abs(priv->cqm_rssi_high_thold);
5394 	} else if (event_id == MLAN_EVENT_ID_FW_BCN_RSSI_HIGH) {
5395 		priv->last_rssi_low = abs(priv->cqm_rssi_thold);
5396 		if (priv->last_rssi_high > priv->cqm_rssi_hyst)
5397 			priv->last_rssi_high -= priv->cqm_rssi_hyst;
5398 	} else {
5399 		priv->last_rssi_low = abs(priv->cqm_rssi_thold);
5400 		priv->last_rssi_high = abs(priv->cqm_rssi_high_thold);
5401 	}
5402 
5403 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
5404 	if (req == NULL) {
5405 		ret = -ENOMEM;
5406 		goto done;
5407 	}
5408 	misc = (mlan_ds_misc_cfg *)req->pbuf;
5409 	req->req_id = MLAN_IOCTL_MISC_CFG;
5410 	misc->sub_command = MLAN_OID_MISC_SUBSCRIBE_EVENT;
5411 	req->action = MLAN_ACT_SET;
5412 	if (!event_id && !priv->cqm_rssi_thold && !priv->cqm_rssi_hyst)
5413 		misc->param.subscribe_event.evt_action =
5414 			SUBSCRIBE_EVT_ACT_BITWISE_CLR;
5415 	else
5416 		misc->param.subscribe_event.evt_action =
5417 			SUBSCRIBE_EVT_ACT_BITWISE_SET;
5418 	misc->param.subscribe_event.evt_bitmap =
5419 		SUBSCRIBE_EVT_RSSI_LOW | SUBSCRIBE_EVT_RSSI_HIGH;
5420 	misc->param.subscribe_event.low_rssi_freq = 0;
5421 	misc->param.subscribe_event.low_rssi = priv->last_rssi_low;
5422 	misc->param.subscribe_event.high_rssi_freq = 0;
5423 	misc->param.subscribe_event.high_rssi = priv->last_rssi_high;
5424 	PRINTM(MIOCTL, "rssi_low=%d, rssi_high=%d action=%d\n",
5425 	       (int)priv->last_rssi_low, (int)priv->last_rssi_high,
5426 	       misc->param.subscribe_event.evt_action);
5427 	ret = woal_request_ioctl(priv, req, wait_option);
5428 done:
5429 	if (ret != MLAN_STATUS_PENDING)
5430 		kfree(req);
5431 	LEAVE();
5432 	return ret;
5433 }
5434 #endif
5435 
5436 /**
5437  *  @brief  Get power mode
5438  *
5439  *  @param priv                 A pointer to moal_private structure
5440  *  @param powermode            A pointer to powermode buf
5441  *
5442  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5443  */
5444 mlan_status
woal_get_powermode(moal_private * priv,int * powermode)5445 woal_get_powermode(moal_private *priv, int *powermode)
5446 {
5447 	mlan_status ret = MLAN_STATUS_SUCCESS;
5448 	int ps_mode;
5449 
5450 	ENTER();
5451 
5452 	if (MLAN_STATUS_SUCCESS !=
5453 	    woal_set_get_power_mgmt(priv, MLAN_ACT_GET, &ps_mode, 0,
5454 				    MOAL_IOCTL_WAIT)) {
5455 		ret = MLAN_STATUS_FAILURE;
5456 		goto done;
5457 	}
5458 
5459 	if (ps_mode)
5460 		*powermode = MFALSE;
5461 	else
5462 		*powermode = MTRUE;
5463 
5464 done:
5465 	LEAVE();
5466 	return ret;
5467 }
5468 
5469 /**
5470  *  @brief set scan type
5471  *
5472  *  @param priv                 A pointer to moal_private structure
5473  *  @param scan_type            MLAN_SCAN_TYPE_ACTIVE/MLAN_SCAN_TYPE_PASSIVE
5474  *
5475  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5476  */
5477 mlan_status
woal_set_scan_type(moal_private * priv,t_u32 scan_type)5478 woal_set_scan_type(moal_private *priv, t_u32 scan_type)
5479 {
5480 	mlan_status ret = MLAN_STATUS_SUCCESS;
5481 	mlan_ds_scan *scan = NULL;
5482 	mlan_ioctl_req *req = NULL;
5483 	mlan_scan_cfg scan_cfg;
5484 
5485 	ENTER();
5486 	memset(&scan_cfg, 0, sizeof(scan_cfg));
5487 	if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) {
5488 		ret = MLAN_STATUS_FAILURE;
5489 		goto done;
5490 	}
5491 
5492 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
5493 	if (req == NULL) {
5494 		ret = MLAN_STATUS_FAILURE;
5495 		goto done;
5496 	}
5497 	scan = (mlan_ds_scan *)req->pbuf;
5498 	scan->sub_command = MLAN_OID_SCAN_CONFIG;
5499 	req->req_id = MLAN_IOCTL_SCAN;
5500 	req->action = MLAN_ACT_SET;
5501 	memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
5502 	scan_cfg.scan_type = scan_type;
5503 	PRINTM(MIOCTL, "Set scan_type=%d\n", (int)scan_type);
5504 	memcpy(&scan->param.scan_cfg, &scan_cfg, sizeof(mlan_scan_cfg));
5505 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5506 
5507 done:
5508 	if (ret != MLAN_STATUS_PENDING)
5509 		kfree(req);
5510 	LEAVE();
5511 	return ret;
5512 }
5513 
5514 /**
5515  *  @brief enable/disable ext_scan
5516  *
5517  *  @param priv                 A pointer to moal_private structure
5518  *  @param enable               MTRUE -- enable, MFALSE --disable
5519  *
5520  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5521  */
5522 mlan_status
woal_enable_ext_scan(moal_private * priv,t_u8 enable)5523 woal_enable_ext_scan(moal_private *priv, t_u8 enable)
5524 {
5525 	mlan_status ret = MLAN_STATUS_SUCCESS;
5526 	mlan_ds_scan *scan = NULL;
5527 	mlan_ioctl_req *req = NULL;
5528 	mlan_scan_cfg scan_cfg;
5529 
5530 	ENTER();
5531 	memset(&scan_cfg, 0, sizeof(scan_cfg));
5532 	if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) {
5533 		ret = MLAN_STATUS_FAILURE;
5534 		goto done;
5535 	}
5536 
5537 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
5538 	if (req == NULL) {
5539 		ret = MLAN_STATUS_FAILURE;
5540 		goto done;
5541 	}
5542 	scan = (mlan_ds_scan *)req->pbuf;
5543 	scan->sub_command = MLAN_OID_SCAN_CONFIG;
5544 	req->req_id = MLAN_IOCTL_SCAN;
5545 	req->action = MLAN_ACT_SET;
5546 	memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg));
5547 	scan_cfg.ext_scan = enable;
5548 	PRINTM(MIOCTL, "Set ext_scan=%d\n", (int)enable);
5549 	memcpy(&scan->param.scan_cfg, &scan_cfg, sizeof(mlan_scan_cfg));
5550 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5551 
5552 done:
5553 	if (ret != MLAN_STATUS_PENDING)
5554 		kfree(req);
5555 	LEAVE();
5556 	return ret;
5557 }
5558 
5559 /**
5560  *  @brief set power mode
5561  *
5562  *  @param priv                 A pointer to moal_private structure
5563  *  @param powermode            A pointer to powermode string.
5564  *
5565  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5566  */
5567 mlan_status
woal_set_powermode(moal_private * priv,char * powermode)5568 woal_set_powermode(moal_private *priv, char *powermode)
5569 {
5570 	mlan_status ret = MLAN_STATUS_SUCCESS;
5571 	int disabled;
5572 
5573 	ENTER();
5574 
5575 	if (*powermode == '1') {
5576 		PRINTM(MIOCTL, "Disable power save\n");
5577 		disabled = 1;
5578 	} else if (*powermode == '0') {
5579 		PRINTM(MIOCTL, "Enable power save\n");
5580 		disabled = 0;
5581 	} else {
5582 		PRINTM(MERROR, "unsupported power mode\n");
5583 		ret = MLAN_STATUS_FAILURE;
5584 		goto done;
5585 	}
5586 
5587 	if (MLAN_STATUS_SUCCESS !=
5588 	    woal_set_get_power_mgmt(priv, MLAN_ACT_SET, &disabled, 0,
5589 				    MOAL_IOCTL_WAIT))
5590 		ret = MLAN_STATUS_FAILURE;
5591 
5592 done:
5593 	LEAVE();
5594 	return ret;
5595 }
5596 
5597 /**
5598  *  @brief set combo scan
5599  *
5600  *  @param priv                 A pointer to moal_private structure
5601  *  @param buf                  A pointer to scan command buf
5602  *  @param length               buf length
5603  *
5604  *  @return                     0 -- success, otherwise fail
5605  */
5606 int
woal_set_combo_scan(moal_private * priv,char * buf,int length)5607 woal_set_combo_scan(moal_private *priv, char *buf, int length)
5608 {
5609 	int ret = 0;
5610 	wlan_user_scan_cfg scan_cfg;
5611 	t_u8 *ptr = buf + WEXT_CSCAN_HEADER_SIZE;
5612 	int buf_left = length - WEXT_CSCAN_HEADER_SIZE;
5613 	int num_ssid = 0;
5614 	int num_chan = 0;
5615 	int ssid_len = 0;
5616 	int i = 0;
5617 	t_u16 passive_scan_time = 0;
5618 	t_u16 specific_scan_time = 0;
5619 
5620 	ENTER();
5621 	memset(&scan_cfg, 0, sizeof(scan_cfg));
5622 	while (buf_left >= 2) {
5623 		switch (*ptr) {
5624 		case WEXT_CSCAN_SSID_SECTION:
5625 			ssid_len = *(ptr + 1);
5626 			if ((buf_left < (ssid_len + 2)) ||
5627 			    (ssid_len > MLAN_MAX_SSID_LENGTH)) {
5628 				PRINTM(MERROR,
5629 				       "Invalid ssid, buf_left=%d, ssid_len=%d\n",
5630 				       buf_left, ssid_len);
5631 				buf_left = 0;
5632 				break;
5633 			}
5634 			if (ssid_len &&
5635 			    (num_ssid < (MRVDRV_MAX_SSID_LIST_LENGTH - 1))) {
5636 				strncpy(scan_cfg.ssid_list[num_ssid].ssid,
5637 					ptr + 2, ssid_len);
5638 				scan_cfg.ssid_list[num_ssid].max_len = 0;
5639 				PRINTM(MIOCTL, "Combo scan: ssid=%s\n",
5640 				       scan_cfg.ssid_list[num_ssid].ssid);
5641 				num_ssid++;
5642 			}
5643 			buf_left -= ssid_len + 2;
5644 			ptr += ssid_len + 2;
5645 			break;
5646 		case WEXT_CSCAN_CHANNEL_SECTION:
5647 			num_chan = ptr[1];
5648 			if ((buf_left < (num_chan + 2)) ||
5649 			    (num_chan > WLAN_USER_SCAN_CHAN_MAX)) {
5650 				PRINTM(MERROR,
5651 				       "Invalid channel list, buf_left=%d, num_chan=%d\n",
5652 				       buf_left, num_chan);
5653 				buf_left = 0;
5654 				break;
5655 			}
5656 			for (i = 0; i < num_chan; i++) {
5657 				scan_cfg.chan_list[i].chan_number = ptr[2 + i];
5658 				PRINTM(MIOCTL, "Combo scan: chan=%d\n",
5659 				       scan_cfg.chan_list[i].chan_number);
5660 			}
5661 			buf_left -= 2 + num_chan;
5662 			ptr += 2 + num_chan;
5663 			break;
5664 		case WEXT_CSCAN_PASV_DWELL_SECTION:
5665 			if (buf_left < 3) {
5666 				PRINTM(MERROR,
5667 				       "Invalid PASV_DWELL_SECTION, buf_left=%d\n",
5668 				       buf_left);
5669 				buf_left = 0;
5670 				break;
5671 			}
5672 			passive_scan_time = ptr[2] << 8 | ptr[1];
5673 			ptr += 3;
5674 			buf_left -= 3;
5675 			break;
5676 		case WEXT_CSCAN_HOME_DWELL_SECTION:
5677 			if (buf_left < 3) {
5678 				PRINTM(MERROR,
5679 				       "Invalid HOME_DWELL_SECTION, buf_left=%d\n",
5680 				       buf_left);
5681 				buf_left = 0;
5682 				break;
5683 			}
5684 			specific_scan_time = ptr[2] << 8 | ptr[1];
5685 			ptr += 3;
5686 			buf_left -= 3;
5687 			break;
5688 		default:
5689 			buf_left = 0;
5690 			break;
5691 		}
5692 	}
5693 	if (passive_scan_time || specific_scan_time) {
5694 		PRINTM(MIOCTL,
5695 		       "Set passive_scan_time=%d specific_scan_time=%d\n",
5696 		       passive_scan_time, specific_scan_time);
5697 		if (MLAN_STATUS_FAILURE ==
5698 		    woal_set_scan_time(priv, 0, passive_scan_time,
5699 				       specific_scan_time)) {
5700 			ret = -EFAULT;
5701 			goto done;
5702 		}
5703 	}
5704 	if (num_ssid || num_chan) {
5705 		if (num_ssid) {
5706 			/* Add broadcast scan to ssid_list */
5707 			scan_cfg.ssid_list[num_ssid].max_len = 0xff;
5708 			if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
5709 				woal_set_scan_type(priv, MLAN_SCAN_TYPE_ACTIVE);
5710 		}
5711 		if (MLAN_STATUS_FAILURE == woal_do_scan(priv, &scan_cfg))
5712 			ret = -EFAULT;
5713 		if (num_ssid && (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE))
5714 			woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE);
5715 	} else {
5716 		/* request broadcast scan */
5717 		if (MLAN_STATUS_FAILURE == woal_do_scan(priv, NULL))
5718 			ret = -EFAULT;
5719 	}
5720 done:
5721 	LEAVE();
5722 	return ret;
5723 }
5724 
5725 /**
5726  *  @brief  Get band
5727  *
5728  *  @param priv                 A pointer to moal_private structure
5729  *  @param band                 A pointer to band buf
5730  *
5731  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5732  */
5733 mlan_status
woal_get_band(moal_private * priv,int * band)5734 woal_get_band(moal_private *priv, int *band)
5735 {
5736 	mlan_status ret = MLAN_STATUS_SUCCESS;
5737 	mlan_ioctl_req *req = NULL;
5738 	mlan_ds_radio_cfg *radio_cfg = NULL;
5739 	int support_band = 0;
5740 
5741 	ENTER();
5742 
5743 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
5744 	if (req == NULL) {
5745 		ret = MLAN_STATUS_FAILURE;
5746 		goto done;
5747 	}
5748 	radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
5749 	radio_cfg->sub_command = MLAN_OID_BAND_CFG;
5750 	req->req_id = MLAN_IOCTL_RADIO_CFG;
5751 	/* Get config_bands, adhoc_start_band and adhoc_channel values from MLAN */
5752 	req->action = MLAN_ACT_GET;
5753 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5754 	if (ret != MLAN_STATUS_SUCCESS)
5755 		goto done;
5756 
5757 	if (radio_cfg->param.band_cfg.
5758 	    config_bands & (BAND_B | BAND_G | BAND_GN))
5759 		support_band |= WIFI_FREQUENCY_BAND_2GHZ;
5760 	if (radio_cfg->param.band_cfg.config_bands & (BAND_A | BAND_AN))
5761 		support_band |= WIFI_FREQUENCY_BAND_5GHZ;
5762 	*band = support_band;
5763 	if (support_band == WIFI_FREQUENCY_ALL_BAND)
5764 		*band = WIFI_FREQUENCY_BAND_AUTO;
5765 done:
5766 	if (ret != MLAN_STATUS_PENDING)
5767 		kfree(req);
5768 	LEAVE();
5769 	return ret;
5770 }
5771 
5772 /**
5773  *  @brief set band
5774  *
5775  *  @param priv             A pointer to moal_private structure
5776  *  @param pband            A pointer to band string.
5777  *
5778  *  @return                 MLAN_STATUS_SUCCESS -- success, otherwise fail
5779  */
5780 mlan_status
woal_set_band(moal_private * priv,char * pband)5781 woal_set_band(moal_private *priv, char *pband)
5782 {
5783 	mlan_status ret = MLAN_STATUS_SUCCESS;
5784 	int band = 0;
5785 	mlan_ioctl_req *req = NULL;
5786 	mlan_ds_radio_cfg *radio_cfg = NULL;
5787 
5788 	ENTER();
5789 	if (priv->media_connected == MTRUE) {
5790 		PRINTM(MERROR, "Set band is not allowed in connected state\n");
5791 		ret = MLAN_STATUS_FAILURE;
5792 		goto done;
5793 	}
5794 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
5795 	if (req == NULL) {
5796 		ret = MLAN_STATUS_FAILURE;
5797 		goto done;
5798 	}
5799 	radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
5800 	radio_cfg->sub_command = MLAN_OID_BAND_CFG;
5801 	req->req_id = MLAN_IOCTL_RADIO_CFG;
5802 
5803 	/* Get fw supported values from MLAN */
5804 	req->action = MLAN_ACT_GET;
5805 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5806 	if (ret != MLAN_STATUS_SUCCESS)
5807 		goto done;
5808 
5809 	if (*pband == '0') {
5810 		PRINTM(MIOCTL, "Set band to AUTO\n");
5811 		band = radio_cfg->param.band_cfg.fw_bands;
5812 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
5813 		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev &&
5814 		    priv->wdev->wiphy) {
5815 			if (radio_cfg->param.band_cfg.fw_bands & BAND_A)
5816 				priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ] =
5817 					&cfg80211_band_5ghz;
5818 			priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ] =
5819 				&cfg80211_band_2ghz;
5820 		}
5821 #endif
5822 	} else if (*pband == '1') {
5823 		PRINTM(MIOCTL, "Set band to 5G\n");
5824 		if (!(radio_cfg->param.band_cfg.fw_bands & BAND_A)) {
5825 			PRINTM(MERROR, "Don't support 5G band\n");
5826 			ret = MLAN_STATUS_FAILURE;
5827 			goto done;
5828 		}
5829 		band = BAND_A;
5830 		if (radio_cfg->param.band_cfg.fw_bands & BAND_AN)
5831 			band |= BAND_AN;
5832 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
5833 		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev &&
5834 		    priv->wdev->wiphy) {
5835 			priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ] =
5836 				&cfg80211_band_5ghz;
5837 			priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
5838 		}
5839 #endif
5840 	} else if (*pband == '2') {
5841 		PRINTM(MIOCTL, "Set band to 2G\n");
5842 		band = BAND_B | BAND_G;
5843 		band |= BAND_GN;
5844 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
5845 		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev &&
5846 		    priv->wdev->wiphy) {
5847 			priv->wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
5848 			priv->wdev->wiphy->bands[IEEE80211_BAND_2GHZ] =
5849 				&cfg80211_band_2ghz;
5850 		}
5851 #endif
5852 	} else {
5853 		PRINTM(MERROR, "unsupported band\n");
5854 		ret = MLAN_STATUS_FAILURE;
5855 		goto done;
5856 	}
5857 	/* Set config_bands to MLAN */
5858 	req->action = MLAN_ACT_SET;
5859 	memset(&radio_cfg->param.band_cfg, 0, sizeof(mlan_ds_band_cfg));
5860 	radio_cfg->param.band_cfg.config_bands = band;
5861 	radio_cfg->param.band_cfg.adhoc_start_band = band;
5862 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5863 
5864 done:
5865 	if (ret != MLAN_STATUS_PENDING)
5866 		kfree(req);
5867 	LEAVE();
5868 	return ret;
5869 }
5870 
5871 /**
5872  *  @brief Add RX Filter
5873  *
5874  *  @param priv                 A pointer to moal_private structure
5875  *  @param rxfilter             A pointer to rxfilter string.
5876  *
5877  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5878  */
5879 mlan_status
woal_add_rxfilter(moal_private * priv,char * rxfilter)5880 woal_add_rxfilter(moal_private *priv, char *rxfilter)
5881 {
5882 	mlan_status ret = MLAN_STATUS_SUCCESS;
5883 	ENTER();
5884 	/*  Android command:
5885 	   "DRIVER RXFILTER-ADD 0"
5886 	   "DRIVER RXFILTER-ADD 1"
5887 	   "DRIVER RXFILTER-ADD 3" */
5888 	if (*rxfilter == '0') {
5889 		PRINTM(MIOCTL, "Add IPV4 multicast filter\n");
5890 		priv->rx_filter |= RX_FILTER_IPV4_MULTICAST;
5891 	} else if (*rxfilter == '1') {
5892 		PRINTM(MIOCTL, "Add broadcast filter\n");
5893 		priv->rx_filter |= RX_FILTER_BROADCAST;
5894 	} else if (*rxfilter == '2') {
5895 		PRINTM(MIOCTL, "Add unicast filter\n");
5896 		priv->rx_filter |= RX_FILTER_UNICAST;
5897 	} else if (*rxfilter == '3') {
5898 		PRINTM(MIOCTL, "Add IPV6 multicast fitler\n");
5899 		priv->rx_filter |= RX_FILTER_IPV6_MULTICAST;
5900 	} else {
5901 		PRINTM(MERROR, "unsupported rx fitler\n");
5902 		ret = MLAN_STATUS_FAILURE;
5903 		goto done;
5904 	}
5905 done:
5906 	LEAVE();
5907 	return ret;
5908 }
5909 
5910 /**
5911  *  @brief Remove RX Filter
5912  *
5913  *  @param priv                 A pointer to moal_private structure
5914  *  @param rxfilter             A pointer to rxfilter string.
5915  *
5916  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
5917  */
5918 mlan_status
woal_remove_rxfilter(moal_private * priv,char * rxfilter)5919 woal_remove_rxfilter(moal_private *priv, char *rxfilter)
5920 {
5921 	mlan_status ret = MLAN_STATUS_SUCCESS;
5922 	ENTER();
5923 	if (*rxfilter == '0') {
5924 		PRINTM(MIOCTL, "Remove IPV4 multicast filter\n");
5925 		priv->rx_filter &= ~RX_FILTER_IPV4_MULTICAST;
5926 	} else if (*rxfilter == '1') {
5927 		PRINTM(MIOCTL, "Remove broadcast filter\n");
5928 		priv->rx_filter &= ~RX_FILTER_BROADCAST;
5929 	} else if (*rxfilter == '2') {
5930 		PRINTM(MIOCTL, "Remove unicast filter\n");
5931 		priv->rx_filter &= ~RX_FILTER_UNICAST;
5932 	} else if (*rxfilter == '3') {
5933 		PRINTM(MIOCTL, "Remove IPV6 multicast fitler\n");
5934 		priv->rx_filter &= ~RX_FILTER_IPV6_MULTICAST;
5935 	} else {
5936 		PRINTM(MERROR, "unsupported rx fitler\n");
5937 		ret = MLAN_STATUS_FAILURE;
5938 		goto done;
5939 	}
5940 done:
5941 	LEAVE();
5942 	return ret;
5943 }
5944 
5945 /**
5946  * @brief Set/Get WMM IE QoS configuration
5947  *
5948  * @param priv     A pointer to moal_private structure
5949  *  @param action  Action set or get
5950  * @param qos_cfg  A pointer to QoS configuration structure
5951  *
5952  * @return         MLAN_STATUS_SUCCESS -- success, otherwise fail
5953  */
5954 mlan_status
woal_priv_qos_cfg(moal_private * priv,t_u32 action,char * qos_cfg)5955 woal_priv_qos_cfg(moal_private *priv, t_u32 action, char *qos_cfg)
5956 {
5957 	mlan_status ret = MLAN_STATUS_SUCCESS;
5958 	mlan_ds_wmm_cfg *cfg = NULL;
5959 	mlan_ioctl_req *req = NULL;
5960 	int qosinfo = 0;
5961 
5962 	ENTER();
5963 
5964 	if (qos_cfg == NULL) {
5965 		PRINTM(MERROR, "QOS info buffer is null\n");
5966 		return MLAN_STATUS_FAILURE;
5967 	}
5968 	if ((action == MLAN_ACT_SET) &&
5969 	    (MLAN_STATUS_SUCCESS != woal_atoi(&qosinfo, qos_cfg))) {
5970 		ret = MLAN_STATUS_FAILURE;
5971 		goto done;
5972 	}
5973 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
5974 	if (req == NULL) {
5975 		ret = MLAN_STATUS_FAILURE;
5976 		goto done;
5977 	}
5978 	cfg = (mlan_ds_wmm_cfg *)req->pbuf;
5979 	cfg->sub_command = MLAN_OID_WMM_CFG_QOS;
5980 	req->req_id = MLAN_IOCTL_WMM_CFG;
5981 	req->action = action;
5982 	if (action == MLAN_ACT_SET) {
5983 		cfg->param.qos_cfg = (t_u8)qosinfo;
5984 		PRINTM(MIOCTL, "set qosinfo=%d\n", qosinfo);
5985 	}
5986 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5987 
5988 	if (action == MLAN_ACT_GET)
5989 		*qos_cfg = cfg->param.qos_cfg;
5990 done:
5991 	if (ret != MLAN_STATUS_PENDING)
5992 		kfree(req);
5993 	LEAVE();
5994 	return ret;
5995 }
5996 
5997 /**
5998  * @brief Set sleep period
5999  *
6000  * @param priv     A pointer to moal_private structure
6001  * @param psleeppd A pointer to sleep period configuration structure
6002  *
6003  * @return         MLAN_STATUS_SUCCESS -- success, otherwise fail
6004  */
6005 mlan_status
woal_set_sleeppd(moal_private * priv,char * psleeppd)6006 woal_set_sleeppd(moal_private *priv, char *psleeppd)
6007 {
6008 	mlan_status ret = MLAN_STATUS_SUCCESS;
6009 	mlan_ds_pm_cfg *pm_cfg = NULL;
6010 	mlan_ioctl_req *req = NULL;
6011 	int sleeppd = 0;
6012 
6013 	ENTER();
6014 
6015 	if (MLAN_STATUS_SUCCESS != woal_atoi(&sleeppd, psleeppd)) {
6016 		ret = MLAN_STATUS_FAILURE;
6017 		goto done;
6018 	}
6019 	PRINTM(MIOCTL, "set sleeppd=%d\n", sleeppd);
6020 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
6021 	if (req == NULL) {
6022 		ret = MLAN_STATUS_FAILURE;
6023 		goto done;
6024 	}
6025 	pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
6026 	pm_cfg->sub_command = MLAN_OID_PM_CFG_SLEEP_PD;
6027 	req->req_id = MLAN_IOCTL_PM_CFG;
6028 	if ((sleeppd <= MAX_SLEEP_PERIOD && sleeppd >= MIN_SLEEP_PERIOD) ||
6029 	    (sleeppd == 0)
6030 	    || (sleeppd == SLEEP_PERIOD_RESERVED_FF)
6031 		) {
6032 		req->action = MLAN_ACT_SET;
6033 		pm_cfg->param.sleep_period = sleeppd;
6034 	} else {
6035 		ret = MLAN_STATUS_FAILURE;
6036 		goto done;
6037 	}
6038 
6039 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6040 
6041 done:
6042 	if (ret != MLAN_STATUS_PENDING)
6043 		kfree(req);
6044 	LEAVE();
6045 	return ret;
6046 }
6047 
6048 /**
6049  * @brief  Set scan period function
6050  *
6051  * @param priv      A pointer to moal_private structure
6052  * @param buf       A pointer to scan command buf
6053  * @param length    buf length
6054  *
6055  * @return          MLAN_STATUS_SUCCESS -- success, otherwise fail
6056  */
6057 int
woal_set_scan_cfg(moal_private * priv,char * buf,int length)6058 woal_set_scan_cfg(moal_private *priv, char *buf, int length)
6059 {
6060 	mlan_status ret = MLAN_STATUS_SUCCESS;
6061 	t_u8 *ptr = buf + NL80211_SCANCFG_HEADER_SIZE;
6062 	int buf_left = length - NL80211_SCANCFG_HEADER_SIZE;
6063 	t_u16 active_scan_time = 0;
6064 	t_u16 passive_scan_time = 0;
6065 	t_u16 specific_scan_time = 0;
6066 
6067 	ENTER();
6068 	while (buf_left >= 2) {
6069 		switch (*ptr) {
6070 		case NL80211_SCANCFG_ACTV_DWELL_SECTION:
6071 			if (buf_left < 3) {
6072 				PRINTM(MERROR,
6073 				       "Invalid ACTV_DWELL_SECTION, buf_left=%d\n",
6074 				       buf_left);
6075 				buf_left = 0;
6076 				break;
6077 			}
6078 			active_scan_time = ptr[2] << 8 | ptr[1];
6079 			ptr += 3;
6080 			buf_left -= 3;
6081 			break;
6082 		case NL80211_SCANCFG_PASV_DWELL_SECTION:
6083 			if (buf_left < 3) {
6084 				PRINTM(MERROR,
6085 				       "Invalid PASV_DWELL_SECTION, buf_left=%d\n",
6086 				       buf_left);
6087 				buf_left = 0;
6088 				break;
6089 			}
6090 			passive_scan_time = ptr[2] << 8 | ptr[1];
6091 			ptr += 3;
6092 			buf_left -= 3;
6093 			break;
6094 		case NL80211_SCANCFG_SPCF_DWELL_SECTION:
6095 			if (buf_left < 3) {
6096 				PRINTM(MERROR,
6097 				       "Invalid SPCF_DWELL_SECTION, buf_left=%d\n",
6098 				       buf_left);
6099 				buf_left = 0;
6100 				break;
6101 			}
6102 			specific_scan_time = ptr[2] << 8 | ptr[1];
6103 			ptr += 3;
6104 			buf_left -= 3;
6105 			break;
6106 		default:
6107 			buf_left = 0;
6108 			break;
6109 		}
6110 	}
6111 
6112 	if (active_scan_time || passive_scan_time || specific_scan_time) {
6113 		PRINTM(MIOCTL,
6114 		       "Set active_scan_time= %d passive_scan_time=%d specific_scan_time=%d\n",
6115 		       active_scan_time, passive_scan_time, specific_scan_time);
6116 		if (MLAN_STATUS_FAILURE ==
6117 		    woal_set_scan_time(priv, active_scan_time,
6118 				       passive_scan_time, specific_scan_time)) {
6119 			ret = -EFAULT;
6120 		}
6121 	}
6122 
6123 	LEAVE();
6124 	return ret;
6125 }
6126 
6127 /**
6128  *  @brief Set Radio On/OFF
6129  *
6130  *  @param priv                 A pointer to moal_private structure
6131  *  @param option               Radio Option
6132  *
6133  *  @return                     0 --success, otherwise fail
6134  */
6135 int
woal_set_radio(moal_private * priv,t_u8 option)6136 woal_set_radio(moal_private *priv, t_u8 option)
6137 {
6138 	int ret = 0;
6139 	mlan_ds_radio_cfg *radio = NULL;
6140 	mlan_ioctl_req *req = NULL;
6141 	mlan_status status = MLAN_STATUS_SUCCESS;
6142 	ENTER();
6143 	if ((option != 0) && (option != 1)) {
6144 		ret = -EINVAL;
6145 		goto done;
6146 	}
6147 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
6148 	if (req == NULL) {
6149 		ret = -ENOMEM;
6150 		goto done;
6151 	}
6152 	radio = (mlan_ds_radio_cfg *)req->pbuf;
6153 	radio->sub_command = MLAN_OID_RADIO_CTRL;
6154 	req->req_id = MLAN_IOCTL_RADIO_CFG;
6155 	req->action = MLAN_ACT_SET;
6156 	radio->param.radio_on_off = option;
6157 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6158 	if (status != MLAN_STATUS_SUCCESS)
6159 		ret = -EFAULT;
6160 
6161 done:
6162 	if (status != MLAN_STATUS_PENDING)
6163 		kfree(req);
6164 	LEAVE();
6165 	return ret;
6166 }
6167 
6168 #endif /* STA_SUPPORT */
6169 
6170 /**
6171  * @brief Set/Get configure multi-channel policy
6172  *
6173  * @param priv		A pointer to moal_private structure
6174  * @param enable	A pointer to enable
6175  * @param wait_option	wait_option of ioctl
6176  * @param action	action of ioctl
6177  *
6178  * @return          MLAN_STATUS_SUCCESS -- success, otherwise fail
6179  */
6180 mlan_status
woal_mc_policy_cfg(moal_private * priv,t_u16 * enable,t_u8 wait_option,t_u8 action)6181 woal_mc_policy_cfg(moal_private *priv, t_u16 *enable,
6182 		   t_u8 wait_option, t_u8 action)
6183 {
6184 	mlan_ioctl_req *req = NULL;
6185 	mlan_ds_misc_cfg *cfg = NULL;
6186 	mlan_status status = MLAN_STATUS_SUCCESS;
6187 
6188 	ENTER();
6189 
6190 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
6191 	if (req == NULL) {
6192 		status = MLAN_STATUS_FAILURE;
6193 		goto done;
6194 	}
6195 
6196 	cfg = (mlan_ds_misc_cfg *)req->pbuf;
6197 	cfg->sub_command = MLAN_OID_MISC_MULTI_CHAN_POLICY;
6198 	req->req_id = MLAN_IOCTL_MISC_CFG;
6199 	req->action = action;
6200 	if (MLAN_ACT_SET == action)
6201 		cfg->param.multi_chan_policy = *enable;
6202 	status = woal_request_ioctl(priv, req, wait_option);
6203 	if (status != MLAN_STATUS_SUCCESS)
6204 		goto done;
6205 	if (MLAN_ACT_GET == action)
6206 		*enable = cfg->param.multi_chan_policy;
6207 
6208 done:
6209 	if (status != MLAN_STATUS_PENDING)
6210 		kfree(req);
6211 	LEAVE();
6212 	return status;
6213 }
6214 
6215 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
6216 /**
6217  * @brief               Set/Get network monitor configurations
6218  *
6219  * @param priv          Pointer to moal_private structure
6220  * @param wait_option  wait option
6221  * @param enable	    Enable/Disable
6222  * @param filter	    Filter flag - Management/Control/Data
6223  * @param band_chan_cfg           Network monitor band channel config
6224  *
6225  * @return             MLAN_STATUS_SUCCESS -- success, otherwise fail
6226  */
6227 mlan_status
woal_set_net_monitor(moal_private * priv,t_u8 wait_option,t_u8 enable,t_u8 filter,netmon_band_chan_cfg * band_chan_cfg)6228 woal_set_net_monitor(moal_private *priv, t_u8 wait_option,
6229 		     t_u8 enable, t_u8 filter,
6230 		     netmon_band_chan_cfg * band_chan_cfg)
6231 {
6232 	mlan_status ret = MLAN_STATUS_SUCCESS;
6233 	mlan_ioctl_req *req = NULL;
6234 	mlan_ds_misc_cfg *misc = NULL;
6235 	mlan_ds_misc_net_monitor *net_mon = NULL;
6236 	mlan_status status = MLAN_STATUS_SUCCESS;
6237 
6238 	ENTER();
6239 
6240 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
6241 	if (req == NULL) {
6242 		ret = MLAN_STATUS_FAILURE;
6243 		goto done;
6244 	}
6245 	misc = (mlan_ds_misc_cfg *)req->pbuf;
6246 	net_mon = (mlan_ds_misc_net_monitor *)&misc->param.net_mon;
6247 	misc->sub_command = MLAN_OID_MISC_NET_MONITOR;
6248 	req->req_id = MLAN_IOCTL_MISC_CFG;
6249 	req->action = MLAN_ACT_SET;
6250 	net_mon->enable_net_mon = enable;
6251 	if (net_mon->enable_net_mon) {
6252 		net_mon->filter_flag = filter;
6253 		if (net_mon->enable_net_mon == CHANNEL_SPEC_SNIFFER_MODE) {
6254 			net_mon->band = band_chan_cfg->band;
6255 			net_mon->channel = band_chan_cfg->channel;
6256 			net_mon->chan_bandwidth = band_chan_cfg->chan_bandwidth;
6257 		}
6258 	}
6259 
6260 	status = woal_request_ioctl(priv, req, wait_option);
6261 	if (status != MLAN_STATUS_SUCCESS) {
6262 		ret = MLAN_STATUS_FAILURE;
6263 		goto done;
6264 	}
6265 
6266 done:
6267 	if (status != MLAN_STATUS_PENDING)
6268 		kfree(req);
6269 
6270 	LEAVE();
6271 	return ret;
6272 }
6273 #endif
6274 
6275 /**
6276  *  @brief Send delelte all BA command to MLAN
6277  *
6278  *  @param priv          A pointer to moal_private structure
6279  *  @param wait_option          Wait option
6280  *
6281  *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
6282  */
6283 mlan_status
woal_delba_all(moal_private * priv,t_u8 wait_option)6284 woal_delba_all(moal_private *priv, t_u8 wait_option)
6285 {
6286 	mlan_ioctl_req *req = NULL;
6287 	mlan_ds_11n_cfg *cfg_11n = NULL;
6288 	mlan_ds_11n_delba *del_ba = NULL;
6289 	t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0 };
6290 	mlan_status status = MLAN_STATUS_SUCCESS;
6291 	int ret = 0;
6292 
6293 	req = (mlan_ioctl_req *)
6294 		woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
6295 	if (req == NULL) {
6296 		ret = -ENOMEM;
6297 		goto done;
6298 	}
6299 	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
6300 	req->req_id = MLAN_IOCTL_11N_CFG;
6301 	cfg_11n->sub_command = MLAN_OID_11N_CFG_DELBA;
6302 
6303 	del_ba = &cfg_11n->param.del_ba;
6304 	memset(del_ba, 0, sizeof(mlan_ds_11n_delba));
6305 	del_ba->direction = DELBA_RX | DELBA_TX;
6306 	del_ba->tid = DELBA_ALL_TIDS;
6307 	memcpy(del_ba->peer_mac_addr, zero_mac, ETH_ALEN);
6308 
6309 	status = woal_request_ioctl(priv, req, wait_option);
6310 
6311 	if (status != MLAN_STATUS_SUCCESS) {
6312 		ret = -EFAULT;
6313 		goto done;
6314 	}
6315 
6316 done:
6317 	if (status != MLAN_STATUS_PENDING)
6318 		kfree(req);
6319 	LEAVE();
6320 	return ret;
6321 }
6322 
6323 /**
6324  *  @brief Send 11d enable/disable command to firmware.
6325  *
6326  *  @param priv             A pointer to moal_private structure
6327  *  @param wait_option      Wait option
6328  *  @param enable           Enable/Disable 11d
6329  *
6330  *  @return                 MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail
6331  */
6332 mlan_status
woal_set_11d(moal_private * priv,t_u8 wait_option,t_u8 enable)6333 woal_set_11d(moal_private *priv, t_u8 wait_option, t_u8 enable)
6334 {
6335 	mlan_ioctl_req *req = NULL;
6336 	mlan_ds_snmp_mib *snmp = NULL;
6337 	mlan_status ret = MLAN_STATUS_SUCCESS;
6338 
6339 	ENTER();
6340 
6341 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib));
6342 	if (req == NULL) {
6343 		LEAVE();
6344 		return -ENOMEM;
6345 	}
6346 
6347 	req->action = MLAN_ACT_SET;
6348 	req->req_id = MLAN_IOCTL_SNMP_MIB;
6349 
6350 	snmp = (mlan_ds_snmp_mib *)req->pbuf;
6351 	snmp->sub_command = MLAN_OID_SNMP_MIB_DOT11D;
6352 	snmp->param.oid_value = enable;
6353 
6354 	ret = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6355 	if (ret != MLAN_STATUS_PENDING)
6356 		kfree(req);
6357 
6358 	LEAVE();
6359 	return ret;
6360 }
6361 
6362 /**
6363  *  @brief Handle miscellaneous ioctls for asynchronous command response
6364  *
6365  *  @param priv     Pointer to moal_private structure
6366  *  @param info     Pointer to mlan_ds_misc_cfg structure
6367  *
6368  *  @return         N/A
6369  */
6370 void
woal_ioctl_get_misc_conf(moal_private * priv,mlan_ds_misc_cfg * info)6371 woal_ioctl_get_misc_conf(moal_private *priv, mlan_ds_misc_cfg *info)
6372 {
6373 	char event[1000];
6374 	mlan_ds_host_clock *host_clock = NULL;
6375 	ENTER();
6376 	switch (info->sub_command) {
6377 	case MLAN_OID_MISC_GET_CORRELATED_TIME:
6378 		host_clock = &info->param.host_clock;
6379 		memset(event, 0, sizeof(event));
6380 		sprintf(event, "%s %llu %llu", CUS_EVT_GET_CORRELATED_TIME,
6381 			host_clock->time, host_clock->fw_time);
6382 		woal_broadcast_event(priv, event, strlen(event));
6383 		PRINTM(MERROR, "CMD = %s\n", event);
6384 	default:
6385 		break;
6386 	}
6387 }
6388 
6389 module_param(disconnect_on_suspend, int, 0);
6390 MODULE_PARM_DESC(disconnect_on_suspend,
6391 		 "1: Enable disconnect wifi on suspend; 0: Disable disconnect wifi on suspend");
6392