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