xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlinux/moal_priv.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /** @file  moal_priv.c
2*4882a593Smuzhiyun  *
3*4882a593Smuzhiyun  * @brief This file contains standard ioctl functions
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Copyright 2008-2021 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/30/2008: initial version
26*4882a593Smuzhiyun ************************************************************************/
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #include "moal_main.h"
29*4882a593Smuzhiyun #ifdef SDIO
30*4882a593Smuzhiyun #include "moal_sdio.h"
31*4882a593Smuzhiyun #endif /* SDIO */
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #include "moal_eth_ioctl.h"
34*4882a593Smuzhiyun #ifdef USB
35*4882a593Smuzhiyun #include "moal_usb.h"
36*4882a593Smuzhiyun #endif
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun /********************************************************
39*4882a593Smuzhiyun 			Local Variables
40*4882a593Smuzhiyun ********************************************************/
41*4882a593Smuzhiyun /** Bands supported in Infra mode */
42*4882a593Smuzhiyun static t_u8 SupportedInfraBand[] = {
43*4882a593Smuzhiyun 	BAND_B,
44*4882a593Smuzhiyun 	BAND_B | BAND_G,
45*4882a593Smuzhiyun 	BAND_G,
46*4882a593Smuzhiyun 	BAND_GN,
47*4882a593Smuzhiyun 	BAND_B | BAND_G | BAND_GN,
48*4882a593Smuzhiyun 	BAND_G | BAND_GN,
49*4882a593Smuzhiyun 	BAND_A,
50*4882a593Smuzhiyun 	BAND_B | BAND_A,
51*4882a593Smuzhiyun 	BAND_B | BAND_G | BAND_A,
52*4882a593Smuzhiyun 	BAND_G | BAND_A,
53*4882a593Smuzhiyun 	BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN,
54*4882a593Smuzhiyun 	BAND_A | BAND_G | BAND_AN | BAND_GN,
55*4882a593Smuzhiyun 	BAND_A | BAND_AN,
56*4882a593Smuzhiyun 	BAND_GN | BAND_GAC,
57*4882a593Smuzhiyun 	BAND_B | BAND_G | BAND_GN | BAND_GAC,
58*4882a593Smuzhiyun 	BAND_G | BAND_GN | BAND_GAC,
59*4882a593Smuzhiyun 	BAND_A | BAND_B | BAND_G | BAND_AN | BAND_GN | BAND_AAC,
60*4882a593Smuzhiyun 	BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC,
61*4882a593Smuzhiyun 	BAND_A | BAND_AN | BAND_AAC,
62*4882a593Smuzhiyun };
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun /** Bands supported in Ad-Hoc mode */
65*4882a593Smuzhiyun static t_u8 SupportedAdhocBand[] = {
66*4882a593Smuzhiyun 	BAND_B,
67*4882a593Smuzhiyun 	BAND_B | BAND_G,
68*4882a593Smuzhiyun 	BAND_G,
69*4882a593Smuzhiyun 	BAND_A,
70*4882a593Smuzhiyun };
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun /********************************************************
73*4882a593Smuzhiyun 			Local Functions
74*4882a593Smuzhiyun ********************************************************/
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun /**
77*4882a593Smuzhiyun  * @brief Associated to a specific indexed entry in the ScanTable
78*4882a593Smuzhiyun  *
79*4882a593Smuzhiyun  * @param priv         A pointer to moal_private structure
80*4882a593Smuzhiyun  * @param req          A pointer to ifreq structure
81*4882a593Smuzhiyun  *
82*4882a593Smuzhiyun  * @return             0 --success, otherwise fail
83*4882a593Smuzhiyun  */
woal_associate_ssid_bssid(moal_private * priv,struct iwreq * wrq)84*4882a593Smuzhiyun static int woal_associate_ssid_bssid(moal_private *priv, struct iwreq *wrq)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	mlan_ssid_bssid ssid_bssid;
87*4882a593Smuzhiyun #ifdef REASSOCIATION
88*4882a593Smuzhiyun 	mlan_bss_info bss_info;
89*4882a593Smuzhiyun #endif
90*4882a593Smuzhiyun 	char buf[64];
91*4882a593Smuzhiyun 	t_u8 buflen;
92*4882a593Smuzhiyun 	t_u8 mac_idx;
93*4882a593Smuzhiyun 	t_u8 i;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	ENTER();
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	memset(&ssid_bssid, 0, sizeof(ssid_bssid));
98*4882a593Smuzhiyun 	mac_idx = 0;
99*4882a593Smuzhiyun 	buflen = MIN(wrq->u.data.length, (sizeof(buf) - 1));
100*4882a593Smuzhiyun 	memset(buf, 0, sizeof(buf));
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	if (buflen < (3 * ETH_ALEN) + 2) {
103*4882a593Smuzhiyun 		PRINTM(MERROR,
104*4882a593Smuzhiyun 		       "Associate: Insufficient length in IOCTL input\n");
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 		/* buffer should be at least 3 characters per BSSID octet "00:"
107*4882a593Smuzhiyun 		**   plus a space separater and at least 1 char in the SSID
108*4882a593Smuzhiyun 		*/
109*4882a593Smuzhiyun 		LEAVE();
110*4882a593Smuzhiyun 		return -EINVAL;
111*4882a593Smuzhiyun 	}
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	if (copy_from_user(buf, wrq->u.data.pointer, buflen) != 0) {
114*4882a593Smuzhiyun 		/* copy_from_user failed  */
115*4882a593Smuzhiyun 		PRINTM(MERROR, "Associate: copy from user failed\n");
116*4882a593Smuzhiyun 		LEAVE();
117*4882a593Smuzhiyun 		return -EINVAL;
118*4882a593Smuzhiyun 	}
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	for (i = 0; (i < buflen) && (buf[i] == ' '); i++) {
121*4882a593Smuzhiyun 		/* Skip white space */
122*4882a593Smuzhiyun 	}
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	/* Copy/Convert the BSSID */
125*4882a593Smuzhiyun 	for (; (i < buflen) && (mac_idx < ETH_ALEN) && (buf[i] != ' '); i++) {
126*4882a593Smuzhiyun 		if (buf[i] == ':') {
127*4882a593Smuzhiyun 			mac_idx++;
128*4882a593Smuzhiyun 		} else {
129*4882a593Smuzhiyun 			if (mac_idx < ETH_ALEN)
130*4882a593Smuzhiyun 				ssid_bssid.bssid[mac_idx] =
131*4882a593Smuzhiyun 					(t_u8)woal_atox(buf + i);
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 			while ((i < buflen) && (isxdigit(buf[i + 1]))) {
134*4882a593Smuzhiyun 				/* Skip entire hex value */
135*4882a593Smuzhiyun 				i++;
136*4882a593Smuzhiyun 			}
137*4882a593Smuzhiyun 		}
138*4882a593Smuzhiyun 	}
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	/* Skip one space between the BSSID and start of the SSID */
141*4882a593Smuzhiyun 	i++;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	/* Copy the SSID */
144*4882a593Smuzhiyun 	ssid_bssid.ssid.ssid_len = buflen - i - 1;
145*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle, ssid_bssid.ssid.ssid, buf + i,
146*4882a593Smuzhiyun 			sizeof(ssid_bssid.ssid.ssid),
147*4882a593Smuzhiyun 			sizeof(ssid_bssid.ssid.ssid));
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	PRINTM(MCMND, "iwpriv assoc: AP=[" MACSTR "], ssid(%d)=[%s]\n",
150*4882a593Smuzhiyun 	       MAC2STR(ssid_bssid.bssid), (int)ssid_bssid.ssid.ssid_len,
151*4882a593Smuzhiyun 	       ssid_bssid.ssid.ssid);
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
154*4882a593Smuzhiyun 	    woal_bss_start(priv, MOAL_IOCTL_WAIT, &ssid_bssid)) {
155*4882a593Smuzhiyun 		LEAVE();
156*4882a593Smuzhiyun 		return -EFAULT;
157*4882a593Smuzhiyun 	}
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun #ifdef REASSOCIATION
160*4882a593Smuzhiyun 	memset(&bss_info, 0x00, sizeof(bss_info));
161*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS ==
162*4882a593Smuzhiyun 	    woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
163*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.ssid,
164*4882a593Smuzhiyun 				&bss_info.ssid, sizeof(mlan_802_11_ssid),
165*4882a593Smuzhiyun 				sizeof(mlan_802_11_ssid));
166*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.bssid,
167*4882a593Smuzhiyun 				&bss_info.bssid, MLAN_MAC_ADDR_LENGTH,
168*4882a593Smuzhiyun 				sizeof(mlan_802_11_mac_addr));
169*4882a593Smuzhiyun 	}
170*4882a593Smuzhiyun #endif /* REASSOCIATION */
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	LEAVE();
173*4882a593Smuzhiyun 	return 0;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun /**
177*4882a593Smuzhiyun  *  @brief Copy Rates
178*4882a593Smuzhiyun  *
179*4882a593Smuzhiyun  *  @param dest    A pointer to destination buffer
180*4882a593Smuzhiyun  *  @param pos     The position for copy
181*4882a593Smuzhiyun  *  @param src     A pointer to source buffer
182*4882a593Smuzhiyun  *  @param len     Length of the source buffer
183*4882a593Smuzhiyun  *
184*4882a593Smuzhiyun  *  @return        Number of rates copied
185*4882a593Smuzhiyun  */
woal_copy_rates(t_u8 * dest,int pos,t_u8 * src,int len)186*4882a593Smuzhiyun static inline int woal_copy_rates(t_u8 *dest, int pos, t_u8 *src, int len)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	int i;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	for (i = 0; i < len && src[i]; i++, pos++) {
191*4882a593Smuzhiyun 		if (pos >= MLAN_SUPPORTED_RATES)
192*4882a593Smuzhiyun 			break;
193*4882a593Smuzhiyun 		dest[pos] = src[i];
194*4882a593Smuzhiyun 	}
195*4882a593Smuzhiyun 	return pos;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun /**
199*4882a593Smuzhiyun  *  @brief Performs warm reset
200*4882a593Smuzhiyun  *
201*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
202*4882a593Smuzhiyun  *
203*4882a593Smuzhiyun  *  @return             0/MLAN_STATUS_SUCCESS --success, otherwise fail
204*4882a593Smuzhiyun  */
woal_warm_reset(moal_private * priv)205*4882a593Smuzhiyun static int woal_warm_reset(moal_private *priv)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun 	int ret = 0;
208*4882a593Smuzhiyun 	moal_handle *handle = priv->phandle;
209*4882a593Smuzhiyun 	moal_handle *ref_handle;
210*4882a593Smuzhiyun 	moal_private *ref_priv;
211*4882a593Smuzhiyun 	ENTER();
212*4882a593Smuzhiyun 	ret = woal_pre_warmreset(priv);
213*4882a593Smuzhiyun 	if (ret)
214*4882a593Smuzhiyun 		goto done;
215*4882a593Smuzhiyun 	ref_handle = (moal_handle *)handle->pref_mac;
216*4882a593Smuzhiyun 	if (ref_handle) {
217*4882a593Smuzhiyun 		ref_priv = woal_get_priv(ref_handle, MLAN_BSS_ROLE_ANY);
218*4882a593Smuzhiyun 		if (ref_priv) {
219*4882a593Smuzhiyun 			ret = woal_pre_warmreset(ref_priv);
220*4882a593Smuzhiyun 			if (ret)
221*4882a593Smuzhiyun 				goto done;
222*4882a593Smuzhiyun 			ret = woal_warmreset(ref_priv);
223*4882a593Smuzhiyun 			if (ret)
224*4882a593Smuzhiyun 				goto done;
225*4882a593Smuzhiyun 		}
226*4882a593Smuzhiyun 	}
227*4882a593Smuzhiyun 	ret = woal_warmreset(priv);
228*4882a593Smuzhiyun done:
229*4882a593Smuzhiyun 	LEAVE();
230*4882a593Smuzhiyun 	return ret;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun /**
234*4882a593Smuzhiyun  *  @brief Get signal
235*4882a593Smuzhiyun  *
236*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
237*4882a593Smuzhiyun  *  @param wrq          A pointer to iwreq structure
238*4882a593Smuzhiyun  *
239*4882a593Smuzhiyun  *  @return             0 --success, otherwise fail
240*4882a593Smuzhiyun  */
woal_get_signal(moal_private * priv,struct iwreq * wrq)241*4882a593Smuzhiyun static int woal_get_signal(moal_private *priv, struct iwreq *wrq)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun /** Input data size */
244*4882a593Smuzhiyun #define IN_DATA_SIZE 2
245*4882a593Smuzhiyun /** Output data size */
246*4882a593Smuzhiyun #define OUT_DATA_SIZE 12
247*4882a593Smuzhiyun 	int ret = 0;
248*4882a593Smuzhiyun 	int in_data[IN_DATA_SIZE];
249*4882a593Smuzhiyun 	int out_data[OUT_DATA_SIZE];
250*4882a593Smuzhiyun 	mlan_ds_get_signal signal;
251*4882a593Smuzhiyun 	int data_length = 0;
252*4882a593Smuzhiyun 	int buflen = 0;
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	ENTER();
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	memset(in_data, 0, sizeof(in_data));
257*4882a593Smuzhiyun 	memset(out_data, 0, sizeof(out_data));
258*4882a593Smuzhiyun 	buflen = MIN(wrq->u.data.length, IN_DATA_SIZE);
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	if (priv->media_connected == MFALSE) {
261*4882a593Smuzhiyun 		PRINTM(MERROR, "Can not get RSSI in disconnected state\n");
262*4882a593Smuzhiyun 		ret = -ENOTSUPP;
263*4882a593Smuzhiyun 		goto done;
264*4882a593Smuzhiyun 	}
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	if (wrq->u.data.length) {
267*4882a593Smuzhiyun 		if (sizeof(int) * wrq->u.data.length > sizeof(in_data)) {
268*4882a593Smuzhiyun 			PRINTM(MERROR, "Too many arguments\n");
269*4882a593Smuzhiyun 			ret = -EINVAL;
270*4882a593Smuzhiyun 			goto done;
271*4882a593Smuzhiyun 		}
272*4882a593Smuzhiyun 		if (copy_from_user(in_data, wrq->u.data.pointer,
273*4882a593Smuzhiyun 				   sizeof(int) * buflen)) {
274*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
275*4882a593Smuzhiyun 			ret = -EFAULT;
276*4882a593Smuzhiyun 			goto done;
277*4882a593Smuzhiyun 		}
278*4882a593Smuzhiyun 	}
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	switch (wrq->u.data.length) {
281*4882a593Smuzhiyun 	case 0: /* No checking, get everything */
282*4882a593Smuzhiyun 		break;
283*4882a593Smuzhiyun 	case 2: /* Check subtype range */
284*4882a593Smuzhiyun 		if (in_data[1] < 1 || in_data[1] > 4) {
285*4882a593Smuzhiyun 			ret = -EINVAL;
286*4882a593Smuzhiyun 			goto done;
287*4882a593Smuzhiyun 		}
288*4882a593Smuzhiyun 		/* Fall through */
289*4882a593Smuzhiyun 	case 1: /* Check type range */
290*4882a593Smuzhiyun 		if (in_data[0] < 1 || in_data[0] > 3) {
291*4882a593Smuzhiyun 			ret = -EINVAL;
292*4882a593Smuzhiyun 			goto done;
293*4882a593Smuzhiyun 		}
294*4882a593Smuzhiyun 		break;
295*4882a593Smuzhiyun 	default:
296*4882a593Smuzhiyun 		ret = -EINVAL;
297*4882a593Smuzhiyun 		goto done;
298*4882a593Smuzhiyun 	}
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	memset(&signal, 0, sizeof(mlan_ds_get_signal));
301*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
302*4882a593Smuzhiyun 	    woal_get_signal_info(priv, MOAL_IOCTL_WAIT, &signal)) {
303*4882a593Smuzhiyun 		ret = -EFAULT;
304*4882a593Smuzhiyun 		goto done;
305*4882a593Smuzhiyun 	}
306*4882a593Smuzhiyun 	PRINTM(MINFO, "RSSI Beacon Last   : %d\n", (int)signal.bcn_rssi_last);
307*4882a593Smuzhiyun 	PRINTM(MINFO, "RSSI Beacon Average: %d\n", (int)signal.bcn_rssi_avg);
308*4882a593Smuzhiyun 	PRINTM(MINFO, "RSSI Data Last     : %d\n", (int)signal.data_rssi_last);
309*4882a593Smuzhiyun 	PRINTM(MINFO, "RSSI Data Average  : %d\n", (int)signal.data_rssi_avg);
310*4882a593Smuzhiyun 	PRINTM(MINFO, "SNR Beacon Last    : %d\n", (int)signal.bcn_snr_last);
311*4882a593Smuzhiyun 	PRINTM(MINFO, "SNR Beacon Average : %d\n", (int)signal.bcn_snr_avg);
312*4882a593Smuzhiyun 	PRINTM(MINFO, "SNR Data Last      : %d\n", (int)signal.data_snr_last);
313*4882a593Smuzhiyun 	PRINTM(MINFO, "SNR Data Average   : %d\n", (int)signal.data_snr_avg);
314*4882a593Smuzhiyun 	PRINTM(MINFO, "NF Beacon Last     : %d\n", (int)signal.bcn_nf_last);
315*4882a593Smuzhiyun 	PRINTM(MINFO, "NF Beacon Average  : %d\n", (int)signal.bcn_nf_avg);
316*4882a593Smuzhiyun 	PRINTM(MINFO, "NF Data Last       : %d\n", (int)signal.data_nf_last);
317*4882a593Smuzhiyun 	PRINTM(MINFO, "NF Data Average    : %d\n", (int)signal.data_nf_avg);
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	/* Check type */
320*4882a593Smuzhiyun 	switch (in_data[0]) {
321*4882a593Smuzhiyun 	case 0: /* Send everything */
322*4882a593Smuzhiyun 		out_data[data_length++] = signal.bcn_rssi_last;
323*4882a593Smuzhiyun 		out_data[data_length++] = signal.bcn_rssi_avg;
324*4882a593Smuzhiyun 		out_data[data_length++] = signal.data_rssi_last;
325*4882a593Smuzhiyun 		out_data[data_length++] = signal.data_rssi_avg;
326*4882a593Smuzhiyun 		out_data[data_length++] = signal.bcn_snr_last;
327*4882a593Smuzhiyun 		out_data[data_length++] = signal.bcn_snr_avg;
328*4882a593Smuzhiyun 		out_data[data_length++] = signal.data_snr_last;
329*4882a593Smuzhiyun 		out_data[data_length++] = signal.data_snr_avg;
330*4882a593Smuzhiyun 		out_data[data_length++] = signal.bcn_nf_last;
331*4882a593Smuzhiyun 		out_data[data_length++] = signal.bcn_nf_avg;
332*4882a593Smuzhiyun 		out_data[data_length++] = signal.data_nf_last;
333*4882a593Smuzhiyun 		out_data[data_length++] = signal.data_nf_avg;
334*4882a593Smuzhiyun 		break;
335*4882a593Smuzhiyun 	case 1: /* RSSI */
336*4882a593Smuzhiyun 		/* Check subtype */
337*4882a593Smuzhiyun 		switch (in_data[1]) {
338*4882a593Smuzhiyun 		case 0: /* Everything */
339*4882a593Smuzhiyun 			out_data[data_length++] = signal.bcn_rssi_last;
340*4882a593Smuzhiyun 			out_data[data_length++] = signal.bcn_rssi_avg;
341*4882a593Smuzhiyun 			out_data[data_length++] = signal.data_rssi_last;
342*4882a593Smuzhiyun 			out_data[data_length++] = signal.data_rssi_avg;
343*4882a593Smuzhiyun 			break;
344*4882a593Smuzhiyun 		case 1: /* bcn last */
345*4882a593Smuzhiyun 			out_data[data_length++] = signal.bcn_rssi_last;
346*4882a593Smuzhiyun 			break;
347*4882a593Smuzhiyun 		case 2: /* bcn avg */
348*4882a593Smuzhiyun 			out_data[data_length++] = signal.bcn_rssi_avg;
349*4882a593Smuzhiyun 			break;
350*4882a593Smuzhiyun 		case 3: /* data last */
351*4882a593Smuzhiyun 			out_data[data_length++] = signal.data_rssi_last;
352*4882a593Smuzhiyun 			break;
353*4882a593Smuzhiyun 		case 4: /* data avg */
354*4882a593Smuzhiyun 			out_data[data_length++] = signal.data_rssi_avg;
355*4882a593Smuzhiyun 			break;
356*4882a593Smuzhiyun 		default:
357*4882a593Smuzhiyun 			break;
358*4882a593Smuzhiyun 		}
359*4882a593Smuzhiyun 		break;
360*4882a593Smuzhiyun 	case 2: /* SNR */
361*4882a593Smuzhiyun 		/* Check subtype */
362*4882a593Smuzhiyun 		switch (in_data[1]) {
363*4882a593Smuzhiyun 		case 0: /* Everything */
364*4882a593Smuzhiyun 			out_data[data_length++] = signal.bcn_snr_last;
365*4882a593Smuzhiyun 			out_data[data_length++] = signal.bcn_snr_avg;
366*4882a593Smuzhiyun 			out_data[data_length++] = signal.data_snr_last;
367*4882a593Smuzhiyun 			out_data[data_length++] = signal.data_snr_avg;
368*4882a593Smuzhiyun 			break;
369*4882a593Smuzhiyun 		case 1: /* bcn last */
370*4882a593Smuzhiyun 			out_data[data_length++] = signal.bcn_snr_last;
371*4882a593Smuzhiyun 			break;
372*4882a593Smuzhiyun 		case 2: /* bcn avg */
373*4882a593Smuzhiyun 			out_data[data_length++] = signal.bcn_snr_avg;
374*4882a593Smuzhiyun 			break;
375*4882a593Smuzhiyun 		case 3: /* data last */
376*4882a593Smuzhiyun 			out_data[data_length++] = signal.data_snr_last;
377*4882a593Smuzhiyun 			break;
378*4882a593Smuzhiyun 		case 4: /* data avg */
379*4882a593Smuzhiyun 			out_data[data_length++] = signal.data_snr_avg;
380*4882a593Smuzhiyun 			break;
381*4882a593Smuzhiyun 		default:
382*4882a593Smuzhiyun 			break;
383*4882a593Smuzhiyun 		}
384*4882a593Smuzhiyun 		break;
385*4882a593Smuzhiyun 	case 3: /* NF */
386*4882a593Smuzhiyun 		/* Check subtype */
387*4882a593Smuzhiyun 		switch (in_data[1]) {
388*4882a593Smuzhiyun 		case 0: /* Everything */
389*4882a593Smuzhiyun 			out_data[data_length++] = signal.bcn_nf_last;
390*4882a593Smuzhiyun 			out_data[data_length++] = signal.bcn_nf_avg;
391*4882a593Smuzhiyun 			out_data[data_length++] = signal.data_nf_last;
392*4882a593Smuzhiyun 			out_data[data_length++] = signal.data_nf_avg;
393*4882a593Smuzhiyun 			break;
394*4882a593Smuzhiyun 		case 1: /* bcn last */
395*4882a593Smuzhiyun 			out_data[data_length++] = signal.bcn_nf_last;
396*4882a593Smuzhiyun 			break;
397*4882a593Smuzhiyun 		case 2: /* bcn avg */
398*4882a593Smuzhiyun 			out_data[data_length++] = signal.bcn_nf_avg;
399*4882a593Smuzhiyun 			break;
400*4882a593Smuzhiyun 		case 3: /* data last */
401*4882a593Smuzhiyun 			out_data[data_length++] = signal.data_nf_last;
402*4882a593Smuzhiyun 			break;
403*4882a593Smuzhiyun 		case 4: /* data avg */
404*4882a593Smuzhiyun 			out_data[data_length++] = signal.data_nf_avg;
405*4882a593Smuzhiyun 			break;
406*4882a593Smuzhiyun 		default:
407*4882a593Smuzhiyun 			break;
408*4882a593Smuzhiyun 		}
409*4882a593Smuzhiyun 		break;
410*4882a593Smuzhiyun 	default:
411*4882a593Smuzhiyun 		break;
412*4882a593Smuzhiyun 	}
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	wrq->u.data.length = data_length;
415*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, out_data,
416*4882a593Smuzhiyun 			 wrq->u.data.length * sizeof(out_data[0]))) {
417*4882a593Smuzhiyun 		PRINTM(MERROR, "Copy to user failed\n");
418*4882a593Smuzhiyun 		ret = -EFAULT;
419*4882a593Smuzhiyun 		goto done;
420*4882a593Smuzhiyun 	}
421*4882a593Smuzhiyun done:
422*4882a593Smuzhiyun 	LEAVE();
423*4882a593Smuzhiyun 	return ret;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun /**
427*4882a593Smuzhiyun  *  @brief Get/Set DeepSleep mode
428*4882a593Smuzhiyun  *
429*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
430*4882a593Smuzhiyun  *  @param wreq	    A pointer to iwreq structure
431*4882a593Smuzhiyun  *
432*4882a593Smuzhiyun  *  @return          0 --success, otherwise fail
433*4882a593Smuzhiyun  */
woal_deep_sleep_ioctl(moal_private * priv,struct iwreq * wrq)434*4882a593Smuzhiyun static int woal_deep_sleep_ioctl(moal_private *priv, struct iwreq *wrq)
435*4882a593Smuzhiyun {
436*4882a593Smuzhiyun 	int ret = 0;
437*4882a593Smuzhiyun 	int user_data_len;
438*4882a593Smuzhiyun 	t_u32 deep_sleep = DEEP_SLEEP_OFF;
439*4882a593Smuzhiyun 	t_u32 data[2] = {0};
440*4882a593Smuzhiyun 	int copy_len;
441*4882a593Smuzhiyun 	t_u16 idletime = DEEP_SLEEP_IDLE_TIME;
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	ENTER();
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 	user_data_len = wrq->u.data.length;
446*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * user_data_len);
447*4882a593Smuzhiyun 	if (user_data_len == 1 || user_data_len == 2) {
448*4882a593Smuzhiyun 		if (copy_from_user(&data, wrq->u.data.pointer, copy_len)) {
449*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
450*4882a593Smuzhiyun 			LEAVE();
451*4882a593Smuzhiyun 			return -EFAULT;
452*4882a593Smuzhiyun 		}
453*4882a593Smuzhiyun 		deep_sleep = data[0];
454*4882a593Smuzhiyun 		if (deep_sleep == DEEP_SLEEP_OFF) {
455*4882a593Smuzhiyun 			PRINTM(MINFO, "Exit Deep Sleep Mode\n");
456*4882a593Smuzhiyun 			ret = woal_set_deep_sleep(priv, MOAL_IOCTL_WAIT, MFALSE,
457*4882a593Smuzhiyun 						  0);
458*4882a593Smuzhiyun 			if (ret != MLAN_STATUS_SUCCESS) {
459*4882a593Smuzhiyun 				LEAVE();
460*4882a593Smuzhiyun 				return -EINVAL;
461*4882a593Smuzhiyun 			}
462*4882a593Smuzhiyun 		} else if (deep_sleep == DEEP_SLEEP_ON) {
463*4882a593Smuzhiyun 			PRINTM(MINFO, "Enter Deep Sleep Mode\n");
464*4882a593Smuzhiyun 			if (user_data_len == 2)
465*4882a593Smuzhiyun 				idletime = data[1];
466*4882a593Smuzhiyun 			else
467*4882a593Smuzhiyun 				idletime = 0;
468*4882a593Smuzhiyun 			ret = woal_set_deep_sleep(priv, MOAL_IOCTL_WAIT, MTRUE,
469*4882a593Smuzhiyun 						  idletime);
470*4882a593Smuzhiyun 			if (ret != MLAN_STATUS_SUCCESS) {
471*4882a593Smuzhiyun 				LEAVE();
472*4882a593Smuzhiyun 				return -EINVAL;
473*4882a593Smuzhiyun 			}
474*4882a593Smuzhiyun 		} else {
475*4882a593Smuzhiyun 			PRINTM(MERROR, "Unknown option = %u\n", deep_sleep);
476*4882a593Smuzhiyun 			LEAVE();
477*4882a593Smuzhiyun 			return -EINVAL;
478*4882a593Smuzhiyun 		}
479*4882a593Smuzhiyun 	} else if (user_data_len > 2) {
480*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid number of arguments %d\n",
481*4882a593Smuzhiyun 		       user_data_len);
482*4882a593Smuzhiyun 		LEAVE();
483*4882a593Smuzhiyun 		return -EINVAL;
484*4882a593Smuzhiyun 	} else { /* Display Deep Sleep settings */
485*4882a593Smuzhiyun 		PRINTM(MINFO, "Get Deep Sleep Mode\n");
486*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS != woal_get_deep_sleep(priv, data)) {
487*4882a593Smuzhiyun 			LEAVE();
488*4882a593Smuzhiyun 			return -EFAULT;
489*4882a593Smuzhiyun 		}
490*4882a593Smuzhiyun 		if (data[0] == 0)
491*4882a593Smuzhiyun 			wrq->u.data.length = 1;
492*4882a593Smuzhiyun 		else
493*4882a593Smuzhiyun 			wrq->u.data.length = 2;
494*4882a593Smuzhiyun 	}
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	/* Copy the Deep Sleep setting to user */
497*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, data,
498*4882a593Smuzhiyun 			 wrq->u.data.length * sizeof(int))) {
499*4882a593Smuzhiyun 		PRINTM(MERROR, "Copy to user failed\n");
500*4882a593Smuzhiyun 		LEAVE();
501*4882a593Smuzhiyun 		return -EINVAL;
502*4882a593Smuzhiyun 	}
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 	LEAVE();
505*4882a593Smuzhiyun 	return 0;
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun /**
509*4882a593Smuzhiyun  *  @brief Set/Get Usr 11n configuration request
510*4882a593Smuzhiyun  *
511*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
512*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
513*4882a593Smuzhiyun  *
514*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
515*4882a593Smuzhiyun  */
woal_11n_htcap_cfg(moal_private * priv,struct iwreq * wrq)516*4882a593Smuzhiyun static int woal_11n_htcap_cfg(moal_private *priv, struct iwreq *wrq)
517*4882a593Smuzhiyun {
518*4882a593Smuzhiyun 	int data[2], copy_len;
519*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
520*4882a593Smuzhiyun 	mlan_ds_11n_cfg *cfg_11n = NULL;
521*4882a593Smuzhiyun 	int ret = 0;
522*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
523*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	ENTER();
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun 	if (data_length > 2) {
528*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid number of arguments\n");
529*4882a593Smuzhiyun 		ret = -EINVAL;
530*4882a593Smuzhiyun 		goto done;
531*4882a593Smuzhiyun 	}
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
534*4882a593Smuzhiyun 	if (req == NULL) {
535*4882a593Smuzhiyun 		ret = -ENOMEM;
536*4882a593Smuzhiyun 		goto done;
537*4882a593Smuzhiyun 	}
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
540*4882a593Smuzhiyun 	cfg_11n->sub_command = MLAN_OID_11N_HTCAP_CFG;
541*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_11N_CFG;
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
544*4882a593Smuzhiyun 	if (data_length == 0) {
545*4882a593Smuzhiyun 		/* Get 11n tx parameters from MLAN */
546*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
547*4882a593Smuzhiyun 		cfg_11n->param.htcap_cfg.misc_cfg = BAND_SELECT_BG;
548*4882a593Smuzhiyun 	} else {
549*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
550*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
551*4882a593Smuzhiyun 			ret = -EFAULT;
552*4882a593Smuzhiyun 			goto done;
553*4882a593Smuzhiyun 		}
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 		cfg_11n->param.htcap_cfg.htcap = data[0];
556*4882a593Smuzhiyun 		PRINTM(MINFO, "SET: htcapinfo:0x%x\n", data[0]);
557*4882a593Smuzhiyun 		cfg_11n->param.htcap_cfg.misc_cfg = BAND_SELECT_BOTH;
558*4882a593Smuzhiyun 		if (data_length == 2) {
559*4882a593Smuzhiyun 			if (data[1] != BAND_SELECT_BG &&
560*4882a593Smuzhiyun 			    data[1] != BAND_SELECT_A &&
561*4882a593Smuzhiyun 			    data[1] != BAND_SELECT_BOTH) {
562*4882a593Smuzhiyun 				PRINTM(MERROR, "Invalid band selection\n");
563*4882a593Smuzhiyun 				ret = -EINVAL;
564*4882a593Smuzhiyun 				goto done;
565*4882a593Smuzhiyun 			}
566*4882a593Smuzhiyun 			cfg_11n->param.htcap_cfg.misc_cfg = data[1];
567*4882a593Smuzhiyun 			PRINTM(MINFO, "SET: htcapinfo band:0x%x\n", data[1]);
568*4882a593Smuzhiyun 		}
569*4882a593Smuzhiyun 		/* Update 11n tx parameters in MLAN */
570*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
571*4882a593Smuzhiyun 	}
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
574*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
575*4882a593Smuzhiyun 		ret = -EFAULT;
576*4882a593Smuzhiyun 		goto done;
577*4882a593Smuzhiyun 	}
578*4882a593Smuzhiyun 	data[0] = cfg_11n->param.htcap_cfg.htcap;
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun 	if (req->action == MLAN_ACT_GET) {
581*4882a593Smuzhiyun 		data_length = 1;
582*4882a593Smuzhiyun 		cfg_11n->param.htcap_cfg.htcap = 0;
583*4882a593Smuzhiyun 		cfg_11n->param.htcap_cfg.misc_cfg = BAND_SELECT_A;
584*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
585*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
586*4882a593Smuzhiyun 			ret = -EFAULT;
587*4882a593Smuzhiyun 			goto done;
588*4882a593Smuzhiyun 		}
589*4882a593Smuzhiyun 		if ((int)cfg_11n->param.htcap_cfg.htcap != data[0]) {
590*4882a593Smuzhiyun 			data_length = 2;
591*4882a593Smuzhiyun 			data[1] = cfg_11n->param.htcap_cfg.htcap;
592*4882a593Smuzhiyun 			PRINTM(MINFO, "GET: htcapinfo for 2.4GHz:0x%x\n",
593*4882a593Smuzhiyun 			       data[0]);
594*4882a593Smuzhiyun 			PRINTM(MINFO, "GET: htcapinfo for 5GHz:0x%x\n",
595*4882a593Smuzhiyun 			       data[1]);
596*4882a593Smuzhiyun 		} else
597*4882a593Smuzhiyun 			PRINTM(MINFO, "GET: htcapinfo:0x%x\n", data[0]);
598*4882a593Smuzhiyun 	}
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, data, sizeof(data))) {
601*4882a593Smuzhiyun 		PRINTM(MERROR, "Copy to user failed\n");
602*4882a593Smuzhiyun 		ret = -EFAULT;
603*4882a593Smuzhiyun 		goto done;
604*4882a593Smuzhiyun 	}
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	wrq->u.data.length = data_length;
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun done:
609*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
610*4882a593Smuzhiyun 		kfree(req);
611*4882a593Smuzhiyun 	LEAVE();
612*4882a593Smuzhiyun 	return ret;
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun /**
616*4882a593Smuzhiyun  *  @brief Enable/Disable amsdu_aggr_ctrl
617*4882a593Smuzhiyun  *
618*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
619*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
620*4882a593Smuzhiyun  *
621*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
622*4882a593Smuzhiyun  */
woal_11n_amsdu_aggr_ctrl(moal_private * priv,struct iwreq * wrq)623*4882a593Smuzhiyun static int woal_11n_amsdu_aggr_ctrl(moal_private *priv, struct iwreq *wrq)
624*4882a593Smuzhiyun {
625*4882a593Smuzhiyun 	int data[2], copy_len;
626*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
627*4882a593Smuzhiyun 	mlan_ds_11n_cfg *cfg_11n = NULL;
628*4882a593Smuzhiyun 	int ret = 0;
629*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
630*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun 	ENTER();
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 	if ((data_length != 0) && (data_length != 1)) {
635*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid number of arguments\n");
636*4882a593Smuzhiyun 		ret = -EINVAL;
637*4882a593Smuzhiyun 		goto done;
638*4882a593Smuzhiyun 	}
639*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
640*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
641*4882a593Smuzhiyun 	if (req == NULL) {
642*4882a593Smuzhiyun 		ret = -ENOMEM;
643*4882a593Smuzhiyun 		goto done;
644*4882a593Smuzhiyun 	}
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
647*4882a593Smuzhiyun 	cfg_11n->sub_command = MLAN_OID_11N_CFG_AMSDU_AGGR_CTRL;
648*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_11N_CFG;
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 	if (data_length == 0) {
651*4882a593Smuzhiyun 		/* Get 11n tx parameters from MLAN */
652*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
653*4882a593Smuzhiyun 	} else if (data_length == 1) {
654*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
655*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
656*4882a593Smuzhiyun 			ret = -EFAULT;
657*4882a593Smuzhiyun 			goto done;
658*4882a593Smuzhiyun 		}
659*4882a593Smuzhiyun 		cfg_11n->param.amsdu_aggr_ctrl.enable = data[0];
660*4882a593Smuzhiyun 		/* Update 11n tx parameters in MLAN */
661*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
662*4882a593Smuzhiyun 	}
663*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
664*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
665*4882a593Smuzhiyun 		ret = -EFAULT;
666*4882a593Smuzhiyun 		goto done;
667*4882a593Smuzhiyun 	}
668*4882a593Smuzhiyun 	data[0] = cfg_11n->param.amsdu_aggr_ctrl.enable;
669*4882a593Smuzhiyun 	data[1] = cfg_11n->param.amsdu_aggr_ctrl.curr_buf_size;
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, data, sizeof(data))) {
672*4882a593Smuzhiyun 		PRINTM(MERROR, "Copy to user failed\n");
673*4882a593Smuzhiyun 		ret = -EFAULT;
674*4882a593Smuzhiyun 		goto done;
675*4882a593Smuzhiyun 	}
676*4882a593Smuzhiyun 	wrq->u.data.length = 2;
677*4882a593Smuzhiyun done:
678*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
679*4882a593Smuzhiyun 		kfree(req);
680*4882a593Smuzhiyun 	LEAVE();
681*4882a593Smuzhiyun 	return ret;
682*4882a593Smuzhiyun }
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun /**
685*4882a593Smuzhiyun  *  @brief Set/Get 11n configuration request
686*4882a593Smuzhiyun  *
687*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
688*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
689*4882a593Smuzhiyun  *
690*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
691*4882a593Smuzhiyun  */
woal_11n_tx_cfg(moal_private * priv,struct iwreq * wrq)692*4882a593Smuzhiyun static int woal_11n_tx_cfg(moal_private *priv, struct iwreq *wrq)
693*4882a593Smuzhiyun {
694*4882a593Smuzhiyun 	int data[2], copy_len;
695*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
696*4882a593Smuzhiyun 	mlan_ds_11n_cfg *cfg_11n = NULL;
697*4882a593Smuzhiyun 	int ret = 0;
698*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
699*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	ENTER();
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun 	if (data_length > 2) {
704*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid number of arguments\n");
705*4882a593Smuzhiyun 		ret = -EINVAL;
706*4882a593Smuzhiyun 		goto done;
707*4882a593Smuzhiyun 	}
708*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
709*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
710*4882a593Smuzhiyun 	if (req == NULL) {
711*4882a593Smuzhiyun 		ret = -ENOMEM;
712*4882a593Smuzhiyun 		goto done;
713*4882a593Smuzhiyun 	}
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun 	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
716*4882a593Smuzhiyun 	cfg_11n->sub_command = MLAN_OID_11N_CFG_TX;
717*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_11N_CFG;
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun 	if (data_length == 0) {
720*4882a593Smuzhiyun 		/* Get 11n tx parameters from MLAN */
721*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
722*4882a593Smuzhiyun 		cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_BG;
723*4882a593Smuzhiyun 	} else {
724*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
725*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
726*4882a593Smuzhiyun 			ret = -EFAULT;
727*4882a593Smuzhiyun 			goto done;
728*4882a593Smuzhiyun 		}
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun 		cfg_11n->param.tx_cfg.httxcap = data[0];
731*4882a593Smuzhiyun 		PRINTM(MINFO, "SET: httxcap:0x%x\n", data[0]);
732*4882a593Smuzhiyun 		cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_BOTH;
733*4882a593Smuzhiyun 		if (data_length == 2) {
734*4882a593Smuzhiyun 			if (data[1] != BAND_SELECT_BG &&
735*4882a593Smuzhiyun 			    data[1] != BAND_SELECT_A &&
736*4882a593Smuzhiyun 			    data[1] != BAND_SELECT_BOTH) {
737*4882a593Smuzhiyun 				PRINTM(MERROR, "Invalid band selection\n");
738*4882a593Smuzhiyun 				ret = -EINVAL;
739*4882a593Smuzhiyun 				goto done;
740*4882a593Smuzhiyun 			}
741*4882a593Smuzhiyun 			cfg_11n->param.tx_cfg.misc_cfg = data[1];
742*4882a593Smuzhiyun 			PRINTM(MINFO, "SET: httxcap band:0x%x\n", data[1]);
743*4882a593Smuzhiyun 		}
744*4882a593Smuzhiyun 		/* Update 11n tx parameters in MLAN */
745*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
746*4882a593Smuzhiyun 	}
747*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
748*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
749*4882a593Smuzhiyun 		ret = -EFAULT;
750*4882a593Smuzhiyun 		goto done;
751*4882a593Smuzhiyun 	}
752*4882a593Smuzhiyun 	data[0] = cfg_11n->param.tx_cfg.httxcap;
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun 	if (req->action == MLAN_ACT_GET) {
755*4882a593Smuzhiyun 		data_length = 1;
756*4882a593Smuzhiyun 		cfg_11n->param.tx_cfg.httxcap = 0;
757*4882a593Smuzhiyun 		cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_A;
758*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
759*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
760*4882a593Smuzhiyun 			ret = -EFAULT;
761*4882a593Smuzhiyun 			goto done;
762*4882a593Smuzhiyun 		}
763*4882a593Smuzhiyun 		if (cfg_11n->param.tx_cfg.httxcap != data[0]) {
764*4882a593Smuzhiyun 			data_length = 2;
765*4882a593Smuzhiyun 			data[1] = cfg_11n->param.tx_cfg.httxcap;
766*4882a593Smuzhiyun 			PRINTM(MINFO, "GET: httxcap for 2.4GHz:0x%x\n",
767*4882a593Smuzhiyun 			       data[0]);
768*4882a593Smuzhiyun 			PRINTM(MINFO, "GET: httxcap for 5GHz:0x%x\n", data[1]);
769*4882a593Smuzhiyun 		} else
770*4882a593Smuzhiyun 			PRINTM(MINFO, "GET: httxcap:0x%x\n", data[0]);
771*4882a593Smuzhiyun 	}
772*4882a593Smuzhiyun 
773*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, data, sizeof(data))) {
774*4882a593Smuzhiyun 		PRINTM(MERROR, "Copy to user failed\n");
775*4882a593Smuzhiyun 		ret = -EFAULT;
776*4882a593Smuzhiyun 		goto done;
777*4882a593Smuzhiyun 	}
778*4882a593Smuzhiyun 	wrq->u.data.length = data_length;
779*4882a593Smuzhiyun 
780*4882a593Smuzhiyun done:
781*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
782*4882a593Smuzhiyun 		kfree(req);
783*4882a593Smuzhiyun 	LEAVE();
784*4882a593Smuzhiyun 	return ret;
785*4882a593Smuzhiyun }
786*4882a593Smuzhiyun 
787*4882a593Smuzhiyun /**
788*4882a593Smuzhiyun  *  @brief Enable/Disable TX Aggregation
789*4882a593Smuzhiyun  *
790*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
791*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
792*4882a593Smuzhiyun  *
793*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
794*4882a593Smuzhiyun  */
woal_11n_prio_tbl(moal_private * priv,struct iwreq * wrq)795*4882a593Smuzhiyun static int woal_11n_prio_tbl(moal_private *priv, struct iwreq *wrq)
796*4882a593Smuzhiyun {
797*4882a593Smuzhiyun 	int data[MAX_NUM_TID * 2], i, j, copy_len;
798*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
799*4882a593Smuzhiyun 	mlan_ds_11n_cfg *cfg_11n = NULL;
800*4882a593Smuzhiyun 	int ret = 0;
801*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
802*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun 	ENTER();
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun 	if (wrq->u.data.pointer == NULL) {
807*4882a593Smuzhiyun 		LEAVE();
808*4882a593Smuzhiyun 		return -EINVAL;
809*4882a593Smuzhiyun 	}
810*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
813*4882a593Smuzhiyun 	if (req == NULL) {
814*4882a593Smuzhiyun 		LEAVE();
815*4882a593Smuzhiyun 		return -ENOMEM;
816*4882a593Smuzhiyun 	}
817*4882a593Smuzhiyun 	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
818*4882a593Smuzhiyun 	cfg_11n->sub_command = MLAN_OID_11N_CFG_AGGR_PRIO_TBL;
819*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_11N_CFG;
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun 	if (data_length == 0) {
822*4882a593Smuzhiyun 		/* Get aggr priority table from MLAN */
823*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
824*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
825*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
826*4882a593Smuzhiyun 			ret = -EFAULT;
827*4882a593Smuzhiyun 			goto error;
828*4882a593Smuzhiyun 		}
829*4882a593Smuzhiyun 		wrq->u.data.length = MAX_NUM_TID * 2;
830*4882a593Smuzhiyun 		for (i = 0, j = 0; i < (wrq->u.data.length); i = i + 2, ++j) {
831*4882a593Smuzhiyun 			data[i] = cfg_11n->param.aggr_prio_tbl.ampdu[j];
832*4882a593Smuzhiyun 			data[i + 1] = cfg_11n->param.aggr_prio_tbl.amsdu[j];
833*4882a593Smuzhiyun 		}
834*4882a593Smuzhiyun 
835*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, data,
836*4882a593Smuzhiyun 				 sizeof(int) * wrq->u.data.length)) {
837*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
838*4882a593Smuzhiyun 			ret = -EFAULT;
839*4882a593Smuzhiyun 			goto error;
840*4882a593Smuzhiyun 		}
841*4882a593Smuzhiyun 	} else if (data_length == 16) {
842*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
843*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
844*4882a593Smuzhiyun 			ret = -EFAULT;
845*4882a593Smuzhiyun 			goto error;
846*4882a593Smuzhiyun 		}
847*4882a593Smuzhiyun 		for (i = 0, j = 0; i < (data_length); i = i + 2, ++j) {
848*4882a593Smuzhiyun 			if ((data[i] > 7 && data[i] != 0xff) ||
849*4882a593Smuzhiyun 			    (data[i + 1] > 7 && data[i + 1] != 0xff)) {
850*4882a593Smuzhiyun 				PRINTM(MERROR,
851*4882a593Smuzhiyun 				       "Invalid priority, valid value 0-7 or 0xff.\n");
852*4882a593Smuzhiyun 				ret = -EFAULT;
853*4882a593Smuzhiyun 				goto error;
854*4882a593Smuzhiyun 			}
855*4882a593Smuzhiyun 			cfg_11n->param.aggr_prio_tbl.ampdu[j] = data[i];
856*4882a593Smuzhiyun 			cfg_11n->param.aggr_prio_tbl.amsdu[j] = data[i + 1];
857*4882a593Smuzhiyun 		}
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun 		/* Update aggr priority table in MLAN */
860*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
861*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
862*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
863*4882a593Smuzhiyun 			ret = -EFAULT;
864*4882a593Smuzhiyun 			goto error;
865*4882a593Smuzhiyun 		}
866*4882a593Smuzhiyun 	} else {
867*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid number of arguments\n");
868*4882a593Smuzhiyun 		ret = -EINVAL;
869*4882a593Smuzhiyun 		goto error;
870*4882a593Smuzhiyun 	}
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun error:
873*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
874*4882a593Smuzhiyun 		kfree(req);
875*4882a593Smuzhiyun 	LEAVE();
876*4882a593Smuzhiyun 	return ret;
877*4882a593Smuzhiyun }
878*4882a593Smuzhiyun 
879*4882a593Smuzhiyun /**
880*4882a593Smuzhiyun  *  @brief Set/Get add BA Reject parameters
881*4882a593Smuzhiyun  *
882*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
883*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
884*4882a593Smuzhiyun  *
885*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
886*4882a593Smuzhiyun  */
woal_addba_reject(moal_private * priv,struct iwreq * wrq)887*4882a593Smuzhiyun static int woal_addba_reject(moal_private *priv, struct iwreq *wrq)
888*4882a593Smuzhiyun {
889*4882a593Smuzhiyun 	int data[MAX_NUM_TID], ret = 0, i, copy_len;
890*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
891*4882a593Smuzhiyun 	mlan_ds_11n_cfg *cfg_11n = NULL;
892*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
893*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
894*4882a593Smuzhiyun 	ENTER();
895*4882a593Smuzhiyun 
896*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
897*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
898*4882a593Smuzhiyun 	if (req == NULL) {
899*4882a593Smuzhiyun 		LEAVE();
900*4882a593Smuzhiyun 		return -ENOMEM;
901*4882a593Smuzhiyun 	}
902*4882a593Smuzhiyun 	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
903*4882a593Smuzhiyun 	cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_REJECT;
904*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_11N_CFG;
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 	if (data_length == 0) {
907*4882a593Smuzhiyun 		PRINTM(MERROR, "Addba reject moal\n");
908*4882a593Smuzhiyun 		/* Get aggr priority table from MLAN */
909*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
910*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
911*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
912*4882a593Smuzhiyun 			ret = -EFAULT;
913*4882a593Smuzhiyun 			goto error;
914*4882a593Smuzhiyun 		}
915*4882a593Smuzhiyun 
916*4882a593Smuzhiyun 		wrq->u.data.length = MAX_NUM_TID;
917*4882a593Smuzhiyun 		for (i = 0; i < (wrq->u.data.length); ++i)
918*4882a593Smuzhiyun 			data[i] = cfg_11n->param.addba_reject[i];
919*4882a593Smuzhiyun 
920*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, data,
921*4882a593Smuzhiyun 				 sizeof(int) * wrq->u.data.length)) {
922*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
923*4882a593Smuzhiyun 			ret = -EFAULT;
924*4882a593Smuzhiyun 			goto error;
925*4882a593Smuzhiyun 		}
926*4882a593Smuzhiyun 	} else if (data_length == 8) {
927*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
928*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
929*4882a593Smuzhiyun 			ret = -EFAULT;
930*4882a593Smuzhiyun 			goto error;
931*4882a593Smuzhiyun 		}
932*4882a593Smuzhiyun 		for (i = 0; i < (data_length); ++i) {
933*4882a593Smuzhiyun 			if (data[i] != 0 && data[i] != 1) {
934*4882a593Smuzhiyun 				PRINTM(MERROR,
935*4882a593Smuzhiyun 				       "addba reject only takes argument as 0 or 1\n");
936*4882a593Smuzhiyun 				ret = -EFAULT;
937*4882a593Smuzhiyun 				goto error;
938*4882a593Smuzhiyun 			}
939*4882a593Smuzhiyun 			cfg_11n->param.addba_reject[i] = data[i];
940*4882a593Smuzhiyun 		}
941*4882a593Smuzhiyun 
942*4882a593Smuzhiyun 		/* Update aggr priority table in MLAN */
943*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
944*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
945*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
946*4882a593Smuzhiyun 			ret = -EFAULT;
947*4882a593Smuzhiyun 			goto error;
948*4882a593Smuzhiyun 		}
949*4882a593Smuzhiyun 	} else {
950*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid number of arguments\n");
951*4882a593Smuzhiyun 		ret = -EINVAL;
952*4882a593Smuzhiyun 		goto error;
953*4882a593Smuzhiyun 	}
954*4882a593Smuzhiyun error:
955*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
956*4882a593Smuzhiyun 		kfree(req);
957*4882a593Smuzhiyun 	LEAVE();
958*4882a593Smuzhiyun 	return ret;
959*4882a593Smuzhiyun }
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun /**
962*4882a593Smuzhiyun  *  @brief Set/Get add BA parameters
963*4882a593Smuzhiyun  *
964*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
965*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
966*4882a593Smuzhiyun  *
967*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
968*4882a593Smuzhiyun  */
woal_addba_para_updt(moal_private * priv,struct iwreq * wrq)969*4882a593Smuzhiyun static int woal_addba_para_updt(moal_private *priv, struct iwreq *wrq)
970*4882a593Smuzhiyun {
971*4882a593Smuzhiyun 	int data[5], ret = 0, copy_len;
972*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
973*4882a593Smuzhiyun 	mlan_ds_11n_cfg *cfg_11n = NULL;
974*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
975*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
976*4882a593Smuzhiyun 
977*4882a593Smuzhiyun 	ENTER();
978*4882a593Smuzhiyun 
979*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
980*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
981*4882a593Smuzhiyun 	if (req == NULL) {
982*4882a593Smuzhiyun 		LEAVE();
983*4882a593Smuzhiyun 		return -ENOMEM;
984*4882a593Smuzhiyun 	}
985*4882a593Smuzhiyun 	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
986*4882a593Smuzhiyun 	cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_PARAM;
987*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_11N_CFG;
988*4882a593Smuzhiyun 
989*4882a593Smuzhiyun 	if (data_length == 0) {
990*4882a593Smuzhiyun 		/* Get Add BA parameters from MLAN */
991*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
992*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
993*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
994*4882a593Smuzhiyun 			ret = -EFAULT;
995*4882a593Smuzhiyun 			goto error;
996*4882a593Smuzhiyun 		}
997*4882a593Smuzhiyun 		data[0] = cfg_11n->param.addba_param.timeout;
998*4882a593Smuzhiyun 		data[1] = cfg_11n->param.addba_param.txwinsize;
999*4882a593Smuzhiyun 		data[2] = cfg_11n->param.addba_param.rxwinsize;
1000*4882a593Smuzhiyun 		data[3] = cfg_11n->param.addba_param.txamsdu;
1001*4882a593Smuzhiyun 		data[4] = cfg_11n->param.addba_param.rxamsdu;
1002*4882a593Smuzhiyun 		PRINTM(MINFO,
1003*4882a593Smuzhiyun 		       "GET: timeout:%d txwinsize:%d rxwinsize:%d txamsdu=%d, rxamsdu=%d\n",
1004*4882a593Smuzhiyun 		       data[0], data[1], data[2], data[3], data[4]);
1005*4882a593Smuzhiyun 		wrq->u.data.length = 5;
1006*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, data,
1007*4882a593Smuzhiyun 				 wrq->u.data.length * sizeof(int))) {
1008*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
1009*4882a593Smuzhiyun 			ret = -EFAULT;
1010*4882a593Smuzhiyun 			goto error;
1011*4882a593Smuzhiyun 		}
1012*4882a593Smuzhiyun 	} else if (data_length == 5) {
1013*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
1014*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
1015*4882a593Smuzhiyun 			ret = -EFAULT;
1016*4882a593Smuzhiyun 			goto error;
1017*4882a593Smuzhiyun 		}
1018*4882a593Smuzhiyun 		if (data[0] < 0 || data[0] > MLAN_DEFAULT_BLOCK_ACK_TIMEOUT) {
1019*4882a593Smuzhiyun 			PRINTM(MERROR, "Incorrect addba timeout value.\n");
1020*4882a593Smuzhiyun 			ret = -EFAULT;
1021*4882a593Smuzhiyun 			goto error;
1022*4882a593Smuzhiyun 		}
1023*4882a593Smuzhiyun 		if (data[1] <= 0 || data[1] > MLAN_AMPDU_MAX_TXWINSIZE ||
1024*4882a593Smuzhiyun 		    data[2] <= 0 || data[2] > MLAN_AMPDU_MAX_RXWINSIZE) {
1025*4882a593Smuzhiyun 			PRINTM(MERROR, "Incorrect Tx/Rx window size.\n");
1026*4882a593Smuzhiyun 			ret = -EFAULT;
1027*4882a593Smuzhiyun 			goto error;
1028*4882a593Smuzhiyun 		}
1029*4882a593Smuzhiyun 		cfg_11n->param.addba_param.timeout = data[0];
1030*4882a593Smuzhiyun 		cfg_11n->param.addba_param.txwinsize = data[1];
1031*4882a593Smuzhiyun 		cfg_11n->param.addba_param.rxwinsize = data[2];
1032*4882a593Smuzhiyun 		if (data[3] < 0 || data[3] > 1 || data[4] < 0 || data[4] > 1) {
1033*4882a593Smuzhiyun 			PRINTM(MERROR, "Incorrect Tx/Rx amsdu.\n");
1034*4882a593Smuzhiyun 			ret = -EFAULT;
1035*4882a593Smuzhiyun 			goto error;
1036*4882a593Smuzhiyun 		}
1037*4882a593Smuzhiyun 		cfg_11n->param.addba_param.txamsdu = data[3];
1038*4882a593Smuzhiyun 		cfg_11n->param.addba_param.rxamsdu = data[4];
1039*4882a593Smuzhiyun 		PRINTM(MINFO,
1040*4882a593Smuzhiyun 		       "SET: timeout:%d txwinsize:%d rxwinsize:%d txamsdu=%d rxamsdu=%d\n",
1041*4882a593Smuzhiyun 		       data[0], data[1], data[2], data[3], data[4]);
1042*4882a593Smuzhiyun 		/* Update Add BA parameters in MLAN */
1043*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
1044*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1045*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
1046*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
1047*4882a593Smuzhiyun 			goto error;
1048*4882a593Smuzhiyun 		}
1049*4882a593Smuzhiyun 	} else {
1050*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid number of arguments\n");
1051*4882a593Smuzhiyun 		ret = -EINVAL;
1052*4882a593Smuzhiyun 		goto error;
1053*4882a593Smuzhiyun 	}
1054*4882a593Smuzhiyun 
1055*4882a593Smuzhiyun error:
1056*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
1057*4882a593Smuzhiyun 		kfree(req);
1058*4882a593Smuzhiyun 	LEAVE();
1059*4882a593Smuzhiyun 	return ret;
1060*4882a593Smuzhiyun }
1061*4882a593Smuzhiyun 
1062*4882a593Smuzhiyun /**
1063*4882a593Smuzhiyun  *  @brief Set/Get Transmit buffer size
1064*4882a593Smuzhiyun  *
1065*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
1066*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
1067*4882a593Smuzhiyun  *
1068*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
1069*4882a593Smuzhiyun  */
woal_txbuf_cfg(moal_private * priv,struct iwreq * wrq)1070*4882a593Smuzhiyun static int woal_txbuf_cfg(moal_private *priv, struct iwreq *wrq)
1071*4882a593Smuzhiyun {
1072*4882a593Smuzhiyun 	int buf_size;
1073*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
1074*4882a593Smuzhiyun 	mlan_ds_11n_cfg *cfg_11n = NULL;
1075*4882a593Smuzhiyun 	int ret = 0;
1076*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
1077*4882a593Smuzhiyun 
1078*4882a593Smuzhiyun 	ENTER();
1079*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
1080*4882a593Smuzhiyun 	if (req == NULL) {
1081*4882a593Smuzhiyun 		ret = -ENOMEM;
1082*4882a593Smuzhiyun 		goto done;
1083*4882a593Smuzhiyun 	}
1084*4882a593Smuzhiyun 	cfg_11n = (mlan_ds_11n_cfg *)req->pbuf;
1085*4882a593Smuzhiyun 	cfg_11n->sub_command = MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE;
1086*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_11N_CFG;
1087*4882a593Smuzhiyun 
1088*4882a593Smuzhiyun 	if (wrq->u.data.length == 0) {
1089*4882a593Smuzhiyun 		/* Get Tx buffer size from MLAN */
1090*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
1091*4882a593Smuzhiyun 	} else {
1092*4882a593Smuzhiyun 		ret = -EINVAL;
1093*4882a593Smuzhiyun 		PRINTM(MERROR,
1094*4882a593Smuzhiyun 		       "Don't support set Tx buffer size after driver loaded!\n");
1095*4882a593Smuzhiyun 		goto done;
1096*4882a593Smuzhiyun 	}
1097*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1098*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
1099*4882a593Smuzhiyun 		ret = -EFAULT;
1100*4882a593Smuzhiyun 		goto done;
1101*4882a593Smuzhiyun 	}
1102*4882a593Smuzhiyun 	buf_size = cfg_11n->param.tx_buf_size;
1103*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, &buf_size, sizeof(buf_size))) {
1104*4882a593Smuzhiyun 		PRINTM(MERROR, "Copy to user failed\n");
1105*4882a593Smuzhiyun 		ret = -EFAULT;
1106*4882a593Smuzhiyun 		goto done;
1107*4882a593Smuzhiyun 	}
1108*4882a593Smuzhiyun 	wrq->u.data.length = 1;
1109*4882a593Smuzhiyun done:
1110*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
1111*4882a593Smuzhiyun 		kfree(req);
1112*4882a593Smuzhiyun 	LEAVE();
1113*4882a593Smuzhiyun 	return ret;
1114*4882a593Smuzhiyun }
1115*4882a593Smuzhiyun 
1116*4882a593Smuzhiyun /**
1117*4882a593Smuzhiyun  *  @brief Set/Get Host Sleep configuration
1118*4882a593Smuzhiyun  *
1119*4882a593Smuzhiyun  *  @param priv             A pointer to moal_private structure
1120*4882a593Smuzhiyun  *  @param wrq              A pointer to iwreq structure
1121*4882a593Smuzhiyun  *  @param invoke_hostcmd   MTRUE --invoke HostCmd, otherwise MFALSE
1122*4882a593Smuzhiyun  *
1123*4882a593Smuzhiyun  *  @return                 0 --success, otherwise fail
1124*4882a593Smuzhiyun  */
woal_hs_cfg(moal_private * priv,struct iwreq * wrq,BOOLEAN invoke_hostcmd)1125*4882a593Smuzhiyun static int woal_hs_cfg(moal_private *priv, struct iwreq *wrq,
1126*4882a593Smuzhiyun 		       BOOLEAN invoke_hostcmd)
1127*4882a593Smuzhiyun {
1128*4882a593Smuzhiyun 	int data[3], copy_len;
1129*4882a593Smuzhiyun 	int ret = 0;
1130*4882a593Smuzhiyun 	mlan_ds_hs_cfg hscfg;
1131*4882a593Smuzhiyun 	t_u16 action;
1132*4882a593Smuzhiyun 	mlan_bss_info bss_info;
1133*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
1134*4882a593Smuzhiyun 
1135*4882a593Smuzhiyun 	ENTER();
1136*4882a593Smuzhiyun 
1137*4882a593Smuzhiyun 	memset(data, 0, sizeof(data));
1138*4882a593Smuzhiyun 	memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg));
1139*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
1140*4882a593Smuzhiyun 
1141*4882a593Smuzhiyun 	if (data_length == 0) {
1142*4882a593Smuzhiyun 		action = MLAN_ACT_GET;
1143*4882a593Smuzhiyun 	} else {
1144*4882a593Smuzhiyun 		action = MLAN_ACT_SET;
1145*4882a593Smuzhiyun 		if (data_length >= 1 && data_length <= 3) {
1146*4882a593Smuzhiyun 			if (copy_from_user(data, wrq->u.data.pointer,
1147*4882a593Smuzhiyun 					   copy_len)) {
1148*4882a593Smuzhiyun 				PRINTM(MERROR, "Copy from user failed\n");
1149*4882a593Smuzhiyun 				ret = -EFAULT;
1150*4882a593Smuzhiyun 				goto done;
1151*4882a593Smuzhiyun 			}
1152*4882a593Smuzhiyun 		} else {
1153*4882a593Smuzhiyun 			PRINTM(MERROR, "Invalid arguments\n");
1154*4882a593Smuzhiyun 			ret = -EINVAL;
1155*4882a593Smuzhiyun 			goto done;
1156*4882a593Smuzhiyun 		}
1157*4882a593Smuzhiyun 	}
1158*4882a593Smuzhiyun 
1159*4882a593Smuzhiyun 	/* HS config is blocked if HS is already activated */
1160*4882a593Smuzhiyun 	if (data_length && (data[0] != (int)HOST_SLEEP_CFG_CANCEL ||
1161*4882a593Smuzhiyun 			    invoke_hostcmd == MFALSE)) {
1162*4882a593Smuzhiyun 		memset(&bss_info, 0, sizeof(bss_info));
1163*4882a593Smuzhiyun 		woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
1164*4882a593Smuzhiyun 		if (bss_info.is_hs_configured) {
1165*4882a593Smuzhiyun 			PRINTM(MERROR, "HS already configured\n");
1166*4882a593Smuzhiyun 			ret = -EFAULT;
1167*4882a593Smuzhiyun 			goto done;
1168*4882a593Smuzhiyun 		}
1169*4882a593Smuzhiyun 	}
1170*4882a593Smuzhiyun 
1171*4882a593Smuzhiyun 	/* Do a GET first if some arguments are not provided */
1172*4882a593Smuzhiyun 	if (data_length >= 1 && data_length < 3) {
1173*4882a593Smuzhiyun 		woal_set_get_hs_params(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT,
1174*4882a593Smuzhiyun 				       &hscfg);
1175*4882a593Smuzhiyun 	}
1176*4882a593Smuzhiyun 
1177*4882a593Smuzhiyun 	if (data_length)
1178*4882a593Smuzhiyun 		hscfg.conditions = data[0];
1179*4882a593Smuzhiyun 	if (data_length >= 2)
1180*4882a593Smuzhiyun 		hscfg.gpio = data[1];
1181*4882a593Smuzhiyun 	if (data_length == 3)
1182*4882a593Smuzhiyun 		hscfg.gap = data[2];
1183*4882a593Smuzhiyun 
1184*4882a593Smuzhiyun 	if ((invoke_hostcmd == MTRUE) && (action == MLAN_ACT_SET)) {
1185*4882a593Smuzhiyun 		/* Need to issue an extra IOCTL first to set up parameters */
1186*4882a593Smuzhiyun 		hscfg.is_invoke_hostcmd = MFALSE;
1187*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS !=
1188*4882a593Smuzhiyun 		    woal_set_get_hs_params(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT,
1189*4882a593Smuzhiyun 					   &hscfg)) {
1190*4882a593Smuzhiyun 			ret = -EFAULT;
1191*4882a593Smuzhiyun 			goto done;
1192*4882a593Smuzhiyun 		}
1193*4882a593Smuzhiyun 	}
1194*4882a593Smuzhiyun 	hscfg.is_invoke_hostcmd = invoke_hostcmd;
1195*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
1196*4882a593Smuzhiyun 	    woal_set_get_hs_params(priv, action, MOAL_IOCTL_WAIT, &hscfg)) {
1197*4882a593Smuzhiyun 		ret = -EFAULT;
1198*4882a593Smuzhiyun 		goto done;
1199*4882a593Smuzhiyun 	}
1200*4882a593Smuzhiyun 
1201*4882a593Smuzhiyun 	if (action == MLAN_ACT_GET) {
1202*4882a593Smuzhiyun 		data[0] = hscfg.conditions;
1203*4882a593Smuzhiyun 		data[1] = hscfg.gpio;
1204*4882a593Smuzhiyun 		data[2] = hscfg.gap;
1205*4882a593Smuzhiyun 		wrq->u.data.length = 3;
1206*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, data,
1207*4882a593Smuzhiyun 				 sizeof(int) * wrq->u.data.length)) {
1208*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
1209*4882a593Smuzhiyun 			ret = -EFAULT;
1210*4882a593Smuzhiyun 			goto done;
1211*4882a593Smuzhiyun 		}
1212*4882a593Smuzhiyun 	}
1213*4882a593Smuzhiyun done:
1214*4882a593Smuzhiyun 	LEAVE();
1215*4882a593Smuzhiyun 	return ret;
1216*4882a593Smuzhiyun }
1217*4882a593Smuzhiyun 
1218*4882a593Smuzhiyun /**
1219*4882a593Smuzhiyun  *  @brief Set Host Sleep parameters
1220*4882a593Smuzhiyun  *
1221*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
1222*4882a593Smuzhiyun  *  @param wrq          A pointer to iwreq structure
1223*4882a593Smuzhiyun  *
1224*4882a593Smuzhiyun  *  @return             0 --success, otherwise fail
1225*4882a593Smuzhiyun  */
woal_hs_setpara(moal_private * priv,struct iwreq * wrq)1226*4882a593Smuzhiyun static int woal_hs_setpara(moal_private *priv, struct iwreq *wrq)
1227*4882a593Smuzhiyun {
1228*4882a593Smuzhiyun 	int ret = 0;
1229*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
1230*4882a593Smuzhiyun 
1231*4882a593Smuzhiyun 	ENTER();
1232*4882a593Smuzhiyun 
1233*4882a593Smuzhiyun 	if (data_length >= 1 && data_length <= 3) {
1234*4882a593Smuzhiyun 		ret = woal_hs_cfg(priv, wrq, MFALSE);
1235*4882a593Smuzhiyun 		goto done;
1236*4882a593Smuzhiyun 	} else {
1237*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid arguments\n");
1238*4882a593Smuzhiyun 		ret = -EINVAL;
1239*4882a593Smuzhiyun 		goto done;
1240*4882a593Smuzhiyun 	}
1241*4882a593Smuzhiyun done:
1242*4882a593Smuzhiyun 	LEAVE();
1243*4882a593Smuzhiyun 	return ret;
1244*4882a593Smuzhiyun }
1245*4882a593Smuzhiyun 
1246*4882a593Smuzhiyun /**
1247*4882a593Smuzhiyun  *  @brief Get/Set inactivity timeout extend
1248*4882a593Smuzhiyun  *
1249*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
1250*4882a593Smuzhiyun  *  @param wrq          A pointer to iwreq structure
1251*4882a593Smuzhiyun  *
1252*4882a593Smuzhiyun  *  @return             0 --success, otherwise fail
1253*4882a593Smuzhiyun  */
woal_inactivity_timeout_ext(moal_private * priv,struct iwreq * wrq)1254*4882a593Smuzhiyun static int woal_inactivity_timeout_ext(moal_private *priv, struct iwreq *wrq)
1255*4882a593Smuzhiyun {
1256*4882a593Smuzhiyun 	int data[4], copy_len;
1257*4882a593Smuzhiyun 	int ret = 0;
1258*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
1259*4882a593Smuzhiyun 	mlan_ds_pm_cfg *pmcfg = NULL;
1260*4882a593Smuzhiyun 	pmlan_ds_inactivity_to inac_to = NULL;
1261*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
1262*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
1263*4882a593Smuzhiyun 
1264*4882a593Smuzhiyun 	ENTER();
1265*4882a593Smuzhiyun 
1266*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
1267*4882a593Smuzhiyun 	memset(data, 0, sizeof(data));
1268*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
1269*4882a593Smuzhiyun 	if (req == NULL) {
1270*4882a593Smuzhiyun 		ret = -ENOMEM;
1271*4882a593Smuzhiyun 		goto done;
1272*4882a593Smuzhiyun 	}
1273*4882a593Smuzhiyun 
1274*4882a593Smuzhiyun 	pmcfg = (mlan_ds_pm_cfg *)req->pbuf;
1275*4882a593Smuzhiyun 	inac_to = &pmcfg->param.inactivity_to;
1276*4882a593Smuzhiyun 	pmcfg->sub_command = MLAN_OID_PM_CFG_INACTIVITY_TO;
1277*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_PM_CFG;
1278*4882a593Smuzhiyun 
1279*4882a593Smuzhiyun 	if ((data_length != 0 && data_length != 3 && data_length != 4) ||
1280*4882a593Smuzhiyun 	    sizeof(int) * data_length > sizeof(data)) {
1281*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid number of parameters\n");
1282*4882a593Smuzhiyun 		ret = -EINVAL;
1283*4882a593Smuzhiyun 		goto done;
1284*4882a593Smuzhiyun 	}
1285*4882a593Smuzhiyun 
1286*4882a593Smuzhiyun 	req->action = MLAN_ACT_GET;
1287*4882a593Smuzhiyun 	if (data_length) {
1288*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
1289*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
1290*4882a593Smuzhiyun 			ret = -EFAULT;
1291*4882a593Smuzhiyun 			goto done;
1292*4882a593Smuzhiyun 		}
1293*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
1294*4882a593Smuzhiyun 		inac_to->timeout_unit = data[0];
1295*4882a593Smuzhiyun 		inac_to->unicast_timeout = data[1];
1296*4882a593Smuzhiyun 		inac_to->mcast_timeout = data[2];
1297*4882a593Smuzhiyun 		inac_to->ps_entry_timeout = data[3];
1298*4882a593Smuzhiyun 	}
1299*4882a593Smuzhiyun 
1300*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1301*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
1302*4882a593Smuzhiyun 		ret = -EFAULT;
1303*4882a593Smuzhiyun 		goto done;
1304*4882a593Smuzhiyun 	}
1305*4882a593Smuzhiyun 
1306*4882a593Smuzhiyun 	/* Copy back current values regardless of GET/SET */
1307*4882a593Smuzhiyun 	data[0] = inac_to->timeout_unit;
1308*4882a593Smuzhiyun 	data[1] = inac_to->unicast_timeout;
1309*4882a593Smuzhiyun 	data[2] = inac_to->mcast_timeout;
1310*4882a593Smuzhiyun 	data[3] = inac_to->ps_entry_timeout;
1311*4882a593Smuzhiyun 
1312*4882a593Smuzhiyun 	if (req->action == MLAN_ACT_GET) {
1313*4882a593Smuzhiyun 		wrq->u.data.length = 4;
1314*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, data,
1315*4882a593Smuzhiyun 				 wrq->u.data.length * sizeof(int))) {
1316*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
1317*4882a593Smuzhiyun 			ret = -EFAULT;
1318*4882a593Smuzhiyun 			goto done;
1319*4882a593Smuzhiyun 		}
1320*4882a593Smuzhiyun 	}
1321*4882a593Smuzhiyun 
1322*4882a593Smuzhiyun done:
1323*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
1324*4882a593Smuzhiyun 		kfree(req);
1325*4882a593Smuzhiyun 	LEAVE();
1326*4882a593Smuzhiyun 	return ret;
1327*4882a593Smuzhiyun }
1328*4882a593Smuzhiyun 
1329*4882a593Smuzhiyun /**
1330*4882a593Smuzhiyun  *  @brief Set/Get system clock
1331*4882a593Smuzhiyun  *
1332*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
1333*4882a593Smuzhiyun  *  @param wrq          A pointer to iwreq structure
1334*4882a593Smuzhiyun  *
1335*4882a593Smuzhiyun  *  @return             0 --success, otherwise fail
1336*4882a593Smuzhiyun  */
woal_ecl_sys_clock(moal_private * priv,struct iwreq * wrq)1337*4882a593Smuzhiyun static int woal_ecl_sys_clock(moal_private *priv, struct iwreq *wrq)
1338*4882a593Smuzhiyun {
1339*4882a593Smuzhiyun 	int data[64], copy_len;
1340*4882a593Smuzhiyun 	int ret = 0;
1341*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
1342*4882a593Smuzhiyun 	mlan_ds_misc_cfg *cfg = NULL;
1343*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
1344*4882a593Smuzhiyun 	int i = 0;
1345*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
1346*4882a593Smuzhiyun 
1347*4882a593Smuzhiyun 	ENTER();
1348*4882a593Smuzhiyun 
1349*4882a593Smuzhiyun 	memset(data, 0, sizeof(data));
1350*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
1351*4882a593Smuzhiyun 
1352*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1353*4882a593Smuzhiyun 	if (req == NULL) {
1354*4882a593Smuzhiyun 		ret = -ENOMEM;
1355*4882a593Smuzhiyun 		goto done;
1356*4882a593Smuzhiyun 	}
1357*4882a593Smuzhiyun 
1358*4882a593Smuzhiyun 	cfg = (mlan_ds_misc_cfg *)req->pbuf;
1359*4882a593Smuzhiyun 	cfg->sub_command = MLAN_OID_MISC_SYS_CLOCK;
1360*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_MISC_CFG;
1361*4882a593Smuzhiyun 
1362*4882a593Smuzhiyun 	if (!data_length)
1363*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
1364*4882a593Smuzhiyun 	else if (data_length <= MLAN_MAX_CLK_NUM) {
1365*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
1366*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
1367*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
1368*4882a593Smuzhiyun 			ret = -EFAULT;
1369*4882a593Smuzhiyun 			goto done;
1370*4882a593Smuzhiyun 		}
1371*4882a593Smuzhiyun 	} else {
1372*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid arguments\n");
1373*4882a593Smuzhiyun 		ret = -EINVAL;
1374*4882a593Smuzhiyun 		goto done;
1375*4882a593Smuzhiyun 	}
1376*4882a593Smuzhiyun 
1377*4882a593Smuzhiyun 	if (req->action == MLAN_ACT_GET) {
1378*4882a593Smuzhiyun 		/* Get configurable clocks */
1379*4882a593Smuzhiyun 		cfg->param.sys_clock.sys_clk_type = MLAN_CLK_CONFIGURABLE;
1380*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1381*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
1382*4882a593Smuzhiyun 			ret = -EFAULT;
1383*4882a593Smuzhiyun 			goto done;
1384*4882a593Smuzhiyun 		}
1385*4882a593Smuzhiyun 
1386*4882a593Smuzhiyun 		/* Current system clock */
1387*4882a593Smuzhiyun 		data[0] = (int)cfg->param.sys_clock.cur_sys_clk;
1388*4882a593Smuzhiyun 		wrq->u.data.length = 1;
1389*4882a593Smuzhiyun 
1390*4882a593Smuzhiyun 		data_length =
1391*4882a593Smuzhiyun 			MIN(cfg->param.sys_clock.sys_clk_num, MLAN_MAX_CLK_NUM);
1392*4882a593Smuzhiyun 
1393*4882a593Smuzhiyun 		/* Configurable clocks */
1394*4882a593Smuzhiyun 		for (i = 0; i < data_length; i++) {
1395*4882a593Smuzhiyun 			data[i + wrq->u.data.length] =
1396*4882a593Smuzhiyun 				(int)cfg->param.sys_clock.sys_clk[i];
1397*4882a593Smuzhiyun 		}
1398*4882a593Smuzhiyun 		wrq->u.data.length += data_length;
1399*4882a593Smuzhiyun 
1400*4882a593Smuzhiyun 		/* Get supported clocks */
1401*4882a593Smuzhiyun 		cfg->param.sys_clock.sys_clk_type = MLAN_CLK_SUPPORTED;
1402*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1403*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
1404*4882a593Smuzhiyun 			ret = -EFAULT;
1405*4882a593Smuzhiyun 			goto done;
1406*4882a593Smuzhiyun 		}
1407*4882a593Smuzhiyun 
1408*4882a593Smuzhiyun 		data_length =
1409*4882a593Smuzhiyun 			MIN(cfg->param.sys_clock.sys_clk_num, MLAN_MAX_CLK_NUM);
1410*4882a593Smuzhiyun 
1411*4882a593Smuzhiyun 		/* Supported clocks */
1412*4882a593Smuzhiyun 		for (i = 0; i < data_length; i++) {
1413*4882a593Smuzhiyun 			data[i + wrq->u.data.length] =
1414*4882a593Smuzhiyun 				(int)cfg->param.sys_clock.sys_clk[i];
1415*4882a593Smuzhiyun 		}
1416*4882a593Smuzhiyun 
1417*4882a593Smuzhiyun 		wrq->u.data.length += data_length;
1418*4882a593Smuzhiyun 
1419*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, data,
1420*4882a593Smuzhiyun 				 sizeof(int) * wrq->u.data.length)) {
1421*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
1422*4882a593Smuzhiyun 			ret = -EFAULT;
1423*4882a593Smuzhiyun 			goto done;
1424*4882a593Smuzhiyun 		}
1425*4882a593Smuzhiyun 	} else {
1426*4882a593Smuzhiyun 		/* Set configurable clocks */
1427*4882a593Smuzhiyun 		cfg->param.sys_clock.sys_clk_type = MLAN_CLK_CONFIGURABLE;
1428*4882a593Smuzhiyun 		cfg->param.sys_clock.sys_clk_num =
1429*4882a593Smuzhiyun 			MIN(MLAN_MAX_CLK_NUM, data_length);
1430*4882a593Smuzhiyun 		for (i = 0; i < cfg->param.sys_clock.sys_clk_num; i++)
1431*4882a593Smuzhiyun 			cfg->param.sys_clock.sys_clk[i] = (t_u16)data[i];
1432*4882a593Smuzhiyun 
1433*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1434*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
1435*4882a593Smuzhiyun 			ret = -EFAULT;
1436*4882a593Smuzhiyun 			goto done;
1437*4882a593Smuzhiyun 		}
1438*4882a593Smuzhiyun 	}
1439*4882a593Smuzhiyun done:
1440*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
1441*4882a593Smuzhiyun 		kfree(req);
1442*4882a593Smuzhiyun 	LEAVE();
1443*4882a593Smuzhiyun 	return ret;
1444*4882a593Smuzhiyun }
1445*4882a593Smuzhiyun 
1446*4882a593Smuzhiyun /**
1447*4882a593Smuzhiyun  *  @brief Set/Get Band and Adhoc-band setting
1448*4882a593Smuzhiyun  *
1449*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
1450*4882a593Smuzhiyun  *  @param wrq          A pointer to iwreq structure
1451*4882a593Smuzhiyun  *
1452*4882a593Smuzhiyun  *  @return             0 --success, otherwise fail
1453*4882a593Smuzhiyun  */
woal_band_cfg(moal_private * priv,struct iwreq * wrq)1454*4882a593Smuzhiyun static int woal_band_cfg(moal_private *priv, struct iwreq *wrq)
1455*4882a593Smuzhiyun {
1456*4882a593Smuzhiyun 	int ret = 0;
1457*4882a593Smuzhiyun 	unsigned int i;
1458*4882a593Smuzhiyun 	int data[3];
1459*4882a593Smuzhiyun 	int user_data_len = wrq->u.data.length, copy_len;
1460*4882a593Smuzhiyun 	t_u32 infra_band = 0;
1461*4882a593Smuzhiyun 	t_u32 adhoc_band = 0;
1462*4882a593Smuzhiyun 	t_u32 adhoc_channel = 0;
1463*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
1464*4882a593Smuzhiyun 	mlan_ds_radio_cfg *radio_cfg = NULL;
1465*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
1466*4882a593Smuzhiyun 
1467*4882a593Smuzhiyun 	ENTER();
1468*4882a593Smuzhiyun 
1469*4882a593Smuzhiyun 	if (sizeof(int) * user_data_len > sizeof(data)) {
1470*4882a593Smuzhiyun 		PRINTM(MERROR, "Too many arguments\n");
1471*4882a593Smuzhiyun 		LEAVE();
1472*4882a593Smuzhiyun 		return -EINVAL;
1473*4882a593Smuzhiyun 	}
1474*4882a593Smuzhiyun 
1475*4882a593Smuzhiyun 	if (user_data_len > 0) {
1476*4882a593Smuzhiyun 		if (priv->media_connected == MTRUE) {
1477*4882a593Smuzhiyun 			LEAVE();
1478*4882a593Smuzhiyun 			return -EOPNOTSUPP;
1479*4882a593Smuzhiyun 		}
1480*4882a593Smuzhiyun 	}
1481*4882a593Smuzhiyun 
1482*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * user_data_len);
1483*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
1484*4882a593Smuzhiyun 	if (req == NULL) {
1485*4882a593Smuzhiyun 		ret = -ENOMEM;
1486*4882a593Smuzhiyun 		goto error;
1487*4882a593Smuzhiyun 	}
1488*4882a593Smuzhiyun 	radio_cfg = (mlan_ds_radio_cfg *)req->pbuf;
1489*4882a593Smuzhiyun 	radio_cfg->sub_command = MLAN_OID_BAND_CFG;
1490*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_RADIO_CFG;
1491*4882a593Smuzhiyun 
1492*4882a593Smuzhiyun 	if (wrq->u.data.length == 0) {
1493*4882a593Smuzhiyun 		/* Get config_bands, adhoc_start_band and adhoc_channel values
1494*4882a593Smuzhiyun 		 * from MLAN */
1495*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
1496*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1497*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
1498*4882a593Smuzhiyun 			ret = -EFAULT;
1499*4882a593Smuzhiyun 			goto error;
1500*4882a593Smuzhiyun 		}
1501*4882a593Smuzhiyun 		/* Infra Band */
1502*4882a593Smuzhiyun 		data[0] = radio_cfg->param.band_cfg.config_bands;
1503*4882a593Smuzhiyun 		/* Adhoc Band */
1504*4882a593Smuzhiyun 		data[1] = radio_cfg->param.band_cfg.adhoc_start_band;
1505*4882a593Smuzhiyun 		/* Adhoc Channel */
1506*4882a593Smuzhiyun 		data[2] = radio_cfg->param.band_cfg.adhoc_channel;
1507*4882a593Smuzhiyun 		wrq->u.data.length = 3;
1508*4882a593Smuzhiyun 
1509*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, data,
1510*4882a593Smuzhiyun 				 sizeof(int) * wrq->u.data.length)) {
1511*4882a593Smuzhiyun 			ret = -EFAULT;
1512*4882a593Smuzhiyun 			goto error;
1513*4882a593Smuzhiyun 		}
1514*4882a593Smuzhiyun 	} else {
1515*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
1516*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
1517*4882a593Smuzhiyun 			ret = -EFAULT;
1518*4882a593Smuzhiyun 			goto error;
1519*4882a593Smuzhiyun 		}
1520*4882a593Smuzhiyun 
1521*4882a593Smuzhiyun 		/* To support only <b/bg/bgn/n> */
1522*4882a593Smuzhiyun 		infra_band = data[0];
1523*4882a593Smuzhiyun 		for (i = 0; i < sizeof(SupportedInfraBand); i++)
1524*4882a593Smuzhiyun 			if (infra_band == SupportedInfraBand[i])
1525*4882a593Smuzhiyun 				break;
1526*4882a593Smuzhiyun 		if (i == sizeof(SupportedInfraBand)) {
1527*4882a593Smuzhiyun 			ret = -EINVAL;
1528*4882a593Smuzhiyun 			goto error;
1529*4882a593Smuzhiyun 		}
1530*4882a593Smuzhiyun 
1531*4882a593Smuzhiyun 		/* Set Adhoc band */
1532*4882a593Smuzhiyun 		if (user_data_len >= 2) {
1533*4882a593Smuzhiyun 			adhoc_band = data[1];
1534*4882a593Smuzhiyun 			for (i = 0; i < sizeof(SupportedAdhocBand); i++)
1535*4882a593Smuzhiyun 				if (adhoc_band == SupportedAdhocBand[i])
1536*4882a593Smuzhiyun 					break;
1537*4882a593Smuzhiyun 			if (i == sizeof(SupportedAdhocBand)) {
1538*4882a593Smuzhiyun 				ret = -EINVAL;
1539*4882a593Smuzhiyun 				goto error;
1540*4882a593Smuzhiyun 			}
1541*4882a593Smuzhiyun 		}
1542*4882a593Smuzhiyun 
1543*4882a593Smuzhiyun 		/* Set Adhoc channel */
1544*4882a593Smuzhiyun 		if (user_data_len >= 3) {
1545*4882a593Smuzhiyun 			adhoc_channel = data[2];
1546*4882a593Smuzhiyun 			if (adhoc_channel == 0) {
1547*4882a593Smuzhiyun 				/* Check if specified adhoc channel is non-zero
1548*4882a593Smuzhiyun 				 */
1549*4882a593Smuzhiyun 				ret = -EINVAL;
1550*4882a593Smuzhiyun 				goto error;
1551*4882a593Smuzhiyun 			}
1552*4882a593Smuzhiyun 		}
1553*4882a593Smuzhiyun 		/* Set config_bands and adhoc_start_band values to MLAN */
1554*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
1555*4882a593Smuzhiyun 		radio_cfg->param.band_cfg.config_bands = infra_band;
1556*4882a593Smuzhiyun 		radio_cfg->param.band_cfg.adhoc_start_band = adhoc_band;
1557*4882a593Smuzhiyun 		radio_cfg->param.band_cfg.adhoc_channel = adhoc_channel;
1558*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1559*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
1560*4882a593Smuzhiyun 			ret = -EFAULT;
1561*4882a593Smuzhiyun 			goto error;
1562*4882a593Smuzhiyun 		}
1563*4882a593Smuzhiyun 	}
1564*4882a593Smuzhiyun 
1565*4882a593Smuzhiyun error:
1566*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
1567*4882a593Smuzhiyun 		kfree(req);
1568*4882a593Smuzhiyun 	LEAVE();
1569*4882a593Smuzhiyun 	return ret;
1570*4882a593Smuzhiyun }
1571*4882a593Smuzhiyun 
1572*4882a593Smuzhiyun /**
1573*4882a593Smuzhiyun  *  @brief Read/Write adapter registers value
1574*4882a593Smuzhiyun  *
1575*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
1576*4882a593Smuzhiyun  *  @param wrq          A pointer to iwreq structure
1577*4882a593Smuzhiyun  *
1578*4882a593Smuzhiyun  *  @return             0 --success, otherwise fail
1579*4882a593Smuzhiyun  */
woal_reg_read_write(moal_private * priv,struct iwreq * wrq)1580*4882a593Smuzhiyun static int woal_reg_read_write(moal_private *priv, struct iwreq *wrq)
1581*4882a593Smuzhiyun {
1582*4882a593Smuzhiyun 	int data[3], copy_len;
1583*4882a593Smuzhiyun 	int ret = 0;
1584*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
1585*4882a593Smuzhiyun 	mlan_ds_reg_mem *reg = NULL;
1586*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
1587*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
1588*4882a593Smuzhiyun 
1589*4882a593Smuzhiyun 	ENTER();
1590*4882a593Smuzhiyun 
1591*4882a593Smuzhiyun 	memset(data, 0, sizeof(data));
1592*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
1593*4882a593Smuzhiyun 
1594*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_reg_mem));
1595*4882a593Smuzhiyun 	if (req == NULL) {
1596*4882a593Smuzhiyun 		ret = -ENOMEM;
1597*4882a593Smuzhiyun 		goto done;
1598*4882a593Smuzhiyun 	}
1599*4882a593Smuzhiyun 
1600*4882a593Smuzhiyun 	reg = (mlan_ds_reg_mem *)req->pbuf;
1601*4882a593Smuzhiyun 	reg->sub_command = MLAN_OID_REG_RW;
1602*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_REG_MEM;
1603*4882a593Smuzhiyun 
1604*4882a593Smuzhiyun 	if (data_length == 2) {
1605*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
1606*4882a593Smuzhiyun 	} else if (data_length == 3) {
1607*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
1608*4882a593Smuzhiyun 	} else {
1609*4882a593Smuzhiyun 		ret = -EINVAL;
1610*4882a593Smuzhiyun 		goto done;
1611*4882a593Smuzhiyun 	}
1612*4882a593Smuzhiyun 	if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
1613*4882a593Smuzhiyun 		PRINTM(MERROR, "Copy from user failed\n");
1614*4882a593Smuzhiyun 		ret = -EFAULT;
1615*4882a593Smuzhiyun 		goto done;
1616*4882a593Smuzhiyun 	}
1617*4882a593Smuzhiyun 	reg->param.reg_rw.type = (t_u32)data[0];
1618*4882a593Smuzhiyun 	reg->param.reg_rw.offset = (t_u32)data[1];
1619*4882a593Smuzhiyun 	if (data_length == 3)
1620*4882a593Smuzhiyun 		reg->param.reg_rw.value = (t_u32)data[2];
1621*4882a593Smuzhiyun 
1622*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1623*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
1624*4882a593Smuzhiyun 		ret = -EFAULT;
1625*4882a593Smuzhiyun 		goto done;
1626*4882a593Smuzhiyun 	}
1627*4882a593Smuzhiyun 
1628*4882a593Smuzhiyun 	if (req->action == MLAN_ACT_GET) {
1629*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &reg->param.reg_rw.value,
1630*4882a593Smuzhiyun 				 sizeof(int))) {
1631*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
1632*4882a593Smuzhiyun 			ret = -EFAULT;
1633*4882a593Smuzhiyun 			goto done;
1634*4882a593Smuzhiyun 		}
1635*4882a593Smuzhiyun 		wrq->u.data.length = 1;
1636*4882a593Smuzhiyun 	}
1637*4882a593Smuzhiyun 
1638*4882a593Smuzhiyun done:
1639*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
1640*4882a593Smuzhiyun 		kfree(req);
1641*4882a593Smuzhiyun 	LEAVE();
1642*4882a593Smuzhiyun 	return ret;
1643*4882a593Smuzhiyun }
1644*4882a593Smuzhiyun 
1645*4882a593Smuzhiyun /**
1646*4882a593Smuzhiyun  *  @brief Read the EEPROM contents of the card
1647*4882a593Smuzhiyun  *
1648*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
1649*4882a593Smuzhiyun  *  @param wrq          A pointer to iwreq structure
1650*4882a593Smuzhiyun  *
1651*4882a593Smuzhiyun  *  @return             0 --success, otherwise fail
1652*4882a593Smuzhiyun  */
woal_read_eeprom(moal_private * priv,struct iwreq * wrq)1653*4882a593Smuzhiyun static int woal_read_eeprom(moal_private *priv, struct iwreq *wrq)
1654*4882a593Smuzhiyun {
1655*4882a593Smuzhiyun 	int data[2], copy_len;
1656*4882a593Smuzhiyun 	int ret = 0;
1657*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
1658*4882a593Smuzhiyun 	mlan_ds_reg_mem *reg = NULL;
1659*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
1660*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
1661*4882a593Smuzhiyun 
1662*4882a593Smuzhiyun 	ENTER();
1663*4882a593Smuzhiyun 
1664*4882a593Smuzhiyun 	memset(data, 0, sizeof(data));
1665*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
1666*4882a593Smuzhiyun 
1667*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_reg_mem));
1668*4882a593Smuzhiyun 	if (req == NULL) {
1669*4882a593Smuzhiyun 		ret = -ENOMEM;
1670*4882a593Smuzhiyun 		goto done;
1671*4882a593Smuzhiyun 	}
1672*4882a593Smuzhiyun 
1673*4882a593Smuzhiyun 	reg = (mlan_ds_reg_mem *)req->pbuf;
1674*4882a593Smuzhiyun 	reg->sub_command = MLAN_OID_EEPROM_RD;
1675*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_REG_MEM;
1676*4882a593Smuzhiyun 
1677*4882a593Smuzhiyun 	if (data_length == 2) {
1678*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
1679*4882a593Smuzhiyun 	} else {
1680*4882a593Smuzhiyun 		ret = -EINVAL;
1681*4882a593Smuzhiyun 		goto done;
1682*4882a593Smuzhiyun 	}
1683*4882a593Smuzhiyun 	if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
1684*4882a593Smuzhiyun 		PRINTM(MERROR, "Copy from user failed\n");
1685*4882a593Smuzhiyun 		ret = -EFAULT;
1686*4882a593Smuzhiyun 		goto done;
1687*4882a593Smuzhiyun 	}
1688*4882a593Smuzhiyun 
1689*4882a593Smuzhiyun 	reg->param.rd_eeprom.offset = (t_u16)data[0];
1690*4882a593Smuzhiyun 	reg->param.rd_eeprom.byte_count = (t_u16)data[1];
1691*4882a593Smuzhiyun 
1692*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1693*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
1694*4882a593Smuzhiyun 		ret = -EFAULT;
1695*4882a593Smuzhiyun 		goto done;
1696*4882a593Smuzhiyun 	}
1697*4882a593Smuzhiyun 
1698*4882a593Smuzhiyun 	if (req->action == MLAN_ACT_GET) {
1699*4882a593Smuzhiyun 		wrq->u.data.length = reg->param.rd_eeprom.byte_count;
1700*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer,
1701*4882a593Smuzhiyun 				 reg->param.rd_eeprom.value,
1702*4882a593Smuzhiyun 				 MIN(wrq->u.data.length, MAX_EEPROM_DATA))) {
1703*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
1704*4882a593Smuzhiyun 			ret = -EFAULT;
1705*4882a593Smuzhiyun 			goto done;
1706*4882a593Smuzhiyun 		}
1707*4882a593Smuzhiyun 	}
1708*4882a593Smuzhiyun 
1709*4882a593Smuzhiyun done:
1710*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
1711*4882a593Smuzhiyun 		kfree(req);
1712*4882a593Smuzhiyun 	LEAVE();
1713*4882a593Smuzhiyun 	return ret;
1714*4882a593Smuzhiyun }
1715*4882a593Smuzhiyun 
1716*4882a593Smuzhiyun /**
1717*4882a593Smuzhiyun  *  @brief Read/Write device memory value
1718*4882a593Smuzhiyun  *
1719*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
1720*4882a593Smuzhiyun  *  @param wrq          A pointer to iwreq structure
1721*4882a593Smuzhiyun  *
1722*4882a593Smuzhiyun  *  @return             0 --success, otherwise fail
1723*4882a593Smuzhiyun  */
woal_mem_read_write(moal_private * priv,struct iwreq * wrq)1724*4882a593Smuzhiyun static int woal_mem_read_write(moal_private *priv, struct iwreq *wrq)
1725*4882a593Smuzhiyun {
1726*4882a593Smuzhiyun 	t_u32 data[2];
1727*4882a593Smuzhiyun 	int ret = 0;
1728*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
1729*4882a593Smuzhiyun 	mlan_ds_reg_mem *reg_mem = NULL;
1730*4882a593Smuzhiyun 	int data_length = wrq->u.data.length, copy_len;
1731*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
1732*4882a593Smuzhiyun 
1733*4882a593Smuzhiyun 	ENTER();
1734*4882a593Smuzhiyun 
1735*4882a593Smuzhiyun 	memset(data, 0, sizeof(data));
1736*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
1737*4882a593Smuzhiyun 
1738*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_reg_mem));
1739*4882a593Smuzhiyun 	if (req == NULL) {
1740*4882a593Smuzhiyun 		ret = -ENOMEM;
1741*4882a593Smuzhiyun 		goto done;
1742*4882a593Smuzhiyun 	}
1743*4882a593Smuzhiyun 
1744*4882a593Smuzhiyun 	reg_mem = (mlan_ds_reg_mem *)req->pbuf;
1745*4882a593Smuzhiyun 	reg_mem->sub_command = MLAN_OID_MEM_RW;
1746*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_REG_MEM;
1747*4882a593Smuzhiyun 
1748*4882a593Smuzhiyun 	if (data_length == 1) {
1749*4882a593Smuzhiyun 		PRINTM(MINFO, "MEM_RW: GET\n");
1750*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
1751*4882a593Smuzhiyun 	} else if (data_length == 2) {
1752*4882a593Smuzhiyun 		PRINTM(MINFO, "MEM_RW: SET\n");
1753*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
1754*4882a593Smuzhiyun 	} else {
1755*4882a593Smuzhiyun 		ret = -EINVAL;
1756*4882a593Smuzhiyun 		goto done;
1757*4882a593Smuzhiyun 	}
1758*4882a593Smuzhiyun 	if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
1759*4882a593Smuzhiyun 		PRINTM(MERROR, "Copy from user failed\n");
1760*4882a593Smuzhiyun 		ret = -EFAULT;
1761*4882a593Smuzhiyun 		goto done;
1762*4882a593Smuzhiyun 	}
1763*4882a593Smuzhiyun 
1764*4882a593Smuzhiyun 	reg_mem->param.mem_rw.addr = (t_u32)data[0];
1765*4882a593Smuzhiyun 	if (data_length == 2)
1766*4882a593Smuzhiyun 		reg_mem->param.mem_rw.value = (t_u32)data[1];
1767*4882a593Smuzhiyun 
1768*4882a593Smuzhiyun 	PRINTM(MINFO, "MEM_RW: Addr=0x%x, Value=0x%x\n",
1769*4882a593Smuzhiyun 	       (int)reg_mem->param.mem_rw.addr,
1770*4882a593Smuzhiyun 	       (int)reg_mem->param.mem_rw.value);
1771*4882a593Smuzhiyun 
1772*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1773*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
1774*4882a593Smuzhiyun 		ret = -EFAULT;
1775*4882a593Smuzhiyun 		goto done;
1776*4882a593Smuzhiyun 	}
1777*4882a593Smuzhiyun 
1778*4882a593Smuzhiyun 	if (req->action == MLAN_ACT_GET) {
1779*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer,
1780*4882a593Smuzhiyun 				 &reg_mem->param.mem_rw.value, sizeof(int))) {
1781*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
1782*4882a593Smuzhiyun 			ret = -EFAULT;
1783*4882a593Smuzhiyun 			goto done;
1784*4882a593Smuzhiyun 		}
1785*4882a593Smuzhiyun 		wrq->u.data.length = 1;
1786*4882a593Smuzhiyun 	}
1787*4882a593Smuzhiyun 
1788*4882a593Smuzhiyun done:
1789*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
1790*4882a593Smuzhiyun 		kfree(req);
1791*4882a593Smuzhiyun 	LEAVE();
1792*4882a593Smuzhiyun 	return ret;
1793*4882a593Smuzhiyun }
1794*4882a593Smuzhiyun 
1795*4882a593Smuzhiyun /**
1796*4882a593Smuzhiyun  *  @brief Set/Get network monitor configurations
1797*4882a593Smuzhiyun  *
1798*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
1799*4882a593Smuzhiyun  *  @param wrq          A pointer to iwreq structure
1800*4882a593Smuzhiyun  *
1801*4882a593Smuzhiyun  *  @return             0 --success, otherwise fail
1802*4882a593Smuzhiyun  */
woal_net_monitor_ioctl(moal_private * priv,struct iwreq * wrq)1803*4882a593Smuzhiyun static int woal_net_monitor_ioctl(moal_private *priv, struct iwreq *wrq)
1804*4882a593Smuzhiyun {
1805*4882a593Smuzhiyun 	int user_data_len = wrq->u.data.length;
1806*4882a593Smuzhiyun 	int data[5] = {0}, copy_len;
1807*4882a593Smuzhiyun 	int ret = 0;
1808*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
1809*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = NULL;
1810*4882a593Smuzhiyun 	mlan_ds_misc_net_monitor *net_mon = NULL;
1811*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
1812*4882a593Smuzhiyun 
1813*4882a593Smuzhiyun 	ENTER();
1814*4882a593Smuzhiyun 
1815*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * user_data_len);
1816*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1817*4882a593Smuzhiyun 	if (req == NULL) {
1818*4882a593Smuzhiyun 		LEAVE();
1819*4882a593Smuzhiyun 		return -ENOMEM;
1820*4882a593Smuzhiyun 	}
1821*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)req->pbuf;
1822*4882a593Smuzhiyun 	net_mon = (mlan_ds_misc_net_monitor *)&misc->param.net_mon;
1823*4882a593Smuzhiyun 	misc->sub_command = MLAN_OID_MISC_NET_MONITOR;
1824*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_MISC_CFG;
1825*4882a593Smuzhiyun 
1826*4882a593Smuzhiyun 	if (!user_data_len) {
1827*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
1828*4882a593Smuzhiyun 	} else if (user_data_len == 1 || user_data_len == 4 ||
1829*4882a593Smuzhiyun 		   user_data_len == 5) {
1830*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
1831*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
1832*4882a593Smuzhiyun 			ret = -EFAULT;
1833*4882a593Smuzhiyun 			goto done;
1834*4882a593Smuzhiyun 		}
1835*4882a593Smuzhiyun 		if (data[0] != MTRUE && data[0] != MFALSE) {
1836*4882a593Smuzhiyun 			PRINTM(MERROR,
1837*4882a593Smuzhiyun 			       "NET_MON: Activity should be enable(=1)/disable(=0)\n");
1838*4882a593Smuzhiyun 			ret = -EINVAL;
1839*4882a593Smuzhiyun 			goto done;
1840*4882a593Smuzhiyun 		}
1841*4882a593Smuzhiyun 		net_mon->enable_net_mon = data[0];
1842*4882a593Smuzhiyun 		if (data[0] == MTRUE) {
1843*4882a593Smuzhiyun 			int i;
1844*4882a593Smuzhiyun 			if (user_data_len != 4 && user_data_len != 5) {
1845*4882a593Smuzhiyun 				PRINTM(MERROR,
1846*4882a593Smuzhiyun 				       "NET_MON: Invalid number of args!\n");
1847*4882a593Smuzhiyun 				ret = -EINVAL;
1848*4882a593Smuzhiyun 				goto done;
1849*4882a593Smuzhiyun 			}
1850*4882a593Smuzhiyun 			/* Supported filter flags */
1851*4882a593Smuzhiyun 			if (!data[1] ||
1852*4882a593Smuzhiyun 			    data[1] & ~(MLAN_NETMON_DATA_FRAME |
1853*4882a593Smuzhiyun 					MLAN_NETMON_MANAGEMENT_FRAME |
1854*4882a593Smuzhiyun 					MLAN_NETMON_CONTROL_FRAME)) {
1855*4882a593Smuzhiyun 				PRINTM(MERROR,
1856*4882a593Smuzhiyun 				       "NET_MON: Invalid filter flag\n");
1857*4882a593Smuzhiyun 				ret = -EINVAL;
1858*4882a593Smuzhiyun 				goto done;
1859*4882a593Smuzhiyun 			}
1860*4882a593Smuzhiyun 			/* Supported bands */
1861*4882a593Smuzhiyun 			for (i = 0; i < (int)sizeof(SupportedInfraBand); i++)
1862*4882a593Smuzhiyun 				if (data[2] == SupportedInfraBand[i])
1863*4882a593Smuzhiyun 					break;
1864*4882a593Smuzhiyun 			if (i == sizeof(SupportedInfraBand)) {
1865*4882a593Smuzhiyun 				PRINTM(MERROR, "NET_MON: Invalid band\n");
1866*4882a593Smuzhiyun 				ret = -EINVAL;
1867*4882a593Smuzhiyun 				goto done;
1868*4882a593Smuzhiyun 			}
1869*4882a593Smuzhiyun 			/* Supported channel */
1870*4882a593Smuzhiyun 			if (data[3] < 1 || data[3] > MLAN_MAX_CHANNEL) {
1871*4882a593Smuzhiyun 				PRINTM(MERROR,
1872*4882a593Smuzhiyun 				       "NET_MON: Invalid channel number\n");
1873*4882a593Smuzhiyun 				ret = -EINVAL;
1874*4882a593Smuzhiyun 				goto done;
1875*4882a593Smuzhiyun 			}
1876*4882a593Smuzhiyun 			if (user_data_len == 5) {
1877*4882a593Smuzhiyun 				/* Secondary channel offset */
1878*4882a593Smuzhiyun 				if (!(data[2] & (BAND_GN | BAND_AN))) {
1879*4882a593Smuzhiyun 					PRINTM(MERROR,
1880*4882a593Smuzhiyun 					       "No 11n in band, can not set "
1881*4882a593Smuzhiyun 					       "secondary channel offset\n");
1882*4882a593Smuzhiyun 					ret = -EINVAL;
1883*4882a593Smuzhiyun 					goto done;
1884*4882a593Smuzhiyun 				}
1885*4882a593Smuzhiyun 				if ((data[4] != CHANNEL_BW_20MHZ) &&
1886*4882a593Smuzhiyun 				    (data[4] != CHANNEL_BW_40MHZ_ABOVE) &&
1887*4882a593Smuzhiyun 				    (data[4] != CHANNEL_BW_40MHZ_BELOW) &&
1888*4882a593Smuzhiyun 				    (data[4] != CHANNEL_BW_80MHZ)) {
1889*4882a593Smuzhiyun 					PRINTM(MERROR,
1890*4882a593Smuzhiyun 					       "Invalid secondary channel bandwidth, "
1891*4882a593Smuzhiyun 					       "only allowed 0, 1, 3 or 4\n");
1892*4882a593Smuzhiyun 					ret = -EINVAL;
1893*4882a593Smuzhiyun 					goto done;
1894*4882a593Smuzhiyun 				}
1895*4882a593Smuzhiyun 				net_mon->chan_bandwidth = data[4];
1896*4882a593Smuzhiyun 			}
1897*4882a593Smuzhiyun 			net_mon->filter_flag = data[1];
1898*4882a593Smuzhiyun 			net_mon->band = data[2];
1899*4882a593Smuzhiyun 			net_mon->channel = data[3];
1900*4882a593Smuzhiyun 		}
1901*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
1902*4882a593Smuzhiyun 	} else {
1903*4882a593Smuzhiyun 		PRINTM(MERROR, "NET_MON: Invalid number of args!\n");
1904*4882a593Smuzhiyun 		ret = -EINVAL;
1905*4882a593Smuzhiyun 		goto done;
1906*4882a593Smuzhiyun 	}
1907*4882a593Smuzhiyun 
1908*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1909*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
1910*4882a593Smuzhiyun 		ret = -EFAULT;
1911*4882a593Smuzhiyun 		goto done;
1912*4882a593Smuzhiyun 	}
1913*4882a593Smuzhiyun 
1914*4882a593Smuzhiyun 	data[0] = net_mon->enable_net_mon;
1915*4882a593Smuzhiyun 	data[1] = net_mon->filter_flag;
1916*4882a593Smuzhiyun 	data[2] = net_mon->band;
1917*4882a593Smuzhiyun 	data[3] = net_mon->channel;
1918*4882a593Smuzhiyun 	data[4] = net_mon->chan_bandwidth;
1919*4882a593Smuzhiyun 	wrq->u.data.length = 5;
1920*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, data,
1921*4882a593Smuzhiyun 			 sizeof(int) * wrq->u.data.length)) {
1922*4882a593Smuzhiyun 		PRINTM(MERROR, "Copy to user failed\n");
1923*4882a593Smuzhiyun 		ret = -EFAULT;
1924*4882a593Smuzhiyun 		goto done;
1925*4882a593Smuzhiyun 	}
1926*4882a593Smuzhiyun 
1927*4882a593Smuzhiyun done:
1928*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
1929*4882a593Smuzhiyun 		kfree(req);
1930*4882a593Smuzhiyun 	LEAVE();
1931*4882a593Smuzhiyun 	return ret;
1932*4882a593Smuzhiyun }
1933*4882a593Smuzhiyun 
1934*4882a593Smuzhiyun /**
1935*4882a593Smuzhiyun  *  @brief Get LOG
1936*4882a593Smuzhiyun  *
1937*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
1938*4882a593Smuzhiyun  *  @param wrq          A pointer to iwreq structure
1939*4882a593Smuzhiyun  *
1940*4882a593Smuzhiyun  *  @return             0 --success, otherwise fail
1941*4882a593Smuzhiyun  */
woal_get_log(moal_private * priv,struct iwreq * wrq)1942*4882a593Smuzhiyun static int woal_get_log(moal_private *priv, struct iwreq *wrq)
1943*4882a593Smuzhiyun {
1944*4882a593Smuzhiyun 	int ret = 0;
1945*4882a593Smuzhiyun 	mlan_ds_get_stats stats;
1946*4882a593Smuzhiyun 	char *buf = NULL;
1947*4882a593Smuzhiyun 	int i = 0;
1948*4882a593Smuzhiyun 
1949*4882a593Smuzhiyun 	ENTER();
1950*4882a593Smuzhiyun 
1951*4882a593Smuzhiyun 	PRINTM(MINFO, " GET STATS\n");
1952*4882a593Smuzhiyun 	buf = kmalloc(GETLOG_BUFSIZE, GFP_KERNEL);
1953*4882a593Smuzhiyun 	if (!buf) {
1954*4882a593Smuzhiyun 		PRINTM(MERROR, "kmalloc failed!\n");
1955*4882a593Smuzhiyun 		ret = -ENOMEM;
1956*4882a593Smuzhiyun 		goto done;
1957*4882a593Smuzhiyun 	}
1958*4882a593Smuzhiyun 
1959*4882a593Smuzhiyun 	memset(&stats, 0, sizeof(mlan_ds_get_stats));
1960*4882a593Smuzhiyun 	if (MLAN_STATUS_SUCCESS !=
1961*4882a593Smuzhiyun 	    woal_get_stats_info(priv, MOAL_IOCTL_WAIT, &stats)) {
1962*4882a593Smuzhiyun 		ret = -EFAULT;
1963*4882a593Smuzhiyun 		goto done;
1964*4882a593Smuzhiyun 	}
1965*4882a593Smuzhiyun 
1966*4882a593Smuzhiyun 	if (wrq->u.data.pointer) {
1967*4882a593Smuzhiyun 		sprintf(buf,
1968*4882a593Smuzhiyun 			"\n"
1969*4882a593Smuzhiyun 			"mcasttxframe     %u\n"
1970*4882a593Smuzhiyun 			"failed           %u\n"
1971*4882a593Smuzhiyun 			"retry            %u\n"
1972*4882a593Smuzhiyun 			"multiretry       %u\n"
1973*4882a593Smuzhiyun 			"framedup         %u\n"
1974*4882a593Smuzhiyun 			"rtssuccess       %u\n"
1975*4882a593Smuzhiyun 			"rtsfailure       %u\n"
1976*4882a593Smuzhiyun 			"ackfailure       %u\n"
1977*4882a593Smuzhiyun 			"rxfrag           %u\n"
1978*4882a593Smuzhiyun 			"mcastrxframe     %u\n"
1979*4882a593Smuzhiyun 			"fcserror         %u\n"
1980*4882a593Smuzhiyun 			"txframe          %u\n"
1981*4882a593Smuzhiyun 			"wepicverrcnt-1   %u\n"
1982*4882a593Smuzhiyun 			"wepicverrcnt-2   %u\n"
1983*4882a593Smuzhiyun 			"wepicverrcnt-3   %u\n"
1984*4882a593Smuzhiyun 			"wepicverrcnt-4   %u\n"
1985*4882a593Smuzhiyun 			"beacon_rcnt      %u\n"
1986*4882a593Smuzhiyun 			"beacon_mcnt      %u\n",
1987*4882a593Smuzhiyun 			stats.mcast_tx_frame, stats.failed, stats.retry,
1988*4882a593Smuzhiyun 			stats.multi_retry, stats.frame_dup, stats.rts_success,
1989*4882a593Smuzhiyun 			stats.rts_failure, stats.ack_failure, stats.rx_frag,
1990*4882a593Smuzhiyun 			stats.mcast_rx_frame, stats.fcs_error, stats.tx_frame,
1991*4882a593Smuzhiyun 			stats.wep_icv_error[0], stats.wep_icv_error[1],
1992*4882a593Smuzhiyun 			stats.wep_icv_error[2], stats.wep_icv_error[3],
1993*4882a593Smuzhiyun 			stats.bcn_rcv_cnt, stats.bcn_miss_cnt);
1994*4882a593Smuzhiyun 		if (priv->phandle->fw_getlog_enable) {
1995*4882a593Smuzhiyun 			sprintf(buf + strlen(buf), "tx_frag_cnt       %u\n",
1996*4882a593Smuzhiyun 				stats.tx_frag_cnt);
1997*4882a593Smuzhiyun 			sprintf(buf + strlen(buf), "qos_tx_frag_cnt        ");
1998*4882a593Smuzhiyun 			for (i = 0; i < 8; i++) {
1999*4882a593Smuzhiyun 				sprintf(buf + strlen(buf), "%u ",
2000*4882a593Smuzhiyun 					stats.qos_tx_frag_cnt[i]);
2001*4882a593Smuzhiyun 			}
2002*4882a593Smuzhiyun 			sprintf(buf + strlen(buf), "\nqos_failed_cnt         ");
2003*4882a593Smuzhiyun 			for (i = 0; i < 8; i++) {
2004*4882a593Smuzhiyun 				sprintf(buf + strlen(buf), "%u ",
2005*4882a593Smuzhiyun 					stats.qos_failed_cnt[i]);
2006*4882a593Smuzhiyun 			}
2007*4882a593Smuzhiyun 			sprintf(buf + strlen(buf), "\nqos_retry_cnt          ");
2008*4882a593Smuzhiyun 			for (i = 0; i < 8; i++) {
2009*4882a593Smuzhiyun 				sprintf(buf + strlen(buf), "%u ",
2010*4882a593Smuzhiyun 					stats.qos_retry_cnt[i]);
2011*4882a593Smuzhiyun 			}
2012*4882a593Smuzhiyun 			sprintf(buf + strlen(buf), "\nqos_multi_retry_cnt    ");
2013*4882a593Smuzhiyun 			for (i = 0; i < 8; i++) {
2014*4882a593Smuzhiyun 				sprintf(buf + strlen(buf), "%u ",
2015*4882a593Smuzhiyun 					stats.qos_multi_retry_cnt[i]);
2016*4882a593Smuzhiyun 			}
2017*4882a593Smuzhiyun 			sprintf(buf + strlen(buf), "\nqos_frm_dup_cnt        ");
2018*4882a593Smuzhiyun 			for (i = 0; i < 8; i++) {
2019*4882a593Smuzhiyun 				sprintf(buf + strlen(buf), "%u ",
2020*4882a593Smuzhiyun 					stats.qos_frm_dup_cnt[i]);
2021*4882a593Smuzhiyun 			}
2022*4882a593Smuzhiyun 			sprintf(buf + strlen(buf), "\nqos_rts_suc_cnt        ");
2023*4882a593Smuzhiyun 			for (i = 0; i < 8; i++) {
2024*4882a593Smuzhiyun 				sprintf(buf + strlen(buf), "%u ",
2025*4882a593Smuzhiyun 					stats.qos_rts_suc_cnt[i]);
2026*4882a593Smuzhiyun 			}
2027*4882a593Smuzhiyun 			sprintf(buf + strlen(buf),
2028*4882a593Smuzhiyun 				"\nqos_rts_failure_cnt        ");
2029*4882a593Smuzhiyun 			for (i = 0; i < 8; i++) {
2030*4882a593Smuzhiyun 				sprintf(buf + strlen(buf), "%u ",
2031*4882a593Smuzhiyun 					stats.qos_rts_failure_cnt[i]);
2032*4882a593Smuzhiyun 			}
2033*4882a593Smuzhiyun 			sprintf(buf + strlen(buf), "\nqos_ack_failure_cnt    ");
2034*4882a593Smuzhiyun 			for (i = 0; i < 8; i++) {
2035*4882a593Smuzhiyun 				sprintf(buf + strlen(buf), "%u ",
2036*4882a593Smuzhiyun 					stats.qos_ack_failure_cnt[i]);
2037*4882a593Smuzhiyun 			}
2038*4882a593Smuzhiyun 			sprintf(buf + strlen(buf), "\nqos_rx_frag_cnt        ");
2039*4882a593Smuzhiyun 			for (i = 0; i < 8; i++) {
2040*4882a593Smuzhiyun 				sprintf(buf + strlen(buf), "%u ",
2041*4882a593Smuzhiyun 					stats.qos_rx_frag_cnt[i]);
2042*4882a593Smuzhiyun 			}
2043*4882a593Smuzhiyun 			sprintf(buf + strlen(buf), "\nqos_tx_frm_cnt         ");
2044*4882a593Smuzhiyun 			for (i = 0; i < 8; i++) {
2045*4882a593Smuzhiyun 				sprintf(buf + strlen(buf), "%u ",
2046*4882a593Smuzhiyun 					stats.qos_tx_frm_cnt[i]);
2047*4882a593Smuzhiyun 			}
2048*4882a593Smuzhiyun 			sprintf(buf + strlen(buf), "\nqos_discarded_frm_cnt  ");
2049*4882a593Smuzhiyun 			for (i = 0; i < 8; i++) {
2050*4882a593Smuzhiyun 				sprintf(buf + strlen(buf), "%u ",
2051*4882a593Smuzhiyun 					stats.qos_discarded_frm_cnt[i]);
2052*4882a593Smuzhiyun 			}
2053*4882a593Smuzhiyun 			sprintf(buf + strlen(buf), "\nqos_mpdus_rx_cnt       ");
2054*4882a593Smuzhiyun 			for (i = 0; i < 8; i++) {
2055*4882a593Smuzhiyun 				sprintf(buf + strlen(buf), "%u ",
2056*4882a593Smuzhiyun 					stats.qos_mpdus_rx_cnt[i]);
2057*4882a593Smuzhiyun 			}
2058*4882a593Smuzhiyun 			sprintf(buf + strlen(buf), "\nqos_retries_rx_cnt     ");
2059*4882a593Smuzhiyun 			for (i = 0; i < 8; i++) {
2060*4882a593Smuzhiyun 				sprintf(buf + strlen(buf), "%u ",
2061*4882a593Smuzhiyun 					stats.qos_retries_rx_cnt[i]);
2062*4882a593Smuzhiyun 			}
2063*4882a593Smuzhiyun 			sprintf(buf + strlen(buf),
2064*4882a593Smuzhiyun 				"\nmgmt_ccmp_replays      %u\n"
2065*4882a593Smuzhiyun 				"tx_amsdu_cnt           %u\n"
2066*4882a593Smuzhiyun 				"failed_amsdu_cnt       %u\n"
2067*4882a593Smuzhiyun 				"retry_amsdu_cnt        %u\n"
2068*4882a593Smuzhiyun 				"multi_retry_amsdu_cnt  %u\n"
2069*4882a593Smuzhiyun 				"tx_octets_in_amsdu_cnt %llu\n"
2070*4882a593Smuzhiyun 				"amsdu_ack_failure_cnt  %u\n"
2071*4882a593Smuzhiyun 				"rx_amsdu_cnt           %u\n"
2072*4882a593Smuzhiyun 				"rx_octets_in_amsdu_cnt %llu\n"
2073*4882a593Smuzhiyun 				"tx_ampdu_cnt           %u\n"
2074*4882a593Smuzhiyun 				"tx_mpdus_in_ampdu_cnt  %u\n"
2075*4882a593Smuzhiyun 				"tx_octets_in_ampdu_cnt %llu\n"
2076*4882a593Smuzhiyun 				"ampdu_rx_cnt           %u\n"
2077*4882a593Smuzhiyun 				"mpdu_in_rx_ampdu_cnt   %u\n"
2078*4882a593Smuzhiyun 				"rx_octets_in_ampdu_cnt %llu\n"
2079*4882a593Smuzhiyun 				"ampdu_delimiter_crc_error_cnt      %u\n",
2080*4882a593Smuzhiyun 				stats.mgmt_ccmp_replays, stats.tx_amsdu_cnt,
2081*4882a593Smuzhiyun 				stats.failed_amsdu_cnt, stats.retry_amsdu_cnt,
2082*4882a593Smuzhiyun 				stats.multi_retry_amsdu_cnt,
2083*4882a593Smuzhiyun 				stats.tx_octets_in_amsdu_cnt,
2084*4882a593Smuzhiyun 				stats.amsdu_ack_failure_cnt, stats.rx_amsdu_cnt,
2085*4882a593Smuzhiyun 				stats.rx_octets_in_amsdu_cnt,
2086*4882a593Smuzhiyun 				stats.tx_ampdu_cnt, stats.tx_mpdus_in_ampdu_cnt,
2087*4882a593Smuzhiyun 				stats.tx_octets_in_ampdu_cnt,
2088*4882a593Smuzhiyun 				stats.ampdu_rx_cnt, stats.mpdu_in_rx_ampdu_cnt,
2089*4882a593Smuzhiyun 				stats.rx_octets_in_ampdu_cnt,
2090*4882a593Smuzhiyun 				stats.ampdu_delimiter_crc_error_cnt);
2091*4882a593Smuzhiyun 		}
2092*4882a593Smuzhiyun 		wrq->u.data.length = MIN(GETLOG_BUFSIZE - 1, strlen(buf) + 1);
2093*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, buf,
2094*4882a593Smuzhiyun 				 wrq->u.data.length)) {
2095*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
2096*4882a593Smuzhiyun 			ret = -EFAULT;
2097*4882a593Smuzhiyun 		}
2098*4882a593Smuzhiyun 	}
2099*4882a593Smuzhiyun done:
2100*4882a593Smuzhiyun 	kfree(buf);
2101*4882a593Smuzhiyun 	LEAVE();
2102*4882a593Smuzhiyun 	return ret;
2103*4882a593Smuzhiyun }
2104*4882a593Smuzhiyun 
2105*4882a593Smuzhiyun /**
2106*4882a593Smuzhiyun  *  @brief Deauthenticate
2107*4882a593Smuzhiyun  *
2108*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
2109*4882a593Smuzhiyun  *  @param wrq          A pointer to iwreq structure
2110*4882a593Smuzhiyun  *
2111*4882a593Smuzhiyun  *  @return             0 --success, otherwise fail
2112*4882a593Smuzhiyun  */
woal_deauth(moal_private * priv,struct iwreq * wrq)2113*4882a593Smuzhiyun static int woal_deauth(moal_private *priv, struct iwreq *wrq)
2114*4882a593Smuzhiyun {
2115*4882a593Smuzhiyun 	int ret = 0;
2116*4882a593Smuzhiyun 	struct sockaddr saddr;
2117*4882a593Smuzhiyun 
2118*4882a593Smuzhiyun 	ENTER();
2119*4882a593Smuzhiyun 	if (wrq->u.data.length) {
2120*4882a593Smuzhiyun 		/* Deauth mentioned BSSID */
2121*4882a593Smuzhiyun 		if (copy_from_user(&saddr, wrq->u.data.pointer,
2122*4882a593Smuzhiyun 				   sizeof(saddr))) {
2123*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
2124*4882a593Smuzhiyun 			ret = -EFAULT;
2125*4882a593Smuzhiyun 			goto done;
2126*4882a593Smuzhiyun 		}
2127*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS !=
2128*4882a593Smuzhiyun 		    woal_disconnect(priv, MOAL_IOCTL_WAIT,
2129*4882a593Smuzhiyun 				    (t_u8 *)saddr.sa_data,
2130*4882a593Smuzhiyun 				    DEF_DEAUTH_REASON_CODE)) {
2131*4882a593Smuzhiyun 			ret = -EFAULT;
2132*4882a593Smuzhiyun 			goto done;
2133*4882a593Smuzhiyun 		}
2134*4882a593Smuzhiyun 	} else {
2135*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS !=
2136*4882a593Smuzhiyun 		    woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL,
2137*4882a593Smuzhiyun 				    DEF_DEAUTH_REASON_CODE))
2138*4882a593Smuzhiyun 			ret = -EFAULT;
2139*4882a593Smuzhiyun 	}
2140*4882a593Smuzhiyun done:
2141*4882a593Smuzhiyun 	LEAVE();
2142*4882a593Smuzhiyun 	return ret;
2143*4882a593Smuzhiyun }
2144*4882a593Smuzhiyun 
2145*4882a593Smuzhiyun /**
2146*4882a593Smuzhiyun  *  @brief Set/Get TX power configurations
2147*4882a593Smuzhiyun  *
2148*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
2149*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
2150*4882a593Smuzhiyun  *
2151*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
2152*4882a593Smuzhiyun  */
woal_tx_power_cfg(moal_private * priv,struct iwreq * wrq)2153*4882a593Smuzhiyun static int woal_tx_power_cfg(moal_private *priv, struct iwreq *wrq)
2154*4882a593Smuzhiyun {
2155*4882a593Smuzhiyun 	int data[5], user_data_len, copy_len;
2156*4882a593Smuzhiyun 	int ret = 0;
2157*4882a593Smuzhiyun 	mlan_bss_info bss_info;
2158*4882a593Smuzhiyun 	mlan_ds_power_cfg *pcfg = NULL;
2159*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
2160*4882a593Smuzhiyun 	int power_data[MAX_POWER_TABLE_SIZE];
2161*4882a593Smuzhiyun 	int i, power_ext_len = 0;
2162*4882a593Smuzhiyun 	int *ptr = power_data;
2163*4882a593Smuzhiyun 	mlan_power_group *pwr_grp = NULL;
2164*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
2165*4882a593Smuzhiyun 	ENTER();
2166*4882a593Smuzhiyun 
2167*4882a593Smuzhiyun 	memset(&bss_info, 0, sizeof(bss_info));
2168*4882a593Smuzhiyun 	woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
2169*4882a593Smuzhiyun 
2170*4882a593Smuzhiyun 	memset(data, 0, sizeof(data));
2171*4882a593Smuzhiyun 	user_data_len = wrq->u.data.length;
2172*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * user_data_len);
2173*4882a593Smuzhiyun 
2174*4882a593Smuzhiyun 	if (user_data_len) {
2175*4882a593Smuzhiyun 		if (sizeof(int) * user_data_len > sizeof(data)) {
2176*4882a593Smuzhiyun 			PRINTM(MERROR, "Too many arguments\n");
2177*4882a593Smuzhiyun 			ret = -EINVAL;
2178*4882a593Smuzhiyun 			goto done;
2179*4882a593Smuzhiyun 		}
2180*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
2181*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
2182*4882a593Smuzhiyun 			ret = -EFAULT;
2183*4882a593Smuzhiyun 			goto done;
2184*4882a593Smuzhiyun 		}
2185*4882a593Smuzhiyun 		switch (user_data_len) {
2186*4882a593Smuzhiyun 		case 1:
2187*4882a593Smuzhiyun 			if (data[0] != 0xFF)
2188*4882a593Smuzhiyun 				ret = -EINVAL;
2189*4882a593Smuzhiyun 			break;
2190*4882a593Smuzhiyun 		case 2:
2191*4882a593Smuzhiyun 		case 4:
2192*4882a593Smuzhiyun 			if (data[0] == 0xFF) {
2193*4882a593Smuzhiyun 				ret = -EINVAL;
2194*4882a593Smuzhiyun 				break;
2195*4882a593Smuzhiyun 			}
2196*4882a593Smuzhiyun 			if (data[1] < bss_info.min_power_level) {
2197*4882a593Smuzhiyun 				PRINTM(MERROR,
2198*4882a593Smuzhiyun 				       "The set powercfg rate value %d dBm is out of range (%d dBm-%d dBm)!\n",
2199*4882a593Smuzhiyun 				       data[1], (int)bss_info.min_power_level,
2200*4882a593Smuzhiyun 				       (int)bss_info.max_power_level);
2201*4882a593Smuzhiyun 				ret = -EINVAL;
2202*4882a593Smuzhiyun 				break;
2203*4882a593Smuzhiyun 			}
2204*4882a593Smuzhiyun 			if (user_data_len == 4) {
2205*4882a593Smuzhiyun 				if (data[1] > data[2]) {
2206*4882a593Smuzhiyun 					PRINTM(MERROR,
2207*4882a593Smuzhiyun 					       "Min power should be less than maximum!\n");
2208*4882a593Smuzhiyun 					ret = -EINVAL;
2209*4882a593Smuzhiyun 					break;
2210*4882a593Smuzhiyun 				}
2211*4882a593Smuzhiyun 				if (data[3] < 0) {
2212*4882a593Smuzhiyun 					PRINTM(MERROR,
2213*4882a593Smuzhiyun 					       "Step should not less than 0!\n");
2214*4882a593Smuzhiyun 					ret = -EINVAL;
2215*4882a593Smuzhiyun 					break;
2216*4882a593Smuzhiyun 				}
2217*4882a593Smuzhiyun 				if (data[2] > bss_info.max_power_level) {
2218*4882a593Smuzhiyun 					PRINTM(MERROR,
2219*4882a593Smuzhiyun 					       "The set powercfg rate value %d dBm is out of range (%d dBm-%d dBm)!\n",
2220*4882a593Smuzhiyun 					       data[2],
2221*4882a593Smuzhiyun 					       (int)bss_info.min_power_level,
2222*4882a593Smuzhiyun 					       (int)bss_info.max_power_level);
2223*4882a593Smuzhiyun 					ret = -EINVAL;
2224*4882a593Smuzhiyun 					break;
2225*4882a593Smuzhiyun 				}
2226*4882a593Smuzhiyun 				if (data[3] > data[2] - data[1]) {
2227*4882a593Smuzhiyun 					PRINTM(MERROR,
2228*4882a593Smuzhiyun 					       "Step should not greater than power difference!\n");
2229*4882a593Smuzhiyun 					ret = -EINVAL;
2230*4882a593Smuzhiyun 					break;
2231*4882a593Smuzhiyun 				}
2232*4882a593Smuzhiyun 			}
2233*4882a593Smuzhiyun 			break;
2234*4882a593Smuzhiyun 		default:
2235*4882a593Smuzhiyun 			ret = -EINVAL;
2236*4882a593Smuzhiyun 			break;
2237*4882a593Smuzhiyun 		}
2238*4882a593Smuzhiyun 		if (ret)
2239*4882a593Smuzhiyun 			goto done;
2240*4882a593Smuzhiyun 	}
2241*4882a593Smuzhiyun 
2242*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_power_cfg));
2243*4882a593Smuzhiyun 	if (req == NULL) {
2244*4882a593Smuzhiyun 		ret = -ENOMEM;
2245*4882a593Smuzhiyun 		goto done;
2246*4882a593Smuzhiyun 	}
2247*4882a593Smuzhiyun 	pcfg = (mlan_ds_power_cfg *)req->pbuf;
2248*4882a593Smuzhiyun 	pcfg->sub_command = MLAN_OID_POWER_CFG_EXT;
2249*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_POWER_CFG;
2250*4882a593Smuzhiyun 	if (!user_data_len)
2251*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
2252*4882a593Smuzhiyun 	else {
2253*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
2254*4882a593Smuzhiyun 		if (data[0] == 0xFF)
2255*4882a593Smuzhiyun 			pcfg->param.power_ext.power_group[0].rate_format =
2256*4882a593Smuzhiyun 				TX_PWR_CFG_AUTO_CTRL_OFF;
2257*4882a593Smuzhiyun 		else {
2258*4882a593Smuzhiyun 			pcfg->param.power_ext.power_group[0].power_step = 0;
2259*4882a593Smuzhiyun 			pcfg->param.power_ext.power_group[0].first_rate_ind =
2260*4882a593Smuzhiyun 				data[0];
2261*4882a593Smuzhiyun 			pcfg->param.power_ext.power_group[0].last_rate_ind =
2262*4882a593Smuzhiyun 				data[0];
2263*4882a593Smuzhiyun 			if (data[0] <= 11) {
2264*4882a593Smuzhiyun 				pcfg->param.power_ext.power_group[0]
2265*4882a593Smuzhiyun 					.rate_format = MLAN_RATE_FORMAT_LG;
2266*4882a593Smuzhiyun 				pcfg->param.power_ext.power_group[0].bandwidth =
2267*4882a593Smuzhiyun 					MLAN_HT_BW20;
2268*4882a593Smuzhiyun 			} else if (data[0] <= 27) {
2269*4882a593Smuzhiyun 				pcfg->param.power_ext.power_group[0]
2270*4882a593Smuzhiyun 					.rate_format = MLAN_RATE_FORMAT_HT;
2271*4882a593Smuzhiyun 				pcfg->param.power_ext.power_group[0].bandwidth =
2272*4882a593Smuzhiyun 					MLAN_HT_BW20;
2273*4882a593Smuzhiyun 				pcfg->param.power_ext.power_group[0]
2274*4882a593Smuzhiyun 					.first_rate_ind -= 12;
2275*4882a593Smuzhiyun 				pcfg->param.power_ext.power_group[0]
2276*4882a593Smuzhiyun 					.last_rate_ind -= 12;
2277*4882a593Smuzhiyun 			} else if ((140 <= data[0]) && (data[0] <= 155)) {
2278*4882a593Smuzhiyun 				pcfg->param.power_ext.power_group[0]
2279*4882a593Smuzhiyun 					.rate_format = MLAN_RATE_FORMAT_HT;
2280*4882a593Smuzhiyun 				pcfg->param.power_ext.power_group[0].bandwidth =
2281*4882a593Smuzhiyun 					MLAN_HT_BW40;
2282*4882a593Smuzhiyun 				pcfg->param.power_ext.power_group[0]
2283*4882a593Smuzhiyun 					.first_rate_ind -= 140;
2284*4882a593Smuzhiyun 				pcfg->param.power_ext.power_group[0]
2285*4882a593Smuzhiyun 					.last_rate_ind -= 140;
2286*4882a593Smuzhiyun 			}
2287*4882a593Smuzhiyun 			if (user_data_len == 2) {
2288*4882a593Smuzhiyun 				pcfg->param.power_ext.power_group[0].power_min =
2289*4882a593Smuzhiyun 					data[1];
2290*4882a593Smuzhiyun 				pcfg->param.power_ext.power_group[0].power_max =
2291*4882a593Smuzhiyun 					data[1];
2292*4882a593Smuzhiyun 			} else if (user_data_len == 4) {
2293*4882a593Smuzhiyun 				pcfg->param.power_ext.power_group[0].power_min =
2294*4882a593Smuzhiyun 					data[1];
2295*4882a593Smuzhiyun 				pcfg->param.power_ext.power_group[0].power_max =
2296*4882a593Smuzhiyun 					data[2];
2297*4882a593Smuzhiyun 				pcfg->param.power_ext.power_group[0].power_step =
2298*4882a593Smuzhiyun 					data[3];
2299*4882a593Smuzhiyun 			}
2300*4882a593Smuzhiyun 			pcfg->param.power_ext.num_pwr_grp = 1;
2301*4882a593Smuzhiyun 		}
2302*4882a593Smuzhiyun 	}
2303*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2304*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
2305*4882a593Smuzhiyun 		ret = -EFAULT;
2306*4882a593Smuzhiyun 		goto done;
2307*4882a593Smuzhiyun 	}
2308*4882a593Smuzhiyun 	if (!user_data_len) {
2309*4882a593Smuzhiyun 		/* GET operation */
2310*4882a593Smuzhiyun 		i = 0;
2311*4882a593Smuzhiyun 		power_ext_len = 0;
2312*4882a593Smuzhiyun 		ptr = power_data;
2313*4882a593Smuzhiyun 		while ((i < (int)pcfg->param.power_ext.num_pwr_grp) &&
2314*4882a593Smuzhiyun 		       ((power_ext_len + 5) < MAX_POWER_TABLE_SIZE)) {
2315*4882a593Smuzhiyun 			pwr_grp = &pcfg->param.power_ext.power_group[i];
2316*4882a593Smuzhiyun 			if (pwr_grp->rate_format == MLAN_RATE_FORMAT_HT) {
2317*4882a593Smuzhiyun 				if (pwr_grp->bandwidth == MLAN_HT_BW20) {
2318*4882a593Smuzhiyun 					pwr_grp->first_rate_ind += 12;
2319*4882a593Smuzhiyun 					pwr_grp->last_rate_ind += 12;
2320*4882a593Smuzhiyun 				} else if (pwr_grp->bandwidth == MLAN_HT_BW40) {
2321*4882a593Smuzhiyun 					pwr_grp->first_rate_ind += 140;
2322*4882a593Smuzhiyun 					pwr_grp->last_rate_ind += 140;
2323*4882a593Smuzhiyun 				}
2324*4882a593Smuzhiyun 			}
2325*4882a593Smuzhiyun 
2326*4882a593Smuzhiyun 			if ((pwr_grp->rate_format == MLAN_RATE_FORMAT_LG) ||
2327*4882a593Smuzhiyun 			    (pwr_grp->rate_format == MLAN_RATE_FORMAT_HT)) {
2328*4882a593Smuzhiyun 				*ptr = pwr_grp->first_rate_ind;
2329*4882a593Smuzhiyun 				ptr++;
2330*4882a593Smuzhiyun 				*ptr = pwr_grp->last_rate_ind;
2331*4882a593Smuzhiyun 				ptr++;
2332*4882a593Smuzhiyun 				*ptr = pwr_grp->power_min;
2333*4882a593Smuzhiyun 				ptr++;
2334*4882a593Smuzhiyun 				*ptr = pwr_grp->power_max;
2335*4882a593Smuzhiyun 				ptr++;
2336*4882a593Smuzhiyun 				*ptr = pwr_grp->power_step;
2337*4882a593Smuzhiyun 				ptr++;
2338*4882a593Smuzhiyun 				power_ext_len += 5;
2339*4882a593Smuzhiyun 			}
2340*4882a593Smuzhiyun 			i++;
2341*4882a593Smuzhiyun 		}
2342*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, (t_u8 *)power_data,
2343*4882a593Smuzhiyun 				 sizeof(int) * power_ext_len)) {
2344*4882a593Smuzhiyun 			ret = -EFAULT;
2345*4882a593Smuzhiyun 			goto done;
2346*4882a593Smuzhiyun 		}
2347*4882a593Smuzhiyun 		wrq->u.data.length = power_ext_len;
2348*4882a593Smuzhiyun 	}
2349*4882a593Smuzhiyun done:
2350*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
2351*4882a593Smuzhiyun 		kfree(req);
2352*4882a593Smuzhiyun 	LEAVE();
2353*4882a593Smuzhiyun 	return ret;
2354*4882a593Smuzhiyun }
2355*4882a593Smuzhiyun 
2356*4882a593Smuzhiyun /**
2357*4882a593Smuzhiyun  *  @brief Get Tx/Rx data rates
2358*4882a593Smuzhiyun  *
2359*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
2360*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
2361*4882a593Smuzhiyun  *
2362*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
2363*4882a593Smuzhiyun  */
woal_get_txrx_rate(moal_private * priv,struct iwreq * wrq)2364*4882a593Smuzhiyun static int woal_get_txrx_rate(moal_private *priv, struct iwreq *wrq)
2365*4882a593Smuzhiyun {
2366*4882a593Smuzhiyun 	int ret = 0;
2367*4882a593Smuzhiyun 	mlan_ds_rate *rate = NULL;
2368*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
2369*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
2370*4882a593Smuzhiyun 
2371*4882a593Smuzhiyun 	ENTER();
2372*4882a593Smuzhiyun 
2373*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
2374*4882a593Smuzhiyun 	if (req == NULL) {
2375*4882a593Smuzhiyun 		ret = -ENOMEM;
2376*4882a593Smuzhiyun 		goto done;
2377*4882a593Smuzhiyun 	}
2378*4882a593Smuzhiyun 	rate = (mlan_ds_rate *)req->pbuf;
2379*4882a593Smuzhiyun 	rate->sub_command = MLAN_OID_GET_DATA_RATE;
2380*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_RATE;
2381*4882a593Smuzhiyun 	req->action = MLAN_ACT_GET;
2382*4882a593Smuzhiyun 
2383*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2384*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
2385*4882a593Smuzhiyun 		ret = -EFAULT;
2386*4882a593Smuzhiyun 		goto done;
2387*4882a593Smuzhiyun 	}
2388*4882a593Smuzhiyun 
2389*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, (t_u8 *)&rate->param.data_rate,
2390*4882a593Smuzhiyun 			 sizeof(int) * 2)) {
2391*4882a593Smuzhiyun 		ret = -EFAULT;
2392*4882a593Smuzhiyun 		goto done;
2393*4882a593Smuzhiyun 	}
2394*4882a593Smuzhiyun 	wrq->u.data.length = 2;
2395*4882a593Smuzhiyun done:
2396*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
2397*4882a593Smuzhiyun 		kfree(req);
2398*4882a593Smuzhiyun 	LEAVE();
2399*4882a593Smuzhiyun 	return ret;
2400*4882a593Smuzhiyun }
2401*4882a593Smuzhiyun 
2402*4882a593Smuzhiyun #ifdef SDIO
2403*4882a593Smuzhiyun /**
2404*4882a593Smuzhiyun  *  @brief Turn on/off the sdio clock
2405*4882a593Smuzhiyun  *
2406*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
2407*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
2408*4882a593Smuzhiyun  *
2409*4882a593Smuzhiyun  *  @return         0/MLAN_STATUS_SUCCESS --success, otherwise fail
2410*4882a593Smuzhiyun  */
woal_sdio_clock_ioctl(moal_private * priv,struct iwreq * wrq)2411*4882a593Smuzhiyun static int woal_sdio_clock_ioctl(moal_private *priv, struct iwreq *wrq)
2412*4882a593Smuzhiyun {
2413*4882a593Smuzhiyun 	int ret = 0;
2414*4882a593Smuzhiyun 	int data = 2;
2415*4882a593Smuzhiyun 	/* Initialize the clock state as on */
2416*4882a593Smuzhiyun 	static int clock_state = 1;
2417*4882a593Smuzhiyun 
2418*4882a593Smuzhiyun 	ENTER();
2419*4882a593Smuzhiyun 
2420*4882a593Smuzhiyun 	if (wrq->u.data.length) {
2421*4882a593Smuzhiyun 		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
2422*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
2423*4882a593Smuzhiyun 			ret = -EFAULT;
2424*4882a593Smuzhiyun 			goto done;
2425*4882a593Smuzhiyun 		}
2426*4882a593Smuzhiyun 	} else {
2427*4882a593Smuzhiyun 		wrq->u.data.length = sizeof(clock_state) / sizeof(int);
2428*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &clock_state,
2429*4882a593Smuzhiyun 				 sizeof(int))) {
2430*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
2431*4882a593Smuzhiyun 			ret = -EFAULT;
2432*4882a593Smuzhiyun 			goto done;
2433*4882a593Smuzhiyun 		}
2434*4882a593Smuzhiyun 
2435*4882a593Smuzhiyun 		goto done;
2436*4882a593Smuzhiyun 	}
2437*4882a593Smuzhiyun 	switch (data) {
2438*4882a593Smuzhiyun 	case CMD_DISABLED:
2439*4882a593Smuzhiyun 		PRINTM(MINFO, "SDIO clock is turned off\n");
2440*4882a593Smuzhiyun 		ret = woal_sdio_set_bus_clock(priv->phandle, MFALSE);
2441*4882a593Smuzhiyun 		clock_state = data;
2442*4882a593Smuzhiyun 		break;
2443*4882a593Smuzhiyun 	case CMD_ENABLED:
2444*4882a593Smuzhiyun 		PRINTM(MINFO, "SDIO clock is turned on\n");
2445*4882a593Smuzhiyun 		ret = woal_sdio_set_bus_clock(priv->phandle, MTRUE);
2446*4882a593Smuzhiyun 		clock_state = data;
2447*4882a593Smuzhiyun 		break;
2448*4882a593Smuzhiyun 	default:
2449*4882a593Smuzhiyun 		ret = -EINVAL;
2450*4882a593Smuzhiyun 		PRINTM(MINFO, "sdioclock: wrong parameter\n");
2451*4882a593Smuzhiyun 		break;
2452*4882a593Smuzhiyun 	}
2453*4882a593Smuzhiyun done:
2454*4882a593Smuzhiyun 	LEAVE();
2455*4882a593Smuzhiyun 	return ret;
2456*4882a593Smuzhiyun }
2457*4882a593Smuzhiyun #endif /* SDIO */
2458*4882a593Smuzhiyun 
2459*4882a593Smuzhiyun /**
2460*4882a593Smuzhiyun  *  @brief Set/Get beacon interval
2461*4882a593Smuzhiyun  *
2462*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
2463*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
2464*4882a593Smuzhiyun  *
2465*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
2466*4882a593Smuzhiyun  */
woal_beacon_interval(moal_private * priv,struct iwreq * wrq)2467*4882a593Smuzhiyun static int woal_beacon_interval(moal_private *priv, struct iwreq *wrq)
2468*4882a593Smuzhiyun {
2469*4882a593Smuzhiyun 	int ret = 0;
2470*4882a593Smuzhiyun 	mlan_ds_bss *bss = NULL;
2471*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
2472*4882a593Smuzhiyun 	int bcn = 0;
2473*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
2474*4882a593Smuzhiyun 
2475*4882a593Smuzhiyun 	ENTER();
2476*4882a593Smuzhiyun 
2477*4882a593Smuzhiyun 	if (wrq->u.data.length) {
2478*4882a593Smuzhiyun 		if (copy_from_user(&bcn, wrq->u.data.pointer, sizeof(int))) {
2479*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
2480*4882a593Smuzhiyun 			ret = -EFAULT;
2481*4882a593Smuzhiyun 			goto done;
2482*4882a593Smuzhiyun 		}
2483*4882a593Smuzhiyun 		if ((bcn < MLAN_MIN_BEACON_INTERVAL) ||
2484*4882a593Smuzhiyun 		    (bcn > MLAN_MAX_BEACON_INTERVAL)) {
2485*4882a593Smuzhiyun 			ret = -EINVAL;
2486*4882a593Smuzhiyun 			goto done;
2487*4882a593Smuzhiyun 		}
2488*4882a593Smuzhiyun 	}
2489*4882a593Smuzhiyun 
2490*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
2491*4882a593Smuzhiyun 	if (req == NULL) {
2492*4882a593Smuzhiyun 		ret = -ENOMEM;
2493*4882a593Smuzhiyun 		goto done;
2494*4882a593Smuzhiyun 	}
2495*4882a593Smuzhiyun 	bss = (mlan_ds_bss *)req->pbuf;
2496*4882a593Smuzhiyun 	bss->sub_command = MLAN_OID_IBSS_BCN_INTERVAL;
2497*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_BSS;
2498*4882a593Smuzhiyun 	if (!wrq->u.data.length)
2499*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
2500*4882a593Smuzhiyun 	else {
2501*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
2502*4882a593Smuzhiyun 		bss->param.bcn_interval = bcn;
2503*4882a593Smuzhiyun 	}
2504*4882a593Smuzhiyun 
2505*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2506*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
2507*4882a593Smuzhiyun 		ret = -EFAULT;
2508*4882a593Smuzhiyun 		goto done;
2509*4882a593Smuzhiyun 	}
2510*4882a593Smuzhiyun 
2511*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, (t_u8 *)&bss->param.bcn_interval,
2512*4882a593Smuzhiyun 			 sizeof(int))) {
2513*4882a593Smuzhiyun 		ret = -EFAULT;
2514*4882a593Smuzhiyun 		goto done;
2515*4882a593Smuzhiyun 	}
2516*4882a593Smuzhiyun 	wrq->u.data.length = 1;
2517*4882a593Smuzhiyun done:
2518*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
2519*4882a593Smuzhiyun 		kfree(req);
2520*4882a593Smuzhiyun 	LEAVE();
2521*4882a593Smuzhiyun 	return ret;
2522*4882a593Smuzhiyun }
2523*4882a593Smuzhiyun 
2524*4882a593Smuzhiyun /**
2525*4882a593Smuzhiyun  * @brief Set/Get TX data rate
2526*4882a593Smuzhiyun  *
2527*4882a593Smuzhiyun  * @param priv      A pointer to moal_private structure
2528*4882a593Smuzhiyun  * @param wrq       A pointer to iwreq structure
2529*4882a593Smuzhiyun  *
2530*4882a593Smuzhiyun  * @return          0 --success, otherwise fail
2531*4882a593Smuzhiyun  */
woal_set_get_txrate(moal_private * priv,struct iwreq * wrq)2532*4882a593Smuzhiyun static int woal_set_get_txrate(moal_private *priv, struct iwreq *wrq)
2533*4882a593Smuzhiyun {
2534*4882a593Smuzhiyun 	int ret = 0;
2535*4882a593Smuzhiyun 	mlan_ds_rate *rate = NULL;
2536*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
2537*4882a593Smuzhiyun 	int rateindex = 0;
2538*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
2539*4882a593Smuzhiyun 
2540*4882a593Smuzhiyun 	ENTER();
2541*4882a593Smuzhiyun 	if (wrq->u.data.length) {
2542*4882a593Smuzhiyun 		if (copy_from_user(&rateindex, wrq->u.data.pointer,
2543*4882a593Smuzhiyun 				   sizeof(int))) {
2544*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
2545*4882a593Smuzhiyun 			ret = -EFAULT;
2546*4882a593Smuzhiyun 			goto done;
2547*4882a593Smuzhiyun 		}
2548*4882a593Smuzhiyun 	}
2549*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
2550*4882a593Smuzhiyun 	if (req == NULL) {
2551*4882a593Smuzhiyun 		ret = -ENOMEM;
2552*4882a593Smuzhiyun 		goto done;
2553*4882a593Smuzhiyun 	}
2554*4882a593Smuzhiyun 
2555*4882a593Smuzhiyun 	rate = (mlan_ds_rate *)req->pbuf;
2556*4882a593Smuzhiyun 	rate->param.rate_cfg.rate_type = MLAN_RATE_INDEX;
2557*4882a593Smuzhiyun 	rate->sub_command = MLAN_OID_RATE_CFG;
2558*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_RATE;
2559*4882a593Smuzhiyun 	if (!wrq->u.data.length)
2560*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
2561*4882a593Smuzhiyun 	else {
2562*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
2563*4882a593Smuzhiyun 		if (rateindex == AUTO_RATE)
2564*4882a593Smuzhiyun 			rate->param.rate_cfg.is_rate_auto = 1;
2565*4882a593Smuzhiyun 		else {
2566*4882a593Smuzhiyun 			if ((rateindex != MLAN_RATE_INDEX_MCS32) &&
2567*4882a593Smuzhiyun 			    ((rateindex < 0) ||
2568*4882a593Smuzhiyun 			     (rateindex > MLAN_RATE_INDEX_MCS15))) {
2569*4882a593Smuzhiyun 				ret = -EINVAL;
2570*4882a593Smuzhiyun 				goto done;
2571*4882a593Smuzhiyun 			}
2572*4882a593Smuzhiyun 		}
2573*4882a593Smuzhiyun 		rate->param.rate_cfg.rate = rateindex;
2574*4882a593Smuzhiyun 	}
2575*4882a593Smuzhiyun 
2576*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2577*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
2578*4882a593Smuzhiyun 		ret = -EFAULT;
2579*4882a593Smuzhiyun 		goto done;
2580*4882a593Smuzhiyun 	} else {
2581*4882a593Smuzhiyun 		if (wrq->u.data.length)
2582*4882a593Smuzhiyun 			priv->rate_index = rateindex;
2583*4882a593Smuzhiyun 	}
2584*4882a593Smuzhiyun 	if (!wrq->u.data.length) {
2585*4882a593Smuzhiyun 		if (rate->param.rate_cfg.is_rate_auto)
2586*4882a593Smuzhiyun 			rateindex = AUTO_RATE;
2587*4882a593Smuzhiyun 		else
2588*4882a593Smuzhiyun 			rateindex = rate->param.rate_cfg.rate;
2589*4882a593Smuzhiyun 		wrq->u.data.length = 1;
2590*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &rateindex, sizeof(int)))
2591*4882a593Smuzhiyun 			ret = -EFAULT;
2592*4882a593Smuzhiyun 	}
2593*4882a593Smuzhiyun done:
2594*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
2595*4882a593Smuzhiyun 		kfree(req);
2596*4882a593Smuzhiyun 	LEAVE();
2597*4882a593Smuzhiyun 	return ret;
2598*4882a593Smuzhiyun }
2599*4882a593Smuzhiyun 
2600*4882a593Smuzhiyun /**
2601*4882a593Smuzhiyun  * @brief Set/Get region code
2602*4882a593Smuzhiyun  *
2603*4882a593Smuzhiyun  * @param priv      A pointer to moal_private structure
2604*4882a593Smuzhiyun  * @param wrq       A pointer to iwreq structure
2605*4882a593Smuzhiyun  *
2606*4882a593Smuzhiyun  * @return          0 --success, otherwise fail
2607*4882a593Smuzhiyun  */
woal_set_get_regioncode(moal_private * priv,struct iwreq * wrq)2608*4882a593Smuzhiyun static int woal_set_get_regioncode(moal_private *priv, struct iwreq *wrq)
2609*4882a593Smuzhiyun {
2610*4882a593Smuzhiyun 	int ret = 0;
2611*4882a593Smuzhiyun 	mlan_ds_misc_cfg *cfg = NULL;
2612*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
2613*4882a593Smuzhiyun 	int region = 0;
2614*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
2615*4882a593Smuzhiyun 
2616*4882a593Smuzhiyun 	ENTER();
2617*4882a593Smuzhiyun 
2618*4882a593Smuzhiyun 	if (wrq->u.data.length) {
2619*4882a593Smuzhiyun 		if (copy_from_user(&region, wrq->u.data.pointer, sizeof(int))) {
2620*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
2621*4882a593Smuzhiyun 			ret = -EFAULT;
2622*4882a593Smuzhiyun 			goto done;
2623*4882a593Smuzhiyun 		}
2624*4882a593Smuzhiyun 	}
2625*4882a593Smuzhiyun 
2626*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2627*4882a593Smuzhiyun 	if (req == NULL) {
2628*4882a593Smuzhiyun 		ret = -ENOMEM;
2629*4882a593Smuzhiyun 		goto done;
2630*4882a593Smuzhiyun 	}
2631*4882a593Smuzhiyun 
2632*4882a593Smuzhiyun 	cfg = (mlan_ds_misc_cfg *)req->pbuf;
2633*4882a593Smuzhiyun 	cfg->sub_command = MLAN_OID_MISC_REGION;
2634*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_MISC_CFG;
2635*4882a593Smuzhiyun 	if (!wrq->u.data.length)
2636*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
2637*4882a593Smuzhiyun 	else {
2638*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
2639*4882a593Smuzhiyun 		cfg->param.region_code = region;
2640*4882a593Smuzhiyun 	}
2641*4882a593Smuzhiyun 
2642*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2643*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
2644*4882a593Smuzhiyun 		ret = -EFAULT;
2645*4882a593Smuzhiyun 		goto done;
2646*4882a593Smuzhiyun 	}
2647*4882a593Smuzhiyun 
2648*4882a593Smuzhiyun 	if (!wrq->u.data.length) {
2649*4882a593Smuzhiyun 		wrq->u.data.length = 1;
2650*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &cfg->param.region_code,
2651*4882a593Smuzhiyun 				 sizeof(int)))
2652*4882a593Smuzhiyun 			ret = -EFAULT;
2653*4882a593Smuzhiyun 	}
2654*4882a593Smuzhiyun done:
2655*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
2656*4882a593Smuzhiyun 		kfree(req);
2657*4882a593Smuzhiyun 	LEAVE();
2658*4882a593Smuzhiyun 	return ret;
2659*4882a593Smuzhiyun }
2660*4882a593Smuzhiyun 
2661*4882a593Smuzhiyun /**
2662*4882a593Smuzhiyun  * @brief Set/Get radio
2663*4882a593Smuzhiyun  *
2664*4882a593Smuzhiyun  * @param priv      A pointer to moal_private structure
2665*4882a593Smuzhiyun  * @param wrq       A pointer to iwreq structure
2666*4882a593Smuzhiyun  *
2667*4882a593Smuzhiyun  * @return          0 --success, otherwise fail
2668*4882a593Smuzhiyun  */
woal_set_get_radio(moal_private * priv,struct iwreq * wrq)2669*4882a593Smuzhiyun static int woal_set_get_radio(moal_private *priv, struct iwreq *wrq)
2670*4882a593Smuzhiyun {
2671*4882a593Smuzhiyun 	int ret = 0;
2672*4882a593Smuzhiyun 	mlan_bss_info bss_info;
2673*4882a593Smuzhiyun 	int option = 0;
2674*4882a593Smuzhiyun 
2675*4882a593Smuzhiyun 	ENTER();
2676*4882a593Smuzhiyun 
2677*4882a593Smuzhiyun 	memset(&bss_info, 0, sizeof(bss_info));
2678*4882a593Smuzhiyun 
2679*4882a593Smuzhiyun 	if (wrq->u.data.length) {
2680*4882a593Smuzhiyun 		/* Set radio */
2681*4882a593Smuzhiyun 		if (copy_from_user(&option, wrq->u.data.pointer, sizeof(int))) {
2682*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
2683*4882a593Smuzhiyun 			ret = -EFAULT;
2684*4882a593Smuzhiyun 			goto done;
2685*4882a593Smuzhiyun 		}
2686*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS != woal_set_radio(priv, (t_u8)option))
2687*4882a593Smuzhiyun 			ret = -EFAULT;
2688*4882a593Smuzhiyun 	} else {
2689*4882a593Smuzhiyun 		/* Get radio status */
2690*4882a593Smuzhiyun 		woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
2691*4882a593Smuzhiyun 		wrq->u.data.length = 1;
2692*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &bss_info.radio_on,
2693*4882a593Smuzhiyun 				 sizeof(bss_info.radio_on))) {
2694*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
2695*4882a593Smuzhiyun 			ret = -EFAULT;
2696*4882a593Smuzhiyun 		}
2697*4882a593Smuzhiyun 	}
2698*4882a593Smuzhiyun done:
2699*4882a593Smuzhiyun 	LEAVE();
2700*4882a593Smuzhiyun 	return ret;
2701*4882a593Smuzhiyun }
2702*4882a593Smuzhiyun 
2703*4882a593Smuzhiyun #ifdef DEBUG_LEVEL1
2704*4882a593Smuzhiyun /**
2705*4882a593Smuzhiyun  *  @brief Get/Set the bit mask of driver debug message control
2706*4882a593Smuzhiyun  *
2707*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
2708*4882a593Smuzhiyun  *  @param wrq          A pointer to wrq structure
2709*4882a593Smuzhiyun  *
2710*4882a593Smuzhiyun  *  @return             0 --success, otherwise fail
2711*4882a593Smuzhiyun  */
woal_drv_dbg(moal_private * priv,struct iwreq * wrq)2712*4882a593Smuzhiyun static int woal_drv_dbg(moal_private *priv, struct iwreq *wrq)
2713*4882a593Smuzhiyun {
2714*4882a593Smuzhiyun 	int data[4], copy_len;
2715*4882a593Smuzhiyun 	int ret = 0;
2716*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
2717*4882a593Smuzhiyun 	ENTER();
2718*4882a593Smuzhiyun 
2719*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
2720*4882a593Smuzhiyun 	if (!data_length) {
2721*4882a593Smuzhiyun 		data[0] = drvdbg;
2722*4882a593Smuzhiyun 		/* Return the current driver debug bit masks */
2723*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, data, sizeof(int))) {
2724*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
2725*4882a593Smuzhiyun 			ret = -EFAULT;
2726*4882a593Smuzhiyun 			goto drvdbgexit;
2727*4882a593Smuzhiyun 		}
2728*4882a593Smuzhiyun 		wrq->u.data.length = 1;
2729*4882a593Smuzhiyun 	} else if (data_length < 3) {
2730*4882a593Smuzhiyun 		/* Get the driver debug bit masks from user */
2731*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
2732*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
2733*4882a593Smuzhiyun 			ret = -EFAULT;
2734*4882a593Smuzhiyun 			goto drvdbgexit;
2735*4882a593Smuzhiyun 		}
2736*4882a593Smuzhiyun 		drvdbg = data[0];
2737*4882a593Smuzhiyun 		/* Set the driver debug bit masks into mlan */
2738*4882a593Smuzhiyun 		woal_set_drvdbg(priv, drvdbg);
2739*4882a593Smuzhiyun 	} else {
2740*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid parameter number\n");
2741*4882a593Smuzhiyun 		goto drvdbgexit;
2742*4882a593Smuzhiyun 	}
2743*4882a593Smuzhiyun 
2744*4882a593Smuzhiyun 	printk(KERN_ALERT "drvdbg = 0x%08x\n", drvdbg);
2745*4882a593Smuzhiyun #ifdef DEBUG_LEVEL2
2746*4882a593Smuzhiyun 	printk(KERN_ALERT "MINFO  (%08x) %s\n", MINFO,
2747*4882a593Smuzhiyun 	       (drvdbg & MINFO) ? "X" : "");
2748*4882a593Smuzhiyun 	printk(KERN_ALERT "MWARN  (%08x) %s\n", MWARN,
2749*4882a593Smuzhiyun 	       (drvdbg & MWARN) ? "X" : "");
2750*4882a593Smuzhiyun 	printk(KERN_ALERT "MENTRY (%08x) %s\n", MENTRY,
2751*4882a593Smuzhiyun 	       (drvdbg & MENTRY) ? "X" : "");
2752*4882a593Smuzhiyun #endif
2753*4882a593Smuzhiyun 	printk(KERN_ALERT "MMPA_D (%08x) %s\n", MMPA_D,
2754*4882a593Smuzhiyun 	       (drvdbg & MMPA_D) ? "X" : "");
2755*4882a593Smuzhiyun 	printk(KERN_ALERT "MIF_D  (%08x) %s\n", MIF_D,
2756*4882a593Smuzhiyun 	       (drvdbg & MIF_D) ? "X" : "");
2757*4882a593Smuzhiyun 	printk(KERN_ALERT "MFW_D  (%08x) %s\n", MFW_D,
2758*4882a593Smuzhiyun 	       (drvdbg & MFW_D) ? "X" : "");
2759*4882a593Smuzhiyun 	printk(KERN_ALERT "MEVT_D (%08x) %s\n", MEVT_D,
2760*4882a593Smuzhiyun 	       (drvdbg & MEVT_D) ? "X" : "");
2761*4882a593Smuzhiyun 	printk(KERN_ALERT "MCMD_D (%08x) %s\n", MCMD_D,
2762*4882a593Smuzhiyun 	       (drvdbg & MCMD_D) ? "X" : "");
2763*4882a593Smuzhiyun 	printk(KERN_ALERT "MDAT_D (%08x) %s\n", MDAT_D,
2764*4882a593Smuzhiyun 	       (drvdbg & MDAT_D) ? "X" : "");
2765*4882a593Smuzhiyun 	printk(KERN_ALERT "MREG_D (%08x) %s\n", MREG_D,
2766*4882a593Smuzhiyun 	       (drvdbg & MREG_D) ? "X" : "");
2767*4882a593Smuzhiyun 	printk(KERN_ALERT "MIOCTL (%08x) %s\n", MIOCTL,
2768*4882a593Smuzhiyun 	       (drvdbg & MIOCTL) ? "X" : "");
2769*4882a593Smuzhiyun 	printk(KERN_ALERT "MINTR  (%08x) %s\n", MINTR,
2770*4882a593Smuzhiyun 	       (drvdbg & MINTR) ? "X" : "");
2771*4882a593Smuzhiyun 	printk(KERN_ALERT "MEVENT (%08x) %s\n", MEVENT,
2772*4882a593Smuzhiyun 	       (drvdbg & MEVENT) ? "X" : "");
2773*4882a593Smuzhiyun 	printk(KERN_ALERT "MCMND  (%08x) %s\n", MCMND,
2774*4882a593Smuzhiyun 	       (drvdbg & MCMND) ? "X" : "");
2775*4882a593Smuzhiyun 	printk(KERN_ALERT "MDATA  (%08x) %s\n", MDATA,
2776*4882a593Smuzhiyun 	       (drvdbg & MDATA) ? "X" : "");
2777*4882a593Smuzhiyun 	printk(KERN_ALERT "MERROR (%08x) %s\n", MERROR,
2778*4882a593Smuzhiyun 	       (drvdbg & MERROR) ? "X" : "");
2779*4882a593Smuzhiyun 	printk(KERN_ALERT "MFATAL (%08x) %s\n", MFATAL,
2780*4882a593Smuzhiyun 	       (drvdbg & MFATAL) ? "X" : "");
2781*4882a593Smuzhiyun 	printk(KERN_ALERT "MMSG   (%08x) %s\n", MMSG,
2782*4882a593Smuzhiyun 	       (drvdbg & MMSG) ? "X" : "");
2783*4882a593Smuzhiyun 
2784*4882a593Smuzhiyun drvdbgexit:
2785*4882a593Smuzhiyun 	LEAVE();
2786*4882a593Smuzhiyun 	return ret;
2787*4882a593Smuzhiyun }
2788*4882a593Smuzhiyun #endif /* DEBUG_LEVEL1 */
2789*4882a593Smuzhiyun 
2790*4882a593Smuzhiyun /**
2791*4882a593Smuzhiyun  * @brief Set/Get QoS configuration
2792*4882a593Smuzhiyun  *
2793*4882a593Smuzhiyun  * @param priv     A pointer to moal_private structure
2794*4882a593Smuzhiyun  * @param wrq      A pointer to iwreq structure
2795*4882a593Smuzhiyun  *
2796*4882a593Smuzhiyun  * @return         0 --success, otherwise fail
2797*4882a593Smuzhiyun  */
woal_set_get_qos_cfg(moal_private * priv,struct iwreq * wrq)2798*4882a593Smuzhiyun static int woal_set_get_qos_cfg(moal_private *priv, struct iwreq *wrq)
2799*4882a593Smuzhiyun {
2800*4882a593Smuzhiyun 	int ret = 0;
2801*4882a593Smuzhiyun 	mlan_ds_wmm_cfg *cfg = NULL;
2802*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
2803*4882a593Smuzhiyun 	int data = 0;
2804*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
2805*4882a593Smuzhiyun 
2806*4882a593Smuzhiyun 	ENTER();
2807*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
2808*4882a593Smuzhiyun 	if (req == NULL) {
2809*4882a593Smuzhiyun 		ret = -ENOMEM;
2810*4882a593Smuzhiyun 		goto done;
2811*4882a593Smuzhiyun 	}
2812*4882a593Smuzhiyun 	cfg = (mlan_ds_wmm_cfg *)req->pbuf;
2813*4882a593Smuzhiyun 	cfg->sub_command = MLAN_OID_WMM_CFG_QOS;
2814*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_WMM_CFG;
2815*4882a593Smuzhiyun 	if (wrq->u.data.length) {
2816*4882a593Smuzhiyun 		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
2817*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
2818*4882a593Smuzhiyun 			ret = -EFAULT;
2819*4882a593Smuzhiyun 			goto done;
2820*4882a593Smuzhiyun 		}
2821*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
2822*4882a593Smuzhiyun 		cfg->param.qos_cfg = (t_u8)data;
2823*4882a593Smuzhiyun 	} else
2824*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
2825*4882a593Smuzhiyun 
2826*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2827*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
2828*4882a593Smuzhiyun 		ret = -EFAULT;
2829*4882a593Smuzhiyun 		goto done;
2830*4882a593Smuzhiyun 	}
2831*4882a593Smuzhiyun 
2832*4882a593Smuzhiyun 	if (!wrq->u.data.length) {
2833*4882a593Smuzhiyun 		data = (int)cfg->param.qos_cfg;
2834*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
2835*4882a593Smuzhiyun 			ret = -EFAULT;
2836*4882a593Smuzhiyun 			goto done;
2837*4882a593Smuzhiyun 		}
2838*4882a593Smuzhiyun 		wrq->u.data.length = 1;
2839*4882a593Smuzhiyun 	}
2840*4882a593Smuzhiyun done:
2841*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
2842*4882a593Smuzhiyun 		kfree(req);
2843*4882a593Smuzhiyun 	LEAVE();
2844*4882a593Smuzhiyun 	return ret;
2845*4882a593Smuzhiyun }
2846*4882a593Smuzhiyun 
2847*4882a593Smuzhiyun #ifndef OPCHAN
2848*4882a593Smuzhiyun /**
2849*4882a593Smuzhiyun  * @brief Set/Get WWS mode
2850*4882a593Smuzhiyun  *
2851*4882a593Smuzhiyun  * @param priv      A pointer to moal_private structure
2852*4882a593Smuzhiyun  * @param wrq       A pointer to iwreq structure
2853*4882a593Smuzhiyun  *
2854*4882a593Smuzhiyun  * @return          0 --success, otherwise fail
2855*4882a593Smuzhiyun  */
woal_wws_cfg(moal_private * priv,struct iwreq * wrq)2856*4882a593Smuzhiyun static int woal_wws_cfg(moal_private *priv, struct iwreq *wrq)
2857*4882a593Smuzhiyun {
2858*4882a593Smuzhiyun 	int ret = 0;
2859*4882a593Smuzhiyun 	mlan_ds_misc_cfg *wws = NULL;
2860*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
2861*4882a593Smuzhiyun 	int data = 0;
2862*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
2863*4882a593Smuzhiyun 
2864*4882a593Smuzhiyun 	ENTER();
2865*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2866*4882a593Smuzhiyun 	if (req == NULL) {
2867*4882a593Smuzhiyun 		ret = -ENOMEM;
2868*4882a593Smuzhiyun 		goto done;
2869*4882a593Smuzhiyun 	}
2870*4882a593Smuzhiyun 	wws = (mlan_ds_misc_cfg *)req->pbuf;
2871*4882a593Smuzhiyun 	wws->sub_command = MLAN_OID_MISC_WWS;
2872*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_MISC_CFG;
2873*4882a593Smuzhiyun 	if (wrq->u.data.length) {
2874*4882a593Smuzhiyun 		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
2875*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
2876*4882a593Smuzhiyun 			ret = -EFAULT;
2877*4882a593Smuzhiyun 			goto done;
2878*4882a593Smuzhiyun 		}
2879*4882a593Smuzhiyun 		if (data != CMD_DISABLED && data != CMD_ENABLED) {
2880*4882a593Smuzhiyun 			ret = -EINVAL;
2881*4882a593Smuzhiyun 			goto done;
2882*4882a593Smuzhiyun 		}
2883*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
2884*4882a593Smuzhiyun 		wws->param.wws_cfg = data;
2885*4882a593Smuzhiyun 	} else
2886*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
2887*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2888*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
2889*4882a593Smuzhiyun 		ret = -EFAULT;
2890*4882a593Smuzhiyun 		goto done;
2891*4882a593Smuzhiyun 	}
2892*4882a593Smuzhiyun 	if (!wrq->u.data.length) {
2893*4882a593Smuzhiyun 		data = wws->param.wws_cfg;
2894*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
2895*4882a593Smuzhiyun 			ret = -EFAULT;
2896*4882a593Smuzhiyun 			goto done;
2897*4882a593Smuzhiyun 		}
2898*4882a593Smuzhiyun 		wrq->u.data.length = 1;
2899*4882a593Smuzhiyun 	}
2900*4882a593Smuzhiyun done:
2901*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
2902*4882a593Smuzhiyun 		kfree(req);
2903*4882a593Smuzhiyun 	LEAVE();
2904*4882a593Smuzhiyun 	return ret;
2905*4882a593Smuzhiyun }
2906*4882a593Smuzhiyun #endif
2907*4882a593Smuzhiyun 
2908*4882a593Smuzhiyun /**
2909*4882a593Smuzhiyun  * @brief Set/Get sleep period
2910*4882a593Smuzhiyun  *
2911*4882a593Smuzhiyun  * @param priv     A pointer to moal_private structure
2912*4882a593Smuzhiyun  * @param wrq      A pointer to iwreq structure
2913*4882a593Smuzhiyun  *
2914*4882a593Smuzhiyun  * @return         0 --success, otherwise fail
2915*4882a593Smuzhiyun  */
woal_sleep_pd(moal_private * priv,struct iwreq * wrq)2916*4882a593Smuzhiyun static int woal_sleep_pd(moal_private *priv, struct iwreq *wrq)
2917*4882a593Smuzhiyun {
2918*4882a593Smuzhiyun 	int ret = 0;
2919*4882a593Smuzhiyun 	mlan_ds_pm_cfg *pm_cfg = NULL;
2920*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
2921*4882a593Smuzhiyun 	int data = 0;
2922*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
2923*4882a593Smuzhiyun 
2924*4882a593Smuzhiyun 	ENTER();
2925*4882a593Smuzhiyun 
2926*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
2927*4882a593Smuzhiyun 	if (req == NULL) {
2928*4882a593Smuzhiyun 		ret = -ENOMEM;
2929*4882a593Smuzhiyun 		goto done;
2930*4882a593Smuzhiyun 	}
2931*4882a593Smuzhiyun 	pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
2932*4882a593Smuzhiyun 	pm_cfg->sub_command = MLAN_OID_PM_CFG_SLEEP_PD;
2933*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_PM_CFG;
2934*4882a593Smuzhiyun 	if (wrq->u.data.length) {
2935*4882a593Smuzhiyun 		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
2936*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
2937*4882a593Smuzhiyun 			ret = -EFAULT;
2938*4882a593Smuzhiyun 			goto done;
2939*4882a593Smuzhiyun 		}
2940*4882a593Smuzhiyun 		if ((data <= MAX_SLEEP_PERIOD && data >= MIN_SLEEP_PERIOD) ||
2941*4882a593Smuzhiyun 		    (data == 0) || (data == SLEEP_PERIOD_RESERVED_FF)) {
2942*4882a593Smuzhiyun 			req->action = MLAN_ACT_SET;
2943*4882a593Smuzhiyun 			pm_cfg->param.sleep_period = data;
2944*4882a593Smuzhiyun 		} else {
2945*4882a593Smuzhiyun 			ret = -EINVAL;
2946*4882a593Smuzhiyun 			goto done;
2947*4882a593Smuzhiyun 		}
2948*4882a593Smuzhiyun 	} else
2949*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
2950*4882a593Smuzhiyun 
2951*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2952*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
2953*4882a593Smuzhiyun 		ret = -EFAULT;
2954*4882a593Smuzhiyun 		goto done;
2955*4882a593Smuzhiyun 	}
2956*4882a593Smuzhiyun 	if (!wrq->u.data.length) {
2957*4882a593Smuzhiyun 		data = pm_cfg->param.sleep_period;
2958*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
2959*4882a593Smuzhiyun 			ret = -EFAULT;
2960*4882a593Smuzhiyun 			goto done;
2961*4882a593Smuzhiyun 		}
2962*4882a593Smuzhiyun 		wrq->u.data.length = 1;
2963*4882a593Smuzhiyun 	}
2964*4882a593Smuzhiyun 
2965*4882a593Smuzhiyun done:
2966*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
2967*4882a593Smuzhiyun 		kfree(req);
2968*4882a593Smuzhiyun 	LEAVE();
2969*4882a593Smuzhiyun 	return ret;
2970*4882a593Smuzhiyun }
2971*4882a593Smuzhiyun 
2972*4882a593Smuzhiyun /**
2973*4882a593Smuzhiyun  * @brief Configure sleep parameters
2974*4882a593Smuzhiyun  *
2975*4882a593Smuzhiyun  * @param priv         A pointer to moal_private structure
2976*4882a593Smuzhiyun  * @param req          A pointer to ifreq structure
2977*4882a593Smuzhiyun  *
2978*4882a593Smuzhiyun  * @return             0 --success, otherwise fail
2979*4882a593Smuzhiyun  */
woal_sleep_params_ioctl(moal_private * priv,struct iwreq * wrq)2980*4882a593Smuzhiyun static int woal_sleep_params_ioctl(moal_private *priv, struct iwreq *wrq)
2981*4882a593Smuzhiyun {
2982*4882a593Smuzhiyun 	int ret = 0;
2983*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
2984*4882a593Smuzhiyun 	mlan_ds_pm_cfg *pm = NULL;
2985*4882a593Smuzhiyun 	mlan_ds_sleep_params *psleep_params = NULL;
2986*4882a593Smuzhiyun 	int data[6] = {0}, i, copy_len;
2987*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
2988*4882a593Smuzhiyun #ifdef DEBUG_LEVEL1
2989*4882a593Smuzhiyun 	char err_str[][36] = {{"sleep clock error in ppm"},
2990*4882a593Smuzhiyun 			      {"wakeup offset in usec"},
2991*4882a593Smuzhiyun 			      {"clock stabilization time in usec"},
2992*4882a593Smuzhiyun 			      {"control periodic calibration(0-2)"},
2993*4882a593Smuzhiyun 			      {"control of external sleepClock(0-2)"},
2994*4882a593Smuzhiyun 			      {"value of reserved for debug"}};
2995*4882a593Smuzhiyun #endif
2996*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
2997*4882a593Smuzhiyun 
2998*4882a593Smuzhiyun 	ENTER();
2999*4882a593Smuzhiyun 
3000*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
3001*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
3002*4882a593Smuzhiyun 	if (req == NULL) {
3003*4882a593Smuzhiyun 		LEAVE();
3004*4882a593Smuzhiyun 		return -ENOMEM;
3005*4882a593Smuzhiyun 	}
3006*4882a593Smuzhiyun 
3007*4882a593Smuzhiyun 	pm = (mlan_ds_pm_cfg *)req->pbuf;
3008*4882a593Smuzhiyun 	pm->sub_command = MLAN_OID_PM_CFG_SLEEP_PARAMS;
3009*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_PM_CFG;
3010*4882a593Smuzhiyun 	psleep_params = (pmlan_ds_sleep_params)&pm->param.sleep_params;
3011*4882a593Smuzhiyun 
3012*4882a593Smuzhiyun 	if (data_length == 0) {
3013*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
3014*4882a593Smuzhiyun 	} else if (data_length == 6) {
3015*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
3016*4882a593Smuzhiyun 			/* copy_from_user failed  */
3017*4882a593Smuzhiyun 			PRINTM(MERROR, "S_PARAMS: copy from user failed\n");
3018*4882a593Smuzhiyun 			ret = -EINVAL;
3019*4882a593Smuzhiyun 			goto done;
3020*4882a593Smuzhiyun 		}
3021*4882a593Smuzhiyun 
3022*4882a593Smuzhiyun #define MIN_VAL 0x0000
3023*4882a593Smuzhiyun #define MAX_VAL 0xFFFF
3024*4882a593Smuzhiyun 		for (i = 0; i < 6; i++) {
3025*4882a593Smuzhiyun 			if ((i == 3) || (i == 4)) {
3026*4882a593Smuzhiyun 				/* These two cases are handled below the loop */
3027*4882a593Smuzhiyun 				continue;
3028*4882a593Smuzhiyun 			}
3029*4882a593Smuzhiyun 			if (data[i] < MIN_VAL || data[i] > MAX_VAL) {
3030*4882a593Smuzhiyun 				PRINTM(MERROR, "Invalid %s (0-65535)!\n",
3031*4882a593Smuzhiyun 				       err_str[i]);
3032*4882a593Smuzhiyun 				ret = -EINVAL;
3033*4882a593Smuzhiyun 				goto done;
3034*4882a593Smuzhiyun 			}
3035*4882a593Smuzhiyun 		}
3036*4882a593Smuzhiyun 		if (data[3] < 0 || data[3] > 2) {
3037*4882a593Smuzhiyun 			PRINTM(MERROR,
3038*4882a593Smuzhiyun 			       "Invalid control periodic calibration (0-2)!\n");
3039*4882a593Smuzhiyun 			ret = -EINVAL;
3040*4882a593Smuzhiyun 			goto done;
3041*4882a593Smuzhiyun 		}
3042*4882a593Smuzhiyun 		if (data[4] < 0 || data[4] > 2) {
3043*4882a593Smuzhiyun 			PRINTM(MERROR,
3044*4882a593Smuzhiyun 			       "Invalid control of external sleep clock (0-2)!\n");
3045*4882a593Smuzhiyun 			ret = -EINVAL;
3046*4882a593Smuzhiyun 			goto done;
3047*4882a593Smuzhiyun 		}
3048*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
3049*4882a593Smuzhiyun 		psleep_params->error = data[0];
3050*4882a593Smuzhiyun 		psleep_params->offset = data[1];
3051*4882a593Smuzhiyun 		psleep_params->stable_time = data[2];
3052*4882a593Smuzhiyun 		psleep_params->cal_control = data[3];
3053*4882a593Smuzhiyun 		psleep_params->ext_sleep_clk = data[4];
3054*4882a593Smuzhiyun 		psleep_params->reserved = data[5];
3055*4882a593Smuzhiyun 	} else {
3056*4882a593Smuzhiyun 		ret = -EINVAL;
3057*4882a593Smuzhiyun 		goto done;
3058*4882a593Smuzhiyun 	}
3059*4882a593Smuzhiyun 
3060*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3061*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
3062*4882a593Smuzhiyun 		ret = -EFAULT;
3063*4882a593Smuzhiyun 		goto done;
3064*4882a593Smuzhiyun 	}
3065*4882a593Smuzhiyun 
3066*4882a593Smuzhiyun 	data[0] = psleep_params->error;
3067*4882a593Smuzhiyun 	data[1] = psleep_params->offset;
3068*4882a593Smuzhiyun 	data[2] = psleep_params->stable_time;
3069*4882a593Smuzhiyun 	data[3] = psleep_params->cal_control;
3070*4882a593Smuzhiyun 	data[4] = psleep_params->ext_sleep_clk;
3071*4882a593Smuzhiyun 	data[5] = psleep_params->reserved;
3072*4882a593Smuzhiyun 	wrq->u.data.length = 6;
3073*4882a593Smuzhiyun 
3074*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, data,
3075*4882a593Smuzhiyun 			 sizeof(int) * wrq->u.data.length)) {
3076*4882a593Smuzhiyun 		PRINTM(MERROR, "QCONFIG: copy to user failed\n");
3077*4882a593Smuzhiyun 		ret = -EFAULT;
3078*4882a593Smuzhiyun 		goto done;
3079*4882a593Smuzhiyun 	}
3080*4882a593Smuzhiyun 
3081*4882a593Smuzhiyun done:
3082*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
3083*4882a593Smuzhiyun 		kfree(req);
3084*4882a593Smuzhiyun 	LEAVE();
3085*4882a593Smuzhiyun 	return ret;
3086*4882a593Smuzhiyun }
3087*4882a593Smuzhiyun 
3088*4882a593Smuzhiyun /**
3089*4882a593Smuzhiyun  *  @brief Set/get user provisioned local power constraint
3090*4882a593Smuzhiyun  *
3091*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
3092*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
3093*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
3094*4882a593Smuzhiyun  */
woal_set_get_11h_local_pwr_constraint(moal_private * priv,struct iwreq * wrq)3095*4882a593Smuzhiyun static int woal_set_get_11h_local_pwr_constraint(moal_private *priv,
3096*4882a593Smuzhiyun 						 struct iwreq *wrq)
3097*4882a593Smuzhiyun {
3098*4882a593Smuzhiyun 	int ret = 0, data = 0;
3099*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
3100*4882a593Smuzhiyun 	mlan_ds_11h_cfg *ds_11hcfg = NULL;
3101*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
3102*4882a593Smuzhiyun 
3103*4882a593Smuzhiyun 	ENTER();
3104*4882a593Smuzhiyun 
3105*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
3106*4882a593Smuzhiyun 	if (req == NULL) {
3107*4882a593Smuzhiyun 		ret = -ENOMEM;
3108*4882a593Smuzhiyun 		goto done;
3109*4882a593Smuzhiyun 	}
3110*4882a593Smuzhiyun 	ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
3111*4882a593Smuzhiyun 	if (wrq->u.data.length) {
3112*4882a593Smuzhiyun 		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
3113*4882a593Smuzhiyun 			PRINTM(MINFO, "Copy from user failed\n");
3114*4882a593Smuzhiyun 			ret = -EFAULT;
3115*4882a593Smuzhiyun 			goto done;
3116*4882a593Smuzhiyun 		}
3117*4882a593Smuzhiyun 		ds_11hcfg->param.usr_local_power_constraint = (t_s8)data;
3118*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
3119*4882a593Smuzhiyun 	} else
3120*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
3121*4882a593Smuzhiyun 
3122*4882a593Smuzhiyun 	ds_11hcfg->sub_command = MLAN_OID_11H_LOCAL_POWER_CONSTRAINT;
3123*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_11H_CFG;
3124*4882a593Smuzhiyun 
3125*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3126*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
3127*4882a593Smuzhiyun 		ret = -EFAULT;
3128*4882a593Smuzhiyun 		goto done;
3129*4882a593Smuzhiyun 	}
3130*4882a593Smuzhiyun 
3131*4882a593Smuzhiyun 	/* Copy response to user */
3132*4882a593Smuzhiyun 	if (req->action == MLAN_ACT_GET) {
3133*4882a593Smuzhiyun 		data = (int)ds_11hcfg->param.usr_local_power_constraint;
3134*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
3135*4882a593Smuzhiyun 			PRINTM(MINFO, "Copy to user failed\n");
3136*4882a593Smuzhiyun 			ret = -EFAULT;
3137*4882a593Smuzhiyun 			goto done;
3138*4882a593Smuzhiyun 		}
3139*4882a593Smuzhiyun 		wrq->u.data.length = 1;
3140*4882a593Smuzhiyun 	}
3141*4882a593Smuzhiyun 
3142*4882a593Smuzhiyun done:
3143*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
3144*4882a593Smuzhiyun 		kfree(req);
3145*4882a593Smuzhiyun 	LEAVE();
3146*4882a593Smuzhiyun 	return ret;
3147*4882a593Smuzhiyun }
3148*4882a593Smuzhiyun 
3149*4882a593Smuzhiyun /**
3150*4882a593Smuzhiyun  *  @brief Set/get HT stream configurations
3151*4882a593Smuzhiyun  *
3152*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
3153*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
3154*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
3155*4882a593Smuzhiyun  */
woal_ht_stream_cfg_ioctl(moal_private * priv,struct iwreq * wrq)3156*4882a593Smuzhiyun static int woal_ht_stream_cfg_ioctl(moal_private *priv, struct iwreq *wrq)
3157*4882a593Smuzhiyun {
3158*4882a593Smuzhiyun 	int ret = 0, data = 0;
3159*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
3160*4882a593Smuzhiyun 	mlan_ds_11n_cfg *cfg = NULL;
3161*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
3162*4882a593Smuzhiyun 
3163*4882a593Smuzhiyun 	ENTER();
3164*4882a593Smuzhiyun 
3165*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
3166*4882a593Smuzhiyun 	if (req == NULL) {
3167*4882a593Smuzhiyun 		ret = -ENOMEM;
3168*4882a593Smuzhiyun 		goto done;
3169*4882a593Smuzhiyun 	}
3170*4882a593Smuzhiyun 	cfg = (mlan_ds_11n_cfg *)req->pbuf;
3171*4882a593Smuzhiyun 	if (wrq->u.data.length) {
3172*4882a593Smuzhiyun 		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
3173*4882a593Smuzhiyun 			PRINTM(MINFO, "Copy from user failed\n");
3174*4882a593Smuzhiyun 			ret = -EFAULT;
3175*4882a593Smuzhiyun 			goto done;
3176*4882a593Smuzhiyun 		}
3177*4882a593Smuzhiyun 		if (data != HT_STREAM_MODE_1X1 && data != HT_STREAM_MODE_2X2) {
3178*4882a593Smuzhiyun 			PRINTM(MINFO, "Invalid argument\n");
3179*4882a593Smuzhiyun 			ret = -EINVAL;
3180*4882a593Smuzhiyun 			goto done;
3181*4882a593Smuzhiyun 		}
3182*4882a593Smuzhiyun 		cfg->param.stream_cfg = data;
3183*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
3184*4882a593Smuzhiyun 	} else
3185*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
3186*4882a593Smuzhiyun 
3187*4882a593Smuzhiyun 	cfg->sub_command = MLAN_OID_11N_CFG_STREAM_CFG;
3188*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_11N_CFG;
3189*4882a593Smuzhiyun 
3190*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3191*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
3192*4882a593Smuzhiyun 		ret = -EFAULT;
3193*4882a593Smuzhiyun 		goto done;
3194*4882a593Smuzhiyun 	}
3195*4882a593Smuzhiyun 
3196*4882a593Smuzhiyun 	/* Copy response to user */
3197*4882a593Smuzhiyun 	data = (int)cfg->param.stream_cfg;
3198*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
3199*4882a593Smuzhiyun 		PRINTM(MINFO, "Copy to user failed\n");
3200*4882a593Smuzhiyun 		ret = -EFAULT;
3201*4882a593Smuzhiyun 		goto done;
3202*4882a593Smuzhiyun 	}
3203*4882a593Smuzhiyun 	wrq->u.data.length = 1;
3204*4882a593Smuzhiyun 
3205*4882a593Smuzhiyun done:
3206*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
3207*4882a593Smuzhiyun 		kfree(req);
3208*4882a593Smuzhiyun 	LEAVE();
3209*4882a593Smuzhiyun 	return ret;
3210*4882a593Smuzhiyun }
3211*4882a593Smuzhiyun 
3212*4882a593Smuzhiyun /**
3213*4882a593Smuzhiyun  *  @brief Set/get MAC control configuration
3214*4882a593Smuzhiyun  *
3215*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
3216*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
3217*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
3218*4882a593Smuzhiyun  */
woal_mac_control_ioctl(moal_private * priv,struct iwreq * wrq)3219*4882a593Smuzhiyun static int woal_mac_control_ioctl(moal_private *priv, struct iwreq *wrq)
3220*4882a593Smuzhiyun {
3221*4882a593Smuzhiyun 	int ret = 0, data = 0;
3222*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
3223*4882a593Smuzhiyun 	mlan_ds_misc_cfg *cfg = NULL;
3224*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
3225*4882a593Smuzhiyun 
3226*4882a593Smuzhiyun 	ENTER();
3227*4882a593Smuzhiyun 
3228*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3229*4882a593Smuzhiyun 	if (req == NULL) {
3230*4882a593Smuzhiyun 		ret = -ENOMEM;
3231*4882a593Smuzhiyun 		goto done;
3232*4882a593Smuzhiyun 	}
3233*4882a593Smuzhiyun 	cfg = (mlan_ds_misc_cfg *)req->pbuf;
3234*4882a593Smuzhiyun 	if (wrq->u.data.length) {
3235*4882a593Smuzhiyun 		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
3236*4882a593Smuzhiyun 			PRINTM(MINFO, "Copy from user failed\n");
3237*4882a593Smuzhiyun 			ret = -EFAULT;
3238*4882a593Smuzhiyun 			goto done;
3239*4882a593Smuzhiyun 		}
3240*4882a593Smuzhiyun 		/* Validation will be done later */
3241*4882a593Smuzhiyun 		cfg->param.mac_ctrl = data;
3242*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
3243*4882a593Smuzhiyun 	} else
3244*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
3245*4882a593Smuzhiyun 
3246*4882a593Smuzhiyun 	cfg->sub_command = MLAN_OID_MISC_MAC_CONTROL;
3247*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_MISC_CFG;
3248*4882a593Smuzhiyun 
3249*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3250*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
3251*4882a593Smuzhiyun 		ret = -EFAULT;
3252*4882a593Smuzhiyun 		goto done;
3253*4882a593Smuzhiyun 	}
3254*4882a593Smuzhiyun 
3255*4882a593Smuzhiyun 	/* Copy response to user */
3256*4882a593Smuzhiyun 	data = (int)cfg->param.mac_ctrl;
3257*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
3258*4882a593Smuzhiyun 		PRINTM(MINFO, "Copy to user failed\n");
3259*4882a593Smuzhiyun 		ret = -EFAULT;
3260*4882a593Smuzhiyun 		goto done;
3261*4882a593Smuzhiyun 	}
3262*4882a593Smuzhiyun 	wrq->u.data.length = 1;
3263*4882a593Smuzhiyun 
3264*4882a593Smuzhiyun done:
3265*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
3266*4882a593Smuzhiyun 		kfree(req);
3267*4882a593Smuzhiyun 	LEAVE();
3268*4882a593Smuzhiyun 	return ret;
3269*4882a593Smuzhiyun }
3270*4882a593Smuzhiyun 
3271*4882a593Smuzhiyun /**
3272*4882a593Smuzhiyun  *  @brief Get thermal reading
3273*4882a593Smuzhiyun  *
3274*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
3275*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
3276*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
3277*4882a593Smuzhiyun  */
woal_thermal_ioctl(moal_private * priv,struct iwreq * wrq)3278*4882a593Smuzhiyun static int woal_thermal_ioctl(moal_private *priv, struct iwreq *wrq)
3279*4882a593Smuzhiyun {
3280*4882a593Smuzhiyun 	int ret = 0, data = 0;
3281*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
3282*4882a593Smuzhiyun 	mlan_ds_misc_cfg *cfg = NULL;
3283*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
3284*4882a593Smuzhiyun 
3285*4882a593Smuzhiyun 	ENTER();
3286*4882a593Smuzhiyun 
3287*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3288*4882a593Smuzhiyun 	if (req == NULL) {
3289*4882a593Smuzhiyun 		ret = -ENOMEM;
3290*4882a593Smuzhiyun 		goto done;
3291*4882a593Smuzhiyun 	}
3292*4882a593Smuzhiyun 	cfg = (mlan_ds_misc_cfg *)req->pbuf;
3293*4882a593Smuzhiyun 	if (wrq->u.data.length) {
3294*4882a593Smuzhiyun 		PRINTM(MERROR, "Set is not supported for this command\n");
3295*4882a593Smuzhiyun 		ret = -EINVAL;
3296*4882a593Smuzhiyun 		goto done;
3297*4882a593Smuzhiyun 	}
3298*4882a593Smuzhiyun 	req->action = MLAN_ACT_GET;
3299*4882a593Smuzhiyun 
3300*4882a593Smuzhiyun 	cfg->sub_command = MLAN_OID_MISC_THERMAL;
3301*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_MISC_CFG;
3302*4882a593Smuzhiyun 
3303*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3304*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
3305*4882a593Smuzhiyun 		ret = -EFAULT;
3306*4882a593Smuzhiyun 		goto done;
3307*4882a593Smuzhiyun 	}
3308*4882a593Smuzhiyun 
3309*4882a593Smuzhiyun 	/* Copy response to user */
3310*4882a593Smuzhiyun 	data = (int)cfg->param.thermal;
3311*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
3312*4882a593Smuzhiyun 		PRINTM(MINFO, "Copy to user failed\n");
3313*4882a593Smuzhiyun 		ret = -EFAULT;
3314*4882a593Smuzhiyun 		goto done;
3315*4882a593Smuzhiyun 	}
3316*4882a593Smuzhiyun 	wrq->u.data.length = 1;
3317*4882a593Smuzhiyun 
3318*4882a593Smuzhiyun done:
3319*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
3320*4882a593Smuzhiyun 		kfree(req);
3321*4882a593Smuzhiyun 	LEAVE();
3322*4882a593Smuzhiyun 	return ret;
3323*4882a593Smuzhiyun }
3324*4882a593Smuzhiyun 
3325*4882a593Smuzhiyun /**
3326*4882a593Smuzhiyun  *  @brief Set/get hotspot enable state
3327*4882a593Smuzhiyun  *
3328*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
3329*4882a593Smuzhiyun  *  @param wrq      Pointer to user data
3330*4882a593Smuzhiyun  *
3331*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
3332*4882a593Smuzhiyun  */
woal_cfg_hotspot(moal_private * priv,struct iwreq * wrq)3333*4882a593Smuzhiyun static int woal_cfg_hotspot(moal_private *priv, struct iwreq *wrq)
3334*4882a593Smuzhiyun {
3335*4882a593Smuzhiyun 	int ret = 0;
3336*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
3337*4882a593Smuzhiyun 	mlan_ds_misc_cfg *cfg = NULL;
3338*4882a593Smuzhiyun 	int config;
3339*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
3340*4882a593Smuzhiyun 
3341*4882a593Smuzhiyun 	ENTER();
3342*4882a593Smuzhiyun 
3343*4882a593Smuzhiyun 	if (wrq->u.data.length > 1) {
3344*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid no of arguments!\n");
3345*4882a593Smuzhiyun 		ret = -EINVAL;
3346*4882a593Smuzhiyun 		goto done;
3347*4882a593Smuzhiyun 	}
3348*4882a593Smuzhiyun 
3349*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
3350*4882a593Smuzhiyun 	if (req == NULL) {
3351*4882a593Smuzhiyun 		ret = -ENOMEM;
3352*4882a593Smuzhiyun 		goto done;
3353*4882a593Smuzhiyun 	}
3354*4882a593Smuzhiyun 	cfg = (mlan_ds_misc_cfg *)req->pbuf;
3355*4882a593Smuzhiyun 	if (wrq->u.data.length == 0)
3356*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
3357*4882a593Smuzhiyun 	else {
3358*4882a593Smuzhiyun 		if (copy_from_user(&config, wrq->u.data.pointer, sizeof(int))) {
3359*4882a593Smuzhiyun 			PRINTM(MERROR, "copy from user failed\n");
3360*4882a593Smuzhiyun 			ret = -EFAULT;
3361*4882a593Smuzhiyun 			goto done;
3362*4882a593Smuzhiyun 		}
3363*4882a593Smuzhiyun 		cfg->param.hotspot_cfg = config;
3364*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
3365*4882a593Smuzhiyun 	}
3366*4882a593Smuzhiyun 
3367*4882a593Smuzhiyun 	cfg->sub_command = MLAN_OID_MISC_HOTSPOT_CFG;
3368*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_MISC_CFG;
3369*4882a593Smuzhiyun 
3370*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3371*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
3372*4882a593Smuzhiyun 		ret = -EFAULT;
3373*4882a593Smuzhiyun 		goto done;
3374*4882a593Smuzhiyun 	}
3375*4882a593Smuzhiyun 
3376*4882a593Smuzhiyun 	config = cfg->param.hotspot_cfg;
3377*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, &config, sizeof(int))) {
3378*4882a593Smuzhiyun 		ret = -EFAULT;
3379*4882a593Smuzhiyun 		goto done;
3380*4882a593Smuzhiyun 	}
3381*4882a593Smuzhiyun 	wrq->u.data.length = 1;
3382*4882a593Smuzhiyun 
3383*4882a593Smuzhiyun done:
3384*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
3385*4882a593Smuzhiyun 		kfree(req);
3386*4882a593Smuzhiyun 	LEAVE();
3387*4882a593Smuzhiyun 	return ret;
3388*4882a593Smuzhiyun }
3389*4882a593Smuzhiyun 
3390*4882a593Smuzhiyun #if defined(REASSOCIATION)
3391*4882a593Smuzhiyun /**
3392*4882a593Smuzhiyun  * @brief Set/Get reassociation settings
3393*4882a593Smuzhiyun  *
3394*4882a593Smuzhiyun  * @param priv     A pointer to moal_private structure
3395*4882a593Smuzhiyun  * @param wrq      A pointer to iwreq structure
3396*4882a593Smuzhiyun  *
3397*4882a593Smuzhiyun  * @return         0 --success, otherwise fail
3398*4882a593Smuzhiyun  */
woal_set_get_reassoc(moal_private * priv,struct iwreq * wrq)3399*4882a593Smuzhiyun static int woal_set_get_reassoc(moal_private *priv, struct iwreq *wrq)
3400*4882a593Smuzhiyun {
3401*4882a593Smuzhiyun 	moal_handle *handle = priv->phandle;
3402*4882a593Smuzhiyun 	int ret = 0;
3403*4882a593Smuzhiyun 	int data = 0;
3404*4882a593Smuzhiyun 
3405*4882a593Smuzhiyun 	ENTER();
3406*4882a593Smuzhiyun 
3407*4882a593Smuzhiyun 	if (wrq->u.data.length) {
3408*4882a593Smuzhiyun 		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
3409*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
3410*4882a593Smuzhiyun 			ret = -EFAULT;
3411*4882a593Smuzhiyun 			goto done;
3412*4882a593Smuzhiyun 		}
3413*4882a593Smuzhiyun 		if (data == 0) {
3414*4882a593Smuzhiyun 			handle->reassoc_on &= ~MBIT(priv->bss_index);
3415*4882a593Smuzhiyun 			priv->reassoc_on = MFALSE;
3416*4882a593Smuzhiyun 			priv->reassoc_required = MFALSE;
3417*4882a593Smuzhiyun 			if (!handle->reassoc_on &&
3418*4882a593Smuzhiyun 			    handle->is_reassoc_timer_set == MTRUE) {
3419*4882a593Smuzhiyun 				woal_cancel_timer(&handle->reassoc_timer);
3420*4882a593Smuzhiyun 				handle->is_reassoc_timer_set = MFALSE;
3421*4882a593Smuzhiyun 			}
3422*4882a593Smuzhiyun 		} else {
3423*4882a593Smuzhiyun 			handle->reassoc_on |= MBIT(priv->bss_index);
3424*4882a593Smuzhiyun 			priv->reassoc_on = MTRUE;
3425*4882a593Smuzhiyun 		}
3426*4882a593Smuzhiyun 	} else {
3427*4882a593Smuzhiyun 		data = (int)(priv->reassoc_on);
3428*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
3429*4882a593Smuzhiyun 			ret = -EFAULT;
3430*4882a593Smuzhiyun 			goto done;
3431*4882a593Smuzhiyun 		}
3432*4882a593Smuzhiyun 		wrq->u.data.length = 1;
3433*4882a593Smuzhiyun 	}
3434*4882a593Smuzhiyun 
3435*4882a593Smuzhiyun done:
3436*4882a593Smuzhiyun 	LEAVE();
3437*4882a593Smuzhiyun 	return ret;
3438*4882a593Smuzhiyun }
3439*4882a593Smuzhiyun #endif /* REASSOCIATION */
3440*4882a593Smuzhiyun 
3441*4882a593Smuzhiyun /**
3442*4882a593Smuzhiyun  *  @brief implement WMM enable command
3443*4882a593Smuzhiyun  *
3444*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
3445*4882a593Smuzhiyun  *  @param wrq      Pointer to user data
3446*4882a593Smuzhiyun  *
3447*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
3448*4882a593Smuzhiyun  */
woal_wmm_enable_ioctl(moal_private * priv,struct iwreq * wrq)3449*4882a593Smuzhiyun static int woal_wmm_enable_ioctl(moal_private *priv, struct iwreq *wrq)
3450*4882a593Smuzhiyun {
3451*4882a593Smuzhiyun 	int ret = 0;
3452*4882a593Smuzhiyun 	mlan_ds_wmm_cfg *wmm = NULL;
3453*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
3454*4882a593Smuzhiyun 	int data = 0;
3455*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
3456*4882a593Smuzhiyun 
3457*4882a593Smuzhiyun 	ENTER();
3458*4882a593Smuzhiyun 
3459*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
3460*4882a593Smuzhiyun 	if (req == NULL) {
3461*4882a593Smuzhiyun 		ret = -ENOMEM;
3462*4882a593Smuzhiyun 		goto done;
3463*4882a593Smuzhiyun 	}
3464*4882a593Smuzhiyun 	wmm = (mlan_ds_wmm_cfg *)req->pbuf;
3465*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_WMM_CFG;
3466*4882a593Smuzhiyun 	wmm->sub_command = MLAN_OID_WMM_CFG_ENABLE;
3467*4882a593Smuzhiyun 
3468*4882a593Smuzhiyun 	if (wrq->u.data.length) {
3469*4882a593Smuzhiyun 		/* Set WMM configuration */
3470*4882a593Smuzhiyun 		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
3471*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
3472*4882a593Smuzhiyun 			ret = -EFAULT;
3473*4882a593Smuzhiyun 			goto done;
3474*4882a593Smuzhiyun 		}
3475*4882a593Smuzhiyun 		if ((data < CMD_DISABLED) || (data > CMD_ENABLED)) {
3476*4882a593Smuzhiyun 			ret = -EINVAL;
3477*4882a593Smuzhiyun 			goto done;
3478*4882a593Smuzhiyun 		}
3479*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
3480*4882a593Smuzhiyun 		if (data == CMD_DISABLED)
3481*4882a593Smuzhiyun 			wmm->param.wmm_enable = MFALSE;
3482*4882a593Smuzhiyun 		else
3483*4882a593Smuzhiyun 			wmm->param.wmm_enable = MTRUE;
3484*4882a593Smuzhiyun 	} else {
3485*4882a593Smuzhiyun 		/* Get WMM status */
3486*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
3487*4882a593Smuzhiyun 	}
3488*4882a593Smuzhiyun 
3489*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3490*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
3491*4882a593Smuzhiyun 		ret = -EFAULT;
3492*4882a593Smuzhiyun 		goto done;
3493*4882a593Smuzhiyun 	}
3494*4882a593Smuzhiyun 
3495*4882a593Smuzhiyun 	if (wrq->u.data.pointer) {
3496*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &wmm->param.wmm_enable,
3497*4882a593Smuzhiyun 				 sizeof(wmm->param.wmm_enable))) {
3498*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
3499*4882a593Smuzhiyun 			ret = -EFAULT;
3500*4882a593Smuzhiyun 			goto done;
3501*4882a593Smuzhiyun 		}
3502*4882a593Smuzhiyun 		wrq->u.data.length = 1;
3503*4882a593Smuzhiyun 	}
3504*4882a593Smuzhiyun done:
3505*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
3506*4882a593Smuzhiyun 		kfree(req);
3507*4882a593Smuzhiyun 	LEAVE();
3508*4882a593Smuzhiyun 	return ret;
3509*4882a593Smuzhiyun }
3510*4882a593Smuzhiyun 
3511*4882a593Smuzhiyun /**
3512*4882a593Smuzhiyun  *  @brief Implement 802.11D enable command
3513*4882a593Smuzhiyun  *
3514*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
3515*4882a593Smuzhiyun  *  @param wrq      Pointer to user data
3516*4882a593Smuzhiyun  *
3517*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
3518*4882a593Smuzhiyun  */
woal_11d_enable_ioctl(moal_private * priv,struct iwreq * wrq)3519*4882a593Smuzhiyun static int woal_11d_enable_ioctl(moal_private *priv, struct iwreq *wrq)
3520*4882a593Smuzhiyun {
3521*4882a593Smuzhiyun 	int ret = 0;
3522*4882a593Smuzhiyun 	mlan_ds_11d_cfg *pcfg_11d = NULL;
3523*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
3524*4882a593Smuzhiyun 	int data = 0;
3525*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
3526*4882a593Smuzhiyun 
3527*4882a593Smuzhiyun 	ENTER();
3528*4882a593Smuzhiyun 
3529*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11d_cfg));
3530*4882a593Smuzhiyun 	if (req == NULL) {
3531*4882a593Smuzhiyun 		ret = -ENOMEM;
3532*4882a593Smuzhiyun 		goto done;
3533*4882a593Smuzhiyun 	}
3534*4882a593Smuzhiyun 
3535*4882a593Smuzhiyun 	pcfg_11d = (mlan_ds_11d_cfg *)req->pbuf;
3536*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_11D_CFG;
3537*4882a593Smuzhiyun 	pcfg_11d->sub_command = MLAN_OID_11D_CFG_ENABLE;
3538*4882a593Smuzhiyun 	if (wrq->u.data.length) {
3539*4882a593Smuzhiyun 		/* Set 11D configuration */
3540*4882a593Smuzhiyun 		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
3541*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
3542*4882a593Smuzhiyun 			ret = -EFAULT;
3543*4882a593Smuzhiyun 			goto done;
3544*4882a593Smuzhiyun 		}
3545*4882a593Smuzhiyun 		if ((data < CMD_DISABLED) || (data > CMD_ENABLED)) {
3546*4882a593Smuzhiyun 			ret = -EINVAL;
3547*4882a593Smuzhiyun 			goto done;
3548*4882a593Smuzhiyun 		}
3549*4882a593Smuzhiyun 		if (data == CMD_DISABLED)
3550*4882a593Smuzhiyun 			pcfg_11d->param.enable_11d = MFALSE;
3551*4882a593Smuzhiyun 		else
3552*4882a593Smuzhiyun 			pcfg_11d->param.enable_11d = MTRUE;
3553*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
3554*4882a593Smuzhiyun 	} else {
3555*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
3556*4882a593Smuzhiyun 	}
3557*4882a593Smuzhiyun 
3558*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3559*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
3560*4882a593Smuzhiyun 		ret = -EFAULT;
3561*4882a593Smuzhiyun 		goto done;
3562*4882a593Smuzhiyun 	}
3563*4882a593Smuzhiyun 
3564*4882a593Smuzhiyun 	if (wrq->u.data.pointer) {
3565*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer,
3566*4882a593Smuzhiyun 				 &pcfg_11d->param.enable_11d,
3567*4882a593Smuzhiyun 				 sizeof(pcfg_11d->param.enable_11d))) {
3568*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
3569*4882a593Smuzhiyun 			ret = -EFAULT;
3570*4882a593Smuzhiyun 			goto done;
3571*4882a593Smuzhiyun 		}
3572*4882a593Smuzhiyun 		wrq->u.data.length = 1;
3573*4882a593Smuzhiyun 	}
3574*4882a593Smuzhiyun done:
3575*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
3576*4882a593Smuzhiyun 		kfree(req);
3577*4882a593Smuzhiyun 	LEAVE();
3578*4882a593Smuzhiyun 	return ret;
3579*4882a593Smuzhiyun }
3580*4882a593Smuzhiyun 
3581*4882a593Smuzhiyun /**
3582*4882a593Smuzhiyun  *  @brief Implement 802.11D clear chan table command
3583*4882a593Smuzhiyun  *
3584*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
3585*4882a593Smuzhiyun  *  @param wrq      Pointer to user data
3586*4882a593Smuzhiyun  *
3587*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
3588*4882a593Smuzhiyun  */
woal_11d_clr_chan_table(moal_private * priv,struct iwreq * wrq)3589*4882a593Smuzhiyun static int woal_11d_clr_chan_table(moal_private *priv, struct iwreq *wrq)
3590*4882a593Smuzhiyun {
3591*4882a593Smuzhiyun 	int ret = 0;
3592*4882a593Smuzhiyun 	mlan_ds_11d_cfg *pcfg_11d = NULL;
3593*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
3594*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
3595*4882a593Smuzhiyun 
3596*4882a593Smuzhiyun 	ENTER();
3597*4882a593Smuzhiyun 
3598*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11d_cfg));
3599*4882a593Smuzhiyun 	if (req == NULL) {
3600*4882a593Smuzhiyun 		ret = -ENOMEM;
3601*4882a593Smuzhiyun 		goto done;
3602*4882a593Smuzhiyun 	}
3603*4882a593Smuzhiyun 
3604*4882a593Smuzhiyun 	pcfg_11d = (mlan_ds_11d_cfg *)req->pbuf;
3605*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_11D_CFG;
3606*4882a593Smuzhiyun 	pcfg_11d->sub_command = MLAN_OID_11D_CLR_CHAN_TABLE;
3607*4882a593Smuzhiyun 	req->action = MLAN_ACT_SET;
3608*4882a593Smuzhiyun 
3609*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3610*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
3611*4882a593Smuzhiyun 		ret = -EFAULT;
3612*4882a593Smuzhiyun 		goto done;
3613*4882a593Smuzhiyun 	}
3614*4882a593Smuzhiyun 
3615*4882a593Smuzhiyun done:
3616*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
3617*4882a593Smuzhiyun 		kfree(req);
3618*4882a593Smuzhiyun 	LEAVE();
3619*4882a593Smuzhiyun 	return ret;
3620*4882a593Smuzhiyun }
3621*4882a593Smuzhiyun 
3622*4882a593Smuzhiyun /**
3623*4882a593Smuzhiyun  *  @brief Control WPS Session Enable/Disable
3624*4882a593Smuzhiyun  *
3625*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
3626*4882a593Smuzhiyun  *  @param wrq      Pointer to user data
3627*4882a593Smuzhiyun  *
3628*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
3629*4882a593Smuzhiyun  */
woal_wps_cfg_ioctl(moal_private * priv,struct iwreq * wrq)3630*4882a593Smuzhiyun static int woal_wps_cfg_ioctl(moal_private *priv, struct iwreq *wrq)
3631*4882a593Smuzhiyun {
3632*4882a593Smuzhiyun 	int ret = 0;
3633*4882a593Smuzhiyun 	mlan_ds_wps_cfg *pwps = NULL;
3634*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
3635*4882a593Smuzhiyun 	char buf[8];
3636*4882a593Smuzhiyun 	struct iwreq *wreq = (struct iwreq *)wrq;
3637*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
3638*4882a593Smuzhiyun 
3639*4882a593Smuzhiyun 	ENTER();
3640*4882a593Smuzhiyun 
3641*4882a593Smuzhiyun 	PRINTM(MINFO, "WOAL_WPS_SESSION\n");
3642*4882a593Smuzhiyun 
3643*4882a593Smuzhiyun 	memset(buf, 0, sizeof(buf));
3644*4882a593Smuzhiyun 	if (copy_from_user(buf, wreq->u.data.pointer,
3645*4882a593Smuzhiyun 			   MIN(sizeof(buf) - 1, wreq->u.data.length))) {
3646*4882a593Smuzhiyun 		PRINTM(MERROR, "Copy from user failed\n");
3647*4882a593Smuzhiyun 		ret = -EFAULT;
3648*4882a593Smuzhiyun 		goto done;
3649*4882a593Smuzhiyun 	}
3650*4882a593Smuzhiyun 
3651*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wps_cfg));
3652*4882a593Smuzhiyun 	if (req == NULL) {
3653*4882a593Smuzhiyun 		ret = -ENOMEM;
3654*4882a593Smuzhiyun 		goto done;
3655*4882a593Smuzhiyun 	}
3656*4882a593Smuzhiyun 
3657*4882a593Smuzhiyun 	pwps = (mlan_ds_wps_cfg *)req->pbuf;
3658*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_WPS_CFG;
3659*4882a593Smuzhiyun 	req->action = MLAN_ACT_SET;
3660*4882a593Smuzhiyun 	pwps->sub_command = MLAN_OID_WPS_CFG_SESSION;
3661*4882a593Smuzhiyun 	if (buf[0] == 1)
3662*4882a593Smuzhiyun 		pwps->param.wps_session = MLAN_WPS_CFG_SESSION_START;
3663*4882a593Smuzhiyun 	else
3664*4882a593Smuzhiyun 		pwps->param.wps_session = MLAN_WPS_CFG_SESSION_END;
3665*4882a593Smuzhiyun 
3666*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3667*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
3668*4882a593Smuzhiyun 		ret = -EFAULT;
3669*4882a593Smuzhiyun 		goto done;
3670*4882a593Smuzhiyun 	}
3671*4882a593Smuzhiyun 
3672*4882a593Smuzhiyun done:
3673*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
3674*4882a593Smuzhiyun 		kfree(req);
3675*4882a593Smuzhiyun 	LEAVE();
3676*4882a593Smuzhiyun 	return ret;
3677*4882a593Smuzhiyun }
3678*4882a593Smuzhiyun 
3679*4882a593Smuzhiyun /**
3680*4882a593Smuzhiyun  *  @brief Set WPA passphrase and SSID
3681*4882a593Smuzhiyun  *
3682*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
3683*4882a593Smuzhiyun  *  @param wrq      A pointer to user data
3684*4882a593Smuzhiyun  *
3685*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
3686*4882a593Smuzhiyun  */
woal_passphrase(moal_private * priv,struct iwreq * wrq)3687*4882a593Smuzhiyun static int woal_passphrase(moal_private *priv, struct iwreq *wrq)
3688*4882a593Smuzhiyun {
3689*4882a593Smuzhiyun 	t_u16 len = 0;
3690*4882a593Smuzhiyun 	char buf[256];
3691*4882a593Smuzhiyun 	char *begin = NULL, *end = NULL, *opt = NULL;
3692*4882a593Smuzhiyun 	int ret = 0, action = -1, i;
3693*4882a593Smuzhiyun 	mlan_ds_sec_cfg *sec = NULL;
3694*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
3695*4882a593Smuzhiyun 	t_u8 zero_mac[] = {0, 0, 0, 0, 0, 0};
3696*4882a593Smuzhiyun 	t_u8 *mac = NULL;
3697*4882a593Smuzhiyun 	int data_length = wrq->u.data.length, copy_len;
3698*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
3699*4882a593Smuzhiyun 
3700*4882a593Smuzhiyun 	ENTER();
3701*4882a593Smuzhiyun 
3702*4882a593Smuzhiyun 	if (!priv->phandle->card_info->embedded_supp) {
3703*4882a593Smuzhiyun 		PRINTM(MERROR, "Not supported cmd on this card\n");
3704*4882a593Smuzhiyun 		ret = -EOPNOTSUPP;
3705*4882a593Smuzhiyun 		goto done;
3706*4882a593Smuzhiyun 	}
3707*4882a593Smuzhiyun 	if (!data_length || data_length >= (int)sizeof(buf) - 1) {
3708*4882a593Smuzhiyun 		PRINTM(MERROR,
3709*4882a593Smuzhiyun 		       "Argument missing or too long for setpassphrase\n");
3710*4882a593Smuzhiyun 		ret = -EINVAL;
3711*4882a593Smuzhiyun 		goto done;
3712*4882a593Smuzhiyun 	}
3713*4882a593Smuzhiyun 	memset(buf, 0, sizeof(buf));
3714*4882a593Smuzhiyun 	copy_len = data_length;
3715*4882a593Smuzhiyun 
3716*4882a593Smuzhiyun 	if (copy_from_user(buf, wrq->u.data.pointer, copy_len)) {
3717*4882a593Smuzhiyun 		PRINTM(MERROR, "Copy from user failed\n");
3718*4882a593Smuzhiyun 		ret = -EFAULT;
3719*4882a593Smuzhiyun 		goto done;
3720*4882a593Smuzhiyun 	}
3721*4882a593Smuzhiyun 	buf[copy_len] = '\0';
3722*4882a593Smuzhiyun 
3723*4882a593Smuzhiyun 	/* Parse the buf to get the cmd_action */
3724*4882a593Smuzhiyun 	begin = buf;
3725*4882a593Smuzhiyun 	end = woal_strsep(&begin, ';', '/');
3726*4882a593Smuzhiyun 	if (!end) {
3727*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid option\n");
3728*4882a593Smuzhiyun 		ret = -EINVAL;
3729*4882a593Smuzhiyun 		goto done;
3730*4882a593Smuzhiyun 	}
3731*4882a593Smuzhiyun 	action = woal_atox(end);
3732*4882a593Smuzhiyun 	if (action < 0 || action > 2 || end[1] != '\0') {
3733*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid action argument %s\n", end);
3734*4882a593Smuzhiyun 		ret = -EINVAL;
3735*4882a593Smuzhiyun 		goto done;
3736*4882a593Smuzhiyun 	}
3737*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
3738*4882a593Smuzhiyun 	if (req == NULL) {
3739*4882a593Smuzhiyun 		ret = -ENOMEM;
3740*4882a593Smuzhiyun 		goto done;
3741*4882a593Smuzhiyun 	}
3742*4882a593Smuzhiyun 	sec = (mlan_ds_sec_cfg *)req->pbuf;
3743*4882a593Smuzhiyun 	sec->sub_command = MLAN_OID_SEC_CFG_PASSPHRASE;
3744*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_SEC_CFG;
3745*4882a593Smuzhiyun 	if (action == 0)
3746*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
3747*4882a593Smuzhiyun 	else
3748*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
3749*4882a593Smuzhiyun 	while (begin) {
3750*4882a593Smuzhiyun 		end = woal_strsep(&begin, ';', '/');
3751*4882a593Smuzhiyun 		opt = woal_strsep(&end, '=', '/');
3752*4882a593Smuzhiyun 		if (!opt || !end || !end[0]) {
3753*4882a593Smuzhiyun 			PRINTM(MERROR, "Invalid option\n");
3754*4882a593Smuzhiyun 			ret = -EINVAL;
3755*4882a593Smuzhiyun 			break;
3756*4882a593Smuzhiyun 		} else if (!strnicmp(opt, "ssid", strlen(opt))) {
3757*4882a593Smuzhiyun 			if (strlen(end) > MLAN_MAX_SSID_LENGTH) {
3758*4882a593Smuzhiyun 				PRINTM(MERROR,
3759*4882a593Smuzhiyun 				       "SSID length exceeds max length\n");
3760*4882a593Smuzhiyun 				ret = -EFAULT;
3761*4882a593Smuzhiyun 				break;
3762*4882a593Smuzhiyun 			}
3763*4882a593Smuzhiyun 			sec->param.passphrase.ssid.ssid_len = strlen(end);
3764*4882a593Smuzhiyun 			moal_memcpy_ext(priv->phandle,
3765*4882a593Smuzhiyun 					sec->param.passphrase.ssid.ssid, end,
3766*4882a593Smuzhiyun 					strlen(end), MLAN_MAX_SSID_LENGTH);
3767*4882a593Smuzhiyun 			PRINTM(MINFO, "ssid=%s, len=%d\n",
3768*4882a593Smuzhiyun 			       sec->param.passphrase.ssid.ssid,
3769*4882a593Smuzhiyun 			       (int)sec->param.passphrase.ssid.ssid_len);
3770*4882a593Smuzhiyun 		} else if (!strnicmp(opt, "bssid", strlen(opt))) {
3771*4882a593Smuzhiyun 			woal_mac2u8(sec->param.passphrase.bssid, end);
3772*4882a593Smuzhiyun 		} else if (!strnicmp(opt, "psk", strlen(opt)) &&
3773*4882a593Smuzhiyun 			   req->action == MLAN_ACT_SET) {
3774*4882a593Smuzhiyun 			if (strlen(end) != MLAN_PMK_HEXSTR_LENGTH) {
3775*4882a593Smuzhiyun 				PRINTM(MERROR, "Invalid PMK length\n");
3776*4882a593Smuzhiyun 				ret = -EINVAL;
3777*4882a593Smuzhiyun 				break;
3778*4882a593Smuzhiyun 			}
3779*4882a593Smuzhiyun 			woal_ascii2hex(
3780*4882a593Smuzhiyun 				(t_u8 *)(sec->param.passphrase.psk.pmk.pmk),
3781*4882a593Smuzhiyun 				end, MLAN_PMK_HEXSTR_LENGTH / 2);
3782*4882a593Smuzhiyun 			sec->param.passphrase.psk_type = MLAN_PSK_PMK;
3783*4882a593Smuzhiyun 		} else if (!strnicmp(opt, "passphrase", strlen(opt)) &&
3784*4882a593Smuzhiyun 			   req->action == MLAN_ACT_SET) {
3785*4882a593Smuzhiyun 			if (strlen(end) < MLAN_MIN_PASSPHRASE_LENGTH ||
3786*4882a593Smuzhiyun 			    strlen(end) > MLAN_MAX_PASSPHRASE_LENGTH) {
3787*4882a593Smuzhiyun 				PRINTM(MERROR,
3788*4882a593Smuzhiyun 				       "Invalid length for passphrase\n");
3789*4882a593Smuzhiyun 				ret = -EINVAL;
3790*4882a593Smuzhiyun 				break;
3791*4882a593Smuzhiyun 			}
3792*4882a593Smuzhiyun 			sec->param.passphrase.psk_type = MLAN_PSK_PASSPHRASE;
3793*4882a593Smuzhiyun 			moal_memcpy_ext(
3794*4882a593Smuzhiyun 				priv->phandle,
3795*4882a593Smuzhiyun 				sec->param.passphrase.psk.passphrase.passphrase,
3796*4882a593Smuzhiyun 				end,
3797*4882a593Smuzhiyun 				sizeof(sec->param.passphrase.psk.passphrase
3798*4882a593Smuzhiyun 					       .passphrase),
3799*4882a593Smuzhiyun 				sizeof(sec->param.passphrase.psk.passphrase
3800*4882a593Smuzhiyun 					       .passphrase));
3801*4882a593Smuzhiyun 			sec->param.passphrase.psk.passphrase.passphrase_len =
3802*4882a593Smuzhiyun 				strlen(end);
3803*4882a593Smuzhiyun 			PRINTM(MINFO, "passphrase=%s, len=%d\n",
3804*4882a593Smuzhiyun 			       sec->param.passphrase.psk.passphrase.passphrase,
3805*4882a593Smuzhiyun 			       (int)sec->param.passphrase.psk.passphrase
3806*4882a593Smuzhiyun 				       .passphrase_len);
3807*4882a593Smuzhiyun 		} else {
3808*4882a593Smuzhiyun 			PRINTM(MERROR, "Invalid option %s\n", opt);
3809*4882a593Smuzhiyun 			ret = -EINVAL;
3810*4882a593Smuzhiyun 			break;
3811*4882a593Smuzhiyun 		}
3812*4882a593Smuzhiyun 	}
3813*4882a593Smuzhiyun 	if (ret)
3814*4882a593Smuzhiyun 		goto done;
3815*4882a593Smuzhiyun 
3816*4882a593Smuzhiyun 	if (action == 2)
3817*4882a593Smuzhiyun 		sec->param.passphrase.psk_type = MLAN_PSK_CLEAR;
3818*4882a593Smuzhiyun 	else if (action == 0)
3819*4882a593Smuzhiyun 		sec->param.passphrase.psk_type = MLAN_PSK_QUERY;
3820*4882a593Smuzhiyun 
3821*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3822*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
3823*4882a593Smuzhiyun 		ret = -EFAULT;
3824*4882a593Smuzhiyun 		goto done;
3825*4882a593Smuzhiyun 	}
3826*4882a593Smuzhiyun 	if (action == 0) {
3827*4882a593Smuzhiyun 		memset(buf, 0, sizeof(buf));
3828*4882a593Smuzhiyun 		if (sec->param.passphrase.ssid.ssid_len) {
3829*4882a593Smuzhiyun 			len += sprintf(buf + len, "ssid:");
3830*4882a593Smuzhiyun 			moal_memcpy_ext(priv->phandle, buf + len,
3831*4882a593Smuzhiyun 					sec->param.passphrase.ssid.ssid,
3832*4882a593Smuzhiyun 					sec->param.passphrase.ssid.ssid_len,
3833*4882a593Smuzhiyun 					sizeof(buf) - len);
3834*4882a593Smuzhiyun 			len += sec->param.passphrase.ssid.ssid_len;
3835*4882a593Smuzhiyun 			len += sprintf(buf + len, " ");
3836*4882a593Smuzhiyun 		}
3837*4882a593Smuzhiyun 		if (memcmp(&sec->param.passphrase.bssid, zero_mac,
3838*4882a593Smuzhiyun 			   sizeof(zero_mac))) {
3839*4882a593Smuzhiyun 			mac = (t_u8 *)&sec->param.passphrase.bssid;
3840*4882a593Smuzhiyun 			len += sprintf(buf + len, "bssid:");
3841*4882a593Smuzhiyun 			for (i = 0; i < ETH_ALEN - 1; ++i)
3842*4882a593Smuzhiyun 				len += sprintf(buf + len, "%02x:", mac[i]);
3843*4882a593Smuzhiyun 			len += sprintf(buf + len, "%02x ", mac[i]);
3844*4882a593Smuzhiyun 		}
3845*4882a593Smuzhiyun 		if (sec->param.passphrase.psk_type == MLAN_PSK_PMK) {
3846*4882a593Smuzhiyun 			len += sprintf(buf + len, "psk:");
3847*4882a593Smuzhiyun 			for (i = 0; i < MLAN_MAX_KEY_LENGTH; ++i)
3848*4882a593Smuzhiyun 				len += sprintf(
3849*4882a593Smuzhiyun 					buf + len, "%02x",
3850*4882a593Smuzhiyun 					sec->param.passphrase.psk.pmk.pmk[i]);
3851*4882a593Smuzhiyun 			len += sprintf(buf + len, "\n");
3852*4882a593Smuzhiyun 		}
3853*4882a593Smuzhiyun 		if (sec->param.passphrase.psk_type == MLAN_PSK_PASSPHRASE) {
3854*4882a593Smuzhiyun 			len += sprintf(
3855*4882a593Smuzhiyun 				buf + len, "passphrase:%s\n",
3856*4882a593Smuzhiyun 				sec->param.passphrase.psk.passphrase.passphrase);
3857*4882a593Smuzhiyun 		}
3858*4882a593Smuzhiyun 		if (wrq->u.data.pointer) {
3859*4882a593Smuzhiyun 			if (copy_to_user(wrq->u.data.pointer, buf,
3860*4882a593Smuzhiyun 					 MIN(len, sizeof(buf)))) {
3861*4882a593Smuzhiyun 				PRINTM(MERROR, "Copy to user failed, len %d\n",
3862*4882a593Smuzhiyun 				       len);
3863*4882a593Smuzhiyun 				ret = -EFAULT;
3864*4882a593Smuzhiyun 				goto done;
3865*4882a593Smuzhiyun 			}
3866*4882a593Smuzhiyun 			wrq->u.data.length = len;
3867*4882a593Smuzhiyun 		}
3868*4882a593Smuzhiyun 	}
3869*4882a593Smuzhiyun done:
3870*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
3871*4882a593Smuzhiyun 		kfree(req);
3872*4882a593Smuzhiyun 	LEAVE();
3873*4882a593Smuzhiyun 	return ret;
3874*4882a593Smuzhiyun }
3875*4882a593Smuzhiyun 
3876*4882a593Smuzhiyun /**
3877*4882a593Smuzhiyun  *  @brief Get esupp mode
3878*4882a593Smuzhiyun  *
3879*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
3880*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
3881*4882a593Smuzhiyun  *
3882*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
3883*4882a593Smuzhiyun  */
woal_get_esupp_mode(moal_private * priv,struct iwreq * wrq)3884*4882a593Smuzhiyun static int woal_get_esupp_mode(moal_private *priv, struct iwreq *wrq)
3885*4882a593Smuzhiyun {
3886*4882a593Smuzhiyun 	int ret = 0;
3887*4882a593Smuzhiyun 	mlan_ds_sec_cfg *sec = NULL;
3888*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
3889*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
3890*4882a593Smuzhiyun 
3891*4882a593Smuzhiyun 	ENTER();
3892*4882a593Smuzhiyun 
3893*4882a593Smuzhiyun 	if (!priv->phandle->card_info->embedded_supp) {
3894*4882a593Smuzhiyun 		PRINTM(MERROR, "Not supported cmd on this card\n");
3895*4882a593Smuzhiyun 		ret = -EOPNOTSUPP;
3896*4882a593Smuzhiyun 		goto done;
3897*4882a593Smuzhiyun 	}
3898*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
3899*4882a593Smuzhiyun 	if (req == NULL) {
3900*4882a593Smuzhiyun 		ret = -ENOMEM;
3901*4882a593Smuzhiyun 		goto done;
3902*4882a593Smuzhiyun 	}
3903*4882a593Smuzhiyun 	sec = (mlan_ds_sec_cfg *)req->pbuf;
3904*4882a593Smuzhiyun 	sec->sub_command = MLAN_OID_SEC_CFG_ESUPP_MODE;
3905*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_SEC_CFG;
3906*4882a593Smuzhiyun 	req->action = MLAN_ACT_GET;
3907*4882a593Smuzhiyun 
3908*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3909*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
3910*4882a593Smuzhiyun 		ret = -EFAULT;
3911*4882a593Smuzhiyun 		goto done;
3912*4882a593Smuzhiyun 	}
3913*4882a593Smuzhiyun 
3914*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, (t_u8 *)&sec->param.esupp_mode,
3915*4882a593Smuzhiyun 			 sizeof(int) * 3)) {
3916*4882a593Smuzhiyun 		ret = -EFAULT;
3917*4882a593Smuzhiyun 		goto done;
3918*4882a593Smuzhiyun 	}
3919*4882a593Smuzhiyun 	wrq->u.data.length = 3;
3920*4882a593Smuzhiyun done:
3921*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
3922*4882a593Smuzhiyun 		kfree(req);
3923*4882a593Smuzhiyun 	LEAVE();
3924*4882a593Smuzhiyun 	return ret;
3925*4882a593Smuzhiyun }
3926*4882a593Smuzhiyun 
3927*4882a593Smuzhiyun /**
3928*4882a593Smuzhiyun  *  @brief Get GTK/PTK
3929*4882a593Smuzhiyun  *
3930*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
3931*4882a593Smuzhiyun  *  @param wrq      A pointer to user data
3932*4882a593Smuzhiyun  *
3933*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
3934*4882a593Smuzhiyun  */
woal_get_key_ioctl(moal_private * priv,struct iwreq * wrq)3935*4882a593Smuzhiyun static int woal_get_key_ioctl(moal_private *priv, struct iwreq *wrq)
3936*4882a593Smuzhiyun {
3937*4882a593Smuzhiyun 	int ret = 0;
3938*4882a593Smuzhiyun 	unsigned int i;
3939*4882a593Smuzhiyun 	t_u8 key_ascii[256];
3940*4882a593Smuzhiyun 	t_u8 *tmp;
3941*4882a593Smuzhiyun 	mlan_ds_sec_cfg *sec = NULL;
3942*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
3943*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
3944*4882a593Smuzhiyun 
3945*4882a593Smuzhiyun 	ENTER();
3946*4882a593Smuzhiyun 
3947*4882a593Smuzhiyun 	memset(key_ascii, 0x00, sizeof(key_ascii));
3948*4882a593Smuzhiyun 	tmp = key_ascii;
3949*4882a593Smuzhiyun 
3950*4882a593Smuzhiyun 	if (priv->media_connected == MFALSE) {
3951*4882a593Smuzhiyun 		PRINTM(MERROR, "Can't get key in un-associated state\n");
3952*4882a593Smuzhiyun 		ret = -EFAULT;
3953*4882a593Smuzhiyun 		goto done;
3954*4882a593Smuzhiyun 	}
3955*4882a593Smuzhiyun 
3956*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
3957*4882a593Smuzhiyun 	if (req == NULL) {
3958*4882a593Smuzhiyun 		ret = -ENOMEM;
3959*4882a593Smuzhiyun 		goto done;
3960*4882a593Smuzhiyun 	}
3961*4882a593Smuzhiyun 
3962*4882a593Smuzhiyun 	/* Get Unicast Key */
3963*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_SEC_CFG;
3964*4882a593Smuzhiyun 	req->action = MLAN_ACT_GET;
3965*4882a593Smuzhiyun 	sec = (mlan_ds_sec_cfg *)req->pbuf;
3966*4882a593Smuzhiyun 	sec->sub_command = MLAN_OID_SEC_QUERY_KEY;
3967*4882a593Smuzhiyun 	sec->param.encrypt_key.key_index = 0;
3968*4882a593Smuzhiyun 	sec->param.encrypt_key.key_flags = 0;
3969*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3970*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
3971*4882a593Smuzhiyun 		ret = -EFAULT;
3972*4882a593Smuzhiyun 		goto done;
3973*4882a593Smuzhiyun 	}
3974*4882a593Smuzhiyun 	if (sec->param.encrypt_key.key_len) {
3975*4882a593Smuzhiyun 		sprintf((char *)tmp, "\n%s", "PTK: ");
3976*4882a593Smuzhiyun 		tmp += 5;
3977*4882a593Smuzhiyun 		for (i = 0; i < sec->param.encrypt_key.key_len; i++)
3978*4882a593Smuzhiyun 			tmp += sprintf((char *)tmp, "%02x",
3979*4882a593Smuzhiyun 				       sec->param.encrypt_key.key_material[i]);
3980*4882a593Smuzhiyun 	}
3981*4882a593Smuzhiyun 
3982*4882a593Smuzhiyun 	/* Get Multicase Key */
3983*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_SEC_CFG;
3984*4882a593Smuzhiyun 	req->action = MLAN_ACT_GET;
3985*4882a593Smuzhiyun 	sec = (mlan_ds_sec_cfg *)req->pbuf;
3986*4882a593Smuzhiyun 	sec->sub_command = MLAN_OID_SEC_QUERY_KEY;
3987*4882a593Smuzhiyun 	sec->param.encrypt_key.key_index = 0;
3988*4882a593Smuzhiyun 	sec->param.encrypt_key.key_flags = KEY_FLAG_GROUP_KEY;
3989*4882a593Smuzhiyun 	memset(sec->param.encrypt_key.mac_addr, 0x0, MLAN_MAC_ADDR_LENGTH);
3990*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3991*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
3992*4882a593Smuzhiyun 		ret = -EFAULT;
3993*4882a593Smuzhiyun 		goto done;
3994*4882a593Smuzhiyun 	}
3995*4882a593Smuzhiyun 	if (sec->param.encrypt_key.key_len) {
3996*4882a593Smuzhiyun 		sprintf((char *)tmp, "\n%s", "GTK: ");
3997*4882a593Smuzhiyun 		tmp += 5;
3998*4882a593Smuzhiyun 		for (i = 0; i < sec->param.encrypt_key.key_len; i++)
3999*4882a593Smuzhiyun 			tmp += sprintf((char *)tmp, "%02x",
4000*4882a593Smuzhiyun 				       sec->param.encrypt_key.key_material[i]);
4001*4882a593Smuzhiyun 	}
4002*4882a593Smuzhiyun 
4003*4882a593Smuzhiyun 	/* Get IGTK Key */
4004*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_SEC_CFG;
4005*4882a593Smuzhiyun 	req->action = MLAN_ACT_GET;
4006*4882a593Smuzhiyun 	sec = (mlan_ds_sec_cfg *)req->pbuf;
4007*4882a593Smuzhiyun 	sec->sub_command = MLAN_OID_SEC_QUERY_KEY;
4008*4882a593Smuzhiyun 	sec->param.encrypt_key.key_index = 0;
4009*4882a593Smuzhiyun 	sec->param.encrypt_key.key_flags = KEY_FLAG_AES_MCAST_IGTK;
4010*4882a593Smuzhiyun 	memset(sec->param.encrypt_key.mac_addr, 0x0, MLAN_MAC_ADDR_LENGTH);
4011*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4012*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
4013*4882a593Smuzhiyun 		ret = -EFAULT;
4014*4882a593Smuzhiyun 		goto done;
4015*4882a593Smuzhiyun 	}
4016*4882a593Smuzhiyun 	if (sec->param.encrypt_key.key_len) {
4017*4882a593Smuzhiyun 		sprintf((char *)tmp, "\n%s", "IGTK: ");
4018*4882a593Smuzhiyun 		tmp += 6;
4019*4882a593Smuzhiyun 		for (i = 0; i < sec->param.encrypt_key.key_len; i++)
4020*4882a593Smuzhiyun 			tmp += sprintf((char *)tmp, "%02x",
4021*4882a593Smuzhiyun 				       sec->param.encrypt_key.key_material[i]);
4022*4882a593Smuzhiyun 	}
4023*4882a593Smuzhiyun 
4024*4882a593Smuzhiyun 	wrq->u.data.length = sizeof(key_ascii) + 1;
4025*4882a593Smuzhiyun 	if (wrq->u.data.pointer) {
4026*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &key_ascii,
4027*4882a593Smuzhiyun 				 tmp - key_ascii)) {
4028*4882a593Smuzhiyun 			PRINTM(MERROR, "copy_to_user failed\n");
4029*4882a593Smuzhiyun 			ret = -EFAULT;
4030*4882a593Smuzhiyun 			goto done;
4031*4882a593Smuzhiyun 		}
4032*4882a593Smuzhiyun 	}
4033*4882a593Smuzhiyun done:
4034*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
4035*4882a593Smuzhiyun 		kfree(req);
4036*4882a593Smuzhiyun 	LEAVE();
4037*4882a593Smuzhiyun 	return ret;
4038*4882a593Smuzhiyun }
4039*4882a593Smuzhiyun 
4040*4882a593Smuzhiyun /**
4041*4882a593Smuzhiyun  *  @brief arpfilter ioctl function
4042*4882a593Smuzhiyun  *
4043*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
4044*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
4045*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
4046*4882a593Smuzhiyun  */
woal_arp_filter(moal_private * priv,struct iwreq * wrq)4047*4882a593Smuzhiyun static int woal_arp_filter(moal_private *priv, struct iwreq *wrq)
4048*4882a593Smuzhiyun {
4049*4882a593Smuzhiyun 	int ret = 0;
4050*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = NULL;
4051*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
4052*4882a593Smuzhiyun 	int data_length = wrq->u.data.length, copy_len;
4053*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
4054*4882a593Smuzhiyun 
4055*4882a593Smuzhiyun 	ENTER();
4056*4882a593Smuzhiyun 
4057*4882a593Smuzhiyun 	copy_len = MIN(sizeof(misc->param.gen_ie.ie_data),
4058*4882a593Smuzhiyun 		       sizeof(int) * data_length);
4059*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
4060*4882a593Smuzhiyun 	if (req == NULL) {
4061*4882a593Smuzhiyun 		ret = -ENOMEM;
4062*4882a593Smuzhiyun 		goto done;
4063*4882a593Smuzhiyun 	}
4064*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)req->pbuf;
4065*4882a593Smuzhiyun 	misc->sub_command = MLAN_OID_MISC_GEN_IE;
4066*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_MISC_CFG;
4067*4882a593Smuzhiyun 	req->action = MLAN_ACT_SET;
4068*4882a593Smuzhiyun 	misc->param.gen_ie.type = MLAN_IE_TYPE_ARP_FILTER;
4069*4882a593Smuzhiyun 	misc->param.gen_ie.len = data_length;
4070*4882a593Smuzhiyun 
4071*4882a593Smuzhiyun 	/* get the whole command from user */
4072*4882a593Smuzhiyun 	if (copy_from_user(misc->param.gen_ie.ie_data, wrq->u.data.pointer,
4073*4882a593Smuzhiyun 			   copy_len)) {
4074*4882a593Smuzhiyun 		PRINTM(MERROR, "copy from user failed\n");
4075*4882a593Smuzhiyun 		ret = -EFAULT;
4076*4882a593Smuzhiyun 		goto done;
4077*4882a593Smuzhiyun 	}
4078*4882a593Smuzhiyun 
4079*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4080*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
4081*4882a593Smuzhiyun 		ret = -EFAULT;
4082*4882a593Smuzhiyun 		goto done;
4083*4882a593Smuzhiyun 	}
4084*4882a593Smuzhiyun done:
4085*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
4086*4882a593Smuzhiyun 		kfree(req);
4087*4882a593Smuzhiyun 	LEAVE();
4088*4882a593Smuzhiyun 	return ret;
4089*4882a593Smuzhiyun }
4090*4882a593Smuzhiyun 
4091*4882a593Smuzhiyun /**
4092*4882a593Smuzhiyun  *  @brief Set/get IP address
4093*4882a593Smuzhiyun  *
4094*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
4095*4882a593Smuzhiyun  *  @param wrq          A pointer to iwreq structure
4096*4882a593Smuzhiyun  *  @return             0 --success, otherwise fail
4097*4882a593Smuzhiyun  */
woal_set_get_ip_addr(moal_private * priv,struct iwreq * wrq)4098*4882a593Smuzhiyun static int woal_set_get_ip_addr(moal_private *priv, struct iwreq *wrq)
4099*4882a593Smuzhiyun {
4100*4882a593Smuzhiyun 	char buf[IPADDR_MAX_BUF];
4101*4882a593Smuzhiyun 	mlan_ioctl_req *ioctl_req = NULL;
4102*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = NULL;
4103*4882a593Smuzhiyun 	int ret = 0, op_code = 0, data_length = wrq->u.data.length;
4104*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
4105*4882a593Smuzhiyun 
4106*4882a593Smuzhiyun 	ENTER();
4107*4882a593Smuzhiyun 
4108*4882a593Smuzhiyun 	memset(buf, 0, IPADDR_MAX_BUF);
4109*4882a593Smuzhiyun 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
4110*4882a593Smuzhiyun 	if (ioctl_req == NULL) {
4111*4882a593Smuzhiyun 		ret = -ENOMEM;
4112*4882a593Smuzhiyun 		goto done;
4113*4882a593Smuzhiyun 	}
4114*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)ioctl_req->pbuf;
4115*4882a593Smuzhiyun 
4116*4882a593Smuzhiyun 	if (data_length <= 1) { /* GET */
4117*4882a593Smuzhiyun 		ioctl_req->action = MLAN_ACT_GET;
4118*4882a593Smuzhiyun 	} else {
4119*4882a593Smuzhiyun 		if (copy_from_user(buf, wrq->u.data.pointer,
4120*4882a593Smuzhiyun 				   MIN(IPADDR_MAX_BUF - 1, data_length))) {
4121*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
4122*4882a593Smuzhiyun 			ret = -EFAULT;
4123*4882a593Smuzhiyun 			goto done;
4124*4882a593Smuzhiyun 		}
4125*4882a593Smuzhiyun 		/* Make sure we have the operation argument */
4126*4882a593Smuzhiyun 		if (data_length > 2 && buf[1] != ';') {
4127*4882a593Smuzhiyun 			PRINTM(MERROR,
4128*4882a593Smuzhiyun 			       "No operation argument. Separate with ';'\n");
4129*4882a593Smuzhiyun 			ret = -EINVAL;
4130*4882a593Smuzhiyun 			goto done;
4131*4882a593Smuzhiyun 		} else {
4132*4882a593Smuzhiyun 			buf[1] = '\0';
4133*4882a593Smuzhiyun 		}
4134*4882a593Smuzhiyun 		ioctl_req->action = MLAN_ACT_SET;
4135*4882a593Smuzhiyun 		/* only one IP is supported in current firmware */
4136*4882a593Smuzhiyun 		memset(misc->param.ipaddr_cfg.ip_addr[0], 0, IPADDR_LEN);
4137*4882a593Smuzhiyun 		in4_pton(&buf[2], MIN((IPADDR_MAX_BUF - 3), (data_length - 2)),
4138*4882a593Smuzhiyun 			 misc->param.ipaddr_cfg.ip_addr[0], ' ', NULL);
4139*4882a593Smuzhiyun 		/* only one IP is supported in current firmware */
4140*4882a593Smuzhiyun 		misc->param.ipaddr_cfg.ip_addr_num = 1;
4141*4882a593Smuzhiyun 		misc->param.ipaddr_cfg.ip_addr_type = IPADDR_TYPE_IPV4;
4142*4882a593Smuzhiyun 	}
4143*4882a593Smuzhiyun 	if (woal_atoi(&op_code, buf) != MLAN_STATUS_SUCCESS) {
4144*4882a593Smuzhiyun 		ret = -EINVAL;
4145*4882a593Smuzhiyun 		goto done;
4146*4882a593Smuzhiyun 	}
4147*4882a593Smuzhiyun 	misc->param.ipaddr_cfg.op_code = (t_u32)op_code;
4148*4882a593Smuzhiyun 	ioctl_req->req_id = MLAN_IOCTL_MISC_CFG;
4149*4882a593Smuzhiyun 	misc->sub_command = MLAN_OID_MISC_IP_ADDR;
4150*4882a593Smuzhiyun 
4151*4882a593Smuzhiyun 	/* Send ioctl to mlan */
4152*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
4153*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
4154*4882a593Smuzhiyun 		ret = -EFAULT;
4155*4882a593Smuzhiyun 		goto done;
4156*4882a593Smuzhiyun 	}
4157*4882a593Smuzhiyun 
4158*4882a593Smuzhiyun 	if (ioctl_req->action == MLAN_ACT_GET) {
4159*4882a593Smuzhiyun 		snprintf(buf, IPADDR_MAX_BUF, "%d;%d.%d.%d.%d",
4160*4882a593Smuzhiyun 			 misc->param.ipaddr_cfg.op_code,
4161*4882a593Smuzhiyun 			 misc->param.ipaddr_cfg.ip_addr[0][0],
4162*4882a593Smuzhiyun 			 misc->param.ipaddr_cfg.ip_addr[0][1],
4163*4882a593Smuzhiyun 			 misc->param.ipaddr_cfg.ip_addr[0][2],
4164*4882a593Smuzhiyun 			 misc->param.ipaddr_cfg.ip_addr[0][3]);
4165*4882a593Smuzhiyun 		wrq->u.data.length = IPADDR_MAX_BUF;
4166*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, buf, IPADDR_MAX_BUF)) {
4167*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
4168*4882a593Smuzhiyun 			ret = -EFAULT;
4169*4882a593Smuzhiyun 		}
4170*4882a593Smuzhiyun 	}
4171*4882a593Smuzhiyun 
4172*4882a593Smuzhiyun done:
4173*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
4174*4882a593Smuzhiyun 		kfree(ioctl_req);
4175*4882a593Smuzhiyun 	LEAVE();
4176*4882a593Smuzhiyun 	return ret;
4177*4882a593Smuzhiyun }
4178*4882a593Smuzhiyun 
4179*4882a593Smuzhiyun /**
4180*4882a593Smuzhiyun  *  @brief Set/Get Transmit beamforming capabilities
4181*4882a593Smuzhiyun  *
4182*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
4183*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
4184*4882a593Smuzhiyun  *
4185*4882a593Smuzhiyun  *  @return         0 -- success, otherwise fail
4186*4882a593Smuzhiyun  */
woal_tx_bf_cap_ioctl(moal_private * priv,struct iwreq * wrq)4187*4882a593Smuzhiyun static int woal_tx_bf_cap_ioctl(moal_private *priv, struct iwreq *wrq)
4188*4882a593Smuzhiyun {
4189*4882a593Smuzhiyun 	int ret = 0, data_length = wrq->u.data.length;
4190*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
4191*4882a593Smuzhiyun 	mlan_ds_11n_cfg *bf_cfg = NULL;
4192*4882a593Smuzhiyun 	int bf_cap = 0;
4193*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
4194*4882a593Smuzhiyun 
4195*4882a593Smuzhiyun 	ENTER();
4196*4882a593Smuzhiyun 
4197*4882a593Smuzhiyun 	if (data_length > 1) {
4198*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid no of arguments!\n");
4199*4882a593Smuzhiyun 		ret = -EINVAL;
4200*4882a593Smuzhiyun 		goto done;
4201*4882a593Smuzhiyun 	}
4202*4882a593Smuzhiyun 	/* Allocate an IOCTL request buffer */
4203*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg));
4204*4882a593Smuzhiyun 	if (req == NULL) {
4205*4882a593Smuzhiyun 		ret = -ENOMEM;
4206*4882a593Smuzhiyun 		goto done;
4207*4882a593Smuzhiyun 	}
4208*4882a593Smuzhiyun 
4209*4882a593Smuzhiyun 	/* Fill request buffer */
4210*4882a593Smuzhiyun 	bf_cfg = (mlan_ds_11n_cfg *)req->pbuf;
4211*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_11N_CFG;
4212*4882a593Smuzhiyun 	bf_cfg->sub_command = MLAN_OID_11N_CFG_TX_BF_CAP;
4213*4882a593Smuzhiyun 	req->action = MLAN_ACT_GET;
4214*4882a593Smuzhiyun 	if (data_length) { /* SET */
4215*4882a593Smuzhiyun 		if (copy_from_user(&bf_cap, wrq->u.data.pointer, sizeof(int))) {
4216*4882a593Smuzhiyun 			PRINTM(MERROR, "copy from user failed\n");
4217*4882a593Smuzhiyun 			ret = -EFAULT;
4218*4882a593Smuzhiyun 			goto done;
4219*4882a593Smuzhiyun 		}
4220*4882a593Smuzhiyun 		bf_cfg->param.tx_bf_cap = bf_cap;
4221*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
4222*4882a593Smuzhiyun 	}
4223*4882a593Smuzhiyun 
4224*4882a593Smuzhiyun 	/* Send IOCTL request to MLAN */
4225*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4226*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
4227*4882a593Smuzhiyun 		ret = -EFAULT;
4228*4882a593Smuzhiyun 		goto done;
4229*4882a593Smuzhiyun 	}
4230*4882a593Smuzhiyun 
4231*4882a593Smuzhiyun 	bf_cap = bf_cfg->param.tx_bf_cap;
4232*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, &bf_cap, sizeof(int))) {
4233*4882a593Smuzhiyun 		ret = -EFAULT;
4234*4882a593Smuzhiyun 		goto done;
4235*4882a593Smuzhiyun 	}
4236*4882a593Smuzhiyun 	wrq->u.data.length = 1;
4237*4882a593Smuzhiyun 
4238*4882a593Smuzhiyun done:
4239*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
4240*4882a593Smuzhiyun 		kfree(req);
4241*4882a593Smuzhiyun 	LEAVE();
4242*4882a593Smuzhiyun 	return ret;
4243*4882a593Smuzhiyun }
4244*4882a593Smuzhiyun 
4245*4882a593Smuzhiyun /* Maximum input output characters in group WOAL_SET_GET_256_CHAR */
4246*4882a593Smuzhiyun #define MAX_IN_OUT_CHAR 256
4247*4882a593Smuzhiyun /** Tx BF Global conf argument index */
4248*4882a593Smuzhiyun #define BF_ENABLE_PARAM 1
4249*4882a593Smuzhiyun #define SOUND_ENABLE_PARAM 2
4250*4882a593Smuzhiyun #define FB_TYPE_PARAM 3
4251*4882a593Smuzhiyun #define SNR_THRESHOLD_PARAM 4
4252*4882a593Smuzhiyun #define SOUND_INTVL_PARAM 5
4253*4882a593Smuzhiyun #define BF_MODE_PARAM 6
4254*4882a593Smuzhiyun #define BF_CFG_ACT_GET 0
4255*4882a593Smuzhiyun #define BF_CFG_ACT_SET 1
4256*4882a593Smuzhiyun 
4257*4882a593Smuzhiyun /**
4258*4882a593Smuzhiyun  *  @brief Set/Get Transmit beamforming configuration
4259*4882a593Smuzhiyun  *
4260*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
4261*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
4262*4882a593Smuzhiyun  *
4263*4882a593Smuzhiyun  *  @return         0 -- success, otherwise fail
4264*4882a593Smuzhiyun  */
woal_tx_bf_cfg_ioctl(moal_private * priv,struct iwreq * wrq)4265*4882a593Smuzhiyun static int woal_tx_bf_cfg_ioctl(moal_private *priv, struct iwreq *wrq)
4266*4882a593Smuzhiyun {
4267*4882a593Smuzhiyun 	int ret = 0, data_length = wrq->u.data.length;
4268*4882a593Smuzhiyun 	int bf_action = 0, interval = 0;
4269*4882a593Smuzhiyun 	int snr = 0, i, tmp_val = 0;
4270*4882a593Smuzhiyun 	t_u8 buf[MAX_IN_OUT_CHAR], char_count = 0;
4271*4882a593Smuzhiyun 	t_u8 *str, *token, *pos;
4272*4882a593Smuzhiyun 	t_u16 action = 0;
4273*4882a593Smuzhiyun 
4274*4882a593Smuzhiyun 	mlan_ds_11n_tx_bf_cfg bf_cfg;
4275*4882a593Smuzhiyun 	mlan_trigger_sound_args *bf_sound = NULL;
4276*4882a593Smuzhiyun 	mlan_tx_bf_peer_args *tx_bf_peer = NULL;
4277*4882a593Smuzhiyun 	mlan_snr_thr_args *bf_snr = NULL;
4278*4882a593Smuzhiyun 	mlan_bf_periodicity_args *bf_periodicity = NULL;
4279*4882a593Smuzhiyun 	mlan_bf_global_cfg_args *bf_global = NULL;
4280*4882a593Smuzhiyun 
4281*4882a593Smuzhiyun 	ENTER();
4282*4882a593Smuzhiyun 
4283*4882a593Smuzhiyun 	memset(&bf_cfg, 0, sizeof(bf_cfg));
4284*4882a593Smuzhiyun 	/* Pointer to corresponding buffer */
4285*4882a593Smuzhiyun 	bf_sound = bf_cfg.body.bf_sound;
4286*4882a593Smuzhiyun 	tx_bf_peer = bf_cfg.body.tx_bf_peer;
4287*4882a593Smuzhiyun 	bf_snr = bf_cfg.body.bf_snr;
4288*4882a593Smuzhiyun 	bf_periodicity = bf_cfg.body.bf_periodicity;
4289*4882a593Smuzhiyun 	bf_global = &bf_cfg.body.bf_global_cfg;
4290*4882a593Smuzhiyun 
4291*4882a593Smuzhiyun 	/* Total characters in buffer */
4292*4882a593Smuzhiyun 	char_count = data_length - 1;
4293*4882a593Smuzhiyun 	memset(buf, 0, sizeof(buf));
4294*4882a593Smuzhiyun 	if (char_count) {
4295*4882a593Smuzhiyun 		if (data_length > (int)sizeof(buf)) {
4296*4882a593Smuzhiyun 			PRINTM(MERROR, "Too many arguments\n");
4297*4882a593Smuzhiyun 			ret = -EINVAL;
4298*4882a593Smuzhiyun 			goto done;
4299*4882a593Smuzhiyun 		}
4300*4882a593Smuzhiyun 		if (copy_from_user(buf, wrq->u.data.pointer, data_length)) {
4301*4882a593Smuzhiyun 			PRINTM(MERROR, "copy from user failed\n");
4302*4882a593Smuzhiyun 			ret = -EFAULT;
4303*4882a593Smuzhiyun 			goto done;
4304*4882a593Smuzhiyun 		}
4305*4882a593Smuzhiyun 
4306*4882a593Smuzhiyun 		if (char_count > 1 && buf[1] != ';') {
4307*4882a593Smuzhiyun 			PRINTM(MERROR,
4308*4882a593Smuzhiyun 			       "No action argument. Separate with ';'\n");
4309*4882a593Smuzhiyun 			ret = -EINVAL;
4310*4882a593Smuzhiyun 			goto done;
4311*4882a593Smuzhiyun 		}
4312*4882a593Smuzhiyun 		/* Replace ';' with NULL in the string to separate args */
4313*4882a593Smuzhiyun 		for (i = 0; i < char_count; i++) {
4314*4882a593Smuzhiyun 			if (buf[i] == ';')
4315*4882a593Smuzhiyun 				buf[i] = '\0';
4316*4882a593Smuzhiyun 		}
4317*4882a593Smuzhiyun 		/* The first byte represents the beamforming action */
4318*4882a593Smuzhiyun 		if (woal_atoi(&bf_action, &buf[0]) != MLAN_STATUS_SUCCESS) {
4319*4882a593Smuzhiyun 			ret = -EINVAL;
4320*4882a593Smuzhiyun 			goto done;
4321*4882a593Smuzhiyun 		}
4322*4882a593Smuzhiyun 		switch (bf_action) {
4323*4882a593Smuzhiyun 		case BF_GLOBAL_CONFIGURATION:
4324*4882a593Smuzhiyun 			if (char_count == 1) {
4325*4882a593Smuzhiyun 				action = MLAN_ACT_GET;
4326*4882a593Smuzhiyun 				bf_cfg.action = BF_CFG_ACT_GET;
4327*4882a593Smuzhiyun 			} else {
4328*4882a593Smuzhiyun 				action = MLAN_ACT_SET;
4329*4882a593Smuzhiyun 				bf_cfg.action = BF_CFG_ACT_SET;
4330*4882a593Smuzhiyun 				/* Eliminate action field */
4331*4882a593Smuzhiyun 				token = &buf[2];
4332*4882a593Smuzhiyun 				for (i = 1, str = &buf[2]; token != NULL; i++) {
4333*4882a593Smuzhiyun 					token = strstr(str, " ");
4334*4882a593Smuzhiyun 					pos = str;
4335*4882a593Smuzhiyun 					if (token != NULL) {
4336*4882a593Smuzhiyun 						*token = '\0';
4337*4882a593Smuzhiyun 						str = token + 1;
4338*4882a593Smuzhiyun 					}
4339*4882a593Smuzhiyun 					woal_atoi(&tmp_val, pos);
4340*4882a593Smuzhiyun 					switch (i) {
4341*4882a593Smuzhiyun 					case BF_ENABLE_PARAM:
4342*4882a593Smuzhiyun 						bf_global->bf_enbl =
4343*4882a593Smuzhiyun 							(t_u8)tmp_val;
4344*4882a593Smuzhiyun 						break;
4345*4882a593Smuzhiyun 					case SOUND_ENABLE_PARAM:
4346*4882a593Smuzhiyun 						bf_global->sounding_enbl =
4347*4882a593Smuzhiyun 							(t_u8)tmp_val;
4348*4882a593Smuzhiyun 						break;
4349*4882a593Smuzhiyun 					case FB_TYPE_PARAM:
4350*4882a593Smuzhiyun 						bf_global->fb_type =
4351*4882a593Smuzhiyun 							(t_u8)tmp_val;
4352*4882a593Smuzhiyun 						break;
4353*4882a593Smuzhiyun 					case SNR_THRESHOLD_PARAM:
4354*4882a593Smuzhiyun 						bf_global->snr_threshold =
4355*4882a593Smuzhiyun 							(t_u8)tmp_val;
4356*4882a593Smuzhiyun 						break;
4357*4882a593Smuzhiyun 					case SOUND_INTVL_PARAM:
4358*4882a593Smuzhiyun 						bf_global->sounding_interval =
4359*4882a593Smuzhiyun 							(t_u16)tmp_val;
4360*4882a593Smuzhiyun 						break;
4361*4882a593Smuzhiyun 					case BF_MODE_PARAM:
4362*4882a593Smuzhiyun 						bf_global->bf_mode =
4363*4882a593Smuzhiyun 							(t_u8)tmp_val;
4364*4882a593Smuzhiyun 						break;
4365*4882a593Smuzhiyun 					default:
4366*4882a593Smuzhiyun 						PRINTM(MERROR,
4367*4882a593Smuzhiyun 						       "Invalid Argument\n");
4368*4882a593Smuzhiyun 						ret = -EINVAL;
4369*4882a593Smuzhiyun 						goto done;
4370*4882a593Smuzhiyun 					}
4371*4882a593Smuzhiyun 				}
4372*4882a593Smuzhiyun 			}
4373*4882a593Smuzhiyun 			break;
4374*4882a593Smuzhiyun 		case TRIGGER_SOUNDING_FOR_PEER:
4375*4882a593Smuzhiyun 			/*
4376*4882a593Smuzhiyun 			 * First arg  = 2   BfAction
4377*4882a593Smuzhiyun 			 * Second arg = 17  MAC "00:50:43:20:BF:64"
4378*4882a593Smuzhiyun 			 */
4379*4882a593Smuzhiyun 			if (char_count != 19) {
4380*4882a593Smuzhiyun 				PRINTM(MERROR, "Invalid argument\n");
4381*4882a593Smuzhiyun 				ret = -EINVAL;
4382*4882a593Smuzhiyun 				goto done;
4383*4882a593Smuzhiyun 			}
4384*4882a593Smuzhiyun 			woal_mac2u8(bf_sound->peer_mac, &buf[2]);
4385*4882a593Smuzhiyun 			action = MLAN_ACT_SET;
4386*4882a593Smuzhiyun 			bf_cfg.action = BF_CFG_ACT_SET;
4387*4882a593Smuzhiyun 			break;
4388*4882a593Smuzhiyun 		case SET_GET_BF_PERIODICITY:
4389*4882a593Smuzhiyun 			/*
4390*4882a593Smuzhiyun 			 * First arg  = 2   BfAction
4391*4882a593Smuzhiyun 			 * Second arg = 18  MAC "00:50:43:20:BF:64;"
4392*4882a593Smuzhiyun 			 * Third arg =  1  (min char)  TX BF interval
4393*4882a593Smuzhiyun 			 *              10 (max char)  u32 maximum value
4394*4882a593Smuzhiyun 			 * 4294967295
4395*4882a593Smuzhiyun 			 */
4396*4882a593Smuzhiyun 			if (char_count < 19 || char_count > 30) {
4397*4882a593Smuzhiyun 				PRINTM(MERROR, "Invalid argument\n");
4398*4882a593Smuzhiyun 				ret = -EINVAL;
4399*4882a593Smuzhiyun 				goto done;
4400*4882a593Smuzhiyun 			}
4401*4882a593Smuzhiyun 
4402*4882a593Smuzhiyun 			woal_mac2u8(bf_periodicity->peer_mac, &buf[2]);
4403*4882a593Smuzhiyun 			if (char_count == 19) {
4404*4882a593Smuzhiyun 				action = MLAN_ACT_GET;
4405*4882a593Smuzhiyun 				bf_cfg.action = BF_CFG_ACT_GET;
4406*4882a593Smuzhiyun 			} else {
4407*4882a593Smuzhiyun 				action = MLAN_ACT_SET;
4408*4882a593Smuzhiyun 				bf_cfg.action = BF_CFG_ACT_SET;
4409*4882a593Smuzhiyun 				if (woal_atoi(&interval, &buf[20]) !=
4410*4882a593Smuzhiyun 				    MLAN_STATUS_SUCCESS) {
4411*4882a593Smuzhiyun 					ret = -EINVAL;
4412*4882a593Smuzhiyun 					goto done;
4413*4882a593Smuzhiyun 				}
4414*4882a593Smuzhiyun 				bf_periodicity->interval = interval;
4415*4882a593Smuzhiyun 			}
4416*4882a593Smuzhiyun 			break;
4417*4882a593Smuzhiyun 		case TX_BF_FOR_PEER_ENBL:
4418*4882a593Smuzhiyun 			/*
4419*4882a593Smuzhiyun 			 * Handle only SET operation here
4420*4882a593Smuzhiyun 			 * First arg  = 2   BfAction
4421*4882a593Smuzhiyun 			 * Second arg = 18  MAC "00:50:43:20:BF:64;"
4422*4882a593Smuzhiyun 			 * Third arg  = 2   enable/disable bf
4423*4882a593Smuzhiyun 			 * Fourth arg = 2   enable/disable sounding
4424*4882a593Smuzhiyun 			 * Fifth arg  = 1   FB Type
4425*4882a593Smuzhiyun 			 */
4426*4882a593Smuzhiyun 			if (char_count != 25 && char_count != 1) {
4427*4882a593Smuzhiyun 				PRINTM(MERROR, "Invalid argument\n");
4428*4882a593Smuzhiyun 				ret = -EINVAL;
4429*4882a593Smuzhiyun 				goto done;
4430*4882a593Smuzhiyun 			}
4431*4882a593Smuzhiyun 			if (char_count == 1) {
4432*4882a593Smuzhiyun 				action = MLAN_ACT_GET;
4433*4882a593Smuzhiyun 				bf_cfg.action = BF_CFG_ACT_GET;
4434*4882a593Smuzhiyun 			} else {
4435*4882a593Smuzhiyun 				woal_mac2u8(tx_bf_peer->peer_mac, &buf[2]);
4436*4882a593Smuzhiyun 				woal_atoi(&tmp_val, &buf[20]);
4437*4882a593Smuzhiyun 				tx_bf_peer->bf_enbl = (t_u8)tmp_val;
4438*4882a593Smuzhiyun 				woal_atoi(&tmp_val, &buf[22]);
4439*4882a593Smuzhiyun 				tx_bf_peer->sounding_enbl = (t_u8)tmp_val;
4440*4882a593Smuzhiyun 				woal_atoi(&tmp_val, &buf[24]);
4441*4882a593Smuzhiyun 				tx_bf_peer->fb_type = (t_u8)tmp_val;
4442*4882a593Smuzhiyun 				action = MLAN_ACT_SET;
4443*4882a593Smuzhiyun 				bf_cfg.action = BF_CFG_ACT_SET;
4444*4882a593Smuzhiyun 			}
4445*4882a593Smuzhiyun 			break;
4446*4882a593Smuzhiyun 		case SET_SNR_THR_PEER:
4447*4882a593Smuzhiyun 			/*
4448*4882a593Smuzhiyun 			 * First arg  = 2   BfAction
4449*4882a593Smuzhiyun 			 * Second arg = 18  MAC "00:50:43:20:BF:64;"
4450*4882a593Smuzhiyun 			 * Third arg  = 1/2 SNR u8 - can be 1/2 charerters
4451*4882a593Smuzhiyun 			 */
4452*4882a593Smuzhiyun 			if (char_count != 1 &&
4453*4882a593Smuzhiyun 			    !(char_count == 21 || char_count == 22)) {
4454*4882a593Smuzhiyun 				PRINTM(MERROR, "Invalid argument\n");
4455*4882a593Smuzhiyun 				ret = -EINVAL;
4456*4882a593Smuzhiyun 				goto done;
4457*4882a593Smuzhiyun 			}
4458*4882a593Smuzhiyun 			if (char_count == 1) {
4459*4882a593Smuzhiyun 				action = MLAN_ACT_GET;
4460*4882a593Smuzhiyun 				bf_cfg.action = BF_CFG_ACT_GET;
4461*4882a593Smuzhiyun 			} else {
4462*4882a593Smuzhiyun 				woal_mac2u8(bf_snr->peer_mac, &buf[2]);
4463*4882a593Smuzhiyun 				if (woal_atoi(&snr, &buf[20]) !=
4464*4882a593Smuzhiyun 				    MLAN_STATUS_SUCCESS) {
4465*4882a593Smuzhiyun 					ret = -EINVAL;
4466*4882a593Smuzhiyun 					goto done;
4467*4882a593Smuzhiyun 				}
4468*4882a593Smuzhiyun 				bf_snr->snr = snr;
4469*4882a593Smuzhiyun 				action = MLAN_ACT_SET;
4470*4882a593Smuzhiyun 				bf_cfg.action = BF_CFG_ACT_SET;
4471*4882a593Smuzhiyun 			}
4472*4882a593Smuzhiyun 			break;
4473*4882a593Smuzhiyun 		default:
4474*4882a593Smuzhiyun 			ret = -EINVAL;
4475*4882a593Smuzhiyun 			goto done;
4476*4882a593Smuzhiyun 		}
4477*4882a593Smuzhiyun 
4478*4882a593Smuzhiyun 		/* Save the value */
4479*4882a593Smuzhiyun 		bf_cfg.bf_action = bf_action;
4480*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS !=
4481*4882a593Smuzhiyun 		    woal_set_get_tx_bf_cfg(priv, action, &bf_cfg)) {
4482*4882a593Smuzhiyun 			ret = -EFAULT;
4483*4882a593Smuzhiyun 			goto done;
4484*4882a593Smuzhiyun 		}
4485*4882a593Smuzhiyun 	} else {
4486*4882a593Smuzhiyun 		ret = -EINVAL;
4487*4882a593Smuzhiyun 		goto done;
4488*4882a593Smuzhiyun 	}
4489*4882a593Smuzhiyun 
4490*4882a593Smuzhiyun 	if (action == MLAN_ACT_GET) {
4491*4882a593Smuzhiyun 		data_length = 0;
4492*4882a593Smuzhiyun 		memset(buf, 0, sizeof(buf));
4493*4882a593Smuzhiyun 		switch (bf_action) {
4494*4882a593Smuzhiyun 		case BF_GLOBAL_CONFIGURATION:
4495*4882a593Smuzhiyun 			data_length += sprintf(buf + data_length, "%d ",
4496*4882a593Smuzhiyun 					       (int)bf_global->bf_enbl);
4497*4882a593Smuzhiyun 			data_length += sprintf(buf + data_length, "%d ",
4498*4882a593Smuzhiyun 					       (int)bf_global->sounding_enbl);
4499*4882a593Smuzhiyun 			data_length += sprintf(buf + data_length, "%d ",
4500*4882a593Smuzhiyun 					       (int)bf_global->fb_type);
4501*4882a593Smuzhiyun 			data_length += sprintf(buf + data_length, "%d ",
4502*4882a593Smuzhiyun 					       (int)bf_global->snr_threshold);
4503*4882a593Smuzhiyun 			data_length +=
4504*4882a593Smuzhiyun 				sprintf(buf + data_length, "%d ",
4505*4882a593Smuzhiyun 					(int)bf_global->sounding_interval);
4506*4882a593Smuzhiyun 			data_length += sprintf(buf + data_length, "%d ",
4507*4882a593Smuzhiyun 					       (int)bf_global->bf_mode);
4508*4882a593Smuzhiyun 			break;
4509*4882a593Smuzhiyun 		case SET_GET_BF_PERIODICITY:
4510*4882a593Smuzhiyun 			data_length += sprintf(buf + data_length,
4511*4882a593Smuzhiyun 					       "%02x:%02x:%02x:%02x:%02x:%02x",
4512*4882a593Smuzhiyun 					       bf_periodicity->peer_mac[0],
4513*4882a593Smuzhiyun 					       bf_periodicity->peer_mac[1],
4514*4882a593Smuzhiyun 					       bf_periodicity->peer_mac[2],
4515*4882a593Smuzhiyun 					       bf_periodicity->peer_mac[3],
4516*4882a593Smuzhiyun 					       bf_periodicity->peer_mac[4],
4517*4882a593Smuzhiyun 					       bf_periodicity->peer_mac[5]);
4518*4882a593Smuzhiyun 			data_length += sprintf(buf + data_length, "%c", ' ');
4519*4882a593Smuzhiyun 			data_length += sprintf(buf + data_length, "%d",
4520*4882a593Smuzhiyun 					       bf_periodicity->interval);
4521*4882a593Smuzhiyun 			break;
4522*4882a593Smuzhiyun 		case TX_BF_FOR_PEER_ENBL:
4523*4882a593Smuzhiyun 			for (i = 0; i < (int)bf_cfg.no_of_peers; i++) {
4524*4882a593Smuzhiyun 				data_length +=
4525*4882a593Smuzhiyun 					sprintf(buf + data_length,
4526*4882a593Smuzhiyun 						"%02x:%02x:%02x:%02x:%02x:%02x",
4527*4882a593Smuzhiyun 						tx_bf_peer->peer_mac[0],
4528*4882a593Smuzhiyun 						tx_bf_peer->peer_mac[1],
4529*4882a593Smuzhiyun 						tx_bf_peer->peer_mac[2],
4530*4882a593Smuzhiyun 						tx_bf_peer->peer_mac[3],
4531*4882a593Smuzhiyun 						tx_bf_peer->peer_mac[4],
4532*4882a593Smuzhiyun 						tx_bf_peer->peer_mac[5]);
4533*4882a593Smuzhiyun 				data_length +=
4534*4882a593Smuzhiyun 					sprintf(buf + data_length, "%c", ' ');
4535*4882a593Smuzhiyun 				data_length += sprintf(buf + data_length, "%d;",
4536*4882a593Smuzhiyun 						       tx_bf_peer->bf_enbl);
4537*4882a593Smuzhiyun 				data_length +=
4538*4882a593Smuzhiyun 					sprintf(buf + data_length, "%d;",
4539*4882a593Smuzhiyun 						tx_bf_peer->sounding_enbl);
4540*4882a593Smuzhiyun 				data_length += sprintf(buf + data_length, "%d ",
4541*4882a593Smuzhiyun 						       tx_bf_peer->fb_type);
4542*4882a593Smuzhiyun 				tx_bf_peer++;
4543*4882a593Smuzhiyun 			}
4544*4882a593Smuzhiyun 			break;
4545*4882a593Smuzhiyun 		case SET_SNR_THR_PEER:
4546*4882a593Smuzhiyun 			for (i = 0; i < (int)bf_cfg.no_of_peers; i++) {
4547*4882a593Smuzhiyun 				data_length +=
4548*4882a593Smuzhiyun 					sprintf(buf + data_length,
4549*4882a593Smuzhiyun 						"%02x:%02x:%02x:%02x:%02x:%02x",
4550*4882a593Smuzhiyun 						bf_snr->peer_mac[0],
4551*4882a593Smuzhiyun 						bf_snr->peer_mac[1],
4552*4882a593Smuzhiyun 						bf_snr->peer_mac[2],
4553*4882a593Smuzhiyun 						bf_snr->peer_mac[3],
4554*4882a593Smuzhiyun 						bf_snr->peer_mac[4],
4555*4882a593Smuzhiyun 						bf_snr->peer_mac[5]);
4556*4882a593Smuzhiyun 				data_length +=
4557*4882a593Smuzhiyun 					sprintf(buf + data_length, "%c", ';');
4558*4882a593Smuzhiyun 				data_length += sprintf(buf + data_length, "%d",
4559*4882a593Smuzhiyun 						       bf_snr->snr);
4560*4882a593Smuzhiyun 				data_length +=
4561*4882a593Smuzhiyun 					sprintf(buf + data_length, "%c", ' ');
4562*4882a593Smuzhiyun 				bf_snr++;
4563*4882a593Smuzhiyun 			}
4564*4882a593Smuzhiyun 			break;
4565*4882a593Smuzhiyun 		}
4566*4882a593Smuzhiyun 		buf[data_length] = '\0';
4567*4882a593Smuzhiyun 	}
4568*4882a593Smuzhiyun 
4569*4882a593Smuzhiyun 	wrq->u.data.length = data_length;
4570*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length)) {
4571*4882a593Smuzhiyun 		ret = -EFAULT;
4572*4882a593Smuzhiyun 		goto done;
4573*4882a593Smuzhiyun 	}
4574*4882a593Smuzhiyun 
4575*4882a593Smuzhiyun done:
4576*4882a593Smuzhiyun 	LEAVE();
4577*4882a593Smuzhiyun 	return ret;
4578*4882a593Smuzhiyun }
4579*4882a593Smuzhiyun 
4580*4882a593Smuzhiyun /**
4581*4882a593Smuzhiyun  *  @brief Retrieve the scan response/beacon table
4582*4882a593Smuzhiyun  *
4583*4882a593Smuzhiyun  *  @param wrq          A pointer to iwreq structure
4584*4882a593Smuzhiyun  *  @param scan_resp    A pointer to mlan_scan_resp structure
4585*4882a593Smuzhiyun  *  @param scan_start   argument
4586*4882a593Smuzhiyun  *
4587*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
4588*4882a593Smuzhiyun  */
moal_ret_get_scan_table_ioctl(struct iwreq * wrq,mlan_scan_resp * scan_resp,t_u32 scan_start)4589*4882a593Smuzhiyun static int moal_ret_get_scan_table_ioctl(struct iwreq *wrq,
4590*4882a593Smuzhiyun 					 mlan_scan_resp *scan_resp,
4591*4882a593Smuzhiyun 					 t_u32 scan_start)
4592*4882a593Smuzhiyun {
4593*4882a593Smuzhiyun 	pBSSDescriptor_t pbss_desc, scan_table;
4594*4882a593Smuzhiyun 	wlan_ioctl_get_scan_table_info *prsp_info;
4595*4882a593Smuzhiyun 	int ret_code;
4596*4882a593Smuzhiyun 	int ret_len;
4597*4882a593Smuzhiyun 	int space_left;
4598*4882a593Smuzhiyun 	t_u8 *pcurrent;
4599*4882a593Smuzhiyun 	t_u8 *pbuffer_end;
4600*4882a593Smuzhiyun 	t_u32 num_scans_done;
4601*4882a593Smuzhiyun 
4602*4882a593Smuzhiyun 	ENTER();
4603*4882a593Smuzhiyun 
4604*4882a593Smuzhiyun 	num_scans_done = 0;
4605*4882a593Smuzhiyun 	ret_code = MLAN_STATUS_SUCCESS;
4606*4882a593Smuzhiyun 
4607*4882a593Smuzhiyun 	prsp_info =
4608*4882a593Smuzhiyun 		(wlan_ioctl_get_scan_table_info __force *)wrq->u.data.pointer;
4609*4882a593Smuzhiyun 	pcurrent = (t_u8 *)prsp_info->scan_table_entry_buf;
4610*4882a593Smuzhiyun 
4611*4882a593Smuzhiyun 	pbuffer_end =
4612*4882a593Smuzhiyun 		(t_u8 __force *)wrq->u.data.pointer + wrq->u.data.length - 1;
4613*4882a593Smuzhiyun 	space_left = pbuffer_end - pcurrent;
4614*4882a593Smuzhiyun 	scan_table = (BSSDescriptor_t *)(scan_resp->pscan_table);
4615*4882a593Smuzhiyun 
4616*4882a593Smuzhiyun 	PRINTM(MINFO, "GetScanTable: scan_start req = %d\n", scan_start);
4617*4882a593Smuzhiyun 	PRINTM(MINFO, "GetScanTable: length avail = %d\n", wrq->u.data.length);
4618*4882a593Smuzhiyun 
4619*4882a593Smuzhiyun 	if (!scan_start) {
4620*4882a593Smuzhiyun 		PRINTM(MINFO, "GetScanTable: get current BSS Descriptor\n");
4621*4882a593Smuzhiyun 
4622*4882a593Smuzhiyun 		/* Use to get current association saved descriptor */
4623*4882a593Smuzhiyun 		pbss_desc = scan_table;
4624*4882a593Smuzhiyun 
4625*4882a593Smuzhiyun 		ret_code = wlan_get_scan_table_ret_entry(pbss_desc, &pcurrent,
4626*4882a593Smuzhiyun 							 &space_left);
4627*4882a593Smuzhiyun 
4628*4882a593Smuzhiyun 		if (ret_code == MLAN_STATUS_SUCCESS)
4629*4882a593Smuzhiyun 			num_scans_done = 1;
4630*4882a593Smuzhiyun 	} else {
4631*4882a593Smuzhiyun 		scan_start--;
4632*4882a593Smuzhiyun 
4633*4882a593Smuzhiyun 		while (space_left &&
4634*4882a593Smuzhiyun 		       (scan_start + num_scans_done <
4635*4882a593Smuzhiyun 			scan_resp->num_in_scan_table) &&
4636*4882a593Smuzhiyun 		       (ret_code == MLAN_STATUS_SUCCESS)) {
4637*4882a593Smuzhiyun 			pbss_desc =
4638*4882a593Smuzhiyun 				(scan_table + (scan_start + num_scans_done));
4639*4882a593Smuzhiyun 
4640*4882a593Smuzhiyun 			PRINTM(MINFO,
4641*4882a593Smuzhiyun 			       "GetScanTable: get current BSS Descriptor [%d]\n",
4642*4882a593Smuzhiyun 			       scan_start + num_scans_done);
4643*4882a593Smuzhiyun 
4644*4882a593Smuzhiyun 			ret_code = wlan_get_scan_table_ret_entry(
4645*4882a593Smuzhiyun 				pbss_desc, &pcurrent, &space_left);
4646*4882a593Smuzhiyun 
4647*4882a593Smuzhiyun 			if (ret_code == MLAN_STATUS_SUCCESS)
4648*4882a593Smuzhiyun 				num_scans_done++;
4649*4882a593Smuzhiyun 		}
4650*4882a593Smuzhiyun 	}
4651*4882a593Smuzhiyun 
4652*4882a593Smuzhiyun 	prsp_info->scan_number = num_scans_done;
4653*4882a593Smuzhiyun 	ret_len = pcurrent - (t_u8 __force *)wrq->u.data.pointer;
4654*4882a593Smuzhiyun 
4655*4882a593Smuzhiyun 	wrq->u.data.length = ret_len;
4656*4882a593Smuzhiyun 
4657*4882a593Smuzhiyun 	/* Return ret_code (EFAULT or E2BIG) in the case where no scan results
4658*4882a593Smuzhiyun 	 * were successfully encoded.
4659*4882a593Smuzhiyun 	 */
4660*4882a593Smuzhiyun 	LEAVE();
4661*4882a593Smuzhiyun 	return num_scans_done ? MLAN_STATUS_SUCCESS : ret_code;
4662*4882a593Smuzhiyun }
4663*4882a593Smuzhiyun 
4664*4882a593Smuzhiyun /**
4665*4882a593Smuzhiyun  *  @brief Get scan table ioctl
4666*4882a593Smuzhiyun  *
4667*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
4668*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
4669*4882a593Smuzhiyun  *
4670*4882a593Smuzhiyun  *  @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
4671*4882a593Smuzhiyun  * otherwise fail
4672*4882a593Smuzhiyun  */
woal_get_scan_table_ioctl(moal_private * priv,struct iwreq * wrq)4673*4882a593Smuzhiyun static mlan_status woal_get_scan_table_ioctl(moal_private *priv,
4674*4882a593Smuzhiyun 					     struct iwreq *wrq)
4675*4882a593Smuzhiyun {
4676*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
4677*4882a593Smuzhiyun 	mlan_ds_scan *scan = NULL;
4678*4882a593Smuzhiyun 	int scan_start = 0;
4679*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
4680*4882a593Smuzhiyun 
4681*4882a593Smuzhiyun 	ENTER();
4682*4882a593Smuzhiyun 
4683*4882a593Smuzhiyun 	/* Allocate an IOCTL request buffer */
4684*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
4685*4882a593Smuzhiyun 	if (req == NULL) {
4686*4882a593Smuzhiyun 		status = MLAN_STATUS_FAILURE;
4687*4882a593Smuzhiyun 		goto done;
4688*4882a593Smuzhiyun 	}
4689*4882a593Smuzhiyun 
4690*4882a593Smuzhiyun 	/* Fill request buffer */
4691*4882a593Smuzhiyun 	scan = (mlan_ds_scan *)req->pbuf;
4692*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_SCAN;
4693*4882a593Smuzhiyun 	req->action = MLAN_ACT_GET;
4694*4882a593Smuzhiyun 
4695*4882a593Smuzhiyun 	/* get the whole command from user */
4696*4882a593Smuzhiyun 	if (copy_from_user(&scan_start, wrq->u.data.pointer,
4697*4882a593Smuzhiyun 			   sizeof(scan_start))) {
4698*4882a593Smuzhiyun 		PRINTM(MERROR, "copy from user failed\n");
4699*4882a593Smuzhiyun 		goto done;
4700*4882a593Smuzhiyun 	}
4701*4882a593Smuzhiyun 	if (scan_start > 0)
4702*4882a593Smuzhiyun 		scan->sub_command = MLAN_OID_SCAN_NORMAL;
4703*4882a593Smuzhiyun 	else
4704*4882a593Smuzhiyun 		scan->sub_command = MLAN_OID_SCAN_GET_CURRENT_BSS;
4705*4882a593Smuzhiyun 	/* Send IOCTL request to MLAN */
4706*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4707*4882a593Smuzhiyun 	if (status == MLAN_STATUS_SUCCESS) {
4708*4882a593Smuzhiyun 		status = moal_ret_get_scan_table_ioctl(
4709*4882a593Smuzhiyun 			wrq, &scan->param.scan_resp, scan_start);
4710*4882a593Smuzhiyun 	}
4711*4882a593Smuzhiyun done:
4712*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
4713*4882a593Smuzhiyun 		kfree(req);
4714*4882a593Smuzhiyun 	LEAVE();
4715*4882a593Smuzhiyun 	return status;
4716*4882a593Smuzhiyun }
4717*4882a593Smuzhiyun 
4718*4882a593Smuzhiyun /**
4719*4882a593Smuzhiyun  *  @brief Set user scan ext -- Async mode, without wait
4720*4882a593Smuzhiyun  *
4721*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
4722*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
4723*4882a593Smuzhiyun  *
4724*4882a593Smuzhiyun  *  @return         0 -- success, otherwise fail
4725*4882a593Smuzhiyun  */
woal_set_user_scan_ext_ioctl(moal_private * priv,struct iwreq * wrq)4726*4882a593Smuzhiyun static int woal_set_user_scan_ext_ioctl(moal_private *priv, struct iwreq *wrq)
4727*4882a593Smuzhiyun {
4728*4882a593Smuzhiyun 	int ret = 0;
4729*4882a593Smuzhiyun 	wlan_user_scan_cfg *scan_req;
4730*4882a593Smuzhiyun 	ENTER();
4731*4882a593Smuzhiyun 	scan_req = (wlan_user_scan_cfg *)kmalloc(sizeof(wlan_user_scan_cfg),
4732*4882a593Smuzhiyun 						 GFP_KERNEL);
4733*4882a593Smuzhiyun 	if (!scan_req) {
4734*4882a593Smuzhiyun 		PRINTM(MERROR, "Malloc buffer failed\n");
4735*4882a593Smuzhiyun 		LEAVE();
4736*4882a593Smuzhiyun 		return -ENOMEM;
4737*4882a593Smuzhiyun 	}
4738*4882a593Smuzhiyun 	memset(scan_req, 0x00, sizeof(wlan_user_scan_cfg));
4739*4882a593Smuzhiyun 	if (copy_from_user(scan_req, wrq->u.data.pointer,
4740*4882a593Smuzhiyun 			   MIN(wrq->u.data.length,
4741*4882a593Smuzhiyun 			       sizeof(wlan_user_scan_cfg)))) {
4742*4882a593Smuzhiyun 		PRINTM(MINFO, "Copy from user failed\n");
4743*4882a593Smuzhiyun 		kfree(scan_req);
4744*4882a593Smuzhiyun 		LEAVE();
4745*4882a593Smuzhiyun 		return -EFAULT;
4746*4882a593Smuzhiyun 	}
4747*4882a593Smuzhiyun 	if (MLAN_STATUS_FAILURE == woal_do_scan(priv, scan_req))
4748*4882a593Smuzhiyun 		ret = -EFAULT;
4749*4882a593Smuzhiyun 	kfree(scan_req);
4750*4882a593Smuzhiyun 	LEAVE();
4751*4882a593Smuzhiyun 	return ret;
4752*4882a593Smuzhiyun }
4753*4882a593Smuzhiyun 
4754*4882a593Smuzhiyun /**
4755*4882a593Smuzhiyun  *  @brief Set user scan
4756*4882a593Smuzhiyun  *
4757*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
4758*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
4759*4882a593Smuzhiyun  *
4760*4882a593Smuzhiyun  *  @return         MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
4761*4882a593Smuzhiyun  * otherwise fail
4762*4882a593Smuzhiyun  */
woal_set_user_scan_ioctl(moal_private * priv,struct iwreq * wrq)4763*4882a593Smuzhiyun static mlan_status woal_set_user_scan_ioctl(moal_private *priv,
4764*4882a593Smuzhiyun 					    struct iwreq *wrq)
4765*4882a593Smuzhiyun {
4766*4882a593Smuzhiyun 	int ret = 0;
4767*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
4768*4882a593Smuzhiyun 	mlan_ds_scan *scan = NULL;
4769*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
4770*4882a593Smuzhiyun 	union iwreq_data wrqu;
4771*4882a593Smuzhiyun 	moal_handle *handle = priv->phandle;
4772*4882a593Smuzhiyun 
4773*4882a593Smuzhiyun 	ENTER();
4774*4882a593Smuzhiyun 
4775*4882a593Smuzhiyun 	if (handle->scan_pending_on_block == MTRUE) {
4776*4882a593Smuzhiyun 		PRINTM(MINFO, "scan already in processing...\n");
4777*4882a593Smuzhiyun 		LEAVE();
4778*4882a593Smuzhiyun 		return ret;
4779*4882a593Smuzhiyun 	}
4780*4882a593Smuzhiyun 	if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->async_sem)) {
4781*4882a593Smuzhiyun 		PRINTM(MERROR, "Acquire semaphore error, request_scan\n");
4782*4882a593Smuzhiyun 		LEAVE();
4783*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
4784*4882a593Smuzhiyun 	}
4785*4882a593Smuzhiyun 	handle->scan_pending_on_block = MTRUE;
4786*4882a593Smuzhiyun 	handle->scan_priv = priv;
4787*4882a593Smuzhiyun 
4788*4882a593Smuzhiyun 	/* Allocate an IOCTL request buffer */
4789*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan) +
4790*4882a593Smuzhiyun 					wrq->u.data.length);
4791*4882a593Smuzhiyun 	if (req == NULL) {
4792*4882a593Smuzhiyun 		ret = -ENOMEM;
4793*4882a593Smuzhiyun 		goto done;
4794*4882a593Smuzhiyun 	}
4795*4882a593Smuzhiyun 
4796*4882a593Smuzhiyun 	/* Fill request buffer */
4797*4882a593Smuzhiyun 	scan = (mlan_ds_scan *)req->pbuf;
4798*4882a593Smuzhiyun 	scan->sub_command = MLAN_OID_SCAN_USER_CONFIG;
4799*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_SCAN;
4800*4882a593Smuzhiyun 	req->action = MLAN_ACT_SET;
4801*4882a593Smuzhiyun 
4802*4882a593Smuzhiyun 	if (copy_from_user(scan->param.user_scan.scan_cfg_buf,
4803*4882a593Smuzhiyun 			   wrq->u.data.pointer, wrq->u.data.length)) {
4804*4882a593Smuzhiyun 		PRINTM(MINFO, "Copy from user failed\n");
4805*4882a593Smuzhiyun 		ret = -EFAULT;
4806*4882a593Smuzhiyun 		goto done;
4807*4882a593Smuzhiyun 	}
4808*4882a593Smuzhiyun 
4809*4882a593Smuzhiyun 	/* Send IOCTL request to MLAN */
4810*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
4811*4882a593Smuzhiyun 	if (status == MLAN_STATUS_SUCCESS) {
4812*4882a593Smuzhiyun 		memset(&wrqu, 0, sizeof(union iwreq_data));
4813*4882a593Smuzhiyun 		wireless_send_event(priv->netdev, SIOCGIWSCAN, &wrqu, NULL);
4814*4882a593Smuzhiyun 	}
4815*4882a593Smuzhiyun 
4816*4882a593Smuzhiyun done:
4817*4882a593Smuzhiyun 	handle->scan_pending_on_block = MFALSE;
4818*4882a593Smuzhiyun 	handle->scan_priv = NULL;
4819*4882a593Smuzhiyun 	MOAL_REL_SEMAPHORE(&handle->async_sem);
4820*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
4821*4882a593Smuzhiyun 		kfree(req);
4822*4882a593Smuzhiyun 	LEAVE();
4823*4882a593Smuzhiyun 	return status;
4824*4882a593Smuzhiyun }
4825*4882a593Smuzhiyun 
4826*4882a593Smuzhiyun #ifdef SDIO
4827*4882a593Smuzhiyun /**
4828*4882a593Smuzhiyun  *  @brief Cmd52 read/write register
4829*4882a593Smuzhiyun  *
4830*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
4831*4882a593Smuzhiyun  *  @param wrq          A pointer to iwreq structure
4832*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
4833*4882a593Smuzhiyun  */
woal_cmd52rdwr_ioctl(moal_private * priv,struct iwreq * wrq)4834*4882a593Smuzhiyun static int woal_cmd52rdwr_ioctl(moal_private *priv, struct iwreq *wrq)
4835*4882a593Smuzhiyun {
4836*4882a593Smuzhiyun 	t_u8 rw = 0, func, data = 0;
4837*4882a593Smuzhiyun 	int buf[3], reg, ret = MLAN_STATUS_SUCCESS;
4838*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
4839*4882a593Smuzhiyun 
4840*4882a593Smuzhiyun 	ENTER();
4841*4882a593Smuzhiyun 
4842*4882a593Smuzhiyun 	if (data_length < 2 || data_length > 3) {
4843*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid number of arguments\n");
4844*4882a593Smuzhiyun 		ret = -EINVAL;
4845*4882a593Smuzhiyun 		goto done;
4846*4882a593Smuzhiyun 	}
4847*4882a593Smuzhiyun 
4848*4882a593Smuzhiyun 	if (copy_from_user(buf, wrq->u.data.pointer,
4849*4882a593Smuzhiyun 			   sizeof(int) * data_length)) {
4850*4882a593Smuzhiyun 		PRINTM(MERROR, "Copy from user failed\n");
4851*4882a593Smuzhiyun 		ret = -EFAULT;
4852*4882a593Smuzhiyun 		goto done;
4853*4882a593Smuzhiyun 	}
4854*4882a593Smuzhiyun 
4855*4882a593Smuzhiyun 	func = (t_u8)buf[0];
4856*4882a593Smuzhiyun 	if (func > 7) {
4857*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid function number!\n");
4858*4882a593Smuzhiyun 		ret = -EINVAL;
4859*4882a593Smuzhiyun 		goto done;
4860*4882a593Smuzhiyun 	}
4861*4882a593Smuzhiyun 	reg = (t_u32)buf[1];
4862*4882a593Smuzhiyun 	if (data_length == 2) {
4863*4882a593Smuzhiyun 		rw = 0; /* CMD52 read */
4864*4882a593Smuzhiyun 		PRINTM(MINFO, "Cmd52 read, func=%d, reg=0x%08X\n", func, reg);
4865*4882a593Smuzhiyun 	}
4866*4882a593Smuzhiyun 	if (data_length == 3) {
4867*4882a593Smuzhiyun 		rw = 1; /* CMD52 write */
4868*4882a593Smuzhiyun 		data = (t_u8)buf[2];
4869*4882a593Smuzhiyun 		PRINTM(MINFO, "Cmd52 write, func=%d, reg=0x%08X, data=0x%02X\n",
4870*4882a593Smuzhiyun 		       func, reg, data);
4871*4882a593Smuzhiyun 	}
4872*4882a593Smuzhiyun 
4873*4882a593Smuzhiyun 	if (!rw) {
4874*4882a593Smuzhiyun #ifdef SDIO_MMC
4875*4882a593Smuzhiyun 		sdio_claim_host(
4876*4882a593Smuzhiyun 			((struct sdio_mmc_card *)priv->phandle->card)->func);
4877*4882a593Smuzhiyun 		if (func)
4878*4882a593Smuzhiyun 			data = sdio_readb(
4879*4882a593Smuzhiyun 				((struct sdio_mmc_card *)priv->phandle->card)
4880*4882a593Smuzhiyun 					->func,
4881*4882a593Smuzhiyun 				reg, &ret);
4882*4882a593Smuzhiyun 		else
4883*4882a593Smuzhiyun 			data = sdio_f0_readb(
4884*4882a593Smuzhiyun 				((struct sdio_mmc_card *)priv->phandle->card)
4885*4882a593Smuzhiyun 					->func,
4886*4882a593Smuzhiyun 				reg, &ret);
4887*4882a593Smuzhiyun 		sdio_release_host(
4888*4882a593Smuzhiyun 			((struct sdio_mmc_card *)priv->phandle->card)->func);
4889*4882a593Smuzhiyun 		if (ret) {
4890*4882a593Smuzhiyun 			PRINTM(MERROR,
4891*4882a593Smuzhiyun 			       "sdio_readb: reading register 0x%X failed\n",
4892*4882a593Smuzhiyun 			       reg);
4893*4882a593Smuzhiyun 			goto done;
4894*4882a593Smuzhiyun 		}
4895*4882a593Smuzhiyun #else
4896*4882a593Smuzhiyun 		if (sdio_read_ioreg(priv->phandle->card, func, reg, &data) <
4897*4882a593Smuzhiyun 		    0) {
4898*4882a593Smuzhiyun 			PRINTM(MERROR,
4899*4882a593Smuzhiyun 			       "sdio_read_ioreg: reading register 0x%X failed\n",
4900*4882a593Smuzhiyun 			       reg);
4901*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
4902*4882a593Smuzhiyun 			goto done;
4903*4882a593Smuzhiyun 		}
4904*4882a593Smuzhiyun #endif
4905*4882a593Smuzhiyun 	} else {
4906*4882a593Smuzhiyun #ifdef SDIO_MMC
4907*4882a593Smuzhiyun 		sdio_claim_host(
4908*4882a593Smuzhiyun 			((struct sdio_mmc_card *)priv->phandle->card)->func);
4909*4882a593Smuzhiyun 		if (func)
4910*4882a593Smuzhiyun 			sdio_writeb(
4911*4882a593Smuzhiyun 				((struct sdio_mmc_card *)priv->phandle->card)
4912*4882a593Smuzhiyun 					->func,
4913*4882a593Smuzhiyun 				data, reg, &ret);
4914*4882a593Smuzhiyun 		else
4915*4882a593Smuzhiyun 			sdio_f0_writeb(
4916*4882a593Smuzhiyun 				((struct sdio_mmc_card *)priv->phandle->card)
4917*4882a593Smuzhiyun 					->func,
4918*4882a593Smuzhiyun 				data, reg, &ret);
4919*4882a593Smuzhiyun 		sdio_release_host(
4920*4882a593Smuzhiyun 			((struct sdio_mmc_card *)priv->phandle->card)->func);
4921*4882a593Smuzhiyun 		if (ret) {
4922*4882a593Smuzhiyun 			PRINTM(MERROR,
4923*4882a593Smuzhiyun 			       "sdio_writeb: writing register 0x%X failed\n",
4924*4882a593Smuzhiyun 			       reg);
4925*4882a593Smuzhiyun 			goto done;
4926*4882a593Smuzhiyun 		}
4927*4882a593Smuzhiyun #else
4928*4882a593Smuzhiyun 		if (sdio_write_ioreg(priv->phandle->card, func, reg, data) <
4929*4882a593Smuzhiyun 		    0) {
4930*4882a593Smuzhiyun 			PRINTM(MERROR,
4931*4882a593Smuzhiyun 			       "sdio_write_ioreg: writing register 0x%X failed\n",
4932*4882a593Smuzhiyun 			       reg);
4933*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
4934*4882a593Smuzhiyun 			goto done;
4935*4882a593Smuzhiyun 		}
4936*4882a593Smuzhiyun #endif
4937*4882a593Smuzhiyun 	}
4938*4882a593Smuzhiyun 
4939*4882a593Smuzhiyun 	buf[0] = data;
4940*4882a593Smuzhiyun 	wrq->u.data.length = 1;
4941*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, buf, sizeof(int))) {
4942*4882a593Smuzhiyun 		PRINTM(MERROR, "Copy to user failed\n");
4943*4882a593Smuzhiyun 		ret = -EFAULT;
4944*4882a593Smuzhiyun 		goto done;
4945*4882a593Smuzhiyun 	}
4946*4882a593Smuzhiyun 
4947*4882a593Smuzhiyun done:
4948*4882a593Smuzhiyun 	LEAVE();
4949*4882a593Smuzhiyun 	return ret;
4950*4882a593Smuzhiyun }
4951*4882a593Smuzhiyun 
4952*4882a593Smuzhiyun /**
4953*4882a593Smuzhiyun  *  @brief Cmd53 read/write register
4954*4882a593Smuzhiyun  *
4955*4882a593Smuzhiyun  *  @param priv         A pointer to moal_private structure
4956*4882a593Smuzhiyun  *  @param wrq          A pointer to iwreq structure
4957*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
4958*4882a593Smuzhiyun  */
woal_cmd53rdwr_ioctl(moal_private * priv,struct iwreq * wrq)4959*4882a593Smuzhiyun static int woal_cmd53rdwr_ioctl(moal_private *priv, struct iwreq *wrq)
4960*4882a593Smuzhiyun {
4961*4882a593Smuzhiyun 	t_u8 *buf = NULL;
4962*4882a593Smuzhiyun 	t_u8 rw, mode;
4963*4882a593Smuzhiyun 	t_u16 blklen = 0, blknum = 0;
4964*4882a593Smuzhiyun 	int reg = 0, pattern_len = 0, pos = 0, ret = MLAN_STATUS_SUCCESS;
4965*4882a593Smuzhiyun 	t_u32 total_len = 0;
4966*4882a593Smuzhiyun 	t_u8 *data = NULL;
4967*4882a593Smuzhiyun 
4968*4882a593Smuzhiyun 	ENTER();
4969*4882a593Smuzhiyun 
4970*4882a593Smuzhiyun 	buf = kmalloc(WOAL_2K_BYTES, GFP_KERNEL);
4971*4882a593Smuzhiyun 	if (!buf) {
4972*4882a593Smuzhiyun 		PRINTM(MERROR, "Cannot allocate buffer for command!\n");
4973*4882a593Smuzhiyun 		ret = -EFAULT;
4974*4882a593Smuzhiyun 		goto done;
4975*4882a593Smuzhiyun 	}
4976*4882a593Smuzhiyun 	data = kmalloc(WOAL_2K_BYTES, GFP_KERNEL);
4977*4882a593Smuzhiyun 	if (!data) {
4978*4882a593Smuzhiyun 		PRINTM(MERROR, "Cannot allocate buffer for command!\n");
4979*4882a593Smuzhiyun 		ret = -EFAULT;
4980*4882a593Smuzhiyun 		goto done;
4981*4882a593Smuzhiyun 	}
4982*4882a593Smuzhiyun 	if (wrq->u.data.length > WOAL_2K_BYTES) {
4983*4882a593Smuzhiyun 		PRINTM(MERROR, "Data lengh is too large!\n");
4984*4882a593Smuzhiyun 		ret = -EINVAL;
4985*4882a593Smuzhiyun 		goto done;
4986*4882a593Smuzhiyun 	}
4987*4882a593Smuzhiyun 	if (copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length)) {
4988*4882a593Smuzhiyun 		PRINTM(MINFO, "Copy from user failed\n");
4989*4882a593Smuzhiyun 		ret = -EFAULT;
4990*4882a593Smuzhiyun 		goto done;
4991*4882a593Smuzhiyun 	}
4992*4882a593Smuzhiyun 
4993*4882a593Smuzhiyun 	rw = buf[0]; /* read/write (0/1) */
4994*4882a593Smuzhiyun 	reg = buf[5]; /* address */
4995*4882a593Smuzhiyun 	reg = (reg << 8) + buf[4];
4996*4882a593Smuzhiyun 	reg = (reg << 8) + buf[3];
4997*4882a593Smuzhiyun 	reg = (reg << 8) + buf[2];
4998*4882a593Smuzhiyun 	mode = buf[6]; /* byte mode/block mode (0/1) */
4999*4882a593Smuzhiyun 	blklen = buf[8]; /* block size */
5000*4882a593Smuzhiyun 	blklen = (blklen << 8) + buf[7];
5001*4882a593Smuzhiyun 	blknum = buf[10]; /* block number or byte number */
5002*4882a593Smuzhiyun 	blknum = (blknum << 8) + buf[9];
5003*4882a593Smuzhiyun 
5004*4882a593Smuzhiyun 	if (mode != BYTE_MODE)
5005*4882a593Smuzhiyun 		mode = BLOCK_MODE;
5006*4882a593Smuzhiyun 	total_len = (mode == BLOCK_MODE) ? blknum * blklen : blknum;
5007*4882a593Smuzhiyun 	if (total_len > WOAL_2K_BYTES) {
5008*4882a593Smuzhiyun 		PRINTM(MERROR, "Total data length is too large!\n");
5009*4882a593Smuzhiyun 		ret = -EINVAL;
5010*4882a593Smuzhiyun 		goto done;
5011*4882a593Smuzhiyun 	}
5012*4882a593Smuzhiyun 	PRINTM(MINFO,
5013*4882a593Smuzhiyun 	       "CMD53 read/write, addr = %#x, mode = %d, block size = %d, block(byte) number = %d\n",
5014*4882a593Smuzhiyun 	       reg, mode, blklen, blknum);
5015*4882a593Smuzhiyun 
5016*4882a593Smuzhiyun 	if (!rw) {
5017*4882a593Smuzhiyun 		sdio_claim_host(
5018*4882a593Smuzhiyun 			((struct sdio_mmc_card *)priv->phandle->card)->func);
5019*4882a593Smuzhiyun 		if (sdio_readsb(
5020*4882a593Smuzhiyun 			    ((struct sdio_mmc_card *)priv->phandle->card)->func,
5021*4882a593Smuzhiyun 			    data, reg, total_len))
5022*4882a593Smuzhiyun 			PRINTM(MERROR,
5023*4882a593Smuzhiyun 			       "sdio_readsb: reading memory 0x%x failed\n",
5024*4882a593Smuzhiyun 			       reg);
5025*4882a593Smuzhiyun 		sdio_release_host(
5026*4882a593Smuzhiyun 			((struct sdio_mmc_card *)priv->phandle->card)->func);
5027*4882a593Smuzhiyun 
5028*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, data, total_len)) {
5029*4882a593Smuzhiyun 			PRINTM(MINFO, "Copy to user failed\n");
5030*4882a593Smuzhiyun 			ret = -EFAULT;
5031*4882a593Smuzhiyun 			goto done;
5032*4882a593Smuzhiyun 		}
5033*4882a593Smuzhiyun 		wrq->u.data.length = total_len;
5034*4882a593Smuzhiyun 	} else {
5035*4882a593Smuzhiyun 		pattern_len = wrq->u.data.length - 11;
5036*4882a593Smuzhiyun 		if (pattern_len > (int)total_len)
5037*4882a593Smuzhiyun 			pattern_len = total_len;
5038*4882a593Smuzhiyun 		memset(data, 0, WOAL_2K_BYTES);
5039*4882a593Smuzhiyun 
5040*4882a593Smuzhiyun 		/* Copy/duplicate the pattern to data buffer */
5041*4882a593Smuzhiyun 		for (pos = 0; pos < (int)total_len; pos++)
5042*4882a593Smuzhiyun 			data[pos] = buf[11 + (pos % pattern_len)];
5043*4882a593Smuzhiyun 
5044*4882a593Smuzhiyun 		sdio_claim_host(
5045*4882a593Smuzhiyun 			((struct sdio_mmc_card *)priv->phandle->card)->func);
5046*4882a593Smuzhiyun 		if (sdio_writesb(
5047*4882a593Smuzhiyun 			    ((struct sdio_mmc_card *)priv->phandle->card)->func,
5048*4882a593Smuzhiyun 			    reg, data, total_len))
5049*4882a593Smuzhiyun 			PRINTM(MERROR,
5050*4882a593Smuzhiyun 			       "sdio_writesb: writing memory 0x%x failed\n",
5051*4882a593Smuzhiyun 			       reg);
5052*4882a593Smuzhiyun 		sdio_release_host(
5053*4882a593Smuzhiyun 			((struct sdio_mmc_card *)priv->phandle->card)->func);
5054*4882a593Smuzhiyun 	}
5055*4882a593Smuzhiyun 
5056*4882a593Smuzhiyun done:
5057*4882a593Smuzhiyun 	kfree(buf);
5058*4882a593Smuzhiyun 	kfree(data);
5059*4882a593Smuzhiyun 	LEAVE();
5060*4882a593Smuzhiyun 	return ret;
5061*4882a593Smuzhiyun }
5062*4882a593Smuzhiyun #endif /* SDIO */
5063*4882a593Smuzhiyun 
5064*4882a593Smuzhiyun #ifdef SDIO
5065*4882a593Smuzhiyun /**
5066*4882a593Smuzhiyun  * @brief Set SDIO Multi-point aggregation control parameters
5067*4882a593Smuzhiyun  *
5068*4882a593Smuzhiyun  * @param priv     A pointer to moal_private structure
5069*4882a593Smuzhiyun  * @param wrq      A pointer to iwreq structure
5070*4882a593Smuzhiyun  *
5071*4882a593Smuzhiyun  * @return         0/MLAN_STATUS_PENDING --success, otherwise fail
5072*4882a593Smuzhiyun  */
woal_do_sdio_mpa_ctrl(moal_private * priv,struct iwreq * wrq)5073*4882a593Smuzhiyun static int woal_do_sdio_mpa_ctrl(moal_private *priv, struct iwreq *wrq)
5074*4882a593Smuzhiyun {
5075*4882a593Smuzhiyun 	int data[6], data_length = wrq->u.data.length, copy_len;
5076*4882a593Smuzhiyun 	int ret = 0;
5077*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = NULL;
5078*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
5079*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
5080*4882a593Smuzhiyun 
5081*4882a593Smuzhiyun 	ENTER();
5082*4882a593Smuzhiyun 
5083*4882a593Smuzhiyun 	if (sizeof(int) * wrq->u.data.length > sizeof(data)) {
5084*4882a593Smuzhiyun 		PRINTM(MERROR, "Too many arguments\n");
5085*4882a593Smuzhiyun 		ret = -EINVAL;
5086*4882a593Smuzhiyun 		goto done;
5087*4882a593Smuzhiyun 	}
5088*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
5089*4882a593Smuzhiyun 
5090*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
5091*4882a593Smuzhiyun 	if (req == NULL) {
5092*4882a593Smuzhiyun 		ret = -ENOMEM;
5093*4882a593Smuzhiyun 		goto done;
5094*4882a593Smuzhiyun 	}
5095*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)req->pbuf;
5096*4882a593Smuzhiyun 	memset(misc, 0, sizeof(mlan_ds_misc_cfg));
5097*4882a593Smuzhiyun 
5098*4882a593Smuzhiyun 	misc->sub_command = MLAN_OID_MISC_SDIO_MPA_CTRL;
5099*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_MISC_CFG;
5100*4882a593Smuzhiyun 
5101*4882a593Smuzhiyun 	/* Get the values first, then modify these values if
5102*4882a593Smuzhiyun 	 * user had modified them */
5103*4882a593Smuzhiyun 
5104*4882a593Smuzhiyun 	req->action = MLAN_ACT_GET;
5105*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5106*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
5107*4882a593Smuzhiyun 		PRINTM(MERROR, "woal_request_ioctl returned %d\n", ret);
5108*4882a593Smuzhiyun 		ret = -EFAULT;
5109*4882a593Smuzhiyun 		goto done;
5110*4882a593Smuzhiyun 	}
5111*4882a593Smuzhiyun 
5112*4882a593Smuzhiyun 	if (data_length == 0) {
5113*4882a593Smuzhiyun 		data[0] = misc->param.mpa_ctrl.tx_enable;
5114*4882a593Smuzhiyun 		data[1] = misc->param.mpa_ctrl.rx_enable;
5115*4882a593Smuzhiyun 		data[2] = misc->param.mpa_ctrl.tx_buf_size;
5116*4882a593Smuzhiyun 		data[3] = misc->param.mpa_ctrl.rx_buf_size;
5117*4882a593Smuzhiyun 		data[4] = misc->param.mpa_ctrl.tx_max_ports;
5118*4882a593Smuzhiyun 		data[5] = misc->param.mpa_ctrl.rx_max_ports;
5119*4882a593Smuzhiyun 
5120*4882a593Smuzhiyun 		PRINTM(MINFO, "Get Param: %d %d %d %d %d %d\n", data[0],
5121*4882a593Smuzhiyun 		       data[1], data[2], data[3], data[4], data[5]);
5122*4882a593Smuzhiyun 
5123*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, data, sizeof(data))) {
5124*4882a593Smuzhiyun 			ret = -EFAULT;
5125*4882a593Smuzhiyun 			goto done;
5126*4882a593Smuzhiyun 		}
5127*4882a593Smuzhiyun 		wrq->u.data.length = ARRAY_SIZE(data);
5128*4882a593Smuzhiyun 		goto done;
5129*4882a593Smuzhiyun 	}
5130*4882a593Smuzhiyun 
5131*4882a593Smuzhiyun 	if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
5132*4882a593Smuzhiyun 		PRINTM(MINFO, "Copy from user failed\n");
5133*4882a593Smuzhiyun 		ret = -EFAULT;
5134*4882a593Smuzhiyun 		goto done;
5135*4882a593Smuzhiyun 	}
5136*4882a593Smuzhiyun 
5137*4882a593Smuzhiyun 	switch (data_length) {
5138*4882a593Smuzhiyun 	case 6:
5139*4882a593Smuzhiyun 		misc->param.mpa_ctrl.rx_max_ports = data[5];
5140*4882a593Smuzhiyun 		/* fall through */
5141*4882a593Smuzhiyun 	case 5:
5142*4882a593Smuzhiyun 		misc->param.mpa_ctrl.tx_max_ports = data[4];
5143*4882a593Smuzhiyun 		/* fall through */
5144*4882a593Smuzhiyun 	case 4:
5145*4882a593Smuzhiyun 		misc->param.mpa_ctrl.rx_buf_size = data[3];
5146*4882a593Smuzhiyun 		/* fall through */
5147*4882a593Smuzhiyun 	case 3:
5148*4882a593Smuzhiyun 		misc->param.mpa_ctrl.tx_buf_size = data[2];
5149*4882a593Smuzhiyun 		/* fall through */
5150*4882a593Smuzhiyun 	case 2:
5151*4882a593Smuzhiyun 		misc->param.mpa_ctrl.rx_enable = data[1];
5152*4882a593Smuzhiyun 		/* fall through */
5153*4882a593Smuzhiyun 	case 1:
5154*4882a593Smuzhiyun 		/* Set cmd */
5155*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
5156*4882a593Smuzhiyun 
5157*4882a593Smuzhiyun 		PRINTM(MINFO, "Set Param: %d %d %d %d %d %d\n", data[0],
5158*4882a593Smuzhiyun 		       data[1], data[2], data[3], data[4], data[5]);
5159*4882a593Smuzhiyun 
5160*4882a593Smuzhiyun 		misc->param.mpa_ctrl.tx_enable = data[0];
5161*4882a593Smuzhiyun 		break;
5162*4882a593Smuzhiyun 	default:
5163*4882a593Smuzhiyun 		PRINTM(MERROR, "Default case error\n");
5164*4882a593Smuzhiyun 		ret = -EINVAL;
5165*4882a593Smuzhiyun 		goto done;
5166*4882a593Smuzhiyun 	}
5167*4882a593Smuzhiyun 
5168*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5169*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
5170*4882a593Smuzhiyun 		PRINTM(MERROR, "woal_request_ioctl returned %d\n", ret);
5171*4882a593Smuzhiyun 		ret = -EFAULT;
5172*4882a593Smuzhiyun 		goto done;
5173*4882a593Smuzhiyun 	}
5174*4882a593Smuzhiyun 
5175*4882a593Smuzhiyun done:
5176*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
5177*4882a593Smuzhiyun 		kfree(req);
5178*4882a593Smuzhiyun 	LEAVE();
5179*4882a593Smuzhiyun 	return ret;
5180*4882a593Smuzhiyun }
5181*4882a593Smuzhiyun #endif
5182*4882a593Smuzhiyun 
5183*4882a593Smuzhiyun /**
5184*4882a593Smuzhiyun  * @brief Set/Get scan configuration parameters
5185*4882a593Smuzhiyun  *
5186*4882a593Smuzhiyun  * @param priv     A pointer to moal_private structure
5187*4882a593Smuzhiyun  * @param wrq      A pointer to iwreq structure
5188*4882a593Smuzhiyun  *
5189*4882a593Smuzhiyun  * @return         0 --success, otherwise fail
5190*4882a593Smuzhiyun  */
woal_set_get_scan_cfg(moal_private * priv,struct iwreq * wrq)5191*4882a593Smuzhiyun static int woal_set_get_scan_cfg(moal_private *priv, struct iwreq *wrq)
5192*4882a593Smuzhiyun {
5193*4882a593Smuzhiyun 	int ret = 0;
5194*4882a593Smuzhiyun 	int data[7], copy_len;
5195*4882a593Smuzhiyun 	mlan_ds_scan *scan = NULL;
5196*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
5197*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
5198*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
5199*4882a593Smuzhiyun 	int arg_len = 0;
5200*4882a593Smuzhiyun 
5201*4882a593Smuzhiyun 	ENTER();
5202*4882a593Smuzhiyun 	arg_len = 7;
5203*4882a593Smuzhiyun 	if (data_length > arg_len) {
5204*4882a593Smuzhiyun 		PRINTM(MERROR, "Too much arguments\n");
5205*4882a593Smuzhiyun 		LEAVE();
5206*4882a593Smuzhiyun 		return -EINVAL;
5207*4882a593Smuzhiyun 	}
5208*4882a593Smuzhiyun 	copy_len = sizeof(int) * data_length;
5209*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan));
5210*4882a593Smuzhiyun 	if (req == NULL) {
5211*4882a593Smuzhiyun 		LEAVE();
5212*4882a593Smuzhiyun 		return -ENOMEM;
5213*4882a593Smuzhiyun 	}
5214*4882a593Smuzhiyun 	scan = (mlan_ds_scan *)req->pbuf;
5215*4882a593Smuzhiyun 	scan->sub_command = MLAN_OID_SCAN_CONFIG;
5216*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_SCAN;
5217*4882a593Smuzhiyun 	memset(data, 0, sizeof(data));
5218*4882a593Smuzhiyun 
5219*4882a593Smuzhiyun 	if (data_length) {
5220*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
5221*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
5222*4882a593Smuzhiyun 			ret = -EFAULT;
5223*4882a593Smuzhiyun 			goto done;
5224*4882a593Smuzhiyun 		}
5225*4882a593Smuzhiyun 		if ((data[0] < 0) || (data[0] > MLAN_SCAN_TYPE_PASSIVE)) {
5226*4882a593Smuzhiyun 			PRINTM(MERROR, "Invalid argument for scan type\n");
5227*4882a593Smuzhiyun 			ret = -EINVAL;
5228*4882a593Smuzhiyun 			goto done;
5229*4882a593Smuzhiyun 		}
5230*4882a593Smuzhiyun 		if ((data[1] < 0) || (data[1] > MLAN_SCAN_MODE_ANY)) {
5231*4882a593Smuzhiyun 			PRINTM(MERROR, "Invalid argument for scan mode\n");
5232*4882a593Smuzhiyun 			ret = -EINVAL;
5233*4882a593Smuzhiyun 			goto done;
5234*4882a593Smuzhiyun 		}
5235*4882a593Smuzhiyun 		if ((data[2] < 0) || (data[2] > MAX_PROBES)) {
5236*4882a593Smuzhiyun 			PRINTM(MERROR, "Invalid argument for scan probes\n");
5237*4882a593Smuzhiyun 			ret = -EINVAL;
5238*4882a593Smuzhiyun 			goto done;
5239*4882a593Smuzhiyun 		}
5240*4882a593Smuzhiyun 		if (((data[3] < 0) ||
5241*4882a593Smuzhiyun 		     (data[3] > MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME)) ||
5242*4882a593Smuzhiyun 		    ((data[4] < 0) ||
5243*4882a593Smuzhiyun 		     (data[4] > MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME)) ||
5244*4882a593Smuzhiyun 		    ((data[5] < 0) ||
5245*4882a593Smuzhiyun 		     (data[5] > MRVDRV_MAX_PASSIVE_SCAN_CHAN_TIME))) {
5246*4882a593Smuzhiyun 			PRINTM(MERROR, "Invalid argument for scan time\n");
5247*4882a593Smuzhiyun 			ret = -EINVAL;
5248*4882a593Smuzhiyun 			goto done;
5249*4882a593Smuzhiyun 		}
5250*4882a593Smuzhiyun 		if ((data[6] < 0) || (data[6] > 1)) {
5251*4882a593Smuzhiyun 			PRINTM(MERROR, "Invalid argument for extended scan\n");
5252*4882a593Smuzhiyun 			ret = -EINVAL;
5253*4882a593Smuzhiyun 			goto done;
5254*4882a593Smuzhiyun 		}
5255*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
5256*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, &scan->param.scan_cfg, data,
5257*4882a593Smuzhiyun 				sizeof(data), sizeof(scan->param.scan_cfg));
5258*4882a593Smuzhiyun 	} else
5259*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
5260*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5261*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
5262*4882a593Smuzhiyun 		ret = -EFAULT;
5263*4882a593Smuzhiyun 		goto done;
5264*4882a593Smuzhiyun 	}
5265*4882a593Smuzhiyun 	if (!data_length) {
5266*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, data, &scan->param.scan_cfg,
5267*4882a593Smuzhiyun 				sizeof(scan->param.scan_cfg), sizeof(data));
5268*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, data, sizeof(data))) {
5269*4882a593Smuzhiyun 			ret = -EFAULT;
5270*4882a593Smuzhiyun 			goto done;
5271*4882a593Smuzhiyun 		}
5272*4882a593Smuzhiyun 		wrq->u.data.length = arg_len;
5273*4882a593Smuzhiyun 	}
5274*4882a593Smuzhiyun done:
5275*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
5276*4882a593Smuzhiyun 		kfree(req);
5277*4882a593Smuzhiyun 	LEAVE();
5278*4882a593Smuzhiyun 	return ret;
5279*4882a593Smuzhiyun }
5280*4882a593Smuzhiyun 
5281*4882a593Smuzhiyun /**
5282*4882a593Smuzhiyun  * @brief Set/Get PS configuration parameters
5283*4882a593Smuzhiyun  *
5284*4882a593Smuzhiyun  * @param priv     A pointer to moal_private structure
5285*4882a593Smuzhiyun  * @param wrq      A pointer to iwreq structure
5286*4882a593Smuzhiyun  *
5287*4882a593Smuzhiyun  * @return         0 --success, otherwise fail
5288*4882a593Smuzhiyun  */
woal_set_get_ps_cfg(moal_private * priv,struct iwreq * wrq)5289*4882a593Smuzhiyun static int woal_set_get_ps_cfg(moal_private *priv, struct iwreq *wrq)
5290*4882a593Smuzhiyun {
5291*4882a593Smuzhiyun 	int data[7], copy_len, ret = 0;
5292*4882a593Smuzhiyun 	mlan_ds_pm_cfg *pm_cfg = NULL;
5293*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
5294*4882a593Smuzhiyun 	int allowed = 3;
5295*4882a593Smuzhiyun 	int i = 3;
5296*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
5297*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
5298*4882a593Smuzhiyun 
5299*4882a593Smuzhiyun 	ENTER();
5300*4882a593Smuzhiyun 
5301*4882a593Smuzhiyun 	allowed++; /* For beacon missing timeout parameter */
5302*4882a593Smuzhiyun 	allowed += 2; /* For delay to PS and PS mode parameters */
5303*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
5304*4882a593Smuzhiyun 
5305*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg));
5306*4882a593Smuzhiyun 	if (req == NULL) {
5307*4882a593Smuzhiyun 		ret = -ENOMEM;
5308*4882a593Smuzhiyun 		goto done;
5309*4882a593Smuzhiyun 	}
5310*4882a593Smuzhiyun 	if (data_length > allowed) {
5311*4882a593Smuzhiyun 		ret = -EINVAL;
5312*4882a593Smuzhiyun 		goto done;
5313*4882a593Smuzhiyun 	}
5314*4882a593Smuzhiyun 	pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
5315*4882a593Smuzhiyun 	pm_cfg->sub_command = MLAN_OID_PM_CFG_PS_CFG;
5316*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_PM_CFG;
5317*4882a593Smuzhiyun 	memset(data, 0, sizeof(data));
5318*4882a593Smuzhiyun 
5319*4882a593Smuzhiyun 	if (data_length) {
5320*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
5321*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
5322*4882a593Smuzhiyun 			ret = -EFAULT;
5323*4882a593Smuzhiyun 			goto done;
5324*4882a593Smuzhiyun 		}
5325*4882a593Smuzhiyun 		if ((data[0] < PS_NULL_DISABLE)) {
5326*4882a593Smuzhiyun 			PRINTM(MERROR,
5327*4882a593Smuzhiyun 			       "Invalid argument for PS null interval\n");
5328*4882a593Smuzhiyun 			ret = -EINVAL;
5329*4882a593Smuzhiyun 			goto done;
5330*4882a593Smuzhiyun 		}
5331*4882a593Smuzhiyun 		if ((data[1] != MRVDRV_IGNORE_MULTIPLE_DTIM) &&
5332*4882a593Smuzhiyun 		    (data[1] != MRVDRV_MATCH_CLOSEST_DTIM) &&
5333*4882a593Smuzhiyun 		    ((data[1] < MRVDRV_MIN_MULTIPLE_DTIM) ||
5334*4882a593Smuzhiyun 		     (data[1] > MRVDRV_MAX_MULTIPLE_DTIM))) {
5335*4882a593Smuzhiyun 			PRINTM(MERROR, "Invalid argument for multiple DTIM\n");
5336*4882a593Smuzhiyun 			ret = -EINVAL;
5337*4882a593Smuzhiyun 			goto done;
5338*4882a593Smuzhiyun 		}
5339*4882a593Smuzhiyun 
5340*4882a593Smuzhiyun 		if ((data[2] < MRVDRV_MIN_LISTEN_INTERVAL) &&
5341*4882a593Smuzhiyun 		    (data[2] != MRVDRV_LISTEN_INTERVAL_DISABLE)) {
5342*4882a593Smuzhiyun 			PRINTM(MERROR,
5343*4882a593Smuzhiyun 			       "Invalid argument for listen interval\n");
5344*4882a593Smuzhiyun 			ret = -EINVAL;
5345*4882a593Smuzhiyun 			goto done;
5346*4882a593Smuzhiyun 		}
5347*4882a593Smuzhiyun 
5348*4882a593Smuzhiyun 		if ((data[i] != DISABLE_BCN_MISS_TO) &&
5349*4882a593Smuzhiyun 		    ((data[i] < MIN_BCN_MISS_TO) ||
5350*4882a593Smuzhiyun 		     (data[i] > MAX_BCN_MISS_TO))) {
5351*4882a593Smuzhiyun 			PRINTM(MERROR,
5352*4882a593Smuzhiyun 			       "Invalid argument for beacon miss timeout\n");
5353*4882a593Smuzhiyun 			ret = -EINVAL;
5354*4882a593Smuzhiyun 			goto done;
5355*4882a593Smuzhiyun 		}
5356*4882a593Smuzhiyun 		i++;
5357*4882a593Smuzhiyun 		if (data_length < allowed - 1)
5358*4882a593Smuzhiyun 			data[i] = DELAY_TO_PS_UNCHANGED;
5359*4882a593Smuzhiyun 		else if ((data[i] < MIN_DELAY_TO_PS) ||
5360*4882a593Smuzhiyun 			 (data[i] > MAX_DELAY_TO_PS)) {
5361*4882a593Smuzhiyun 			PRINTM(MERROR, "Invalid argument for delay to PS\n");
5362*4882a593Smuzhiyun 			ret = -EINVAL;
5363*4882a593Smuzhiyun 			goto done;
5364*4882a593Smuzhiyun 		}
5365*4882a593Smuzhiyun 		i++;
5366*4882a593Smuzhiyun 		if ((data[i] != PS_MODE_UNCHANGED) &&
5367*4882a593Smuzhiyun 		    (data[i] != PS_MODE_AUTO) && (data[i] != PS_MODE_POLL) &&
5368*4882a593Smuzhiyun 		    (data[i] != PS_MODE_NULL)) {
5369*4882a593Smuzhiyun 			PRINTM(MERROR, "Invalid argument for PS mode\n");
5370*4882a593Smuzhiyun 			ret = -EINVAL;
5371*4882a593Smuzhiyun 			goto done;
5372*4882a593Smuzhiyun 		}
5373*4882a593Smuzhiyun 		i++;
5374*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
5375*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, &pm_cfg->param.ps_cfg, data,
5376*4882a593Smuzhiyun 				sizeof(data), sizeof(pm_cfg->param.ps_cfg));
5377*4882a593Smuzhiyun 	} else
5378*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
5379*4882a593Smuzhiyun 
5380*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5381*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
5382*4882a593Smuzhiyun 		ret = -EFAULT;
5383*4882a593Smuzhiyun 		goto done;
5384*4882a593Smuzhiyun 	}
5385*4882a593Smuzhiyun 	moal_memcpy_ext(priv->phandle, data, &pm_cfg->param.ps_cfg,
5386*4882a593Smuzhiyun 			MIN((sizeof(int) * allowed),
5387*4882a593Smuzhiyun 			    sizeof(pm_cfg->param.ps_cfg)),
5388*4882a593Smuzhiyun 			sizeof(data));
5389*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * allowed)) {
5390*4882a593Smuzhiyun 		ret = -EFAULT;
5391*4882a593Smuzhiyun 		goto done;
5392*4882a593Smuzhiyun 	}
5393*4882a593Smuzhiyun 	wrq->u.data.length = allowed;
5394*4882a593Smuzhiyun 
5395*4882a593Smuzhiyun 	if (req->action == MLAN_ACT_SET) {
5396*4882a593Smuzhiyun 		pm_cfg = (mlan_ds_pm_cfg *)req->pbuf;
5397*4882a593Smuzhiyun 		pm_cfg->sub_command = MLAN_OID_PM_CFG_IEEE_PS;
5398*4882a593Smuzhiyun 		pm_cfg->param.ps_mode = 1;
5399*4882a593Smuzhiyun 		req->req_id = MLAN_IOCTL_PM_CFG;
5400*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
5401*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5402*4882a593Smuzhiyun 	}
5403*4882a593Smuzhiyun 
5404*4882a593Smuzhiyun done:
5405*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
5406*4882a593Smuzhiyun 		kfree(req);
5407*4882a593Smuzhiyun 	LEAVE();
5408*4882a593Smuzhiyun 	return ret;
5409*4882a593Smuzhiyun }
5410*4882a593Smuzhiyun 
5411*4882a593Smuzhiyun /**
5412*4882a593Smuzhiyun  *  @brief Private IOCTL entry to send an ADDTS TSPEC
5413*4882a593Smuzhiyun  *
5414*4882a593Smuzhiyun  *  Receive a ADDTS command from the application.  The command structure
5415*4882a593Smuzhiyun  *    contains a TSPEC and timeout in milliseconds.  The timeout is performed
5416*4882a593Smuzhiyun  *    in the firmware after the ADDTS command frame is sent.
5417*4882a593Smuzhiyun  *
5418*4882a593Smuzhiyun  *  The TSPEC is received in the API as an opaque block. The firmware will
5419*4882a593Smuzhiyun  *    send the entire data block, including the bytes after the TSPEC.  This
5420*4882a593Smuzhiyun  *    is done to allow extra IEs to be packaged with the TSPEC in the ADDTS
5421*4882a593Smuzhiyun  *    action frame.
5422*4882a593Smuzhiyun  *
5423*4882a593Smuzhiyun  *  The IOCTL structure contains two return fields:
5424*4882a593Smuzhiyun  *    - The firmware command result, which indicates failure and timeouts
5425*4882a593Smuzhiyun  *    - The IEEE Status code which contains the corresponding value from
5426*4882a593Smuzhiyun  *      any ADDTS response frame received.
5427*4882a593Smuzhiyun  *
5428*4882a593Smuzhiyun  *  In addition, the opaque TSPEC data block passed in is replaced with the
5429*4882a593Smuzhiyun  *    TSPEC received in the ADDTS response frame.  In case of failure, the
5430*4882a593Smuzhiyun  *    AP may modify the TSPEC on return and in the case of success, the
5431*4882a593Smuzhiyun  *    medium time is returned as calculated by the AP.  Along with the TSPEC,
5432*4882a593Smuzhiyun  *    any IEs that are sent in the ADDTS response are also returned and can be
5433*4882a593Smuzhiyun  *    parsed using the IOCTL length as an indicator of extra elements.
5434*4882a593Smuzhiyun  *
5435*4882a593Smuzhiyun  *  The return value to the application layer indicates a driver execution
5436*4882a593Smuzhiyun  *    success or failure.  A successful return could still indicate a firmware
5437*4882a593Smuzhiyun  *    failure or AP negotiation failure via the commandResult field copied
5438*4882a593Smuzhiyun  *    back to the application.
5439*4882a593Smuzhiyun  *
5440*4882a593Smuzhiyun  *  @param priv    Pointer to the mlan_private driver data struct
5441*4882a593Smuzhiyun  *  @param wrq     A pointer to iwreq structure containing the
5442*4882a593Smuzhiyun  *                 wlan_ioctl_wmm_addts_req_t struct for this ADDTS request
5443*4882a593Smuzhiyun  *
5444*4882a593Smuzhiyun  *  @return        0 if successful; IOCTL error code otherwise
5445*4882a593Smuzhiyun  */
woal_wmm_addts_req_ioctl(moal_private * priv,struct iwreq * wrq)5446*4882a593Smuzhiyun static int woal_wmm_addts_req_ioctl(moal_private *priv, struct iwreq *wrq)
5447*4882a593Smuzhiyun {
5448*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
5449*4882a593Smuzhiyun 	mlan_ds_wmm_cfg *cfg = NULL;
5450*4882a593Smuzhiyun 	wlan_ioctl_wmm_addts_req_t addts_ioctl;
5451*4882a593Smuzhiyun 	int ret = 0;
5452*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
5453*4882a593Smuzhiyun 
5454*4882a593Smuzhiyun 	ENTER();
5455*4882a593Smuzhiyun 
5456*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
5457*4882a593Smuzhiyun 	if (req == NULL) {
5458*4882a593Smuzhiyun 		ret = -ENOMEM;
5459*4882a593Smuzhiyun 		goto done;
5460*4882a593Smuzhiyun 	}
5461*4882a593Smuzhiyun 
5462*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_WMM_CFG;
5463*4882a593Smuzhiyun 	cfg = (mlan_ds_wmm_cfg *)req->pbuf;
5464*4882a593Smuzhiyun 	cfg->sub_command = MLAN_OID_WMM_CFG_ADDTS;
5465*4882a593Smuzhiyun 
5466*4882a593Smuzhiyun 	memset(&addts_ioctl, 0x00, sizeof(addts_ioctl));
5467*4882a593Smuzhiyun 
5468*4882a593Smuzhiyun 	if (wrq->u.data.length) {
5469*4882a593Smuzhiyun 		if (copy_from_user(&addts_ioctl, wrq->u.data.pointer,
5470*4882a593Smuzhiyun 				   MIN(wrq->u.data.length,
5471*4882a593Smuzhiyun 				       sizeof(addts_ioctl)))) {
5472*4882a593Smuzhiyun 			PRINTM(MERROR, "TSPEC: ADDTS copy from user failed\n");
5473*4882a593Smuzhiyun 			ret = -EFAULT;
5474*4882a593Smuzhiyun 			goto done;
5475*4882a593Smuzhiyun 		}
5476*4882a593Smuzhiyun 
5477*4882a593Smuzhiyun 		cfg->param.addts.timeout = addts_ioctl.timeout_ms;
5478*4882a593Smuzhiyun 		cfg->param.addts.ie_data_len = addts_ioctl.ie_data_len;
5479*4882a593Smuzhiyun 
5480*4882a593Smuzhiyun 		if (cfg->param.addts.ie_data_len >
5481*4882a593Smuzhiyun 		    sizeof(cfg->param.addts.ie_data)) {
5482*4882a593Smuzhiyun 			PRINTM(MERROR, "IE data length too large\n");
5483*4882a593Smuzhiyun 			ret = -EFAULT;
5484*4882a593Smuzhiyun 			goto done;
5485*4882a593Smuzhiyun 		}
5486*4882a593Smuzhiyun 
5487*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, cfg->param.addts.ie_data,
5488*4882a593Smuzhiyun 				addts_ioctl.ie_data,
5489*4882a593Smuzhiyun 				cfg->param.addts.ie_data_len,
5490*4882a593Smuzhiyun 				sizeof(cfg->param.addts.ie_data));
5491*4882a593Smuzhiyun 
5492*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5493*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
5494*4882a593Smuzhiyun 			ret = -EFAULT;
5495*4882a593Smuzhiyun 			goto done;
5496*4882a593Smuzhiyun 		}
5497*4882a593Smuzhiyun 		addts_ioctl.cmd_result = cfg->param.addts.result;
5498*4882a593Smuzhiyun 		addts_ioctl.ieee_status_code =
5499*4882a593Smuzhiyun 			(t_u8)cfg->param.addts.status_code;
5500*4882a593Smuzhiyun 		addts_ioctl.ie_data_len = cfg->param.addts.ie_data_len;
5501*4882a593Smuzhiyun 
5502*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, addts_ioctl.ie_data,
5503*4882a593Smuzhiyun 				cfg->param.addts.ie_data,
5504*4882a593Smuzhiyun 				cfg->param.addts.ie_data_len,
5505*4882a593Smuzhiyun 				sizeof(addts_ioctl.ie_data));
5506*4882a593Smuzhiyun 
5507*4882a593Smuzhiyun 		wrq->u.data.length =
5508*4882a593Smuzhiyun 			(sizeof(addts_ioctl) - sizeof(addts_ioctl.ie_data) +
5509*4882a593Smuzhiyun 			 cfg->param.addts.ie_data_len);
5510*4882a593Smuzhiyun 
5511*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &addts_ioctl,
5512*4882a593Smuzhiyun 				 wrq->u.data.length)) {
5513*4882a593Smuzhiyun 			PRINTM(MERROR, "TSPEC: ADDTS copy to user failed\n");
5514*4882a593Smuzhiyun 			ret = -EFAULT;
5515*4882a593Smuzhiyun 			goto done;
5516*4882a593Smuzhiyun 		}
5517*4882a593Smuzhiyun 	}
5518*4882a593Smuzhiyun 
5519*4882a593Smuzhiyun done:
5520*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
5521*4882a593Smuzhiyun 		kfree(req);
5522*4882a593Smuzhiyun 	LEAVE();
5523*4882a593Smuzhiyun 	return ret;
5524*4882a593Smuzhiyun }
5525*4882a593Smuzhiyun 
5526*4882a593Smuzhiyun /**
5527*4882a593Smuzhiyun  *  @brief Private IOCTL entry to send a DELTS TSPEC
5528*4882a593Smuzhiyun  *
5529*4882a593Smuzhiyun  *  Receive a DELTS command from the application.  The command structure
5530*4882a593Smuzhiyun  *    contains a TSPEC and reason code along with space for a command result
5531*4882a593Smuzhiyun  *    to be returned.  The information is packaged is sent to the wlan_cmd.c
5532*4882a593Smuzhiyun  *    firmware command prep and send routines for execution in the firmware.
5533*4882a593Smuzhiyun  *
5534*4882a593Smuzhiyun  *  The reason code is not used for WMM implementations but is indicated in
5535*4882a593Smuzhiyun  *    the 802.11e specification.
5536*4882a593Smuzhiyun  *
5537*4882a593Smuzhiyun  *  The return value to the application layer indicates a driver execution
5538*4882a593Smuzhiyun  *    success or failure.  A successful return could still indicate a firmware
5539*4882a593Smuzhiyun  *    failure via the cmd_result field copied back to the application.
5540*4882a593Smuzhiyun  *
5541*4882a593Smuzhiyun  *  @param priv    Pointer to the mlan_private driver data struct
5542*4882a593Smuzhiyun  *  @param wrq     A pointer to iwreq structure containing the
5543*4882a593Smuzhiyun  *                 wlan_ioctl_wmm_delts_req_t struct for this DELTS request
5544*4882a593Smuzhiyun  *
5545*4882a593Smuzhiyun  *  @return        0 if successful; IOCTL error code otherwise
5546*4882a593Smuzhiyun  */
woal_wmm_delts_req_ioctl(moal_private * priv,struct iwreq * wrq)5547*4882a593Smuzhiyun static int woal_wmm_delts_req_ioctl(moal_private *priv, struct iwreq *wrq)
5548*4882a593Smuzhiyun {
5549*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
5550*4882a593Smuzhiyun 	mlan_ds_wmm_cfg *cfg = NULL;
5551*4882a593Smuzhiyun 	wlan_ioctl_wmm_delts_req_t delts_ioctl;
5552*4882a593Smuzhiyun 	int ret = 0;
5553*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
5554*4882a593Smuzhiyun 
5555*4882a593Smuzhiyun 	ENTER();
5556*4882a593Smuzhiyun 
5557*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
5558*4882a593Smuzhiyun 	if (req == NULL) {
5559*4882a593Smuzhiyun 		ret = -ENOMEM;
5560*4882a593Smuzhiyun 		goto done;
5561*4882a593Smuzhiyun 	}
5562*4882a593Smuzhiyun 
5563*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_WMM_CFG;
5564*4882a593Smuzhiyun 	cfg = (mlan_ds_wmm_cfg *)req->pbuf;
5565*4882a593Smuzhiyun 	cfg->sub_command = MLAN_OID_WMM_CFG_DELTS;
5566*4882a593Smuzhiyun 
5567*4882a593Smuzhiyun 	memset(&delts_ioctl, 0x00, sizeof(delts_ioctl));
5568*4882a593Smuzhiyun 
5569*4882a593Smuzhiyun 	if (wrq->u.data.length) {
5570*4882a593Smuzhiyun 		if (copy_from_user(&delts_ioctl, wrq->u.data.pointer,
5571*4882a593Smuzhiyun 				   MIN(wrq->u.data.length,
5572*4882a593Smuzhiyun 				       sizeof(delts_ioctl)))) {
5573*4882a593Smuzhiyun 			PRINTM(MERROR, "TSPEC: DELTS copy from user failed\n");
5574*4882a593Smuzhiyun 			ret = -EFAULT;
5575*4882a593Smuzhiyun 			goto done;
5576*4882a593Smuzhiyun 		}
5577*4882a593Smuzhiyun 
5578*4882a593Smuzhiyun 		cfg->param.delts.status_code =
5579*4882a593Smuzhiyun 			(t_u32)delts_ioctl.ieee_reason_code;
5580*4882a593Smuzhiyun 		cfg->param.delts.ie_data_len = (t_u8)delts_ioctl.ie_data_len;
5581*4882a593Smuzhiyun 
5582*4882a593Smuzhiyun 		if ((cfg->param.delts.ie_data_len) >
5583*4882a593Smuzhiyun 		    sizeof(cfg->param.delts.ie_data)) {
5584*4882a593Smuzhiyun 			PRINTM(MERROR, "IE data length too large\n");
5585*4882a593Smuzhiyun 			ret = -EFAULT;
5586*4882a593Smuzhiyun 			goto done;
5587*4882a593Smuzhiyun 		}
5588*4882a593Smuzhiyun 
5589*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, cfg->param.delts.ie_data,
5590*4882a593Smuzhiyun 				delts_ioctl.ie_data,
5591*4882a593Smuzhiyun 				cfg->param.delts.ie_data_len,
5592*4882a593Smuzhiyun 				sizeof(cfg->param.delts.ie_data));
5593*4882a593Smuzhiyun 
5594*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5595*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
5596*4882a593Smuzhiyun 			ret = -EFAULT;
5597*4882a593Smuzhiyun 			goto done;
5598*4882a593Smuzhiyun 		}
5599*4882a593Smuzhiyun 
5600*4882a593Smuzhiyun 		/* Return the firmware command result back to the application
5601*4882a593Smuzhiyun 		 * layer */
5602*4882a593Smuzhiyun 		delts_ioctl.cmd_result = cfg->param.delts.result;
5603*4882a593Smuzhiyun 		wrq->u.data.length = sizeof(delts_ioctl);
5604*4882a593Smuzhiyun 
5605*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &delts_ioctl,
5606*4882a593Smuzhiyun 				 wrq->u.data.length)) {
5607*4882a593Smuzhiyun 			PRINTM(MERROR, "TSPEC: DELTS copy to user failed\n");
5608*4882a593Smuzhiyun 			ret = -EFAULT;
5609*4882a593Smuzhiyun 			goto done;
5610*4882a593Smuzhiyun 		}
5611*4882a593Smuzhiyun 	}
5612*4882a593Smuzhiyun 
5613*4882a593Smuzhiyun done:
5614*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
5615*4882a593Smuzhiyun 		kfree(req);
5616*4882a593Smuzhiyun 	LEAVE();
5617*4882a593Smuzhiyun 	return ret;
5618*4882a593Smuzhiyun }
5619*4882a593Smuzhiyun 
5620*4882a593Smuzhiyun /**
5621*4882a593Smuzhiyun  *  @brief Private IOCTL entry to get/set a specified AC Queue's parameters
5622*4882a593Smuzhiyun  *
5623*4882a593Smuzhiyun  *  Receive a AC Queue configuration command which is used to get, set, or
5624*4882a593Smuzhiyun  *    default the parameters associated with a specific WMM AC Queue.
5625*4882a593Smuzhiyun  *
5626*4882a593Smuzhiyun  *  @param priv    Pointer to the mlan_private driver data struct
5627*4882a593Smuzhiyun  *  @param wrq     A pointer to iwreq structure containing the
5628*4882a593Smuzhiyun  *                 wlan_ioctl_wmm_queue_config_t struct
5629*4882a593Smuzhiyun  *
5630*4882a593Smuzhiyun  *  @return        0 if successful; IOCTL error code otherwise
5631*4882a593Smuzhiyun  */
woal_wmm_queue_config_ioctl(moal_private * priv,struct iwreq * wrq)5632*4882a593Smuzhiyun static int woal_wmm_queue_config_ioctl(moal_private *priv, struct iwreq *wrq)
5633*4882a593Smuzhiyun {
5634*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
5635*4882a593Smuzhiyun 	mlan_ds_wmm_cfg *pwmm = NULL;
5636*4882a593Smuzhiyun 	mlan_ds_wmm_queue_config *pqcfg = NULL;
5637*4882a593Smuzhiyun 	wlan_ioctl_wmm_queue_config_t qcfg_ioctl;
5638*4882a593Smuzhiyun 	int ret = 0;
5639*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
5640*4882a593Smuzhiyun 
5641*4882a593Smuzhiyun 	ENTER();
5642*4882a593Smuzhiyun 
5643*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
5644*4882a593Smuzhiyun 	if (req == NULL) {
5645*4882a593Smuzhiyun 		ret = -ENOMEM;
5646*4882a593Smuzhiyun 		goto done;
5647*4882a593Smuzhiyun 	}
5648*4882a593Smuzhiyun 
5649*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_WMM_CFG;
5650*4882a593Smuzhiyun 	pwmm = (mlan_ds_wmm_cfg *)req->pbuf;
5651*4882a593Smuzhiyun 	pwmm->sub_command = MLAN_OID_WMM_CFG_QUEUE_CONFIG;
5652*4882a593Smuzhiyun 
5653*4882a593Smuzhiyun 	memset(&qcfg_ioctl, 0x00, sizeof(qcfg_ioctl));
5654*4882a593Smuzhiyun 	pqcfg = (mlan_ds_wmm_queue_config *)&pwmm->param.q_cfg;
5655*4882a593Smuzhiyun 
5656*4882a593Smuzhiyun 	if (wrq->u.data.length) {
5657*4882a593Smuzhiyun 		if (copy_from_user(&qcfg_ioctl, wrq->u.data.pointer,
5658*4882a593Smuzhiyun 				   MIN(wrq->u.data.length,
5659*4882a593Smuzhiyun 				       sizeof(qcfg_ioctl)))) {
5660*4882a593Smuzhiyun 			PRINTM(MERROR, "QCONFIG: copy from user failed\n");
5661*4882a593Smuzhiyun 			ret = -EFAULT;
5662*4882a593Smuzhiyun 			goto done;
5663*4882a593Smuzhiyun 		}
5664*4882a593Smuzhiyun 
5665*4882a593Smuzhiyun 		pqcfg->action = qcfg_ioctl.action;
5666*4882a593Smuzhiyun 		pqcfg->access_category = qcfg_ioctl.access_category;
5667*4882a593Smuzhiyun 		pqcfg->msdu_lifetime_expiry = qcfg_ioctl.msdu_lifetime_expiry;
5668*4882a593Smuzhiyun 
5669*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5670*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
5671*4882a593Smuzhiyun 			ret = -EFAULT;
5672*4882a593Smuzhiyun 			goto done;
5673*4882a593Smuzhiyun 		}
5674*4882a593Smuzhiyun 		memset(&qcfg_ioctl, 0x00, sizeof(qcfg_ioctl));
5675*4882a593Smuzhiyun 		qcfg_ioctl.action = pqcfg->action;
5676*4882a593Smuzhiyun 		qcfg_ioctl.access_category = pqcfg->access_category;
5677*4882a593Smuzhiyun 		qcfg_ioctl.msdu_lifetime_expiry = pqcfg->msdu_lifetime_expiry;
5678*4882a593Smuzhiyun 		wrq->u.data.length = sizeof(qcfg_ioctl);
5679*4882a593Smuzhiyun 
5680*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &qcfg_ioctl,
5681*4882a593Smuzhiyun 				 wrq->u.data.length)) {
5682*4882a593Smuzhiyun 			PRINTM(MERROR, "QCONFIG: copy to user failed\n");
5683*4882a593Smuzhiyun 			ret = -EFAULT;
5684*4882a593Smuzhiyun 			goto done;
5685*4882a593Smuzhiyun 		}
5686*4882a593Smuzhiyun 	}
5687*4882a593Smuzhiyun 
5688*4882a593Smuzhiyun done:
5689*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
5690*4882a593Smuzhiyun 		kfree(req);
5691*4882a593Smuzhiyun 	LEAVE();
5692*4882a593Smuzhiyun 	return ret;
5693*4882a593Smuzhiyun }
5694*4882a593Smuzhiyun 
5695*4882a593Smuzhiyun /**
5696*4882a593Smuzhiyun  *  @brief Private IOCTL entry to get and start/stop queue stats on a WMM AC
5697*4882a593Smuzhiyun  *
5698*4882a593Smuzhiyun  *  Receive a AC Queue statistics command from the application for a specific
5699*4882a593Smuzhiyun  *    WMM AC.  The command can:
5700*4882a593Smuzhiyun  *         - Turn stats on
5701*4882a593Smuzhiyun  *         - Turn stats off
5702*4882a593Smuzhiyun  *         - Collect and clear the stats
5703*4882a593Smuzhiyun  *
5704*4882a593Smuzhiyun  *  @param priv    Pointer to the moal_private driver data struct
5705*4882a593Smuzhiyun  *  @param wrq     A pointer to iwreq structure containing the
5706*4882a593Smuzhiyun  *                 wlan_ioctl_wmm_queue_stats_t struct
5707*4882a593Smuzhiyun  *
5708*4882a593Smuzhiyun  *  @return        0 if successful; IOCTL error code otherwise
5709*4882a593Smuzhiyun  */
woal_wmm_queue_stats_ioctl(moal_private * priv,struct iwreq * wrq)5710*4882a593Smuzhiyun static int woal_wmm_queue_stats_ioctl(moal_private *priv, struct iwreq *wrq)
5711*4882a593Smuzhiyun {
5712*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
5713*4882a593Smuzhiyun 	mlan_ds_wmm_cfg *pwmm = NULL;
5714*4882a593Smuzhiyun 	mlan_ds_wmm_queue_stats *pqstats = NULL;
5715*4882a593Smuzhiyun 	wlan_ioctl_wmm_queue_stats_t qstats_ioctl;
5716*4882a593Smuzhiyun 	int ret = 0;
5717*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
5718*4882a593Smuzhiyun 
5719*4882a593Smuzhiyun 	ENTER();
5720*4882a593Smuzhiyun 
5721*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
5722*4882a593Smuzhiyun 	if (req == NULL) {
5723*4882a593Smuzhiyun 		ret = -ENOMEM;
5724*4882a593Smuzhiyun 		goto done;
5725*4882a593Smuzhiyun 	}
5726*4882a593Smuzhiyun 
5727*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_WMM_CFG;
5728*4882a593Smuzhiyun 	pwmm = (mlan_ds_wmm_cfg *)req->pbuf;
5729*4882a593Smuzhiyun 	pwmm->sub_command = MLAN_OID_WMM_CFG_QUEUE_STATS;
5730*4882a593Smuzhiyun 
5731*4882a593Smuzhiyun 	memset(&qstats_ioctl, 0x00, sizeof(qstats_ioctl));
5732*4882a593Smuzhiyun 	pqstats = (mlan_ds_wmm_queue_stats *)&pwmm->param.q_stats;
5733*4882a593Smuzhiyun 
5734*4882a593Smuzhiyun 	if (wrq->u.data.length) {
5735*4882a593Smuzhiyun 		if (copy_from_user(&qstats_ioctl, wrq->u.data.pointer,
5736*4882a593Smuzhiyun 				   MIN(wrq->u.data.length,
5737*4882a593Smuzhiyun 				       sizeof(qstats_ioctl)))) {
5738*4882a593Smuzhiyun 			PRINTM(MERROR, "QSTATS: copy from user failed\n");
5739*4882a593Smuzhiyun 			ret = -EFAULT;
5740*4882a593Smuzhiyun 			goto done;
5741*4882a593Smuzhiyun 		}
5742*4882a593Smuzhiyun 
5743*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, (void *)pqstats,
5744*4882a593Smuzhiyun 				(void *)&qstats_ioctl, sizeof(qstats_ioctl),
5745*4882a593Smuzhiyun 				sizeof(qstats_ioctl));
5746*4882a593Smuzhiyun 		PRINTM(MINFO, "QSTATS: IOCTL [%d,%d]\n", qstats_ioctl.action,
5747*4882a593Smuzhiyun 		       qstats_ioctl.user_priority);
5748*4882a593Smuzhiyun 
5749*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5750*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
5751*4882a593Smuzhiyun 			ret = -EFAULT;
5752*4882a593Smuzhiyun 			goto done;
5753*4882a593Smuzhiyun 		}
5754*4882a593Smuzhiyun 
5755*4882a593Smuzhiyun 		memset(&qstats_ioctl, 0x00, sizeof(qstats_ioctl));
5756*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, (void *)&qstats_ioctl,
5757*4882a593Smuzhiyun 				(void *)pqstats, sizeof(qstats_ioctl),
5758*4882a593Smuzhiyun 				sizeof(qstats_ioctl));
5759*4882a593Smuzhiyun 		wrq->u.data.length = sizeof(qstats_ioctl);
5760*4882a593Smuzhiyun 
5761*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &qstats_ioctl,
5762*4882a593Smuzhiyun 				 wrq->u.data.length)) {
5763*4882a593Smuzhiyun 			PRINTM(MERROR, "QSTATS: copy to user failed\n");
5764*4882a593Smuzhiyun 			ret = -EFAULT;
5765*4882a593Smuzhiyun 			goto done;
5766*4882a593Smuzhiyun 		}
5767*4882a593Smuzhiyun 	}
5768*4882a593Smuzhiyun 
5769*4882a593Smuzhiyun done:
5770*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
5771*4882a593Smuzhiyun 		kfree(req);
5772*4882a593Smuzhiyun 	LEAVE();
5773*4882a593Smuzhiyun 	return ret;
5774*4882a593Smuzhiyun }
5775*4882a593Smuzhiyun 
5776*4882a593Smuzhiyun /**
5777*4882a593Smuzhiyun  *  @brief Private IOCTL entry to get the status of the WMM queues
5778*4882a593Smuzhiyun  *
5779*4882a593Smuzhiyun  *  Return the following information for each WMM AC:
5780*4882a593Smuzhiyun  *        - WMM IE Acm Required
5781*4882a593Smuzhiyun  *        - Firmware Flow Required
5782*4882a593Smuzhiyun  *        - Firmware Flow Established
5783*4882a593Smuzhiyun  *        - Firmware Queue Enabled
5784*4882a593Smuzhiyun  *        - Firmware Delivery Enabled
5785*4882a593Smuzhiyun  *        - Firmware Trigger Enabled
5786*4882a593Smuzhiyun  *
5787*4882a593Smuzhiyun  *  @param priv    Pointer to the moal_private driver data struct
5788*4882a593Smuzhiyun  *  @param wrq     A pointer to iwreq structure containing the
5789*4882a593Smuzhiyun  *                 wlan_ioctl_wmm_queue_status_t struct for request
5790*4882a593Smuzhiyun  *
5791*4882a593Smuzhiyun  *  @return        0 if successful; IOCTL error code otherwise
5792*4882a593Smuzhiyun  */
woal_wmm_queue_status_ioctl(moal_private * priv,struct iwreq * wrq)5793*4882a593Smuzhiyun static int woal_wmm_queue_status_ioctl(moal_private *priv, struct iwreq *wrq)
5794*4882a593Smuzhiyun {
5795*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
5796*4882a593Smuzhiyun 	mlan_ds_wmm_cfg *pwmm = NULL;
5797*4882a593Smuzhiyun 	wlan_ioctl_wmm_queue_status_t qstatus_ioctl;
5798*4882a593Smuzhiyun 	int ret = 0;
5799*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
5800*4882a593Smuzhiyun 
5801*4882a593Smuzhiyun 	ENTER();
5802*4882a593Smuzhiyun 
5803*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
5804*4882a593Smuzhiyun 	if (req == NULL) {
5805*4882a593Smuzhiyun 		ret = -ENOMEM;
5806*4882a593Smuzhiyun 		goto done;
5807*4882a593Smuzhiyun 	}
5808*4882a593Smuzhiyun 
5809*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_WMM_CFG;
5810*4882a593Smuzhiyun 	pwmm = (mlan_ds_wmm_cfg *)req->pbuf;
5811*4882a593Smuzhiyun 	pwmm->sub_command = MLAN_OID_WMM_CFG_QUEUE_STATUS;
5812*4882a593Smuzhiyun 
5813*4882a593Smuzhiyun 	if (wrq->u.data.length == sizeof(qstatus_ioctl)) {
5814*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5815*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
5816*4882a593Smuzhiyun 			ret = -EFAULT;
5817*4882a593Smuzhiyun 			goto done;
5818*4882a593Smuzhiyun 		}
5819*4882a593Smuzhiyun 
5820*4882a593Smuzhiyun 		memset(&qstatus_ioctl, 0x00, sizeof(qstatus_ioctl));
5821*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, (void *)&qstatus_ioctl,
5822*4882a593Smuzhiyun 				(void *)&pwmm->param.q_status,
5823*4882a593Smuzhiyun 				sizeof(qstatus_ioctl), sizeof(qstatus_ioctl));
5824*4882a593Smuzhiyun 		wrq->u.data.length = sizeof(qstatus_ioctl);
5825*4882a593Smuzhiyun 	} else {
5826*4882a593Smuzhiyun 		wrq->u.data.length = 0;
5827*4882a593Smuzhiyun 	}
5828*4882a593Smuzhiyun 
5829*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, &qstatus_ioctl,
5830*4882a593Smuzhiyun 			 wrq->u.data.length)) {
5831*4882a593Smuzhiyun 		PRINTM(MERROR, "QSTATUS: copy to user failed\n");
5832*4882a593Smuzhiyun 		ret = -EFAULT;
5833*4882a593Smuzhiyun 		goto done;
5834*4882a593Smuzhiyun 	}
5835*4882a593Smuzhiyun 
5836*4882a593Smuzhiyun done:
5837*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
5838*4882a593Smuzhiyun 		kfree(req);
5839*4882a593Smuzhiyun 	LEAVE();
5840*4882a593Smuzhiyun 	return ret;
5841*4882a593Smuzhiyun }
5842*4882a593Smuzhiyun 
5843*4882a593Smuzhiyun /**
5844*4882a593Smuzhiyun  *  @brief Private IOCTL entry to get the status of the WMM Traffic Streams
5845*4882a593Smuzhiyun  *
5846*4882a593Smuzhiyun  *  @param priv    Pointer to the moal_private driver data struct
5847*4882a593Smuzhiyun  *  @param wrq     A pointer to iwreq structure containing the
5848*4882a593Smuzhiyun  *                 wlan_ioctl_wmm_ts_status_t struct for request
5849*4882a593Smuzhiyun  *
5850*4882a593Smuzhiyun  *  @return        0 if successful; IOCTL error code otherwise
5851*4882a593Smuzhiyun  */
woal_wmm_ts_status_ioctl(moal_private * priv,struct iwreq * wrq)5852*4882a593Smuzhiyun static int woal_wmm_ts_status_ioctl(moal_private *priv, struct iwreq *wrq)
5853*4882a593Smuzhiyun {
5854*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
5855*4882a593Smuzhiyun 	mlan_ds_wmm_cfg *pwmm = NULL;
5856*4882a593Smuzhiyun 	wlan_ioctl_wmm_ts_status_t ts_status_ioctl;
5857*4882a593Smuzhiyun 	int ret = 0;
5858*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
5859*4882a593Smuzhiyun 
5860*4882a593Smuzhiyun 	ENTER();
5861*4882a593Smuzhiyun 
5862*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg));
5863*4882a593Smuzhiyun 	if (req == NULL) {
5864*4882a593Smuzhiyun 		ret = -ENOMEM;
5865*4882a593Smuzhiyun 		goto done;
5866*4882a593Smuzhiyun 	}
5867*4882a593Smuzhiyun 
5868*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_WMM_CFG;
5869*4882a593Smuzhiyun 	pwmm = (mlan_ds_wmm_cfg *)req->pbuf;
5870*4882a593Smuzhiyun 	pwmm->sub_command = MLAN_OID_WMM_CFG_TS_STATUS;
5871*4882a593Smuzhiyun 
5872*4882a593Smuzhiyun 	memset(&ts_status_ioctl, 0x00, sizeof(ts_status_ioctl));
5873*4882a593Smuzhiyun 
5874*4882a593Smuzhiyun 	if (wrq->u.data.length == sizeof(ts_status_ioctl)) {
5875*4882a593Smuzhiyun 		if (copy_from_user(&ts_status_ioctl, wrq->u.data.pointer,
5876*4882a593Smuzhiyun 				   MIN(wrq->u.data.length,
5877*4882a593Smuzhiyun 				       sizeof(ts_status_ioctl)))) {
5878*4882a593Smuzhiyun 			PRINTM(MERROR, "TS_STATUS: copy from user failed\n");
5879*4882a593Smuzhiyun 			ret = -EFAULT;
5880*4882a593Smuzhiyun 			goto done;
5881*4882a593Smuzhiyun 		}
5882*4882a593Smuzhiyun 
5883*4882a593Smuzhiyun 		memset(&pwmm->param.ts_status, 0x00, sizeof(ts_status_ioctl));
5884*4882a593Smuzhiyun 		pwmm->param.ts_status.tid = ts_status_ioctl.tid;
5885*4882a593Smuzhiyun 
5886*4882a593Smuzhiyun 		status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
5887*4882a593Smuzhiyun 		if (status != MLAN_STATUS_SUCCESS) {
5888*4882a593Smuzhiyun 			ret = -EFAULT;
5889*4882a593Smuzhiyun 			goto done;
5890*4882a593Smuzhiyun 		}
5891*4882a593Smuzhiyun 
5892*4882a593Smuzhiyun 		memset(&ts_status_ioctl, 0x00, sizeof(ts_status_ioctl));
5893*4882a593Smuzhiyun 		moal_memcpy_ext(priv->phandle, (void *)&ts_status_ioctl,
5894*4882a593Smuzhiyun 				(void *)&pwmm->param.ts_status,
5895*4882a593Smuzhiyun 				sizeof(ts_status_ioctl),
5896*4882a593Smuzhiyun 				sizeof(ts_status_ioctl));
5897*4882a593Smuzhiyun 		wrq->u.data.length = sizeof(ts_status_ioctl);
5898*4882a593Smuzhiyun 	} else {
5899*4882a593Smuzhiyun 		wrq->u.data.length = 0;
5900*4882a593Smuzhiyun 	}
5901*4882a593Smuzhiyun 
5902*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, &ts_status_ioctl,
5903*4882a593Smuzhiyun 			 wrq->u.data.length)) {
5904*4882a593Smuzhiyun 		PRINTM(MERROR, "TS_STATUS: copy to user failed\n");
5905*4882a593Smuzhiyun 		ret = -EFAULT;
5906*4882a593Smuzhiyun 		goto done;
5907*4882a593Smuzhiyun 	}
5908*4882a593Smuzhiyun 
5909*4882a593Smuzhiyun done:
5910*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
5911*4882a593Smuzhiyun 		kfree(req);
5912*4882a593Smuzhiyun 	LEAVE();
5913*4882a593Smuzhiyun 	return ret;
5914*4882a593Smuzhiyun }
5915*4882a593Smuzhiyun 
5916*4882a593Smuzhiyun /**
5917*4882a593Smuzhiyun  *  @brief Private IOCTL entry to get the By-passed TX packet from upper layer
5918*4882a593Smuzhiyun  *
5919*4882a593Smuzhiyun  *  @param priv    Pointer to the moal_private driver data struct
5920*4882a593Smuzhiyun  *  @param wrq     A pointer to iwreq structure containing the packet
5921*4882a593Smuzhiyun  *
5922*4882a593Smuzhiyun  *  @return        0 if successful; IOCTL error code otherwise
5923*4882a593Smuzhiyun  */
woal_bypassed_packet_ioctl(moal_private * priv,struct iwreq * wrq)5924*4882a593Smuzhiyun static int woal_bypassed_packet_ioctl(moal_private *priv, struct iwreq *wrq)
5925*4882a593Smuzhiyun {
5926*4882a593Smuzhiyun 	int ret = 0;
5927*4882a593Smuzhiyun 	struct sk_buff *skb = NULL;
5928*4882a593Smuzhiyun 	struct ethhdr *eth;
5929*4882a593Smuzhiyun 	t_u16 moreLen = 0, copyLen = 0;
5930*4882a593Smuzhiyun 	ENTER();
5931*4882a593Smuzhiyun 
5932*4882a593Smuzhiyun #define MLAN_BYPASS_PKT_EXTRA_OFFSET (4)
5933*4882a593Smuzhiyun 
5934*4882a593Smuzhiyun 	copyLen = wrq->u.data.length;
5935*4882a593Smuzhiyun 	moreLen = MLAN_MIN_DATA_HEADER_LEN + MLAN_BYPASS_PKT_EXTRA_OFFSET +
5936*4882a593Smuzhiyun 		  sizeof(mlan_buffer);
5937*4882a593Smuzhiyun 
5938*4882a593Smuzhiyun 	skb = alloc_skb(copyLen + moreLen, GFP_KERNEL);
5939*4882a593Smuzhiyun 	if (skb == NULL) {
5940*4882a593Smuzhiyun 		PRINTM(MERROR, "kmalloc no memory !!\n");
5941*4882a593Smuzhiyun 		LEAVE();
5942*4882a593Smuzhiyun 		return -ENOMEM;
5943*4882a593Smuzhiyun 	}
5944*4882a593Smuzhiyun 
5945*4882a593Smuzhiyun 	skb_reserve(skb, moreLen);
5946*4882a593Smuzhiyun 
5947*4882a593Smuzhiyun 	if (copy_from_user(skb_put(skb, copyLen), wrq->u.data.pointer,
5948*4882a593Smuzhiyun 			   copyLen)) {
5949*4882a593Smuzhiyun 		PRINTM(MERROR, "PortBlock: copy from user failed\n");
5950*4882a593Smuzhiyun 		dev_kfree_skb_any(skb);
5951*4882a593Smuzhiyun 		ret = -EFAULT;
5952*4882a593Smuzhiyun 		goto done;
5953*4882a593Smuzhiyun 	}
5954*4882a593Smuzhiyun 
5955*4882a593Smuzhiyun 	eth = (struct ethhdr *)skb->data;
5956*4882a593Smuzhiyun 	eth->h_proto = __constant_htons(eth->h_proto);
5957*4882a593Smuzhiyun 	skb->dev = priv->netdev;
5958*4882a593Smuzhiyun 
5959*4882a593Smuzhiyun 	HEXDUMP("Bypass TX Data", skb->data, MIN(skb->len, 100));
5960*4882a593Smuzhiyun 
5961*4882a593Smuzhiyun 	woal_hard_start_xmit(skb, priv->netdev);
5962*4882a593Smuzhiyun done:
5963*4882a593Smuzhiyun 	LEAVE();
5964*4882a593Smuzhiyun 	return ret;
5965*4882a593Smuzhiyun }
5966*4882a593Smuzhiyun 
5967*4882a593Smuzhiyun /**
5968*4882a593Smuzhiyun  *  @brief Set/Get auth type
5969*4882a593Smuzhiyun  *
5970*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
5971*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
5972*4882a593Smuzhiyun  *
5973*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
5974*4882a593Smuzhiyun  */
woal_auth_type(moal_private * priv,struct iwreq * wrq)5975*4882a593Smuzhiyun static int woal_auth_type(moal_private *priv, struct iwreq *wrq)
5976*4882a593Smuzhiyun {
5977*4882a593Smuzhiyun 	int auth_type;
5978*4882a593Smuzhiyun 	t_u32 auth_mode;
5979*4882a593Smuzhiyun 	int ret = 0;
5980*4882a593Smuzhiyun 
5981*4882a593Smuzhiyun 	ENTER();
5982*4882a593Smuzhiyun 	if (wrq->u.data.length == 0) {
5983*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS !=
5984*4882a593Smuzhiyun 		    woal_get_auth_mode(priv, MOAL_IOCTL_WAIT, &auth_mode)) {
5985*4882a593Smuzhiyun 			ret = -EFAULT;
5986*4882a593Smuzhiyun 			goto done;
5987*4882a593Smuzhiyun 		}
5988*4882a593Smuzhiyun 		auth_type = auth_mode;
5989*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &auth_type,
5990*4882a593Smuzhiyun 				 sizeof(auth_type))) {
5991*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
5992*4882a593Smuzhiyun 			ret = -EFAULT;
5993*4882a593Smuzhiyun 			goto done;
5994*4882a593Smuzhiyun 		}
5995*4882a593Smuzhiyun 		wrq->u.data.length = 1;
5996*4882a593Smuzhiyun 	} else {
5997*4882a593Smuzhiyun 		if (copy_from_user(&auth_type, wrq->u.data.pointer,
5998*4882a593Smuzhiyun 				   sizeof(auth_type))) {
5999*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
6000*4882a593Smuzhiyun 			ret = -EFAULT;
6001*4882a593Smuzhiyun 			goto done;
6002*4882a593Smuzhiyun 		}
6003*4882a593Smuzhiyun 		PRINTM(MINFO, "SET: auth_type %d\n", auth_type);
6004*4882a593Smuzhiyun 		if (((auth_type < MLAN_AUTH_MODE_OPEN) ||
6005*4882a593Smuzhiyun 		     (auth_type > MLAN_AUTH_MODE_SHARED)) &&
6006*4882a593Smuzhiyun 		    (auth_type != MLAN_AUTH_MODE_AUTO)) {
6007*4882a593Smuzhiyun 			ret = -EINVAL;
6008*4882a593Smuzhiyun 			goto done;
6009*4882a593Smuzhiyun 		}
6010*4882a593Smuzhiyun 		auth_mode = auth_type;
6011*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS !=
6012*4882a593Smuzhiyun 		    woal_set_auth_mode(priv, MOAL_IOCTL_WAIT, auth_mode)) {
6013*4882a593Smuzhiyun 			ret = -EFAULT;
6014*4882a593Smuzhiyun 			goto done;
6015*4882a593Smuzhiyun 		}
6016*4882a593Smuzhiyun 	}
6017*4882a593Smuzhiyun done:
6018*4882a593Smuzhiyun 	LEAVE();
6019*4882a593Smuzhiyun 	return ret;
6020*4882a593Smuzhiyun }
6021*4882a593Smuzhiyun 
6022*4882a593Smuzhiyun /**
6023*4882a593Smuzhiyun  *  @brief Set/Get Port Control mode
6024*4882a593Smuzhiyun  *
6025*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
6026*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
6027*4882a593Smuzhiyun  *
6028*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
6029*4882a593Smuzhiyun  */
woal_port_ctrl(moal_private * priv,struct iwreq * wrq)6030*4882a593Smuzhiyun static int woal_port_ctrl(moal_private *priv, struct iwreq *wrq)
6031*4882a593Smuzhiyun {
6032*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
6033*4882a593Smuzhiyun 	mlan_ds_sec_cfg *sec = NULL;
6034*4882a593Smuzhiyun 	int ret = 0;
6035*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
6036*4882a593Smuzhiyun 	ENTER();
6037*4882a593Smuzhiyun 
6038*4882a593Smuzhiyun 	/* Allocate an IOCTL request buffer */
6039*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
6040*4882a593Smuzhiyun 	if (req == NULL) {
6041*4882a593Smuzhiyun 		ret = -ENOMEM;
6042*4882a593Smuzhiyun 		goto done;
6043*4882a593Smuzhiyun 	}
6044*4882a593Smuzhiyun 
6045*4882a593Smuzhiyun 	/* Fill request buffer */
6046*4882a593Smuzhiyun 	sec = (mlan_ds_sec_cfg *)req->pbuf;
6047*4882a593Smuzhiyun 	sec->sub_command = MLAN_OID_SEC_CFG_PORT_CTRL_ENABLED;
6048*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_SEC_CFG;
6049*4882a593Smuzhiyun 
6050*4882a593Smuzhiyun 	if (wrq->u.data.length) {
6051*4882a593Smuzhiyun 		if (copy_from_user(&sec->param.port_ctrl_enabled,
6052*4882a593Smuzhiyun 				   wrq->u.data.pointer, sizeof(int)) != 0) {
6053*4882a593Smuzhiyun 			PRINTM(MERROR, "port_ctrl:Copy from user failed\n");
6054*4882a593Smuzhiyun 			ret = -EFAULT;
6055*4882a593Smuzhiyun 			goto done;
6056*4882a593Smuzhiyun 		}
6057*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
6058*4882a593Smuzhiyun 	} else {
6059*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
6060*4882a593Smuzhiyun 	}
6061*4882a593Smuzhiyun 
6062*4882a593Smuzhiyun 	/* Send IOCTL request to MLAN */
6063*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6064*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
6065*4882a593Smuzhiyun 		ret = -EFAULT;
6066*4882a593Smuzhiyun 		goto done;
6067*4882a593Smuzhiyun 	}
6068*4882a593Smuzhiyun 
6069*4882a593Smuzhiyun 	if (!wrq->u.data.length) {
6070*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer,
6071*4882a593Smuzhiyun 				 &sec->param.port_ctrl_enabled, sizeof(int))) {
6072*4882a593Smuzhiyun 			PRINTM(MERROR, "port_ctrl:Copy to user failed\n");
6073*4882a593Smuzhiyun 			ret = -EFAULT;
6074*4882a593Smuzhiyun 			goto done;
6075*4882a593Smuzhiyun 		}
6076*4882a593Smuzhiyun 		wrq->u.data.length = 1;
6077*4882a593Smuzhiyun 	}
6078*4882a593Smuzhiyun 
6079*4882a593Smuzhiyun done:
6080*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
6081*4882a593Smuzhiyun 		kfree(req);
6082*4882a593Smuzhiyun 	LEAVE();
6083*4882a593Smuzhiyun 	return ret;
6084*4882a593Smuzhiyun }
6085*4882a593Smuzhiyun 
6086*4882a593Smuzhiyun /**
6087*4882a593Smuzhiyun  *  @brief Set/Get DFS Testing settings
6088*4882a593Smuzhiyun  *
6089*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
6090*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
6091*4882a593Smuzhiyun  *
6092*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
6093*4882a593Smuzhiyun  */
woal_dfs_testing(moal_private * priv,struct iwreq * wrq)6094*4882a593Smuzhiyun static int woal_dfs_testing(moal_private *priv, struct iwreq *wrq)
6095*4882a593Smuzhiyun {
6096*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
6097*4882a593Smuzhiyun 	mlan_ds_11h_cfg *ds_11hcfg = NULL;
6098*4882a593Smuzhiyun 	int ret = 0;
6099*4882a593Smuzhiyun 	int data[4], copy_len;
6100*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
6101*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
6102*4882a593Smuzhiyun 	ENTER();
6103*4882a593Smuzhiyun 
6104*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
6105*4882a593Smuzhiyun 	/* Allocate an IOCTL request buffer */
6106*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
6107*4882a593Smuzhiyun 	if (req == NULL) {
6108*4882a593Smuzhiyun 		ret = -ENOMEM;
6109*4882a593Smuzhiyun 		goto done;
6110*4882a593Smuzhiyun 	}
6111*4882a593Smuzhiyun 
6112*4882a593Smuzhiyun 	/* Fill request buffer */
6113*4882a593Smuzhiyun 	ds_11hcfg = (mlan_ds_11h_cfg *)req->pbuf;
6114*4882a593Smuzhiyun 	ds_11hcfg->sub_command = MLAN_OID_11H_DFS_TESTING;
6115*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_11H_CFG;
6116*4882a593Smuzhiyun 
6117*4882a593Smuzhiyun 	if (!data_length) {
6118*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
6119*4882a593Smuzhiyun 	} else if (data_length == 4) {
6120*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
6121*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
6122*4882a593Smuzhiyun 			ret = -EFAULT;
6123*4882a593Smuzhiyun 			goto done;
6124*4882a593Smuzhiyun 		}
6125*4882a593Smuzhiyun 		if ((unsigned)data[0] > 1800) {
6126*4882a593Smuzhiyun 			PRINTM(MERROR, "The maximum user CAC is 1800 sec.\n");
6127*4882a593Smuzhiyun 			ret = -EINVAL;
6128*4882a593Smuzhiyun 			goto done;
6129*4882a593Smuzhiyun 		}
6130*4882a593Smuzhiyun 		if ((unsigned)data[1] > 0xFFFF) {
6131*4882a593Smuzhiyun 			PRINTM(MERROR, "The maximum user NOP is 65535 sec.\n");
6132*4882a593Smuzhiyun 			ret = -EINVAL;
6133*4882a593Smuzhiyun 			goto done;
6134*4882a593Smuzhiyun 		}
6135*4882a593Smuzhiyun 		if ((unsigned)data[3] > 0xFF) {
6136*4882a593Smuzhiyun 			PRINTM(MERROR,
6137*4882a593Smuzhiyun 			       "The maximum user fixed channel is 255.\n");
6138*4882a593Smuzhiyun 			ret = -EINVAL;
6139*4882a593Smuzhiyun 			goto done;
6140*4882a593Smuzhiyun 		}
6141*4882a593Smuzhiyun 		ds_11hcfg->param.dfs_testing.usr_cac_period_msec =
6142*4882a593Smuzhiyun 			(t_u16)data[0];
6143*4882a593Smuzhiyun 		ds_11hcfg->param.dfs_testing.usr_nop_period_sec =
6144*4882a593Smuzhiyun 			(t_u16)data[1];
6145*4882a593Smuzhiyun 		ds_11hcfg->param.dfs_testing.usr_no_chan_change =
6146*4882a593Smuzhiyun 			data[2] ? 1 : 0;
6147*4882a593Smuzhiyun 		ds_11hcfg->param.dfs_testing.usr_fixed_new_chan = (t_u8)data[3];
6148*4882a593Smuzhiyun 		priv->phandle->cac_period_jiffies = (t_u16)data[0] * HZ;
6149*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
6150*4882a593Smuzhiyun 	} else {
6151*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid number of args!\n");
6152*4882a593Smuzhiyun 		ret = -EINVAL;
6153*4882a593Smuzhiyun 		goto done;
6154*4882a593Smuzhiyun 	}
6155*4882a593Smuzhiyun 
6156*4882a593Smuzhiyun 	/* Send IOCTL request to MLAN */
6157*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6158*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
6159*4882a593Smuzhiyun 		ret = -EFAULT;
6160*4882a593Smuzhiyun 		goto done;
6161*4882a593Smuzhiyun 	}
6162*4882a593Smuzhiyun 
6163*4882a593Smuzhiyun 	if (!data_length) {
6164*4882a593Smuzhiyun 		data[0] = ds_11hcfg->param.dfs_testing.usr_cac_period_msec;
6165*4882a593Smuzhiyun 		data[1] = ds_11hcfg->param.dfs_testing.usr_nop_period_sec;
6166*4882a593Smuzhiyun 		data[2] = ds_11hcfg->param.dfs_testing.usr_no_chan_change;
6167*4882a593Smuzhiyun 		data[3] = ds_11hcfg->param.dfs_testing.usr_fixed_new_chan;
6168*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int) * 4)) {
6169*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
6170*4882a593Smuzhiyun 			ret = -EFAULT;
6171*4882a593Smuzhiyun 			goto done;
6172*4882a593Smuzhiyun 		}
6173*4882a593Smuzhiyun 		wrq->u.data.length = 4;
6174*4882a593Smuzhiyun 	}
6175*4882a593Smuzhiyun 
6176*4882a593Smuzhiyun done:
6177*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
6178*4882a593Smuzhiyun 		kfree(req);
6179*4882a593Smuzhiyun 	LEAVE();
6180*4882a593Smuzhiyun 	return ret;
6181*4882a593Smuzhiyun }
6182*4882a593Smuzhiyun 
6183*4882a593Smuzhiyun /**
6184*4882a593Smuzhiyun  *  @brief Set/Get Mgmt Frame passthru mask
6185*4882a593Smuzhiyun  *
6186*4882a593Smuzhiyun  *  @param priv     A pointer to moal_private structure
6187*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
6188*4882a593Smuzhiyun  *
6189*4882a593Smuzhiyun  *  @return         0 -- success, otherwise fail
6190*4882a593Smuzhiyun  */
woal_mgmt_frame_passthru_ctrl(moal_private * priv,struct iwreq * wrq)6191*4882a593Smuzhiyun static int woal_mgmt_frame_passthru_ctrl(moal_private *priv, struct iwreq *wrq)
6192*4882a593Smuzhiyun {
6193*4882a593Smuzhiyun 	int ret = 0, data_length = wrq->u.data.length;
6194*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
6195*4882a593Smuzhiyun 	mlan_ds_misc_cfg *mgmt_cfg = NULL;
6196*4882a593Smuzhiyun 	int mask = 0;
6197*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
6198*4882a593Smuzhiyun 
6199*4882a593Smuzhiyun 	ENTER();
6200*4882a593Smuzhiyun 
6201*4882a593Smuzhiyun 	if (data_length > 1) {
6202*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid no of arguments!\n");
6203*4882a593Smuzhiyun 		ret = -EINVAL;
6204*4882a593Smuzhiyun 		goto done;
6205*4882a593Smuzhiyun 	}
6206*4882a593Smuzhiyun 	/* Allocate an IOCTL request buffer */
6207*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
6208*4882a593Smuzhiyun 	if (req == NULL) {
6209*4882a593Smuzhiyun 		ret = -ENOMEM;
6210*4882a593Smuzhiyun 		goto done;
6211*4882a593Smuzhiyun 	}
6212*4882a593Smuzhiyun 
6213*4882a593Smuzhiyun 	/* Fill request buffer */
6214*4882a593Smuzhiyun 	mgmt_cfg = (mlan_ds_misc_cfg *)req->pbuf;
6215*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_MISC_CFG;
6216*4882a593Smuzhiyun 	mgmt_cfg->sub_command = MLAN_OID_MISC_RX_MGMT_IND;
6217*4882a593Smuzhiyun 
6218*4882a593Smuzhiyun 	if (data_length) { /* SET */
6219*4882a593Smuzhiyun 		if (copy_from_user(&mask, wrq->u.data.pointer, sizeof(int))) {
6220*4882a593Smuzhiyun 			PRINTM(MERROR, "copy from user failed\n");
6221*4882a593Smuzhiyun 			ret = -EFAULT;
6222*4882a593Smuzhiyun 			goto done;
6223*4882a593Smuzhiyun 		}
6224*4882a593Smuzhiyun 		mgmt_cfg->param.mgmt_subtype_mask = mask;
6225*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
6226*4882a593Smuzhiyun 	} else {
6227*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
6228*4882a593Smuzhiyun 	}
6229*4882a593Smuzhiyun 
6230*4882a593Smuzhiyun 	/* Send IOCTL request to MLAN */
6231*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6232*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
6233*4882a593Smuzhiyun 		ret = -EFAULT;
6234*4882a593Smuzhiyun 		goto done;
6235*4882a593Smuzhiyun 	}
6236*4882a593Smuzhiyun 
6237*4882a593Smuzhiyun 	mask = mgmt_cfg->param.mgmt_subtype_mask;
6238*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, &mask, sizeof(int))) {
6239*4882a593Smuzhiyun 		ret = -EFAULT;
6240*4882a593Smuzhiyun 		goto done;
6241*4882a593Smuzhiyun 	}
6242*4882a593Smuzhiyun 	wrq->u.data.length = 1;
6243*4882a593Smuzhiyun 
6244*4882a593Smuzhiyun done:
6245*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
6246*4882a593Smuzhiyun 		kfree(req);
6247*4882a593Smuzhiyun 	LEAVE();
6248*4882a593Smuzhiyun 	return ret;
6249*4882a593Smuzhiyun }
6250*4882a593Smuzhiyun 
6251*4882a593Smuzhiyun /**
6252*4882a593Smuzhiyun  *  @brief Set/Get CFP table codes
6253*4882a593Smuzhiyun  *
6254*4882a593Smuzhiyun  *  @param priv     Pointer to the moal_private driver data struct
6255*4882a593Smuzhiyun  *  @param wrq      A pointer to iwreq structure
6256*4882a593Smuzhiyun  *
6257*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
6258*4882a593Smuzhiyun  */
woal_cfp_code(moal_private * priv,struct iwreq * wrq)6259*4882a593Smuzhiyun static int woal_cfp_code(moal_private *priv, struct iwreq *wrq)
6260*4882a593Smuzhiyun {
6261*4882a593Smuzhiyun 	int ret = 0;
6262*4882a593Smuzhiyun 	int data[2], copy_len;
6263*4882a593Smuzhiyun 	int data_length = wrq->u.data.length;
6264*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
6265*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc_cfg = NULL;
6266*4882a593Smuzhiyun 	mlan_ds_misc_cfp_code *cfp_code = NULL;
6267*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
6268*4882a593Smuzhiyun 
6269*4882a593Smuzhiyun 	ENTER();
6270*4882a593Smuzhiyun 
6271*4882a593Smuzhiyun 	if (data_length > 2) {
6272*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid number of argument!\n");
6273*4882a593Smuzhiyun 		ret = -EINVAL;
6274*4882a593Smuzhiyun 		goto done;
6275*4882a593Smuzhiyun 	}
6276*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
6277*4882a593Smuzhiyun 
6278*4882a593Smuzhiyun 	/* Allocate an IOCTL request buffer */
6279*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
6280*4882a593Smuzhiyun 	if (req == NULL) {
6281*4882a593Smuzhiyun 		ret = -ENOMEM;
6282*4882a593Smuzhiyun 		goto done;
6283*4882a593Smuzhiyun 	}
6284*4882a593Smuzhiyun 
6285*4882a593Smuzhiyun 	/* Fill request buffer */
6286*4882a593Smuzhiyun 	misc_cfg = (mlan_ds_misc_cfg *)req->pbuf;
6287*4882a593Smuzhiyun 	cfp_code = &misc_cfg->param.cfp_code;
6288*4882a593Smuzhiyun 	misc_cfg->sub_command = MLAN_OID_MISC_CFP_CODE;
6289*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_MISC_CFG;
6290*4882a593Smuzhiyun 
6291*4882a593Smuzhiyun 	if (!data_length) {
6292*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
6293*4882a593Smuzhiyun 	} else {
6294*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
6295*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
6296*4882a593Smuzhiyun 			ret = -EFAULT;
6297*4882a593Smuzhiyun 			goto done;
6298*4882a593Smuzhiyun 		}
6299*4882a593Smuzhiyun 		cfp_code->cfp_code_bg = data[0];
6300*4882a593Smuzhiyun 		if (data_length == 2)
6301*4882a593Smuzhiyun 			cfp_code->cfp_code_a = data[1];
6302*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
6303*4882a593Smuzhiyun 	}
6304*4882a593Smuzhiyun 
6305*4882a593Smuzhiyun 	/* Send IOCTL request to MLAN */
6306*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6307*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
6308*4882a593Smuzhiyun 		ret = -EFAULT;
6309*4882a593Smuzhiyun 		goto done;
6310*4882a593Smuzhiyun 	}
6311*4882a593Smuzhiyun 
6312*4882a593Smuzhiyun 	if (!data_length) {
6313*4882a593Smuzhiyun 		data[0] = cfp_code->cfp_code_bg;
6314*4882a593Smuzhiyun 		data[1] = cfp_code->cfp_code_a;
6315*4882a593Smuzhiyun 		data_length = 2;
6316*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, &data,
6317*4882a593Smuzhiyun 				 sizeof(int) * data_length)) {
6318*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy to user failed\n");
6319*4882a593Smuzhiyun 			ret = -EFAULT;
6320*4882a593Smuzhiyun 			goto done;
6321*4882a593Smuzhiyun 		}
6322*4882a593Smuzhiyun 		wrq->u.data.length = data_length;
6323*4882a593Smuzhiyun 	}
6324*4882a593Smuzhiyun 
6325*4882a593Smuzhiyun done:
6326*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
6327*4882a593Smuzhiyun 		kfree(req);
6328*4882a593Smuzhiyun 	LEAVE();
6329*4882a593Smuzhiyun 	return ret;
6330*4882a593Smuzhiyun }
6331*4882a593Smuzhiyun 
6332*4882a593Smuzhiyun /**
6333*4882a593Smuzhiyun  * @brief Set/Get Tx/Rx antenna
6334*4882a593Smuzhiyun  *
6335*4882a593Smuzhiyun  * @param priv     A pointer to moal_private structure
6336*4882a593Smuzhiyun  * @param wrq      A pointer to iwreq structure
6337*4882a593Smuzhiyun  *
6338*4882a593Smuzhiyun  * @return         0 --success, otherwise fail
6339*4882a593Smuzhiyun  */
woal_set_get_tx_rx_ant(moal_private * priv,struct iwreq * wrq)6340*4882a593Smuzhiyun static int woal_set_get_tx_rx_ant(moal_private *priv, struct iwreq *wrq)
6341*4882a593Smuzhiyun {
6342*4882a593Smuzhiyun 	int ret = 0;
6343*4882a593Smuzhiyun 	mlan_ds_radio_cfg *radio = NULL;
6344*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
6345*4882a593Smuzhiyun 	int data[3] = {0};
6346*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
6347*4882a593Smuzhiyun 	int copy_len;
6348*4882a593Smuzhiyun 
6349*4882a593Smuzhiyun 	ENTER();
6350*4882a593Smuzhiyun 
6351*4882a593Smuzhiyun 	if (wrq->u.data.length > 2) {
6352*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid number of argument!\n");
6353*4882a593Smuzhiyun 		ret = -EFAULT;
6354*4882a593Smuzhiyun 		goto done;
6355*4882a593Smuzhiyun 	}
6356*4882a593Smuzhiyun 	if (wrq->u.data.length * sizeof(int) > sizeof(data)) {
6357*4882a593Smuzhiyun 		PRINTM(MERROR, "Too many arguments\n");
6358*4882a593Smuzhiyun 		ret = -EFAULT;
6359*4882a593Smuzhiyun 		goto done;
6360*4882a593Smuzhiyun 	}
6361*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), wrq->u.data.length * sizeof(int));
6362*4882a593Smuzhiyun 
6363*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
6364*4882a593Smuzhiyun 	if (req == NULL) {
6365*4882a593Smuzhiyun 		ret = -ENOMEM;
6366*4882a593Smuzhiyun 		goto done;
6367*4882a593Smuzhiyun 	}
6368*4882a593Smuzhiyun 	radio = (mlan_ds_radio_cfg *)req->pbuf;
6369*4882a593Smuzhiyun 	radio->sub_command = MLAN_OID_ANT_CFG;
6370*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_RADIO_CFG;
6371*4882a593Smuzhiyun 	if (wrq->u.data.length) {
6372*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
6373*4882a593Smuzhiyun 			PRINTM(MERROR, "Copy from user failed\n");
6374*4882a593Smuzhiyun 			ret = -EFAULT;
6375*4882a593Smuzhiyun 			goto done;
6376*4882a593Smuzhiyun 		}
6377*4882a593Smuzhiyun 
6378*4882a593Smuzhiyun 		if (priv->phandle->feature_control & FEATURE_CTRL_STREAM_2X2) {
6379*4882a593Smuzhiyun 			radio->param.ant_cfg.tx_antenna = data[0];
6380*4882a593Smuzhiyun 			radio->param.ant_cfg.rx_antenna = data[0];
6381*4882a593Smuzhiyun 			if (wrq->u.data.length == 2)
6382*4882a593Smuzhiyun 				radio->param.ant_cfg.rx_antenna = data[1];
6383*4882a593Smuzhiyun 		} else {
6384*4882a593Smuzhiyun 			radio->param.ant_cfg_1x1.antenna = data[0];
6385*4882a593Smuzhiyun 			if (wrq->u.data.length == 2)
6386*4882a593Smuzhiyun 				radio->param.ant_cfg_1x1.evaluate_time =
6387*4882a593Smuzhiyun 					data[1];
6388*4882a593Smuzhiyun 		}
6389*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
6390*4882a593Smuzhiyun 	} else
6391*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
6392*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6393*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
6394*4882a593Smuzhiyun 		ret = -EFAULT;
6395*4882a593Smuzhiyun 		goto done;
6396*4882a593Smuzhiyun 	}
6397*4882a593Smuzhiyun 	if (!wrq->u.data.length) {
6398*4882a593Smuzhiyun 		wrq->u.data.length = 1;
6399*4882a593Smuzhiyun 		if (priv->phandle->feature_control & FEATURE_CTRL_STREAM_2X2) {
6400*4882a593Smuzhiyun 			data[0] = radio->param.ant_cfg.tx_antenna;
6401*4882a593Smuzhiyun 			data[1] = radio->param.ant_cfg.rx_antenna;
6402*4882a593Smuzhiyun 			if (data[0] && data[1] && (data[0] != data[1]))
6403*4882a593Smuzhiyun 				wrq->u.data.length = 2;
6404*4882a593Smuzhiyun 		} else {
6405*4882a593Smuzhiyun 			data[0] = (int)radio->param.ant_cfg_1x1.antenna;
6406*4882a593Smuzhiyun 			data[1] = (int)radio->param.ant_cfg_1x1.evaluate_time;
6407*4882a593Smuzhiyun 			data[2] = (int)radio->param.ant_cfg_1x1.current_antenna;
6408*4882a593Smuzhiyun 			if (data[0] == 0xffff && data[2] > 0)
6409*4882a593Smuzhiyun 				wrq->u.data.length = 3;
6410*4882a593Smuzhiyun 			else if (data[0] == 0xffff)
6411*4882a593Smuzhiyun 				wrq->u.data.length = 2;
6412*4882a593Smuzhiyun 		}
6413*4882a593Smuzhiyun 		if (copy_to_user(wrq->u.data.pointer, data,
6414*4882a593Smuzhiyun 				 wrq->u.data.length * sizeof(int))) {
6415*4882a593Smuzhiyun 			ret = -EFAULT;
6416*4882a593Smuzhiyun 			goto done;
6417*4882a593Smuzhiyun 		}
6418*4882a593Smuzhiyun 	}
6419*4882a593Smuzhiyun done:
6420*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
6421*4882a593Smuzhiyun 		kfree(req);
6422*4882a593Smuzhiyun 	LEAVE();
6423*4882a593Smuzhiyun 	return ret;
6424*4882a593Smuzhiyun }
6425*4882a593Smuzhiyun 
6426*4882a593Smuzhiyun /**
6427*4882a593Smuzhiyun  * @brief Configure gpio independent reset
6428*4882a593Smuzhiyun  *
6429*4882a593Smuzhiyun  * @param priv         A pointer to moal_private structure
6430*4882a593Smuzhiyun  * @param req          A pointer to ifreq structure
6431*4882a593Smuzhiyun  *
6432*4882a593Smuzhiyun  * @return             0 --success, otherwise fail
6433*4882a593Smuzhiyun  */
woal_ind_rst_ioctl(moal_private * priv,struct iwreq * wrq)6434*4882a593Smuzhiyun static int woal_ind_rst_ioctl(moal_private *priv, struct iwreq *wrq)
6435*4882a593Smuzhiyun {
6436*4882a593Smuzhiyun 	int data[2], data_length = wrq->u.data.length, copy_len;
6437*4882a593Smuzhiyun 	int ret = 0;
6438*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = NULL;
6439*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
6440*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
6441*4882a593Smuzhiyun 
6442*4882a593Smuzhiyun 	ENTER();
6443*4882a593Smuzhiyun 
6444*4882a593Smuzhiyun 	if (sizeof(int) * wrq->u.data.length > sizeof(data)) {
6445*4882a593Smuzhiyun 		PRINTM(MERROR, "Too many arguments\n");
6446*4882a593Smuzhiyun 		ret = -EINVAL;
6447*4882a593Smuzhiyun 		goto done;
6448*4882a593Smuzhiyun 	}
6449*4882a593Smuzhiyun 	copy_len = MIN(sizeof(data), sizeof(int) * data_length);
6450*4882a593Smuzhiyun 
6451*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
6452*4882a593Smuzhiyun 	if (req == NULL) {
6453*4882a593Smuzhiyun 		ret = -ENOMEM;
6454*4882a593Smuzhiyun 		goto done;
6455*4882a593Smuzhiyun 	}
6456*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)req->pbuf;
6457*4882a593Smuzhiyun 	memset(misc, 0, sizeof(mlan_ds_misc_cfg));
6458*4882a593Smuzhiyun 
6459*4882a593Smuzhiyun 	misc->sub_command = MLAN_OID_MISC_IND_RST_CFG;
6460*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_MISC_CFG;
6461*4882a593Smuzhiyun 
6462*4882a593Smuzhiyun 	if (data_length == 0) {
6463*4882a593Smuzhiyun 		req->action = MLAN_ACT_GET;
6464*4882a593Smuzhiyun 	} else if ((data_length == 1) || (data_length == 2)) {
6465*4882a593Smuzhiyun 		req->action = MLAN_ACT_SET;
6466*4882a593Smuzhiyun 
6467*4882a593Smuzhiyun 		if (copy_from_user(data, wrq->u.data.pointer, copy_len)) {
6468*4882a593Smuzhiyun 			/* copy_from_user failed  */
6469*4882a593Smuzhiyun 			PRINTM(MERROR, "S_PARAMS: copy from user failed\n");
6470*4882a593Smuzhiyun 			ret = -EINVAL;
6471*4882a593Smuzhiyun 			goto done;
6472*4882a593Smuzhiyun 		}
6473*4882a593Smuzhiyun 
6474*4882a593Smuzhiyun 		/* ir_mode */
6475*4882a593Smuzhiyun 		if (data[0] < 0 || data[0] > 2) {
6476*4882a593Smuzhiyun 			PRINTM(MERROR, "Invalid ir mode parameter (0/1/2)!\n");
6477*4882a593Smuzhiyun 			ret = -EINVAL;
6478*4882a593Smuzhiyun 			goto done;
6479*4882a593Smuzhiyun 		}
6480*4882a593Smuzhiyun 		misc->param.ind_rst_cfg.ir_mode = data[0];
6481*4882a593Smuzhiyun 
6482*4882a593Smuzhiyun 		/* gpio_pin */
6483*4882a593Smuzhiyun 		if (data_length == 2) {
6484*4882a593Smuzhiyun 			if ((data[1] != 0xFF) && (data[1] < 0)) {
6485*4882a593Smuzhiyun 				PRINTM(MERROR, "Invalid gpio pin no !\n");
6486*4882a593Smuzhiyun 				ret = -EINVAL;
6487*4882a593Smuzhiyun 				goto done;
6488*4882a593Smuzhiyun 			}
6489*4882a593Smuzhiyun 			misc->param.ind_rst_cfg.gpio_pin = data[1];
6490*4882a593Smuzhiyun 		}
6491*4882a593Smuzhiyun 
6492*4882a593Smuzhiyun 	} else {
6493*4882a593Smuzhiyun 		ret = -EINVAL;
6494*4882a593Smuzhiyun 		goto done;
6495*4882a593Smuzhiyun 	}
6496*4882a593Smuzhiyun 
6497*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
6498*4882a593Smuzhiyun 	if (status != MLAN_STATUS_SUCCESS) {
6499*4882a593Smuzhiyun 		ret = -EFAULT;
6500*4882a593Smuzhiyun 		goto done;
6501*4882a593Smuzhiyun 	}
6502*4882a593Smuzhiyun 
6503*4882a593Smuzhiyun 	data[0] = misc->param.ind_rst_cfg.ir_mode;
6504*4882a593Smuzhiyun 	data[1] = misc->param.ind_rst_cfg.gpio_pin;
6505*4882a593Smuzhiyun 	wrq->u.data.length = 2;
6506*4882a593Smuzhiyun 
6507*4882a593Smuzhiyun 	if (copy_to_user(wrq->u.data.pointer, data,
6508*4882a593Smuzhiyun 			 sizeof(int) * wrq->u.data.length)) {
6509*4882a593Smuzhiyun 		PRINTM(MERROR, "QCONFIG: copy to user failed\n");
6510*4882a593Smuzhiyun 		ret = -EFAULT;
6511*4882a593Smuzhiyun 		goto done;
6512*4882a593Smuzhiyun 	}
6513*4882a593Smuzhiyun 
6514*4882a593Smuzhiyun done:
6515*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
6516*4882a593Smuzhiyun 		kfree(req);
6517*4882a593Smuzhiyun 	LEAVE();
6518*4882a593Smuzhiyun 	return ret;
6519*4882a593Smuzhiyun }
6520*4882a593Smuzhiyun 
6521*4882a593Smuzhiyun /********************************************************
6522*4882a593Smuzhiyun 			Global Functions
6523*4882a593Smuzhiyun ********************************************************/
6524*4882a593Smuzhiyun /**
6525*4882a593Smuzhiyun  *  @brief ioctl function - entry point
6526*4882a593Smuzhiyun  *
6527*4882a593Smuzhiyun  *  @param dev      A pointer to net_device structure
6528*4882a593Smuzhiyun  *  @param req      A pointer to ifreq structure
6529*4882a593Smuzhiyun  *  @param cmd      Command
6530*4882a593Smuzhiyun  *
6531*4882a593Smuzhiyun  *  @return         0 --success, otherwise fail
6532*4882a593Smuzhiyun  */
woal_wext_do_ioctl(struct net_device * dev,struct ifreq * req,int cmd)6533*4882a593Smuzhiyun int woal_wext_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
6534*4882a593Smuzhiyun {
6535*4882a593Smuzhiyun 	moal_private *priv = (moal_private *)netdev_priv(dev);
6536*4882a593Smuzhiyun 	struct iwreq *wrq = (struct iwreq *)req;
6537*4882a593Smuzhiyun 	int ret = 0;
6538*4882a593Smuzhiyun 
6539*4882a593Smuzhiyun 	if (!IS_STA_WEXT(priv->phandle->params.cfg80211_wext))
6540*4882a593Smuzhiyun 		return -EOPNOTSUPP;
6541*4882a593Smuzhiyun 
6542*4882a593Smuzhiyun 	ENTER();
6543*4882a593Smuzhiyun 
6544*4882a593Smuzhiyun 	PRINTM(MINFO, "woal_wext_do_ioctl: ioctl cmd = 0x%x\n", cmd);
6545*4882a593Smuzhiyun 	switch (cmd) {
6546*4882a593Smuzhiyun 	case WOAL_SETONEINT_GETWORDCHAR:
6547*4882a593Smuzhiyun 		switch (wrq->u.data.flags) {
6548*4882a593Smuzhiyun 		case WOAL_VERSION: /* Get driver version */
6549*4882a593Smuzhiyun 			ret = woal_get_driver_version(priv, req);
6550*4882a593Smuzhiyun 			break;
6551*4882a593Smuzhiyun 		case WOAL_VEREXT: /* Get extended driver version */
6552*4882a593Smuzhiyun 			ret = woal_get_driver_verext(priv, req);
6553*4882a593Smuzhiyun 			break;
6554*4882a593Smuzhiyun 		default:
6555*4882a593Smuzhiyun 			ret = -EOPNOTSUPP;
6556*4882a593Smuzhiyun 			break;
6557*4882a593Smuzhiyun 		}
6558*4882a593Smuzhiyun 		break;
6559*4882a593Smuzhiyun 	case WOAL_SETNONE_GETNONE:
6560*4882a593Smuzhiyun 		switch (wrq->u.data.flags) {
6561*4882a593Smuzhiyun 		case WOAL_WARMRESET:
6562*4882a593Smuzhiyun 			ret = woal_warm_reset(priv);
6563*4882a593Smuzhiyun 			break;
6564*4882a593Smuzhiyun #ifdef USB
6565*4882a593Smuzhiyun #ifdef CONFIG_USB_SUSPEND
6566*4882a593Smuzhiyun 		case WOAL_USB_SUSPEND:
6567*4882a593Smuzhiyun 			ret = woal_enter_usb_suspend(priv->phandle);
6568*4882a593Smuzhiyun 			break;
6569*4882a593Smuzhiyun 		case WOAL_USB_RESUME:
6570*4882a593Smuzhiyun 			ret = woal_exit_usb_suspend(priv->phandle);
6571*4882a593Smuzhiyun 			break;
6572*4882a593Smuzhiyun #endif /* CONFIG_USB_SUSPEND */
6573*4882a593Smuzhiyun #endif
6574*4882a593Smuzhiyun 		case WOAL_11D_CLR_CHAN_TABLE:
6575*4882a593Smuzhiyun 			ret = woal_11d_clr_chan_table(priv, wrq);
6576*4882a593Smuzhiyun 			break;
6577*4882a593Smuzhiyun 		default:
6578*4882a593Smuzhiyun 			ret = -EOPNOTSUPP;
6579*4882a593Smuzhiyun 			break;
6580*4882a593Smuzhiyun 		}
6581*4882a593Smuzhiyun 		break;
6582*4882a593Smuzhiyun 	case WOAL_SETONEINT_GETONEINT:
6583*4882a593Smuzhiyun 		switch (wrq->u.data.flags) {
6584*4882a593Smuzhiyun 		case WOAL_SET_GET_TXRATE:
6585*4882a593Smuzhiyun 			ret = woal_set_get_txrate(priv, wrq);
6586*4882a593Smuzhiyun 			break;
6587*4882a593Smuzhiyun 		case WOAL_SET_GET_REGIONCODE:
6588*4882a593Smuzhiyun 			ret = woal_set_get_regioncode(priv, wrq);
6589*4882a593Smuzhiyun 			break;
6590*4882a593Smuzhiyun 		case WOAL_SET_RADIO:
6591*4882a593Smuzhiyun 			ret = woal_set_get_radio(priv, wrq);
6592*4882a593Smuzhiyun 			break;
6593*4882a593Smuzhiyun 		case WOAL_WMM_ENABLE:
6594*4882a593Smuzhiyun 			ret = woal_wmm_enable_ioctl(priv, wrq);
6595*4882a593Smuzhiyun 			break;
6596*4882a593Smuzhiyun 		case WOAL_11D_ENABLE:
6597*4882a593Smuzhiyun 			ret = woal_11d_enable_ioctl(priv, wrq);
6598*4882a593Smuzhiyun 			break;
6599*4882a593Smuzhiyun 		case WOAL_SET_GET_QOS_CFG:
6600*4882a593Smuzhiyun 			ret = woal_set_get_qos_cfg(priv, wrq);
6601*4882a593Smuzhiyun 			break;
6602*4882a593Smuzhiyun #if defined(REASSOCIATION)
6603*4882a593Smuzhiyun 		case WOAL_SET_GET_REASSOC:
6604*4882a593Smuzhiyun 			ret = woal_set_get_reassoc(priv, wrq);
6605*4882a593Smuzhiyun 			break;
6606*4882a593Smuzhiyun #endif /* REASSOCIATION */
6607*4882a593Smuzhiyun 		case WOAL_TXBUF_CFG:
6608*4882a593Smuzhiyun 			ret = woal_txbuf_cfg(priv, wrq);
6609*4882a593Smuzhiyun 			break;
6610*4882a593Smuzhiyun #ifndef OPCHAN
6611*4882a593Smuzhiyun 		case WOAL_SET_GET_WWS_CFG:
6612*4882a593Smuzhiyun 			ret = woal_wws_cfg(priv, wrq);
6613*4882a593Smuzhiyun 			break;
6614*4882a593Smuzhiyun #endif
6615*4882a593Smuzhiyun 		case WOAL_SLEEP_PD:
6616*4882a593Smuzhiyun 			ret = woal_sleep_pd(priv, wrq);
6617*4882a593Smuzhiyun 			break;
6618*4882a593Smuzhiyun 		case WOAL_AUTH_TYPE:
6619*4882a593Smuzhiyun 			ret = woal_auth_type(priv, wrq);
6620*4882a593Smuzhiyun 			break;
6621*4882a593Smuzhiyun 		case WOAL_PORT_CTRL:
6622*4882a593Smuzhiyun 			ret = woal_port_ctrl(priv, wrq);
6623*4882a593Smuzhiyun 			break;
6624*4882a593Smuzhiyun #ifdef WIFI_DIRECT_SUPPORT
6625*4882a593Smuzhiyun #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
6626*4882a593Smuzhiyun 		case WOAL_SET_GET_BSS_ROLE:
6627*4882a593Smuzhiyun 			ret = woal_set_get_bss_role(priv, wrq);
6628*4882a593Smuzhiyun 			break;
6629*4882a593Smuzhiyun #endif
6630*4882a593Smuzhiyun #endif
6631*4882a593Smuzhiyun 		case WOAL_SET_GET_11H_LOCAL_PWR_CONSTRAINT:
6632*4882a593Smuzhiyun 			ret = woal_set_get_11h_local_pwr_constraint(priv, wrq);
6633*4882a593Smuzhiyun 			break;
6634*4882a593Smuzhiyun 		case WOAL_HT_STREAM_CFG:
6635*4882a593Smuzhiyun 			ret = woal_ht_stream_cfg_ioctl(priv, wrq);
6636*4882a593Smuzhiyun 			break;
6637*4882a593Smuzhiyun 		case WOAL_MAC_CONTROL:
6638*4882a593Smuzhiyun 			ret = woal_mac_control_ioctl(priv, wrq);
6639*4882a593Smuzhiyun 			break;
6640*4882a593Smuzhiyun 		case WOAL_THERMAL:
6641*4882a593Smuzhiyun 			ret = woal_thermal_ioctl(priv, wrq);
6642*4882a593Smuzhiyun 			break;
6643*4882a593Smuzhiyun 		case WOAL_CFG_HOTSPOT:
6644*4882a593Smuzhiyun 			ret = woal_cfg_hotspot(priv, wrq);
6645*4882a593Smuzhiyun 			break;
6646*4882a593Smuzhiyun 		default:
6647*4882a593Smuzhiyun 			ret = -EOPNOTSUPP;
6648*4882a593Smuzhiyun 			break;
6649*4882a593Smuzhiyun 		}
6650*4882a593Smuzhiyun 		break;
6651*4882a593Smuzhiyun 
6652*4882a593Smuzhiyun 	case WOAL_SET_GET_SIXTEEN_INT:
6653*4882a593Smuzhiyun 		switch ((int)wrq->u.data.flags) {
6654*4882a593Smuzhiyun 		case WOAL_TX_POWERCFG:
6655*4882a593Smuzhiyun 			ret = woal_tx_power_cfg(priv, wrq);
6656*4882a593Smuzhiyun 			break;
6657*4882a593Smuzhiyun #ifdef DEBUG_LEVEL1
6658*4882a593Smuzhiyun 		case WOAL_DRV_DBG:
6659*4882a593Smuzhiyun 			ret = woal_drv_dbg(priv, wrq);
6660*4882a593Smuzhiyun 			break;
6661*4882a593Smuzhiyun #endif
6662*4882a593Smuzhiyun 		case WOAL_BEACON_INTERVAL:
6663*4882a593Smuzhiyun 			ret = woal_beacon_interval(priv, wrq);
6664*4882a593Smuzhiyun 			break;
6665*4882a593Smuzhiyun 		case WOAL_SIGNAL:
6666*4882a593Smuzhiyun 			ret = woal_get_signal(priv, wrq);
6667*4882a593Smuzhiyun 			break;
6668*4882a593Smuzhiyun 		case WOAL_DEEP_SLEEP:
6669*4882a593Smuzhiyun 			ret = woal_deep_sleep_ioctl(priv, wrq);
6670*4882a593Smuzhiyun 			break;
6671*4882a593Smuzhiyun 		case WOAL_11N_TX_CFG:
6672*4882a593Smuzhiyun 			ret = woal_11n_tx_cfg(priv, wrq);
6673*4882a593Smuzhiyun 			break;
6674*4882a593Smuzhiyun 		case WOAL_11N_AMSDU_AGGR_CTRL:
6675*4882a593Smuzhiyun 			ret = woal_11n_amsdu_aggr_ctrl(priv, wrq);
6676*4882a593Smuzhiyun 			break;
6677*4882a593Smuzhiyun 		case WOAL_11N_HTCAP_CFG:
6678*4882a593Smuzhiyun 			ret = woal_11n_htcap_cfg(priv, wrq);
6679*4882a593Smuzhiyun 			break;
6680*4882a593Smuzhiyun 		case WOAL_PRIO_TBL:
6681*4882a593Smuzhiyun 			ret = woal_11n_prio_tbl(priv, wrq);
6682*4882a593Smuzhiyun 			break;
6683*4882a593Smuzhiyun 		case WOAL_ADDBA_UPDT:
6684*4882a593Smuzhiyun 			ret = woal_addba_para_updt(priv, wrq);
6685*4882a593Smuzhiyun 			break;
6686*4882a593Smuzhiyun 		case WOAL_ADDBA_REJECT:
6687*4882a593Smuzhiyun 			ret = woal_addba_reject(priv, wrq);
6688*4882a593Smuzhiyun 			break;
6689*4882a593Smuzhiyun 		case WOAL_TX_BF_CAP:
6690*4882a593Smuzhiyun 			ret = woal_tx_bf_cap_ioctl(priv, wrq);
6691*4882a593Smuzhiyun 			break;
6692*4882a593Smuzhiyun 		case WOAL_HS_CFG:
6693*4882a593Smuzhiyun 			ret = woal_hs_cfg(priv, wrq, MTRUE);
6694*4882a593Smuzhiyun 			break;
6695*4882a593Smuzhiyun 		case WOAL_HS_SETPARA:
6696*4882a593Smuzhiyun 			ret = woal_hs_setpara(priv, wrq);
6697*4882a593Smuzhiyun 			break;
6698*4882a593Smuzhiyun 		case WOAL_REG_READ_WRITE:
6699*4882a593Smuzhiyun 			ret = woal_reg_read_write(priv, wrq);
6700*4882a593Smuzhiyun 			break;
6701*4882a593Smuzhiyun 		case WOAL_INACTIVITY_TIMEOUT_EXT:
6702*4882a593Smuzhiyun 			ret = woal_inactivity_timeout_ext(priv, wrq);
6703*4882a593Smuzhiyun 			break;
6704*4882a593Smuzhiyun #ifdef SDIO
6705*4882a593Smuzhiyun 		case WOAL_SDIO_CLOCK:
6706*4882a593Smuzhiyun 			ret = woal_sdio_clock_ioctl(priv, wrq);
6707*4882a593Smuzhiyun 			break;
6708*4882a593Smuzhiyun 		case WOAL_CMD_52RDWR:
6709*4882a593Smuzhiyun 			ret = woal_cmd52rdwr_ioctl(priv, wrq);
6710*4882a593Smuzhiyun 			break;
6711*4882a593Smuzhiyun 		case WOAL_SDIO_MPA_CTRL:
6712*4882a593Smuzhiyun 			ret = woal_do_sdio_mpa_ctrl(priv, wrq);
6713*4882a593Smuzhiyun 			break;
6714*4882a593Smuzhiyun #endif
6715*4882a593Smuzhiyun 		case WOAL_BAND_CFG:
6716*4882a593Smuzhiyun 			ret = woal_band_cfg(priv, wrq);
6717*4882a593Smuzhiyun 			break;
6718*4882a593Smuzhiyun 		case WOAL_SCAN_CFG:
6719*4882a593Smuzhiyun 			ret = woal_set_get_scan_cfg(priv, wrq);
6720*4882a593Smuzhiyun 			break;
6721*4882a593Smuzhiyun 		case WOAL_PS_CFG:
6722*4882a593Smuzhiyun 			ret = woal_set_get_ps_cfg(priv, wrq);
6723*4882a593Smuzhiyun 			break;
6724*4882a593Smuzhiyun 		case WOAL_MEM_READ_WRITE:
6725*4882a593Smuzhiyun 			ret = woal_mem_read_write(priv, wrq);
6726*4882a593Smuzhiyun 			break;
6727*4882a593Smuzhiyun 		case WOAL_SLEEP_PARAMS:
6728*4882a593Smuzhiyun 			ret = woal_sleep_params_ioctl(priv, wrq);
6729*4882a593Smuzhiyun 			break;
6730*4882a593Smuzhiyun 		case WOAL_NET_MONITOR:
6731*4882a593Smuzhiyun 			ret = woal_net_monitor_ioctl(priv, wrq);
6732*4882a593Smuzhiyun 			break;
6733*4882a593Smuzhiyun 		case WOAL_DFS_TESTING:
6734*4882a593Smuzhiyun 			ret = woal_dfs_testing(priv, wrq);
6735*4882a593Smuzhiyun 			break;
6736*4882a593Smuzhiyun 		case WOAL_MGMT_FRAME_CTRL:
6737*4882a593Smuzhiyun 			ret = woal_mgmt_frame_passthru_ctrl(priv, wrq);
6738*4882a593Smuzhiyun 			break;
6739*4882a593Smuzhiyun 		case WOAL_CFP_CODE:
6740*4882a593Smuzhiyun 			ret = woal_cfp_code(priv, wrq);
6741*4882a593Smuzhiyun 			break;
6742*4882a593Smuzhiyun 		case WOAL_SET_GET_TX_RX_ANT:
6743*4882a593Smuzhiyun 			ret = woal_set_get_tx_rx_ant(priv, wrq);
6744*4882a593Smuzhiyun 			break;
6745*4882a593Smuzhiyun 		case WOAL_IND_RST_CFG:
6746*4882a593Smuzhiyun 			ret = woal_ind_rst_ioctl(priv, wrq);
6747*4882a593Smuzhiyun 			break;
6748*4882a593Smuzhiyun 		default:
6749*4882a593Smuzhiyun 			ret = -EINVAL;
6750*4882a593Smuzhiyun 			break;
6751*4882a593Smuzhiyun 		}
6752*4882a593Smuzhiyun 		break;
6753*4882a593Smuzhiyun 
6754*4882a593Smuzhiyun 	case WOALGETLOG:
6755*4882a593Smuzhiyun 		ret = woal_get_log(priv, wrq);
6756*4882a593Smuzhiyun 		break;
6757*4882a593Smuzhiyun 
6758*4882a593Smuzhiyun 	case WOAL_SET_GET_256_CHAR:
6759*4882a593Smuzhiyun 		switch (wrq->u.data.flags) {
6760*4882a593Smuzhiyun 		case WOAL_PASSPHRASE:
6761*4882a593Smuzhiyun 			ret = woal_passphrase(priv, wrq);
6762*4882a593Smuzhiyun 			break;
6763*4882a593Smuzhiyun 		case WOAL_GET_KEY:
6764*4882a593Smuzhiyun 			ret = woal_get_key_ioctl(priv, wrq);
6765*4882a593Smuzhiyun 			break;
6766*4882a593Smuzhiyun 		case WOAL_ASSOCIATE:
6767*4882a593Smuzhiyun 			ret = woal_associate_ssid_bssid(priv, wrq);
6768*4882a593Smuzhiyun 			break;
6769*4882a593Smuzhiyun 		case WOAL_WMM_QUEUE_STATUS:
6770*4882a593Smuzhiyun 			ret = woal_wmm_queue_status_ioctl(priv, wrq);
6771*4882a593Smuzhiyun 			break;
6772*4882a593Smuzhiyun 
6773*4882a593Smuzhiyun 		case WOAL_WMM_TS_STATUS:
6774*4882a593Smuzhiyun 			ret = woal_wmm_ts_status_ioctl(priv, wrq);
6775*4882a593Smuzhiyun 			break;
6776*4882a593Smuzhiyun 		case WOAL_IP_ADDRESS:
6777*4882a593Smuzhiyun 			ret = woal_set_get_ip_addr(priv, wrq);
6778*4882a593Smuzhiyun 			break;
6779*4882a593Smuzhiyun 		case WOAL_TX_BF_CFG:
6780*4882a593Smuzhiyun 			ret = woal_tx_bf_cfg_ioctl(priv, wrq);
6781*4882a593Smuzhiyun 			break;
6782*4882a593Smuzhiyun 		default:
6783*4882a593Smuzhiyun 			ret = -EINVAL;
6784*4882a593Smuzhiyun 			break;
6785*4882a593Smuzhiyun 		}
6786*4882a593Smuzhiyun 		break;
6787*4882a593Smuzhiyun 
6788*4882a593Smuzhiyun 	case WOAL_SETADDR_GETNONE:
6789*4882a593Smuzhiyun 		switch ((int)wrq->u.data.flags) {
6790*4882a593Smuzhiyun 		case WOAL_DEAUTH:
6791*4882a593Smuzhiyun 			ret = woal_deauth(priv, wrq);
6792*4882a593Smuzhiyun 			break;
6793*4882a593Smuzhiyun 		default:
6794*4882a593Smuzhiyun 			ret = -EINVAL;
6795*4882a593Smuzhiyun 			break;
6796*4882a593Smuzhiyun 		}
6797*4882a593Smuzhiyun 		break;
6798*4882a593Smuzhiyun 
6799*4882a593Smuzhiyun 	case WOAL_SETNONE_GETTWELVE_CHAR:
6800*4882a593Smuzhiyun 		/*
6801*4882a593Smuzhiyun 		 * We've not used IW_PRIV_TYPE_FIXED so sub-ioctl number is
6802*4882a593Smuzhiyun 		 * in flags of iwreq structure, otherwise it will be in
6803*4882a593Smuzhiyun 		 * mode member of iwreq structure.
6804*4882a593Smuzhiyun 		 */
6805*4882a593Smuzhiyun 		switch ((int)wrq->u.data.flags) {
6806*4882a593Smuzhiyun 		case WOAL_WPS_SESSION:
6807*4882a593Smuzhiyun 			ret = woal_wps_cfg_ioctl(priv, wrq);
6808*4882a593Smuzhiyun 			break;
6809*4882a593Smuzhiyun 		default:
6810*4882a593Smuzhiyun 			ret = -EINVAL;
6811*4882a593Smuzhiyun 			break;
6812*4882a593Smuzhiyun 		}
6813*4882a593Smuzhiyun 		break;
6814*4882a593Smuzhiyun 	case WOAL_SETNONE_GET_FOUR_INT:
6815*4882a593Smuzhiyun 		switch ((int)wrq->u.data.flags) {
6816*4882a593Smuzhiyun 		case WOAL_DATA_RATE:
6817*4882a593Smuzhiyun 			ret = woal_get_txrx_rate(priv, wrq);
6818*4882a593Smuzhiyun 			break;
6819*4882a593Smuzhiyun 		case WOAL_ESUPP_MODE:
6820*4882a593Smuzhiyun 			ret = woal_get_esupp_mode(priv, wrq);
6821*4882a593Smuzhiyun 			break;
6822*4882a593Smuzhiyun 		default:
6823*4882a593Smuzhiyun 			ret = -EINVAL;
6824*4882a593Smuzhiyun 			break;
6825*4882a593Smuzhiyun 		}
6826*4882a593Smuzhiyun 		break;
6827*4882a593Smuzhiyun 
6828*4882a593Smuzhiyun 	case WOAL_SET_GET_64_INT:
6829*4882a593Smuzhiyun 		switch ((int)wrq->u.data.flags) {
6830*4882a593Smuzhiyun 		case WOAL_ECL_SYS_CLOCK:
6831*4882a593Smuzhiyun 			ret = woal_ecl_sys_clock(priv, wrq);
6832*4882a593Smuzhiyun 			break;
6833*4882a593Smuzhiyun 		}
6834*4882a593Smuzhiyun 
6835*4882a593Smuzhiyun 		break;
6836*4882a593Smuzhiyun 
6837*4882a593Smuzhiyun 	case WOAL_HOST_CMD:
6838*4882a593Smuzhiyun 		ret = woal_host_command(priv, wrq);
6839*4882a593Smuzhiyun 		break;
6840*4882a593Smuzhiyun 	case WOAL_ARP_FILTER:
6841*4882a593Smuzhiyun 		ret = woal_arp_filter(priv, wrq);
6842*4882a593Smuzhiyun 		break;
6843*4882a593Smuzhiyun 	case WOAL_SET_INTS_GET_CHARS:
6844*4882a593Smuzhiyun 		switch ((int)wrq->u.data.flags) {
6845*4882a593Smuzhiyun 		case WOAL_READ_EEPROM:
6846*4882a593Smuzhiyun 			ret = woal_read_eeprom(priv, wrq);
6847*4882a593Smuzhiyun 			break;
6848*4882a593Smuzhiyun 		}
6849*4882a593Smuzhiyun 		break;
6850*4882a593Smuzhiyun 	case WOAL_SET_GET_2K_BYTES:
6851*4882a593Smuzhiyun 		switch ((int)wrq->u.data.flags) {
6852*4882a593Smuzhiyun #ifdef SDIO
6853*4882a593Smuzhiyun 		case WOAL_CMD_53RDWR:
6854*4882a593Smuzhiyun 			ret = woal_cmd53rdwr_ioctl(priv, wrq);
6855*4882a593Smuzhiyun 			break;
6856*4882a593Smuzhiyun #endif
6857*4882a593Smuzhiyun 		case WOAL_SET_USER_SCAN:
6858*4882a593Smuzhiyun 			ret = woal_set_user_scan_ioctl(priv, wrq);
6859*4882a593Smuzhiyun 			break;
6860*4882a593Smuzhiyun 		case WOAL_GET_SCAN_TABLE:
6861*4882a593Smuzhiyun 			ret = woal_get_scan_table_ioctl(priv, wrq);
6862*4882a593Smuzhiyun 			break;
6863*4882a593Smuzhiyun 		case WOAL_SET_USER_SCAN_EXT:
6864*4882a593Smuzhiyun 			ret = woal_set_user_scan_ext_ioctl(priv, wrq);
6865*4882a593Smuzhiyun 			break;
6866*4882a593Smuzhiyun 		case WOAL_WMM_ADDTS:
6867*4882a593Smuzhiyun 			ret = woal_wmm_addts_req_ioctl(priv, wrq);
6868*4882a593Smuzhiyun 			break;
6869*4882a593Smuzhiyun 		case WOAL_WMM_DELTS:
6870*4882a593Smuzhiyun 			ret = woal_wmm_delts_req_ioctl(priv, wrq);
6871*4882a593Smuzhiyun 			break;
6872*4882a593Smuzhiyun 		case WOAL_WMM_QUEUE_CONFIG:
6873*4882a593Smuzhiyun 			ret = woal_wmm_queue_config_ioctl(priv, wrq);
6874*4882a593Smuzhiyun 			break;
6875*4882a593Smuzhiyun 		case WOAL_WMM_QUEUE_STATS:
6876*4882a593Smuzhiyun 			ret = woal_wmm_queue_stats_ioctl(priv, wrq);
6877*4882a593Smuzhiyun 			break;
6878*4882a593Smuzhiyun 		case WOAL_BYPASSED_PACKET:
6879*4882a593Smuzhiyun 			ret = woal_bypassed_packet_ioctl(priv, wrq);
6880*4882a593Smuzhiyun 			break;
6881*4882a593Smuzhiyun 		default:
6882*4882a593Smuzhiyun 			ret = -EINVAL;
6883*4882a593Smuzhiyun 			break;
6884*4882a593Smuzhiyun 		}
6885*4882a593Smuzhiyun 		break;
6886*4882a593Smuzhiyun 
6887*4882a593Smuzhiyun #ifdef UAP_WEXT
6888*4882a593Smuzhiyun 	case WOAL_FROYO_START:
6889*4882a593Smuzhiyun 		break;
6890*4882a593Smuzhiyun 	case WOAL_FROYO_WL_FW_RELOAD:
6891*4882a593Smuzhiyun 		break;
6892*4882a593Smuzhiyun 	case WOAL_FROYO_STOP:
6893*4882a593Smuzhiyun 		if (IS_UAP_WEXT(priv->phandle->params.cfg80211_wext) &&
6894*4882a593Smuzhiyun 		    MLAN_STATUS_SUCCESS !=
6895*4882a593Smuzhiyun 			    woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL,
6896*4882a593Smuzhiyun 					    DEF_DEAUTH_REASON_CODE)) {
6897*4882a593Smuzhiyun 			ret = -EFAULT;
6898*4882a593Smuzhiyun 		}
6899*4882a593Smuzhiyun 		break;
6900*4882a593Smuzhiyun #endif
6901*4882a593Smuzhiyun 	default:
6902*4882a593Smuzhiyun 		ret = -EINVAL;
6903*4882a593Smuzhiyun 		break;
6904*4882a593Smuzhiyun 	}
6905*4882a593Smuzhiyun 
6906*4882a593Smuzhiyun 	LEAVE();
6907*4882a593Smuzhiyun 	return ret;
6908*4882a593Smuzhiyun }
6909*4882a593Smuzhiyun 
6910*4882a593Smuzhiyun /**
6911*4882a593Smuzhiyun  *  @brief Get data rates
6912*4882a593Smuzhiyun  *
6913*4882a593Smuzhiyun  *  @param priv          A pointer to moal_private structure
6914*4882a593Smuzhiyun  *  @param wait_option   Wait option
6915*4882a593Smuzhiyun  *  @param m_rates       A pointer to moal_802_11_rates structure
6916*4882a593Smuzhiyun  *
6917*4882a593Smuzhiyun  *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
6918*4882a593Smuzhiyun  * otherwise fail
6919*4882a593Smuzhiyun  */
woal_get_data_rates(moal_private * priv,t_u8 wait_option,moal_802_11_rates * m_rates)6920*4882a593Smuzhiyun mlan_status woal_get_data_rates(moal_private *priv, t_u8 wait_option,
6921*4882a593Smuzhiyun 				moal_802_11_rates *m_rates)
6922*4882a593Smuzhiyun {
6923*4882a593Smuzhiyun 	mlan_ds_rate *rate = NULL;
6924*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
6925*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
6926*4882a593Smuzhiyun 	ENTER();
6927*4882a593Smuzhiyun 
6928*4882a593Smuzhiyun 	/* Allocate an IOCTL request buffer */
6929*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate));
6930*4882a593Smuzhiyun 	if (req == NULL) {
6931*4882a593Smuzhiyun 		status = MLAN_STATUS_FAILURE;
6932*4882a593Smuzhiyun 		goto done;
6933*4882a593Smuzhiyun 	}
6934*4882a593Smuzhiyun 
6935*4882a593Smuzhiyun 	/* Fill request buffer */
6936*4882a593Smuzhiyun 	rate = (mlan_ds_rate *)req->pbuf;
6937*4882a593Smuzhiyun 	rate->sub_command = MLAN_OID_SUPPORTED_RATES;
6938*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_RATE;
6939*4882a593Smuzhiyun 	req->action = MLAN_ACT_GET;
6940*4882a593Smuzhiyun 
6941*4882a593Smuzhiyun 	/* Send IOCTL request to MLAN */
6942*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, wait_option);
6943*4882a593Smuzhiyun 	if (status == MLAN_STATUS_SUCCESS) {
6944*4882a593Smuzhiyun 		if (m_rates)
6945*4882a593Smuzhiyun 			m_rates->num_of_rates = woal_copy_rates(
6946*4882a593Smuzhiyun 				m_rates->rates, m_rates->num_of_rates,
6947*4882a593Smuzhiyun 				rate->param.rates, MLAN_SUPPORTED_RATES);
6948*4882a593Smuzhiyun 	}
6949*4882a593Smuzhiyun done:
6950*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
6951*4882a593Smuzhiyun 		kfree(req);
6952*4882a593Smuzhiyun 	LEAVE();
6953*4882a593Smuzhiyun 	return status;
6954*4882a593Smuzhiyun }
6955*4882a593Smuzhiyun 
6956*4882a593Smuzhiyun /**
6957*4882a593Smuzhiyun  *  @brief Get channel list
6958*4882a593Smuzhiyun  *
6959*4882a593Smuzhiyun  *  @param priv            A pointer to moal_private structure
6960*4882a593Smuzhiyun  *  @param wait_option     Wait option
6961*4882a593Smuzhiyun  *  @param chan_list       A pointer to mlan_chan_list structure
6962*4882a593Smuzhiyun  *
6963*4882a593Smuzhiyun  *  @return                MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
6964*4882a593Smuzhiyun  * otherwise fail
6965*4882a593Smuzhiyun  */
woal_get_channel_list(moal_private * priv,t_u8 wait_option,mlan_chan_list * chan_list)6966*4882a593Smuzhiyun mlan_status woal_get_channel_list(moal_private *priv, t_u8 wait_option,
6967*4882a593Smuzhiyun 				  mlan_chan_list *chan_list)
6968*4882a593Smuzhiyun {
6969*4882a593Smuzhiyun 	mlan_ds_bss *bss = NULL;
6970*4882a593Smuzhiyun 	mlan_ioctl_req *req = NULL;
6971*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
6972*4882a593Smuzhiyun 	ENTER();
6973*4882a593Smuzhiyun 
6974*4882a593Smuzhiyun 	/* Allocate an IOCTL request buffer */
6975*4882a593Smuzhiyun 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
6976*4882a593Smuzhiyun 	if (req == NULL) {
6977*4882a593Smuzhiyun 		status = MLAN_STATUS_FAILURE;
6978*4882a593Smuzhiyun 		goto done;
6979*4882a593Smuzhiyun 	}
6980*4882a593Smuzhiyun 
6981*4882a593Smuzhiyun 	/* Fill request buffer */
6982*4882a593Smuzhiyun 	bss = (mlan_ds_bss *)req->pbuf;
6983*4882a593Smuzhiyun 	bss->sub_command = MLAN_OID_BSS_CHANNEL_LIST;
6984*4882a593Smuzhiyun 	req->req_id = MLAN_IOCTL_BSS;
6985*4882a593Smuzhiyun 	req->action = MLAN_ACT_GET;
6986*4882a593Smuzhiyun 
6987*4882a593Smuzhiyun 	/* Send IOCTL request to MLAN */
6988*4882a593Smuzhiyun 	status = woal_request_ioctl(priv, req, wait_option);
6989*4882a593Smuzhiyun 	if (status == MLAN_STATUS_SUCCESS) {
6990*4882a593Smuzhiyun 		if (chan_list) {
6991*4882a593Smuzhiyun 			moal_memcpy_ext(priv->phandle, chan_list,
6992*4882a593Smuzhiyun 					&bss->param.chanlist,
6993*4882a593Smuzhiyun 					sizeof(mlan_chan_list),
6994*4882a593Smuzhiyun 					sizeof(mlan_chan_list));
6995*4882a593Smuzhiyun 		}
6996*4882a593Smuzhiyun 	}
6997*4882a593Smuzhiyun done:
6998*4882a593Smuzhiyun 	if (status != MLAN_STATUS_PENDING)
6999*4882a593Smuzhiyun 		kfree(req);
7000*4882a593Smuzhiyun 	LEAVE();
7001*4882a593Smuzhiyun 	return status;
7002*4882a593Smuzhiyun }
7003*4882a593Smuzhiyun 
7004*4882a593Smuzhiyun /**
7005*4882a593Smuzhiyun  *  @brief Handle get info resp
7006*4882a593Smuzhiyun  *
7007*4882a593Smuzhiyun  *  @param priv     Pointer to moal_private structure
7008*4882a593Smuzhiyun  *  @param info     Pointer to mlan_ds_get_info structure
7009*4882a593Smuzhiyun  *
7010*4882a593Smuzhiyun  *  @return         N/A
7011*4882a593Smuzhiyun  */
woal_ioctl_get_info_resp(moal_private * priv,mlan_ds_get_info * info)7012*4882a593Smuzhiyun void woal_ioctl_get_info_resp(moal_private *priv, mlan_ds_get_info *info)
7013*4882a593Smuzhiyun {
7014*4882a593Smuzhiyun 	ENTER();
7015*4882a593Smuzhiyun 	switch (info->sub_command) {
7016*4882a593Smuzhiyun 	case MLAN_OID_GET_STATS:
7017*4882a593Smuzhiyun 		priv->w_stats.discard.fragment = info->param.stats.fcs_error;
7018*4882a593Smuzhiyun 		priv->w_stats.discard.retries = info->param.stats.retry;
7019*4882a593Smuzhiyun 		priv->w_stats.discard.misc = info->param.stats.ack_failure;
7020*4882a593Smuzhiyun 		break;
7021*4882a593Smuzhiyun 	case MLAN_OID_GET_SIGNAL:
7022*4882a593Smuzhiyun 		if (info->param.signal.selector & BCN_RSSI_AVG_MASK)
7023*4882a593Smuzhiyun 			priv->w_stats.qual.level =
7024*4882a593Smuzhiyun 				info->param.signal.bcn_rssi_avg;
7025*4882a593Smuzhiyun 		if (info->param.signal.selector & BCN_NF_AVG_MASK)
7026*4882a593Smuzhiyun 			priv->w_stats.qual.noise =
7027*4882a593Smuzhiyun 				info->param.signal.bcn_nf_avg;
7028*4882a593Smuzhiyun 		break;
7029*4882a593Smuzhiyun 	default:
7030*4882a593Smuzhiyun 		break;
7031*4882a593Smuzhiyun 	}
7032*4882a593Smuzhiyun 	LEAVE();
7033*4882a593Smuzhiyun }
7034*4882a593Smuzhiyun 
7035*4882a593Smuzhiyun /**
7036*4882a593Smuzhiyun  *  @brief Handle get BSS resp
7037*4882a593Smuzhiyun  *
7038*4882a593Smuzhiyun  *  @param priv     Pointer to moal_private structure
7039*4882a593Smuzhiyun  *  @param bss      Pointer to mlan_ds_bss structure
7040*4882a593Smuzhiyun  *
7041*4882a593Smuzhiyun  *  @return         N/A
7042*4882a593Smuzhiyun  */
woal_ioctl_get_bss_resp(moal_private * priv,mlan_ds_bss * bss)7043*4882a593Smuzhiyun void woal_ioctl_get_bss_resp(moal_private *priv, mlan_ds_bss *bss)
7044*4882a593Smuzhiyun {
7045*4882a593Smuzhiyun 	t_u32 mode = 0;
7046*4882a593Smuzhiyun 
7047*4882a593Smuzhiyun 	ENTER();
7048*4882a593Smuzhiyun 
7049*4882a593Smuzhiyun 	switch (bss->sub_command) {
7050*4882a593Smuzhiyun 	case MLAN_OID_BSS_MODE:
7051*4882a593Smuzhiyun 		if (bss->param.bss_mode == MLAN_BSS_MODE_INFRA)
7052*4882a593Smuzhiyun 			mode = IW_MODE_INFRA;
7053*4882a593Smuzhiyun 		else if (bss->param.bss_mode == MLAN_BSS_MODE_IBSS)
7054*4882a593Smuzhiyun 			mode = IW_MODE_ADHOC;
7055*4882a593Smuzhiyun 		else
7056*4882a593Smuzhiyun 			mode = IW_MODE_AUTO;
7057*4882a593Smuzhiyun 		priv->w_stats.status = mode;
7058*4882a593Smuzhiyun 		break;
7059*4882a593Smuzhiyun 	default:
7060*4882a593Smuzhiyun 		break;
7061*4882a593Smuzhiyun 	}
7062*4882a593Smuzhiyun 
7063*4882a593Smuzhiyun 	LEAVE();
7064*4882a593Smuzhiyun 	return;
7065*4882a593Smuzhiyun }
7066