xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/mvl88w8977/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  *  Copyright (C) 2009-2017, Marvell International Ltd.
7  *
8  *  This software file (the "File") is distributed by Marvell International
9  *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
10  *  (the "License").  You may use, redistribute and/or modify this File in
11  *  accordance with the terms and conditions of the License, a copy of which
12  *  is available by writing to the Free Software Foundation, Inc.,
13  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14  *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15  *
16  *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17  *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18  *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
19  *  this warranty disclaimer.
20  */
21 
22 /*************************************************************
23 Change Log:
24     05/11/2009: initial version
25 ************************************************************/
26 #include "mlan.h"
27 #ifdef STA_SUPPORT
28 #include "mlan_join.h"
29 #endif /* STA_SUPPORT */
30 #include "mlan_util.h"
31 #include "mlan_fw.h"
32 #include "mlan_main.h"
33 #include "mlan_wmm.h"
34 #include "mlan_11n.h"
35 #include "mlan_sdio.h"
36 #ifdef UAP_SUPPORT
37 #include "mlan_uap.h"
38 #endif
39 #ifdef DRV_EMBEDDED_AUTHENTICATOR
40 #include "authenticator_api.h"
41 #endif
42 /********************************************************
43 			Local Variables
44 ********************************************************/
45 
46 /********************************************************
47 			Global Variables
48 ********************************************************/
49 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
50 extern mlan_operations *mlan_ops[];
51 #endif
52 extern t_u8 ac_to_tid[4][2];
53 
54 /********************************************************
55 			Local Functions
56 ********************************************************/
57 
58 /** Custom IE auto index and mask */
59 #define	MLAN_CUSTOM_IE_AUTO_IDX_MASK	0xffff
60 /** Custom IE mask for delete operation */
61 #define	MLAN_CUSTOM_IE_DELETE_MASK      0
62 /** Custom IE mask for create new index */
63 #define MLAN_CUSTOM_IE_NEW_MASK         0x8000
64 /** Custom IE header size */
65 #define	MLAN_CUSTOM_IE_HDR_SIZE         (sizeof(custom_ie)-MAX_IE_SIZE)
66 
67 /**
68  *  @brief Check if current custom IE index is used on other interfaces.
69  *
70  *  @param pmpriv   A pointer to mlan_private structure
71  *  @param idx		index to check for in use
72  *
73  *  @return		MLAN_STATUS_SUCCESS --unused, otherwise used.
74  */
75 static mlan_status
wlan_is_custom_ie_index_unused(IN pmlan_private pmpriv,IN t_u16 idx)76 wlan_is_custom_ie_index_unused(IN pmlan_private pmpriv, IN t_u16 idx)
77 {
78 	t_u8 i = 0;
79 	pmlan_adapter pmadapter = pmpriv->adapter;
80 	pmlan_private priv;
81 	ENTER();
82 
83 	for (i = 0; i < pmadapter->priv_num; i++) {
84 		priv = pmadapter->priv[i];
85 		/* Check for other interfaces only */
86 		if (priv && priv->bss_index != pmpriv->bss_index) {
87 
88 			if (priv->mgmt_ie[idx].mgmt_subtype_mask &&
89 			    priv->mgmt_ie[idx].ie_length) {
90 				/* used entry found */
91 				LEAVE();
92 				return MLAN_STATUS_FAILURE;
93 			}
94 		}
95 	}
96 	LEAVE();
97 	return MLAN_STATUS_SUCCESS;
98 }
99 
100 /**
101  *  @brief Get the custom IE index
102  *
103  *  @param pmpriv       A pointer to mlan_private structure
104  *  @param pioctl_req	A pointer to ioctl request buffer
105  *  @param mask	mask value for which the index to be returned
106  *  @param ie_data	a pointer to custom_ie structure
107  *  @param idx		will hold the computed index
108  *
109  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
110  */
111 static mlan_status
wlan_custom_ioctl_get_autoidx(IN pmlan_private pmpriv,IN pmlan_ioctl_req pioctl_req,IN t_u16 mask,IN custom_ie * ie_data,OUT t_u16 * idx)112 wlan_custom_ioctl_get_autoidx(IN pmlan_private pmpriv,
113 			      IN pmlan_ioctl_req pioctl_req,
114 			      IN t_u16 mask,
115 			      IN custom_ie *ie_data, OUT t_u16 *idx)
116 {
117 	t_u16 index = 0, insert = MFALSE;
118 	mlan_status ret = MLAN_STATUS_SUCCESS;
119 
120 	ENTER();
121 	/* Determine the index where the IE needs to be inserted */
122 	while (!insert) {
123 		while (index <
124 		       MIN(pmpriv->adapter->max_mgmt_ie_index,
125 			   MAX_MGMT_IE_INDEX)) {
126 			if (pmpriv->mgmt_ie[index].mgmt_subtype_mask ==
127 			    MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
128 				index++;
129 				continue;
130 			}
131 			if (pmpriv->mgmt_ie[index].mgmt_subtype_mask == mask) {
132 				/* Duplicate IE should be avoided */
133 				if (pmpriv->mgmt_ie[index].ie_length) {
134 					if (!memcmp
135 					    (pmpriv->adapter,
136 					     pmpriv->mgmt_ie[index].ie_buffer,
137 					     ie_data->ie_buffer,
138 					     pmpriv->mgmt_ie[index].
139 					     ie_length)) {
140 						PRINTM(MINFO,
141 						       "IE with the same mask exists at index %d mask=0x%x\n",
142 						       index, mask);
143 						*idx = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
144 						goto done;
145 					}
146 				}
147 				/* Check if enough space is available */
148 				if (pmpriv->mgmt_ie[index].ie_length +
149 				    ie_data->ie_length > MAX_IE_SIZE) {
150 					index++;
151 					continue;
152 				}
153 				insert = MTRUE;
154 				break;
155 			}
156 			index++;
157 		}
158 		if (!insert) {
159 			for (index = 0;
160 			     index < MIN(pmpriv->adapter->max_mgmt_ie_index,
161 					 MAX_MGMT_IE_INDEX); index++) {
162 				if (pmpriv->mgmt_ie[index].ie_length == 0) {
163 					/*
164 					 * Check if this index is in use
165 					 * by other interface If yes,
166 					 * move ahead to next index
167 					 */
168 					if (MLAN_STATUS_SUCCESS ==
169 					    wlan_is_custom_ie_index_unused
170 					    (pmpriv, index)) {
171 						insert = MTRUE;
172 						break;
173 					} else {
174 						PRINTM(MINFO,
175 						       "Skipping IE index %d in use.\n",
176 						       index);
177 					}
178 				}
179 			}
180 		}
181 		if (index == pmpriv->adapter->max_mgmt_ie_index && !insert) {
182 			PRINTM(MERROR, "Failed to Set the IE buffer\n");
183 			if (pioctl_req)
184 				pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
185 			ret = MLAN_STATUS_FAILURE;
186 			goto done;
187 		}
188 	}
189 
190 	*idx = index;
191 done:
192 	LEAVE();
193 	return ret;
194 }
195 
196 /**
197  *  @brief Delete custom IE
198  *
199  *  @param pmpriv       A pointer to mlan_private structure
200  *  @param pioctl_req	A pointer to ioctl request buffer
201  *  @param ie_data	a pointer to custom_ie structure
202  *  @param idx		index supplied
203  *
204  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
205  */
206 
207 static mlan_status
wlan_custom_ioctl_auto_delete(IN pmlan_private pmpriv,IN pmlan_ioctl_req pioctl_req,IN custom_ie * ie_data,IN t_u16 idx)208 wlan_custom_ioctl_auto_delete(IN pmlan_private pmpriv,
209 			      IN pmlan_ioctl_req pioctl_req,
210 			      IN custom_ie *ie_data, IN t_u16 idx)
211 {
212 	mlan_status ret = MLAN_STATUS_SUCCESS;
213 	pmlan_adapter pmadapter = pmpriv->adapter;
214 	t_u16 index = 0, insert = MFALSE, del_len;
215 	t_u8 del_ie[MAX_IE_SIZE], ie[MAX_IE_SIZE];
216 	t_s32 cnt, tmp_len = 0;
217 	t_u8 *tmp_ie;
218 
219 	ENTER();
220 	memset(pmpriv->adapter, del_ie, 0, MAX_IE_SIZE);
221 	memcpy(pmpriv->adapter, del_ie, ie_data->ie_buffer,
222 	       MIN(MAX_IE_SIZE, ie_data->ie_length));
223 	del_len = MIN(MAX_IE_SIZE - 1, ie_data->ie_length);
224 
225 	if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == idx)
226 		ie_data->ie_index = 0;
227 
228 	for (index = 0;
229 	     index < MIN(pmadapter->max_mgmt_ie_index, MAX_MGMT_IE_INDEX);
230 	     index++) {
231 		if (MLAN_CUSTOM_IE_AUTO_IDX_MASK != idx)
232 			index = idx;
233 		tmp_ie = pmpriv->mgmt_ie[index].ie_buffer;
234 		tmp_len = pmpriv->mgmt_ie[index].ie_length;
235 		cnt = 0;
236 		while (tmp_len) {
237 			if (!memcmp(pmpriv->adapter, tmp_ie, del_ie, del_len)) {
238 				memcpy(pmpriv->adapter, ie,
239 				       pmpriv->mgmt_ie[index].ie_buffer, cnt);
240 				if (pmpriv->mgmt_ie[index].ie_length >
241 				    (cnt + del_len))
242 					memcpy(pmpriv->adapter, &ie[cnt],
243 					       &pmpriv->mgmt_ie[index].
244 					       ie_buffer[MIN
245 							 ((MAX_IE_SIZE - 1),
246 							  (cnt + del_len))],
247 					       (pmpriv->mgmt_ie[index].
248 						ie_length - (cnt + del_len)));
249 				memset(pmpriv->adapter,
250 				       &pmpriv->mgmt_ie[index].ie_buffer, 0,
251 				       sizeof(pmpriv->mgmt_ie[index].
252 					      ie_buffer));
253 				memcpy(pmpriv->adapter,
254 				       &pmpriv->mgmt_ie[index].ie_buffer, ie,
255 				       pmpriv->mgmt_ie[index].ie_length -
256 				       del_len);
257 				pmpriv->mgmt_ie[index].ie_length -= del_len;
258 				if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == idx)
259 					/* set a bit to indicate caller about update */
260 					ie_data->ie_index |=
261 						(((t_u16)1) << index);
262 				insert = MTRUE;
263 				tmp_ie = pmpriv->mgmt_ie[index].ie_buffer;
264 				tmp_len = pmpriv->mgmt_ie[index].ie_length;
265 				cnt = 0;
266 				continue;
267 			}
268 			tmp_ie++;
269 			tmp_len--;
270 			cnt++;
271 		}
272 		if (MLAN_CUSTOM_IE_AUTO_IDX_MASK != idx)
273 			break;
274 	}
275 	if (index == pmadapter->max_mgmt_ie_index && !insert) {
276 		PRINTM(MERROR, "Failed to Clear IE buffer\n");
277 		if (pioctl_req)
278 			pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
279 		ret = MLAN_STATUS_FAILURE;
280 	}
281 	LEAVE();
282 	return ret;
283 }
284 
285 /********************************************************
286 			Global Functions
287 ********************************************************/
288 
289 /**
290  *  @brief Get correlated time
291  *
292  *  @param pmadapter	A pointer to mlan_adapter structure
293  *  @param pioctl_req	A pointer to ioctl request buffer
294  *
295  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
296  */
297 mlan_status
wlan_misc_get_correlated_time(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)298 wlan_misc_get_correlated_time(IN pmlan_adapter pmadapter,
299 			      IN pmlan_ioctl_req pioctl_req)
300 {
301 	pmlan_private pmpriv = MNULL;
302 	mlan_status ret = MLAN_STATUS_SUCCESS;
303 	mlan_ds_misc_cfg *misc = MNULL;
304 	mlan_ds_host_clock *host_clock = MNULL;
305 
306 	ENTER();
307 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
308 	host_clock = &misc->param.host_clock;
309 
310 	if (pioctl_req != MNULL) {
311 		pmpriv = pmadapter->priv[pioctl_req->bss_index];
312 	} else {
313 		PRINTM(MERROR, "MLAN IOCTL information is not present\n");
314 		ret = MLAN_STATUS_FAILURE;
315 		goto exit;
316 	}
317 
318 	/* Send request to firmware */
319 	ret = wlan_prepare_cmd(pmpriv,
320 			       HostCmd_CMD_HOST_CLOCK_CFG,
321 			       HostCmd_ACT_GEN_GET,
322 			       0, (t_void *)pioctl_req, (t_void *)host_clock);
323 
324 	if (ret == MLAN_STATUS_SUCCESS)
325 		ret = MLAN_STATUS_PENDING;
326 
327 exit:
328 	LEAVE();
329 	return ret;
330 }
331 
332 /**
333  *  @brief send host cmd
334  *
335  *  @param pmadapter	A pointer to mlan_adapter structure
336  *  @param pioctl_req	A pointer to ioctl request buffer
337  *
338  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
339  */
340 mlan_status
wlan_misc_ioctl_host_cmd(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)341 wlan_misc_ioctl_host_cmd(IN pmlan_adapter pmadapter,
342 			 IN pmlan_ioctl_req pioctl_req)
343 {
344 	mlan_status ret = MLAN_STATUS_SUCCESS;
345 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
346 	mlan_ds_misc_cfg *misc = MNULL;
347 
348 	ENTER();
349 
350 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
351 
352 	/* Send request to firmware */
353 	ret = wlan_prepare_cmd(pmpriv,
354 			       0,
355 			       0,
356 			       0,
357 			       (t_void *)pioctl_req,
358 			       (t_void *)&misc->param.hostcmd);
359 	if (ret == MLAN_STATUS_SUCCESS)
360 		ret = MLAN_STATUS_PENDING;
361 
362 	LEAVE();
363 	return ret;
364 }
365 
366 /**
367  *  @brief Send function init/shutdown command to firmware
368  *
369  *  @param pmadapter	A pointer to mlan_adapter structure
370  *  @param pioctl_req	A pointer to ioctl request buffer
371  *
372  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
373  */
374 mlan_status
wlan_misc_ioctl_init_shutdown(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)375 wlan_misc_ioctl_init_shutdown(IN pmlan_adapter pmadapter,
376 			      IN pmlan_ioctl_req pioctl_req)
377 {
378 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
379 	mlan_status ret = MLAN_STATUS_SUCCESS;
380 	mlan_ds_misc_cfg *misc_cfg = MNULL;
381 	t_u16 cmd;
382 
383 	ENTER();
384 
385 	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
386 	if (misc_cfg->param.func_init_shutdown == MLAN_FUNC_INIT)
387 		cmd = HostCmd_CMD_FUNC_INIT;
388 	else if (misc_cfg->param.func_init_shutdown == MLAN_FUNC_SHUTDOWN)
389 		cmd = HostCmd_CMD_FUNC_SHUTDOWN;
390 	else {
391 		PRINTM(MERROR, "Unsupported parameter\n");
392 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
393 		ret = MLAN_STATUS_FAILURE;
394 		goto exit;
395 	}
396 
397 	/* Send command to firmware */
398 	ret = wlan_prepare_cmd(pmpriv,
399 			       cmd,
400 			       HostCmd_ACT_GEN_SET,
401 			       0, (t_void *)pioctl_req, MNULL);
402 
403 	if (ret == MLAN_STATUS_SUCCESS)
404 		ret = MLAN_STATUS_PENDING;
405 
406 exit:
407 	LEAVE();
408 	return ret;
409 }
410 
411 /**
412  *  @brief Get debug information
413  *
414  *  @param pmadapter	A pointer to mlan_adapter structure
415  *  @param pioctl_req	A pointer to ioctl request buffer
416  *
417  *  @return		MLAN_STATUS_SUCCESS --success
418  */
419 mlan_status
wlan_get_info_debug_info(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)420 wlan_get_info_debug_info(IN pmlan_adapter pmadapter,
421 			 IN pmlan_ioctl_req pioctl_req)
422 {
423 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
424 	mlan_status ret = MLAN_STATUS_SUCCESS;
425 	mlan_ds_get_info *info;
426 	mlan_debug_info *debug_info = MNULL;
427 	t_u32 i;
428 	t_u8 *ptid;
429 
430 	ENTER();
431 
432 	info = (mlan_ds_get_info *)pioctl_req->pbuf;
433 	debug_info = (mlan_debug_info *)info->param.debug_info;
434 
435 	if (pioctl_req->action == MLAN_ACT_GET) {
436 		ptid = ac_to_tid[WMM_AC_BK];
437 		debug_info->wmm_ac_bk =
438 			pmpriv->wmm.packets_out[ptid[0]] +
439 			pmpriv->wmm.packets_out[ptid[1]];
440 		ptid = ac_to_tid[WMM_AC_BE];
441 		debug_info->wmm_ac_be =
442 			pmpriv->wmm.packets_out[ptid[0]] +
443 			pmpriv->wmm.packets_out[ptid[1]];
444 		ptid = ac_to_tid[WMM_AC_VI];
445 		debug_info->wmm_ac_vi =
446 			pmpriv->wmm.packets_out[ptid[0]] +
447 			pmpriv->wmm.packets_out[ptid[1]];
448 		ptid = ac_to_tid[WMM_AC_VO];
449 		debug_info->wmm_ac_vo =
450 			pmpriv->wmm.packets_out[ptid[0]] +
451 			pmpriv->wmm.packets_out[ptid[1]];
452 		debug_info->max_tx_buf_size = (t_u32)pmadapter->max_tx_buf_size;
453 		debug_info->tx_buf_size = (t_u32)pmadapter->tx_buf_size;
454 		debug_info->curr_tx_buf_size =
455 			(t_u32)pmadapter->curr_tx_buf_size;
456 		debug_info->rx_tbl_num =
457 			wlan_get_rxreorder_tbl(pmpriv, debug_info->rx_tbl);
458 		debug_info->tx_tbl_num =
459 			wlan_get_txbastream_tbl(pmpriv, debug_info->tx_tbl);
460 		debug_info->ralist_num =
461 			wlan_get_ralist_info(pmpriv, debug_info->ralist);
462 		debug_info->tdls_peer_num =
463 			wlan_get_tdls_list(pmpriv, debug_info->tdls_peer_list);
464 		debug_info->ps_mode = pmadapter->ps_mode;
465 		debug_info->ps_state = pmadapter->ps_state;
466 #ifdef STA_SUPPORT
467 		debug_info->is_deep_sleep = pmadapter->is_deep_sleep;
468 #endif /* STA_SUPPORT */
469 		debug_info->pm_wakeup_card_req = pmadapter->pm_wakeup_card_req;
470 		debug_info->pm_wakeup_fw_try = pmadapter->pm_wakeup_fw_try;
471 		debug_info->pm_wakeup_in_secs = pmadapter->pm_wakeup_in_secs;
472 		debug_info->is_hs_configured = pmadapter->is_hs_configured;
473 		debug_info->hs_activated = pmadapter->hs_activated;
474 		debug_info->pps_uapsd_mode = pmadapter->pps_uapsd_mode;
475 		debug_info->sleep_pd = pmadapter->sleep_period.period;
476 		debug_info->qos_cfg = pmpriv->wmm_qosinfo;
477 		debug_info->tx_lock_flag = pmadapter->tx_lock_flag;
478 		debug_info->port_open = pmpriv->port_open;
479 		debug_info->bypass_pkt_count = pmadapter->bypass_pkt_count;
480 		debug_info->scan_processing = pmadapter->scan_processing;
481 		debug_info->mlan_processing = pmadapter->mlan_processing;
482 		debug_info->main_lock_flag = pmadapter->main_lock_flag;
483 		debug_info->main_process_cnt = pmadapter->main_process_cnt;
484 		debug_info->delay_task_flag = pmadapter->delay_task_flag;
485 		debug_info->num_cmd_host_to_card_failure
486 			= pmadapter->dbg.num_cmd_host_to_card_failure;
487 		debug_info->num_cmd_sleep_cfm_host_to_card_failure
488 			= pmadapter->dbg.num_cmd_sleep_cfm_host_to_card_failure;
489 		debug_info->num_tx_host_to_card_failure
490 			= pmadapter->dbg.num_tx_host_to_card_failure;
491 		debug_info->num_alloc_buffer_failure =
492 			pmadapter->dbg.num_alloc_buffer_failure;
493 		debug_info->num_pkt_dropped = pmadapter->dbg.num_pkt_dropped;
494 
495 		debug_info->num_cmdevt_card_to_host_failure
496 			= pmadapter->dbg.num_cmdevt_card_to_host_failure;
497 		debug_info->num_rx_card_to_host_failure
498 			= pmadapter->dbg.num_rx_card_to_host_failure;
499 		debug_info->num_int_read_failure =
500 			pmadapter->dbg.num_int_read_failure;
501 		debug_info->last_int_status = pmadapter->dbg.last_int_status;
502 		debug_info->num_event_deauth = pmadapter->dbg.num_event_deauth;
503 		debug_info->num_event_disassoc =
504 			pmadapter->dbg.num_event_disassoc;
505 		debug_info->num_event_link_lost =
506 			pmadapter->dbg.num_event_link_lost;
507 		debug_info->num_cmd_deauth = pmadapter->dbg.num_cmd_deauth;
508 		debug_info->num_cmd_assoc_success =
509 			pmadapter->dbg.num_cmd_assoc_success;
510 		debug_info->num_cmd_assoc_failure =
511 			pmadapter->dbg.num_cmd_assoc_failure;
512 		debug_info->num_tx_timeout = pmadapter->dbg.num_tx_timeout;
513 		debug_info->num_cmd_timeout = pmadapter->num_cmd_timeout;
514 		debug_info->dbg_num_cmd_timeout =
515 			pmadapter->dbg.num_cmd_timeout;
516 		debug_info->timeout_cmd_id = pmadapter->dbg.timeout_cmd_id;
517 		debug_info->timeout_cmd_act = pmadapter->dbg.timeout_cmd_act;
518 		memcpy(pmadapter, debug_info->last_cmd_id,
519 		       pmadapter->dbg.last_cmd_id,
520 		       sizeof(pmadapter->dbg.last_cmd_id));
521 		memcpy(pmadapter, debug_info->last_cmd_act,
522 		       pmadapter->dbg.last_cmd_act,
523 		       sizeof(pmadapter->dbg.last_cmd_act));
524 		debug_info->last_cmd_index = pmadapter->dbg.last_cmd_index;
525 		memcpy(pmadapter, debug_info->last_cmd_resp_id,
526 		       pmadapter->dbg.last_cmd_resp_id,
527 		       sizeof(pmadapter->dbg.last_cmd_resp_id));
528 		debug_info->last_cmd_resp_index =
529 			pmadapter->dbg.last_cmd_resp_index;
530 		memcpy(pmadapter, debug_info->last_event,
531 		       pmadapter->dbg.last_event,
532 		       sizeof(pmadapter->dbg.last_event));
533 		debug_info->last_event_index = pmadapter->dbg.last_event_index;
534 		debug_info->num_no_cmd_node = pmadapter->dbg.num_no_cmd_node;
535 		debug_info->pending_cmd =
536 			(pmadapter->curr_cmd) ? pmadapter->dbg.
537 			last_cmd_id[pmadapter->dbg.last_cmd_index] : 0;
538 		debug_info->dnld_cmd_in_secs = pmadapter->dnld_cmd_in_secs;
539 		debug_info->mp_rd_bitmap = pmadapter->mp_rd_bitmap;
540 		debug_info->mp_wr_bitmap = pmadapter->mp_wr_bitmap;
541 		debug_info->curr_rd_port = pmadapter->curr_rd_port;
542 		debug_info->curr_wr_port = pmadapter->curr_wr_port;
543 		debug_info->mp_invalid_update = pmadapter->mp_invalid_update;
544 		debug_info->num_of_irq = pmadapter->num_of_irq;
545 		memcpy(pmadapter, debug_info->mp_update, pmadapter->mp_update,
546 		       sizeof(pmadapter->mp_update));
547 #ifdef SDIO_MULTI_PORT_TX_AGGR
548 		memcpy(pmadapter, debug_info->mpa_tx_count,
549 		       pmadapter->mpa_tx_count,
550 		       sizeof(pmadapter->mpa_tx_count));
551 		debug_info->mpa_sent_last_pkt = pmadapter->mpa_sent_last_pkt;
552 		debug_info->mpa_sent_no_ports = pmadapter->mpa_sent_no_ports;
553 		debug_info->last_recv_wr_bitmap =
554 			pmadapter->last_recv_wr_bitmap;
555 		debug_info->last_mp_index = pmadapter->last_mp_index;
556 		memcpy(pmadapter, debug_info->last_mp_wr_bitmap,
557 		       pmadapter->last_mp_wr_bitmap,
558 		       sizeof(pmadapter->last_mp_wr_bitmap));
559 		memcpy(pmadapter, debug_info->last_mp_wr_ports,
560 		       pmadapter->last_mp_wr_ports,
561 		       sizeof(pmadapter->last_mp_wr_ports));
562 		memcpy(pmadapter, debug_info->last_mp_wr_len,
563 		       pmadapter->last_mp_wr_len,
564 		       sizeof(pmadapter->last_mp_wr_len));
565 		memcpy(pmadapter, debug_info->last_mp_wr_info,
566 		       pmadapter->last_mp_wr_info,
567 		       sizeof(pmadapter->last_mp_wr_info));
568 		memcpy(pmadapter, debug_info->last_curr_wr_port,
569 		       pmadapter->last_curr_wr_port,
570 		       sizeof(pmadapter->last_curr_wr_port));
571 		debug_info->mpa_buf = pmadapter->mpa_buf;
572 		debug_info->mpa_buf_size = pmadapter->mpa_buf_size;
573 #endif /* SDIO_MULTI_PORT_TX_AGGR */
574 #ifdef SDIO_MULTI_PORT_RX_AGGR
575 		debug_info->sdio_rx_aggr = pmadapter->sdio_rx_aggr_enable;
576 		memcpy(pmadapter, debug_info->mpa_rx_count,
577 		       pmadapter->mpa_rx_count,
578 		       sizeof(pmadapter->mpa_rx_count));
579 #endif
580 		debug_info->data_sent = pmadapter->data_sent;
581 		debug_info->cmd_sent = pmadapter->cmd_sent;
582 		debug_info->cmd_resp_received = pmadapter->cmd_resp_received;
583 		debug_info->tx_pkts_queued =
584 			util_scalar_read(pmadapter->pmoal_handle,
585 					 &pmpriv->wmm.tx_pkts_queued, MNULL,
586 					 MNULL);
587 #ifdef UAP_SUPPORT
588 		debug_info->num_bridge_pkts =
589 			util_scalar_read(pmadapter->pmoal_handle,
590 					 &pmadapter->pending_bridge_pkts,
591 					 pmadapter->callbacks.moal_spin_lock,
592 					 pmadapter->callbacks.moal_spin_unlock);
593 		debug_info->num_drop_pkts = pmpriv->num_drop_pkts;
594 #endif
595 		debug_info->mlan_processing = pmadapter->mlan_processing;
596 		debug_info->mlan_rx_processing = pmadapter->mlan_rx_processing;
597 		debug_info->rx_pkts_queued = pmadapter->rx_pkts_queued;
598 		debug_info->mlan_adapter = pmadapter;
599 		debug_info->mlan_adapter_size = sizeof(mlan_adapter);
600 		debug_info->mlan_priv_num = pmadapter->priv_num;
601 		for (i = 0; i < pmadapter->priv_num; i++) {
602 			debug_info->mlan_priv[i] = pmadapter->priv[i];
603 			debug_info->mlan_priv_size[i] = sizeof(mlan_private);
604 		}
605 	}
606 
607 	pioctl_req->data_read_written =
608 		sizeof(mlan_debug_info) + MLAN_SUB_COMMAND_SIZE;
609 
610 	LEAVE();
611 	return ret;
612 }
613 
614 /**
615  *  @brief Set/Get the MAC control configuration.
616  *
617  *  @param pmadapter    A pointer to mlan_adapter structure
618  *  @param pioctl_req   A pointer to ioctl request buffer
619  *
620  *  @return             MLAN_STATUS_PENDING -- success, otherwise fail
621  */
622 mlan_status
wlan_misc_ioctl_mac_control(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)623 wlan_misc_ioctl_mac_control(IN pmlan_adapter pmadapter,
624 			    IN pmlan_ioctl_req pioctl_req)
625 {
626 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
627 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
628 	mlan_status ret = MLAN_STATUS_SUCCESS;
629 	t_u16 cmd_action = 0;
630 
631 	ENTER();
632 
633 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
634 
635 	if (pioctl_req->action == MLAN_ACT_GET) {
636 		misc->param.mac_ctrl = pmpriv->curr_pkt_filter;
637 	} else {
638 		pmpriv->curr_pkt_filter = misc->param.mac_ctrl;
639 		cmd_action = HostCmd_ACT_GEN_SET;
640 
641 		/* Send command to firmware */
642 		ret = wlan_prepare_cmd(pmpriv,
643 				       HostCmd_CMD_MAC_CONTROL,
644 				       cmd_action, 0,
645 				       (t_void *)pioctl_req,
646 				       &misc->param.mac_ctrl);
647 
648 		if (ret == MLAN_STATUS_SUCCESS)
649 			ret = MLAN_STATUS_PENDING;
650 	}
651 
652 	LEAVE();
653 	return ret;
654 }
655 
656 /**
657  *  @brief This function wakes up the card.
658  *
659  *  @param pmadapter		A pointer to mlan_adapter structure
660  *
661  *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
662  */
663 mlan_status
wlan_pm_wakeup_card(IN pmlan_adapter pmadapter)664 wlan_pm_wakeup_card(IN pmlan_adapter pmadapter)
665 {
666 	mlan_status ret = MLAN_STATUS_SUCCESS;
667 	t_u32 age_ts_usec;
668 	pmlan_callbacks pcb = &pmadapter->callbacks;
669 
670 	ENTER();
671 	PRINTM(MEVENT, "Wakeup device...\n");
672 	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
673 						  &pmadapter->pm_wakeup_in_secs,
674 						  &age_ts_usec);
675 
676 	if (pmadapter->fw_wakeup_method == WAKEUP_FW_THRU_GPIO) {
677 		/* GPIO_PORT_TO_LOW(); */
678 	} else
679 		ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
680 					  HOST_TO_CARD_EVENT_REG,
681 					  HOST_POWER_UP);
682 	LEAVE();
683 	return ret;
684 }
685 
686 /**
687  *  @brief This function resets the PM setting of the card.
688  *
689  *  @param pmadapter		A pointer to mlan_adapter structure
690  *
691  *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
692  */
693 mlan_status
wlan_pm_reset_card(IN pmlan_adapter pmadapter)694 wlan_pm_reset_card(IN pmlan_adapter pmadapter)
695 {
696 	mlan_status ret = MLAN_STATUS_SUCCESS;
697 	pmlan_callbacks pcb = &pmadapter->callbacks;
698 
699 	ENTER();
700 
701 	if (pmadapter->fw_wakeup_method == WAKEUP_FW_THRU_GPIO) {
702 		/* GPIO_PORT_TO_HIGH(); */
703 	} else
704 		ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
705 					  HOST_TO_CARD_EVENT_REG, 0);
706 
707 	LEAVE();
708 	return ret;
709 }
710 
711 /**
712  *  @brief Set/Get HS configuration
713  *
714  *  @param pmadapter	A pointer to mlan_adapter structure
715  *  @param pioctl_req	A pointer to ioctl request buffer
716  *
717  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
718  */
719 mlan_status
wlan_pm_ioctl_hscfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)720 wlan_pm_ioctl_hscfg(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
721 {
722 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
723 	mlan_ds_pm_cfg *pm = MNULL;
724 	mlan_status status = MLAN_STATUS_SUCCESS;
725 	t_u32 prev_cond = 0;
726 
727 	ENTER();
728 
729 	pm = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
730 
731 	switch (pioctl_req->action) {
732 	case MLAN_ACT_SET:
733 #ifdef STA_SUPPORT
734 		if (pmadapter->pps_uapsd_mode) {
735 			PRINTM(MINFO,
736 			       "Host Sleep IOCTL is blocked in UAPSD/PPS mode\n");
737 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
738 			status = MLAN_STATUS_FAILURE;
739 			break;
740 		}
741 #endif /* STA_SUPPORT */
742 		if (pm->param.hs_cfg.is_invoke_hostcmd == MTRUE) {
743 			if (pm->param.hs_cfg.conditions ==
744 			    HOST_SLEEP_CFG_CANCEL) {
745 				if (pmadapter->is_hs_configured == MFALSE) {
746 					/* Already cancelled */
747 					break;
748 				}
749 				/* Save previous condition */
750 				prev_cond = pmadapter->hs_cfg.conditions;
751 				pmadapter->hs_cfg.conditions =
752 					pm->param.hs_cfg.conditions;
753 			} else if (pmadapter->hs_cfg.conditions ==
754 				   HOST_SLEEP_CFG_CANCEL) {
755 				/* Return failure if no parameters for HS enable */
756 				pioctl_req->status_code =
757 					MLAN_ERROR_INVALID_PARAMETER;
758 				status = MLAN_STATUS_FAILURE;
759 				break;
760 			}
761 			status = wlan_prepare_cmd(pmpriv,
762 						  HostCmd_CMD_802_11_HS_CFG_ENH,
763 						  HostCmd_ACT_GEN_SET,
764 						  0, (t_void *)pioctl_req,
765 						  (t_void *)(&pmadapter->
766 							     hs_cfg));
767 			if (status == MLAN_STATUS_SUCCESS)
768 				status = MLAN_STATUS_PENDING;
769 			if (pm->param.hs_cfg.conditions ==
770 			    HOST_SLEEP_CFG_CANCEL) {
771 				/* Restore previous condition */
772 				pmadapter->hs_cfg.conditions = prev_cond;
773 			}
774 		} else {
775 			pmadapter->hs_cfg.conditions =
776 				pm->param.hs_cfg.conditions;
777 			pmadapter->hs_cfg.gpio = (t_u8)pm->param.hs_cfg.gpio;
778 			pmadapter->hs_cfg.gap = (t_u8)pm->param.hs_cfg.gap;
779 			pmadapter->param_type_ind =
780 				(t_u8)pm->param.hs_cfg.param_type_ind;
781 			pmadapter->ind_gpio = (t_u8)pm->param.hs_cfg.ind_gpio;
782 			pmadapter->level = (t_u8)pm->param.hs_cfg.level;
783 			pmadapter->param_type_ext =
784 				(t_u8)pm->param.hs_cfg.param_type_ext;
785 			pmadapter->event_force_ignore =
786 				pm->param.hs_cfg.event_force_ignore;
787 			pmadapter->event_use_ext_gap =
788 				pm->param.hs_cfg.event_use_ext_gap;
789 			pmadapter->ext_gap = pm->param.hs_cfg.ext_gap;
790 			pmadapter->gpio_wave = pm->param.hs_cfg.gpio_wave;
791 			pmadapter->hs_wake_interval =
792 				pm->param.hs_cfg.hs_wake_interval;
793 		}
794 		break;
795 	case MLAN_ACT_GET:
796 		pm->param.hs_cfg.conditions = pmadapter->hs_cfg.conditions;
797 		pm->param.hs_cfg.gpio = pmadapter->hs_cfg.gpio;
798 		pm->param.hs_cfg.gap = pmadapter->hs_cfg.gap;
799 		pm->param.hs_cfg.param_type_ind = pmadapter->param_type_ind;
800 		pm->param.hs_cfg.ind_gpio = pmadapter->ind_gpio;
801 		pm->param.hs_cfg.level = pmadapter->level;
802 		pm->param.hs_cfg.param_type_ext = pmadapter->param_type_ext;
803 		pm->param.hs_cfg.event_force_ignore =
804 			pmadapter->event_force_ignore;
805 		pm->param.hs_cfg.event_use_ext_gap =
806 			pmadapter->event_use_ext_gap;
807 		pm->param.hs_cfg.ext_gap = pmadapter->ext_gap;
808 		pm->param.hs_cfg.gpio_wave = pmadapter->gpio_wave;
809 		pm->param.hs_cfg.hs_wake_interval = pmadapter->hs_wake_interval;
810 		break;
811 	default:
812 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
813 		status = MLAN_STATUS_FAILURE;
814 		break;
815 	}
816 
817 	LEAVE();
818 	return status;
819 }
820 
821 /**
822  *  @brief Get/Set the firmware wakeup method
823  *
824  *  @param pmadapter	A pointer to mlan_adapter structure
825  *  @param pioctl_req	A pointer to ioctl request buffer
826  *
827  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
828  */
829 mlan_status
wlan_fw_wakeup_method(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)830 wlan_fw_wakeup_method(IN pmlan_adapter pmadapter, IN 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_pm_cfg *pmcfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
836 
837 	ENTER();
838 
839 	if (pioctl_req->action == MLAN_ACT_SET)
840 		cmd_action = HostCmd_ACT_GEN_SET;
841 	else
842 		cmd_action = HostCmd_ACT_GEN_GET;
843 
844 	ret = wlan_prepare_cmd(pmpriv,
845 			       HostCmd_CMD_802_11_FW_WAKE_METHOD,
846 			       cmd_action,
847 			       0,
848 			       (t_void *)pioctl_req,
849 			       &pmcfg->param.fw_wakeup_params);
850 
851 	if (ret == MLAN_STATUS_SUCCESS)
852 		ret = MLAN_STATUS_PENDING;
853 	LEAVE();
854 	return ret;
855 }
856 
857 /**
858  *  @brief Set Robustcoex gpiocfg
859  *
860  *  @param pmadapter	A pointer to mlan_adapter structure
861  *  @param pioctl_req	A pointer to ioctl request buffer
862  *
863  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
864  */
865 mlan_status
wlan_misc_robustcoex(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)866 wlan_misc_robustcoex(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
867 {
868 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
869 	mlan_status ret = MLAN_STATUS_SUCCESS;
870 	t_u16 cmd_action;
871 	mlan_ds_misc_cfg *robust_coex_cfg =
872 		(mlan_ds_misc_cfg *)pioctl_req->pbuf;
873 
874 	ENTER();
875 
876 	if (pioctl_req->action == MLAN_ACT_SET)
877 		cmd_action = HostCmd_ACT_GEN_SET;
878 	else
879 		cmd_action = HostCmd_ACT_GEN_GET;
880 
881 	ret = wlan_prepare_cmd(pmpriv,
882 			       HostCmd_CMD_802_11_ROBUSTCOEX,
883 			       cmd_action,
884 			       0,
885 			       (t_void *)pioctl_req,
886 			       &robust_coex_cfg->param.robustcoexparams);
887 
888 	if (ret == MLAN_STATUS_SUCCESS)
889 		ret = MLAN_STATUS_PENDING;
890 	LEAVE();
891 	return ret;
892 }
893 
894 /**
895  *  @brief This function allocates a mlan_buffer.
896  *
897  *  @param pmadapter Pointer to mlan_adapter
898  *  @param data_len   Data length
899  *  @param head_room  head_room reserved in mlan_buffer
900  *  @param malloc_flag  flag to user moal_malloc
901  *  @return           mlan_buffer pointer or MNULL
902  */
903 pmlan_buffer
wlan_alloc_mlan_buffer(mlan_adapter * pmadapter,t_u32 data_len,t_u32 head_room,t_u32 malloc_flag)904 wlan_alloc_mlan_buffer(mlan_adapter *pmadapter, t_u32 data_len, t_u32 head_room,
905 		       t_u32 malloc_flag)
906 {
907 	mlan_status ret = MLAN_STATUS_SUCCESS;
908 	pmlan_buffer pmbuf = MNULL;
909 	t_u32 buf_size = 0;
910 	t_u8 *tmp_buf = MNULL;
911 	pmlan_callbacks pcb = &pmadapter->callbacks;
912 
913 	ENTER();
914 
915 	/* make sure that the data length is at least SDIO block size */
916 	data_len =
917 		(data_len + MLAN_SDIO_BLOCK_SIZE -
918 		 1) / MLAN_SDIO_BLOCK_SIZE * MLAN_SDIO_BLOCK_SIZE;
919 
920 	/* head_room is not implemented for malloc mlan buffer */
921 
922 	switch (malloc_flag) {
923 	case MOAL_MALLOC_BUFFER:
924 		buf_size = sizeof(mlan_buffer) + data_len + DMA_ALIGNMENT;
925 		ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size,
926 				       MLAN_MEM_DEF | MLAN_MEM_DMA,
927 				       (t_u8 **)&pmbuf);
928 		if ((ret != MLAN_STATUS_SUCCESS) || !pmbuf) {
929 			pmbuf = MNULL;
930 			goto exit;
931 		}
932 		memset(pmadapter, pmbuf, 0, sizeof(mlan_buffer));
933 
934 		pmbuf->pdesc = MNULL;
935 		/* Align address */
936 		pmbuf->pbuf =
937 			(t_u8 *)ALIGN_ADDR((t_u8 *)pmbuf + sizeof(mlan_buffer),
938 					   DMA_ALIGNMENT);
939 		pmbuf->data_offset = 0;
940 		pmbuf->data_len = data_len;
941 		pmbuf->flags |= MLAN_BUF_FLAG_MALLOC_BUF;
942 		break;
943 
944 	case MOAL_ALLOC_MLAN_BUFFER:
945 		/* use moal_alloc_mlan_buffer, head_room supported */
946 		ret = pcb->moal_alloc_mlan_buffer(pmadapter->pmoal_handle,
947 						  data_len + DMA_ALIGNMENT +
948 						  head_room, &pmbuf);
949 		if ((ret != MLAN_STATUS_SUCCESS) || !pmbuf) {
950 			PRINTM(MERROR, "Failed to allocate 'mlan_buffer'\n");
951 			goto exit;
952 		}
953 		pmbuf->data_offset = head_room;
954 		tmp_buf =
955 			(t_u8 *)ALIGN_ADDR(pmbuf->pbuf + pmbuf->data_offset,
956 					   DMA_ALIGNMENT);
957 		pmbuf->data_offset +=
958 			(t_u32)(tmp_buf - (pmbuf->pbuf + pmbuf->data_offset));
959 		pmbuf->data_len = data_len;
960 		pmbuf->flags = 0;
961 		break;
962 	}
963 
964 exit:
965 	LEAVE();
966 	return pmbuf;
967 }
968 
969 /**
970  *  @brief This function frees a mlan_buffer.
971  *
972  *  @param pmadapter  Pointer to mlan_adapter
973  *  @param pmbuf      Pointer to mlan_buffer
974  *
975  *  @return           N/A
976  */
977 t_void
wlan_free_mlan_buffer(mlan_adapter * pmadapter,pmlan_buffer pmbuf)978 wlan_free_mlan_buffer(mlan_adapter *pmadapter, pmlan_buffer pmbuf)
979 {
980 	pmlan_callbacks pcb = &pmadapter->callbacks;
981 	ENTER();
982 
983 	if (pcb && pmbuf) {
984 		if (pmbuf->flags & MLAN_BUF_FLAG_BRIDGE_BUF)
985 			util_scalar_decrement(pmadapter->pmoal_handle,
986 					      &pmadapter->pending_bridge_pkts,
987 					      pmadapter->callbacks.
988 					      moal_spin_lock,
989 					      pmadapter->callbacks.
990 					      moal_spin_unlock);
991 		if (pmbuf->flags & MLAN_BUF_FLAG_MALLOC_BUF)
992 			pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmbuf);
993 		else
994 			pcb->moal_free_mlan_buffer(pmadapter->pmoal_handle,
995 						   pmbuf);
996 	}
997 
998 	LEAVE();
999 	return;
1000 }
1001 
1002 /**
1003  *  @brief Delay function implementation
1004  *
1005  *  @param pmadapter        A pointer to mlan_adapter structure
1006  *  @param delay            Delay value
1007  *  @param u                Units of delay (sec, msec or usec)
1008  *
1009  *  @return                 N/A
1010  */
1011 t_void
wlan_delay_func(mlan_adapter * pmadapter,t_u32 delay,t_delay_unit u)1012 wlan_delay_func(mlan_adapter *pmadapter, t_u32 delay, t_delay_unit u)
1013 {
1014 	t_u32 now_tv_sec, now_tv_usec;
1015 	t_u32 upto_tv_sec, upto_tv_usec;
1016 	pmlan_callbacks pcb = &pmadapter->callbacks;
1017 
1018 	ENTER();
1019 
1020 	if (pcb->moal_udelay) {
1021 		if (u == SEC)
1022 			delay *= 1000000;
1023 		else if (u == MSEC)
1024 			delay *= 1000;
1025 		pcb->moal_udelay(pmadapter->pmoal_handle, delay);
1026 	} else {
1027 
1028 		pcb->moal_get_system_time(pmadapter->pmoal_handle, &upto_tv_sec,
1029 					  &upto_tv_usec);
1030 
1031 		switch (u) {
1032 		case SEC:
1033 			upto_tv_sec += delay;
1034 			break;
1035 		case MSEC:
1036 			delay *= 1000;
1037 		case USEC:
1038 			upto_tv_sec += (delay / 1000000);
1039 			upto_tv_usec += (delay % 1000000);
1040 			break;
1041 		}
1042 
1043 		do {
1044 			pcb->moal_get_system_time(pmadapter->pmoal_handle,
1045 						  &now_tv_sec, &now_tv_usec);
1046 			if (now_tv_sec > upto_tv_sec) {
1047 				LEAVE();
1048 				return;
1049 			}
1050 
1051 			if ((now_tv_sec == upto_tv_sec) &&
1052 			    (now_tv_usec >= upto_tv_usec)) {
1053 				LEAVE();
1054 				return;
1055 			}
1056 		} while (MTRUE);
1057 	}
1058 
1059 	LEAVE();
1060 	return;
1061 }
1062 
1063 /**
1064  *  @brief Send coalescing status command to firmware
1065  *
1066  *  @param pmadapter	A pointer to mlan_adapter structure
1067  *  @param pioctl_req	A pointer to ioctl request buffer
1068  *
1069  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
1070  */
1071 mlan_status
wlan_misc_ioctl_coalescing_status(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1072 wlan_misc_ioctl_coalescing_status(IN pmlan_adapter pmadapter,
1073 				  IN pmlan_ioctl_req pioctl_req)
1074 {
1075 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1076 	mlan_status ret = MLAN_STATUS_SUCCESS;
1077 	mlan_ds_misc_cfg *misc = MNULL;
1078 	t_u16 cmd_action = 0;
1079 
1080 	ENTER();
1081 
1082 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
1083 
1084 	if (pioctl_req->action == MLAN_ACT_SET)
1085 		cmd_action = HostCmd_ACT_GEN_SET;
1086 	else
1087 		cmd_action = HostCmd_ACT_GEN_GET;
1088 
1089 	ret = wlan_prepare_cmd(pmpriv,
1090 			       HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
1091 			       cmd_action,
1092 			       0,
1093 			       (t_void *)pioctl_req,
1094 			       &misc->param.coalescing_status);
1095 
1096 	if (ret == MLAN_STATUS_SUCCESS)
1097 		ret = MLAN_STATUS_PENDING;
1098 
1099 	LEAVE();
1100 	return ret;
1101 }
1102 
1103 /**
1104  *  @brief BSS remove
1105  *
1106  *  @param pmadapter	A pointer to mlan_adapter structure
1107  *  @param pioctl_req	A pointer to ioctl request buffer
1108  *
1109  *  @return		MLAN_STATUS_PENDING --success, MLAN_STATUS_FAILURE
1110  */
1111 mlan_status
wlan_bss_ioctl_bss_remove(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1112 wlan_bss_ioctl_bss_remove(IN pmlan_adapter pmadapter,
1113 			  IN pmlan_ioctl_req pioctl_req)
1114 {
1115 	ENTER();
1116 	wlan_cancel_bss_pending_cmd(pmadapter, pioctl_req->bss_index);
1117 	LEAVE();
1118 	return MLAN_STATUS_SUCCESS;
1119 }
1120 
1121 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
1122 /**
1123  *  @brief Set/Get BSS role
1124  *
1125  *  @param pmadapter	A pointer to mlan_adapter structure
1126  *  @param pioctl_req	A pointer to ioctl request buffer
1127  *
1128  *  @return		MLAN_STATUS_PENDING --success, MLAN_STATUS_FAILURE
1129  */
1130 mlan_status
wlan_bss_ioctl_bss_role(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1131 wlan_bss_ioctl_bss_role(IN pmlan_adapter pmadapter,
1132 			IN pmlan_ioctl_req pioctl_req)
1133 {
1134 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1135 	mlan_ds_bss *bss = MNULL;
1136 	mlan_status ret = MLAN_STATUS_SUCCESS;
1137 	HostCmd_DS_VERSION_EXT dummy;
1138 #if defined(WIFI_DIRECT_SUPPORT)
1139 	t_u8 bss_mode;
1140 #endif
1141 	t_u8 i, global_band = 0;
1142 	int j;
1143 
1144 	ENTER();
1145 
1146 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
1147 	if (pioctl_req->action == MLAN_ACT_GET) {
1148 		bss->param.bss_role = GET_BSS_ROLE(pmpriv);
1149 	} else {
1150 		if (GET_BSS_ROLE(pmpriv) == bss->param.bss_role) {
1151 			PRINTM(MIOCTL, "BSS ie already in the desired role!\n");
1152 			goto done;
1153 		}
1154 		mlan_block_rx_process(pmadapter, MTRUE);
1155 		/** Switch BSS role */
1156 		wlan_free_priv(pmpriv);
1157 
1158 		pmpriv->bss_role = bss->param.bss_role;
1159 		if (pmpriv->bss_type == MLAN_BSS_TYPE_UAP)
1160 			pmpriv->bss_type = MLAN_BSS_TYPE_STA;
1161 		else if (pmpriv->bss_type == MLAN_BSS_TYPE_STA)
1162 			pmpriv->bss_type = MLAN_BSS_TYPE_UAP;
1163 		/* Initialize private structures */
1164 		wlan_init_priv(pmpriv);
1165 		mlan_block_rx_process(pmadapter, MFALSE);
1166 		/* Initialize function table */
1167 		for (j = 0; mlan_ops[j]; j++) {
1168 			if (mlan_ops[j]->bss_role == GET_BSS_ROLE(pmpriv)) {
1169 				memcpy(pmadapter, &pmpriv->ops, mlan_ops[j],
1170 				       sizeof(mlan_operations));
1171 			}
1172 		}
1173 
1174 		for (i = 0; i < pmadapter->priv_num; i++) {
1175 			if (pmadapter->priv[i] &&
1176 			    GET_BSS_ROLE(pmadapter->priv[i]) ==
1177 			    MLAN_BSS_ROLE_STA)
1178 				global_band |= pmadapter->priv[i]->config_bands;
1179 		}
1180 
1181 		if (global_band != pmadapter->config_bands) {
1182 			if (wlan_set_regiontable
1183 			    (pmpriv, (t_u8)pmadapter->region_code,
1184 			     global_band | pmadapter->adhoc_start_band)) {
1185 				pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
1186 				LEAVE();
1187 				return MLAN_STATUS_FAILURE;
1188 			}
1189 
1190 			if (wlan_11d_set_universaltable
1191 			    (pmpriv,
1192 			     global_band | pmadapter->adhoc_start_band)) {
1193 				pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
1194 				LEAVE();
1195 				return MLAN_STATUS_FAILURE;
1196 			}
1197 			pmadapter->config_bands = global_band;
1198 		}
1199 
1200 		/* Issue commands to initialize firmware */
1201 #if defined(WIFI_DIRECT_SUPPORT)
1202 		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA)
1203 			bss_mode = BSS_MODE_WIFIDIRECT_CLIENT;
1204 		else
1205 			bss_mode = BSS_MODE_WIFIDIRECT_GO;
1206 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SET_BSS_MODE,
1207 				       HostCmd_ACT_GEN_SET, 0, MNULL,
1208 				       &bss_mode);
1209 		if (ret)
1210 			goto done;
1211 #endif
1212 		ret = pmpriv->ops.init_cmd(pmpriv, MFALSE);
1213 		if (ret == MLAN_STATUS_FAILURE)
1214 			goto done;
1215 
1216 		/* Issue dummy Get command to complete the ioctl */
1217 		memset(pmadapter, &dummy, 0, sizeof(HostCmd_DS_VERSION_EXT));
1218 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_VERSION_EXT,
1219 				       HostCmd_ACT_GEN_GET, 0,
1220 				       (t_void *)pioctl_req, (t_void *)&dummy);
1221 		if (ret == MLAN_STATUS_SUCCESS)
1222 			ret = MLAN_STATUS_PENDING;
1223 	}
1224 
1225 done:
1226 	LEAVE();
1227 	return ret;
1228 }
1229 #endif
1230 
1231 /**
1232  *  @brief Set the custom IE
1233  *
1234  *  @param pmadapter	A pointer to mlan_adapter structure
1235  *  @param pioctl_req	A pointer to ioctl request buffer
1236  *  @param send_ioctl	Flag to indicate if ioctl should be sent with cmd
1237  *                      (MTRUE if from moal/user, MFALSE if internal)
1238  *
1239  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
1240  */
1241 mlan_status
wlan_misc_ioctl_custom_ie_list(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req,IN t_bool send_ioctl)1242 wlan_misc_ioctl_custom_ie_list(IN pmlan_adapter pmadapter,
1243 			       IN pmlan_ioctl_req pioctl_req,
1244 			       IN t_bool send_ioctl)
1245 {
1246 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1247 	mlan_status ret = MLAN_STATUS_SUCCESS;
1248 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
1249 	custom_ie *ie_data = MNULL;
1250 	t_u16 cmd_action = 0, index, mask, i, len, app_data_len;
1251 	t_s32 ioctl_len;
1252 	t_u8 *tmp_ie;
1253 
1254 	ENTER();
1255 
1256 	if ((misc->param.cust_ie.len == 0) ||
1257 	    (misc->param.cust_ie.len == sizeof(t_u16))) {
1258 		pioctl_req->action = MLAN_ACT_GET;
1259 		/* Get the IE */
1260 		cmd_action = HostCmd_ACT_GEN_GET;
1261 	} else {
1262 		/* ioctl_len : ioctl length from application, start with
1263 		 * misc->param.cust_ie.len and reach upto 0 */
1264 		ioctl_len = misc->param.cust_ie.len;
1265 
1266 		/* app_data_len : length from application, start with 0
1267 		 * and reach upto ioctl_len */
1268 		app_data_len = sizeof(MrvlIEtypesHeader_t);
1269 		misc->param.cust_ie.len = 0;
1270 
1271 		while (ioctl_len > 0) {
1272 			ie_data = (custom_ie *)(((t_u8 *)&misc->param.cust_ie)
1273 						+ app_data_len);
1274 			ioctl_len -=
1275 				(ie_data->ie_length + MLAN_CUSTOM_IE_HDR_SIZE);
1276 			app_data_len +=
1277 				(ie_data->ie_length + MLAN_CUSTOM_IE_HDR_SIZE);
1278 
1279 			index = ie_data->ie_index;
1280 			mask = ie_data->mgmt_subtype_mask;
1281 
1282 			/* Need to be Autohandled */
1283 			if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == index) {
1284 				/* Automatic Deletion */
1285 				if (mask == MLAN_CUSTOM_IE_DELETE_MASK) {
1286 					ret = wlan_custom_ioctl_auto_delete
1287 						(pmpriv, pioctl_req, ie_data,
1288 						 index);
1289 					/* if IE to delete is not found, return error */
1290 					if (ret == MLAN_STATUS_FAILURE)
1291 						goto done;
1292 					index = ie_data->ie_index;
1293 					memset(pmadapter, ie_data, 0,
1294 					       sizeof(custom_ie) *
1295 					       MAX_MGMT_IE_INDEX_TO_FW);
1296 					len = 0;
1297 					for (i = 0;
1298 					     i < pmadapter->max_mgmt_ie_index;
1299 					     i++) {
1300 						/* Check if index is updated before sending to FW */
1301 						if (index & ((t_u16)1) << i) {
1302 							memcpy(pmadapter,
1303 							       (t_u8 *)ie_data +
1304 							       len, &i,
1305 							       sizeof(ie_data->
1306 								      ie_index));
1307 							len += sizeof(ie_data->
1308 								      ie_index);
1309 							memcpy(pmadapter,
1310 							       (t_u8 *)ie_data +
1311 							       len,
1312 							       &pmpriv->
1313 							       mgmt_ie[i].
1314 							       mgmt_subtype_mask,
1315 							       sizeof(ie_data->
1316 								      mgmt_subtype_mask));
1317 							len += sizeof(ie_data->
1318 								      mgmt_subtype_mask);
1319 							memcpy(pmadapter,
1320 							       (t_u8 *)ie_data +
1321 							       len,
1322 							       &pmpriv->
1323 							       mgmt_ie[i].
1324 							       ie_length,
1325 							       sizeof(ie_data->
1326 								      ie_length));
1327 							len += sizeof(ie_data->
1328 								      ie_length);
1329 							if (pmpriv->mgmt_ie[i].
1330 							    ie_length) {
1331 								memcpy(pmadapter, (t_u8 *)ie_data + len, &pmpriv->mgmt_ie[i].ie_buffer, pmpriv->mgmt_ie[i].ie_length);
1332 								len += pmpriv->
1333 									mgmt_ie
1334 									[i].
1335 									ie_length;
1336 							}
1337 						}
1338 					}
1339 					misc->param.cust_ie.len += len;
1340 					pioctl_req->action = MLAN_ACT_SET;
1341 					cmd_action = HostCmd_ACT_GEN_SET;
1342 				} else {	/* Automatic Addition */
1343 					if (MLAN_STATUS_FAILURE ==
1344 					    wlan_custom_ioctl_get_autoidx
1345 					    (pmpriv, pioctl_req, mask, ie_data,
1346 					     &index)) {
1347 						PRINTM(MERROR,
1348 						       "Failed to Set the IE buffer\n");
1349 						ret = MLAN_STATUS_FAILURE;
1350 						goto done;
1351 					}
1352 					mask &= ~MLAN_CUSTOM_IE_NEW_MASK;
1353 					if (MLAN_CUSTOM_IE_AUTO_IDX_MASK ==
1354 					    index) {
1355 						ret = MLAN_STATUS_SUCCESS;
1356 						goto done;
1357 					}
1358 					tmp_ie = (t_u8 *)&pmpriv->
1359 						mgmt_ie[index].ie_buffer;
1360 					memcpy(pmadapter,
1361 					       tmp_ie +
1362 					       pmpriv->mgmt_ie[index].ie_length,
1363 					       &ie_data->ie_buffer,
1364 					       ie_data->ie_length);
1365 					pmpriv->mgmt_ie[index].ie_length +=
1366 						ie_data->ie_length;
1367 					pmpriv->mgmt_ie[index].ie_index = index;
1368 					pmpriv->mgmt_ie[index].
1369 						mgmt_subtype_mask = mask;
1370 
1371 					pioctl_req->action = MLAN_ACT_SET;
1372 					cmd_action = HostCmd_ACT_GEN_SET;
1373 					ie_data->ie_index = index;
1374 					ie_data->ie_length =
1375 						pmpriv->mgmt_ie[index].
1376 						ie_length;
1377 					memcpy(pmadapter, &ie_data->ie_buffer,
1378 					       &pmpriv->mgmt_ie[index].
1379 					       ie_buffer,
1380 					       pmpriv->mgmt_ie[index].
1381 					       ie_length);
1382 					misc->param.cust_ie.len +=
1383 						pmpriv->mgmt_ie[index].
1384 						ie_length +
1385 						MLAN_CUSTOM_IE_HDR_SIZE;
1386 				}
1387 			} else {
1388 				if (index >= pmadapter->max_mgmt_ie_index) {
1389 					PRINTM(MERROR,
1390 					       "Invalid custom IE index %d\n",
1391 					       index);
1392 					ret = MLAN_STATUS_FAILURE;
1393 					goto done;
1394 				}
1395 				/* Set/Clear the IE and save it */
1396 				if (ie_data->mgmt_subtype_mask ==
1397 				    MLAN_CUSTOM_IE_DELETE_MASK &&
1398 				    ie_data->ie_length) {
1399 					PRINTM(MINFO, "Clear the IE buffer\n");
1400 					ret = wlan_custom_ioctl_auto_delete
1401 						(pmpriv, pioctl_req, ie_data,
1402 						 index);
1403 					/* if IE to delete is not found, return error */
1404 					if (ret == MLAN_STATUS_FAILURE)
1405 						goto done;
1406 					memset(pmadapter, ie_data, 0,
1407 					       sizeof(custom_ie) *
1408 					       MAX_MGMT_IE_INDEX_TO_FW);
1409 					memcpy(pmadapter, (t_u8 *)ie_data,
1410 					       &pmpriv->mgmt_ie[index],
1411 					       pmpriv->mgmt_ie[index].
1412 					       ie_length +
1413 					       MLAN_CUSTOM_IE_HDR_SIZE);
1414 				} else {
1415 					/*
1416 					 * Check if this index is being used on
1417 					 * any other interfaces. If yes, then
1418 					 * the request needs to be rejected.
1419 					 */
1420 					ret = wlan_is_custom_ie_index_unused
1421 						(pmpriv, index);
1422 					if (ret == MLAN_STATUS_FAILURE) {
1423 						PRINTM(MERROR,
1424 						       "IE index is used by other interface.\n");
1425 						PRINTM(MERROR,
1426 						       "Set or delete on index %d is not allowed.\n",
1427 						       index);
1428 						pioctl_req->status_code =
1429 							MLAN_ERROR_IOCTL_FAIL;
1430 						goto done;
1431 					}
1432 					PRINTM(MINFO, "Set the IE buffer\n");
1433 					if (ie_data->mgmt_subtype_mask ==
1434 					    MLAN_CUSTOM_IE_DELETE_MASK)
1435 						ie_data->ie_length = 0;
1436 					else {
1437 						if ((pmpriv->mgmt_ie[index].
1438 						     mgmt_subtype_mask ==
1439 						     ie_data->mgmt_subtype_mask)
1440 						    && (pmpriv->mgmt_ie[index].
1441 							ie_length ==
1442 							ie_data->ie_length) &&
1443 						    !memcmp(pmpriv->adapter,
1444 							    pmpriv->
1445 							    mgmt_ie[index].
1446 							    ie_buffer,
1447 							    ie_data->ie_buffer,
1448 							    ie_data->
1449 							    ie_length)) {
1450 							PRINTM(MIOCTL,
1451 							       "same custom ie already configured!\n");
1452 							if (ioctl_len <= 0 &&
1453 							    misc->param.cust_ie.
1454 							    len == 0) {
1455 								goto done;
1456 							} else {
1457 								/* remove matching IE from app buffer */
1458 								app_data_len -=
1459 									ie_data->
1460 									ie_length
1461 									+
1462 									MLAN_CUSTOM_IE_HDR_SIZE;
1463 								memmove(pmadapter, (t_u8 *)ie_data, ie_data->ie_buffer + ie_data->ie_length, ioctl_len);
1464 								continue;
1465 							}
1466 						}
1467 					}
1468 					memset(pmadapter,
1469 					       &pmpriv->mgmt_ie[index], 0,
1470 					       sizeof(custom_ie));
1471 					memcpy(pmadapter,
1472 					       &pmpriv->mgmt_ie[index], ie_data,
1473 					       sizeof(custom_ie));
1474 				}
1475 
1476 				misc->param.cust_ie.len +=
1477 					pmpriv->mgmt_ie[index].ie_length +
1478 					MLAN_CUSTOM_IE_HDR_SIZE;
1479 				pioctl_req->action = MLAN_ACT_SET;
1480 				cmd_action = HostCmd_ACT_GEN_SET;
1481 			}
1482 		}
1483 	}
1484 
1485 	/* Send command to firmware */
1486 	if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
1487 		ret = wlan_prepare_cmd(pmpriv,
1488 				       HostCmd_CMD_MGMT_IE_LIST,
1489 				       cmd_action,
1490 				       0,
1491 				       (send_ioctl) ? (t_void *)pioctl_req :
1492 				       MNULL, &misc->param.cust_ie);
1493 	}
1494 #ifdef UAP_SUPPORT
1495 	else if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
1496 		ret = wlan_prepare_cmd(pmpriv,
1497 				       HOST_CMD_APCMD_SYS_CONFIGURE,
1498 				       cmd_action,
1499 				       0,
1500 				       (send_ioctl) ? (t_void *)pioctl_req :
1501 				       MNULL,
1502 				       (send_ioctl) ? MNULL : &misc->param.
1503 				       cust_ie);
1504 	}
1505 #endif
1506 	if (ret == MLAN_STATUS_SUCCESS)
1507 		ret = MLAN_STATUS_PENDING;
1508 done:
1509 	LEAVE();
1510 	return ret;
1511 }
1512 
1513 /**
1514  *  @brief Read/write adapter register
1515  *
1516  *  @param pmadapter	A pointer to mlan_adapter structure
1517  *  @param pioctl_req	A pointer to ioctl request buffer
1518  *
1519  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
1520  */
1521 mlan_status
wlan_reg_mem_ioctl_reg_rw(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1522 wlan_reg_mem_ioctl_reg_rw(IN pmlan_adapter pmadapter,
1523 			  IN pmlan_ioctl_req pioctl_req)
1524 {
1525 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1526 	mlan_ds_reg_mem *reg_mem = MNULL;
1527 	mlan_status ret = MLAN_STATUS_SUCCESS;
1528 	t_u16 cmd_action = 0, cmd_no;
1529 
1530 	ENTER();
1531 
1532 	reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
1533 	if (pioctl_req->action == MLAN_ACT_GET)
1534 		cmd_action = HostCmd_ACT_GEN_GET;
1535 	else
1536 		cmd_action = HostCmd_ACT_GEN_SET;
1537 
1538 	switch (reg_mem->param.reg_rw.type) {
1539 	case MLAN_REG_MAC:
1540 		cmd_no = HostCmd_CMD_MAC_REG_ACCESS;
1541 		break;
1542 	case MLAN_REG_BBP:
1543 		cmd_no = HostCmd_CMD_BBP_REG_ACCESS;
1544 		break;
1545 	case MLAN_REG_RF:
1546 		cmd_no = HostCmd_CMD_RF_REG_ACCESS;
1547 		break;
1548 	case MLAN_REG_CAU:
1549 		cmd_no = HostCmd_CMD_CAU_REG_ACCESS;
1550 		break;
1551 	case MLAN_REG_PSU:
1552 		cmd_no = HostCmd_CMD_TARGET_ACCESS;
1553 		break;
1554 	default:
1555 		pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1556 		ret = MLAN_STATUS_FAILURE;
1557 		goto exit;
1558 	}
1559 
1560 	/* Send request to firmware */
1561 	ret = wlan_prepare_cmd(pmpriv, cmd_no, cmd_action,
1562 			       0, (t_void *)pioctl_req,
1563 			       (t_void *)&reg_mem->param.reg_rw);
1564 
1565 	if (ret == MLAN_STATUS_SUCCESS)
1566 		ret = MLAN_STATUS_PENDING;
1567 
1568 exit:
1569 	LEAVE();
1570 	return ret;
1571 }
1572 
1573 /**
1574  *  @brief Read the EEPROM contents of the card
1575  *
1576  *  @param pmadapter	A pointer to mlan_adapter structure
1577  *  @param pioctl_req	A pointer to ioctl request buffer
1578  *
1579  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
1580  */
1581 mlan_status
wlan_reg_mem_ioctl_read_eeprom(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1582 wlan_reg_mem_ioctl_read_eeprom(IN pmlan_adapter pmadapter,
1583 			       IN pmlan_ioctl_req pioctl_req)
1584 {
1585 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1586 	mlan_ds_reg_mem *reg_mem = MNULL;
1587 	mlan_status ret = MLAN_STATUS_SUCCESS;
1588 	t_u16 cmd_action = 0;
1589 
1590 	ENTER();
1591 
1592 	reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
1593 	if (pioctl_req->action == MLAN_ACT_GET)
1594 		cmd_action = HostCmd_ACT_GEN_GET;
1595 
1596 	/* Send request to firmware */
1597 	ret = wlan_prepare_cmd(pmpriv,
1598 			       HostCmd_CMD_802_11_EEPROM_ACCESS,
1599 			       cmd_action, 0, (t_void *)pioctl_req,
1600 			       (t_void *)&reg_mem->param.rd_eeprom);
1601 
1602 	if (ret == MLAN_STATUS_SUCCESS)
1603 		ret = MLAN_STATUS_PENDING;
1604 
1605 	LEAVE();
1606 	return ret;
1607 }
1608 
1609 /**
1610  *  @brief Read/write memory of device
1611  *
1612  *  @param pmadapter	A pointer to mlan_adapter structure
1613  *  @param pioctl_req	A pointer to ioctl request buffer
1614  *
1615  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
1616  */
1617 mlan_status
wlan_reg_mem_ioctl_mem_rw(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1618 wlan_reg_mem_ioctl_mem_rw(IN pmlan_adapter pmadapter,
1619 			  IN pmlan_ioctl_req pioctl_req)
1620 {
1621 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1622 	mlan_ds_reg_mem *reg_mem = MNULL;
1623 	mlan_status ret = MLAN_STATUS_SUCCESS;
1624 	t_u16 cmd_action = 0;
1625 
1626 	ENTER();
1627 
1628 	reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
1629 	if (pioctl_req->action == MLAN_ACT_GET)
1630 		cmd_action = HostCmd_ACT_GEN_GET;
1631 	else
1632 		cmd_action = HostCmd_ACT_GEN_SET;
1633 
1634 	/* Send request to firmware */
1635 	ret = wlan_prepare_cmd(pmpriv,
1636 			       HostCmd_CMD_MEM_ACCESS,
1637 			       cmd_action, 0,
1638 			       (t_void *)pioctl_req,
1639 			       (t_void *)&reg_mem->param.mem_rw);
1640 
1641 	if (ret == MLAN_STATUS_SUCCESS)
1642 		ret = MLAN_STATUS_PENDING;
1643 
1644 	LEAVE();
1645 	return ret;
1646 }
1647 
1648 /**
1649  *  @brief This function will check if station list is empty
1650  *
1651  *  @param priv    A pointer to mlan_private
1652  *
1653  *  @return	   MFALSE/MTRUE
1654  */
1655 t_u8
wlan_is_station_list_empty(mlan_private * priv)1656 wlan_is_station_list_empty(mlan_private *priv)
1657 {
1658 	ENTER();
1659 	if (!(util_peek_list(priv->adapter->pmoal_handle,
1660 			     &priv->sta_list,
1661 			     priv->adapter->callbacks.moal_spin_lock,
1662 			     priv->adapter->callbacks.moal_spin_unlock))) {
1663 		LEAVE();
1664 		return MTRUE;
1665 	}
1666 	LEAVE();
1667 	return MFALSE;
1668 }
1669 
1670 /**
1671  *  @brief This function will return the pointer to station entry in station list
1672  *          table which matches the give mac address
1673  *
1674  *  @param priv    A pointer to mlan_private
1675  *  @param mac     mac address to find in station list table
1676  *
1677  *  @return	   A pointer to structure sta_node
1678  */
1679 sta_node *
wlan_get_station_entry(mlan_private * priv,t_u8 * mac)1680 wlan_get_station_entry(mlan_private *priv, t_u8 *mac)
1681 {
1682 	sta_node *sta_ptr;
1683 
1684 	ENTER();
1685 
1686 	if (!mac) {
1687 		LEAVE();
1688 		return MNULL;
1689 	}
1690 	sta_ptr = (sta_node *)util_peek_list(priv->adapter->pmoal_handle,
1691 					     &priv->sta_list,
1692 					     priv->adapter->callbacks.
1693 					     moal_spin_lock,
1694 					     priv->adapter->callbacks.
1695 					     moal_spin_unlock);
1696 
1697 	while (sta_ptr && (sta_ptr != (sta_node *)&priv->sta_list)) {
1698 		if (!memcmp
1699 		    (priv->adapter, sta_ptr->mac_addr, mac,
1700 		     MLAN_MAC_ADDR_LENGTH)) {
1701 			LEAVE();
1702 			return sta_ptr;
1703 		}
1704 		sta_ptr = sta_ptr->pnext;
1705 	}
1706 	LEAVE();
1707 	return MNULL;
1708 }
1709 
1710 /**
1711  *  @brief This function will add a pointer to station entry in station list
1712  *          table with the give mac address, if it does not exist already
1713  *
1714  *  @param priv    A pointer to mlan_private
1715  *  @param mac     mac address to find in station list table
1716  *
1717  *  @return	   A pointer to structure sta_node
1718  */
1719 sta_node *
wlan_add_station_entry(mlan_private * priv,t_u8 * mac)1720 wlan_add_station_entry(mlan_private *priv, t_u8 *mac)
1721 {
1722 	sta_node *sta_ptr = MNULL;
1723 	mlan_adapter *pmadapter = priv->adapter;
1724 
1725 	ENTER();
1726 	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
1727 					    priv->wmm.ra_list_spinlock);
1728 
1729 	sta_ptr = wlan_get_station_entry(priv, mac);
1730 	if (sta_ptr)
1731 		goto done;
1732 	if (priv->adapter->callbacks.
1733 	    moal_malloc(priv->adapter->pmoal_handle, sizeof(sta_node),
1734 			MLAN_MEM_DEF, (t_u8 **)&sta_ptr)) {
1735 		PRINTM(MERROR, "Failed to allocate memory for station node\n");
1736 		pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
1737 						      priv->wmm.
1738 						      ra_list_spinlock);
1739 		LEAVE();
1740 		return MNULL;
1741 	}
1742 	memset(priv->adapter, sta_ptr, 0, sizeof(sta_node));
1743 	memcpy(priv->adapter, sta_ptr->mac_addr, mac, MLAN_MAC_ADDR_LENGTH);
1744 	util_enqueue_list_tail(priv->adapter->pmoal_handle, &priv->sta_list,
1745 			       (pmlan_linked_list)sta_ptr,
1746 			       priv->adapter->callbacks.moal_spin_lock,
1747 			       priv->adapter->callbacks.moal_spin_unlock);
1748 #ifdef DRV_EMBEDDED_AUTHENTICATOR
1749 	if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
1750 	    IsAuthenticatorEnabled(priv->psapriv))
1751 		authenticator_init_client(priv->psapriv,
1752 					  &sta_ptr->cm_connectioninfo, mac);
1753 #endif
1754 done:
1755 	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
1756 					      priv->wmm.ra_list_spinlock);
1757 	LEAVE();
1758 	return sta_ptr;
1759 }
1760 
1761 /**
1762  *  @brief This function will delete a station entry from station list
1763  *
1764  *
1765  *  @param priv    A pointer to mlan_private
1766  *  @param mac     station's mac address
1767  *
1768  *  @return	   N/A
1769  */
1770 t_void
wlan_delete_station_entry(mlan_private * priv,t_u8 * mac)1771 wlan_delete_station_entry(mlan_private *priv, t_u8 *mac)
1772 {
1773 	sta_node *sta_ptr = MNULL;
1774 	mlan_adapter *pmadapter = priv->adapter;
1775 	ENTER();
1776 	pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
1777 					    priv->wmm.ra_list_spinlock);
1778 	sta_ptr = wlan_get_station_entry(priv, mac);
1779 	if (sta_ptr) {
1780 #ifdef DRV_EMBEDDED_AUTHENTICATOR
1781 		if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
1782 		    IsAuthenticatorEnabled(priv->psapriv))
1783 			authenticator_free_client(priv->psapriv,
1784 						  sta_ptr->cm_connectioninfo);
1785 #endif
1786 		util_unlink_list(priv->adapter->pmoal_handle, &priv->sta_list,
1787 				 (pmlan_linked_list)sta_ptr,
1788 				 priv->adapter->callbacks.moal_spin_lock,
1789 				 priv->adapter->callbacks.moal_spin_unlock);
1790 		priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle,
1791 						    (t_u8 *)sta_ptr);
1792 	}
1793 	pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
1794 					      priv->wmm.ra_list_spinlock);
1795 	LEAVE();
1796 	return;
1797 }
1798 
1799 /**
1800  *  @brief Clean up wapi station list
1801  *
1802  *  @param priv  Pointer to the mlan_private driver data struct
1803  *
1804  *  @return      N/A
1805  */
1806 t_void
wlan_delete_station_list(pmlan_private priv)1807 wlan_delete_station_list(pmlan_private priv)
1808 {
1809 	sta_node *sta_ptr;
1810 
1811 	ENTER();
1812 	while ((sta_ptr =
1813 		(sta_node *)util_dequeue_list(priv->adapter->pmoal_handle,
1814 					      &priv->sta_list,
1815 					      priv->adapter->callbacks.
1816 					      moal_spin_lock,
1817 					      priv->adapter->callbacks.
1818 					      moal_spin_unlock))) {
1819 #ifdef DRV_EMBEDDED_AUTHENTICATOR
1820 		if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
1821 		    IsAuthenticatorEnabled(priv->psapriv))
1822 			authenticator_free_client(priv->psapriv,
1823 						  sta_ptr->cm_connectioninfo);
1824 #endif
1825 		priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle,
1826 						    (t_u8 *)sta_ptr);
1827 	}
1828 	LEAVE();
1829 	return;
1830 }
1831 
1832 /**
1833  *  @brief Get tdls peer list
1834  *
1835  *  @param priv         A pointer to mlan_private structure
1836  *  @param buf          A pointer to tdls_peer_info buf
1837  *  @return             number of tdls peer
1838  */
1839 int
wlan_get_tdls_list(mlan_private * priv,tdls_peer_info * buf)1840 wlan_get_tdls_list(mlan_private *priv, tdls_peer_info *buf)
1841 {
1842 	tdls_peer_info *peer_info = buf;
1843 	sta_node *sta_ptr = MNULL;
1844 	int count = 0;
1845 	ENTER();
1846 	if (priv->bss_type != MLAN_BSS_TYPE_STA) {
1847 		LEAVE();
1848 		return count;
1849 	}
1850 	sta_ptr = (sta_node *)util_peek_list(priv->adapter->pmoal_handle,
1851 					     &priv->sta_list,
1852 					     priv->adapter->callbacks.
1853 					     moal_spin_lock,
1854 					     priv->adapter->callbacks.
1855 					     moal_spin_unlock);
1856 	if (!sta_ptr) {
1857 		LEAVE();
1858 		return count;
1859 	}
1860 	while (sta_ptr != (sta_node *)&priv->sta_list) {
1861 		if (sta_ptr->status == TDLS_SETUP_COMPLETE) {
1862 			peer_info->snr = sta_ptr->snr;
1863 			peer_info->nf = sta_ptr->nf;
1864 			memcpy(priv->adapter, peer_info->mac_addr,
1865 			       sta_ptr->mac_addr, MLAN_MAC_ADDR_LENGTH);
1866 			memcpy(priv->adapter, peer_info->ht_cap,
1867 			       &sta_ptr->HTcap, sizeof(IEEEtypes_HTCap_t));
1868 			memcpy(priv->adapter, peer_info->ext_cap,
1869 			       &sta_ptr->ExtCap, sizeof(IEEEtypes_ExtCap_t));
1870 			peer_info++;
1871 			count++;
1872 		}
1873 		sta_ptr = sta_ptr->pnext;
1874 		if (count >= MLAN_MAX_TDLS_PEER_SUPPORTED)
1875 			break;
1876 	}
1877 	LEAVE();
1878 	return count;
1879 }
1880 
1881 /**
1882  *  @brief Set the TDLS configuration to FW.
1883  *
1884  *  @param pmadapter	A pointer to mlan_adapter structure
1885  *  @param pioctl_req	A pointer to ioctl request buffer
1886  *
1887  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
1888  */
1889 mlan_status
wlan_misc_ioctl_tdls_config(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1890 wlan_misc_ioctl_tdls_config(IN pmlan_adapter pmadapter,
1891 			    IN pmlan_ioctl_req pioctl_req)
1892 {
1893 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1894 	mlan_status ret = MLAN_STATUS_SUCCESS;
1895 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
1896 	tdls_all_config *tdls_all_cfg =
1897 		(tdls_all_config *)misc->param.tdls_config.tdls_data;
1898 	t_u8 event_buf[100];
1899 	mlan_event *pevent = (mlan_event *)event_buf;
1900 	tdls_tear_down_event *tdls_evt =
1901 		(tdls_tear_down_event *)pevent->event_buf;
1902 	sta_node *sta_ptr = MNULL;
1903 	MrvlIEtypes_Data_t *pMrvlTlv = MNULL;
1904 	t_u8 *pos = MNULL;
1905 	t_u16 remain_len = 0;
1906 
1907 	ENTER();
1908 
1909 	if (misc->param.tdls_config.tdls_action == WLAN_TDLS_TEAR_DOWN_REQ) {
1910 		sta_ptr =
1911 			wlan_get_station_entry(pmpriv,
1912 					       tdls_all_cfg->u.tdls_tear_down.
1913 					       peer_mac_addr);
1914 		if (sta_ptr && sta_ptr->external_tdls) {
1915 			pevent->bss_index = pmpriv->bss_index;
1916 			pevent->event_id = MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ;
1917 			pevent->event_len = sizeof(tdls_tear_down_event);
1918 			memcpy(pmpriv->adapter, (t_u8 *)tdls_evt->peer_mac_addr,
1919 			       tdls_all_cfg->u.tdls_tear_down.peer_mac_addr,
1920 			       MLAN_MAC_ADDR_LENGTH);
1921 			tdls_evt->reason_code =
1922 				tdls_all_cfg->u.tdls_tear_down.reason_code;
1923 			wlan_recv_event(pmpriv,
1924 					MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ,
1925 					pevent);
1926 			LEAVE();
1927 			return ret;
1928 		}
1929 	}
1930 	if (misc->param.tdls_config.tdls_action == WLAN_HOST_TDLS_CONFIG) {
1931 		pmpriv->host_tdls_uapsd_support =
1932 			tdls_all_cfg->u.host_tdls_cfg.uapsd_support;
1933 		pmpriv->host_tdls_cs_support =
1934 			tdls_all_cfg->u.host_tdls_cfg.cs_support;
1935 		pos = tdls_all_cfg->u.host_tdls_cfg.tlv_buffer;
1936 		remain_len = tdls_all_cfg->u.host_tdls_cfg.tlv_len;
1937 		while (remain_len > sizeof(MrvlIEtypesHeader_t)) {
1938 			remain_len -= sizeof(MrvlIEtypesHeader_t);
1939 			pMrvlTlv = (MrvlIEtypes_Data_t *)pos;
1940 			switch (pMrvlTlv->header.type) {
1941 			case SUPPORTED_CHANNELS:
1942 				pmpriv->chan_supp_len =
1943 					(t_u8)pMrvlTlv->header.len;
1944 				memset(pmadapter, pmpriv->chan_supp, 0,
1945 				       sizeof(pmpriv->chan_supp));
1946 				memcpy(pmadapter, pmpriv->chan_supp,
1947 				       pMrvlTlv->data, MIN(pMrvlTlv->header.len,
1948 							   MAX_IE_SIZE));
1949 				DBG_HEXDUMP(MCMD_D, "TDLS supported channel",
1950 					    pmpriv->chan_supp,
1951 					    pmpriv->chan_supp_len);
1952 				break;
1953 			case REGULATORY_CLASS:
1954 				pmpriv->supp_regulatory_class_len =
1955 					(t_u8)pMrvlTlv->header.len;
1956 				memset(pmadapter, pmpriv->supp_regulatory_class,
1957 				       0,
1958 				       sizeof(pmpriv->supp_regulatory_class));
1959 				memcpy(pmadapter, pmpriv->supp_regulatory_class,
1960 				       pMrvlTlv->data, MIN(pMrvlTlv->header.len,
1961 							   MAX_IE_SIZE));
1962 				DBG_HEXDUMP(MCMD_D,
1963 					    "TDLS supported regulatory class",
1964 					    pmpriv->supp_regulatory_class,
1965 					    pmpriv->supp_regulatory_class_len);
1966 				break;
1967 			default:
1968 				break;
1969 			}
1970 			remain_len -= pMrvlTlv->header.len;
1971 			pos += sizeof(MrvlIEtypesHeader_t) +
1972 				pMrvlTlv->header.len;
1973 		}
1974 		LEAVE();
1975 		return ret;
1976 	}
1977 	pioctl_req->action = MLAN_ACT_SET;
1978 
1979 	/* Send command to firmware */
1980 	ret = wlan_prepare_cmd(pmpriv,
1981 			       HostCmd_CMD_TDLS_CONFIG,
1982 			       HostCmd_ACT_GEN_SET,
1983 			       0,
1984 			       (t_void *)pioctl_req, &misc->param.tdls_config);
1985 
1986 	if (ret == MLAN_STATUS_SUCCESS)
1987 		ret = MLAN_STATUS_PENDING;
1988 	LEAVE();
1989 	return ret;
1990 }
1991 
1992 /**
1993  *  @brief enable tdls config for cs and uapsd.
1994  *
1995  *  @param pmpriv	A pointer to mlan_private structure
1996  *  @param enable   	MTRUE/MFALSE
1997  *
1998  *  @return	        N/A
1999  */
2000 t_void
wlan_tdls_config(IN pmlan_private pmpriv,IN t_u8 enable)2001 wlan_tdls_config(IN pmlan_private pmpriv, IN t_u8 enable)
2002 {
2003 	mlan_adapter *pmadapter = pmpriv->adapter;
2004 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
2005 	mlan_ds_misc_tdls_config *tdls_config = MNULL;
2006 	tdls_all_config *tdls_all_cfg = MNULL;
2007 	mlan_status ret = MLAN_STATUS_SUCCESS;
2008 
2009 	ENTER();
2010 
2011 	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2012 			       sizeof(mlan_ds_misc_tdls_config), MLAN_MEM_DEF,
2013 			       (t_u8 **)&tdls_config);
2014 	if (ret != MLAN_STATUS_SUCCESS || !tdls_config) {
2015 		PRINTM(MERROR, "Memory allocation for tdls_config failed!\n");
2016 		LEAVE();
2017 		return;
2018 	}
2019 	memset(pmadapter, (t_u8 *)tdls_config, 0,
2020 	       sizeof(mlan_ds_misc_tdls_config));
2021 	tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
2022 	tdls_all_cfg->u.tdls_config.enable = enable;
2023 	tdls_config->tdls_action = WLAN_TDLS_CONFIG;
2024 	/* Send command to firmware */
2025 	wlan_prepare_cmd(pmpriv,
2026 			 HostCmd_CMD_TDLS_CONFIG,
2027 			 HostCmd_ACT_GEN_SET, 0, MNULL, tdls_config);
2028 	PRINTM(MCMND, "tdls_config: enable=%d\n", enable);
2029 
2030 	if (tdls_config)
2031 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tdls_config);
2032 
2033 	LEAVE();
2034 }
2035 
2036 /**
2037  *  @brief set tdls channel switch parameters.
2038  *
2039  *  @param pmpriv	A pointer to mlan_private structure
2040  *
2041  *  @return	        N/A
2042  */
2043 t_void
wlan_tdls_cs_param_config(IN pmlan_private pmpriv)2044 wlan_tdls_cs_param_config(IN pmlan_private pmpriv)
2045 {
2046 	mlan_adapter *pmadapter = pmpriv->adapter;
2047 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
2048 	mlan_ds_misc_tdls_config *tdls_config = MNULL;
2049 	tdls_all_config *tdls_all_cfg = MNULL;
2050 	mlan_status ret = MLAN_STATUS_SUCCESS;
2051 
2052 	ENTER();
2053 
2054 	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2055 			       sizeof(mlan_ds_misc_tdls_config), MLAN_MEM_DEF,
2056 			       (t_u8 **)&tdls_config);
2057 	if (ret != MLAN_STATUS_SUCCESS || !tdls_config) {
2058 		PRINTM(MERROR, "Memory allocation for tdls_config failed!\n");
2059 		LEAVE();
2060 		return;
2061 	}
2062 	memset(pmadapter, (t_u8 *)tdls_config, 0,
2063 	       sizeof(mlan_ds_misc_tdls_config));
2064 
2065 	tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
2066 	tdls_config->tdls_action = WLAN_TDLS_CS_PARAMS;
2067 	tdls_all_cfg->u.tdls_cs_params.unit_time = 2;
2068 	tdls_all_cfg->u.tdls_cs_params.threshold_otherlink = 10;
2069 	tdls_all_cfg->u.tdls_cs_params.threshold_directlink = 0;
2070 
2071 	/* Send command to firmware */
2072 	wlan_prepare_cmd(pmpriv,
2073 			 HostCmd_CMD_TDLS_CONFIG,
2074 			 HostCmd_ACT_GEN_SET, 0, MNULL, tdls_config);
2075 
2076 	if (tdls_config)
2077 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tdls_config);
2078 
2079 	LEAVE();
2080 }
2081 
2082 /**
2083  *  @brief start tdls channel switch
2084  *
2085  *  @param pmpriv	A pointer to mlan_private structure
2086   *  @param peer_mac_addr 	A pointer to peer mac address
2087   *  @param pioctl_buf   A pointer to ioctl request buffer
2088  *
2089  *  @return	         N/A
2090  */
2091 t_void
wlan_tdls_cs_start(IN pmlan_private pmpriv,IN t_u8 * peer_mac_addr,IN pmlan_ioctl_req pioctl_buf)2092 wlan_tdls_cs_start(IN pmlan_private pmpriv,
2093 		   IN t_u8 *peer_mac_addr, IN pmlan_ioctl_req pioctl_buf)
2094 {
2095 	mlan_adapter *pmadapter = pmpriv->adapter;
2096 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
2097 	mlan_ds_misc_tdls_config *tdls_config = MNULL;
2098 	tdls_all_config *tdls_all_cfg = MNULL;
2099 	mlan_ds_misc_cfg *misc = MNULL;
2100 	mlan_status ret = MLAN_STATUS_SUCCESS;
2101 
2102 	ENTER();
2103 
2104 	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2105 			       sizeof(mlan_ds_misc_tdls_config), MLAN_MEM_DEF,
2106 			       (t_u8 **)&tdls_config);
2107 	if (ret != MLAN_STATUS_SUCCESS || !tdls_config) {
2108 		PRINTM(MERROR, "Memory allocation for tdls_config failed!\n");
2109 		LEAVE();
2110 		return;
2111 	}
2112 	memset(pmadapter, (t_u8 *)tdls_config, 0,
2113 	       sizeof(mlan_ds_misc_tdls_config));
2114 
2115 	if (pioctl_buf) {
2116 		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
2117 		memcpy(pmpriv->adapter, tdls_config, &misc->param.tdls_config,
2118 		       sizeof(mlan_ds_misc_tdls_config));
2119 		tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
2120 		if (tdls_all_cfg->u.tdls_chan_switch.primary_channel > 14) {
2121 			tdls_all_cfg->u.tdls_chan_switch.
2122 				secondary_channel_offset =
2123 				wlan_get_second_channel_offset(tdls_all_cfg->u.
2124 							       tdls_chan_switch.
2125 							       primary_channel);
2126 		}
2127 		PRINTM(MCMND, "Start TDLS CS: channel=%d\n",
2128 		       tdls_all_cfg->u.tdls_chan_switch.primary_channel);
2129 	} else {
2130 		tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
2131 		tdls_config->tdls_action = WLAN_TDLS_INIT_CHAN_SWITCH;
2132 		memcpy(pmpriv->adapter,
2133 		       tdls_all_cfg->u.tdls_chan_switch.peer_mac_addr,
2134 		       peer_mac_addr, MLAN_MAC_ADDR_LENGTH);
2135 		tdls_all_cfg->u.tdls_chan_switch.primary_channel =
2136 			pmpriv->tdls_cs_channel;
2137 		if (pmpriv->tdls_cs_channel > 14) {
2138 			tdls_all_cfg->u.tdls_chan_switch.band = BAND_5GHZ;
2139 			tdls_all_cfg->u.tdls_chan_switch.
2140 				secondary_channel_offset =
2141 				wlan_get_second_channel_offset(pmpriv->
2142 							       tdls_cs_channel);
2143 		} else {
2144 			tdls_all_cfg->u.tdls_chan_switch.band = BAND_2GHZ;
2145 		}
2146 		PRINTM(MCMND, "Start TDLS CS: channel=%d\n",
2147 		       pmpriv->tdls_cs_channel);
2148 	}
2149 	tdls_all_cfg->u.tdls_chan_switch.switch_time = 10;
2150 	tdls_all_cfg->u.tdls_chan_switch.switch_timeout = 16;
2151 	tdls_all_cfg->u.tdls_chan_switch.regulatory_class = 12;
2152 	tdls_all_cfg->u.tdls_chan_switch.periodicity = 1;
2153 
2154 	/* Send command to firmware */
2155 	wlan_prepare_cmd(pmpriv,
2156 			 HostCmd_CMD_TDLS_CONFIG,
2157 			 HostCmd_ACT_GEN_SET, 0, MNULL, tdls_config);
2158 
2159 	if (tdls_config)
2160 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tdls_config);
2161 
2162 	LEAVE();
2163 }
2164 
2165 /**
2166  *  @brief stop tdls channel switch
2167  *
2168  *  @param pmpriv	A pointer to mlan_private structure
2169  *  @param peer_mac_addr 	A pointer to peer mac address
2170  *  @return	                N/A
2171  */
2172 t_void
wlan_tdls_cs_stop(IN pmlan_private pmpriv,IN t_u8 * peer_mac_addr)2173 wlan_tdls_cs_stop(IN pmlan_private pmpriv, IN t_u8 *peer_mac_addr)
2174 {
2175 	mlan_adapter *pmadapter = pmpriv->adapter;
2176 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
2177 	mlan_ds_misc_tdls_config *tdls_config = MNULL;
2178 	tdls_all_config *tdls_all_cfg = MNULL;
2179 	mlan_status ret = MLAN_STATUS_SUCCESS;
2180 
2181 	ENTER();
2182 
2183 	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2184 			       sizeof(mlan_ds_misc_tdls_config), MLAN_MEM_DEF,
2185 			       (t_u8 **)&tdls_config);
2186 	if (ret != MLAN_STATUS_SUCCESS || !tdls_config) {
2187 		PRINTM(MERROR, "Memory allocation for tdls_config failed!\n");
2188 		LEAVE();
2189 		return;
2190 	}
2191 	memset(pmadapter, (t_u8 *)tdls_config, 0,
2192 	       sizeof(mlan_ds_misc_tdls_config));
2193 
2194 	tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
2195 	tdls_config->tdls_action = WLAN_TDLS_STOP_CHAN_SWITCH;
2196 
2197 	memcpy(pmpriv->adapter,
2198 	       tdls_all_cfg->u.tdls_stop_chan_switch.peer_mac_addr,
2199 	       peer_mac_addr, MLAN_MAC_ADDR_LENGTH);
2200 	PRINTM(MCMND, "Stop TDLS CS\n");
2201 	/* Send command to firmware */
2202 	wlan_prepare_cmd(pmpriv,
2203 			 HostCmd_CMD_TDLS_CONFIG,
2204 			 HostCmd_ACT_GEN_SET, 0, MNULL, tdls_config);
2205 
2206 	if (tdls_config)
2207 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tdls_config);
2208 
2209 	LEAVE();
2210 }
2211 
2212 /**
2213  *  @brief Set/Get the TDLS off channel.
2214  *
2215  *  @param pmadapter	A pointer to mlan_adapter structure
2216  *  @param pioctl_req	A pointer to ioctl request buffer
2217  *
2218  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2219  */
2220 mlan_status
wlan_misc_ioctl_tdls_cs_channel(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2221 wlan_misc_ioctl_tdls_cs_channel(IN pmlan_adapter pmadapter,
2222 				IN pmlan_ioctl_req pioctl_req)
2223 {
2224 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2225 	mlan_status ret = MLAN_STATUS_SUCCESS;
2226 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2227 
2228 	ENTER();
2229 
2230 	if (MLAN_ACT_GET == pioctl_req->action)
2231 		misc->param.tdls_cs_channel = pmpriv->tdls_cs_channel;
2232 	else if (MLAN_ACT_SET == pioctl_req->action) {
2233 		pmpriv->tdls_cs_channel = misc->param.tdls_cs_channel;
2234 
2235 	}
2236 	LEAVE();
2237 	return ret;
2238 }
2239 
2240 /**
2241  *  @brief Set/Get the TDLS idle time.
2242  *
2243  *  @param pmadapter	A pointer to mlan_adapter structure
2244  *  @param pioctl_req	A pointer to ioctl request buffer
2245  *
2246  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2247  */
2248 mlan_status
wlan_misc_ioctl_tdls_idle_time(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2249 wlan_misc_ioctl_tdls_idle_time(IN pmlan_adapter pmadapter,
2250 			       IN pmlan_ioctl_req pioctl_req)
2251 {
2252 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2253 	mlan_status ret = MLAN_STATUS_SUCCESS;
2254 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2255 
2256 	ENTER();
2257 
2258 	if (MLAN_ACT_GET == pioctl_req->action) {
2259 		misc->param.tdls_idle_time = pmpriv->tdls_idle_time;
2260 	} else if (MLAN_ACT_SET == pioctl_req->action) {
2261 		pmpriv->tdls_idle_time = misc->param.tdls_idle_time;
2262 	}
2263 	LEAVE();
2264 	return ret;
2265 }
2266 
2267 /**
2268  *  @brief Set the TDLS operation to FW.
2269  *
2270  *  @param pmadapter	A pointer to mlan_adapter structure
2271  *  @param pioctl_req	A pointer to ioctl request buffer
2272  *
2273  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2274  */
2275 mlan_status
wlan_misc_ioctl_tdls_oper(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2276 wlan_misc_ioctl_tdls_oper(IN pmlan_adapter pmadapter,
2277 			  IN pmlan_ioctl_req pioctl_req)
2278 {
2279 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2280 	mlan_status ret = MLAN_STATUS_SUCCESS;
2281 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2282 	mlan_ds_misc_tdls_oper *ptdls_oper = &misc->param.tdls_oper;
2283 	t_u8 event_buf[100];
2284 	mlan_event *ptdls_event = (mlan_event *)event_buf;
2285 	tdls_tear_down_event *tdls_evt =
2286 		(tdls_tear_down_event *)ptdls_event->event_buf;
2287 	sta_node *sta_ptr = MNULL;
2288 	t_u8 i = 0;
2289 
2290 	ENTER();
2291 	sta_ptr = wlan_get_station_entry(pmpriv, ptdls_oper->peer_mac);
2292 	switch (ptdls_oper->tdls_action) {
2293 	case WLAN_TDLS_ENABLE_LINK:
2294 		if (sta_ptr && (sta_ptr->status != TDLS_SETUP_FAILURE)) {
2295 			PRINTM(MMSG, "TDLS: Enable link " MACSTR " success\n",
2296 			       MAC2STR(ptdls_oper->peer_mac));
2297 			sta_ptr->status = TDLS_SETUP_COMPLETE;
2298 			pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL;
2299 			if (!pmpriv->txaggrctrl)
2300 				wlan_11n_send_delba_to_peer(pmpriv,
2301 							    pmpriv->
2302 							    curr_bss_params.
2303 							    bss_descriptor.
2304 							    mac_address);
2305 			if (sta_ptr->HTcap.ieee_hdr.element_id == HT_CAPABILITY) {
2306 				sta_ptr->is_11n_enabled = MTRUE;
2307 				if (GETHT_MAXAMSDU
2308 				    (sta_ptr->HTcap.ht_cap.ht_cap_info))
2309 					sta_ptr->max_amsdu =
2310 						MLAN_TX_DATA_BUF_SIZE_8K;
2311 				else
2312 					sta_ptr->max_amsdu =
2313 						MLAN_TX_DATA_BUF_SIZE_4K;
2314 				for (i = 0; i < MAX_NUM_TID; i++) {
2315 					if (sta_ptr->is_11n_enabled)
2316 						sta_ptr->ampdu_sta[i] =
2317 							pmpriv->
2318 							aggr_prio_tbl[i].
2319 							ampdu_user;
2320 					else
2321 						sta_ptr->ampdu_sta[i] =
2322 							BA_STREAM_NOT_ALLOWED;
2323 				}
2324 				memset(pmpriv->adapter, sta_ptr->rx_seq, 0xff,
2325 				       sizeof(sta_ptr->rx_seq));
2326 			}
2327 			wlan_restore_tdls_packets(pmpriv, ptdls_oper->peer_mac,
2328 						  TDLS_SETUP_COMPLETE);
2329 			if (ISSUPP_EXTCAP_TDLS_CHAN_SWITCH
2330 			    (sta_ptr->ExtCap.ext_cap)) {
2331 				wlan_tdls_config(pmpriv, MTRUE);
2332 				wlan_tdls_cs_param_config(pmpriv);
2333 		    /**tdls cs start*/
2334 				if (pmpriv->tdls_cs_channel &&
2335 				    pmpriv->tdls_cs_channel !=
2336 				    pmpriv->curr_bss_params.bss_descriptor.
2337 				    channel)
2338 					wlan_tdls_cs_start(pmpriv,
2339 							   ptdls_oper->peer_mac,
2340 							   MNULL);
2341 			}
2342 		} else {
2343 			PRINTM(MMSG, "TDLS: Enable link " MACSTR " fail\n",
2344 			       MAC2STR(ptdls_oper->peer_mac));
2345 			/*for supplicant 2.0, we need send event to request teardown,
2346 			 **for latest supplicant, we only need return fail, and supplicant will send teardown packet and disable tdls link*/
2347 			if (sta_ptr) {
2348 				ptdls_event->bss_index = pmpriv->bss_index;
2349 				ptdls_event->event_id =
2350 					MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ;
2351 				ptdls_event->event_len =
2352 					sizeof(tdls_tear_down_event);
2353 				memcpy(pmpriv->adapter,
2354 				       (t_u8 *)tdls_evt->peer_mac_addr,
2355 				       ptdls_oper->peer_mac,
2356 				       MLAN_MAC_ADDR_LENGTH);
2357 				tdls_evt->reason_code =
2358 					MLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
2359 				wlan_recv_event(pmpriv,
2360 						MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ,
2361 						ptdls_event);
2362 				wlan_restore_tdls_packets(pmpriv,
2363 							  ptdls_oper->peer_mac,
2364 							  TDLS_TEAR_DOWN);
2365 				if (sta_ptr->is_11n_enabled) {
2366 					wlan_cleanup_reorder_tbl(pmpriv,
2367 								 ptdls_oper->
2368 								 peer_mac);
2369 					wlan_11n_cleanup_txbastream_tbl(pmpriv,
2370 									ptdls_oper->
2371 									peer_mac);
2372 				}
2373 				wlan_delete_station_entry(pmpriv,
2374 							  ptdls_oper->peer_mac);
2375 				if (MTRUE == wlan_is_station_list_empty(pmpriv))
2376 					pmadapter->tdls_status = TDLS_NOT_SETUP;
2377 				else
2378 					pmadapter->tdls_status =
2379 						TDLS_IN_BASE_CHANNEL;
2380 			}
2381 			ret = MLAN_STATUS_FAILURE;
2382 		}
2383 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
2384 				MNULL);
2385 		break;
2386 	case WLAN_TDLS_DISABLE_LINK:
2387 		/* Send command to firmware to delete tdls link */
2388 		ret = wlan_prepare_cmd(pmpriv,
2389 				       HostCmd_CMD_TDLS_OPERATION,
2390 				       HostCmd_ACT_GEN_SET,
2391 				       0, (t_void *)pioctl_req, ptdls_oper);
2392 		if (ret == MLAN_STATUS_SUCCESS)
2393 			ret = MLAN_STATUS_PENDING;
2394 		break;
2395 	case WLAN_TDLS_CREATE_LINK:
2396 		PRINTM(MIOCTL, "CREATE TDLS LINK\n");
2397 		if (sta_ptr && sta_ptr->status == TDLS_SETUP_INPROGRESS) {
2398 			PRINTM(MIOCTL, "We already create the link\n");
2399 			break;
2400 		}
2401 		if (!sta_ptr)
2402 			sta_ptr =
2403 				wlan_add_station_entry(pmpriv,
2404 						       misc->param.tdls_oper.
2405 						       peer_mac);
2406 		if (sta_ptr) {
2407 			sta_ptr->status = TDLS_SETUP_INPROGRESS;
2408 			sta_ptr->external_tdls = MTRUE;
2409 			wlan_hold_tdls_packets(pmpriv,
2410 					       misc->param.tdls_oper.peer_mac);
2411 		}
2412 		ret = wlan_prepare_cmd(pmpriv,
2413 				       HostCmd_CMD_TDLS_OPERATION,
2414 				       HostCmd_ACT_GEN_SET,
2415 				       0, (t_void *)pioctl_req, ptdls_oper);
2416 		if (ret == MLAN_STATUS_SUCCESS)
2417 			ret = MLAN_STATUS_PENDING;
2418 		break;
2419 	case WLAN_TDLS_CONFIG_LINK:
2420 		if (!sta_ptr || sta_ptr->status == TDLS_SETUP_FAILURE) {
2421 			PRINTM(MERROR, "Can not CONFIG TDLS Link\n");
2422 			ret = MLAN_STATUS_FAILURE;
2423 			break;
2424 		}
2425 		ret = wlan_prepare_cmd(pmpriv,
2426 				       HostCmd_CMD_TDLS_OPERATION,
2427 				       HostCmd_ACT_GEN_SET,
2428 				       0, (t_void *)pioctl_req, ptdls_oper);
2429 		if (ret == MLAN_STATUS_SUCCESS)
2430 			ret = MLAN_STATUS_PENDING;
2431 		break;
2432 	case WLAN_TDLS_INIT_CHAN_SWITCH:
2433 		if (sta_ptr &&
2434 		    ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(sta_ptr->ExtCap.ext_cap)) {
2435 			wlan_tdls_config(pmpriv, MTRUE);
2436 			wlan_tdls_cs_param_config(pmpriv);
2437 		/**tdls cs start*/
2438 			wlan_tdls_cs_start(pmpriv, ptdls_oper->peer_mac,
2439 					   pioctl_req);
2440 		}
2441 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
2442 				MNULL);
2443 		break;
2444 	default:
2445 		break;
2446 	}
2447 	LEAVE();
2448 	return ret;
2449 }
2450 
2451 /**
2452  *  @brief Get AP's ext capability
2453  *
2454  *  @param pmpriv	A pointer to mlan_adapter structure
2455  *  @param ext_cap  A pointer to ExtCap_t structure
2456  *
2457  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2458  */
2459 void
wlan_get_ap_ext_cap(mlan_private * pmpriv,ExtCap_t * ext_cap)2460 wlan_get_ap_ext_cap(mlan_private *pmpriv, ExtCap_t *ext_cap)
2461 {
2462 	pmlan_adapter pmadapter = pmpriv->adapter;
2463 	BSSDescriptor_t *pbss_desc;
2464 	pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
2465 	memset(pmadapter, ext_cap, 0, sizeof(ExtCap_t));
2466 	if (pbss_desc->pext_cap) {
2467 		memcpy(pmadapter, (t_u8 *)ext_cap,
2468 		       (t_u8 *)pbss_desc->pext_cap + sizeof(IEEEtypes_Header_t),
2469 		       pbss_desc->pext_cap->ieee_hdr.len);
2470 	}
2471 	return;
2472 }
2473 
2474 /**
2475  *  @brief Set the TDLS operation to FW.
2476  *
2477  *  @param pmadapter	A pointer to mlan_adapter structure
2478  *  @param pioctl_req	A pointer to ioctl request buffer
2479  *
2480  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
2481  */
2482 mlan_status
wlan_misc_ioctl_tdls_get_ies(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2483 wlan_misc_ioctl_tdls_get_ies(IN pmlan_adapter pmadapter,
2484 			     IN pmlan_ioctl_req pioctl_req)
2485 {
2486 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2487 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2488 	mlan_ds_misc_tdls_ies *tdls_ies = &misc->param.tdls_ies;
2489 	mlan_status ret = MLAN_STATUS_SUCCESS;
2490 	BSSDescriptor_t *pbss_desc;
2491 	t_u32 usr_dot_11n_dev_cap;
2492 	IEEEtypes_ExtCap_t *ext_cap = MNULL;
2493 	ExtCap_t ap_ext_cap;
2494 	IEEEtypes_HTCap_t *ht_cap = MNULL;
2495 	IEEEtypes_HTInfo_t *ht_info = MNULL;
2496 	t_u8 supp_chan[] = { 1, 11 };
2497 	t_u8 regulatory_class[] = { 1,
2498 				   /**current class*/
2499 		1, 2, 3, 4, 12, 22, 23, 24, 25, 27, 28, 29, 30, 32, 33
2500 	};								 /**list regulatory class*/
2501 	IEEEtypes_Generic_t *pSupp_chan = MNULL, *pRegulatory_class = MNULL;
2502 	sta_node *sta_ptr = MNULL;
2503 	ENTER();
2504 
2505 	/* We don't need peer information for TDLS setup */
2506 	if (!(tdls_ies->flags & TDLS_IE_FLAGS_SETUP))
2507 		sta_ptr = wlan_get_station_entry(pmpriv, tdls_ies->peer_mac);
2508 	pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
2509 	wlan_get_ap_ext_cap(pmpriv, &ap_ext_cap);
2510 	if (pbss_desc->bss_band & BAND_A)
2511 		usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_a;
2512 	else
2513 		usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_bg;
2514 
2515     /** fill the extcap */
2516 	if (tdls_ies->flags & TDLS_IE_FLAGS_EXTCAP) {
2517 		ext_cap = (IEEEtypes_ExtCap_t *)tdls_ies->ext_cap;
2518 		ext_cap->ieee_hdr.element_id = EXT_CAPABILITY;
2519 		ext_cap->ieee_hdr.len = sizeof(ExtCap_t);
2520 		SET_EXTCAP_TDLS(ext_cap->ext_cap);
2521 		RESET_EXTCAP_TDLS_UAPSD(ext_cap->ext_cap);
2522 		RESET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap->ext_cap);
2523 
2524 		if (pmpriv->host_tdls_uapsd_support) {
2525 			/* uapsd in tdls confirm frame */
2526 			if (tdls_ies->flags & TDLS_IE_FLAGS_HTINFO) {
2527 				if (sta_ptr &&
2528 				    ISSUPP_EXTCAP_TDLS_UAPSD(sta_ptr->ExtCap.
2529 							     ext_cap))
2530 					SET_EXTCAP_TDLS_UAPSD(ext_cap->ext_cap);
2531 			} else {
2532 				SET_EXTCAP_TDLS_UAPSD(ext_cap->ext_cap);
2533 			}
2534 		}
2535 		/*  channel switch support */
2536 		if (pmpriv->host_tdls_cs_support &&
2537 		    !IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ap_ext_cap)) {
2538 			/* channel switch in tdls confirm frame */
2539 			if (tdls_ies->flags & TDLS_IE_FLAGS_HTINFO) {
2540 				if (sta_ptr &&
2541 				    ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(sta_ptr->
2542 								   ExtCap.
2543 								   ext_cap))
2544 					SET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap->
2545 								    ext_cap);
2546 			} else {
2547 				SET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap->ext_cap);
2548 			}
2549 		}
2550 
2551 		DBG_HEXDUMP(MCMD_D, "TDLS extcap", tdls_ies->ext_cap,
2552 			    sizeof(IEEEtypes_ExtCap_t));
2553 	}
2554 
2555     /** default qos info is 0xf, compare with peer device qos info for tdls confirm */
2556 	if (tdls_ies->flags & TDLS_IE_FLAGS_QOS_INFO) {
2557 		if (sta_ptr && sta_ptr->rate_len)
2558 			tdls_ies->QosInfo = sta_ptr->qos_info & 0xf;
2559 		PRINTM(MCMND, "TDLS Qos info=0x%x\n", tdls_ies->QosInfo);
2560 	}
2561 
2562     /** fill the htcap based on hwspec */
2563 	if (tdls_ies->flags & TDLS_IE_FLAGS_HTCAP) {
2564 		ht_cap = (IEEEtypes_HTCap_t *)tdls_ies->ht_cap;
2565 		memset(pmadapter, ht_cap, 0, sizeof(IEEEtypes_HTCap_t));
2566 		if ((sta_ptr &&
2567 		     !ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(sta_ptr->ExtCap.ext_cap))
2568 		    || IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ap_ext_cap))
2569 			wlan_fill_ht_cap_ie(pmpriv, ht_cap,
2570 					    pbss_desc->bss_band);
2571 		else if (pmpriv->host_tdls_cs_support &&
2572 			 (pmadapter->fw_bands & BAND_A))
2573 			wlan_fill_ht_cap_ie(pmpriv, ht_cap, BAND_A);
2574 		else
2575 			wlan_fill_ht_cap_ie(pmpriv, ht_cap,
2576 					    pbss_desc->bss_band);
2577 		DBG_HEXDUMP(MCMD_D, "TDLS htcap", tdls_ies->ht_cap,
2578 			    sizeof(IEEEtypes_HTCap_t));
2579 	}
2580     /** fill the htinfo */
2581 	if (tdls_ies->flags & TDLS_IE_FLAGS_HTINFO) {
2582 		ht_info = (IEEEtypes_HTInfo_t *)tdls_ies->ht_info;
2583 		pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
2584 		ht_info->ieee_hdr.element_id = HT_OPERATION;
2585 		ht_info->ieee_hdr.len = sizeof(HTInfo_t);
2586 		ht_info->ht_info.pri_chan = pbss_desc->channel;
2587 		/* follow AP's channel bandwidth */
2588 		if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
2589 		    pbss_desc->pht_info &&
2590 		    ISALLOWED_CHANWIDTH40(pbss_desc->pht_info->ht_info.
2591 					  field2)) {
2592 			ht_info->ht_info.field2 =
2593 				pbss_desc->pht_info->ht_info.field2;
2594 		} else {
2595 			ht_info->ht_info.field2 =
2596 				wlan_get_second_channel_offset(pbss_desc->
2597 							       channel);
2598 		}
2599 		if (sta_ptr)
2600 			memcpy(pmadapter, &sta_ptr->HTInfo, tdls_ies->ht_info,
2601 			       sizeof(IEEEtypes_HTInfo_t));
2602 		DBG_HEXDUMP(MCMD_D, "TDLS htinfo", tdls_ies->ht_info,
2603 			    sizeof(IEEEtypes_HTInfo_t));
2604 	}
2605 
2606     /** supported channels andl regulatory IE*/
2607 	if (pmpriv->host_tdls_cs_support &&
2608 	    (tdls_ies->flags & TDLS_IE_FLAGS_SUPP_CS_IE)
2609 	    && !IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ap_ext_cap)) {
2610 	/** supported channels IE*/
2611 		pSupp_chan = (IEEEtypes_Generic_t *)tdls_ies->supp_chan;
2612 		pSupp_chan->ieee_hdr.element_id = SUPPORTED_CHANNELS;
2613 		if (pmpriv->chan_supp_len) {
2614 			pSupp_chan->ieee_hdr.len = pmpriv->chan_supp_len;
2615 			memcpy(pmadapter, pSupp_chan->data, pmpriv->chan_supp,
2616 			       pmpriv->chan_supp_len);
2617 		} else {
2618 			pSupp_chan->ieee_hdr.len = sizeof(supp_chan);
2619 			memcpy(pmadapter, pSupp_chan->data, supp_chan,
2620 			       sizeof(supp_chan));
2621 		}
2622 		DBG_HEXDUMP(MCMD_D, "TDLS supported channel",
2623 			    tdls_ies->supp_chan,
2624 			    pSupp_chan->ieee_hdr.len +
2625 			    sizeof(IEEEtypes_Header_t));
2626 
2627 	/**fill supported Regulatory Class IE*/
2628 		pRegulatory_class =
2629 			(IEEEtypes_Generic_t *)tdls_ies->regulatory_class;
2630 		pRegulatory_class->ieee_hdr.element_id = REGULATORY_CLASS;
2631 		if (pmpriv->supp_regulatory_class_len) {
2632 			pRegulatory_class->ieee_hdr.len =
2633 				pmpriv->supp_regulatory_class_len;
2634 			memcpy(pmadapter, pRegulatory_class->data,
2635 			       pmpriv->supp_regulatory_class,
2636 			       pmpriv->supp_regulatory_class_len);
2637 		} else {
2638 			pRegulatory_class->ieee_hdr.len =
2639 				sizeof(regulatory_class);
2640 			memcpy(pmadapter, pRegulatory_class->data,
2641 			       regulatory_class, sizeof(regulatory_class));
2642 		}
2643 		DBG_HEXDUMP(MCMD_D, "TDLS supported regulatory class",
2644 			    tdls_ies->regulatory_class,
2645 			    pRegulatory_class->ieee_hdr.len +
2646 			    sizeof(IEEEtypes_Header_t));
2647 	}
2648 	LEAVE();
2649 	return ret;
2650 }
2651 
2652 /**
2653  *  @brief Get extended version information
2654  *
2655  *  @param pmadapter    A pointer to mlan_adapter structure
2656  *  @param pioctl_req   A pointer to ioctl request buffer
2657  *
2658  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
2659  */
2660 mlan_status
wlan_get_info_ver_ext(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2661 wlan_get_info_ver_ext(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
2662 {
2663 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
2664 	mlan_ds_get_info *pinfo = (mlan_ds_get_info *)pioctl_req->pbuf;
2665 	mlan_status ret = MLAN_STATUS_SUCCESS;
2666 
2667 	ENTER();
2668 
2669 	/* Send request to firmware */
2670 	ret = wlan_prepare_cmd(pmpriv,
2671 			       HostCmd_CMD_VERSION_EXT,
2672 			       HostCmd_ACT_GEN_GET,
2673 			       0,
2674 			       (t_void *)pioctl_req,
2675 			       &pinfo->param.ver_ext.version_str_sel);
2676 
2677 	if (ret == MLAN_STATUS_SUCCESS)
2678 		ret = MLAN_STATUS_PENDING;
2679 
2680 	LEAVE();
2681 	return ret;
2682 }
2683 
2684 #ifdef DEBUG_LEVEL1
2685 /**
2686  *  @brief Set driver debug bit masks in order to enhance performance
2687  *
2688  *  @param pmadapter    A pointer to mlan_adapter structure
2689  *  @param pioctl_req   A pointer to ioctl request buffer
2690  *
2691  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
2692  */
2693 mlan_status
wlan_set_drvdbg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2694 wlan_set_drvdbg(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
2695 {
2696 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2697 	mlan_status ret = MLAN_STATUS_SUCCESS;
2698 
2699 	ENTER();
2700 
2701 	/* Set driver debug bit masks */
2702 	mlan_drvdbg = misc->param.drvdbg;
2703 
2704 	LEAVE();
2705 	return ret;
2706 }
2707 #endif
2708 
2709 /**
2710  *  @brief Rx mgmt frame forward register
2711  *
2712  *  @param pmadapter    A pointer to mlan_adapter structure
2713  *  @param pioctl_req   A pointer to ioctl request buffer
2714  *
2715  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
2716  */
2717 mlan_status
wlan_reg_rx_mgmt_ind(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2718 wlan_reg_rx_mgmt_ind(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
2719 {
2720 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
2721 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2722 	mlan_status ret = MLAN_STATUS_SUCCESS;
2723 
2724 	ENTER();
2725 
2726 	/* Set passthru mask for mgmt frame */
2727 	pmpriv->mgmt_frame_passthru_mask = misc->param.mgmt_subtype_mask;
2728 
2729 	/* Send request to firmware */
2730 	ret = wlan_prepare_cmd(pmpriv,
2731 			       HostCmd_CMD_RX_MGMT_IND,
2732 			       pioctl_req->action,
2733 			       0,
2734 			       (t_void *)pioctl_req,
2735 			       &misc->param.mgmt_subtype_mask);
2736 
2737 	if (ret == MLAN_STATUS_SUCCESS)
2738 		ret = MLAN_STATUS_PENDING;
2739 
2740 	LEAVE();
2741 	return ret;
2742 }
2743 
2744 /**
2745  *   @brief This function processes the 802.11 mgmt Frame
2746  *
2747  *   @param priv            A pointer to mlan_private
2748  *
2749  *   @param payload         A pointer to the received buffer
2750  *   @param payload_len     Length of the received buffer
2751  *   @param prx_pd          A pointer to RxPD
2752  *
2753  *   @return                MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2754  */
2755 mlan_status
wlan_process_802dot11_mgmt_pkt(IN mlan_private * priv,IN t_u8 * payload,IN t_u32 payload_len,IN RxPD * prx_pd)2756 wlan_process_802dot11_mgmt_pkt(IN mlan_private *priv,
2757 			       IN t_u8 *payload,
2758 			       IN t_u32 payload_len, IN RxPD *prx_pd)
2759 {
2760 	pmlan_adapter pmadapter = priv->adapter;
2761 	pmlan_callbacks pcb = &pmadapter->callbacks;
2762 	mlan_status ret = MLAN_STATUS_SUCCESS;
2763 	wlan_802_11_header *pieee_pkt_hdr = MNULL;
2764 	t_u16 sub_type = 0;
2765 	t_u8 *event_buf = MNULL;
2766 	mlan_event *pevent = MNULL;
2767 	t_u8 unicast = 0;
2768 	IEEE80211_MGMT *mgmt = MNULL;
2769 	t_u8 category = 0;
2770 	t_u8 action_code = 0;
2771 	struct timestamps tstamps;
2772 	ENTER();
2773 	if (payload_len > (MAX_EVENT_SIZE - sizeof(mlan_event))) {
2774 		PRINTM(MERROR, "Dropping large mgmt frame,len =%d\n",
2775 		       payload_len);
2776 		LEAVE();
2777 		return ret;
2778 	}
2779 	/* Check  packet type-subtype and compare with mgmt_passthru_mask
2780 	 * If event is needed to host, just eventify it */
2781 	pieee_pkt_hdr = (wlan_802_11_header *)payload;
2782 	sub_type = IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE(pieee_pkt_hdr->frm_ctl);
2783 	if (((1 << sub_type) & priv->mgmt_frame_passthru_mask) == 0) {
2784 		PRINTM(MINFO, "Dropping mgmt frame for subtype %d snr=%d.\n",
2785 		       sub_type, prx_pd->snr);
2786 		LEAVE();
2787 		return ret;
2788 	}
2789 	switch (sub_type) {
2790 	case SUBTYPE_ASSOC_REQUEST:
2791 	case SUBTYPE_REASSOC_REQUEST:
2792 	case SUBTYPE_DISASSOC:
2793 	case SUBTYPE_DEAUTH:
2794 	case SUBTYPE_AUTH:
2795 	case SUBTYPE_PROBE_RESP:
2796 		unicast = MTRUE;
2797 		break;
2798 	case SUBTYPE_ACTION:
2799 		category = *(payload + sizeof(wlan_802_11_header));
2800 		action_code = *(payload + sizeof(wlan_802_11_header) + 1);
2801 		if (category == IEEE_MGMT_ACTION_CATEGORY_BLOCK_ACK) {
2802 			PRINTM(MINFO,
2803 			       "Drop BLOCK ACK action frame: action_code=%d\n",
2804 			       action_code);
2805 			LEAVE();
2806 			return ret;
2807 		}
2808 		if ((category == IEEE_MGMT_ACTION_CATEGORY_PUBLIC) &&
2809 		    (action_code == BSS_20_40_COEX)) {
2810 			PRINTM(MINFO,
2811 			       "Drop 20/40 BSS Coexistence Management frame\n");
2812 			LEAVE();
2813 			return ret;
2814 		}
2815 		if ((category == CATEGORY_PUBLIC) &&
2816 		    (action_code == TDLS_DISCOVERY_RESPONSE)) {
2817 			pcb->moal_updata_peer_signal(pmadapter->pmoal_handle,
2818 						     priv->bss_index,
2819 						     pieee_pkt_hdr->addr2,
2820 						     prx_pd->snr, prx_pd->nf);
2821 			PRINTM(MINFO,
2822 			       "Rx: TDLS discovery response, nf=%d, snr=%d\n",
2823 			       prx_pd->nf, prx_pd->snr);
2824 		}
2825 		if ((category == IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM) &&
2826 		    (action_code == 0x1)) {
2827 			prx_pd->toa_tod_tstamps =
2828 				wlan_le64_to_cpu(prx_pd->toa_tod_tstamps);
2829 			tstamps.t3 = prx_pd->toa_tod_tstamps >> 32;
2830 			tstamps.t2 = (t_u32)prx_pd->toa_tod_tstamps;
2831 			tstamps.t2_err = 0;
2832 			tstamps.t3_err = 0;
2833 			tstamps.ingress_time = pmadapter->host_bbu_clk_delta;
2834 			pcb->moal_do_div(tstamps.ingress_time, 10);
2835 			tstamps.ingress_time += tstamps.t2;	//t2, t3 is 10ns and delta is in 1 ns unit;
2836 			PRINTM(MINFO, "T2: %d, T3: %d, ingress: %lu\n",
2837 			       tstamps.t2, tstamps.t3, tstamps.ingress_time);
2838 		}
2839 		unicast = MTRUE;
2840 		break;
2841 	default:
2842 		break;
2843 	}
2844 	if (unicast == MTRUE) {
2845 		if (memcmp
2846 		    (pmadapter, pieee_pkt_hdr->addr1, priv->curr_addr,
2847 		     MLAN_MAC_ADDR_LENGTH)) {
2848 			PRINTM(MINFO,
2849 			       "Dropping mgmt frame for others: type=%d " MACSTR
2850 			       "\n", sub_type, MAC2STR(pieee_pkt_hdr->addr1));
2851 			LEAVE();
2852 			return ret;
2853 		}
2854 	}
2855 	/* Allocate memory for event buffer */
2856 	ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
2857 			       MLAN_MEM_DEF, &event_buf);
2858 	if ((ret != MLAN_STATUS_SUCCESS) || !event_buf) {
2859 		PRINTM(MERROR, "Could not allocate buffer for event buf\n");
2860 		LEAVE();
2861 		return MLAN_STATUS_FAILURE;
2862 	}
2863 	pevent = (pmlan_event)event_buf;
2864 	pevent->bss_index = priv->bss_index;
2865 	mgmt = (IEEE80211_MGMT *)payload;
2866 	if (sub_type == SUBTYPE_ACTION &&
2867 	    mgmt->u.ft_resp.category == FT_CATEGORY &&
2868 	    mgmt->u.ft_resp.action == FT_ACTION_RESPONSE &&
2869 	    mgmt->u.ft_resp.status_code == 0) {
2870 		PRINTM(MCMND, "FT Action response received\n");
2871 #define FT_ACTION_HEAD_LEN (24 + 6 +16)
2872 		pevent->event_id = MLAN_EVENT_ID_DRV_FT_RESPONSE;
2873 		pevent->event_len =
2874 			payload_len + MLAN_MAC_ADDR_LENGTH - FT_ACTION_HEAD_LEN;
2875 		memcpy(pmadapter, (t_u8 *)pevent->event_buf,
2876 		       &mgmt->u.ft_resp.target_ap_addr, MLAN_MAC_ADDR_LENGTH);
2877 		memcpy(pmadapter,
2878 		       (t_u8 *)(pevent->event_buf + MLAN_MAC_ADDR_LENGTH),
2879 		       payload + FT_ACTION_HEAD_LEN,
2880 		       payload_len - FT_ACTION_HEAD_LEN);
2881 	} else if (sub_type == SUBTYPE_AUTH &&
2882 		   mgmt->u.auth.auth_alg == MLAN_AUTH_MODE_FT &&
2883 		   mgmt->u.auth.auth_transaction == 2 &&
2884 		   mgmt->u.auth.status_code == 0) {
2885 		PRINTM(MCMND, "FT auth response received \n");
2886 #define AUTH_PACKET_LEN (24 + 6 +6)
2887 		pevent->event_id = MLAN_EVENT_ID_DRV_FT_RESPONSE;
2888 		pevent->event_len =
2889 			payload_len + MLAN_MAC_ADDR_LENGTH - AUTH_PACKET_LEN;
2890 		memcpy(pmadapter, (t_u8 *)pevent->event_buf, mgmt->sa,
2891 		       MLAN_MAC_ADDR_LENGTH);
2892 		memcpy(pmadapter,
2893 		       (t_u8 *)(pevent->event_buf + MLAN_MAC_ADDR_LENGTH),
2894 		       payload + AUTH_PACKET_LEN,
2895 		       payload_len - AUTH_PACKET_LEN);
2896 	} else {
2897 		pevent->event_id = MLAN_EVENT_ID_DRV_MGMT_FRAME;
2898 		pevent->event_len = payload_len + sizeof(pevent->event_id);
2899 		memcpy(pmadapter, (t_u8 *)pevent->event_buf,
2900 		       (t_u8 *)&pevent->event_id, sizeof(pevent->event_id));
2901 		memcpy(pmadapter,
2902 		       (t_u8 *)(pevent->event_buf + sizeof(pevent->event_id)),
2903 		       payload, payload_len);
2904 		//Append timestamp info at the end of event
2905 		if ((category == IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM) &&
2906 		    (action_code == 0x1)) {
2907 			memcpy(pmadapter,
2908 			       (t_u8 *)(pevent->event_buf +
2909 					sizeof(pevent->event_id) + payload_len),
2910 			       &tstamps, sizeof(struct timestamps));
2911 			pevent->event_len =
2912 				payload_len + sizeof(pevent->event_id) +
2913 				sizeof(struct timestamps);
2914 		}
2915 
2916 	}
2917 	wlan_recv_event(priv, pevent->event_id, pevent);
2918 	if (event_buf)
2919 		pcb->moal_mfree(pmadapter->pmoal_handle, event_buf);
2920 	LEAVE();
2921 	return MLAN_STATUS_SUCCESS;
2922 }
2923 
2924 #ifdef STA_SUPPORT
2925 /**
2926  *  @brief Extended capabilities configuration
2927  *
2928  *  @param pmadapter    A pointer to mlan_adapter structure
2929  *  @param pioctl_req   A pointer to ioctl request buffer
2930  *
2931  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
2932  */
2933 mlan_status
wlan_misc_ext_capa_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2934 wlan_misc_ext_capa_cfg(IN pmlan_adapter pmadapter,
2935 		       IN pmlan_ioctl_req pioctl_req)
2936 {
2937 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
2938 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2939 	mlan_status ret = MLAN_STATUS_SUCCESS;
2940 
2941 	ENTER();
2942 
2943 	if (MLAN_ACT_GET == pioctl_req->action)
2944 		memcpy(pmpriv->adapter, &misc->param.ext_cap, &pmpriv->ext_cap,
2945 		       sizeof(misc->param.ext_cap));
2946 	else if (MLAN_ACT_SET == pioctl_req->action) {
2947 		memcpy(pmpriv->adapter, &pmpriv->ext_cap, &misc->param.ext_cap,
2948 		       sizeof(misc->param.ext_cap));
2949 		/* Save default Extended Capability */
2950 		memcpy(pmpriv->adapter, &pmpriv->def_ext_cap, &pmpriv->ext_cap,
2951 		       sizeof(pmpriv->ext_cap));
2952 	}
2953 
2954 	LEAVE();
2955 	return ret;
2956 }
2957 
2958 /**
2959  *  @brief Check whether Extended Capabilities IE support
2960  *
2961  *  @param pmpriv             A pointer to mlan_private structure
2962  *
2963  *  @return                   MTRUE or MFALSE;
2964  */
2965 t_u32
wlan_is_ext_capa_support(mlan_private * pmpriv)2966 wlan_is_ext_capa_support(mlan_private *pmpriv)
2967 {
2968 	ENTER();
2969 
2970 	if (ISSUPP_EXTCAP_TDLS(pmpriv->ext_cap)
2971 	    || ISSUPP_EXTCAP_INTERWORKING(pmpriv->ext_cap)
2972 	    || ISSUPP_EXTCAP_BSS_TRANSITION(pmpriv->ext_cap)
2973 	    || ISSUPP_EXTCAP_QOS_MAP(pmpriv->ext_cap)
2974 		) {
2975 		LEAVE();
2976 		return MTRUE;
2977 	} else {
2978 		LEAVE();
2979 		return MFALSE;
2980 	}
2981 }
2982 #endif
2983 
2984 #ifdef STA_SUPPORT
2985 /**
2986  *  @brief Add Extended Capabilities IE
2987  *
2988  *  @param pmpriv             A pointer to mlan_private structure
2989  *  @param pptlv_out          A pointer to TLV to fill in
2990  *
2991  *  @return                   N/A
2992  */
2993 void
wlan_add_ext_capa_info_ie(IN mlan_private * pmpriv,OUT t_u8 ** pptlv_out)2994 wlan_add_ext_capa_info_ie(IN mlan_private *pmpriv, OUT t_u8 **pptlv_out)
2995 {
2996 	MrvlIETypes_ExtCap_t *pext_cap = MNULL;
2997 
2998 	ENTER();
2999 
3000 	pext_cap = (MrvlIETypes_ExtCap_t *)*pptlv_out;
3001 	memset(pmpriv->adapter, pext_cap, 0, sizeof(MrvlIETypes_ExtCap_t));
3002 	pext_cap->header.type = wlan_cpu_to_le16(EXT_CAPABILITY);
3003 	pext_cap->header.len = wlan_cpu_to_le16(sizeof(ExtCap_t));
3004 	if (pmpriv->adapter->ecsa_enable)
3005 		SET_EXTCAP_EXT_CHANNEL_SWITCH(pmpriv->ext_cap);
3006 	else
3007 		RESET_EXTCAP_EXT_CHANNEL_SWITCH(pmpriv->ext_cap);
3008 	SET_EXTCAP_FTMI(pmpriv->ext_cap);
3009 	SET_EXTCAP_INTERNETWORKING(pmpriv->ext_cap);
3010 	memcpy(pmpriv->adapter, &pext_cap->ext_cap, &pmpriv->ext_cap,
3011 	       sizeof(pmpriv->ext_cap));
3012 	*pptlv_out += sizeof(MrvlIETypes_ExtCap_t);
3013 
3014 	LEAVE();
3015 }
3016 #endif
3017 
3018 /**
3019  *  @brief Get OTP user data
3020  *
3021  *  @param pmadapter    A pointer to mlan_adapter structure
3022  *  @param pioctl_req   A pointer to ioctl request buffer
3023  *
3024  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
3025  */
3026 mlan_status
wlan_misc_otp_user_data(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3027 wlan_misc_otp_user_data(IN pmlan_adapter pmadapter,
3028 			IN pmlan_ioctl_req pioctl_req)
3029 {
3030 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3031 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
3032 	mlan_status ret = MLAN_STATUS_FAILURE;
3033 
3034 	ENTER();
3035 
3036 	if (misc->param.otp_user_data.user_data_length > MAX_OTP_USER_DATA_LEN) {
3037 		PRINTM(MERROR, "Invalid OTP user data length\n");
3038 		pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3039 		LEAVE();
3040 		return ret;
3041 	}
3042 
3043 	ret = wlan_prepare_cmd(pmpriv,
3044 			       HostCmd_CMD_OTP_READ_USER_DATA,
3045 			       HostCmd_ACT_GEN_GET,
3046 			       0,
3047 			       (t_void *)pioctl_req,
3048 			       &misc->param.otp_user_data);
3049 
3050 	if (ret == MLAN_STATUS_SUCCESS)
3051 		ret = MLAN_STATUS_PENDING;
3052 
3053 	LEAVE();
3054 	return ret;
3055 }
3056 
3057 /**
3058  *  @brief This function will search for the specific ie
3059  *
3060  *  @param priv    A pointer to mlan_private
3061  *  @param pevent  A pointer to event buf
3062  *  @param sta_ptr A pointer to sta_node
3063  *
3064  *  @return	       N/A
3065  */
3066 void
wlan_check_sta_capability(pmlan_private priv,pmlan_buffer pevent,sta_node * sta_ptr)3067 wlan_check_sta_capability(pmlan_private priv, pmlan_buffer pevent,
3068 			  sta_node *sta_ptr)
3069 {
3070 	t_u16 tlv_type, tlv_len;
3071 	t_u16 frame_control, frame_sub_type = 0;
3072 	t_u8 *assoc_req_ie = MNULL;
3073 	t_u8 ie_len = 0, assoc_ie_len = 0;
3074 	IEEEtypes_HTCap_t *pht_cap = MNULL;
3075 #ifdef UAP_SUPPORT
3076 	t_u8 *ext_rate = MNULL, *erp = MNULL;
3077 #endif
3078 
3079 	int tlv_buf_left = pevent->data_len - ASSOC_EVENT_FIX_SIZE;
3080 	MrvlIEtypesHeader_t *tlv = (MrvlIEtypesHeader_t *)
3081 		(pevent->pbuf + pevent->data_offset + ASSOC_EVENT_FIX_SIZE);
3082 	MrvlIETypes_MgmtFrameSet_t *mgmt_tlv = MNULL;
3083 
3084 	ENTER();
3085 	while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
3086 		tlv_type = wlan_le16_to_cpu(tlv->type);
3087 		tlv_len = wlan_le16_to_cpu(tlv->len);
3088 		if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
3089 		    (unsigned int)tlv_buf_left) {
3090 			PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
3091 			       tlv_len, tlv_buf_left);
3092 			break;
3093 		}
3094 		if (tlv_type == TLV_TYPE_MGMT_FRAME) {
3095 			mgmt_tlv = (MrvlIETypes_MgmtFrameSet_t *)tlv;
3096 			memcpy(priv->adapter, &frame_control,
3097 			       (t_u8 *)&(mgmt_tlv->frame_control),
3098 			       sizeof(frame_control));
3099 			frame_sub_type =
3100 				IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE
3101 				(frame_control);
3102 			if ((mgmt_tlv->frame_control.type == 0) &&
3103 			    ((frame_sub_type == SUBTYPE_BEACON)
3104 #ifdef UAP_SUPPORT
3105 			     || (frame_sub_type == SUBTYPE_ASSOC_REQUEST)
3106 			     || (frame_sub_type == SUBTYPE_REASSOC_REQUEST)
3107 #endif
3108 			    )) {
3109 				if (frame_sub_type == SUBTYPE_BEACON)
3110 					assoc_ie_len =
3111 						sizeof(IEEEtypes_Beacon_t);
3112 #ifdef UAP_SUPPORT
3113 				else if (frame_sub_type ==
3114 					 SUBTYPE_ASSOC_REQUEST)
3115 					assoc_ie_len =
3116 						sizeof(IEEEtypes_AssocRqst_t);
3117 				else if (frame_sub_type ==
3118 					 SUBTYPE_REASSOC_REQUEST)
3119 					assoc_ie_len =
3120 						sizeof(IEEEtypes_ReAssocRqst_t);
3121 #endif
3122 				ie_len = tlv_len -
3123 					sizeof(IEEEtypes_FrameCtl_t) -
3124 					assoc_ie_len;
3125 				assoc_req_ie =
3126 					(t_u8 *)tlv +
3127 					sizeof(MrvlIETypes_MgmtFrameSet_t) +
3128 					assoc_ie_len;
3129 				sta_ptr->is_wmm_enabled =
3130 					wlan_is_wmm_ie_present(priv->adapter,
3131 							       assoc_req_ie,
3132 							       ie_len);
3133 				PRINTM(MCMND, "STA: is_wmm_enabled=%d\n",
3134 				       sta_ptr->is_wmm_enabled);
3135 				pht_cap =
3136 					(IEEEtypes_HTCap_t *)
3137 					wlan_get_specific_ie(priv, assoc_req_ie,
3138 							     ie_len,
3139 							     HT_CAPABILITY);
3140 				if (pht_cap) {
3141 					PRINTM(MCMND, "STA supports 11n\n");
3142 					sta_ptr->is_11n_enabled = MTRUE;
3143 					memcpy(priv->adapter,
3144 					       (t_u8 *)&sta_ptr->HTcap, pht_cap,
3145 					       sizeof(IEEEtypes_HTCap_t));
3146 					if (GETHT_MAXAMSDU
3147 					    (wlan_le16_to_cpu
3148 					     (pht_cap->ht_cap.ht_cap_info)))
3149 						sta_ptr->max_amsdu =
3150 							MLAN_TX_DATA_BUF_SIZE_8K;
3151 					else
3152 						sta_ptr->max_amsdu =
3153 							MLAN_TX_DATA_BUF_SIZE_4K;
3154 				} else {
3155 					PRINTM(MCMND,
3156 					       "STA doesn't support 11n\n");
3157 				}
3158 #ifdef UAP_SUPPORT
3159 				/* Note: iphone6 does not have ERP_INFO */
3160 				ext_rate =
3161 					wlan_get_specific_ie(priv, assoc_req_ie,
3162 							     ie_len,
3163 							     EXTENDED_SUPPORTED_RATES);
3164 				erp = wlan_get_specific_ie(priv, assoc_req_ie,
3165 							   ie_len, ERP_INFO);
3166 				if (!ext_rate)
3167 					PRINTM(MCMND,
3168 					       "STA doesn't support EXTENDED_SUPPORTED_RATES\n");
3169 				if (!erp)
3170 					PRINTM(MCMND,
3171 					       "STA doesn't support ERP_INFO\n");
3172 				if (sta_ptr->is_11n_enabled) {
3173 					if (priv->uap_channel <= 14)
3174 						sta_ptr->bandmode = BAND_GN;
3175 					else
3176 						sta_ptr->bandmode = BAND_AN;
3177 				} else if (ext_rate || erp) {
3178 					if (priv->uap_channel <= 14)
3179 						sta_ptr->bandmode = BAND_G;
3180 					else
3181 						sta_ptr->bandmode = BAND_A;
3182 				} else
3183 					sta_ptr->bandmode = BAND_B;
3184 #endif
3185 #ifdef DRV_EMBEDDED_AUTHENTICATOR
3186 				if (IsAuthenticatorEnabled(priv->psapriv))
3187 					authenticator_get_sta_security_info
3188 						(priv->psapriv,
3189 						 sta_ptr->cm_connectioninfo,
3190 						 assoc_req_ie, ie_len);
3191 #endif
3192 				break;
3193 			}
3194 		}
3195 		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
3196 		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
3197 					      sizeof(MrvlIEtypesHeader_t));
3198 	}
3199 	LEAVE();
3200 
3201 	return;
3202 }
3203 
3204 /**
3205  *  @brief check if WMM ie present.
3206  *
3207  *  @param pmadapter A pointer to mlan_adapter structure
3208  *  @param pbuf     A pointer to IE buffer
3209  *  @param buf_len  IE buffer len
3210  *
3211  *  @return         MTRUE/MFALSE
3212  */
3213 t_u8
wlan_is_wmm_ie_present(pmlan_adapter pmadapter,t_u8 * pbuf,t_u16 buf_len)3214 wlan_is_wmm_ie_present(pmlan_adapter pmadapter, t_u8 *pbuf, t_u16 buf_len)
3215 {
3216 	t_u16 bytes_left = buf_len;
3217 	IEEEtypes_ElementId_e element_id;
3218 	t_u8 *pcurrent_ptr = pbuf;
3219 	t_u8 element_len;
3220 	t_u16 total_ie_len;
3221 	IEEEtypes_VendorSpecific_t *pvendor_ie;
3222 	const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
3223 	t_u8 find_wmm_ie = MFALSE;
3224 
3225 	ENTER();
3226 
3227 	/* Process variable IE */
3228 	while (bytes_left >= 2) {
3229 		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
3230 		element_len = *((t_u8 *)pcurrent_ptr + 1);
3231 		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
3232 
3233 		if (bytes_left < total_ie_len) {
3234 			PRINTM(MERROR, "InterpretIE: Error in processing IE, "
3235 			       "bytes left < IE length\n");
3236 			bytes_left = 0;
3237 			continue;
3238 		}
3239 		switch (element_id) {
3240 		case VENDOR_SPECIFIC_221:
3241 			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
3242 			if (!memcmp
3243 			    (pmadapter, pvendor_ie->vend_hdr.oui, wmm_oui,
3244 			     sizeof(wmm_oui))) {
3245 				find_wmm_ie = MTRUE;
3246 				PRINTM(MINFO, "find WMM IE\n");
3247 			}
3248 			break;
3249 		default:
3250 			break;
3251 		}
3252 		pcurrent_ptr += element_len + 2;
3253 		/* Need to account for IE ID and IE Len */
3254 		bytes_left -= (element_len + 2);
3255 		if (find_wmm_ie)
3256 			break;
3257 	}
3258 
3259 	LEAVE();
3260 	return find_wmm_ie;
3261 }
3262 
3263 /**
3264  *  @brief This function will search for the specific ie
3265  *
3266  *
3267  *  @param priv    A pointer to mlan_private
3268  *  @param ie_buf  A pointer to ie_buf
3269  *  @param ie_len  total ie length
3270  *  @param id      ie's id
3271  *
3272  *  @return	       ie's poiner or MNULL
3273  */
3274 t_u8 *
wlan_get_specific_ie(pmlan_private priv,t_u8 * ie_buf,t_u8 ie_len,IEEEtypes_ElementId_e id)3275 wlan_get_specific_ie(pmlan_private priv, t_u8 *ie_buf, t_u8 ie_len,
3276 		     IEEEtypes_ElementId_e id)
3277 {
3278 	t_u32 bytes_left = ie_len;
3279 	t_u8 *pcurrent_ptr = ie_buf;
3280 	t_u16 total_ie_len;
3281 	t_u8 *ie_ptr = MNULL;
3282 	IEEEtypes_ElementId_e element_id;
3283 	t_u8 element_len;
3284 
3285 	ENTER();
3286 
3287 	DBG_HEXDUMP(MCMD_D, "ie", ie_buf, ie_len);
3288 	while (bytes_left >= 2) {
3289 		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
3290 		element_len = *((t_u8 *)pcurrent_ptr + 1);
3291 		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
3292 		if (bytes_left < total_ie_len) {
3293 			PRINTM(MERROR, "InterpretIE: Error in processing IE, "
3294 			       "bytes left < IE length\n");
3295 			break;
3296 		}
3297 		if (element_id == id) {
3298 			PRINTM(MCMND, "Find IE: id=%d\n", id);
3299 			DBG_HEXDUMP(MCMND, "IE", pcurrent_ptr, total_ie_len);
3300 			ie_ptr = pcurrent_ptr;
3301 			break;
3302 		}
3303 		pcurrent_ptr += element_len + 2;
3304 		/* Need to account for IE ID and IE Len */
3305 		bytes_left -= (element_len + 2);
3306 	}
3307 
3308 	LEAVE();
3309 
3310 	return ie_ptr;
3311 }
3312 
3313 /**
3314  *  @brief Get pm info
3315  *
3316  *  @param pmadapter	A pointer to mlan_adapter structure
3317  *  @param pioctl_req	A pointer to ioctl request buffer
3318  *
3319  *  @return		        MLAN_STATUS_SUCCESS --success
3320  */
3321 mlan_status
wlan_get_pm_info(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3322 wlan_get_pm_info(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
3323 {
3324 	mlan_status ret = MLAN_STATUS_SUCCESS;
3325 	mlan_ds_pm_cfg *pm_cfg = MNULL;
3326 
3327 	ENTER();
3328 
3329 	pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
3330 	pm_cfg->param.ps_info.is_suspend_allowed = MTRUE;
3331 	wlan_request_cmd_lock(pmadapter);
3332 	if (util_peek_list(pmadapter->pmoal_handle, &pmadapter->cmd_pending_q,
3333 			   MNULL, MNULL) || pmadapter->curr_cmd
3334 	    || !wlan_bypass_tx_list_empty(pmadapter)
3335 	    || !wlan_wmm_lists_empty(pmadapter)
3336 	    || pmadapter->sdio_ireg) {
3337 		pm_cfg->param.ps_info.is_suspend_allowed = MFALSE;
3338 		PRINTM(MIOCTL,
3339 		       "PM: cmd_pending_q=%p,curr_cmd=%p,wmm_list_empty=%d, by_pass=%d sdio_ireg=0x%x\n",
3340 		       util_peek_list(pmadapter->pmoal_handle,
3341 				      &pmadapter->cmd_pending_q, MNULL, MNULL),
3342 		       pmadapter->curr_cmd, wlan_wmm_lists_empty(pmadapter),
3343 		       wlan_bypass_tx_list_empty(pmadapter),
3344 		       pmadapter->sdio_ireg);
3345 	}
3346 	wlan_release_cmd_lock(pmadapter);
3347 	LEAVE();
3348 	return ret;
3349 }
3350 
3351 /**
3352  *  @brief Get hs wakeup reason
3353  *
3354  *  @param pmadapter	A pointer to mlan_adapter structure
3355  *  @param pioctl_req	A pointer to ioctl request buffer
3356  *
3357  *  @return		        MLAN_STATUS_SUCCESS --success
3358  */
3359 mlan_status
wlan_get_hs_wakeup_reason(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3360 wlan_get_hs_wakeup_reason(IN pmlan_adapter pmadapter,
3361 			  IN pmlan_ioctl_req pioctl_req)
3362 {
3363 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3364 	pmlan_ds_pm_cfg pm_cfg = MNULL;
3365 	mlan_status ret = MLAN_STATUS_FAILURE;
3366 
3367 	ENTER();
3368 
3369 	pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
3370 
3371 	/* Send command to firmware */
3372 	ret = wlan_prepare_cmd(pmpriv,
3373 			       HostCmd_CMD_HS_WAKEUP_REASON,
3374 			       HostCmd_ACT_GEN_GET,
3375 			       0,
3376 			       (t_void *)pioctl_req,
3377 			       &pm_cfg->param.wakeup_reason);
3378 
3379 	if (ret == MLAN_STATUS_SUCCESS)
3380 		ret = MLAN_STATUS_PENDING;
3381 
3382 	LEAVE();
3383 	return ret;
3384 
3385 }
3386 
3387 /**
3388  *  @brief Set/Get radio status
3389  *
3390  *  @param pmadapter	A pointer to mlan_adapter structure
3391  *  @param pioctl_req	A pointer to ioctl request buffer
3392  *
3393  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
3394  */
3395 mlan_status
wlan_radio_ioctl_radio_ctl(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3396 wlan_radio_ioctl_radio_ctl(IN pmlan_adapter pmadapter,
3397 			   IN pmlan_ioctl_req pioctl_req)
3398 {
3399 	mlan_status ret = MLAN_STATUS_SUCCESS;
3400 	mlan_ds_radio_cfg *radio_cfg = MNULL;
3401 	t_u16 cmd_action = 0;
3402 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3403 
3404 	ENTER();
3405 
3406 	radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
3407 	if (pioctl_req->action == MLAN_ACT_SET) {
3408 		if (pmadapter->radio_on == radio_cfg->param.radio_on_off) {
3409 			ret = MLAN_STATUS_SUCCESS;
3410 			goto exit;
3411 		} else {
3412 			if (pmpriv->media_connected == MTRUE) {
3413 				ret = MLAN_STATUS_FAILURE;
3414 				goto exit;
3415 			}
3416 			cmd_action = HostCmd_ACT_GEN_SET;
3417 		}
3418 	} else
3419 		cmd_action = HostCmd_ACT_GEN_GET;
3420 
3421 	/* Send request to firmware */
3422 	ret = wlan_prepare_cmd(pmpriv,
3423 			       HostCmd_CMD_802_11_RADIO_CONTROL,
3424 			       cmd_action,
3425 			       0,
3426 			       (t_void *)pioctl_req,
3427 			       &radio_cfg->param.radio_on_off);
3428 
3429 	if (ret == MLAN_STATUS_SUCCESS)
3430 		ret = MLAN_STATUS_PENDING;
3431 
3432 exit:
3433 	LEAVE();
3434 	return ret;
3435 }
3436 
3437 /**
3438  *  @brief Set/Get antenna configuration
3439  *
3440  *  @param pmadapter    A pointer to mlan_adapter structure
3441  *  @param pioctl_req   A pointer to ioctl request buffer
3442  *
3443  *  @return     MLAN_STATUS_PENDING --success, otherwise fail
3444  */
3445 mlan_status
wlan_radio_ioctl_ant_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3446 wlan_radio_ioctl_ant_cfg(IN pmlan_adapter pmadapter,
3447 			 IN pmlan_ioctl_req pioctl_req)
3448 {
3449 	mlan_status ret = MLAN_STATUS_SUCCESS;
3450 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3451 	mlan_ds_radio_cfg *radio_cfg = MNULL;
3452 	t_u16 cmd_action = 0;
3453 	mlan_ds_ant_cfg_1x1 *ant_cfg;
3454 
3455 	ENTER();
3456 
3457 	radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
3458 
3459 	if (pioctl_req->action == MLAN_ACT_SET) {
3460 		/* User input validation */
3461 		if (!radio_cfg->param.ant_cfg_1x1.antenna ||
3462 		    ((radio_cfg->param.ant_cfg_1x1.antenna != RF_ANTENNA_AUTO)
3463 		     && (radio_cfg->param.ant_cfg_1x1.antenna & 0xFFFC))) {
3464 			PRINTM(MERROR, "Invalid antenna setting\n");
3465 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3466 			ret = MLAN_STATUS_FAILURE;
3467 			goto exit;
3468 		}
3469 		cmd_action = HostCmd_ACT_GEN_SET;
3470 	} else
3471 		cmd_action = HostCmd_ACT_GEN_GET;
3472 
3473 	/* Cast it to t_u16, antenna mode for command HostCmd_CMD_802_11_RF_ANTENNA requires 2 bytes */
3474 	ant_cfg = &radio_cfg->param.ant_cfg_1x1;
3475 
3476 	/* Send request to firmware */
3477 	ret = wlan_prepare_cmd(pmpriv,
3478 			       HostCmd_CMD_802_11_RF_ANTENNA,
3479 			       cmd_action,
3480 			       0, (t_void *)pioctl_req, (t_void *)ant_cfg);
3481 
3482 	if (ret == MLAN_STATUS_SUCCESS)
3483 		ret = MLAN_STATUS_PENDING;
3484 
3485 exit:
3486 	LEAVE();
3487 	return ret;
3488 }
3489 
3490 /**
3491  *  @brief Get rate bitmap
3492  *
3493  *  @param pmadapter	A pointer to mlan_adapter structure
3494  *  @param pioctl_req	A pointer to ioctl request buffer
3495  *
3496  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
3497  */
3498 static mlan_status
wlan_rate_ioctl_get_rate_bitmap(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3499 wlan_rate_ioctl_get_rate_bitmap(IN pmlan_adapter pmadapter,
3500 				IN pmlan_ioctl_req pioctl_req)
3501 {
3502 	mlan_status ret = MLAN_STATUS_SUCCESS;
3503 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3504 
3505 	ENTER();
3506 
3507 	/* Send request to firmware */
3508 	ret = wlan_prepare_cmd(pmpriv,
3509 			       HostCmd_CMD_TX_RATE_CFG,
3510 			       HostCmd_ACT_GEN_GET,
3511 			       0, (t_void *)pioctl_req, MNULL);
3512 	if (ret == MLAN_STATUS_SUCCESS)
3513 		ret = MLAN_STATUS_PENDING;
3514 
3515 	LEAVE();
3516 	return ret;
3517 }
3518 
3519 /**
3520  *  @brief Set rate bitmap
3521  *
3522  *  @param pmadapter	A pointer to mlan_adapter structure
3523  *  @param pioctl_req	A pointer to ioctl request buffer
3524  *
3525  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
3526  */
3527 static mlan_status
wlan_rate_ioctl_set_rate_bitmap(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3528 wlan_rate_ioctl_set_rate_bitmap(IN pmlan_adapter pmadapter,
3529 				IN pmlan_ioctl_req pioctl_req)
3530 {
3531 	mlan_ds_rate *ds_rate = MNULL;
3532 	mlan_status ret = MLAN_STATUS_FAILURE;
3533 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3534 	t_u16 *bitmap_rates = MNULL;
3535 
3536 	ENTER();
3537 
3538 	ds_rate = (mlan_ds_rate *)pioctl_req->pbuf;
3539 	bitmap_rates = ds_rate->param.rate_cfg.bitmap_rates;
3540 
3541 	PRINTM(MINFO, "RateBitmap=%04x%04x%04x%04x%04x%04x%04x%04x"
3542 	       "%04x%04x%04x%04x%04x%04x%04x%04x%04x%04x, "
3543 	       "IsRateAuto=%d, DataRate=%d\n",
3544 	       bitmap_rates[17], bitmap_rates[16],
3545 	       bitmap_rates[15], bitmap_rates[14],
3546 	       bitmap_rates[13], bitmap_rates[12],
3547 	       bitmap_rates[11], bitmap_rates[10],
3548 	       bitmap_rates[9], bitmap_rates[8],
3549 	       bitmap_rates[7], bitmap_rates[6],
3550 	       bitmap_rates[5], bitmap_rates[4],
3551 	       bitmap_rates[3], bitmap_rates[2],
3552 	       bitmap_rates[1], bitmap_rates[0],
3553 	       pmpriv->is_data_rate_auto, pmpriv->data_rate);
3554 
3555 	/* Send request to firmware */
3556 	ret = wlan_prepare_cmd(pmpriv,
3557 			       HostCmd_CMD_TX_RATE_CFG,
3558 			       HostCmd_ACT_GEN_SET,
3559 			       0, (t_void *)pioctl_req, (t_void *)bitmap_rates);
3560 	if (ret == MLAN_STATUS_SUCCESS)
3561 		ret = MLAN_STATUS_PENDING;
3562 
3563 	LEAVE();
3564 	return ret;
3565 }
3566 
3567 /**
3568  *  @brief Get rate value
3569  *
3570  *  @param pmadapter	A pointer to mlan_adapter structure
3571  *  @param pioctl_req	A pointer to ioctl request buffer
3572  *
3573  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
3574  */
3575 static mlan_status
wlan_rate_ioctl_get_rate_value(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3576 wlan_rate_ioctl_get_rate_value(IN pmlan_adapter pmadapter,
3577 			       IN pmlan_ioctl_req pioctl_req)
3578 {
3579 	mlan_ds_rate *rate = MNULL;
3580 	mlan_status ret = MLAN_STATUS_SUCCESS;
3581 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3582 
3583 	ENTER();
3584 
3585 	rate = (mlan_ds_rate *)pioctl_req->pbuf;
3586 	rate->param.rate_cfg.is_rate_auto = pmpriv->is_data_rate_auto;
3587 	pioctl_req->data_read_written =
3588 		sizeof(mlan_rate_cfg_t) + MLAN_SUB_COMMAND_SIZE;
3589 
3590 	/* If not connected, set rate to the lowest in each band */
3591 	if (pmpriv->media_connected != MTRUE) {
3592 		if (pmpriv->config_bands & (BAND_B | BAND_G)) {
3593 			/* Return the lowest supported rate for BG band */
3594 			rate->param.rate_cfg.rate = SupportedRates_BG[0] & 0x7f;
3595 		} else if (pmpriv->config_bands & (BAND_A | BAND_B)) {
3596 			/* Return the lowest supported rate for A band */
3597 			rate->param.rate_cfg.rate = SupportedRates_BG[0] & 0x7f;
3598 		} else if (pmpriv->config_bands & BAND_A) {
3599 			/* Return the lowest supported rate for A band */
3600 			rate->param.rate_cfg.rate = SupportedRates_A[0] & 0x7f;
3601 		} else if (pmpriv->config_bands & BAND_G) {
3602 			/* Return the lowest supported rate for G band */
3603 			rate->param.rate_cfg.rate = SupportedRates_G[0] & 0x7f;
3604 		} else if (pmpriv->config_bands & BAND_B) {
3605 			/* Return the lowest supported rate for B band */
3606 			rate->param.rate_cfg.rate = SupportedRates_B[0] & 0x7f;
3607 		} else if (pmpriv->config_bands & BAND_GN) {
3608 			/* Return the lowest supported rate for N band */
3609 			rate->param.rate_cfg.rate = SupportedRates_N[0] & 0x7f;
3610 		} else {
3611 			PRINTM(MMSG, "Invalid Band 0x%x\n",
3612 			       pmpriv->config_bands);
3613 		}
3614 
3615 	} else {
3616 		/* Send request to firmware */
3617 		ret = wlan_prepare_cmd(pmpriv,
3618 				       HostCmd_CMD_802_11_TX_RATE_QUERY,
3619 				       HostCmd_ACT_GEN_GET,
3620 				       0, (t_void *)pioctl_req, MNULL);
3621 		if (ret == MLAN_STATUS_SUCCESS)
3622 			ret = MLAN_STATUS_PENDING;
3623 	}
3624 
3625 	LEAVE();
3626 	return ret;
3627 }
3628 
3629 /**
3630  *  @brief Set rate value
3631  *
3632  *  @param pmadapter	A pointer to mlan_adapter structure
3633  *  @param pioctl_req	A pointer to ioctl request buffer
3634  *
3635  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
3636  */
3637 static mlan_status
wlan_rate_ioctl_set_rate_value(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3638 wlan_rate_ioctl_set_rate_value(IN pmlan_adapter pmadapter,
3639 			       IN pmlan_ioctl_req pioctl_req)
3640 {
3641 	mlan_ds_rate *ds_rate = MNULL;
3642 	WLAN_802_11_RATES rates;
3643 	t_u8 *rate = MNULL;
3644 	int rate_index = 0;
3645 	t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
3646 	t_u32 i = 0;
3647 	mlan_status ret = MLAN_STATUS_SUCCESS;
3648 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3649 
3650 	ENTER();
3651 
3652 	ds_rate = (mlan_ds_rate *)pioctl_req->pbuf;
3653 
3654 	if (ds_rate->param.rate_cfg.is_rate_auto) {
3655 		memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
3656 		/* Support all HR/DSSS rates */
3657 		bitmap_rates[0] = 0x000F;
3658 		/* Support all OFDM rates */
3659 		bitmap_rates[1] = 0x00FF;
3660 		/* Rates talbe [0] HR/DSSS,[1] OFDM,[2..9] HT,[10..17] VHT */
3661 		/* Support all HT-MCSs rate */
3662 		for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates) - 3 - 8; i++)
3663 			bitmap_rates[i + 2] = 0xFFFF;
3664 		bitmap_rates[9] = 0x3FFF;
3665 		/* Set to 0 as default value */
3666 		for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates) - 10; i++)
3667 			bitmap_rates[i + 10] = 0x0;
3668 	} else {
3669 		memset(pmadapter, rates, 0, sizeof(rates));
3670 		wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode,
3671 					   (pmpriv->bss_mode ==
3672 					    MLAN_BSS_MODE_INFRA) ? pmpriv->
3673 					   config_bands : pmadapter->
3674 					   adhoc_start_band, rates);
3675 		rate = rates;
3676 		for (i = 0; (rate[i] && i < WLAN_SUPPORTED_RATES); i++) {
3677 			PRINTM(MINFO, "Rate=0x%X  Wanted=0x%X\n", rate[i],
3678 			       ds_rate->param.rate_cfg.rate);
3679 			if ((rate[i] & 0x7f) ==
3680 			    (ds_rate->param.rate_cfg.rate & 0x7f))
3681 				break;
3682 		}
3683 		if (!rate[i] || (i == WLAN_SUPPORTED_RATES)) {
3684 			PRINTM(MERROR, "The fixed data rate 0x%X is out "
3685 			       "of range\n", ds_rate->param.rate_cfg.rate);
3686 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3687 			ret = MLAN_STATUS_FAILURE;
3688 			goto exit;
3689 		}
3690 		memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
3691 
3692 		rate_index =
3693 			wlan_data_rate_to_index(pmadapter,
3694 						ds_rate->param.rate_cfg.rate);
3695 
3696 		/* Only allow b/g rates to be set */
3697 		if (rate_index >= MLAN_RATE_INDEX_HRDSSS0 &&
3698 		    rate_index <= MLAN_RATE_INDEX_HRDSSS3)
3699 			bitmap_rates[0] = 1 << rate_index;
3700 		else {
3701 			rate_index -= 1;	/* There is a 0x00 in the table */
3702 			if (rate_index >= MLAN_RATE_INDEX_OFDM0 &&
3703 			    rate_index <= MLAN_RATE_INDEX_OFDM7)
3704 				bitmap_rates[1] =
3705 					1 << (rate_index -
3706 					      MLAN_RATE_INDEX_OFDM0);
3707 		}
3708 	}
3709 
3710 	/* Send request to firmware */
3711 	ret = wlan_prepare_cmd(pmpriv,
3712 			       HostCmd_CMD_TX_RATE_CFG,
3713 			       HostCmd_ACT_GEN_SET,
3714 			       0, (t_void *)pioctl_req, bitmap_rates);
3715 	if (ret == MLAN_STATUS_SUCCESS)
3716 		ret = MLAN_STATUS_PENDING;
3717 
3718 exit:
3719 	LEAVE();
3720 	return ret;
3721 }
3722 
3723 /**
3724  *  @brief Get rate index
3725  *
3726  *  @param pmadapter	A pointer to mlan_adapter structure
3727  *  @param pioctl_req	A pointer to ioctl request buffer
3728  *
3729  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
3730  */
3731 static mlan_status
wlan_rate_ioctl_get_rate_index(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3732 wlan_rate_ioctl_get_rate_index(IN pmlan_adapter pmadapter,
3733 			       IN pmlan_ioctl_req pioctl_req)
3734 {
3735 	mlan_status ret = MLAN_STATUS_SUCCESS;
3736 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3737 
3738 	ENTER();
3739 
3740 	/* Send request to firmware */
3741 	ret = wlan_prepare_cmd(pmpriv,
3742 			       HostCmd_CMD_TX_RATE_CFG,
3743 			       HostCmd_ACT_GEN_GET,
3744 			       0, (t_void *)pioctl_req, MNULL);
3745 	if (ret == MLAN_STATUS_SUCCESS)
3746 		ret = MLAN_STATUS_PENDING;
3747 
3748 	LEAVE();
3749 	return ret;
3750 }
3751 
3752 /**
3753  *  @brief Set rate index
3754  *
3755  *  @param pmadapter	A pointer to mlan_adapter structure
3756  *  @param pioctl_req	A pointer to ioctl request buffer
3757  *
3758  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
3759  */
3760 static mlan_status
wlan_rate_ioctl_set_rate_index(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3761 wlan_rate_ioctl_set_rate_index(IN pmlan_adapter pmadapter,
3762 			       IN pmlan_ioctl_req pioctl_req)
3763 {
3764 	t_u32 rate_index;
3765 	t_u32 rate_format;
3766 	t_u32 i;
3767 	mlan_ds_rate *ds_rate = MNULL;
3768 	mlan_status ret = MLAN_STATUS_FAILURE;
3769 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3770 	t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
3771 
3772 	ENTER();
3773 
3774 	ds_rate = (mlan_ds_rate *)pioctl_req->pbuf;
3775 	rate_format = ds_rate->param.rate_cfg.rate_format;
3776 	rate_index = ds_rate->param.rate_cfg.rate;
3777 
3778 	if (ds_rate->param.rate_cfg.is_rate_auto) {
3779 		memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
3780 		/* Rates talbe [0]: HR/DSSS;[1]: OFDM; [2..9] HT; */
3781 		/* Support all HR/DSSS rates */
3782 		bitmap_rates[0] = 0x000F;
3783 		/* Support all OFDM rates */
3784 		bitmap_rates[1] = 0x00FF;
3785 		/* Support all HT-MCSs rate */
3786 		for (i = 2; i < 9; i++)
3787 			bitmap_rates[i] = 0xFFFF;
3788 		bitmap_rates[9] = 0x3FFF;
3789 	} else {
3790 		PRINTM(MINFO, "Rate index is %d\n", rate_index);
3791 		memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
3792 		if (rate_format == MLAN_RATE_FORMAT_LG) {
3793 			/* Bitmap of HR/DSSS rates */
3794 			if ((rate_index >= MLAN_RATE_INDEX_HRDSSS0) &&
3795 			    (rate_index <= MLAN_RATE_INDEX_HRDSSS3)) {
3796 				bitmap_rates[0] = 1 << rate_index;
3797 				ret = MLAN_STATUS_SUCCESS;
3798 				/* Bitmap of OFDM rates */
3799 			} else if ((rate_index >= MLAN_RATE_INDEX_OFDM0) &&
3800 				   (rate_index <= MLAN_RATE_INDEX_OFDM7)) {
3801 				bitmap_rates[1] =
3802 					1 << (rate_index -
3803 					      MLAN_RATE_INDEX_OFDM0);
3804 				ret = MLAN_STATUS_SUCCESS;
3805 			}
3806 		} else if (rate_format == MLAN_RATE_FORMAT_HT) {
3807 			if ((rate_index >= MLAN_RATE_INDEX_MCS0) &&
3808 			    (rate_index <= MLAN_RATE_INDEX_MCS32)) {
3809 				bitmap_rates[2 + (rate_index / 16)] =
3810 					1 << (rate_index % 16);
3811 				ret = MLAN_STATUS_SUCCESS;
3812 			}
3813 		}
3814 
3815 		if (ret == MLAN_STATUS_FAILURE) {
3816 			PRINTM(MERROR, "Invalid MCS index=%d. \n", rate_index);
3817 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3818 			LEAVE();
3819 			return MLAN_STATUS_FAILURE;
3820 		}
3821 	}
3822 
3823 	PRINTM(MINFO, "RateBitmap=%04x%04x%04x%04x%04x%04x%04x%04x"
3824 	       "%04x%04x%04x%04x%04x%04x%04x%04x%04x%04x, "
3825 	       "IsRateAuto=%d, DataRate=%d\n",
3826 	       bitmap_rates[17], bitmap_rates[16],
3827 	       bitmap_rates[15], bitmap_rates[14],
3828 	       bitmap_rates[13], bitmap_rates[12],
3829 	       bitmap_rates[11], bitmap_rates[10],
3830 	       bitmap_rates[9], bitmap_rates[8],
3831 	       bitmap_rates[7], bitmap_rates[6],
3832 	       bitmap_rates[5], bitmap_rates[4],
3833 	       bitmap_rates[3], bitmap_rates[2],
3834 	       bitmap_rates[1], bitmap_rates[0],
3835 	       pmpriv->is_data_rate_auto, pmpriv->data_rate);
3836 
3837 	/* Send request to firmware */
3838 	ret = wlan_prepare_cmd(pmpriv,
3839 			       HostCmd_CMD_TX_RATE_CFG,
3840 			       HostCmd_ACT_GEN_SET,
3841 			       0, (t_void *)pioctl_req, (t_void *)bitmap_rates);
3842 	if (ret == MLAN_STATUS_SUCCESS)
3843 		ret = MLAN_STATUS_PENDING;
3844 
3845 	LEAVE();
3846 	return ret;
3847 }
3848 
3849 /**
3850  *  @brief Rate configuration command handler
3851  *
3852  *  @param pmadapter	A pointer to mlan_adapter structure
3853  *  @param pioctl_req	A pointer to ioctl request buffer
3854  *
3855  *  @return		MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
3856  */
3857 mlan_status
wlan_rate_ioctl_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3858 wlan_rate_ioctl_cfg(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
3859 {
3860 	mlan_ds_rate *rate = MNULL;
3861 	mlan_status status = MLAN_STATUS_SUCCESS;
3862 
3863 	ENTER();
3864 
3865 	rate = (mlan_ds_rate *)pioctl_req->pbuf;
3866 	if (rate->param.rate_cfg.rate_type == MLAN_RATE_BITMAP) {
3867 		if (pioctl_req->action == MLAN_ACT_GET)
3868 			status = wlan_rate_ioctl_get_rate_bitmap(pmadapter,
3869 								 pioctl_req);
3870 		else
3871 			status = wlan_rate_ioctl_set_rate_bitmap(pmadapter,
3872 								 pioctl_req);
3873 	} else if (rate->param.rate_cfg.rate_type == MLAN_RATE_VALUE) {
3874 		if (pioctl_req->action == MLAN_ACT_GET)
3875 			status = wlan_rate_ioctl_get_rate_value(pmadapter,
3876 								pioctl_req);
3877 		else
3878 			status = wlan_rate_ioctl_set_rate_value(pmadapter,
3879 								pioctl_req);
3880 	} else {
3881 		if (pioctl_req->action == MLAN_ACT_GET)
3882 			status = wlan_rate_ioctl_get_rate_index(pmadapter,
3883 								pioctl_req);
3884 		else
3885 			status = wlan_rate_ioctl_set_rate_index(pmadapter,
3886 								pioctl_req);
3887 	}
3888 
3889 	LEAVE();
3890 	return status;
3891 }
3892 
3893 /**
3894  *  @brief Get data rates
3895  *
3896  *  @param pmadapter    A pointer to mlan_adapter structure
3897  *  @param pioctl_req   A pointer to ioctl request buffer
3898  *
3899  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
3900  */
3901 mlan_status
wlan_rate_ioctl_get_data_rate(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3902 wlan_rate_ioctl_get_data_rate(IN pmlan_adapter pmadapter,
3903 			      IN pmlan_ioctl_req pioctl_req)
3904 {
3905 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3906 	mlan_status ret = MLAN_STATUS_SUCCESS;
3907 
3908 	ENTER();
3909 
3910 	if (pioctl_req->action != MLAN_ACT_GET) {
3911 		ret = MLAN_STATUS_FAILURE;
3912 		goto exit;
3913 	}
3914 
3915 	/* Send request to firmware */
3916 	ret = wlan_prepare_cmd(pmpriv,
3917 			       HostCmd_CMD_802_11_TX_RATE_QUERY,
3918 			       HostCmd_ACT_GEN_GET,
3919 			       0, (t_void *)pioctl_req, MNULL);
3920 	if (ret == MLAN_STATUS_SUCCESS)
3921 		ret = MLAN_STATUS_PENDING;
3922 
3923 exit:
3924 	LEAVE();
3925 	return ret;
3926 }
3927 
3928 /**
3929  *  @brief Set/Get remain on channel setting
3930  *
3931  *  @param pmadapter	A pointer to mlan_adapter structure
3932  *  @param pioctl_req	A pointer to ioctl request buffer
3933  *
3934  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
3935  */
3936 mlan_status
wlan_radio_ioctl_remain_chan_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3937 wlan_radio_ioctl_remain_chan_cfg(IN pmlan_adapter pmadapter,
3938 				 IN pmlan_ioctl_req pioctl_req)
3939 {
3940 	mlan_status ret = MLAN_STATUS_SUCCESS;
3941 	mlan_ds_radio_cfg *radio_cfg = MNULL;
3942 	t_u16 cmd_action = 0;
3943 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3944 
3945 	ENTER();
3946 
3947 	radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
3948 	if (pioctl_req->action == MLAN_ACT_SET)
3949 		cmd_action = HostCmd_ACT_GEN_SET;
3950 	else
3951 		cmd_action = HostCmd_ACT_GEN_GET;
3952 
3953 	/* Send request to firmware */
3954 	ret = wlan_prepare_cmd(pmpriv,
3955 			       HostCmd_CMD_802_11_REMAIN_ON_CHANNEL,
3956 			       cmd_action,
3957 			       0,
3958 			       (t_void *)pioctl_req,
3959 			       &radio_cfg->param.remain_chan);
3960 
3961 	if (ret == MLAN_STATUS_SUCCESS)
3962 		ret = MLAN_STATUS_PENDING;
3963 
3964 	LEAVE();
3965 	return ret;
3966 }
3967 
3968 #ifdef WIFI_DIRECT_SUPPORT
3969 /**
3970  *  @brief Set/Get wifi_direct_mode
3971  *
3972  *  @param pmadapter	A pointer to mlan_adapter structure
3973  *  @param pioctl_req	A pointer to ioctl request buffer
3974  *
3975  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
3976  */
3977 mlan_status
wlan_bss_ioctl_wifi_direct_mode(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3978 wlan_bss_ioctl_wifi_direct_mode(IN pmlan_adapter pmadapter,
3979 				IN pmlan_ioctl_req pioctl_req)
3980 {
3981 	mlan_status ret = MLAN_STATUS_SUCCESS;
3982 	mlan_ds_bss *bss = MNULL;
3983 
3984 	t_u16 cmd_action = 0;
3985 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3986 
3987 	ENTER();
3988 
3989 	bss = (mlan_ds_bss *)pioctl_req->pbuf;
3990 
3991 	if (pioctl_req->action == MLAN_ACT_SET)
3992 		cmd_action = HostCmd_ACT_GEN_SET;
3993 	else
3994 		cmd_action = HostCmd_ACT_GEN_GET;
3995 
3996 	/* Send request to firmware */
3997 	ret = wlan_prepare_cmd(pmpriv,
3998 			       HOST_CMD_WIFI_DIRECT_MODE_CONFIG,
3999 			       cmd_action,
4000 			       0, (t_void *)pioctl_req, &bss->param.wfd_mode);
4001 
4002 	if (ret == MLAN_STATUS_SUCCESS)
4003 		ret = MLAN_STATUS_PENDING;
4004 
4005 	LEAVE();
4006 	return ret;
4007 }
4008 
4009 /**
4010  *  @brief Set/Get p2p config
4011  *
4012  *  @param pmadapter	A pointer to mlan_adapter structure
4013  *  @param pioctl_req	A pointer to ioctl request buffer
4014  *
4015  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
4016  */
4017 mlan_status
wlan_misc_p2p_config(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4018 wlan_misc_p2p_config(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
4019 {
4020 	mlan_status ret = MLAN_STATUS_SUCCESS;
4021 	mlan_ds_misc_cfg *misc_cfg = MNULL;
4022 	t_u16 cmd_action = 0;
4023 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4024 
4025 	ENTER();
4026 
4027 	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4028 	if (pioctl_req->action == MLAN_ACT_SET)
4029 		cmd_action = HostCmd_ACT_GEN_SET;
4030 	else
4031 		cmd_action = HostCmd_ACT_GEN_GET;
4032 
4033 	/* Send request to firmware */
4034 	ret = wlan_prepare_cmd(pmpriv,
4035 			       HOST_CMD_P2P_PARAMS_CONFIG,
4036 			       cmd_action,
4037 			       0,
4038 			       (t_void *)pioctl_req,
4039 			       &misc_cfg->param.p2p_config);
4040 
4041 	if (ret == MLAN_STATUS_SUCCESS)
4042 		ret = MLAN_STATUS_PENDING;
4043 
4044 	LEAVE();
4045 	return ret;
4046 }
4047 #endif
4048 
4049 /**
4050  *  @brief Set coalesce config
4051  *
4052  *  @param pmadapter	A pointer to mlan_adapter structure
4053  *  @param pioctl_req	A pointer to ioctl request buffer
4054  *
4055  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
4056  */
4057 mlan_status
wlan_misc_ioctl_coalesce_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4058 wlan_misc_ioctl_coalesce_cfg(IN pmlan_adapter pmadapter,
4059 			     IN pmlan_ioctl_req pioctl_req)
4060 {
4061 	mlan_status ret = MLAN_STATUS_SUCCESS;
4062 	mlan_ds_misc_cfg *misc_cfg = MNULL;
4063 	t_u16 cmd_action = 0;
4064 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4065 
4066 	ENTER();
4067 
4068 	misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4069 	if (pioctl_req->action == MLAN_ACT_SET)
4070 		cmd_action = HostCmd_ACT_GEN_SET;
4071 	else
4072 		cmd_action = HostCmd_ACT_GEN_GET;
4073 
4074 	/* Send request to firmware */
4075 	ret = wlan_prepare_cmd(pmpriv,
4076 			       HostCmd_CMD_COALESCE_CFG,
4077 			       cmd_action,
4078 			       0,
4079 			       (t_void *)pioctl_req,
4080 			       &misc_cfg->param.coalesce_cfg);
4081 
4082 	if (ret == MLAN_STATUS_SUCCESS)
4083 		ret = MLAN_STATUS_PENDING;
4084 
4085 	LEAVE();
4086 	return ret;
4087 }
4088 
4089 /**
4090  *  @brief Get/Set Tx control configuration
4091  *
4092  *  @param pmadapter    A pointer to mlan_adapter structure
4093  *  @param pioctl_req   A pointer to ioctl request buffer
4094  *
4095  *  @return             MLAN_STATUS_SUCCESS
4096  */
4097 mlan_status
wlan_misc_ioctl_txcontrol(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4098 wlan_misc_ioctl_txcontrol(IN pmlan_adapter pmadapter,
4099 			  IN pmlan_ioctl_req pioctl_req)
4100 {
4101 	mlan_status ret = MLAN_STATUS_SUCCESS;
4102 	mlan_ds_misc_cfg *misc = MNULL;
4103 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4104 
4105 	ENTER();
4106 
4107 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4108 	if (pioctl_req->action == MLAN_ACT_SET)
4109 		pmpriv->pkt_tx_ctrl = misc->param.tx_control;
4110 	else
4111 		misc->param.tx_control = pmpriv->pkt_tx_ctrl;
4112 
4113 	LEAVE();
4114 	return ret;
4115 }
4116 
4117 #ifdef RX_PACKET_COALESCE
4118 /**
4119  *  @brief Get/Set RX packet coalescing configuration
4120  *
4121  *  @param pmadapter    A pointer to mlan_adapter structure
4122  *  @param pioctl_req   A pointer to ioctl request buffer
4123  *
4124  *  @return             MLAN_STATUS_SUCCESS
4125  */
4126 mlan_status
wlan_misc_ioctl_rx_pkt_coalesce_config(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4127 wlan_misc_ioctl_rx_pkt_coalesce_config(IN pmlan_adapter pmadapter,
4128 				       IN pmlan_ioctl_req pioctl_req)
4129 {
4130 	mlan_status ret = MLAN_STATUS_SUCCESS;
4131 	mlan_ds_misc_cfg *misc = MNULL;
4132 	t_u16 cmd_action = 0;
4133 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4134 
4135 	ENTER();
4136 
4137 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4138 
4139 	if (pioctl_req->action == MLAN_ACT_SET)
4140 		cmd_action = HostCmd_ACT_GEN_SET;
4141 	else
4142 		cmd_action = HostCmd_ACT_GEN_GET;
4143 
4144 	/* Send request to firmware */
4145 	ret = wlan_prepare_cmd(pmpriv,
4146 			       HostCmd_CMD_RX_PKT_COALESCE_CFG,
4147 			       cmd_action,
4148 			       0,
4149 			       (t_void *)pioctl_req, &misc->param.rx_coalesce);
4150 
4151 	if (ret == MLAN_STATUS_SUCCESS)
4152 		ret = MLAN_STATUS_PENDING;
4153 
4154 	LEAVE();
4155 	return ret;
4156 }
4157 #endif
4158 /**
4159  *  @brief Get/Set channel time and buffer weight configuration
4160  *
4161  *  @param pmadapter    A pointer to mlan_adapter structure
4162  *  @param pioctl_req   A pointer to ioctl request buffer
4163  *
4164  *  @return             MLAN_STATUS_SUCCESS
4165  */
4166 mlan_status
wlan_misc_ioctl_multi_chan_config(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4167 wlan_misc_ioctl_multi_chan_config(IN pmlan_adapter pmadapter,
4168 				  IN pmlan_ioctl_req pioctl_req)
4169 {
4170 	mlan_status ret = MLAN_STATUS_SUCCESS;
4171 	mlan_ds_misc_cfg *misc = MNULL;
4172 	t_u16 cmd_action = 0;
4173 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4174 
4175 	ENTER();
4176 
4177 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4178 
4179 	if (pioctl_req->action == MLAN_ACT_SET)
4180 		cmd_action = HostCmd_ACT_GEN_SET;
4181 	else
4182 		cmd_action = HostCmd_ACT_GEN_GET;
4183 
4184 	/* Send request to firmware */
4185 	ret = wlan_prepare_cmd(pmpriv,
4186 			       HostCmd_CMD_MULTI_CHAN_CONFIG,
4187 			       cmd_action,
4188 			       0,
4189 			       (t_void *)pioctl_req,
4190 			       &misc->param.multi_chan_cfg);
4191 
4192 	if (ret == MLAN_STATUS_SUCCESS)
4193 		ret = MLAN_STATUS_PENDING;
4194 
4195 	LEAVE();
4196 	return ret;
4197 }
4198 
4199 /**
4200  *  @brief Get/Set multi-channel policy setting
4201  *
4202  *  @param pmadapter    A pointer to mlan_adapter structure
4203  *  @param pioctl_req   A pointer to ioctl request buffer
4204  *
4205  *  @return             MLAN_STATUS_SUCCESS
4206  */
4207 mlan_status
wlan_misc_ioctl_multi_chan_policy(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4208 wlan_misc_ioctl_multi_chan_policy(IN pmlan_adapter pmadapter,
4209 				  IN pmlan_ioctl_req pioctl_req)
4210 {
4211 	mlan_status ret = MLAN_STATUS_SUCCESS;
4212 	mlan_ds_misc_cfg *misc = MNULL;
4213 	t_u16 cmd_action = 0;
4214 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4215 
4216 	ENTER();
4217 
4218 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4219 
4220 	if (pioctl_req->action == MLAN_ACT_SET) {
4221 		if (pmadapter->dfs_repeater) {
4222 			PRINTM(MMSG,
4223 			       "DFS-Repeater is on, can not enable DRCS\n");
4224 			ret = MLAN_STATUS_FAILURE;
4225 			goto fail;
4226 		}
4227 		cmd_action = HostCmd_ACT_GEN_SET;
4228 	} else {
4229 		cmd_action = HostCmd_ACT_GEN_GET;
4230 	}
4231 
4232 	/* Send request to firmware */
4233 	ret = wlan_prepare_cmd(pmpriv,
4234 			       HostCmd_CMD_MULTI_CHAN_POLICY,
4235 			       cmd_action,
4236 			       0,
4237 			       (t_void *)pioctl_req,
4238 			       &misc->param.multi_chan_policy);
4239 
4240 	if (ret == MLAN_STATUS_SUCCESS)
4241 		ret = MLAN_STATUS_PENDING;
4242 fail:
4243 	LEAVE();
4244 	return ret;
4245 }
4246 
4247 /**
4248  *  @brief Get/Set DRCS configuration
4249  *
4250  *  @param pmadapter    A pointer to mlan_adapter structure
4251  *  @param pioctl_req   A pointer to ioctl request buffer
4252  *
4253  *  @return             MLAN_STATUS_SUCCESS
4254  */
4255 mlan_status
wlan_misc_ioctl_drcs_config(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4256 wlan_misc_ioctl_drcs_config(IN pmlan_adapter pmadapter,
4257 			    IN pmlan_ioctl_req pioctl_req)
4258 {
4259 	mlan_status ret = MLAN_STATUS_SUCCESS;
4260 	mlan_ds_misc_cfg *misc = MNULL;
4261 	t_u16 cmd_action = 0;
4262 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4263 
4264 	ENTER();
4265 
4266 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4267 
4268 	if (pioctl_req->action == MLAN_ACT_SET)
4269 		cmd_action = HostCmd_ACT_GEN_SET;
4270 	else
4271 		cmd_action = HostCmd_ACT_GEN_GET;
4272 
4273 	/* Send request to firmware */
4274 	ret = wlan_prepare_cmd(pmpriv,
4275 			       HostCmd_CMD_DRCS_CONFIG,
4276 			       cmd_action,
4277 			       0, (t_void *)pioctl_req, &misc->param.drcs_cfg);
4278 
4279 	if (ret == MLAN_STATUS_SUCCESS)
4280 		ret = MLAN_STATUS_PENDING;
4281 
4282 	LEAVE();
4283 	return ret;
4284 }
4285 
4286 /**
4287  *  @brief Is any uAP started or STA connected?
4288  *
4289  *  @param pmadapter    A pointer to mlan_adapter structure
4290  *
4291  *  @return             MTRUE/MFALSE
4292  */
4293 t_bool
wlan_check_interface_active(mlan_adapter * pmadapter)4294 wlan_check_interface_active(mlan_adapter *pmadapter)
4295 {
4296 	t_bool ret = MFALSE;
4297 	pmlan_private pmpriv;
4298 	int i;
4299 
4300 	if (pmadapter == MNULL)
4301 		return MFALSE;
4302 
4303 	for (i = 0; i < pmadapter->priv_num; i++) {
4304 		pmpriv = pmadapter->priv[i];
4305 		if (pmpriv) {
4306 #ifdef UAP_SUPPORT
4307 			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
4308 				ret = pmpriv->uap_bss_started;
4309 			else
4310 #endif
4311 			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA)
4312 				ret = pmpriv->media_connected;
4313 		}
4314 		if (ret)
4315 			return MTRUE;
4316 	}
4317 
4318 	return MFALSE;
4319 }
4320 
4321 /**
4322  *  @brief Get/Set DFS REPEATER mode
4323  *
4324  *  @param pmadapter    A pointer to mlan_adapter structure
4325  *  @param pioctl_req   A pointer to ioctl request buffer
4326  *
4327  *  @return             MLAN_STATUS_SUCCESS
4328  */
4329 mlan_status
wlan_misc_ioctl_dfs_repeater_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4330 wlan_misc_ioctl_dfs_repeater_cfg(IN pmlan_adapter pmadapter,
4331 				 IN pmlan_ioctl_req pioctl_req)
4332 {
4333 	mlan_status ret = MLAN_STATUS_SUCCESS;
4334 	mlan_ds_misc_cfg *misc = MNULL;
4335 	t_u16 cmd_action = 0;
4336 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4337 
4338 	ENTER();
4339 
4340 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4341 
4342 	if (pioctl_req->action == MLAN_ACT_SET) {
4343 		/* Make sure no interface is active
4344 		 * before setting the dfs repeater mode
4345 		 */
4346 		if (wlan_check_interface_active(pmadapter)) {
4347 			PRINTM(MMSG, "DFS-Repeater active priv found,"
4348 			       " skip enabling the mode.\n");
4349 			ret = MLAN_STATUS_FAILURE;
4350 			goto done;
4351 		}
4352 
4353 		/* If DRCS is on then we should not set
4354 		 * DFS-repeater mode */
4355 		if (pmadapter->mc_policy) {
4356 			PRINTM(MERROR,
4357 			       "DFS-repeater cannot be started when DRCS is on\n");
4358 			ret = MLAN_STATUS_FAILURE;
4359 			goto done;
4360 		}
4361 		cmd_action = HostCmd_ACT_GEN_SET;
4362 	} else {
4363 		cmd_action = HostCmd_ACT_GEN_GET;
4364 	}
4365 
4366 	/* Send request to firmware */
4367 	ret = wlan_prepare_cmd(pmpriv, HostCmd_DFS_REPEATER_MODE, cmd_action, 0,
4368 			       (t_void *)pioctl_req, &misc->param.dfs_repeater);
4369 
4370 done:
4371 	if (ret == MLAN_STATUS_SUCCESS)
4372 		ret = MLAN_STATUS_PENDING;
4373 
4374 	LEAVE();
4375 	return ret;
4376 }
4377 
4378 /**
4379  *  @brief Configure PMIC in Firmware
4380  *
4381  *  @param pmadapter    A pointer to mlan_adapter structure
4382  *  @param pioctl_req   A pointer to ioctl request buffer
4383  *
4384  *  @return             MLAN_STATUS_SUCCESS
4385  */
4386 mlan_status
wlan_misc_ioctl_pmic_configure(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4387 wlan_misc_ioctl_pmic_configure(IN pmlan_adapter pmadapter,
4388 			       IN pmlan_ioctl_req pioctl_req)
4389 {
4390 	mlan_status ret = MLAN_STATUS_SUCCESS;
4391 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4392 
4393 	ENTER();
4394 
4395 	/* Send request to firmware */
4396 	ret = wlan_prepare_cmd(pmpriv,
4397 			       HOST_CMD_PMIC_CONFIGURE,
4398 			       HostCmd_ACT_GEN_SET,
4399 			       0, (t_void *)pioctl_req, MNULL);
4400 
4401 	if (ret == MLAN_STATUS_SUCCESS)
4402 		ret = MLAN_STATUS_PENDING;
4403 
4404 	LEAVE();
4405 	return ret;
4406 }
4407 
4408 /*  @brief Set/Get CW Mode Level control
4409  *
4410  *  @param pmadapter    A pointer to mlan_adapter structure
4411  *  @param pioctl_req   A pointer to ioctl request buffer
4412  *
4413  *  @return             MLAN_STATUS_SUCCESS
4414  */
4415 mlan_status
wlan_misc_ioctl_cwmode_ctrl(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4416 wlan_misc_ioctl_cwmode_ctrl(IN pmlan_adapter pmadapter,
4417 			    IN pmlan_ioctl_req pioctl_req)
4418 {
4419 	mlan_status ret = MLAN_STATUS_SUCCESS;
4420 	mlan_ds_misc_cfg *misc = MNULL;
4421 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4422 	t_u16 cmd_action = 0;
4423 
4424 	ENTER();
4425 
4426 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4427 
4428 	if (pioctl_req->action == MLAN_ACT_SET)
4429 		cmd_action = HostCmd_ACT_GEN_SET;
4430 	else
4431 		cmd_action = HostCmd_ACT_GEN_GET;
4432 
4433 	/* Send request to firmware */
4434 	ret = wlan_prepare_cmd(pmpriv,
4435 			       HostCmd_CMD_CW_MODE_CTRL,
4436 			       cmd_action,
4437 			       0, (t_void *)pioctl_req, &misc->param.cwmode);
4438 
4439 	if (ret == MLAN_STATUS_SUCCESS)
4440 		ret = MLAN_STATUS_PENDING;
4441 
4442 	LEAVE();
4443 	return ret;
4444 }
4445 
4446 /**
4447  *  @brief Set/Get WPA passphrase for esupplicant
4448  *
4449  *  @param pmadapter	A pointer to mlan_adapter structure
4450  *  @param pioctl_req	A pointer to ioctl request buffer
4451  *
4452  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
4453  */
4454 mlan_status
wlan_sec_ioctl_passphrase(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4455 wlan_sec_ioctl_passphrase(IN pmlan_adapter pmadapter,
4456 			  IN pmlan_ioctl_req pioctl_req)
4457 {
4458 	mlan_status ret = MLAN_STATUS_SUCCESS;
4459 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4460 	mlan_ds_sec_cfg *sec = MNULL;
4461 	t_u16 cmd_action = 0;
4462 #ifdef STA_SUPPORT
4463 	BSSDescriptor_t *pbss_desc;
4464 	int i = 0;
4465 #endif
4466 	ENTER();
4467 
4468 	sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
4469 #ifdef DRV_EMBEDDED_SUPPLICANT
4470 	if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA &&
4471 	    !IS_FW_SUPPORT_SUPPLICANT(pmpriv->adapter)) {
4472 		if (sec->param.passphrase.psk_type == MLAN_PSK_QUERY)
4473 			SupplicantQueryPassphrase(pmpriv->psapriv,
4474 						  (void *)&sec->param.
4475 						  passphrase);
4476 		else if (sec->param.passphrase.psk_type == MLAN_PSK_CLEAR)
4477 			SupplicantClearPMK(pmpriv->psapriv,
4478 					   (void *)&sec->param.passphrase);
4479 		else
4480 			SupplicantSetPassphrase(pmpriv->psapriv,
4481 						(void *)&sec->param.passphrase);
4482 
4483 		LEAVE();
4484 		return ret;
4485 	}
4486 #endif
4487 
4488 	if (pioctl_req->action == MLAN_ACT_SET) {
4489 		if (sec->param.passphrase.psk_type == MLAN_PSK_CLEAR)
4490 			cmd_action = HostCmd_ACT_GEN_REMOVE;
4491 		else
4492 			cmd_action = HostCmd_ACT_GEN_SET;
4493 	} else if (pioctl_req->action == MLAN_ACT_CLEAR) {
4494 		cmd_action = HostCmd_ACT_GEN_REMOVE;
4495 	} else {
4496 		if (sec->param.passphrase.psk_type == MLAN_PSK_QUERY) {
4497 #ifdef STA_SUPPORT
4498 			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA &&
4499 			    sec->param.passphrase.ssid.ssid_len == 0) {
4500 				i = wlan_find_bssid_in_list(pmpriv,
4501 							    (t_u8 *)&sec->param.
4502 							    passphrase.bssid,
4503 							    MLAN_BSS_MODE_AUTO);
4504 				if (i >= 0) {
4505 					pbss_desc = &pmadapter->pscan_table[i];
4506 					memcpy(pmadapter,
4507 					       &sec->param.passphrase.ssid,
4508 					       &pbss_desc->ssid,
4509 					       sizeof(mlan_802_11_ssid));
4510 					memset(pmadapter,
4511 					       &sec->param.passphrase.bssid, 0,
4512 					       MLAN_MAC_ADDR_LENGTH);
4513 					PRINTM(MINFO,
4514 					       "PSK_QUERY: found ssid=%s\n",
4515 					       sec->param.passphrase.ssid.ssid);
4516 				}
4517 			} else
4518 #endif
4519 				memset(pmadapter, &sec->param.passphrase.bssid,
4520 				       0, MLAN_MAC_ADDR_LENGTH);
4521 		}
4522 		cmd_action = HostCmd_ACT_GEN_GET;
4523 	}
4524 
4525 	/* Send request to firmware */
4526 	ret = wlan_prepare_cmd(pmpriv,
4527 			       HostCmd_CMD_SUPPLICANT_PMK,
4528 			       cmd_action,
4529 			       0, (t_void *)pioctl_req, (t_void *)sec);
4530 	if (ret == MLAN_STATUS_SUCCESS)
4531 		ret = MLAN_STATUS_PENDING;
4532 
4533 	LEAVE();
4534 	return ret;
4535 }
4536 
4537 /**
4538  *  @brief Set per packet Txctl and Rxinfo configuration
4539  *
4540  *  @param pmadapter    A pointer to mlan_adapter structure
4541  *  @param pioctl_req   A pointer to ioctl request buffer
4542  *
4543  *  @return             MLAN_STATUS_SUCCESS --success, otherwise fail
4544  */
4545 mlan_status
wlan_misc_per_pkt_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4546 wlan_misc_per_pkt_cfg(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
4547 {
4548 	mlan_status ret = MLAN_STATUS_SUCCESS;
4549 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4550 	mlan_ds_misc_cfg *misc = MNULL;
4551 
4552 	ENTER();
4553 
4554 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4555 	pmpriv->rx_pkt_info = MFALSE;
4556 	if (misc->param.txrx_pkt_ctrl & RX_PKT_INFO)
4557 		pmpriv->rx_pkt_info = MTRUE;
4558 
4559 	LEAVE();
4560 	return ret;
4561 }
4562 
4563 /**
4564  *  @brief Set/Get region code
4565  *
4566  *  @param pmadapter	A pointer to mlan_adapter structure
4567  *  @param pioctl_req	A pointer to ioctl request buffer
4568  *
4569  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
4570  */
4571 mlan_status
wlan_misc_ioctl_region(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4572 wlan_misc_ioctl_region(IN pmlan_adapter pmadapter,
4573 		       IN pmlan_ioctl_req pioctl_req)
4574 {
4575 	mlan_status ret = MLAN_STATUS_SUCCESS;
4576 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4577 	mlan_ds_misc_cfg *misc = MNULL;
4578 	int i;
4579 
4580 	ENTER();
4581 
4582 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4583 	if (pioctl_req->action == MLAN_ACT_GET) {
4584 		misc->param.region_code = pmadapter->region_code;
4585 	} else {
4586 		if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
4587 			PRINTM(MERROR,
4588 			       "ForceRegionRule is set in the on-chip OTP"
4589 			       " memory\n");
4590 			LEAVE();
4591 			return MLAN_STATUS_FAILURE;
4592 		}
4593 		for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
4594 			/* Use the region code to search for the index */
4595 			if (misc->param.region_code == region_code_index[i]) {
4596 				pmadapter->region_code =
4597 					(t_u16)misc->param.region_code;
4598 				break;
4599 			}
4600 		}
4601 		/* It's unidentified region code */
4602 		if (i >= MRVDRV_MAX_REGION_CODE) {
4603 			PRINTM(MERROR, "Region Code not identified\n");
4604 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4605 			LEAVE();
4606 			return MLAN_STATUS_FAILURE;
4607 		}
4608 		pmadapter->cfp_code_bg = misc->param.region_code;
4609 		pmadapter->cfp_code_a = misc->param.region_code;
4610 		if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
4611 					 pmadapter->config_bands | pmadapter->
4612 					 adhoc_start_band)) {
4613 			pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
4614 			ret = MLAN_STATUS_FAILURE;
4615 		}
4616 	}
4617 	pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
4618 
4619 	LEAVE();
4620 	return ret;
4621 }
4622 
4623 /**
4624  *  @brief Configure GPIO independent reset
4625  *
4626  *  @param pmadapter	A pointer to mlan_adapter structure
4627  *  @param pioctl_req	A pointer to ioctl request buffer
4628  *
4629  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
4630  */
4631 mlan_status
wlan_misc_ioctl_ind_rst_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4632 wlan_misc_ioctl_ind_rst_cfg(IN pmlan_adapter pmadapter,
4633 			    IN pmlan_ioctl_req pioctl_req)
4634 {
4635 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4636 	mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4637 	mlan_status ret = MLAN_STATUS_SUCCESS;
4638 	t_u16 cmd_action = 0;
4639 
4640 	ENTER();
4641 
4642 	if (pioctl_req->action == MLAN_ACT_GET)
4643 		cmd_action = HostCmd_ACT_GEN_GET;
4644 	else
4645 		cmd_action = HostCmd_ACT_GEN_SET;
4646 
4647 	/* Send request to firmware */
4648 	ret = wlan_prepare_cmd(pmpriv,
4649 			       HostCmd_CMD_INDEPENDENT_RESET_CFG,
4650 			       cmd_action, 0,
4651 			       (t_void *)pioctl_req,
4652 			       (t_void *)&misc->param.ind_rst_cfg);
4653 
4654 	if (ret == MLAN_STATUS_SUCCESS)
4655 		ret = MLAN_STATUS_PENDING;
4656 
4657 	LEAVE();
4658 	return ret;
4659 }
4660 
4661 /**
4662  *  @brief  Get timestamp from firmware
4663  *
4664  *  @param pmadapter	A pointer to mlan_adapter structure
4665  *  @param pioctl_req	A pointer to ioctl request buffer
4666  *
4667  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
4668  */
4669 mlan_status
wlan_misc_ioctl_get_tsf(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4670 wlan_misc_ioctl_get_tsf(IN pmlan_adapter pmadapter,
4671 			IN pmlan_ioctl_req pioctl_req)
4672 {
4673 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4674 	mlan_status ret = MLAN_STATUS_SUCCESS;
4675 	t_u16 cmd_action = 0;
4676 
4677 	ENTER();
4678 
4679 	if (pioctl_req->action == MLAN_ACT_GET)
4680 		cmd_action = HostCmd_ACT_GEN_GET;
4681 	else {
4682 		PRINTM(MERROR, "No support set tsf!");
4683 		return MLAN_STATUS_FAILURE;
4684 	}
4685 
4686 	/* Send request to firmware */
4687 	ret = wlan_prepare_cmd(pmpriv,
4688 			       HostCmd_CMD_GET_TSF,
4689 			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
4690 
4691 	if (ret == MLAN_STATUS_SUCCESS)
4692 		ret = MLAN_STATUS_PENDING;
4693 
4694 	LEAVE();
4695 	return ret;
4696 }
4697 
4698 /**
4699  *  @brief  Create custom regulatory cfg
4700  *
4701  *  @param pmadapter	A pointer to mlan_adapter structure
4702  *  @param pioctl_req	A pointer to ioctl request buffer
4703  *
4704  *  @return		MLAN_STATUS_PENDING --success, otherwise fail
4705  */
4706 mlan_status
wlan_misc_chan_reg_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4707 wlan_misc_chan_reg_cfg(IN pmlan_adapter pmadapter,
4708 		       IN pmlan_ioctl_req pioctl_req)
4709 {
4710 	mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4711 	mlan_status ret = MLAN_STATUS_SUCCESS;
4712 	t_u16 cmd_action = 0;
4713 
4714 	ENTER();
4715 
4716 	if (pioctl_req->action == MLAN_ACT_GET)
4717 		cmd_action = HostCmd_ACT_GEN_GET;
4718 	else {
4719 		PRINTM(MERROR, "No support set channel region cfg!");
4720 		return MLAN_STATUS_FAILURE;
4721 	}
4722 
4723 	/* Send request to firmware */
4724 	ret = wlan_prepare_cmd(pmpriv,
4725 			       HostCmd_CMD_CHAN_REGION_CFG,
4726 			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
4727 
4728 	if (ret == MLAN_STATUS_SUCCESS)
4729 		ret = MLAN_STATUS_PENDING;
4730 
4731 	LEAVE();
4732 	return ret;
4733 }
4734 
4735 /**
4736  *  @brief Check operating class validation
4737  *
4738  *  @param pmadapter    A pointer to mlan_adapter structure
4739  *  @param pioctl_req   Pointer to the IOCTL request buffer
4740  *
4741  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4742  */
4743 mlan_status
wlan_misc_ioctl_operclass_validation(IN pmlan_adapter pmadapter,IN mlan_ioctl_req * pioctl_req)4744 wlan_misc_ioctl_operclass_validation(IN pmlan_adapter pmadapter,
4745 				     IN mlan_ioctl_req *pioctl_req)
4746 {
4747 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4748 	mlan_ds_misc_cfg *misc = MNULL;
4749 	t_u8 channel, oper_class;
4750 	mlan_status ret = MLAN_STATUS_SUCCESS;
4751 
4752 	ENTER();
4753 
4754 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4755 	channel = misc->param.bw_chan_oper.channel;
4756 	oper_class = misc->param.bw_chan_oper.oper_class;
4757 	if (pioctl_req->action == MLAN_ACT_GET) {
4758 		ret = wlan_check_operclass_validation(pmpriv, channel,
4759 						      oper_class);
4760 	} else {
4761 		PRINTM(MERROR, "Unsupported cmd_action\n");
4762 		LEAVE();
4763 		return MLAN_STATUS_FAILURE;
4764 	}
4765 
4766 	LEAVE();
4767 	return ret;
4768 }
4769 
4770 /**
4771  *  @brief Get non-global operating class
4772  *
4773  *  @param pmadapter    A pointer to mlan_adapter structure
4774  *  @param pioctl_req   Pointer to the IOCTL request buffer
4775  *
4776  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4777  */
4778 mlan_status
wlan_misc_ioctl_oper_class(IN pmlan_adapter pmadapter,IN mlan_ioctl_req * pioctl_req)4779 wlan_misc_ioctl_oper_class(IN pmlan_adapter pmadapter,
4780 			   IN mlan_ioctl_req *pioctl_req)
4781 {
4782 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4783 	mlan_ds_misc_cfg *misc = MNULL;
4784 	t_u8 channel, bandwidth, oper_class;
4785 	mlan_status ret = MLAN_STATUS_SUCCESS;
4786 
4787 	ENTER();
4788 
4789 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4790 	channel = misc->param.bw_chan_oper.channel;
4791 	switch (misc->param.bw_chan_oper.bandwidth) {
4792 	case 20:
4793 		bandwidth = BW_20MHZ;
4794 		break;
4795 	case 40:
4796 		bandwidth = BW_40MHZ;
4797 		break;
4798 	case 80:
4799 		bandwidth = BW_80MHZ;
4800 		break;
4801 	default:
4802 		bandwidth = BW_20MHZ;
4803 		break;
4804 	}
4805 
4806 	if (pioctl_req->action == MLAN_ACT_GET) {
4807 		ret = wlan_get_curr_oper_class(pmpriv, channel, bandwidth,
4808 					       &oper_class);
4809 		misc->param.bw_chan_oper.oper_class = oper_class;
4810 	} else {
4811 		PRINTM(MERROR, "Unsupported cmd_action\n");
4812 		LEAVE();
4813 		return MLAN_STATUS_FAILURE;
4814 	}
4815 
4816 	LEAVE();
4817 	return ret;
4818 }
4819 
4820 /**
4821  *  @brief config dynamic bandwidth
4822  *
4823  *  @param pmadapter    A pointer to mlan_adapter structure
4824  *  @param pioctl_req   Pointer to the IOCTL request buffer
4825  *
4826  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4827  */
4828 mlan_status
wlan_misc_ioctl_fw_dump_event(IN pmlan_adapter pmadapter,IN mlan_ioctl_req * pioctl_req)4829 wlan_misc_ioctl_fw_dump_event(IN pmlan_adapter pmadapter,
4830 			      IN mlan_ioctl_req *pioctl_req)
4831 {
4832 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4833 	mlan_ds_misc_cfg *misc = MNULL;
4834 	t_u16 cmd_action = 0;
4835 	mlan_status ret = MLAN_STATUS_SUCCESS;
4836 
4837 	ENTER();
4838 
4839 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4840 
4841 	if (pioctl_req->action == MLAN_ACT_SET)
4842 		cmd_action = HostCmd_ACT_GEN_SET;
4843 	else if (pioctl_req->action == MLAN_ACT_GET)
4844 		cmd_action = HostCmd_ACT_GEN_GET;
4845 	else {
4846 		PRINTM(MERROR, "Unsupported cmd_action\n");
4847 		LEAVE();
4848 		return MLAN_STATUS_FAILURE;
4849 	}
4850 
4851 	/* Send request to firmware */
4852 	ret = wlan_prepare_cmd(pmpriv,
4853 			       HostCmd_CMD_FW_DUMP_EVENT,
4854 			       cmd_action, 0, (t_void *)pioctl_req, MNULL);
4855 
4856 	if (ret == MLAN_STATUS_SUCCESS)
4857 		ret = MLAN_STATUS_PENDING;
4858 
4859 	LEAVE();
4860 	return ret;
4861 }
4862 
4863 /**
4864  *  @brief Set/Get the network monitor configuration.
4865  *
4866  *  @param pmadapter    A pointer to mlan_adapter structure
4867  *  @param pioctl_req   A pointer to ioctl request buffer
4868  *
4869  *  @return             MLAN_STATUS_PENDING --success, otherwise fail
4870  */
4871 mlan_status
wlan_misc_ioctl_net_monitor(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4872 wlan_misc_ioctl_net_monitor(IN pmlan_adapter pmadapter,
4873 			    IN pmlan_ioctl_req pioctl_req)
4874 {
4875 	mlan_private *pmpriv;
4876 	mlan_ds_misc_cfg *misc;
4877 	mlan_status ret = MLAN_STATUS_SUCCESS;
4878 	t_u16 cmd_action = 0;
4879 
4880 	ENTER();
4881 
4882 	if (!pioctl_req) {
4883 		LEAVE();
4884 		return MLAN_STATUS_FAILURE;
4885 	}
4886 	pmpriv = pmadapter->priv[pioctl_req->bss_index];
4887 
4888 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4889 
4890 	if (misc->param.net_mon.enable_net_mon == CHANNEL_SPEC_SNIFFER_MODE) {
4891 		/* Net monitor IOCTL not allowed in connected state */
4892 		if (pmpriv->media_connected == MTRUE) {
4893 			PRINTM(MERROR,
4894 			       "IOCTL not allowed in connected state\n");
4895 			pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
4896 			LEAVE();
4897 			return MLAN_STATUS_FAILURE;
4898 		}
4899 	}
4900 
4901 	if (pioctl_req->action == MLAN_ACT_SET)
4902 		cmd_action = HostCmd_ACT_GEN_SET;
4903 	else
4904 		cmd_action = HostCmd_ACT_GEN_GET;
4905 
4906 	/* Send command to firmware */
4907 	ret = wlan_prepare_cmd(pmpriv,
4908 			       HostCmd_CMD_802_11_NET_MONITOR,
4909 			       cmd_action,
4910 			       0, (t_void *)pioctl_req, &misc->param.net_mon);
4911 
4912 	if (ret == MLAN_STATUS_SUCCESS)
4913 		ret = MLAN_STATUS_PENDING;
4914 
4915 	LEAVE();
4916 	return ret;
4917 }
4918 
4919 /**
4920  *  @brief config boot sleep
4921  *
4922  *  @param pmadapter    A pointer to mlan_adapter structure
4923  *  @param pioctl_req   Pointer to the IOCTL request buffer
4924  *
4925  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4926  */
4927 mlan_status
wlan_misc_bootsleep(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4928 wlan_misc_bootsleep(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
4929 {
4930 	pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4931 	mlan_ds_misc_cfg *misc = MNULL;
4932 	t_u16 cmd_action = 0;
4933 	mlan_status ret = MLAN_STATUS_SUCCESS;
4934 
4935 	ENTER();
4936 
4937 	misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4938 
4939 	if (pioctl_req->action == MLAN_ACT_SET)
4940 		cmd_action = HostCmd_ACT_GEN_SET;
4941 	else if (pioctl_req->action == MLAN_ACT_GET)
4942 		cmd_action = HostCmd_ACT_GEN_GET;
4943 	else {
4944 		PRINTM(MERROR, "Unsupported cmd_action 0x%x\n",
4945 		       pioctl_req->action);
4946 		LEAVE();
4947 		return MLAN_STATUS_FAILURE;
4948 	}
4949 
4950 	/* Send request to firmware */
4951 	ret = wlan_prepare_cmd(pmpriv,
4952 			       HostCmd_CMD_BOOT_SLEEP,
4953 			       cmd_action,
4954 			       0,
4955 			       (t_void *)pioctl_req, &misc->param.boot_sleep);
4956 
4957 	if (ret == MLAN_STATUS_SUCCESS)
4958 		ret = MLAN_STATUS_PENDING;
4959 
4960 	LEAVE();
4961 	return ret;
4962 }
4963