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