xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlan/mlan_misc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /**
2*4882a593Smuzhiyun  * @file mlan_misc.c
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  *  @brief This file include miscellaneous functions for MLAN module
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  *  Copyright 2009-2022 NXP
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  *  This software file (the File) is distributed by NXP
10*4882a593Smuzhiyun  *  under the terms of the GNU General Public License Version 2, June 1991
11*4882a593Smuzhiyun  *  (the License).  You may use, redistribute and/or modify the File in
12*4882a593Smuzhiyun  *  accordance with the terms and conditions of the License, a copy of which
13*4882a593Smuzhiyun  *  is available by writing to the Free Software Foundation, Inc.,
14*4882a593Smuzhiyun  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
15*4882a593Smuzhiyun  *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
18*4882a593Smuzhiyun  *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
19*4882a593Smuzhiyun  *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
20*4882a593Smuzhiyun  *  this warranty disclaimer.
21*4882a593Smuzhiyun  *
22*4882a593Smuzhiyun  */
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun /*************************************************************
25*4882a593Smuzhiyun Change Log:
26*4882a593Smuzhiyun     05/11/2009: initial version
27*4882a593Smuzhiyun ************************************************************/
28*4882a593Smuzhiyun #include "mlan.h"
29*4882a593Smuzhiyun #ifdef STA_SUPPORT
30*4882a593Smuzhiyun #include "mlan_join.h"
31*4882a593Smuzhiyun #endif /* STA_SUPPORT */
32*4882a593Smuzhiyun #include "mlan_util.h"
33*4882a593Smuzhiyun #include "mlan_fw.h"
34*4882a593Smuzhiyun #include "mlan_main.h"
35*4882a593Smuzhiyun #include "mlan_wmm.h"
36*4882a593Smuzhiyun #include "mlan_11n.h"
37*4882a593Smuzhiyun #include "mlan_11ac.h"
38*4882a593Smuzhiyun #include "mlan_11ax.h"
39*4882a593Smuzhiyun #ifdef UAP_SUPPORT
40*4882a593Smuzhiyun #include "mlan_uap.h"
41*4882a593Smuzhiyun #endif
42*4882a593Smuzhiyun #ifdef DRV_EMBEDDED_AUTHENTICATOR
43*4882a593Smuzhiyun #include "authenticator_api.h"
44*4882a593Smuzhiyun #endif
45*4882a593Smuzhiyun /********************************************************
46*4882a593Smuzhiyun 			Local Variables
47*4882a593Smuzhiyun ********************************************************/
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun /********************************************************
50*4882a593Smuzhiyun 			Global Variables
51*4882a593Smuzhiyun ********************************************************/
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun /********************************************************
54*4882a593Smuzhiyun 			Local Functions
55*4882a593Smuzhiyun ********************************************************/
56*4882a593Smuzhiyun #if defined(PCIE) || defined(SDIO)
57*4882a593Smuzhiyun /**
58*4882a593Smuzhiyun  *  @brief Check pending irq
59*4882a593Smuzhiyun  *
60*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
61*4882a593Smuzhiyun  *
62*4882a593Smuzhiyun  *  @return        MTRUE/MFALSE;
63*4882a593Smuzhiyun  */
wlan_pending_interrupt(pmlan_adapter pmadapter)64*4882a593Smuzhiyun static t_u8 wlan_pending_interrupt(pmlan_adapter pmadapter)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun 	if (!IS_USB(pmadapter->card_type) && pmadapter->ireg)
67*4882a593Smuzhiyun 		return MTRUE;
68*4882a593Smuzhiyun 	return MFALSE;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun #endif
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun /** Custom IE auto index and mask */
73*4882a593Smuzhiyun #define MLAN_CUSTOM_IE_AUTO_IDX_MASK 0xffff
74*4882a593Smuzhiyun /** Custom IE mask for delete operation */
75*4882a593Smuzhiyun #define MLAN_CUSTOM_IE_DELETE_MASK 0
76*4882a593Smuzhiyun /** Custom IE mask for create new index */
77*4882a593Smuzhiyun #define MLAN_CUSTOM_IE_NEW_MASK 0x8000
78*4882a593Smuzhiyun /** Custom IE header size */
79*4882a593Smuzhiyun #define MLAN_CUSTOM_IE_HDR_SIZE (sizeof(custom_ie) - MAX_IE_SIZE)
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun /**
82*4882a593Smuzhiyun  *  @brief Check if current custom IE index is used on other interfaces.
83*4882a593Smuzhiyun  *
84*4882a593Smuzhiyun  *  @param pmpriv   A pointer to mlan_private structure
85*4882a593Smuzhiyun  *  @param idx		index to check for in use
86*4882a593Smuzhiyun  *
87*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS --unused, otherwise used.
88*4882a593Smuzhiyun  */
wlan_is_custom_ie_index_unused(pmlan_private pmpriv,t_u16 idx)89*4882a593Smuzhiyun static mlan_status wlan_is_custom_ie_index_unused(pmlan_private pmpriv,
90*4882a593Smuzhiyun 						  t_u16 idx)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun 	t_u8 i = 0;
93*4882a593Smuzhiyun 	pmlan_adapter pmadapter = pmpriv->adapter;
94*4882a593Smuzhiyun 	pmlan_private priv;
95*4882a593Smuzhiyun 	ENTER();
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	for (i = 0; i < pmadapter->priv_num; i++) {
98*4882a593Smuzhiyun 		priv = pmadapter->priv[i];
99*4882a593Smuzhiyun 		/* Check for other interfaces only */
100*4882a593Smuzhiyun 		if (priv && priv->bss_index != pmpriv->bss_index) {
101*4882a593Smuzhiyun 			if (priv->mgmt_ie[idx].mgmt_subtype_mask &&
102*4882a593Smuzhiyun 			    priv->mgmt_ie[idx].ie_length) {
103*4882a593Smuzhiyun 				/* used entry found */
104*4882a593Smuzhiyun 				LEAVE();
105*4882a593Smuzhiyun 				return MLAN_STATUS_FAILURE;
106*4882a593Smuzhiyun 			}
107*4882a593Smuzhiyun 		}
108*4882a593Smuzhiyun 	}
109*4882a593Smuzhiyun 	LEAVE();
110*4882a593Smuzhiyun 	return MLAN_STATUS_SUCCESS;
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun /**
114*4882a593Smuzhiyun  *  @brief Get the custom IE index
115*4882a593Smuzhiyun  *
116*4882a593Smuzhiyun  *  @param pmpriv       A pointer to mlan_private structure
117*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
118*4882a593Smuzhiyun  *  @param mask	mask value for which the index to be returned
119*4882a593Smuzhiyun  *  @param ie_data	a pointer to custom_ie structure
120*4882a593Smuzhiyun  *  @param idx		will hold the computed index
121*4882a593Smuzhiyun  *
122*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
123*4882a593Smuzhiyun  */
wlan_custom_ioctl_get_autoidx(pmlan_private pmpriv,pmlan_ioctl_req pioctl_req,t_u16 mask,custom_ie * ie_data,t_u16 * idx)124*4882a593Smuzhiyun static mlan_status wlan_custom_ioctl_get_autoidx(pmlan_private pmpriv,
125*4882a593Smuzhiyun 						 pmlan_ioctl_req pioctl_req,
126*4882a593Smuzhiyun 						 t_u16 mask, custom_ie *ie_data,
127*4882a593Smuzhiyun 						 t_u16 *idx)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun 	t_u16 index = 0, insert = MFALSE;
130*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	ENTER();
133*4882a593Smuzhiyun 	/* Determine the index where the IE needs to be inserted */
134*4882a593Smuzhiyun 	while (!insert) {
135*4882a593Smuzhiyun 		while (index < MIN(pmpriv->adapter->max_mgmt_ie_index,
136*4882a593Smuzhiyun 				   MAX_MGMT_IE_INDEX)) {
137*4882a593Smuzhiyun 			if (pmpriv->mgmt_ie[index].mgmt_subtype_mask ==
138*4882a593Smuzhiyun 			    MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
139*4882a593Smuzhiyun 				index++;
140*4882a593Smuzhiyun 				continue;
141*4882a593Smuzhiyun 			}
142*4882a593Smuzhiyun 			if (pmpriv->mgmt_ie[index].mgmt_subtype_mask == mask) {
143*4882a593Smuzhiyun 				/* Duplicate IE should be avoided */
144*4882a593Smuzhiyun 				if (pmpriv->mgmt_ie[index].ie_length) {
145*4882a593Smuzhiyun 					if (!memcmp(pmpriv->adapter,
146*4882a593Smuzhiyun 						    pmpriv->mgmt_ie[index]
147*4882a593Smuzhiyun 							    .ie_buffer,
148*4882a593Smuzhiyun 						    ie_data->ie_buffer,
149*4882a593Smuzhiyun 						    pmpriv->mgmt_ie[index]
150*4882a593Smuzhiyun 							    .ie_length)) {
151*4882a593Smuzhiyun 						PRINTM(MINFO,
152*4882a593Smuzhiyun 						       "IE with the same mask exists at index %d mask=0x%x\n",
153*4882a593Smuzhiyun 						       index, mask);
154*4882a593Smuzhiyun 						*idx = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
155*4882a593Smuzhiyun 						goto done;
156*4882a593Smuzhiyun 					}
157*4882a593Smuzhiyun 				}
158*4882a593Smuzhiyun 				/* Check if enough space is available */
159*4882a593Smuzhiyun 				if (pmpriv->mgmt_ie[index].ie_length +
160*4882a593Smuzhiyun 					    ie_data->ie_length >
161*4882a593Smuzhiyun 				    MAX_IE_SIZE) {
162*4882a593Smuzhiyun 					index++;
163*4882a593Smuzhiyun 					continue;
164*4882a593Smuzhiyun 				}
165*4882a593Smuzhiyun 				insert = MTRUE;
166*4882a593Smuzhiyun 				break;
167*4882a593Smuzhiyun 			}
168*4882a593Smuzhiyun 			index++;
169*4882a593Smuzhiyun 		}
170*4882a593Smuzhiyun 		if (!insert) {
171*4882a593Smuzhiyun 			for (index = 0;
172*4882a593Smuzhiyun 			     index < MIN(pmpriv->adapter->max_mgmt_ie_index,
173*4882a593Smuzhiyun 					 MAX_MGMT_IE_INDEX);
174*4882a593Smuzhiyun 			     index++) {
175*4882a593Smuzhiyun 				if (pmpriv->mgmt_ie[index].ie_length == 0) {
176*4882a593Smuzhiyun 					/*
177*4882a593Smuzhiyun 					 * Check if this index is in use
178*4882a593Smuzhiyun 					 * by other interface If yes,
179*4882a593Smuzhiyun 					 * move ahead to next index
180*4882a593Smuzhiyun 					 */
181*4882a593Smuzhiyun 					if (MLAN_STATUS_SUCCESS ==
182*4882a593Smuzhiyun 					    wlan_is_custom_ie_index_unused(
183*4882a593Smuzhiyun 						    pmpriv, index)) {
184*4882a593Smuzhiyun 						insert = MTRUE;
185*4882a593Smuzhiyun 						break;
186*4882a593Smuzhiyun 					} else {
187*4882a593Smuzhiyun 						PRINTM(MINFO,
188*4882a593Smuzhiyun 						       "Skipping IE index %d in use.\n",
189*4882a593Smuzhiyun 						       index);
190*4882a593Smuzhiyun 					}
191*4882a593Smuzhiyun 				}
192*4882a593Smuzhiyun 			}
193*4882a593Smuzhiyun 		}
194*4882a593Smuzhiyun 		if (index == pmpriv->adapter->max_mgmt_ie_index && !insert) {
195*4882a593Smuzhiyun 			PRINTM(MERROR, "Failed to Set the IE buffer\n");
196*4882a593Smuzhiyun 			if (pioctl_req)
197*4882a593Smuzhiyun 				pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
198*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
199*4882a593Smuzhiyun 			goto done;
200*4882a593Smuzhiyun 		}
201*4882a593Smuzhiyun 	}
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	*idx = index;
204*4882a593Smuzhiyun done:
205*4882a593Smuzhiyun 	LEAVE();
206*4882a593Smuzhiyun 	return ret;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun /**
210*4882a593Smuzhiyun  *  @brief Delete custom IE
211*4882a593Smuzhiyun  *
212*4882a593Smuzhiyun  *  @param pmpriv       A pointer to mlan_private structure
213*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
214*4882a593Smuzhiyun  *  @param ie_data	a pointer to custom_ie structure
215*4882a593Smuzhiyun  *  @param idx		index supplied
216*4882a593Smuzhiyun  *
217*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
218*4882a593Smuzhiyun  */
219*4882a593Smuzhiyun 
wlan_custom_ioctl_auto_delete(pmlan_private pmpriv,pmlan_ioctl_req pioctl_req,custom_ie * ie_data,t_u16 idx)220*4882a593Smuzhiyun static mlan_status wlan_custom_ioctl_auto_delete(pmlan_private pmpriv,
221*4882a593Smuzhiyun 						 pmlan_ioctl_req pioctl_req,
222*4882a593Smuzhiyun 						 custom_ie *ie_data, t_u16 idx)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
225*4882a593Smuzhiyun 	pmlan_adapter pmadapter = pmpriv->adapter;
226*4882a593Smuzhiyun 	t_u16 index = 0, insert = MFALSE, del_len;
227*4882a593Smuzhiyun 	t_u8 del_ie[MAX_IE_SIZE], ie[MAX_IE_SIZE];
228*4882a593Smuzhiyun 	t_s32 cnt, tmp_len = 0;
229*4882a593Smuzhiyun 	t_u8 *tmp_ie;
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	ENTER();
232*4882a593Smuzhiyun 	memset(pmpriv->adapter, del_ie, 0, MAX_IE_SIZE);
233*4882a593Smuzhiyun 	memcpy_ext(pmpriv->adapter, del_ie, ie_data->ie_buffer,
234*4882a593Smuzhiyun 		   ie_data->ie_length, MAX_IE_SIZE);
235*4882a593Smuzhiyun 	del_len = MIN(MAX_IE_SIZE - 1, ie_data->ie_length);
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == idx)
238*4882a593Smuzhiyun 		ie_data->ie_index = 0;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	for (index = 0;
241*4882a593Smuzhiyun 	     index < MIN(pmadapter->max_mgmt_ie_index, MAX_MGMT_IE_INDEX);
242*4882a593Smuzhiyun 	     index++) {
243*4882a593Smuzhiyun 		if (MLAN_CUSTOM_IE_AUTO_IDX_MASK != idx &&
244*4882a593Smuzhiyun 		    idx < MAX_MGMT_IE_INDEX)
245*4882a593Smuzhiyun 			index = idx;
246*4882a593Smuzhiyun 		tmp_ie = pmpriv->mgmt_ie[index].ie_buffer;
247*4882a593Smuzhiyun 		tmp_len = pmpriv->mgmt_ie[index].ie_length;
248*4882a593Smuzhiyun 		cnt = 0;
249*4882a593Smuzhiyun 		while (tmp_len) {
250*4882a593Smuzhiyun 			if (!memcmp(pmpriv->adapter, tmp_ie, del_ie, del_len)) {
251*4882a593Smuzhiyun 				memcpy_ext(pmpriv->adapter, ie,
252*4882a593Smuzhiyun 					   pmpriv->mgmt_ie[index].ie_buffer,
253*4882a593Smuzhiyun 					   cnt, MAX_IE_SIZE);
254*4882a593Smuzhiyun 				if (pmpriv->mgmt_ie[index].ie_length >
255*4882a593Smuzhiyun 				    (cnt + del_len))
256*4882a593Smuzhiyun 					memcpy_ext(
257*4882a593Smuzhiyun 						pmpriv->adapter, &ie[cnt],
258*4882a593Smuzhiyun 						&pmpriv->mgmt_ie[index].ie_buffer
259*4882a593Smuzhiyun 							 [MIN((MAX_IE_SIZE - 1),
260*4882a593Smuzhiyun 							      (cnt + del_len))],
261*4882a593Smuzhiyun 						(pmpriv->mgmt_ie[index]
262*4882a593Smuzhiyun 							 .ie_length -
263*4882a593Smuzhiyun 						 (cnt + del_len)),
264*4882a593Smuzhiyun 						MAX_IE_SIZE - cnt);
265*4882a593Smuzhiyun 				memset(pmpriv->adapter,
266*4882a593Smuzhiyun 				       &pmpriv->mgmt_ie[index].ie_buffer, 0,
267*4882a593Smuzhiyun 				       sizeof(pmpriv->mgmt_ie[index].ie_buffer));
268*4882a593Smuzhiyun 				memcpy_ext(pmpriv->adapter,
269*4882a593Smuzhiyun 					   &pmpriv->mgmt_ie[index].ie_buffer,
270*4882a593Smuzhiyun 					   ie,
271*4882a593Smuzhiyun 					   pmpriv->mgmt_ie[index].ie_length -
272*4882a593Smuzhiyun 						   del_len,
273*4882a593Smuzhiyun 					   MAX_IE_SIZE);
274*4882a593Smuzhiyun 				pmpriv->mgmt_ie[index].ie_length -= del_len;
275*4882a593Smuzhiyun 				if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == idx)
276*4882a593Smuzhiyun 					/* set a bit to indicate caller about
277*4882a593Smuzhiyun 					 * update */
278*4882a593Smuzhiyun 					ie_data->ie_index |=
279*4882a593Smuzhiyun 						(((t_u16)1) << index);
280*4882a593Smuzhiyun 				insert = MTRUE;
281*4882a593Smuzhiyun 				tmp_ie = pmpriv->mgmt_ie[index].ie_buffer;
282*4882a593Smuzhiyun 				tmp_len = pmpriv->mgmt_ie[index].ie_length;
283*4882a593Smuzhiyun 				cnt = 0;
284*4882a593Smuzhiyun 				continue;
285*4882a593Smuzhiyun 			}
286*4882a593Smuzhiyun 			tmp_ie++;
287*4882a593Smuzhiyun 			tmp_len--;
288*4882a593Smuzhiyun 			cnt++;
289*4882a593Smuzhiyun 		}
290*4882a593Smuzhiyun 		if (MLAN_CUSTOM_IE_AUTO_IDX_MASK != idx)
291*4882a593Smuzhiyun 			break;
292*4882a593Smuzhiyun 	}
293*4882a593Smuzhiyun 	if (index == pmadapter->max_mgmt_ie_index && !insert) {
294*4882a593Smuzhiyun 		PRINTM(MERROR, "Failed to Clear IE buffer\n");
295*4882a593Smuzhiyun 		if (pioctl_req)
296*4882a593Smuzhiyun 			pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
297*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
298*4882a593Smuzhiyun 	}
299*4882a593Smuzhiyun 	LEAVE();
300*4882a593Smuzhiyun 	return ret;
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun /********************************************************
304*4882a593Smuzhiyun 			Global Functions
305*4882a593Smuzhiyun ********************************************************/
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun /**
308*4882a593Smuzhiyun  *  @brief send host cmd
309*4882a593Smuzhiyun  *
310*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
311*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
312*4882a593Smuzhiyun  *
313*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
314*4882a593Smuzhiyun  */
wlan_misc_ioctl_host_cmd(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)315*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_host_cmd(pmlan_adapter pmadapter,
316*4882a593Smuzhiyun 				     pmlan_ioctl_req pioctl_req)
317*4882a593Smuzhiyun {
318*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
319*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
320*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	ENTER();
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	/* Send request to firmware */
327*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, 0, 0, 0, (t_void *)pioctl_req,
328*4882a593Smuzhiyun 			       (t_void *)&misc->param.hostcmd);
329*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
330*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	LEAVE();
333*4882a593Smuzhiyun 	return ret;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun /**
337*4882a593Smuzhiyun  *  @brief Send function init/shutdown command to firmware
338*4882a593Smuzhiyun  *
339*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
340*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
341*4882a593Smuzhiyun  *
342*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
343*4882a593Smuzhiyun  */
wlan_misc_ioctl_init_shutdown(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)344*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_init_shutdown(pmlan_adapter pmadapter,
345*4882a593Smuzhiyun 					  pmlan_ioctl_req pioctl_req)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
348*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
349*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc_cfg = MNULL;
350*4882a593Smuzhiyun 	t_u16 cmd;
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	ENTER();
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
355*4882a593Smuzhiyun 	if (misc_cfg->param.func_init_shutdown == MLAN_FUNC_INIT)
356*4882a593Smuzhiyun 		cmd = HostCmd_CMD_FUNC_INIT;
357*4882a593Smuzhiyun 	else if (misc_cfg->param.func_init_shutdown == MLAN_FUNC_SHUTDOWN)
358*4882a593Smuzhiyun 		cmd = HostCmd_CMD_FUNC_SHUTDOWN;
359*4882a593Smuzhiyun 	else {
360*4882a593Smuzhiyun 		PRINTM(MERROR, "Unsupported parameter\n");
361*4882a593Smuzhiyun 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
362*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
363*4882a593Smuzhiyun 		goto exit;
364*4882a593Smuzhiyun 	}
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	/* Send command to firmware */
367*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, cmd, HostCmd_ACT_GEN_SET, 0,
368*4882a593Smuzhiyun 			       (t_void *)pioctl_req, MNULL);
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
371*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun exit:
374*4882a593Smuzhiyun 	LEAVE();
375*4882a593Smuzhiyun 	return ret;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun /**
379*4882a593Smuzhiyun  *  @brief Get debug information
380*4882a593Smuzhiyun  *
381*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
382*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
383*4882a593Smuzhiyun  *
384*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS --success
385*4882a593Smuzhiyun  */
wlan_get_info_debug_info(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)386*4882a593Smuzhiyun mlan_status wlan_get_info_debug_info(pmlan_adapter pmadapter,
387*4882a593Smuzhiyun 				     pmlan_ioctl_req pioctl_req)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
390*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
391*4882a593Smuzhiyun 	mlan_ds_get_info *info;
392*4882a593Smuzhiyun 	mlan_debug_info *debug_info = MNULL;
393*4882a593Smuzhiyun 	t_u32 i;
394*4882a593Smuzhiyun 	t_u8 *ptid;
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	ENTER();
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	info = (mlan_ds_get_info *)pioctl_req->pbuf;
399*4882a593Smuzhiyun 	debug_info = (mlan_debug_info *)info->param.debug_info;
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_GET) {
402*4882a593Smuzhiyun 		ptid = ac_to_tid[WMM_AC_BK];
403*4882a593Smuzhiyun 		debug_info->wmm_ac_bk = pmpriv->wmm.packets_out[ptid[0]] +
404*4882a593Smuzhiyun 					pmpriv->wmm.packets_out[ptid[1]];
405*4882a593Smuzhiyun 		ptid = ac_to_tid[WMM_AC_BE];
406*4882a593Smuzhiyun 		debug_info->wmm_ac_be = pmpriv->wmm.packets_out[ptid[0]] +
407*4882a593Smuzhiyun 					pmpriv->wmm.packets_out[ptid[1]];
408*4882a593Smuzhiyun 		ptid = ac_to_tid[WMM_AC_VI];
409*4882a593Smuzhiyun 		debug_info->wmm_ac_vi = pmpriv->wmm.packets_out[ptid[0]] +
410*4882a593Smuzhiyun 					pmpriv->wmm.packets_out[ptid[1]];
411*4882a593Smuzhiyun 		ptid = ac_to_tid[WMM_AC_VO];
412*4882a593Smuzhiyun 		debug_info->wmm_ac_vo = pmpriv->wmm.packets_out[ptid[0]] +
413*4882a593Smuzhiyun 					pmpriv->wmm.packets_out[ptid[1]];
414*4882a593Smuzhiyun 		debug_info->max_tx_buf_size = (t_u32)pmadapter->max_tx_buf_size;
415*4882a593Smuzhiyun 		debug_info->tx_buf_size = (t_u32)pmadapter->tx_buf_size;
416*4882a593Smuzhiyun 		debug_info->curr_tx_buf_size =
417*4882a593Smuzhiyun 			(t_u32)pmadapter->curr_tx_buf_size;
418*4882a593Smuzhiyun 		debug_info->rx_tbl_num =
419*4882a593Smuzhiyun 			wlan_get_rxreorder_tbl(pmpriv, debug_info->rx_tbl);
420*4882a593Smuzhiyun 		debug_info->tx_tbl_num =
421*4882a593Smuzhiyun 			wlan_get_txbastream_tbl(pmpriv, debug_info->tx_tbl);
422*4882a593Smuzhiyun 		debug_info->ralist_num =
423*4882a593Smuzhiyun 			wlan_get_ralist_info(pmpriv, debug_info->ralist);
424*4882a593Smuzhiyun 		debug_info->tdls_peer_num =
425*4882a593Smuzhiyun 			wlan_get_tdls_list(pmpriv, debug_info->tdls_peer_list);
426*4882a593Smuzhiyun 		debug_info->ps_mode = pmadapter->ps_mode;
427*4882a593Smuzhiyun 		debug_info->ps_state = pmadapter->ps_state;
428*4882a593Smuzhiyun #ifdef STA_SUPPORT
429*4882a593Smuzhiyun 		debug_info->is_deep_sleep = pmadapter->is_deep_sleep;
430*4882a593Smuzhiyun #endif /* STA_SUPPORT */
431*4882a593Smuzhiyun 		debug_info->pm_wakeup_card_req = pmadapter->pm_wakeup_card_req;
432*4882a593Smuzhiyun 		debug_info->pm_wakeup_fw_try = pmadapter->pm_wakeup_fw_try;
433*4882a593Smuzhiyun 		debug_info->pm_wakeup_in_secs = pmadapter->pm_wakeup_in_secs;
434*4882a593Smuzhiyun 		debug_info->pm_wakeup_timeout = pmadapter->pm_wakeup_timeout;
435*4882a593Smuzhiyun 		debug_info->is_hs_configured = pmadapter->is_hs_configured;
436*4882a593Smuzhiyun 		debug_info->hs_activated = pmadapter->hs_activated;
437*4882a593Smuzhiyun 		debug_info->pps_uapsd_mode = pmadapter->pps_uapsd_mode;
438*4882a593Smuzhiyun 		debug_info->sleep_pd = pmadapter->sleep_period.period;
439*4882a593Smuzhiyun 		debug_info->qos_cfg = pmpriv->wmm_qosinfo;
440*4882a593Smuzhiyun 		debug_info->tx_lock_flag = pmadapter->tx_lock_flag;
441*4882a593Smuzhiyun 		debug_info->port_open = pmpriv->port_open;
442*4882a593Smuzhiyun 		debug_info->bypass_pkt_count = pmadapter->bypass_pkt_count;
443*4882a593Smuzhiyun 		debug_info->scan_processing = pmadapter->scan_processing;
444*4882a593Smuzhiyun 		debug_info->scan_state = pmadapter->scan_state;
445*4882a593Smuzhiyun 		debug_info->mlan_processing = pmadapter->mlan_processing;
446*4882a593Smuzhiyun 		debug_info->main_lock_flag = pmadapter->main_lock_flag;
447*4882a593Smuzhiyun 		debug_info->main_process_cnt = pmadapter->main_process_cnt;
448*4882a593Smuzhiyun 		debug_info->delay_task_flag = pmadapter->delay_task_flag;
449*4882a593Smuzhiyun 		debug_info->num_cmd_host_to_card_failure =
450*4882a593Smuzhiyun 			pmadapter->dbg.num_cmd_host_to_card_failure;
451*4882a593Smuzhiyun 		debug_info->num_cmd_sleep_cfm_host_to_card_failure =
452*4882a593Smuzhiyun 			pmadapter->dbg.num_cmd_sleep_cfm_host_to_card_failure;
453*4882a593Smuzhiyun 		debug_info->num_tx_host_to_card_failure =
454*4882a593Smuzhiyun 			pmadapter->dbg.num_tx_host_to_card_failure;
455*4882a593Smuzhiyun 		debug_info->num_alloc_buffer_failure =
456*4882a593Smuzhiyun 			pmadapter->dbg.num_alloc_buffer_failure;
457*4882a593Smuzhiyun 		debug_info->num_pkt_dropped = pmadapter->dbg.num_pkt_dropped;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 		debug_info->num_event_deauth = pmadapter->dbg.num_event_deauth;
460*4882a593Smuzhiyun 		debug_info->num_event_disassoc =
461*4882a593Smuzhiyun 			pmadapter->dbg.num_event_disassoc;
462*4882a593Smuzhiyun 		debug_info->num_event_link_lost =
463*4882a593Smuzhiyun 			pmadapter->dbg.num_event_link_lost;
464*4882a593Smuzhiyun 		debug_info->num_cmd_deauth = pmadapter->dbg.num_cmd_deauth;
465*4882a593Smuzhiyun 		debug_info->num_cmd_assoc_success =
466*4882a593Smuzhiyun 			pmadapter->dbg.num_cmd_assoc_success;
467*4882a593Smuzhiyun 		debug_info->num_cmd_assoc_failure =
468*4882a593Smuzhiyun 			pmadapter->dbg.num_cmd_assoc_failure;
469*4882a593Smuzhiyun 		debug_info->num_cmd_timeout = pmadapter->num_cmd_timeout;
470*4882a593Smuzhiyun 		debug_info->timeout_cmd_id = pmadapter->dbg.timeout_cmd_id;
471*4882a593Smuzhiyun 		debug_info->timeout_cmd_act = pmadapter->dbg.timeout_cmd_act;
472*4882a593Smuzhiyun 		memcpy_ext(pmadapter, debug_info->last_cmd_id,
473*4882a593Smuzhiyun 			   pmadapter->dbg.last_cmd_id,
474*4882a593Smuzhiyun 			   sizeof(pmadapter->dbg.last_cmd_id),
475*4882a593Smuzhiyun 			   sizeof(debug_info->last_cmd_id));
476*4882a593Smuzhiyun 		memcpy_ext(pmadapter, debug_info->last_cmd_act,
477*4882a593Smuzhiyun 			   pmadapter->dbg.last_cmd_act,
478*4882a593Smuzhiyun 			   sizeof(pmadapter->dbg.last_cmd_act),
479*4882a593Smuzhiyun 			   sizeof(debug_info->last_cmd_act));
480*4882a593Smuzhiyun 		debug_info->last_cmd_index = pmadapter->dbg.last_cmd_index;
481*4882a593Smuzhiyun 		memcpy_ext(pmadapter, debug_info->last_cmd_resp_id,
482*4882a593Smuzhiyun 			   pmadapter->dbg.last_cmd_resp_id,
483*4882a593Smuzhiyun 			   sizeof(pmadapter->dbg.last_cmd_resp_id),
484*4882a593Smuzhiyun 			   sizeof(debug_info->last_cmd_resp_id));
485*4882a593Smuzhiyun 		debug_info->last_cmd_resp_index =
486*4882a593Smuzhiyun 			pmadapter->dbg.last_cmd_resp_index;
487*4882a593Smuzhiyun 		memcpy_ext(pmadapter, debug_info->last_event,
488*4882a593Smuzhiyun 			   pmadapter->dbg.last_event,
489*4882a593Smuzhiyun 			   sizeof(pmadapter->dbg.last_event),
490*4882a593Smuzhiyun 			   sizeof(debug_info->last_event));
491*4882a593Smuzhiyun 		debug_info->last_event_index = pmadapter->dbg.last_event_index;
492*4882a593Smuzhiyun 		debug_info->num_no_cmd_node = pmadapter->dbg.num_no_cmd_node;
493*4882a593Smuzhiyun 		debug_info->pending_cmd =
494*4882a593Smuzhiyun 			(pmadapter->curr_cmd) ?
495*4882a593Smuzhiyun 				pmadapter->dbg.last_cmd_id
496*4882a593Smuzhiyun 					[pmadapter->dbg.last_cmd_index] :
497*4882a593Smuzhiyun 				0;
498*4882a593Smuzhiyun 		debug_info->dnld_cmd_in_secs = pmadapter->dnld_cmd_in_secs;
499*4882a593Smuzhiyun #ifdef SDIO
500*4882a593Smuzhiyun 		if (IS_SD(pmadapter->card_type)) {
501*4882a593Smuzhiyun 			debug_info->num_cmdevt_card_to_host_failure =
502*4882a593Smuzhiyun 				pmadapter->dbg.num_cmdevt_card_to_host_failure;
503*4882a593Smuzhiyun 			debug_info->num_rx_card_to_host_failure =
504*4882a593Smuzhiyun 				pmadapter->dbg.num_rx_card_to_host_failure;
505*4882a593Smuzhiyun 			debug_info->num_int_read_failure =
506*4882a593Smuzhiyun 				pmadapter->dbg.num_int_read_failure;
507*4882a593Smuzhiyun 			debug_info->last_int_status =
508*4882a593Smuzhiyun 				pmadapter->dbg.last_int_status;
509*4882a593Smuzhiyun 			debug_info->mp_rd_bitmap =
510*4882a593Smuzhiyun 				pmadapter->pcard_sd->mp_rd_bitmap;
511*4882a593Smuzhiyun 			debug_info->mp_wr_bitmap =
512*4882a593Smuzhiyun 				pmadapter->pcard_sd->mp_wr_bitmap;
513*4882a593Smuzhiyun 			debug_info->curr_rd_port =
514*4882a593Smuzhiyun 				pmadapter->pcard_sd->curr_rd_port;
515*4882a593Smuzhiyun 			debug_info->curr_wr_port =
516*4882a593Smuzhiyun 				pmadapter->pcard_sd->curr_wr_port;
517*4882a593Smuzhiyun 			debug_info->mp_invalid_update =
518*4882a593Smuzhiyun 				pmadapter->pcard_sd->mp_invalid_update;
519*4882a593Smuzhiyun 			debug_info->num_of_irq =
520*4882a593Smuzhiyun 				pmadapter->pcard_sd->num_of_irq;
521*4882a593Smuzhiyun 			memcpy_ext(pmadapter, debug_info->mp_update,
522*4882a593Smuzhiyun 				   pmadapter->pcard_sd->mp_update,
523*4882a593Smuzhiyun 				   sizeof(pmadapter->pcard_sd->mp_update),
524*4882a593Smuzhiyun 				   sizeof(debug_info->mp_update));
525*4882a593Smuzhiyun 			memcpy_ext(pmadapter, debug_info->mpa_tx_count,
526*4882a593Smuzhiyun 				   pmadapter->pcard_sd->mpa_tx_count,
527*4882a593Smuzhiyun 				   sizeof(pmadapter->pcard_sd->mpa_tx_count),
528*4882a593Smuzhiyun 				   sizeof(debug_info->mpa_tx_count));
529*4882a593Smuzhiyun 			debug_info->mpa_sent_last_pkt =
530*4882a593Smuzhiyun 				pmadapter->pcard_sd->mpa_sent_last_pkt;
531*4882a593Smuzhiyun 			debug_info->mpa_sent_no_ports =
532*4882a593Smuzhiyun 				pmadapter->pcard_sd->mpa_sent_no_ports;
533*4882a593Smuzhiyun 			debug_info->last_recv_wr_bitmap =
534*4882a593Smuzhiyun 				pmadapter->pcard_sd->last_recv_wr_bitmap;
535*4882a593Smuzhiyun 			debug_info->last_recv_rd_bitmap =
536*4882a593Smuzhiyun 				pmadapter->pcard_sd->last_recv_rd_bitmap;
537*4882a593Smuzhiyun 			debug_info->mp_data_port_mask =
538*4882a593Smuzhiyun 				pmadapter->pcard_sd->mp_data_port_mask;
539*4882a593Smuzhiyun 			debug_info->last_mp_index =
540*4882a593Smuzhiyun 				pmadapter->pcard_sd->last_mp_index;
541*4882a593Smuzhiyun 			memcpy_ext(
542*4882a593Smuzhiyun 				pmadapter, debug_info->last_mp_wr_bitmap,
543*4882a593Smuzhiyun 				pmadapter->pcard_sd->last_mp_wr_bitmap,
544*4882a593Smuzhiyun 				sizeof(pmadapter->pcard_sd->last_mp_wr_bitmap),
545*4882a593Smuzhiyun 				sizeof(debug_info->last_mp_wr_bitmap));
546*4882a593Smuzhiyun 			memcpy_ext(
547*4882a593Smuzhiyun 				pmadapter, debug_info->last_mp_wr_ports,
548*4882a593Smuzhiyun 				pmadapter->pcard_sd->last_mp_wr_ports,
549*4882a593Smuzhiyun 				sizeof(pmadapter->pcard_sd->last_mp_wr_ports),
550*4882a593Smuzhiyun 				sizeof(debug_info->last_mp_wr_ports));
551*4882a593Smuzhiyun 			memcpy_ext(pmadapter, debug_info->last_mp_wr_len,
552*4882a593Smuzhiyun 				   pmadapter->pcard_sd->last_mp_wr_len,
553*4882a593Smuzhiyun 				   sizeof(pmadapter->pcard_sd->last_mp_wr_len),
554*4882a593Smuzhiyun 				   sizeof(debug_info->last_mp_wr_len));
555*4882a593Smuzhiyun 			memcpy_ext(pmadapter, debug_info->last_mp_wr_info,
556*4882a593Smuzhiyun 				   pmadapter->pcard_sd->last_mp_wr_info,
557*4882a593Smuzhiyun 				   sizeof(pmadapter->pcard_sd->last_mp_wr_info),
558*4882a593Smuzhiyun 				   sizeof(debug_info->last_mp_wr_info));
559*4882a593Smuzhiyun 			memcpy_ext(
560*4882a593Smuzhiyun 				pmadapter, debug_info->last_curr_wr_port,
561*4882a593Smuzhiyun 				pmadapter->pcard_sd->last_curr_wr_port,
562*4882a593Smuzhiyun 				sizeof(pmadapter->pcard_sd->last_curr_wr_port),
563*4882a593Smuzhiyun 				sizeof(debug_info->last_curr_wr_port));
564*4882a593Smuzhiyun 			debug_info->mpa_buf = pmadapter->pcard_sd->mpa_buf;
565*4882a593Smuzhiyun 			debug_info->mpa_buf_size =
566*4882a593Smuzhiyun 				pmadapter->pcard_sd->mpa_buf_size;
567*4882a593Smuzhiyun 			debug_info->sdio_rx_aggr =
568*4882a593Smuzhiyun 				pmadapter->pcard_sd->sdio_rx_aggr_enable;
569*4882a593Smuzhiyun 			memcpy_ext(pmadapter, debug_info->mpa_rx_count,
570*4882a593Smuzhiyun 				   pmadapter->pcard_sd->mpa_rx_count,
571*4882a593Smuzhiyun 				   sizeof(pmadapter->pcard_sd->mpa_rx_count),
572*4882a593Smuzhiyun 				   sizeof(debug_info->mpa_rx_count));
573*4882a593Smuzhiyun 			debug_info->mp_aggr_pkt_limit =
574*4882a593Smuzhiyun 				pmadapter->pcard_sd->mp_aggr_pkt_limit;
575*4882a593Smuzhiyun 		}
576*4882a593Smuzhiyun #endif
577*4882a593Smuzhiyun #ifdef PCIE
578*4882a593Smuzhiyun 		if (IS_PCIE(pmadapter->card_type)) {
579*4882a593Smuzhiyun 			debug_info->txbd_rdptr =
580*4882a593Smuzhiyun 				pmadapter->pcard_pcie->txbd_rdptr;
581*4882a593Smuzhiyun 			debug_info->txbd_wrptr =
582*4882a593Smuzhiyun 				pmadapter->pcard_pcie->txbd_wrptr;
583*4882a593Smuzhiyun 			debug_info->rxbd_rdptr =
584*4882a593Smuzhiyun 				pmadapter->pcard_pcie->rxbd_rdptr;
585*4882a593Smuzhiyun 			debug_info->rxbd_wrptr =
586*4882a593Smuzhiyun 				pmadapter->pcard_pcie->rxbd_wrptr;
587*4882a593Smuzhiyun 			debug_info->eventbd_rdptr =
588*4882a593Smuzhiyun 				pmadapter->pcard_pcie->evtbd_rdptr;
589*4882a593Smuzhiyun 			debug_info->eventbd_wrptr =
590*4882a593Smuzhiyun 				pmadapter->pcard_pcie->evtbd_wrptr;
591*4882a593Smuzhiyun 			debug_info->txbd_ring_vbase =
592*4882a593Smuzhiyun 				pmadapter->pcard_pcie->txbd_ring_vbase;
593*4882a593Smuzhiyun 			debug_info->txbd_ring_size =
594*4882a593Smuzhiyun 				pmadapter->pcard_pcie->txbd_ring_size;
595*4882a593Smuzhiyun 			debug_info->rxbd_ring_vbase =
596*4882a593Smuzhiyun 				pmadapter->pcard_pcie->rxbd_ring_vbase;
597*4882a593Smuzhiyun 			debug_info->rxbd_ring_size =
598*4882a593Smuzhiyun 				pmadapter->pcard_pcie->rxbd_ring_size;
599*4882a593Smuzhiyun 			debug_info->evtbd_ring_vbase =
600*4882a593Smuzhiyun 				pmadapter->pcard_pcie->evtbd_ring_vbase;
601*4882a593Smuzhiyun 			debug_info->evtbd_ring_size =
602*4882a593Smuzhiyun 				pmadapter->pcard_pcie->evtbd_ring_size;
603*4882a593Smuzhiyun 			debug_info->txrx_bd_size =
604*4882a593Smuzhiyun 				pmadapter->pcard_pcie->txrx_bd_size;
605*4882a593Smuzhiyun 		}
606*4882a593Smuzhiyun #endif
607*4882a593Smuzhiyun 		debug_info->data_sent = pmadapter->data_sent;
608*4882a593Smuzhiyun 		debug_info->data_sent_cnt = pmadapter->data_sent_cnt;
609*4882a593Smuzhiyun 		debug_info->cmd_sent = pmadapter->cmd_sent;
610*4882a593Smuzhiyun 		debug_info->cmd_resp_received = pmadapter->cmd_resp_received;
611*4882a593Smuzhiyun 		debug_info->tx_pkts_queued =
612*4882a593Smuzhiyun 			util_scalar_read(pmadapter->pmoal_handle,
613*4882a593Smuzhiyun 					 &pmpriv->wmm.tx_pkts_queued, MNULL,
614*4882a593Smuzhiyun 					 MNULL);
615*4882a593Smuzhiyun #ifdef UAP_SUPPORT
616*4882a593Smuzhiyun 		debug_info->num_bridge_pkts =
617*4882a593Smuzhiyun 			util_scalar_read(pmadapter->pmoal_handle,
618*4882a593Smuzhiyun 					 &pmadapter->pending_bridge_pkts,
619*4882a593Smuzhiyun 					 pmadapter->callbacks.moal_spin_lock,
620*4882a593Smuzhiyun 					 pmadapter->callbacks.moal_spin_unlock);
621*4882a593Smuzhiyun 		debug_info->num_drop_pkts = pmpriv->num_drop_pkts;
622*4882a593Smuzhiyun #endif
623*4882a593Smuzhiyun 		debug_info->fw_hang_report = pmadapter->fw_hang_report;
624*4882a593Smuzhiyun 		debug_info->mlan_processing = pmadapter->mlan_processing;
625*4882a593Smuzhiyun 		debug_info->mlan_rx_processing = pmadapter->mlan_rx_processing;
626*4882a593Smuzhiyun 		debug_info->rx_pkts_queued = pmadapter->rx_pkts_queued;
627*4882a593Smuzhiyun 		debug_info->mlan_adapter = pmadapter;
628*4882a593Smuzhiyun 		debug_info->mlan_adapter_size = sizeof(mlan_adapter);
629*4882a593Smuzhiyun 		debug_info->mlan_priv_num = pmadapter->priv_num;
630*4882a593Smuzhiyun 		for (i = 0; i < pmadapter->priv_num; i++) {
631*4882a593Smuzhiyun 			debug_info->mlan_priv[i] = pmadapter->priv[i];
632*4882a593Smuzhiyun 			debug_info->mlan_priv_size[i] = sizeof(mlan_private);
633*4882a593Smuzhiyun 		}
634*4882a593Smuzhiyun 	}
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun 	pioctl_req->data_read_written =
637*4882a593Smuzhiyun 		sizeof(mlan_debug_info) + MLAN_SUB_COMMAND_SIZE;
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun 	LEAVE();
640*4882a593Smuzhiyun 	return ret;
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun /**
644*4882a593Smuzhiyun  *  @brief Set/Get the MAC control configuration.
645*4882a593Smuzhiyun  *
646*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
647*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
648*4882a593Smuzhiyun  *
649*4882a593Smuzhiyun  *  @return             MLAN_STATUS_PENDING -- success, otherwise fail
650*4882a593Smuzhiyun  */
wlan_misc_ioctl_mac_control(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)651*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_mac_control(pmlan_adapter pmadapter,
652*4882a593Smuzhiyun 					pmlan_ioctl_req pioctl_req)
653*4882a593Smuzhiyun {
654*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
655*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
656*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
657*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun 	ENTER();
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_GET) {
664*4882a593Smuzhiyun 		misc->param.mac_ctrl = pmpriv->curr_pkt_filter;
665*4882a593Smuzhiyun 	} else {
666*4882a593Smuzhiyun 		pmpriv->curr_pkt_filter = misc->param.mac_ctrl;
667*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun 		/* Send command to firmware */
670*4882a593Smuzhiyun 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
671*4882a593Smuzhiyun 				       cmd_action, 0, (t_void *)pioctl_req,
672*4882a593Smuzhiyun 				       &misc->param.mac_ctrl);
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 		if (ret == MLAN_STATUS_SUCCESS)
675*4882a593Smuzhiyun 			ret = MLAN_STATUS_PENDING;
676*4882a593Smuzhiyun 	}
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun 	LEAVE();
679*4882a593Smuzhiyun 	return ret;
680*4882a593Smuzhiyun }
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun /**
683*4882a593Smuzhiyun  *  @brief This timer function handles wakeup card timeout.
684*4882a593Smuzhiyun  *
685*4882a593Smuzhiyun  *  @param function_context   A pointer to function_context
686*4882a593Smuzhiyun  *  @return        N/A
687*4882a593Smuzhiyun  */
wlan_wakeup_card_timeout_func(void * function_context)688*4882a593Smuzhiyun t_void wlan_wakeup_card_timeout_func(void *function_context)
689*4882a593Smuzhiyun {
690*4882a593Smuzhiyun 	pmlan_adapter pmadapter = (pmlan_adapter)function_context;
691*4882a593Smuzhiyun 	mlan_private *pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun 	ENTER();
694*4882a593Smuzhiyun 
695*4882a593Smuzhiyun 	PRINTM(MERROR, "%s: ps_state=%d\n", __FUNCTION__, pmadapter->ps_state);
696*4882a593Smuzhiyun 	if (pmadapter->ps_state != PS_STATE_AWAKE) {
697*4882a593Smuzhiyun 		PRINTM_NETINTF(MERROR, pmpriv);
698*4882a593Smuzhiyun 		PRINTM(MERROR, "Wakeup card timeout!\n");
699*4882a593Smuzhiyun 		pmadapter->pm_wakeup_timeout++;
700*4882a593Smuzhiyun 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
701*4882a593Smuzhiyun 	}
702*4882a593Smuzhiyun 	pmadapter->wakeup_fw_timer_is_set = MFALSE;
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun 	LEAVE();
705*4882a593Smuzhiyun }
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun /**
708*4882a593Smuzhiyun  *  @brief Set/Get HS configuration
709*4882a593Smuzhiyun  *
710*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
711*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
712*4882a593Smuzhiyun  *
713*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
714*4882a593Smuzhiyun  * otherwise fail
715*4882a593Smuzhiyun  */
wlan_pm_ioctl_hscfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)716*4882a593Smuzhiyun mlan_status wlan_pm_ioctl_hscfg(pmlan_adapter pmadapter,
717*4882a593Smuzhiyun 				pmlan_ioctl_req pioctl_req)
718*4882a593Smuzhiyun {
719*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
720*4882a593Smuzhiyun 	mlan_ds_pm_cfg *pm = MNULL;
721*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
722*4882a593Smuzhiyun 	t_u32 prev_cond = 0;
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun 	ENTER();
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun 	pm = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun 	switch (pioctl_req->action) {
729*4882a593Smuzhiyun 	case MLAN_ACT_SET:
730*4882a593Smuzhiyun #ifdef STA_SUPPORT
731*4882a593Smuzhiyun 		if (pmadapter->pps_uapsd_mode) {
732*4882a593Smuzhiyun 			PRINTM(MINFO,
733*4882a593Smuzhiyun 			       "Host Sleep IOCTL is blocked in UAPSD/PPS mode\n");
734*4882a593Smuzhiyun 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
735*4882a593Smuzhiyun 			status = MLAN_STATUS_FAILURE;
736*4882a593Smuzhiyun 			break;
737*4882a593Smuzhiyun 		}
738*4882a593Smuzhiyun #endif /* STA_SUPPORT */
739*4882a593Smuzhiyun 		if (pm->param.hs_cfg.is_invoke_hostcmd == MTRUE) {
740*4882a593Smuzhiyun 			if (pm->param.hs_cfg.conditions ==
741*4882a593Smuzhiyun 			    HOST_SLEEP_CFG_CANCEL) {
742*4882a593Smuzhiyun 				if (pmadapter->is_hs_configured == MFALSE) {
743*4882a593Smuzhiyun 					/* Already cancelled */
744*4882a593Smuzhiyun 					break;
745*4882a593Smuzhiyun 				}
746*4882a593Smuzhiyun 				/* Save previous condition */
747*4882a593Smuzhiyun 				prev_cond = pmadapter->hs_cfg.conditions;
748*4882a593Smuzhiyun 				pmadapter->hs_cfg.conditions =
749*4882a593Smuzhiyun 					pm->param.hs_cfg.conditions;
750*4882a593Smuzhiyun 			} else if (pmadapter->hs_cfg.conditions ==
751*4882a593Smuzhiyun 				   HOST_SLEEP_CFG_CANCEL) {
752*4882a593Smuzhiyun 				/* Return failure if no parameters for HS enable
753*4882a593Smuzhiyun 				 */
754*4882a593Smuzhiyun 				pioctl_req->status_code =
755*4882a593Smuzhiyun 					MLAN_ERROR_INVALID_PARAMETER;
756*4882a593Smuzhiyun 				status = MLAN_STATUS_FAILURE;
757*4882a593Smuzhiyun 				break;
758*4882a593Smuzhiyun 			}
759*4882a593Smuzhiyun 			status = wlan_prepare_cmd(
760*4882a593Smuzhiyun 				pmpriv, HostCmd_CMD_802_11_HS_CFG_ENH,
761*4882a593Smuzhiyun 				HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
762*4882a593Smuzhiyun 				(t_void *)(&pmadapter->hs_cfg));
763*4882a593Smuzhiyun 			if (status == MLAN_STATUS_SUCCESS)
764*4882a593Smuzhiyun 				status = MLAN_STATUS_PENDING;
765*4882a593Smuzhiyun 			if (pm->param.hs_cfg.conditions ==
766*4882a593Smuzhiyun 			    HOST_SLEEP_CFG_CANCEL) {
767*4882a593Smuzhiyun 				/* Restore previous condition */
768*4882a593Smuzhiyun 				pmadapter->hs_cfg.conditions = prev_cond;
769*4882a593Smuzhiyun 			}
770*4882a593Smuzhiyun 		} else {
771*4882a593Smuzhiyun 			pmadapter->hs_cfg.conditions =
772*4882a593Smuzhiyun 				pm->param.hs_cfg.conditions;
773*4882a593Smuzhiyun 			pmadapter->hs_cfg.gpio = (t_u8)pm->param.hs_cfg.gpio;
774*4882a593Smuzhiyun 			pmadapter->hs_cfg.gap = (t_u8)pm->param.hs_cfg.gap;
775*4882a593Smuzhiyun 			pmadapter->param_type_ind =
776*4882a593Smuzhiyun 				(t_u8)pm->param.hs_cfg.param_type_ind;
777*4882a593Smuzhiyun 			pmadapter->ind_gpio = (t_u8)pm->param.hs_cfg.ind_gpio;
778*4882a593Smuzhiyun 			pmadapter->level = (t_u8)pm->param.hs_cfg.level;
779*4882a593Smuzhiyun 			pmadapter->param_type_ext =
780*4882a593Smuzhiyun 				(t_u8)pm->param.hs_cfg.param_type_ext;
781*4882a593Smuzhiyun 			pmadapter->event_force_ignore =
782*4882a593Smuzhiyun 				pm->param.hs_cfg.event_force_ignore;
783*4882a593Smuzhiyun 			pmadapter->event_use_ext_gap =
784*4882a593Smuzhiyun 				pm->param.hs_cfg.event_use_ext_gap;
785*4882a593Smuzhiyun 			pmadapter->ext_gap = pm->param.hs_cfg.ext_gap;
786*4882a593Smuzhiyun 			pmadapter->gpio_wave = pm->param.hs_cfg.gpio_wave;
787*4882a593Smuzhiyun 			pmadapter->hs_wake_interval =
788*4882a593Smuzhiyun 				pm->param.hs_cfg.hs_wake_interval;
789*4882a593Smuzhiyun 			pmadapter->min_wake_holdoff =
790*4882a593Smuzhiyun 				pm->param.hs_cfg.min_wake_holdoff;
791*4882a593Smuzhiyun 		}
792*4882a593Smuzhiyun 		break;
793*4882a593Smuzhiyun 	case MLAN_ACT_GET:
794*4882a593Smuzhiyun 		pm->param.hs_cfg.conditions = pmadapter->hs_cfg.conditions;
795*4882a593Smuzhiyun 		pm->param.hs_cfg.gpio = pmadapter->hs_cfg.gpio;
796*4882a593Smuzhiyun 		pm->param.hs_cfg.gap = pmadapter->hs_cfg.gap;
797*4882a593Smuzhiyun 		pm->param.hs_cfg.param_type_ind = pmadapter->param_type_ind;
798*4882a593Smuzhiyun 		pm->param.hs_cfg.ind_gpio = pmadapter->ind_gpio;
799*4882a593Smuzhiyun 		pm->param.hs_cfg.level = pmadapter->level;
800*4882a593Smuzhiyun 		pm->param.hs_cfg.param_type_ext = pmadapter->param_type_ext;
801*4882a593Smuzhiyun 		pm->param.hs_cfg.event_force_ignore =
802*4882a593Smuzhiyun 			pmadapter->event_force_ignore;
803*4882a593Smuzhiyun 		pm->param.hs_cfg.event_use_ext_gap =
804*4882a593Smuzhiyun 			pmadapter->event_use_ext_gap;
805*4882a593Smuzhiyun 		pm->param.hs_cfg.ext_gap = pmadapter->ext_gap;
806*4882a593Smuzhiyun 		pm->param.hs_cfg.gpio_wave = pmadapter->gpio_wave;
807*4882a593Smuzhiyun 		pm->param.hs_cfg.hs_wake_interval = pmadapter->hs_wake_interval;
808*4882a593Smuzhiyun 		pm->param.hs_cfg.min_wake_holdoff = pmadapter->min_wake_holdoff;
809*4882a593Smuzhiyun 		break;
810*4882a593Smuzhiyun 	default:
811*4882a593Smuzhiyun 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
812*4882a593Smuzhiyun 		status = MLAN_STATUS_FAILURE;
813*4882a593Smuzhiyun 		break;
814*4882a593Smuzhiyun 	}
815*4882a593Smuzhiyun 
816*4882a593Smuzhiyun 	LEAVE();
817*4882a593Smuzhiyun 	return status;
818*4882a593Smuzhiyun }
819*4882a593Smuzhiyun 
820*4882a593Smuzhiyun /**
821*4882a593Smuzhiyun  *  @brief Set Robustcoex gpiocfg
822*4882a593Smuzhiyun  *
823*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
824*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
825*4882a593Smuzhiyun  *
826*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
827*4882a593Smuzhiyun  * otherwise fail
828*4882a593Smuzhiyun  */
wlan_misc_robustcoex(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)829*4882a593Smuzhiyun mlan_status wlan_misc_robustcoex(pmlan_adapter pmadapter,
830*4882a593Smuzhiyun 				 pmlan_ioctl_req pioctl_req)
831*4882a593Smuzhiyun {
832*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
833*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
834*4882a593Smuzhiyun 	t_u16 cmd_action;
835*4882a593Smuzhiyun 	mlan_ds_misc_cfg *robust_coex_cfg =
836*4882a593Smuzhiyun 		(mlan_ds_misc_cfg *)pioctl_req->pbuf;
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 	ENTER();
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
841*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
842*4882a593Smuzhiyun 	else
843*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
844*4882a593Smuzhiyun 
845*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_ROBUSTCOEX,
846*4882a593Smuzhiyun 			       cmd_action, 0, (t_void *)pioctl_req,
847*4882a593Smuzhiyun 			       &robust_coex_cfg->param.robustcoexparams);
848*4882a593Smuzhiyun 
849*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
850*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
851*4882a593Smuzhiyun 	LEAVE();
852*4882a593Smuzhiyun 	return ret;
853*4882a593Smuzhiyun }
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun /**
856*4882a593Smuzhiyun  *  @brief Set/get DMCS config
857*4882a593Smuzhiyun  *
858*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
859*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
860*4882a593Smuzhiyun  *
861*4882a593Smuzhiyun  *  @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
862*4882a593Smuzhiyun  */
wlan_misc_dmcs_config(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)863*4882a593Smuzhiyun mlan_status wlan_misc_dmcs_config(pmlan_adapter pmadapter,
864*4882a593Smuzhiyun 				  pmlan_ioctl_req pioctl_req)
865*4882a593Smuzhiyun {
866*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
867*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
868*4882a593Smuzhiyun 	t_u16 cmd_action;
869*4882a593Smuzhiyun 	mlan_ds_misc_cfg *dmcs_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun 	ENTER();
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
874*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
875*4882a593Smuzhiyun 	else
876*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_DMCS_CONFIG, cmd_action, 0,
879*4882a593Smuzhiyun 			       (t_void *)pioctl_req,
880*4882a593Smuzhiyun 			       &dmcs_cfg->param.dmcs_policy);
881*4882a593Smuzhiyun 
882*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
883*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
884*4882a593Smuzhiyun 	LEAVE();
885*4882a593Smuzhiyun 	return ret;
886*4882a593Smuzhiyun }
887*4882a593Smuzhiyun 
888*4882a593Smuzhiyun #if defined(PCIE)
889*4882a593Smuzhiyun /**
890*4882a593Smuzhiyun  *  @brief Enable SSU support
891*4882a593Smuzhiyun  *
892*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
893*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
894*4882a593Smuzhiyun  *
895*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
896*4882a593Smuzhiyun  * otherwise fail
897*4882a593Smuzhiyun  */
wlan_misc_ssu(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)898*4882a593Smuzhiyun mlan_status wlan_misc_ssu(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
899*4882a593Smuzhiyun {
900*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
901*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
902*4882a593Smuzhiyun 	t_u16 cmd_action = HostCmd_ACT_GEN_GET;
903*4882a593Smuzhiyun 	mlan_ds_misc_cfg *ssu_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
904*4882a593Smuzhiyun 
905*4882a593Smuzhiyun 	ENTER();
906*4882a593Smuzhiyun 
907*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
908*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
909*4882a593Smuzhiyun 	else if (pioctl_req->action == MLAN_ACT_DEFAULT)
910*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET_DEFAULT;
911*4882a593Smuzhiyun 	else if (pioctl_req->action == MLAN_ACT_GET)
912*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
913*4882a593Smuzhiyun 
914*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SSU, cmd_action, 0,
915*4882a593Smuzhiyun 			       (t_void *)pioctl_req,
916*4882a593Smuzhiyun 			       &ssu_cfg->param.ssu_params);
917*4882a593Smuzhiyun 
918*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
919*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
920*4882a593Smuzhiyun 	LEAVE();
921*4882a593Smuzhiyun 	return ret;
922*4882a593Smuzhiyun }
923*4882a593Smuzhiyun #endif
924*4882a593Smuzhiyun 
925*4882a593Smuzhiyun /**
926*4882a593Smuzhiyun  *  @brief Set the hal/phy cfg params.
927*4882a593Smuzhiyun  *
928*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
929*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
930*4882a593Smuzhiyun  *
931*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
932*4882a593Smuzhiyun  * otherwise fail
933*4882a593Smuzhiyun  */
wlan_misc_hal_phy_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)934*4882a593Smuzhiyun mlan_status wlan_misc_hal_phy_cfg(pmlan_adapter pmadapter,
935*4882a593Smuzhiyun 				  pmlan_ioctl_req pioctl_req)
936*4882a593Smuzhiyun {
937*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
938*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
939*4882a593Smuzhiyun 	mlan_ds_misc_cfg *hal_phy_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
940*4882a593Smuzhiyun 	t_u16 cmd_act;
941*4882a593Smuzhiyun 
942*4882a593Smuzhiyun 	ENTER();
943*4882a593Smuzhiyun 
944*4882a593Smuzhiyun 	cmd_act = HostCmd_ACT_GEN_SET;
945*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_HAL_PHY_CFG, cmd_act, 0,
946*4882a593Smuzhiyun 			       (t_void *)pioctl_req,
947*4882a593Smuzhiyun 			       &hal_phy_cfg->param.hal_phy_cfg_params);
948*4882a593Smuzhiyun 
949*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
950*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
951*4882a593Smuzhiyun 
952*4882a593Smuzhiyun 	LEAVE();
953*4882a593Smuzhiyun 	return ret;
954*4882a593Smuzhiyun }
955*4882a593Smuzhiyun 
956*4882a593Smuzhiyun /**
957*4882a593Smuzhiyun  *  @brief Enable/disable CSI support
958*4882a593Smuzhiyun  *
959*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
960*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
961*4882a593Smuzhiyun  *
962*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
963*4882a593Smuzhiyun  * otherwise fail
964*4882a593Smuzhiyun  */
wlan_misc_csi(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)965*4882a593Smuzhiyun mlan_status wlan_misc_csi(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
966*4882a593Smuzhiyun {
967*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
968*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
969*4882a593Smuzhiyun 	mlan_ds_misc_cfg *csi_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
970*4882a593Smuzhiyun 	t_u16 cmd_act;
971*4882a593Smuzhiyun 
972*4882a593Smuzhiyun 	ENTER();
973*4882a593Smuzhiyun 
974*4882a593Smuzhiyun 	if (csi_cfg->param.csi_params.csi_enable == 1) {
975*4882a593Smuzhiyun 		if (pmadapter->csi_enabled) {
976*4882a593Smuzhiyun 			PRINTM(MERROR,
977*4882a593Smuzhiyun 			       "Enable CSI: CSI was already enabled.\n");
978*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
979*4882a593Smuzhiyun 			goto done;
980*4882a593Smuzhiyun 		}
981*4882a593Smuzhiyun 		cmd_act = CSI_CMD_ENABLE;
982*4882a593Smuzhiyun 	} else {
983*4882a593Smuzhiyun 		if (!pmadapter->csi_enabled) {
984*4882a593Smuzhiyun 			PRINTM(MERROR,
985*4882a593Smuzhiyun 			       "Disable CSI: CSI was already disabled.\n");
986*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
987*4882a593Smuzhiyun 			goto done;
988*4882a593Smuzhiyun 		}
989*4882a593Smuzhiyun 		cmd_act = CSI_CMD_DISABLE;
990*4882a593Smuzhiyun 	}
991*4882a593Smuzhiyun 
992*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CSI, cmd_act, 0,
993*4882a593Smuzhiyun 			       (t_void *)pioctl_req,
994*4882a593Smuzhiyun 			       &csi_cfg->param.csi_params);
995*4882a593Smuzhiyun 
996*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
997*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
998*4882a593Smuzhiyun 
999*4882a593Smuzhiyun done:
1000*4882a593Smuzhiyun 	LEAVE();
1001*4882a593Smuzhiyun 	return ret;
1002*4882a593Smuzhiyun }
1003*4882a593Smuzhiyun 
1004*4882a593Smuzhiyun /**
1005*4882a593Smuzhiyun  *  @brief This function allocates a mlan_buffer.
1006*4882a593Smuzhiyun  *
1007*4882a593Smuzhiyun  *  @param pmadapter Pointer to mlan_adapter
1008*4882a593Smuzhiyun  *  @param data_len   Data length
1009*4882a593Smuzhiyun  *  @param head_room  head_room reserved in mlan_buffer
1010*4882a593Smuzhiyun  *  @param malloc_flag  flag to user moal_malloc
1011*4882a593Smuzhiyun  *  @return           mlan_buffer pointer or MNULL
1012*4882a593Smuzhiyun  */
wlan_alloc_mlan_buffer(mlan_adapter * pmadapter,t_u32 data_len,t_u32 head_room,t_u32 malloc_flag)1013*4882a593Smuzhiyun pmlan_buffer wlan_alloc_mlan_buffer(mlan_adapter *pmadapter, t_u32 data_len,
1014*4882a593Smuzhiyun 				    t_u32 head_room, t_u32 malloc_flag)
1015*4882a593Smuzhiyun {
1016*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
1017*4882a593Smuzhiyun 	pmlan_buffer pmbuf = MNULL;
1018*4882a593Smuzhiyun 	t_u32 buf_size = 0;
1019*4882a593Smuzhiyun 	t_u8 *tmp_buf = MNULL;
1020*4882a593Smuzhiyun 	pmlan_callbacks pcb = &pmadapter->callbacks;
1021*4882a593Smuzhiyun 	t_u32 mem_flags = MLAN_MEM_DEF | MLAN_MEM_DMA;
1022*4882a593Smuzhiyun 
1023*4882a593Smuzhiyun 	ENTER();
1024*4882a593Smuzhiyun 
1025*4882a593Smuzhiyun #ifdef SDIO
1026*4882a593Smuzhiyun 	/* make sure that the data length is at least SDIO block size */
1027*4882a593Smuzhiyun 	if (IS_SD(pmadapter->card_type))
1028*4882a593Smuzhiyun 		data_len = (data_len + MLAN_SDIO_BLOCK_SIZE - 1) /
1029*4882a593Smuzhiyun 			   MLAN_SDIO_BLOCK_SIZE * MLAN_SDIO_BLOCK_SIZE;
1030*4882a593Smuzhiyun #endif
1031*4882a593Smuzhiyun 
1032*4882a593Smuzhiyun 	/* head_room is not implemented for malloc mlan buffer */
1033*4882a593Smuzhiyun 	if (malloc_flag & MOAL_MALLOC_BUFFER) {
1034*4882a593Smuzhiyun 		buf_size = sizeof(mlan_buffer) + data_len + DMA_ALIGNMENT;
1035*4882a593Smuzhiyun 		if (malloc_flag & MOAL_MEM_FLAG_ATOMIC)
1036*4882a593Smuzhiyun 			mem_flags |= MLAN_MEM_FLAG_ATOMIC;
1037*4882a593Smuzhiyun 		ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size,
1038*4882a593Smuzhiyun 				       mem_flags, (t_u8 **)&pmbuf);
1039*4882a593Smuzhiyun 		if ((ret != MLAN_STATUS_SUCCESS) || !pmbuf) {
1040*4882a593Smuzhiyun 			pmbuf = MNULL;
1041*4882a593Smuzhiyun 			goto exit;
1042*4882a593Smuzhiyun 		}
1043*4882a593Smuzhiyun 		memset(pmadapter, pmbuf, 0, sizeof(mlan_buffer));
1044*4882a593Smuzhiyun 
1045*4882a593Smuzhiyun 		pmbuf->pdesc = MNULL;
1046*4882a593Smuzhiyun 		/* Align address */
1047*4882a593Smuzhiyun 		pmbuf->pbuf = (t_u8 *)ALIGN_ADDR(
1048*4882a593Smuzhiyun 			(t_u8 *)pmbuf + sizeof(mlan_buffer), DMA_ALIGNMENT);
1049*4882a593Smuzhiyun 		pmbuf->data_offset = 0;
1050*4882a593Smuzhiyun 		pmbuf->data_len = data_len;
1051*4882a593Smuzhiyun 		pmbuf->flags |= MLAN_BUF_FLAG_MALLOC_BUF;
1052*4882a593Smuzhiyun 	} else if (malloc_flag & MOAL_ALLOC_MLAN_BUFFER) {
1053*4882a593Smuzhiyun 		/* use moal_alloc_mlan_buffer, head_room supported */
1054*4882a593Smuzhiyun 		ret = pcb->moal_alloc_mlan_buffer(
1055*4882a593Smuzhiyun 			pmadapter->pmoal_handle,
1056*4882a593Smuzhiyun 			data_len + DMA_ALIGNMENT + head_room, &pmbuf);
1057*4882a593Smuzhiyun 		if ((ret != MLAN_STATUS_SUCCESS) || !pmbuf) {
1058*4882a593Smuzhiyun 			PRINTM(MERROR, "Failed to allocate 'mlan_buffer'\n");
1059*4882a593Smuzhiyun 			goto exit;
1060*4882a593Smuzhiyun 		}
1061*4882a593Smuzhiyun 		pmbuf->data_offset = head_room;
1062*4882a593Smuzhiyun 		tmp_buf = (t_u8 *)ALIGN_ADDR(pmbuf->pbuf + pmbuf->data_offset,
1063*4882a593Smuzhiyun 					     DMA_ALIGNMENT);
1064*4882a593Smuzhiyun 		pmbuf->data_offset +=
1065*4882a593Smuzhiyun 			(t_u32)(tmp_buf - (pmbuf->pbuf + pmbuf->data_offset));
1066*4882a593Smuzhiyun 		pmbuf->data_len = data_len;
1067*4882a593Smuzhiyun 		pmbuf->flags = 0;
1068*4882a593Smuzhiyun 	}
1069*4882a593Smuzhiyun 
1070*4882a593Smuzhiyun exit:
1071*4882a593Smuzhiyun 	LEAVE();
1072*4882a593Smuzhiyun 	return pmbuf;
1073*4882a593Smuzhiyun }
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun /**
1076*4882a593Smuzhiyun  *  @brief This function frees a mlan_buffer.
1077*4882a593Smuzhiyun  *
1078*4882a593Smuzhiyun  *  @param pmadapter  Pointer to mlan_adapter
1079*4882a593Smuzhiyun  *  @param pmbuf      Pointer to mlan_buffer
1080*4882a593Smuzhiyun  *
1081*4882a593Smuzhiyun  *  @return           N/A
1082*4882a593Smuzhiyun  */
wlan_free_mlan_buffer(mlan_adapter * pmadapter,pmlan_buffer pmbuf)1083*4882a593Smuzhiyun t_void wlan_free_mlan_buffer(mlan_adapter *pmadapter, pmlan_buffer pmbuf)
1084*4882a593Smuzhiyun {
1085*4882a593Smuzhiyun 	pmlan_callbacks pcb = &pmadapter->callbacks;
1086*4882a593Smuzhiyun 	ENTER();
1087*4882a593Smuzhiyun 
1088*4882a593Smuzhiyun 	if (pcb && pmbuf) {
1089*4882a593Smuzhiyun 		if (pmbuf->flags & MLAN_BUF_FLAG_BRIDGE_BUF)
1090*4882a593Smuzhiyun 			util_scalar_decrement(
1091*4882a593Smuzhiyun 				pmadapter->pmoal_handle,
1092*4882a593Smuzhiyun 				&pmadapter->pending_bridge_pkts,
1093*4882a593Smuzhiyun 				pmadapter->callbacks.moal_spin_lock,
1094*4882a593Smuzhiyun 				pmadapter->callbacks.moal_spin_unlock);
1095*4882a593Smuzhiyun 		if (pmbuf->flags & MLAN_BUF_FLAG_MALLOC_BUF)
1096*4882a593Smuzhiyun 			pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmbuf);
1097*4882a593Smuzhiyun 		else
1098*4882a593Smuzhiyun 			pcb->moal_free_mlan_buffer(pmadapter->pmoal_handle,
1099*4882a593Smuzhiyun 						   pmbuf);
1100*4882a593Smuzhiyun 	}
1101*4882a593Smuzhiyun 
1102*4882a593Smuzhiyun 	LEAVE();
1103*4882a593Smuzhiyun 	return;
1104*4882a593Smuzhiyun }
1105*4882a593Smuzhiyun 
1106*4882a593Smuzhiyun /**
1107*4882a593Smuzhiyun  *  @brief Delay function implementation
1108*4882a593Smuzhiyun  *
1109*4882a593Smuzhiyun  *  @param pmadapter        A pointer to mlan_adapter structure
1110*4882a593Smuzhiyun  *  @param delay            Delay value
1111*4882a593Smuzhiyun  *  @param u                Units of delay (sec, msec or usec)
1112*4882a593Smuzhiyun  *
1113*4882a593Smuzhiyun  *  @return                 N/A
1114*4882a593Smuzhiyun  */
wlan_delay_func(mlan_adapter * pmadapter,t_u32 delay,t_delay_unit u)1115*4882a593Smuzhiyun t_void wlan_delay_func(mlan_adapter *pmadapter, t_u32 delay, t_delay_unit u)
1116*4882a593Smuzhiyun {
1117*4882a593Smuzhiyun 	t_u32 now_tv_sec, now_tv_usec;
1118*4882a593Smuzhiyun 	t_u32 upto_tv_sec, upto_tv_usec;
1119*4882a593Smuzhiyun 	pmlan_callbacks pcb = &pmadapter->callbacks;
1120*4882a593Smuzhiyun 
1121*4882a593Smuzhiyun 	ENTER();
1122*4882a593Smuzhiyun 
1123*4882a593Smuzhiyun 	if (pcb->moal_udelay) {
1124*4882a593Smuzhiyun 		if (u == SEC)
1125*4882a593Smuzhiyun 			delay *= 1000000;
1126*4882a593Smuzhiyun 		else if (u == MSEC)
1127*4882a593Smuzhiyun 			delay *= 1000;
1128*4882a593Smuzhiyun 		pcb->moal_udelay(pmadapter->pmoal_handle, delay);
1129*4882a593Smuzhiyun 	} else {
1130*4882a593Smuzhiyun 		pcb->moal_get_system_time(pmadapter->pmoal_handle, &upto_tv_sec,
1131*4882a593Smuzhiyun 					  &upto_tv_usec);
1132*4882a593Smuzhiyun 
1133*4882a593Smuzhiyun 		switch (u) {
1134*4882a593Smuzhiyun 		case SEC:
1135*4882a593Smuzhiyun 			upto_tv_sec += delay;
1136*4882a593Smuzhiyun 			break;
1137*4882a593Smuzhiyun 		case MSEC:
1138*4882a593Smuzhiyun 			delay *= 1000;
1139*4882a593Smuzhiyun 			/* fall through */
1140*4882a593Smuzhiyun 		case USEC:
1141*4882a593Smuzhiyun 			upto_tv_sec += (delay / 1000000);
1142*4882a593Smuzhiyun 			upto_tv_usec += (delay % 1000000);
1143*4882a593Smuzhiyun 			break;
1144*4882a593Smuzhiyun 		}
1145*4882a593Smuzhiyun 
1146*4882a593Smuzhiyun 		do {
1147*4882a593Smuzhiyun 			pcb->moal_get_system_time(pmadapter->pmoal_handle,
1148*4882a593Smuzhiyun 						  &now_tv_sec, &now_tv_usec);
1149*4882a593Smuzhiyun 			if (now_tv_sec > upto_tv_sec) {
1150*4882a593Smuzhiyun 				LEAVE();
1151*4882a593Smuzhiyun 				return;
1152*4882a593Smuzhiyun 			}
1153*4882a593Smuzhiyun 
1154*4882a593Smuzhiyun 			if ((now_tv_sec == upto_tv_sec) &&
1155*4882a593Smuzhiyun 			    (now_tv_usec >= upto_tv_usec)) {
1156*4882a593Smuzhiyun 				LEAVE();
1157*4882a593Smuzhiyun 				return;
1158*4882a593Smuzhiyun 			}
1159*4882a593Smuzhiyun 		} while (MTRUE);
1160*4882a593Smuzhiyun 	}
1161*4882a593Smuzhiyun 
1162*4882a593Smuzhiyun 	LEAVE();
1163*4882a593Smuzhiyun 	return;
1164*4882a593Smuzhiyun }
1165*4882a593Smuzhiyun 
1166*4882a593Smuzhiyun /**
1167*4882a593Smuzhiyun  *  @brief BSS remove
1168*4882a593Smuzhiyun  *
1169*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
1170*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
1171*4882a593Smuzhiyun  *
1172*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, MLAN_STATUS_FAILURE
1173*4882a593Smuzhiyun  */
wlan_bss_ioctl_bss_remove(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1174*4882a593Smuzhiyun mlan_status wlan_bss_ioctl_bss_remove(pmlan_adapter pmadapter,
1175*4882a593Smuzhiyun 				      pmlan_ioctl_req pioctl_req)
1176*4882a593Smuzhiyun {
1177*4882a593Smuzhiyun 	ENTER();
1178*4882a593Smuzhiyun 	wlan_cancel_bss_pending_cmd(pmadapter, pioctl_req->bss_index);
1179*4882a593Smuzhiyun 	LEAVE();
1180*4882a593Smuzhiyun 	return MLAN_STATUS_SUCCESS;
1181*4882a593Smuzhiyun }
1182*4882a593Smuzhiyun 
1183*4882a593Smuzhiyun #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
1184*4882a593Smuzhiyun /**
1185*4882a593Smuzhiyun  *  @brief Set/Get BSS role
1186*4882a593Smuzhiyun  *
1187*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
1188*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
1189*4882a593Smuzhiyun  *
1190*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, MLAN_STATUS_FAILURE
1191*4882a593Smuzhiyun  */
wlan_bss_ioctl_bss_role(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1192*4882a593Smuzhiyun mlan_status wlan_bss_ioctl_bss_role(pmlan_adapter pmadapter,
1193*4882a593Smuzhiyun 				    pmlan_ioctl_req pioctl_req)
1194*4882a593Smuzhiyun {
1195*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1196*4882a593Smuzhiyun 	mlan_ds_bss *bss = MNULL;
1197*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
1198*4882a593Smuzhiyun 	HostCmd_DS_VERSION_EXT dummy;
1199*4882a593Smuzhiyun #ifdef USB
1200*4882a593Smuzhiyun 	pmlan_callbacks pcb = &pmadapter->callbacks;
1201*4882a593Smuzhiyun 	pmlan_buffer pmbuf;
1202*4882a593Smuzhiyun #endif
1203*4882a593Smuzhiyun #if defined(WIFI_DIRECT_SUPPORT)
1204*4882a593Smuzhiyun 	t_u8 bss_mode;
1205*4882a593Smuzhiyun #endif
1206*4882a593Smuzhiyun 	t_u8 i, global_band = 0;
1207*4882a593Smuzhiyun 	int j;
1208*4882a593Smuzhiyun 
1209*4882a593Smuzhiyun 	ENTER();
1210*4882a593Smuzhiyun 
1211*4882a593Smuzhiyun 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
1212*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_GET) {
1213*4882a593Smuzhiyun 		bss->param.bss_role = GET_BSS_ROLE(pmpriv);
1214*4882a593Smuzhiyun 	} else {
1215*4882a593Smuzhiyun 		if (GET_BSS_ROLE(pmpriv) == bss->param.bss_role) {
1216*4882a593Smuzhiyun 			PRINTM(MIOCTL, "BSS ie already in the desired role!\n");
1217*4882a593Smuzhiyun 			goto done;
1218*4882a593Smuzhiyun 		}
1219*4882a593Smuzhiyun 		mlan_block_rx_process(pmadapter, MTRUE);
1220*4882a593Smuzhiyun 		/** Switch BSS role */
1221*4882a593Smuzhiyun 		wlan_free_priv(pmpriv);
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun #ifdef USB
1224*4882a593Smuzhiyun 		if (IS_USB(pmadapter->card_type)) {
1225*4882a593Smuzhiyun 			while ((pmbuf = (pmlan_buffer)util_dequeue_list(
1226*4882a593Smuzhiyun 					pmadapter->pmoal_handle,
1227*4882a593Smuzhiyun 					&pmadapter->rx_data_queue,
1228*4882a593Smuzhiyun 					pcb->moal_spin_lock,
1229*4882a593Smuzhiyun 					pcb->moal_spin_unlock))) {
1230*4882a593Smuzhiyun 				pcb->moal_recv_complete(pmadapter->pmoal_handle,
1231*4882a593Smuzhiyun 							pmbuf,
1232*4882a593Smuzhiyun 							pmadapter->rx_data_ep,
1233*4882a593Smuzhiyun 							MLAN_STATUS_FAILURE);
1234*4882a593Smuzhiyun 			}
1235*4882a593Smuzhiyun 		}
1236*4882a593Smuzhiyun #endif
1237*4882a593Smuzhiyun 		pmpriv->bss_role = bss->param.bss_role;
1238*4882a593Smuzhiyun 		if (pmpriv->bss_type == MLAN_BSS_TYPE_UAP)
1239*4882a593Smuzhiyun 			pmpriv->bss_type = MLAN_BSS_TYPE_STA;
1240*4882a593Smuzhiyun 		else if (pmpriv->bss_type == MLAN_BSS_TYPE_STA)
1241*4882a593Smuzhiyun 			pmpriv->bss_type = MLAN_BSS_TYPE_UAP;
1242*4882a593Smuzhiyun 		/* Initialize private structures */
1243*4882a593Smuzhiyun 		wlan_init_priv(pmpriv);
1244*4882a593Smuzhiyun 		/* restore mac address */
1245*4882a593Smuzhiyun 		memcpy_ext(pmpriv->adapter, pmpriv->curr_addr,
1246*4882a593Smuzhiyun 			   pmpriv->adapter->permanent_addr,
1247*4882a593Smuzhiyun 			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
1248*4882a593Smuzhiyun 		mlan_block_rx_process(pmadapter, MFALSE);
1249*4882a593Smuzhiyun 		/* Initialize function table */
1250*4882a593Smuzhiyun 		for (j = 0; mlan_ops[j]; j++) {
1251*4882a593Smuzhiyun 			if (mlan_ops[j]->bss_role == GET_BSS_ROLE(pmpriv)) {
1252*4882a593Smuzhiyun 				memcpy_ext(pmadapter, &pmpriv->ops, mlan_ops[j],
1253*4882a593Smuzhiyun 					   sizeof(mlan_operations),
1254*4882a593Smuzhiyun 					   sizeof(mlan_operations));
1255*4882a593Smuzhiyun 			}
1256*4882a593Smuzhiyun 		}
1257*4882a593Smuzhiyun 
1258*4882a593Smuzhiyun 		for (i = 0; i < pmadapter->priv_num; i++) {
1259*4882a593Smuzhiyun 			if (pmadapter->priv[i] &&
1260*4882a593Smuzhiyun 			    GET_BSS_ROLE(pmadapter->priv[i]) ==
1261*4882a593Smuzhiyun 				    MLAN_BSS_ROLE_STA)
1262*4882a593Smuzhiyun 				global_band |= pmadapter->priv[i]->config_bands;
1263*4882a593Smuzhiyun 		}
1264*4882a593Smuzhiyun 
1265*4882a593Smuzhiyun 		if (global_band != pmadapter->config_bands) {
1266*4882a593Smuzhiyun 			if (wlan_set_regiontable(
1267*4882a593Smuzhiyun 				    pmpriv, (t_u8)pmadapter->region_code,
1268*4882a593Smuzhiyun 				    global_band |
1269*4882a593Smuzhiyun 					    pmadapter->adhoc_start_band)) {
1270*4882a593Smuzhiyun 				pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
1271*4882a593Smuzhiyun 				LEAVE();
1272*4882a593Smuzhiyun 				return MLAN_STATUS_FAILURE;
1273*4882a593Smuzhiyun 			}
1274*4882a593Smuzhiyun 
1275*4882a593Smuzhiyun 			if (wlan_11d_set_universaltable(
1276*4882a593Smuzhiyun 				    pmpriv,
1277*4882a593Smuzhiyun 				    global_band |
1278*4882a593Smuzhiyun 					    pmadapter->adhoc_start_band)) {
1279*4882a593Smuzhiyun 				pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
1280*4882a593Smuzhiyun 				LEAVE();
1281*4882a593Smuzhiyun 				return MLAN_STATUS_FAILURE;
1282*4882a593Smuzhiyun 			}
1283*4882a593Smuzhiyun 			pmadapter->config_bands = global_band;
1284*4882a593Smuzhiyun 		}
1285*4882a593Smuzhiyun 
1286*4882a593Smuzhiyun 		/* Issue commands to initialize firmware */
1287*4882a593Smuzhiyun #if defined(WIFI_DIRECT_SUPPORT)
1288*4882a593Smuzhiyun 		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA)
1289*4882a593Smuzhiyun 			bss_mode = BSS_MODE_WIFIDIRECT_CLIENT;
1290*4882a593Smuzhiyun 		else
1291*4882a593Smuzhiyun 			bss_mode = BSS_MODE_WIFIDIRECT_GO;
1292*4882a593Smuzhiyun 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SET_BSS_MODE,
1293*4882a593Smuzhiyun 				       HostCmd_ACT_GEN_SET, 0, MNULL,
1294*4882a593Smuzhiyun 				       &bss_mode);
1295*4882a593Smuzhiyun 		if (ret)
1296*4882a593Smuzhiyun 			goto done;
1297*4882a593Smuzhiyun #endif
1298*4882a593Smuzhiyun 		ret = pmpriv->ops.init_cmd(pmpriv, MFALSE);
1299*4882a593Smuzhiyun 		if (ret == MLAN_STATUS_FAILURE)
1300*4882a593Smuzhiyun 			goto done;
1301*4882a593Smuzhiyun 
1302*4882a593Smuzhiyun 		/* Issue dummy Get command to complete the ioctl */
1303*4882a593Smuzhiyun 		memset(pmadapter, &dummy, 0, sizeof(HostCmd_DS_VERSION_EXT));
1304*4882a593Smuzhiyun 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_VERSION_EXT,
1305*4882a593Smuzhiyun 				       HostCmd_ACT_GEN_GET, 0,
1306*4882a593Smuzhiyun 				       (t_void *)pioctl_req, (t_void *)&dummy);
1307*4882a593Smuzhiyun 		if (ret == MLAN_STATUS_SUCCESS)
1308*4882a593Smuzhiyun 			ret = MLAN_STATUS_PENDING;
1309*4882a593Smuzhiyun 	}
1310*4882a593Smuzhiyun 
1311*4882a593Smuzhiyun done:
1312*4882a593Smuzhiyun 	LEAVE();
1313*4882a593Smuzhiyun 	return ret;
1314*4882a593Smuzhiyun }
1315*4882a593Smuzhiyun #endif
1316*4882a593Smuzhiyun 
1317*4882a593Smuzhiyun /**
1318*4882a593Smuzhiyun  *  @brief Set the custom IE
1319*4882a593Smuzhiyun  *
1320*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
1321*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
1322*4882a593Smuzhiyun  *  @param send_ioctl	Flag to indicate if ioctl should be sent with cmd
1323*4882a593Smuzhiyun  *                      (MTRUE if from moal/user, MFALSE if internal)
1324*4882a593Smuzhiyun  *
1325*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
1326*4882a593Smuzhiyun  */
wlan_misc_ioctl_custom_ie_list(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req,t_bool send_ioctl)1327*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_custom_ie_list(pmlan_adapter pmadapter,
1328*4882a593Smuzhiyun 					   pmlan_ioctl_req pioctl_req,
1329*4882a593Smuzhiyun 					   t_bool send_ioctl)
1330*4882a593Smuzhiyun {
1331*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1332*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
1333*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
1334*4882a593Smuzhiyun 	custom_ie *ie_data = MNULL;
1335*4882a593Smuzhiyun 	t_u16 cmd_action = 0, index, mask, i, len, app_data_len;
1336*4882a593Smuzhiyun 	t_s32 ioctl_len;
1337*4882a593Smuzhiyun 	t_u8 *tmp_ie;
1338*4882a593Smuzhiyun 
1339*4882a593Smuzhiyun 	ENTER();
1340*4882a593Smuzhiyun 
1341*4882a593Smuzhiyun 	if ((misc->param.cust_ie.len == 0) ||
1342*4882a593Smuzhiyun 	    (misc->param.cust_ie.len == sizeof(t_u16))) {
1343*4882a593Smuzhiyun 		pioctl_req->action = MLAN_ACT_GET;
1344*4882a593Smuzhiyun 		/* Get the IE */
1345*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
1346*4882a593Smuzhiyun 	} else {
1347*4882a593Smuzhiyun 		/* ioctl_len : ioctl length from application, start with
1348*4882a593Smuzhiyun 		 * misc->param.cust_ie.len and reach upto 0 */
1349*4882a593Smuzhiyun 		ioctl_len = misc->param.cust_ie.len;
1350*4882a593Smuzhiyun 
1351*4882a593Smuzhiyun 		/* app_data_len : length from application, start with 0
1352*4882a593Smuzhiyun 		 * and reach upto ioctl_len */
1353*4882a593Smuzhiyun 		app_data_len = sizeof(MrvlIEtypesHeader_t);
1354*4882a593Smuzhiyun 		misc->param.cust_ie.len = 0;
1355*4882a593Smuzhiyun 
1356*4882a593Smuzhiyun 		while (ioctl_len > 0) {
1357*4882a593Smuzhiyun 			ie_data = (custom_ie *)(((t_u8 *)&misc->param.cust_ie) +
1358*4882a593Smuzhiyun 						app_data_len);
1359*4882a593Smuzhiyun 			ioctl_len -=
1360*4882a593Smuzhiyun 				(ie_data->ie_length + MLAN_CUSTOM_IE_HDR_SIZE);
1361*4882a593Smuzhiyun 			app_data_len +=
1362*4882a593Smuzhiyun 				(ie_data->ie_length + MLAN_CUSTOM_IE_HDR_SIZE);
1363*4882a593Smuzhiyun 
1364*4882a593Smuzhiyun 			index = ie_data->ie_index;
1365*4882a593Smuzhiyun 			mask = ie_data->mgmt_subtype_mask;
1366*4882a593Smuzhiyun 
1367*4882a593Smuzhiyun 			/* Need to be Autohandled */
1368*4882a593Smuzhiyun 			if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == index) {
1369*4882a593Smuzhiyun 				/* Automatic Deletion */
1370*4882a593Smuzhiyun 				if (mask == MLAN_CUSTOM_IE_DELETE_MASK) {
1371*4882a593Smuzhiyun 					ret = wlan_custom_ioctl_auto_delete(
1372*4882a593Smuzhiyun 						pmpriv, pioctl_req, ie_data,
1373*4882a593Smuzhiyun 						index);
1374*4882a593Smuzhiyun 					/* if IE to delete is not found, return
1375*4882a593Smuzhiyun 					 * error */
1376*4882a593Smuzhiyun 					if (ret == MLAN_STATUS_FAILURE)
1377*4882a593Smuzhiyun 						goto done;
1378*4882a593Smuzhiyun 					index = ie_data->ie_index;
1379*4882a593Smuzhiyun 					memset(pmadapter, ie_data, 0,
1380*4882a593Smuzhiyun 					       sizeof(custom_ie) *
1381*4882a593Smuzhiyun 						       MAX_MGMT_IE_INDEX_TO_FW);
1382*4882a593Smuzhiyun 					len = 0;
1383*4882a593Smuzhiyun 					for (i = 0;
1384*4882a593Smuzhiyun 					     i < pmadapter->max_mgmt_ie_index;
1385*4882a593Smuzhiyun 					     i++) {
1386*4882a593Smuzhiyun 						/* Check if index is updated
1387*4882a593Smuzhiyun 						 * before sending to FW */
1388*4882a593Smuzhiyun 						if (index & ((t_u16)1) << i) {
1389*4882a593Smuzhiyun 							memcpy_ext(
1390*4882a593Smuzhiyun 								pmadapter,
1391*4882a593Smuzhiyun 								(t_u8 *)ie_data +
1392*4882a593Smuzhiyun 									len,
1393*4882a593Smuzhiyun 								&i,
1394*4882a593Smuzhiyun 								sizeof(ie_data->ie_index),
1395*4882a593Smuzhiyun 								sizeof(ie_data->ie_index));
1396*4882a593Smuzhiyun 							len += sizeof(
1397*4882a593Smuzhiyun 								ie_data->ie_index);
1398*4882a593Smuzhiyun 							memcpy_ext(
1399*4882a593Smuzhiyun 								pmadapter,
1400*4882a593Smuzhiyun 								(t_u8 *)ie_data +
1401*4882a593Smuzhiyun 									len,
1402*4882a593Smuzhiyun 								&pmpriv->mgmt_ie[i]
1403*4882a593Smuzhiyun 									 .mgmt_subtype_mask,
1404*4882a593Smuzhiyun 								sizeof(ie_data->mgmt_subtype_mask),
1405*4882a593Smuzhiyun 								sizeof(ie_data->mgmt_subtype_mask));
1406*4882a593Smuzhiyun 							len += sizeof(
1407*4882a593Smuzhiyun 								ie_data->mgmt_subtype_mask);
1408*4882a593Smuzhiyun 							memcpy_ext(
1409*4882a593Smuzhiyun 								pmadapter,
1410*4882a593Smuzhiyun 								(t_u8 *)ie_data +
1411*4882a593Smuzhiyun 									len,
1412*4882a593Smuzhiyun 								&pmpriv->mgmt_ie[i]
1413*4882a593Smuzhiyun 									 .ie_length,
1414*4882a593Smuzhiyun 								sizeof(ie_data->ie_length),
1415*4882a593Smuzhiyun 								sizeof(ie_data->ie_length));
1416*4882a593Smuzhiyun 							len += sizeof(
1417*4882a593Smuzhiyun 								ie_data->ie_length);
1418*4882a593Smuzhiyun 							if (pmpriv->mgmt_ie[i]
1419*4882a593Smuzhiyun 								    .ie_length) {
1420*4882a593Smuzhiyun 								memcpy_ext(
1421*4882a593Smuzhiyun 									pmadapter,
1422*4882a593Smuzhiyun 									(t_u8 *)ie_data +
1423*4882a593Smuzhiyun 										len,
1424*4882a593Smuzhiyun 									&pmpriv->mgmt_ie[i]
1425*4882a593Smuzhiyun 										 .ie_buffer,
1426*4882a593Smuzhiyun 									pmpriv->mgmt_ie[i]
1427*4882a593Smuzhiyun 										.ie_length,
1428*4882a593Smuzhiyun 									pmpriv->mgmt_ie[i]
1429*4882a593Smuzhiyun 										.ie_length);
1430*4882a593Smuzhiyun 								len += pmpriv->mgmt_ie[i]
1431*4882a593Smuzhiyun 									       .ie_length;
1432*4882a593Smuzhiyun 							}
1433*4882a593Smuzhiyun 						}
1434*4882a593Smuzhiyun 					}
1435*4882a593Smuzhiyun 					misc->param.cust_ie.len += len;
1436*4882a593Smuzhiyun 					pioctl_req->action = MLAN_ACT_SET;
1437*4882a593Smuzhiyun 					cmd_action = HostCmd_ACT_GEN_SET;
1438*4882a593Smuzhiyun 				} else { /* Automatic Addition */
1439*4882a593Smuzhiyun 					if (MLAN_STATUS_FAILURE ==
1440*4882a593Smuzhiyun 					    wlan_custom_ioctl_get_autoidx(
1441*4882a593Smuzhiyun 						    pmpriv, pioctl_req, mask,
1442*4882a593Smuzhiyun 						    ie_data, &index)) {
1443*4882a593Smuzhiyun 						PRINTM(MERROR,
1444*4882a593Smuzhiyun 						       "Failed to Set the IE buffer\n");
1445*4882a593Smuzhiyun 						ret = MLAN_STATUS_FAILURE;
1446*4882a593Smuzhiyun 						goto done;
1447*4882a593Smuzhiyun 					}
1448*4882a593Smuzhiyun 					mask &= ~MLAN_CUSTOM_IE_NEW_MASK;
1449*4882a593Smuzhiyun 					if (MLAN_CUSTOM_IE_AUTO_IDX_MASK ==
1450*4882a593Smuzhiyun 						    index ||
1451*4882a593Smuzhiyun 					    index >= MAX_MGMT_IE_INDEX) {
1452*4882a593Smuzhiyun 						ret = MLAN_STATUS_SUCCESS;
1453*4882a593Smuzhiyun 						goto done;
1454*4882a593Smuzhiyun 					}
1455*4882a593Smuzhiyun 					tmp_ie = (t_u8 *)&pmpriv->mgmt_ie[index]
1456*4882a593Smuzhiyun 							 .ie_buffer;
1457*4882a593Smuzhiyun 					memcpy_ext(
1458*4882a593Smuzhiyun 						pmadapter,
1459*4882a593Smuzhiyun 						tmp_ie + pmpriv->mgmt_ie[index]
1460*4882a593Smuzhiyun 								 .ie_length,
1461*4882a593Smuzhiyun 						&ie_data->ie_buffer,
1462*4882a593Smuzhiyun 						ie_data->ie_length,
1463*4882a593Smuzhiyun 						ie_data->ie_length);
1464*4882a593Smuzhiyun 					pmpriv->mgmt_ie[index].ie_length +=
1465*4882a593Smuzhiyun 						ie_data->ie_length;
1466*4882a593Smuzhiyun 					pmpriv->mgmt_ie[index].ie_index = index;
1467*4882a593Smuzhiyun 					pmpriv->mgmt_ie[index]
1468*4882a593Smuzhiyun 						.mgmt_subtype_mask = mask;
1469*4882a593Smuzhiyun 
1470*4882a593Smuzhiyun 					pioctl_req->action = MLAN_ACT_SET;
1471*4882a593Smuzhiyun 					cmd_action = HostCmd_ACT_GEN_SET;
1472*4882a593Smuzhiyun 					ie_data->ie_index = index;
1473*4882a593Smuzhiyun 					ie_data->ie_length =
1474*4882a593Smuzhiyun 						pmpriv->mgmt_ie[index].ie_length;
1475*4882a593Smuzhiyun 					memcpy_ext(
1476*4882a593Smuzhiyun 						pmadapter, &ie_data->ie_buffer,
1477*4882a593Smuzhiyun 						&pmpriv->mgmt_ie[index]
1478*4882a593Smuzhiyun 							 .ie_buffer,
1479*4882a593Smuzhiyun 						pmpriv->mgmt_ie[index].ie_length,
1480*4882a593Smuzhiyun 						MAX_IE_SIZE);
1481*4882a593Smuzhiyun 					misc->param.cust_ie.len +=
1482*4882a593Smuzhiyun 						pmpriv->mgmt_ie[index]
1483*4882a593Smuzhiyun 							.ie_length +
1484*4882a593Smuzhiyun 						MLAN_CUSTOM_IE_HDR_SIZE;
1485*4882a593Smuzhiyun 				}
1486*4882a593Smuzhiyun 			} else {
1487*4882a593Smuzhiyun 				if (index >= pmadapter->max_mgmt_ie_index ||
1488*4882a593Smuzhiyun 				    index >= MAX_MGMT_IE_INDEX) {
1489*4882a593Smuzhiyun 					PRINTM(MERROR,
1490*4882a593Smuzhiyun 					       "Invalid custom IE index %d\n",
1491*4882a593Smuzhiyun 					       index);
1492*4882a593Smuzhiyun 					ret = MLAN_STATUS_FAILURE;
1493*4882a593Smuzhiyun 					goto done;
1494*4882a593Smuzhiyun 				}
1495*4882a593Smuzhiyun 				/* Set/Clear the IE and save it */
1496*4882a593Smuzhiyun 				if (ie_data->mgmt_subtype_mask ==
1497*4882a593Smuzhiyun 					    MLAN_CUSTOM_IE_DELETE_MASK &&
1498*4882a593Smuzhiyun 				    ie_data->ie_length) {
1499*4882a593Smuzhiyun 					PRINTM(MINFO, "Clear the IE buffer\n");
1500*4882a593Smuzhiyun 					ret = wlan_custom_ioctl_auto_delete(
1501*4882a593Smuzhiyun 						pmpriv, pioctl_req, ie_data,
1502*4882a593Smuzhiyun 						index);
1503*4882a593Smuzhiyun 					/* if IE to delete is not found, return
1504*4882a593Smuzhiyun 					 * error */
1505*4882a593Smuzhiyun 					if (ret == MLAN_STATUS_FAILURE)
1506*4882a593Smuzhiyun 						goto done;
1507*4882a593Smuzhiyun 					memset(pmadapter, ie_data, 0,
1508*4882a593Smuzhiyun 					       sizeof(custom_ie) *
1509*4882a593Smuzhiyun 						       MAX_MGMT_IE_INDEX_TO_FW);
1510*4882a593Smuzhiyun 					memcpy_ext(
1511*4882a593Smuzhiyun 						pmadapter, (t_u8 *)ie_data,
1512*4882a593Smuzhiyun 						&pmpriv->mgmt_ie[index],
1513*4882a593Smuzhiyun 						pmpriv->mgmt_ie[index].ie_length +
1514*4882a593Smuzhiyun 							MLAN_CUSTOM_IE_HDR_SIZE,
1515*4882a593Smuzhiyun 						pmpriv->mgmt_ie[index].ie_length +
1516*4882a593Smuzhiyun 							MLAN_CUSTOM_IE_HDR_SIZE);
1517*4882a593Smuzhiyun 				} else {
1518*4882a593Smuzhiyun 					/*
1519*4882a593Smuzhiyun 					 * Check if this index is being used on
1520*4882a593Smuzhiyun 					 * any other interfaces. If yes, then
1521*4882a593Smuzhiyun 					 * the request needs to be rejected.
1522*4882a593Smuzhiyun 					 */
1523*4882a593Smuzhiyun 					ret = wlan_is_custom_ie_index_unused(
1524*4882a593Smuzhiyun 						pmpriv, index);
1525*4882a593Smuzhiyun 					if (ret == MLAN_STATUS_FAILURE) {
1526*4882a593Smuzhiyun 						PRINTM(MERROR,
1527*4882a593Smuzhiyun 						       "IE index is used by other interface.\n");
1528*4882a593Smuzhiyun 						PRINTM(MERROR,
1529*4882a593Smuzhiyun 						       "Set or delete on index %d is not allowed.\n",
1530*4882a593Smuzhiyun 						       index);
1531*4882a593Smuzhiyun 						pioctl_req->status_code =
1532*4882a593Smuzhiyun 							MLAN_ERROR_IOCTL_FAIL;
1533*4882a593Smuzhiyun 						goto done;
1534*4882a593Smuzhiyun 					}
1535*4882a593Smuzhiyun 					PRINTM(MINFO, "Set the IE buffer\n");
1536*4882a593Smuzhiyun 					if (ie_data->mgmt_subtype_mask ==
1537*4882a593Smuzhiyun 					    MLAN_CUSTOM_IE_DELETE_MASK)
1538*4882a593Smuzhiyun 						ie_data->ie_length = 0;
1539*4882a593Smuzhiyun 					else {
1540*4882a593Smuzhiyun 						if ((pmpriv->mgmt_ie[index]
1541*4882a593Smuzhiyun 							     .mgmt_subtype_mask ==
1542*4882a593Smuzhiyun 						     ie_data->mgmt_subtype_mask) &&
1543*4882a593Smuzhiyun 						    (pmpriv->mgmt_ie[index]
1544*4882a593Smuzhiyun 							     .ie_length ==
1545*4882a593Smuzhiyun 						     ie_data->ie_length) &&
1546*4882a593Smuzhiyun 						    !memcmp(pmpriv->adapter,
1547*4882a593Smuzhiyun 							    pmpriv->mgmt_ie[index]
1548*4882a593Smuzhiyun 								    .ie_buffer,
1549*4882a593Smuzhiyun 							    ie_data->ie_buffer,
1550*4882a593Smuzhiyun 							    ie_data->ie_length)) {
1551*4882a593Smuzhiyun 							PRINTM(MIOCTL,
1552*4882a593Smuzhiyun 							       "same custom ie already configured!\n");
1553*4882a593Smuzhiyun 							if (ioctl_len <= 0 &&
1554*4882a593Smuzhiyun 							    misc->param.cust_ie
1555*4882a593Smuzhiyun 									    .len ==
1556*4882a593Smuzhiyun 								    0) {
1557*4882a593Smuzhiyun 								goto done;
1558*4882a593Smuzhiyun 							} else {
1559*4882a593Smuzhiyun 								/* remove
1560*4882a593Smuzhiyun 								 * matching IE
1561*4882a593Smuzhiyun 								 * from app
1562*4882a593Smuzhiyun 								 * buffer */
1563*4882a593Smuzhiyun 								app_data_len -=
1564*4882a593Smuzhiyun 									ie_data->ie_length +
1565*4882a593Smuzhiyun 									MLAN_CUSTOM_IE_HDR_SIZE;
1566*4882a593Smuzhiyun 								memmove(pmadapter,
1567*4882a593Smuzhiyun 									(t_u8 *)ie_data,
1568*4882a593Smuzhiyun 									ie_data->ie_buffer +
1569*4882a593Smuzhiyun 										ie_data->ie_length,
1570*4882a593Smuzhiyun 									ioctl_len);
1571*4882a593Smuzhiyun 								continue;
1572*4882a593Smuzhiyun 							}
1573*4882a593Smuzhiyun 						}
1574*4882a593Smuzhiyun 					}
1575*4882a593Smuzhiyun 					memset(pmadapter,
1576*4882a593Smuzhiyun 					       &pmpriv->mgmt_ie[index], 0,
1577*4882a593Smuzhiyun 					       sizeof(custom_ie));
1578*4882a593Smuzhiyun 					memcpy_ext(pmadapter,
1579*4882a593Smuzhiyun 						   &pmpriv->mgmt_ie[index],
1580*4882a593Smuzhiyun 						   ie_data, sizeof(custom_ie),
1581*4882a593Smuzhiyun 						   sizeof(custom_ie));
1582*4882a593Smuzhiyun 				}
1583*4882a593Smuzhiyun 
1584*4882a593Smuzhiyun 				misc->param.cust_ie.len +=
1585*4882a593Smuzhiyun 					pmpriv->mgmt_ie[index].ie_length +
1586*4882a593Smuzhiyun 					MLAN_CUSTOM_IE_HDR_SIZE;
1587*4882a593Smuzhiyun 				pioctl_req->action = MLAN_ACT_SET;
1588*4882a593Smuzhiyun 				cmd_action = HostCmd_ACT_GEN_SET;
1589*4882a593Smuzhiyun 			}
1590*4882a593Smuzhiyun 		}
1591*4882a593Smuzhiyun 	}
1592*4882a593Smuzhiyun 
1593*4882a593Smuzhiyun 	/* Send command to firmware */
1594*4882a593Smuzhiyun 	if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
1595*4882a593Smuzhiyun 		ret = wlan_prepare_cmd(
1596*4882a593Smuzhiyun 			pmpriv, HostCmd_CMD_MGMT_IE_LIST, cmd_action, 0,
1597*4882a593Smuzhiyun 			(send_ioctl) ? (t_void *)pioctl_req : MNULL,
1598*4882a593Smuzhiyun 			&misc->param.cust_ie);
1599*4882a593Smuzhiyun 	}
1600*4882a593Smuzhiyun #ifdef UAP_SUPPORT
1601*4882a593Smuzhiyun 	else if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
1602*4882a593Smuzhiyun 		ret = wlan_prepare_cmd(
1603*4882a593Smuzhiyun 			pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action, 0,
1604*4882a593Smuzhiyun 			(send_ioctl) ? (t_void *)pioctl_req : MNULL,
1605*4882a593Smuzhiyun 			(send_ioctl) ? MNULL : &misc->param.cust_ie);
1606*4882a593Smuzhiyun 	}
1607*4882a593Smuzhiyun #endif
1608*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
1609*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
1610*4882a593Smuzhiyun done:
1611*4882a593Smuzhiyun 	LEAVE();
1612*4882a593Smuzhiyun 	return ret;
1613*4882a593Smuzhiyun }
1614*4882a593Smuzhiyun 
1615*4882a593Smuzhiyun /**
1616*4882a593Smuzhiyun  *  @brief Read/write adapter register
1617*4882a593Smuzhiyun  *
1618*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
1619*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
1620*4882a593Smuzhiyun  *
1621*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
1622*4882a593Smuzhiyun  */
wlan_reg_mem_ioctl_reg_rw(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1623*4882a593Smuzhiyun mlan_status wlan_reg_mem_ioctl_reg_rw(pmlan_adapter pmadapter,
1624*4882a593Smuzhiyun 				      pmlan_ioctl_req pioctl_req)
1625*4882a593Smuzhiyun {
1626*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1627*4882a593Smuzhiyun 	mlan_ds_reg_mem *reg_mem = MNULL;
1628*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
1629*4882a593Smuzhiyun 	t_u16 cmd_action = 0, cmd_no;
1630*4882a593Smuzhiyun 
1631*4882a593Smuzhiyun 	ENTER();
1632*4882a593Smuzhiyun 
1633*4882a593Smuzhiyun 	reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
1634*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_GET)
1635*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
1636*4882a593Smuzhiyun 	else
1637*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
1638*4882a593Smuzhiyun 
1639*4882a593Smuzhiyun 	switch (reg_mem->param.reg_rw.type) {
1640*4882a593Smuzhiyun 	case MLAN_REG_MAC:
1641*4882a593Smuzhiyun #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
1642*4882a593Smuzhiyun 	defined(PCIE9097) || defined(USB9097) || defined(SDNW62X) ||           \
1643*4882a593Smuzhiyun 	defined(PCIENW62X) || defined(USBNW62X) || defined(SD9097)
1644*4882a593Smuzhiyun 	case MLAN_REG_MAC2:
1645*4882a593Smuzhiyun #endif
1646*4882a593Smuzhiyun 		cmd_no = HostCmd_CMD_MAC_REG_ACCESS;
1647*4882a593Smuzhiyun 		break;
1648*4882a593Smuzhiyun 	case MLAN_REG_BBP:
1649*4882a593Smuzhiyun #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
1650*4882a593Smuzhiyun 	defined(PCIE9097) || defined(USB9097) || defined(SDNW62X) ||           \
1651*4882a593Smuzhiyun 	defined(PCIENW62X) || defined(USBNW62X) || defined(SD9097)
1652*4882a593Smuzhiyun 	case MLAN_REG_BBP2:
1653*4882a593Smuzhiyun #endif
1654*4882a593Smuzhiyun 		cmd_no = HostCmd_CMD_BBP_REG_ACCESS;
1655*4882a593Smuzhiyun 		break;
1656*4882a593Smuzhiyun 	case MLAN_REG_RF:
1657*4882a593Smuzhiyun #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
1658*4882a593Smuzhiyun 	defined(PCIE9097) || defined(USB9097) || defined(SDNW62X) ||           \
1659*4882a593Smuzhiyun 	defined(PCIENW62X) || defined(USBNW62X) || defined(SD9097)
1660*4882a593Smuzhiyun 	case MLAN_REG_RF2:
1661*4882a593Smuzhiyun #endif
1662*4882a593Smuzhiyun 		cmd_no = HostCmd_CMD_RF_REG_ACCESS;
1663*4882a593Smuzhiyun 		break;
1664*4882a593Smuzhiyun 	case MLAN_REG_CAU:
1665*4882a593Smuzhiyun 		cmd_no = HostCmd_CMD_CAU_REG_ACCESS;
1666*4882a593Smuzhiyun 		break;
1667*4882a593Smuzhiyun 	case MLAN_REG_PSU:
1668*4882a593Smuzhiyun 		cmd_no = HostCmd_CMD_TARGET_ACCESS;
1669*4882a593Smuzhiyun 		break;
1670*4882a593Smuzhiyun 	case MLAN_REG_BCA:
1671*4882a593Smuzhiyun #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
1672*4882a593Smuzhiyun 	defined(PCIE9097) || defined(USB9097) || defined(SDNW62X) ||           \
1673*4882a593Smuzhiyun 	defined(PCIENW62X) || defined(USBNW62X) || defined(SD9097)
1674*4882a593Smuzhiyun 	case MLAN_REG_BCA2:
1675*4882a593Smuzhiyun #endif
1676*4882a593Smuzhiyun 		cmd_no = HostCmd_CMD_BCA_REG_ACCESS;
1677*4882a593Smuzhiyun 		break;
1678*4882a593Smuzhiyun #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
1679*4882a593Smuzhiyun 	defined(PCIE9097) || defined(USB9097) || defined(SDNW62X) ||           \
1680*4882a593Smuzhiyun 	defined(PCIENW62X) || defined(USBNW62X) || defined(SD9097) ||          \
1681*4882a593Smuzhiyun 	defined(SD9177)
1682*4882a593Smuzhiyun 	case MLAN_REG_CIU:
1683*4882a593Smuzhiyun 		cmd_no = HostCmd_CMD_REG_ACCESS;
1684*4882a593Smuzhiyun 		break;
1685*4882a593Smuzhiyun #endif
1686*4882a593Smuzhiyun 	default:
1687*4882a593Smuzhiyun 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1688*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
1689*4882a593Smuzhiyun 		goto exit;
1690*4882a593Smuzhiyun 	}
1691*4882a593Smuzhiyun 
1692*4882a593Smuzhiyun 	/* Send request to firmware */
1693*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, cmd_no, cmd_action, 0,
1694*4882a593Smuzhiyun 			       (t_void *)pioctl_req,
1695*4882a593Smuzhiyun 			       (t_void *)&reg_mem->param.reg_rw);
1696*4882a593Smuzhiyun 
1697*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
1698*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
1699*4882a593Smuzhiyun 
1700*4882a593Smuzhiyun exit:
1701*4882a593Smuzhiyun 	LEAVE();
1702*4882a593Smuzhiyun 	return ret;
1703*4882a593Smuzhiyun }
1704*4882a593Smuzhiyun 
1705*4882a593Smuzhiyun /**
1706*4882a593Smuzhiyun  *  @brief Read the EEPROM contents of the card
1707*4882a593Smuzhiyun  *
1708*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
1709*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
1710*4882a593Smuzhiyun  *
1711*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
1712*4882a593Smuzhiyun  */
wlan_reg_mem_ioctl_read_eeprom(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1713*4882a593Smuzhiyun mlan_status wlan_reg_mem_ioctl_read_eeprom(pmlan_adapter pmadapter,
1714*4882a593Smuzhiyun 					   pmlan_ioctl_req pioctl_req)
1715*4882a593Smuzhiyun {
1716*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1717*4882a593Smuzhiyun 	mlan_ds_reg_mem *reg_mem = MNULL;
1718*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
1719*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
1720*4882a593Smuzhiyun 
1721*4882a593Smuzhiyun 	ENTER();
1722*4882a593Smuzhiyun 
1723*4882a593Smuzhiyun 	reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
1724*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_GET)
1725*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
1726*4882a593Smuzhiyun 
1727*4882a593Smuzhiyun 	/* Send request to firmware */
1728*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_EEPROM_ACCESS,
1729*4882a593Smuzhiyun 			       cmd_action, 0, (t_void *)pioctl_req,
1730*4882a593Smuzhiyun 			       (t_void *)&reg_mem->param.rd_eeprom);
1731*4882a593Smuzhiyun 
1732*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
1733*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
1734*4882a593Smuzhiyun 
1735*4882a593Smuzhiyun 	LEAVE();
1736*4882a593Smuzhiyun 	return ret;
1737*4882a593Smuzhiyun }
1738*4882a593Smuzhiyun 
1739*4882a593Smuzhiyun /**
1740*4882a593Smuzhiyun  *  @brief Read/write memory of device
1741*4882a593Smuzhiyun  *
1742*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
1743*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
1744*4882a593Smuzhiyun  *
1745*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
1746*4882a593Smuzhiyun  */
wlan_reg_mem_ioctl_mem_rw(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1747*4882a593Smuzhiyun mlan_status wlan_reg_mem_ioctl_mem_rw(pmlan_adapter pmadapter,
1748*4882a593Smuzhiyun 				      pmlan_ioctl_req pioctl_req)
1749*4882a593Smuzhiyun {
1750*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1751*4882a593Smuzhiyun 	mlan_ds_reg_mem *reg_mem = MNULL;
1752*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
1753*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
1754*4882a593Smuzhiyun 
1755*4882a593Smuzhiyun 	ENTER();
1756*4882a593Smuzhiyun 
1757*4882a593Smuzhiyun 	reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
1758*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_GET)
1759*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
1760*4882a593Smuzhiyun 	else
1761*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
1762*4882a593Smuzhiyun 
1763*4882a593Smuzhiyun 	/* Send request to firmware */
1764*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MEM_ACCESS, cmd_action, 0,
1765*4882a593Smuzhiyun 			       (t_void *)pioctl_req,
1766*4882a593Smuzhiyun 			       (t_void *)&reg_mem->param.mem_rw);
1767*4882a593Smuzhiyun 
1768*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
1769*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
1770*4882a593Smuzhiyun 
1771*4882a593Smuzhiyun 	LEAVE();
1772*4882a593Smuzhiyun 	return ret;
1773*4882a593Smuzhiyun }
1774*4882a593Smuzhiyun 
1775*4882a593Smuzhiyun /**
1776*4882a593Smuzhiyun  *  @brief This function will check if station list is empty
1777*4882a593Smuzhiyun  *
1778*4882a593Smuzhiyun  *  @param priv    A pointer to mlan_private
1779*4882a593Smuzhiyun  *
1780*4882a593Smuzhiyun  *  @return	   MFALSE/MTRUE
1781*4882a593Smuzhiyun  */
wlan_is_station_list_empty(mlan_private * priv)1782*4882a593Smuzhiyun t_u8 wlan_is_station_list_empty(mlan_private *priv)
1783*4882a593Smuzhiyun {
1784*4882a593Smuzhiyun 	ENTER();
1785*4882a593Smuzhiyun 	if (!(util_peek_list(priv->adapter->pmoal_handle, &priv->sta_list,
1786*4882a593Smuzhiyun 			     priv->adapter->callbacks.moal_spin_lock,
1787*4882a593Smuzhiyun 			     priv->adapter->callbacks.moal_spin_unlock))) {
1788*4882a593Smuzhiyun 		LEAVE();
1789*4882a593Smuzhiyun 		return MTRUE;
1790*4882a593Smuzhiyun 	}
1791*4882a593Smuzhiyun 	LEAVE();
1792*4882a593Smuzhiyun 	return MFALSE;
1793*4882a593Smuzhiyun }
1794*4882a593Smuzhiyun 
1795*4882a593Smuzhiyun /**
1796*4882a593Smuzhiyun  *  @brief This function will return the pointer to station entry in station
1797*4882a593Smuzhiyun  * list table which matches the give mac address
1798*4882a593Smuzhiyun  *
1799*4882a593Smuzhiyun  *  @param priv    A pointer to mlan_private
1800*4882a593Smuzhiyun  *  @param mac     mac address to find in station list table
1801*4882a593Smuzhiyun  *
1802*4882a593Smuzhiyun  *  @return	   A pointer to structure sta_node
1803*4882a593Smuzhiyun  */
wlan_get_station_entry(mlan_private * priv,t_u8 * mac)1804*4882a593Smuzhiyun sta_node *wlan_get_station_entry(mlan_private *priv, t_u8 *mac)
1805*4882a593Smuzhiyun {
1806*4882a593Smuzhiyun 	sta_node *sta_ptr;
1807*4882a593Smuzhiyun 
1808*4882a593Smuzhiyun 	ENTER();
1809*4882a593Smuzhiyun 
1810*4882a593Smuzhiyun 	if (!mac) {
1811*4882a593Smuzhiyun 		LEAVE();
1812*4882a593Smuzhiyun 		return MNULL;
1813*4882a593Smuzhiyun 	}
1814*4882a593Smuzhiyun 	sta_ptr = (sta_node *)util_peek_list(priv->adapter->pmoal_handle,
1815*4882a593Smuzhiyun 					     &priv->sta_list, MNULL, MNULL);
1816*4882a593Smuzhiyun 
1817*4882a593Smuzhiyun 	while (sta_ptr && (sta_ptr != (sta_node *)&priv->sta_list)) {
1818*4882a593Smuzhiyun 		if (!memcmp(priv->adapter, sta_ptr->mac_addr, mac,
1819*4882a593Smuzhiyun 			    MLAN_MAC_ADDR_LENGTH)) {
1820*4882a593Smuzhiyun 			LEAVE();
1821*4882a593Smuzhiyun 			return sta_ptr;
1822*4882a593Smuzhiyun 		}
1823*4882a593Smuzhiyun 		sta_ptr = sta_ptr->pnext;
1824*4882a593Smuzhiyun 	}
1825*4882a593Smuzhiyun 	LEAVE();
1826*4882a593Smuzhiyun 	return MNULL;
1827*4882a593Smuzhiyun }
1828*4882a593Smuzhiyun 
1829*4882a593Smuzhiyun /**
1830*4882a593Smuzhiyun  *  @brief This function will add a pointer to station entry in station list
1831*4882a593Smuzhiyun  *          table with the give mac address, if it does not exist already
1832*4882a593Smuzhiyun  *
1833*4882a593Smuzhiyun  *  @param priv    A pointer to mlan_private
1834*4882a593Smuzhiyun  *  @param mac     mac address to find in station list table
1835*4882a593Smuzhiyun  *
1836*4882a593Smuzhiyun  *  @return	   A pointer to structure sta_node
1837*4882a593Smuzhiyun  */
wlan_add_station_entry(mlan_private * priv,t_u8 * mac)1838*4882a593Smuzhiyun sta_node *wlan_add_station_entry(mlan_private *priv, t_u8 *mac)
1839*4882a593Smuzhiyun {
1840*4882a593Smuzhiyun 	sta_node *sta_ptr = MNULL;
1841*4882a593Smuzhiyun 
1842*4882a593Smuzhiyun 	ENTER();
1843*4882a593Smuzhiyun 
1844*4882a593Smuzhiyun 	sta_ptr = wlan_get_station_entry(priv, mac);
1845*4882a593Smuzhiyun 	if (sta_ptr)
1846*4882a593Smuzhiyun 		goto done;
1847*4882a593Smuzhiyun 	if (priv->adapter->callbacks.moal_malloc(priv->adapter->pmoal_handle,
1848*4882a593Smuzhiyun 						 sizeof(sta_node), MLAN_MEM_DEF,
1849*4882a593Smuzhiyun 						 (t_u8 **)&sta_ptr)) {
1850*4882a593Smuzhiyun 		PRINTM(MERROR, "Failed to allocate memory for station node\n");
1851*4882a593Smuzhiyun 		LEAVE();
1852*4882a593Smuzhiyun 		return MNULL;
1853*4882a593Smuzhiyun 	}
1854*4882a593Smuzhiyun 	memset(priv->adapter, sta_ptr, 0, sizeof(sta_node));
1855*4882a593Smuzhiyun 	memcpy_ext(priv->adapter, sta_ptr->mac_addr, mac, MLAN_MAC_ADDR_LENGTH,
1856*4882a593Smuzhiyun 		   MLAN_MAC_ADDR_LENGTH);
1857*4882a593Smuzhiyun 	util_enqueue_list_tail(priv->adapter->pmoal_handle, &priv->sta_list,
1858*4882a593Smuzhiyun 			       (pmlan_linked_list)sta_ptr,
1859*4882a593Smuzhiyun 			       priv->adapter->callbacks.moal_spin_lock,
1860*4882a593Smuzhiyun 			       priv->adapter->callbacks.moal_spin_unlock);
1861*4882a593Smuzhiyun #ifdef DRV_EMBEDDED_AUTHENTICATOR
1862*4882a593Smuzhiyun 	if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
1863*4882a593Smuzhiyun 	    IsAuthenticatorEnabled(priv->psapriv))
1864*4882a593Smuzhiyun 		authenticator_init_client(priv->psapriv,
1865*4882a593Smuzhiyun 					  &sta_ptr->cm_connectioninfo, mac);
1866*4882a593Smuzhiyun #endif
1867*4882a593Smuzhiyun done:
1868*4882a593Smuzhiyun 	LEAVE();
1869*4882a593Smuzhiyun 	return sta_ptr;
1870*4882a593Smuzhiyun }
1871*4882a593Smuzhiyun 
1872*4882a593Smuzhiyun /**
1873*4882a593Smuzhiyun  *  @brief This function will delete a station entry from station list
1874*4882a593Smuzhiyun  *
1875*4882a593Smuzhiyun  *
1876*4882a593Smuzhiyun  *  @param priv    A pointer to mlan_private
1877*4882a593Smuzhiyun  *  @param mac     station's mac address
1878*4882a593Smuzhiyun  *
1879*4882a593Smuzhiyun  *  @return	   N/A
1880*4882a593Smuzhiyun  */
wlan_delete_station_entry(mlan_private * priv,t_u8 * mac)1881*4882a593Smuzhiyun t_void wlan_delete_station_entry(mlan_private *priv, t_u8 *mac)
1882*4882a593Smuzhiyun {
1883*4882a593Smuzhiyun 	sta_node *sta_ptr = MNULL;
1884*4882a593Smuzhiyun 	ENTER();
1885*4882a593Smuzhiyun 	sta_ptr = wlan_get_station_entry(priv, mac);
1886*4882a593Smuzhiyun 	if (sta_ptr) {
1887*4882a593Smuzhiyun #ifdef DRV_EMBEDDED_AUTHENTICATOR
1888*4882a593Smuzhiyun 		if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
1889*4882a593Smuzhiyun 		    IsAuthenticatorEnabled(priv->psapriv))
1890*4882a593Smuzhiyun 			authenticator_free_client(priv->psapriv,
1891*4882a593Smuzhiyun 						  sta_ptr->cm_connectioninfo);
1892*4882a593Smuzhiyun #endif
1893*4882a593Smuzhiyun 		util_unlink_list(priv->adapter->pmoal_handle, &priv->sta_list,
1894*4882a593Smuzhiyun 				 (pmlan_linked_list)sta_ptr,
1895*4882a593Smuzhiyun 				 priv->adapter->callbacks.moal_spin_lock,
1896*4882a593Smuzhiyun 				 priv->adapter->callbacks.moal_spin_unlock);
1897*4882a593Smuzhiyun 		priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle,
1898*4882a593Smuzhiyun 						    (t_u8 *)sta_ptr);
1899*4882a593Smuzhiyun 	}
1900*4882a593Smuzhiyun 
1901*4882a593Smuzhiyun 	LEAVE();
1902*4882a593Smuzhiyun 	return;
1903*4882a593Smuzhiyun }
1904*4882a593Smuzhiyun 
1905*4882a593Smuzhiyun /**
1906*4882a593Smuzhiyun  *  @brief Clean up wapi station list
1907*4882a593Smuzhiyun  *
1908*4882a593Smuzhiyun  *  @param priv  Pointer to the mlan_private driver data struct
1909*4882a593Smuzhiyun  *
1910*4882a593Smuzhiyun  *  @return      N/A
1911*4882a593Smuzhiyun  */
wlan_delete_station_list(pmlan_private priv)1912*4882a593Smuzhiyun t_void wlan_delete_station_list(pmlan_private priv)
1913*4882a593Smuzhiyun {
1914*4882a593Smuzhiyun 	sta_node *sta_ptr;
1915*4882a593Smuzhiyun 
1916*4882a593Smuzhiyun 	ENTER();
1917*4882a593Smuzhiyun 	while ((sta_ptr = (sta_node *)util_dequeue_list(
1918*4882a593Smuzhiyun 			priv->adapter->pmoal_handle, &priv->sta_list,
1919*4882a593Smuzhiyun 			priv->adapter->callbacks.moal_spin_lock,
1920*4882a593Smuzhiyun 			priv->adapter->callbacks.moal_spin_unlock))) {
1921*4882a593Smuzhiyun #ifdef DRV_EMBEDDED_AUTHENTICATOR
1922*4882a593Smuzhiyun 		if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
1923*4882a593Smuzhiyun 		    IsAuthenticatorEnabled(priv->psapriv))
1924*4882a593Smuzhiyun 			authenticator_free_client(priv->psapriv,
1925*4882a593Smuzhiyun 						  sta_ptr->cm_connectioninfo);
1926*4882a593Smuzhiyun #endif
1927*4882a593Smuzhiyun 		priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle,
1928*4882a593Smuzhiyun 						    (t_u8 *)sta_ptr);
1929*4882a593Smuzhiyun 	}
1930*4882a593Smuzhiyun 	LEAVE();
1931*4882a593Smuzhiyun 	return;
1932*4882a593Smuzhiyun }
1933*4882a593Smuzhiyun 
1934*4882a593Smuzhiyun /**
1935*4882a593Smuzhiyun  *  @brief Get tdls peer list
1936*4882a593Smuzhiyun  *
1937*4882a593Smuzhiyun  *  @param priv         A pointer to mlan_private structure
1938*4882a593Smuzhiyun  *  @param buf          A pointer to tdls_peer_info buf
1939*4882a593Smuzhiyun  *  @return             number of tdls peer
1940*4882a593Smuzhiyun  */
wlan_get_tdls_list(mlan_private * priv,tdls_peer_info * buf)1941*4882a593Smuzhiyun int wlan_get_tdls_list(mlan_private *priv, tdls_peer_info *buf)
1942*4882a593Smuzhiyun {
1943*4882a593Smuzhiyun 	tdls_peer_info *peer_info = buf;
1944*4882a593Smuzhiyun 	sta_node *sta_ptr = MNULL;
1945*4882a593Smuzhiyun 	int count = 0;
1946*4882a593Smuzhiyun 	IEEEtypes_Header_t *ieee_hdr;
1947*4882a593Smuzhiyun 	ENTER();
1948*4882a593Smuzhiyun 	if (priv->bss_type != MLAN_BSS_TYPE_STA) {
1949*4882a593Smuzhiyun 		LEAVE();
1950*4882a593Smuzhiyun 		return count;
1951*4882a593Smuzhiyun 	}
1952*4882a593Smuzhiyun 	sta_ptr = (sta_node *)util_peek_list(
1953*4882a593Smuzhiyun 		priv->adapter->pmoal_handle, &priv->sta_list,
1954*4882a593Smuzhiyun 		priv->adapter->callbacks.moal_spin_lock,
1955*4882a593Smuzhiyun 		priv->adapter->callbacks.moal_spin_unlock);
1956*4882a593Smuzhiyun 	if (!sta_ptr) {
1957*4882a593Smuzhiyun 		LEAVE();
1958*4882a593Smuzhiyun 		return count;
1959*4882a593Smuzhiyun 	}
1960*4882a593Smuzhiyun 	while (sta_ptr != (sta_node *)&priv->sta_list) {
1961*4882a593Smuzhiyun 		if (sta_ptr->status == TDLS_SETUP_COMPLETE) {
1962*4882a593Smuzhiyun 			peer_info->snr = sta_ptr->snr;
1963*4882a593Smuzhiyun 			peer_info->nf = sta_ptr->nf;
1964*4882a593Smuzhiyun 			memcpy_ext(priv->adapter, peer_info->mac_addr,
1965*4882a593Smuzhiyun 				   sta_ptr->mac_addr, MLAN_MAC_ADDR_LENGTH,
1966*4882a593Smuzhiyun 				   MLAN_MAC_ADDR_LENGTH);
1967*4882a593Smuzhiyun 			memcpy_ext(priv->adapter, peer_info->ht_cap,
1968*4882a593Smuzhiyun 				   &sta_ptr->HTcap, sizeof(IEEEtypes_HTCap_t),
1969*4882a593Smuzhiyun 				   sizeof(peer_info->ht_cap));
1970*4882a593Smuzhiyun 			memcpy_ext(priv->adapter, peer_info->ext_cap,
1971*4882a593Smuzhiyun 				   &sta_ptr->ExtCap, sizeof(IEEEtypes_ExtCap_t),
1972*4882a593Smuzhiyun 				   sizeof(peer_info->ext_cap));
1973*4882a593Smuzhiyun 			memcpy_ext(priv->adapter, peer_info->vht_cap,
1974*4882a593Smuzhiyun 				   &sta_ptr->vht_cap,
1975*4882a593Smuzhiyun 				   sizeof(IEEEtypes_VHTCap_t),
1976*4882a593Smuzhiyun 				   sizeof(peer_info->vht_cap));
1977*4882a593Smuzhiyun 			ieee_hdr = (IEEEtypes_Header_t *)peer_info->he_cap;
1978*4882a593Smuzhiyun 			memcpy_ext(priv->adapter, peer_info->he_cap,
1979*4882a593Smuzhiyun 				   &sta_ptr->he_cap,
1980*4882a593Smuzhiyun 				   sizeof(IEEEtypes_Header_t) + ieee_hdr->len,
1981*4882a593Smuzhiyun 				   sizeof(peer_info->he_cap));
1982*4882a593Smuzhiyun 			peer_info++;
1983*4882a593Smuzhiyun 			count++;
1984*4882a593Smuzhiyun 		}
1985*4882a593Smuzhiyun 		sta_ptr = sta_ptr->pnext;
1986*4882a593Smuzhiyun 		if (count >= MLAN_MAX_TDLS_PEER_SUPPORTED)
1987*4882a593Smuzhiyun 			break;
1988*4882a593Smuzhiyun 	}
1989*4882a593Smuzhiyun 	LEAVE();
1990*4882a593Smuzhiyun 	return count;
1991*4882a593Smuzhiyun }
1992*4882a593Smuzhiyun 
1993*4882a593Smuzhiyun /**
1994*4882a593Smuzhiyun  *  @brief Set the TDLS configuration to FW.
1995*4882a593Smuzhiyun  *
1996*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
1997*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
1998*4882a593Smuzhiyun  *
1999*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2000*4882a593Smuzhiyun  */
wlan_misc_ioctl_tdls_config(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2001*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_tdls_config(pmlan_adapter pmadapter,
2002*4882a593Smuzhiyun 					pmlan_ioctl_req pioctl_req)
2003*4882a593Smuzhiyun {
2004*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2005*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
2006*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2007*4882a593Smuzhiyun 	tdls_all_config *tdls_all_cfg =
2008*4882a593Smuzhiyun 		(tdls_all_config *)misc->param.tdls_config.tdls_data;
2009*4882a593Smuzhiyun 	t_u8 event_buf[100];
2010*4882a593Smuzhiyun 	mlan_event *pevent = (mlan_event *)event_buf;
2011*4882a593Smuzhiyun 	tdls_tear_down_event *tdls_evt =
2012*4882a593Smuzhiyun 		(tdls_tear_down_event *)pevent->event_buf;
2013*4882a593Smuzhiyun 	sta_node *sta_ptr = MNULL;
2014*4882a593Smuzhiyun 	MrvlIEtypes_Data_t *pMrvlTlv = MNULL;
2015*4882a593Smuzhiyun 	t_u8 *pos = MNULL;
2016*4882a593Smuzhiyun 	t_u16 remain_len = 0;
2017*4882a593Smuzhiyun 
2018*4882a593Smuzhiyun 	ENTER();
2019*4882a593Smuzhiyun 
2020*4882a593Smuzhiyun 	if (misc->param.tdls_config.tdls_action == WLAN_TDLS_TEAR_DOWN_REQ) {
2021*4882a593Smuzhiyun 		sta_ptr = wlan_get_station_entry(
2022*4882a593Smuzhiyun 			pmpriv, tdls_all_cfg->u.tdls_tear_down.peer_mac_addr);
2023*4882a593Smuzhiyun 		if (sta_ptr && sta_ptr->external_tdls) {
2024*4882a593Smuzhiyun 			pevent->bss_index = pmpriv->bss_index;
2025*4882a593Smuzhiyun 			pevent->event_id = MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ;
2026*4882a593Smuzhiyun 			pevent->event_len = sizeof(tdls_tear_down_event);
2027*4882a593Smuzhiyun 			memcpy_ext(pmpriv->adapter,
2028*4882a593Smuzhiyun 				   (t_u8 *)tdls_evt->peer_mac_addr,
2029*4882a593Smuzhiyun 				   tdls_all_cfg->u.tdls_tear_down.peer_mac_addr,
2030*4882a593Smuzhiyun 				   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
2031*4882a593Smuzhiyun 			tdls_evt->reason_code =
2032*4882a593Smuzhiyun 				tdls_all_cfg->u.tdls_tear_down.reason_code;
2033*4882a593Smuzhiyun 			wlan_recv_event(pmpriv,
2034*4882a593Smuzhiyun 					MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ,
2035*4882a593Smuzhiyun 					pevent);
2036*4882a593Smuzhiyun 			LEAVE();
2037*4882a593Smuzhiyun 			return ret;
2038*4882a593Smuzhiyun 		}
2039*4882a593Smuzhiyun 	}
2040*4882a593Smuzhiyun 	if (misc->param.tdls_config.tdls_action == WLAN_HOST_TDLS_CONFIG) {
2041*4882a593Smuzhiyun 		pmpriv->host_tdls_uapsd_support =
2042*4882a593Smuzhiyun 			tdls_all_cfg->u.host_tdls_cfg.uapsd_support;
2043*4882a593Smuzhiyun 		pmpriv->host_tdls_cs_support =
2044*4882a593Smuzhiyun 			tdls_all_cfg->u.host_tdls_cfg.cs_support;
2045*4882a593Smuzhiyun 		pos = tdls_all_cfg->u.host_tdls_cfg.tlv_buffer;
2046*4882a593Smuzhiyun 		remain_len = tdls_all_cfg->u.host_tdls_cfg.tlv_len;
2047*4882a593Smuzhiyun 		while (remain_len > sizeof(MrvlIEtypesHeader_t)) {
2048*4882a593Smuzhiyun 			remain_len -= sizeof(MrvlIEtypesHeader_t);
2049*4882a593Smuzhiyun 			pMrvlTlv = (MrvlIEtypes_Data_t *)pos;
2050*4882a593Smuzhiyun 			switch (pMrvlTlv->header.type) {
2051*4882a593Smuzhiyun 			case SUPPORTED_CHANNELS:
2052*4882a593Smuzhiyun 				pmpriv->chan_supp_len = (t_u8)MIN(
2053*4882a593Smuzhiyun 					pMrvlTlv->header.len, MAX_IE_SIZE);
2054*4882a593Smuzhiyun 				memset(pmadapter, pmpriv->chan_supp, 0,
2055*4882a593Smuzhiyun 				       sizeof(pmpriv->chan_supp));
2056*4882a593Smuzhiyun 				memcpy_ext(pmadapter, pmpriv->chan_supp,
2057*4882a593Smuzhiyun 					   pMrvlTlv->data, pMrvlTlv->header.len,
2058*4882a593Smuzhiyun 					   MAX_IE_SIZE);
2059*4882a593Smuzhiyun 				DBG_HEXDUMP(MCMD_D, "TDLS supported channel",
2060*4882a593Smuzhiyun 					    pmpriv->chan_supp,
2061*4882a593Smuzhiyun 					    pmpriv->chan_supp_len);
2062*4882a593Smuzhiyun 				break;
2063*4882a593Smuzhiyun 			case REGULATORY_CLASS:
2064*4882a593Smuzhiyun 				pmpriv->supp_regulatory_class_len = (t_u8)MIN(
2065*4882a593Smuzhiyun 					pMrvlTlv->header.len, MAX_IE_SIZE);
2066*4882a593Smuzhiyun 				memset(pmadapter, pmpriv->supp_regulatory_class,
2067*4882a593Smuzhiyun 				       0,
2068*4882a593Smuzhiyun 				       sizeof(pmpriv->supp_regulatory_class));
2069*4882a593Smuzhiyun 				memcpy_ext(pmadapter,
2070*4882a593Smuzhiyun 					   pmpriv->supp_regulatory_class,
2071*4882a593Smuzhiyun 					   pMrvlTlv->data, pMrvlTlv->header.len,
2072*4882a593Smuzhiyun 					   MAX_IE_SIZE);
2073*4882a593Smuzhiyun 				DBG_HEXDUMP(MCMD_D,
2074*4882a593Smuzhiyun 					    "TDLS supported regulatory class",
2075*4882a593Smuzhiyun 					    pmpriv->supp_regulatory_class,
2076*4882a593Smuzhiyun 					    pmpriv->supp_regulatory_class_len);
2077*4882a593Smuzhiyun 				break;
2078*4882a593Smuzhiyun 			default:
2079*4882a593Smuzhiyun 				break;
2080*4882a593Smuzhiyun 			}
2081*4882a593Smuzhiyun 			remain_len -= pMrvlTlv->header.len;
2082*4882a593Smuzhiyun 			pos += sizeof(MrvlIEtypesHeader_t) +
2083*4882a593Smuzhiyun 			       pMrvlTlv->header.len;
2084*4882a593Smuzhiyun 		}
2085*4882a593Smuzhiyun 		LEAVE();
2086*4882a593Smuzhiyun 		return ret;
2087*4882a593Smuzhiyun 	}
2088*4882a593Smuzhiyun 	pioctl_req->action = MLAN_ACT_SET;
2089*4882a593Smuzhiyun 
2090*4882a593Smuzhiyun 	/* Send command to firmware */
2091*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TDLS_CONFIG,
2092*4882a593Smuzhiyun 			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
2093*4882a593Smuzhiyun 			       &misc->param.tdls_config);
2094*4882a593Smuzhiyun 
2095*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
2096*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
2097*4882a593Smuzhiyun 	LEAVE();
2098*4882a593Smuzhiyun 	return ret;
2099*4882a593Smuzhiyun }
2100*4882a593Smuzhiyun 
2101*4882a593Smuzhiyun /**
2102*4882a593Smuzhiyun  *  @brief enable tdls config for cs and uapsd.
2103*4882a593Smuzhiyun  *
2104*4882a593Smuzhiyun  *  @param pmpriv	A pointer to mlan_private structure
2105*4882a593Smuzhiyun  *  @param enable   	MTRUE/MFALSE
2106*4882a593Smuzhiyun  *
2107*4882a593Smuzhiyun  *  @return
2108*4882a593Smuzhiyun  */
wlan_tdls_config(pmlan_private pmpriv,t_u8 enable)2109*4882a593Smuzhiyun t_void wlan_tdls_config(pmlan_private pmpriv, t_u8 enable)
2110*4882a593Smuzhiyun {
2111*4882a593Smuzhiyun 	mlan_adapter *pmadapter = pmpriv->adapter;
2112*4882a593Smuzhiyun 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
2113*4882a593Smuzhiyun 	mlan_ds_misc_tdls_config *tdls_config = MNULL;
2114*4882a593Smuzhiyun 	tdls_all_config *tdls_all_cfg = MNULL;
2115*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
2116*4882a593Smuzhiyun 
2117*4882a593Smuzhiyun 	ENTER();
2118*4882a593Smuzhiyun 
2119*4882a593Smuzhiyun 	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2120*4882a593Smuzhiyun 			       sizeof(mlan_ds_misc_tdls_config), MLAN_MEM_DEF,
2121*4882a593Smuzhiyun 			       (t_u8 **)&tdls_config);
2122*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS || !tdls_config) {
2123*4882a593Smuzhiyun 		PRINTM(MERROR, "Memory allocation for tdls_config failed!\n");
2124*4882a593Smuzhiyun 		LEAVE();
2125*4882a593Smuzhiyun 		return;
2126*4882a593Smuzhiyun 	}
2127*4882a593Smuzhiyun 	memset(pmadapter, (t_u8 *)tdls_config, 0,
2128*4882a593Smuzhiyun 	       sizeof(mlan_ds_misc_tdls_config));
2129*4882a593Smuzhiyun 	tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
2130*4882a593Smuzhiyun 	tdls_all_cfg->u.tdls_config.enable = enable;
2131*4882a593Smuzhiyun 	tdls_config->tdls_action = WLAN_TDLS_CONFIG;
2132*4882a593Smuzhiyun 	/* Send command to firmware */
2133*4882a593Smuzhiyun 	wlan_prepare_cmd(pmpriv, HostCmd_CMD_TDLS_CONFIG, HostCmd_ACT_GEN_SET,
2134*4882a593Smuzhiyun 			 0, MNULL, tdls_config);
2135*4882a593Smuzhiyun 	PRINTM(MCMND, "tdls_config: enable=%d\n", enable);
2136*4882a593Smuzhiyun 
2137*4882a593Smuzhiyun 	if (tdls_config)
2138*4882a593Smuzhiyun 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tdls_config);
2139*4882a593Smuzhiyun 
2140*4882a593Smuzhiyun 	LEAVE();
2141*4882a593Smuzhiyun }
2142*4882a593Smuzhiyun 
2143*4882a593Smuzhiyun /**
2144*4882a593Smuzhiyun  *  @brief set tdls channel switch parameters.
2145*4882a593Smuzhiyun  *
2146*4882a593Smuzhiyun  *  @param pmpriv	A pointer to mlan_private structure
2147*4882a593Smuzhiyun  *
2148*4882a593Smuzhiyun  *  @return
2149*4882a593Smuzhiyun  */
wlan_tdls_cs_param_config(pmlan_private pmpriv)2150*4882a593Smuzhiyun static t_void wlan_tdls_cs_param_config(pmlan_private pmpriv)
2151*4882a593Smuzhiyun {
2152*4882a593Smuzhiyun 	mlan_adapter *pmadapter = pmpriv->adapter;
2153*4882a593Smuzhiyun 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
2154*4882a593Smuzhiyun 	mlan_ds_misc_tdls_config *tdls_config = MNULL;
2155*4882a593Smuzhiyun 	tdls_all_config *tdls_all_cfg = MNULL;
2156*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
2157*4882a593Smuzhiyun 
2158*4882a593Smuzhiyun 	ENTER();
2159*4882a593Smuzhiyun 
2160*4882a593Smuzhiyun 	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2161*4882a593Smuzhiyun 			       sizeof(mlan_ds_misc_tdls_config), MLAN_MEM_DEF,
2162*4882a593Smuzhiyun 			       (t_u8 **)&tdls_config);
2163*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS || !tdls_config) {
2164*4882a593Smuzhiyun 		PRINTM(MERROR, "Memory allocation for tdls_config failed!\n");
2165*4882a593Smuzhiyun 		LEAVE();
2166*4882a593Smuzhiyun 		return;
2167*4882a593Smuzhiyun 	}
2168*4882a593Smuzhiyun 	memset(pmadapter, (t_u8 *)tdls_config, 0,
2169*4882a593Smuzhiyun 	       sizeof(mlan_ds_misc_tdls_config));
2170*4882a593Smuzhiyun 
2171*4882a593Smuzhiyun 	tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
2172*4882a593Smuzhiyun 	tdls_config->tdls_action = WLAN_TDLS_CS_PARAMS;
2173*4882a593Smuzhiyun 	tdls_all_cfg->u.tdls_cs_params.unit_time = 2;
2174*4882a593Smuzhiyun 	tdls_all_cfg->u.tdls_cs_params.threshold_otherlink = 10;
2175*4882a593Smuzhiyun 	tdls_all_cfg->u.tdls_cs_params.threshold_directlink = 0;
2176*4882a593Smuzhiyun 
2177*4882a593Smuzhiyun 	/* Send command to firmware */
2178*4882a593Smuzhiyun 	wlan_prepare_cmd(pmpriv, HostCmd_CMD_TDLS_CONFIG, HostCmd_ACT_GEN_SET,
2179*4882a593Smuzhiyun 			 0, MNULL, tdls_config);
2180*4882a593Smuzhiyun 
2181*4882a593Smuzhiyun 	if (tdls_config)
2182*4882a593Smuzhiyun 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tdls_config);
2183*4882a593Smuzhiyun 
2184*4882a593Smuzhiyun 	LEAVE();
2185*4882a593Smuzhiyun }
2186*4882a593Smuzhiyun 
2187*4882a593Smuzhiyun /**
2188*4882a593Smuzhiyun  *  @brief start tdls channel switch
2189*4882a593Smuzhiyun  *
2190*4882a593Smuzhiyun  *  @param pmpriv	A pointer to mlan_private structure
2191*4882a593Smuzhiyun  *  @param peer_mac_addr 	A pointer to peer mac address
2192*4882a593Smuzhiyun  *  @param pioctl_buf   A pointer to ioctl request buffer
2193*4882a593Smuzhiyun  *
2194*4882a593Smuzhiyun  *  @return
2195*4882a593Smuzhiyun  */
wlan_tdls_cs_start(pmlan_private pmpriv,t_u8 * peer_mac_addr,pmlan_ioctl_req pioctl_buf)2196*4882a593Smuzhiyun static t_void wlan_tdls_cs_start(pmlan_private pmpriv, t_u8 *peer_mac_addr,
2197*4882a593Smuzhiyun 				 pmlan_ioctl_req pioctl_buf)
2198*4882a593Smuzhiyun {
2199*4882a593Smuzhiyun 	mlan_adapter *pmadapter = pmpriv->adapter;
2200*4882a593Smuzhiyun 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
2201*4882a593Smuzhiyun 	mlan_ds_misc_tdls_config *tdls_config = MNULL;
2202*4882a593Smuzhiyun 	tdls_all_config *tdls_all_cfg = MNULL;
2203*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
2204*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
2205*4882a593Smuzhiyun 
2206*4882a593Smuzhiyun 	ENTER();
2207*4882a593Smuzhiyun 
2208*4882a593Smuzhiyun 	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2209*4882a593Smuzhiyun 			       sizeof(mlan_ds_misc_tdls_config), MLAN_MEM_DEF,
2210*4882a593Smuzhiyun 			       (t_u8 **)&tdls_config);
2211*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS || !tdls_config) {
2212*4882a593Smuzhiyun 		PRINTM(MERROR, "Memory allocation for tdls_config failed!\n");
2213*4882a593Smuzhiyun 		LEAVE();
2214*4882a593Smuzhiyun 		return;
2215*4882a593Smuzhiyun 	}
2216*4882a593Smuzhiyun 	memset(pmadapter, (t_u8 *)tdls_config, 0,
2217*4882a593Smuzhiyun 	       sizeof(mlan_ds_misc_tdls_config));
2218*4882a593Smuzhiyun 
2219*4882a593Smuzhiyun 	if (pioctl_buf) {
2220*4882a593Smuzhiyun 		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
2221*4882a593Smuzhiyun 		memcpy_ext(pmpriv->adapter, tdls_config,
2222*4882a593Smuzhiyun 			   &misc->param.tdls_config,
2223*4882a593Smuzhiyun 			   sizeof(mlan_ds_misc_tdls_config),
2224*4882a593Smuzhiyun 			   sizeof(mlan_ds_misc_tdls_config));
2225*4882a593Smuzhiyun 		tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
2226*4882a593Smuzhiyun 		if (tdls_all_cfg->u.tdls_chan_switch.primary_channel > 14) {
2227*4882a593Smuzhiyun 			tdls_all_cfg->u.tdls_chan_switch
2228*4882a593Smuzhiyun 				.secondary_channel_offset =
2229*4882a593Smuzhiyun 				wlan_get_second_channel_offset(
2230*4882a593Smuzhiyun 					pmpriv, tdls_all_cfg->u.tdls_chan_switch
2231*4882a593Smuzhiyun 							.primary_channel);
2232*4882a593Smuzhiyun 		}
2233*4882a593Smuzhiyun 		PRINTM(MCMND, "Start TDLS CS: channel=%d\n",
2234*4882a593Smuzhiyun 		       tdls_all_cfg->u.tdls_chan_switch.primary_channel);
2235*4882a593Smuzhiyun 	} else {
2236*4882a593Smuzhiyun 		tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
2237*4882a593Smuzhiyun 		tdls_config->tdls_action = WLAN_TDLS_INIT_CHAN_SWITCH;
2238*4882a593Smuzhiyun 		memcpy_ext(pmpriv->adapter,
2239*4882a593Smuzhiyun 			   tdls_all_cfg->u.tdls_chan_switch.peer_mac_addr,
2240*4882a593Smuzhiyun 			   peer_mac_addr, MLAN_MAC_ADDR_LENGTH,
2241*4882a593Smuzhiyun 			   MLAN_MAC_ADDR_LENGTH);
2242*4882a593Smuzhiyun 		tdls_all_cfg->u.tdls_chan_switch.primary_channel =
2243*4882a593Smuzhiyun 			pmpriv->tdls_cs_channel;
2244*4882a593Smuzhiyun 		if (pmpriv->tdls_cs_channel > 14) {
2245*4882a593Smuzhiyun 			tdls_all_cfg->u.tdls_chan_switch.band = BAND_5GHZ;
2246*4882a593Smuzhiyun 			tdls_all_cfg->u.tdls_chan_switch
2247*4882a593Smuzhiyun 				.secondary_channel_offset =
2248*4882a593Smuzhiyun 				wlan_get_second_channel_offset(
2249*4882a593Smuzhiyun 					pmpriv, pmpriv->tdls_cs_channel);
2250*4882a593Smuzhiyun 		} else {
2251*4882a593Smuzhiyun 			tdls_all_cfg->u.tdls_chan_switch.band = BAND_2GHZ;
2252*4882a593Smuzhiyun 		}
2253*4882a593Smuzhiyun 		PRINTM(MCMND, "Start TDLS CS: channel=%d\n",
2254*4882a593Smuzhiyun 		       pmpriv->tdls_cs_channel);
2255*4882a593Smuzhiyun 	}
2256*4882a593Smuzhiyun 	tdls_all_cfg->u.tdls_chan_switch.switch_time = 10;
2257*4882a593Smuzhiyun 	tdls_all_cfg->u.tdls_chan_switch.switch_timeout = 16;
2258*4882a593Smuzhiyun 	tdls_all_cfg->u.tdls_chan_switch.regulatory_class = 12;
2259*4882a593Smuzhiyun 	tdls_all_cfg->u.tdls_chan_switch.periodicity = 1;
2260*4882a593Smuzhiyun 
2261*4882a593Smuzhiyun 	/* Send command to firmware */
2262*4882a593Smuzhiyun 	wlan_prepare_cmd(pmpriv, HostCmd_CMD_TDLS_CONFIG, HostCmd_ACT_GEN_SET,
2263*4882a593Smuzhiyun 			 0, MNULL, tdls_config);
2264*4882a593Smuzhiyun 
2265*4882a593Smuzhiyun 	if (tdls_config)
2266*4882a593Smuzhiyun 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tdls_config);
2267*4882a593Smuzhiyun 
2268*4882a593Smuzhiyun 	LEAVE();
2269*4882a593Smuzhiyun }
2270*4882a593Smuzhiyun 
2271*4882a593Smuzhiyun #if 0
2272*4882a593Smuzhiyun /**
2273*4882a593Smuzhiyun  *  @brief stop tdls channel switch
2274*4882a593Smuzhiyun  *
2275*4882a593Smuzhiyun  *  @param pmpriv	A pointer to mlan_private structure
2276*4882a593Smuzhiyun  *  @param peer_mac_addr 	A pointer to peer mac address
2277*4882a593Smuzhiyun  *  @param pioctl_buf   A pointer to command buffer
2278*4882a593Smuzhiyun  *  @return
2279*4882a593Smuzhiyun  */
2280*4882a593Smuzhiyun static t_void wlan_tdls_cs_stop(pmlan_private pmpriv, t_u8 *peer_mac_addr)
2281*4882a593Smuzhiyun {
2282*4882a593Smuzhiyun 	mlan_adapter *pmadapter = pmpriv->adapter;
2283*4882a593Smuzhiyun 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
2284*4882a593Smuzhiyun 	mlan_ds_misc_tdls_config *tdls_config = MNULL;
2285*4882a593Smuzhiyun 	tdls_all_config *tdls_all_cfg = MNULL;
2286*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
2287*4882a593Smuzhiyun 
2288*4882a593Smuzhiyun 	ENTER();
2289*4882a593Smuzhiyun 
2290*4882a593Smuzhiyun 	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2291*4882a593Smuzhiyun 			       sizeof(mlan_ds_misc_tdls_config), MLAN_MEM_DEF,
2292*4882a593Smuzhiyun 			       (t_u8 **)&tdls_config);
2293*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS || !tdls_config) {
2294*4882a593Smuzhiyun 		PRINTM(MERROR, "Memory allocation for tdls_config failed!\n");
2295*4882a593Smuzhiyun 		LEAVE();
2296*4882a593Smuzhiyun 		return;
2297*4882a593Smuzhiyun 	}
2298*4882a593Smuzhiyun 	memset(pmadapter, (t_u8 *)tdls_config, 0,
2299*4882a593Smuzhiyun 	       sizeof(mlan_ds_misc_tdls_config));
2300*4882a593Smuzhiyun 
2301*4882a593Smuzhiyun 	tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
2302*4882a593Smuzhiyun 	tdls_config->tdls_action = WLAN_TDLS_STOP_CHAN_SWITCH;
2303*4882a593Smuzhiyun 
2304*4882a593Smuzhiyun 	memcpy_ext(pmpriv->adapter,
2305*4882a593Smuzhiyun 		   tdls_all_cfg->u.tdls_stop_chan_switch.peer_mac_addr,
2306*4882a593Smuzhiyun 		   peer_mac_addr, MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
2307*4882a593Smuzhiyun 	PRINTM(MCMND, "Stop TDLS CS\n");
2308*4882a593Smuzhiyun 	/* Send command to firmware */
2309*4882a593Smuzhiyun 	wlan_prepare_cmd(pmpriv, HostCmd_CMD_TDLS_CONFIG, HostCmd_ACT_GEN_SET,
2310*4882a593Smuzhiyun 			 0, MNULL, tdls_config);
2311*4882a593Smuzhiyun 
2312*4882a593Smuzhiyun 	if (tdls_config)
2313*4882a593Smuzhiyun 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tdls_config);
2314*4882a593Smuzhiyun 
2315*4882a593Smuzhiyun 	LEAVE();
2316*4882a593Smuzhiyun }
2317*4882a593Smuzhiyun #endif
2318*4882a593Smuzhiyun 
2319*4882a593Smuzhiyun /**
2320*4882a593Smuzhiyun  *  @brief Set/Get the TDLS off channel.
2321*4882a593Smuzhiyun  *
2322*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
2323*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
2324*4882a593Smuzhiyun  *
2325*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2326*4882a593Smuzhiyun  */
wlan_misc_ioctl_tdls_cs_channel(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2327*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_tdls_cs_channel(pmlan_adapter pmadapter,
2328*4882a593Smuzhiyun 					    pmlan_ioctl_req pioctl_req)
2329*4882a593Smuzhiyun {
2330*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2331*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
2332*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2333*4882a593Smuzhiyun 
2334*4882a593Smuzhiyun 	ENTER();
2335*4882a593Smuzhiyun 
2336*4882a593Smuzhiyun 	if (MLAN_ACT_GET == pioctl_req->action)
2337*4882a593Smuzhiyun 		misc->param.tdls_cs_channel = pmpriv->tdls_cs_channel;
2338*4882a593Smuzhiyun 	else if (MLAN_ACT_SET == pioctl_req->action) {
2339*4882a593Smuzhiyun 		pmpriv->tdls_cs_channel = misc->param.tdls_cs_channel;
2340*4882a593Smuzhiyun 	}
2341*4882a593Smuzhiyun 	LEAVE();
2342*4882a593Smuzhiyun 	return ret;
2343*4882a593Smuzhiyun }
2344*4882a593Smuzhiyun /**
2345*4882a593Smuzhiyun  *  @brief Set/Get the TDLS idle time.
2346*4882a593Smuzhiyun  *
2347*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
2348*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
2349*4882a593Smuzhiyun  *
2350*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2351*4882a593Smuzhiyun  */
wlan_misc_ioctl_tdls_idle_time(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2352*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_tdls_idle_time(pmlan_adapter pmadapter,
2353*4882a593Smuzhiyun 					   pmlan_ioctl_req pioctl_req)
2354*4882a593Smuzhiyun {
2355*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2356*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
2357*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2358*4882a593Smuzhiyun 
2359*4882a593Smuzhiyun 	ENTER();
2360*4882a593Smuzhiyun 
2361*4882a593Smuzhiyun 	if (MLAN_ACT_GET == pioctl_req->action) {
2362*4882a593Smuzhiyun 		misc->param.tdls_idle_time = pmpriv->tdls_idle_time;
2363*4882a593Smuzhiyun 	} else if (MLAN_ACT_SET == pioctl_req->action) {
2364*4882a593Smuzhiyun 		pmpriv->tdls_idle_time = misc->param.tdls_idle_time;
2365*4882a593Smuzhiyun 	}
2366*4882a593Smuzhiyun 	LEAVE();
2367*4882a593Smuzhiyun 	return ret;
2368*4882a593Smuzhiyun }
2369*4882a593Smuzhiyun 
2370*4882a593Smuzhiyun /**
2371*4882a593Smuzhiyun  *  @brief Set the TDLS operation to FW.
2372*4882a593Smuzhiyun  *
2373*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
2374*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
2375*4882a593Smuzhiyun  *
2376*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2377*4882a593Smuzhiyun  */
wlan_misc_ioctl_tdls_oper(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2378*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_tdls_oper(pmlan_adapter pmadapter,
2379*4882a593Smuzhiyun 				      pmlan_ioctl_req pioctl_req)
2380*4882a593Smuzhiyun {
2381*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2382*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
2383*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2384*4882a593Smuzhiyun 	mlan_ds_misc_tdls_oper *ptdls_oper = &misc->param.tdls_oper;
2385*4882a593Smuzhiyun 	t_u8 event_buf[100];
2386*4882a593Smuzhiyun 	mlan_event *ptdls_event = (mlan_event *)event_buf;
2387*4882a593Smuzhiyun 	tdls_tear_down_event *tdls_evt =
2388*4882a593Smuzhiyun 		(tdls_tear_down_event *)ptdls_event->event_buf;
2389*4882a593Smuzhiyun 	sta_node *sta_ptr = MNULL;
2390*4882a593Smuzhiyun 	t_u8 i = 0;
2391*4882a593Smuzhiyun 
2392*4882a593Smuzhiyun 	ENTER();
2393*4882a593Smuzhiyun 	sta_ptr = wlan_get_station_entry(pmpriv, ptdls_oper->peer_mac);
2394*4882a593Smuzhiyun 	switch (ptdls_oper->tdls_action) {
2395*4882a593Smuzhiyun 	case WLAN_TDLS_ENABLE_LINK:
2396*4882a593Smuzhiyun 		if (sta_ptr && (sta_ptr->status != TDLS_SETUP_FAILURE)) {
2397*4882a593Smuzhiyun 			PRINTM(MMSG, "TDLS: Enable link " MACSTR " success\n",
2398*4882a593Smuzhiyun 			       MAC2STR(ptdls_oper->peer_mac));
2399*4882a593Smuzhiyun 			sta_ptr->status = TDLS_SETUP_COMPLETE;
2400*4882a593Smuzhiyun 			pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL;
2401*4882a593Smuzhiyun 			if (!pmpriv->txaggrctrl)
2402*4882a593Smuzhiyun 				wlan_11n_send_delba_to_peer(
2403*4882a593Smuzhiyun 					pmpriv,
2404*4882a593Smuzhiyun 					pmpriv->curr_bss_params.bss_descriptor
2405*4882a593Smuzhiyun 						.mac_address);
2406*4882a593Smuzhiyun 			if (sta_ptr->HTcap.ieee_hdr.element_id ==
2407*4882a593Smuzhiyun 			    HT_CAPABILITY) {
2408*4882a593Smuzhiyun 				sta_ptr->is_11n_enabled = MTRUE;
2409*4882a593Smuzhiyun 				if (GETHT_MAXAMSDU(
2410*4882a593Smuzhiyun 					    sta_ptr->HTcap.ht_cap.ht_cap_info))
2411*4882a593Smuzhiyun 					sta_ptr->max_amsdu =
2412*4882a593Smuzhiyun 						MLAN_TX_DATA_BUF_SIZE_8K;
2413*4882a593Smuzhiyun 				else
2414*4882a593Smuzhiyun 					sta_ptr->max_amsdu =
2415*4882a593Smuzhiyun 						MLAN_TX_DATA_BUF_SIZE_4K;
2416*4882a593Smuzhiyun 				for (i = 0; i < MAX_NUM_TID; i++) {
2417*4882a593Smuzhiyun 					if (sta_ptr->is_11n_enabled ||
2418*4882a593Smuzhiyun 					    sta_ptr->is_11ax_enabled)
2419*4882a593Smuzhiyun 						sta_ptr->ampdu_sta[i] =
2420*4882a593Smuzhiyun 							pmpriv->aggr_prio_tbl[i]
2421*4882a593Smuzhiyun 								.ampdu_user;
2422*4882a593Smuzhiyun 					else
2423*4882a593Smuzhiyun 						sta_ptr->ampdu_sta[i] =
2424*4882a593Smuzhiyun 							BA_STREAM_NOT_ALLOWED;
2425*4882a593Smuzhiyun 				}
2426*4882a593Smuzhiyun 				memset(pmpriv->adapter, sta_ptr->rx_seq, 0xff,
2427*4882a593Smuzhiyun 				       sizeof(sta_ptr->rx_seq));
2428*4882a593Smuzhiyun 			}
2429*4882a593Smuzhiyun 			wlan_restore_tdls_packets(pmpriv, ptdls_oper->peer_mac,
2430*4882a593Smuzhiyun 						  TDLS_SETUP_COMPLETE);
2431*4882a593Smuzhiyun 			if (ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(
2432*4882a593Smuzhiyun 				    sta_ptr->ExtCap.ext_cap)) {
2433*4882a593Smuzhiyun 				wlan_tdls_config(pmpriv, MTRUE);
2434*4882a593Smuzhiyun 				wlan_tdls_cs_param_config(pmpriv);
2435*4882a593Smuzhiyun 				/**tdls cs start*/
2436*4882a593Smuzhiyun 				if (pmpriv->tdls_cs_channel &&
2437*4882a593Smuzhiyun 				    pmpriv->tdls_cs_channel !=
2438*4882a593Smuzhiyun 					    pmpriv->curr_bss_params
2439*4882a593Smuzhiyun 						    .bss_descriptor.channel)
2440*4882a593Smuzhiyun 					wlan_tdls_cs_start(pmpriv,
2441*4882a593Smuzhiyun 							   ptdls_oper->peer_mac,
2442*4882a593Smuzhiyun 							   MNULL);
2443*4882a593Smuzhiyun 			}
2444*4882a593Smuzhiyun 		} else {
2445*4882a593Smuzhiyun 			PRINTM(MMSG, "TDLS: Enable link " MACSTR " fail\n",
2446*4882a593Smuzhiyun 			       MAC2STR(ptdls_oper->peer_mac));
2447*4882a593Smuzhiyun 			/*for supplicant 2.0, we need send event to request
2448*4882a593Smuzhiyun 			 *teardown, *for latest supplicant, we only need return
2449*4882a593Smuzhiyun 			 *fail, and supplicant will send teardown packet and
2450*4882a593Smuzhiyun 			 *disable tdls link*/
2451*4882a593Smuzhiyun 			if (sta_ptr) {
2452*4882a593Smuzhiyun 				ptdls_event->bss_index = pmpriv->bss_index;
2453*4882a593Smuzhiyun 				ptdls_event->event_id =
2454*4882a593Smuzhiyun 					MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ;
2455*4882a593Smuzhiyun 				ptdls_event->event_len =
2456*4882a593Smuzhiyun 					sizeof(tdls_tear_down_event);
2457*4882a593Smuzhiyun 				memcpy_ext(pmpriv->adapter,
2458*4882a593Smuzhiyun 					   (t_u8 *)tdls_evt->peer_mac_addr,
2459*4882a593Smuzhiyun 					   ptdls_oper->peer_mac,
2460*4882a593Smuzhiyun 					   MLAN_MAC_ADDR_LENGTH,
2461*4882a593Smuzhiyun 					   MLAN_MAC_ADDR_LENGTH);
2462*4882a593Smuzhiyun 				tdls_evt->reason_code =
2463*4882a593Smuzhiyun 					MLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
2464*4882a593Smuzhiyun 				wlan_recv_event(
2465*4882a593Smuzhiyun 					pmpriv,
2466*4882a593Smuzhiyun 					MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ,
2467*4882a593Smuzhiyun 					ptdls_event);
2468*4882a593Smuzhiyun 				wlan_restore_tdls_packets(pmpriv,
2469*4882a593Smuzhiyun 							  ptdls_oper->peer_mac,
2470*4882a593Smuzhiyun 							  TDLS_TEAR_DOWN);
2471*4882a593Smuzhiyun 				if (sta_ptr->is_11n_enabled ||
2472*4882a593Smuzhiyun 				    sta_ptr->is_11ax_enabled) {
2473*4882a593Smuzhiyun 					wlan_cleanup_reorder_tbl(
2474*4882a593Smuzhiyun 						pmpriv, ptdls_oper->peer_mac);
2475*4882a593Smuzhiyun 					wlan_11n_cleanup_txbastream_tbl(
2476*4882a593Smuzhiyun 						pmpriv, ptdls_oper->peer_mac);
2477*4882a593Smuzhiyun 				}
2478*4882a593Smuzhiyun 				wlan_delete_station_entry(pmpriv,
2479*4882a593Smuzhiyun 							  ptdls_oper->peer_mac);
2480*4882a593Smuzhiyun 				if (MTRUE == wlan_is_station_list_empty(pmpriv))
2481*4882a593Smuzhiyun 					pmadapter->tdls_status = TDLS_NOT_SETUP;
2482*4882a593Smuzhiyun 				else
2483*4882a593Smuzhiyun 					pmadapter->tdls_status =
2484*4882a593Smuzhiyun 						TDLS_IN_BASE_CHANNEL;
2485*4882a593Smuzhiyun 			}
2486*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
2487*4882a593Smuzhiyun 		}
2488*4882a593Smuzhiyun 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
2489*4882a593Smuzhiyun 				MNULL);
2490*4882a593Smuzhiyun 		break;
2491*4882a593Smuzhiyun 	case WLAN_TDLS_DISABLE_LINK:
2492*4882a593Smuzhiyun 		/* Send command to firmware to delete tdls link*/
2493*4882a593Smuzhiyun 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TDLS_OPERATION,
2494*4882a593Smuzhiyun 				       HostCmd_ACT_GEN_SET, 0,
2495*4882a593Smuzhiyun 				       (t_void *)pioctl_req, ptdls_oper);
2496*4882a593Smuzhiyun 		if (ret == MLAN_STATUS_SUCCESS)
2497*4882a593Smuzhiyun 			ret = MLAN_STATUS_PENDING;
2498*4882a593Smuzhiyun 		break;
2499*4882a593Smuzhiyun 	case WLAN_TDLS_CREATE_LINK:
2500*4882a593Smuzhiyun 		PRINTM(MIOCTL, "CREATE TDLS LINK\n");
2501*4882a593Smuzhiyun 		if (sta_ptr && sta_ptr->status == TDLS_SETUP_INPROGRESS) {
2502*4882a593Smuzhiyun 			PRINTM(MIOCTL, "We already create the link\n");
2503*4882a593Smuzhiyun 			break;
2504*4882a593Smuzhiyun 		}
2505*4882a593Smuzhiyun 		if (!sta_ptr)
2506*4882a593Smuzhiyun 			sta_ptr = wlan_add_station_entry(
2507*4882a593Smuzhiyun 				pmpriv, misc->param.tdls_oper.peer_mac);
2508*4882a593Smuzhiyun 		if (sta_ptr) {
2509*4882a593Smuzhiyun 			sta_ptr->status = TDLS_SETUP_INPROGRESS;
2510*4882a593Smuzhiyun 			sta_ptr->external_tdls = MTRUE;
2511*4882a593Smuzhiyun 			wlan_hold_tdls_packets(pmpriv,
2512*4882a593Smuzhiyun 					       misc->param.tdls_oper.peer_mac);
2513*4882a593Smuzhiyun 		}
2514*4882a593Smuzhiyun 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TDLS_OPERATION,
2515*4882a593Smuzhiyun 				       HostCmd_ACT_GEN_SET, 0,
2516*4882a593Smuzhiyun 				       (t_void *)pioctl_req, ptdls_oper);
2517*4882a593Smuzhiyun 		if (ret == MLAN_STATUS_SUCCESS)
2518*4882a593Smuzhiyun 			ret = MLAN_STATUS_PENDING;
2519*4882a593Smuzhiyun 		break;
2520*4882a593Smuzhiyun 	case WLAN_TDLS_CONFIG_LINK:
2521*4882a593Smuzhiyun 		if (!sta_ptr || sta_ptr->status == TDLS_SETUP_FAILURE) {
2522*4882a593Smuzhiyun 			PRINTM(MERROR, "Can not CONFIG TDLS Link\n");
2523*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
2524*4882a593Smuzhiyun 			break;
2525*4882a593Smuzhiyun 		}
2526*4882a593Smuzhiyun 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TDLS_OPERATION,
2527*4882a593Smuzhiyun 				       HostCmd_ACT_GEN_SET, 0,
2528*4882a593Smuzhiyun 				       (t_void *)pioctl_req, ptdls_oper);
2529*4882a593Smuzhiyun 		if (ret == MLAN_STATUS_SUCCESS)
2530*4882a593Smuzhiyun 			ret = MLAN_STATUS_PENDING;
2531*4882a593Smuzhiyun 		break;
2532*4882a593Smuzhiyun 	case WLAN_TDLS_INIT_CHAN_SWITCH:
2533*4882a593Smuzhiyun 		if (sta_ptr &&
2534*4882a593Smuzhiyun 		    ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(sta_ptr->ExtCap.ext_cap)) {
2535*4882a593Smuzhiyun 			wlan_tdls_config(pmpriv, MTRUE);
2536*4882a593Smuzhiyun 			wlan_tdls_cs_param_config(pmpriv);
2537*4882a593Smuzhiyun 			/**tdls cs start*/
2538*4882a593Smuzhiyun 			wlan_tdls_cs_start(pmpriv, ptdls_oper->peer_mac,
2539*4882a593Smuzhiyun 					   pioctl_req);
2540*4882a593Smuzhiyun 		}
2541*4882a593Smuzhiyun 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
2542*4882a593Smuzhiyun 				MNULL);
2543*4882a593Smuzhiyun 		break;
2544*4882a593Smuzhiyun 	default:
2545*4882a593Smuzhiyun 		break;
2546*4882a593Smuzhiyun 	}
2547*4882a593Smuzhiyun 	LEAVE();
2548*4882a593Smuzhiyun 	return ret;
2549*4882a593Smuzhiyun }
2550*4882a593Smuzhiyun 
2551*4882a593Smuzhiyun /**
2552*4882a593Smuzhiyun  *  @brief Get AP's ext capability
2553*4882a593Smuzhiyun  *
2554*4882a593Smuzhiyun  *  @param pmpriv	A pointer to mlan_adapter structure
2555*4882a593Smuzhiyun  *  @param ext_cap  A pointer to ExtCap_t structure
2556*4882a593Smuzhiyun  *
2557*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2558*4882a593Smuzhiyun  */
wlan_get_ap_ext_cap(mlan_private * pmpriv,ExtCap_t * ext_cap)2559*4882a593Smuzhiyun static void wlan_get_ap_ext_cap(mlan_private *pmpriv, ExtCap_t *ext_cap)
2560*4882a593Smuzhiyun {
2561*4882a593Smuzhiyun 	pmlan_adapter pmadapter = pmpriv->adapter;
2562*4882a593Smuzhiyun 	BSSDescriptor_t *pbss_desc;
2563*4882a593Smuzhiyun 	pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
2564*4882a593Smuzhiyun 	memset(pmadapter, ext_cap, 0, sizeof(ExtCap_t));
2565*4882a593Smuzhiyun 	if (pbss_desc->pext_cap) {
2566*4882a593Smuzhiyun 		memcpy_ext(pmadapter, (t_u8 *)ext_cap,
2567*4882a593Smuzhiyun 			   (t_u8 *)pbss_desc->pext_cap +
2568*4882a593Smuzhiyun 				   sizeof(IEEEtypes_Header_t),
2569*4882a593Smuzhiyun 			   pbss_desc->pext_cap->ieee_hdr.len, sizeof(ExtCap_t));
2570*4882a593Smuzhiyun 	}
2571*4882a593Smuzhiyun 	return;
2572*4882a593Smuzhiyun }
2573*4882a593Smuzhiyun 
2574*4882a593Smuzhiyun /**
2575*4882a593Smuzhiyun  *  @brief Set the TDLS operation to FW.
2576*4882a593Smuzhiyun  *
2577*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
2578*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
2579*4882a593Smuzhiyun  *
2580*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2581*4882a593Smuzhiyun  */
wlan_misc_ioctl_tdls_get_ies(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2582*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_tdls_get_ies(pmlan_adapter pmadapter,
2583*4882a593Smuzhiyun 					 pmlan_ioctl_req pioctl_req)
2584*4882a593Smuzhiyun {
2585*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2586*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2587*4882a593Smuzhiyun 	mlan_ds_misc_tdls_ies *tdls_ies = &misc->param.tdls_ies;
2588*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
2589*4882a593Smuzhiyun 	BSSDescriptor_t *pbss_desc;
2590*4882a593Smuzhiyun 	t_u32 usr_dot_11n_dev_cap;
2591*4882a593Smuzhiyun 	IEEEtypes_ExtCap_t *ext_cap = MNULL;
2592*4882a593Smuzhiyun 	ExtCap_t ap_ext_cap;
2593*4882a593Smuzhiyun 	IEEEtypes_HTCap_t *ht_cap = MNULL;
2594*4882a593Smuzhiyun 	IEEEtypes_HTInfo_t *ht_info = MNULL;
2595*4882a593Smuzhiyun 	IEEEtypes_VHTCap_t *vht_cap = MNULL;
2596*4882a593Smuzhiyun 	IEEEtypes_VHTOprat_t *vht_oprat = MNULL;
2597*4882a593Smuzhiyun 	IEEEtypes_AssocRsp_t *passoc_rsp = MNULL;
2598*4882a593Smuzhiyun 	IEEEtypes_AID_t *aid_info = MNULL;
2599*4882a593Smuzhiyun 	IEEEtypes_HECap_t *he_cap = MNULL;
2600*4882a593Smuzhiyun 	IEEEtypes_HeOp_t *he_op = MNULL;
2601*4882a593Smuzhiyun 	t_u8 supp_chan[] = {1, 11};
2602*4882a593Smuzhiyun 	t_u8 regulatory_class[] = {1, /**current class*/
2603*4882a593Smuzhiyun 				   1,  2,  3,  4,  12, 22, 23, 24,
2604*4882a593Smuzhiyun 				   25, 27, 28, 29, 30, 32, 33}; /**list
2605*4882a593Smuzhiyun 								   regulatory
2606*4882a593Smuzhiyun 								   class*/
2607*4882a593Smuzhiyun 	IEEEtypes_Generic_t *pSupp_chan = MNULL, *pRegulatory_class = MNULL;
2608*4882a593Smuzhiyun 	sta_node *sta_ptr = MNULL;
2609*4882a593Smuzhiyun 	ENTER();
2610*4882a593Smuzhiyun 
2611*4882a593Smuzhiyun 	/* We don't need peer information for TDLS setup */
2612*4882a593Smuzhiyun 	if (!(tdls_ies->flags & TDLS_IE_FLAGS_SETUP))
2613*4882a593Smuzhiyun 		sta_ptr = wlan_get_station_entry(pmpriv, tdls_ies->peer_mac);
2614*4882a593Smuzhiyun 	pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
2615*4882a593Smuzhiyun 	wlan_get_ap_ext_cap(pmpriv, &ap_ext_cap);
2616*4882a593Smuzhiyun 	if (pbss_desc->bss_band & BAND_A)
2617*4882a593Smuzhiyun 		usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_a;
2618*4882a593Smuzhiyun 	else
2619*4882a593Smuzhiyun 		usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_bg;
2620*4882a593Smuzhiyun 
2621*4882a593Smuzhiyun 	/** fill the extcap */
2622*4882a593Smuzhiyun 	if (tdls_ies->flags & TDLS_IE_FLAGS_EXTCAP) {
2623*4882a593Smuzhiyun 		ext_cap = (IEEEtypes_ExtCap_t *)tdls_ies->ext_cap;
2624*4882a593Smuzhiyun 		ext_cap->ieee_hdr.element_id = EXT_CAPABILITY;
2625*4882a593Smuzhiyun 		ext_cap->ieee_hdr.len = sizeof(ExtCap_t);
2626*4882a593Smuzhiyun 		SET_EXTCAP_TDLS(ext_cap->ext_cap);
2627*4882a593Smuzhiyun 		RESET_EXTCAP_TDLS_UAPSD(ext_cap->ext_cap);
2628*4882a593Smuzhiyun 		RESET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap->ext_cap);
2629*4882a593Smuzhiyun 
2630*4882a593Smuzhiyun 		if (pmpriv->host_tdls_uapsd_support) {
2631*4882a593Smuzhiyun 			/* uapsd in tdls confirm frame*/
2632*4882a593Smuzhiyun 			if (tdls_ies->flags & TDLS_IE_FLAGS_HTINFO) {
2633*4882a593Smuzhiyun 				if (sta_ptr && ISSUPP_EXTCAP_TDLS_UAPSD(
2634*4882a593Smuzhiyun 						       sta_ptr->ExtCap.ext_cap))
2635*4882a593Smuzhiyun 					SET_EXTCAP_TDLS_UAPSD(ext_cap->ext_cap);
2636*4882a593Smuzhiyun 			} else {
2637*4882a593Smuzhiyun 				SET_EXTCAP_TDLS_UAPSD(ext_cap->ext_cap);
2638*4882a593Smuzhiyun 			}
2639*4882a593Smuzhiyun 		}
2640*4882a593Smuzhiyun 		/*  channel switch support */
2641*4882a593Smuzhiyun 		if (pmpriv->host_tdls_cs_support &&
2642*4882a593Smuzhiyun 		    !IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ap_ext_cap)) {
2643*4882a593Smuzhiyun 			/* channel switch in tdls confirm frame*/
2644*4882a593Smuzhiyun 			if (tdls_ies->flags & TDLS_IE_FLAGS_HTINFO) {
2645*4882a593Smuzhiyun 				if (sta_ptr && ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(
2646*4882a593Smuzhiyun 						       sta_ptr->ExtCap.ext_cap))
2647*4882a593Smuzhiyun 					SET_EXTCAP_TDLS_CHAN_SWITCH(
2648*4882a593Smuzhiyun 						ext_cap->ext_cap);
2649*4882a593Smuzhiyun 			} else {
2650*4882a593Smuzhiyun 				SET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap->ext_cap);
2651*4882a593Smuzhiyun 			}
2652*4882a593Smuzhiyun 		}
2653*4882a593Smuzhiyun 
2654*4882a593Smuzhiyun 		RESET_EXTCAP_TDLS_WIDER_BANDWIDTH(ext_cap->ext_cap);
2655*4882a593Smuzhiyun 		if ((pmadapter->fw_bands & BAND_AAC) &&
2656*4882a593Smuzhiyun 		    (MFALSE == wlan_is_ap_in_11ac_mode(pmpriv)))
2657*4882a593Smuzhiyun 			SET_EXTCAP_TDLS_WIDER_BANDWIDTH(ext_cap->ext_cap);
2658*4882a593Smuzhiyun 		/* if peer does not support wider bandwidth, don't set wider
2659*4882a593Smuzhiyun 		 * bandwidth*/
2660*4882a593Smuzhiyun 		if (sta_ptr && sta_ptr->rate_len &&
2661*4882a593Smuzhiyun 		    !ISSUPP_EXTCAP_TDLS_WIDER_BANDWIDTH(
2662*4882a593Smuzhiyun 			    sta_ptr->ExtCap.ext_cap))
2663*4882a593Smuzhiyun 			RESET_EXTCAP_TDLS_WIDER_BANDWIDTH(ext_cap->ext_cap);
2664*4882a593Smuzhiyun 		DBG_HEXDUMP(MCMD_D, "TDLS extcap", tdls_ies->ext_cap,
2665*4882a593Smuzhiyun 			    sizeof(IEEEtypes_ExtCap_t));
2666*4882a593Smuzhiyun 	}
2667*4882a593Smuzhiyun 
2668*4882a593Smuzhiyun 	/** default qos info is 0xf, compare with peer device qos info for tdls
2669*4882a593Smuzhiyun 	 * confirm */
2670*4882a593Smuzhiyun 	if (tdls_ies->flags & TDLS_IE_FLAGS_QOS_INFO) {
2671*4882a593Smuzhiyun 		if (sta_ptr && sta_ptr->rate_len)
2672*4882a593Smuzhiyun 			tdls_ies->QosInfo = sta_ptr->qos_info & 0xf;
2673*4882a593Smuzhiyun 		PRINTM(MCMND, "TDLS Qos info=0x%x\n", tdls_ies->QosInfo);
2674*4882a593Smuzhiyun 	}
2675*4882a593Smuzhiyun 
2676*4882a593Smuzhiyun 	/** fill the htcap based on hwspec */
2677*4882a593Smuzhiyun 	if (tdls_ies->flags & TDLS_IE_FLAGS_HTCAP) {
2678*4882a593Smuzhiyun 		ht_cap = (IEEEtypes_HTCap_t *)tdls_ies->ht_cap;
2679*4882a593Smuzhiyun 		memset(pmadapter, ht_cap, 0, sizeof(IEEEtypes_HTCap_t));
2680*4882a593Smuzhiyun 		if ((sta_ptr && !ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(
2681*4882a593Smuzhiyun 					sta_ptr->ExtCap.ext_cap)) ||
2682*4882a593Smuzhiyun 		    IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ap_ext_cap))
2683*4882a593Smuzhiyun 			wlan_fill_ht_cap_ie(pmpriv, ht_cap,
2684*4882a593Smuzhiyun 					    pbss_desc->bss_band);
2685*4882a593Smuzhiyun 		else if (pmpriv->host_tdls_cs_support &&
2686*4882a593Smuzhiyun 			 (pmadapter->fw_bands & BAND_A))
2687*4882a593Smuzhiyun 			wlan_fill_ht_cap_ie(pmpriv, ht_cap, BAND_A);
2688*4882a593Smuzhiyun 		else
2689*4882a593Smuzhiyun 			wlan_fill_ht_cap_ie(pmpriv, ht_cap,
2690*4882a593Smuzhiyun 					    pbss_desc->bss_band);
2691*4882a593Smuzhiyun 		DBG_HEXDUMP(MCMD_D, "TDLS htcap", tdls_ies->ht_cap,
2692*4882a593Smuzhiyun 			    sizeof(IEEEtypes_HTCap_t));
2693*4882a593Smuzhiyun 	}
2694*4882a593Smuzhiyun 	/** if peer did not support 11AC, do not add vht related ie */
2695*4882a593Smuzhiyun 	if (sta_ptr && sta_ptr->rate_len &&
2696*4882a593Smuzhiyun 	    (sta_ptr->vht_cap.ieee_hdr.element_id != VHT_CAPABILITY))
2697*4882a593Smuzhiyun 		tdls_ies->flags &=
2698*4882a593Smuzhiyun 			~(TDLS_IE_FLAGS_VHTCAP | TDLS_IE_FLAGS_VHTOPRAT |
2699*4882a593Smuzhiyun 			  TDLS_IE_FLAGS_AID);
2700*4882a593Smuzhiyun 	/** fill the vhtcap based on hwspec */
2701*4882a593Smuzhiyun 	if (tdls_ies->flags & TDLS_IE_FLAGS_VHTCAP) {
2702*4882a593Smuzhiyun 		vht_cap = (IEEEtypes_VHTCap_t *)tdls_ies->vht_cap;
2703*4882a593Smuzhiyun 		memset(pmadapter, vht_cap, 0, sizeof(IEEEtypes_VHTCap_t));
2704*4882a593Smuzhiyun 		wlan_fill_vht_cap_ie(pmpriv, vht_cap, pbss_desc->bss_band);
2705*4882a593Smuzhiyun 		if (ht_cap)
2706*4882a593Smuzhiyun 			SETHT_SUPPCHANWIDTH(ht_cap->ht_cap.ht_cap_info);
2707*4882a593Smuzhiyun 		DBG_HEXDUMP(MCMD_D, "TDLS VHT Cap IE", tdls_ies->vht_cap,
2708*4882a593Smuzhiyun 			    sizeof(IEEEtypes_VHTCap_t));
2709*4882a593Smuzhiyun 	}
2710*4882a593Smuzhiyun 	/** fill the vhtoperation based on hwspec */
2711*4882a593Smuzhiyun 	if (tdls_ies->flags & TDLS_IE_FLAGS_VHTOPRAT) {
2712*4882a593Smuzhiyun 		vht_oprat = (IEEEtypes_VHTOprat_t *)tdls_ies->vht_oprat;
2713*4882a593Smuzhiyun 		memset(pmadapter, vht_oprat, 0, sizeof(IEEEtypes_VHTOprat_t));
2714*4882a593Smuzhiyun 		if (sta_ptr &&
2715*4882a593Smuzhiyun 		    (sta_ptr->vht_cap.ieee_hdr.element_id == VHT_CAPABILITY) &&
2716*4882a593Smuzhiyun 		    (pbss_desc->bss_band & BAND_A)) {
2717*4882a593Smuzhiyun 			wlan_fill_tdls_vht_oprat_ie(pmpriv, vht_oprat, sta_ptr);
2718*4882a593Smuzhiyun 		}
2719*4882a593Smuzhiyun 		if (sta_ptr)
2720*4882a593Smuzhiyun 			memcpy_ext(pmadapter, &sta_ptr->vht_oprat,
2721*4882a593Smuzhiyun 				   tdls_ies->vht_oprat,
2722*4882a593Smuzhiyun 				   sizeof(IEEEtypes_VHTOprat_t),
2723*4882a593Smuzhiyun 				   sizeof(IEEEtypes_VHTOprat_t));
2724*4882a593Smuzhiyun 		DBG_HEXDUMP(MCMD_D, "TDLS VHT Operation IE",
2725*4882a593Smuzhiyun 			    tdls_ies->vht_oprat, sizeof(IEEEtypes_VHTOprat_t));
2726*4882a593Smuzhiyun 	}
2727*4882a593Smuzhiyun 	/** fill the AID info */
2728*4882a593Smuzhiyun 	if (tdls_ies->flags & TDLS_IE_FLAGS_AID) {
2729*4882a593Smuzhiyun 		if (pmpriv->curr_bss_params.host_mlme)
2730*4882a593Smuzhiyun 			passoc_rsp = (IEEEtypes_AssocRsp_t
2731*4882a593Smuzhiyun 					      *)(pmpriv->assoc_rsp_buf +
2732*4882a593Smuzhiyun 						 sizeof(IEEEtypes_MgmtHdr_t));
2733*4882a593Smuzhiyun 		else
2734*4882a593Smuzhiyun 			passoc_rsp =
2735*4882a593Smuzhiyun 				(IEEEtypes_AssocRsp_t *)pmpriv->assoc_rsp_buf;
2736*4882a593Smuzhiyun 		aid_info = (IEEEtypes_AID_t *)tdls_ies->aid_info;
2737*4882a593Smuzhiyun 		memset(pmadapter, aid_info, 0, sizeof(IEEEtypes_AID_t));
2738*4882a593Smuzhiyun 		aid_info->ieee_hdr.element_id = AID_INFO;
2739*4882a593Smuzhiyun 		aid_info->ieee_hdr.len = sizeof(t_u16);
2740*4882a593Smuzhiyun 		aid_info->AID = wlan_le16_to_cpu(passoc_rsp->a_id);
2741*4882a593Smuzhiyun 		PRINTM(MCMND, "TDLS AID=0x%x\n", aid_info->AID);
2742*4882a593Smuzhiyun 	}
2743*4882a593Smuzhiyun 	/** fill the hecap based on hwspec */
2744*4882a593Smuzhiyun 	if (tdls_ies->flags & TDLS_IE_FLAGS_HECAP) {
2745*4882a593Smuzhiyun 		he_cap = (IEEEtypes_HECap_t *)tdls_ies->he_cap;
2746*4882a593Smuzhiyun 		memset(pmadapter, he_cap, 0, sizeof(IEEEtypes_HECap_t));
2747*4882a593Smuzhiyun 		wlan_fill_he_cap_ie(pmpriv, he_cap, pbss_desc->bss_band);
2748*4882a593Smuzhiyun 		DBG_HEXDUMP(MCMD_D, "TDLS HE Cap IE", tdls_ies->he_cap,
2749*4882a593Smuzhiyun 			    sizeof(IEEEtypes_Header_t) + he_cap->ieee_hdr.len);
2750*4882a593Smuzhiyun 	}
2751*4882a593Smuzhiyun 
2752*4882a593Smuzhiyun 	if (tdls_ies->flags & TDLS_IE_FLAGS_HEOP) {
2753*4882a593Smuzhiyun 		he_op = (IEEEtypes_HeOp_t *)tdls_ies->he_op;
2754*4882a593Smuzhiyun 		memset(pmadapter, he_op, 0, sizeof(IEEEtypes_HeOp_t));
2755*4882a593Smuzhiyun 		wlan_fill_he_op_ie(pmpriv, he_op);
2756*4882a593Smuzhiyun 	}
2757*4882a593Smuzhiyun 	if (sta_ptr) {
2758*4882a593Smuzhiyun 		memcpy_ext(pmadapter, &sta_ptr->he_op, tdls_ies->he_op,
2759*4882a593Smuzhiyun 			   sizeof(IEEEtypes_HeOp_t), sizeof(IEEEtypes_HeOp_t));
2760*4882a593Smuzhiyun 		DBG_HEXDUMP(MCMD_D, "TDLS HE Operation IE", tdls_ies->he_op,
2761*4882a593Smuzhiyun 			    sizeof(IEEEtypes_HeOp_t));
2762*4882a593Smuzhiyun 	}
2763*4882a593Smuzhiyun 	/** fill the htinfo */
2764*4882a593Smuzhiyun 	if (tdls_ies->flags & TDLS_IE_FLAGS_HTINFO) {
2765*4882a593Smuzhiyun 		ht_info = (IEEEtypes_HTInfo_t *)tdls_ies->ht_info;
2766*4882a593Smuzhiyun 		pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
2767*4882a593Smuzhiyun 		ht_info->ieee_hdr.element_id = HT_OPERATION;
2768*4882a593Smuzhiyun 		ht_info->ieee_hdr.len = sizeof(HTInfo_t);
2769*4882a593Smuzhiyun 		ht_info->ht_info.pri_chan = pbss_desc->channel;
2770*4882a593Smuzhiyun 		/* follow AP's channel bandwidth */
2771*4882a593Smuzhiyun 		if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
2772*4882a593Smuzhiyun 		    pbss_desc->pht_info &&
2773*4882a593Smuzhiyun 		    ISALLOWED_CHANWIDTH40(
2774*4882a593Smuzhiyun 			    pbss_desc->pht_info->ht_info.field2)) {
2775*4882a593Smuzhiyun 			ht_info->ht_info.field2 =
2776*4882a593Smuzhiyun 				pbss_desc->pht_info->ht_info.field2;
2777*4882a593Smuzhiyun 		} else {
2778*4882a593Smuzhiyun 			ht_info->ht_info.field2 =
2779*4882a593Smuzhiyun 				wlan_get_second_channel_offset(
2780*4882a593Smuzhiyun 					pmpriv, pbss_desc->channel);
2781*4882a593Smuzhiyun 		}
2782*4882a593Smuzhiyun 		if (vht_oprat &&
2783*4882a593Smuzhiyun 		    vht_oprat->ieee_hdr.element_id == VHT_OPERATION) {
2784*4882a593Smuzhiyun 			ht_info->ht_info.field2 =
2785*4882a593Smuzhiyun 				wlan_get_second_channel_offset(
2786*4882a593Smuzhiyun 					pmpriv, pbss_desc->channel);
2787*4882a593Smuzhiyun 			ht_info->ht_info.field2 |= MBIT(2);
2788*4882a593Smuzhiyun 		}
2789*4882a593Smuzhiyun 		if (sta_ptr)
2790*4882a593Smuzhiyun 			memcpy_ext(pmadapter, &sta_ptr->HTInfo,
2791*4882a593Smuzhiyun 				   tdls_ies->ht_info,
2792*4882a593Smuzhiyun 				   sizeof(IEEEtypes_HTInfo_t),
2793*4882a593Smuzhiyun 				   sizeof(IEEEtypes_HTInfo_t));
2794*4882a593Smuzhiyun 		DBG_HEXDUMP(MCMD_D, "TDLS htinfo", tdls_ies->ht_info,
2795*4882a593Smuzhiyun 			    sizeof(IEEEtypes_HTInfo_t));
2796*4882a593Smuzhiyun 	}
2797*4882a593Smuzhiyun 
2798*4882a593Smuzhiyun 	/** supported channels andl regulatory IE*/
2799*4882a593Smuzhiyun 	if (pmpriv->host_tdls_cs_support &&
2800*4882a593Smuzhiyun 	    (tdls_ies->flags & TDLS_IE_FLAGS_SUPP_CS_IE) &&
2801*4882a593Smuzhiyun 	    !IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ap_ext_cap)) {
2802*4882a593Smuzhiyun 		/** supported channels IE*/
2803*4882a593Smuzhiyun 		pSupp_chan = (IEEEtypes_Generic_t *)tdls_ies->supp_chan;
2804*4882a593Smuzhiyun 		pSupp_chan->ieee_hdr.element_id = SUPPORTED_CHANNELS;
2805*4882a593Smuzhiyun 		if (pmpriv->chan_supp_len) {
2806*4882a593Smuzhiyun 			pSupp_chan->ieee_hdr.len = pmpriv->chan_supp_len;
2807*4882a593Smuzhiyun 			memcpy_ext(pmadapter, pSupp_chan->data,
2808*4882a593Smuzhiyun 				   pmpriv->chan_supp, pmpriv->chan_supp_len,
2809*4882a593Smuzhiyun 				   sizeof(pSupp_chan->data));
2810*4882a593Smuzhiyun 		} else {
2811*4882a593Smuzhiyun 			pSupp_chan->ieee_hdr.len = sizeof(supp_chan);
2812*4882a593Smuzhiyun 			memcpy_ext(pmadapter, pSupp_chan->data, supp_chan,
2813*4882a593Smuzhiyun 				   sizeof(supp_chan), sizeof(pSupp_chan->data));
2814*4882a593Smuzhiyun 		}
2815*4882a593Smuzhiyun 		DBG_HEXDUMP(
2816*4882a593Smuzhiyun 			MCMD_D, "TDLS supported channel", tdls_ies->supp_chan,
2817*4882a593Smuzhiyun 			pSupp_chan->ieee_hdr.len + sizeof(IEEEtypes_Header_t));
2818*4882a593Smuzhiyun 
2819*4882a593Smuzhiyun 		/**fill supported Regulatory Class IE*/
2820*4882a593Smuzhiyun 		pRegulatory_class =
2821*4882a593Smuzhiyun 			(IEEEtypes_Generic_t *)tdls_ies->regulatory_class;
2822*4882a593Smuzhiyun 		pRegulatory_class->ieee_hdr.element_id = REGULATORY_CLASS;
2823*4882a593Smuzhiyun 		if (pmpriv->supp_regulatory_class_len) {
2824*4882a593Smuzhiyun 			pRegulatory_class->ieee_hdr.len =
2825*4882a593Smuzhiyun 				pmpriv->supp_regulatory_class_len;
2826*4882a593Smuzhiyun 			memcpy_ext(pmadapter, pRegulatory_class->data,
2827*4882a593Smuzhiyun 				   pmpriv->supp_regulatory_class,
2828*4882a593Smuzhiyun 				   pmpriv->supp_regulatory_class_len,
2829*4882a593Smuzhiyun 				   sizeof(pRegulatory_class->data));
2830*4882a593Smuzhiyun 		} else {
2831*4882a593Smuzhiyun 			pRegulatory_class->ieee_hdr.len =
2832*4882a593Smuzhiyun 				sizeof(regulatory_class);
2833*4882a593Smuzhiyun 			memcpy_ext(pmadapter, pRegulatory_class->data,
2834*4882a593Smuzhiyun 				   regulatory_class, sizeof(regulatory_class),
2835*4882a593Smuzhiyun 				   sizeof(pRegulatory_class->data));
2836*4882a593Smuzhiyun 		}
2837*4882a593Smuzhiyun 		DBG_HEXDUMP(MCMD_D, "TDLS supported regulatory class",
2838*4882a593Smuzhiyun 			    tdls_ies->regulatory_class,
2839*4882a593Smuzhiyun 			    pRegulatory_class->ieee_hdr.len +
2840*4882a593Smuzhiyun 				    sizeof(IEEEtypes_Header_t));
2841*4882a593Smuzhiyun 	}
2842*4882a593Smuzhiyun 	LEAVE();
2843*4882a593Smuzhiyun 	return ret;
2844*4882a593Smuzhiyun }
2845*4882a593Smuzhiyun 
2846*4882a593Smuzhiyun /**
2847*4882a593Smuzhiyun  *  @brief Set mimo switch configuration
2848*4882a593Smuzhiyun  *
2849*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
2850*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
2851*4882a593Smuzhiyun  *
2852*4882a593Smuzhiyun  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
2853*4882a593Smuzhiyun  */
wlan_radio_ioctl_mimo_switch_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2854*4882a593Smuzhiyun mlan_status wlan_radio_ioctl_mimo_switch_cfg(pmlan_adapter pmadapter,
2855*4882a593Smuzhiyun 					     pmlan_ioctl_req pioctl_req)
2856*4882a593Smuzhiyun {
2857*4882a593Smuzhiyun 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
2858*4882a593Smuzhiyun 	mlan_ds_radio_cfg *radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
2859*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
2860*4882a593Smuzhiyun 
2861*4882a593Smuzhiyun 	ENTER();
2862*4882a593Smuzhiyun 
2863*4882a593Smuzhiyun 	/* Send request to firmware */
2864*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_MIMO_SWITCH, 0, 0,
2865*4882a593Smuzhiyun 			       (t_void *)pioctl_req,
2866*4882a593Smuzhiyun 			       &(radio_cfg->param.mimo_switch_cfg));
2867*4882a593Smuzhiyun 
2868*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
2869*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
2870*4882a593Smuzhiyun 
2871*4882a593Smuzhiyun 	LEAVE();
2872*4882a593Smuzhiyun 	return ret;
2873*4882a593Smuzhiyun }
2874*4882a593Smuzhiyun 
2875*4882a593Smuzhiyun /**
2876*4882a593Smuzhiyun  *  @brief Get extended version information
2877*4882a593Smuzhiyun  *
2878*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
2879*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
2880*4882a593Smuzhiyun  *
2881*4882a593Smuzhiyun  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
2882*4882a593Smuzhiyun  */
wlan_get_info_ver_ext(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2883*4882a593Smuzhiyun mlan_status wlan_get_info_ver_ext(pmlan_adapter pmadapter,
2884*4882a593Smuzhiyun 				  pmlan_ioctl_req pioctl_req)
2885*4882a593Smuzhiyun {
2886*4882a593Smuzhiyun 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
2887*4882a593Smuzhiyun 	mlan_ds_get_info *pinfo = (mlan_ds_get_info *)pioctl_req->pbuf;
2888*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
2889*4882a593Smuzhiyun 
2890*4882a593Smuzhiyun 	ENTER();
2891*4882a593Smuzhiyun 
2892*4882a593Smuzhiyun 	/* Send request to firmware */
2893*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_VERSION_EXT,
2894*4882a593Smuzhiyun 			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
2895*4882a593Smuzhiyun 			       &pinfo->param.ver_ext.version_str_sel);
2896*4882a593Smuzhiyun 
2897*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
2898*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
2899*4882a593Smuzhiyun 
2900*4882a593Smuzhiyun 	LEAVE();
2901*4882a593Smuzhiyun 	return ret;
2902*4882a593Smuzhiyun }
2903*4882a593Smuzhiyun 
2904*4882a593Smuzhiyun /**
2905*4882a593Smuzhiyun  *  @brief Set/Get link layer statistics
2906*4882a593Smuzhiyun  *
2907*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
2908*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
2909*4882a593Smuzhiyun  *
2910*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2911*4882a593Smuzhiyun  */
wlan_ioctl_link_statistic(mlan_private * pmpriv,pmlan_ioctl_req pioctl_req)2912*4882a593Smuzhiyun mlan_status wlan_ioctl_link_statistic(mlan_private *pmpriv,
2913*4882a593Smuzhiyun 				      pmlan_ioctl_req pioctl_req)
2914*4882a593Smuzhiyun {
2915*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
2916*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
2917*4882a593Smuzhiyun 
2918*4882a593Smuzhiyun 	ENTER();
2919*4882a593Smuzhiyun 
2920*4882a593Smuzhiyun 	/* Check buffer length of MLAN IOCTL */
2921*4882a593Smuzhiyun 	if (pioctl_req->buf_len < sizeof(mlan_ds_get_stats)) {
2922*4882a593Smuzhiyun 		PRINTM(MWARN,
2923*4882a593Smuzhiyun 		       "MLAN IOCTL information buffer length is too short.\n");
2924*4882a593Smuzhiyun 		pioctl_req->data_read_written = 0;
2925*4882a593Smuzhiyun 		pioctl_req->buf_len_needed = sizeof(mlan_ds_get_stats);
2926*4882a593Smuzhiyun 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
2927*4882a593Smuzhiyun 		ret = MLAN_STATUS_RESOURCE;
2928*4882a593Smuzhiyun 		goto exit;
2929*4882a593Smuzhiyun 	}
2930*4882a593Smuzhiyun 
2931*4882a593Smuzhiyun 	switch (pioctl_req->action) {
2932*4882a593Smuzhiyun 	case MLAN_ACT_GET:
2933*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
2934*4882a593Smuzhiyun 		break;
2935*4882a593Smuzhiyun 	case MLAN_ACT_SET:
2936*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
2937*4882a593Smuzhiyun 		break;
2938*4882a593Smuzhiyun 	case MLAN_ACT_CLEAR:
2939*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_REMOVE;
2940*4882a593Smuzhiyun 		break;
2941*4882a593Smuzhiyun 	default:
2942*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
2943*4882a593Smuzhiyun 		goto exit;
2944*4882a593Smuzhiyun 	}
2945*4882a593Smuzhiyun 
2946*4882a593Smuzhiyun 	/* Send request to firmware */
2947*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_LINK_STATS,
2948*4882a593Smuzhiyun 			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
2949*4882a593Smuzhiyun 
2950*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
2951*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
2952*4882a593Smuzhiyun 
2953*4882a593Smuzhiyun exit:
2954*4882a593Smuzhiyun 	LEAVE();
2955*4882a593Smuzhiyun 	return ret;
2956*4882a593Smuzhiyun }
2957*4882a593Smuzhiyun 
2958*4882a593Smuzhiyun /**
2959*4882a593Smuzhiyun  *  @brief Get TX/RX histogram statistic
2960*4882a593Smuzhiyun  *
2961*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
2962*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
2963*4882a593Smuzhiyun  *
2964*4882a593Smuzhiyun  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
2965*4882a593Smuzhiyun  */
wlan_get_tx_rx_histogram(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2966*4882a593Smuzhiyun mlan_status wlan_get_tx_rx_histogram(pmlan_adapter pmadapter,
2967*4882a593Smuzhiyun 				     pmlan_ioctl_req pioctl_req)
2968*4882a593Smuzhiyun {
2969*4882a593Smuzhiyun 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
2970*4882a593Smuzhiyun 	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2971*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
2972*4882a593Smuzhiyun 
2973*4882a593Smuzhiyun 	ENTER();
2974*4882a593Smuzhiyun 
2975*4882a593Smuzhiyun 	/* Send request to firmware */
2976*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_TX_RX_PKT_STATS,
2977*4882a593Smuzhiyun 			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
2978*4882a593Smuzhiyun 			       &(pmisc->param.tx_rx_histogram));
2979*4882a593Smuzhiyun 
2980*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
2981*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
2982*4882a593Smuzhiyun 
2983*4882a593Smuzhiyun 	LEAVE();
2984*4882a593Smuzhiyun 	return ret;
2985*4882a593Smuzhiyun }
2986*4882a593Smuzhiyun 
2987*4882a593Smuzhiyun #ifdef DEBUG_LEVEL1
2988*4882a593Smuzhiyun /**
2989*4882a593Smuzhiyun  *  @brief Set driver debug bit masks in order to enhance performance
2990*4882a593Smuzhiyun  *
2991*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
2992*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
2993*4882a593Smuzhiyun  *
2994*4882a593Smuzhiyun  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
2995*4882a593Smuzhiyun  */
wlan_set_drvdbg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2996*4882a593Smuzhiyun mlan_status wlan_set_drvdbg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
2997*4882a593Smuzhiyun {
2998*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2999*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
3000*4882a593Smuzhiyun 
3001*4882a593Smuzhiyun 	ENTER();
3002*4882a593Smuzhiyun 
3003*4882a593Smuzhiyun 	/* Set driver debug bit masks */
3004*4882a593Smuzhiyun 	mlan_drvdbg = misc->param.drvdbg;
3005*4882a593Smuzhiyun 
3006*4882a593Smuzhiyun 	LEAVE();
3007*4882a593Smuzhiyun 	return ret;
3008*4882a593Smuzhiyun }
3009*4882a593Smuzhiyun #endif
3010*4882a593Smuzhiyun 
3011*4882a593Smuzhiyun /**
3012*4882a593Smuzhiyun  *  @brief Rx mgmt frame forward register
3013*4882a593Smuzhiyun  *
3014*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
3015*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
3016*4882a593Smuzhiyun  *
3017*4882a593Smuzhiyun  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
3018*4882a593Smuzhiyun  */
wlan_reg_rx_mgmt_ind(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3019*4882a593Smuzhiyun mlan_status wlan_reg_rx_mgmt_ind(pmlan_adapter pmadapter,
3020*4882a593Smuzhiyun 				 pmlan_ioctl_req pioctl_req)
3021*4882a593Smuzhiyun {
3022*4882a593Smuzhiyun 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3023*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
3024*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
3025*4882a593Smuzhiyun 
3026*4882a593Smuzhiyun 	ENTER();
3027*4882a593Smuzhiyun 
3028*4882a593Smuzhiyun 	/* Set passthru mask for mgmt frame */
3029*4882a593Smuzhiyun 	pmpriv->mgmt_frame_passthru_mask = misc->param.mgmt_subtype_mask;
3030*4882a593Smuzhiyun 
3031*4882a593Smuzhiyun 	/* Send request to firmware */
3032*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RX_MGMT_IND,
3033*4882a593Smuzhiyun 			       pioctl_req->action, 0, (t_void *)pioctl_req,
3034*4882a593Smuzhiyun 			       &misc->param.mgmt_subtype_mask);
3035*4882a593Smuzhiyun 
3036*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
3037*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
3038*4882a593Smuzhiyun 
3039*4882a593Smuzhiyun 	LEAVE();
3040*4882a593Smuzhiyun 	return ret;
3041*4882a593Smuzhiyun }
3042*4882a593Smuzhiyun 
3043*4882a593Smuzhiyun /**
3044*4882a593Smuzhiyun  *   @brief This function processes the 802.11 mgmt Frame
3045*4882a593Smuzhiyun  *
3046*4882a593Smuzhiyun  *   @param priv            A pointer to mlan_private
3047*4882a593Smuzhiyun  *
3048*4882a593Smuzhiyun  *   @param payload         A pointer to the received buffer
3049*4882a593Smuzhiyun  *   @param payload_len     Length of the received buffer
3050*4882a593Smuzhiyun  *   @param prx_pd          A pointer to RxPD
3051*4882a593Smuzhiyun  *
3052*4882a593Smuzhiyun  *   @return                MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3053*4882a593Smuzhiyun  */
wlan_process_802dot11_mgmt_pkt(mlan_private * priv,t_u8 * payload,t_u32 payload_len,RxPD * prx_pd)3054*4882a593Smuzhiyun mlan_status wlan_process_802dot11_mgmt_pkt(mlan_private *priv, t_u8 *payload,
3055*4882a593Smuzhiyun 					   t_u32 payload_len, RxPD *prx_pd)
3056*4882a593Smuzhiyun {
3057*4882a593Smuzhiyun 	pmlan_adapter pmadapter = priv->adapter;
3058*4882a593Smuzhiyun 	pmlan_callbacks pcb = &pmadapter->callbacks;
3059*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
3060*4882a593Smuzhiyun 	wlan_802_11_header *pieee_pkt_hdr = MNULL;
3061*4882a593Smuzhiyun 	t_u16 sub_type = 0;
3062*4882a593Smuzhiyun 	t_u8 *event_buf = MNULL;
3063*4882a593Smuzhiyun 	mlan_event *pevent = MNULL;
3064*4882a593Smuzhiyun 	t_u8 unicast = 0;
3065*4882a593Smuzhiyun 	t_u8 broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
3066*4882a593Smuzhiyun 	IEEE80211_MGMT *mgmt = MNULL;
3067*4882a593Smuzhiyun 	t_u8 category = 0;
3068*4882a593Smuzhiyun 	t_u8 action_code = 0;
3069*4882a593Smuzhiyun #ifdef UAP_SUPPORT
3070*4882a593Smuzhiyun 	sta_node *sta_ptr = MNULL;
3071*4882a593Smuzhiyun 	MrvlIETypes_MgmtFrameSet_t *tlv;
3072*4882a593Smuzhiyun 	pmlan_buffer pmbuf;
3073*4882a593Smuzhiyun #endif
3074*4882a593Smuzhiyun 
3075*4882a593Smuzhiyun 	ENTER();
3076*4882a593Smuzhiyun 	if (payload_len > (MAX_EVENT_SIZE - sizeof(mlan_event))) {
3077*4882a593Smuzhiyun 		PRINTM(MERROR, "Dropping large mgmt frame,len =%d\n",
3078*4882a593Smuzhiyun 		       payload_len);
3079*4882a593Smuzhiyun 		LEAVE();
3080*4882a593Smuzhiyun 		return ret;
3081*4882a593Smuzhiyun 	}
3082*4882a593Smuzhiyun 	/* Check  packet type-subtype and compare with mgmt_passthru_mask
3083*4882a593Smuzhiyun 	 * If event is needed to host, just eventify it */
3084*4882a593Smuzhiyun 	pieee_pkt_hdr = (wlan_802_11_header *)payload;
3085*4882a593Smuzhiyun 	sub_type = IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE(pieee_pkt_hdr->frm_ctl);
3086*4882a593Smuzhiyun 	if (((1 << sub_type) & priv->mgmt_frame_passthru_mask) == 0) {
3087*4882a593Smuzhiyun 		PRINTM(MINFO, "Dropping mgmt frame for subtype %d snr=%d.\n",
3088*4882a593Smuzhiyun 		       sub_type, prx_pd->snr);
3089*4882a593Smuzhiyun 		LEAVE();
3090*4882a593Smuzhiyun 		return ret;
3091*4882a593Smuzhiyun 	}
3092*4882a593Smuzhiyun 	switch (sub_type) {
3093*4882a593Smuzhiyun 	case SUBTYPE_ASSOC_REQUEST:
3094*4882a593Smuzhiyun 	case SUBTYPE_REASSOC_REQUEST:
3095*4882a593Smuzhiyun #ifdef UAP_SUPPORT
3096*4882a593Smuzhiyun 		if (priv->uap_host_based & UAP_FLAG_HOST_MLME) {
3097*4882a593Smuzhiyun 			PRINTM_NETINTF(MMSG, priv);
3098*4882a593Smuzhiyun 			if (!memcmp(pmadapter, pieee_pkt_hdr->addr3,
3099*4882a593Smuzhiyun 				    priv->curr_addr, MLAN_MAC_ADDR_LENGTH)) {
3100*4882a593Smuzhiyun 				PRINTM(MMSG,
3101*4882a593Smuzhiyun 				       "wlan: HostMlme MICRO_AP_STA_ASSOC " MACSTR
3102*4882a593Smuzhiyun 				       "\n",
3103*4882a593Smuzhiyun 				       MAC2STR(pieee_pkt_hdr->addr2));
3104*4882a593Smuzhiyun 				mgmt = (IEEE80211_MGMT *)payload;
3105*4882a593Smuzhiyun 				sta_ptr = wlan_add_station_entry(
3106*4882a593Smuzhiyun 					priv, pieee_pkt_hdr->addr2);
3107*4882a593Smuzhiyun 				if (sta_ptr) {
3108*4882a593Smuzhiyun 					sta_ptr->capability = wlan_le16_to_cpu(
3109*4882a593Smuzhiyun 						mgmt->u.assoc_req.capab_info);
3110*4882a593Smuzhiyun 					pmbuf = wlan_alloc_mlan_buffer(
3111*4882a593Smuzhiyun 						pmadapter, payload_len, 0,
3112*4882a593Smuzhiyun 						MOAL_MALLOC_BUFFER);
3113*4882a593Smuzhiyun 					if (pmbuf) {
3114*4882a593Smuzhiyun 						PRINTM(MCMND,
3115*4882a593Smuzhiyun 						       "check sta capability\n");
3116*4882a593Smuzhiyun 						pmbuf->data_len =
3117*4882a593Smuzhiyun 							ASSOC_EVENT_FIX_SIZE;
3118*4882a593Smuzhiyun 						tlv = (MrvlIETypes_MgmtFrameSet_t
3119*4882a593Smuzhiyun 							       *)(pmbuf->pbuf +
3120*4882a593Smuzhiyun 								  pmbuf->data_offset +
3121*4882a593Smuzhiyun 								  pmbuf->data_len);
3122*4882a593Smuzhiyun 						tlv->type = wlan_cpu_to_le16(
3123*4882a593Smuzhiyun 							TLV_TYPE_MGMT_FRAME);
3124*4882a593Smuzhiyun 						tlv->len = sizeof(
3125*4882a593Smuzhiyun 							IEEEtypes_FrameCtl_t);
3126*4882a593Smuzhiyun 						memcpy_ext(
3127*4882a593Smuzhiyun 							pmadapter,
3128*4882a593Smuzhiyun 							(t_u8 *)&tlv
3129*4882a593Smuzhiyun 								->frame_control,
3130*4882a593Smuzhiyun 							&pieee_pkt_hdr->frm_ctl,
3131*4882a593Smuzhiyun 							sizeof(IEEEtypes_FrameCtl_t),
3132*4882a593Smuzhiyun 							sizeof(IEEEtypes_FrameCtl_t));
3133*4882a593Smuzhiyun 						pmbuf->data_len += sizeof(
3134*4882a593Smuzhiyun 							MrvlIETypes_MgmtFrameSet_t);
3135*4882a593Smuzhiyun 						memcpy_ext(
3136*4882a593Smuzhiyun 							pmadapter,
3137*4882a593Smuzhiyun 							pmbuf->pbuf +
3138*4882a593Smuzhiyun 								pmbuf->data_offset +
3139*4882a593Smuzhiyun 								pmbuf->data_len,
3140*4882a593Smuzhiyun 							payload +
3141*4882a593Smuzhiyun 								sizeof(wlan_802_11_header),
3142*4882a593Smuzhiyun 							payload_len -
3143*4882a593Smuzhiyun 								sizeof(wlan_802_11_header),
3144*4882a593Smuzhiyun 							payload_len -
3145*4882a593Smuzhiyun 								sizeof(wlan_802_11_header));
3146*4882a593Smuzhiyun 						pmbuf->data_len +=
3147*4882a593Smuzhiyun 							payload_len -
3148*4882a593Smuzhiyun 							sizeof(wlan_802_11_header);
3149*4882a593Smuzhiyun 						tlv->len +=
3150*4882a593Smuzhiyun 							payload_len -
3151*4882a593Smuzhiyun 							sizeof(wlan_802_11_header);
3152*4882a593Smuzhiyun 						tlv->len = wlan_cpu_to_le16(
3153*4882a593Smuzhiyun 							tlv->len);
3154*4882a593Smuzhiyun 						DBG_HEXDUMP(
3155*4882a593Smuzhiyun 							MCMD_D, "assoc_req",
3156*4882a593Smuzhiyun 							pmbuf->pbuf +
3157*4882a593Smuzhiyun 								pmbuf->data_offset,
3158*4882a593Smuzhiyun 							pmbuf->data_len);
3159*4882a593Smuzhiyun 						wlan_check_sta_capability(
3160*4882a593Smuzhiyun 							priv, pmbuf, sta_ptr);
3161*4882a593Smuzhiyun 						wlan_free_mlan_buffer(pmadapter,
3162*4882a593Smuzhiyun 								      pmbuf);
3163*4882a593Smuzhiyun 					}
3164*4882a593Smuzhiyun 				}
3165*4882a593Smuzhiyun 			} else {
3166*4882a593Smuzhiyun 				PRINTM(MMSG,
3167*4882a593Smuzhiyun 				       "wlan: Drop MICRO_AP_STA_ASSOC " MACSTR
3168*4882a593Smuzhiyun 				       " from unknown BSSID " MACSTR "\n",
3169*4882a593Smuzhiyun 				       MAC2STR(pieee_pkt_hdr->addr2),
3170*4882a593Smuzhiyun 				       MAC2STR(pieee_pkt_hdr->addr3));
3171*4882a593Smuzhiyun 			}
3172*4882a593Smuzhiyun 		}
3173*4882a593Smuzhiyun 		unicast = MTRUE;
3174*4882a593Smuzhiyun 		break;
3175*4882a593Smuzhiyun #endif
3176*4882a593Smuzhiyun 	case SUBTYPE_AUTH:
3177*4882a593Smuzhiyun 		unicast = MTRUE;
3178*4882a593Smuzhiyun 		PRINTM_NETINTF(MMSG, priv);
3179*4882a593Smuzhiyun 		PRINTM(MMSG, "wlan: HostMlme Auth received from " MACSTR "\n",
3180*4882a593Smuzhiyun 		       MAC2STR(pieee_pkt_hdr->addr2));
3181*4882a593Smuzhiyun 		break;
3182*4882a593Smuzhiyun 	case SUBTYPE_PROBE_RESP:
3183*4882a593Smuzhiyun 		unicast = MTRUE;
3184*4882a593Smuzhiyun 		break;
3185*4882a593Smuzhiyun 	case SUBTYPE_DISASSOC:
3186*4882a593Smuzhiyun 	case SUBTYPE_DEAUTH:
3187*4882a593Smuzhiyun 		if (memcmp(pmadapter, pieee_pkt_hdr->addr1, broadcast,
3188*4882a593Smuzhiyun 			   MLAN_MAC_ADDR_LENGTH))
3189*4882a593Smuzhiyun 			unicast = MTRUE;
3190*4882a593Smuzhiyun #ifdef UAP_SUPPORT
3191*4882a593Smuzhiyun 		if (priv->uap_host_based & UAP_FLAG_HOST_MLME) {
3192*4882a593Smuzhiyun 			if (!memcmp(pmadapter, pieee_pkt_hdr->addr3,
3193*4882a593Smuzhiyun 				    priv->curr_addr, MLAN_MAC_ADDR_LENGTH)) {
3194*4882a593Smuzhiyun 				PRINTM_NETINTF(MMSG, priv);
3195*4882a593Smuzhiyun 				PRINTM(MMSG,
3196*4882a593Smuzhiyun 				       "wlan: HostMlme Deauth Receive from " MACSTR
3197*4882a593Smuzhiyun 				       "\n",
3198*4882a593Smuzhiyun 				       MAC2STR(pieee_pkt_hdr->addr2));
3199*4882a593Smuzhiyun 			}
3200*4882a593Smuzhiyun 		}
3201*4882a593Smuzhiyun #endif
3202*4882a593Smuzhiyun 		if (priv->bss_role == MLAN_BSS_ROLE_STA) {
3203*4882a593Smuzhiyun 			if (priv->curr_bss_params.host_mlme) {
3204*4882a593Smuzhiyun 				if (memcmp(pmadapter, pieee_pkt_hdr->addr3,
3205*4882a593Smuzhiyun 					   (t_u8 *)priv->curr_bss_params
3206*4882a593Smuzhiyun 						   .bss_descriptor.mac_address,
3207*4882a593Smuzhiyun 					   MLAN_MAC_ADDR_LENGTH)) {
3208*4882a593Smuzhiyun 					PRINTM(MCMND,
3209*4882a593Smuzhiyun 					       "Dropping Deauth frame from other bssid: type=%d " MACSTR
3210*4882a593Smuzhiyun 					       "\n",
3211*4882a593Smuzhiyun 					       sub_type,
3212*4882a593Smuzhiyun 					       MAC2STR(pieee_pkt_hdr->addr3));
3213*4882a593Smuzhiyun 					LEAVE();
3214*4882a593Smuzhiyun 					return ret;
3215*4882a593Smuzhiyun 				}
3216*4882a593Smuzhiyun 				PRINTM_NETINTF(MMSG, priv);
3217*4882a593Smuzhiyun 				PRINTM(MMSG,
3218*4882a593Smuzhiyun 				       "wlan: HostMlme Disconnected: sub_type=%d\n",
3219*4882a593Smuzhiyun 				       sub_type);
3220*4882a593Smuzhiyun 				pmadapter->pending_disconnect_priv = priv;
3221*4882a593Smuzhiyun 				wlan_recv_event(
3222*4882a593Smuzhiyun 					priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
3223*4882a593Smuzhiyun 					MNULL);
3224*4882a593Smuzhiyun 			}
3225*4882a593Smuzhiyun 		}
3226*4882a593Smuzhiyun 		break;
3227*4882a593Smuzhiyun 	case SUBTYPE_ACTION:
3228*4882a593Smuzhiyun 		category = *(payload + sizeof(wlan_802_11_header));
3229*4882a593Smuzhiyun 		action_code = *(payload + sizeof(wlan_802_11_header) + 1);
3230*4882a593Smuzhiyun 		if (category == IEEE_MGMT_ACTION_CATEGORY_BLOCK_ACK) {
3231*4882a593Smuzhiyun 			PRINTM(MINFO,
3232*4882a593Smuzhiyun 			       "Drop BLOCK ACK action frame: action_code=%d\n",
3233*4882a593Smuzhiyun 			       action_code);
3234*4882a593Smuzhiyun 			LEAVE();
3235*4882a593Smuzhiyun 			return ret;
3236*4882a593Smuzhiyun 		}
3237*4882a593Smuzhiyun 		if ((category == IEEE_MGMT_ACTION_CATEGORY_PUBLIC) &&
3238*4882a593Smuzhiyun 		    (action_code == BSS_20_40_COEX)) {
3239*4882a593Smuzhiyun 			PRINTM(MINFO,
3240*4882a593Smuzhiyun 			       "Drop 20/40 BSS Coexistence Management frame\n");
3241*4882a593Smuzhiyun 			LEAVE();
3242*4882a593Smuzhiyun 			return ret;
3243*4882a593Smuzhiyun 		}
3244*4882a593Smuzhiyun 		if ((category == CATEGORY_PUBLIC) &&
3245*4882a593Smuzhiyun 		    (action_code == TDLS_DISCOVERY_RESPONSE)) {
3246*4882a593Smuzhiyun 			pcb->moal_updata_peer_signal(pmadapter->pmoal_handle,
3247*4882a593Smuzhiyun 						     priv->bss_index,
3248*4882a593Smuzhiyun 						     pieee_pkt_hdr->addr2,
3249*4882a593Smuzhiyun 						     prx_pd->snr, prx_pd->nf);
3250*4882a593Smuzhiyun 			PRINTM(MINFO,
3251*4882a593Smuzhiyun 			       "Rx: TDLS discovery response, nf=%d, snr=%d\n",
3252*4882a593Smuzhiyun 			       prx_pd->nf, prx_pd->snr);
3253*4882a593Smuzhiyun 		}
3254*4882a593Smuzhiyun 		if (memcmp(pmadapter, pieee_pkt_hdr->addr1, broadcast,
3255*4882a593Smuzhiyun 			   MLAN_MAC_ADDR_LENGTH))
3256*4882a593Smuzhiyun 			unicast = MTRUE;
3257*4882a593Smuzhiyun 		break;
3258*4882a593Smuzhiyun 	default:
3259*4882a593Smuzhiyun 		break;
3260*4882a593Smuzhiyun 	}
3261*4882a593Smuzhiyun 	if (unicast == MTRUE) {
3262*4882a593Smuzhiyun 		if (memcmp(pmadapter, pieee_pkt_hdr->addr1, priv->curr_addr,
3263*4882a593Smuzhiyun 			   MLAN_MAC_ADDR_LENGTH)) {
3264*4882a593Smuzhiyun 			PRINTM(MINFO,
3265*4882a593Smuzhiyun 			       "Dropping mgmt frame for others: type=%d " MACSTR
3266*4882a593Smuzhiyun 			       "\n",
3267*4882a593Smuzhiyun 			       sub_type, MAC2STR(pieee_pkt_hdr->addr1));
3268*4882a593Smuzhiyun 			LEAVE();
3269*4882a593Smuzhiyun 			return ret;
3270*4882a593Smuzhiyun 		}
3271*4882a593Smuzhiyun 	}
3272*4882a593Smuzhiyun 	/* Allocate memory for event buffer */
3273*4882a593Smuzhiyun 	ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
3274*4882a593Smuzhiyun 			       MLAN_MEM_DEF, &event_buf);
3275*4882a593Smuzhiyun 	if ((ret != MLAN_STATUS_SUCCESS) || !event_buf) {
3276*4882a593Smuzhiyun 		PRINTM(MERROR, "Could not allocate buffer for event buf\n");
3277*4882a593Smuzhiyun 		LEAVE();
3278*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
3279*4882a593Smuzhiyun 	}
3280*4882a593Smuzhiyun 	pevent = (pmlan_event)event_buf;
3281*4882a593Smuzhiyun 	pevent->bss_index = priv->bss_index;
3282*4882a593Smuzhiyun 	mgmt = (IEEE80211_MGMT *)payload;
3283*4882a593Smuzhiyun 	if (!priv->curr_bss_params.host_mlme && sub_type == SUBTYPE_ACTION &&
3284*4882a593Smuzhiyun 	    mgmt->u.ft_resp.category == FT_CATEGORY &&
3285*4882a593Smuzhiyun 	    mgmt->u.ft_resp.action == FT_ACTION_RESPONSE &&
3286*4882a593Smuzhiyun 	    mgmt->u.ft_resp.status_code == 0) {
3287*4882a593Smuzhiyun 		PRINTM(MCMND, "FT Action response received\n");
3288*4882a593Smuzhiyun #define FT_ACTION_HEAD_LEN (24 + 6 + 16)
3289*4882a593Smuzhiyun 		pevent->event_id = MLAN_EVENT_ID_DRV_FT_RESPONSE;
3290*4882a593Smuzhiyun 		pevent->event_len =
3291*4882a593Smuzhiyun 			payload_len + MLAN_MAC_ADDR_LENGTH - FT_ACTION_HEAD_LEN;
3292*4882a593Smuzhiyun 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
3293*4882a593Smuzhiyun 			   &mgmt->u.ft_resp.target_ap_addr,
3294*4882a593Smuzhiyun 			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
3295*4882a593Smuzhiyun 		memcpy_ext(pmadapter,
3296*4882a593Smuzhiyun 			   (t_u8 *)(pevent->event_buf + MLAN_MAC_ADDR_LENGTH),
3297*4882a593Smuzhiyun 			   payload + FT_ACTION_HEAD_LEN,
3298*4882a593Smuzhiyun 			   payload_len - FT_ACTION_HEAD_LEN,
3299*4882a593Smuzhiyun 			   pevent->event_len - MLAN_MAC_ADDR_LENGTH);
3300*4882a593Smuzhiyun 	} else if (!priv->curr_bss_params.host_mlme &&
3301*4882a593Smuzhiyun 		   sub_type == SUBTYPE_AUTH &&
3302*4882a593Smuzhiyun 		   mgmt->u.auth.auth_alg == MLAN_AUTH_MODE_FT &&
3303*4882a593Smuzhiyun 		   mgmt->u.auth.auth_transaction == 2 &&
3304*4882a593Smuzhiyun 		   mgmt->u.auth.status_code == 0) {
3305*4882a593Smuzhiyun 		PRINTM(MCMND, "FT auth response received \n");
3306*4882a593Smuzhiyun #define AUTH_PACKET_LEN (24 + 6 + 6)
3307*4882a593Smuzhiyun 		pevent->event_id = MLAN_EVENT_ID_DRV_FT_RESPONSE;
3308*4882a593Smuzhiyun 		pevent->event_len =
3309*4882a593Smuzhiyun 			payload_len + MLAN_MAC_ADDR_LENGTH - AUTH_PACKET_LEN;
3310*4882a593Smuzhiyun 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf, mgmt->sa,
3311*4882a593Smuzhiyun 			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
3312*4882a593Smuzhiyun 		memcpy_ext(pmadapter,
3313*4882a593Smuzhiyun 			   (t_u8 *)(pevent->event_buf + MLAN_MAC_ADDR_LENGTH),
3314*4882a593Smuzhiyun 			   payload + AUTH_PACKET_LEN,
3315*4882a593Smuzhiyun 			   payload_len - AUTH_PACKET_LEN,
3316*4882a593Smuzhiyun 			   pevent->event_len - MLAN_MAC_ADDR_LENGTH);
3317*4882a593Smuzhiyun 	} else {
3318*4882a593Smuzhiyun 		pevent->event_id = MLAN_EVENT_ID_DRV_MGMT_FRAME;
3319*4882a593Smuzhiyun 		pevent->event_len = payload_len + sizeof(pevent->event_id);
3320*4882a593Smuzhiyun 		memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
3321*4882a593Smuzhiyun 			   (t_u8 *)&pevent->event_id, sizeof(pevent->event_id),
3322*4882a593Smuzhiyun 			   pevent->event_len);
3323*4882a593Smuzhiyun 		memcpy_ext(
3324*4882a593Smuzhiyun 			pmadapter,
3325*4882a593Smuzhiyun 			(t_u8 *)(pevent->event_buf + sizeof(pevent->event_id)),
3326*4882a593Smuzhiyun 			payload, payload_len, payload_len);
3327*4882a593Smuzhiyun 	}
3328*4882a593Smuzhiyun 	wlan_recv_event(priv, pevent->event_id, pevent);
3329*4882a593Smuzhiyun 	if (event_buf)
3330*4882a593Smuzhiyun 		pcb->moal_mfree(pmadapter->pmoal_handle, event_buf);
3331*4882a593Smuzhiyun 	LEAVE();
3332*4882a593Smuzhiyun 	return MLAN_STATUS_SUCCESS;
3333*4882a593Smuzhiyun }
3334*4882a593Smuzhiyun 
3335*4882a593Smuzhiyun #ifdef STA_SUPPORT
3336*4882a593Smuzhiyun /**
3337*4882a593Smuzhiyun  *  @brief Extended capabilities configuration
3338*4882a593Smuzhiyun  *
3339*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
3340*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
3341*4882a593Smuzhiyun  *
3342*4882a593Smuzhiyun  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
3343*4882a593Smuzhiyun  */
wlan_misc_ext_capa_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3344*4882a593Smuzhiyun mlan_status wlan_misc_ext_capa_cfg(pmlan_adapter pmadapter,
3345*4882a593Smuzhiyun 				   pmlan_ioctl_req pioctl_req)
3346*4882a593Smuzhiyun {
3347*4882a593Smuzhiyun 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3348*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
3349*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
3350*4882a593Smuzhiyun 
3351*4882a593Smuzhiyun 	ENTER();
3352*4882a593Smuzhiyun 
3353*4882a593Smuzhiyun 	if (MLAN_ACT_GET == pioctl_req->action)
3354*4882a593Smuzhiyun 		memcpy_ext(pmpriv->adapter, &misc->param.ext_cap,
3355*4882a593Smuzhiyun 			   &pmpriv->def_ext_cap, sizeof(misc->param.ext_cap),
3356*4882a593Smuzhiyun 			   sizeof(misc->param.ext_cap));
3357*4882a593Smuzhiyun 	else if (MLAN_ACT_SET == pioctl_req->action) {
3358*4882a593Smuzhiyun 		memcpy_ext(pmpriv->adapter, &pmpriv->ext_cap,
3359*4882a593Smuzhiyun 			   &misc->param.ext_cap, sizeof(misc->param.ext_cap),
3360*4882a593Smuzhiyun 			   sizeof(pmpriv->ext_cap));
3361*4882a593Smuzhiyun 		/* Save default Extended Capability */
3362*4882a593Smuzhiyun 		memcpy_ext(pmpriv->adapter, &pmpriv->def_ext_cap,
3363*4882a593Smuzhiyun 			   &pmpriv->ext_cap, sizeof(pmpriv->ext_cap),
3364*4882a593Smuzhiyun 			   sizeof(pmpriv->def_ext_cap));
3365*4882a593Smuzhiyun 		if (pmpriv->config_bands & BAND_AAC)
3366*4882a593Smuzhiyun 			SET_EXTCAP_OPERMODENTF(pmpriv->ext_cap);
3367*4882a593Smuzhiyun 	}
3368*4882a593Smuzhiyun 
3369*4882a593Smuzhiyun 	LEAVE();
3370*4882a593Smuzhiyun 	return ret;
3371*4882a593Smuzhiyun }
3372*4882a593Smuzhiyun 
3373*4882a593Smuzhiyun /**
3374*4882a593Smuzhiyun  *  @brief Check whether Extended Capabilities IE support
3375*4882a593Smuzhiyun  *
3376*4882a593Smuzhiyun  *  @param pmpriv             A pointer to mlan_private structure
3377*4882a593Smuzhiyun  *
3378*4882a593Smuzhiyun  *  @return                   MTRUE or MFALSE;
3379*4882a593Smuzhiyun  */
wlan_is_ext_capa_support(mlan_private * pmpriv)3380*4882a593Smuzhiyun t_u32 wlan_is_ext_capa_support(mlan_private *pmpriv)
3381*4882a593Smuzhiyun {
3382*4882a593Smuzhiyun 	ENTER();
3383*4882a593Smuzhiyun 
3384*4882a593Smuzhiyun 	if (ISSUPP_EXTCAP_TDLS(pmpriv->ext_cap) ||
3385*4882a593Smuzhiyun 	    ISSUPP_EXTCAP_INTERWORKING(pmpriv->ext_cap) ||
3386*4882a593Smuzhiyun 	    ISSUPP_EXTCAP_BSS_TRANSITION(pmpriv->ext_cap) ||
3387*4882a593Smuzhiyun 	    ISSUPP_EXTCAP_QOS_MAP(pmpriv->ext_cap) ||
3388*4882a593Smuzhiyun 	    ISSUPP_EXTCAP_OPERMODENTF(pmpriv->ext_cap)) {
3389*4882a593Smuzhiyun 		LEAVE();
3390*4882a593Smuzhiyun 		return MTRUE;
3391*4882a593Smuzhiyun 	} else {
3392*4882a593Smuzhiyun 		LEAVE();
3393*4882a593Smuzhiyun 		return MFALSE;
3394*4882a593Smuzhiyun 	}
3395*4882a593Smuzhiyun }
3396*4882a593Smuzhiyun #endif
3397*4882a593Smuzhiyun 
3398*4882a593Smuzhiyun /**
3399*4882a593Smuzhiyun  *  @brief Set hotspot enable/disable
3400*4882a593Smuzhiyun  *
3401*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
3402*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
3403*4882a593Smuzhiyun  *
3404*4882a593Smuzhiyun  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
3405*4882a593Smuzhiyun  */
wlan_misc_hotspot_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3406*4882a593Smuzhiyun mlan_status wlan_misc_hotspot_cfg(pmlan_adapter pmadapter,
3407*4882a593Smuzhiyun 				  pmlan_ioctl_req pioctl_req)
3408*4882a593Smuzhiyun {
3409*4882a593Smuzhiyun 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3410*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
3411*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
3412*4882a593Smuzhiyun 
3413*4882a593Smuzhiyun 	ENTER();
3414*4882a593Smuzhiyun 
3415*4882a593Smuzhiyun 	if (MLAN_ACT_GET == pioctl_req->action)
3416*4882a593Smuzhiyun 		misc->param.hotspot_cfg = pmpriv->hotspot_cfg;
3417*4882a593Smuzhiyun 	else if (MLAN_ACT_SET == pioctl_req->action)
3418*4882a593Smuzhiyun 		pmpriv->hotspot_cfg = misc->param.hotspot_cfg;
3419*4882a593Smuzhiyun 
3420*4882a593Smuzhiyun 	LEAVE();
3421*4882a593Smuzhiyun 	return ret;
3422*4882a593Smuzhiyun }
3423*4882a593Smuzhiyun 
3424*4882a593Smuzhiyun #ifdef STA_SUPPORT
3425*4882a593Smuzhiyun /**
3426*4882a593Smuzhiyun  *  @brief Add Extended Capabilities IE
3427*4882a593Smuzhiyun  *
3428*4882a593Smuzhiyun  *  @param pmpriv             A pointer to mlan_private structure
3429*4882a593Smuzhiyun  *  @param pbss_desc          A pointer to BSSDescriptor_t structure
3430*4882a593Smuzhiyun  *  @param pptlv_out          A pointer to TLV to fill in
3431*4882a593Smuzhiyun  *
3432*4882a593Smuzhiyun  *  @return                   N/A
3433*4882a593Smuzhiyun  */
wlan_add_ext_capa_info_ie(mlan_private * pmpriv,BSSDescriptor_t * pbss_desc,t_u8 ** pptlv_out)3434*4882a593Smuzhiyun void wlan_add_ext_capa_info_ie(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc,
3435*4882a593Smuzhiyun 			       t_u8 **pptlv_out)
3436*4882a593Smuzhiyun {
3437*4882a593Smuzhiyun 	MrvlIETypes_ExtCap_t *pext_cap = MNULL;
3438*4882a593Smuzhiyun 
3439*4882a593Smuzhiyun 	ENTER();
3440*4882a593Smuzhiyun 
3441*4882a593Smuzhiyun 	pext_cap = (MrvlIETypes_ExtCap_t *)*pptlv_out;
3442*4882a593Smuzhiyun 	memset(pmpriv->adapter, pext_cap, 0, sizeof(MrvlIETypes_ExtCap_t));
3443*4882a593Smuzhiyun 	pext_cap->header.type = wlan_cpu_to_le16(EXT_CAPABILITY);
3444*4882a593Smuzhiyun 	pext_cap->header.len = wlan_cpu_to_le16(sizeof(ExtCap_t));
3445*4882a593Smuzhiyun 	if (pmpriv->adapter->ecsa_enable)
3446*4882a593Smuzhiyun 		SET_EXTCAP_EXT_CHANNEL_SWITCH(pmpriv->ext_cap);
3447*4882a593Smuzhiyun 	else
3448*4882a593Smuzhiyun 		RESET_EXTCAP_EXT_CHANNEL_SWITCH(pmpriv->ext_cap);
3449*4882a593Smuzhiyun 	if (pbss_desc && pbss_desc->multi_bssid_ap)
3450*4882a593Smuzhiyun 		SET_EXTCAP_MULTI_BSSID(pmpriv->ext_cap);
3451*4882a593Smuzhiyun 	if (wlan_check_11ax_twt_supported(pmpriv, pbss_desc))
3452*4882a593Smuzhiyun 		SET_EXTCAP_TWT_REQ(pmpriv->ext_cap);
3453*4882a593Smuzhiyun 	memcpy_ext(pmpriv->adapter, &pext_cap->ext_cap, &pmpriv->ext_cap,
3454*4882a593Smuzhiyun 		   sizeof(pmpriv->ext_cap), sizeof(pext_cap->ext_cap));
3455*4882a593Smuzhiyun 	*pptlv_out += sizeof(MrvlIETypes_ExtCap_t);
3456*4882a593Smuzhiyun 
3457*4882a593Smuzhiyun 	LEAVE();
3458*4882a593Smuzhiyun }
3459*4882a593Smuzhiyun #endif
3460*4882a593Smuzhiyun 
3461*4882a593Smuzhiyun /**
3462*4882a593Smuzhiyun  *  @brief Get OTP user data
3463*4882a593Smuzhiyun  *
3464*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
3465*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
3466*4882a593Smuzhiyun  *
3467*4882a593Smuzhiyun  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
3468*4882a593Smuzhiyun  */
wlan_misc_otp_user_data(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3469*4882a593Smuzhiyun mlan_status wlan_misc_otp_user_data(pmlan_adapter pmadapter,
3470*4882a593Smuzhiyun 				    pmlan_ioctl_req pioctl_req)
3471*4882a593Smuzhiyun {
3472*4882a593Smuzhiyun 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3473*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
3474*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_FAILURE;
3475*4882a593Smuzhiyun 
3476*4882a593Smuzhiyun 	ENTER();
3477*4882a593Smuzhiyun 
3478*4882a593Smuzhiyun 	if (misc->param.otp_user_data.user_data_length >
3479*4882a593Smuzhiyun 	    MAX_OTP_USER_DATA_LEN) {
3480*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid OTP user data length\n");
3481*4882a593Smuzhiyun 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3482*4882a593Smuzhiyun 		LEAVE();
3483*4882a593Smuzhiyun 		return ret;
3484*4882a593Smuzhiyun 	}
3485*4882a593Smuzhiyun 
3486*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_OTP_READ_USER_DATA,
3487*4882a593Smuzhiyun 			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
3488*4882a593Smuzhiyun 			       &misc->param.otp_user_data);
3489*4882a593Smuzhiyun 
3490*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
3491*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
3492*4882a593Smuzhiyun 
3493*4882a593Smuzhiyun 	LEAVE();
3494*4882a593Smuzhiyun 	return ret;
3495*4882a593Smuzhiyun }
3496*4882a593Smuzhiyun 
3497*4882a593Smuzhiyun #ifdef UAP_SUPPORT
3498*4882a593Smuzhiyun /**
3499*4882a593Smuzhiyun  *  @brief	Check 11B support Rates
3500*4882a593Smuzhiyun  *
3501*4882a593Smuzhiyun  *
3502*4882a593Smuzhiyun  *  @param pmadapter	Private mlan adapter structure
3503*4882a593Smuzhiyun  *
3504*4882a593Smuzhiyun  *  @return MTRUE/MFALSE
3505*4882a593Smuzhiyun  *
3506*4882a593Smuzhiyun  */
wlan_check_ie_11b_support_rates(pIEEEtypes_Generic_t prates)3507*4882a593Smuzhiyun static t_u8 wlan_check_ie_11b_support_rates(pIEEEtypes_Generic_t prates)
3508*4882a593Smuzhiyun {
3509*4882a593Smuzhiyun 	int i;
3510*4882a593Smuzhiyun 	t_u8 rate;
3511*4882a593Smuzhiyun 	t_u8 ret = MTRUE;
3512*4882a593Smuzhiyun 	for (i = 0; i < prates->ieee_hdr.len; i++) {
3513*4882a593Smuzhiyun 		rate = prates->data[i] & 0x7f;
3514*4882a593Smuzhiyun 		if ((rate != 0x02) && (rate != 0x04) && (rate != 0x0b) &&
3515*4882a593Smuzhiyun 		    (rate != 0x16)) {
3516*4882a593Smuzhiyun 			ret = MFALSE;
3517*4882a593Smuzhiyun 			break;
3518*4882a593Smuzhiyun 		}
3519*4882a593Smuzhiyun 	}
3520*4882a593Smuzhiyun 	return ret;
3521*4882a593Smuzhiyun }
3522*4882a593Smuzhiyun #endif
3523*4882a593Smuzhiyun 
3524*4882a593Smuzhiyun /**
3525*4882a593Smuzhiyun  *  @brief This function will search for the specific ie
3526*4882a593Smuzhiyun  *
3527*4882a593Smuzhiyun  *  @param priv    A pointer to mlan_private
3528*4882a593Smuzhiyun  *  @param pevent  A pointer to event buf
3529*4882a593Smuzhiyun  *  @param sta_ptr A pointer to sta_node
3530*4882a593Smuzhiyun  *
3531*4882a593Smuzhiyun  *  @return	       N/A
3532*4882a593Smuzhiyun  */
wlan_check_sta_capability(pmlan_private priv,pmlan_buffer pevent,sta_node * sta_ptr)3533*4882a593Smuzhiyun void wlan_check_sta_capability(pmlan_private priv, pmlan_buffer pevent,
3534*4882a593Smuzhiyun 			       sta_node *sta_ptr)
3535*4882a593Smuzhiyun {
3536*4882a593Smuzhiyun 	t_u16 tlv_type, tlv_len;
3537*4882a593Smuzhiyun 	t_u16 frame_control, frame_sub_type = 0;
3538*4882a593Smuzhiyun 	t_u8 *assoc_req_ie = MNULL;
3539*4882a593Smuzhiyun 	t_u8 ie_len = 0, assoc_ie_len = 0;
3540*4882a593Smuzhiyun 	IEEEtypes_HTCap_t *pht_cap = MNULL;
3541*4882a593Smuzhiyun 	IEEEtypes_VHTCap_t *pvht_cap = MNULL;
3542*4882a593Smuzhiyun 	IEEEtypes_Extension_t *phe_cap = MNULL;
3543*4882a593Smuzhiyun #ifdef UAP_SUPPORT
3544*4882a593Smuzhiyun 	t_u8 *rate = MNULL;
3545*4882a593Smuzhiyun 	t_u8 b_only = MFALSE;
3546*4882a593Smuzhiyun #endif
3547*4882a593Smuzhiyun 
3548*4882a593Smuzhiyun 	int tlv_buf_left = pevent->data_len - ASSOC_EVENT_FIX_SIZE;
3549*4882a593Smuzhiyun 	MrvlIEtypesHeader_t *tlv =
3550*4882a593Smuzhiyun 		(MrvlIEtypesHeader_t *)(pevent->pbuf + pevent->data_offset +
3551*4882a593Smuzhiyun 					ASSOC_EVENT_FIX_SIZE);
3552*4882a593Smuzhiyun 	MrvlIETypes_MgmtFrameSet_t *mgmt_tlv = MNULL;
3553*4882a593Smuzhiyun 
3554*4882a593Smuzhiyun 	ENTER();
3555*4882a593Smuzhiyun 	while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
3556*4882a593Smuzhiyun 		tlv_type = wlan_le16_to_cpu(tlv->type);
3557*4882a593Smuzhiyun 		tlv_len = wlan_le16_to_cpu(tlv->len);
3558*4882a593Smuzhiyun 		if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
3559*4882a593Smuzhiyun 		    (unsigned int)tlv_buf_left) {
3560*4882a593Smuzhiyun 			PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
3561*4882a593Smuzhiyun 			       tlv_len, tlv_buf_left);
3562*4882a593Smuzhiyun 			break;
3563*4882a593Smuzhiyun 		}
3564*4882a593Smuzhiyun 		if (tlv_type == TLV_TYPE_MGMT_FRAME) {
3565*4882a593Smuzhiyun 			mgmt_tlv = (MrvlIETypes_MgmtFrameSet_t *)tlv;
3566*4882a593Smuzhiyun 			memcpy_ext(priv->adapter, &frame_control,
3567*4882a593Smuzhiyun 				   (t_u8 *)&(mgmt_tlv->frame_control),
3568*4882a593Smuzhiyun 				   sizeof(frame_control),
3569*4882a593Smuzhiyun 				   sizeof(frame_control));
3570*4882a593Smuzhiyun 			frame_sub_type = IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE(
3571*4882a593Smuzhiyun 				frame_control);
3572*4882a593Smuzhiyun 			if ((mgmt_tlv->frame_control.type == 0) &&
3573*4882a593Smuzhiyun 			    ((frame_sub_type == SUBTYPE_BEACON)
3574*4882a593Smuzhiyun #ifdef UAP_SUPPORT
3575*4882a593Smuzhiyun 			     || (frame_sub_type == SUBTYPE_ASSOC_REQUEST) ||
3576*4882a593Smuzhiyun 			     (frame_sub_type == SUBTYPE_REASSOC_REQUEST)
3577*4882a593Smuzhiyun #endif
3578*4882a593Smuzhiyun 				     )) {
3579*4882a593Smuzhiyun 				if (frame_sub_type == SUBTYPE_BEACON)
3580*4882a593Smuzhiyun 					assoc_ie_len =
3581*4882a593Smuzhiyun 						sizeof(IEEEtypes_Beacon_t);
3582*4882a593Smuzhiyun #ifdef UAP_SUPPORT
3583*4882a593Smuzhiyun 				else if (frame_sub_type ==
3584*4882a593Smuzhiyun 					 SUBTYPE_ASSOC_REQUEST)
3585*4882a593Smuzhiyun 					assoc_ie_len =
3586*4882a593Smuzhiyun 						sizeof(IEEEtypes_AssocRqst_t);
3587*4882a593Smuzhiyun 				else if (frame_sub_type ==
3588*4882a593Smuzhiyun 					 SUBTYPE_REASSOC_REQUEST)
3589*4882a593Smuzhiyun 					assoc_ie_len =
3590*4882a593Smuzhiyun 						sizeof(IEEEtypes_ReAssocRqst_t);
3591*4882a593Smuzhiyun #endif
3592*4882a593Smuzhiyun 				ie_len = tlv_len -
3593*4882a593Smuzhiyun 					 sizeof(IEEEtypes_FrameCtl_t) -
3594*4882a593Smuzhiyun 					 assoc_ie_len;
3595*4882a593Smuzhiyun 				assoc_req_ie =
3596*4882a593Smuzhiyun 					(t_u8 *)tlv +
3597*4882a593Smuzhiyun 					sizeof(MrvlIETypes_MgmtFrameSet_t) +
3598*4882a593Smuzhiyun 					assoc_ie_len;
3599*4882a593Smuzhiyun 				sta_ptr->is_wmm_enabled =
3600*4882a593Smuzhiyun 					wlan_is_wmm_ie_present(priv->adapter,
3601*4882a593Smuzhiyun 							       assoc_req_ie,
3602*4882a593Smuzhiyun 							       ie_len);
3603*4882a593Smuzhiyun 				PRINTM(MCMND, "STA: is_wmm_enabled=%d\n",
3604*4882a593Smuzhiyun 				       sta_ptr->is_wmm_enabled);
3605*4882a593Smuzhiyun 				pht_cap = (IEEEtypes_HTCap_t *)
3606*4882a593Smuzhiyun 					wlan_get_specific_ie(priv, assoc_req_ie,
3607*4882a593Smuzhiyun 							     ie_len,
3608*4882a593Smuzhiyun 							     HT_CAPABILITY, 0);
3609*4882a593Smuzhiyun 				if (pht_cap) {
3610*4882a593Smuzhiyun 					PRINTM(MCMND, "STA supports 11n\n");
3611*4882a593Smuzhiyun 					sta_ptr->is_11n_enabled = MTRUE;
3612*4882a593Smuzhiyun 					memcpy_ext(priv->adapter,
3613*4882a593Smuzhiyun 						   (t_u8 *)&sta_ptr->HTcap,
3614*4882a593Smuzhiyun 						   pht_cap,
3615*4882a593Smuzhiyun 						   sizeof(IEEEtypes_HTCap_t),
3616*4882a593Smuzhiyun 						   sizeof(IEEEtypes_HTCap_t));
3617*4882a593Smuzhiyun 					if (GETHT_MAXAMSDU(wlan_le16_to_cpu(
3618*4882a593Smuzhiyun 						    pht_cap->ht_cap
3619*4882a593Smuzhiyun 							    .ht_cap_info)))
3620*4882a593Smuzhiyun 						sta_ptr->max_amsdu =
3621*4882a593Smuzhiyun 							MLAN_TX_DATA_BUF_SIZE_8K;
3622*4882a593Smuzhiyun 					else
3623*4882a593Smuzhiyun 						sta_ptr->max_amsdu =
3624*4882a593Smuzhiyun 							MLAN_TX_DATA_BUF_SIZE_4K;
3625*4882a593Smuzhiyun 				} else {
3626*4882a593Smuzhiyun 					PRINTM(MCMND,
3627*4882a593Smuzhiyun 					       "STA doesn't support 11n\n");
3628*4882a593Smuzhiyun 				}
3629*4882a593Smuzhiyun 				pvht_cap = (IEEEtypes_VHTCap_t *)
3630*4882a593Smuzhiyun 					wlan_get_specific_ie(priv, assoc_req_ie,
3631*4882a593Smuzhiyun 							     ie_len,
3632*4882a593Smuzhiyun 							     VHT_CAPABILITY, 0);
3633*4882a593Smuzhiyun 				if (pvht_cap &&
3634*4882a593Smuzhiyun 				    (priv->is_11ac_enabled == MTRUE)) {
3635*4882a593Smuzhiyun 					PRINTM(MCMND, "STA supports 11ac\n");
3636*4882a593Smuzhiyun 					sta_ptr->is_11ac_enabled = MTRUE;
3637*4882a593Smuzhiyun 					if (GET_VHTCAP_MAXMPDULEN(wlan_le32_to_cpu(
3638*4882a593Smuzhiyun 						    pvht_cap->vht_cap
3639*4882a593Smuzhiyun 							    .vht_cap_info)) ==
3640*4882a593Smuzhiyun 					    2)
3641*4882a593Smuzhiyun 						sta_ptr->max_amsdu =
3642*4882a593Smuzhiyun 							MLAN_TX_DATA_BUF_SIZE_12K;
3643*4882a593Smuzhiyun 					else if (GET_VHTCAP_MAXMPDULEN(wlan_le32_to_cpu(
3644*4882a593Smuzhiyun 							 pvht_cap->vht_cap
3645*4882a593Smuzhiyun 								 .vht_cap_info)) ==
3646*4882a593Smuzhiyun 						 1)
3647*4882a593Smuzhiyun 						sta_ptr->max_amsdu =
3648*4882a593Smuzhiyun 							MLAN_TX_DATA_BUF_SIZE_8K;
3649*4882a593Smuzhiyun 					else
3650*4882a593Smuzhiyun 						sta_ptr->max_amsdu =
3651*4882a593Smuzhiyun 							MLAN_TX_DATA_BUF_SIZE_4K;
3652*4882a593Smuzhiyun 				} else {
3653*4882a593Smuzhiyun 					PRINTM(MCMND,
3654*4882a593Smuzhiyun 					       "STA doesn't support 11ac\n");
3655*4882a593Smuzhiyun 				}
3656*4882a593Smuzhiyun 				phe_cap = (IEEEtypes_Extension_t *)
3657*4882a593Smuzhiyun 					wlan_get_specific_ie(priv, assoc_req_ie,
3658*4882a593Smuzhiyun 							     ie_len, EXTENSION,
3659*4882a593Smuzhiyun 							     HE_CAPABILITY);
3660*4882a593Smuzhiyun 				if (phe_cap &&
3661*4882a593Smuzhiyun 				    (priv->is_11ax_enabled == MTRUE)) {
3662*4882a593Smuzhiyun 					PRINTM(MCMND, "STA supports 11ax\n");
3663*4882a593Smuzhiyun 					sta_ptr->is_11ax_enabled = MTRUE;
3664*4882a593Smuzhiyun 					memcpy_ext(
3665*4882a593Smuzhiyun 						priv->adapter,
3666*4882a593Smuzhiyun 						(t_u8 *)&sta_ptr->he_cap,
3667*4882a593Smuzhiyun 						phe_cap,
3668*4882a593Smuzhiyun 						phe_cap->ieee_hdr.len +
3669*4882a593Smuzhiyun 							sizeof(IEEEtypes_Header_t),
3670*4882a593Smuzhiyun 						sizeof(IEEEtypes_HECap_t));
3671*4882a593Smuzhiyun 					sta_ptr->he_cap.ieee_hdr.len = MIN(
3672*4882a593Smuzhiyun 						phe_cap->ieee_hdr.len,
3673*4882a593Smuzhiyun 						sizeof(IEEEtypes_HECap_t) -
3674*4882a593Smuzhiyun 							sizeof(IEEEtypes_Header_t));
3675*4882a593Smuzhiyun 				} else {
3676*4882a593Smuzhiyun 					PRINTM(MCMND,
3677*4882a593Smuzhiyun 					       "STA doesn't support 11ax\n");
3678*4882a593Smuzhiyun 				}
3679*4882a593Smuzhiyun #ifdef UAP_SUPPORT
3680*4882a593Smuzhiyun 				/* Note: iphone6 does not have ERP_INFO */
3681*4882a593Smuzhiyun 				rate = wlan_get_specific_ie(priv, assoc_req_ie,
3682*4882a593Smuzhiyun 							    ie_len,
3683*4882a593Smuzhiyun 							    SUPPORTED_RATES, 0);
3684*4882a593Smuzhiyun 				if (rate)
3685*4882a593Smuzhiyun 					b_only = wlan_check_ie_11b_support_rates(
3686*4882a593Smuzhiyun 						(pIEEEtypes_Generic_t)rate);
3687*4882a593Smuzhiyun 				if (sta_ptr->is_11ax_enabled) {
3688*4882a593Smuzhiyun 					if (priv->uap_channel <= 14)
3689*4882a593Smuzhiyun 						sta_ptr->bandmode = BAND_GAX;
3690*4882a593Smuzhiyun 					else
3691*4882a593Smuzhiyun 						sta_ptr->bandmode = BAND_AAX;
3692*4882a593Smuzhiyun 				} else if (sta_ptr->is_11ac_enabled) {
3693*4882a593Smuzhiyun 					if (priv->uap_channel <= 14)
3694*4882a593Smuzhiyun 						sta_ptr->bandmode = BAND_GAC;
3695*4882a593Smuzhiyun 					else
3696*4882a593Smuzhiyun 						sta_ptr->bandmode = BAND_AAC;
3697*4882a593Smuzhiyun 				} else if (sta_ptr->is_11n_enabled) {
3698*4882a593Smuzhiyun 					if (priv->uap_channel <= 14)
3699*4882a593Smuzhiyun 						sta_ptr->bandmode = BAND_GN;
3700*4882a593Smuzhiyun 					else
3701*4882a593Smuzhiyun 						sta_ptr->bandmode = BAND_AN;
3702*4882a593Smuzhiyun 				} else if (priv->uap_channel <= 14) {
3703*4882a593Smuzhiyun 					if (b_only)
3704*4882a593Smuzhiyun 						sta_ptr->bandmode = BAND_B;
3705*4882a593Smuzhiyun 					else
3706*4882a593Smuzhiyun 						sta_ptr->bandmode = BAND_G;
3707*4882a593Smuzhiyun 				} else
3708*4882a593Smuzhiyun 					sta_ptr->bandmode = BAND_A;
3709*4882a593Smuzhiyun #endif
3710*4882a593Smuzhiyun #ifdef DRV_EMBEDDED_AUTHENTICATOR
3711*4882a593Smuzhiyun 				if (IsAuthenticatorEnabled(priv->psapriv))
3712*4882a593Smuzhiyun 					authenticator_get_sta_security_info(
3713*4882a593Smuzhiyun 						priv->psapriv,
3714*4882a593Smuzhiyun 						sta_ptr->cm_connectioninfo,
3715*4882a593Smuzhiyun 						assoc_req_ie, ie_len);
3716*4882a593Smuzhiyun #endif
3717*4882a593Smuzhiyun 				break;
3718*4882a593Smuzhiyun 			}
3719*4882a593Smuzhiyun 		}
3720*4882a593Smuzhiyun 		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
3721*4882a593Smuzhiyun 		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
3722*4882a593Smuzhiyun 					      sizeof(MrvlIEtypesHeader_t));
3723*4882a593Smuzhiyun 	}
3724*4882a593Smuzhiyun 	LEAVE();
3725*4882a593Smuzhiyun 
3726*4882a593Smuzhiyun 	return;
3727*4882a593Smuzhiyun }
3728*4882a593Smuzhiyun 
3729*4882a593Smuzhiyun /**
3730*4882a593Smuzhiyun  *  @brief check if WMM ie present.
3731*4882a593Smuzhiyun  *
3732*4882a593Smuzhiyun  *  @param pmadapter A pointer to mlan_adapter structure
3733*4882a593Smuzhiyun  *  @param pbuf     A pointer to IE buffer
3734*4882a593Smuzhiyun  *  @param buf_len  IE buffer len
3735*4882a593Smuzhiyun  *
3736*4882a593Smuzhiyun  *  @return         MTRUE/MFALSE
3737*4882a593Smuzhiyun  */
wlan_is_wmm_ie_present(pmlan_adapter pmadapter,t_u8 * pbuf,t_u16 buf_len)3738*4882a593Smuzhiyun t_u8 wlan_is_wmm_ie_present(pmlan_adapter pmadapter, t_u8 *pbuf, t_u16 buf_len)
3739*4882a593Smuzhiyun {
3740*4882a593Smuzhiyun 	t_u16 bytes_left = buf_len;
3741*4882a593Smuzhiyun 	IEEEtypes_ElementId_e element_id;
3742*4882a593Smuzhiyun 	t_u8 *pcurrent_ptr = pbuf;
3743*4882a593Smuzhiyun 	t_u8 element_len;
3744*4882a593Smuzhiyun 	t_u16 total_ie_len;
3745*4882a593Smuzhiyun 	IEEEtypes_VendorSpecific_t *pvendor_ie;
3746*4882a593Smuzhiyun 	const t_u8 wmm_oui[4] = {0x00, 0x50, 0xf2, 0x02};
3747*4882a593Smuzhiyun 	t_u8 find_wmm_ie = MFALSE;
3748*4882a593Smuzhiyun 
3749*4882a593Smuzhiyun 	ENTER();
3750*4882a593Smuzhiyun 
3751*4882a593Smuzhiyun 	/* Process variable IE */
3752*4882a593Smuzhiyun 	while (bytes_left >= 2) {
3753*4882a593Smuzhiyun 		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
3754*4882a593Smuzhiyun 		element_len = *((t_u8 *)pcurrent_ptr + 1);
3755*4882a593Smuzhiyun 		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
3756*4882a593Smuzhiyun 
3757*4882a593Smuzhiyun 		if (bytes_left < total_ie_len) {
3758*4882a593Smuzhiyun 			PRINTM(MERROR, "InterpretIE: Error in processing IE, "
3759*4882a593Smuzhiyun 				       "bytes left < IE length\n");
3760*4882a593Smuzhiyun 			bytes_left = 0;
3761*4882a593Smuzhiyun 			continue;
3762*4882a593Smuzhiyun 		}
3763*4882a593Smuzhiyun 		switch (element_id) {
3764*4882a593Smuzhiyun 		case VENDOR_SPECIFIC_221:
3765*4882a593Smuzhiyun 			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
3766*4882a593Smuzhiyun 			if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
3767*4882a593Smuzhiyun 				    wmm_oui, sizeof(wmm_oui))) {
3768*4882a593Smuzhiyun 				find_wmm_ie = MTRUE;
3769*4882a593Smuzhiyun 				PRINTM(MINFO, "find WMM IE\n");
3770*4882a593Smuzhiyun 			}
3771*4882a593Smuzhiyun 			break;
3772*4882a593Smuzhiyun 		default:
3773*4882a593Smuzhiyun 			break;
3774*4882a593Smuzhiyun 		}
3775*4882a593Smuzhiyun 		pcurrent_ptr += element_len + 2;
3776*4882a593Smuzhiyun 		/* Need to account for IE ID and IE Len */
3777*4882a593Smuzhiyun 		bytes_left -= (element_len + 2);
3778*4882a593Smuzhiyun 		if (find_wmm_ie)
3779*4882a593Smuzhiyun 			break;
3780*4882a593Smuzhiyun 	}
3781*4882a593Smuzhiyun 
3782*4882a593Smuzhiyun 	LEAVE();
3783*4882a593Smuzhiyun 	return find_wmm_ie;
3784*4882a593Smuzhiyun }
3785*4882a593Smuzhiyun 
3786*4882a593Smuzhiyun /**
3787*4882a593Smuzhiyun  *  @brief This function will search for the specific ie
3788*4882a593Smuzhiyun  *
3789*4882a593Smuzhiyun  *
3790*4882a593Smuzhiyun  *  @param priv    A pointer to mlan_private
3791*4882a593Smuzhiyun  *  @param ie_buf  A pointer to ie_buf
3792*4882a593Smuzhiyun  *  @param ie_len  total ie length
3793*4882a593Smuzhiyun  *  @param id      ie's id
3794*4882a593Smuzhiyun  *  @param ext_id  ie's extension id
3795*4882a593Smuzhiyun  *
3796*4882a593Smuzhiyun  *  @return	       ie's poiner or MNULL
3797*4882a593Smuzhiyun  */
wlan_get_specific_ie(pmlan_private priv,t_u8 * ie_buf,t_u8 ie_len,IEEEtypes_ElementId_e id,t_u8 ext_id)3798*4882a593Smuzhiyun t_u8 *wlan_get_specific_ie(pmlan_private priv, t_u8 *ie_buf, t_u8 ie_len,
3799*4882a593Smuzhiyun 			   IEEEtypes_ElementId_e id, t_u8 ext_id)
3800*4882a593Smuzhiyun {
3801*4882a593Smuzhiyun 	t_u32 bytes_left = ie_len;
3802*4882a593Smuzhiyun 	t_u8 *pcurrent_ptr = ie_buf;
3803*4882a593Smuzhiyun 	t_u16 total_ie_len;
3804*4882a593Smuzhiyun 	t_u8 *ie_ptr = MNULL;
3805*4882a593Smuzhiyun 	IEEEtypes_ElementId_e element_id;
3806*4882a593Smuzhiyun 	t_u8 element_len;
3807*4882a593Smuzhiyun 	t_u8 element_eid;
3808*4882a593Smuzhiyun 
3809*4882a593Smuzhiyun 	ENTER();
3810*4882a593Smuzhiyun 
3811*4882a593Smuzhiyun 	DBG_HEXDUMP(MDAT_D, "ie", ie_buf, ie_len);
3812*4882a593Smuzhiyun 	while (bytes_left >= 2) {
3813*4882a593Smuzhiyun 		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
3814*4882a593Smuzhiyun 		element_len = *((t_u8 *)pcurrent_ptr + 1);
3815*4882a593Smuzhiyun 		element_eid = *((t_u8 *)pcurrent_ptr + 2);
3816*4882a593Smuzhiyun 		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
3817*4882a593Smuzhiyun 		if (bytes_left < total_ie_len) {
3818*4882a593Smuzhiyun 			PRINTM(MERROR, "InterpretIE: Error in processing IE, "
3819*4882a593Smuzhiyun 				       "bytes left < IE length\n");
3820*4882a593Smuzhiyun 			break;
3821*4882a593Smuzhiyun 		}
3822*4882a593Smuzhiyun 		if ((!ext_id && element_id == id) ||
3823*4882a593Smuzhiyun 		    (id == EXTENSION && element_id == id &&
3824*4882a593Smuzhiyun 		     ext_id == element_eid)) {
3825*4882a593Smuzhiyun 			PRINTM(MCMND, "Find IE: id=%d ext_id=%d\n", id, ext_id);
3826*4882a593Smuzhiyun 			DBG_HEXDUMP(MCMD_D, "IE", pcurrent_ptr, total_ie_len);
3827*4882a593Smuzhiyun 			ie_ptr = pcurrent_ptr;
3828*4882a593Smuzhiyun 			break;
3829*4882a593Smuzhiyun 		}
3830*4882a593Smuzhiyun 		pcurrent_ptr += element_len + 2;
3831*4882a593Smuzhiyun 		/* Need to account for IE ID and IE Len */
3832*4882a593Smuzhiyun 		bytes_left -= (element_len + 2);
3833*4882a593Smuzhiyun 	}
3834*4882a593Smuzhiyun 
3835*4882a593Smuzhiyun 	LEAVE();
3836*4882a593Smuzhiyun 
3837*4882a593Smuzhiyun 	return ie_ptr;
3838*4882a593Smuzhiyun }
3839*4882a593Smuzhiyun 
3840*4882a593Smuzhiyun /**
3841*4882a593Smuzhiyun  *  @brief Get pm info
3842*4882a593Smuzhiyun  *
3843*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
3844*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
3845*4882a593Smuzhiyun  *
3846*4882a593Smuzhiyun  *  @return		        MLAN_STATUS_SUCCESS --success
3847*4882a593Smuzhiyun  */
wlan_get_pm_info(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3848*4882a593Smuzhiyun mlan_status wlan_get_pm_info(pmlan_adapter pmadapter,
3849*4882a593Smuzhiyun 			     pmlan_ioctl_req pioctl_req)
3850*4882a593Smuzhiyun {
3851*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
3852*4882a593Smuzhiyun 	mlan_ds_pm_cfg *pm_cfg = MNULL;
3853*4882a593Smuzhiyun 
3854*4882a593Smuzhiyun 	ENTER();
3855*4882a593Smuzhiyun 
3856*4882a593Smuzhiyun 	pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
3857*4882a593Smuzhiyun 	pm_cfg->param.ps_info.is_suspend_allowed = MTRUE;
3858*4882a593Smuzhiyun 	wlan_request_cmd_lock(pmadapter);
3859*4882a593Smuzhiyun 	if (util_peek_list(pmadapter->pmoal_handle, &pmadapter->cmd_pending_q,
3860*4882a593Smuzhiyun 			   MNULL, MNULL) ||
3861*4882a593Smuzhiyun 	    pmadapter->curr_cmd || !wlan_bypass_tx_list_empty(pmadapter) ||
3862*4882a593Smuzhiyun 	    !wlan_wmm_lists_empty(pmadapter)
3863*4882a593Smuzhiyun #if defined(SDIO) || defined(PCIE)
3864*4882a593Smuzhiyun 	    || wlan_pending_interrupt(pmadapter)
3865*4882a593Smuzhiyun #endif
3866*4882a593Smuzhiyun 	) {
3867*4882a593Smuzhiyun 		pm_cfg->param.ps_info.is_suspend_allowed = MFALSE;
3868*4882a593Smuzhiyun #if defined(SDIO) || defined(PCIE)
3869*4882a593Smuzhiyun 		PRINTM(MIOCTL,
3870*4882a593Smuzhiyun 		       "PM: cmd_pending_q=%p,curr_cmd=%p,wmm_list_empty=%d, by_pass=%d irq_pending=%d\n",
3871*4882a593Smuzhiyun 		       util_peek_list(pmadapter->pmoal_handle,
3872*4882a593Smuzhiyun 				      &pmadapter->cmd_pending_q, MNULL, MNULL),
3873*4882a593Smuzhiyun 		       pmadapter->curr_cmd, wlan_wmm_lists_empty(pmadapter),
3874*4882a593Smuzhiyun 		       wlan_bypass_tx_list_empty(pmadapter),
3875*4882a593Smuzhiyun 		       wlan_pending_interrupt(pmadapter));
3876*4882a593Smuzhiyun #else
3877*4882a593Smuzhiyun 		PRINTM(MIOCTL,
3878*4882a593Smuzhiyun 		       "PM: cmd_pending_q=%p,curr_cmd=%p,wmm_list_empty=%d, by_pass=%d\n",
3879*4882a593Smuzhiyun 		       util_peek_list(pmadapter->pmoal_handle,
3880*4882a593Smuzhiyun 				      &pmadapter->cmd_pending_q, MNULL, MNULL),
3881*4882a593Smuzhiyun 		       pmadapter->curr_cmd, wlan_wmm_lists_empty(pmadapter),
3882*4882a593Smuzhiyun 		       wlan_bypass_tx_list_empty(pmadapter));
3883*4882a593Smuzhiyun #endif
3884*4882a593Smuzhiyun 	}
3885*4882a593Smuzhiyun 	wlan_release_cmd_lock(pmadapter);
3886*4882a593Smuzhiyun 	LEAVE();
3887*4882a593Smuzhiyun 	return ret;
3888*4882a593Smuzhiyun }
3889*4882a593Smuzhiyun 
3890*4882a593Smuzhiyun /**
3891*4882a593Smuzhiyun  *  @brief Get hs wakeup reason
3892*4882a593Smuzhiyun  *
3893*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
3894*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
3895*4882a593Smuzhiyun  *
3896*4882a593Smuzhiyun  *  @return		        MLAN_STATUS_SUCCESS --success
3897*4882a593Smuzhiyun  */
wlan_get_hs_wakeup_reason(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3898*4882a593Smuzhiyun mlan_status wlan_get_hs_wakeup_reason(pmlan_adapter pmadapter,
3899*4882a593Smuzhiyun 				      pmlan_ioctl_req pioctl_req)
3900*4882a593Smuzhiyun {
3901*4882a593Smuzhiyun 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3902*4882a593Smuzhiyun 	pmlan_ds_pm_cfg pm_cfg = MNULL;
3903*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_FAILURE;
3904*4882a593Smuzhiyun 
3905*4882a593Smuzhiyun 	ENTER();
3906*4882a593Smuzhiyun 
3907*4882a593Smuzhiyun 	pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
3908*4882a593Smuzhiyun 
3909*4882a593Smuzhiyun 	/* Send command to firmware */
3910*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_HS_WAKEUP_REASON,
3911*4882a593Smuzhiyun 			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
3912*4882a593Smuzhiyun 			       &pm_cfg->param.wakeup_reason);
3913*4882a593Smuzhiyun 
3914*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
3915*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
3916*4882a593Smuzhiyun 
3917*4882a593Smuzhiyun 	LEAVE();
3918*4882a593Smuzhiyun 	return ret;
3919*4882a593Smuzhiyun }
3920*4882a593Smuzhiyun 
3921*4882a593Smuzhiyun /**
3922*4882a593Smuzhiyun  *  @brief Set/Get radio status
3923*4882a593Smuzhiyun  *
3924*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
3925*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
3926*4882a593Smuzhiyun  *
3927*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
3928*4882a593Smuzhiyun  */
wlan_radio_ioctl_radio_ctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3929*4882a593Smuzhiyun mlan_status wlan_radio_ioctl_radio_ctl(pmlan_adapter pmadapter,
3930*4882a593Smuzhiyun 				       pmlan_ioctl_req pioctl_req)
3931*4882a593Smuzhiyun {
3932*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
3933*4882a593Smuzhiyun 	mlan_ds_radio_cfg *radio_cfg = MNULL;
3934*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
3935*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3936*4882a593Smuzhiyun 
3937*4882a593Smuzhiyun 	ENTER();
3938*4882a593Smuzhiyun 
3939*4882a593Smuzhiyun 	radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
3940*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET) {
3941*4882a593Smuzhiyun 		if (pmadapter->radio_on == radio_cfg->param.radio_on_off) {
3942*4882a593Smuzhiyun 			ret = MLAN_STATUS_SUCCESS;
3943*4882a593Smuzhiyun 			goto exit;
3944*4882a593Smuzhiyun 		} else {
3945*4882a593Smuzhiyun 			if (pmpriv->media_connected == MTRUE) {
3946*4882a593Smuzhiyun 				ret = MLAN_STATUS_FAILURE;
3947*4882a593Smuzhiyun 				goto exit;
3948*4882a593Smuzhiyun 			}
3949*4882a593Smuzhiyun 			cmd_action = HostCmd_ACT_GEN_SET;
3950*4882a593Smuzhiyun 		}
3951*4882a593Smuzhiyun 	} else
3952*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
3953*4882a593Smuzhiyun 
3954*4882a593Smuzhiyun 	/* Send request to firmware */
3955*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_RADIO_CONTROL,
3956*4882a593Smuzhiyun 			       cmd_action, 0, (t_void *)pioctl_req,
3957*4882a593Smuzhiyun 			       &radio_cfg->param.radio_on_off);
3958*4882a593Smuzhiyun 
3959*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
3960*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
3961*4882a593Smuzhiyun 
3962*4882a593Smuzhiyun exit:
3963*4882a593Smuzhiyun 	LEAVE();
3964*4882a593Smuzhiyun 	return ret;
3965*4882a593Smuzhiyun }
3966*4882a593Smuzhiyun 
3967*4882a593Smuzhiyun /**
3968*4882a593Smuzhiyun  *  @brief Set/Get antenna configuration
3969*4882a593Smuzhiyun  *
3970*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
3971*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
3972*4882a593Smuzhiyun  *
3973*4882a593Smuzhiyun  *  @return     MLAN_STATUS_PENDING --success, otherwise fail
3974*4882a593Smuzhiyun  */
wlan_radio_ioctl_ant_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3975*4882a593Smuzhiyun mlan_status wlan_radio_ioctl_ant_cfg(pmlan_adapter pmadapter,
3976*4882a593Smuzhiyun 				     pmlan_ioctl_req pioctl_req)
3977*4882a593Smuzhiyun {
3978*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
3979*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3980*4882a593Smuzhiyun 	mlan_ds_radio_cfg *radio_cfg = MNULL;
3981*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
3982*4882a593Smuzhiyun 	mlan_ds_ant_cfg *ant_cfg = MNULL;
3983*4882a593Smuzhiyun 	mlan_ds_ant_cfg_1x1 *ant_cfg_1x1 = MNULL;
3984*4882a593Smuzhiyun 
3985*4882a593Smuzhiyun 	ENTER();
3986*4882a593Smuzhiyun 
3987*4882a593Smuzhiyun 	radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
3988*4882a593Smuzhiyun 	if (IS_STREAM_2X2(pmadapter->feature_control))
3989*4882a593Smuzhiyun 		ant_cfg = &radio_cfg->param.ant_cfg;
3990*4882a593Smuzhiyun 
3991*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET) {
3992*4882a593Smuzhiyun 		/* User input validation */
3993*4882a593Smuzhiyun 		if (IS_STREAM_2X2(pmadapter->feature_control)) {
3994*4882a593Smuzhiyun #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
3995*4882a593Smuzhiyun 	defined(PCIE9097) || defined(SD9097) || defined(USB9097) ||            \
3996*4882a593Smuzhiyun 	defined(SDNW62X) || defined(PCIENW62X) || defined(USBNW62X)
3997*4882a593Smuzhiyun 			if (IS_CARD9098(pmadapter->card_type) ||
3998*4882a593Smuzhiyun 			    IS_CARD9097(pmadapter->card_type) ||
3999*4882a593Smuzhiyun 			    IS_CARDNW62X(pmadapter->card_type)) {
4000*4882a593Smuzhiyun 				ant_cfg->tx_antenna &= 0x0303;
4001*4882a593Smuzhiyun 				ant_cfg->rx_antenna &= 0x0303;
4002*4882a593Smuzhiyun 				/** 2G antcfg TX */
4003*4882a593Smuzhiyun 				if (ant_cfg->tx_antenna & 0x00FF) {
4004*4882a593Smuzhiyun 					pmadapter->user_htstream &= ~0xF0;
4005*4882a593Smuzhiyun 					pmadapter->user_htstream |=
4006*4882a593Smuzhiyun 						(bitcount(ant_cfg->tx_antenna &
4007*4882a593Smuzhiyun 							  0x00FF)
4008*4882a593Smuzhiyun 						 << 4);
4009*4882a593Smuzhiyun 				}
4010*4882a593Smuzhiyun 				/* 5G antcfg tx */
4011*4882a593Smuzhiyun 				if (ant_cfg->tx_antenna & 0xFF00) {
4012*4882a593Smuzhiyun 					pmadapter->user_htstream &= ~0xF000;
4013*4882a593Smuzhiyun 					pmadapter->user_htstream |=
4014*4882a593Smuzhiyun 						(bitcount(ant_cfg->tx_antenna &
4015*4882a593Smuzhiyun 							  0xFF00)
4016*4882a593Smuzhiyun 						 << 12);
4017*4882a593Smuzhiyun 				}
4018*4882a593Smuzhiyun 				/* 2G antcfg RX */
4019*4882a593Smuzhiyun 				if (ant_cfg->rx_antenna & 0x00FF) {
4020*4882a593Smuzhiyun 					pmadapter->user_htstream &= ~0xF;
4021*4882a593Smuzhiyun 					pmadapter->user_htstream |= bitcount(
4022*4882a593Smuzhiyun 						ant_cfg->rx_antenna & 0x00FF);
4023*4882a593Smuzhiyun 				}
4024*4882a593Smuzhiyun 				/* 5G antcfg RX */
4025*4882a593Smuzhiyun 				if (ant_cfg->rx_antenna & 0xFF00) {
4026*4882a593Smuzhiyun 					pmadapter->user_htstream &= ~0xF00;
4027*4882a593Smuzhiyun 					pmadapter->user_htstream |=
4028*4882a593Smuzhiyun 						(bitcount(ant_cfg->rx_antenna &
4029*4882a593Smuzhiyun 							  0xFF00)
4030*4882a593Smuzhiyun 						 << 8);
4031*4882a593Smuzhiyun 				}
4032*4882a593Smuzhiyun 				PRINTM(MCMND,
4033*4882a593Smuzhiyun 				       "user_htstream=0x%x, tx_antenna=0x%x >rx_antenna=0x%x\n",
4034*4882a593Smuzhiyun 				       pmadapter->user_htstream,
4035*4882a593Smuzhiyun 				       ant_cfg->tx_antenna,
4036*4882a593Smuzhiyun 				       ant_cfg->rx_antenna);
4037*4882a593Smuzhiyun 			} else {
4038*4882a593Smuzhiyun #endif
4039*4882a593Smuzhiyun 
4040*4882a593Smuzhiyun 				ant_cfg->tx_antenna &= 0x0003;
4041*4882a593Smuzhiyun 				ant_cfg->rx_antenna &= 0x0003;
4042*4882a593Smuzhiyun #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
4043*4882a593Smuzhiyun 	defined(PCIE9097) || defined(SD9097) || defined(USB9097) ||            \
4044*4882a593Smuzhiyun 	defined(SDNW62X) || defined(PCIENW62X) || defined(USBNW62X)
4045*4882a593Smuzhiyun 			}
4046*4882a593Smuzhiyun #endif
4047*4882a593Smuzhiyun 			if (!ant_cfg->tx_antenna ||
4048*4882a593Smuzhiyun 			    bitcount(ant_cfg->tx_antenna & 0x00FF) >
4049*4882a593Smuzhiyun 				    pmadapter->number_of_antenna ||
4050*4882a593Smuzhiyun 			    bitcount(ant_cfg->tx_antenna & 0xFF00) >
4051*4882a593Smuzhiyun 				    pmadapter->number_of_antenna) {
4052*4882a593Smuzhiyun 				PRINTM(MERROR,
4053*4882a593Smuzhiyun 				       "Invalid TX antenna setting: 0x%x\n",
4054*4882a593Smuzhiyun 				       ant_cfg->tx_antenna);
4055*4882a593Smuzhiyun 				pioctl_req->status_code =
4056*4882a593Smuzhiyun 					MLAN_ERROR_INVALID_PARAMETER;
4057*4882a593Smuzhiyun 				ret = MLAN_STATUS_FAILURE;
4058*4882a593Smuzhiyun 				goto exit;
4059*4882a593Smuzhiyun 			}
4060*4882a593Smuzhiyun 			if (ant_cfg->rx_antenna) {
4061*4882a593Smuzhiyun 				if (bitcount(ant_cfg->rx_antenna & 0x00FF) >
4062*4882a593Smuzhiyun 					    pmadapter->number_of_antenna ||
4063*4882a593Smuzhiyun 				    bitcount(ant_cfg->rx_antenna & 0xFF00) >
4064*4882a593Smuzhiyun 					    pmadapter->number_of_antenna) {
4065*4882a593Smuzhiyun 					PRINTM(MERROR,
4066*4882a593Smuzhiyun 					       "Invalid RX antenna setting: 0x%x\n",
4067*4882a593Smuzhiyun 					       ant_cfg->rx_antenna);
4068*4882a593Smuzhiyun 					pioctl_req->status_code =
4069*4882a593Smuzhiyun 						MLAN_ERROR_INVALID_PARAMETER;
4070*4882a593Smuzhiyun 					ret = MLAN_STATUS_FAILURE;
4071*4882a593Smuzhiyun 					goto exit;
4072*4882a593Smuzhiyun 				}
4073*4882a593Smuzhiyun 			} else
4074*4882a593Smuzhiyun 				ant_cfg->rx_antenna = ant_cfg->tx_antenna;
4075*4882a593Smuzhiyun 		} else if (!radio_cfg->param.ant_cfg_1x1.antenna ||
4076*4882a593Smuzhiyun 			   ((radio_cfg->param.ant_cfg_1x1.antenna !=
4077*4882a593Smuzhiyun 			     RF_ANTENNA_AUTO) &&
4078*4882a593Smuzhiyun 			    (radio_cfg->param.ant_cfg_1x1.antenna & 0xFFFC))) {
4079*4882a593Smuzhiyun 			PRINTM(MERROR, "Invalid antenna setting\n");
4080*4882a593Smuzhiyun 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4081*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
4082*4882a593Smuzhiyun 			goto exit;
4083*4882a593Smuzhiyun 		}
4084*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
4085*4882a593Smuzhiyun 	} else
4086*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
4087*4882a593Smuzhiyun 
4088*4882a593Smuzhiyun 	/* Cast it to t_u16, antenna mode for command
4089*4882a593Smuzhiyun 	 * HostCmd_CMD_802_11_RF_ANTENNA requires 2 bytes */
4090*4882a593Smuzhiyun 	if (!IS_STREAM_2X2(pmadapter->feature_control))
4091*4882a593Smuzhiyun 		ant_cfg_1x1 = &radio_cfg->param.ant_cfg_1x1;
4092*4882a593Smuzhiyun 
4093*4882a593Smuzhiyun 	/* Send request to firmware */
4094*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_RF_ANTENNA,
4095*4882a593Smuzhiyun 			       cmd_action, 0, (t_void *)pioctl_req,
4096*4882a593Smuzhiyun 			       (IS_STREAM_2X2(pmadapter->feature_control)) ?
4097*4882a593Smuzhiyun 				       (t_void *)ant_cfg :
4098*4882a593Smuzhiyun 				       (t_void *)ant_cfg_1x1);
4099*4882a593Smuzhiyun 
4100*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
4101*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
4102*4882a593Smuzhiyun 
4103*4882a593Smuzhiyun exit:
4104*4882a593Smuzhiyun 	LEAVE();
4105*4882a593Smuzhiyun 	return ret;
4106*4882a593Smuzhiyun }
4107*4882a593Smuzhiyun 
4108*4882a593Smuzhiyun /**
4109*4882a593Smuzhiyun  *  @brief Get rate bitmap
4110*4882a593Smuzhiyun  *
4111*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
4112*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
4113*4882a593Smuzhiyun  *
4114*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
4115*4882a593Smuzhiyun  */
wlan_rate_ioctl_get_rate_bitmap(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4116*4882a593Smuzhiyun static mlan_status wlan_rate_ioctl_get_rate_bitmap(pmlan_adapter pmadapter,
4117*4882a593Smuzhiyun 						   pmlan_ioctl_req pioctl_req)
4118*4882a593Smuzhiyun {
4119*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
4120*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4121*4882a593Smuzhiyun 
4122*4882a593Smuzhiyun 	ENTER();
4123*4882a593Smuzhiyun 
4124*4882a593Smuzhiyun 	/* Send request to firmware */
4125*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
4126*4882a593Smuzhiyun 			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
4127*4882a593Smuzhiyun 			       MNULL);
4128*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
4129*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
4130*4882a593Smuzhiyun 
4131*4882a593Smuzhiyun 	LEAVE();
4132*4882a593Smuzhiyun 	return ret;
4133*4882a593Smuzhiyun }
4134*4882a593Smuzhiyun 
4135*4882a593Smuzhiyun /**
4136*4882a593Smuzhiyun  *  @brief Set rate bitmap
4137*4882a593Smuzhiyun  *
4138*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
4139*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
4140*4882a593Smuzhiyun  *
4141*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
4142*4882a593Smuzhiyun  */
wlan_rate_ioctl_set_rate_bitmap(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4143*4882a593Smuzhiyun static mlan_status wlan_rate_ioctl_set_rate_bitmap(pmlan_adapter pmadapter,
4144*4882a593Smuzhiyun 						   pmlan_ioctl_req pioctl_req)
4145*4882a593Smuzhiyun {
4146*4882a593Smuzhiyun 	mlan_ds_rate *ds_rate = MNULL;
4147*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_FAILURE;
4148*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4149*4882a593Smuzhiyun 	t_u16 *bitmap_rates = MNULL;
4150*4882a593Smuzhiyun 
4151*4882a593Smuzhiyun 	ENTER();
4152*4882a593Smuzhiyun 
4153*4882a593Smuzhiyun 	ds_rate = (mlan_ds_rate *)pioctl_req->pbuf;
4154*4882a593Smuzhiyun 	bitmap_rates = ds_rate->param.rate_cfg.bitmap_rates;
4155*4882a593Smuzhiyun 
4156*4882a593Smuzhiyun 	PRINTM(MINFO,
4157*4882a593Smuzhiyun 	       "RateBitmap=%04x%04x%04x%04x%04x%04x%04x%04x"
4158*4882a593Smuzhiyun 	       "%04x%04x%04x%04x%04x%04x%04x%04x%04x%04x, "
4159*4882a593Smuzhiyun 	       "IsRateAuto=%d, DataRate=%d\n",
4160*4882a593Smuzhiyun 	       bitmap_rates[17], bitmap_rates[16], bitmap_rates[15],
4161*4882a593Smuzhiyun 	       bitmap_rates[14], bitmap_rates[13], bitmap_rates[12],
4162*4882a593Smuzhiyun 	       bitmap_rates[11], bitmap_rates[10], bitmap_rates[9],
4163*4882a593Smuzhiyun 	       bitmap_rates[8], bitmap_rates[7], bitmap_rates[6],
4164*4882a593Smuzhiyun 	       bitmap_rates[5], bitmap_rates[4], bitmap_rates[3],
4165*4882a593Smuzhiyun 	       bitmap_rates[2], bitmap_rates[1], bitmap_rates[0],
4166*4882a593Smuzhiyun 	       pmpriv->is_data_rate_auto, pmpriv->data_rate);
4167*4882a593Smuzhiyun 
4168*4882a593Smuzhiyun 	/* Send request to firmware */
4169*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
4170*4882a593Smuzhiyun 			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
4171*4882a593Smuzhiyun 			       (t_void *)bitmap_rates);
4172*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
4173*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
4174*4882a593Smuzhiyun 
4175*4882a593Smuzhiyun 	LEAVE();
4176*4882a593Smuzhiyun 	return ret;
4177*4882a593Smuzhiyun }
4178*4882a593Smuzhiyun 
4179*4882a593Smuzhiyun /**
4180*4882a593Smuzhiyun  *  @brief Get rate value
4181*4882a593Smuzhiyun  *
4182*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
4183*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
4184*4882a593Smuzhiyun  *
4185*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
4186*4882a593Smuzhiyun  * otherwise fail
4187*4882a593Smuzhiyun  */
wlan_rate_ioctl_get_rate_value(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4188*4882a593Smuzhiyun static mlan_status wlan_rate_ioctl_get_rate_value(pmlan_adapter pmadapter,
4189*4882a593Smuzhiyun 						  pmlan_ioctl_req pioctl_req)
4190*4882a593Smuzhiyun {
4191*4882a593Smuzhiyun 	mlan_ds_rate *rate = MNULL;
4192*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
4193*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4194*4882a593Smuzhiyun 
4195*4882a593Smuzhiyun 	ENTER();
4196*4882a593Smuzhiyun 
4197*4882a593Smuzhiyun 	rate = (mlan_ds_rate *)pioctl_req->pbuf;
4198*4882a593Smuzhiyun 	rate->param.rate_cfg.is_rate_auto = pmpriv->is_data_rate_auto;
4199*4882a593Smuzhiyun 	pioctl_req->data_read_written =
4200*4882a593Smuzhiyun 		sizeof(mlan_rate_cfg_t) + MLAN_SUB_COMMAND_SIZE;
4201*4882a593Smuzhiyun 
4202*4882a593Smuzhiyun 	/* If not connected, set rate to the lowest in each band */
4203*4882a593Smuzhiyun 	if (pmpriv->media_connected != MTRUE) {
4204*4882a593Smuzhiyun 		if (pmpriv->config_bands & (BAND_B | BAND_G)) {
4205*4882a593Smuzhiyun 			/* Return the lowest supported rate for BG band */
4206*4882a593Smuzhiyun 			rate->param.rate_cfg.rate = SupportedRates_BG[0] & 0x7f;
4207*4882a593Smuzhiyun 		} else if (pmpriv->config_bands & (BAND_A | BAND_B)) {
4208*4882a593Smuzhiyun 			/* Return the lowest supported rate for A band */
4209*4882a593Smuzhiyun 			rate->param.rate_cfg.rate = SupportedRates_BG[0] & 0x7f;
4210*4882a593Smuzhiyun 		} else if (pmpriv->config_bands & BAND_A) {
4211*4882a593Smuzhiyun 			/* Return the lowest supported rate for A band */
4212*4882a593Smuzhiyun 			rate->param.rate_cfg.rate = SupportedRates_A[0] & 0x7f;
4213*4882a593Smuzhiyun 		} else if (pmpriv->config_bands & BAND_G) {
4214*4882a593Smuzhiyun 			/* Return the lowest supported rate for G band */
4215*4882a593Smuzhiyun 			rate->param.rate_cfg.rate = SupportedRates_G[0] & 0x7f;
4216*4882a593Smuzhiyun 		} else if (pmpriv->config_bands & BAND_B) {
4217*4882a593Smuzhiyun 			/* Return the lowest supported rate for B band */
4218*4882a593Smuzhiyun 			rate->param.rate_cfg.rate = SupportedRates_B[0] & 0x7f;
4219*4882a593Smuzhiyun 		} else if (pmpriv->config_bands & BAND_GN) {
4220*4882a593Smuzhiyun 			/* Return the lowest supported rate for N band */
4221*4882a593Smuzhiyun 			rate->param.rate_cfg.rate = SupportedRates_N[0] & 0x7f;
4222*4882a593Smuzhiyun 		} else {
4223*4882a593Smuzhiyun 			PRINTM(MMSG, "Invalid Band 0x%x\n",
4224*4882a593Smuzhiyun 			       pmpriv->config_bands);
4225*4882a593Smuzhiyun 		}
4226*4882a593Smuzhiyun 
4227*4882a593Smuzhiyun 	} else {
4228*4882a593Smuzhiyun 		/* Send request to firmware */
4229*4882a593Smuzhiyun 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_TX_RATE_QUERY,
4230*4882a593Smuzhiyun 				       HostCmd_ACT_GEN_GET, 0,
4231*4882a593Smuzhiyun 				       (t_void *)pioctl_req, MNULL);
4232*4882a593Smuzhiyun 		if (ret == MLAN_STATUS_SUCCESS)
4233*4882a593Smuzhiyun 			ret = MLAN_STATUS_PENDING;
4234*4882a593Smuzhiyun 	}
4235*4882a593Smuzhiyun 
4236*4882a593Smuzhiyun 	LEAVE();
4237*4882a593Smuzhiyun 	return ret;
4238*4882a593Smuzhiyun }
4239*4882a593Smuzhiyun 
4240*4882a593Smuzhiyun /**
4241*4882a593Smuzhiyun  *  @brief Set rate value
4242*4882a593Smuzhiyun  *
4243*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
4244*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
4245*4882a593Smuzhiyun  *
4246*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
4247*4882a593Smuzhiyun  */
wlan_rate_ioctl_set_rate_value(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4248*4882a593Smuzhiyun static mlan_status wlan_rate_ioctl_set_rate_value(pmlan_adapter pmadapter,
4249*4882a593Smuzhiyun 						  pmlan_ioctl_req pioctl_req)
4250*4882a593Smuzhiyun {
4251*4882a593Smuzhiyun 	mlan_ds_rate *ds_rate = MNULL;
4252*4882a593Smuzhiyun 	WLAN_802_11_RATES rates;
4253*4882a593Smuzhiyun 	t_u8 *rate = MNULL;
4254*4882a593Smuzhiyun 	int rate_index = 0;
4255*4882a593Smuzhiyun 	t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
4256*4882a593Smuzhiyun 	t_u32 i = 0;
4257*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
4258*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4259*4882a593Smuzhiyun 
4260*4882a593Smuzhiyun 	ENTER();
4261*4882a593Smuzhiyun 
4262*4882a593Smuzhiyun 	ds_rate = (mlan_ds_rate *)pioctl_req->pbuf;
4263*4882a593Smuzhiyun 
4264*4882a593Smuzhiyun 	if (ds_rate->param.rate_cfg.is_rate_auto) {
4265*4882a593Smuzhiyun 		memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
4266*4882a593Smuzhiyun 		/* Support all HR/DSSS rates */
4267*4882a593Smuzhiyun 		bitmap_rates[0] = 0x000F;
4268*4882a593Smuzhiyun 		/* Support all OFDM rates */
4269*4882a593Smuzhiyun 		bitmap_rates[1] = 0x00FF;
4270*4882a593Smuzhiyun 		/* Rates talbe [0] HR/DSSS,[1] OFDM,[2..9] HT,[10..17] VHT */
4271*4882a593Smuzhiyun 		/* Support all HT-MCSs rate */
4272*4882a593Smuzhiyun 		for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates) - 3 - 8; i++)
4273*4882a593Smuzhiyun 			bitmap_rates[i + 2] = 0xFFFF;
4274*4882a593Smuzhiyun 		bitmap_rates[9] = 0x3FFF;
4275*4882a593Smuzhiyun 		/* Support all VHT-MCSs rate */
4276*4882a593Smuzhiyun 		for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates) - 10; i++)
4277*4882a593Smuzhiyun 			bitmap_rates[i + 10] = 0x03FF; /* 10 Bits valid */
4278*4882a593Smuzhiyun 	} else {
4279*4882a593Smuzhiyun 		memset(pmadapter, rates, 0, sizeof(rates));
4280*4882a593Smuzhiyun 		wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode,
4281*4882a593Smuzhiyun 					   (pmpriv->bss_mode ==
4282*4882a593Smuzhiyun 					    MLAN_BSS_MODE_INFRA) ?
4283*4882a593Smuzhiyun 						   pmpriv->config_bands :
4284*4882a593Smuzhiyun 						   pmadapter->adhoc_start_band,
4285*4882a593Smuzhiyun 					   rates);
4286*4882a593Smuzhiyun 		rate = rates;
4287*4882a593Smuzhiyun 		for (i = 0; (rate[i] && i < WLAN_SUPPORTED_RATES); i++) {
4288*4882a593Smuzhiyun 			PRINTM(MINFO, "Rate=0x%X  Wanted=0x%X\n", rate[i],
4289*4882a593Smuzhiyun 			       ds_rate->param.rate_cfg.rate);
4290*4882a593Smuzhiyun 			if ((rate[i] & 0x7f) ==
4291*4882a593Smuzhiyun 			    (ds_rate->param.rate_cfg.rate & 0x7f))
4292*4882a593Smuzhiyun 				break;
4293*4882a593Smuzhiyun 		}
4294*4882a593Smuzhiyun 		if ((i < WLAN_SUPPORTED_RATES && !rate[i]) ||
4295*4882a593Smuzhiyun 		    (i == WLAN_SUPPORTED_RATES)) {
4296*4882a593Smuzhiyun 			PRINTM(MERROR,
4297*4882a593Smuzhiyun 			       "The fixed data rate 0x%X is out "
4298*4882a593Smuzhiyun 			       "of range\n",
4299*4882a593Smuzhiyun 			       ds_rate->param.rate_cfg.rate);
4300*4882a593Smuzhiyun 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4301*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
4302*4882a593Smuzhiyun 			goto exit;
4303*4882a593Smuzhiyun 		}
4304*4882a593Smuzhiyun 		memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
4305*4882a593Smuzhiyun 		rate_index = wlan_data_rate_to_index(
4306*4882a593Smuzhiyun 			pmadapter, ds_rate->param.rate_cfg.rate);
4307*4882a593Smuzhiyun 		/* Only allow b/g rates to be set */
4308*4882a593Smuzhiyun 		if (rate_index >= MLAN_RATE_INDEX_HRDSSS0 &&
4309*4882a593Smuzhiyun 		    rate_index <= MLAN_RATE_INDEX_HRDSSS3)
4310*4882a593Smuzhiyun 			bitmap_rates[0] = 1 << rate_index;
4311*4882a593Smuzhiyun 		else {
4312*4882a593Smuzhiyun 			rate_index -= 1; /* There is a 0x00 in the table */
4313*4882a593Smuzhiyun 			if (rate_index >= MLAN_RATE_INDEX_OFDM0 &&
4314*4882a593Smuzhiyun 			    rate_index <= MLAN_RATE_INDEX_OFDM7)
4315*4882a593Smuzhiyun 				bitmap_rates[1] = 1 << (rate_index -
4316*4882a593Smuzhiyun 							MLAN_RATE_INDEX_OFDM0);
4317*4882a593Smuzhiyun 		}
4318*4882a593Smuzhiyun 	}
4319*4882a593Smuzhiyun 
4320*4882a593Smuzhiyun 	/* Send request to firmware */
4321*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
4322*4882a593Smuzhiyun 			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
4323*4882a593Smuzhiyun 			       bitmap_rates);
4324*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
4325*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
4326*4882a593Smuzhiyun 
4327*4882a593Smuzhiyun exit:
4328*4882a593Smuzhiyun 	LEAVE();
4329*4882a593Smuzhiyun 	return ret;
4330*4882a593Smuzhiyun }
4331*4882a593Smuzhiyun 
4332*4882a593Smuzhiyun /**
4333*4882a593Smuzhiyun  *  @brief Get rate index
4334*4882a593Smuzhiyun  *
4335*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
4336*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
4337*4882a593Smuzhiyun  *
4338*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
4339*4882a593Smuzhiyun  */
wlan_rate_ioctl_get_rate_index(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4340*4882a593Smuzhiyun static mlan_status wlan_rate_ioctl_get_rate_index(pmlan_adapter pmadapter,
4341*4882a593Smuzhiyun 						  pmlan_ioctl_req pioctl_req)
4342*4882a593Smuzhiyun {
4343*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
4344*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4345*4882a593Smuzhiyun 
4346*4882a593Smuzhiyun 	ENTER();
4347*4882a593Smuzhiyun 
4348*4882a593Smuzhiyun 	/* Send request to firmware */
4349*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
4350*4882a593Smuzhiyun 			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
4351*4882a593Smuzhiyun 			       MNULL);
4352*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
4353*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
4354*4882a593Smuzhiyun 
4355*4882a593Smuzhiyun 	LEAVE();
4356*4882a593Smuzhiyun 	return ret;
4357*4882a593Smuzhiyun }
4358*4882a593Smuzhiyun 
4359*4882a593Smuzhiyun /**
4360*4882a593Smuzhiyun  *  @brief Set rate index
4361*4882a593Smuzhiyun  *
4362*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
4363*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
4364*4882a593Smuzhiyun  *
4365*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
4366*4882a593Smuzhiyun  */
wlan_rate_ioctl_set_rate_index(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4367*4882a593Smuzhiyun static mlan_status wlan_rate_ioctl_set_rate_index(pmlan_adapter pmadapter,
4368*4882a593Smuzhiyun 						  pmlan_ioctl_req pioctl_req)
4369*4882a593Smuzhiyun {
4370*4882a593Smuzhiyun 	t_u32 rate_index;
4371*4882a593Smuzhiyun 	t_u32 rate_format;
4372*4882a593Smuzhiyun 	t_u32 nss;
4373*4882a593Smuzhiyun 	t_u32 i;
4374*4882a593Smuzhiyun 	mlan_ds_rate *ds_rate = MNULL;
4375*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_FAILURE;
4376*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4377*4882a593Smuzhiyun 	t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
4378*4882a593Smuzhiyun 	int tx_mcs_supp = GET_TXMCSSUPP(pmpriv->usr_dev_mcs_support);
4379*4882a593Smuzhiyun 
4380*4882a593Smuzhiyun 	ENTER();
4381*4882a593Smuzhiyun 
4382*4882a593Smuzhiyun 	ds_rate = (mlan_ds_rate *)pioctl_req->pbuf;
4383*4882a593Smuzhiyun 	rate_format = ds_rate->param.rate_cfg.rate_format;
4384*4882a593Smuzhiyun 	nss = ds_rate->param.rate_cfg.nss;
4385*4882a593Smuzhiyun 	rate_index = ds_rate->param.rate_cfg.rate;
4386*4882a593Smuzhiyun 
4387*4882a593Smuzhiyun 	if (ds_rate->param.rate_cfg.is_rate_auto) {
4388*4882a593Smuzhiyun 		memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
4389*4882a593Smuzhiyun 		/* Rates talbe [0]: HR/DSSS;[1]: OFDM; [2..9] HT; */
4390*4882a593Smuzhiyun 		/* Support all HR/DSSS rates */
4391*4882a593Smuzhiyun 		bitmap_rates[0] = 0x000F;
4392*4882a593Smuzhiyun 		/* Support all OFDM rates */
4393*4882a593Smuzhiyun 		bitmap_rates[1] = 0x00FF;
4394*4882a593Smuzhiyun 		/* Support all HT-MCSs rate */
4395*4882a593Smuzhiyun 		for (i = 2; i < 9; i++)
4396*4882a593Smuzhiyun 			bitmap_rates[i] = 0xFFFF;
4397*4882a593Smuzhiyun 		bitmap_rates[9] = 0x3FFF;
4398*4882a593Smuzhiyun 		/* [10..17] VHT */
4399*4882a593Smuzhiyun 		/* Support all VHT-MCSs rate for NSS 1 and 2 */
4400*4882a593Smuzhiyun 		for (i = 10; i < 12; i++)
4401*4882a593Smuzhiyun 			bitmap_rates[i] = 0x03FF; /* 10 Bits valid */
4402*4882a593Smuzhiyun 		/* Set to 0 as default value for all other NSSs */
4403*4882a593Smuzhiyun 		for (i = 12; i < 17; i++)
4404*4882a593Smuzhiyun 			bitmap_rates[i] = 0x0;
4405*4882a593Smuzhiyun 		/* [18..25] HE */
4406*4882a593Smuzhiyun 		/* Support all HE-MCSs rate for NSS1 and 2 */
4407*4882a593Smuzhiyun 		for (i = 18; i < 20; i++)
4408*4882a593Smuzhiyun 			bitmap_rates[i] = 0x0FFF;
4409*4882a593Smuzhiyun 		for (i = 20; i < NELEMENTS(bitmap_rates); i++)
4410*4882a593Smuzhiyun 			bitmap_rates[i] = 0x0;
4411*4882a593Smuzhiyun 	} else {
4412*4882a593Smuzhiyun 		PRINTM(MINFO, "Rate index is %d\n", rate_index);
4413*4882a593Smuzhiyun 		if ((rate_format == MLAN_RATE_FORMAT_HT) &&
4414*4882a593Smuzhiyun 		    (rate_index > MLAN_RATE_INDEX_MCS7 &&
4415*4882a593Smuzhiyun 		     rate_index <= MLAN_RATE_INDEX_MCS15) &&
4416*4882a593Smuzhiyun 		    (tx_mcs_supp < 2)) {
4417*4882a593Smuzhiyun 			PRINTM(MERROR,
4418*4882a593Smuzhiyun 			       "HW don't support 2x2, rate_index=%d hw_mcs_supp=0x%x\n",
4419*4882a593Smuzhiyun 			       rate_index, pmpriv->usr_dev_mcs_support);
4420*4882a593Smuzhiyun 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4421*4882a593Smuzhiyun 			LEAVE();
4422*4882a593Smuzhiyun 			return MLAN_STATUS_FAILURE;
4423*4882a593Smuzhiyun 		}
4424*4882a593Smuzhiyun 		memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
4425*4882a593Smuzhiyun 		if (rate_format == MLAN_RATE_FORMAT_LG) {
4426*4882a593Smuzhiyun 			/* Bitmap of HR/DSSS rates */
4427*4882a593Smuzhiyun 			if (rate_index <= MLAN_RATE_INDEX_HRDSSS3) {
4428*4882a593Smuzhiyun 				bitmap_rates[0] = 1 << rate_index;
4429*4882a593Smuzhiyun 				ret = MLAN_STATUS_SUCCESS;
4430*4882a593Smuzhiyun 				/* Bitmap of OFDM rates */
4431*4882a593Smuzhiyun 			} else if ((rate_index >= MLAN_RATE_INDEX_OFDM0) &&
4432*4882a593Smuzhiyun 				   (rate_index <= MLAN_RATE_INDEX_OFDM7)) {
4433*4882a593Smuzhiyun 				bitmap_rates[1] = 1 << (rate_index -
4434*4882a593Smuzhiyun 							MLAN_RATE_INDEX_OFDM0);
4435*4882a593Smuzhiyun 				ret = MLAN_STATUS_SUCCESS;
4436*4882a593Smuzhiyun 			}
4437*4882a593Smuzhiyun 		} else if (rate_format == MLAN_RATE_FORMAT_HT) {
4438*4882a593Smuzhiyun 			if (rate_index <= MLAN_RATE_INDEX_MCS32) {
4439*4882a593Smuzhiyun 				bitmap_rates[2 + (rate_index / 16)] =
4440*4882a593Smuzhiyun 					1 << (rate_index % 16);
4441*4882a593Smuzhiyun 				ret = MLAN_STATUS_SUCCESS;
4442*4882a593Smuzhiyun 			}
4443*4882a593Smuzhiyun 		}
4444*4882a593Smuzhiyun 		if (rate_format == MLAN_RATE_FORMAT_VHT) {
4445*4882a593Smuzhiyun 			if ((rate_index <= MLAN_RATE_INDEX_MCS9) &&
4446*4882a593Smuzhiyun 			    (MLAN_RATE_NSS1 <= nss) &&
4447*4882a593Smuzhiyun 			    (nss <= MLAN_RATE_NSS2)) {
4448*4882a593Smuzhiyun 				bitmap_rates[10 + nss - MLAN_RATE_NSS1] =
4449*4882a593Smuzhiyun 					(1 << rate_index);
4450*4882a593Smuzhiyun 				ret = MLAN_STATUS_SUCCESS;
4451*4882a593Smuzhiyun 			}
4452*4882a593Smuzhiyun 		}
4453*4882a593Smuzhiyun 		if (rate_format == MLAN_RATE_FORMAT_HE) {
4454*4882a593Smuzhiyun 			if (IS_FW_SUPPORT_11AX(pmadapter)) {
4455*4882a593Smuzhiyun 				if ((rate_index <= MLAN_RATE_INDEX_MCS11) &&
4456*4882a593Smuzhiyun 				    (MLAN_RATE_NSS1 <= nss) &&
4457*4882a593Smuzhiyun 				    (nss <= MLAN_RATE_NSS2)) {
4458*4882a593Smuzhiyun 					bitmap_rates[18 + nss - MLAN_RATE_NSS1] =
4459*4882a593Smuzhiyun 						(1 << rate_index);
4460*4882a593Smuzhiyun 					ret = MLAN_STATUS_SUCCESS;
4461*4882a593Smuzhiyun 				}
4462*4882a593Smuzhiyun 			} else {
4463*4882a593Smuzhiyun 				PRINTM(MERROR,
4464*4882a593Smuzhiyun 				       "Error! Fw doesn't support 11AX\n");
4465*4882a593Smuzhiyun 				LEAVE();
4466*4882a593Smuzhiyun 				return MLAN_STATUS_FAILURE;
4467*4882a593Smuzhiyun 			}
4468*4882a593Smuzhiyun 		}
4469*4882a593Smuzhiyun 
4470*4882a593Smuzhiyun 		if (ret == MLAN_STATUS_FAILURE) {
4471*4882a593Smuzhiyun 			PRINTM(MERROR, "Invalid MCS index=%d. \n", rate_index);
4472*4882a593Smuzhiyun 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4473*4882a593Smuzhiyun 			LEAVE();
4474*4882a593Smuzhiyun 			return MLAN_STATUS_FAILURE;
4475*4882a593Smuzhiyun 		}
4476*4882a593Smuzhiyun 	}
4477*4882a593Smuzhiyun 
4478*4882a593Smuzhiyun 	PRINTM(MINFO,
4479*4882a593Smuzhiyun 	       "RateBitmap=%04x%04x%04x%04x%04x%04x%04x%04x"
4480*4882a593Smuzhiyun 	       "%04x%04x%04x%04x%04x%04x%04x%04x%04x%04x, "
4481*4882a593Smuzhiyun 	       "IsRateAuto=%d, DataRate=%d\n",
4482*4882a593Smuzhiyun 	       bitmap_rates[17], bitmap_rates[16], bitmap_rates[15],
4483*4882a593Smuzhiyun 	       bitmap_rates[14], bitmap_rates[13], bitmap_rates[12],
4484*4882a593Smuzhiyun 	       bitmap_rates[11], bitmap_rates[10], bitmap_rates[9],
4485*4882a593Smuzhiyun 	       bitmap_rates[8], bitmap_rates[7], bitmap_rates[6],
4486*4882a593Smuzhiyun 	       bitmap_rates[5], bitmap_rates[4], bitmap_rates[3],
4487*4882a593Smuzhiyun 	       bitmap_rates[2], bitmap_rates[1], bitmap_rates[0],
4488*4882a593Smuzhiyun 	       pmpriv->is_data_rate_auto, pmpriv->data_rate);
4489*4882a593Smuzhiyun 
4490*4882a593Smuzhiyun 	/* Send request to firmware */
4491*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_RATE_CFG,
4492*4882a593Smuzhiyun 			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
4493*4882a593Smuzhiyun 			       (t_void *)bitmap_rates);
4494*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
4495*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
4496*4882a593Smuzhiyun 
4497*4882a593Smuzhiyun 	LEAVE();
4498*4882a593Smuzhiyun 	return ret;
4499*4882a593Smuzhiyun }
4500*4882a593Smuzhiyun 
4501*4882a593Smuzhiyun /**
4502*4882a593Smuzhiyun  *  @brief Rate configuration command handler
4503*4882a593Smuzhiyun  *
4504*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
4505*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
4506*4882a593Smuzhiyun  *
4507*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
4508*4882a593Smuzhiyun  * otherwise fail
4509*4882a593Smuzhiyun  */
wlan_rate_ioctl_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4510*4882a593Smuzhiyun mlan_status wlan_rate_ioctl_cfg(pmlan_adapter pmadapter,
4511*4882a593Smuzhiyun 				pmlan_ioctl_req pioctl_req)
4512*4882a593Smuzhiyun {
4513*4882a593Smuzhiyun 	mlan_ds_rate *rate = MNULL;
4514*4882a593Smuzhiyun 	mlan_status status = MLAN_STATUS_SUCCESS;
4515*4882a593Smuzhiyun 
4516*4882a593Smuzhiyun 	ENTER();
4517*4882a593Smuzhiyun 
4518*4882a593Smuzhiyun 	rate = (mlan_ds_rate *)pioctl_req->pbuf;
4519*4882a593Smuzhiyun 	if (rate->param.rate_cfg.rate_type == MLAN_RATE_BITMAP) {
4520*4882a593Smuzhiyun 		if (pioctl_req->action == MLAN_ACT_GET)
4521*4882a593Smuzhiyun 			status = wlan_rate_ioctl_get_rate_bitmap(pmadapter,
4522*4882a593Smuzhiyun 								 pioctl_req);
4523*4882a593Smuzhiyun 		else
4524*4882a593Smuzhiyun 			status = wlan_rate_ioctl_set_rate_bitmap(pmadapter,
4525*4882a593Smuzhiyun 								 pioctl_req);
4526*4882a593Smuzhiyun 	} else if (rate->param.rate_cfg.rate_type == MLAN_RATE_VALUE) {
4527*4882a593Smuzhiyun 		if (pioctl_req->action == MLAN_ACT_GET)
4528*4882a593Smuzhiyun 			status = wlan_rate_ioctl_get_rate_value(pmadapter,
4529*4882a593Smuzhiyun 								pioctl_req);
4530*4882a593Smuzhiyun 		else
4531*4882a593Smuzhiyun 			status = wlan_rate_ioctl_set_rate_value(pmadapter,
4532*4882a593Smuzhiyun 								pioctl_req);
4533*4882a593Smuzhiyun 	} else {
4534*4882a593Smuzhiyun 		if (pioctl_req->action == MLAN_ACT_GET)
4535*4882a593Smuzhiyun 			status = wlan_rate_ioctl_get_rate_index(pmadapter,
4536*4882a593Smuzhiyun 								pioctl_req);
4537*4882a593Smuzhiyun 		else
4538*4882a593Smuzhiyun 			status = wlan_rate_ioctl_set_rate_index(pmadapter,
4539*4882a593Smuzhiyun 								pioctl_req);
4540*4882a593Smuzhiyun 	}
4541*4882a593Smuzhiyun 
4542*4882a593Smuzhiyun 	LEAVE();
4543*4882a593Smuzhiyun 	return status;
4544*4882a593Smuzhiyun }
4545*4882a593Smuzhiyun 
4546*4882a593Smuzhiyun /**
4547*4882a593Smuzhiyun  *  @brief Get data rates
4548*4882a593Smuzhiyun  *
4549*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
4550*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
4551*4882a593Smuzhiyun  *
4552*4882a593Smuzhiyun  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
4553*4882a593Smuzhiyun  */
wlan_rate_ioctl_get_data_rate(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4554*4882a593Smuzhiyun mlan_status wlan_rate_ioctl_get_data_rate(pmlan_adapter pmadapter,
4555*4882a593Smuzhiyun 					  pmlan_ioctl_req pioctl_req)
4556*4882a593Smuzhiyun {
4557*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4558*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
4559*4882a593Smuzhiyun 
4560*4882a593Smuzhiyun 	ENTER();
4561*4882a593Smuzhiyun 
4562*4882a593Smuzhiyun 	if (pioctl_req->action != MLAN_ACT_GET) {
4563*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
4564*4882a593Smuzhiyun 		goto exit;
4565*4882a593Smuzhiyun 	}
4566*4882a593Smuzhiyun 
4567*4882a593Smuzhiyun 	/* Send request to firmware */
4568*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_TX_RATE_QUERY,
4569*4882a593Smuzhiyun 			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
4570*4882a593Smuzhiyun 			       MNULL);
4571*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
4572*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
4573*4882a593Smuzhiyun 
4574*4882a593Smuzhiyun exit:
4575*4882a593Smuzhiyun 	LEAVE();
4576*4882a593Smuzhiyun 	return ret;
4577*4882a593Smuzhiyun }
4578*4882a593Smuzhiyun 
4579*4882a593Smuzhiyun /**
4580*4882a593Smuzhiyun  *  @brief Set/Get remain on channel setting
4581*4882a593Smuzhiyun  *
4582*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
4583*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
4584*4882a593Smuzhiyun  *
4585*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
4586*4882a593Smuzhiyun  */
wlan_radio_ioctl_remain_chan_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4587*4882a593Smuzhiyun mlan_status wlan_radio_ioctl_remain_chan_cfg(pmlan_adapter pmadapter,
4588*4882a593Smuzhiyun 					     pmlan_ioctl_req pioctl_req)
4589*4882a593Smuzhiyun {
4590*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
4591*4882a593Smuzhiyun 	mlan_ds_radio_cfg *radio_cfg = MNULL;
4592*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
4593*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4594*4882a593Smuzhiyun 
4595*4882a593Smuzhiyun 	ENTER();
4596*4882a593Smuzhiyun 
4597*4882a593Smuzhiyun 	radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
4598*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
4599*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
4600*4882a593Smuzhiyun 	else
4601*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
4602*4882a593Smuzhiyun 
4603*4882a593Smuzhiyun 	/* Send request to firmware */
4604*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_REMAIN_ON_CHANNEL,
4605*4882a593Smuzhiyun 			       cmd_action, 0, (t_void *)pioctl_req,
4606*4882a593Smuzhiyun 			       &radio_cfg->param.remain_chan);
4607*4882a593Smuzhiyun 
4608*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
4609*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
4610*4882a593Smuzhiyun 
4611*4882a593Smuzhiyun 	LEAVE();
4612*4882a593Smuzhiyun 	return ret;
4613*4882a593Smuzhiyun }
4614*4882a593Smuzhiyun 
4615*4882a593Smuzhiyun #ifdef WIFI_DIRECT_SUPPORT
4616*4882a593Smuzhiyun /**
4617*4882a593Smuzhiyun  *  @brief Set/Get wifi_direct_mode
4618*4882a593Smuzhiyun  *
4619*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
4620*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
4621*4882a593Smuzhiyun  *
4622*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
4623*4882a593Smuzhiyun  */
wlan_bss_ioctl_wifi_direct_mode(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4624*4882a593Smuzhiyun mlan_status wlan_bss_ioctl_wifi_direct_mode(pmlan_adapter pmadapter,
4625*4882a593Smuzhiyun 					    pmlan_ioctl_req pioctl_req)
4626*4882a593Smuzhiyun {
4627*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
4628*4882a593Smuzhiyun 	mlan_ds_bss *bss = MNULL;
4629*4882a593Smuzhiyun 
4630*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
4631*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4632*4882a593Smuzhiyun 
4633*4882a593Smuzhiyun 	ENTER();
4634*4882a593Smuzhiyun 
4635*4882a593Smuzhiyun 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
4636*4882a593Smuzhiyun 
4637*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
4638*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
4639*4882a593Smuzhiyun 	else
4640*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
4641*4882a593Smuzhiyun 
4642*4882a593Smuzhiyun 	/* Send request to firmware */
4643*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_WIFI_DIRECT_MODE_CONFIG,
4644*4882a593Smuzhiyun 			       cmd_action, 0, (t_void *)pioctl_req,
4645*4882a593Smuzhiyun 			       &bss->param.wfd_mode);
4646*4882a593Smuzhiyun 
4647*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
4648*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
4649*4882a593Smuzhiyun 
4650*4882a593Smuzhiyun 	LEAVE();
4651*4882a593Smuzhiyun 	return ret;
4652*4882a593Smuzhiyun }
4653*4882a593Smuzhiyun 
4654*4882a593Smuzhiyun /**
4655*4882a593Smuzhiyun  *  @brief Set/Get p2p config
4656*4882a593Smuzhiyun  *
4657*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
4658*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
4659*4882a593Smuzhiyun  *
4660*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
4661*4882a593Smuzhiyun  */
wlan_misc_p2p_config(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4662*4882a593Smuzhiyun mlan_status wlan_misc_p2p_config(pmlan_adapter pmadapter,
4663*4882a593Smuzhiyun 				 pmlan_ioctl_req pioctl_req)
4664*4882a593Smuzhiyun {
4665*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
4666*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc_cfg = MNULL;
4667*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
4668*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4669*4882a593Smuzhiyun 
4670*4882a593Smuzhiyun 	ENTER();
4671*4882a593Smuzhiyun 
4672*4882a593Smuzhiyun 	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4673*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
4674*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
4675*4882a593Smuzhiyun 	else
4676*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
4677*4882a593Smuzhiyun 
4678*4882a593Smuzhiyun 	/* Send request to firmware */
4679*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_P2P_PARAMS_CONFIG, cmd_action,
4680*4882a593Smuzhiyun 			       0, (t_void *)pioctl_req,
4681*4882a593Smuzhiyun 			       &misc_cfg->param.p2p_config);
4682*4882a593Smuzhiyun 
4683*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
4684*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
4685*4882a593Smuzhiyun 
4686*4882a593Smuzhiyun 	LEAVE();
4687*4882a593Smuzhiyun 	return ret;
4688*4882a593Smuzhiyun }
4689*4882a593Smuzhiyun #endif
4690*4882a593Smuzhiyun 
4691*4882a593Smuzhiyun /**
4692*4882a593Smuzhiyun  *  @brief Set/Get GPIO TSF Latch config
4693*4882a593Smuzhiyun  *
4694*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
4695*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
4696*4882a593Smuzhiyun  *
4697*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
4698*4882a593Smuzhiyun  */
wlan_misc_gpio_tsf_latch_config(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4699*4882a593Smuzhiyun mlan_status wlan_misc_gpio_tsf_latch_config(pmlan_adapter pmadapter,
4700*4882a593Smuzhiyun 					    pmlan_ioctl_req pioctl_req)
4701*4882a593Smuzhiyun {
4702*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
4703*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc_cfg = MNULL;
4704*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
4705*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4706*4882a593Smuzhiyun 
4707*4882a593Smuzhiyun 	ENTER();
4708*4882a593Smuzhiyun 
4709*4882a593Smuzhiyun 	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4710*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
4711*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
4712*4882a593Smuzhiyun 	else
4713*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
4714*4882a593Smuzhiyun 
4715*4882a593Smuzhiyun 	/* Send request to firmware */
4716*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG,
4717*4882a593Smuzhiyun 			       cmd_action, 0, (t_void *)pioctl_req,
4718*4882a593Smuzhiyun 			       &misc_cfg->param.gpio_tsf_latch_config);
4719*4882a593Smuzhiyun 
4720*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
4721*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
4722*4882a593Smuzhiyun 
4723*4882a593Smuzhiyun 	LEAVE();
4724*4882a593Smuzhiyun 	return ret;
4725*4882a593Smuzhiyun }
4726*4882a593Smuzhiyun 
4727*4882a593Smuzhiyun /**
4728*4882a593Smuzhiyun  *  @brief Get TSF info
4729*4882a593Smuzhiyun  *
4730*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
4731*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
4732*4882a593Smuzhiyun  *
4733*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
4734*4882a593Smuzhiyun  */
wlan_misc_get_tsf_info(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4735*4882a593Smuzhiyun mlan_status wlan_misc_get_tsf_info(pmlan_adapter pmadapter,
4736*4882a593Smuzhiyun 				   pmlan_ioctl_req pioctl_req)
4737*4882a593Smuzhiyun {
4738*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
4739*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc_cfg = MNULL;
4740*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
4741*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4742*4882a593Smuzhiyun 
4743*4882a593Smuzhiyun 	ENTER();
4744*4882a593Smuzhiyun 
4745*4882a593Smuzhiyun 	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4746*4882a593Smuzhiyun 	cmd_action = HostCmd_ACT_GEN_GET;
4747*4882a593Smuzhiyun 
4748*4882a593Smuzhiyun 	/* Send request to firmware */
4749*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG,
4750*4882a593Smuzhiyun 			       cmd_action, 0, (t_void *)pioctl_req,
4751*4882a593Smuzhiyun 			       &misc_cfg->param.tsf_info);
4752*4882a593Smuzhiyun 
4753*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
4754*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
4755*4882a593Smuzhiyun 
4756*4882a593Smuzhiyun 	LEAVE();
4757*4882a593Smuzhiyun 	return ret;
4758*4882a593Smuzhiyun }
4759*4882a593Smuzhiyun 
4760*4882a593Smuzhiyun /**
4761*4882a593Smuzhiyun  *  @brief Set coalesce config
4762*4882a593Smuzhiyun  *
4763*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
4764*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
4765*4882a593Smuzhiyun  *
4766*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
4767*4882a593Smuzhiyun  */
wlan_misc_ioctl_coalesce_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4768*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_coalesce_cfg(pmlan_adapter pmadapter,
4769*4882a593Smuzhiyun 					 pmlan_ioctl_req pioctl_req)
4770*4882a593Smuzhiyun {
4771*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
4772*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc_cfg = MNULL;
4773*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
4774*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4775*4882a593Smuzhiyun 
4776*4882a593Smuzhiyun 	ENTER();
4777*4882a593Smuzhiyun 
4778*4882a593Smuzhiyun 	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4779*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
4780*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
4781*4882a593Smuzhiyun 	else
4782*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
4783*4882a593Smuzhiyun 
4784*4882a593Smuzhiyun 	/* Send request to firmware */
4785*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_COALESCE_CFG, cmd_action, 0,
4786*4882a593Smuzhiyun 			       (t_void *)pioctl_req,
4787*4882a593Smuzhiyun 			       &misc_cfg->param.coalesce_cfg);
4788*4882a593Smuzhiyun 
4789*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
4790*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
4791*4882a593Smuzhiyun 
4792*4882a593Smuzhiyun 	LEAVE();
4793*4882a593Smuzhiyun 	return ret;
4794*4882a593Smuzhiyun }
4795*4882a593Smuzhiyun 
4796*4882a593Smuzhiyun /**
4797*4882a593Smuzhiyun  *  @brief Get/Set USB packet aggregation parameters
4798*4882a593Smuzhiyun  *
4799*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
4800*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
4801*4882a593Smuzhiyun  *
4802*4882a593Smuzhiyun  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
4803*4882a593Smuzhiyun  */
wlan_misc_ioctl_aggr_ctrl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4804*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_aggr_ctrl(pmlan_adapter pmadapter,
4805*4882a593Smuzhiyun 				      pmlan_ioctl_req pioctl_req)
4806*4882a593Smuzhiyun {
4807*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
4808*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
4809*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
4810*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4811*4882a593Smuzhiyun 
4812*4882a593Smuzhiyun 	ENTER();
4813*4882a593Smuzhiyun 
4814*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4815*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
4816*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
4817*4882a593Smuzhiyun 	else
4818*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
4819*4882a593Smuzhiyun 
4820*4882a593Smuzhiyun 	/* Send request to firmware */
4821*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_PACKET_AGGR_CTRL, cmd_action,
4822*4882a593Smuzhiyun 			       0, (t_void *)pioctl_req,
4823*4882a593Smuzhiyun 			       &misc->param.aggr_params);
4824*4882a593Smuzhiyun 
4825*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS) {
4826*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
4827*4882a593Smuzhiyun 	}
4828*4882a593Smuzhiyun 
4829*4882a593Smuzhiyun 	LEAVE();
4830*4882a593Smuzhiyun 	return ret;
4831*4882a593Smuzhiyun }
4832*4882a593Smuzhiyun 
4833*4882a593Smuzhiyun #ifdef USB
4834*4882a593Smuzhiyun /**
4835*4882a593Smuzhiyun  *  @brief Get/Set USB packet aggregation parameters
4836*4882a593Smuzhiyun  *
4837*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
4838*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
4839*4882a593Smuzhiyun  *
4840*4882a593Smuzhiyun  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
4841*4882a593Smuzhiyun  */
wlan_misc_ioctl_usb_aggr_ctrl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4842*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_usb_aggr_ctrl(pmlan_adapter pmadapter,
4843*4882a593Smuzhiyun 					  pmlan_ioctl_req pioctl_req)
4844*4882a593Smuzhiyun {
4845*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
4846*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
4847*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
4848*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4849*4882a593Smuzhiyun 
4850*4882a593Smuzhiyun 	ENTER();
4851*4882a593Smuzhiyun 
4852*4882a593Smuzhiyun 	if (pmadapter->pcard_usb->fw_usb_aggr == MFALSE) {
4853*4882a593Smuzhiyun 		PRINTM(MERROR, "USB aggregation not supported by FW\n");
4854*4882a593Smuzhiyun 		pioctl_req->status_code = MLAN_ERROR_CMD_INVALID;
4855*4882a593Smuzhiyun 		LEAVE();
4856*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
4857*4882a593Smuzhiyun 	}
4858*4882a593Smuzhiyun 
4859*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4860*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
4861*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
4862*4882a593Smuzhiyun 	else
4863*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
4864*4882a593Smuzhiyun 
4865*4882a593Smuzhiyun 	/* Send request to firmware */
4866*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv,
4867*4882a593Smuzhiyun 			       HostCmd_CMD_PACKET_AGGR_OVER_HOST_INTERFACE,
4868*4882a593Smuzhiyun 			       cmd_action, 0, (t_void *)pioctl_req,
4869*4882a593Smuzhiyun 			       &misc->param.usb_aggr_params);
4870*4882a593Smuzhiyun 
4871*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS) {
4872*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
4873*4882a593Smuzhiyun 	}
4874*4882a593Smuzhiyun 
4875*4882a593Smuzhiyun 	LEAVE();
4876*4882a593Smuzhiyun 	return ret;
4877*4882a593Smuzhiyun }
4878*4882a593Smuzhiyun #endif
4879*4882a593Smuzhiyun 
4880*4882a593Smuzhiyun /**
4881*4882a593Smuzhiyun  *  @brief Get/Set Tx control configuration
4882*4882a593Smuzhiyun  *
4883*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
4884*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
4885*4882a593Smuzhiyun  *
4886*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS
4887*4882a593Smuzhiyun  */
wlan_misc_ioctl_txcontrol(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4888*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_txcontrol(pmlan_adapter pmadapter,
4889*4882a593Smuzhiyun 				      pmlan_ioctl_req pioctl_req)
4890*4882a593Smuzhiyun {
4891*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
4892*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
4893*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4894*4882a593Smuzhiyun 
4895*4882a593Smuzhiyun 	ENTER();
4896*4882a593Smuzhiyun 
4897*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4898*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
4899*4882a593Smuzhiyun 		pmpriv->pkt_tx_ctrl = misc->param.tx_control;
4900*4882a593Smuzhiyun 	else
4901*4882a593Smuzhiyun 		misc->param.tx_control = pmpriv->pkt_tx_ctrl;
4902*4882a593Smuzhiyun 
4903*4882a593Smuzhiyun 	LEAVE();
4904*4882a593Smuzhiyun 	return ret;
4905*4882a593Smuzhiyun }
4906*4882a593Smuzhiyun 
4907*4882a593Smuzhiyun #ifdef RX_PACKET_COALESCE
4908*4882a593Smuzhiyun /**
4909*4882a593Smuzhiyun  *  @brief Get/Set RX packet coalescing configuration
4910*4882a593Smuzhiyun  *
4911*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
4912*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
4913*4882a593Smuzhiyun  *
4914*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS
4915*4882a593Smuzhiyun  */
wlan_misc_ioctl_rx_pkt_coalesce_config(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4916*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_rx_pkt_coalesce_config(pmlan_adapter pmadapter,
4917*4882a593Smuzhiyun 						   pmlan_ioctl_req pioctl_req)
4918*4882a593Smuzhiyun {
4919*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
4920*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
4921*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
4922*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4923*4882a593Smuzhiyun 
4924*4882a593Smuzhiyun 	ENTER();
4925*4882a593Smuzhiyun 
4926*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4927*4882a593Smuzhiyun 
4928*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
4929*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
4930*4882a593Smuzhiyun 	else
4931*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
4932*4882a593Smuzhiyun 
4933*4882a593Smuzhiyun 	/* Send request to firmware */
4934*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RX_PKT_COALESCE_CFG,
4935*4882a593Smuzhiyun 			       cmd_action, 0, (t_void *)pioctl_req,
4936*4882a593Smuzhiyun 			       &misc->param.rx_coalesce);
4937*4882a593Smuzhiyun 
4938*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
4939*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
4940*4882a593Smuzhiyun 
4941*4882a593Smuzhiyun 	LEAVE();
4942*4882a593Smuzhiyun 	return ret;
4943*4882a593Smuzhiyun }
4944*4882a593Smuzhiyun #endif
4945*4882a593Smuzhiyun 
4946*4882a593Smuzhiyun /**
4947*4882a593Smuzhiyun  *  @brief Is any uAP started or STA connected?
4948*4882a593Smuzhiyun  *
4949*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
4950*4882a593Smuzhiyun  *
4951*4882a593Smuzhiyun  *  @return             MTRUE/MFALSE
4952*4882a593Smuzhiyun  */
wlan_check_interface_active(mlan_adapter * pmadapter)4953*4882a593Smuzhiyun t_bool wlan_check_interface_active(mlan_adapter *pmadapter)
4954*4882a593Smuzhiyun {
4955*4882a593Smuzhiyun 	t_bool ret = MFALSE;
4956*4882a593Smuzhiyun 	pmlan_private pmpriv;
4957*4882a593Smuzhiyun 	int i;
4958*4882a593Smuzhiyun 
4959*4882a593Smuzhiyun 	if (pmadapter == MNULL)
4960*4882a593Smuzhiyun 		return MFALSE;
4961*4882a593Smuzhiyun 
4962*4882a593Smuzhiyun 	for (i = 0; i < pmadapter->priv_num; i++) {
4963*4882a593Smuzhiyun 		pmpriv = pmadapter->priv[i];
4964*4882a593Smuzhiyun 		if (pmpriv) {
4965*4882a593Smuzhiyun #ifdef UAP_SUPPORT
4966*4882a593Smuzhiyun 			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
4967*4882a593Smuzhiyun 				ret = pmpriv->uap_bss_started;
4968*4882a593Smuzhiyun 			else
4969*4882a593Smuzhiyun #endif
4970*4882a593Smuzhiyun 				if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA)
4971*4882a593Smuzhiyun 				ret = pmpriv->media_connected;
4972*4882a593Smuzhiyun 		}
4973*4882a593Smuzhiyun 		if (ret)
4974*4882a593Smuzhiyun 			return MTRUE;
4975*4882a593Smuzhiyun 	}
4976*4882a593Smuzhiyun 
4977*4882a593Smuzhiyun 	return MFALSE;
4978*4882a593Smuzhiyun }
4979*4882a593Smuzhiyun 
4980*4882a593Smuzhiyun /**
4981*4882a593Smuzhiyun  *  @brief Get/Set DFS REPEATER mode
4982*4882a593Smuzhiyun  *
4983*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
4984*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
4985*4882a593Smuzhiyun  *
4986*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS
4987*4882a593Smuzhiyun  */
wlan_misc_ioctl_dfs_repeater_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4988*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_dfs_repeater_cfg(pmlan_adapter pmadapter,
4989*4882a593Smuzhiyun 					     pmlan_ioctl_req pioctl_req)
4990*4882a593Smuzhiyun {
4991*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
4992*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
4993*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
4994*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4995*4882a593Smuzhiyun 
4996*4882a593Smuzhiyun 	ENTER();
4997*4882a593Smuzhiyun 
4998*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4999*4882a593Smuzhiyun 
5000*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET) {
5001*4882a593Smuzhiyun 		/* Make sure no interface is active
5002*4882a593Smuzhiyun 		 * before setting the dfs repeater mode
5003*4882a593Smuzhiyun 		 */
5004*4882a593Smuzhiyun 		if (wlan_check_interface_active(pmadapter)) {
5005*4882a593Smuzhiyun 			PRINTM(MMSG, "DFS-Repeater active priv found,"
5006*4882a593Smuzhiyun 				     " skip enabling the mode.\n");
5007*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
5008*4882a593Smuzhiyun 			goto done;
5009*4882a593Smuzhiyun 		}
5010*4882a593Smuzhiyun 
5011*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
5012*4882a593Smuzhiyun 	} else {
5013*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
5014*4882a593Smuzhiyun 	}
5015*4882a593Smuzhiyun 
5016*4882a593Smuzhiyun 	/* Send request to firmware */
5017*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_DFS_REPEATER_MODE, cmd_action, 0,
5018*4882a593Smuzhiyun 			       (t_void *)pioctl_req, &misc->param.dfs_repeater);
5019*4882a593Smuzhiyun 
5020*4882a593Smuzhiyun done:
5021*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
5022*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
5023*4882a593Smuzhiyun 
5024*4882a593Smuzhiyun 	LEAVE();
5025*4882a593Smuzhiyun 	return ret;
5026*4882a593Smuzhiyun }
5027*4882a593Smuzhiyun 
5028*4882a593Smuzhiyun /**
5029*4882a593Smuzhiyun  *  @brief Set/Get Low Power Mode
5030*4882a593Smuzhiyun  *
5031*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
5032*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
5033*4882a593Smuzhiyun  *
5034*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS
5035*4882a593Smuzhiyun  */
wlan_misc_ioctl_low_pwr_mode(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)5036*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_low_pwr_mode(pmlan_adapter pmadapter,
5037*4882a593Smuzhiyun 					 pmlan_ioctl_req pioctl_req)
5038*4882a593Smuzhiyun {
5039*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5040*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
5041*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
5042*4882a593Smuzhiyun 
5043*4882a593Smuzhiyun 	ENTER();
5044*4882a593Smuzhiyun 
5045*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
5046*4882a593Smuzhiyun 
5047*4882a593Smuzhiyun 	/* Send request to firmware */
5048*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCMD_CONFIG_LOW_POWER_MODE,
5049*4882a593Smuzhiyun 			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
5050*4882a593Smuzhiyun 			       &misc->param.low_pwr_mode);
5051*4882a593Smuzhiyun 
5052*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
5053*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
5054*4882a593Smuzhiyun 
5055*4882a593Smuzhiyun 	LEAVE();
5056*4882a593Smuzhiyun 	return ret;
5057*4882a593Smuzhiyun }
5058*4882a593Smuzhiyun 
5059*4882a593Smuzhiyun /**
5060*4882a593Smuzhiyun  *  @brief Configure PMIC in Firmware
5061*4882a593Smuzhiyun  *
5062*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
5063*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
5064*4882a593Smuzhiyun  *
5065*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS
5066*4882a593Smuzhiyun  */
wlan_misc_ioctl_pmic_configure(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)5067*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_pmic_configure(pmlan_adapter pmadapter,
5068*4882a593Smuzhiyun 					   pmlan_ioctl_req pioctl_req)
5069*4882a593Smuzhiyun {
5070*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5071*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
5072*4882a593Smuzhiyun 
5073*4882a593Smuzhiyun 	ENTER();
5074*4882a593Smuzhiyun 
5075*4882a593Smuzhiyun 	/* Send request to firmware */
5076*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_PMIC_CONFIGURE,
5077*4882a593Smuzhiyun 			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
5078*4882a593Smuzhiyun 			       MNULL);
5079*4882a593Smuzhiyun 
5080*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
5081*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
5082*4882a593Smuzhiyun 
5083*4882a593Smuzhiyun 	LEAVE();
5084*4882a593Smuzhiyun 	return ret;
5085*4882a593Smuzhiyun }
5086*4882a593Smuzhiyun 
5087*4882a593Smuzhiyun /*  @brief Set/Get CW Mode Level control
5088*4882a593Smuzhiyun  *
5089*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
5090*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
5091*4882a593Smuzhiyun  *
5092*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS
5093*4882a593Smuzhiyun  */
wlan_misc_ioctl_cwmode_ctrl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)5094*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_cwmode_ctrl(pmlan_adapter pmadapter,
5095*4882a593Smuzhiyun 					pmlan_ioctl_req pioctl_req)
5096*4882a593Smuzhiyun {
5097*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5098*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
5099*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
5100*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
5101*4882a593Smuzhiyun 
5102*4882a593Smuzhiyun 	ENTER();
5103*4882a593Smuzhiyun 
5104*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
5105*4882a593Smuzhiyun 
5106*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
5107*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
5108*4882a593Smuzhiyun 	else
5109*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
5110*4882a593Smuzhiyun 
5111*4882a593Smuzhiyun 	/* Send request to firmware */
5112*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CW_MODE_CTRL, cmd_action, 0,
5113*4882a593Smuzhiyun 			       (t_void *)pioctl_req, &misc->param.cwmode);
5114*4882a593Smuzhiyun 
5115*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
5116*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
5117*4882a593Smuzhiyun 
5118*4882a593Smuzhiyun 	LEAVE();
5119*4882a593Smuzhiyun 	return ret;
5120*4882a593Smuzhiyun }
5121*4882a593Smuzhiyun 
5122*4882a593Smuzhiyun /**
5123*4882a593Smuzhiyun  *  @brief push value to stack
5124*4882a593Smuzhiyun  *
5125*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
5126*4882a593Smuzhiyun  *  @param s        A pointer to mef_stack
5127*4882a593Smuzhiyun  *  @param len          Length of value
5128*4882a593Smuzhiyun  *  @param val          A pointer to value
5129*4882a593Smuzhiyun  *
5130*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS or FAIL
5131*4882a593Smuzhiyun  */
push_n(pmlan_adapter pmadapter,mef_stack * s,t_u8 len,t_u8 * val)5132*4882a593Smuzhiyun inline mlan_status push_n(pmlan_adapter pmadapter, mef_stack *s, t_u8 len,
5133*4882a593Smuzhiyun 			  t_u8 *val)
5134*4882a593Smuzhiyun {
5135*4882a593Smuzhiyun 	if ((s->sp + len) <= MAX_NUM_STACK_BYTES) {
5136*4882a593Smuzhiyun 		memcpy_ext(pmadapter, s->byte + s->sp, val, len,
5137*4882a593Smuzhiyun 			   MAX_NUM_STACK_BYTES - s->sp);
5138*4882a593Smuzhiyun 		s->sp += len;
5139*4882a593Smuzhiyun 		return MLAN_STATUS_SUCCESS;
5140*4882a593Smuzhiyun 	} else {
5141*4882a593Smuzhiyun 		PRINTM(MERROR, "Stack is full\n");
5142*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
5143*4882a593Smuzhiyun 	}
5144*4882a593Smuzhiyun }
5145*4882a593Smuzhiyun 
5146*4882a593Smuzhiyun /**
5147*4882a593Smuzhiyun  *  @brief push value to stack accoring to operand type
5148*4882a593Smuzhiyun  *
5149*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
5150*4882a593Smuzhiyun  *  @param s        A pointer to mef_stack
5151*4882a593Smuzhiyun  *  @param op           A pointer to mef_op
5152*4882a593Smuzhiyun  *
5153*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS or FAIL
5154*4882a593Smuzhiyun  */
mef_push(pmlan_adapter pmadapter,mef_stack * s,mef_op * op)5155*4882a593Smuzhiyun inline mlan_status mef_push(pmlan_adapter pmadapter, mef_stack *s, mef_op *op)
5156*4882a593Smuzhiyun {
5157*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5158*4882a593Smuzhiyun 	t_u8 nbytes;
5159*4882a593Smuzhiyun 	switch (op->operand_type) {
5160*4882a593Smuzhiyun 	case OPERAND_DNUM:
5161*4882a593Smuzhiyun 		ret = push_n(pmadapter, s, 4, op->val);
5162*4882a593Smuzhiyun 		if (ret == MLAN_STATUS_SUCCESS)
5163*4882a593Smuzhiyun 			ret = push_n(pmadapter, s, 1, &op->operand_type);
5164*4882a593Smuzhiyun 		else
5165*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
5166*4882a593Smuzhiyun 		break;
5167*4882a593Smuzhiyun 	case OPERAND_BYTE_SEQ:
5168*4882a593Smuzhiyun 		nbytes = op->val[0];
5169*4882a593Smuzhiyun 		if (MLAN_STATUS_SUCCESS ==
5170*4882a593Smuzhiyun 			    push_n(pmadapter, s, nbytes, op->val + 1) &&
5171*4882a593Smuzhiyun 		    MLAN_STATUS_SUCCESS == push_n(pmadapter, s, 1, op->val) &&
5172*4882a593Smuzhiyun 		    MLAN_STATUS_SUCCESS ==
5173*4882a593Smuzhiyun 			    push_n(pmadapter, s, 1, &op->operand_type))
5174*4882a593Smuzhiyun 			ret = MLAN_STATUS_SUCCESS;
5175*4882a593Smuzhiyun 		else
5176*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
5177*4882a593Smuzhiyun 		break;
5178*4882a593Smuzhiyun 	default:
5179*4882a593Smuzhiyun 		ret = push_n(pmadapter, s, 1, &op->operand_type);
5180*4882a593Smuzhiyun 		break;
5181*4882a593Smuzhiyun 	}
5182*4882a593Smuzhiyun 	return ret;
5183*4882a593Smuzhiyun }
5184*4882a593Smuzhiyun 
5185*4882a593Smuzhiyun /**
5186*4882a593Smuzhiyun  *  @brief push dnum filter to stack
5187*4882a593Smuzhiyun  *
5188*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
5189*4882a593Smuzhiyun  *  @param s        A pointer to mef_stack
5190*4882a593Smuzhiyun  *  @param filter       A pointer to filter item
5191*4882a593Smuzhiyun  *
5192*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS or FAIL
5193*4882a593Smuzhiyun  */
push_filter_dnum_eq(pmlan_adapter pmadapter,mef_stack * s,mef_filter_t * filter)5194*4882a593Smuzhiyun static mlan_status push_filter_dnum_eq(pmlan_adapter pmadapter, mef_stack *s,
5195*4882a593Smuzhiyun 				       mef_filter_t *filter)
5196*4882a593Smuzhiyun {
5197*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5198*4882a593Smuzhiyun 	t_u32 dnum;
5199*4882a593Smuzhiyun 	mef_op op;
5200*4882a593Smuzhiyun 
5201*4882a593Smuzhiyun 	ENTER();
5202*4882a593Smuzhiyun 
5203*4882a593Smuzhiyun 	if (!filter) {
5204*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
5205*4882a593Smuzhiyun 		goto done;
5206*4882a593Smuzhiyun 	}
5207*4882a593Smuzhiyun 	if (filter->fill_flag != (FILLING_TYPE | FILLING_PATTERN |
5208*4882a593Smuzhiyun 				  FILLING_OFFSET | FILLING_NUM_BYTES)) {
5209*4882a593Smuzhiyun 		PRINTM(MERROR, "Filter item fill error\n");
5210*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
5211*4882a593Smuzhiyun 		goto done;
5212*4882a593Smuzhiyun 	}
5213*4882a593Smuzhiyun 
5214*4882a593Smuzhiyun 	/* Format of decimal num:
5215*4882a593Smuzhiyun 	 * |   5 bytes  |    5 bytes    |    5 bytes    |        1 byte | |
5216*4882a593Smuzhiyun 	 * pattern  |     offset    |  num of bytes |  type (TYPE_DNUM_EQ)  |
5217*4882a593Smuzhiyun 	 */
5218*4882a593Smuzhiyun 
5219*4882a593Smuzhiyun 	/* push pattern */
5220*4882a593Smuzhiyun 	memset(pmadapter, &op, 0, sizeof(op));
5221*4882a593Smuzhiyun 	op.operand_type = OPERAND_DNUM;
5222*4882a593Smuzhiyun 	dnum = filter->pattern;
5223*4882a593Smuzhiyun 	memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
5224*4882a593Smuzhiyun 	ret = mef_push(pmadapter, s, &op);
5225*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS)
5226*4882a593Smuzhiyun 		goto done;
5227*4882a593Smuzhiyun 
5228*4882a593Smuzhiyun 	/* push offset */
5229*4882a593Smuzhiyun 	memset(pmadapter, &op, 0, sizeof(op));
5230*4882a593Smuzhiyun 	op.operand_type = OPERAND_DNUM;
5231*4882a593Smuzhiyun 	dnum = filter->offset;
5232*4882a593Smuzhiyun 	memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
5233*4882a593Smuzhiyun 	ret = mef_push(pmadapter, s, &op);
5234*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS)
5235*4882a593Smuzhiyun 		goto done;
5236*4882a593Smuzhiyun 
5237*4882a593Smuzhiyun 	/* push num of bytes */
5238*4882a593Smuzhiyun 	memset(pmadapter, &op, 0, sizeof(op));
5239*4882a593Smuzhiyun 	op.operand_type = OPERAND_DNUM;
5240*4882a593Smuzhiyun 	dnum = filter->num_bytes;
5241*4882a593Smuzhiyun 	memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
5242*4882a593Smuzhiyun 	ret = mef_push(pmadapter, s, &op);
5243*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS)
5244*4882a593Smuzhiyun 		goto done;
5245*4882a593Smuzhiyun 
5246*4882a593Smuzhiyun 	/* push type */
5247*4882a593Smuzhiyun 	memset(pmadapter, &op, 0, sizeof(op));
5248*4882a593Smuzhiyun 	op.operand_type = TYPE_DNUM_EQ;
5249*4882a593Smuzhiyun 	ret = mef_push(pmadapter, s, &op);
5250*4882a593Smuzhiyun 
5251*4882a593Smuzhiyun done:
5252*4882a593Smuzhiyun 	LEAVE();
5253*4882a593Smuzhiyun 	return ret;
5254*4882a593Smuzhiyun }
5255*4882a593Smuzhiyun 
5256*4882a593Smuzhiyun /**
5257*4882a593Smuzhiyun  *  @brief push byte_eq filter to stack
5258*4882a593Smuzhiyun  *
5259*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
5260*4882a593Smuzhiyun  *  @param s            A pointer to mef_stack
5261*4882a593Smuzhiyun  *  @param filter       A pointer to filter item
5262*4882a593Smuzhiyun  *
5263*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS or FAIL
5264*4882a593Smuzhiyun  */
push_filter_byte_eq(pmlan_adapter pmadapter,mef_stack * s,mef_filter_t * filter)5265*4882a593Smuzhiyun static mlan_status push_filter_byte_eq(pmlan_adapter pmadapter, mef_stack *s,
5266*4882a593Smuzhiyun 				       mef_filter_t *filter)
5267*4882a593Smuzhiyun {
5268*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5269*4882a593Smuzhiyun 	t_u32 dnum;
5270*4882a593Smuzhiyun 	mef_op op;
5271*4882a593Smuzhiyun 
5272*4882a593Smuzhiyun 	ENTER();
5273*4882a593Smuzhiyun 
5274*4882a593Smuzhiyun 	if (!filter) {
5275*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
5276*4882a593Smuzhiyun 		goto done;
5277*4882a593Smuzhiyun 	}
5278*4882a593Smuzhiyun 	if (filter->fill_flag != (FILLING_TYPE | FILLING_REPEAT |
5279*4882a593Smuzhiyun 				  FILLING_BYTE_SEQ | FILLING_OFFSET)) {
5280*4882a593Smuzhiyun 		PRINTM(MERROR, "Filter item fill error\n");
5281*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
5282*4882a593Smuzhiyun 		goto done;
5283*4882a593Smuzhiyun 	}
5284*4882a593Smuzhiyun 
5285*4882a593Smuzhiyun 	/* Format of decimal num:
5286*4882a593Smuzhiyun 	 * |   5 bytes  |      val      |    5 bytes    |        1 byte | |
5287*4882a593Smuzhiyun 	 * repeat   |   bytes seq   |    offset     |  type (TYPE_BYTE_EQ)  |
5288*4882a593Smuzhiyun 	 */
5289*4882a593Smuzhiyun 
5290*4882a593Smuzhiyun 	/* push repeat */
5291*4882a593Smuzhiyun 	memset(pmadapter, &op, 0, sizeof(op));
5292*4882a593Smuzhiyun 	op.operand_type = OPERAND_DNUM;
5293*4882a593Smuzhiyun 	dnum = filter->repeat;
5294*4882a593Smuzhiyun 	memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
5295*4882a593Smuzhiyun 	ret = mef_push(pmadapter, s, &op);
5296*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS)
5297*4882a593Smuzhiyun 		goto done;
5298*4882a593Smuzhiyun 
5299*4882a593Smuzhiyun 	/* push bytes seq */
5300*4882a593Smuzhiyun 	memset(pmadapter, &op, 0, sizeof(op));
5301*4882a593Smuzhiyun 	op.operand_type = OPERAND_BYTE_SEQ;
5302*4882a593Smuzhiyun 	op.val[0] = filter->num_byte_seq;
5303*4882a593Smuzhiyun 	memcpy_ext(pmadapter, &op.val[1], filter->byte_seq,
5304*4882a593Smuzhiyun 		   filter->num_byte_seq, MAX_NUM_BYTE_SEQ);
5305*4882a593Smuzhiyun 	ret = mef_push(pmadapter, s, &op);
5306*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS)
5307*4882a593Smuzhiyun 		goto done;
5308*4882a593Smuzhiyun 
5309*4882a593Smuzhiyun 	/* push offset */
5310*4882a593Smuzhiyun 	memset(pmadapter, &op, 0, sizeof(op));
5311*4882a593Smuzhiyun 	op.operand_type = OPERAND_DNUM;
5312*4882a593Smuzhiyun 	dnum = filter->offset;
5313*4882a593Smuzhiyun 	memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
5314*4882a593Smuzhiyun 	ret = mef_push(pmadapter, s, &op);
5315*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS)
5316*4882a593Smuzhiyun 		goto done;
5317*4882a593Smuzhiyun 
5318*4882a593Smuzhiyun 	/* push type */
5319*4882a593Smuzhiyun 	memset(pmadapter, &op, 0, sizeof(op));
5320*4882a593Smuzhiyun 	op.operand_type = TYPE_BYTE_EQ;
5321*4882a593Smuzhiyun 	ret = mef_push(pmadapter, s, &op);
5322*4882a593Smuzhiyun 
5323*4882a593Smuzhiyun done:
5324*4882a593Smuzhiyun 	LEAVE();
5325*4882a593Smuzhiyun 	return ret;
5326*4882a593Smuzhiyun }
5327*4882a593Smuzhiyun 
5328*4882a593Smuzhiyun /**
5329*4882a593Smuzhiyun  *  @brief push bite_eq filter to stack
5330*4882a593Smuzhiyun  *
5331*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
5332*4882a593Smuzhiyun  *  @param s            A pointer to mef_stack
5333*4882a593Smuzhiyun  *  @param filter       A pointer to filter item
5334*4882a593Smuzhiyun  *
5335*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS or FAIL
5336*4882a593Smuzhiyun  */
push_filter_bit_eq(pmlan_adapter pmadapter,mef_stack * s,mef_filter_t * filter)5337*4882a593Smuzhiyun static mlan_status push_filter_bit_eq(pmlan_adapter pmadapter, mef_stack *s,
5338*4882a593Smuzhiyun 				      mef_filter_t *filter)
5339*4882a593Smuzhiyun {
5340*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5341*4882a593Smuzhiyun 	t_u32 dnum;
5342*4882a593Smuzhiyun 	mef_op op;
5343*4882a593Smuzhiyun 
5344*4882a593Smuzhiyun 	ENTER();
5345*4882a593Smuzhiyun 
5346*4882a593Smuzhiyun 	if (!filter) {
5347*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
5348*4882a593Smuzhiyun 		goto done;
5349*4882a593Smuzhiyun 	}
5350*4882a593Smuzhiyun 	if (filter->fill_flag != (FILLING_TYPE | FILLING_REPEAT |
5351*4882a593Smuzhiyun 				  FILLING_BYTE_SEQ | FILLING_OFFSET)) {
5352*4882a593Smuzhiyun 		PRINTM(MERROR, "Filter item fill error\n");
5353*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
5354*4882a593Smuzhiyun 		goto done;
5355*4882a593Smuzhiyun 	}
5356*4882a593Smuzhiyun 
5357*4882a593Smuzhiyun 	/* Format of decimal num:
5358*4882a593Smuzhiyun 	 * |   val      |    5 bytes    |      val      |        1 byte | |
5359*4882a593Smuzhiyun 	 * bytes seq  |    offset     |    mask seq   |  type (TYPE_BIT_EQ)   |
5360*4882a593Smuzhiyun 	 */
5361*4882a593Smuzhiyun 
5362*4882a593Smuzhiyun 	/* push bytes seq */
5363*4882a593Smuzhiyun 	memset(pmadapter, &op, 0, sizeof(op));
5364*4882a593Smuzhiyun 	op.operand_type = OPERAND_BYTE_SEQ;
5365*4882a593Smuzhiyun 	op.val[0] = filter->num_byte_seq;
5366*4882a593Smuzhiyun 	memcpy_ext(pmadapter, &op.val[1], filter->byte_seq,
5367*4882a593Smuzhiyun 		   filter->num_byte_seq, MAX_NUM_BYTE_SEQ);
5368*4882a593Smuzhiyun 	ret = mef_push(pmadapter, s, &op);
5369*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS)
5370*4882a593Smuzhiyun 		goto done;
5371*4882a593Smuzhiyun 
5372*4882a593Smuzhiyun 	/* push offset */
5373*4882a593Smuzhiyun 	memset(pmadapter, &op, 0, sizeof(op));
5374*4882a593Smuzhiyun 	op.operand_type = OPERAND_DNUM;
5375*4882a593Smuzhiyun 	dnum = filter->offset;
5376*4882a593Smuzhiyun 	memcpy_ext(pmadapter, op.val, &dnum, sizeof(dnum), sizeof(op.val));
5377*4882a593Smuzhiyun 	ret = mef_push(pmadapter, s, &op);
5378*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS)
5379*4882a593Smuzhiyun 		goto done;
5380*4882a593Smuzhiyun 
5381*4882a593Smuzhiyun 	/* push mask seq */
5382*4882a593Smuzhiyun 	memset(pmadapter, &op, 0, sizeof(op));
5383*4882a593Smuzhiyun 	op.operand_type = OPERAND_BYTE_SEQ;
5384*4882a593Smuzhiyun 	op.val[0] = filter->num_mask_seq;
5385*4882a593Smuzhiyun 	memcpy_ext(pmadapter, &op.val[1], filter->mask_seq,
5386*4882a593Smuzhiyun 		   filter->num_mask_seq, MAX_NUM_BYTE_SEQ);
5387*4882a593Smuzhiyun 	ret = mef_push(pmadapter, s, &op);
5388*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS)
5389*4882a593Smuzhiyun 		goto done;
5390*4882a593Smuzhiyun 
5391*4882a593Smuzhiyun 	/* push type */
5392*4882a593Smuzhiyun 	memset(pmadapter, &op, 0, sizeof(op));
5393*4882a593Smuzhiyun 	op.operand_type = TYPE_BIT_EQ;
5394*4882a593Smuzhiyun 	ret = mef_push(pmadapter, s, &op);
5395*4882a593Smuzhiyun 
5396*4882a593Smuzhiyun done:
5397*4882a593Smuzhiyun 	LEAVE();
5398*4882a593Smuzhiyun 	return ret;
5399*4882a593Smuzhiyun }
5400*4882a593Smuzhiyun 
5401*4882a593Smuzhiyun /**
5402*4882a593Smuzhiyun  *  @brief push filter to stack
5403*4882a593Smuzhiyun  *
5404*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
5405*4882a593Smuzhiyun  *  @param s        A pointer to mef_stack
5406*4882a593Smuzhiyun  *  @param filter       A pointer to filter item
5407*4882a593Smuzhiyun  *
5408*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS or FAIL
5409*4882a593Smuzhiyun  */
wlan_push_filter(pmlan_adapter pmadapter,mef_stack * s,mef_filter_t * filter)5410*4882a593Smuzhiyun static mlan_status wlan_push_filter(pmlan_adapter pmadapter, mef_stack *s,
5411*4882a593Smuzhiyun 				    mef_filter_t *filter)
5412*4882a593Smuzhiyun {
5413*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5414*4882a593Smuzhiyun 
5415*4882a593Smuzhiyun 	switch (filter->type) {
5416*4882a593Smuzhiyun 	case TYPE_DNUM_EQ:
5417*4882a593Smuzhiyun 		ret = push_filter_dnum_eq(pmadapter, s, filter);
5418*4882a593Smuzhiyun 		break;
5419*4882a593Smuzhiyun 	case TYPE_BYTE_EQ:
5420*4882a593Smuzhiyun 		ret = push_filter_byte_eq(pmadapter, s, filter);
5421*4882a593Smuzhiyun 		break;
5422*4882a593Smuzhiyun 	case TYPE_BIT_EQ:
5423*4882a593Smuzhiyun 		ret = push_filter_bit_eq(pmadapter, s, filter);
5424*4882a593Smuzhiyun 		break;
5425*4882a593Smuzhiyun 	default:
5426*4882a593Smuzhiyun 		PRINTM(MERROR, "Invalid filter type\n");
5427*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
5428*4882a593Smuzhiyun 		break;
5429*4882a593Smuzhiyun 	}
5430*4882a593Smuzhiyun 	return ret;
5431*4882a593Smuzhiyun }
5432*4882a593Smuzhiyun 
5433*4882a593Smuzhiyun /**
5434*4882a593Smuzhiyun  *  @brief generate mef data
5435*4882a593Smuzhiyun  *
5436*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
5437*4882a593Smuzhiyun  *  @param s        A pointer to mef_stack
5438*4882a593Smuzhiyun  *  @param entry        A pointer to mef_entry_t
5439*4882a593Smuzhiyun  *
5440*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS or FAIL
5441*4882a593Smuzhiyun  */
wlan_generate_mef_filter_stack(pmlan_adapter pmadapter,mef_stack * s,mef_entry_t * entry)5442*4882a593Smuzhiyun static mlan_status wlan_generate_mef_filter_stack(pmlan_adapter pmadapter,
5443*4882a593Smuzhiyun 						  mef_stack *s,
5444*4882a593Smuzhiyun 						  mef_entry_t *entry)
5445*4882a593Smuzhiyun {
5446*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5447*4882a593Smuzhiyun 	mef_op op;
5448*4882a593Smuzhiyun 	int i;
5449*4882a593Smuzhiyun 
5450*4882a593Smuzhiyun 	ENTER();
5451*4882a593Smuzhiyun 
5452*4882a593Smuzhiyun 	for (i = 0; i < entry->filter_num; i++) {
5453*4882a593Smuzhiyun 		ret = wlan_push_filter(pmadapter, s, &entry->filter_item[i]);
5454*4882a593Smuzhiyun 		if (ret != MLAN_STATUS_SUCCESS) {
5455*4882a593Smuzhiyun 			PRINTM(MERROR, "push filter to stack error\n");
5456*4882a593Smuzhiyun 			goto done;
5457*4882a593Smuzhiyun 		}
5458*4882a593Smuzhiyun 		if (i != 0) {
5459*4882a593Smuzhiyun 			memset(pmadapter, &op, 0, sizeof(op));
5460*4882a593Smuzhiyun 			op.operand_type = entry->rpn[i];
5461*4882a593Smuzhiyun 			ret = mef_push(pmadapter, s, &op);
5462*4882a593Smuzhiyun 			if (ret != MLAN_STATUS_SUCCESS) {
5463*4882a593Smuzhiyun 				PRINTM(MERROR, "push filter rpn error\n");
5464*4882a593Smuzhiyun 				goto done;
5465*4882a593Smuzhiyun 			}
5466*4882a593Smuzhiyun 		}
5467*4882a593Smuzhiyun 	}
5468*4882a593Smuzhiyun done:
5469*4882a593Smuzhiyun 	LEAVE();
5470*4882a593Smuzhiyun 	return ret;
5471*4882a593Smuzhiyun }
5472*4882a593Smuzhiyun 
5473*4882a593Smuzhiyun /**
5474*4882a593Smuzhiyun  *  @brief Set the mef entries to firmware
5475*4882a593Smuzhiyun  *
5476*4882a593Smuzhiyun  *  @param pmpriv        A pointer to mlan_private structure
5477*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
5478*4882a593Smuzhiyun  *  @param pmef      A pointer to mef_cfg structure
5479*4882a593Smuzhiyun  *
5480*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS or FAIL
5481*4882a593Smuzhiyun  */
wlan_set_mef_entry(mlan_private * pmpriv,pmlan_adapter pmadapter,mef_cfg_data * pmef)5482*4882a593Smuzhiyun mlan_status wlan_set_mef_entry(mlan_private *pmpriv, pmlan_adapter pmadapter,
5483*4882a593Smuzhiyun 			       mef_cfg_data *pmef)
5484*4882a593Smuzhiyun {
5485*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5486*4882a593Smuzhiyun 	mlan_ds_misc_cmd *hostcmd;
5487*4882a593Smuzhiyun 	HostCmd_DS_GEN *hostcmd_hdr;
5488*4882a593Smuzhiyun 	HostCmd_DS_MEF_CFG *mef_hdr;
5489*4882a593Smuzhiyun 	mef_entry_header *entry_hdr;
5490*4882a593Smuzhiyun 	mef_stack *stack;
5491*4882a593Smuzhiyun 	mef_entry_t *pentry;
5492*4882a593Smuzhiyun 	t_u8 *buf;
5493*4882a593Smuzhiyun 	t_u32 i, buf_len;
5494*4882a593Smuzhiyun 	pmlan_callbacks pcb;
5495*4882a593Smuzhiyun 
5496*4882a593Smuzhiyun 	ENTER();
5497*4882a593Smuzhiyun 
5498*4882a593Smuzhiyun 	if (pmef->entry_num > MAX_NUM_ENTRIES) {
5499*4882a593Smuzhiyun 		PRINTM(MERROR, "Too many entries\n");
5500*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
5501*4882a593Smuzhiyun 		goto done;
5502*4882a593Smuzhiyun 	}
5503*4882a593Smuzhiyun 	pcb = &pmadapter->callbacks;
5504*4882a593Smuzhiyun 	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
5505*4882a593Smuzhiyun 			       sizeof(mlan_ds_misc_cmd), MLAN_MEM_DEF,
5506*4882a593Smuzhiyun 			       (t_u8 **)&hostcmd);
5507*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS || hostcmd == MNULL) {
5508*4882a593Smuzhiyun 		PRINTM(MERROR, "Failed to allocate cmd data buffer\n");
5509*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
5510*4882a593Smuzhiyun 		goto err_handle;
5511*4882a593Smuzhiyun 	}
5512*4882a593Smuzhiyun 
5513*4882a593Smuzhiyun 	/** Fill the cmd header data*/
5514*4882a593Smuzhiyun 	memset(pmadapter, hostcmd, 0, sizeof(mlan_ds_misc_cmd));
5515*4882a593Smuzhiyun 	buf = hostcmd->cmd;
5516*4882a593Smuzhiyun 	hostcmd_hdr = (HostCmd_DS_GEN *)buf;
5517*4882a593Smuzhiyun 	hostcmd_hdr->command = wlan_cpu_to_le16(HostCmd_CMD_MEF_CFG);
5518*4882a593Smuzhiyun 	buf_len = S_DS_GEN;
5519*4882a593Smuzhiyun 
5520*4882a593Smuzhiyun 	/** Fill HostCmd_DS_MEF_CFG*/
5521*4882a593Smuzhiyun 	mef_hdr = (HostCmd_DS_MEF_CFG *)(buf + buf_len);
5522*4882a593Smuzhiyun 	mef_hdr->criteria = wlan_cpu_to_le32(pmef->criteria);
5523*4882a593Smuzhiyun 	mef_hdr->nentries = wlan_cpu_to_le16(pmef->entry_num);
5524*4882a593Smuzhiyun 	buf_len += sizeof(HostCmd_DS_MEF_CFG);
5525*4882a593Smuzhiyun 
5526*4882a593Smuzhiyun 	/** generate mef entry data*/
5527*4882a593Smuzhiyun 	for (i = 0, pentry = pmef->pentry; i < pmef->entry_num; i++, pentry++) {
5528*4882a593Smuzhiyun 		/** Fill entry header data*/
5529*4882a593Smuzhiyun 		entry_hdr = (mef_entry_header *)(buf + buf_len);
5530*4882a593Smuzhiyun 		entry_hdr->mode = pentry->mode;
5531*4882a593Smuzhiyun 		entry_hdr->action = pentry->action;
5532*4882a593Smuzhiyun 		buf_len += sizeof(mef_entry_header);
5533*4882a593Smuzhiyun 
5534*4882a593Smuzhiyun 		/** Fill Stack data*/
5535*4882a593Smuzhiyun 		stack = (mef_stack *)(buf + buf_len);
5536*4882a593Smuzhiyun 		ret = wlan_generate_mef_filter_stack(pmadapter, stack, pentry);
5537*4882a593Smuzhiyun 		if (ret != MLAN_STATUS_SUCCESS) {
5538*4882a593Smuzhiyun 			PRINTM(MERROR, "Generate mef data error\n");
5539*4882a593Smuzhiyun 			goto err_handle;
5540*4882a593Smuzhiyun 		}
5541*4882a593Smuzhiyun 		buf_len += (stack->sp + sizeof(stack->sp));
5542*4882a593Smuzhiyun 	}
5543*4882a593Smuzhiyun 	hostcmd_hdr->size = wlan_cpu_to_le16(buf_len);
5544*4882a593Smuzhiyun 	hostcmd->len = wlan_cpu_to_le32(buf_len);
5545*4882a593Smuzhiyun 
5546*4882a593Smuzhiyun 	DBG_HEXDUMP(MCMD_D, "MEF DATA", (t_u8 *)hostcmd, buf_len + 4);
5547*4882a593Smuzhiyun 
5548*4882a593Smuzhiyun 	/** Send command to firmware*/
5549*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, 0, 0, 0, (t_void *)MNULL,
5550*4882a593Smuzhiyun 			       (t_void *)hostcmd);
5551*4882a593Smuzhiyun 
5552*4882a593Smuzhiyun err_handle:
5553*4882a593Smuzhiyun 	if (hostcmd)
5554*4882a593Smuzhiyun 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
5555*4882a593Smuzhiyun done:
5556*4882a593Smuzhiyun 	LEAVE();
5557*4882a593Smuzhiyun 	return ret;
5558*4882a593Smuzhiyun }
5559*4882a593Smuzhiyun 
5560*4882a593Smuzhiyun /*
5561*4882a593Smuzhiyun  *  @brief generate Host_CMD_MEF_CFG cmd data to firmware
5562*4882a593Smuzhiyun  *
5563*4882a593Smuzhiyun  *  @param pmpriv       A pointer to mlan_private structure
5564*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
5565*4882a593Smuzhiyun  *
5566*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS or FAIL
5567*4882a593Smuzhiyun  */
wlan_process_mef_cfg_cmd(mlan_private * pmpriv,pmlan_adapter pmadapter)5568*4882a593Smuzhiyun mlan_status wlan_process_mef_cfg_cmd(mlan_private *pmpriv,
5569*4882a593Smuzhiyun 				     pmlan_adapter pmadapter)
5570*4882a593Smuzhiyun {
5571*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5572*4882a593Smuzhiyun 	pmlan_callbacks pcb;
5573*4882a593Smuzhiyun 	mef_cfg_data mef;
5574*4882a593Smuzhiyun 	mef_entry_t *pentry = MNULL;
5575*4882a593Smuzhiyun 	mef_entry *pmef;
5576*4882a593Smuzhiyun 	t_u16 entry_num = 0;
5577*4882a593Smuzhiyun 
5578*4882a593Smuzhiyun 	ENTER();
5579*4882a593Smuzhiyun 
5580*4882a593Smuzhiyun 	pcb = &pmadapter->callbacks;
5581*4882a593Smuzhiyun 	memset(pmadapter, &mef, 0, sizeof(mef_cfg_data));
5582*4882a593Smuzhiyun 
5583*4882a593Smuzhiyun 	/** check how many entries in adapter*/
5584*4882a593Smuzhiyun 	pmef = &pmadapter->entry_cfg;
5585*4882a593Smuzhiyun 	entry_num += pmef->enable_autoarp_entry;
5586*4882a593Smuzhiyun 	entry_num += pmef->num_wowlan_entry;
5587*4882a593Smuzhiyun 	entry_num += pmef->num_ipv6_ns_offload;
5588*4882a593Smuzhiyun 	if (!entry_num && !pmef->clear_mef_entry) {
5589*4882a593Smuzhiyun 		PRINTM(MIOCTL, "No filter entries\n");
5590*4882a593Smuzhiyun 		goto done;
5591*4882a593Smuzhiyun 	}
5592*4882a593Smuzhiyun 	if (entry_num) {
5593*4882a593Smuzhiyun 		ret = pcb->moal_malloc(pmadapter->pmoal_handle,
5594*4882a593Smuzhiyun 				       sizeof(mef_entry_t) * entry_num,
5595*4882a593Smuzhiyun 				       MLAN_MEM_DEF, (t_u8 **)&mef.pentry);
5596*4882a593Smuzhiyun 		if (ret != MLAN_STATUS_SUCCESS || mef.pentry == MNULL) {
5597*4882a593Smuzhiyun 			PRINTM(MERROR, "Failed to allocate cmd data buffer\n");
5598*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
5599*4882a593Smuzhiyun 			goto err_handle;
5600*4882a593Smuzhiyun 		}
5601*4882a593Smuzhiyun 	}
5602*4882a593Smuzhiyun 
5603*4882a593Smuzhiyun 	/** Fill mef_cfg structure*/
5604*4882a593Smuzhiyun 	mef.criteria = pmef->criteria;
5605*4882a593Smuzhiyun 	mef.entry_num = entry_num;
5606*4882a593Smuzhiyun 	memset(pmadapter, mef.pentry, 0, sizeof(mef_entry_t) * entry_num);
5607*4882a593Smuzhiyun 	pentry = mef.pentry;
5608*4882a593Smuzhiyun 	/** Fill mef_entry_t structure*/
5609*4882a593Smuzhiyun 	/** Copy Auto arp response entry*/
5610*4882a593Smuzhiyun 	if (pmef->enable_autoarp_entry) {
5611*4882a593Smuzhiyun 		memcpy_ext(pmadapter, pentry, &pmef->entry[5],
5612*4882a593Smuzhiyun 			   sizeof(mef_entry_t), sizeof(mef_entry_t));
5613*4882a593Smuzhiyun 		pentry += pmef->enable_autoarp_entry;
5614*4882a593Smuzhiyun 	}
5615*4882a593Smuzhiyun 	/** Copy wowlan entry*/
5616*4882a593Smuzhiyun 	if (pmef->num_wowlan_entry) {
5617*4882a593Smuzhiyun 		memcpy_ext(pmadapter, pentry, &pmef->entry[6],
5618*4882a593Smuzhiyun 			   sizeof(mef_entry_t), sizeof(mef_entry_t));
5619*4882a593Smuzhiyun 		pentry += pmef->num_wowlan_entry;
5620*4882a593Smuzhiyun 	}
5621*4882a593Smuzhiyun 	/** Copy IPv6 NS message offload entry */
5622*4882a593Smuzhiyun 	if (pmef->num_ipv6_ns_offload)
5623*4882a593Smuzhiyun 		memcpy_ext(pmadapter, pentry, &pmef->entry[7],
5624*4882a593Smuzhiyun 			   sizeof(mef_entry_t), sizeof(mef_entry_t));
5625*4882a593Smuzhiyun 
5626*4882a593Smuzhiyun 	/** Set Entries to firmware*/
5627*4882a593Smuzhiyun 	ret = wlan_set_mef_entry(pmpriv, pmadapter, &mef);
5628*4882a593Smuzhiyun 	if (ret != MLAN_STATUS_SUCCESS)
5629*4882a593Smuzhiyun 		PRINTM(MERROR, "Set MEF entries error\n");
5630*4882a593Smuzhiyun 
5631*4882a593Smuzhiyun err_handle:
5632*4882a593Smuzhiyun 	if (mef.pentry)
5633*4882a593Smuzhiyun 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)mef.pentry);
5634*4882a593Smuzhiyun done:
5635*4882a593Smuzhiyun 	LEAVE();
5636*4882a593Smuzhiyun 	return ret;
5637*4882a593Smuzhiyun }
5638*4882a593Smuzhiyun 
5639*4882a593Smuzhiyun /*  @brief Get/Set NV-FLT-CONFIG parameters
5640*4882a593Smuzhiyun  *
5641*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
5642*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
5643*4882a593Smuzhiyun  *
5644*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS
5645*4882a593Smuzhiyun  */
wlan_misc_ioctl_mef_flt_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)5646*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_mef_flt_cfg(pmlan_adapter pmadapter,
5647*4882a593Smuzhiyun 					pmlan_ioctl_req pioctl_req)
5648*4882a593Smuzhiyun {
5649*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5650*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc_cfg = MNULL;
5651*4882a593Smuzhiyun 	mlan_ds_misc_mef_flt_cfg *mef_cfg = MNULL;
5652*4882a593Smuzhiyun 	mef_entry *pmef = MNULL;
5653*4882a593Smuzhiyun 
5654*4882a593Smuzhiyun 	ENTER();
5655*4882a593Smuzhiyun 
5656*4882a593Smuzhiyun 	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
5657*4882a593Smuzhiyun 	mef_cfg = &misc_cfg->param.mef_flt_cfg;
5658*4882a593Smuzhiyun 	pmef = &pmadapter->entry_cfg;
5659*4882a593Smuzhiyun 	switch (pioctl_req->action) {
5660*4882a593Smuzhiyun 	case MLAN_ACT_SET:
5661*4882a593Smuzhiyun 		if (mef_cfg->mef_act_type == MEF_ACT_WOWLAN) {
5662*4882a593Smuzhiyun 			pmef->num_wowlan_entry = 1;
5663*4882a593Smuzhiyun 			pmef->criteria |= mef_cfg->criteria;
5664*4882a593Smuzhiyun 			memcpy_ext(pmadapter, &pmef->entry[6],
5665*4882a593Smuzhiyun 				   &mef_cfg->mef_entry, sizeof(mef_entry_t),
5666*4882a593Smuzhiyun 				   sizeof(mef_entry_t));
5667*4882a593Smuzhiyun 		}
5668*4882a593Smuzhiyun 		if (mef_cfg->mef_act_type == MEF_ACT_IPV6_NS) {
5669*4882a593Smuzhiyun 			pmef->num_ipv6_ns_offload = 1;
5670*4882a593Smuzhiyun 			pmef->criteria |= mef_cfg->criteria;
5671*4882a593Smuzhiyun 			memcpy_ext(pmadapter, &pmef->entry[7],
5672*4882a593Smuzhiyun 				   &mef_cfg->mef_entry, sizeof(mef_entry_t),
5673*4882a593Smuzhiyun 				   sizeof(mef_entry_t));
5674*4882a593Smuzhiyun 		}
5675*4882a593Smuzhiyun 		/** Set AUTO ARP Entry to adapter*/
5676*4882a593Smuzhiyun 		if (mef_cfg->mef_act_type == MEF_ACT_AUTOARP) {
5677*4882a593Smuzhiyun 			if (mef_cfg->op_code & MLAN_IPADDR_OP_AUTO_ARP_RESP) {
5678*4882a593Smuzhiyun 				pmef->enable_autoarp_entry = 1;
5679*4882a593Smuzhiyun 				pmef->criteria |= mef_cfg->criteria;
5680*4882a593Smuzhiyun 				memcpy_ext(pmadapter, &pmef->entry[5],
5681*4882a593Smuzhiyun 					   &mef_cfg->mef_entry,
5682*4882a593Smuzhiyun 					   sizeof(mef_entry_t),
5683*4882a593Smuzhiyun 					   sizeof(mef_entry_t));
5684*4882a593Smuzhiyun 				if (MLAN_STATUS_SUCCESS !=
5685*4882a593Smuzhiyun 				    wlan_process_mef_cfg_cmd(
5686*4882a593Smuzhiyun 					    pmadapter
5687*4882a593Smuzhiyun 						    ->priv[pioctl_req->bss_index],
5688*4882a593Smuzhiyun 					    pmadapter))
5689*4882a593Smuzhiyun 					PRINTM(MERROR,
5690*4882a593Smuzhiyun 					       "Set MEF Entries Error\n");
5691*4882a593Smuzhiyun 			} else if (!(mef_cfg->op_code &
5692*4882a593Smuzhiyun 				     MLAN_IPADDR_OP_IP_REMOVE)) {
5693*4882a593Smuzhiyun 				pmef->enable_autoarp_entry = 0;
5694*4882a593Smuzhiyun 				pmef->num_wowlan_entry = 0;
5695*4882a593Smuzhiyun 				pmef->num_ipv6_ns_offload = 0;
5696*4882a593Smuzhiyun 				pmef->clear_mef_entry = 1;
5697*4882a593Smuzhiyun 				memset(pmadapter, &pmef->entry[5], 0,
5698*4882a593Smuzhiyun 				       sizeof(mef_entry_t));
5699*4882a593Smuzhiyun 				memset(pmadapter, &pmef->entry[6], 0,
5700*4882a593Smuzhiyun 				       sizeof(mef_entry_t));
5701*4882a593Smuzhiyun 				memset(pmadapter, &pmef->entry[7], 0,
5702*4882a593Smuzhiyun 				       sizeof(mef_entry_t));
5703*4882a593Smuzhiyun 				if (MLAN_STATUS_SUCCESS !=
5704*4882a593Smuzhiyun 				    wlan_process_mef_cfg_cmd(
5705*4882a593Smuzhiyun 					    pmadapter
5706*4882a593Smuzhiyun 						    ->priv[pioctl_req->bss_index],
5707*4882a593Smuzhiyun 					    pmadapter))
5708*4882a593Smuzhiyun 					PRINTM(MERROR,
5709*4882a593Smuzhiyun 					       "Clear MEF Entries Error\n");
5710*4882a593Smuzhiyun 			}
5711*4882a593Smuzhiyun 		}
5712*4882a593Smuzhiyun 		break;
5713*4882a593Smuzhiyun 	case MLAN_ACT_GET:
5714*4882a593Smuzhiyun 		if (mef_cfg->mef_act_type == MEF_ACT_WOWLAN)
5715*4882a593Smuzhiyun 			memcpy_ext(pmadapter, &mef_cfg->mef_entry,
5716*4882a593Smuzhiyun 				   &pmef->entry[6], sizeof(mef_entry_t),
5717*4882a593Smuzhiyun 				   sizeof(mef_entry_t));
5718*4882a593Smuzhiyun 		break;
5719*4882a593Smuzhiyun 	default:
5720*4882a593Smuzhiyun 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
5721*4882a593Smuzhiyun 		ret = MLAN_STATUS_FAILURE;
5722*4882a593Smuzhiyun 		break;
5723*4882a593Smuzhiyun 	}
5724*4882a593Smuzhiyun 
5725*4882a593Smuzhiyun 	LEAVE();
5726*4882a593Smuzhiyun 	return ret;
5727*4882a593Smuzhiyun }
5728*4882a593Smuzhiyun 
5729*4882a593Smuzhiyun /**
5730*4882a593Smuzhiyun  *  @brief Set/Get WPA passphrase for esupplicant
5731*4882a593Smuzhiyun  *
5732*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
5733*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
5734*4882a593Smuzhiyun  *
5735*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
5736*4882a593Smuzhiyun  */
wlan_sec_ioctl_passphrase(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)5737*4882a593Smuzhiyun mlan_status wlan_sec_ioctl_passphrase(pmlan_adapter pmadapter,
5738*4882a593Smuzhiyun 				      pmlan_ioctl_req pioctl_req)
5739*4882a593Smuzhiyun {
5740*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5741*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
5742*4882a593Smuzhiyun 	mlan_ds_sec_cfg *sec = MNULL;
5743*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
5744*4882a593Smuzhiyun #ifdef STA_SUPPORT
5745*4882a593Smuzhiyun 	BSSDescriptor_t *pbss_desc;
5746*4882a593Smuzhiyun 	int i = 0;
5747*4882a593Smuzhiyun #endif
5748*4882a593Smuzhiyun 	ENTER();
5749*4882a593Smuzhiyun 
5750*4882a593Smuzhiyun 	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
5751*4882a593Smuzhiyun #ifdef DRV_EMBEDDED_SUPPLICANT
5752*4882a593Smuzhiyun 	if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA &&
5753*4882a593Smuzhiyun 	    !IS_FW_SUPPORT_SUPPLICANT(pmpriv->adapter)) {
5754*4882a593Smuzhiyun 		if (sec->param.passphrase.psk_type == MLAN_PSK_QUERY)
5755*4882a593Smuzhiyun 			SupplicantQueryPassphrase(
5756*4882a593Smuzhiyun 				pmpriv->psapriv,
5757*4882a593Smuzhiyun 				(void *)&sec->param.passphrase);
5758*4882a593Smuzhiyun 		else if (sec->param.passphrase.psk_type == MLAN_PSK_CLEAR)
5759*4882a593Smuzhiyun 			SupplicantClearPMK(pmpriv->psapriv,
5760*4882a593Smuzhiyun 					   (void *)&sec->param.passphrase);
5761*4882a593Smuzhiyun 		else
5762*4882a593Smuzhiyun 			SupplicantSetPassphrase(pmpriv->psapriv,
5763*4882a593Smuzhiyun 						(void *)&sec->param.passphrase);
5764*4882a593Smuzhiyun 
5765*4882a593Smuzhiyun 		LEAVE();
5766*4882a593Smuzhiyun 		return ret;
5767*4882a593Smuzhiyun 	}
5768*4882a593Smuzhiyun #endif
5769*4882a593Smuzhiyun 
5770*4882a593Smuzhiyun 	if (!IS_FW_SUPPORT_SUPPLICANT(pmpriv->adapter)) {
5771*4882a593Smuzhiyun 		LEAVE();
5772*4882a593Smuzhiyun 		return ret;
5773*4882a593Smuzhiyun 	}
5774*4882a593Smuzhiyun 
5775*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET) {
5776*4882a593Smuzhiyun 		if (sec->param.passphrase.psk_type == MLAN_PSK_CLEAR)
5777*4882a593Smuzhiyun 			cmd_action = HostCmd_ACT_GEN_REMOVE;
5778*4882a593Smuzhiyun 		else
5779*4882a593Smuzhiyun 			cmd_action = HostCmd_ACT_GEN_SET;
5780*4882a593Smuzhiyun 	} else if (pioctl_req->action == MLAN_ACT_CLEAR) {
5781*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_REMOVE;
5782*4882a593Smuzhiyun 	} else {
5783*4882a593Smuzhiyun 		if (sec->param.passphrase.psk_type == MLAN_PSK_QUERY) {
5784*4882a593Smuzhiyun #ifdef STA_SUPPORT
5785*4882a593Smuzhiyun 			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA &&
5786*4882a593Smuzhiyun 			    sec->param.passphrase.ssid.ssid_len == 0) {
5787*4882a593Smuzhiyun 				i = wlan_find_bssid_in_list(
5788*4882a593Smuzhiyun 					pmpriv,
5789*4882a593Smuzhiyun 					(t_u8 *)&sec->param.passphrase.bssid,
5790*4882a593Smuzhiyun 					MLAN_BSS_MODE_AUTO);
5791*4882a593Smuzhiyun 				if (i >= 0) {
5792*4882a593Smuzhiyun 					pbss_desc = &pmadapter->pscan_table[i];
5793*4882a593Smuzhiyun 					memcpy_ext(pmadapter,
5794*4882a593Smuzhiyun 						   &sec->param.passphrase.ssid,
5795*4882a593Smuzhiyun 						   &pbss_desc->ssid,
5796*4882a593Smuzhiyun 						   sizeof(mlan_802_11_ssid),
5797*4882a593Smuzhiyun 						   sizeof(mlan_802_11_ssid));
5798*4882a593Smuzhiyun 					memset(pmadapter,
5799*4882a593Smuzhiyun 					       &sec->param.passphrase.bssid, 0,
5800*4882a593Smuzhiyun 					       MLAN_MAC_ADDR_LENGTH);
5801*4882a593Smuzhiyun 					PRINTM(MINFO,
5802*4882a593Smuzhiyun 					       "PSK_QUERY: found ssid=%s\n",
5803*4882a593Smuzhiyun 					       sec->param.passphrase.ssid.ssid);
5804*4882a593Smuzhiyun 				}
5805*4882a593Smuzhiyun 			} else
5806*4882a593Smuzhiyun #endif
5807*4882a593Smuzhiyun 				memset(pmadapter, &sec->param.passphrase.bssid,
5808*4882a593Smuzhiyun 				       0, MLAN_MAC_ADDR_LENGTH);
5809*4882a593Smuzhiyun 		}
5810*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
5811*4882a593Smuzhiyun 	}
5812*4882a593Smuzhiyun 
5813*4882a593Smuzhiyun 	/* Send request to firmware */
5814*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SUPPLICANT_PMK, cmd_action,
5815*4882a593Smuzhiyun 			       0, (t_void *)pioctl_req, (t_void *)sec);
5816*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
5817*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
5818*4882a593Smuzhiyun 
5819*4882a593Smuzhiyun 	LEAVE();
5820*4882a593Smuzhiyun 	return ret;
5821*4882a593Smuzhiyun }
5822*4882a593Smuzhiyun 
5823*4882a593Smuzhiyun /**
5824*4882a593Smuzhiyun  *  @brief Set per packet Txctl and Rxinfo configuration
5825*4882a593Smuzhiyun  *
5826*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
5827*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
5828*4882a593Smuzhiyun  *
5829*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
5830*4882a593Smuzhiyun  */
wlan_misc_per_pkt_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)5831*4882a593Smuzhiyun mlan_status wlan_misc_per_pkt_cfg(pmlan_adapter pmadapter,
5832*4882a593Smuzhiyun 				  pmlan_ioctl_req pioctl_req)
5833*4882a593Smuzhiyun {
5834*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5835*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
5836*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
5837*4882a593Smuzhiyun 
5838*4882a593Smuzhiyun 	ENTER();
5839*4882a593Smuzhiyun 
5840*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
5841*4882a593Smuzhiyun 	pmpriv->rx_pkt_info = MFALSE;
5842*4882a593Smuzhiyun 	if (misc->param.txrx_pkt_ctrl & RX_PKT_INFO)
5843*4882a593Smuzhiyun 		pmpriv->rx_pkt_info = MTRUE;
5844*4882a593Smuzhiyun 
5845*4882a593Smuzhiyun 	LEAVE();
5846*4882a593Smuzhiyun 	return ret;
5847*4882a593Smuzhiyun }
5848*4882a593Smuzhiyun 
5849*4882a593Smuzhiyun /**
5850*4882a593Smuzhiyun  *  @brief Set/Get region code
5851*4882a593Smuzhiyun  *
5852*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
5853*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
5854*4882a593Smuzhiyun  *
5855*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
5856*4882a593Smuzhiyun  */
wlan_misc_ioctl_region(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)5857*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_region(pmlan_adapter pmadapter,
5858*4882a593Smuzhiyun 				   pmlan_ioctl_req pioctl_req)
5859*4882a593Smuzhiyun {
5860*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5861*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
5862*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
5863*4882a593Smuzhiyun 	int i;
5864*4882a593Smuzhiyun 
5865*4882a593Smuzhiyun 	ENTER();
5866*4882a593Smuzhiyun 
5867*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
5868*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_GET) {
5869*4882a593Smuzhiyun 		misc->param.region_code = pmadapter->region_code;
5870*4882a593Smuzhiyun 	} else {
5871*4882a593Smuzhiyun 		if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
5872*4882a593Smuzhiyun 			PRINTM(MERROR,
5873*4882a593Smuzhiyun 			       "ForceRegionRule is set in the on-chip OTP"
5874*4882a593Smuzhiyun 			       " memory\n");
5875*4882a593Smuzhiyun 			LEAVE();
5876*4882a593Smuzhiyun 			return MLAN_STATUS_FAILURE;
5877*4882a593Smuzhiyun 		}
5878*4882a593Smuzhiyun 		for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
5879*4882a593Smuzhiyun 			/* Use the region code to search for the index */
5880*4882a593Smuzhiyun 			if (misc->param.region_code == region_code_index[i]) {
5881*4882a593Smuzhiyun 				pmadapter->region_code =
5882*4882a593Smuzhiyun 					(t_u16)misc->param.region_code;
5883*4882a593Smuzhiyun 				break;
5884*4882a593Smuzhiyun 			}
5885*4882a593Smuzhiyun 		}
5886*4882a593Smuzhiyun 		/* It's unidentified region code */
5887*4882a593Smuzhiyun 		if (i >= MRVDRV_MAX_REGION_CODE) {
5888*4882a593Smuzhiyun 			PRINTM(MERROR, "Region Code not identified\n");
5889*4882a593Smuzhiyun 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
5890*4882a593Smuzhiyun 			LEAVE();
5891*4882a593Smuzhiyun 			return MLAN_STATUS_FAILURE;
5892*4882a593Smuzhiyun 		}
5893*4882a593Smuzhiyun 		pmadapter->cfp_code_bg = misc->param.region_code;
5894*4882a593Smuzhiyun 		pmadapter->cfp_code_a = misc->param.region_code;
5895*4882a593Smuzhiyun 		if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
5896*4882a593Smuzhiyun 					 pmadapter->config_bands |
5897*4882a593Smuzhiyun 						 pmadapter->adhoc_start_band)) {
5898*4882a593Smuzhiyun 			pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
5899*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
5900*4882a593Smuzhiyun 		}
5901*4882a593Smuzhiyun 	}
5902*4882a593Smuzhiyun 	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
5903*4882a593Smuzhiyun 
5904*4882a593Smuzhiyun 	LEAVE();
5905*4882a593Smuzhiyun 	return ret;
5906*4882a593Smuzhiyun }
5907*4882a593Smuzhiyun 
5908*4882a593Smuzhiyun /**
5909*4882a593Smuzhiyun  *  @brief Configure GPIO independent reset
5910*4882a593Smuzhiyun  *
5911*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
5912*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
5913*4882a593Smuzhiyun  *
5914*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
5915*4882a593Smuzhiyun  */
wlan_misc_ioctl_ind_rst_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)5916*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_ind_rst_cfg(pmlan_adapter pmadapter,
5917*4882a593Smuzhiyun 					pmlan_ioctl_req pioctl_req)
5918*4882a593Smuzhiyun {
5919*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
5920*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
5921*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5922*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
5923*4882a593Smuzhiyun 
5924*4882a593Smuzhiyun 	ENTER();
5925*4882a593Smuzhiyun 
5926*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_GET)
5927*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
5928*4882a593Smuzhiyun 	else
5929*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
5930*4882a593Smuzhiyun 
5931*4882a593Smuzhiyun 	/* Send request to firmware */
5932*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_INDEPENDENT_RESET_CFG,
5933*4882a593Smuzhiyun 			       cmd_action, 0, (t_void *)pioctl_req,
5934*4882a593Smuzhiyun 			       (t_void *)&misc->param.ind_rst_cfg);
5935*4882a593Smuzhiyun 
5936*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
5937*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
5938*4882a593Smuzhiyun 
5939*4882a593Smuzhiyun 	LEAVE();
5940*4882a593Smuzhiyun 	return ret;
5941*4882a593Smuzhiyun }
5942*4882a593Smuzhiyun 
5943*4882a593Smuzhiyun /**
5944*4882a593Smuzhiyun  *  @brief  Get timestamp from firmware
5945*4882a593Smuzhiyun  *
5946*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
5947*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
5948*4882a593Smuzhiyun  *
5949*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
5950*4882a593Smuzhiyun  */
wlan_misc_ioctl_get_tsf(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)5951*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_get_tsf(pmlan_adapter pmadapter,
5952*4882a593Smuzhiyun 				    pmlan_ioctl_req pioctl_req)
5953*4882a593Smuzhiyun {
5954*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
5955*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5956*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
5957*4882a593Smuzhiyun 
5958*4882a593Smuzhiyun 	ENTER();
5959*4882a593Smuzhiyun 
5960*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_GET)
5961*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
5962*4882a593Smuzhiyun 	else {
5963*4882a593Smuzhiyun 		PRINTM(MERROR, "No support set tsf!");
5964*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
5965*4882a593Smuzhiyun 	}
5966*4882a593Smuzhiyun 
5967*4882a593Smuzhiyun 	/* Send request to firmware */
5968*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_GET_TSF, cmd_action, 0,
5969*4882a593Smuzhiyun 			       (t_void *)pioctl_req, MNULL);
5970*4882a593Smuzhiyun 
5971*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
5972*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
5973*4882a593Smuzhiyun 
5974*4882a593Smuzhiyun 	LEAVE();
5975*4882a593Smuzhiyun 	return ret;
5976*4882a593Smuzhiyun }
5977*4882a593Smuzhiyun 
5978*4882a593Smuzhiyun /**
5979*4882a593Smuzhiyun  *  @brief  Create custom regulatory cfg
5980*4882a593Smuzhiyun  *
5981*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
5982*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
5983*4882a593Smuzhiyun  *
5984*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
5985*4882a593Smuzhiyun  */
wlan_misc_chan_reg_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)5986*4882a593Smuzhiyun mlan_status wlan_misc_chan_reg_cfg(pmlan_adapter pmadapter,
5987*4882a593Smuzhiyun 				   pmlan_ioctl_req pioctl_req)
5988*4882a593Smuzhiyun {
5989*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
5990*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
5991*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
5992*4882a593Smuzhiyun 
5993*4882a593Smuzhiyun 	ENTER();
5994*4882a593Smuzhiyun 
5995*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_GET)
5996*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
5997*4882a593Smuzhiyun 	else {
5998*4882a593Smuzhiyun 		PRINTM(MERROR, "No support set channel region cfg!");
5999*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
6000*4882a593Smuzhiyun 	}
6001*4882a593Smuzhiyun 
6002*4882a593Smuzhiyun 	/* Send request to firmware */
6003*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CHAN_REGION_CFG, cmd_action,
6004*4882a593Smuzhiyun 			       0, (t_void *)pioctl_req, MNULL);
6005*4882a593Smuzhiyun 
6006*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6007*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6008*4882a593Smuzhiyun 
6009*4882a593Smuzhiyun 	LEAVE();
6010*4882a593Smuzhiyun 	return ret;
6011*4882a593Smuzhiyun }
6012*4882a593Smuzhiyun 
6013*4882a593Smuzhiyun /**
6014*4882a593Smuzhiyun  *  @brief Check operating class validation
6015*4882a593Smuzhiyun  *
6016*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
6017*4882a593Smuzhiyun  *  @param pioctl_req   Pointer to the IOCTL request buffer
6018*4882a593Smuzhiyun  *
6019*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
6020*4882a593Smuzhiyun  */
wlan_misc_ioctl_operclass_validation(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)6021*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_operclass_validation(pmlan_adapter pmadapter,
6022*4882a593Smuzhiyun 						 mlan_ioctl_req *pioctl_req)
6023*4882a593Smuzhiyun {
6024*4882a593Smuzhiyun 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
6025*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
6026*4882a593Smuzhiyun 	t_u8 channel, oper_class;
6027*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6028*4882a593Smuzhiyun 
6029*4882a593Smuzhiyun 	ENTER();
6030*4882a593Smuzhiyun 
6031*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6032*4882a593Smuzhiyun 	channel = misc->param.bw_chan_oper.channel;
6033*4882a593Smuzhiyun 	oper_class = misc->param.bw_chan_oper.oper_class;
6034*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_GET) {
6035*4882a593Smuzhiyun 		ret = wlan_check_operclass_validation(pmpriv, channel,
6036*4882a593Smuzhiyun 						      oper_class);
6037*4882a593Smuzhiyun 	} else {
6038*4882a593Smuzhiyun 		PRINTM(MERROR, "Unsupported cmd_action\n");
6039*4882a593Smuzhiyun 		LEAVE();
6040*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
6041*4882a593Smuzhiyun 	}
6042*4882a593Smuzhiyun 
6043*4882a593Smuzhiyun 	LEAVE();
6044*4882a593Smuzhiyun 	return ret;
6045*4882a593Smuzhiyun }
6046*4882a593Smuzhiyun 
6047*4882a593Smuzhiyun /**
6048*4882a593Smuzhiyun  *  @brief  Get Region channel power setting
6049*4882a593Smuzhiyun  *
6050*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
6051*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
6052*4882a593Smuzhiyun  *
6053*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
6054*4882a593Smuzhiyun  */
wlan_get_rgchnpwr_cfg(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)6055*4882a593Smuzhiyun mlan_status wlan_get_rgchnpwr_cfg(pmlan_adapter pmadapter,
6056*4882a593Smuzhiyun 				  mlan_ioctl_req *pioctl_req)
6057*4882a593Smuzhiyun {
6058*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
6059*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6060*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6061*4882a593Smuzhiyun 
6062*4882a593Smuzhiyun 	ENTER();
6063*4882a593Smuzhiyun 
6064*4882a593Smuzhiyun 	cmd_action = HostCmd_ACT_GEN_GET;
6065*4882a593Smuzhiyun 
6066*4882a593Smuzhiyun 	/* Send request to firmware */
6067*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CHAN_REGION_CFG, cmd_action,
6068*4882a593Smuzhiyun 			       0, (t_void *)pioctl_req, MNULL);
6069*4882a593Smuzhiyun 
6070*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6071*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6072*4882a593Smuzhiyun 
6073*4882a593Smuzhiyun 	LEAVE();
6074*4882a593Smuzhiyun 	return ret;
6075*4882a593Smuzhiyun }
6076*4882a593Smuzhiyun 
6077*4882a593Smuzhiyun /**
6078*4882a593Smuzhiyun  *  @brief  Get/Set mc_aggr_cfg
6079*4882a593Smuzhiyun  *
6080*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
6081*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
6082*4882a593Smuzhiyun  *
6083*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
6084*4882a593Smuzhiyun  */
wlan_misc_ioctl_mc_aggr_cfg(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)6085*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_mc_aggr_cfg(pmlan_adapter pmadapter,
6086*4882a593Smuzhiyun 					mlan_ioctl_req *pioctl_req)
6087*4882a593Smuzhiyun {
6088*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
6089*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6090*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6091*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
6092*4882a593Smuzhiyun 
6093*4882a593Smuzhiyun 	ENTER();
6094*4882a593Smuzhiyun 
6095*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6096*4882a593Smuzhiyun 	cmd_action = pioctl_req->action;
6097*4882a593Smuzhiyun 
6098*4882a593Smuzhiyun 	/* Send request to firmware */
6099*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MC_AGGR_CFG, cmd_action, 0,
6100*4882a593Smuzhiyun 			       (t_void *)pioctl_req,
6101*4882a593Smuzhiyun 			       (t_void *)&misc->param.mc_aggr_cfg);
6102*4882a593Smuzhiyun 
6103*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6104*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6105*4882a593Smuzhiyun 
6106*4882a593Smuzhiyun 	LEAVE();
6107*4882a593Smuzhiyun 	return ret;
6108*4882a593Smuzhiyun }
6109*4882a593Smuzhiyun /**
6110*4882a593Smuzhiyun  *  @brief  get channel load results
6111*4882a593Smuzhiyun  *
6112*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
6113*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
6114*4882a593Smuzhiyun  *
6115*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
6116*4882a593Smuzhiyun  */
wlan_misc_ioctl_ch_load_results(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)6117*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_ch_load_results(pmlan_adapter pmadapter,
6118*4882a593Smuzhiyun 					    mlan_ioctl_req *pioctl_req)
6119*4882a593Smuzhiyun {
6120*4882a593Smuzhiyun 	mlan_private *pmpriv = MNULL;
6121*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6122*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6123*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
6124*4882a593Smuzhiyun 
6125*4882a593Smuzhiyun 	ENTER();
6126*4882a593Smuzhiyun 	if (pioctl_req == MNULL)
6127*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
6128*4882a593Smuzhiyun 	pmpriv = pmadapter->priv[pioctl_req->bss_index];
6129*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6130*4882a593Smuzhiyun 	cmd_action = pioctl_req->action;
6131*4882a593Smuzhiyun 
6132*4882a593Smuzhiyun 	/* Send request to firmware */
6133*4882a593Smuzhiyun 	if (pmpriv->ch_load_param == 255) {
6134*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
6135*4882a593Smuzhiyun 	} else {
6136*4882a593Smuzhiyun 		misc->param.ch_load.ch_load_param = pmpriv->ch_load_param;
6137*4882a593Smuzhiyun 		misc->param.ch_load.noise = pmpriv->noise;
6138*4882a593Smuzhiyun 		misc->param.ch_load.rx_quality = pmpriv->rx_quality;
6139*4882a593Smuzhiyun 	}
6140*4882a593Smuzhiyun 
6141*4882a593Smuzhiyun 	LEAVE();
6142*4882a593Smuzhiyun 	return ret;
6143*4882a593Smuzhiyun }
6144*4882a593Smuzhiyun 
6145*4882a593Smuzhiyun /**
6146*4882a593Smuzhiyun  *  @brief  get channel load
6147*4882a593Smuzhiyun  *
6148*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
6149*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
6150*4882a593Smuzhiyun  *
6151*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
6152*4882a593Smuzhiyun  */
wlan_misc_ioctl_ch_load(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)6153*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_ch_load(pmlan_adapter pmadapter,
6154*4882a593Smuzhiyun 				    mlan_ioctl_req *pioctl_req)
6155*4882a593Smuzhiyun {
6156*4882a593Smuzhiyun 	mlan_private *pmpriv = MNULL;
6157*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6158*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6159*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
6160*4882a593Smuzhiyun 
6161*4882a593Smuzhiyun 	ENTER();
6162*4882a593Smuzhiyun 	if (pioctl_req == MNULL)
6163*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
6164*4882a593Smuzhiyun 	pmpriv = pmadapter->priv[pioctl_req->bss_index];
6165*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6166*4882a593Smuzhiyun 	cmd_action = pioctl_req->action;
6167*4882a593Smuzhiyun 
6168*4882a593Smuzhiyun 	/* Send request to firmware */
6169*4882a593Smuzhiyun 	pmpriv->ch_load_param = 255; /* Default value for identifying
6170*4882a593Smuzhiyun 					update/non-updated value*/
6171*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_GET_CH_LOAD, cmd_action, 0,
6172*4882a593Smuzhiyun 			       (t_void *)pioctl_req,
6173*4882a593Smuzhiyun 			       (t_void *)&misc->param.ch_load);
6174*4882a593Smuzhiyun 
6175*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6176*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6177*4882a593Smuzhiyun 
6178*4882a593Smuzhiyun 	LEAVE();
6179*4882a593Smuzhiyun 	return ret;
6180*4882a593Smuzhiyun }
6181*4882a593Smuzhiyun 
6182*4882a593Smuzhiyun /**
6183*4882a593Smuzhiyun  *  @brief  Get CHAN_TPRC setting
6184*4882a593Smuzhiyun  *
6185*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
6186*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
6187*4882a593Smuzhiyun  *
6188*4882a593Smuzhiyun  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
6189*4882a593Smuzhiyun  */
wlan_get_chan_trpc_cfg(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)6190*4882a593Smuzhiyun mlan_status wlan_get_chan_trpc_cfg(pmlan_adapter pmadapter,
6191*4882a593Smuzhiyun 				   mlan_ioctl_req *pioctl_req)
6192*4882a593Smuzhiyun {
6193*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
6194*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6195*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6196*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
6197*4882a593Smuzhiyun 
6198*4882a593Smuzhiyun 	ENTER();
6199*4882a593Smuzhiyun 
6200*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6201*4882a593Smuzhiyun 	cmd_action = HostCmd_ACT_GEN_GET;
6202*4882a593Smuzhiyun 
6203*4882a593Smuzhiyun 	/* Send request to firmware */
6204*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CHANNEL_TRPC_CONFIG, cmd_action,
6205*4882a593Smuzhiyun 			       0, (t_void *)pioctl_req,
6206*4882a593Smuzhiyun 			       (t_void *)&misc->param.trpc_cfg);
6207*4882a593Smuzhiyun 
6208*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6209*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6210*4882a593Smuzhiyun 
6211*4882a593Smuzhiyun 	LEAVE();
6212*4882a593Smuzhiyun 	return ret;
6213*4882a593Smuzhiyun }
6214*4882a593Smuzhiyun 
6215*4882a593Smuzhiyun /**
6216*4882a593Smuzhiyun  *  @brief Get non-global operating class
6217*4882a593Smuzhiyun  *
6218*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
6219*4882a593Smuzhiyun  *  @param pioctl_req   Pointer to the IOCTL request buffer
6220*4882a593Smuzhiyun  *
6221*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
6222*4882a593Smuzhiyun  */
wlan_misc_ioctl_oper_class(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)6223*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_oper_class(pmlan_adapter pmadapter,
6224*4882a593Smuzhiyun 				       mlan_ioctl_req *pioctl_req)
6225*4882a593Smuzhiyun {
6226*4882a593Smuzhiyun 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
6227*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
6228*4882a593Smuzhiyun 	t_u8 channel, bandwidth, oper_class = 0;
6229*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6230*4882a593Smuzhiyun 
6231*4882a593Smuzhiyun 	ENTER();
6232*4882a593Smuzhiyun 
6233*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6234*4882a593Smuzhiyun 	channel = misc->param.bw_chan_oper.channel;
6235*4882a593Smuzhiyun 	switch (misc->param.bw_chan_oper.bandwidth) {
6236*4882a593Smuzhiyun 	case 20:
6237*4882a593Smuzhiyun 		bandwidth = BW_20MHZ;
6238*4882a593Smuzhiyun 		break;
6239*4882a593Smuzhiyun 	case 40:
6240*4882a593Smuzhiyun 		bandwidth = BW_40MHZ;
6241*4882a593Smuzhiyun 		break;
6242*4882a593Smuzhiyun 	case 80:
6243*4882a593Smuzhiyun 		bandwidth = BW_80MHZ;
6244*4882a593Smuzhiyun 		break;
6245*4882a593Smuzhiyun 	default:
6246*4882a593Smuzhiyun 		bandwidth = BW_20MHZ;
6247*4882a593Smuzhiyun 		break;
6248*4882a593Smuzhiyun 	}
6249*4882a593Smuzhiyun 
6250*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_GET) {
6251*4882a593Smuzhiyun 		ret = wlan_get_curr_oper_class(pmpriv, channel, bandwidth,
6252*4882a593Smuzhiyun 					       &oper_class);
6253*4882a593Smuzhiyun 		misc->param.bw_chan_oper.oper_class = oper_class;
6254*4882a593Smuzhiyun 	} else {
6255*4882a593Smuzhiyun 		PRINTM(MERROR, "Unsupported cmd_action\n");
6256*4882a593Smuzhiyun 		LEAVE();
6257*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
6258*4882a593Smuzhiyun 	}
6259*4882a593Smuzhiyun 
6260*4882a593Smuzhiyun 	LEAVE();
6261*4882a593Smuzhiyun 	return ret;
6262*4882a593Smuzhiyun }
6263*4882a593Smuzhiyun 
6264*4882a593Smuzhiyun /**
6265*4882a593Smuzhiyun  *  @brief config dynamic bandwidth
6266*4882a593Smuzhiyun  *
6267*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
6268*4882a593Smuzhiyun  *  @param pioctl_req   Pointer to the IOCTL request buffer
6269*4882a593Smuzhiyun  *
6270*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
6271*4882a593Smuzhiyun  */
wlan_misc_ioctl_fw_dump_event(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)6272*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_fw_dump_event(pmlan_adapter pmadapter,
6273*4882a593Smuzhiyun 					  mlan_ioctl_req *pioctl_req)
6274*4882a593Smuzhiyun {
6275*4882a593Smuzhiyun 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
6276*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6277*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6278*4882a593Smuzhiyun 
6279*4882a593Smuzhiyun 	ENTER();
6280*4882a593Smuzhiyun 
6281*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
6282*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
6283*4882a593Smuzhiyun 	else if (pioctl_req->action == MLAN_ACT_GET)
6284*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
6285*4882a593Smuzhiyun 	else {
6286*4882a593Smuzhiyun 		PRINTM(MERROR, "Unsupported cmd_action\n");
6287*4882a593Smuzhiyun 		LEAVE();
6288*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
6289*4882a593Smuzhiyun 	}
6290*4882a593Smuzhiyun 
6291*4882a593Smuzhiyun 	/* Send request to firmware */
6292*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_FW_DUMP_EVENT, cmd_action, 0,
6293*4882a593Smuzhiyun 			       (t_void *)pioctl_req, MNULL);
6294*4882a593Smuzhiyun 
6295*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6296*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6297*4882a593Smuzhiyun 
6298*4882a593Smuzhiyun 	LEAVE();
6299*4882a593Smuzhiyun 	return ret;
6300*4882a593Smuzhiyun }
6301*4882a593Smuzhiyun 
6302*4882a593Smuzhiyun /**
6303*4882a593Smuzhiyun  *  @brief Set/Get the network monitor configuration.
6304*4882a593Smuzhiyun  *
6305*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
6306*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
6307*4882a593Smuzhiyun  *
6308*4882a593Smuzhiyun  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
6309*4882a593Smuzhiyun  */
wlan_misc_ioctl_net_monitor(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)6310*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_net_monitor(pmlan_adapter pmadapter,
6311*4882a593Smuzhiyun 					pmlan_ioctl_req pioctl_req)
6312*4882a593Smuzhiyun {
6313*4882a593Smuzhiyun 	mlan_private *pmpriv;
6314*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc;
6315*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6316*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6317*4882a593Smuzhiyun 
6318*4882a593Smuzhiyun 	ENTER();
6319*4882a593Smuzhiyun 
6320*4882a593Smuzhiyun 	if (!pioctl_req) {
6321*4882a593Smuzhiyun 		LEAVE();
6322*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
6323*4882a593Smuzhiyun 	}
6324*4882a593Smuzhiyun 	pmpriv = pmadapter->priv[pioctl_req->bss_index];
6325*4882a593Smuzhiyun 
6326*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6327*4882a593Smuzhiyun 
6328*4882a593Smuzhiyun 	if (misc->param.net_mon.enable_net_mon == CHANNEL_SPEC_SNIFFER_MODE) {
6329*4882a593Smuzhiyun 		/* Net monitor IOCTL not allowed in connected state */
6330*4882a593Smuzhiyun 		if (pmpriv->media_connected == MTRUE) {
6331*4882a593Smuzhiyun 			PRINTM(MERROR,
6332*4882a593Smuzhiyun 			       "IOCTL not allowed in connected state\n");
6333*4882a593Smuzhiyun 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
6334*4882a593Smuzhiyun 			LEAVE();
6335*4882a593Smuzhiyun 			return MLAN_STATUS_FAILURE;
6336*4882a593Smuzhiyun 		}
6337*4882a593Smuzhiyun 	}
6338*4882a593Smuzhiyun 
6339*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
6340*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
6341*4882a593Smuzhiyun 	else
6342*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
6343*4882a593Smuzhiyun 
6344*4882a593Smuzhiyun 	/* Send command to firmware */
6345*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_NET_MONITOR,
6346*4882a593Smuzhiyun 			       cmd_action, 0, (t_void *)pioctl_req,
6347*4882a593Smuzhiyun 			       &misc->param.net_mon);
6348*4882a593Smuzhiyun 
6349*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6350*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6351*4882a593Smuzhiyun 
6352*4882a593Smuzhiyun 	LEAVE();
6353*4882a593Smuzhiyun 	return ret;
6354*4882a593Smuzhiyun }
6355*4882a593Smuzhiyun 
6356*4882a593Smuzhiyun /**
6357*4882a593Smuzhiyun  *  @brief config boot sleep
6358*4882a593Smuzhiyun  *
6359*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
6360*4882a593Smuzhiyun  *  @param pioctl_req   Pointer to the IOCTL request buffer
6361*4882a593Smuzhiyun  *
6362*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
6363*4882a593Smuzhiyun  */
wlan_misc_bootsleep(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)6364*4882a593Smuzhiyun mlan_status wlan_misc_bootsleep(pmlan_adapter pmadapter,
6365*4882a593Smuzhiyun 				pmlan_ioctl_req pioctl_req)
6366*4882a593Smuzhiyun {
6367*4882a593Smuzhiyun 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
6368*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
6369*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6370*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6371*4882a593Smuzhiyun 
6372*4882a593Smuzhiyun 	ENTER();
6373*4882a593Smuzhiyun 
6374*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6375*4882a593Smuzhiyun 
6376*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
6377*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
6378*4882a593Smuzhiyun 	else if (pioctl_req->action == MLAN_ACT_GET)
6379*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
6380*4882a593Smuzhiyun 	else {
6381*4882a593Smuzhiyun 		PRINTM(MERROR, "Unsupported cmd_action 0x%x\n",
6382*4882a593Smuzhiyun 		       pioctl_req->action);
6383*4882a593Smuzhiyun 		LEAVE();
6384*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
6385*4882a593Smuzhiyun 	}
6386*4882a593Smuzhiyun 
6387*4882a593Smuzhiyun 	/* Send request to firmware */
6388*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_BOOT_SLEEP, cmd_action, 0,
6389*4882a593Smuzhiyun 			       (t_void *)pioctl_req, &misc->param.boot_sleep);
6390*4882a593Smuzhiyun 
6391*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6392*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6393*4882a593Smuzhiyun 
6394*4882a593Smuzhiyun 	LEAVE();
6395*4882a593Smuzhiyun 	return ret;
6396*4882a593Smuzhiyun }
6397*4882a593Smuzhiyun 
6398*4882a593Smuzhiyun /**
6399*4882a593Smuzhiyun  *  @brief Set/Get Infra/Ad-hoc band configuration
6400*4882a593Smuzhiyun  *
6401*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
6402*4882a593Smuzhiyun  *  @param pioctl_req   A pointer to ioctl request buffer
6403*4882a593Smuzhiyun  *
6404*4882a593Smuzhiyun  *  @return     MLAN_STATUS_SUCCESS --success, otherwise fail
6405*4882a593Smuzhiyun  */
wlan_radio_ioctl_band_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)6406*4882a593Smuzhiyun mlan_status wlan_radio_ioctl_band_cfg(pmlan_adapter pmadapter,
6407*4882a593Smuzhiyun 				      pmlan_ioctl_req pioctl_req)
6408*4882a593Smuzhiyun {
6409*4882a593Smuzhiyun 	t_u32 i, global_band = 0;
6410*4882a593Smuzhiyun 	t_u32 infra_band = 0;
6411*4882a593Smuzhiyun 	t_u32 adhoc_band = 0;
6412*4882a593Smuzhiyun 	t_u32 adhoc_channel = 0;
6413*4882a593Smuzhiyun 	mlan_ds_radio_cfg *radio_cfg = MNULL;
6414*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
6415*4882a593Smuzhiyun 
6416*4882a593Smuzhiyun 	ENTER();
6417*4882a593Smuzhiyun 
6418*4882a593Smuzhiyun 	radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
6419*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET) {
6420*4882a593Smuzhiyun 		infra_band = radio_cfg->param.band_cfg.config_bands;
6421*4882a593Smuzhiyun 		adhoc_band = radio_cfg->param.band_cfg.adhoc_start_band;
6422*4882a593Smuzhiyun 		adhoc_channel = radio_cfg->param.band_cfg.adhoc_channel;
6423*4882a593Smuzhiyun 
6424*4882a593Smuzhiyun 		/* SET Infra band */
6425*4882a593Smuzhiyun 		if ((infra_band | pmadapter->fw_bands) & ~pmadapter->fw_bands) {
6426*4882a593Smuzhiyun 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
6427*4882a593Smuzhiyun 			LEAVE();
6428*4882a593Smuzhiyun 			return MLAN_STATUS_FAILURE;
6429*4882a593Smuzhiyun 		}
6430*4882a593Smuzhiyun 
6431*4882a593Smuzhiyun 		/* SET Ad-hoc Band */
6432*4882a593Smuzhiyun 		if ((adhoc_band | pmadapter->fw_bands) & ~pmadapter->fw_bands) {
6433*4882a593Smuzhiyun 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
6434*4882a593Smuzhiyun 			LEAVE();
6435*4882a593Smuzhiyun 			return MLAN_STATUS_FAILURE;
6436*4882a593Smuzhiyun 		}
6437*4882a593Smuzhiyun 		if (!adhoc_band)
6438*4882a593Smuzhiyun 			adhoc_band = pmadapter->adhoc_start_band;
6439*4882a593Smuzhiyun 
6440*4882a593Smuzhiyun 		for (i = 0; i < pmadapter->priv_num; i++) {
6441*4882a593Smuzhiyun 			if (pmadapter->priv[i] &&
6442*4882a593Smuzhiyun 			    pmadapter->priv[i] != pmpriv &&
6443*4882a593Smuzhiyun 			    GET_BSS_ROLE(pmadapter->priv[i]) ==
6444*4882a593Smuzhiyun 				    MLAN_BSS_ROLE_STA)
6445*4882a593Smuzhiyun 				global_band |=
6446*4882a593Smuzhiyun 					(t_u32)pmadapter->priv[i]->config_bands;
6447*4882a593Smuzhiyun 		}
6448*4882a593Smuzhiyun 		global_band |= infra_band;
6449*4882a593Smuzhiyun 
6450*4882a593Smuzhiyun 		if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
6451*4882a593Smuzhiyun 					 global_band | adhoc_band)) {
6452*4882a593Smuzhiyun 			pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
6453*4882a593Smuzhiyun 			LEAVE();
6454*4882a593Smuzhiyun 			return MLAN_STATUS_FAILURE;
6455*4882a593Smuzhiyun 		}
6456*4882a593Smuzhiyun #ifdef STA_SUPPORT
6457*4882a593Smuzhiyun 		if (wlan_11d_set_universaltable(pmpriv,
6458*4882a593Smuzhiyun 						global_band | adhoc_band)) {
6459*4882a593Smuzhiyun 			pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
6460*4882a593Smuzhiyun 			LEAVE();
6461*4882a593Smuzhiyun 			return MLAN_STATUS_FAILURE;
6462*4882a593Smuzhiyun 		}
6463*4882a593Smuzhiyun #endif
6464*4882a593Smuzhiyun 		pmpriv->config_bands = infra_band;
6465*4882a593Smuzhiyun 		pmadapter->config_bands = global_band;
6466*4882a593Smuzhiyun 
6467*4882a593Smuzhiyun 		pmadapter->adhoc_start_band = adhoc_band;
6468*4882a593Smuzhiyun 		pmpriv->intf_state_11h.adhoc_auto_sel_chan = MFALSE;
6469*4882a593Smuzhiyun 
6470*4882a593Smuzhiyun #ifdef STA_SUPPORT
6471*4882a593Smuzhiyun 		/*
6472*4882a593Smuzhiyun 		 * If no adhoc_channel is supplied verify if the existing
6473*4882a593Smuzhiyun 		 * adhoc channel compiles with new adhoc_band
6474*4882a593Smuzhiyun 		 */
6475*4882a593Smuzhiyun 		if (!adhoc_channel) {
6476*4882a593Smuzhiyun 			if (!wlan_find_cfp_by_band_and_channel(
6477*4882a593Smuzhiyun 				    pmadapter, pmadapter->adhoc_start_band,
6478*4882a593Smuzhiyun 				    pmpriv->adhoc_channel)) {
6479*4882a593Smuzhiyun 				/* Pass back the default channel */
6480*4882a593Smuzhiyun 				radio_cfg->param.band_cfg.adhoc_channel =
6481*4882a593Smuzhiyun 					DEFAULT_AD_HOC_CHANNEL;
6482*4882a593Smuzhiyun 				if ((pmadapter->adhoc_start_band & BAND_A)) {
6483*4882a593Smuzhiyun 					radio_cfg->param.band_cfg.adhoc_channel =
6484*4882a593Smuzhiyun 						DEFAULT_AD_HOC_CHANNEL_A;
6485*4882a593Smuzhiyun 				}
6486*4882a593Smuzhiyun 			}
6487*4882a593Smuzhiyun 		} else {
6488*4882a593Smuzhiyun 			/* Return error if adhoc_band and adhoc_channel
6489*4882a593Smuzhiyun 			 * combination is invalid
6490*4882a593Smuzhiyun 			 */
6491*4882a593Smuzhiyun 			if (!wlan_find_cfp_by_band_and_channel(
6492*4882a593Smuzhiyun 				    pmadapter, pmadapter->adhoc_start_band,
6493*4882a593Smuzhiyun 				    (t_u16)adhoc_channel)) {
6494*4882a593Smuzhiyun 				pioctl_req->status_code =
6495*4882a593Smuzhiyun 					MLAN_ERROR_INVALID_PARAMETER;
6496*4882a593Smuzhiyun 				LEAVE();
6497*4882a593Smuzhiyun 				return MLAN_STATUS_FAILURE;
6498*4882a593Smuzhiyun 			}
6499*4882a593Smuzhiyun 			pmpriv->adhoc_channel = (t_u8)adhoc_channel;
6500*4882a593Smuzhiyun 		}
6501*4882a593Smuzhiyun 
6502*4882a593Smuzhiyun #endif
6503*4882a593Smuzhiyun 
6504*4882a593Smuzhiyun 	} else {
6505*4882a593Smuzhiyun 		/* Infra Bands   */
6506*4882a593Smuzhiyun 		radio_cfg->param.band_cfg.config_bands = pmpriv->config_bands;
6507*4882a593Smuzhiyun 		/* Adhoc Band    */
6508*4882a593Smuzhiyun 		radio_cfg->param.band_cfg.adhoc_start_band =
6509*4882a593Smuzhiyun 			pmadapter->adhoc_start_band;
6510*4882a593Smuzhiyun 		/* Adhoc Channel */
6511*4882a593Smuzhiyun 		radio_cfg->param.band_cfg.adhoc_channel = pmpriv->adhoc_channel;
6512*4882a593Smuzhiyun 		/* FW support Bands */
6513*4882a593Smuzhiyun 		radio_cfg->param.band_cfg.fw_bands = pmadapter->fw_bands;
6514*4882a593Smuzhiyun 		PRINTM(MINFO, "Global config band = %d\n",
6515*4882a593Smuzhiyun 		       pmadapter->config_bands);
6516*4882a593Smuzhiyun #ifdef STA_SUPPORT
6517*4882a593Smuzhiyun #endif
6518*4882a593Smuzhiyun 	}
6519*4882a593Smuzhiyun 
6520*4882a593Smuzhiyun 	LEAVE();
6521*4882a593Smuzhiyun 	return MLAN_STATUS_SUCCESS;
6522*4882a593Smuzhiyun }
6523*4882a593Smuzhiyun 
6524*4882a593Smuzhiyun /**
6525*4882a593Smuzhiyun  *  @brief Rx Abort Cfg
6526*4882a593Smuzhiyun  *
6527*4882a593Smuzhiyun  *  @param pmadapter   A pointer to mlan_adapter structure
6528*4882a593Smuzhiyun  *  @param pioctl_req  A pointer to ioctl request buffer
6529*4882a593Smuzhiyun  *
6530*4882a593Smuzhiyun  *  @return        MLAN_STATUS_PENDING --success, otherwise fail
6531*4882a593Smuzhiyun  */
wlan_misc_ioctl_rxabortcfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)6532*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_rxabortcfg(pmlan_adapter pmadapter,
6533*4882a593Smuzhiyun 				       pmlan_ioctl_req pioctl_req)
6534*4882a593Smuzhiyun {
6535*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
6536*4882a593Smuzhiyun 	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6537*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6538*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6539*4882a593Smuzhiyun 
6540*4882a593Smuzhiyun 	ENTER();
6541*4882a593Smuzhiyun 
6542*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
6543*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
6544*4882a593Smuzhiyun 	else
6545*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
6546*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RX_ABORT_CFG, cmd_action, 0,
6547*4882a593Smuzhiyun 			       (t_void *)pioctl_req,
6548*4882a593Smuzhiyun 			       &(pmisc->param.rx_abort_cfg));
6549*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6550*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6551*4882a593Smuzhiyun 
6552*4882a593Smuzhiyun 	LEAVE();
6553*4882a593Smuzhiyun 	return ret;
6554*4882a593Smuzhiyun }
6555*4882a593Smuzhiyun /**
6556*4882a593Smuzhiyun  *  @brief Rx Abort Cfg ext
6557*4882a593Smuzhiyun  *
6558*4882a593Smuzhiyun  *  @param pmadapter   A pointer to mlan_adapter structure
6559*4882a593Smuzhiyun  *  @param pioctl_req  A pointer to ioctl request buffer
6560*4882a593Smuzhiyun  *
6561*4882a593Smuzhiyun  *  @return        MLAN_STATUS_PENDING --success, otherwise fail
6562*4882a593Smuzhiyun  */
wlan_misc_ioctl_rxabortcfg_ext(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)6563*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_rxabortcfg_ext(pmlan_adapter pmadapter,
6564*4882a593Smuzhiyun 					   pmlan_ioctl_req pioctl_req)
6565*4882a593Smuzhiyun {
6566*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
6567*4882a593Smuzhiyun 	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6568*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6569*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6570*4882a593Smuzhiyun 
6571*4882a593Smuzhiyun 	ENTER();
6572*4882a593Smuzhiyun 
6573*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
6574*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
6575*4882a593Smuzhiyun 	else
6576*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
6577*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RX_ABORT_CFG_EXT, cmd_action,
6578*4882a593Smuzhiyun 			       0, (t_void *)pioctl_req,
6579*4882a593Smuzhiyun 			       &(pmisc->param.rx_abort_cfg_ext));
6580*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6581*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6582*4882a593Smuzhiyun 
6583*4882a593Smuzhiyun 	LEAVE();
6584*4882a593Smuzhiyun 	return ret;
6585*4882a593Smuzhiyun }
6586*4882a593Smuzhiyun 
6587*4882a593Smuzhiyun /**
6588*4882a593Smuzhiyun  *  @brief Dot11mc unassociated FTM CFG
6589*4882a593Smuzhiyun  *
6590*4882a593Smuzhiyun  *  @param pmadapter   A pointer to mlan_adapter structure
6591*4882a593Smuzhiyun  *  @param pioctl_req  A pointer to ioctl request buffer
6592*4882a593Smuzhiyun  *
6593*4882a593Smuzhiyun  *  @return        MLAN_STATUS_PENDING --success, otherwise fail
6594*4882a593Smuzhiyun  */
wlan_misc_ioctl_dot11mc_unassoc_ftm_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)6595*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_dot11mc_unassoc_ftm_cfg(pmlan_adapter pmadapter,
6596*4882a593Smuzhiyun 						    pmlan_ioctl_req pioctl_req)
6597*4882a593Smuzhiyun {
6598*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
6599*4882a593Smuzhiyun 	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6600*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6601*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6602*4882a593Smuzhiyun 
6603*4882a593Smuzhiyun 	ENTER();
6604*4882a593Smuzhiyun 
6605*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
6606*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
6607*4882a593Smuzhiyun 	else
6608*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
6609*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_DOT11MC_UNASSOC_FTM_CFG,
6610*4882a593Smuzhiyun 			       cmd_action, 0, (t_void *)pioctl_req,
6611*4882a593Smuzhiyun 			       &(pmisc->param.dot11mc_unassoc_ftm_cfg));
6612*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6613*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6614*4882a593Smuzhiyun 
6615*4882a593Smuzhiyun 	LEAVE();
6616*4882a593Smuzhiyun 	return ret;
6617*4882a593Smuzhiyun }
6618*4882a593Smuzhiyun 
6619*4882a593Smuzhiyun /**
6620*4882a593Smuzhiyun  *  @brief Tx ampdu protection mode
6621*4882a593Smuzhiyun  *
6622*4882a593Smuzhiyun  *  @param pmadapter   A pointer to mlan_adapter structure
6623*4882a593Smuzhiyun  *  @param pioctl_req  A pointer to ioctl request buffer
6624*4882a593Smuzhiyun  *
6625*4882a593Smuzhiyun  *  @return        MLAN_STATUS_PENDING --success, otherwise fail
6626*4882a593Smuzhiyun  */
wlan_misc_ioctl_tx_ampdu_prot_mode(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)6627*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_tx_ampdu_prot_mode(pmlan_adapter pmadapter,
6628*4882a593Smuzhiyun 					       pmlan_ioctl_req pioctl_req)
6629*4882a593Smuzhiyun {
6630*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
6631*4882a593Smuzhiyun 	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6632*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6633*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6634*4882a593Smuzhiyun 
6635*4882a593Smuzhiyun 	ENTER();
6636*4882a593Smuzhiyun 
6637*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
6638*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
6639*4882a593Smuzhiyun 	else
6640*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
6641*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TX_AMPDU_PROT_MODE,
6642*4882a593Smuzhiyun 			       cmd_action, 0, (t_void *)pioctl_req,
6643*4882a593Smuzhiyun 			       &(pmisc->param.tx_ampdu_prot_mode));
6644*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6645*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6646*4882a593Smuzhiyun 
6647*4882a593Smuzhiyun 	LEAVE();
6648*4882a593Smuzhiyun 	return ret;
6649*4882a593Smuzhiyun }
6650*4882a593Smuzhiyun 
6651*4882a593Smuzhiyun /**
6652*4882a593Smuzhiyun  *  @brief Rate adapt config
6653*4882a593Smuzhiyun  *
6654*4882a593Smuzhiyun  *  @param pmadapter   A pointer to mlan_adapter structure
6655*4882a593Smuzhiyun  *  @param pioctl_req  A pointer to ioctl request buffer
6656*4882a593Smuzhiyun  *
6657*4882a593Smuzhiyun  *  @return        MLAN_STATUS_PENDING --success, otherwise fail
6658*4882a593Smuzhiyun  */
wlan_misc_ioctl_rate_adapt_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)6659*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_rate_adapt_cfg(pmlan_adapter pmadapter,
6660*4882a593Smuzhiyun 					   pmlan_ioctl_req pioctl_req)
6661*4882a593Smuzhiyun {
6662*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
6663*4882a593Smuzhiyun 	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6664*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6665*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6666*4882a593Smuzhiyun 
6667*4882a593Smuzhiyun 	ENTER();
6668*4882a593Smuzhiyun 
6669*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
6670*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
6671*4882a593Smuzhiyun 	else
6672*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
6673*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RATE_ADAPT_CFG, cmd_action,
6674*4882a593Smuzhiyun 			       0, (t_void *)pioctl_req,
6675*4882a593Smuzhiyun 			       &(pmisc->param.rate_adapt_cfg));
6676*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6677*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6678*4882a593Smuzhiyun 
6679*4882a593Smuzhiyun 	LEAVE();
6680*4882a593Smuzhiyun 	return ret;
6681*4882a593Smuzhiyun }
6682*4882a593Smuzhiyun 
6683*4882a593Smuzhiyun /**
6684*4882a593Smuzhiyun  *  @brief CCK Desense config
6685*4882a593Smuzhiyun  *
6686*4882a593Smuzhiyun  *  @param pmadapter   A pointer to mlan_adapter structure
6687*4882a593Smuzhiyun  *  @param pioctl_req  A pointer to ioctl request buffer
6688*4882a593Smuzhiyun  *
6689*4882a593Smuzhiyun  *  @return        MLAN_STATUS_PENDING --success, otherwise fail
6690*4882a593Smuzhiyun  */
wlan_misc_ioctl_cck_desense_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)6691*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_cck_desense_cfg(pmlan_adapter pmadapter,
6692*4882a593Smuzhiyun 					    pmlan_ioctl_req pioctl_req)
6693*4882a593Smuzhiyun {
6694*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
6695*4882a593Smuzhiyun 	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6696*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6697*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6698*4882a593Smuzhiyun 
6699*4882a593Smuzhiyun 	ENTER();
6700*4882a593Smuzhiyun 
6701*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
6702*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
6703*4882a593Smuzhiyun 	else
6704*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
6705*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CCK_DESENSE_CFG, cmd_action,
6706*4882a593Smuzhiyun 			       0, (t_void *)pioctl_req,
6707*4882a593Smuzhiyun 			       &(pmisc->param.cck_desense_cfg));
6708*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6709*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6710*4882a593Smuzhiyun 
6711*4882a593Smuzhiyun 	LEAVE();
6712*4882a593Smuzhiyun 	return ret;
6713*4882a593Smuzhiyun }
6714*4882a593Smuzhiyun 
6715*4882a593Smuzhiyun /**
6716*4882a593Smuzhiyun  *  @brief config dynamic bandwidth
6717*4882a593Smuzhiyun  *
6718*4882a593Smuzhiyun  *  @param pmadapter    A pointer to mlan_adapter structure
6719*4882a593Smuzhiyun  *  @param pioctl_req   Pointer to the IOCTL request buffer
6720*4882a593Smuzhiyun  *
6721*4882a593Smuzhiyun  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
6722*4882a593Smuzhiyun  */
wlan_misc_ioctl_dyn_bw(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)6723*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_dyn_bw(pmlan_adapter pmadapter,
6724*4882a593Smuzhiyun 				   mlan_ioctl_req *pioctl_req)
6725*4882a593Smuzhiyun {
6726*4882a593Smuzhiyun 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
6727*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
6728*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6729*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6730*4882a593Smuzhiyun 
6731*4882a593Smuzhiyun 	ENTER();
6732*4882a593Smuzhiyun 
6733*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6734*4882a593Smuzhiyun 
6735*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
6736*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
6737*4882a593Smuzhiyun 	else if (pioctl_req->action == MLAN_ACT_GET)
6738*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
6739*4882a593Smuzhiyun 	else {
6740*4882a593Smuzhiyun 		PRINTM(MERROR, "Unsupported cmd_action\n");
6741*4882a593Smuzhiyun 		LEAVE();
6742*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
6743*4882a593Smuzhiyun 	}
6744*4882a593Smuzhiyun 
6745*4882a593Smuzhiyun 	/* Send request to firmware */
6746*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_DYN_BW, cmd_action, 0,
6747*4882a593Smuzhiyun 			       (t_void *)pioctl_req, &misc->param.dyn_bw);
6748*4882a593Smuzhiyun 
6749*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6750*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6751*4882a593Smuzhiyun 
6752*4882a593Smuzhiyun 	LEAVE();
6753*4882a593Smuzhiyun 	return ret;
6754*4882a593Smuzhiyun }
6755*4882a593Smuzhiyun 
6756*4882a593Smuzhiyun /**
6757*4882a593Smuzhiyun  *  @brief Set/Get low power mode configuration parameter
6758*4882a593Smuzhiyun  *
6759*4882a593Smuzhiyun  *  @param pmadapter	A pointer to mlan_adapter structure
6760*4882a593Smuzhiyun  *  @param pioctl_req	A pointer to ioctl request buffer
6761*4882a593Smuzhiyun  *
6762*4882a593Smuzhiyun  *  @return		MLAN_STATUS_SUCCESS --success
6763*4882a593Smuzhiyun  */
wlan_power_ioctl_set_get_lpm(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)6764*4882a593Smuzhiyun mlan_status wlan_power_ioctl_set_get_lpm(pmlan_adapter pmadapter,
6765*4882a593Smuzhiyun 					 pmlan_ioctl_req pioctl_req)
6766*4882a593Smuzhiyun {
6767*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6768*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
6769*4882a593Smuzhiyun 	mlan_ds_power_cfg *pm_cfg = MNULL;
6770*4882a593Smuzhiyun 	t_u16 cmd_action = 0, lpm = 0;
6771*4882a593Smuzhiyun 
6772*4882a593Smuzhiyun 	ENTER();
6773*4882a593Smuzhiyun 
6774*4882a593Smuzhiyun 	pm_cfg = (mlan_ds_power_cfg *)pioctl_req->pbuf;
6775*4882a593Smuzhiyun 	cmd_action = HostCmd_ACT_GEN_GET;
6776*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET) {
6777*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
6778*4882a593Smuzhiyun 		lpm = pm_cfg->param.lpm;
6779*4882a593Smuzhiyun 	}
6780*4882a593Smuzhiyun 
6781*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_LOW_POWER_MODE_CFG,
6782*4882a593Smuzhiyun 			       cmd_action, 0, (t_void *)pioctl_req, &lpm);
6783*4882a593Smuzhiyun 
6784*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6785*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6786*4882a593Smuzhiyun 
6787*4882a593Smuzhiyun 	LEAVE();
6788*4882a593Smuzhiyun 	return ret;
6789*4882a593Smuzhiyun }
6790*4882a593Smuzhiyun 
6791*4882a593Smuzhiyun /**
6792*4882a593Smuzhiyun  *  @brief RF Test Mode config
6793*4882a593Smuzhiyun  *
6794*4882a593Smuzhiyun  *  @param pmadapter   A pointer to mlan_adapter structure
6795*4882a593Smuzhiyun  *  @param pioctl_req  A pointer to ioctl request buffer
6796*4882a593Smuzhiyun  *
6797*4882a593Smuzhiyun  *  @return        MLAN_STATUS_PENDING --success, otherwise fail
6798*4882a593Smuzhiyun  */
wlan_misc_ioctl_rf_test_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)6799*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_rf_test_cfg(pmlan_adapter pmadapter,
6800*4882a593Smuzhiyun 					pmlan_ioctl_req pioctl_req)
6801*4882a593Smuzhiyun {
6802*4882a593Smuzhiyun 	mlan_private *pmpriv = MNULL;
6803*4882a593Smuzhiyun 	mlan_ds_misc_cfg *pmisc = MNULL;
6804*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_FAILURE;
6805*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6806*4882a593Smuzhiyun 
6807*4882a593Smuzhiyun 	ENTER();
6808*4882a593Smuzhiyun 
6809*4882a593Smuzhiyun 	if (!pioctl_req)
6810*4882a593Smuzhiyun 		goto done;
6811*4882a593Smuzhiyun 
6812*4882a593Smuzhiyun 	pmpriv = pmadapter->priv[pioctl_req->bss_index];
6813*4882a593Smuzhiyun 	pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6814*4882a593Smuzhiyun 
6815*4882a593Smuzhiyun 	switch (pmisc->sub_command) {
6816*4882a593Smuzhiyun 	case MLAN_OID_MISC_RF_TEST_GENERIC:
6817*4882a593Smuzhiyun 		if (pioctl_req->action == MLAN_ACT_SET)
6818*4882a593Smuzhiyun 			cmd_action = HostCmd_ACT_GEN_SET;
6819*4882a593Smuzhiyun 		else
6820*4882a593Smuzhiyun 			cmd_action = HostCmd_ACT_GEN_GET;
6821*4882a593Smuzhiyun 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MFG_COMMAND,
6822*4882a593Smuzhiyun 				       cmd_action, 0, (t_void *)pioctl_req,
6823*4882a593Smuzhiyun 				       &(pmisc->param.mfg_generic_cfg));
6824*4882a593Smuzhiyun 		break;
6825*4882a593Smuzhiyun 	case MLAN_OID_MISC_RF_TEST_TX_CONT:
6826*4882a593Smuzhiyun 		if (pioctl_req->action == MLAN_ACT_SET)
6827*4882a593Smuzhiyun 			cmd_action = HostCmd_ACT_GEN_SET;
6828*4882a593Smuzhiyun 		else {
6829*4882a593Smuzhiyun 			PRINTM(MERROR, "Unsupported cmd_action\n");
6830*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
6831*4882a593Smuzhiyun 			goto done;
6832*4882a593Smuzhiyun 		}
6833*4882a593Smuzhiyun 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MFG_COMMAND,
6834*4882a593Smuzhiyun 				       cmd_action, 0, (t_void *)pioctl_req,
6835*4882a593Smuzhiyun 				       &(pmisc->param.mfg_tx_cont));
6836*4882a593Smuzhiyun 		break;
6837*4882a593Smuzhiyun 	case MLAN_OID_MISC_RF_TEST_TX_FRAME:
6838*4882a593Smuzhiyun 		if (pioctl_req->action == MLAN_ACT_SET)
6839*4882a593Smuzhiyun 			cmd_action = HostCmd_ACT_GEN_SET;
6840*4882a593Smuzhiyun 		else {
6841*4882a593Smuzhiyun 			PRINTM(MERROR, "Unsupported cmd_action\n");
6842*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
6843*4882a593Smuzhiyun 			goto done;
6844*4882a593Smuzhiyun 		}
6845*4882a593Smuzhiyun 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MFG_COMMAND,
6846*4882a593Smuzhiyun 				       cmd_action, 0, (t_void *)pioctl_req,
6847*4882a593Smuzhiyun 				       &(pmisc->param.mfg_tx_frame2));
6848*4882a593Smuzhiyun 		break;
6849*4882a593Smuzhiyun 	case MLAN_OID_MISC_RF_TEST_HE_POWER:
6850*4882a593Smuzhiyun 		if (pioctl_req->action == MLAN_ACT_SET)
6851*4882a593Smuzhiyun 			cmd_action = HostCmd_ACT_GEN_SET;
6852*4882a593Smuzhiyun 		else {
6853*4882a593Smuzhiyun 			PRINTM(MERROR, "Unsupported cmd_action\n");
6854*4882a593Smuzhiyun 			ret = MLAN_STATUS_FAILURE;
6855*4882a593Smuzhiyun 			goto done;
6856*4882a593Smuzhiyun 		}
6857*4882a593Smuzhiyun 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MFG_COMMAND,
6858*4882a593Smuzhiyun 				       cmd_action, 0, (t_void *)pioctl_req,
6859*4882a593Smuzhiyun 				       &(pmisc->param.mfg_he_power));
6860*4882a593Smuzhiyun 		break;
6861*4882a593Smuzhiyun 	}
6862*4882a593Smuzhiyun 
6863*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6864*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6865*4882a593Smuzhiyun done:
6866*4882a593Smuzhiyun 	LEAVE();
6867*4882a593Smuzhiyun 	return ret;
6868*4882a593Smuzhiyun }
6869*4882a593Smuzhiyun 
6870*4882a593Smuzhiyun /**
6871*4882a593Smuzhiyun  *  @brief Range ext mode config
6872*4882a593Smuzhiyun  *
6873*4882a593Smuzhiyun  *  @param pmadapter   A pointer to mlan_adapter structure
6874*4882a593Smuzhiyun  *  @param pioctl_req  A pointer to ioctl request buffer
6875*4882a593Smuzhiyun  *
6876*4882a593Smuzhiyun  *  @return        MLAN_STATUS_PENDING --success, otherwise fail
6877*4882a593Smuzhiyun  */
wlan_misc_ioctl_range_ext(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)6878*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_range_ext(pmlan_adapter pmadapter,
6879*4882a593Smuzhiyun 				      pmlan_ioctl_req pioctl_req)
6880*4882a593Smuzhiyun {
6881*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
6882*4882a593Smuzhiyun 	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6883*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6884*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6885*4882a593Smuzhiyun 
6886*4882a593Smuzhiyun 	ENTER();
6887*4882a593Smuzhiyun 
6888*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
6889*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
6890*4882a593Smuzhiyun 	else
6891*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
6892*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RANGE_EXT, cmd_action, 0,
6893*4882a593Smuzhiyun 			       (t_void *)pioctl_req,
6894*4882a593Smuzhiyun 			       &(pmisc->param.range_ext_mode));
6895*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6896*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6897*4882a593Smuzhiyun 
6898*4882a593Smuzhiyun 	LEAVE();
6899*4882a593Smuzhiyun 	return ret;
6900*4882a593Smuzhiyun }
6901*4882a593Smuzhiyun 
6902*4882a593Smuzhiyun #ifdef UAP_SUPPORT
6903*4882a593Smuzhiyun /**
6904*4882a593Smuzhiyun  *  @brief set wacp mode
6905*4882a593Smuzhiyun  *
6906*4882a593Smuzhiyun  *  @param pmadapter   A pointer to mlan_adapter structure
6907*4882a593Smuzhiyun  *  @param pioctl_req  A pointer to ioctl request buffer
6908*4882a593Smuzhiyun  *
6909*4882a593Smuzhiyun  *  @return            MLAN_STATUS_PENDING --success, otherwise fail
6910*4882a593Smuzhiyun  */
wlan_misc_ioctl_wacp_mode(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)6911*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_wacp_mode(IN pmlan_adapter pmadapter,
6912*4882a593Smuzhiyun 				      IN pmlan_ioctl_req pioctl_req)
6913*4882a593Smuzhiyun {
6914*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6915*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
6916*4882a593Smuzhiyun 	mlan_ds_misc_cfg *misc = MNULL;
6917*4882a593Smuzhiyun 	t_u16 cmd_action;
6918*4882a593Smuzhiyun 
6919*4882a593Smuzhiyun 	ENTER();
6920*4882a593Smuzhiyun 
6921*4882a593Smuzhiyun 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
6922*4882a593Smuzhiyun 
6923*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_SET)
6924*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_SET;
6925*4882a593Smuzhiyun 	else
6926*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
6927*4882a593Smuzhiyun 
6928*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action,
6929*4882a593Smuzhiyun 			       0, (t_void *)pioctl_req,
6930*4882a593Smuzhiyun 			       (t_void *)&misc->param.wacp_mode);
6931*4882a593Smuzhiyun 
6932*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6933*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6934*4882a593Smuzhiyun 
6935*4882a593Smuzhiyun 	LEAVE();
6936*4882a593Smuzhiyun 	return ret;
6937*4882a593Smuzhiyun }
6938*4882a593Smuzhiyun #endif
6939*4882a593Smuzhiyun 
wlan_misc_ioctl_get_sensor_temp(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)6940*4882a593Smuzhiyun mlan_status wlan_misc_ioctl_get_sensor_temp(pmlan_adapter pmadapter,
6941*4882a593Smuzhiyun 					    pmlan_ioctl_req pioctl_req)
6942*4882a593Smuzhiyun {
6943*4882a593Smuzhiyun 	mlan_status ret = MLAN_STATUS_SUCCESS;
6944*4882a593Smuzhiyun 	t_u16 cmd_action = 0;
6945*4882a593Smuzhiyun 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
6946*4882a593Smuzhiyun 
6947*4882a593Smuzhiyun 	ENTER();
6948*4882a593Smuzhiyun 
6949*4882a593Smuzhiyun 	if (pioctl_req->action == MLAN_ACT_GET)
6950*4882a593Smuzhiyun 		cmd_action = HostCmd_ACT_GEN_GET;
6951*4882a593Smuzhiyun 	else {
6952*4882a593Smuzhiyun 		PRINTM(MERROR, " Sensor temp only support get operation \n");
6953*4882a593Smuzhiyun 		LEAVE();
6954*4882a593Smuzhiyun 		return MLAN_STATUS_FAILURE;
6955*4882a593Smuzhiyun 	}
6956*4882a593Smuzhiyun 
6957*4882a593Smuzhiyun 	/* Send request to firmware */
6958*4882a593Smuzhiyun 	ret = wlan_prepare_cmd(pmpriv, HostCmd_DS_GET_SENSOR_TEMP, cmd_action,
6959*4882a593Smuzhiyun 			       0, (t_void *)pioctl_req, MNULL);
6960*4882a593Smuzhiyun 
6961*4882a593Smuzhiyun 	if (ret == MLAN_STATUS_SUCCESS)
6962*4882a593Smuzhiyun 		ret = MLAN_STATUS_PENDING;
6963*4882a593Smuzhiyun 
6964*4882a593Smuzhiyun 	LEAVE();
6965*4882a593Smuzhiyun 	return ret;
6966*4882a593Smuzhiyun }
6967