xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlan/mlan_sta_ioctl.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /** @file mlan_sta_ioctl.c
2  *
3  *  @brief This file contains the functions for station ioctl.
4  *
5  *
6  *  Copyright 2008-2022 NXP
7  *
8  *  This software file (the File) is distributed by NXP
9  *  under the terms of the GNU General Public License Version 2, June 1991
10  *  (the License).  You may use, redistribute and/or modify the File in
11  *  accordance with the terms and conditions of the License, a copy of which
12  *  is available by writing to the Free Software Foundation, Inc.,
13  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14  *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15  *
16  *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17  *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18  *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
19  *  this warranty disclaimer.
20  *
21  */
22 
23 /******************************************************
24 Change log:
25     10/21/2008: initial version
26 ******************************************************/
27 
28 #include "mlan.h"
29 #include "mlan_join.h"
30 #include "mlan_util.h"
31 #include "mlan_fw.h"
32 #include "mlan_main.h"
33 #include "mlan_wmm.h"
34 #include "mlan_11n.h"
35 #include "mlan_11ac.h"
36 #include "mlan_11ax.h"
37 #include "mlan_11h.h"
38 #ifdef DRV_EMBEDDED_SUPPLICANT
39 #include "authenticator_api.h"
40 #endif
41 
42 /********************************************************
43 			Local Variables
44 ********************************************************/
45 
46 /********************************************************
47 			Global Variables
48 ********************************************************/
49 
50 /********************************************************
51 			Local Functions
52 ********************************************************/
53 
54 /**
55  *  @brief Get signal information
56  *
57  *  @param pmadapter	A pointer to mlan_adapter structure
58  *  @param pioctl_req	A pointer to ioctl request buffer
59  *
60  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
61  */
wlan_get_info_signal(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)62 static mlan_status wlan_get_info_signal(pmlan_adapter pmadapter,
63 					pmlan_ioctl_req pioctl_req)
64 {
65 	pmlan_private pmpriv = MNULL;
66 	mlan_status ret = MLAN_STATUS_SUCCESS;
67 
68 	ENTER();
69 
70 	if (pioctl_req != MNULL) {
71 		pmpriv = pmadapter->priv[pioctl_req->bss_index];
72 	} else {
73 		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
74 		ret = MLAN_STATUS_FAILURE;
75 		goto exit;
76 	}
77 
78 	/* Check information buffer length of MLAN IOCTL */
79 	if (pioctl_req->buf_len < sizeof(mlan_ds_get_signal)) {
80 		PRINTM(MWARN,
81 		       "MLAN IOCTL information buffer length is too short.\n");
82 		pioctl_req->data_read_written = 0;
83 		pioctl_req->buf_len_needed = sizeof(mlan_ds_get_signal);
84 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
85 		ret = MLAN_STATUS_RESOURCE;
86 		goto exit;
87 	}
88 
89 	/* Signal info can be obtained only if connected */
90 	if (pmpriv->media_connected == MFALSE) {
91 		PRINTM(MINFO, "Can not get signal in disconnected state\n");
92 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
93 		ret = MLAN_STATUS_FAILURE;
94 		goto exit;
95 	}
96 
97 	/* Send request to firmware */
98 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RSSI_INFO,
99 			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
100 			       MNULL);
101 
102 	if (ret == MLAN_STATUS_SUCCESS)
103 		ret = MLAN_STATUS_PENDING;
104 
105 exit:
106 	LEAVE();
107 	return ret;
108 }
109 
110 /**
111  *  @brief Get signal information
112  *
113  *  @param pmadapter	A pointer to mlan_adapter structure
114  *  @param pioctl_req	A pointer to ioctl request buffer
115  *
116  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
117  */
wlan_get_info_signal_ext(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)118 static mlan_status wlan_get_info_signal_ext(pmlan_adapter pmadapter,
119 					    pmlan_ioctl_req pioctl_req)
120 {
121 	pmlan_private pmpriv = MNULL;
122 	mlan_status ret = MLAN_STATUS_SUCCESS;
123 	mlan_ds_get_info *info = MNULL;
124 
125 	ENTER();
126 
127 	if (pioctl_req != MNULL) {
128 		pmpriv = pmadapter->priv[pioctl_req->bss_index];
129 	} else {
130 		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
131 		ret = MLAN_STATUS_FAILURE;
132 		goto exit;
133 	}
134 	info = (mlan_ds_get_info *)pioctl_req->pbuf;
135 
136 	/* Check information buffer length of MLAN IOCTL */
137 	if (pioctl_req->buf_len < sizeof(mlan_ds_get_info)) {
138 		PRINTM(MWARN,
139 		       "MLAN IOCTL information buffer length is too short.\n");
140 		pioctl_req->data_read_written = 0;
141 		pioctl_req->buf_len_needed = sizeof(mlan_ds_get_info);
142 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
143 		ret = MLAN_STATUS_RESOURCE;
144 		goto exit;
145 	}
146 
147 	/* Send request to firmware */
148 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RSSI_INFO_EXT,
149 			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
150 			       (t_void *)info);
151 
152 	if (ret == MLAN_STATUS_SUCCESS)
153 		ret = MLAN_STATUS_PENDING;
154 
155 exit:
156 	LEAVE();
157 	return ret;
158 }
159 
160 /**
161  *  @brief Get statistics information
162  *
163  *  @param pmadapter	A pointer to mlan_adapter structure
164  *  @param pioctl_req	A pointer to ioctl request buffer
165  *
166  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
167  */
wlan_get_info_stats(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)168 static mlan_status wlan_get_info_stats(pmlan_adapter pmadapter,
169 				       pmlan_ioctl_req pioctl_req)
170 {
171 	pmlan_private pmpriv = MNULL;
172 	mlan_status ret = MLAN_STATUS_SUCCESS;
173 
174 	ENTER();
175 
176 	if (pioctl_req != MNULL) {
177 		pmpriv = pmadapter->priv[pioctl_req->bss_index];
178 	} else {
179 		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
180 		ret = MLAN_STATUS_FAILURE;
181 		goto exit;
182 	}
183 
184 	/* Check information buffer length of MLAN IOCTL */
185 	if (pioctl_req->buf_len < sizeof(mlan_ds_get_stats)) {
186 		PRINTM(MWARN,
187 		       "MLAN IOCTL information buffer length is too short.\n");
188 		pioctl_req->data_read_written = 0;
189 		pioctl_req->buf_len_needed = sizeof(mlan_ds_get_stats);
190 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
191 		ret = MLAN_STATUS_RESOURCE;
192 		goto exit;
193 	}
194 
195 	/* Send request to firmware */
196 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_GET_LOG,
197 			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
198 			       MNULL);
199 
200 	if (ret == MLAN_STATUS_SUCCESS)
201 		ret = MLAN_STATUS_PENDING;
202 
203 exit:
204 	LEAVE();
205 	return ret;
206 }
207 
208 /**
209  *  @brief Get sta channel information
210  *
211  *  @param pmadapter	A pointer to mlan_adapter structure
212  *  @param pioctl_req	A pointer to ioctl request buffer
213  *
214  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
215  */
wlan_bss_ioctl_get_chan_info(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)216 static mlan_status wlan_bss_ioctl_get_chan_info(pmlan_adapter pmadapter,
217 						pmlan_ioctl_req pioctl_req)
218 {
219 	pmlan_private pmpriv = MNULL;
220 	mlan_status ret = MLAN_STATUS_SUCCESS;
221 
222 	ENTER();
223 
224 	if (pioctl_req != MNULL) {
225 		pmpriv = pmadapter->priv[pioctl_req->bss_index];
226 	} else {
227 		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
228 		ret = MLAN_STATUS_FAILURE;
229 		goto exit;
230 	}
231 
232 	/* Check information buffer length of MLAN IOCTL */
233 	if (pioctl_req->buf_len < sizeof(chan_band_info)) {
234 		PRINTM(MWARN,
235 		       "MLAN IOCTL information buffer length is too short.\n");
236 		pioctl_req->data_read_written = 0;
237 		pioctl_req->buf_len_needed = sizeof(chan_band_info);
238 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
239 		ret = MLAN_STATUS_RESOURCE;
240 		goto exit;
241 	}
242 
243 	/* Send request to firmware */
244 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_STA_CONFIGURE,
245 			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
246 			       MNULL);
247 
248 	if (ret == MLAN_STATUS_SUCCESS)
249 		ret = MLAN_STATUS_PENDING;
250 
251 exit:
252 	LEAVE();
253 	return ret;
254 }
255 
256 /**
257  *  @brief Get BSS information
258  *
259  *  @param pmadapter	A pointer to mlan_adapter structure
260  *  @param pioctl_req	A pointer to ioctl request buffer
261  *
262  *  @return		MLAN_STATUS_SUCCESS --success
263  */
wlan_get_info_bss_info(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)264 static mlan_status wlan_get_info_bss_info(pmlan_adapter pmadapter,
265 					  pmlan_ioctl_req pioctl_req)
266 {
267 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
268 	mlan_status ret = MLAN_STATUS_SUCCESS;
269 	mlan_ds_get_info *info;
270 	BSSDescriptor_t *pbss_desc;
271 	t_s32 tbl_idx = 0;
272 
273 	ENTER();
274 
275 	/* Get current BSS info */
276 	pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
277 	info = (mlan_ds_get_info *)pioctl_req->pbuf;
278 
279 	/* BSS mode */
280 	info->param.bss_info.bss_mode = pmpriv->bss_mode;
281 
282 	/* SSID */
283 	memcpy_ext(pmadapter, &info->param.bss_info.ssid, &pbss_desc->ssid,
284 		   sizeof(mlan_802_11_ssid), sizeof(mlan_802_11_ssid));
285 
286 	/* BSSID */
287 	memcpy_ext(pmadapter, &info->param.bss_info.bssid,
288 		   &pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH,
289 		   MLAN_MAC_ADDR_LENGTH);
290 
291 	/* Channel */
292 	info->param.bss_info.bss_chan = pbss_desc->channel;
293 
294 	/* Beacon interval */
295 	info->param.bss_info.beacon_interval = pbss_desc->beacon_period;
296 
297 	/* Band */
298 	info->param.bss_info.bss_band = pbss_desc->bss_band;
299 
300 	/* Region code */
301 	info->param.bss_info.region_code = pmadapter->region_code;
302 
303 	/* Scan table index if connected */
304 	info->param.bss_info.scan_table_idx = 0;
305 	info->param.bss_info.scan_block = pmadapter->scan_block;
306 	if (pmpriv->media_connected == MTRUE) {
307 		tbl_idx = wlan_find_ssid_in_list(pmpriv, &pbss_desc->ssid,
308 						 pbss_desc->mac_address,
309 						 pmpriv->bss_mode);
310 		if (tbl_idx >= 0)
311 			info->param.bss_info.scan_table_idx = tbl_idx;
312 	}
313 
314 	/* Connection status */
315 	info->param.bss_info.media_connected = pmpriv->media_connected;
316 
317 	/* Radio status */
318 	info->param.bss_info.radio_on = pmadapter->radio_on;
319 
320 	/* Tx power information */
321 	info->param.bss_info.max_power_level = pmpriv->max_tx_power_level;
322 	info->param.bss_info.min_power_level = pmpriv->min_tx_power_level;
323 
324 	/* AdHoc state */
325 	info->param.bss_info.adhoc_state = pmpriv->adhoc_state;
326 
327 	/* Last beacon NF */
328 	info->param.bss_info.bcn_nf_last = pmpriv->bcn_nf_last;
329 
330 	/* wep status */
331 	if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled)
332 		info->param.bss_info.wep_status = MTRUE;
333 	else
334 		info->param.bss_info.wep_status = MFALSE;
335 
336 	info->param.bss_info.is_hs_configured = pmadapter->is_hs_configured;
337 	info->param.bss_info.is_deep_sleep = pmadapter->is_deep_sleep;
338 
339 	/* Capability Info */
340 	info->param.bss_info.capability_info = 0;
341 	memcpy_ext(pmadapter, &info->param.bss_info.capability_info,
342 		   &pbss_desc->cap_info,
343 		   sizeof(info->param.bss_info.capability_info),
344 		   sizeof(info->param.bss_info.capability_info));
345 
346 	memset(pmadapter, &info->param.bss_info.ext_cap, 0, sizeof(ExtCap_t));
347 	if (pbss_desc->pext_cap) {
348 		memcpy_ext(pmadapter, &info->param.bss_info.ext_cap,
349 			   (t_u8 *)pbss_desc->pext_cap +
350 				   sizeof(IEEEtypes_Header_t),
351 			   pbss_desc->pext_cap->ieee_hdr.len,
352 			   sizeof(info->param.bss_info.ext_cap));
353 	}
354 
355 	/* Listen Interval */
356 	info->param.bss_info.listen_interval = pmpriv->listen_interval;
357 
358 	/* Association ID */
359 	info->param.bss_info.assoc_id =
360 		(t_u16)((IEEEtypes_AssocRsp_t *)pmpriv->assoc_rsp_buf)->a_id;
361 
362 	/* AP/Peer supported rates */
363 	memset(pmadapter, info->param.bss_info.peer_supp_rates, 0,
364 	       sizeof(info->param.bss_info.peer_supp_rates));
365 	memcpy_ext(pmadapter, info->param.bss_info.peer_supp_rates,
366 		   pbss_desc->supported_rates,
367 		   sizeof(pbss_desc->supported_rates),
368 		   sizeof(info->param.bss_info.peer_supp_rates));
369 	if (pbss_desc->pmd_ie) {
370 		info->param.bss_info.mdid = pbss_desc->pmd_ie->mdid;
371 		info->param.bss_info.ft_cap = pbss_desc->pmd_ie->ft_cap;
372 	}
373 	pioctl_req->data_read_written =
374 		sizeof(mlan_bss_info) + MLAN_SUB_COMMAND_SIZE;
375 
376 	LEAVE();
377 	return ret;
378 }
379 
380 /**
381  *  @brief Get information handler
382  *
383  *  @param pmadapter	A pointer to mlan_adapter structure
384  *  @param pioctl_req	A pointer to ioctl request buffer
385  *
386  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
387  */
wlan_get_info_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)388 static mlan_status wlan_get_info_ioctl(pmlan_adapter pmadapter,
389 				       pmlan_ioctl_req pioctl_req)
390 {
391 	mlan_status status = MLAN_STATUS_SUCCESS;
392 	mlan_ds_get_info *pget_info = MNULL;
393 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
394 
395 	ENTER();
396 
397 	pget_info = (mlan_ds_get_info *)pioctl_req->pbuf;
398 
399 	switch (pget_info->sub_command) {
400 	case MLAN_OID_GET_STATS:
401 		status = wlan_get_info_stats(pmadapter, pioctl_req);
402 		break;
403 	case MLAN_OID_GET_SIGNAL:
404 		status = wlan_get_info_signal(pmadapter, pioctl_req);
405 		break;
406 	case MLAN_OID_GET_SIGNAL_EXT:
407 		status = wlan_get_info_signal_ext(pmadapter, pioctl_req);
408 		break;
409 	case MLAN_OID_GET_FW_INFO:
410 		pioctl_req->data_read_written =
411 			sizeof(mlan_fw_info) + MLAN_SUB_COMMAND_SIZE;
412 		pget_info->param.fw_info.fw_ver = pmadapter->fw_release_number;
413 		pget_info->param.fw_info.hotfix_version =
414 			pmadapter->fw_hotfix_ver;
415 		pget_info->param.fw_info.tx_buf_size = pmadapter->tx_buf_size;
416 
417 		memcpy_ext(pmadapter, &pget_info->param.fw_info.mac_addr,
418 			   pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH,
419 			   MLAN_MAC_ADDR_LENGTH);
420 		pget_info->param.fw_info.fw_bands = pmadapter->fw_bands;
421 		pget_info->param.fw_info.region_code = pmadapter->region_code;
422 		if (pmadapter->otp_region && pmadapter->otp_region->force_reg)
423 			pget_info->param.fw_info.force_reg = MTRUE;
424 		else
425 			pget_info->param.fw_info.force_reg = MFALSE;
426 		pget_info->param.fw_info.ecsa_enable = pmadapter->ecsa_enable;
427 		pget_info->param.fw_info.getlog_enable =
428 			pmadapter->getlog_enable;
429 		pget_info->param.fw_info.hw_dev_mcs_support =
430 			pmadapter->hw_dev_mcs_support;
431 		pget_info->param.fw_info.hw_dot_11n_dev_cap =
432 			pmadapter->hw_dot_11n_dev_cap;
433 		pget_info->param.fw_info.usr_dev_mcs_support =
434 			pmpriv->usr_dev_mcs_support;
435 		if (IS_FW_SUPPORT_NO_80MHZ(pmadapter))
436 			pget_info->param.fw_info.prohibit_80mhz = MTRUE;
437 		else
438 			pget_info->param.fw_info.prohibit_80mhz = MFALSE;
439 		pget_info->param.fw_info.hw_dot_11ac_mcs_support =
440 			pmadapter->hw_dot_11ac_mcs_support;
441 		pget_info->param.fw_info.hw_dot_11ac_dev_cap =
442 			pmadapter->hw_dot_11ac_dev_cap;
443 		pget_info->param.fw_info.usr_dot_11ac_dev_cap_bg =
444 			pmpriv->usr_dot_11ac_dev_cap_bg;
445 		pget_info->param.fw_info.usr_dot_11ac_mcs_support =
446 			pmpriv->usr_dot_11ac_mcs_support;
447 		pget_info->param.fw_info.usr_dot_11ac_dev_cap_a =
448 			pmpriv->usr_dot_11ac_dev_cap_a;
449 		pget_info->param.fw_info.uuid_lo = pmadapter->uuid_lo;
450 		pget_info->param.fw_info.uuid_hi = pmadapter->uuid_hi;
451 		pget_info->param.fw_info.hw_hecap_len = pmadapter->hw_hecap_len;
452 		pget_info->param.fw_info.hw_2g_hecap_len =
453 			pmadapter->hw_2g_hecap_len;
454 		memcpy_ext(pmadapter, pget_info->param.fw_info.hw_he_cap,
455 			   pmadapter->hw_he_cap, pmadapter->hw_hecap_len,
456 			   sizeof(pget_info->param.fw_info.hw_he_cap));
457 		memcpy_ext(pmadapter, pget_info->param.fw_info.hw_2g_he_cap,
458 			   pmadapter->hw_2g_he_cap, pmadapter->hw_2g_hecap_len,
459 			   sizeof(pget_info->param.fw_info.hw_2g_he_cap));
460 		pget_info->param.fw_info.fw_supplicant_support =
461 			IS_FW_SUPPORT_SUPPLICANT(pmadapter) ? 0x01 : 0x00;
462 		pget_info->param.fw_info.antinfo = pmadapter->antinfo;
463 		pget_info->param.fw_info.max_ap_assoc_sta =
464 			pmadapter->max_sta_conn;
465 		pget_info->param.fw_info.fw_roaming_support =
466 			(pmadapter->fw_cap_info & FW_ROAMING_SUPPORT) ? 0x01 :
467 									0x00;
468 		pget_info->param.fw_info.fw_beacon_prot =
469 			IS_FW_SUPPORT_BEACON_PROT(pmadapter) ? 0x01 : 0x00;
470 		break;
471 	case MLAN_OID_GET_BSS_INFO:
472 		status = wlan_get_info_bss_info(pmadapter, pioctl_req);
473 		break;
474 	case MLAN_OID_GET_DEBUG_INFO:
475 		status = wlan_get_info_debug_info(pmadapter, pioctl_req);
476 		break;
477 	case MLAN_OID_GET_VER_EXT:
478 		status = wlan_get_info_ver_ext(pmadapter, pioctl_req);
479 		break;
480 	case MLAN_OID_LINK_STATS:
481 		status = wlan_ioctl_link_statistic(pmpriv, pioctl_req);
482 		break;
483 	default:
484 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
485 		status = MLAN_STATUS_FAILURE;
486 		break;
487 	}
488 
489 	LEAVE();
490 	return status;
491 }
492 
493 /**
494  *  @brief Set/Get SNMP MIB handler
495  *
496  *  @param pmadapter	A pointer to mlan_adapter structure
497  *  @param pioctl_req	A pointer to ioctl request buffer
498  *
499  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
500  */
wlan_snmp_mib_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)501 static mlan_status wlan_snmp_mib_ioctl(pmlan_adapter pmadapter,
502 				       pmlan_ioctl_req pioctl_req)
503 {
504 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
505 	mlan_status ret = MLAN_STATUS_SUCCESS;
506 	t_u16 cmd_action = 0;
507 	t_u16 cmd_oid = 0;
508 	mlan_ds_snmp_mib *mib = MNULL;
509 	t_u32 value = 0;
510 
511 	ENTER();
512 
513 	if (pioctl_req->buf_len < sizeof(mlan_ds_snmp_mib)) {
514 		PRINTM(MWARN,
515 		       "MLAN IOCTL information buffer length is too short.\n");
516 		pioctl_req->data_read_written = 0;
517 		pioctl_req->buf_len_needed = sizeof(mlan_ds_snmp_mib);
518 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
519 		ret = MLAN_STATUS_RESOURCE;
520 		goto exit;
521 	}
522 
523 	mib = (mlan_ds_snmp_mib *)pioctl_req->pbuf;
524 	if (pioctl_req->action == MLAN_ACT_SET)
525 		cmd_action = HostCmd_ACT_GEN_SET;
526 	else
527 		cmd_action = HostCmd_ACT_GEN_GET;
528 
529 	switch (mib->sub_command) {
530 	case MLAN_OID_SNMP_MIB_RTS_THRESHOLD:
531 		value = mib->param.rts_threshold;
532 		cmd_oid = RtsThresh_i;
533 		break;
534 	case MLAN_OID_SNMP_MIB_FRAG_THRESHOLD:
535 		value = mib->param.frag_threshold;
536 		cmd_oid = FragThresh_i;
537 		break;
538 	case MLAN_OID_SNMP_MIB_RETRY_COUNT:
539 		value = mib->param.retry_count;
540 		cmd_oid = ShortRetryLim_i;
541 		break;
542 	case MLAN_OID_SNMP_MIB_DTIM_PERIOD:
543 		value = mib->param.dtim_period;
544 		cmd_oid = DtimPeriod_i;
545 		break;
546 	case MLAN_OID_SNMP_MIB_SIGNALEXT_ENABLE:
547 		value = mib->param.signalext_enable;
548 		cmd_oid = SignalextEnable_i;
549 		break;
550 	case MLAN_OID_SNMP_MIB_CHAN_TRACK:
551 		if (!IS_FW_SUPPORT_CHAN_TRACK(pmadapter)) {
552 			goto exit;
553 		}
554 		value = mib->param.chan_track;
555 		cmd_oid = ChanTrackParam_i;
556 		break;
557 	}
558 
559 	/* Send request to firmware */
560 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, cmd_action,
561 			       cmd_oid, (t_void *)pioctl_req, &value);
562 
563 	if (ret == MLAN_STATUS_SUCCESS)
564 		ret = MLAN_STATUS_PENDING;
565 
566 exit:
567 	LEAVE();
568 	return ret;
569 }
570 
571 /**
572  *  @brief Radio command handler
573  *
574  *  @param pmadapter	A pointer to mlan_adapter structure
575  *  @param pioctl_req	A pointer to ioctl request buffer
576  *
577  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
578  */
wlan_radio_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)579 static mlan_status wlan_radio_ioctl(pmlan_adapter pmadapter,
580 				    pmlan_ioctl_req pioctl_req)
581 {
582 	mlan_status status = MLAN_STATUS_SUCCESS;
583 	mlan_ds_radio_cfg *radio_cfg = MNULL;
584 
585 	ENTER();
586 
587 	if (pioctl_req->buf_len < sizeof(mlan_ds_radio_cfg)) {
588 		PRINTM(MWARN,
589 		       "MLAN IOCTL information buffer length is too short.\n");
590 		pioctl_req->data_read_written = 0;
591 		pioctl_req->buf_len_needed = sizeof(mlan_ds_radio_cfg);
592 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
593 		LEAVE();
594 		return MLAN_STATUS_RESOURCE;
595 	}
596 	radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
597 	switch (radio_cfg->sub_command) {
598 	case MLAN_OID_RADIO_CTRL:
599 		status = wlan_radio_ioctl_radio_ctl(pmadapter, pioctl_req);
600 		break;
601 	case MLAN_OID_BAND_CFG:
602 		status = wlan_radio_ioctl_band_cfg(pmadapter, pioctl_req);
603 		break;
604 	case MLAN_OID_ANT_CFG:
605 		status = wlan_radio_ioctl_ant_cfg(pmadapter, pioctl_req);
606 		break;
607 	case MLAN_OID_REMAIN_CHAN_CFG:
608 		status =
609 			wlan_radio_ioctl_remain_chan_cfg(pmadapter, pioctl_req);
610 		break;
611 	case MLAN_OID_MIMO_SWITCH:
612 		status =
613 			wlan_radio_ioctl_mimo_switch_cfg(pmadapter, pioctl_req);
614 		break;
615 	default:
616 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
617 		status = MLAN_STATUS_FAILURE;
618 		break;
619 	}
620 
621 	LEAVE();
622 	return status;
623 }
624 
625 /**
626  *  @brief Set/Get MAC address
627  *
628  *  @param pmadapter	A pointer to mlan_adapter structure
629  *  @param pioctl_req	A pointer to ioctl request buffer
630  *
631  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
632  */
wlan_bss_ioctl_mac_address(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)633 static mlan_status wlan_bss_ioctl_mac_address(pmlan_adapter pmadapter,
634 					      pmlan_ioctl_req pioctl_req)
635 {
636 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
637 	mlan_ds_bss *bss = MNULL;
638 	t_u16 cmd_action;
639 	mlan_status ret = MLAN_STATUS_SUCCESS;
640 
641 	ENTER();
642 
643 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
644 	if (pioctl_req->action == MLAN_ACT_GET) {
645 		cmd_action = HostCmd_ACT_GEN_GET;
646 	} else {
647 		cmd_action = HostCmd_ACT_GEN_SET;
648 		memcpy_ext(pmadapter, pmpriv->curr_addr, &bss->param.mac_addr,
649 			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
650 	}
651 
652 	/* Send request to firmware */
653 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_MAC_ADDRESS,
654 			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
655 	if (ret == MLAN_STATUS_SUCCESS)
656 		ret = MLAN_STATUS_PENDING;
657 
658 	LEAVE();
659 	return ret;
660 }
661 
662 /**
663  *  @brief Set multicast list
664  *
665  *  @param pmadapter	A pointer to mlan_adapter structure
666  *  @param pioctl_req	A pointer to ioctl request buffer
667  *
668  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
669  * otherwise fail
670  */
wlan_bss_ioctl_set_multicast_list(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)671 static mlan_status wlan_bss_ioctl_set_multicast_list(pmlan_adapter pmadapter,
672 						     pmlan_ioctl_req pioctl_req)
673 {
674 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
675 	mlan_ds_bss *bss = MNULL;
676 	mlan_status ret = MLAN_STATUS_SUCCESS;
677 	t_u16 old_pkt_filter;
678 
679 	ENTER();
680 
681 	old_pkt_filter = pmpriv->curr_pkt_filter;
682 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
683 	if (pioctl_req->action == MLAN_ACT_GET) {
684 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
685 		ret = MLAN_STATUS_FAILURE;
686 		goto exit;
687 	}
688 	pioctl_req->data_read_written =
689 		sizeof(mlan_multicast_list) + MLAN_SUB_COMMAND_SIZE;
690 	if (bss->param.multicast_list.mode == MLAN_PROMISC_MODE) {
691 		PRINTM(MINFO, "Enable Promiscuous mode\n");
692 		pmpriv->curr_pkt_filter |= HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
693 		pmpriv->curr_pkt_filter &=
694 			~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
695 	} else {
696 		/* Multicast */
697 		pmpriv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
698 		if (bss->param.multicast_list.mode == MLAN_ALL_MULTI_MODE) {
699 			PRINTM(MINFO, "Enabling All Multicast!\n");
700 			pmpriv->curr_pkt_filter |=
701 				HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
702 		} else {
703 			pmpriv->curr_pkt_filter &=
704 				~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
705 			if (bss->param.multicast_list.num_multicast_addr) {
706 				PRINTM(MINFO, "Set multicast list=%d\n",
707 				       bss->param.multicast_list
708 					       .num_multicast_addr);
709 				/* Set multicast addresses to firmware */
710 				if (old_pkt_filter == pmpriv->curr_pkt_filter) {
711 					/* Send request to firmware */
712 					ret = wlan_prepare_cmd(
713 						pmpriv,
714 						HostCmd_CMD_MAC_MULTICAST_ADR,
715 						HostCmd_ACT_GEN_SET, 0,
716 						(t_void *)pioctl_req,
717 						&bss->param.multicast_list);
718 					if (ret == MLAN_STATUS_SUCCESS)
719 						ret = MLAN_STATUS_PENDING;
720 				} else {
721 					/* Send request to firmware */
722 					ret = wlan_prepare_cmd(
723 						pmpriv,
724 						HostCmd_CMD_MAC_MULTICAST_ADR,
725 						HostCmd_ACT_GEN_SET, 0, MNULL,
726 						&bss->param.multicast_list);
727 				}
728 				if (ret)
729 					goto exit;
730 			}
731 		}
732 	}
733 	PRINTM(MINFO, "old_pkt_filter=0x%x, curr_pkt_filter=0x%x\n",
734 	       old_pkt_filter, pmpriv->curr_pkt_filter);
735 	if (old_pkt_filter != pmpriv->curr_pkt_filter) {
736 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
737 				       HostCmd_ACT_GEN_SET, 0,
738 				       (t_void *)pioctl_req,
739 				       &pmpriv->curr_pkt_filter);
740 		if (ret == MLAN_STATUS_SUCCESS)
741 			ret = MLAN_STATUS_PENDING;
742 	}
743 
744 exit:
745 	LEAVE();
746 	return ret;
747 }
748 
749 /**
750  *  @brief Get channel list
751  *
752  *  @param pmadapter	A pointer to mlan_adapter structure
753  *  @param pioctl_req	A pointer to ioctl request buffer
754  *
755  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
756  */
wlan_bss_ioctl_get_channel_list(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)757 static mlan_status wlan_bss_ioctl_get_channel_list(pmlan_adapter pmadapter,
758 						   pmlan_ioctl_req pioctl_req)
759 {
760 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
761 	mlan_ds_bss *bss = MNULL;
762 	mlan_status ret = MLAN_STATUS_SUCCESS;
763 	chan_freq_power_t *cfp;
764 	t_u32 i, j;
765 
766 	ENTER();
767 
768 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
769 	if (pioctl_req->action != MLAN_ACT_GET) {
770 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
771 		LEAVE();
772 		return MLAN_STATUS_FAILURE;
773 	}
774 	if ((wlan_11d_is_enabled(pmpriv) && pmpriv->media_connected == MTRUE) &&
775 	    ((pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) ||
776 	     (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS &&
777 	      pmpriv->adhoc_state != ADHOC_STARTED))) {
778 		t_u8 chan_no;
779 		t_u16 band;
780 
781 		parsed_region_chan_11d_t *parsed_region_chan = MNULL;
782 		parsed_region_chan_11d_t region_chan;
783 
784 		BSSDescriptor_t *pbss_desc =
785 			&pmpriv->curr_bss_params.bss_descriptor;
786 
787 		memset(pmadapter, &region_chan, 0,
788 		       sizeof(parsed_region_chan_11d_t));
789 
790 		/*If country IE is present in the associated AP then return the
791 		   channel list from country IE
792 		   else return it from the learning table*/
793 
794 		if (wlan_11d_parse_domain_info(
795 			    pmadapter, &pbss_desc->country_info,
796 			    pbss_desc->bss_band,
797 			    &region_chan) == MLAN_STATUS_SUCCESS) {
798 			parsed_region_chan = &region_chan;
799 		} else {
800 			parsed_region_chan = &pmadapter->parsed_region_chan;
801 		}
802 
803 		PRINTM(MINFO, "no_of_chan=%d\n",
804 		       parsed_region_chan->no_of_chan);
805 
806 		for (i = 0;
807 		     (bss->param.chanlist.num_of_chan < MLAN_MAX_CHANNEL_NUM) &&
808 		     (i < parsed_region_chan->no_of_chan);
809 		     i++) {
810 			chan_no = parsed_region_chan->chan_pwr[i].chan;
811 			band = parsed_region_chan->chan_pwr[i].band;
812 			PRINTM(MINFO, "band=%d, chan_no=%d\n", band, chan_no);
813 			bss->param.chanlist.cf[bss->param.chanlist.num_of_chan]
814 				.channel = (t_u32)chan_no;
815 			bss->param.chanlist.cf[bss->param.chanlist.num_of_chan]
816 				.freq = (t_u32)wlan_11d_chan_2_freq(
817 				pmadapter, chan_no, band);
818 			bss->param.chanlist.num_of_chan++;
819 		}
820 	} else {
821 		for (j = 0;
822 		     (bss->param.chanlist.num_of_chan < MLAN_MAX_CHANNEL_NUM) &&
823 		     (j < MAX_REGION_CHANNEL_NUM);
824 		     j++) {
825 			cfp = pmadapter->region_channel[j].pcfp;
826 			for (i = 0; (bss->param.chanlist.num_of_chan <
827 				     MLAN_MAX_CHANNEL_NUM) &&
828 				    pmadapter->region_channel[j].valid && cfp &&
829 				    (i < pmadapter->region_channel[j].num_cfp);
830 			     i++) {
831 				bss->param.chanlist
832 					.cf[bss->param.chanlist.num_of_chan]
833 					.channel = (t_u32)cfp->channel;
834 				bss->param.chanlist
835 					.cf[bss->param.chanlist.num_of_chan]
836 					.freq = (t_u32)cfp->freq;
837 				bss->param.chanlist.num_of_chan++;
838 				cfp++;
839 			}
840 		}
841 	}
842 
843 	PRINTM(MINFO, "num of channel=%d\n", bss->param.chanlist.num_of_chan);
844 
845 	LEAVE();
846 	return ret;
847 }
848 
849 /** Highest channel used in 2.4GHz band */
850 #define MAX_CHANNEL_BAND_B (14)
851 
852 /** Highest frequency used in 2.4GHz band */
853 #define MAX_FREQUENCY_BAND_B (2484)
854 
855 /**
856  *  @brief Set/Get BSS channel
857  *
858  *  @param pmadapter	A pointer to mlan_adapter structure
859  *  @param pioctl_req	A pointer to ioctl request buffer
860  *
861  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
862  */
wlan_bss_ioctl_channel(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)863 static mlan_status wlan_bss_ioctl_channel(pmlan_adapter pmadapter,
864 					  pmlan_ioctl_req pioctl_req)
865 {
866 	mlan_private *pmpriv = MNULL;
867 	mlan_ds_bss *bss = MNULL;
868 	mlan_status ret = MLAN_STATUS_SUCCESS;
869 	chan_freq_power_t *cfp = MNULL;
870 	ENTER();
871 
872 	if ((pioctl_req == MNULL) || (pioctl_req->pbuf == MNULL)) {
873 		PRINTM(MERROR, "Request buffer not found!\n");
874 		LEAVE();
875 		return MLAN_STATUS_FAILURE;
876 	}
877 	pmpriv = pmadapter->priv[pioctl_req->bss_index];
878 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
879 	if (pioctl_req->action == MLAN_ACT_GET) {
880 		cfp = wlan_find_cfp_by_band_and_channel(
881 			pmadapter, pmpriv->curr_bss_params.band,
882 			(t_u16)pmpriv->curr_bss_params.bss_descriptor.channel);
883 		if (cfp) {
884 			bss->param.bss_chan.channel = cfp->channel;
885 			bss->param.bss_chan.freq = cfp->freq;
886 		} else {
887 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
888 			ret = MLAN_STATUS_FAILURE;
889 		}
890 		pioctl_req->data_read_written =
891 			sizeof(chan_freq) + MLAN_SUB_COMMAND_SIZE;
892 		LEAVE();
893 		return ret;
894 	}
895 	if (!bss->param.bss_chan.channel && !bss->param.bss_chan.freq) {
896 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
897 		LEAVE();
898 		return MLAN_STATUS_FAILURE;
899 	}
900 	if (pmadapter->adhoc_start_band & BAND_A)
901 		pmadapter->adhoc_start_band = BAND_G | BAND_B;
902 	if (bss->param.bss_chan.channel) {
903 		if (bss->param.bss_chan.channel <= MAX_CHANNEL_BAND_B)
904 			cfp = wlan_find_cfp_by_band_and_channel(
905 				pmadapter, BAND_B,
906 				(t_u16)bss->param.bss_chan.channel);
907 		if (!cfp) {
908 			cfp = wlan_find_cfp_by_band_and_channel(
909 				pmadapter, BAND_A,
910 				(t_u16)bss->param.bss_chan.channel);
911 			if (cfp) {
912 				pmadapter->adhoc_start_band = BAND_A;
913 			}
914 		}
915 	} else {
916 		if (bss->param.bss_chan.freq <= MAX_FREQUENCY_BAND_B)
917 			cfp = wlan_find_cfp_by_band_and_freq(
918 				pmadapter, BAND_B, bss->param.bss_chan.freq);
919 		if (!cfp) {
920 			cfp = wlan_find_cfp_by_band_and_freq(
921 				pmadapter, BAND_A, bss->param.bss_chan.freq);
922 			if (cfp) {
923 				pmadapter->adhoc_start_band = BAND_A;
924 			}
925 		}
926 	}
927 	if (!cfp || !cfp->channel) {
928 		PRINTM(MERROR, "Invalid channel/freq\n");
929 		if (pioctl_req)
930 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
931 		LEAVE();
932 		return MLAN_STATUS_FAILURE;
933 	}
934 	pmpriv->adhoc_channel = (t_u8)cfp->channel;
935 	pmpriv->intf_state_11h.adhoc_auto_sel_chan = MFALSE;
936 	bss->param.bss_chan.channel = cfp->channel;
937 	bss->param.bss_chan.freq = cfp->freq;
938 
939 	LEAVE();
940 	return ret;
941 }
942 
943 /**
944  *  @brief Set/Get BSS mode
945  *
946  *  @param pmadapter	A pointer to mlan_adapter structure
947  *  @param pioctl_req	A pointer to ioctl request buffer
948  *
949  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
950  * otherwise fail
951  */
wlan_bss_ioctl_mode(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)952 static mlan_status wlan_bss_ioctl_mode(pmlan_adapter pmadapter,
953 				       pmlan_ioctl_req pioctl_req)
954 {
955 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
956 	mlan_ds_bss *bss = MNULL;
957 	mlan_status ret = MLAN_STATUS_SUCCESS;
958 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
959 
960 	ENTER();
961 
962 	if (pioctl_req->action == MLAN_ACT_GET) {
963 		bss->param.bss_mode = pmpriv->bss_mode;
964 		pioctl_req->data_read_written =
965 			sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
966 		goto exit;
967 	}
968 
969 	if ((pmpriv->bss_mode == bss->param.bss_mode) ||
970 	    (bss->param.bss_mode == MLAN_BSS_MODE_AUTO)) {
971 		PRINTM(MINFO, "Already set to required mode! No change!\n");
972 		pmpriv->bss_mode = bss->param.bss_mode;
973 		goto exit;
974 	}
975 
976 	if (pmpriv->bss_mode != MLAN_BSS_MODE_AUTO)
977 		ret = wlan_disconnect(pmpriv, MNULL, MNULL);
978 	else
979 		ret = wlan_disconnect(pmpriv, pioctl_req, MNULL);
980 
981 	if (pmpriv->sec_info.authentication_mode != MLAN_AUTH_MODE_AUTO)
982 		pmpriv->sec_info.authentication_mode = MLAN_AUTH_MODE_OPEN;
983 	pmpriv->bss_mode = bss->param.bss_mode;
984 	if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA)
985 		pmpriv->port_ctrl_mode = MTRUE;
986 	else
987 		pmpriv->port_ctrl_mode = MFALSE;
988 	if (pmpriv->bss_mode != MLAN_BSS_MODE_AUTO) {
989 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SET_BSS_MODE,
990 				       HostCmd_ACT_GEN_SET, 0,
991 				       (t_void *)pioctl_req, MNULL);
992 		if (ret == MLAN_STATUS_SUCCESS)
993 			ret = MLAN_STATUS_PENDING;
994 	}
995 exit:
996 	LEAVE();
997 	return ret;
998 }
999 
1000 /**
1001  *  @brief Start BSS
1002  *
1003  *  @param pmadapter	A pointer to mlan_adapter structure
1004  *  @param pioctl_req	A pointer to ioctl request buffer
1005  *
1006  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
1007  */
wlan_bss_ioctl_start(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1008 static mlan_status wlan_bss_ioctl_start(pmlan_adapter pmadapter,
1009 					pmlan_ioctl_req pioctl_req)
1010 {
1011 	mlan_status ret = MLAN_STATUS_SUCCESS;
1012 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1013 	mlan_ds_bss *bss = (mlan_ds_bss *)pioctl_req->pbuf;
1014 	t_s32 i = -1;
1015 	t_u8 zero_mac[] = {0, 0, 0, 0, 0, 0};
1016 
1017 	ENTER();
1018 
1019 	if (pmadapter->enable_net_mon == CHANNEL_SPEC_SNIFFER_MODE) {
1020 		PRINTM(MINFO,
1021 		       "Association is blocked in Channel Specified Network Monitor mode...\n");
1022 		LEAVE();
1023 		return MLAN_STATUS_FAILURE;
1024 	}
1025 	/* Before ASSOC REQ, If "port ctrl" mode is enabled,
1026 	 * move the port to CLOSED state */
1027 	if (pmpriv->port_ctrl_mode == MTRUE) {
1028 		PRINTM(MINFO, "bss_ioctl_start(): port_state=CLOSED\n");
1029 		pmpriv->prior_port_status = pmpriv->port_open;
1030 		pmpriv->port_open = MFALSE;
1031 	}
1032 	pmadapter->scan_block = MFALSE;
1033 
1034 	if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) {
1035 		if (!bss->param.ssid_bssid.idx ||
1036 		    bss->param.ssid_bssid.idx > pmadapter->num_in_scan_table) {
1037 			/* Search for the requested SSID in the scan table */
1038 			if (bss->param.ssid_bssid.ssid.ssid_len) {
1039 				if (memcmp(pmadapter,
1040 					   &bss->param.ssid_bssid.bssid,
1041 					   zero_mac, sizeof(zero_mac)))
1042 					i = wlan_find_ssid_in_list(
1043 						pmpriv,
1044 						&bss->param.ssid_bssid.ssid,
1045 						(t_u8 *)&bss->param.ssid_bssid
1046 							.bssid,
1047 						MLAN_BSS_MODE_INFRA);
1048 				else
1049 					i = wlan_find_ssid_in_list(
1050 						pmpriv,
1051 						&bss->param.ssid_bssid.ssid,
1052 						MNULL, MLAN_BSS_MODE_INFRA);
1053 			} else {
1054 				i = wlan_find_bssid_in_list(
1055 					pmpriv,
1056 					(t_u8 *)&bss->param.ssid_bssid.bssid,
1057 					MLAN_BSS_MODE_INFRA);
1058 			}
1059 		} else {
1060 			/* use bsslist index number to assoicate */
1061 			i = wlan_is_network_compatible(
1062 				pmpriv, bss->param.ssid_bssid.idx - 1,
1063 				pmpriv->bss_mode);
1064 		}
1065 		if (i >= 0) {
1066 			/* block if upper-layer tries to reconnect before new
1067 			 * scan */
1068 			if (wlan_11h_get_csa_closed_channel(pmpriv) ==
1069 			    (t_u8)pmadapter->pscan_table[i].channel) {
1070 				PRINTM(MINFO,
1071 				       "Attempt to reconnect on csa_closed_chan(%d)\n",
1072 				       pmadapter->pscan_table[i].channel);
1073 				pioctl_req->status_code =
1074 					MLAN_ERROR_INVALID_PARAMETER;
1075 				ret = MLAN_STATUS_FAILURE;
1076 				goto start_ssid_done;
1077 			}
1078 			PRINTM(MINFO,
1079 			       "SSID found in scan list ... associating...\n");
1080 			pmpriv->curr_bss_params.host_mlme =
1081 				bss->param.ssid_bssid.host_mlme;
1082 			memcpy_ext(pmpriv->adapter,
1083 				   &pmpriv->curr_bss_params.prev_bssid,
1084 				   &bss->param.ssid_bssid.prev_bssid,
1085 				   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
1086 			/* Clear any past association response stored for
1087 			 * application retrieval */
1088 			pmpriv->assoc_rsp_size = 0;
1089 			pmpriv->curr_chan_flags =
1090 				bss->param.ssid_bssid.channel_flags;
1091 			if (IS_FW_SUPPORT_NO_80MHZ(pmadapter))
1092 				pmpriv->curr_chan_flags |= CHAN_FLAGS_NO_80MHZ;
1093 			ret = wlan_associate(pmpriv, pioctl_req,
1094 					     &pmadapter->pscan_table[i]);
1095 			if (ret)
1096 				goto start_ssid_done;
1097 		} else { /* i >= 0 */
1098 			PRINTM(MERROR,
1099 			       "SSID not found in scan list: ssid=%s, " MACSTR
1100 			       ", idx=%d\n",
1101 			       bss->param.ssid_bssid.ssid.ssid,
1102 			       MAC2STR(bss->param.ssid_bssid.bssid),
1103 			       (int)bss->param.ssid_bssid.idx);
1104 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1105 			ret = MLAN_STATUS_FAILURE;
1106 			goto start_ssid_done;
1107 		}
1108 	} else {
1109 		/* Adhoc mode */
1110 		/* If the requested SSID matches current SSID, return */
1111 		if (bss->param.ssid_bssid.ssid.ssid_len &&
1112 		    (!wlan_ssid_cmp(pmadapter,
1113 				    &pmpriv->curr_bss_params.bss_descriptor.ssid,
1114 				    &bss->param.ssid_bssid.ssid))) {
1115 			ret = MLAN_STATUS_SUCCESS;
1116 			goto start_ssid_done;
1117 		}
1118 
1119 		/* Exit Adhoc mode first */
1120 		PRINTM(MINFO, "Sending Adhoc Stop\n");
1121 		ret = wlan_disconnect(pmpriv, MNULL, MNULL);
1122 		if (ret)
1123 			goto start_ssid_done;
1124 
1125 		pmpriv->adhoc_is_link_sensed = MFALSE;
1126 
1127 		if (!bss->param.ssid_bssid.idx ||
1128 		    bss->param.ssid_bssid.idx > pmadapter->num_in_scan_table) {
1129 			/* Search for the requested network in the scan table */
1130 			if (bss->param.ssid_bssid.ssid.ssid_len) {
1131 				i = wlan_find_ssid_in_list(
1132 					pmpriv, &bss->param.ssid_bssid.ssid,
1133 					MNULL, MLAN_BSS_MODE_IBSS);
1134 			} else {
1135 				i = wlan_find_bssid_in_list(
1136 					pmpriv,
1137 					(t_u8 *)&bss->param.ssid_bssid.bssid,
1138 					MLAN_BSS_MODE_IBSS);
1139 			}
1140 		} else {
1141 			/* use bsslist index number to assoicate */
1142 			i = wlan_is_network_compatible(
1143 				pmpriv, bss->param.ssid_bssid.idx - 1,
1144 				pmpriv->bss_mode);
1145 		}
1146 
1147 		if (i >= 0) {
1148 			PRINTM(MINFO,
1149 			       "Network found in scan list ... joining ...\n");
1150 			pmpriv->curr_chan_flags =
1151 				bss->param.ssid_bssid.channel_flags;
1152 			ret = wlan_adhoc_join(pmpriv, pioctl_req,
1153 					      &pmadapter->pscan_table[i]);
1154 			if (ret)
1155 				goto start_ssid_done;
1156 		} else { /* i >= 0 */
1157 			PRINTM(MINFO,
1158 			       "Network not found in the list, "
1159 			       "creating adhoc with ssid = %s\n",
1160 			       bss->param.ssid_bssid.ssid.ssid);
1161 			pmpriv->curr_chan_flags =
1162 				bss->param.ssid_bssid.channel_flags;
1163 			ret = wlan_adhoc_start(pmpriv, pioctl_req,
1164 					       &bss->param.ssid_bssid.ssid);
1165 			if (ret)
1166 				goto start_ssid_done;
1167 		}
1168 	}
1169 
1170 	if (ret == MLAN_STATUS_SUCCESS)
1171 		ret = MLAN_STATUS_PENDING;
1172 
1173 start_ssid_done:
1174 	LEAVE();
1175 	return ret;
1176 }
1177 
1178 /**
1179  *  @brief Stop BSS
1180  *
1181  *  @param pmadapter	A pointer to mlan_adapter structure
1182  *  @param pioctl_req	A pointer to ioctl request buffer
1183  *
1184  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
1185  * otherwise fail
1186  */
wlan_bss_ioctl_stop(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1187 static mlan_status wlan_bss_ioctl_stop(pmlan_adapter pmadapter,
1188 				       pmlan_ioctl_req pioctl_req)
1189 {
1190 	mlan_status ret = MLAN_STATUS_SUCCESS;
1191 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
1192 	mlan_ds_bss *bss = (mlan_ds_bss *)pioctl_req->pbuf;
1193 
1194 	ENTER();
1195 
1196 	ret = wlan_disconnect(pmpriv, pioctl_req, &bss->param.deauth_param);
1197 
1198 	LEAVE();
1199 	return ret;
1200 }
1201 
1202 /**
1203  *  @brief Set/Get IBSS channel
1204  *
1205  *  @param pmadapter	A pointer to mlan_adapter structure
1206  *  @param pioctl_req	A pointer to ioctl request buffer
1207  *
1208  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
1209  * otherwise fail
1210  */
wlan_bss_ioctl_ibss_channel(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1211 static mlan_status wlan_bss_ioctl_ibss_channel(pmlan_adapter pmadapter,
1212 					       pmlan_ioctl_req pioctl_req)
1213 {
1214 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1215 	mlan_ds_bss *bss = MNULL;
1216 	mlan_status ret = MLAN_STATUS_SUCCESS;
1217 	t_u16 cmd_action;
1218 
1219 	ENTER();
1220 
1221 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
1222 	if (pioctl_req->action == MLAN_ACT_GET) {
1223 		if (pmpriv->media_connected == MFALSE) {
1224 			bss->param.bss_chan.channel = pmpriv->adhoc_channel;
1225 			goto exit;
1226 		}
1227 		cmd_action = HostCmd_ACT_GEN_GET;
1228 	} else {
1229 		cmd_action = HostCmd_ACT_GEN_SET;
1230 		pmpriv->adhoc_channel = (t_u8)bss->param.bss_chan.channel;
1231 		pmpriv->intf_state_11h.adhoc_auto_sel_chan = MFALSE;
1232 	}
1233 
1234 	/* Send request to firmware */
1235 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_RF_CHANNEL,
1236 			       cmd_action, 0, (t_void *)pioctl_req,
1237 			       &bss->param.bss_chan.channel);
1238 	if (ret == MLAN_STATUS_SUCCESS)
1239 		ret = MLAN_STATUS_PENDING;
1240 
1241 exit:
1242 	LEAVE();
1243 	return ret;
1244 }
1245 
1246 /**
1247  *  @brief Set/Get Listen Interval
1248  *
1249  *  @param pmadapter	A pointer to mlan_adapter structure
1250  *  @param pioctl_req	A pointer to ioctl request buffer
1251  *
1252  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
1253  * otherwise fail
1254  */
wlan_bss_ioctl_listen_interval(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1255 static mlan_status wlan_bss_ioctl_listen_interval(pmlan_adapter pmadapter,
1256 						  pmlan_ioctl_req pioctl_req)
1257 {
1258 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1259 	mlan_ds_bss *bss = MNULL;
1260 
1261 	ENTER();
1262 
1263 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
1264 	if (pioctl_req->action == MLAN_ACT_GET)
1265 		bss->param.listen_interval = pmpriv->listen_interval;
1266 	else
1267 		pmpriv->listen_interval = bss->param.listen_interval;
1268 
1269 	LEAVE();
1270 	return MLAN_STATUS_SUCCESS;
1271 }
1272 
1273 /*
1274  *  @brief Set/Get beacon interval
1275  *
1276  *  @param pmadapter	A pointer to mlan_adapter structure
1277  *  @param pioctl_req	A pointer to ioctl request buffer
1278  *
1279  *  @return		MLAN_STATUS_SUCCESS --success
1280  */
wlan_bss_ioctl_beacon_interval(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1281 static mlan_status wlan_bss_ioctl_beacon_interval(pmlan_adapter pmadapter,
1282 						  pmlan_ioctl_req pioctl_req)
1283 {
1284 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1285 	mlan_ds_bss *bss = MNULL;
1286 	mlan_status ret = MLAN_STATUS_SUCCESS;
1287 	ENTER();
1288 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
1289 	if (pioctl_req->action == MLAN_ACT_GET) {
1290 		bss->param.bcn_interval = pmpriv->beacon_period;
1291 		if (pmpriv->media_connected == MTRUE)
1292 			bss->param.bcn_interval =
1293 				pmpriv->curr_bss_params.bss_descriptor
1294 					.beacon_period;
1295 	} else
1296 		pmpriv->beacon_period = (t_u16)bss->param.bcn_interval;
1297 	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
1298 	LEAVE();
1299 	return ret;
1300 }
1301 
1302 /**
1303  *  @brief Set/Get ATIM window
1304  *
1305  *  @param pmadapter	A pointer to mlan_adapter structure
1306  *  @param pioctl_req	A pointer to ioctl request buffer
1307  *
1308  *  @return		MLAN_STATUS_SUCCESS --success
1309  */
wlan_bss_ioctl_atim_window(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1310 static mlan_status wlan_bss_ioctl_atim_window(pmlan_adapter pmadapter,
1311 					      pmlan_ioctl_req pioctl_req)
1312 {
1313 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1314 	mlan_ds_bss *bss = MNULL;
1315 	mlan_status ret = MLAN_STATUS_SUCCESS;
1316 	ENTER();
1317 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
1318 	if (pioctl_req->action == MLAN_ACT_GET) {
1319 		bss->param.atim_window = pmpriv->atim_window;
1320 		if (pmpriv->media_connected == MTRUE)
1321 			bss->param.atim_window =
1322 				pmpriv->curr_bss_params.bss_descriptor
1323 					.atim_window;
1324 	} else
1325 		pmpriv->atim_window = (t_u16)bss->param.atim_window;
1326 
1327 	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
1328 	LEAVE();
1329 	return ret;
1330 }
1331 
1332 /**
1333  *  @brief Query embe
1334  *
1335  *  @param priv                 A pointer to mlan_private structure
1336  *  @param pioctl_req           A pointer to ioctl request buffer
1337  *
1338  *  @return                     MLAN_STATUS_SUCCESS -- success, otherwise fail
1339  */
wlan_query_passphrase(mlan_private * priv,pmlan_ioctl_req pioctl_req)1340 static mlan_status wlan_query_passphrase(mlan_private *priv,
1341 					 pmlan_ioctl_req pioctl_req)
1342 {
1343 	mlan_adapter *pmadapter = priv->adapter;
1344 	pmlan_callbacks pcb = &pmadapter->callbacks;
1345 	mlan_ds_bss *bss = MNULL;
1346 	mlan_ssid_bssid *ssid_bssid = MNULL;
1347 	mlan_ds_sec_cfg *sec = MNULL;
1348 	mlan_ds_passphrase *sec_pp;
1349 	int i = 0;
1350 	BSSDescriptor_t *pbss_desc;
1351 	mlan_status ret = MLAN_STATUS_SUCCESS;
1352 
1353 	ENTER();
1354 
1355 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
1356 	ssid_bssid = &bss->param.ssid_bssid;
1357 
1358 	ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(mlan_ds_sec_cfg),
1359 			       MLAN_MEM_DEF, (t_u8 **)&sec);
1360 	if (ret || !sec) {
1361 		PRINTM(MERROR, "Could not allocate sec!\n");
1362 		LEAVE();
1363 		return ret;
1364 	}
1365 	memset(pmadapter, sec, 0, sizeof(mlan_ds_sec_cfg));
1366 	sec_pp = (mlan_ds_passphrase *)&sec->param.passphrase;
1367 	sec_pp->psk_type = MLAN_PSK_QUERY;
1368 	if (ssid_bssid->ssid.ssid_len == 0) {
1369 		i = wlan_find_bssid_in_list(priv, (t_u8 *)&ssid_bssid->bssid,
1370 					    MLAN_BSS_MODE_AUTO);
1371 		if (i >= 0) {
1372 			pbss_desc = &pmadapter->pscan_table[i];
1373 			memcpy_ext(pmadapter, (t_u8 *)&sec_pp->ssid,
1374 				   &pbss_desc->ssid, sizeof(mlan_802_11_ssid),
1375 				   sizeof(mlan_802_11_ssid));
1376 		} else
1377 			memcpy_ext(pmadapter, (t_u8 *)&sec_pp->bssid,
1378 				   &ssid_bssid->bssid, MLAN_MAC_ADDR_LENGTH,
1379 				   MLAN_MAC_ADDR_LENGTH);
1380 	} else {
1381 		memcpy_ext(pmadapter, (t_u8 *)&sec_pp->ssid, &ssid_bssid->ssid,
1382 			   sizeof(mlan_802_11_ssid), sizeof(mlan_802_11_ssid));
1383 	}
1384 
1385 	/* Send request to firmware */
1386 	ret = wlan_prepare_cmd(priv, HostCmd_CMD_SUPPLICANT_PMK,
1387 			       HostCmd_ACT_GEN_GET, 0, (t_void *)pioctl_req,
1388 			       (t_void *)sec);
1389 	if (sec)
1390 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)sec);
1391 	LEAVE();
1392 	return ret;
1393 }
1394 
1395 /**
1396  *  @brief Search for a BSS
1397  *
1398  *  @param pmadapter	A pointer to mlan_adapter structure
1399  *  @param pioctl_req	A pointer to ioctl request buffer
1400  *
1401  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
1402  * otherwise fail
1403  */
wlan_bss_ioctl_find_bss(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1404 static mlan_status wlan_bss_ioctl_find_bss(pmlan_adapter pmadapter,
1405 					   pmlan_ioctl_req pioctl_req)
1406 {
1407 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1408 	mlan_status ret = MLAN_STATUS_SUCCESS;
1409 #ifdef DRV_EMBEDDED_SUPPLICANT
1410 	mlan_ds_bss *bss = MNULL;
1411 	mlan_ssid_bssid *ssid_bssid = MNULL;
1412 #endif
1413 
1414 	ENTER();
1415 
1416 	if (pmpriv->ewpa_query) {
1417 		if (wlan_query_passphrase(pmpriv, pioctl_req) ==
1418 		    MLAN_STATUS_SUCCESS) {
1419 			PRINTM(MINFO, "Find BSS ioctl: query passphrase\n");
1420 			LEAVE();
1421 			return MLAN_STATUS_PENDING;
1422 		}
1423 	}
1424 #ifdef DRV_EMBEDDED_SUPPLICANT
1425 	if (!IS_FW_SUPPORT_SUPPLICANT(pmpriv->adapter)) {
1426 		bss = (mlan_ds_bss *)pioctl_req->pbuf;
1427 		ssid_bssid = &bss->param.ssid_bssid;
1428 		supplicantQueryPassphraseAndEnable(pmpriv->psapriv,
1429 						   (t_u8 *)ssid_bssid);
1430 	}
1431 #endif
1432 
1433 	ret = wlan_find_bss(pmpriv, pioctl_req);
1434 
1435 	LEAVE();
1436 	return ret;
1437 }
1438 
1439 /**
1440  *  @brief Search for a BSS
1441  *
1442  *  @param pmadapter	A pointer to mlan_adapter structure
1443  *  @param pioctl_req	A pointer to ioctl request buffer
1444  *
1445  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
1446  * otherwise fail
1447  */
wlan_bss_ioctl_find_bssid(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1448 static mlan_status wlan_bss_ioctl_find_bssid(pmlan_adapter pmadapter,
1449 					     pmlan_ioctl_req pioctl_req)
1450 {
1451 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1452 	mlan_ds_bss *bss = MNULL;
1453 	mlan_status ret = MLAN_STATUS_SUCCESS;
1454 	int i = 0;
1455 
1456 	ENTER();
1457 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
1458 	i = wlan_find_bssid_in_list(pmpriv, (t_u8 *)&bss->param.bssid,
1459 				    MLAN_BSS_MODE_AUTO);
1460 	if (i < 0) {
1461 		PRINTM(MCMND, "Can not find bssid " MACSTR "\n",
1462 		       MAC2STR((t_u8 *)&bss->param.bssid));
1463 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1464 		LEAVE();
1465 		return MLAN_STATUS_FAILURE;
1466 	}
1467 	PRINTM(MCMND, "Find bssid " MACSTR "\n",
1468 	       MAC2STR((t_u8 *)&bss->param.bssid));
1469 	LEAVE();
1470 	return ret;
1471 }
1472 
1473 /**
1474  *  @brief Check if BSS channel is valid for Station's region
1475  *
1476  *  @param pmadapter	A pointer to mlan_adapter structure
1477  *  @param pioctl_req	A pointer to ioctl request buffer
1478  *
1479  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
1480  * otherwise fail
1481  */
1482 static mlan_status
wlan_bss_ioctl_bss_11d_check_channel(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1483 wlan_bss_ioctl_bss_11d_check_channel(pmlan_adapter pmadapter,
1484 				     pmlan_ioctl_req pioctl_req)
1485 {
1486 	mlan_status ret = MLAN_STATUS_SUCCESS;
1487 	mlan_ds_bss *bss = MNULL;
1488 	mlan_ssid_bssid *ssid_bssid = MNULL;
1489 
1490 	ENTER();
1491 
1492 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
1493 	ssid_bssid = &bss->param.ssid_bssid;
1494 
1495 	PRINTM(MINFO, "ssid: %s idx:%d\n", ssid_bssid->ssid.ssid,
1496 	       ssid_bssid->idx);
1497 	PRINTM(MINFO, "band:%d channel:%d\n", (t_u8)ssid_bssid->bss_band,
1498 	       (t_u32)ssid_bssid->channel);
1499 
1500 	/* check if this channel is supported in the region */
1501 	if (!wlan_find_cfp_by_band_and_channel(pmadapter, ssid_bssid->bss_band,
1502 					       (t_u32)ssid_bssid->channel)) {
1503 		PRINTM(MERROR, "Unsupported Channel for region 0x%x\n",
1504 		       pmadapter->region_code);
1505 		ret = MLAN_STATUS_FAILURE;
1506 	}
1507 
1508 	LEAVE();
1509 	return ret;
1510 }
1511 
1512 /**
1513  *  @brief BSS command handler
1514  *
1515  *  @param pmadapter	A pointer to mlan_adapter structure
1516  *  @param pioctl_req	A pointer to ioctl request buffer
1517  *
1518  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
1519  */
wlan_bss_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1520 static mlan_status wlan_bss_ioctl(pmlan_adapter pmadapter,
1521 				  pmlan_ioctl_req pioctl_req)
1522 {
1523 	mlan_status status = MLAN_STATUS_SUCCESS;
1524 	mlan_ds_bss *bss = MNULL;
1525 
1526 	ENTER();
1527 
1528 	if (pioctl_req->buf_len < sizeof(mlan_ds_bss)) {
1529 		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
1530 		pioctl_req->data_read_written = 0;
1531 		pioctl_req->buf_len_needed = sizeof(mlan_ds_bss);
1532 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1533 		LEAVE();
1534 		return MLAN_STATUS_RESOURCE;
1535 	}
1536 
1537 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
1538 
1539 	switch (bss->sub_command) {
1540 	case MLAN_OID_BSS_START:
1541 		status = wlan_bss_ioctl_start(pmadapter, pioctl_req);
1542 		break;
1543 	case MLAN_OID_BSS_STOP:
1544 		status = wlan_bss_ioctl_stop(pmadapter, pioctl_req);
1545 		break;
1546 	case MLAN_OID_BSS_MODE:
1547 		status = wlan_bss_ioctl_mode(pmadapter, pioctl_req);
1548 		break;
1549 	case MLAN_OID_BSS_CHANNEL:
1550 		status = wlan_bss_ioctl_channel(pmadapter, pioctl_req);
1551 		break;
1552 	case MLAN_OID_BSS_CHANNEL_LIST:
1553 		status = wlan_bss_ioctl_get_channel_list(pmadapter, pioctl_req);
1554 		break;
1555 	case MLAN_OID_BSS_MAC_ADDR:
1556 		status = wlan_bss_ioctl_mac_address(pmadapter, pioctl_req);
1557 		break;
1558 	case MLAN_OID_BSS_MULTICAST_LIST:
1559 		status = wlan_bss_ioctl_set_multicast_list(pmadapter,
1560 							   pioctl_req);
1561 		break;
1562 	case MLAN_OID_BSS_FIND_BSS:
1563 		status = wlan_bss_ioctl_find_bss(pmadapter, pioctl_req);
1564 		break;
1565 	case MLAN_OID_BSS_FIND_BSSID:
1566 		status = wlan_bss_ioctl_find_bssid(pmadapter, pioctl_req);
1567 		break;
1568 	case MLAN_OID_IBSS_BCN_INTERVAL:
1569 		status = wlan_bss_ioctl_beacon_interval(pmadapter, pioctl_req);
1570 		break;
1571 	case MLAN_OID_IBSS_ATIM_WINDOW:
1572 		status = wlan_bss_ioctl_atim_window(pmadapter, pioctl_req);
1573 		break;
1574 	case MLAN_OID_IBSS_CHANNEL:
1575 		status = wlan_bss_ioctl_ibss_channel(pmadapter, pioctl_req);
1576 		break;
1577 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
1578 	case MLAN_OID_BSS_ROLE:
1579 		util_enqueue_list_tail(pmadapter->pmoal_handle,
1580 				       &pmadapter->ioctl_pending_q,
1581 				       (pmlan_linked_list)pioctl_req,
1582 				       pmadapter->callbacks.moal_spin_lock,
1583 				       pmadapter->callbacks.moal_spin_unlock);
1584 		pmadapter->pending_ioctl = MTRUE;
1585 		status = MLAN_STATUS_PENDING;
1586 		break;
1587 #endif
1588 #ifdef WIFI_DIRECT_SUPPORT
1589 	case MLAN_OID_WIFI_DIRECT_MODE:
1590 		status = wlan_bss_ioctl_wifi_direct_mode(pmadapter, pioctl_req);
1591 		break;
1592 #endif
1593 	case MLAN_OID_BSS_LISTEN_INTERVAL:
1594 		status = wlan_bss_ioctl_listen_interval(pmadapter, pioctl_req);
1595 		break;
1596 	case MLAN_OID_BSS_REMOVE:
1597 		status = wlan_bss_ioctl_bss_remove(pmadapter, pioctl_req);
1598 		break;
1599 
1600 	case MLAN_OID_BSS_11D_CHECK_CHANNEL:
1601 		status = wlan_bss_ioctl_bss_11d_check_channel(pmadapter,
1602 							      pioctl_req);
1603 		break;
1604 	case MLAN_OID_BSS_CHAN_INFO:
1605 		status = wlan_bss_ioctl_get_chan_info(pmadapter, pioctl_req);
1606 		break;
1607 	default:
1608 		status = MLAN_STATUS_FAILURE;
1609 		break;
1610 	}
1611 
1612 	LEAVE();
1613 	return status;
1614 }
1615 
1616 /**
1617  *  @brief Get supported rates
1618  *
1619  *  @param pmadapter	A pointer to mlan_adapter structure
1620  *  @param pioctl_req	A pointer to ioctl request buffer
1621  *
1622  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
1623  */
1624 static mlan_status
wlan_rate_ioctl_get_supported_rate(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1625 wlan_rate_ioctl_get_supported_rate(pmlan_adapter pmadapter,
1626 				   pmlan_ioctl_req pioctl_req)
1627 {
1628 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1629 	mlan_ds_rate *rate = MNULL;
1630 	mlan_status ret = MLAN_STATUS_SUCCESS;
1631 
1632 	ENTER();
1633 	if (pioctl_req->action != MLAN_ACT_GET) {
1634 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1635 		LEAVE();
1636 		return MLAN_STATUS_FAILURE;
1637 	}
1638 	rate = (mlan_ds_rate *)pioctl_req->pbuf;
1639 	if (rate->param.rate_band_cfg.config_bands &&
1640 	    rate->param.rate_band_cfg.bss_mode)
1641 		wlan_get_active_data_rates(
1642 			pmpriv, rate->param.rate_band_cfg.bss_mode,
1643 			rate->param.rate_band_cfg.config_bands,
1644 			rate->param.rates);
1645 	else
1646 		wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode,
1647 					   (pmpriv->bss_mode ==
1648 					    MLAN_BSS_MODE_INFRA) ?
1649 						   pmpriv->config_bands :
1650 						   pmadapter->adhoc_start_band,
1651 					   rate->param.rates);
1652 	pioctl_req->data_read_written =
1653 		MLAN_SUPPORTED_RATES + MLAN_SUB_COMMAND_SIZE;
1654 	LEAVE();
1655 	return ret;
1656 }
1657 
1658 /**
1659  *  @brief Rate command handler
1660  *
1661  *  @param pmadapter	A pointer to mlan_adapter structure
1662  *  @param pioctl_req	A pointer to ioctl request buffer
1663  *
1664  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
1665  * otherwise fail
1666  */
wlan_rate_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1667 static mlan_status wlan_rate_ioctl(pmlan_adapter pmadapter,
1668 				   pmlan_ioctl_req pioctl_req)
1669 {
1670 	mlan_status status = MLAN_STATUS_SUCCESS;
1671 	mlan_ds_rate *rate = MNULL;
1672 
1673 	ENTER();
1674 
1675 	if (pioctl_req->buf_len < sizeof(mlan_ds_rate)) {
1676 		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
1677 		pioctl_req->data_read_written = 0;
1678 		pioctl_req->buf_len_needed = sizeof(mlan_ds_rate);
1679 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1680 		LEAVE();
1681 		return MLAN_STATUS_RESOURCE;
1682 	}
1683 	rate = (mlan_ds_rate *)pioctl_req->pbuf;
1684 	switch (rate->sub_command) {
1685 	case MLAN_OID_RATE_CFG:
1686 		status = wlan_rate_ioctl_cfg(pmadapter, pioctl_req);
1687 		break;
1688 	case MLAN_OID_GET_DATA_RATE:
1689 		status = wlan_rate_ioctl_get_data_rate(pmadapter, pioctl_req);
1690 		break;
1691 	case MLAN_OID_SUPPORTED_RATES:
1692 		status = wlan_rate_ioctl_get_supported_rate(pmadapter,
1693 							    pioctl_req);
1694 		break;
1695 	default:
1696 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1697 		status = MLAN_STATUS_FAILURE;
1698 		break;
1699 	}
1700 	LEAVE();
1701 	return status;
1702 }
1703 
1704 /**
1705  *  @brief Get Tx power configuration
1706  *
1707  *  @param pmadapter	A pointer to mlan_adapter structure
1708  *  @param cmd_no	Firmware command number used to retrieve power values
1709  *  @param pioctl_req	A pointer to ioctl request buffer
1710  *
1711  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
1712  */
wlan_power_ioctl_get_power(pmlan_adapter pmadapter,t_u16 cmd_no,pmlan_ioctl_req pioctl_req)1713 static mlan_status wlan_power_ioctl_get_power(pmlan_adapter pmadapter,
1714 					      t_u16 cmd_no,
1715 					      pmlan_ioctl_req pioctl_req)
1716 {
1717 	mlan_status ret = MLAN_STATUS_SUCCESS;
1718 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1719 
1720 	ENTER();
1721 
1722 	/* Send request to firmware */
1723 	ret = wlan_prepare_cmd(pmpriv, cmd_no, HostCmd_ACT_GEN_GET, 0,
1724 			       (t_void *)pioctl_req, MNULL);
1725 
1726 	if (ret == MLAN_STATUS_SUCCESS)
1727 		ret = MLAN_STATUS_PENDING;
1728 
1729 	LEAVE();
1730 	return ret;
1731 }
1732 
1733 /**
1734  *  @brief Set Tx power configuration
1735  *
1736  *  @param pmadapter	A pointer to mlan_adapter structure
1737  *  @param pioctl_req	A pointer to ioctl request buffer
1738  *
1739  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
1740  */
wlan_power_ioctl_set_power(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1741 static mlan_status wlan_power_ioctl_set_power(pmlan_adapter pmadapter,
1742 					      pmlan_ioctl_req pioctl_req)
1743 {
1744 	mlan_ds_power_cfg *power = MNULL;
1745 	mlan_status ret = MLAN_STATUS_SUCCESS;
1746 
1747 	HostCmd_DS_TXPWR_CFG *txp_cfg = MNULL;
1748 	MrvlTypes_Power_Group_t *pg_tlv = MNULL;
1749 	Power_Group_t *pg = MNULL;
1750 	pmlan_callbacks pcb = &pmadapter->callbacks;
1751 	t_u8 *buf = MNULL;
1752 	t_s8 dbm = 0;
1753 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1754 
1755 	ENTER();
1756 
1757 	power = (mlan_ds_power_cfg *)pioctl_req->pbuf;
1758 	if (!power->param.power_cfg.is_power_auto) {
1759 		dbm = (t_s8)power->param.power_cfg.power_level;
1760 		if ((dbm < pmpriv->min_tx_power_level) ||
1761 		    (dbm > pmpriv->max_tx_power_level)) {
1762 			PRINTM(MERROR,
1763 			       "The set txpower value %d dBm is out of range (%d dBm-%d dBm)!\n",
1764 			       dbm, pmpriv->min_tx_power_level,
1765 			       pmpriv->max_tx_power_level);
1766 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1767 			ret = MLAN_STATUS_FAILURE;
1768 			goto exit;
1769 		}
1770 	}
1771 
1772 	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
1773 			       MRVDRV_SIZE_OF_CMD_BUFFER, MLAN_MEM_DEF, &buf);
1774 	if (ret != MLAN_STATUS_SUCCESS || buf == MNULL) {
1775 		PRINTM(MERROR,
1776 		       "ALLOC_CMD_BUF: Failed to allocate command buffer\n");
1777 		pioctl_req->status_code = MLAN_ERROR_NO_MEM;
1778 		ret = MLAN_STATUS_FAILURE;
1779 		goto exit;
1780 	}
1781 	memset(pmadapter, buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
1782 	txp_cfg = (HostCmd_DS_TXPWR_CFG *)buf;
1783 	txp_cfg->action = HostCmd_ACT_GEN_SET;
1784 	if (!power->param.power_cfg.is_power_auto) {
1785 		txp_cfg->mode = 1;
1786 		pg_tlv = (MrvlTypes_Power_Group_t
1787 				  *)(buf + sizeof(HostCmd_DS_TXPWR_CFG));
1788 		pg_tlv->type = TLV_TYPE_POWER_GROUP;
1789 		pg_tlv->length = 4 * sizeof(Power_Group_t);
1790 		pg = (Power_Group_t *)(buf + sizeof(HostCmd_DS_TXPWR_CFG) +
1791 				       sizeof(MrvlTypes_Power_Group_t));
1792 		/* Power group for modulation class HR/DSSS */
1793 		pg->first_rate_code = 0x00;
1794 		pg->last_rate_code = 0x03;
1795 		pg->modulation_class = MOD_CLASS_HR_DSSS;
1796 		pg->power_step = 0;
1797 		pg->power_min = (t_s8)dbm;
1798 		pg->power_max = (t_s8)dbm;
1799 		pg++;
1800 		/* Power group for modulation class OFDM */
1801 		pg->first_rate_code = 0x00;
1802 		pg->last_rate_code = 0x07;
1803 		pg->modulation_class = MOD_CLASS_OFDM;
1804 		pg->power_step = 0;
1805 		pg->power_min = (t_s8)dbm;
1806 		pg->power_max = (t_s8)dbm;
1807 		pg++;
1808 		/* Power group for modulation class HTBW20 */
1809 		pg->first_rate_code = 0x00;
1810 		pg->last_rate_code = 0x20;
1811 		pg->modulation_class = MOD_CLASS_HT;
1812 		pg->power_step = 0;
1813 		pg->power_min = (t_s8)dbm;
1814 		pg->power_max = (t_s8)dbm;
1815 		pg->ht_bandwidth = HT_BW_20;
1816 		pg++;
1817 		/* Power group for modulation class HTBW40 */
1818 		pg->first_rate_code = 0x00;
1819 		pg->last_rate_code = 0x20;
1820 		pg->modulation_class = MOD_CLASS_HT;
1821 		pg->power_step = 0;
1822 		pg->power_min = (t_s8)dbm;
1823 		pg->power_max = (t_s8)dbm;
1824 		pg->ht_bandwidth = HT_BW_40;
1825 	}
1826 
1827 	/* Send request to firmware */
1828 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TXPWR_CFG,
1829 			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
1830 			       buf);
1831 
1832 	if (ret == MLAN_STATUS_SUCCESS)
1833 		ret = MLAN_STATUS_PENDING;
1834 
1835 	if (buf)
1836 		pcb->moal_mfree(pmadapter->pmoal_handle, buf);
1837 
1838 exit:
1839 	LEAVE();
1840 	return ret;
1841 }
1842 
1843 /**
1844  *  @brief Set extended power configuration
1845  *
1846  *  @param pmadapter	A pointer to mlan_adapter structure
1847  *  @param pioctl_req	A pointer to ioctl request buffer
1848  *
1849  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
1850  */
wlan_power_ioctl_set_power_ext(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1851 static mlan_status wlan_power_ioctl_set_power_ext(pmlan_adapter pmadapter,
1852 						  pmlan_ioctl_req pioctl_req)
1853 {
1854 	mlan_status ret = MLAN_STATUS_SUCCESS;
1855 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1856 	mlan_ds_power_cfg *power = MNULL;
1857 	pmlan_callbacks pcb = &pmadapter->callbacks;
1858 	t_u8 *buf = MNULL;
1859 	HostCmd_DS_TXPWR_CFG *txp_cfg = MNULL;
1860 	MrvlTypes_Power_Group_t *pg_tlv = MNULL;
1861 	Power_Group_t *pg = MNULL;
1862 	mlan_power_group *pwr_grp = MNULL;
1863 
1864 	ENTER();
1865 
1866 	power = (mlan_ds_power_cfg *)pioctl_req->pbuf;
1867 	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
1868 			       MRVDRV_SIZE_OF_CMD_BUFFER, MLAN_MEM_DEF, &buf);
1869 	if (ret != MLAN_STATUS_SUCCESS || buf == MNULL) {
1870 		PRINTM(MERROR,
1871 		       "ALLOC_CMD_BUF: Failed to allocate command buffer\n");
1872 		pioctl_req->status_code = MLAN_ERROR_NO_MEM;
1873 		ret = MLAN_STATUS_FAILURE;
1874 		goto exit;
1875 	}
1876 	memset(pmadapter, buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
1877 	txp_cfg = (HostCmd_DS_TXPWR_CFG *)buf;
1878 	txp_cfg->action = HostCmd_ACT_GEN_SET;
1879 	pwr_grp = &power->param.power_ext.power_group[0];
1880 	if (pwr_grp->rate_format == TX_PWR_CFG_AUTO_CTRL_OFF)
1881 		txp_cfg->mode = 0;
1882 	else {
1883 		txp_cfg->mode = 1;
1884 
1885 		pg_tlv = (MrvlTypes_Power_Group_t
1886 				  *)(buf + sizeof(HostCmd_DS_TXPWR_CFG));
1887 		pg_tlv->type = TLV_TYPE_POWER_GROUP;
1888 		pg_tlv->length = sizeof(Power_Group_t);
1889 		pg = (Power_Group_t *)(buf + sizeof(HostCmd_DS_TXPWR_CFG) +
1890 				       sizeof(MrvlTypes_Power_Group_t));
1891 		pg->ht_bandwidth = pwr_grp->bandwidth;
1892 		pg->power_min = (t_s8)pwr_grp->power_min;
1893 		pg->power_max = (t_s8)pwr_grp->power_max;
1894 		pg->power_step = (t_s8)pwr_grp->power_step;
1895 
1896 		if (pwr_grp->rate_format == MLAN_RATE_FORMAT_LG) {
1897 			if (pwr_grp->first_rate_ind <=
1898 			    MLAN_RATE_INDEX_HRDSSS3) {
1899 				pg->modulation_class = MOD_CLASS_HR_DSSS;
1900 			} else {
1901 				pg->modulation_class = MOD_CLASS_OFDM;
1902 				pwr_grp->first_rate_ind -=
1903 					MLAN_RATE_INDEX_OFDM0;
1904 				pwr_grp->last_rate_ind -= MLAN_RATE_INDEX_OFDM0;
1905 			}
1906 			pg->first_rate_code = (t_u8)pwr_grp->first_rate_ind;
1907 			pg->last_rate_code = (t_u8)pwr_grp->last_rate_ind;
1908 		} else if (pwr_grp->rate_format == MLAN_RATE_FORMAT_HT) {
1909 			pg->modulation_class = MOD_CLASS_HT;
1910 			pg->first_rate_code = (t_u8)pwr_grp->first_rate_ind;
1911 			pg->last_rate_code = (t_u8)pwr_grp->last_rate_ind;
1912 		} else if (pwr_grp->rate_format == MLAN_RATE_FORMAT_VHT) {
1913 			pg->modulation_class = MOD_CLASS_VHT;
1914 			pg->first_rate_code =
1915 				(t_u8)((pwr_grp->first_rate_ind & 0xF) |
1916 				       ((pwr_grp->nss - 1) << 4));
1917 			pg->last_rate_code =
1918 				(t_u8)((pwr_grp->last_rate_ind & 0xF) |
1919 				       ((pwr_grp->nss - 1) << 4));
1920 		} else {
1921 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1922 			ret = MLAN_STATUS_FAILURE;
1923 		}
1924 	}
1925 	if (ret == MLAN_STATUS_FAILURE) {
1926 		if (buf)
1927 			pcb->moal_mfree(pmadapter->pmoal_handle, buf);
1928 		goto exit;
1929 	}
1930 
1931 	/* Send request to firmware */
1932 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_TXPWR_CFG,
1933 			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
1934 			       buf);
1935 	if (ret == MLAN_STATUS_SUCCESS)
1936 		ret = MLAN_STATUS_PENDING;
1937 	if (buf)
1938 		pcb->moal_mfree(pmadapter->pmoal_handle, buf);
1939 
1940 exit:
1941 	LEAVE();
1942 	return ret;
1943 }
1944 
1945 /**
1946  *  @brief Power configuration command handler
1947  *
1948  *  @param pmadapter	A pointer to mlan_adapter structure
1949  *  @param pioctl_req	A pointer to ioctl request buffer
1950  *
1951  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
1952  */
wlan_power_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1953 static mlan_status wlan_power_ioctl(pmlan_adapter pmadapter,
1954 				    pmlan_ioctl_req pioctl_req)
1955 {
1956 	mlan_status status = MLAN_STATUS_SUCCESS;
1957 	mlan_ds_power_cfg *power = MNULL;
1958 
1959 	ENTER();
1960 
1961 	if (pioctl_req->buf_len < sizeof(mlan_ds_power_cfg)) {
1962 		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
1963 		pioctl_req->data_read_written = 0;
1964 		pioctl_req->buf_len_needed = sizeof(mlan_ds_power_cfg);
1965 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1966 		LEAVE();
1967 		return MLAN_STATUS_RESOURCE;
1968 	}
1969 	power = (mlan_ds_power_cfg *)pioctl_req->pbuf;
1970 	switch (power->sub_command) {
1971 	case MLAN_OID_POWER_CFG:
1972 		if (pioctl_req->action == MLAN_ACT_GET)
1973 			status = wlan_power_ioctl_get_power(
1974 				pmadapter, HostCmd_CMD_TXPWR_CFG, pioctl_req);
1975 		else
1976 			status = wlan_power_ioctl_set_power(pmadapter,
1977 							    pioctl_req);
1978 		break;
1979 
1980 	case MLAN_OID_POWER_CFG_EXT:
1981 		if (pioctl_req->action == MLAN_ACT_GET)
1982 			status = wlan_power_ioctl_get_power(
1983 				pmadapter, HostCmd_CMD_TXPWR_CFG, pioctl_req);
1984 		else
1985 			status = wlan_power_ioctl_set_power_ext(pmadapter,
1986 								pioctl_req);
1987 		break;
1988 	case MLAN_OID_POWER_LOW_POWER_MODE:
1989 		status = wlan_power_ioctl_set_get_lpm(pmadapter, pioctl_req);
1990 		break;
1991 	default:
1992 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1993 		status = MLAN_STATUS_FAILURE;
1994 		break;
1995 	}
1996 	LEAVE();
1997 	return status;
1998 }
1999 
2000 /**
2001  *  @brief Set power save configurations
2002  *
2003  *  @param pmadapter	A pointer to mlan_adapter structure
2004  *  @param pioctl_req	A pointer to ioctl request buffer
2005  *  @param ps_mode	Power save mode
2006  *
2007  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2008  */
wlan_pm_ioctl_ps_mode(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req,t_u16 ps_mode)2009 static mlan_status wlan_pm_ioctl_ps_mode(pmlan_adapter pmadapter,
2010 					 pmlan_ioctl_req pioctl_req,
2011 					 t_u16 ps_mode)
2012 {
2013 	mlan_status ret = MLAN_STATUS_SUCCESS;
2014 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2015 	t_u16 sub_cmd;
2016 
2017 	ENTER();
2018 
2019 	if (pioctl_req->action == MLAN_ACT_SET) {
2020 		sub_cmd = (pmadapter->ps_mode == Wlan802_11PowerModePSP) ?
2021 				  EN_AUTO_PS :
2022 				  DIS_AUTO_PS;
2023 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
2024 				       sub_cmd, BITMAP_STA_PS,
2025 				       (t_void *)pioctl_req, MNULL);
2026 		if ((ret == MLAN_STATUS_SUCCESS) && (sub_cmd == DIS_AUTO_PS)) {
2027 			ret = wlan_prepare_cmd(pmpriv,
2028 					       HostCmd_CMD_802_11_PS_MODE_ENH,
2029 					       GET_PS, 0, MNULL, MNULL);
2030 		}
2031 	} else {
2032 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
2033 				       GET_PS, 0, (t_void *)pioctl_req, MNULL);
2034 	}
2035 
2036 	if (ret == MLAN_STATUS_SUCCESS)
2037 		ret = MLAN_STATUS_PENDING;
2038 
2039 	LEAVE();
2040 	return ret;
2041 }
2042 
2043 /**
2044  *  @brief Set/Get Inactivity timeout extend
2045  *
2046  *  @param pmadapter	A pointer to mlan_adapter structure
2047  *  @param pioctl_req	A pointer to ioctl request buffer
2048  *
2049  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2050  */
wlan_pm_ioctl_inactivity_timeout(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2051 static mlan_status wlan_pm_ioctl_inactivity_timeout(pmlan_adapter pmadapter,
2052 						    pmlan_ioctl_req pioctl_req)
2053 {
2054 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2055 	mlan_ds_pm_cfg *pmcfg = MNULL;
2056 	mlan_status ret = MLAN_STATUS_SUCCESS;
2057 	t_u16 cmd_action = 0;
2058 
2059 	ENTER();
2060 
2061 	pmcfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
2062 	cmd_action = HostCmd_ACT_GEN_GET;
2063 	if (pioctl_req->action == MLAN_ACT_SET)
2064 		cmd_action = HostCmd_ACT_GEN_SET;
2065 
2066 	/* Send request to firmware */
2067 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_INACTIVITY_TIMEOUT_EXT,
2068 			       cmd_action, 0, (t_void *)pioctl_req,
2069 			       (t_void *)&pmcfg->param.inactivity_to);
2070 
2071 	if (ret == MLAN_STATUS_SUCCESS)
2072 		ret = MLAN_STATUS_PENDING;
2073 
2074 	LEAVE();
2075 	return ret;
2076 }
2077 
2078 /**
2079  *  @brief Enable/Disable Auto Deep Sleep
2080  *
2081  *  @param pmadapter	A pointer to mlan_adapter structure
2082  *  @param pioctl_req	A pointer to ioctl request buffer
2083  *
2084  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2085  */
wlan_set_auto_deep_sleep(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2086 static mlan_status wlan_set_auto_deep_sleep(pmlan_adapter pmadapter,
2087 					    pmlan_ioctl_req pioctl_req)
2088 {
2089 	mlan_status ret = MLAN_STATUS_SUCCESS;
2090 	pmlan_private pmpriv =
2091 		(pmlan_private)pmadapter->priv[pioctl_req->bss_index];
2092 	mlan_ds_auto_ds auto_ds;
2093 	t_u32 mode;
2094 
2095 	ENTER();
2096 
2097 	if (((mlan_ds_pm_cfg *)pioctl_req->pbuf)
2098 		    ->param.auto_deep_sleep.auto_ds == DEEP_SLEEP_ON) {
2099 		auto_ds.auto_ds = DEEP_SLEEP_ON;
2100 		PRINTM(MINFO, "Auto Deep Sleep: on\n");
2101 		mode = EN_AUTO_PS;
2102 	} else {
2103 		auto_ds.auto_ds = DEEP_SLEEP_OFF;
2104 		PRINTM(MINFO, "Auto Deep Sleep: off\n");
2105 		mode = DIS_AUTO_PS;
2106 	}
2107 	if (((mlan_ds_pm_cfg *)pioctl_req->pbuf)->param.auto_deep_sleep.idletime)
2108 		auto_ds.idletime = ((mlan_ds_pm_cfg *)pioctl_req->pbuf)
2109 					   ->param.auto_deep_sleep.idletime;
2110 	else
2111 		auto_ds.idletime = pmadapter->idle_time;
2112 	/* note: the command could be queued and executed
2113 	   later if there is command in progress. */
2114 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
2115 			       (t_u16)mode, BITMAP_AUTO_DS,
2116 			       (t_void *)pioctl_req, &auto_ds);
2117 	if (ret) {
2118 		LEAVE();
2119 		return ret;
2120 	}
2121 	ret = MLAN_STATUS_PENDING;
2122 	LEAVE();
2123 	return ret;
2124 }
2125 
2126 /**
2127  *  @brief Set/Get sleep period
2128  *
2129  *  @param pmadapter	A pointer to mlan_adapter structure
2130  *  @param pioctl_req	A pointer to ioctl request buffer
2131  *
2132  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2133  */
wlan_set_get_sleep_pd(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2134 static mlan_status wlan_set_get_sleep_pd(pmlan_adapter pmadapter,
2135 					 pmlan_ioctl_req pioctl_req)
2136 {
2137 	mlan_status ret = MLAN_STATUS_SUCCESS;
2138 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
2139 	mlan_ds_pm_cfg *pm_cfg = MNULL;
2140 	t_u16 cmd_action = 0, sleep_pd = 0;
2141 
2142 	ENTER();
2143 
2144 	pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
2145 	cmd_action = HostCmd_ACT_GEN_GET;
2146 	if (pioctl_req->action == MLAN_ACT_SET) {
2147 		cmd_action = HostCmd_ACT_GEN_SET;
2148 		sleep_pd = (t_u16)pm_cfg->param.sleep_period;
2149 	}
2150 
2151 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SLEEP_PERIOD,
2152 			       cmd_action, 0, (t_void *)pioctl_req, &sleep_pd);
2153 
2154 	if (ret == MLAN_STATUS_SUCCESS)
2155 		ret = MLAN_STATUS_PENDING;
2156 
2157 	LEAVE();
2158 	return ret;
2159 }
2160 
2161 /**
2162  *  @brief Set/Get PS configuration parameter
2163  *
2164  *  @param pmadapter	A pointer to mlan_adapter structure
2165  *  @param pioctl_req	A pointer to ioctl request buffer
2166  *
2167  *  @return		MLAN_STATUS_SUCCESS --success
2168  */
wlan_set_get_ps_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2169 static mlan_status wlan_set_get_ps_cfg(pmlan_adapter pmadapter,
2170 				       pmlan_ioctl_req pioctl_req)
2171 {
2172 	mlan_ds_pm_cfg *pm_cfg = MNULL;
2173 
2174 	ENTER();
2175 
2176 	pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
2177 	if (pioctl_req->action == MLAN_ACT_GET) {
2178 		pm_cfg->param.ps_cfg.ps_null_interval =
2179 			(t_u32)pmadapter->null_pkt_interval;
2180 		pm_cfg->param.ps_cfg.multiple_dtim_interval =
2181 			(t_u32)pmadapter->multiple_dtim;
2182 		pm_cfg->param.ps_cfg.listen_interval =
2183 			(t_u32)pmadapter->local_listen_interval;
2184 		pm_cfg->param.ps_cfg.bcn_miss_timeout =
2185 			(t_u32)pmadapter->bcn_miss_time_out;
2186 		pm_cfg->param.ps_cfg.delay_to_ps =
2187 			(t_u32)pmadapter->delay_to_ps;
2188 		pm_cfg->param.ps_cfg.ps_mode =
2189 			(t_u32)pmadapter->enhanced_ps_mode;
2190 	} else {
2191 		if (pm_cfg->param.ps_cfg.ps_null_interval)
2192 			pmadapter->null_pkt_interval =
2193 				(t_u16)pm_cfg->param.ps_cfg.ps_null_interval;
2194 		else
2195 			pm_cfg->param.ps_cfg.ps_null_interval =
2196 				(t_u32)pmadapter->null_pkt_interval;
2197 		if (pm_cfg->param.ps_cfg.multiple_dtim_interval)
2198 			pmadapter->multiple_dtim =
2199 				(t_u16)pm_cfg->param.ps_cfg
2200 					.multiple_dtim_interval;
2201 		else
2202 			pm_cfg->param.ps_cfg.multiple_dtim_interval =
2203 				(t_u32)pmadapter->multiple_dtim;
2204 		if (((t_s32)pm_cfg->param.ps_cfg.listen_interval) ==
2205 		    MRVDRV_LISTEN_INTERVAL_DISABLE)
2206 			pmadapter->local_listen_interval = 0;
2207 		else if (pm_cfg->param.ps_cfg.listen_interval)
2208 			pmadapter->local_listen_interval =
2209 				(t_u16)pm_cfg->param.ps_cfg.listen_interval;
2210 		else
2211 			pm_cfg->param.ps_cfg.listen_interval =
2212 				(t_u32)pmadapter->local_listen_interval;
2213 		if (pm_cfg->param.ps_cfg.bcn_miss_timeout)
2214 			pmadapter->bcn_miss_time_out =
2215 				(t_u16)pm_cfg->param.ps_cfg.bcn_miss_timeout;
2216 		else
2217 			pm_cfg->param.ps_cfg.bcn_miss_timeout =
2218 				(t_u32)pmadapter->bcn_miss_time_out;
2219 		if (pm_cfg->param.ps_cfg.delay_to_ps != DELAY_TO_PS_UNCHANGED)
2220 			pmadapter->delay_to_ps =
2221 				(t_u16)pm_cfg->param.ps_cfg.delay_to_ps;
2222 		else
2223 			pm_cfg->param.ps_cfg.delay_to_ps =
2224 				(t_u32)pmadapter->delay_to_ps;
2225 		if (pm_cfg->param.ps_cfg.ps_mode)
2226 			pmadapter->enhanced_ps_mode =
2227 				(t_u16)pm_cfg->param.ps_cfg.ps_mode;
2228 		else
2229 			pm_cfg->param.ps_cfg.ps_mode =
2230 				(t_u32)pmadapter->enhanced_ps_mode;
2231 	}
2232 	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
2233 
2234 	LEAVE();
2235 	return MLAN_STATUS_SUCCESS;
2236 }
2237 
2238 /**
2239  *  @brief Set/Get PS configuration parameter
2240  *
2241  *  @param pmadapter	A pointer to mlan_adapter structure
2242  *  @param pioctl_req	A pointer to ioctl request buffer
2243  *
2244  *  @return		MLAN_STATUS_SUCCESS --success
2245  */
wlan_set_get_bcn_timeout(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2246 static mlan_status wlan_set_get_bcn_timeout(pmlan_adapter pmadapter,
2247 					    pmlan_ioctl_req pioctl_req)
2248 {
2249 	mlan_status ret = MLAN_STATUS_SUCCESS;
2250 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2251 	mlan_ds_pm_cfg *pm_cfg = MNULL;
2252 
2253 	ENTER();
2254 
2255 	pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
2256 
2257 	/* Send command to firmware */
2258 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
2259 			       EN_AUTO_PS, BITMAP_BCN_TMO, (t_void *)pioctl_req,
2260 			       &pm_cfg->param.bcn_timeout);
2261 
2262 	if (ret == MLAN_STATUS_SUCCESS)
2263 		ret = MLAN_STATUS_PENDING;
2264 
2265 	LEAVE();
2266 	return ret;
2267 }
2268 
2269 /**
2270  *  @brief Get/Set the sleep parameters
2271  *
2272  *  @param pmadapter	A pointer to mlan_adapter structure
2273  *  @param pioctl_req	A pointer to ioctl request buffer
2274  *
2275  *  @return		        MLAN_STATUS_PENDING --success, otherwise fail
2276  */
wlan_set_get_sleep_params(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2277 static mlan_status wlan_set_get_sleep_params(pmlan_adapter pmadapter,
2278 					     pmlan_ioctl_req pioctl_req)
2279 {
2280 	mlan_status ret = MLAN_STATUS_SUCCESS;
2281 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2282 	mlan_ds_pm_cfg *pm_cfg = MNULL;
2283 	t_u16 cmd_action = 0;
2284 
2285 	ENTER();
2286 
2287 	pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
2288 	cmd_action = HostCmd_ACT_GEN_GET;
2289 	if (pioctl_req->action == MLAN_ACT_SET)
2290 		cmd_action = HostCmd_ACT_GEN_SET;
2291 
2292 	/* Send command to firmware */
2293 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SLEEP_PARAMS,
2294 			       cmd_action, 0, (t_void *)pioctl_req,
2295 			       &pm_cfg->param.sleep_params);
2296 
2297 	if (ret == MLAN_STATUS_SUCCESS)
2298 		ret = MLAN_STATUS_PENDING;
2299 
2300 	LEAVE();
2301 	return ret;
2302 }
2303 
2304 /**
2305  *  @brief config management frame wakeup filter
2306  *
2307  *  @param pmadapter	A pointer to mlan_adapter structure
2308  *  @param pioctl_req	A pointer to ioctl request buffer
2309  *
2310  *  @return		        MLAN_STATUS_PENDING --success, otherwise fail
2311  */
wlan_config_mgmt_filter(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2312 mlan_status wlan_config_mgmt_filter(pmlan_adapter pmadapter,
2313 				    pmlan_ioctl_req pioctl_req)
2314 {
2315 	mlan_status ret = MLAN_STATUS_SUCCESS;
2316 	mlan_ds_pm_cfg *pm_cfg = MNULL;
2317 	int i = 0;
2318 
2319 	ENTER();
2320 
2321 	memset(pmadapter, pmadapter->mgmt_filter, 0,
2322 	       sizeof(mlan_mgmt_frame_wakeup) * MAX_MGMT_FRAME_FILTER);
2323 	pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
2324 	if (pioctl_req->action == MLAN_ACT_SET) {
2325 		for (i = 0; i < MAX_MGMT_FRAME_FILTER; i++)
2326 			if (!pm_cfg->param.mgmt_filter[i].type)
2327 				break;
2328 		memcpy_ext(pmadapter, (t_u8 *)pmadapter->mgmt_filter,
2329 			   (t_u8 *)pm_cfg->param.mgmt_filter,
2330 			   (i + 1) * sizeof(mlan_mgmt_frame_wakeup),
2331 			   sizeof(pmadapter->mgmt_filter));
2332 	} else if (pioctl_req->action == MLAN_ACT_GET)
2333 		PRINTM(MERROR, "Get not support\n");
2334 	LEAVE();
2335 	return ret;
2336 }
2337 
2338 /**
2339  *  @brief Power save command handler
2340  *
2341  *  @param pmadapter	A pointer to mlan_adapter structure
2342  *  @param pioctl_req	A pointer to ioctl request buffer
2343  *
2344  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
2345  */
wlan_pm_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2346 static mlan_status wlan_pm_ioctl(pmlan_adapter pmadapter,
2347 				 pmlan_ioctl_req pioctl_req)
2348 {
2349 	mlan_status status = MLAN_STATUS_SUCCESS;
2350 	mlan_ds_pm_cfg *pm = MNULL;
2351 
2352 	ENTER();
2353 
2354 	if (pioctl_req->buf_len < sizeof(mlan_ds_pm_cfg)) {
2355 		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
2356 		pioctl_req->data_read_written = 0;
2357 		pioctl_req->buf_len_needed = sizeof(mlan_ds_pm_cfg);
2358 		LEAVE();
2359 		return MLAN_STATUS_RESOURCE;
2360 	}
2361 	pm = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
2362 	switch (pm->sub_command) {
2363 	case MLAN_OID_PM_CFG_IEEE_PS:
2364 		switch (pioctl_req->action) {
2365 		case MLAN_ACT_SET:
2366 			/**Block ieee power save disable command when bt coex
2367 			 * enable*/
2368 			if (pmadapter->coex_scan && !pm->param.ps_mode)
2369 				break;
2370 			if (pm->param.ps_mode)
2371 				pmadapter->ps_mode = Wlan802_11PowerModePSP;
2372 			else
2373 				pmadapter->ps_mode = Wlan802_11PowerModeCAM;
2374 			status = wlan_pm_ioctl_ps_mode(pmadapter, pioctl_req,
2375 						       pmadapter->ps_mode);
2376 			break;
2377 		case MLAN_ACT_GET:
2378 			status = wlan_pm_ioctl_ps_mode(pmadapter, pioctl_req,
2379 						       pmadapter->ps_mode);
2380 			break;
2381 		default:
2382 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
2383 			status = MLAN_STATUS_FAILURE;
2384 			break;
2385 		}
2386 		break;
2387 	case MLAN_OID_PM_CFG_HS_CFG:
2388 		status = wlan_pm_ioctl_hscfg(pmadapter, pioctl_req);
2389 		break;
2390 	case MLAN_OID_PM_CFG_INACTIVITY_TO:
2391 		status =
2392 			wlan_pm_ioctl_inactivity_timeout(pmadapter, pioctl_req);
2393 		break;
2394 	case MLAN_OID_PM_CFG_DEEP_SLEEP:
2395 		switch (pioctl_req->action) {
2396 		case MLAN_ACT_SET:
2397 			if (pmadapter->is_deep_sleep &&
2398 			    pm->param.auto_deep_sleep.auto_ds ==
2399 				    DEEP_SLEEP_ON) {
2400 				PRINTM(MMSG,
2401 				       "Station already in enhanced deep sleep mode\n");
2402 				status = MLAN_STATUS_FAILURE;
2403 				break;
2404 			} else if (!pmadapter->is_deep_sleep &&
2405 				   pm->param.auto_deep_sleep.auto_ds ==
2406 					   DEEP_SLEEP_OFF) {
2407 				PRINTM(MMSG,
2408 				       "Station already not in enhanced deep sleep mode\n");
2409 				status = MLAN_STATUS_FAILURE;
2410 				break;
2411 			}
2412 			status =
2413 				wlan_set_auto_deep_sleep(pmadapter, pioctl_req);
2414 			break;
2415 		case MLAN_ACT_GET:
2416 			if (pmadapter->is_deep_sleep) {
2417 				pm->param.auto_deep_sleep.auto_ds =
2418 					DEEP_SLEEP_ON;
2419 				pm->param.auto_deep_sleep.idletime =
2420 					pmadapter->idle_time;
2421 			} else
2422 				pm->param.auto_deep_sleep.auto_ds =
2423 					DEEP_SLEEP_OFF;
2424 			break;
2425 		default:
2426 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
2427 			status = MLAN_STATUS_FAILURE;
2428 			break;
2429 		}
2430 		break;
2431 	case MLAN_OID_PM_CFG_PS_CFG:
2432 		status = wlan_set_get_ps_cfg(pmadapter, pioctl_req);
2433 		break;
2434 	case MLAN_OID_PM_CFG_SLEEP_PD:
2435 		status = wlan_set_get_sleep_pd(pmadapter, pioctl_req);
2436 		break;
2437 	case MLAN_OID_PM_CFG_SLEEP_PARAMS:
2438 		status = wlan_set_get_sleep_params(pmadapter, pioctl_req);
2439 		break;
2440 	case MLAN_OID_PM_INFO:
2441 		status = wlan_get_pm_info(pmadapter, pioctl_req);
2442 		break;
2443 	case MLAN_OID_PM_HS_WAKEUP_REASON:
2444 		status = wlan_get_hs_wakeup_reason(pmadapter, pioctl_req);
2445 		break;
2446 	case MLAN_OID_PM_MGMT_FILTER:
2447 		status = wlan_config_mgmt_filter(pmadapter, pioctl_req);
2448 		break;
2449 	case MLAN_OID_PM_CFG_BCN_TIMEOUT:
2450 		status = wlan_set_get_bcn_timeout(pmadapter, pioctl_req);
2451 		break;
2452 	default:
2453 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
2454 		status = MLAN_STATUS_FAILURE;
2455 		break;
2456 	}
2457 	LEAVE();
2458 	return status;
2459 }
2460 
2461 /**
2462  *  @brief Set/Get WPA IE
2463  *
2464  *  @param priv         A pointer to mlan_private structure
2465  *  @param ie_data_ptr  A pointer to IE
2466  *  @param ie_len       Length of the IE
2467  *
2468  *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
2469  */
wlan_set_wpa_ie_helper(mlan_private * priv,t_u8 * ie_data_ptr,t_u16 ie_len)2470 static mlan_status wlan_set_wpa_ie_helper(mlan_private *priv, t_u8 *ie_data_ptr,
2471 					  t_u16 ie_len)
2472 {
2473 	ENTER();
2474 
2475 	if (ie_len) {
2476 		if (ie_len > sizeof(priv->wpa_ie)) {
2477 			PRINTM(MERROR, "failed to copy, WPA IE is too big\n");
2478 			LEAVE();
2479 			return MLAN_STATUS_FAILURE;
2480 		}
2481 		memcpy_ext(priv->adapter, priv->wpa_ie, ie_data_ptr, ie_len,
2482 			   sizeof(priv->wpa_ie));
2483 		priv->wpa_ie_len = (t_u8)ie_len;
2484 		PRINTM(MIOCTL, "Set Wpa_ie_len=%d IE=%#x\n", priv->wpa_ie_len,
2485 		       priv->wpa_ie[0]);
2486 		DBG_HEXDUMP(MCMD_D, "Wpa_ie", priv->wpa_ie, priv->wpa_ie_len);
2487 		if (priv->wpa_ie[0] == WPA_IE) {
2488 			priv->sec_info.wpa_enabled = MTRUE;
2489 		} else if (priv->wpa_ie[0] == RSN_IE) {
2490 			priv->sec_info.wpa2_enabled = MTRUE;
2491 		} else {
2492 			priv->sec_info.wpa_enabled = MFALSE;
2493 			priv->sec_info.wpa2_enabled = MFALSE;
2494 		}
2495 	} else {
2496 		memset(priv->adapter, priv->wpa_ie, 0, sizeof(priv->wpa_ie));
2497 		priv->wpa_ie_len = 0;
2498 		PRINTM(MINFO, "Reset Wpa_ie_len=%d IE=%#x\n", priv->wpa_ie_len,
2499 		       priv->wpa_ie[0]);
2500 		priv->sec_info.wpa_enabled = MFALSE;
2501 		priv->sec_info.wpa2_enabled = MFALSE;
2502 	}
2503 
2504 	LEAVE();
2505 	return MLAN_STATUS_SUCCESS;
2506 }
2507 
2508 /**
2509  *  @brief Set OSEN IE
2510  *
2511  *  @param priv         A pointer to mlan_private structure
2512  *  @param ie_data_ptr  A pointer to IE
2513  *  @param ie_len       Length of the IE
2514  *
2515  *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
2516  */
wlan_set_osen_ie(mlan_private * priv,t_u8 * ie_data_ptr,t_u16 ie_len)2517 static mlan_status wlan_set_osen_ie(mlan_private *priv, t_u8 *ie_data_ptr,
2518 				    t_u16 ie_len)
2519 {
2520 	ENTER();
2521 	if (ie_len) {
2522 		if (ie_len > sizeof(priv->osen_ie)) {
2523 			PRINTM(MWARN, "failed to copy, WAPI IE is too big\n");
2524 			LEAVE();
2525 			return MLAN_STATUS_FAILURE;
2526 		}
2527 		memcpy_ext(priv->adapter, priv->osen_ie, ie_data_ptr, ie_len,
2528 			   sizeof(priv->osen_ie));
2529 		priv->osen_ie_len = (t_u8)ie_len;
2530 		PRINTM(MIOCTL, "Set osen_ie_len=%d IE=%#x\n", priv->osen_ie_len,
2531 		       priv->osen_ie[0]);
2532 		DBG_HEXDUMP(MCMD_D, "osen_ie", priv->osen_ie,
2533 			    priv->osen_ie_len);
2534 		priv->sec_info.osen_enabled = MTRUE;
2535 	} else {
2536 		memset(priv->adapter, priv->osen_ie, 0, sizeof(priv->osen_ie));
2537 		priv->osen_ie_len = (t_u8)ie_len;
2538 		PRINTM(MINFO, "Reset osen_ie_len=%d IE=%#x\n",
2539 		       priv->osen_ie_len, priv->osen_ie[0]);
2540 		priv->sec_info.osen_enabled = MFALSE;
2541 	}
2542 	LEAVE();
2543 	return MLAN_STATUS_SUCCESS;
2544 }
2545 
2546 /**
2547  *  @brief Set WAPI IE
2548  *
2549  *  @param priv         A pointer to mlan_private structure
2550  *  @param ie_data_ptr  A pointer to IE
2551  *  @param ie_len       Length of the IE
2552  *
2553  *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
2554  */
wlan_set_wapi_ie(mlan_private * priv,t_u8 * ie_data_ptr,t_u16 ie_len)2555 static mlan_status wlan_set_wapi_ie(mlan_private *priv, t_u8 *ie_data_ptr,
2556 				    t_u16 ie_len)
2557 {
2558 	ENTER();
2559 	if (ie_len) {
2560 		if (ie_len > sizeof(priv->wapi_ie)) {
2561 			PRINTM(MWARN, "failed to copy, WAPI IE is too big\n");
2562 			LEAVE();
2563 			return MLAN_STATUS_FAILURE;
2564 		}
2565 		memcpy_ext(priv->adapter, priv->wapi_ie, ie_data_ptr, ie_len,
2566 			   sizeof(priv->wapi_ie));
2567 		priv->wapi_ie_len = (t_u8)ie_len;
2568 		PRINTM(MIOCTL, "Set wapi_ie_len=%d IE=%#x\n", priv->wapi_ie_len,
2569 		       priv->wapi_ie[0]);
2570 		DBG_HEXDUMP(MCMD_D, "wapi_ie", priv->wapi_ie,
2571 			    priv->wapi_ie_len);
2572 		if (priv->wapi_ie[0] == WAPI_IE)
2573 			priv->sec_info.wapi_enabled = MTRUE;
2574 	} else {
2575 		memset(priv->adapter, priv->wapi_ie, 0, sizeof(priv->wapi_ie));
2576 		priv->wapi_ie_len = (t_u8)ie_len;
2577 		PRINTM(MINFO, "Reset wapi_ie_len=%d IE=%#x\n",
2578 		       priv->wapi_ie_len, priv->wapi_ie[0]);
2579 		priv->sec_info.wapi_enabled = MFALSE;
2580 	}
2581 	LEAVE();
2582 	return MLAN_STATUS_SUCCESS;
2583 }
2584 
2585 /**
2586  *  @brief Set/Get WAPI status
2587  *
2588  *  @param pmadapter	A pointer to mlan_adapter structure
2589  *  @param pioctl_req	A pointer to ioctl request buffer
2590  *
2591  *  @return		MLAN_STATUS_SUCCESS --success
2592  */
wlan_sec_ioctl_wapi_enable(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2593 static mlan_status wlan_sec_ioctl_wapi_enable(pmlan_adapter pmadapter,
2594 					      pmlan_ioctl_req pioctl_req)
2595 {
2596 	mlan_status ret = MLAN_STATUS_SUCCESS;
2597 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2598 	mlan_ds_sec_cfg *sec = MNULL;
2599 	ENTER();
2600 	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
2601 	if (pioctl_req->action == MLAN_ACT_GET) {
2602 		if (pmpriv->wapi_ie_len)
2603 			sec->param.wapi_enabled = MTRUE;
2604 		else
2605 			sec->param.wapi_enabled = MFALSE;
2606 	} else {
2607 		if (sec->param.wapi_enabled == MFALSE)
2608 			wlan_set_wapi_ie(pmpriv, MNULL, 0);
2609 	}
2610 	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
2611 	LEAVE();
2612 	return ret;
2613 }
2614 
2615 /**
2616  *  @brief Set WAPI key
2617  *
2618  *  @param pmadapter	A pointer to mlan_adapter structure
2619  *  @param pioctl_req	A pointer to ioctl request buffer
2620  *
2621  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2622  */
wlan_sec_ioctl_set_wapi_key(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2623 static mlan_status wlan_sec_ioctl_set_wapi_key(pmlan_adapter pmadapter,
2624 					       pmlan_ioctl_req pioctl_req)
2625 {
2626 	mlan_status ret = MLAN_STATUS_SUCCESS;
2627 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2628 	mlan_ds_sec_cfg *sec = MNULL;
2629 	ENTER();
2630 
2631 	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
2632 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
2633 			       HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED,
2634 			       (t_void *)pioctl_req, &sec->param.encrypt_key);
2635 	if (ret == MLAN_STATUS_SUCCESS)
2636 		ret = MLAN_STATUS_PENDING;
2637 
2638 	LEAVE();
2639 	return ret;
2640 }
2641 
2642 /**
2643  *  @brief Set/Get Port Control status
2644  *
2645  *  @param pmadapter	A pointer to mlan_adapter structure
2646  *  @param pioctl_req	A pointer to ioctl request buffer
2647  *
2648  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
2649  */
wlan_sec_ioctl_port_ctrl_enable(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2650 static mlan_status wlan_sec_ioctl_port_ctrl_enable(pmlan_adapter pmadapter,
2651 						   pmlan_ioctl_req pioctl_req)
2652 {
2653 	mlan_status ret = MLAN_STATUS_SUCCESS;
2654 	mlan_ds_sec_cfg *sec = MNULL;
2655 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2656 
2657 	ENTER();
2658 
2659 	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
2660 	if (pioctl_req->action == MLAN_ACT_GET) {
2661 		if (pmpriv->port_ctrl_mode)
2662 			sec->param.port_ctrl_enabled = MTRUE;
2663 		else
2664 			sec->param.port_ctrl_enabled = MFALSE;
2665 	} else {
2666 		if (sec->param.port_ctrl_enabled) {
2667 			pmpriv->port_ctrl_mode = MTRUE;
2668 			pmpriv->port_open = MFALSE;
2669 		} else {
2670 			if (pmpriv->port_ctrl_mode == MTRUE) {
2671 				pmpriv->port_ctrl_mode = MFALSE;
2672 				/* Cleanup the bypass TX queue */
2673 				wlan_cleanup_bypass_txq(pmpriv);
2674 			}
2675 		}
2676 	}
2677 	PRINTM(MINFO, "port_ctrl: port_ctrl_mode=%d port_open=%d\n",
2678 	       pmpriv->port_ctrl_mode, pmpriv->port_open);
2679 
2680 	LEAVE();
2681 	return ret;
2682 }
2683 
2684 /**
2685  *  @brief Set/Get authentication mode
2686  *
2687  *  @param pmadapter	A pointer to mlan_adapter structure
2688  *  @param pioctl_req	A pointer to ioctl request buffer
2689  *
2690  *  @return		MLAN_STATUS_SUCCESS --success
2691  */
wlan_sec_ioctl_auth_mode(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2692 static mlan_status wlan_sec_ioctl_auth_mode(pmlan_adapter pmadapter,
2693 					    pmlan_ioctl_req pioctl_req)
2694 {
2695 	mlan_status ret = MLAN_STATUS_SUCCESS;
2696 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2697 	mlan_ds_sec_cfg *sec = MNULL;
2698 	ENTER();
2699 	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
2700 	if (pioctl_req->action == MLAN_ACT_GET)
2701 		sec->param.auth_mode = pmpriv->sec_info.authentication_mode;
2702 	else
2703 		pmpriv->sec_info.authentication_mode = sec->param.auth_mode;
2704 
2705 	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
2706 	LEAVE();
2707 	return ret;
2708 }
2709 
2710 /**
2711  *  @brief Set/Get encryption mode
2712  *
2713  *  @param pmadapter	A pointer to mlan_adapter structure
2714  *  @param pioctl_req	A pointer to ioctl request buffer
2715  *
2716  *  @return		MLAN_STATUS_SUCCESS --success
2717  */
wlan_sec_ioctl_encrypt_mode(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2718 static mlan_status wlan_sec_ioctl_encrypt_mode(pmlan_adapter pmadapter,
2719 					       pmlan_ioctl_req pioctl_req)
2720 {
2721 	mlan_status ret = MLAN_STATUS_SUCCESS;
2722 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2723 	mlan_ds_sec_cfg *sec = MNULL;
2724 	ENTER();
2725 	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
2726 	if (pioctl_req->action == MLAN_ACT_GET)
2727 		sec->param.encrypt_mode = pmpriv->sec_info.encryption_mode;
2728 	else
2729 		pmpriv->sec_info.encryption_mode = sec->param.encrypt_mode;
2730 
2731 	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
2732 	LEAVE();
2733 	return ret;
2734 }
2735 
2736 /**
2737  *  @brief Get Random charactor
2738  *
2739  *  @param pmadapter	A pointer to mlan_adapter structure
2740  *
2741  *  @return		random charactor
2742  */
wlan_get_random_charactor(pmlan_adapter pmadapter)2743 static t_u8 wlan_get_random_charactor(pmlan_adapter pmadapter)
2744 {
2745 	t_u32 sec, usec;
2746 	t_u8 ch = 0;
2747 
2748 	ENTER();
2749 
2750 	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec,
2751 						  &usec);
2752 	sec = (sec & 0xFFFF) + (sec >> 16);
2753 	usec = (usec & 0xFFFF) + (usec >> 16);
2754 	ch = (((sec << 16) + usec) % 26) + 'a';
2755 	LEAVE();
2756 	return ch;
2757 }
2758 
2759 /**
2760  *  @brief Set/Get WPA status
2761  *
2762  *  @param pmadapter	A pointer to mlan_adapter structure
2763  *  @param pioctl_req	A pointer to ioctl request buffer
2764  *
2765  *  @return		MLAN_STATUS_SUCCESS --success
2766  */
wlan_sec_ioctl_wpa_enable(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2767 static mlan_status wlan_sec_ioctl_wpa_enable(pmlan_adapter pmadapter,
2768 					     pmlan_ioctl_req pioctl_req)
2769 {
2770 	mlan_status ret = MLAN_STATUS_SUCCESS;
2771 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2772 	mlan_ds_sec_cfg *sec = MNULL;
2773 	ENTER();
2774 	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
2775 	if (pioctl_req->action == MLAN_ACT_GET) {
2776 		if (pmpriv->wpa_ie_len)
2777 			sec->param.wpa_enabled = MTRUE;
2778 		else
2779 			sec->param.wpa_enabled = MFALSE;
2780 	} else {
2781 		if (sec->param.wpa_enabled == MFALSE)
2782 			wlan_set_wpa_ie_helper(pmpriv, MNULL, 0);
2783 	}
2784 	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
2785 	LEAVE();
2786 	return ret;
2787 }
2788 
2789 /**
2790  *  @brief Set WEP keys
2791  *
2792  *  @param pmadapter	A pointer to mlan_adapter structure
2793  *  @param pioctl_req	A pointer to ioctl request buffer
2794  *
2795  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2796  */
wlan_sec_ioctl_set_wep_key(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2797 static mlan_status wlan_sec_ioctl_set_wep_key(pmlan_adapter pmadapter,
2798 					      pmlan_ioctl_req pioctl_req)
2799 {
2800 	mlan_status ret = MLAN_STATUS_SUCCESS;
2801 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2802 	mlan_ds_sec_cfg *sec = MNULL;
2803 	mrvl_wep_key_t *pwep_key = MNULL;
2804 	int index;
2805 	int i = 0;
2806 
2807 	ENTER();
2808 
2809 	if (pmpriv->wep_key_curr_index >= MRVL_NUM_WEP_KEY)
2810 		pmpriv->wep_key_curr_index = 0;
2811 	pwep_key = &pmpriv->wep_key[pmpriv->wep_key_curr_index];
2812 	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
2813 	if (sec->param.encrypt_key.key_index == MLAN_KEY_INDEX_DEFAULT) {
2814 		index = pmpriv->wep_key_curr_index;
2815 		sec->param.encrypt_key.key_index = index;
2816 	} else {
2817 		if (sec->param.encrypt_key.key_index >= MRVL_NUM_WEP_KEY) {
2818 			if ((sec->param.encrypt_key.key_remove == MTRUE) &&
2819 			    (sec->param.encrypt_key.key_index <= 5)) {
2820 				/* call firmware remove key */
2821 				ret = wlan_prepare_cmd(
2822 					pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
2823 					HostCmd_ACT_GEN_SET, 0,
2824 					(t_void *)pioctl_req,
2825 					&sec->param.encrypt_key);
2826 				if (ret == MLAN_STATUS_SUCCESS)
2827 					ret = MLAN_STATUS_PENDING;
2828 				goto exit;
2829 			}
2830 			PRINTM(MERROR, "Key_index is invalid\n");
2831 			ret = MLAN_STATUS_FAILURE;
2832 			goto exit;
2833 		}
2834 		index = sec->param.encrypt_key.key_index;
2835 	}
2836 
2837 	if ((sec->param.encrypt_key.key_disable == MTRUE) ||
2838 	    (sec->param.encrypt_key.key_remove == MTRUE)) {
2839 		pmpriv->sec_info.wep_status = Wlan802_11WEPDisabled;
2840 		/* remove key */
2841 		if (sec->param.encrypt_key.key_remove == MTRUE) {
2842 			memset(pmadapter, &pmpriv->wep_key[index], 0,
2843 			       sizeof(mrvl_wep_key_t));
2844 			/* call firmware remove key */
2845 			ret = wlan_prepare_cmd(pmpriv,
2846 					       HostCmd_CMD_802_11_KEY_MATERIAL,
2847 					       HostCmd_ACT_GEN_SET, 0, MNULL,
2848 					       &sec->param.encrypt_key);
2849 			if (ret)
2850 				goto exit;
2851 		}
2852 	} else {
2853 		if (sec->param.encrypt_key.key_len) {
2854 			if ((sec->param.encrypt_key.key_len !=
2855 			     WEP_104_BIT_LEN) &&
2856 			    (sec->param.encrypt_key.key_len !=
2857 			     WEP_40_BIT_LEN)) {
2858 				PRINTM(MERROR, "Invalid wep key len=%d\n",
2859 				       sec->param.encrypt_key.key_len);
2860 				/* We will use random key to clear the key
2861 				 * buffer in FW */
2862 				if (sec->param.encrypt_key.key_len <
2863 				    WEP_40_BIT_LEN)
2864 					sec->param.encrypt_key.key_len =
2865 						WEP_40_BIT_LEN;
2866 				else
2867 					sec->param.encrypt_key.key_len =
2868 						WEP_104_BIT_LEN;
2869 				for (i = 0;
2870 				     i < (int)sec->param.encrypt_key.key_len;
2871 				     i++)
2872 					sec->param.encrypt_key.key_material[i] =
2873 						wlan_get_random_charactor(
2874 							pmadapter);
2875 			}
2876 			pwep_key = &pmpriv->wep_key[index];
2877 			/* Cleanup */
2878 			memset(pmadapter, pwep_key, 0, sizeof(mrvl_wep_key_t));
2879 			/* Copy the key in the driver */
2880 
2881 			memcpy_ext(pmadapter, pwep_key->key_material,
2882 				   sec->param.encrypt_key.key_material,
2883 				   sec->param.encrypt_key.key_len,
2884 				   MRVL_KEY_BUFFER_SIZE_IN_BYTE);
2885 			pwep_key->key_index = index;
2886 			pwep_key->key_length = sec->param.encrypt_key.key_len;
2887 			if (pmpriv->sec_info.wep_status !=
2888 			    Wlan802_11WEPEnabled) {
2889 				/*
2890 				 * The status is set as Key Absent
2891 				 * so as to make sure we display the
2892 				 * keys when iwlist mlanX key is used
2893 				 */
2894 				pmpriv->sec_info.wep_status =
2895 					Wlan802_11WEPKeyAbsent;
2896 			}
2897 		}
2898 		if (sec->param.encrypt_key.is_current_wep_key == MTRUE) {
2899 			/* Copy the required key as the current key */
2900 			pwep_key = &pmpriv->wep_key[index];
2901 			if (!pwep_key->key_length) {
2902 				if (pmpriv->sec_info.wpa_enabled ||
2903 				    pmpriv->sec_info.wpa2_enabled ||
2904 				    pmpriv->sec_info.wapi_enabled) {
2905 					ret = MLAN_STATUS_SUCCESS;
2906 					goto exit;
2907 				}
2908 				PRINTM(MERROR,
2909 				       "Key %d not set,so cannot enable it\n",
2910 				       index);
2911 				pioctl_req->status_code =
2912 					MLAN_ERROR_CMD_RESP_FAIL;
2913 				ret = MLAN_STATUS_FAILURE;
2914 				goto exit;
2915 			}
2916 			pmpriv->wep_key_curr_index = (t_u16)index;
2917 			pmpriv->sec_info.wep_status = Wlan802_11WEPEnabled;
2918 		}
2919 		if (sec->param.encrypt_key.key_flags && pwep_key->key_length) {
2920 			pmpriv->wep_key_curr_index = (t_u16)index;
2921 			// Only do this if the key is an xmit key.  If the key
2922 			// is a group key, we might be in wpa/wep mixed mode in
2923 			// which case we don't want to set wep_status =
2924 			// Wlan802_11WEPEnabled because that enables WEP at the
2925 			// MAC controller level and WPA stops working properly.
2926 			if (sec->param.encrypt_key.key_flags &
2927 			    KEY_FLAG_SET_TX_KEY) {
2928 				pmpriv->sec_info.wep_status =
2929 					Wlan802_11WEPEnabled;
2930 			}
2931 		}
2932 	}
2933 	if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled)
2934 		pmpriv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
2935 	else
2936 		pmpriv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
2937 
2938 	/* Send request to firmware */
2939 	if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled &&
2940 	    pwep_key->key_length) {
2941 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
2942 				       HostCmd_ACT_GEN_SET, 0, MNULL,
2943 				       &pmpriv->curr_pkt_filter);
2944 		if (ret)
2945 			goto exit;
2946 		if (!sec->param.encrypt_key.key_len) {
2947 			sec->param.encrypt_key.key_index = pwep_key->key_index;
2948 			sec->param.encrypt_key.key_len = pwep_key->key_length;
2949 			memcpy_ext(pmadapter,
2950 				   sec->param.encrypt_key.key_material,
2951 				   pwep_key->key_material,
2952 				   sec->param.encrypt_key.key_len,
2953 				   MLAN_MAX_KEY_LENGTH);
2954 		}
2955 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
2956 				       HostCmd_ACT_GEN_SET, 0,
2957 				       (t_void *)pioctl_req,
2958 				       &sec->param.encrypt_key);
2959 	} else {
2960 		if (pwep_key->key_length) {
2961 			if (!sec->param.encrypt_key.key_len) {
2962 				sec->param.encrypt_key.key_index =
2963 					pwep_key->key_index;
2964 				sec->param.encrypt_key.key_len =
2965 					pwep_key->key_length;
2966 				memcpy_ext(pmadapter,
2967 					   sec->param.encrypt_key.key_material,
2968 					   pwep_key->key_material,
2969 					   sec->param.encrypt_key.key_len,
2970 					   MLAN_MAX_KEY_LENGTH);
2971 			}
2972 			ret = wlan_prepare_cmd(pmpriv,
2973 					       HostCmd_CMD_802_11_KEY_MATERIAL,
2974 					       HostCmd_ACT_GEN_SET, 0, MNULL,
2975 					       &sec->param.encrypt_key);
2976 			if (ret)
2977 				goto exit;
2978 		}
2979 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
2980 				       HostCmd_ACT_GEN_SET, 0,
2981 				       (t_void *)pioctl_req,
2982 				       &pmpriv->curr_pkt_filter);
2983 	}
2984 	if (ret == MLAN_STATUS_SUCCESS)
2985 		ret = MLAN_STATUS_PENDING;
2986 
2987 exit:
2988 	LEAVE();
2989 	return ret;
2990 }
2991 
2992 /**
2993  *  @brief Set WPA key
2994  *
2995  *  @param pmadapter	A pointer to mlan_adapter structure
2996  *  @param pioctl_req	A pointer to ioctl request buffer
2997  *
2998  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2999  */
wlan_sec_ioctl_set_wpa_key(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3000 static mlan_status wlan_sec_ioctl_set_wpa_key(pmlan_adapter pmadapter,
3001 					      pmlan_ioctl_req pioctl_req)
3002 {
3003 	mlan_status ret = MLAN_STATUS_SUCCESS;
3004 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3005 	mlan_ds_sec_cfg *sec = MNULL;
3006 
3007 	ENTER();
3008 
3009 	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
3010 	/* Current driver only supports key length of up to 32 bytes */
3011 	if (sec->param.encrypt_key.key_len > MLAN_MAX_KEY_LENGTH) {
3012 		PRINTM(MERROR, "Key length is incorrect\n");
3013 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3014 		ret = MLAN_STATUS_FAILURE;
3015 		goto exit;
3016 	}
3017 
3018 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
3019 			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
3020 			       &sec->param.encrypt_key);
3021 
3022 	if (ret == MLAN_STATUS_SUCCESS)
3023 		ret = MLAN_STATUS_PENDING;
3024 
3025 exit:
3026 	LEAVE();
3027 	return ret;
3028 }
3029 
3030 /**
3031  *  @brief Get security keys
3032  *
3033  *  @param pmadapter	A pointer to mlan_adapter structure
3034  *  @param pioctl_req	A pointer to ioctl request buffer
3035  *
3036  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
3037  */
wlan_sec_ioctl_get_key(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3038 static mlan_status wlan_sec_ioctl_get_key(pmlan_adapter pmadapter,
3039 					  pmlan_ioctl_req pioctl_req)
3040 {
3041 	mlan_status ret = MLAN_STATUS_SUCCESS;
3042 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3043 	mlan_ds_sec_cfg *sec = MNULL;
3044 	int index;
3045 	ENTER();
3046 
3047 	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
3048 
3049 	if (pmpriv->wep_key_curr_index >= MRVL_NUM_WEP_KEY)
3050 		pmpriv->wep_key_curr_index = 0;
3051 
3052 	if ((pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) ||
3053 	    (pmpriv->sec_info.wep_status == Wlan802_11WEPKeyAbsent) ||
3054 	    pmpriv->sec_info.ewpa_enabled || pmpriv->sec_info.wpa_enabled ||
3055 	    pmpriv->sec_info.wpa2_enabled) {
3056 		sec->param.encrypt_key.key_disable = MFALSE;
3057 	} else {
3058 		sec->param.encrypt_key.key_disable = MTRUE;
3059 	}
3060 	if (sec->param.encrypt_key.key_index == MLAN_KEY_INDEX_DEFAULT) {
3061 		if ((pmpriv->wep_key[pmpriv->wep_key_curr_index].key_length) &&
3062 		    (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled)) {
3063 			index = pmpriv->wep_key_curr_index;
3064 			sec->param.encrypt_key.key_index =
3065 				pmpriv->wep_key[index].key_index;
3066 			memcpy_ext(pmadapter,
3067 				   sec->param.encrypt_key.key_material,
3068 				   pmpriv->wep_key[index].key_material,
3069 				   pmpriv->wep_key[index].key_length,
3070 				   MLAN_MAX_KEY_LENGTH);
3071 			sec->param.encrypt_key.key_len =
3072 				MIN(MLAN_MAX_KEY_LENGTH,
3073 				    pmpriv->wep_key[index].key_length);
3074 		} else if ((pmpriv->sec_info.wpa_enabled) ||
3075 			   (pmpriv->sec_info.ewpa_enabled) ||
3076 			   (pmpriv->sec_info.wpa2_enabled) ||
3077 			   (pmpriv->sec_info.wapi_enabled)) {
3078 			/* Return WPA enabled */
3079 			sec->param.encrypt_key.key_disable = MFALSE;
3080 			memcpy_ext(pmadapter,
3081 				   sec->param.encrypt_key.key_material,
3082 				   pmpriv->aes_key.key_material,
3083 				   pmpriv->aes_key.key_len,
3084 				   MLAN_MAX_KEY_LENGTH);
3085 			sec->param.encrypt_key.key_len = MIN(
3086 				MLAN_MAX_KEY_LENGTH, pmpriv->aes_key.key_len);
3087 		} else {
3088 			sec->param.encrypt_key.key_disable = MTRUE;
3089 		}
3090 	} else {
3091 		index = sec->param.encrypt_key.key_index;
3092 		if (pmpriv->wep_key[index].key_length) {
3093 			sec->param.encrypt_key.key_index =
3094 				pmpriv->wep_key[index].key_index;
3095 			memcpy_ext(pmadapter,
3096 				   sec->param.encrypt_key.key_material,
3097 				   pmpriv->wep_key[index].key_material,
3098 				   pmpriv->wep_key[index].key_length,
3099 				   MLAN_MAX_KEY_LENGTH);
3100 			sec->param.encrypt_key.key_len =
3101 				MIN(MLAN_MAX_KEY_LENGTH,
3102 				    pmpriv->wep_key[index].key_length);
3103 		} else if ((pmpriv->sec_info.wpa_enabled) ||
3104 			   (pmpriv->sec_info.ewpa_enabled) ||
3105 			   (pmpriv->sec_info.wpa2_enabled) ||
3106 			   (pmpriv->sec_info.wapi_enabled)) {
3107 			/* Return WPA enabled */
3108 			sec->param.encrypt_key.key_disable = MFALSE;
3109 		} else {
3110 			sec->param.encrypt_key.key_disable = MTRUE;
3111 		}
3112 	}
3113 
3114 	LEAVE();
3115 	return ret;
3116 }
3117 
3118 /**
3119  *  @brief Set security key(s)
3120  *
3121  *  @param pmadapter	A pointer to mlan_adapter structure
3122  *  @param pioctl_req	A pointer to ioctl request buffer
3123  *
3124  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
3125  * otherwise fail
3126  */
wlan_sec_ioctl_encrypt_key(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3127 static mlan_status wlan_sec_ioctl_encrypt_key(pmlan_adapter pmadapter,
3128 					      pmlan_ioctl_req pioctl_req)
3129 {
3130 	mlan_status status = MLAN_STATUS_SUCCESS;
3131 	mlan_ds_sec_cfg *sec = MNULL;
3132 	ENTER();
3133 	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
3134 	if (pioctl_req->action == MLAN_ACT_SET) {
3135 		if (sec->param.encrypt_key.is_wapi_key)
3136 			status = wlan_sec_ioctl_set_wapi_key(pmadapter,
3137 							     pioctl_req);
3138 		else if (sec->param.encrypt_key.key_len > MAX_WEP_KEY_SIZE)
3139 			status = wlan_sec_ioctl_set_wpa_key(pmadapter,
3140 							    pioctl_req);
3141 		else
3142 			status = wlan_sec_ioctl_set_wep_key(pmadapter,
3143 							    pioctl_req);
3144 	} else {
3145 		status = wlan_sec_ioctl_get_key(pmadapter, pioctl_req);
3146 	}
3147 	LEAVE();
3148 	return status;
3149 }
3150 
3151 /**
3152  *  @brief Query Encrpyt key
3153  *
3154  *  @param pmadapter    A pointer to mlan_adapter structure
3155  *  @param pioctl_req   A pointer to ioctl request buffer
3156  *
3157  *  @return     MLAN_STATUS_PENDING --success, otherwise fail
3158  */
wlan_sec_ioctl_query_key(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3159 static mlan_status wlan_sec_ioctl_query_key(pmlan_adapter pmadapter,
3160 					    pmlan_ioctl_req pioctl_req)
3161 {
3162 	mlan_status ret = MLAN_STATUS_SUCCESS;
3163 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3164 	mlan_ds_sec_cfg *sec = MNULL;
3165 
3166 	ENTER();
3167 
3168 	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
3169 	/* Current driver only supports get PTK/GTK */
3170 	if (pmpriv->port_open &&
3171 	    (pmpriv->sec_info.wpa_enabled || pmpriv->sec_info.wpa2_enabled ||
3172 	     pmpriv->sec_info.wapi_enabled)) {
3173 		/* Send request to firmware */
3174 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL,
3175 				       HostCmd_ACT_GEN_GET, KEY_INFO_ENABLED,
3176 				       (t_void *)pioctl_req,
3177 				       &sec->param.encrypt_key);
3178 
3179 		if (ret == MLAN_STATUS_SUCCESS)
3180 			ret = MLAN_STATUS_PENDING;
3181 	}
3182 	LEAVE();
3183 	return ret;
3184 }
3185 
3186 /**
3187  *  @brief Set/Get esupplicant status
3188  *
3189  *  @param pmadapter	A pointer to mlan_adapter structure
3190  *  @param pioctl_req	A pointer to ioctl request buffer
3191  *
3192  *  @return		MLAN_STATUS_SUCCESS --success
3193  */
wlan_sec_ioctl_ewpa_enable(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3194 static mlan_status wlan_sec_ioctl_ewpa_enable(pmlan_adapter pmadapter,
3195 					      pmlan_ioctl_req pioctl_req)
3196 {
3197 	mlan_status ret = MLAN_STATUS_SUCCESS;
3198 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3199 	mlan_ds_sec_cfg *sec = MNULL;
3200 	ENTER();
3201 	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
3202 	if (pioctl_req->action == MLAN_ACT_GET) {
3203 		sec->param.ewpa_enabled = pmpriv->sec_info.ewpa_enabled;
3204 	} else {
3205 		pmpriv->sec_info.ewpa_enabled = (t_u8)sec->param.ewpa_enabled;
3206 		PRINTM(MINFO, "Set: ewpa_enabled = %d\n",
3207 		       (int)pmpriv->sec_info.ewpa_enabled);
3208 	}
3209 	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
3210 	LEAVE();
3211 	return ret;
3212 }
3213 
3214 /**
3215  *  @brief Get esupplicant mode
3216  *
3217  *  @param pmadapter	A pointer to mlan_adapter structure
3218  *  @param pioctl_req	A pointer to ioctl request buffer
3219  *
3220  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
3221  */
wlan_sec_ioctl_esupp_mode(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3222 static mlan_status wlan_sec_ioctl_esupp_mode(pmlan_adapter pmadapter,
3223 					     pmlan_ioctl_req pioctl_req)
3224 {
3225 	mlan_status ret = MLAN_STATUS_SUCCESS;
3226 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3227 	t_u16 cmd_action = 0;
3228 	mlan_ds_sec_cfg *sec = MNULL;
3229 
3230 	ENTER();
3231 
3232 	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
3233 	if (pioctl_req->action == MLAN_ACT_SET) {
3234 		cmd_action = HostCmd_ACT_GEN_SET;
3235 		if (pmpriv->media_connected == MTRUE) {
3236 			PRINTM(MERROR,
3237 			       "Cannot set esupplicant mode configuration while connected.\n");
3238 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3239 			ret = MLAN_STATUS_FAILURE;
3240 			goto exit;
3241 		}
3242 		if (!sec->param.esupp_mode.rsn_mode ||
3243 		    (sec->param.esupp_mode.rsn_mode & RSN_TYPE_VALID_BITS) !=
3244 			    sec->param.esupp_mode.rsn_mode) {
3245 			PRINTM(MERROR, "Invalid RSN mode\n");
3246 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3247 			ret = MLAN_STATUS_FAILURE;
3248 			goto exit;
3249 		}
3250 		if (!sec->param.esupp_mode.act_paircipher ||
3251 		    (sec->param.esupp_mode.act_paircipher &
3252 		     EMBED_CIPHER_VALID_BITS) !=
3253 			    sec->param.esupp_mode.act_paircipher) {
3254 			PRINTM(MERROR, "Invalid pairwise cipher\n");
3255 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3256 			ret = MLAN_STATUS_FAILURE;
3257 			goto exit;
3258 		}
3259 		if (!sec->param.esupp_mode.act_groupcipher ||
3260 		    (sec->param.esupp_mode.act_groupcipher &
3261 		     EMBED_CIPHER_VALID_BITS) !=
3262 			    sec->param.esupp_mode.act_groupcipher) {
3263 			PRINTM(MERROR, "Invalid group cipher\n");
3264 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3265 			ret = MLAN_STATUS_FAILURE;
3266 			goto exit;
3267 		}
3268 	} else {
3269 		cmd_action = HostCmd_ACT_GEN_GET_CURRENT;
3270 	}
3271 
3272 	/* Send request to firmware */
3273 	if (sec) {
3274 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SUPPLICANT_PROFILE,
3275 				       cmd_action, 0, (t_void *)pioctl_req,
3276 				       &sec->param.esupp_mode);
3277 	} else {
3278 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SUPPLICANT_PROFILE,
3279 				       cmd_action, 0, (t_void *)pioctl_req,
3280 				       MNULL);
3281 	}
3282 	if (ret == MLAN_STATUS_SUCCESS)
3283 		ret = MLAN_STATUS_PENDING;
3284 
3285 exit:
3286 	LEAVE();
3287 	return ret;
3288 }
3289 
3290 /**
3291  *  @brief Security configuration handler
3292  *
3293  *  @param pmadapter	A pointer to mlan_adapter structure
3294  *  @param pioctl_req	A pointer to ioctl request buffer
3295  *
3296  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
3297  * otherwise fail
3298  */
wlan_sec_cfg_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3299 static mlan_status wlan_sec_cfg_ioctl(pmlan_adapter pmadapter,
3300 				      pmlan_ioctl_req pioctl_req)
3301 {
3302 	mlan_status status = MLAN_STATUS_SUCCESS;
3303 	mlan_ds_sec_cfg *sec = MNULL;
3304 
3305 	ENTER();
3306 
3307 	if (pioctl_req->buf_len < sizeof(mlan_ds_sec_cfg)) {
3308 		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
3309 		pioctl_req->data_read_written = 0;
3310 		pioctl_req->buf_len_needed = sizeof(mlan_ds_sec_cfg);
3311 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3312 		LEAVE();
3313 		return MLAN_STATUS_RESOURCE;
3314 	}
3315 	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
3316 	switch (sec->sub_command) {
3317 	case MLAN_OID_SEC_CFG_AUTH_MODE:
3318 		status = wlan_sec_ioctl_auth_mode(pmadapter, pioctl_req);
3319 		break;
3320 	case MLAN_OID_SEC_CFG_ENCRYPT_MODE:
3321 		status = wlan_sec_ioctl_encrypt_mode(pmadapter, pioctl_req);
3322 		break;
3323 	case MLAN_OID_SEC_CFG_WPA_ENABLED:
3324 		status = wlan_sec_ioctl_wpa_enable(pmadapter, pioctl_req);
3325 		break;
3326 	case MLAN_OID_SEC_CFG_WAPI_ENABLED:
3327 		status = wlan_sec_ioctl_wapi_enable(pmadapter, pioctl_req);
3328 		break;
3329 	case MLAN_OID_SEC_CFG_PORT_CTRL_ENABLED:
3330 		status = wlan_sec_ioctl_port_ctrl_enable(pmadapter, pioctl_req);
3331 		break;
3332 	case MLAN_OID_SEC_CFG_ENCRYPT_KEY:
3333 		status = wlan_sec_ioctl_encrypt_key(pmadapter, pioctl_req);
3334 		break;
3335 	case MLAN_OID_SEC_QUERY_KEY:
3336 		status = wlan_sec_ioctl_query_key(pmadapter, pioctl_req);
3337 		break;
3338 	case MLAN_OID_SEC_CFG_PASSPHRASE:
3339 		status = wlan_sec_ioctl_passphrase(pmadapter, pioctl_req);
3340 		break;
3341 	case MLAN_OID_SEC_CFG_EWPA_ENABLED:
3342 		status = wlan_sec_ioctl_ewpa_enable(pmadapter, pioctl_req);
3343 		break;
3344 	case MLAN_OID_SEC_CFG_ESUPP_MODE:
3345 		status = wlan_sec_ioctl_esupp_mode(pmadapter, pioctl_req);
3346 		break;
3347 
3348 	default:
3349 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3350 		status = MLAN_STATUS_FAILURE;
3351 		break;
3352 	}
3353 	LEAVE();
3354 	return status;
3355 }
3356 
3357 /**
3358  *  @brief  Append/Reset IE buffer.
3359  *
3360  *  Pass an opaque block of data, expected to be IEEE IEs, to the driver
3361  *    for eventual passthrough to the firmware in an associate/join
3362  *    (and potentially start) command.  This function is the main body
3363  *    for both wlan_set_gen_ie_ioctl and wlan_set_gen_ie
3364  *
3365  *  Data is appended to an existing buffer and then wrapped in a passthrough
3366  *    TLV in the command API to the firmware.  The firmware treats the data
3367  *    as a transparent passthrough to the transmitted management frame.
3368  *
3369  *  @param priv         A pointer to mlan_private structure
3370  *  @param ie_data_ptr  A pointer to iwreq structure
3371  *  @param ie_len       Length of the IE or IE block passed in ie_data_ptr
3372  *
3373  *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
3374  */
wlan_set_gen_ie_helper(mlan_private * priv,t_u8 * ie_data_ptr,t_u16 ie_len)3375 static mlan_status wlan_set_gen_ie_helper(mlan_private *priv, t_u8 *ie_data_ptr,
3376 					  t_u16 ie_len)
3377 {
3378 	mlan_status ret = MLAN_STATUS_SUCCESS;
3379 	IEEEtypes_VendorHeader_t *pvendor_ie;
3380 	const t_u8 wpa_oui[] = {0x00, 0x50, 0xf2, 0x01};
3381 	const t_u8 wps_oui[] = {0x00, 0x50, 0xf2, 0x04};
3382 	const t_u8 osen_oui[] = {0x50, 0x6f, 0x9a, 0x12};
3383 	t_u8 i = 0, temp[12] = {0};
3384 
3385 	ENTER();
3386 
3387 	/* If the passed length is zero, reset the buffer */
3388 	if (!ie_len) {
3389 		priv->gen_ie_buf_len = 0;
3390 		priv->wps.session_enable = MFALSE;
3391 		wlan_set_wpa_ie_helper(priv, MNULL, 0);
3392 		wlan_set_wapi_ie(priv, MNULL, 0);
3393 		wlan_set_osen_ie(priv, MNULL, 0);
3394 	} else if (!ie_data_ptr) {
3395 		/* MNULL check */
3396 		ret = MLAN_STATUS_FAILURE;
3397 	} else {
3398 		pvendor_ie = (IEEEtypes_VendorHeader_t *)ie_data_ptr;
3399 		if (pvendor_ie->element_id == EXT_CAPABILITY) {
3400 			memcpy_ext(priv->adapter, temp, &priv->ext_cap,
3401 				   sizeof(priv->ext_cap), sizeof(temp));
3402 			for (i = 0;
3403 			     i < MIN(sizeof(priv->ext_cap), pvendor_ie->len);
3404 			     i++)
3405 				temp[i] |= ie_data_ptr[2 + i];
3406 			memcpy_ext(priv->adapter, &priv->ext_cap, temp,
3407 				   sizeof(temp), sizeof(priv->ext_cap));
3408 		} else
3409 			/* Test to see if it is a WPA IE, if not, then it is a
3410 			   gen IE*/
3411 			if (((pvendor_ie->element_id == WPA_IE) &&
3412 			     (!memcmp(priv->adapter, pvendor_ie->oui, wpa_oui,
3413 				      sizeof(wpa_oui)))) ||
3414 			    (pvendor_ie->element_id == RSN_IE)) {
3415 			/* IE is a WPA/WPA2 IE so call set_wpa function */
3416 			ret = wlan_set_wpa_ie_helper(priv, ie_data_ptr, ie_len);
3417 			priv->wps.session_enable = MFALSE;
3418 		} else if (pvendor_ie->element_id == WAPI_IE) {
3419 			/* IE is a WAPI IE so call set_wapi function */
3420 			ret = wlan_set_wapi_ie(priv, ie_data_ptr, ie_len);
3421 		} else if ((pvendor_ie->element_id == VENDOR_SPECIFIC_221) &&
3422 			   (!memcmp(priv->adapter, pvendor_ie->oui, osen_oui,
3423 				    sizeof(osen_oui)))) {
3424 			/* IE is a OSEN IE so call set_osen function */
3425 			ret = wlan_set_osen_ie(priv, ie_data_ptr, ie_len);
3426 
3427 		} else if ((pvendor_ie->element_id == WPS_IE) &&
3428 			   (priv->wps.session_enable == MFALSE) &&
3429 			   (!memcmp(priv->adapter, pvendor_ie->oui, wps_oui,
3430 				    sizeof(wps_oui)))) {
3431 			/*
3432 			 * Discard first two byte (Element ID and Length)
3433 			 * because they are not needed in the case of setting
3434 			 * WPS_IE
3435 			 */
3436 			if (pvendor_ie->len > 4) {
3437 				memcpy_ext(priv->adapter,
3438 					   (t_u8 *)&priv->wps.wps_ie,
3439 					   ie_data_ptr, ie_len,
3440 					   sizeof(IEEEtypes_VendorSpecific_t));
3441 				HEXDUMP("wps_ie", (t_u8 *)&priv->wps.wps_ie,
3442 					priv->wps.wps_ie.vend_hdr.len + 2);
3443 			} else {
3444 				/* Only wps oui exist, reset driver wps buffer
3445 				 */
3446 				memset(priv->adapter, (t_u8 *)&priv->wps.wps_ie,
3447 				       0x00, sizeof(priv->wps.wps_ie));
3448 				PRINTM(MINFO, "wps_ie cleared\n");
3449 			}
3450 		} else {
3451 			/*
3452 			 * Verify that the passed length is not larger than
3453 			 * the available space remaining in the buffer
3454 			 */
3455 			if (ie_len <
3456 			    (sizeof(priv->gen_ie_buf) - priv->gen_ie_buf_len)) {
3457 				/* Test to see if it is a WPS IE, if so, enable
3458 				 * wps session flag */
3459 				pvendor_ie =
3460 					(IEEEtypes_VendorHeader_t *)ie_data_ptr;
3461 				if ((pvendor_ie->element_id == WPS_IE) &&
3462 				    (!memcmp(priv->adapter, pvendor_ie->oui,
3463 					     wps_oui, sizeof(wps_oui)))) {
3464 					priv->wps.session_enable = MTRUE;
3465 					PRINTM(MINFO, "WPS Session Enabled.\n");
3466 				}
3467 
3468 				/* Append the passed data to the end of
3469 				 * the genIeBuffer */
3470 				memcpy_ext(priv->adapter,
3471 					   priv->gen_ie_buf +
3472 						   priv->gen_ie_buf_len,
3473 					   ie_data_ptr, ie_len,
3474 					   MRVDRV_GENIE_BUF_SIZE -
3475 						   priv->gen_ie_buf_len);
3476 				/* Increment the stored buffer length by
3477 				 * the size passed */
3478 				priv->gen_ie_buf_len += ie_len;
3479 			} else {
3480 				/* Passed data does not fit in the
3481 				 * remaining buffer space */
3482 				ret = MLAN_STATUS_FAILURE;
3483 			}
3484 		}
3485 	}
3486 
3487 	/* Return MLAN_STATUS_SUCCESS, or MLAN_STATUS_FAILURE for error case */
3488 	LEAVE();
3489 	return ret;
3490 }
3491 
3492 /**
3493  *  @brief Set/Get WWS mode
3494  *
3495  *  @param pmadapter	A pointer to mlan_adapter structure
3496  *  @param pioctl_req	A pointer to ioctl request buffer
3497  *
3498  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
3499  */
wlan_misc_ioctl_wws_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3500 static mlan_status wlan_misc_ioctl_wws_cfg(pmlan_adapter pmadapter,
3501 					   pmlan_ioctl_req pioctl_req)
3502 {
3503 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3504 	mlan_status ret = MLAN_STATUS_SUCCESS;
3505 	mlan_ds_misc_cfg *misc_cfg = MNULL;
3506 	t_u16 cmd_action = 0;
3507 	t_u32 enable = 0;
3508 
3509 	ENTER();
3510 
3511 	if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
3512 		PRINTM(MWARN,
3513 		       "MLAN IOCTL information buffer length is too short.\n");
3514 		pioctl_req->data_read_written = 0;
3515 		pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
3516 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3517 		ret = MLAN_STATUS_RESOURCE;
3518 		goto exit;
3519 	}
3520 
3521 	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
3522 	if (pioctl_req->action == MLAN_ACT_SET)
3523 		cmd_action = HostCmd_ACT_GEN_SET;
3524 	else
3525 		cmd_action = HostCmd_ACT_GEN_GET;
3526 
3527 	enable = misc_cfg->param.wws_cfg;
3528 
3529 	/* Send request to firmware */
3530 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, cmd_action,
3531 			       WwsMode_i, (t_void *)pioctl_req, &enable);
3532 
3533 	if (ret == MLAN_STATUS_SUCCESS)
3534 		ret = MLAN_STATUS_PENDING;
3535 
3536 exit:
3537 	LEAVE();
3538 	return ret;
3539 }
3540 
3541 /**
3542  *  @brief Set/Get 11D status
3543  *
3544  *  @param pmadapter	A pointer to mlan_adapter structure
3545  *  @param pioctl_req	A pointer to ioctl request buffer
3546  *
3547  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
3548  * otherwise fail
3549  */
wlan_11d_cfg_ioctl_enable(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3550 static mlan_status wlan_11d_cfg_ioctl_enable(pmlan_adapter pmadapter,
3551 					     pmlan_ioctl_req pioctl_req)
3552 {
3553 	mlan_status ret = MLAN_STATUS_SUCCESS;
3554 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3555 	mlan_ds_11d_cfg *pcfg_11d = MNULL;
3556 
3557 	ENTER();
3558 
3559 	pcfg_11d = (mlan_ds_11d_cfg *)pioctl_req->pbuf;
3560 
3561 	if (pioctl_req->action == MLAN_ACT_SET) {
3562 		if (pmpriv->media_connected == MTRUE) {
3563 			PRINTM(MIOCTL,
3564 			       "11D setting cannot be changed while interface is active.\n");
3565 			ret = MLAN_STATUS_FAILURE;
3566 			goto done;
3567 		}
3568 
3569 		PRINTM(MINFO, "11D: 11dcfg SET=%d\n",
3570 		       pcfg_11d->param.enable_11d);
3571 
3572 		/* Compare with current settings */
3573 		if (pmpriv->state_11d.user_enable_11d !=
3574 		    pcfg_11d->param.enable_11d) {
3575 			ret = wlan_11d_enable(
3576 				pmpriv, pioctl_req,
3577 				(state_11d_t)pcfg_11d->param.enable_11d);
3578 			if (ret == MLAN_STATUS_SUCCESS)
3579 				ret = MLAN_STATUS_PENDING;
3580 		} else {
3581 			PRINTM(MINFO,
3582 			       "11D: same as current setting, do nothing\n");
3583 		}
3584 	} else {
3585 		pcfg_11d->param.enable_11d =
3586 			(t_u32)pmpriv->state_11d.user_enable_11d;
3587 		pioctl_req->data_read_written =
3588 			sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
3589 		PRINTM(MINFO, "11D: 11dcfg GET=%d\n",
3590 		       pcfg_11d->param.enable_11d);
3591 	}
3592 
3593 done:
3594 	LEAVE();
3595 	return ret;
3596 }
3597 
3598 /**
3599  *  @brief Clear 11D chan table
3600  *
3601  *  @param pmadapter	A pointer to mlan_adapter structure
3602  *  @param pioctl_req	A pointer to ioctl request buffer
3603  *
3604  *  @return		MLAN_STATUS_SUCCESS --success
3605  */
wlan_11d_clr_chan_table(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3606 static mlan_status wlan_11d_clr_chan_table(pmlan_adapter pmadapter,
3607 					   pmlan_ioctl_req pioctl_req)
3608 {
3609 	mlan_status ret = MLAN_STATUS_SUCCESS;
3610 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3611 
3612 	ENTER();
3613 
3614 	if (pioctl_req->action == MLAN_ACT_SET) {
3615 		PRINTM(MINFO, "11D: 11dclrtbl SET\n");
3616 
3617 		if (wlan_11d_clear_parsedtable(pmpriv) == MLAN_STATUS_SUCCESS)
3618 			PRINTM(MINFO,
3619 			       "11D: cleared parsed_region_chan (now no_of_chan=%d)\n",
3620 			       pmadapter->parsed_region_chan.no_of_chan);
3621 	}
3622 
3623 	LEAVE();
3624 	return ret;
3625 }
3626 
3627 /**
3628  *  @brief 11D configuration handler
3629  *
3630  *  @param pmadapter	A pointer to mlan_adapter structure
3631  *  @param pioctl_req	A pointer to ioctl request buffer
3632  *
3633  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
3634  * otherwise fail
3635  */
wlan_11d_cfg_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3636 static mlan_status wlan_11d_cfg_ioctl(pmlan_adapter pmadapter,
3637 				      pmlan_ioctl_req pioctl_req)
3638 {
3639 	mlan_status status = MLAN_STATUS_SUCCESS;
3640 	mlan_ds_11d_cfg *pcfg_11d = MNULL;
3641 
3642 	ENTER();
3643 
3644 	if (pioctl_req->buf_len < sizeof(mlan_ds_11d_cfg)) {
3645 		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
3646 		pioctl_req->data_read_written = 0;
3647 		pioctl_req->buf_len_needed = sizeof(mlan_ds_11d_cfg);
3648 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3649 		status = MLAN_STATUS_RESOURCE;
3650 		goto exit;
3651 	}
3652 
3653 	pcfg_11d = (mlan_ds_11d_cfg *)pioctl_req->pbuf;
3654 	switch (pcfg_11d->sub_command) {
3655 	case MLAN_OID_11D_CFG_ENABLE:
3656 		status = wlan_11d_cfg_ioctl_enable(pmadapter, pioctl_req);
3657 		break;
3658 	case MLAN_OID_11D_CLR_CHAN_TABLE:
3659 		status = wlan_11d_clr_chan_table(pmadapter, pioctl_req);
3660 		break;
3661 	case MLAN_OID_11D_DOMAIN_INFO_EXT:
3662 		status = wlan_11d_cfg_domain_info(pmadapter, pioctl_req);
3663 		break;
3664 	default:
3665 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3666 		status = MLAN_STATUS_FAILURE;
3667 		break;
3668 	}
3669 
3670 exit:
3671 	LEAVE();
3672 	return status;
3673 }
3674 
3675 /**
3676  *  @brief WPS configuration handler
3677  *
3678  *  @param pmadapter	A pointer to mlan_adapter structure
3679  *  @param pioctl_req	A pointer to ioctl request buffer
3680  *
3681  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
3682  */
wlan_wps_cfg_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3683 static mlan_status wlan_wps_cfg_ioctl(pmlan_adapter pmadapter,
3684 				      pmlan_ioctl_req pioctl_req)
3685 {
3686 	mlan_status status = MLAN_STATUS_SUCCESS;
3687 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3688 	mlan_ds_wps_cfg *pwps = MNULL;
3689 
3690 	ENTER();
3691 
3692 	if (pioctl_req->buf_len < sizeof(mlan_ds_wps_cfg)) {
3693 		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
3694 		pioctl_req->data_read_written = 0;
3695 		pioctl_req->buf_len_needed = sizeof(mlan_ds_wps_cfg);
3696 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3697 		LEAVE();
3698 		return MLAN_STATUS_RESOURCE;
3699 	}
3700 
3701 	pwps = (mlan_ds_wps_cfg *)pioctl_req->pbuf;
3702 	switch (pwps->sub_command) {
3703 	case MLAN_OID_WPS_CFG_SESSION:
3704 		if (pioctl_req->action == MLAN_ACT_SET) {
3705 			if (pwps->param.wps_session ==
3706 			    MLAN_WPS_CFG_SESSION_START)
3707 				pmpriv->wps.session_enable = MTRUE;
3708 			else
3709 				pmpriv->wps.session_enable = MFALSE;
3710 		} else {
3711 			pwps->param.wps_session =
3712 				(t_u32)pmpriv->wps.session_enable;
3713 			pioctl_req->data_read_written = sizeof(t_u32);
3714 			PRINTM(MINFO, "wpscfg GET=%d\n",
3715 			       pwps->param.wps_session);
3716 		}
3717 		break;
3718 	default:
3719 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3720 		status = MLAN_STATUS_FAILURE;
3721 		break;
3722 	}
3723 
3724 	LEAVE();
3725 	return status;
3726 }
3727 
3728 /**
3729  *  @brief register memory access handler
3730  *
3731  *  @param pmadapter	A pointer to mlan_adapter structure
3732  *  @param pioctl_req	A pointer to ioctl request buffer
3733  *
3734  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
3735  */
wlan_reg_mem_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3736 static mlan_status wlan_reg_mem_ioctl(pmlan_adapter pmadapter,
3737 				      pmlan_ioctl_req pioctl_req)
3738 {
3739 	mlan_status status = MLAN_STATUS_SUCCESS;
3740 	mlan_ds_reg_mem *reg_mem = MNULL;
3741 
3742 	ENTER();
3743 
3744 	if (pioctl_req->buf_len < sizeof(mlan_ds_reg_mem)) {
3745 		PRINTM(MWARN, "MLAN REG_MEM IOCTL length is too short\n");
3746 		pioctl_req->data_read_written = 0;
3747 		pioctl_req->buf_len_needed = sizeof(mlan_ds_reg_mem);
3748 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3749 		LEAVE();
3750 		return MLAN_STATUS_RESOURCE;
3751 	}
3752 	reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
3753 	switch (reg_mem->sub_command) {
3754 	case MLAN_OID_REG_RW:
3755 		status = wlan_reg_mem_ioctl_reg_rw(pmadapter, pioctl_req);
3756 		break;
3757 	case MLAN_OID_EEPROM_RD:
3758 		status = wlan_reg_mem_ioctl_read_eeprom(pmadapter, pioctl_req);
3759 		break;
3760 	case MLAN_OID_MEM_RW:
3761 		status = wlan_reg_mem_ioctl_mem_rw(pmadapter, pioctl_req);
3762 		break;
3763 	default:
3764 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3765 		status = MLAN_STATUS_FAILURE;
3766 		break;
3767 	}
3768 	LEAVE();
3769 	return status;
3770 }
3771 
3772 /**
3773  *  @brief 802.11h ad-hoc start channel check
3774  *
3775  *  @param pmadapter	A pointer to mlan_adapter structure
3776  *  @param pioctl_req	A pointer to ioctl request buffer
3777  *
3778  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
3779  */
wlan_11h_channel_check_req(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3780 static mlan_status wlan_11h_channel_check_req(pmlan_adapter pmadapter,
3781 					      pmlan_ioctl_req pioctl_req)
3782 {
3783 	pmlan_private pmpriv = MNULL;
3784 	mlan_status ret = MLAN_STATUS_FAILURE;
3785 	t_u8 chan_width = CHAN_BW_20MHZ;
3786 	Band_Config_t bandcfg;
3787 
3788 	ENTER();
3789 
3790 	if (pioctl_req != MNULL) {
3791 		pmpriv = pmadapter->priv[pioctl_req->bss_index];
3792 	} else {
3793 		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
3794 		LEAVE();
3795 		return MLAN_STATUS_FAILURE;
3796 	}
3797 
3798 	memset(pmadapter, &bandcfg, 0, sizeof(Band_Config_t));
3799 	pmpriv->adhoc_state = ADHOC_STARTING;
3800 
3801 	if ((pmadapter->adhoc_start_band & BAND_A)) {
3802 		if (pmpriv->intf_state_11h.adhoc_auto_sel_chan)
3803 			pmpriv->adhoc_channel =
3804 				wlan_11h_get_adhoc_start_channel(pmpriv);
3805 
3806 		/*
3807 		 * Check if the region and channel requires a channel
3808 		 * availability check.
3809 		 */
3810 		if (wlan_11h_radar_detect_required(pmpriv,
3811 						   pmpriv->adhoc_channel) &&
3812 		    !wlan_11h_is_channel_under_nop(pmadapter,
3813 						   pmpriv->adhoc_channel)) {
3814 			/*
3815 			 * Radar detection is required for this channel, make
3816 			 * sure 11h is activated in the firmware
3817 			 */
3818 			ret = wlan_11h_activate(pmpriv, MNULL, MTRUE);
3819 			ret = wlan_11h_config_master_radar_det(pmpriv, MTRUE);
3820 			ret = wlan_11h_check_update_radar_det_state(pmpriv);
3821 
3822 			/* Check for radar on the channel */
3823 			if ((pmadapter->chan_bandwidth ==
3824 			     CHANNEL_BW_40MHZ_ABOVE) ||
3825 			    (pmadapter->chan_bandwidth ==
3826 			     CHANNEL_BW_40MHZ_BELOW)) {
3827 				chan_width = CHAN_BW_40MHZ;
3828 				if (pmadapter->chanrpt_param_bandcfg) {
3829 					bandcfg.chan2Offset =
3830 						pmadapter->chan_bandwidth;
3831 				}
3832 			} else if (pmadapter->chan_bandwidth ==
3833 				   CHANNEL_BW_80MHZ)
3834 				chan_width = CHAN_BW_80MHZ;
3835 			if (pmadapter->chanrpt_param_bandcfg) {
3836 				bandcfg.chanWidth = chan_width;
3837 				bandcfg.chanBand = BAND_5GHZ;
3838 			} else {
3839 				*((t_u8 *)&bandcfg) = chan_width;
3840 			}
3841 
3842 			ret = wlan_11h_issue_radar_detect(pmpriv, pioctl_req,
3843 							  pmpriv->adhoc_channel,
3844 							  bandcfg);
3845 			if (ret == MLAN_STATUS_SUCCESS)
3846 				ret = MLAN_STATUS_PENDING;
3847 		}
3848 	}
3849 
3850 	LEAVE();
3851 	return ret;
3852 }
3853 
3854 /**
3855  *  @brief 802.11h set/get local power constraint
3856  *
3857  *  @param pmadapter	A pointer to mlan_adapter structure
3858  *  @param pioctl_req	A pointer to ioctl request buffer
3859  *
3860  *  @return		MLAN_STATUS_SUCCESS
3861  */
3862 static mlan_status
wlan_11h_ioctl_local_power_constraint(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3863 wlan_11h_ioctl_local_power_constraint(pmlan_adapter pmadapter,
3864 				      pmlan_ioctl_req pioctl_req)
3865 {
3866 	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
3867 	t_s8 *plocalpower = &pmadapter->state_11h.usr_def_power_constraint;
3868 
3869 	ENTER();
3870 
3871 	ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
3872 
3873 	if (pioctl_req->action == MLAN_ACT_GET)
3874 		ds_11hcfg->param.usr_local_power_constraint = *plocalpower;
3875 	else
3876 		*plocalpower = ds_11hcfg->param.usr_local_power_constraint;
3877 
3878 	LEAVE();
3879 	return MLAN_STATUS_SUCCESS;
3880 }
3881 
3882 /**
3883  *  @brief 11h configuration handler
3884  *
3885  *  @param pmadapter	A pointer to mlan_adapter structure
3886  *  @param pioctl_req	A pointer to ioctl request buffer
3887  *
3888  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
3889  * otherwise fail
3890  */
wlan_11h_cfg_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3891 static mlan_status wlan_11h_cfg_ioctl(pmlan_adapter pmadapter,
3892 				      pmlan_ioctl_req pioctl_req)
3893 {
3894 	mlan_status status = MLAN_STATUS_SUCCESS;
3895 	mlan_ds_11h_cfg *ds_11hcfg = MNULL;
3896 
3897 	ENTER();
3898 
3899 	if (pioctl_req->buf_len < sizeof(mlan_ds_11h_cfg)) {
3900 		PRINTM(MWARN, "MLAN 11H IOCTL length is too short.\n");
3901 		pioctl_req->data_read_written = 0;
3902 		pioctl_req->buf_len_needed = sizeof(mlan_ds_11h_cfg);
3903 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3904 		LEAVE();
3905 		return MLAN_STATUS_RESOURCE;
3906 	}
3907 	ds_11hcfg = (mlan_ds_11h_cfg *)pioctl_req->pbuf;
3908 
3909 	switch (ds_11hcfg->sub_command) {
3910 	case MLAN_OID_11H_CHANNEL_CHECK:
3911 		status = wlan_11h_channel_check_req(pmadapter, pioctl_req);
3912 		break;
3913 	case MLAN_OID_11H_LOCAL_POWER_CONSTRAINT:
3914 		status = wlan_11h_ioctl_local_power_constraint(pmadapter,
3915 							       pioctl_req);
3916 		break;
3917 	case MLAN_OID_11H_DFS_TESTING:
3918 		status = wlan_11h_ioctl_dfs_testing(pmadapter, pioctl_req);
3919 		break;
3920 	case MLAN_OID_11H_DFS_W53_CFG:
3921 		status = wlan_11h_ioctl_dfs_w53_cfg(pmadapter, pioctl_req);
3922 		break;
3923 	default:
3924 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
3925 		status = MLAN_STATUS_FAILURE;
3926 		break;
3927 	}
3928 
3929 	LEAVE();
3930 	return status;
3931 }
3932 
3933 /**
3934  *  @brief Set/Get generic IE
3935  *
3936  *  @param pmadapter	A pointer to mlan_adapter structure
3937  *  @param pioctl_req	A pointer to ioctl request buffer
3938  *
3939  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
3940  */
wlan_misc_ioctl_gen_ie(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)3941 static mlan_status wlan_misc_ioctl_gen_ie(pmlan_adapter pmadapter,
3942 					  pmlan_ioctl_req pioctl_req)
3943 {
3944 	mlan_status ret = MLAN_STATUS_SUCCESS;
3945 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3946 	mlan_ds_misc_cfg *misc = MNULL;
3947 
3948 	ENTER();
3949 
3950 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
3951 	switch (misc->param.gen_ie.type) {
3952 	case MLAN_IE_TYPE_GEN_IE:
3953 		if (pioctl_req->action == MLAN_ACT_GET) {
3954 			misc->param.gen_ie.len = pmpriv->wpa_ie_len;
3955 			memcpy_ext(pmadapter, misc->param.gen_ie.ie_data,
3956 				   pmpriv->wpa_ie, misc->param.gen_ie.len,
3957 				   MAX_IE_SIZE);
3958 		} else {
3959 			ret = wlan_set_gen_ie_helper(
3960 				pmpriv, misc->param.gen_ie.ie_data,
3961 				(t_u16)misc->param.gen_ie.len);
3962 		}
3963 		break;
3964 	case MLAN_IE_TYPE_ARP_FILTER:
3965 		memset(pmadapter, pmadapter->arp_filter, 0,
3966 		       sizeof(pmadapter->arp_filter));
3967 		if (misc->param.gen_ie.len > ARP_FILTER_MAX_BUF_SIZE) {
3968 			pmadapter->arp_filter_size = 0;
3969 			PRINTM(MERROR, "Invalid ARP Filter Size\n");
3970 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3971 			ret = MLAN_STATUS_FAILURE;
3972 		} else if (misc->param.gen_ie.len <=
3973 			   sizeof(MrvlIEtypesHeader_t)) {
3974 			pmadapter->arp_filter_size = 0;
3975 			PRINTM(MINFO, "Clear ARP filter\n");
3976 		} else {
3977 			memcpy_ext(pmadapter, pmadapter->arp_filter,
3978 				   misc->param.gen_ie.ie_data,
3979 				   misc->param.gen_ie.len,
3980 				   ARP_FILTER_MAX_BUF_SIZE);
3981 			pmadapter->arp_filter_size = misc->param.gen_ie.len;
3982 			HEXDUMP("ArpFilter", pmadapter->arp_filter,
3983 				pmadapter->arp_filter_size);
3984 		}
3985 		break;
3986 	default:
3987 		PRINTM(MERROR, "Invalid IE type\n");
3988 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3989 		ret = MLAN_STATUS_FAILURE;
3990 	}
3991 	pioctl_req->data_read_written =
3992 		sizeof(mlan_ds_misc_gen_ie) + MLAN_SUB_COMMAND_SIZE;
3993 	LEAVE();
3994 	return ret;
3995 }
3996 
3997 /**
3998  *  @brief Perform warm reset
3999  *
4000  *  @param pmadapter	A pointer to mlan_adapter structure
4001  *  @param pioctl_req	A pointer to ioctl request buffer
4002  *
4003  *  @return		MLAN_STATUS_PENDING --success, MLAN_STATUS_FAILURE
4004  */
wlan_misc_ioctl_warm_reset(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4005 mlan_status wlan_misc_ioctl_warm_reset(pmlan_adapter pmadapter,
4006 				       pmlan_ioctl_req pioctl_req)
4007 {
4008 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4009 	mlan_status ret = MLAN_STATUS_SUCCESS;
4010 	pmlan_callbacks pcb = &pmadapter->callbacks;
4011 	pmlan_buffer pmbuf;
4012 	t_s32 i = 0;
4013 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4014 
4015 	ENTER();
4016 	mlan_block_rx_process(pmadapter, MTRUE);
4017 
4018 	/* Cancel all pending commands and complete ioctls */
4019 	if (misc->param.fw_reload)
4020 		wlan_cancel_all_pending_cmd(pmadapter, MTRUE);
4021 
4022 	/** Init all the head nodes and free all the locks here */
4023 	for (i = 0; i < pmadapter->priv_num; i++)
4024 		wlan_free_priv(pmadapter->priv[i]);
4025 
4026 	while ((pmbuf = (pmlan_buffer)util_dequeue_list(
4027 			pmadapter->pmoal_handle, &pmadapter->rx_data_queue,
4028 			pcb->moal_spin_lock, pcb->moal_spin_unlock))) {
4029 		pmadapter->ops.data_complete(pmadapter, pmbuf,
4030 					     MLAN_STATUS_FAILURE);
4031 	}
4032 	pmadapter->rx_pkts_queued = 0;
4033 
4034 	/* Initialize adapter structure */
4035 	wlan_init_adapter(pmadapter);
4036 	pmadapter->hw_status = WlanHardwareStatusInitializing;
4037 
4038 	/* Initialize private structures */
4039 	for (i = 0; i < pmadapter->priv_num; i++) {
4040 		if (pmadapter->priv[i])
4041 			wlan_init_priv(pmadapter->priv[i]);
4042 	}
4043 	mlan_block_rx_process(pmadapter, MFALSE);
4044 
4045 	if (misc->param.fw_reload != MTRUE) {
4046 		/* Restart the firmware */
4047 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_FUNC_SHUTDOWN,
4048 				       HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
4049 		if (ret)
4050 			goto done;
4051 	}
4052 
4053 	/* Issue firmware initialize commands for first BSS,
4054 	 * for other interfaces it will be called after getting
4055 	 * the last init command response of previous interface
4056 	 */
4057 	pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
4058 	if (!pmpriv) {
4059 		ret = MLAN_STATUS_FAILURE;
4060 		LEAVE();
4061 		return ret;
4062 	}
4063 	ret = wlan_adapter_get_hw_spec(pmpriv->adapter);
4064 	if (ret == MLAN_STATUS_FAILURE) {
4065 		LEAVE();
4066 		return ret;
4067 	}
4068 	ret = pmpriv->ops.init_cmd(pmpriv, MTRUE);
4069 	if (ret == MLAN_STATUS_FAILURE) {
4070 		LEAVE();
4071 		return ret;
4072 	}
4073 	if (ret == MLAN_STATUS_PENDING)
4074 		pmadapter->pwarm_reset_ioctl_req = pioctl_req;
4075 done:
4076 	LEAVE();
4077 	return ret;
4078 }
4079 
4080 #ifdef SDIO
4081 /**
4082  *  @brief Reconfigure SDIO multiport aggregation parameters
4083  *
4084  *  @param pmadapter	A pointer to mlan_adapter structure
4085  *  @param pioctl_req	A pointer to ioctl request buffer
4086  *
4087  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
4088  */
wlan_misc_ioctl_sdio_mpa_ctrl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4089 static mlan_status wlan_misc_ioctl_sdio_mpa_ctrl(pmlan_adapter pmadapter,
4090 						 pmlan_ioctl_req pioctl_req)
4091 {
4092 	mlan_status ret = MLAN_STATUS_SUCCESS;
4093 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4094 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4095 	mlan_ds_misc_sdio_mpa_ctrl *mpa_ctrl = MNULL;
4096 
4097 	ENTER();
4098 
4099 	mpa_ctrl = &misc->param.mpa_ctrl;
4100 
4101 	if (pioctl_req->action == MLAN_ACT_SET) {
4102 		if (pmpriv->media_connected == MTRUE) {
4103 			PRINTM(MMSG,
4104 			       "SDIO MPA CTRL: not allowed in connected state\n");
4105 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
4106 			ret = MLAN_STATUS_FAILURE;
4107 			goto exit;
4108 		}
4109 
4110 		if (mpa_ctrl->tx_enable > 1) {
4111 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4112 			ret = MLAN_STATUS_FAILURE;
4113 			goto exit;
4114 		}
4115 
4116 		if (mpa_ctrl->rx_enable > 1) {
4117 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4118 			ret = MLAN_STATUS_FAILURE;
4119 			goto exit;
4120 		}
4121 
4122 		if (mpa_ctrl->tx_max_ports > SDIO_MP_AGGR_DEF_PKT_LIMIT) {
4123 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4124 			ret = MLAN_STATUS_FAILURE;
4125 			goto exit;
4126 		}
4127 
4128 		if (mpa_ctrl->rx_max_ports > SDIO_MP_AGGR_DEF_PKT_LIMIT) {
4129 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4130 			ret = MLAN_STATUS_FAILURE;
4131 			goto exit;
4132 		}
4133 
4134 		if (mpa_ctrl->tx_buf_size || mpa_ctrl->rx_buf_size) {
4135 			wlan_free_sdio_mpa_buffers(pmadapter);
4136 
4137 			if (mpa_ctrl->tx_buf_size > 0)
4138 				pmadapter->pcard_sd->mpa_tx.buf_size =
4139 					mpa_ctrl->tx_buf_size;
4140 
4141 			if (mpa_ctrl->rx_buf_size > 0)
4142 				pmadapter->pcard_sd->mpa_rx.buf_size =
4143 					mpa_ctrl->rx_buf_size;
4144 
4145 			if (wlan_alloc_sdio_mpa_buffers(
4146 				    pmadapter,
4147 				    pmadapter->pcard_sd->mpa_tx.buf_size,
4148 				    pmadapter->pcard_sd->mpa_rx.buf_size) !=
4149 			    MLAN_STATUS_SUCCESS) {
4150 				PRINTM(MERROR,
4151 				       "Failed to allocate sdio mp-a buffers\n");
4152 				pioctl_req->status_code = MLAN_ERROR_NO_MEM;
4153 				ret = MLAN_STATUS_FAILURE;
4154 				goto exit;
4155 			}
4156 		}
4157 
4158 		if (mpa_ctrl->tx_max_ports > 0)
4159 			pmadapter->pcard_sd->mpa_tx.pkt_aggr_limit =
4160 				mpa_ctrl->tx_max_ports;
4161 		if (mpa_ctrl->rx_max_ports > 0)
4162 			pmadapter->pcard_sd->mpa_rx.pkt_aggr_limit =
4163 				mpa_ctrl->rx_max_ports;
4164 
4165 		pmadapter->pcard_sd->mpa_tx.enabled = (t_u8)mpa_ctrl->tx_enable;
4166 		pmadapter->pcard_sd->mpa_rx.enabled = (t_u8)mpa_ctrl->rx_enable;
4167 
4168 	} else {
4169 		mpa_ctrl->tx_enable =
4170 			(t_u16)pmadapter->pcard_sd->mpa_tx.enabled;
4171 		mpa_ctrl->rx_enable =
4172 			(t_u16)pmadapter->pcard_sd->mpa_rx.enabled;
4173 		mpa_ctrl->tx_buf_size =
4174 			(t_u16)pmadapter->pcard_sd->mpa_tx.buf_size;
4175 		mpa_ctrl->rx_buf_size =
4176 			(t_u16)pmadapter->pcard_sd->mpa_rx.buf_size;
4177 		mpa_ctrl->tx_max_ports =
4178 			(t_u16)pmadapter->pcard_sd->mpa_tx.pkt_aggr_limit;
4179 		mpa_ctrl->rx_max_ports =
4180 			(t_u16)pmadapter->pcard_sd->mpa_rx.pkt_aggr_limit;
4181 	}
4182 
4183 exit:
4184 	LEAVE();
4185 	return ret;
4186 }
4187 #endif
4188 
4189 /**
4190  *  @brief Set/Get system clock configuration
4191  *
4192  *  @param pmadapter	A pointer to mlan_adapter structure
4193  *  @param pioctl_req	A pointer to ioctl request buffer
4194  *
4195  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
4196  */
wlan_misc_ioctl_sysclock(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4197 static mlan_status wlan_misc_ioctl_sysclock(pmlan_adapter pmadapter,
4198 					    pmlan_ioctl_req pioctl_req)
4199 {
4200 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4201 	mlan_ds_misc_cfg *misc = MNULL;
4202 	mlan_status ret = MLAN_STATUS_SUCCESS;
4203 	t_u16 cmd_action = 0;
4204 
4205 	ENTER();
4206 
4207 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4208 	if (pioctl_req->action == MLAN_ACT_GET)
4209 		cmd_action = HostCmd_ACT_GEN_GET;
4210 	else
4211 		cmd_action = HostCmd_ACT_GEN_SET;
4212 
4213 	/* Send request to firmware */
4214 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_ECL_SYSTEM_CLOCK_CONFIG,
4215 			       cmd_action, 0, (t_void *)pioctl_req,
4216 			       (t_void *)&misc->param.sys_clock);
4217 
4218 	if (ret == MLAN_STATUS_SUCCESS)
4219 		ret = MLAN_STATUS_PENDING;
4220 
4221 	LEAVE();
4222 	return ret;
4223 }
4224 
4225 /**
4226  *  @brief Get the associate response
4227  *
4228  *  @param pmadapter	A pointer to mlan_adapter structure
4229  *  @param pioctl_req	A pointer to ioctl request buffer
4230  *
4231  *  @return		MLAN_STATUS_SUCCESS --success
4232  */
wlan_misc_ioctl_get_assoc_rsp(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4233 static mlan_status wlan_misc_ioctl_get_assoc_rsp(pmlan_adapter pmadapter,
4234 						 pmlan_ioctl_req pioctl_req)
4235 {
4236 	mlan_ds_misc_cfg *misc = MNULL;
4237 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4238 	mlan_status ret = MLAN_STATUS_SUCCESS;
4239 
4240 	ENTER();
4241 
4242 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4243 	if ((pioctl_req->action == MLAN_ACT_GET) && pmpriv->assoc_rsp_size) {
4244 		memcpy_ext(pmadapter, misc->param.assoc_resp.assoc_resp_buf,
4245 			   pmpriv->assoc_rsp_buf, pmpriv->assoc_rsp_size,
4246 			   ASSOC_RSP_BUF_SIZE);
4247 		misc->param.assoc_resp.assoc_resp_len =
4248 			MIN(ASSOC_RSP_BUF_SIZE, pmpriv->assoc_rsp_size);
4249 	}
4250 
4251 	LEAVE();
4252 	return ret;
4253 }
4254 
4255 /**
4256  *  @brief Get the associate request IEs
4257  *
4258  *  @param pmadapter	A pointer to mlan_adapter structure
4259  *  @param pioctl_req	A pointer to ioctl request buffer
4260  *
4261  *  @return		MLAN_STATUS_SUCCESS --success
4262  */
wlan_misc_ioctl_get_assoc_req(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4263 static mlan_status wlan_misc_ioctl_get_assoc_req(pmlan_adapter pmadapter,
4264 						 pmlan_ioctl_req pioctl_req)
4265 {
4266 	mlan_ds_misc_cfg *misc = MNULL;
4267 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4268 	mlan_status ret = MLAN_STATUS_SUCCESS;
4269 
4270 	ENTER();
4271 
4272 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4273 	if ((pioctl_req->action == MLAN_ACT_GET) && pmpriv->assoc_req_size) {
4274 		memcpy_ext(pmadapter, misc->param.assoc_req.assoc_req_buf,
4275 			   pmpriv->assoc_req_buf, pmpriv->assoc_req_size,
4276 			   ASSOC_RSP_BUF_SIZE);
4277 		misc->param.assoc_req.assoc_req_len =
4278 			MIN(ASSOC_RSP_BUF_SIZE, pmpriv->assoc_req_size);
4279 	}
4280 
4281 	LEAVE();
4282 	return ret;
4283 }
4284 
4285 /**
4286  *  @brief Send function softreset command to firmware
4287  *
4288  *  @param pmadapter	A pointer to mlan_adapter structure
4289  *  @param pioctl_req	A pointer to ioctl request buffer
4290  *
4291  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
4292  */
wlan_misc_ioctl_soft_reset(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4293 static mlan_status wlan_misc_ioctl_soft_reset(pmlan_adapter pmadapter,
4294 					      pmlan_ioctl_req pioctl_req)
4295 {
4296 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4297 	mlan_status ret = MLAN_STATUS_SUCCESS;
4298 
4299 	ENTER();
4300 	/* Send command to firmware */
4301 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SOFT_RESET,
4302 			       HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
4303 			       MNULL);
4304 
4305 	if (ret == MLAN_STATUS_SUCCESS)
4306 		ret = MLAN_STATUS_PENDING;
4307 	LEAVE();
4308 	return ret;
4309 }
4310 
4311 /**
4312  *  @brief Get the thermal reading
4313  *
4314  *  @param pmadapter    A pointer to mlan_adapter structure
4315  *  @param pioctl_req   A pointer to ioctl request buffer
4316  *
4317  *  @return             MLAN_STATUS_PENDING -- success, otherwise fail
4318  */
wlan_misc_ioctl_thermal(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4319 static mlan_status wlan_misc_ioctl_thermal(pmlan_adapter pmadapter,
4320 					   pmlan_ioctl_req pioctl_req)
4321 {
4322 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4323 	mlan_status ret = MLAN_STATUS_SUCCESS;
4324 	t_u16 cmd_action = 0;
4325 
4326 	ENTER();
4327 
4328 	if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
4329 		PRINTM(MWARN,
4330 		       "MLAN IOCTL information buffer length is too short.\n");
4331 		pioctl_req->data_read_written = 0;
4332 		pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
4333 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4334 		LEAVE();
4335 		return MLAN_STATUS_RESOURCE;
4336 	}
4337 
4338 	if (pioctl_req->action == MLAN_ACT_SET) {
4339 		PRINTM(MERROR, "Thermal reading setting is not allowed!\n");
4340 		LEAVE();
4341 		return MLAN_STATUS_FAILURE;
4342 	} else {
4343 		cmd_action = HostCmd_ACT_GEN_GET;
4344 	}
4345 
4346 	/* Send command to firmware */
4347 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, cmd_action,
4348 			       Thermal_i, (t_void *)pioctl_req, MNULL);
4349 
4350 	if (ret == MLAN_STATUS_SUCCESS)
4351 		ret = MLAN_STATUS_PENDING;
4352 
4353 	LEAVE();
4354 	return ret;
4355 }
4356 
4357 /**
4358  *  @brief Get/Set subscribe event
4359  *
4360  *  @param pmadapter    A pointer to mlan_adapter structure
4361  *  @param pioctl_req   A pointer to ioctl request buffer
4362  *
4363  *  @return             MLAN_STATUS_PENDING -- success, otherwise fail
4364  */
wlan_misc_ioctl_subscribe_evt(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4365 static mlan_status wlan_misc_ioctl_subscribe_evt(pmlan_adapter pmadapter,
4366 						 pmlan_ioctl_req pioctl_req)
4367 {
4368 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4369 	mlan_status ret = MLAN_STATUS_SUCCESS;
4370 	mlan_ds_misc_cfg *misc = MNULL;
4371 	t_u16 cmd_action = 0;
4372 
4373 	ENTER();
4374 
4375 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4376 	if (pioctl_req->action == MLAN_ACT_SET)
4377 		cmd_action = HostCmd_ACT_GEN_SET;
4378 	else
4379 		cmd_action = HostCmd_ACT_GEN_GET;
4380 
4381 	/* Send command to firmware */
4382 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
4383 			       cmd_action, 0, (t_void *)pioctl_req,
4384 			       &misc->param.subscribe_event);
4385 
4386 	if (ret == MLAN_STATUS_SUCCESS)
4387 		ret = MLAN_STATUS_PENDING;
4388 
4389 	LEAVE();
4390 	return ret;
4391 }
4392 
4393 /**
4394  *  @brief Get/Set fw auto reconnect
4395  *
4396  *  @param pmadapter    A pointer to mlan_adapter structure
4397  *  @param pioctl_req   A pointer to ioctl request buffer
4398  *
4399  *  @return             MLAN_STATUS_PENDING -- success, otherwise fail
4400  */
wlan_misc_ioctl_fw_auto_reconnect(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4401 static mlan_status wlan_misc_ioctl_fw_auto_reconnect(pmlan_adapter pmadapter,
4402 						     pmlan_ioctl_req pioctl_req)
4403 {
4404 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4405 	mlan_status ret = MLAN_STATUS_SUCCESS;
4406 	mlan_ds_misc_cfg *misc = MNULL;
4407 	t_u16 cmd_action = 0;
4408 
4409 	ENTER();
4410 
4411 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4412 	if (pioctl_req->action == MLAN_ACT_SET)
4413 		cmd_action = HostCmd_ACT_GEN_SET;
4414 	else
4415 		cmd_action = HostCmd_ACT_GEN_GET;
4416 
4417 	/* Send command to firmware */
4418 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_FW_AUTO_RECONNECT,
4419 			       cmd_action, 0, (t_void *)pioctl_req,
4420 			       &misc->param.fw_auto_reconnect);
4421 
4422 	if (ret == MLAN_STATUS_SUCCESS)
4423 		ret = MLAN_STATUS_PENDING;
4424 
4425 	LEAVE();
4426 	return ret;
4427 }
4428 
4429 /**
4430  *  @brief Set ARP filter based on IP address
4431  *
4432  *  @param pmadapter    A pointer to mlan_adapter structure
4433  *  @param pioctl_req   A pointer to ioctl request buffer
4434  *  @param ipv4_addr    ipv4 Address
4435  *
4436  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
4437  */
wlan_ipaddr_arp_filter(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req,t_u32 ipv4_addr)4438 static mlan_status wlan_ipaddr_arp_filter(pmlan_adapter pmadapter,
4439 					  pmlan_ioctl_req pioctl_req,
4440 					  t_u32 ipv4_addr)
4441 {
4442 	mlan_status ret = MLAN_STATUS_SUCCESS;
4443 	pmlan_callbacks pcb = &pmadapter->callbacks;
4444 	t_u8 *buf;
4445 	arpfilter_header *arpfilter = MNULL;
4446 	filter_entry *entry = MNULL;
4447 	t_u32 len;
4448 
4449 	ENTER();
4450 
4451 	pcb->moal_malloc(pmadapter->pmoal_handle, MRVDRV_SIZE_OF_CMD_BUFFER,
4452 			 MLAN_MEM_DEF, &buf);
4453 	if (!buf) {
4454 		ret = MLAN_STATUS_FAILURE;
4455 		goto done;
4456 	}
4457 
4458 	/* Construct the ARP filter TLV */
4459 	arpfilter = (arpfilter_header *)buf;
4460 	arpfilter->type = wlan_cpu_to_le16(TLV_TYPE_ARP_FILTER);
4461 
4462 	if (ipv4_addr) {
4463 		arpfilter->len = wlan_cpu_to_le16(sizeof(filter_entry) * 3);
4464 		entry = (filter_entry *)(buf + sizeof(arpfilter_header));
4465 		entry->addr_type = wlan_cpu_to_le16(ADDR_TYPE_BROADCAST);
4466 		entry->eth_type = wlan_cpu_to_le16(ETHER_TYPE_ARP);
4467 		entry->ipv4_addr = wlan_cpu_to_le32(ipv4_addr);
4468 		entry++;
4469 		entry->addr_type = wlan_cpu_to_le16(ADDR_TYPE_UNICAST);
4470 		entry->eth_type = wlan_cpu_to_le16(ETHER_TYPE_ANY);
4471 		entry->ipv4_addr = wlan_cpu_to_le32(IPV4_ADDR_ANY);
4472 		entry++;
4473 		entry->addr_type = wlan_cpu_to_le16(ADDR_TYPE_MULTICAST);
4474 		entry->eth_type = wlan_cpu_to_le16(ETHER_TYPE_ANY);
4475 		entry->ipv4_addr = wlan_cpu_to_le32(IPV4_ADDR_ANY);
4476 	} else
4477 		arpfilter->len = 0;
4478 
4479 	/* Update the total length */
4480 	len = sizeof(arpfilter_header) + wlan_le16_to_cpu(arpfilter->len);
4481 
4482 	memset(pmadapter, pmadapter->arp_filter, 0,
4483 	       sizeof(pmadapter->arp_filter));
4484 	if (len > ARP_FILTER_MAX_BUF_SIZE) {
4485 		pmadapter->arp_filter_size = 0;
4486 		PRINTM(MERROR, "Invalid ARP Filter Size\n");
4487 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4488 		ret = MLAN_STATUS_FAILURE;
4489 	} else if (len <= sizeof(MrvlIEtypesHeader_t)) {
4490 		pmadapter->arp_filter_size = 0;
4491 		PRINTM(MINFO, "Clear ARP filter\n");
4492 	} else {
4493 		memcpy_ext(pmadapter, pmadapter->arp_filter, buf, len,
4494 			   ARP_FILTER_MAX_BUF_SIZE);
4495 		pmadapter->arp_filter_size = len;
4496 		HEXDUMP("ArpFilter", pmadapter->arp_filter,
4497 			pmadapter->arp_filter_size);
4498 	}
4499 
4500 done:
4501 	if (buf)
4502 		pcb->moal_mfree(pmadapter->pmoal_handle, buf);
4503 	LEAVE();
4504 	return ret;
4505 }
4506 
4507 /**
4508  *  @brief MEF configuration
4509  *
4510  *  @param pmadapter    A pointer to mlan_adapter structure
4511  *  @param pioctl_req   A pointer to ioctl request buffer
4512  *
4513  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
4514  */
wlan_misc_ioctl_mef_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4515 static mlan_status wlan_misc_ioctl_mef_cfg(pmlan_adapter pmadapter,
4516 					   pmlan_ioctl_req pioctl_req)
4517 {
4518 	mlan_status ret = MLAN_STATUS_SUCCESS;
4519 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4520 	mlan_ds_misc_mef_cfg *mef_cfg =
4521 		&((mlan_ds_misc_cfg *)pioctl_req->pbuf)->param.mef_cfg;
4522 	pmlan_callbacks pcb = &pmadapter->callbacks;
4523 	HostCmd_DS_GEN *hostcmd_hdr;
4524 	HostCmd_DS_MEF_CFG *mefcmd;
4525 	mlan_ds_misc_cmd *hostcmd = MNULL;
4526 	t_u32 buf_len = 0;
4527 	t_u8 *buf, *filter;
4528 	t_u8 fltr_buf[] = {0x02, 0x00, 0x2f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
4529 			   0x01, 0x00, 0x5e, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00,
4530 			   0x01, 0x41, 0x06, 0x00, 0x00, 0x00, 0x01, 0xff, 0x01,
4531 			   0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x41, 0x45, 0x01,
4532 			   0x00, 0x00, 0x00, 0x01, 0x33, 0x33, 0x02, 0x02, 0x00,
4533 			   0x00, 0x00, 0x00, 0x01, 0x41, 0x45};
4534 
4535 	ENTER();
4536 
4537 	/* GET operation */
4538 	if (pioctl_req->action == MLAN_ACT_GET) {
4539 		/* TODO: need to store for get operation */
4540 		goto done;
4541 	}
4542 
4543 	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
4544 			       sizeof(mlan_ds_misc_cmd), MLAN_MEM_DEF,
4545 			       (t_u8 **)&hostcmd);
4546 
4547 	if (ret != MLAN_STATUS_SUCCESS || hostcmd == MNULL) {
4548 		PRINTM(MERROR, "Failed to allocate hostcmd  buffer\n");
4549 		pioctl_req->status_code = MLAN_ERROR_NO_MEM;
4550 		ret = MLAN_STATUS_FAILURE;
4551 		goto done;
4552 	}
4553 
4554 	memset(pmpriv->adapter, hostcmd, 0, sizeof(mlan_ds_misc_cmd));
4555 	buf = hostcmd->cmd;
4556 
4557 	/* Prepare hostcmd buffer */
4558 	hostcmd_hdr = (HostCmd_DS_GEN *)(buf);
4559 	hostcmd_hdr->command = wlan_cpu_to_le16(HostCmd_CMD_MEF_CFG);
4560 	mefcmd = (HostCmd_DS_MEF_CFG *)(buf + S_DS_GEN);
4561 	buf_len = S_DS_GEN;
4562 
4563 	switch (mef_cfg->sub_id) {
4564 	case MEF_CFG_DISABLE:
4565 		PRINTM(MINFO, "Disable MEF\n");
4566 		mefcmd->criteria = wlan_cpu_to_le32(0);
4567 		mefcmd->nentries = wlan_cpu_to_le16(0);
4568 		buf_len += sizeof(HostCmd_DS_MEF_CFG);
4569 		break;
4570 	case MEF_CFG_RX_FILTER_ENABLE:
4571 		PRINTM(MINFO, "Enable Rx filter\n");
4572 		mefcmd->criteria = wlan_cpu_to_le32((MBIT(3) | MBIT(0)));
4573 		mefcmd->nentries = wlan_cpu_to_le16(1);
4574 		buf_len += sizeof(HostCmd_DS_MEF_CFG);
4575 		filter = buf + buf_len;
4576 		memcpy_ext(pmpriv->adapter, filter, fltr_buf, sizeof(fltr_buf),
4577 			   MRVDRV_SIZE_OF_CMD_BUFFER - buf_len);
4578 		buf_len += sizeof(fltr_buf);
4579 		break;
4580 	case MEF_CFG_AUTO_ARP_RESP:
4581 		PRINTM(MINFO, "Enable auto ARP response\n");
4582 		/* TODO */
4583 		break;
4584 	case MEF_CFG_HOSTCMD:
4585 		PRINTM(MINFO, "MEF hostcmd from MOAL\n");
4586 		filter = buf + buf_len;
4587 		memcpy_ext(pmpriv->adapter, filter, mef_cfg->param.cmd_buf.cmd,
4588 			   mef_cfg->param.cmd_buf.len,
4589 			   MRVDRV_SIZE_OF_CMD_BUFFER - buf_len);
4590 		buf_len += mef_cfg->param.cmd_buf.len;
4591 		break;
4592 	default:
4593 		PRINTM(MERROR, "Invalid sub ID parameter\n");
4594 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4595 		ret = MLAN_STATUS_FAILURE;
4596 		goto done;
4597 		break;
4598 	}
4599 	hostcmd_hdr->size = wlan_cpu_to_le16(buf_len);
4600 	hostcmd->len = buf_len;
4601 
4602 	/* Send command to firmware */
4603 	ret = wlan_prepare_cmd(pmpriv, 0, 0, 0, (t_void *)pioctl_req,
4604 			       (t_void *)hostcmd);
4605 	if (ret == MLAN_STATUS_SUCCESS)
4606 		ret = MLAN_STATUS_PENDING;
4607 
4608 done:
4609 	if (hostcmd)
4610 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
4611 
4612 	LEAVE();
4613 	return ret;
4614 }
4615 
4616 /**
4617  *  @brief ipaddr configuration
4618  *
4619  *  @param pmadapter    A pointer to mlan_adapter structure
4620  *  @param pioctl_req   A pointer to ioctl request buffer
4621  *
4622  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
4623  */
wlan_misc_ioctl_ipaddr_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4624 static mlan_status wlan_misc_ioctl_ipaddr_cfg(pmlan_adapter pmadapter,
4625 					      pmlan_ioctl_req pioctl_req)
4626 {
4627 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4628 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4629 	mlan_status ret = MLAN_STATUS_SUCCESS;
4630 	t_u32 ipv4_addr[MAX_IPADDR] = {0};
4631 	int i = 0;
4632 
4633 	ENTER();
4634 
4635 	/* GET operation */
4636 	if (pioctl_req->action == MLAN_ACT_GET) {
4637 		memcpy_ext(pmadapter, misc->param.ipaddr_cfg.ip_addr,
4638 			   pmpriv->ip_addr, IPADDR_LEN, IPADDR_LEN);
4639 		misc->param.ipaddr_cfg.op_code = pmpriv->op_code;
4640 		goto done;
4641 	}
4642 	/* only one IP is supported in current firmware */
4643 	for (i = 0; i < (int)misc->param.ipaddr_cfg.ip_addr_num; i++) {
4644 		memcpy_ext(pmadapter, &ipv4_addr[i],
4645 			   misc->param.ipaddr_cfg.ip_addr[i], sizeof(t_u32),
4646 			   sizeof(t_u32));
4647 	}
4648 
4649 	if (misc->param.ipaddr_cfg.op_code != MLAN_IPADDR_OP_IP_REMOVE &&
4650 	    !misc->param.ipaddr_cfg.ip_addr_num) {
4651 		PRINTM(MERROR, "Invalid IPv4 address\n");
4652 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4653 		ret = MLAN_STATUS_FAILURE;
4654 		goto done;
4655 	}
4656 	if (misc->param.ipaddr_cfg.op_code & MLAN_IPADDR_OP_ARP_FILTER)
4657 		ret = wlan_ipaddr_arp_filter(pmadapter, pioctl_req,
4658 					     ipv4_addr[0]);
4659 	else if (pmpriv->op_code & MLAN_IPADDR_OP_ARP_FILTER)
4660 		ret = wlan_ipaddr_arp_filter(pmadapter, pioctl_req, 0);
4661 	if (ret == MLAN_STATUS_FAILURE)
4662 		goto done;
4663 
4664 	/* Save the values in MLAN */
4665 	if (pioctl_req->action == MLAN_ACT_SET) {
4666 		pmpriv->op_code = misc->param.ipaddr_cfg.op_code;
4667 		memcpy_ext(pmadapter, pmpriv->ip_addr,
4668 			   misc->param.ipaddr_cfg.ip_addr, IPADDR_LEN,
4669 			   IPADDR_LEN);
4670 	}
4671 
4672 done:
4673 	LEAVE();
4674 	return ret;
4675 }
4676 
4677 /**
4678  *  @brief CFP code configuration
4679  *
4680  *  @param pmadapter    A pointer to mlan_adapter structure
4681  *  @param pioctl_req   A pointer to ioctl request buffer
4682  *
4683  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
4684  */
wlan_misc_ioctl_cfp_code_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4685 static mlan_status wlan_misc_ioctl_cfp_code_cfg(pmlan_adapter pmadapter,
4686 						pmlan_ioctl_req pioctl_req)
4687 {
4688 	mlan_status ret = MLAN_STATUS_SUCCESS;
4689 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4690 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4691 	mlan_ds_misc_cfp_code *cfp_code = MNULL;
4692 	t_u32 region_bg = 0;
4693 	t_u32 region_a = 0;
4694 	int i;
4695 
4696 	ENTER();
4697 
4698 	cfp_code = &misc->param.cfp_code;
4699 	if (pioctl_req->action == MLAN_ACT_SET) {
4700 		if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
4701 			PRINTM(MERROR,
4702 			       "ForceRegionRule is set in the on-chip OTP"
4703 			       "memory\n");
4704 			ret = MLAN_STATUS_FAILURE;
4705 			goto done;
4706 		}
4707 		/* Save the values in MLAN */
4708 		if (!cfp_code->cfp_code_bg)
4709 			cfp_code->cfp_code_bg = pmadapter->cfp_code_bg;
4710 		for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
4711 			/* Use the region code to search for the index */
4712 			if (cfp_code->cfp_code_bg == region_code_index[i]) {
4713 				region_bg = cfp_code->cfp_code_bg;
4714 				break;
4715 			}
4716 		}
4717 		if (!cfp_code->cfp_code_a)
4718 			cfp_code->cfp_code_a = pmadapter->cfp_code_a;
4719 		for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
4720 			/* Use the region code to search for the index */
4721 			if (cfp_code->cfp_code_a == region_code_index[i]) {
4722 				region_a = cfp_code->cfp_code_a;
4723 				break;
4724 			}
4725 		}
4726 		if (!region_a) {
4727 			for (i = 0; i < MRVDRV_MAX_CFP_CODE_A; i++) {
4728 				/* Use the CFP code to search for the index */
4729 				if (cfp_code->cfp_code_a == cfp_code_index_a[i])
4730 					break;
4731 			}
4732 			if (i >= MRVDRV_MAX_CFP_CODE_A) {
4733 				PRINTM(MERROR,
4734 				       "CFP Code not identified for A\n");
4735 				pioctl_req->status_code =
4736 					MLAN_ERROR_INVALID_PARAMETER;
4737 				ret = MLAN_STATUS_FAILURE;
4738 				goto done;
4739 			}
4740 		}
4741 		pmadapter->cfp_code_bg = (t_u8)cfp_code->cfp_code_bg;
4742 		pmadapter->cfp_code_a = (t_u8)cfp_code->cfp_code_a;
4743 		if (region_bg && region_a && (region_bg == region_a))
4744 			pmadapter->region_code = pmadapter->cfp_code_a;
4745 		else
4746 			pmadapter->region_code = 0;
4747 		if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
4748 					 pmadapter->config_bands |
4749 						 pmadapter->adhoc_start_band)) {
4750 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4751 			ret = MLAN_STATUS_FAILURE;
4752 			goto done;
4753 		}
4754 	} else {
4755 		/* GET operation */
4756 		cfp_code->cfp_code_bg = pmadapter->cfp_code_bg;
4757 		cfp_code->cfp_code_a = pmadapter->cfp_code_a;
4758 	}
4759 
4760 done:
4761 	LEAVE();
4762 	return ret;
4763 }
4764 
4765 /**
4766  *  @brief This function sets up country code and downloads CMD to FW
4767  *
4768  *  @param pmadapter    A pointer to mlan_adapter structure
4769  *  @param pioctl_req   Pointer to the IOCTL request buffer
4770  *
4771  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4772  */
wlan_misc_ioctl_country_code(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)4773 static mlan_status wlan_misc_ioctl_country_code(pmlan_adapter pmadapter,
4774 						mlan_ioctl_req *pioctl_req)
4775 {
4776 	mlan_status ret = MLAN_STATUS_SUCCESS;
4777 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4778 	mlan_ds_misc_country_code *country_code = MNULL;
4779 	mlan_ds_misc_cfg *cfg_misc = MNULL;
4780 	t_u8 cfp_bg = 0, cfp_a = 0;
4781 
4782 	ENTER();
4783 
4784 	cfg_misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4785 	country_code = &cfg_misc->param.country_code;
4786 
4787 	if (pioctl_req->action == MLAN_ACT_SET) {
4788 		if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
4789 			PRINTM(MERROR,
4790 			       "ForceRegionRule is set in the on-chip OTP"
4791 			       "memory\n");
4792 			ret = MLAN_STATUS_FAILURE;
4793 			goto done;
4794 		}
4795 		/* Update region code and table based on country code */
4796 		if (wlan_misc_country_2_cfp_table_code(
4797 			    pmadapter, country_code->country_code, &cfp_bg,
4798 			    &cfp_a)) {
4799 			PRINTM(MERROR, "Country code not found!\n");
4800 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4801 			ret = MLAN_STATUS_FAILURE;
4802 			goto done;
4803 		}
4804 		pmadapter->cfp_code_bg = cfp_bg;
4805 		pmadapter->cfp_code_a = cfp_a;
4806 		if (cfp_a)
4807 			pmadapter->region_code = cfp_a;
4808 		else if (cfp_bg)
4809 			pmadapter->region_code = cfp_bg;
4810 		else
4811 			pmadapter->region_code = 0;
4812 		if (wlan_set_regiontable(pmpriv, pmadapter->region_code,
4813 					 pmadapter->config_bands |
4814 						 pmadapter->adhoc_start_band)) {
4815 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4816 			ret = MLAN_STATUS_FAILURE;
4817 			goto done;
4818 		}
4819 		memcpy_ext(pmadapter, pmadapter->country_code,
4820 			   country_code->country_code, COUNTRY_CODE_LEN,
4821 			   COUNTRY_CODE_LEN);
4822 	} else {
4823 		/* GET operation */
4824 		memcpy_ext(pmadapter, country_code->country_code,
4825 			   pmadapter->country_code, COUNTRY_CODE_LEN,
4826 			   COUNTRY_CODE_LEN);
4827 	}
4828 
4829 done:
4830 	LEAVE();
4831 	return ret;
4832 }
4833 
4834 /**
4835  *  @brief Configure MFPC and MFPR for management frame protection
4836  *
4837  *  @param pmadapter    A pointer to mlan_adapter structure
4838  *  @param pioctl_req   Pointer to the IOCTL request buffer
4839  *
4840  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4841  */
wlan_misc_pmfcfg(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)4842 static mlan_status wlan_misc_pmfcfg(pmlan_adapter pmadapter,
4843 				    mlan_ioctl_req *pioctl_req)
4844 {
4845 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4846 	mlan_status ret = MLAN_STATUS_SUCCESS;
4847 	mlan_ds_misc_cfg *cfg_misc = MNULL;
4848 	mlan_ds_misc_pmfcfg *pmfcfg;
4849 
4850 	cfg_misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4851 	pmfcfg = &cfg_misc->param.pmfcfg;
4852 
4853 	if (pioctl_req->action == MLAN_ACT_SET) {
4854 		pmpriv->pmfcfg.mfpc = pmfcfg->mfpc;
4855 		pmpriv->pmfcfg.mfpr = pmfcfg->mfpr;
4856 	} else {
4857 		/* GET operation */
4858 		pmfcfg->mfpc = pmpriv->pmfcfg.mfpc;
4859 		pmfcfg->mfpr = pmpriv->pmfcfg.mfpr;
4860 	}
4861 
4862 	LEAVE();
4863 	return ret;
4864 }
4865 
4866 /**
4867  *  @brief HW ARB Cfg
4868  *
4869  *  @param pmadapter   A pointer to mlan_adapter structure
4870  *  @param pioctl_req  A pointer to ioctl request buffer
4871  *
4872  *  @return        MLAN_STATUS_PENDING --success, otherwise fail
4873  */
wlan_misc_ioctl_arb_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4874 mlan_status wlan_misc_ioctl_arb_cfg(pmlan_adapter pmadapter,
4875 				    pmlan_ioctl_req pioctl_req)
4876 {
4877 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4878 	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4879 	mlan_status ret = MLAN_STATUS_SUCCESS;
4880 	t_u16 cmd_action = 0;
4881 
4882 	ENTER();
4883 
4884 	if (pioctl_req->action == MLAN_ACT_SET)
4885 		cmd_action = HostCmd_ACT_GEN_SET;
4886 	else
4887 		cmd_action = HostCmd_ACT_GEN_GET;
4888 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_ARB_CONFIG, cmd_action, 0,
4889 			       (t_void *)pioctl_req, &(pmisc->param.arb_cfg));
4890 	if (ret == MLAN_STATUS_SUCCESS)
4891 		ret = MLAN_STATUS_PENDING;
4892 
4893 	LEAVE();
4894 	return ret;
4895 }
4896 
4897 /**
4898  *  @brief Save tp accounting command configurations.
4899  *
4900  *  @param pmadapter   A pointer to mlan_adapter structure
4901  *  @param pioctl_req  A pointer to ioctl request buffer
4902  *
4903  *  @return        MLAN_STATUS_PENDING --success, otherwise fail
4904  */
wlan_misc_ioctl_tp_state(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4905 mlan_status wlan_misc_ioctl_tp_state(pmlan_adapter pmadapter,
4906 				     pmlan_ioctl_req pioctl_req)
4907 {
4908 	mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4909 	mlan_status ret = MLAN_STATUS_SUCCESS;
4910 
4911 	ENTER();
4912 
4913 	pmadapter->tp_state_on = pmisc->param.tp_state.on;
4914 	pmadapter->tp_state_drop_point = pmisc->param.tp_state.drop_point;
4915 
4916 	LEAVE();
4917 	return ret;
4918 }
4919 
wlan_misc_ioctl_ips_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4920 static mlan_status wlan_misc_ioctl_ips_cfg(pmlan_adapter pmadapter,
4921 					   pmlan_ioctl_req pioctl_req)
4922 {
4923 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4924 	mlan_ds_misc_cfg *misc = MNULL;
4925 	t_u16 cmd_action = 0;
4926 	mlan_status ret = MLAN_STATUS_SUCCESS;
4927 
4928 	ENTER();
4929 
4930 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4931 	cmd_action = HostCmd_ACT_GEN_SET;
4932 
4933 	/* Send request to firmware */
4934 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_IPS_CONFIG, cmd_action, 0,
4935 			       (t_void *)pioctl_req, &misc->param.ips_ctrl);
4936 
4937 	if (ret == MLAN_STATUS_SUCCESS)
4938 		ret = MLAN_STATUS_PENDING;
4939 
4940 	LEAVE();
4941 	return ret;
4942 }
4943 
4944 /**
4945  *  @brief IPv6 Router Advertisement offload configuration
4946  *
4947  *  @param pmadapter    A pointer to mlan_adapter structure
4948  *  @param pioctl_req   Pointer to the IOCTL request buffer
4949  *
4950  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4951  */
wlan_misc_ioctl_ipv6_ra_offload(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)4952 mlan_status wlan_misc_ioctl_ipv6_ra_offload(pmlan_adapter pmadapter,
4953 					    mlan_ioctl_req *pioctl_req)
4954 {
4955 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4956 	mlan_ds_misc_cfg *misc = MNULL;
4957 	t_u16 cmd_action = 0;
4958 	mlan_status ret = MLAN_STATUS_SUCCESS;
4959 
4960 	ENTER();
4961 
4962 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4963 	if (pioctl_req->action == MLAN_ACT_SET)
4964 		cmd_action = HostCmd_ACT_GEN_SET;
4965 	else if (pioctl_req->action == MLAN_ACT_GET)
4966 		cmd_action = HostCmd_ACT_GEN_GET;
4967 
4968 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_IPV6_RA_OFFLOAD_CFG,
4969 			       cmd_action, 0, (t_void *)pioctl_req,
4970 			       &misc->param.ipv6_ra_offload);
4971 	if (ret == MLAN_STATUS_SUCCESS)
4972 		ret = MLAN_STATUS_PENDING;
4973 
4974 	LEAVE();
4975 	return ret;
4976 }
4977 
4978 /**
4979  *  @brief Gtk Rekey Offload
4980  *
4981  *  @param pmadapter	A pointer to mlan_adapter structure
4982  *  @param pioctl_req	A pointer to ioctl request buffer
4983  *
4984  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
4985  */
wlan_misc_ioctl_gtk_rekey_offload(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)4986 static mlan_status wlan_misc_ioctl_gtk_rekey_offload(pmlan_adapter pmadapter,
4987 						     pmlan_ioctl_req pioctl_req)
4988 {
4989 	mlan_status ret = MLAN_STATUS_SUCCESS;
4990 	mlan_ds_misc_cfg *misc_cfg = MNULL;
4991 	t_u16 cmd_action = 0;
4992 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4993 
4994 	ENTER();
4995 	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4996 	if (pioctl_req->action == MLAN_ACT_SET)
4997 		cmd_action = HostCmd_ACT_GEN_SET;
4998 	else if (pioctl_req->action == MLAN_ACT_CLEAR)
4999 		cmd_action = HostCmd_ACT_GEN_REMOVE;
5000 	else
5001 		cmd_action = HostCmd_ACT_GEN_GET;
5002 
5003 	if (!pmpriv->wpa_is_gtk_set) {
5004 		/* Store the gtk rekey data if it has already set gtk */
5005 		memcpy_ext(pmadapter, &pmpriv->gtk_rekey,
5006 			   &misc_cfg->param.gtk_rekey,
5007 			   sizeof(mlan_ds_misc_gtk_rekey_data),
5008 			   sizeof(mlan_ds_misc_gtk_rekey_data));
5009 		LEAVE();
5010 		return ret;
5011 	}
5012 	/* Send request to firmware if it hasn't set gtk yet */
5013 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG,
5014 			       cmd_action, 0, (t_void *)pioctl_req,
5015 			       &misc_cfg->param.gtk_rekey);
5016 
5017 	if (ret == MLAN_STATUS_SUCCESS)
5018 		ret = MLAN_STATUS_PENDING;
5019 
5020 	LEAVE();
5021 	return ret;
5022 }
5023 
5024 /**
5025  *  @brief enable/disable roam offload in firmware
5026  *
5027  *  @param pmadapter    A pointer to mlan_adapter structure
5028  *  @param pioctl_req   Pointer to the IOCTL request buffer
5029  *
5030  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5031  */
wlan_misc_roam_offload(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)5032 static mlan_status wlan_misc_roam_offload(pmlan_adapter pmadapter,
5033 					  mlan_ioctl_req *pioctl_req)
5034 {
5035 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
5036 	mlan_ds_misc_cfg *misc = MNULL;
5037 	t_u16 cmd_action = 0;
5038 	mlan_status ret = MLAN_STATUS_SUCCESS;
5039 
5040 	ENTER();
5041 
5042 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
5043 
5044 	if (!(pmadapter->fw_cap_info & FW_ROAMING_SUPPORT)) {
5045 		PRINTM(MERROR, "Firmware roaming not support\n");
5046 		LEAVE();
5047 		return MLAN_STATUS_FAILURE;
5048 	}
5049 
5050 	if (!IS_FW_SUPPORT_SUPPLICANT(pmadapter)) {
5051 		PRINTM(MERROR, "Embedded supplicant do not enable\n");
5052 		LEAVE();
5053 		return MLAN_STATUS_FAILURE;
5054 	}
5055 
5056 	if ((misc->param.roam_offload.config_mode == ROAM_OFFLOAD_ENABLE) &&
5057 	    misc->param.roam_offload.userset_passphrase) {
5058 		pmpriv->adapter->userset_passphrase =
5059 			misc->param.roam_offload.userset_passphrase;
5060 		if (!misc->param.roam_offload.enable) {
5061 			LEAVE();
5062 			return MLAN_STATUS_SUCCESS;
5063 		}
5064 	}
5065 
5066 	if (pioctl_req->action == MLAN_ACT_SET)
5067 		cmd_action = HostCmd_ACT_GEN_SET;
5068 	else {
5069 		PRINTM(MERROR, "Unsupported cmd_action\n");
5070 		LEAVE();
5071 		return MLAN_STATUS_FAILURE;
5072 	}
5073 
5074 	/* Send request to firmware */
5075 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_ROAM_OFFLOAD, cmd_action, 0,
5076 			       (t_void *)pioctl_req, &misc->param.roam_offload);
5077 
5078 	if (ret == MLAN_STATUS_SUCCESS)
5079 		ret = MLAN_STATUS_PENDING;
5080 
5081 	LEAVE();
5082 	return ret;
5083 }
5084 
5085 /**
5086  *  @brief set roam offload aplist to firmware
5087  *
5088  *  @param pmadapter    A pointer to mlan_adapter structure
5089  *  @param pioctl_req   Pointer to the IOCTL request buffer
5090  *
5091  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5092  */
wlan_misc_roam_offload_aplist(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)5093 static mlan_status wlan_misc_roam_offload_aplist(pmlan_adapter pmadapter,
5094 						 mlan_ioctl_req *pioctl_req)
5095 {
5096 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
5097 	mlan_ds_misc_cfg *misc = MNULL;
5098 	t_u16 cmd_action = 0;
5099 	mlan_status ret = MLAN_STATUS_SUCCESS;
5100 
5101 	ENTER();
5102 
5103 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
5104 
5105 	if (pioctl_req->action == MLAN_ACT_SET)
5106 		cmd_action = HostCmd_ACT_GEN_SET;
5107 	else {
5108 		PRINTM(MERROR, "Unsupported cmd_action\n");
5109 		LEAVE();
5110 		return MLAN_STATUS_FAILURE;
5111 	}
5112 
5113 	/* Send request to firmware */
5114 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_ROAM_OFFLOAD, cmd_action, 0,
5115 			       (t_void *)pioctl_req, &misc->param.roam_offload);
5116 
5117 	if (ret == MLAN_STATUS_SUCCESS)
5118 		ret = MLAN_STATUS_PENDING;
5119 
5120 	LEAVE();
5121 	return ret;
5122 }
5123 
5124 /**
5125  *  @brief cloud keep alive
5126  *
5127  *  @param pmadapter    A pointer to mlan_adapter structure
5128  *  @param pioctl_req   Pointer to the IOCTL request buffer
5129  *
5130  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5131  */
wlan_misc_cloud_keep_alive(pmlan_adapter pmadapter,mlan_ioctl_req * pioctl_req)5132 static mlan_status wlan_misc_cloud_keep_alive(pmlan_adapter pmadapter,
5133 					      mlan_ioctl_req *pioctl_req)
5134 {
5135 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
5136 	mlan_ds_misc_cfg *misc = MNULL;
5137 	t_u16 cmd_action = 0;
5138 	mlan_status ret = MLAN_STATUS_SUCCESS;
5139 
5140 	ENTER();
5141 
5142 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
5143 
5144 	if (pioctl_req->action == MLAN_ACT_SET)
5145 		cmd_action = HostCmd_ACT_GEN_SET;
5146 	else if (pioctl_req->action == MLAN_ACT_GET) {
5147 		cmd_action = HostCmd_ACT_GEN_GET;
5148 	} else if (pioctl_req->action == MLAN_ACT_RESET) {
5149 		cmd_action = HostCmd_ACT_GEN_RESET;
5150 	} else {
5151 		cmd_action = HostCmd_ACT_GEN_REMOVE;
5152 	}
5153 
5154 	/* Send request to firmware */
5155 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_AUTO_TX, cmd_action,
5156 			       OID_CLOUD_KEEP_ALIVE, (t_void *)pioctl_req,
5157 			       &misc->param.keep_alive);
5158 
5159 	if (ret == MLAN_STATUS_SUCCESS)
5160 		ret = MLAN_STATUS_PENDING;
5161 
5162 	LEAVE();
5163 	return ret;
5164 }
5165 
5166 /**
5167  *  @brief Miscellaneous configuration handler
5168  *
5169  *  @param pmadapter	A pointer to mlan_adapter structure
5170  *  @param pioctl_req	A pointer to ioctl request buffer
5171  *
5172  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
5173  * otherwise fail
5174  */
wlan_misc_cfg_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)5175 static mlan_status wlan_misc_cfg_ioctl(pmlan_adapter pmadapter,
5176 				       pmlan_ioctl_req pioctl_req)
5177 {
5178 	mlan_status status = MLAN_STATUS_SUCCESS;
5179 	mlan_ds_misc_cfg *misc = MNULL;
5180 
5181 	ENTER();
5182 
5183 	if ((pioctl_req == MNULL) || (pioctl_req->pbuf == MNULL)) {
5184 		PRINTM(MERROR, "Request buffer not found!\n");
5185 		LEAVE();
5186 		return MLAN_STATUS_FAILURE;
5187 	}
5188 	if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) {
5189 		PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n");
5190 		pioctl_req->data_read_written = 0;
5191 		pioctl_req->buf_len_needed = sizeof(mlan_ds_misc_cfg);
5192 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
5193 		LEAVE();
5194 		return MLAN_STATUS_RESOURCE;
5195 	}
5196 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
5197 	switch (misc->sub_command) {
5198 	case MLAN_OID_MISC_GEN_IE:
5199 		status = wlan_misc_ioctl_gen_ie(pmadapter, pioctl_req);
5200 		break;
5201 	case MLAN_OID_MISC_REGION:
5202 		status = wlan_misc_ioctl_region(pmadapter, pioctl_req);
5203 		break;
5204 	case MLAN_OID_MISC_WARM_RESET:
5205 		PRINTM(MCMND, "Request WARM RESET\n");
5206 		util_enqueue_list_tail(pmadapter->pmoal_handle,
5207 				       &pmadapter->ioctl_pending_q,
5208 				       (pmlan_linked_list)pioctl_req,
5209 				       pmadapter->callbacks.moal_spin_lock,
5210 				       pmadapter->callbacks.moal_spin_unlock);
5211 		pmadapter->pending_ioctl = MTRUE;
5212 		status = MLAN_STATUS_PENDING;
5213 		break;
5214 #ifdef SDIO
5215 	case MLAN_OID_MISC_SDIO_MPA_CTRL:
5216 		status = wlan_misc_ioctl_sdio_mpa_ctrl(pmadapter, pioctl_req);
5217 		break;
5218 #endif
5219 	case MLAN_OID_MISC_HOST_CMD:
5220 		status = wlan_misc_ioctl_host_cmd(pmadapter, pioctl_req);
5221 		break;
5222 	case MLAN_OID_MISC_SYS_CLOCK:
5223 		status = wlan_misc_ioctl_sysclock(pmadapter, pioctl_req);
5224 		break;
5225 	case MLAN_OID_MISC_WWS:
5226 		status = wlan_misc_ioctl_wws_cfg(pmadapter, pioctl_req);
5227 		break;
5228 	case MLAN_OID_MISC_ASSOC_RSP:
5229 		status = wlan_misc_ioctl_get_assoc_rsp(pmadapter, pioctl_req);
5230 		break;
5231 	case MLAN_OID_MISC_ASSOC_REQ:
5232 		status = wlan_misc_ioctl_get_assoc_req(pmadapter, pioctl_req);
5233 		break;
5234 	case MLAN_OID_MISC_INIT_SHUTDOWN:
5235 		status = wlan_misc_ioctl_init_shutdown(pmadapter, pioctl_req);
5236 		break;
5237 	case MLAN_OID_MISC_SOFT_RESET:
5238 		status = wlan_misc_ioctl_soft_reset(pmadapter, pioctl_req);
5239 		break;
5240 	case MLAN_OID_MISC_CUSTOM_IE:
5241 		status = wlan_misc_ioctl_custom_ie_list(pmadapter, pioctl_req,
5242 							MTRUE);
5243 		break;
5244 	case MLAN_OID_MISC_TDLS_CONFIG:
5245 		status = wlan_misc_ioctl_tdls_config(pmadapter, pioctl_req);
5246 		break;
5247 	case MLAN_OID_MISC_TDLS_OPER:
5248 		status = wlan_misc_ioctl_tdls_oper(pmadapter, pioctl_req);
5249 		break;
5250 	case MLAN_OID_MISC_GET_TDLS_IES:
5251 		status = wlan_misc_ioctl_tdls_get_ies(pmadapter, pioctl_req);
5252 		break;
5253 	case MLAN_OID_MISC_TDLS_CS_CHANNEL:
5254 		status = wlan_misc_ioctl_tdls_cs_channel(pmadapter, pioctl_req);
5255 		break;
5256 	case MLAN_OID_MISC_TDLS_IDLE_TIME:
5257 		status = wlan_misc_ioctl_tdls_idle_time(pmadapter, pioctl_req);
5258 		break;
5259 
5260 	case MLAN_OID_MISC_NET_MONITOR:
5261 		status = wlan_misc_ioctl_net_monitor(pmadapter, pioctl_req);
5262 		break;
5263 	case MLAN_OID_MISC_MAC_CONTROL:
5264 		status = wlan_misc_ioctl_mac_control(pmadapter, pioctl_req);
5265 		break;
5266 	case MLAN_OID_MISC_MEF_CFG:
5267 		status = wlan_misc_ioctl_mef_cfg(pmadapter, pioctl_req);
5268 		break;
5269 	case MLAN_OID_MISC_RX_MGMT_IND:
5270 		status = wlan_reg_rx_mgmt_ind(pmadapter, pioctl_req);
5271 		break;
5272 #ifdef DEBUG_LEVEL1
5273 	case MLAN_OID_MISC_DRVDBG:
5274 		status = wlan_set_drvdbg(pmadapter, pioctl_req);
5275 		break;
5276 #endif
5277 	case MLAN_OID_MISC_IP_ADDR:
5278 		status = wlan_misc_ioctl_ipaddr_cfg(pmadapter, pioctl_req);
5279 		break;
5280 	case MLAN_OID_MISC_CFP_CODE:
5281 		status = wlan_misc_ioctl_cfp_code_cfg(pmadapter, pioctl_req);
5282 		break;
5283 	case MLAN_OID_MISC_COUNTRY_CODE:
5284 		status = wlan_misc_ioctl_country_code(pmadapter, pioctl_req);
5285 		break;
5286 	case MLAN_OID_MISC_THERMAL:
5287 		status = wlan_misc_ioctl_thermal(pmadapter, pioctl_req);
5288 		break;
5289 	case MLAN_OID_MISC_SUBSCRIBE_EVENT:
5290 		status = wlan_misc_ioctl_subscribe_evt(pmadapter, pioctl_req);
5291 		break;
5292 	case MLAN_OID_MISC_HOTSPOT_CFG:
5293 		status = wlan_misc_hotspot_cfg(pmadapter, pioctl_req);
5294 		break;
5295 	case MLAN_OID_MISC_OTP_USER_DATA:
5296 		status = wlan_misc_otp_user_data(pmadapter, pioctl_req);
5297 		break;
5298 	case MLAN_OID_MISC_AUTO_ASSOC:
5299 		status = wlan_misc_ioctl_fw_auto_reconnect(pmadapter,
5300 							   pioctl_req);
5301 		break;
5302 #ifdef USB
5303 	case MLAN_OID_MISC_USB_AGGR_CTRL:
5304 		status = wlan_misc_ioctl_usb_aggr_ctrl(pmadapter, pioctl_req);
5305 		break;
5306 #endif
5307 	case MLAN_OID_MISC_AGGR_CTRL:
5308 		status = wlan_misc_ioctl_aggr_ctrl(pmadapter, pioctl_req);
5309 		break;
5310 	case MLAN_OID_MISC_TXCONTROL:
5311 		status = wlan_misc_ioctl_txcontrol(pmadapter, pioctl_req);
5312 		break;
5313 #ifdef STA_SUPPORT
5314 	case MLAN_OID_MISC_EXT_CAP_CFG:
5315 		status = wlan_misc_ext_capa_cfg(pmadapter, pioctl_req);
5316 		break;
5317 #endif
5318 	case MLAN_OID_MISC_PMFCFG:
5319 		status = wlan_misc_pmfcfg(pmadapter, pioctl_req);
5320 		break;
5321 #ifdef RX_PACKET_COALESCE
5322 	case MLAN_OID_MISC_RX_PACKET_COALESCE:
5323 		status = wlan_misc_ioctl_rx_pkt_coalesce_config(pmadapter,
5324 								pioctl_req);
5325 		break;
5326 #endif
5327 	case MLAN_OID_MISC_LOW_PWR_MODE:
5328 		status = wlan_misc_ioctl_low_pwr_mode(pmadapter, pioctl_req);
5329 		break;
5330 	case MLAN_OID_MISC_PMIC_CFG:
5331 		status = wlan_misc_ioctl_pmic_configure(pmadapter, pioctl_req);
5332 		break;
5333 	case MLAN_OID_MISC_CWMODE_CTRL:
5334 		status = wlan_misc_ioctl_cwmode_ctrl(pmadapter, pioctl_req);
5335 		break;
5336 	case MLAN_OID_MISC_MEF_FLT_CFG:
5337 		status = wlan_misc_ioctl_mef_flt_cfg(pmadapter, pioctl_req);
5338 		break;
5339 	case MLAN_OID_MISC_DFS_REAPTER_MODE:
5340 		status =
5341 			wlan_misc_ioctl_dfs_repeater_cfg(pmadapter, pioctl_req);
5342 		break;
5343 	case MLAN_OID_MISC_COALESCE_CFG:
5344 		status = wlan_misc_ioctl_coalesce_cfg(pmadapter, pioctl_req);
5345 		break;
5346 	case MLAN_OID_MISC_GET_SENSOR_TEMP:
5347 		status = wlan_misc_ioctl_get_sensor_temp(pmadapter, pioctl_req);
5348 		break;
5349 	case MLAN_OID_MISC_OPER_CLASS:
5350 		status = wlan_misc_ioctl_oper_class(pmadapter, pioctl_req);
5351 		break;
5352 	case MLAN_OID_MISC_OPER_CLASS_CHECK:
5353 		status = wlan_misc_ioctl_operclass_validation(pmadapter,
5354 							      pioctl_req);
5355 		break;
5356 	case MLAN_OID_MISC_IPV6_RA_OFFLOAD:
5357 		status = wlan_misc_ioctl_ipv6_ra_offload(pmadapter, pioctl_req);
5358 		break;
5359 	case MLAN_OID_MISC_GTK_REKEY_OFFLOAD:
5360 		status = wlan_misc_ioctl_gtk_rekey_offload(pmadapter,
5361 							   pioctl_req);
5362 		break;
5363 	case MLAN_OID_MISC_IND_RST_CFG:
5364 		status = wlan_misc_ioctl_ind_rst_cfg(pmadapter, pioctl_req);
5365 		break;
5366 	case MLAN_OID_MISC_MC_AGGR_CFG:
5367 		status = wlan_misc_ioctl_mc_aggr_cfg(pmadapter, pioctl_req);
5368 		break;
5369 	case MLAN_OID_MISC_CH_LOAD:
5370 		status = wlan_misc_ioctl_ch_load(pmadapter, pioctl_req);
5371 		break;
5372 	case MLAN_OID_MISC_CH_LOAD_RESULTS:
5373 		status = wlan_misc_ioctl_ch_load_results(pmadapter, pioctl_req);
5374 		break;
5375 	case MLAN_OID_MISC_GET_TSF:
5376 		status = wlan_misc_ioctl_get_tsf(pmadapter, pioctl_req);
5377 		break;
5378 	case MLAN_OID_MISC_ROAM_OFFLOAD:
5379 		status = wlan_misc_roam_offload(pmadapter, pioctl_req);
5380 		break;
5381 	case MLAN_OID_MISC_ROAM_OFFLOAD_APLIST:
5382 		status = wlan_misc_roam_offload_aplist(pmadapter, pioctl_req);
5383 		break;
5384 	case MLAN_OID_MISC_GET_CHAN_REGION_CFG:
5385 		status = wlan_misc_chan_reg_cfg(pmadapter, pioctl_req);
5386 		break;
5387 	case MLAN_OID_MISC_CLOUD_KEEP_ALIVE:
5388 		status = wlan_misc_cloud_keep_alive(pmadapter, pioctl_req);
5389 		break;
5390 	case MLAN_OID_MISC_DYN_BW:
5391 		status = wlan_misc_ioctl_dyn_bw(pmadapter, pioctl_req);
5392 		break;
5393 	case MLAN_OID_MISC_FW_DUMP_EVENT:
5394 		status = wlan_misc_ioctl_fw_dump_event(pmadapter, pioctl_req);
5395 		break;
5396 	case MLAN_OID_MISC_PER_PKT_CFG:
5397 		status = wlan_misc_per_pkt_cfg(pmadapter, pioctl_req);
5398 		break;
5399 	case MLAN_OID_MISC_ROBUSTCOEX:
5400 		status = wlan_misc_robustcoex(pmadapter, pioctl_req);
5401 		break;
5402 	case MLAN_OID_MISC_DMCS_CONFIG:
5403 		status = wlan_misc_dmcs_config(pmadapter, pioctl_req);
5404 		break;
5405 	case MLAN_OID_MISC_GET_TX_RX_HISTOGRAM:
5406 		status = wlan_get_tx_rx_histogram(pmadapter, pioctl_req);
5407 		break;
5408 	case MLAN_OID_MISC_BOOT_SLEEP:
5409 		status = wlan_misc_bootsleep(pmadapter, pioctl_req);
5410 		break;
5411 	case MLAN_OID_MISC_CFP_INFO:
5412 		status = wlan_get_cfpinfo(pmadapter, pioctl_req);
5413 		break;
5414 #if defined(PCIE)
5415 	case MLAN_OID_MISC_SSU:
5416 		if (pmadapter->ssu_buf)
5417 			status = MLAN_STATUS_FAILURE;
5418 		else
5419 			status = wlan_misc_ssu(pmadapter, pioctl_req);
5420 		break;
5421 #endif
5422 	case MLAN_OID_MISC_CSI:
5423 		status = wlan_misc_csi(pmadapter, pioctl_req);
5424 		break;
5425 	case MLAN_OID_MISC_HAL_PHY_CFG:
5426 		status = wlan_misc_hal_phy_cfg(pmadapter, pioctl_req);
5427 		break;
5428 	case MLAN_OID_MISC_GPIO_TSF_LATCH:
5429 		status = wlan_misc_gpio_tsf_latch_config(pmadapter, pioctl_req);
5430 		break;
5431 	case MLAN_OID_MISC_GET_TSF_INFO:
5432 		status = wlan_misc_get_tsf_info(pmadapter, pioctl_req);
5433 		break;
5434 	case MLAN_OID_MISC_RX_ABORT_CFG:
5435 		status = wlan_misc_ioctl_rxabortcfg(pmadapter, pioctl_req);
5436 		break;
5437 	case MLAN_OID_MISC_RX_ABORT_CFG_EXT:
5438 		status = wlan_misc_ioctl_rxabortcfg_ext(pmadapter, pioctl_req);
5439 		break;
5440 	case MLAN_OID_MISC_TX_AMPDU_PROT_MODE:
5441 		status = wlan_misc_ioctl_tx_ampdu_prot_mode(pmadapter,
5442 							    pioctl_req);
5443 		break;
5444 	case MLAN_OID_MISC_DOT11MC_UNASSOC_FTM_CFG:
5445 		status = wlan_misc_ioctl_dot11mc_unassoc_ftm_cfg(pmadapter,
5446 								 pioctl_req);
5447 		break;
5448 	case MLAN_OID_MISC_RATE_ADAPT_CFG:
5449 		status = wlan_misc_ioctl_rate_adapt_cfg(pmadapter, pioctl_req);
5450 		break;
5451 	case MLAN_OID_MISC_CCK_DESENSE_CFG:
5452 		status = wlan_misc_ioctl_cck_desense_cfg(pmadapter, pioctl_req);
5453 		break;
5454 	case MLAN_OID_MISC_GET_REGIONPWR_CFG:
5455 		status = wlan_get_rgchnpwr_cfg(pmadapter, pioctl_req);
5456 		break;
5457 	case MLAN_OID_MISC_GET_CHAN_TRPC_CFG:
5458 		status = wlan_get_chan_trpc_cfg(pmadapter, pioctl_req);
5459 		break;
5460 	case MLAN_OID_MISC_RF_TEST_GENERIC:
5461 	case MLAN_OID_MISC_RF_TEST_TX_CONT:
5462 	case MLAN_OID_MISC_RF_TEST_TX_FRAME:
5463 	case MLAN_OID_MISC_RF_TEST_HE_POWER:
5464 		status = wlan_misc_ioctl_rf_test_cfg(pmadapter, pioctl_req);
5465 		break;
5466 	case MLAN_OID_MISC_ARB_CONFIG:
5467 		status = wlan_misc_ioctl_arb_cfg(pmadapter, pioctl_req);
5468 		break;
5469 	case MLAN_OID_MISC_RANGE_EXT:
5470 		status = wlan_misc_ioctl_range_ext(pmadapter, pioctl_req);
5471 		break;
5472 	case MLAN_OID_MISC_TP_STATE:
5473 		status = wlan_misc_ioctl_tp_state(pmadapter, pioctl_req);
5474 		break;
5475 	case MLAN_OID_MISC_IPS_CFG:
5476 		status = wlan_misc_ioctl_ips_cfg(pmadapter, pioctl_req);
5477 		break;
5478 	default:
5479 		if (pioctl_req)
5480 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
5481 		status = MLAN_STATUS_FAILURE;
5482 		break;
5483 	}
5484 	LEAVE();
5485 	return status;
5486 }
5487 
5488 /**
5489  *  @brief Set/Get scan configuration parameter
5490  *
5491  *  @param pmadapter	A pointer to mlan_adapter structure
5492  *  @param pioctl_req	A pointer to ioctl request buffer
5493  *  @param action	    Set/Get
5494  *
5495  *  @return		MLAN_STATUS_SUCCESS --success
5496  */
wlan_set_get_scan_cfg(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req,t_u32 action)5497 static mlan_status wlan_set_get_scan_cfg(pmlan_adapter pmadapter,
5498 					 pmlan_ioctl_req pioctl_req,
5499 					 t_u32 action)
5500 {
5501 	mlan_ds_scan *scan = MNULL;
5502 
5503 	ENTER();
5504 
5505 	scan = (mlan_ds_scan *)pioctl_req->pbuf;
5506 	if (action == MLAN_ACT_SET) {
5507 		if (scan->param.scan_cfg.scan_type)
5508 			pmadapter->scan_type =
5509 				(t_u8)scan->param.scan_cfg.scan_type;
5510 		if (scan->param.scan_cfg.scan_mode)
5511 			pmadapter->scan_mode = scan->param.scan_cfg.scan_mode;
5512 		if (scan->param.scan_cfg.scan_probe)
5513 			pmadapter->scan_probes =
5514 				(t_u16)scan->param.scan_cfg.scan_probe;
5515 		if (scan->param.scan_cfg.scan_time.specific_scan_time)
5516 			pmadapter->specific_scan_time =
5517 				(t_u16)scan->param.scan_cfg.scan_time
5518 					.specific_scan_time;
5519 		if (scan->param.scan_cfg.scan_time.active_scan_time)
5520 			pmadapter->active_scan_time =
5521 				(t_u16)scan->param.scan_cfg.scan_time
5522 					.active_scan_time;
5523 		if (scan->param.scan_cfg.scan_time.passive_scan_time)
5524 			pmadapter->passive_scan_time =
5525 				(t_u16)scan->param.scan_cfg.scan_time
5526 					.passive_scan_time;
5527 		if (scan->param.scan_cfg.passive_to_active_scan)
5528 			pmadapter->passive_to_active_scan =
5529 				scan->param.scan_cfg.passive_to_active_scan;
5530 		if (scan->param.scan_cfg.ext_scan)
5531 			pmadapter->ext_scan = scan->param.scan_cfg.ext_scan - 1;
5532 		pmadapter->scan_chan_gap = scan->param.scan_cfg.scan_chan_gap;
5533 	}
5534 	scan->param.scan_cfg.scan_type = (t_u32)pmadapter->scan_type;
5535 	scan->param.scan_cfg.scan_mode = pmadapter->scan_mode;
5536 	scan->param.scan_cfg.scan_probe = (t_u32)pmadapter->scan_probes;
5537 	scan->param.scan_cfg.scan_time.specific_scan_time =
5538 		(t_u32)pmadapter->specific_scan_time;
5539 	scan->param.scan_cfg.scan_time.active_scan_time =
5540 		(t_u32)pmadapter->active_scan_time;
5541 	scan->param.scan_cfg.scan_time.passive_scan_time =
5542 		(t_u32)pmadapter->passive_scan_time;
5543 	scan->param.scan_cfg.passive_to_active_scan =
5544 		pmadapter->passive_to_active_scan;
5545 	scan->param.scan_cfg.ext_scan = pmadapter->ext_scan + 1;
5546 	scan->param.scan_cfg.scan_chan_gap = pmadapter->scan_chan_gap;
5547 	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
5548 
5549 	LEAVE();
5550 	return MLAN_STATUS_SUCCESS;
5551 }
5552 
5553 /**
5554  *  @brief Set/Get scan
5555  *
5556  *  @param pmadapter	A pointer to mlan_adapter structure
5557  *  @param pioctl_req	A pointer to ioctl request buffer
5558  *
5559  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
5560  * otherwise fail
5561  */
wlan_scan_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)5562 static mlan_status wlan_scan_ioctl(pmlan_adapter pmadapter,
5563 				   pmlan_ioctl_req pioctl_req)
5564 {
5565 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
5566 	mlan_status status = MLAN_STATUS_SUCCESS;
5567 	mlan_ds_scan *pscan;
5568 
5569 	ENTER();
5570 
5571 	pscan = (mlan_ds_scan *)pioctl_req->pbuf;
5572 	if (pscan->sub_command == MLAN_OID_SCAN_CONFIG ||
5573 	    pscan->sub_command == MLAN_OID_SCAN_BGSCAN_CONFIG)
5574 		goto start_config;
5575 	if (pmadapter->scan_processing && pioctl_req->action == MLAN_ACT_SET &&
5576 	    pscan->sub_command != MLAN_OID_SCAN_CANCEL) {
5577 		PRINTM(MINFO, "Scan already in process...\n");
5578 		LEAVE();
5579 		return status;
5580 	}
5581 
5582 	if (pmadapter->enable_net_mon == CHANNEL_SPEC_SNIFFER_MODE) {
5583 		PRINTM(MINFO,
5584 		       "Scan is blocked in Channel Specified Network Monitor mode...\n");
5585 		LEAVE();
5586 		return MLAN_STATUS_FAILURE;
5587 	}
5588 
5589 	if (pmadapter->scan_block && pioctl_req->action == MLAN_ACT_SET) {
5590 		PRINTM(MERROR, "Scan is blocked during association...\n");
5591 		LEAVE();
5592 		return MLAN_STATUS_FAILURE;
5593 	}
5594 start_config:
5595 	/* Set scan */
5596 	if (pioctl_req->action == MLAN_ACT_SET) {
5597 		switch (pscan->sub_command) {
5598 		case MLAN_OID_SCAN_NORMAL:
5599 			status = wlan_scan_networks(pmpriv, pioctl_req, MNULL);
5600 			break;
5601 		case MLAN_OID_SCAN_SPECIFIC_SSID:
5602 			status = wlan_scan_specific_ssid(
5603 				pmpriv, pioctl_req,
5604 				&pscan->param.scan_req.scan_ssid);
5605 			break;
5606 		case MLAN_OID_SCAN_USER_CONFIG:
5607 			status = wlan_scan_networks(
5608 				pmpriv, pioctl_req,
5609 				(wlan_user_scan_cfg *)
5610 					pscan->param.user_scan.scan_cfg_buf);
5611 			break;
5612 		case MLAN_OID_SCAN_CONFIG:
5613 			status = wlan_set_get_scan_cfg(pmadapter, pioctl_req,
5614 						       MLAN_ACT_SET);
5615 			break;
5616 		case MLAN_OID_SCAN_CANCEL:
5617 			status = wlan_cancel_pending_scan_cmd(pmadapter,
5618 							      pioctl_req);
5619 			break;
5620 		case MLAN_OID_SCAN_TABLE_FLUSH:
5621 			status = wlan_flush_scan_table(pmadapter);
5622 			break;
5623 		case MLAN_OID_SCAN_BGSCAN_CONFIG:
5624 			/* Send request to firmware */
5625 			status = wlan_prepare_cmd(
5626 				pmpriv, HostCmd_CMD_802_11_BG_SCAN_CONFIG,
5627 				HostCmd_ACT_GEN_SET, 0, (t_void *)pioctl_req,
5628 				pscan->param.user_scan.scan_cfg_buf);
5629 			break;
5630 		default:
5631 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
5632 			status = MLAN_STATUS_FAILURE;
5633 			break;
5634 		}
5635 
5636 		if ((status == MLAN_STATUS_SUCCESS) &&
5637 		    (pscan->sub_command != MLAN_OID_SCAN_TABLE_FLUSH) &&
5638 		    (pscan->sub_command != MLAN_OID_SCAN_CANCEL) &&
5639 		    (pscan->sub_command != MLAN_OID_SCAN_CONFIG)) {
5640 			PRINTM(MINFO,
5641 			       "wlan_scan_ioctl: return MLAN_STATUS_PENDING\n");
5642 			status = MLAN_STATUS_PENDING;
5643 		}
5644 	}
5645 	/* Get scan */
5646 	else {
5647 		if (pscan->sub_command == MLAN_OID_SCAN_CONFIG) {
5648 			status = wlan_set_get_scan_cfg(pmadapter, pioctl_req,
5649 						       MLAN_ACT_GET);
5650 		} else if (pscan->sub_command ==
5651 			   MLAN_OID_SCAN_GET_CURRENT_BSS) {
5652 			pscan->param.scan_resp.num_in_scan_table =
5653 				pmadapter->num_in_scan_table;
5654 			pscan->param.scan_resp.pscan_table =
5655 				(t_u8 *)&pmpriv->curr_bss_params.bss_descriptor;
5656 			pioctl_req->data_read_written =
5657 				sizeof(mlan_scan_resp) + MLAN_SUB_COMMAND_SIZE;
5658 		} else {
5659 			if (pmadapter->bgscan_reported) {
5660 				pmadapter->bgscan_reported = MFALSE;
5661 				/* Clear the previous scan result */
5662 				memset(pmadapter, pmadapter->pscan_table, 0x00,
5663 				       sizeof(BSSDescriptor_t) *
5664 					       MRVDRV_MAX_BSSID_LIST);
5665 				pmadapter->num_in_scan_table = 0;
5666 				pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
5667 				status = wlan_prepare_cmd(
5668 					pmpriv,
5669 					HostCmd_CMD_802_11_BG_SCAN_QUERY,
5670 					HostCmd_ACT_GEN_GET, 0,
5671 					(t_void *)pioctl_req, MNULL);
5672 				if (status == MLAN_STATUS_SUCCESS) {
5673 					PRINTM(MINFO,
5674 					       "wlan_scan_ioctl: return MLAN_STATUS_PENDING\n");
5675 					status = MLAN_STATUS_PENDING;
5676 				}
5677 			} else {
5678 				pscan->param.scan_resp.pscan_table =
5679 					(t_u8 *)pmadapter->pscan_table;
5680 				pscan->param.scan_resp.num_in_scan_table =
5681 					pmadapter->num_in_scan_table;
5682 				pscan->param.scan_resp.age_in_secs =
5683 					pmadapter->age_in_secs;
5684 				pioctl_req->data_read_written =
5685 					sizeof(mlan_scan_resp) +
5686 					MLAN_SUB_COMMAND_SIZE;
5687 				pscan->param.scan_resp.pchan_stats =
5688 					(t_u8 *)pmadapter->pchan_stats;
5689 				pscan->param.scan_resp.num_in_chan_stats =
5690 					pmadapter->num_in_chan_stats;
5691 			}
5692 		}
5693 	}
5694 
5695 	LEAVE();
5696 	return status;
5697 }
5698 
5699 /********************************************************
5700 			Global Functions
5701 ********************************************************/
5702 
5703 /**
5704  *  @brief Set ewpa mode
5705  *
5706  *  @param priv                 A pointer to mlan_private structure
5707  *  @param psec_pp              A pointer to mlan_ds_passphrase structure
5708  *
5709  *  @return                     MLAN_STATUS_SUCCESS
5710  */
wlan_set_ewpa_mode(mlan_private * priv,mlan_ds_passphrase * psec_pp)5711 mlan_status wlan_set_ewpa_mode(mlan_private *priv, mlan_ds_passphrase *psec_pp)
5712 {
5713 	ENTER();
5714 
5715 	if ((psec_pp->psk_type == MLAN_PSK_PASSPHRASE &&
5716 	     psec_pp->psk.passphrase.passphrase_len > 0) ||
5717 	    (psec_pp->psk_type == MLAN_PSK_PMK))
5718 		priv->sec_info.ewpa_enabled = MTRUE;
5719 	else
5720 		priv->sec_info.ewpa_enabled = MFALSE;
5721 
5722 	PRINTM(MINFO, "Set ewpa mode = %d\n", priv->sec_info.ewpa_enabled);
5723 
5724 	LEAVE();
5725 	return MLAN_STATUS_SUCCESS;
5726 }
5727 
5728 /**
5729  *  @brief Search for a BSS
5730  *
5731  *  @param pmpriv           A pointer to mlan_private structure
5732  *  @param pioctl_req       A pointer to ioctl request buffer
5733  *
5734  *  @return		            MLAN_STATUS_SUCCESS --success, otherwise
5735  * fail
5736  */
wlan_find_bss(mlan_private * pmpriv,pmlan_ioctl_req pioctl_req)5737 mlan_status wlan_find_bss(mlan_private *pmpriv, pmlan_ioctl_req pioctl_req)
5738 {
5739 	mlan_adapter *pmadapter = pmpriv->adapter;
5740 	mlan_ds_bss *bss = MNULL;
5741 	mlan_status ret = MLAN_STATUS_SUCCESS;
5742 	t_u8 zero_mac[] = {0, 0, 0, 0, 0, 0};
5743 	t_u8 mac[MLAN_MAC_ADDR_LENGTH];
5744 	int i = 0;
5745 	BSSDescriptor_t *pbss_desc = MNULL;
5746 
5747 	ENTER();
5748 
5749 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
5750 
5751 	if (memcmp(pmadapter, &bss->param.ssid_bssid.bssid, zero_mac,
5752 		   sizeof(zero_mac))) {
5753 		if (bss->param.ssid_bssid.ssid.ssid_len) /* ssid & bssid */
5754 			i = wlan_find_ssid_in_list(
5755 				pmpriv, &bss->param.ssid_bssid.ssid,
5756 				(t_u8 *)&bss->param.ssid_bssid.bssid,
5757 				pmpriv->bss_mode);
5758 		else
5759 			i = wlan_find_bssid_in_list(
5760 				pmpriv, (t_u8 *)&bss->param.ssid_bssid.bssid,
5761 				pmpriv->bss_mode);
5762 		if (i < 0) {
5763 			memcpy_ext(pmadapter, mac, &bss->param.ssid_bssid.bssid,
5764 				   sizeof(mac), MLAN_MAC_ADDR_LENGTH);
5765 			PRINTM(MIOCTL, "Can not find bssid " MACSTR "\n",
5766 			       MAC2STR(mac));
5767 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
5768 			LEAVE();
5769 			return MLAN_STATUS_FAILURE;
5770 		}
5771 		pbss_desc = &pmadapter->pscan_table[i];
5772 		memcpy_ext(pmadapter, &bss->param.ssid_bssid.ssid,
5773 			   &pbss_desc->ssid, sizeof(mlan_802_11_ssid),
5774 			   sizeof(mlan_802_11_ssid));
5775 		bss->param.ssid_bssid.rssi = pbss_desc->rssi;
5776 		bss->param.ssid_bssid.channel = (t_u16)pbss_desc->channel;
5777 
5778 		bss->param.ssid_bssid.bss_band = pbss_desc->bss_band;
5779 		/* index in bss list,start from 1 */
5780 		bss->param.ssid_bssid.idx = i + 1;
5781 	} else if (bss->param.ssid_bssid.ssid.ssid_len) {
5782 		i = wlan_find_ssid_in_list(pmpriv, &bss->param.ssid_bssid.ssid,
5783 					   MNULL, pmpriv->bss_mode);
5784 		if (i < 0) {
5785 			PRINTM(MIOCTL, "Can not find ssid %s\n",
5786 			       bss->param.ssid_bssid.ssid.ssid);
5787 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
5788 			LEAVE();
5789 			return MLAN_STATUS_FAILURE;
5790 		}
5791 		pbss_desc = &pmadapter->pscan_table[i];
5792 		memcpy_ext(pmadapter, (t_u8 *)&bss->param.ssid_bssid.bssid,
5793 			   (t_u8 *)&pbss_desc->mac_address,
5794 			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
5795 		bss->param.ssid_bssid.rssi = pbss_desc->rssi;
5796 		bss->param.ssid_bssid.channel = (t_u16)pbss_desc->channel;
5797 
5798 		bss->param.ssid_bssid.bss_band = pbss_desc->bss_band;
5799 		/* index in bss list, start from 1 */
5800 		bss->param.ssid_bssid.idx = i + 1;
5801 	} else {
5802 		ret = wlan_find_best_network(pmpriv, &bss->param.ssid_bssid);
5803 	}
5804 
5805 	if (pbss_desc) {
5806 		/**if rsn do not have ft akm, don't set ft cap and ft md*/
5807 		if (pbss_desc->pmd_ie &&
5808 		    wlan_ft_akm_is_used(pmpriv, (t_u8 *)pbss_desc->prsn_ie)) {
5809 			bss->param.ssid_bssid.ft_md = pbss_desc->pmd_ie->mdid;
5810 			bss->param.ssid_bssid.ft_cap =
5811 				pbss_desc->pmd_ie->ft_cap;
5812 		}
5813 	}
5814 
5815 	LEAVE();
5816 	return ret;
5817 }
5818 
5819 /**
5820  *  @brief MLAN station ioctl handler
5821  *
5822  *  @param adapter  A pointer to mlan_adapter structure
5823  *  @param pioctl_req	A pointer to ioctl request buffer
5824  *
5825  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success,
5826  * otherwise fail
5827  */
wlan_ops_sta_ioctl(t_void * adapter,pmlan_ioctl_req pioctl_req)5828 mlan_status wlan_ops_sta_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req)
5829 {
5830 	pmlan_adapter pmadapter = (pmlan_adapter)adapter;
5831 	mlan_status status = MLAN_STATUS_SUCCESS;
5832 
5833 	ENTER();
5834 
5835 	switch (pioctl_req->req_id) {
5836 	case MLAN_IOCTL_SCAN:
5837 		status = wlan_scan_ioctl(pmadapter, pioctl_req);
5838 		break;
5839 	case MLAN_IOCTL_BSS:
5840 		status = wlan_bss_ioctl(pmadapter, pioctl_req);
5841 		break;
5842 	case MLAN_IOCTL_RADIO_CFG:
5843 		status = wlan_radio_ioctl(pmadapter, pioctl_req);
5844 		break;
5845 	case MLAN_IOCTL_SNMP_MIB:
5846 		status = wlan_snmp_mib_ioctl(pmadapter, pioctl_req);
5847 		break;
5848 	case MLAN_IOCTL_GET_INFO:
5849 		status = wlan_get_info_ioctl(pmadapter, pioctl_req);
5850 		break;
5851 	case MLAN_IOCTL_SEC_CFG:
5852 		status = wlan_sec_cfg_ioctl(pmadapter, pioctl_req);
5853 		break;
5854 	case MLAN_IOCTL_RATE:
5855 		status = wlan_rate_ioctl(pmadapter, pioctl_req);
5856 		break;
5857 	case MLAN_IOCTL_POWER_CFG:
5858 		status = wlan_power_ioctl(pmadapter, pioctl_req);
5859 		break;
5860 	case MLAN_IOCTL_PM_CFG:
5861 		status = wlan_pm_ioctl(pmadapter, pioctl_req);
5862 		break;
5863 	case MLAN_IOCTL_WMM_CFG:
5864 		status = wlan_wmm_cfg_ioctl(pmadapter, pioctl_req);
5865 		break;
5866 	case MLAN_IOCTL_WPS_CFG:
5867 		status = wlan_wps_cfg_ioctl(pmadapter, pioctl_req);
5868 		break;
5869 	case MLAN_IOCTL_11N_CFG:
5870 		status = wlan_11n_cfg_ioctl(pmadapter, pioctl_req);
5871 		break;
5872 	case MLAN_IOCTL_11D_CFG:
5873 		status = wlan_11d_cfg_ioctl(pmadapter, pioctl_req);
5874 		break;
5875 	case MLAN_IOCTL_REG_MEM:
5876 		status = wlan_reg_mem_ioctl(pmadapter, pioctl_req);
5877 		break;
5878 	case MLAN_IOCTL_MISC_CFG:
5879 		status = wlan_misc_cfg_ioctl(pmadapter, pioctl_req);
5880 		break;
5881 	case MLAN_IOCTL_11H_CFG:
5882 		status = wlan_11h_cfg_ioctl(pmadapter, pioctl_req);
5883 		break;
5884 	case MLAN_IOCTL_11AC_CFG:
5885 		status = wlan_11ac_cfg_ioctl(pmadapter, pioctl_req);
5886 		break;
5887 	case MLAN_IOCTL_11AX_CFG:
5888 		status = wlan_11ax_cfg_ioctl(pmadapter, pioctl_req);
5889 		break;
5890 	default:
5891 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
5892 		status = MLAN_STATUS_FAILURE;
5893 		break;
5894 	}
5895 	LEAVE();
5896 	return status;
5897 }
5898