xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlan/mlan_cmdevt.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /**
2  * @file mlan_cmdevt.c
3  *
4  *  @brief This file contains the handling of CMD/EVENT in MLAN
5  *
6  *
7  *  Copyright 2009-2022 NXP
8  *
9  *  This software file (the File) is distributed by NXP
10  *  under the terms of the GNU General Public License Version 2, June 1991
11  *  (the License).  You may use, redistribute and/or modify the File in
12  *  accordance with the terms and conditions of the License, a copy of which
13  *  is available by writing to the Free Software Foundation, Inc.,
14  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
15  *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
16  *
17  *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
20  *  this warranty disclaimer.
21  *
22  */
23 
24 /*************************************************************
25 Change Log:
26     05/12/2009: initial version
27 ************************************************************/
28 #include "mlan.h"
29 #ifdef STA_SUPPORT
30 #include "mlan_join.h"
31 #endif
32 #include "mlan_util.h"
33 #include "mlan_fw.h"
34 #include "mlan_main.h"
35 #include "mlan_wmm.h"
36 #include "mlan_11n.h"
37 #include "mlan_11ac.h"
38 #include "mlan_11ax.h"
39 #include "mlan_11h.h"
40 #ifdef SDIO
41 #include "mlan_sdio.h"
42 #endif /* SDIO */
43 #ifdef PCIE
44 #include "mlan_pcie.h"
45 #endif /* PCIE */
46 #include "mlan_init.h"
47 
48 /********************************************************
49 			Local Variables
50 ********************************************************/
51 
52 /*******************************************************
53 			Global Variables
54 ********************************************************/
55 
56 /********************************************************
57 			Local Functions
58 ********************************************************/
59 #ifdef STA_SUPPORT
60 /**
61  *  @brief This function check if the command was cancel scan command
62  *
63  *  @param pcmd    A pointer to HostCmd_DS_COMMAND structure
64  *  @return        N/A
65  */
wlan_is_cancel_scan_cmd(HostCmd_DS_COMMAND * pcmd)66 static t_u8 wlan_is_cancel_scan_cmd(HostCmd_DS_COMMAND *pcmd)
67 {
68 	HostCmd_DS_802_11_SCAN_EXT *pext_scan_cmd = &pcmd->params.ext_scan;
69 	if (pext_scan_cmd->ext_scan_type == EXT_SCAN_CANCEL)
70 		return MTRUE;
71 	else
72 		return MFALSE;
73 }
74 /**
75  *  @brief This function inserts scan command node to scan_pending_q.
76  *
77  *  @param pmpriv       A pointer to mlan_private structure
78  *  @param pcmd_node    A pointer to cmd_ctrl_node structure
79  *  @return             N/A
80  */
wlan_queue_scan_cmd(mlan_private * pmpriv,cmd_ctrl_node * pcmd_node)81 static t_void wlan_queue_scan_cmd(mlan_private *pmpriv,
82 				  cmd_ctrl_node *pcmd_node)
83 {
84 	mlan_adapter *pmadapter = pmpriv->adapter;
85 
86 	ENTER();
87 
88 	if (pcmd_node == MNULL)
89 		goto done;
90 	pcmd_node->cmd_flag |= CMD_F_SCAN;
91 
92 	util_enqueue_list_tail(pmadapter->pmoal_handle,
93 			       &pmadapter->scan_pending_q,
94 			       (pmlan_linked_list)pcmd_node, MNULL, MNULL);
95 
96 done:
97 	LEAVE();
98 }
99 
100 /**
101  *  @brief This function check if cmd allowed to send to firmware
102  *         during scan
103  *
104  *  @param cmd_id     cmd id
105  *
106  *  @return           MTRUE/MFALSE
107  */
wlan_is_cmd_allowed_during_scan(t_u16 cmd_id)108 static t_u8 wlan_is_cmd_allowed_during_scan(t_u16 cmd_id)
109 {
110 	t_u8 ret = MTRUE;
111 	ENTER();
112 	switch (cmd_id) {
113 	case HostCmd_CMD_FUNC_INIT:
114 	case HostCmd_CMD_CFG_DATA:
115 	case HostCmd_CMD_REGION_POWER_CFG:
116 	case HostCmd_CHANNEL_TRPC_CONFIG:
117 	case HostCmd_CMD_FUNC_SHUTDOWN:
118 	case HostCmd_CMD_802_11_ASSOCIATE:
119 	case HostCmd_CMD_802_11_DEAUTHENTICATE:
120 	case HostCmd_CMD_802_11_DISASSOCIATE:
121 	case HostCmd_CMD_802_11_AD_HOC_START:
122 	case HostCmd_CMD_802_11_AD_HOC_JOIN:
123 	case HostCmd_CMD_802_11_AD_HOC_STOP:
124 	case HostCmd_CMD_11N_ADDBA_REQ:
125 	case HostCmd_CMD_11N_ADDBA_RSP:
126 	case HostCmd_CMD_11N_DELBA:
127 	case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
128 	case HostCmd_CMD_TDLS_CONFIG:
129 	case HostCmd_CMD_TDLS_OPERATION:
130 	case HostCmd_CMD_SOFT_RESET:
131 #ifdef UAP_SUPPORT
132 	case HOST_CMD_APCMD_SYS_RESET:
133 	case HOST_CMD_APCMD_BSS_START:
134 	case HOST_CMD_APCMD_BSS_STOP:
135 	case HOST_CMD_APCMD_STA_DEAUTH:
136 #endif
137 	case HostCmd_CMD_802_11_BG_SCAN_CONFIG:
138 	case HostCMD_APCMD_ACS_SCAN:
139 		ret = MFALSE;
140 		break;
141 	default:
142 		break;
143 	}
144 	LEAVE();
145 	return ret;
146 }
147 
148 /**
149  *  @brief This function move the cmd from ext_cmd_pending_q to
150  *        cmd_pending_q
151  *
152  *  @param cmd_id     cmd id
153  *
154  *  @return           MTRUE/MFALSE
155  */
wlan_move_cmd_to_cmd_pending_q(pmlan_adapter pmadapter)156 t_void wlan_move_cmd_to_cmd_pending_q(pmlan_adapter pmadapter)
157 {
158 	cmd_ctrl_node *pcmd_node = MNULL;
159 
160 	ENTER();
161 
162 	wlan_request_cmd_lock(pmadapter);
163 	while ((pcmd_node = (cmd_ctrl_node *)util_peek_list(
164 			pmadapter->pmoal_handle, &pmadapter->ext_cmd_pending_q,
165 			MNULL, MNULL))) {
166 		util_unlink_list(pmadapter->pmoal_handle,
167 				 &pmadapter->ext_cmd_pending_q,
168 				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
169 		wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node, MTRUE);
170 	}
171 	wlan_release_cmd_lock(pmadapter);
172 	LEAVE();
173 }
174 
175 /**
176  *  @brief This function inserts scan command node to scan_cmd_pending_q.
177  *
178  *  @param pmpriv       A pointer to mlan_private structure
179  *  @param pcmd_node    A pointer to cmd_ctrl_node structure
180  *  @return             N/A
181  */
wlan_queue_cmd_to_ext_cmd_pending_queue(mlan_private * pmpriv,cmd_ctrl_node * pcmd_node)182 static t_void wlan_queue_cmd_to_ext_cmd_pending_queue(mlan_private *pmpriv,
183 						      cmd_ctrl_node *pcmd_node)
184 {
185 	mlan_adapter *pmadapter = pmpriv->adapter;
186 
187 	ENTER();
188 
189 	if (pcmd_node == MNULL)
190 		goto done;
191 
192 	util_enqueue_list_tail(pmadapter->pmoal_handle,
193 			       &pmadapter->ext_cmd_pending_q,
194 			       (pmlan_linked_list)pcmd_node, MNULL, MNULL);
195 
196 done:
197 	LEAVE();
198 }
199 
200 /**
201  *  @brief Internal function used to flush the scan cmd pending queue
202  *
203  *  @param pmadapter    A pointer to mlan_adapter structure
204  *
205  *  @return             N/A
206  */
wlan_flush_ext_cmd_pending_queue(pmlan_adapter pmadapter)207 t_void wlan_flush_ext_cmd_pending_queue(pmlan_adapter pmadapter)
208 {
209 	cmd_ctrl_node *pcmd_node = MNULL;
210 	HostCmd_DS_COMMAND *pcmd = MNULL;
211 	mlan_ioctl_req *pioctl_buf = MNULL;
212 	pmlan_callbacks pcb = &pmadapter->callbacks;
213 	ENTER();
214 
215 	wlan_request_cmd_lock(pmadapter);
216 	while ((pcmd_node = (cmd_ctrl_node *)util_peek_list(
217 			pmadapter->pmoal_handle, &pmadapter->ext_cmd_pending_q,
218 			MNULL, MNULL))) {
219 		util_unlink_list(pmadapter->pmoal_handle,
220 				 &pmadapter->ext_cmd_pending_q,
221 				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
222 		pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
223 					      pcmd_node->cmdbuf->data_offset);
224 		PRINTM(MCMND, "flush ext_cmd_pending_queue: cmd 0x%02x\n",
225 		       wlan_le16_to_cpu(pcmd->command));
226 		if (pcmd_node->pioctl_buf) {
227 			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
228 			pcmd_node->pioctl_buf = MNULL;
229 			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
230 			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
231 						 pioctl_buf,
232 						 MLAN_STATUS_FAILURE);
233 		}
234 		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
235 	}
236 	wlan_release_cmd_lock(pmadapter);
237 	LEAVE();
238 }
239 
240 /**
241  *  @brief This function inserts command node to scan_pending_q or
242  *  cmd_pending_q
243  *
244  *  @param pmpriv       A pointer to mlan_private structure
245  *  @param pcmd_node    A pointer to cmd_ctrl_node structure
246  *  @return             N/A
247  */
248 
wlan_queue_cmd(mlan_private * pmpriv,cmd_ctrl_node * pcmd_node,t_u16 cmd_no)249 static t_void wlan_queue_cmd(mlan_private *pmpriv, cmd_ctrl_node *pcmd_node,
250 			     t_u16 cmd_no)
251 {
252 	ENTER();
253 	if (pmpriv->adapter->scan_processing &&
254 	    pmpriv->adapter->ext_scan_type == EXT_SCAN_ENHANCE) {
255 		if (MFALSE == wlan_is_cmd_allowed_during_scan(cmd_no)) {
256 			PRINTM(MCMND, "QUEUE_CMD: cmd=0x%x ext_cmd_pending_q\n",
257 			       cmd_no);
258 			wlan_queue_cmd_to_ext_cmd_pending_queue(pmpriv,
259 								pcmd_node);
260 			return;
261 		}
262 	}
263 	wlan_insert_cmd_to_pending_q(pmpriv->adapter, pcmd_node, MTRUE);
264 	LEAVE();
265 }
266 
267 /**
268  *  @brief Internal function used to flush the scan pending queue
269  *
270  *  @param pmadapter    A pointer to mlan_adapter structure
271  *
272  *  @return             N/A
273  */
wlan_check_scan_queue(pmlan_adapter pmadapter)274 static void wlan_check_scan_queue(pmlan_adapter pmadapter)
275 {
276 	cmd_ctrl_node *pcmd_node = MNULL;
277 	t_u16 num = 0;
278 
279 	pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
280 						    &pmadapter->scan_pending_q,
281 						    MNULL, MNULL);
282 	if (!pcmd_node) {
283 		PRINTM(MERROR, "No pending scan command\n");
284 		return;
285 	}
286 	while (pcmd_node != (cmd_ctrl_node *)&pmadapter->scan_pending_q) {
287 		num++;
288 		pcmd_node = pcmd_node->pnext;
289 	}
290 	PRINTM(MERROR, "num_pending_scan=%d\n", num);
291 }
292 #endif
293 
294 /**
295  *  @brief This function will dump the pending commands id
296  *
297  *  @param pmadapter    A pointer to mlan_adapter
298  *
299  *  @return             N/A
300  */
wlan_dump_pending_commands(pmlan_adapter pmadapter)301 static void wlan_dump_pending_commands(pmlan_adapter pmadapter)
302 {
303 	cmd_ctrl_node *pcmd_node = MNULL;
304 	HostCmd_DS_COMMAND *pcmd;
305 
306 	ENTER();
307 	wlan_request_cmd_lock(pmadapter);
308 	pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
309 						    &pmadapter->cmd_pending_q,
310 						    MNULL, MNULL);
311 	if (!pcmd_node) {
312 		wlan_release_cmd_lock(pmadapter);
313 		LEAVE();
314 		return;
315 	}
316 	while (pcmd_node != (cmd_ctrl_node *)&pmadapter->cmd_pending_q) {
317 		pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
318 					      pcmd_node->cmdbuf->data_offset);
319 		PRINTM(MERROR, "pending command id: 0x%x ioctl_buf=%p\n",
320 		       wlan_le16_to_cpu(pcmd->command), pcmd_node->pioctl_buf);
321 		pcmd_node = pcmd_node->pnext;
322 	}
323 #ifdef STA_SUPPORT
324 	wlan_check_scan_queue(pmadapter);
325 #endif
326 	wlan_release_cmd_lock(pmadapter);
327 	LEAVE();
328 	return;
329 }
330 
331 #define REASON_CODE_NO_CMD_NODE 1
332 #define REASON_CODE_CMD_TIMEOUT 2
333 #define REASON_CODE_CMD_TO_CARD_FAILURE 3
334 #define REASON_CODE_EXT_SCAN_TIMEOUT 4
335 /**
336  *  @brief This function dump debug info
337  *
338  *  @return     N/A
339  */
wlan_dump_info(mlan_adapter * pmadapter,t_u8 reason)340 static t_void wlan_dump_info(mlan_adapter *pmadapter, t_u8 reason)
341 {
342 	cmd_ctrl_node *pcmd_node = MNULL;
343 #ifdef DEBUG_LEVEL1
344 	t_u32 sec = 0, usec = 0;
345 #endif
346 	t_u16 i;
347 #ifdef SDIO
348 	t_u8 j;
349 	t_u8 mp_aggr_pkt_limit;
350 #endif
351 	t_u16 cmd_id, cmd_act;
352 	mlan_private *pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
353 
354 	ENTER();
355 
356 	PRINTM(MERROR, "------------Dump info-----------\n", reason);
357 	switch (reason) {
358 	case REASON_CODE_NO_CMD_NODE:
359 		pmadapter->dbg.num_no_cmd_node++;
360 		PRINTM(MERROR, "No Free command node\n");
361 		break;
362 	case REASON_CODE_CMD_TIMEOUT:
363 		PRINTM(MERROR, "Commmand Timeout\n");
364 		break;
365 	case REASON_CODE_CMD_TO_CARD_FAILURE:
366 		PRINTM(MERROR, "Command to card failure\n");
367 		break;
368 	case REASON_CODE_EXT_SCAN_TIMEOUT:
369 		PRINTM(MERROR, "EXT_SCAN_STATUS event Timeout\n");
370 		break;
371 	default:
372 		break;
373 	}
374 	if ((reason == REASON_CODE_NO_CMD_NODE) &&
375 	    (pmadapter->dbg.num_no_cmd_node > 1)) {
376 		if (pmadapter->dbg.num_no_cmd_node >= 5) {
377 			if (pmpriv)
378 				wlan_recv_event(pmpriv,
379 						MLAN_EVENT_ID_DRV_DBG_DUMP,
380 						MNULL);
381 		}
382 		LEAVE();
383 		return;
384 	}
385 	wlan_dump_pending_commands(pmadapter);
386 	if (reason != REASON_CODE_CMD_TIMEOUT) {
387 		if (!pmadapter->curr_cmd) {
388 			PRINTM(MERROR, "CurCmd Empty\n");
389 		} else {
390 			pcmd_node = pmadapter->curr_cmd;
391 			cmd_id = pmadapter->dbg.last_cmd_id
392 					 [pmadapter->dbg.last_cmd_index];
393 			cmd_act = pmadapter->dbg.last_cmd_act
394 					  [pmadapter->dbg.last_cmd_index];
395 			PRINTM_GET_SYS_TIME(MERROR, &sec, &usec);
396 			PRINTM(MERROR,
397 			       "Current cmd id (%lu.%06lu) = 0x%x, act = 0x%x\n",
398 			       sec, usec, cmd_id, cmd_act);
399 #if defined(SDIO) || defined(PCIE)
400 			if (!IS_USB(pmadapter->card_type) &&
401 			    pcmd_node->cmdbuf) {
402 				t_u8 *pcmd_buf;
403 				pcmd_buf = pcmd_node->cmdbuf->pbuf +
404 					   pcmd_node->cmdbuf->data_offset +
405 					   pmadapter->ops.intf_header_len;
406 				for (i = 0; i < 16; i++)
407 					PRINTM(MERROR, "%02x ", *pcmd_buf++);
408 				PRINTM(MERROR, "\n");
409 			}
410 #endif
411 			pmpriv = pcmd_node->priv;
412 			if (pmpriv)
413 				PRINTM(MERROR, "BSS type = %d BSS role= %d\n",
414 				       pmpriv->bss_type, pmpriv->bss_role);
415 		}
416 	}
417 	PRINTM(MERROR, "mlan_processing =%d\n", pmadapter->mlan_processing);
418 	PRINTM(MERROR, "main_lock_flag =%d\n", pmadapter->main_lock_flag);
419 	PRINTM(MERROR, "main_process_cnt =%d\n", pmadapter->main_process_cnt);
420 	PRINTM(MERROR, "delay_task_flag =%d\n", pmadapter->delay_task_flag);
421 	PRINTM(MERROR, "mlan_rx_processing =%d\n",
422 	       pmadapter->mlan_rx_processing);
423 	PRINTM(MERROR, "rx_pkts_queued=%d\n", pmadapter->rx_pkts_queued);
424 	PRINTM(MERROR, "more_task_flag = %d\n", pmadapter->more_task_flag);
425 	PRINTM(MERROR, "num_cmd_timeout = %d\n", pmadapter->num_cmd_timeout);
426 	PRINTM(MERROR, "last_cmd_index = %d\n", pmadapter->dbg.last_cmd_index);
427 	PRINTM(MERROR, "last_cmd_id = ");
428 	for (i = 0; i < DBG_CMD_NUM; i++)
429 		PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_id[i]);
430 	PRINTM(MERROR, "\n");
431 	PRINTM(MERROR, "last_cmd_act = ");
432 	for (i = 0; i < DBG_CMD_NUM; i++)
433 		PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_act[i]);
434 	PRINTM(MERROR, "\n");
435 	PRINTM(MERROR, "last_cmd_resp_index = %d\n",
436 	       pmadapter->dbg.last_cmd_resp_index);
437 	PRINTM(MERROR, "last_cmd_resp_id = ");
438 	for (i = 0; i < DBG_CMD_NUM; i++)
439 		PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_resp_id[i]);
440 	PRINTM(MERROR, "\n");
441 	PRINTM(MERROR, "last_event_index = %d\n",
442 	       pmadapter->dbg.last_event_index);
443 	PRINTM(MERROR, "last_event = ");
444 	for (i = 0; i < DBG_CMD_NUM; i++)
445 		PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_event[i]);
446 	PRINTM(MERROR, "\n");
447 
448 	PRINTM(MERROR, "num_data_h2c_failure = %d\n",
449 	       pmadapter->dbg.num_tx_host_to_card_failure);
450 	PRINTM(MERROR, "num_cmd_h2c_failure = %d\n",
451 	       pmadapter->dbg.num_cmd_host_to_card_failure);
452 #ifdef SDIO
453 	if (IS_SD(pmadapter->card_type)) {
454 		PRINTM(MERROR, "num_data_c2h_failure = %d\n",
455 		       pmadapter->dbg.num_rx_card_to_host_failure);
456 		PRINTM(MERROR, "num_cmdevt_c2h_failure = %d\n",
457 		       pmadapter->dbg.num_cmdevt_card_to_host_failure);
458 		PRINTM(MERROR, "num_int_read_failure = %d\n",
459 		       pmadapter->dbg.num_int_read_failure);
460 		PRINTM(MERROR, "last_int_status = %d\n",
461 		       pmadapter->dbg.last_int_status);
462 	}
463 #endif
464 	PRINTM(MERROR, "num_alloc_buffer_failure = %d\n",
465 	       pmadapter->dbg.num_alloc_buffer_failure);
466 	PRINTM(MERROR, "num_pkt_dropped = %d\n",
467 	       pmadapter->dbg.num_pkt_dropped);
468 	PRINTM(MERROR, "num_no_cmd_node = %d\n",
469 	       pmadapter->dbg.num_no_cmd_node);
470 	PRINTM(MERROR, "num_event_deauth = %d\n",
471 	       pmadapter->dbg.num_event_deauth);
472 	PRINTM(MERROR, "num_event_disassoc = %d\n",
473 	       pmadapter->dbg.num_event_disassoc);
474 	PRINTM(MERROR, "num_event_link_lost = %d\n",
475 	       pmadapter->dbg.num_event_link_lost);
476 	PRINTM(MERROR, "num_cmd_deauth = %d\n", pmadapter->dbg.num_cmd_deauth);
477 	PRINTM(MERROR, "num_cmd_assoc_success = %d\n",
478 	       pmadapter->dbg.num_cmd_assoc_success);
479 	PRINTM(MERROR, "num_cmd_assoc_failure = %d\n",
480 	       pmadapter->dbg.num_cmd_assoc_failure);
481 	PRINTM(MERROR, "num_cons_assoc_failure = %d\n",
482 	       pmadapter->dbg.num_cons_assoc_failure);
483 	PRINTM(MERROR, "cmd_resp_received=%d\n", pmadapter->cmd_resp_received);
484 	PRINTM(MERROR, "event_received=%d\n", pmadapter->event_received);
485 
486 	PRINTM(MERROR, "max_tx_buf_size=%d\n", pmadapter->max_tx_buf_size);
487 	PRINTM(MERROR, "tx_buf_size=%d\n", pmadapter->tx_buf_size);
488 	PRINTM(MERROR, "curr_tx_buf_size=%d\n", pmadapter->curr_tx_buf_size);
489 
490 	PRINTM(MERROR, "data_sent=%d cmd_sent=%d\n", pmadapter->data_sent,
491 	       pmadapter->cmd_sent);
492 
493 	PRINTM(MERROR, "ps_mode=%d ps_state=%d\n", pmadapter->ps_mode,
494 	       pmadapter->ps_state);
495 	PRINTM(MERROR, "wakeup_dev_req=%d wakeup_tries=%d wakeup_timeout=%d\n",
496 	       pmadapter->pm_wakeup_card_req, pmadapter->pm_wakeup_fw_try,
497 	       pmadapter->pm_wakeup_timeout);
498 	PRINTM(MERROR, "hs_configured=%d hs_activated=%d\n",
499 	       pmadapter->is_hs_configured, pmadapter->hs_activated);
500 	PRINTM(MERROR, "pps_uapsd_mode=%d sleep_pd=%d\n",
501 	       pmadapter->pps_uapsd_mode, pmadapter->sleep_period.period);
502 	PRINTM(MERROR, "tx_lock_flag = %d\n", pmadapter->tx_lock_flag);
503 	PRINTM(MERROR, "scan_processing = %d\n", pmadapter->scan_processing);
504 	PRINTM(MERROR, "scan_state = 0x%x\n", pmadapter->scan_state);
505 	PRINTM(MERROR, "bypass_pkt_count=%d\n", pmadapter->bypass_pkt_count);
506 #ifdef SDIO
507 	if (IS_SD(pmadapter->card_type)) {
508 		mp_aggr_pkt_limit = pmadapter->pcard_sd->mp_aggr_pkt_limit;
509 		PRINTM(MERROR, "mp_rd_bitmap=0x%x curr_rd_port=0x%x\n",
510 		       pmadapter->pcard_sd->mp_rd_bitmap,
511 		       pmadapter->pcard_sd->curr_rd_port);
512 		PRINTM(MERROR, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n",
513 		       pmadapter->pcard_sd->mp_wr_bitmap,
514 		       pmadapter->pcard_sd->curr_wr_port);
515 		PRINTM(MMSG, "mp_data_port_mask = 0x%x\n",
516 		       pmadapter->pcard_sd->mp_data_port_mask);
517 
518 		PRINTM(MERROR,
519 		       "last_recv_rd_bitmap=0x%x mp_invalid_update=%d\n",
520 		       pmadapter->pcard_sd->last_recv_rd_bitmap,
521 		       pmadapter->pcard_sd->mp_invalid_update);
522 		PRINTM(MERROR, "last_recv_wr_bitmap=0x%x last_mp_index=%d\n",
523 		       pmadapter->pcard_sd->last_recv_wr_bitmap,
524 		       pmadapter->pcard_sd->last_mp_index);
525 		for (i = 0; i < SDIO_MP_DBG_NUM; i++) {
526 			PRINTM(MERROR,
527 			       "mp_wr_bitmap: 0x%x mp_wr_ports=0x%x len=%d curr_wr_port=0x%x\n",
528 			       pmadapter->pcard_sd->last_mp_wr_bitmap[i],
529 			       pmadapter->pcard_sd->last_mp_wr_ports[i],
530 			       pmadapter->pcard_sd->last_mp_wr_len[i],
531 			       pmadapter->pcard_sd->last_curr_wr_port[i]);
532 			for (j = 0; j < mp_aggr_pkt_limit; j++) {
533 				PRINTM(MERROR, "0x%02x ",
534 				       pmadapter->pcard_sd->last_mp_wr_info
535 					       [i * mp_aggr_pkt_limit + j]);
536 			}
537 			PRINTM(MERROR, "\n");
538 		}
539 	}
540 #endif
541 #ifdef PCIE
542 	if (IS_PCIE(pmadapter->card_type)) {
543 		PRINTM(MERROR, "txbd_rdptr=0x%x txbd_wrptr=0x%x\n",
544 		       pmadapter->pcard_pcie->txbd_rdptr,
545 		       pmadapter->pcard_pcie->txbd_wrptr);
546 		PRINTM(MERROR, "rxbd_rdptr=0x%x rxbd_wrptr=0x%x\n",
547 		       pmadapter->pcard_pcie->rxbd_rdptr,
548 		       pmadapter->pcard_pcie->rxbd_wrptr);
549 		PRINTM(MERROR, "evtbd_rdptr=0x%x evt_wrptr=0x%x\n",
550 		       pmadapter->pcard_pcie->evtbd_rdptr,
551 		       pmadapter->pcard_pcie->evtbd_wrptr);
552 		PRINTM(MERROR, "last_wr_index:%d\n",
553 		       pmadapter->pcard_pcie->txbd_wrptr &
554 			       (pmadapter->pcard_pcie->txrx_bd_size - 1));
555 		PRINTM(MERROR, " txrx_bd_size = %d\n",
556 		       pmadapter->pcard_pcie->txrx_bd_size);
557 		PRINTM(MERROR, "Tx pkt size:\n");
558 		for (i = 0; i < pmadapter->pcard_pcie->txrx_bd_size; i++) {
559 			PRINTM(MERROR, "%04d ",
560 			       pmadapter->pcard_pcie->last_tx_pkt_size[i]);
561 			if (((i + 1) % 16) == 0)
562 				PRINTM(MERROR, "\n");
563 		}
564 	}
565 #endif
566 	for (i = 0; i < pmadapter->priv_num; ++i) {
567 		if (pmadapter->priv[i])
568 			wlan_dump_ralist(pmadapter->priv[i]);
569 	}
570 	if (reason != REASON_CODE_CMD_TIMEOUT) {
571 		if ((pmadapter->dbg.num_no_cmd_node >= 5) ||
572 		    (pmadapter->pm_wakeup_card_req &&
573 		     pmadapter->pm_wakeup_fw_try) ||
574 		    (reason == REASON_CODE_EXT_SCAN_TIMEOUT)) {
575 			if (pmpriv)
576 				wlan_recv_event(pmpriv,
577 						MLAN_EVENT_ID_DRV_DBG_DUMP,
578 						MNULL);
579 			else {
580 				pmpriv = wlan_get_priv(pmadapter,
581 						       MLAN_BSS_ROLE_ANY);
582 				if (pmpriv)
583 					wlan_recv_event(
584 						pmpriv,
585 						MLAN_EVENT_ID_DRV_DBG_DUMP,
586 						MNULL);
587 			}
588 		}
589 	}
590 	PRINTM(MERROR, "-------- Dump info End---------\n", reason);
591 	LEAVE();
592 	return;
593 }
594 
595 /**
596  *  @brief This function convert a given character to hex
597  *
598  *  @param chr        Character to be converted
599  *
600  *  @return           The converted hex if chr is a valid hex, else 0
601  */
wlan_hexval(t_u8 chr)602 static t_u32 wlan_hexval(t_u8 chr)
603 {
604 	if (chr >= '0' && chr <= '9')
605 		return chr - '0';
606 	if (chr >= 'A' && chr <= 'F')
607 		return chr - 'A' + 10;
608 	if (chr >= 'a' && chr <= 'f')
609 		return chr - 'a' + 10;
610 
611 	return 0;
612 }
613 
614 /**
615  *  @brief This function convert a given string to hex
616  *
617  *  @param a            A pointer to string to be converted
618  *
619  *  @return             The converted hex value if param a is a valid hex, else
620  * 0
621  */
wlan_atox(t_u8 * a)622 static int wlan_atox(t_u8 *a)
623 {
624 	int i = 0;
625 
626 	ENTER();
627 
628 	while (wlan_isxdigit(*a))
629 		i = i * 16 + wlan_hexval(*a++);
630 
631 	LEAVE();
632 	return i;
633 }
634 
635 /**
636  *  @brief This function parse cal data from ASCII to hex
637  *
638  *  @param src          A pointer to source data
639  *  @param len          Source data length
640  *  @param dst          A pointer to a buf to store the parsed data
641  *
642  *  @return             The parsed hex data length
643  */
wlan_parse_cal_cfg(t_u8 * src,t_size len,t_u8 * dst)644 static t_u32 wlan_parse_cal_cfg(t_u8 *src, t_size len, t_u8 *dst)
645 {
646 	t_u8 *ptr;
647 	t_u8 *dptr;
648 
649 	ENTER();
650 	ptr = src;
651 	dptr = dst;
652 
653 	while (ptr - src < len) {
654 		if (*ptr && (wlan_isspace(*ptr) || *ptr == '\t')) {
655 			ptr++;
656 			continue;
657 		}
658 
659 		if (wlan_isxdigit(*ptr)) {
660 			*dptr++ = wlan_atox(ptr);
661 			ptr += 2;
662 		} else {
663 			ptr++;
664 		}
665 	}
666 	LEAVE();
667 	return dptr - dst;
668 }
669 
670 /**
671  *  @brief This function finds first occurrence of a char in a string
672  *
673  *  @param s            A pointer to the string to be searched
674  *  @param c            The character to search for
675  *
676  *  @return             Location of the first occurrence of the char
677  *                      if found, else NULL
678  */
wlan_strchr(t_u8 * s,int c)679 static t_u8 *wlan_strchr(t_u8 *s, int c)
680 {
681 	t_u8 *pos = s;
682 	while (*pos != '\0') {
683 		if (*pos == (t_u8)c)
684 			return pos;
685 		pos++;
686 	}
687 	return MNULL;
688 }
689 
690 #define CFG_TYPE_HOSTCMD 0
691 #define CFG_TYPE_DPDFILE 1
692 
693 /**
694  *    @brief WOAL parse ASCII format raw data to hex format
695  *
696  *    @param pmpriv       MOAL handle
697  *    @param cfg_type     Conf file type
698  *    @param data         Source data
699  *    @param size         data length
700  *    @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
701  */
wlan_process_hostcmd_cfg(pmlan_private pmpriv,t_u16 cfg_type,t_u8 * data,t_size size)702 static t_u32 wlan_process_hostcmd_cfg(pmlan_private pmpriv, t_u16 cfg_type,
703 				      t_u8 *data, t_size size)
704 {
705 	mlan_status ret = MLAN_STATUS_SUCCESS;
706 	t_u8 *pos = data;
707 	t_u8 *intf_s, *intf_e;
708 	t_u8 *buf = MNULL;
709 	t_u8 *ptr = MNULL;
710 	t_u32 cmd_len = 0;
711 	t_u8 start_raw = MFALSE;
712 	mlan_ds_misc_cmd *hostcmd;
713 	HostCmd_DS_GEN *pcmd = MNULL;
714 	HostCmd_DS_802_11_CFG_DATA *pcfg_cmd = MNULL;
715 	mlan_adapter *pmadapter = MNULL;
716 	mlan_callbacks *pcb = MNULL;
717 	t_u8 hostcmd_flag = MFALSE;
718 
719 	ENTER();
720 	if (!pmpriv) {
721 		PRINTM(MERROR, "pmpriv is NULL\n");
722 		LEAVE();
723 		return MLAN_STATUS_FAILURE;
724 	}
725 	pmadapter = pmpriv->adapter;
726 	pcb = (mlan_callbacks *)&pmadapter->callbacks;
727 	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
728 			       sizeof(mlan_ds_misc_cmd), MLAN_MEM_DEF,
729 			       (t_u8 **)&hostcmd);
730 	if (ret || !hostcmd) {
731 		PRINTM(MERROR, "Could not allocate buffer space!\n");
732 		LEAVE();
733 		return ret;
734 	}
735 	buf = hostcmd->cmd;
736 	ptr = buf;
737 	while ((pos - data) < size) {
738 		while (*pos == ' ' || *pos == '\t')
739 			pos++;
740 		if (*pos == '#') { /* Line comment */
741 			while (*pos != '\n')
742 				pos++;
743 			pos++;
744 		}
745 		if ((*pos == '\r' && *(pos + 1) == '\n') || *pos == '\n' ||
746 		    *pos == '\0') {
747 			pos++;
748 			continue; /* Needn't process this line */
749 		}
750 
751 		if (*pos == '}') {
752 			if (cfg_type == CFG_TYPE_DPDFILE && pcmd) {
753 				/* Fill command head for DPD RAW data conf */
754 				hostcmd->len = ptr - buf;
755 				pcmd->command =
756 					wlan_cpu_to_le16(HostCmd_CMD_CFG_DATA);
757 				pcmd->size = wlan_cpu_to_le16(hostcmd->len);
758 				pcfg_cmd = (HostCmd_DS_802_11_CFG_DATA
759 						    *)((t_u8 *)pcmd + S_DS_GEN);
760 				pcfg_cmd->action =
761 					wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
762 				pcfg_cmd->type = wlan_cpu_to_le16(OID_TYPE_DPD);
763 				pcfg_cmd->data_len = wlan_cpu_to_le16(
764 					hostcmd->len - S_DS_GEN -
765 					sizeof(HostCmd_DS_802_11_CFG_DATA));
766 				pcmd = MNULL;
767 				pcfg_cmd = MNULL;
768 			} else {
769 				/* For hostcmd data conf */
770 				cmd_len = *((t_u16 *)(buf + sizeof(t_u16)));
771 				hostcmd->len = cmd_len;
772 			}
773 			ret = wlan_prepare_cmd(pmpriv, 0, 0, 0, MNULL,
774 					       (t_void *)hostcmd);
775 			memset(pmadapter, buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
776 			ptr = buf;
777 			start_raw = MFALSE;
778 			pos++;
779 			continue;
780 		}
781 
782 		if (start_raw == MFALSE) {
783 			intf_s = wlan_strchr(pos, '=');
784 			if (intf_s) {
785 				if (*(intf_s + 1) == '=')
786 					hostcmd_flag = MTRUE;
787 				intf_e = wlan_strchr(intf_s, '{');
788 			} else
789 				intf_e = MNULL;
790 
791 			if (intf_s && intf_e) {
792 				start_raw = MTRUE;
793 				pos = intf_e + 1;
794 				/* Reserve command head for DPD RAW data conf */
795 				if (cfg_type == CFG_TYPE_DPDFILE &&
796 				    !hostcmd_flag) {
797 					pcmd = (HostCmd_DS_GEN *)ptr;
798 					ptr += S_DS_GEN +
799 					       sizeof(HostCmd_DS_802_11_CFG_DATA);
800 				}
801 				continue;
802 			}
803 		}
804 
805 		if (start_raw) {
806 			/* Raw data block exists */
807 			while (*pos != '\n') {
808 				if ((*pos <= 'f' && *pos >= 'a') ||
809 				    (*pos <= 'F' && *pos >= 'A') ||
810 				    (*pos <= '9' && *pos >= '0')) {
811 					*ptr++ = wlan_atox(pos);
812 					pos += 2;
813 				} else
814 					pos++;
815 			}
816 		}
817 	}
818 	pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
819 	LEAVE();
820 	return ret;
821 }
822 
823 /**
824  *  @brief This function initializes the command node.
825  *
826  *  @param pmpriv       A pointer to mlan_private structure
827  *  @param pcmd_node    A pointer to cmd_ctrl_node structure
828  *  @param cmd_no       cmd id
829  *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
830  *  @param pdata_buf    A pointer to information buffer
831  *
832  *  @return             N/A
833  */
wlan_init_cmd_node(pmlan_private pmpriv,cmd_ctrl_node * pcmd_node,t_u32 cmd_no,t_void * pioctl_buf,t_void * pdata_buf)834 static void wlan_init_cmd_node(pmlan_private pmpriv, cmd_ctrl_node *pcmd_node,
835 			       t_u32 cmd_no, t_void *pioctl_buf,
836 			       t_void *pdata_buf)
837 {
838 	mlan_adapter *pmadapter = pmpriv->adapter;
839 
840 	ENTER();
841 
842 	if (pcmd_node == MNULL) {
843 		LEAVE();
844 		return;
845 	}
846 	pcmd_node->priv = pmpriv;
847 	pcmd_node->cmd_no = cmd_no;
848 	pcmd_node->pioctl_buf = pioctl_buf;
849 	pcmd_node->pdata_buf = pdata_buf;
850 
851 #ifdef USB
852 	if (IS_USB(pmadapter->card_type)) {
853 		pcmd_node->cmdbuf =
854 			wlan_alloc_mlan_buffer(pmadapter,
855 					       MRVDRV_SIZE_OF_CMD_BUFFER, 0,
856 					       MOAL_MALLOC_BUFFER);
857 		if (!pcmd_node->cmdbuf) {
858 			PRINTM(MERROR, "Failed to allocate cmd_buffer\n");
859 			LEAVE();
860 			return;
861 		}
862 	}
863 #endif /* USB */
864 #if defined(SDIO) || defined(PCIE)
865 	if (!IS_USB(pmadapter->card_type))
866 		pcmd_node->cmdbuf = pcmd_node->pmbuf;
867 #endif
868 
869 	/* Make sure head_ptr for cmd buf is Align */
870 	pcmd_node->cmdbuf->data_offset = 0;
871 	memset(pmadapter, pcmd_node->cmdbuf->pbuf, 0,
872 	       MRVDRV_SIZE_OF_CMD_BUFFER);
873 
874 	/* Prepare mlan_buffer for command sending */
875 	pcmd_node->cmdbuf->buf_type = MLAN_BUF_TYPE_CMD;
876 #ifdef USB
877 	if (IS_USB(pmadapter->card_type))
878 		pcmd_node->cmdbuf->data_offset += MLAN_TYPE_LEN;
879 #endif
880 #if defined(SDIO) || defined(PCIE)
881 	if (!IS_USB(pmadapter->card_type))
882 		pcmd_node->cmdbuf->data_offset +=
883 			pmadapter->ops.intf_header_len;
884 #endif
885 
886 	LEAVE();
887 }
888 
889 /**
890  *  @brief This function gets a free command node if available in
891  *              command free queue.
892  *
893  *  @param pmadapter        A pointer to mlan_adapter structure
894  *
895  *  @return cmd_ctrl_node   A pointer to cmd_ctrl_node structure or MNULL
896  */
wlan_get_cmd_node(mlan_adapter * pmadapter)897 static cmd_ctrl_node *wlan_get_cmd_node(mlan_adapter *pmadapter)
898 {
899 	cmd_ctrl_node *pcmd_node;
900 
901 	ENTER();
902 
903 	if (pmadapter == MNULL) {
904 		LEAVE();
905 		return MNULL;
906 	}
907 	wlan_request_cmd_lock(pmadapter);
908 	if (util_peek_list(pmadapter->pmoal_handle, &pmadapter->cmd_free_q,
909 			   MNULL, MNULL)) {
910 		pcmd_node = (cmd_ctrl_node *)util_dequeue_list(
911 			pmadapter->pmoal_handle, &pmadapter->cmd_free_q, MNULL,
912 			MNULL);
913 	} else {
914 		PRINTM(MERROR,
915 		       "GET_CMD_NODE: cmd_ctrl_node is not available\n");
916 		pcmd_node = MNULL;
917 	}
918 	wlan_release_cmd_lock(pmadapter);
919 	LEAVE();
920 	return pcmd_node;
921 }
922 
923 /**
924  *  @brief This function cleans command node.
925  *
926  *  @param pmadapter    A pointer to mlan_adapter structure
927  *  @param pcmd_node    A pointer to cmd_ctrl_node structure
928  *
929  *  @return             N/A
930  */
wlan_clean_cmd_node(pmlan_adapter pmadapter,cmd_ctrl_node * pcmd_node)931 static t_void wlan_clean_cmd_node(pmlan_adapter pmadapter,
932 				  cmd_ctrl_node *pcmd_node)
933 {
934 	ENTER();
935 
936 	if (pcmd_node == MNULL) {
937 		LEAVE();
938 		return;
939 	}
940 	pcmd_node->cmd_no = 0;
941 	pcmd_node->cmd_flag = 0;
942 	pcmd_node->pioctl_buf = MNULL;
943 	pcmd_node->pdata_buf = MNULL;
944 
945 #ifdef USB
946 	if (IS_USB(pmadapter->card_type) && pcmd_node->cmdbuf) {
947 		wlan_free_mlan_buffer(pmadapter, pcmd_node->cmdbuf);
948 		pcmd_node->cmdbuf = MNULL;
949 	}
950 #endif
951 
952 	if (pcmd_node->respbuf) {
953 		pmadapter->ops.cmdrsp_complete(pmadapter, pcmd_node->respbuf,
954 					       MLAN_STATUS_SUCCESS);
955 		pcmd_node->respbuf = MNULL;
956 	}
957 
958 	LEAVE();
959 	return;
960 }
961 
962 #ifdef STA_SUPPORT
963 /**
964  *  @brief This function will return the pointer to the first entry in
965  *          pending cmd which is scan command
966  *
967  *  @param pmadapter    A pointer to mlan_adapter
968  *
969  *  @return             A pointer to first entry match pioctl_req
970  */
wlan_get_pending_scan_cmd(pmlan_adapter pmadapter)971 static cmd_ctrl_node *wlan_get_pending_scan_cmd(pmlan_adapter pmadapter)
972 {
973 	cmd_ctrl_node *pcmd_node = MNULL;
974 
975 	ENTER();
976 
977 	pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
978 						    &pmadapter->cmd_pending_q,
979 						    MNULL, MNULL);
980 	if (!pcmd_node) {
981 		LEAVE();
982 		return MNULL;
983 	}
984 	while (pcmd_node != (cmd_ctrl_node *)&pmadapter->cmd_pending_q) {
985 		if (pcmd_node->cmd_flag & CMD_F_SCAN) {
986 			LEAVE();
987 			return pcmd_node;
988 		}
989 		pcmd_node = pcmd_node->pnext;
990 	}
991 	LEAVE();
992 	return MNULL;
993 }
994 #endif
995 
996 /**
997  *  @brief This function will return the pointer to the first entry in
998  *          pending cmd which matches the given pioctl_req
999  *
1000  *  @param pmadapter    A pointer to mlan_adapter
1001  *  @param pioctl_req   A pointer to mlan_ioctl_req buf
1002  *
1003  *  @return             A pointer to first entry match pioctl_req
1004  */
wlan_get_pending_ioctl_cmd(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)1005 static cmd_ctrl_node *wlan_get_pending_ioctl_cmd(pmlan_adapter pmadapter,
1006 						 pmlan_ioctl_req pioctl_req)
1007 {
1008 	cmd_ctrl_node *pcmd_node = MNULL;
1009 
1010 	ENTER();
1011 
1012 	pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
1013 						    &pmadapter->cmd_pending_q,
1014 						    MNULL, MNULL);
1015 	if (!pcmd_node) {
1016 		LEAVE();
1017 		return MNULL;
1018 	}
1019 	while (pcmd_node != (cmd_ctrl_node *)&pmadapter->cmd_pending_q) {
1020 		if (pcmd_node->pioctl_buf &&
1021 		    (pcmd_node->pioctl_buf == pioctl_req)) {
1022 			LEAVE();
1023 			return pcmd_node;
1024 		}
1025 		pcmd_node = pcmd_node->pnext;
1026 	}
1027 	LEAVE();
1028 	return MNULL;
1029 }
1030 
1031 /**
1032  *  @brief This function will return the pointer to the first entry in
1033  *          pending cmd which matches the given bss_index
1034  *
1035  *  @param pmadapter    A pointer to mlan_adapter
1036  *  @param bss_index    bss_index
1037  *
1038  *  @return             A pointer to first entry match pioctl_req
1039  */
wlan_get_bss_pending_ioctl_cmd(pmlan_adapter pmadapter,t_u32 bss_index)1040 static cmd_ctrl_node *wlan_get_bss_pending_ioctl_cmd(pmlan_adapter pmadapter,
1041 						     t_u32 bss_index)
1042 {
1043 	cmd_ctrl_node *pcmd_node = MNULL;
1044 	mlan_ioctl_req *pioctl_buf = MNULL;
1045 	ENTER();
1046 
1047 	pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
1048 						    &pmadapter->cmd_pending_q,
1049 						    MNULL, MNULL);
1050 	if (!pcmd_node) {
1051 		LEAVE();
1052 		return MNULL;
1053 	}
1054 	while (pcmd_node != (cmd_ctrl_node *)&pmadapter->cmd_pending_q) {
1055 		if (pcmd_node->pioctl_buf) {
1056 			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
1057 			if (pioctl_buf->bss_index == bss_index) {
1058 				LEAVE();
1059 				return pcmd_node;
1060 			}
1061 		}
1062 		pcmd_node = pcmd_node->pnext;
1063 	}
1064 	LEAVE();
1065 	return MNULL;
1066 }
1067 
1068 /**
1069  *  @brief This function handles the command response of host_cmd
1070  *
1071  *  @param pmpriv       A pointer to mlan_private structure
1072  *  @param resp         A pointer to HostCmd_DS_COMMAND
1073  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
1074  *
1075  *  @return        MLAN_STATUS_SUCCESS
1076  */
wlan_ret_host_cmd(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)1077 static mlan_status wlan_ret_host_cmd(pmlan_private pmpriv,
1078 				     HostCmd_DS_COMMAND *resp,
1079 				     mlan_ioctl_req *pioctl_buf)
1080 {
1081 	mlan_ds_misc_cfg *misc;
1082 	t_u16 size = wlan_le16_to_cpu(resp->size);
1083 
1084 	ENTER();
1085 
1086 	PRINTM(MINFO, "host command response size = %d\n", size);
1087 	size = MIN(size, MRVDRV_SIZE_OF_CMD_BUFFER);
1088 	if (pioctl_buf) {
1089 		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
1090 		misc->param.hostcmd.len = size;
1091 		memcpy_ext(pmpriv->adapter, misc->param.hostcmd.cmd,
1092 			   (void *)resp, size, MRVDRV_SIZE_OF_CMD_BUFFER);
1093 	}
1094 
1095 	LEAVE();
1096 	return MLAN_STATUS_SUCCESS;
1097 }
1098 
1099 /**
1100  *  @brief This function sends host command to firmware.
1101  *
1102  *  @param pmpriv       A pointer to mlan_private structure
1103  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
1104  *  @param pdata_buf    A pointer to data buffer
1105  *  @param cmd_no       A pointer to cmd_no
1106  *  @return             MLAN_STATUS_SUCCESS
1107  */
wlan_cmd_host_cmd(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_void * pdata_buf,t_u16 * cmd_no)1108 static mlan_status wlan_cmd_host_cmd(pmlan_private pmpriv,
1109 				     HostCmd_DS_COMMAND *cmd, t_void *pdata_buf,
1110 				     t_u16 *cmd_no)
1111 {
1112 	mlan_ds_misc_cmd *pcmd_ptr = (mlan_ds_misc_cmd *)pdata_buf;
1113 
1114 	ENTER();
1115 
1116 	/* Copy the HOST command to command buffer */
1117 	memcpy_ext(pmpriv->adapter, (void *)cmd, pcmd_ptr->cmd, pcmd_ptr->len,
1118 		   MRVDRV_SIZE_OF_CMD_BUFFER);
1119 	*cmd_no = wlan_le16_to_cpu(cmd->command);
1120 	PRINTM(MCMND, "Prepare Host command: 0x%x size = %d\n", *cmd_no,
1121 	       pcmd_ptr->len);
1122 	LEAVE();
1123 	return MLAN_STATUS_SUCCESS;
1124 }
1125 
1126 /**
1127  *  @brief This function get the cmd timeout value
1128  *
1129  *  @param cmd_id     cmd id
1130  *
1131  *  @return           timeout value for this command
1132  */
wlan_get_cmd_timeout(t_u16 cmd_id)1133 static t_u32 wlan_get_cmd_timeout(t_u16 cmd_id)
1134 {
1135 	t_u32 timeout;
1136 	ENTER();
1137 	switch (cmd_id) {
1138 	case HostCmd_CMD_802_11_SCAN:
1139 	case HostCmd_CMD_802_11_SCAN_EXT:
1140 		timeout = MRVDRV_TIMER_10S * 2;
1141 		break;
1142 	case HostCmd_CMD_FUNC_INIT:
1143 	case HostCmd_CMD_FUNC_SHUTDOWN:
1144 	case HostCmd_CMD_802_11_ASSOCIATE:
1145 	case HostCmd_CMD_802_11_DEAUTHENTICATE:
1146 	case HostCmd_CMD_802_11_DISASSOCIATE:
1147 	case HostCmd_CMD_802_11_AD_HOC_START:
1148 	case HostCmd_CMD_802_11_AD_HOC_JOIN:
1149 	case HostCmd_CMD_802_11_AD_HOC_STOP:
1150 	case HostCmd_CMD_11N_ADDBA_REQ:
1151 	case HostCmd_CMD_11N_ADDBA_RSP:
1152 	case HostCmd_CMD_11N_DELBA:
1153 	case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
1154 	case HostCmd_CMD_TDLS_CONFIG:
1155 	case HostCmd_CMD_TDLS_OPERATION:
1156 	case HostCmd_CMD_SUPPLICANT_PMK:
1157 	case HostCmd_CMD_SUPPLICANT_PROFILE:
1158 	case HostCmd_CMD_SOFT_RESET:
1159 #ifdef UAP_SUPPORT
1160 	case HOST_CMD_APCMD_SYS_RESET:
1161 	case HOST_CMD_APCMD_BSS_START:
1162 	case HOST_CMD_APCMD_BSS_STOP:
1163 	case HOST_CMD_APCMD_STA_DEAUTH:
1164 #endif
1165 	case HostCMD_APCMD_ACS_SCAN:
1166 		timeout = MRVDRV_TIMER_5S;
1167 		break;
1168 	default:
1169 #ifdef IMX_SUPPORT
1170 		/*
1171 		 * During the roaming test and the 5AP connection test, cmd
1172 		 * timeout are observed for commands like 0x5e, 0x16, 0xd1.
1173 		 * Observed that response has come just after default timeout of
1174 		 * 2 seconds for these commands. This random timeout is not
1175 		 * observed when the default timeout is increased to 5 seconds
1176 		 * (As an work around, Increase the default timeout to 5
1177 		 * seconds. Need to further debug exact reason for delay in cmd
1178 		 * responses)
1179 		 *
1180 		 */
1181 		timeout = MRVDRV_TIMER_1S * 5;
1182 #else
1183 		timeout = MRVDRV_TIMER_1S * 5;
1184 #endif
1185 		break;
1186 	}
1187 	LEAVE();
1188 	return timeout;
1189 }
1190 
1191 /**
1192  *  @brief This function downloads a command to firmware.
1193  *
1194  *  @param pmpriv       A pointer to mlan_private structure
1195  *  @param pcmd_node    A pointer to cmd_ctrl_node structure
1196  *
1197  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1198  */
wlan_dnld_cmd_to_fw(mlan_private * pmpriv,cmd_ctrl_node * pcmd_node)1199 static mlan_status wlan_dnld_cmd_to_fw(mlan_private *pmpriv,
1200 				       cmd_ctrl_node *pcmd_node)
1201 {
1202 	mlan_adapter *pmadapter = pmpriv->adapter;
1203 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
1204 	mlan_status ret = MLAN_STATUS_SUCCESS;
1205 	HostCmd_DS_COMMAND *pcmd;
1206 	mlan_ioctl_req *pioctl_buf = MNULL;
1207 	t_u16 cmd_code;
1208 	t_u16 cmd_size;
1209 	t_u32 age_ts_usec;
1210 #ifdef USB
1211 	t_u32 tmp;
1212 #endif
1213 #ifdef DEBUG_LEVEL1
1214 	t_u32 sec = 0, usec = 0;
1215 #endif
1216 	t_u32 timeout = 0;
1217 
1218 	ENTER();
1219 
1220 	if (pcmd_node)
1221 		if (pcmd_node->pioctl_buf != MNULL)
1222 			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
1223 	if (!pmadapter || !pcmd_node) {
1224 		if (pioctl_buf)
1225 			pioctl_buf->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
1226 		ret = MLAN_STATUS_FAILURE;
1227 		goto done;
1228 	}
1229 
1230 	pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
1231 				      pcmd_node->cmdbuf->data_offset);
1232 
1233 	/* Sanity test */
1234 	if (pcmd == MNULL || pcmd->size == 0) {
1235 		PRINTM(MERROR,
1236 		       "DNLD_CMD: pcmd is null or command size is zero, "
1237 		       "Not sending\n");
1238 		if (pioctl_buf)
1239 			pioctl_buf->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
1240 		wlan_request_cmd_lock(pmadapter);
1241 		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
1242 		wlan_release_cmd_lock(pmadapter);
1243 		ret = MLAN_STATUS_FAILURE;
1244 		goto done;
1245 	}
1246 
1247 	/* Set command sequence number */
1248 	pmadapter->seq_num++;
1249 	pcmd->seq_num = wlan_cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO(
1250 		pmadapter->seq_num, pcmd_node->priv->bss_num,
1251 		pcmd_node->priv->bss_type));
1252 	cmd_code = wlan_le16_to_cpu(pcmd->command);
1253 	pcmd_node->cmd_no = cmd_code;
1254 	timeout = wlan_get_cmd_timeout(cmd_code);
1255 	cmd_size = wlan_le16_to_cpu(pcmd->size);
1256 
1257 	pcmd_node->cmdbuf->data_len = cmd_size;
1258 
1259 	wlan_request_cmd_lock(pmadapter);
1260 	pmadapter->curr_cmd = pcmd_node;
1261 	wlan_release_cmd_lock(pmadapter);
1262 
1263 	/* Save the last command id and action to debug log */
1264 	pmadapter->dbg.last_cmd_index =
1265 		(pmadapter->dbg.last_cmd_index + 1) % DBG_CMD_NUM;
1266 	pmadapter->dbg.last_cmd_id[pmadapter->dbg.last_cmd_index] = cmd_code;
1267 	pmadapter->dbg.last_cmd_act[pmadapter->dbg.last_cmd_index] =
1268 		wlan_le16_to_cpu(*(t_u16 *)((t_u8 *)pcmd + S_DS_GEN));
1269 	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
1270 						  &pmadapter->dnld_cmd_in_secs,
1271 						  &age_ts_usec);
1272 
1273 #ifdef USB
1274 	if (IS_USB(pmadapter->card_type)) {
1275 		/* Add extra header for USB */
1276 		if (pcmd_node->cmdbuf->data_offset < MLAN_TYPE_LEN) {
1277 			PRINTM(MERROR,
1278 			       "DNLD_CMD: data_offset is too small=%d\n",
1279 			       pcmd_node->cmdbuf->data_offset);
1280 			if (pioctl_buf)
1281 				pioctl_buf->status_code =
1282 					MLAN_ERROR_CMD_DNLD_FAIL;
1283 
1284 			wlan_request_cmd_lock(pmadapter);
1285 			wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
1286 			pmadapter->curr_cmd = MNULL;
1287 			wlan_release_cmd_lock(pmadapter);
1288 			if (pmadapter->dbg.last_cmd_index)
1289 				pmadapter->dbg.last_cmd_index--;
1290 			else
1291 				pmadapter->dbg.last_cmd_index = DBG_CMD_NUM - 1;
1292 			ret = MLAN_STATUS_FAILURE;
1293 			goto done;
1294 		}
1295 		tmp = wlan_cpu_to_le32(MLAN_USB_TYPE_CMD);
1296 		memcpy_ext(pmadapter, (t_u8 *)pcmd - MLAN_TYPE_LEN,
1297 			   (t_u8 *)&tmp, MLAN_TYPE_LEN, MLAN_TYPE_LEN);
1298 		pcmd_node->cmdbuf->data_offset -= MLAN_TYPE_LEN;
1299 		pcmd_node->cmdbuf->data_len += MLAN_TYPE_LEN;
1300 	}
1301 #endif
1302 
1303 	if (pcmd->command == HostCmd_CMD_802_11_SCAN_EXT)
1304 		pmadapter->scan_state |= wlan_get_ext_scan_state(pcmd);
1305 
1306 	PRINTM_GET_SYS_TIME(MCMND, &sec, &usec);
1307 	PRINTM_NETINTF(MCMND, pmpriv);
1308 	PRINTM(MCMND,
1309 	       "DNLD_CMD (%lu.%06lu): 0x%x, act 0x%x, len %d, seqno 0x%x timeout %d\n",
1310 	       sec, usec, cmd_code,
1311 	       wlan_le16_to_cpu(*(t_u16 *)((t_u8 *)pcmd + S_DS_GEN)), cmd_size,
1312 	       wlan_le16_to_cpu(pcmd->seq_num), timeout);
1313 	DBG_HEXDUMP(MCMD_D, "DNLD_CMD", (t_u8 *)pcmd, cmd_size);
1314 
1315 #if defined(SDIO) || defined(PCIE)
1316 	if (!IS_USB(pmadapter->card_type)) {
1317 		pcmd_node->cmdbuf->data_offset -=
1318 			pmadapter->ops.intf_header_len;
1319 		pcmd_node->cmdbuf->data_len += pmadapter->ops.intf_header_len;
1320 	}
1321 #endif
1322 
1323 	/* Send the command to lower layer */
1324 	ret = pmadapter->ops.host_to_card(pmpriv, MLAN_TYPE_CMD,
1325 					  pcmd_node->cmdbuf, MNULL);
1326 
1327 #ifdef USB
1328 	if (IS_USB(pmadapter->card_type) && (ret == MLAN_STATUS_PENDING))
1329 		pcmd_node->cmdbuf = MNULL;
1330 #endif
1331 
1332 	if (ret == MLAN_STATUS_FAILURE) {
1333 		PRINTM(MERROR, "DNLD_CMD: Host to Card Failed\n");
1334 		if (pcmd_node->pioctl_buf) {
1335 			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
1336 			pioctl_buf->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
1337 		}
1338 
1339 		wlan_request_cmd_lock(pmadapter);
1340 		wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
1341 		pmadapter->curr_cmd = MNULL;
1342 		wlan_release_cmd_lock(pmadapter);
1343 		if (pmadapter->dbg.last_cmd_index)
1344 			pmadapter->dbg.last_cmd_index--;
1345 		else
1346 			pmadapter->dbg.last_cmd_index = DBG_CMD_NUM - 1;
1347 
1348 		pmadapter->dbg.num_cmd_host_to_card_failure++;
1349 		wlan_dump_info(pmadapter, REASON_CODE_CMD_TO_CARD_FAILURE);
1350 		ret = MLAN_STATUS_FAILURE;
1351 		goto done;
1352 	}
1353 
1354 	/* Clear BSS_NO_BITS from HostCmd */
1355 	cmd_code &= HostCmd_CMD_ID_MASK;
1356 
1357 	/* For the command who has no command response, we should return here */
1358 	if (cmd_code == HostCmd_CMD_FW_DUMP_EVENT ||
1359 	    cmd_code == HostCmd_CMD_SOFT_RESET) {
1360 		if (pcmd_node->pioctl_buf) {
1361 			PRINTM(MMSG,
1362 			       "CMD(0x%x) has no cmd resp: free curr_cmd and do ioctl_complete\n",
1363 			       cmd_code);
1364 			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
1365 			wlan_request_cmd_lock(pmadapter);
1366 			wlan_insert_cmd_to_free_q(pmadapter,
1367 						  pmadapter->curr_cmd);
1368 			pmadapter->curr_cmd = MNULL;
1369 			wlan_release_cmd_lock(pmadapter);
1370 		}
1371 		goto done;
1372 	}
1373 
1374 	/* Setup the timer after transmit command */
1375 	pcb->moal_start_timer(pmadapter->pmoal_handle,
1376 			      pmadapter->pmlan_cmd_timer, MFALSE, timeout);
1377 
1378 	pmadapter->cmd_timer_is_set = MTRUE;
1379 
1380 	ret = MLAN_STATUS_SUCCESS;
1381 
1382 done:
1383 	LEAVE();
1384 	return ret;
1385 }
1386 
1387 /**
1388  *  @brief This function sends sleep confirm command to firmware.
1389  *
1390  *  @param pmadapter  A pointer to mlan_adapter structure
1391  *
1392  *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1393  */
wlan_dnld_sleep_confirm_cmd(mlan_adapter * pmadapter)1394 static mlan_status wlan_dnld_sleep_confirm_cmd(mlan_adapter *pmadapter)
1395 {
1396 	mlan_status ret = MLAN_STATUS_SUCCESS;
1397 	static t_u32 i;
1398 #if defined(SDIO) || defined(PCIE)
1399 	t_u16 cmd_len = 0;
1400 #endif
1401 	opt_sleep_confirm_buffer *sleep_cfm_buf =
1402 		(opt_sleep_confirm_buffer *)(pmadapter->psleep_cfm->pbuf +
1403 					     pmadapter->psleep_cfm->data_offset);
1404 	mlan_buffer *pmbuf = MNULL;
1405 	mlan_private *pmpriv = MNULL;
1406 
1407 	ENTER();
1408 
1409 	pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
1410 	if (!pmpriv) {
1411 		LEAVE();
1412 		return MLAN_STATUS_FAILURE;
1413 	}
1414 #if defined(SDIO) || defined(PCIE)
1415 	if (!IS_USB(pmadapter->card_type)) {
1416 		cmd_len = sizeof(OPT_Confirm_Sleep);
1417 		pmbuf = pmadapter->psleep_cfm;
1418 	}
1419 #endif
1420 	pmadapter->seq_num++;
1421 	sleep_cfm_buf->ps_cfm_sleep.seq_num =
1422 		wlan_cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO(
1423 			pmadapter->seq_num, pmpriv->bss_num, pmpriv->bss_type));
1424 	DBG_HEXDUMP(MCMD_D, "SLEEP_CFM", &sleep_cfm_buf->ps_cfm_sleep,
1425 		    sizeof(OPT_Confirm_Sleep));
1426 
1427 	/* Send sleep confirm command to firmware */
1428 #ifdef USB
1429 	if (IS_USB(pmadapter->card_type)) {
1430 		pmbuf = wlan_alloc_mlan_buffer(pmadapter,
1431 					       sizeof(opt_sleep_confirm_buffer),
1432 					       0, MOAL_MALLOC_BUFFER);
1433 
1434 		if (!pmbuf) {
1435 			PRINTM(MERROR,
1436 			       "Failed to allocate sleep confirm buffers\n");
1437 			LEAVE();
1438 			return MLAN_STATUS_FAILURE;
1439 		}
1440 		pmbuf->buf_type = MLAN_BUF_TYPE_CMD;
1441 		pmbuf->data_len = pmadapter->psleep_cfm->data_len;
1442 		memcpy_ext(pmadapter, pmbuf->pbuf + pmbuf->data_offset,
1443 			   pmadapter->psleep_cfm->pbuf +
1444 				   pmadapter->psleep_cfm->data_offset,
1445 			   pmadapter->psleep_cfm->data_len, pmbuf->data_len);
1446 	}
1447 #endif /* USB */
1448 
1449 #if defined(SDIO) || defined(PCIE)
1450 	if (!IS_USB(pmadapter->card_type))
1451 		pmadapter->psleep_cfm->data_len =
1452 			cmd_len + pmadapter->ops.intf_header_len;
1453 #endif
1454 
1455 	if (pmbuf)
1456 		ret = pmadapter->ops.host_to_card(pmpriv, MLAN_TYPE_CMD, pmbuf,
1457 						  MNULL);
1458 
1459 #ifdef USB
1460 	if (IS_USB(pmadapter->card_type) && (ret != MLAN_STATUS_PENDING))
1461 		wlan_free_mlan_buffer(pmadapter, pmbuf);
1462 #endif
1463 	if (ret == MLAN_STATUS_FAILURE) {
1464 		PRINTM(MERROR, "SLEEP_CFM: failed\n");
1465 		pmadapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++;
1466 		goto done;
1467 	} else {
1468 		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
1469 			pmadapter->ps_state = PS_STATE_SLEEP_CFM;
1470 #ifdef STA_SUPPORT
1471 		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
1472 			if (!sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl) {
1473 				/* Response is not needed for sleep confirm
1474 				 * command */
1475 				pmadapter->ps_state = PS_STATE_SLEEP;
1476 			} else {
1477 				pmadapter->ps_state = PS_STATE_SLEEP_CFM;
1478 			}
1479 
1480 			if (!sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl &&
1481 			    (pmadapter->is_hs_configured &&
1482 			     !pmadapter->sleep_period.period)) {
1483 				pmadapter->pm_wakeup_card_req = MTRUE;
1484 				wlan_host_sleep_activated_event(
1485 					wlan_get_priv(pmadapter,
1486 						      MLAN_BSS_ROLE_STA),
1487 					MTRUE);
1488 			}
1489 		}
1490 #endif /* STA_SUPPORT */
1491 
1492 		PRINTM_NETINTF(MEVENT, pmpriv);
1493 #define NUM_SC_PER_LINE 16
1494 		if (++i % NUM_SC_PER_LINE == 0)
1495 			PRINTM(MEVENT, "+\n");
1496 		else
1497 			PRINTM(MEVENT, "+");
1498 	}
1499 
1500 done:
1501 	LEAVE();
1502 	return ret;
1503 }
1504 
1505 /**
1506  *  @brief Fetch bitmap rate index
1507  *
1508  *  @param rate_scope	A pointer to MrvlRateScope_t
1509  *
1510  *  @return		bitmap rate index
1511  */
wlan_get_bitmap_index(MrvlRateScope_t * rate_scope)1512 static t_u16 wlan_get_bitmap_index(MrvlRateScope_t *rate_scope)
1513 {
1514 	t_u16 index = 0;
1515 
1516 	if (rate_scope != MNULL) {
1517 		index += NELEMENTS(rate_scope->ht_mcs_rate_bitmap);
1518 		index += NELEMENTS(rate_scope->vht_mcs_rate_bitmap);
1519 	}
1520 
1521 	return index;
1522 }
1523 
1524 /********************************************************
1525 			Global Functions
1526 ********************************************************/
1527 
1528 /**
1529  *  @brief Event handler
1530  *
1531  *  @param priv     A pointer to mlan_private structure
1532  *  @param event_id Event ID
1533  *  @param pmevent  Event buffer
1534  *
1535  *  @return         MLAN_STATUS_SUCCESS
1536  */
wlan_recv_event(pmlan_private priv,mlan_event_id event_id,t_void * pmevent)1537 mlan_status wlan_recv_event(pmlan_private priv, mlan_event_id event_id,
1538 			    t_void *pmevent)
1539 {
1540 	pmlan_callbacks pcb = MNULL;
1541 
1542 	ENTER();
1543 
1544 	if (!priv) {
1545 		LEAVE();
1546 		return MLAN_STATUS_FAILURE;
1547 	}
1548 	pcb = &priv->adapter->callbacks;
1549 
1550 	if (pmevent)
1551 		/* The caller has provided the event. */
1552 		pcb->moal_recv_event(priv->adapter->pmoal_handle,
1553 				     (pmlan_event)pmevent);
1554 	else {
1555 		mlan_event mevent;
1556 
1557 		memset(priv->adapter, &mevent, 0, sizeof(mlan_event));
1558 		mevent.bss_index = priv->bss_index;
1559 		mevent.event_id = event_id;
1560 		mevent.event_len = 0;
1561 
1562 		pcb->moal_recv_event(priv->adapter->pmoal_handle, &mevent);
1563 	}
1564 
1565 	LEAVE();
1566 	return MLAN_STATUS_SUCCESS;
1567 }
1568 
1569 /**
1570  *  @brief This function allocates the command buffer and links
1571  *          it to command free queue.
1572  *
1573  *  @param pmadapter    A pointer to mlan_adapter structure
1574  *
1575  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1576  */
wlan_alloc_cmd_buffer(mlan_adapter * pmadapter)1577 mlan_status wlan_alloc_cmd_buffer(mlan_adapter *pmadapter)
1578 {
1579 	mlan_status ret = MLAN_STATUS_SUCCESS;
1580 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
1581 	cmd_ctrl_node *pcmd_array = MNULL;
1582 	t_u32 buf_size;
1583 	t_u32 i;
1584 
1585 	ENTER();
1586 
1587 	/* Allocate and initialize cmd_ctrl_node */
1588 	buf_size = sizeof(cmd_ctrl_node) * MRVDRV_NUM_OF_CMD_BUFFER;
1589 	ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size,
1590 			       MLAN_MEM_DEF | MLAN_MEM_DMA,
1591 			       (t_u8 **)&pcmd_array);
1592 	if (ret != MLAN_STATUS_SUCCESS || !pcmd_array) {
1593 		PRINTM(MERROR,
1594 		       "ALLOC_CMD_BUF: Failed to allocate pcmd_array\n");
1595 		ret = MLAN_STATUS_FAILURE;
1596 		goto done;
1597 	}
1598 
1599 	pmadapter->cmd_pool = pcmd_array;
1600 	memset(pmadapter, pmadapter->cmd_pool, 0, buf_size);
1601 
1602 #if defined(PCIE) || defined(SDIO)
1603 	if (!IS_USB(pmadapter->card_type)) {
1604 		/* Allocate and initialize command buffers */
1605 		for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1606 			pcmd_array[i].pmbuf = wlan_alloc_mlan_buffer(
1607 				pmadapter, MRVDRV_SIZE_OF_CMD_BUFFER, 0,
1608 				MOAL_MALLOC_BUFFER);
1609 			if (!pcmd_array[i].pmbuf) {
1610 				PRINTM(MERROR,
1611 				       "ALLOC_CMD_BUF: Failed to allocate command buffer\n");
1612 				ret = MLAN_STATUS_FAILURE;
1613 				goto done;
1614 			}
1615 		}
1616 	}
1617 #endif
1618 	wlan_request_cmd_lock(pmadapter);
1619 	for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++)
1620 		wlan_insert_cmd_to_free_q(pmadapter, &pcmd_array[i]);
1621 	wlan_release_cmd_lock(pmadapter);
1622 	ret = MLAN_STATUS_SUCCESS;
1623 done:
1624 	LEAVE();
1625 	return ret;
1626 }
1627 
1628 /**
1629  *  @brief This function frees the command buffer.
1630  *
1631  *  @param pmadapter    A pointer to mlan_adapter structure
1632  *
1633  *  @return             MLAN_STATUS_SUCCESS
1634  */
wlan_free_cmd_buffer(mlan_adapter * pmadapter)1635 mlan_status wlan_free_cmd_buffer(mlan_adapter *pmadapter)
1636 {
1637 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
1638 	cmd_ctrl_node *pcmd_array;
1639 	t_u32 i;
1640 
1641 	ENTER();
1642 
1643 	/* Need to check if cmd pool is allocated or not */
1644 	if (pmadapter->cmd_pool == MNULL) {
1645 		PRINTM(MINFO, "FREE_CMD_BUF: cmd_pool is Null\n");
1646 		goto done;
1647 	}
1648 
1649 	pcmd_array = pmadapter->cmd_pool;
1650 
1651 	/* Release shared memory buffers */
1652 	for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1653 #ifdef USB
1654 		if (IS_USB(pmadapter->card_type) && pcmd_array[i].cmdbuf) {
1655 			PRINTM(MINFO, "Free all the USB command buffer.\n");
1656 			wlan_free_mlan_buffer(pmadapter, pcmd_array[i].cmdbuf);
1657 			pcmd_array[i].cmdbuf = MNULL;
1658 		}
1659 #endif
1660 #if defined(SDIO) || defined(PCIE)
1661 		if (!IS_USB(pmadapter->card_type) && pcmd_array[i].pmbuf) {
1662 			PRINTM(MINFO, "Free all the command buffer.\n");
1663 			wlan_free_mlan_buffer(pmadapter, pcmd_array[i].pmbuf);
1664 			pcmd_array[i].pmbuf = MNULL;
1665 		}
1666 #endif
1667 		if (pcmd_array[i].respbuf) {
1668 #ifdef USB
1669 			if (IS_USB(pmadapter->card_type))
1670 				pmadapter->callbacks.moal_recv_complete(
1671 					pmadapter->pmoal_handle,
1672 					pcmd_array[i].respbuf,
1673 					pmadapter->rx_cmd_ep,
1674 					MLAN_STATUS_SUCCESS);
1675 #endif
1676 #if defined(SDIO) || defined(PCIE)
1677 			if (!IS_USB(pmadapter->card_type))
1678 				wlan_free_mlan_buffer(pmadapter,
1679 						      pcmd_array[i].respbuf);
1680 #endif
1681 			pcmd_array[i].respbuf = MNULL;
1682 		}
1683 	}
1684 	/* Release cmd_ctrl_node */
1685 	if (pmadapter->cmd_pool) {
1686 		PRINTM(MINFO, "Free command pool.\n");
1687 		pcb->moal_mfree(pmadapter->pmoal_handle,
1688 				(t_u8 *)pmadapter->cmd_pool);
1689 		pmadapter->cmd_pool = MNULL;
1690 	}
1691 
1692 done:
1693 	LEAVE();
1694 	return MLAN_STATUS_SUCCESS;
1695 }
1696 
1697 /**
1698  *  @brief This function handles events generated by firmware
1699  *
1700  *  @param pmadapter    A pointer to mlan_adapter structure
1701  *
1702  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1703  */
wlan_process_event(pmlan_adapter pmadapter)1704 mlan_status wlan_process_event(pmlan_adapter pmadapter)
1705 {
1706 	mlan_status ret = MLAN_STATUS_SUCCESS;
1707 	pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
1708 	pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event;
1709 	t_u32 eventcause = pmadapter->event_cause;
1710 #ifdef DEBUG_LEVEL1
1711 	t_u32 in_ts_sec = 0, in_ts_usec = 0;
1712 #endif
1713 	ENTER();
1714 
1715 	/* Save the last event to debug log */
1716 	pmadapter->dbg.last_event_index =
1717 		(pmadapter->dbg.last_event_index + 1) % DBG_CMD_NUM;
1718 	pmadapter->dbg.last_event[pmadapter->dbg.last_event_index] =
1719 		(t_u16)eventcause;
1720 
1721 	if ((eventcause & EVENT_ID_MASK) == EVENT_RADAR_DETECTED) {
1722 		priv = wlan_get_priv_by_id(pmadapter,
1723 					   EVENT_GET_BSS_NUM(eventcause),
1724 					   EVENT_GET_BSS_TYPE(eventcause));
1725 		if (priv && priv->bss_type != MLAN_BSS_TYPE_DFS) {
1726 			if (wlan_11h_dfs_event_preprocessing(pmadapter) ==
1727 			    MLAN_STATUS_SUCCESS) {
1728 				memcpy_ext(pmadapter, (t_u8 *)&eventcause,
1729 					   pmbuf->pbuf + pmbuf->data_offset,
1730 					   sizeof(eventcause),
1731 					   sizeof(eventcause));
1732 			} else {
1733 				priv = wlan_get_priv_by_id(
1734 					pmadapter,
1735 					EVENT_GET_BSS_NUM(eventcause),
1736 					EVENT_GET_BSS_TYPE(eventcause));
1737 				if (priv)
1738 					PRINTM_NETINTF(MEVENT, priv);
1739 				PRINTM(MERROR,
1740 				       "Error processing DFS Event: 0x%x\n",
1741 				       eventcause);
1742 				goto done;
1743 			}
1744 		}
1745 	}
1746 	/* Get BSS number and corresponding priv */
1747 	priv = wlan_get_priv_by_id(pmadapter, EVENT_GET_BSS_NUM(eventcause),
1748 				   EVENT_GET_BSS_TYPE(eventcause));
1749 	if (!priv)
1750 		priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
1751 	if (!priv) {
1752 		ret = MLAN_STATUS_FAILURE;
1753 		goto done;
1754 	}
1755 
1756 	/* Clear BSS_NO_BITS from event */
1757 	eventcause &= EVENT_ID_MASK;
1758 	pmadapter->event_cause = eventcause;
1759 
1760 	if (pmbuf) {
1761 		pmbuf->bss_index = priv->bss_index;
1762 		memcpy_ext(pmadapter, pmbuf->pbuf + pmbuf->data_offset,
1763 			   (t_u8 *)&eventcause, sizeof(eventcause),
1764 			   sizeof(eventcause));
1765 	}
1766 
1767 	if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE &&
1768 	    eventcause != EVENT_FW_DUMP_INFO) {
1769 		PRINTM_GET_SYS_TIME(MEVENT, &in_ts_sec, &in_ts_usec);
1770 		PRINTM_NETINTF(MEVENT, priv);
1771 		PRINTM(MEVENT, "%lu.%06lu : Event: 0x%x\n", in_ts_sec,
1772 		       in_ts_usec, eventcause);
1773 	}
1774 
1775 	ret = priv->ops.process_event(priv);
1776 done:
1777 	pmadapter->event_cause = 0;
1778 	pmadapter->pmlan_buffer_event = MNULL;
1779 	if (pmbuf)
1780 		pmadapter->ops.event_complete(pmadapter, pmbuf,
1781 					      MLAN_STATUS_SUCCESS);
1782 
1783 	LEAVE();
1784 	return ret;
1785 }
1786 
1787 /**
1788  *  @brief This function requests a lock on command queue.
1789  *
1790  *  @param pmadapter    A pointer to mlan_adapter structure
1791  *
1792  *  @return             N/A
1793  */
wlan_request_cmd_lock(mlan_adapter * pmadapter)1794 t_void wlan_request_cmd_lock(mlan_adapter *pmadapter)
1795 {
1796 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
1797 
1798 	ENTER();
1799 
1800 	/* Call MOAL spin lock callback function */
1801 	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmlan_cmd_lock);
1802 
1803 	LEAVE();
1804 	return;
1805 }
1806 
1807 /**
1808  *  @brief This function releases a lock on command queue.
1809  *
1810  *  @param pmadapter    A pointer to mlan_adapter structure
1811  *
1812  *  @return             N/A
1813  */
wlan_release_cmd_lock(mlan_adapter * pmadapter)1814 t_void wlan_release_cmd_lock(mlan_adapter *pmadapter)
1815 {
1816 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
1817 
1818 	ENTER();
1819 
1820 	/* Call MOAL spin unlock callback function */
1821 	pcb->moal_spin_unlock(pmadapter->pmoal_handle,
1822 			      pmadapter->pmlan_cmd_lock);
1823 
1824 	LEAVE();
1825 	return;
1826 }
1827 
1828 /**
1829  *  @brief This function prepare the command before sending to firmware.
1830  *
1831  *  @param pmpriv       A pointer to mlan_private structure
1832  *  @param cmd_no       Command number
1833  *  @param cmd_action   Command action: GET or SET
1834  *  @param cmd_oid      Cmd oid: treated as sub command
1835  *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
1836  *  @param pdata_buf    A pointer to information buffer
1837  *
1838  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1839  */
wlan_prepare_cmd(mlan_private * pmpriv,t_u16 cmd_no,t_u16 cmd_action,t_u32 cmd_oid,t_void * pioctl_buf,t_void * pdata_buf)1840 mlan_status wlan_prepare_cmd(mlan_private *pmpriv, t_u16 cmd_no,
1841 			     t_u16 cmd_action, t_u32 cmd_oid,
1842 			     t_void *pioctl_buf, t_void *pdata_buf)
1843 {
1844 	mlan_status ret = MLAN_STATUS_SUCCESS;
1845 	mlan_adapter *pmadapter = MNULL;
1846 	cmd_ctrl_node *pcmd_node = MNULL;
1847 	HostCmd_DS_COMMAND *cmd_ptr = MNULL;
1848 	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
1849 
1850 	ENTER();
1851 
1852 	if (!pmpriv) {
1853 		LEAVE();
1854 		return MLAN_STATUS_FAILURE;
1855 	}
1856 	pmadapter = pmpriv->adapter;
1857 
1858 	/* Sanity test */
1859 	if (!pmadapter || pmadapter->surprise_removed) {
1860 		PRINTM(MERROR, "PREP_CMD: Card is Removed\n");
1861 		if (pioctl_req)
1862 			pioctl_req->status_code = MLAN_ERROR_FW_NOT_READY;
1863 		ret = MLAN_STATUS_FAILURE;
1864 		goto done;
1865 	}
1866 
1867 	if (pmadapter->hw_status == WlanHardwareStatusReset) {
1868 		if ((cmd_no != HostCmd_CMD_FUNC_INIT)
1869 #ifdef PCIE
1870 		    && (cmd_no != HostCmd_CMD_PCIE_HOST_BUF_DETAILS)
1871 #endif
1872 		) {
1873 			PRINTM(MERROR, "PREP_CMD: FW is in reset state\n");
1874 			if (pioctl_req)
1875 				pioctl_req->status_code =
1876 					MLAN_ERROR_FW_NOT_READY;
1877 			ret = MLAN_STATUS_FAILURE;
1878 			goto done;
1879 		}
1880 	}
1881 
1882 	/* Get a new command node */
1883 	pcmd_node = wlan_get_cmd_node(pmadapter);
1884 
1885 	if (pcmd_node == MNULL) {
1886 		PRINTM(MERROR, "PREP_CMD: No free cmd node\n");
1887 		wlan_dump_info(pmadapter, REASON_CODE_NO_CMD_NODE);
1888 		if (pioctl_req)
1889 			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
1890 		ret = MLAN_STATUS_FAILURE;
1891 		goto done;
1892 	}
1893 	/** reset num no cmd node */
1894 	pmadapter->dbg.num_no_cmd_node = 0;
1895 
1896 	/* Initialize the command node */
1897 	wlan_init_cmd_node(pmpriv, pcmd_node, cmd_no, pioctl_buf, pdata_buf);
1898 
1899 	if (pcmd_node->cmdbuf == MNULL) {
1900 		PRINTM(MERROR, "PREP_CMD: No free cmd buf\n");
1901 		if (pioctl_req)
1902 			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
1903 		ret = MLAN_STATUS_FAILURE;
1904 		goto done;
1905 	}
1906 
1907 	cmd_ptr = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
1908 					 pcmd_node->cmdbuf->data_offset);
1909 	cmd_ptr->command = cmd_no;
1910 	cmd_ptr->result = 0;
1911 
1912 	/* Prepare command */
1913 	if (cmd_no)
1914 		ret = pmpriv->ops.prepare_cmd(pmpriv, cmd_no, cmd_action,
1915 					      cmd_oid, pioctl_buf, pdata_buf,
1916 					      cmd_ptr);
1917 	else {
1918 		ret = wlan_cmd_host_cmd(pmpriv, cmd_ptr, pdata_buf, &cmd_no);
1919 		pcmd_node->cmd_flag |= CMD_F_HOSTCMD;
1920 	}
1921 
1922 	/* Return error, since the command preparation failed */
1923 	if (ret != MLAN_STATUS_SUCCESS) {
1924 		PRINTM(MERROR, "PREP_CMD: Command 0x%x preparation failed\n",
1925 		       cmd_no);
1926 		pcmd_node->pioctl_buf = MNULL;
1927 		if (pioctl_req)
1928 			pioctl_req->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
1929 		wlan_request_cmd_lock(pmadapter);
1930 		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
1931 		wlan_release_cmd_lock(pmadapter);
1932 		ret = MLAN_STATUS_FAILURE;
1933 		goto done;
1934 	}
1935 
1936 	wlan_request_cmd_lock(pmadapter);
1937 	/* Send command */
1938 #ifdef STA_SUPPORT
1939 	if (cmd_no == HostCmd_CMD_802_11_SCAN ||
1940 	    cmd_no == HostCmd_CMD_802_11_SCAN_EXT) {
1941 		if (cmd_no == HostCmd_CMD_802_11_SCAN_EXT &&
1942 		    pmadapter->ext_scan && pmadapter->ext_scan_enh &&
1943 		    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE &&
1944 		    wlan_is_cancel_scan_cmd(cmd_ptr)) {
1945 			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
1946 						     MFALSE);
1947 		} else
1948 
1949 			wlan_queue_scan_cmd(pmpriv, pcmd_node);
1950 	} else {
1951 #endif
1952 		if ((cmd_no == HostCmd_CMD_802_11_HS_CFG_ENH) &&
1953 		    (cmd_action == HostCmd_ACT_GEN_SET) &&
1954 		    (pmadapter->hs_cfg.conditions == HOST_SLEEP_CFG_CANCEL))
1955 			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
1956 						     MFALSE);
1957 		else
1958 			wlan_queue_cmd(pmpriv, pcmd_node, cmd_no);
1959 #ifdef STA_SUPPORT
1960 	}
1961 #endif
1962 	wlan_release_cmd_lock(pmadapter);
1963 done:
1964 	LEAVE();
1965 	return ret;
1966 }
1967 
1968 /**
1969  *  @brief This function inserts command node to cmd_free_q
1970  *              after cleaning it.
1971  *
1972  *  @param pmadapter    A pointer to mlan_adapter structure
1973  *  @param pcmd_node    A pointer to cmd_ctrl_node structure
1974  *
1975  *  @return             N/A
1976  */
wlan_insert_cmd_to_free_q(mlan_adapter * pmadapter,cmd_ctrl_node * pcmd_node)1977 t_void wlan_insert_cmd_to_free_q(mlan_adapter *pmadapter,
1978 				 cmd_ctrl_node *pcmd_node)
1979 {
1980 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
1981 	mlan_ioctl_req *pioctl_req = MNULL;
1982 	ENTER();
1983 
1984 	if (pcmd_node == MNULL)
1985 		goto done;
1986 	if (pcmd_node->pioctl_buf) {
1987 		pioctl_req = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
1988 		if (pioctl_req->status_code != MLAN_ERROR_NO_ERROR)
1989 			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
1990 						 pioctl_req,
1991 						 MLAN_STATUS_FAILURE);
1992 		else
1993 			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
1994 						 pioctl_req,
1995 						 MLAN_STATUS_SUCCESS);
1996 	}
1997 	/* Clean the node */
1998 	wlan_clean_cmd_node(pmadapter, pcmd_node);
1999 
2000 	/* Insert node into cmd_free_q */
2001 	util_enqueue_list_tail(pmadapter->pmoal_handle, &pmadapter->cmd_free_q,
2002 			       (pmlan_linked_list)pcmd_node, MNULL, MNULL);
2003 done:
2004 	LEAVE();
2005 }
2006 
2007 /**
2008  *  @brief This function queues the command to cmd list.
2009  *
2010  *  @param pmadapter    A pointer to mlan_adapter structure
2011  *  @param pcmd_node    A pointer to cmd_ctrl_node structure
2012  *  @param add_tail      Specify if the cmd needs to be queued in the header or
2013  * tail
2014  *
2015  *  @return             N/A
2016  */
wlan_insert_cmd_to_pending_q(mlan_adapter * pmadapter,cmd_ctrl_node * pcmd_node,t_u32 add_tail)2017 t_void wlan_insert_cmd_to_pending_q(mlan_adapter *pmadapter,
2018 				    cmd_ctrl_node *pcmd_node, t_u32 add_tail)
2019 {
2020 	HostCmd_DS_COMMAND *pcmd = MNULL;
2021 	t_u16 command;
2022 
2023 	ENTER();
2024 
2025 	if (pcmd_node == MNULL) {
2026 		PRINTM(MERROR, "QUEUE_CMD: pcmd_node is MNULL\n");
2027 		goto done;
2028 	}
2029 
2030 	pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
2031 				      pcmd_node->cmdbuf->data_offset);
2032 
2033 	command = wlan_le16_to_cpu(pcmd->command);
2034 
2035 	/* Exit_PS command needs to be queued in the header always. */
2036 	if (command == HostCmd_CMD_802_11_PS_MODE_ENH) {
2037 		HostCmd_DS_802_11_PS_MODE_ENH *pm = &pcmd->params.psmode_enh;
2038 		if (wlan_le16_to_cpu(pm->action) == DIS_AUTO_PS) {
2039 			if (pmadapter->ps_state != PS_STATE_AWAKE)
2040 				add_tail = MFALSE;
2041 		}
2042 	}
2043 
2044 	if (add_tail) {
2045 		util_enqueue_list_tail(pmadapter->pmoal_handle,
2046 				       &pmadapter->cmd_pending_q,
2047 				       (pmlan_linked_list)pcmd_node, MNULL,
2048 				       MNULL);
2049 	} else {
2050 		util_enqueue_list_head(pmadapter->pmoal_handle,
2051 				       &pmadapter->cmd_pending_q,
2052 				       (pmlan_linked_list)pcmd_node, MNULL,
2053 				       MNULL);
2054 	}
2055 
2056 	PRINTM_NETINTF(MCMND, pcmd_node->priv);
2057 	PRINTM(MCMND, "QUEUE_CMD: cmd=0x%x is queued\n", command);
2058 
2059 done:
2060 	LEAVE();
2061 	return;
2062 }
2063 
2064 /**
2065  *  @brief This function executes next command in command
2066  *      pending queue. It will put firmware back to PS mode
2067  *      if applicable.
2068  *
2069  *  @param pmadapter     A pointer to mlan_adapter structure
2070  *
2071  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2072  */
wlan_exec_next_cmd(mlan_adapter * pmadapter)2073 mlan_status wlan_exec_next_cmd(mlan_adapter *pmadapter)
2074 {
2075 	mlan_private *priv = MNULL;
2076 	cmd_ctrl_node *pcmd_node = MNULL;
2077 	mlan_status ret = MLAN_STATUS_SUCCESS;
2078 	HostCmd_DS_COMMAND *pcmd;
2079 
2080 	ENTER();
2081 
2082 	/* Sanity test */
2083 	if (pmadapter == MNULL) {
2084 		PRINTM(MERROR, "EXEC_NEXT_CMD: pmadapter is MNULL\n");
2085 		ret = MLAN_STATUS_FAILURE;
2086 		goto done;
2087 	}
2088 	/* Check if already in processing */
2089 	if (pmadapter->curr_cmd) {
2090 		PRINTM(MERROR,
2091 		       "EXEC_NEXT_CMD: there is command in processing!\n");
2092 		ret = MLAN_STATUS_FAILURE;
2093 		goto done;
2094 	}
2095 
2096 	wlan_request_cmd_lock(pmadapter);
2097 	/* Check if any command is pending */
2098 	pcmd_node = (cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
2099 						    &pmadapter->cmd_pending_q,
2100 						    MNULL, MNULL);
2101 
2102 	if (pcmd_node) {
2103 		pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
2104 					      pcmd_node->cmdbuf->data_offset);
2105 		priv = pcmd_node->priv;
2106 
2107 		if (pmadapter->ps_state != PS_STATE_AWAKE) {
2108 			PRINTM(MERROR,
2109 			       "Cannot send command in sleep state, this should not happen\n");
2110 			wlan_release_cmd_lock(pmadapter);
2111 			goto done;
2112 		}
2113 
2114 		util_unlink_list(pmadapter->pmoal_handle,
2115 				 &pmadapter->cmd_pending_q,
2116 				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
2117 		wlan_release_cmd_lock(pmadapter);
2118 		ret = wlan_dnld_cmd_to_fw(priv, pcmd_node);
2119 		priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
2120 		/* Any command sent to the firmware when host is in sleep mode,
2121 		 * should de-configure host sleep */
2122 		/* We should skip the host sleep configuration command itself
2123 		 * though */
2124 		if (priv && (pcmd->command !=
2125 			     wlan_cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH))) {
2126 			if (pmadapter->hs_activated == MTRUE) {
2127 				pmadapter->is_hs_configured = MFALSE;
2128 				wlan_host_sleep_activated_event(priv, MFALSE);
2129 			}
2130 		}
2131 		goto done;
2132 	} else {
2133 		wlan_release_cmd_lock(pmadapter);
2134 	}
2135 	ret = MLAN_STATUS_SUCCESS;
2136 done:
2137 	LEAVE();
2138 	return ret;
2139 }
2140 
2141 /**
2142  *  @brief This function handles the command response
2143  *
2144  *  @param pmadapter    A pointer to mlan_adapter structure
2145  *
2146  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2147  */
wlan_process_cmdresp(mlan_adapter * pmadapter)2148 mlan_status wlan_process_cmdresp(mlan_adapter *pmadapter)
2149 {
2150 	HostCmd_DS_COMMAND *resp = MNULL;
2151 	mlan_private *pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
2152 	mlan_private *pmpriv_next = MNULL;
2153 	mlan_status ret = MLAN_STATUS_SUCCESS;
2154 	t_u16 orig_cmdresp_no;
2155 	t_u16 cmdresp_no;
2156 	t_u16 cmdresp_result;
2157 	mlan_ioctl_req *pioctl_buf = MNULL;
2158 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
2159 #ifdef DEBUG_LEVEL1
2160 	t_u32 sec = 0, usec = 0;
2161 #endif
2162 	t_u32 i;
2163 
2164 	ENTER();
2165 
2166 	if (pmadapter->curr_cmd)
2167 		if (pmadapter->curr_cmd->pioctl_buf != MNULL) {
2168 			pioctl_buf = (mlan_ioctl_req *)
2169 					     pmadapter->curr_cmd->pioctl_buf;
2170 		}
2171 
2172 	if (!pmadapter->curr_cmd || !pmadapter->curr_cmd->respbuf) {
2173 		resp = (HostCmd_DS_COMMAND *)pmadapter->upld_buf;
2174 		resp->command = wlan_le16_to_cpu(resp->command);
2175 		PRINTM(MERROR, "CMD_RESP: No curr_cmd, 0x%x\n", resp->command);
2176 		if (pioctl_buf)
2177 			pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
2178 		ret = MLAN_STATUS_FAILURE;
2179 		goto done;
2180 	}
2181 
2182 	DBG_HEXDUMP(MCMD_D, "CMD_RESP",
2183 		    pmadapter->curr_cmd->respbuf->pbuf +
2184 			    pmadapter->curr_cmd->respbuf->data_offset,
2185 		    pmadapter->curr_cmd->respbuf->data_len);
2186 
2187 	resp = (HostCmd_DS_COMMAND *)(pmadapter->curr_cmd->respbuf->pbuf +
2188 				      pmadapter->curr_cmd->respbuf->data_offset);
2189 	orig_cmdresp_no = wlan_le16_to_cpu(resp->command);
2190 	cmdresp_no = (orig_cmdresp_no & HostCmd_CMD_ID_MASK);
2191 	if (pmadapter->curr_cmd->cmd_no != cmdresp_no) {
2192 		PRINTM(MERROR, "cmdresp error: cmd=0x%x cmd_resp=0x%x\n",
2193 		       pmadapter->curr_cmd->cmd_no, cmdresp_no);
2194 		ret = MLAN_STATUS_FAILURE;
2195 		goto done;
2196 	}
2197 	pmadapter->dnld_cmd_in_secs = 0;
2198 	/* Now we got response from FW, cancel the command timer */
2199 	if (pmadapter->cmd_timer_is_set) {
2200 		/* Cancel command timeout timer */
2201 		pcb->moal_stop_timer(pmadapter->pmoal_handle,
2202 				     pmadapter->pmlan_cmd_timer);
2203 		/* Cancel command timeout timer */
2204 		pmadapter->cmd_timer_is_set = MFALSE;
2205 	}
2206 	pmadapter->num_cmd_timeout = 0;
2207 	wlan_request_cmd_lock(pmadapter);
2208 	if (pmadapter->curr_cmd->cmd_flag & CMD_F_CANCELED) {
2209 		cmd_ctrl_node *free_cmd = pmadapter->curr_cmd;
2210 		pmadapter->curr_cmd = MNULL;
2211 		PRINTM(MCMND, "CMD_RESP: 0x%x been canceled!\n",
2212 		       wlan_le16_to_cpu(resp->command));
2213 		if (pioctl_buf)
2214 			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2215 		wlan_insert_cmd_to_free_q(pmadapter, free_cmd);
2216 		wlan_release_cmd_lock(pmadapter);
2217 		ret = MLAN_STATUS_FAILURE;
2218 		goto done;
2219 	} else {
2220 		wlan_release_cmd_lock(pmadapter);
2221 	}
2222 	if (pmadapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
2223 		/* Copy original response back to response buffer */
2224 		if (pmpriv)
2225 			wlan_ret_host_cmd(pmpriv, resp, pioctl_buf);
2226 	}
2227 	resp->size = wlan_le16_to_cpu(resp->size);
2228 	resp->seq_num = wlan_le16_to_cpu(resp->seq_num);
2229 	resp->result = wlan_le16_to_cpu(resp->result);
2230 
2231 	/* Get BSS number and corresponding priv */
2232 	pmpriv = wlan_get_priv_by_id(pmadapter,
2233 				     HostCmd_GET_BSS_NO(resp->seq_num),
2234 				     HostCmd_GET_BSS_TYPE(resp->seq_num));
2235 	if (!pmpriv)
2236 		pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
2237 	/* Clear RET_BIT from HostCmd */
2238 	resp->command = (orig_cmdresp_no & HostCmd_CMD_ID_MASK);
2239 	if (!pmpriv) {
2240 		ret = MLAN_STATUS_FAILURE;
2241 		goto done;
2242 	}
2243 	cmdresp_no = resp->command;
2244 
2245 	cmdresp_result = resp->result;
2246 
2247 	/* Save the last command response to debug log */
2248 	pmadapter->dbg.last_cmd_resp_index =
2249 		(pmadapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM;
2250 	pmadapter->dbg.last_cmd_resp_id[pmadapter->dbg.last_cmd_resp_index] =
2251 		orig_cmdresp_no;
2252 
2253 	PRINTM_GET_SYS_TIME(MCMND, &sec, &usec);
2254 	PRINTM_NETINTF(MCMND, pmadapter->curr_cmd->priv);
2255 	PRINTM(MCMND,
2256 	       "CMD_RESP (%lu.%06lu): 0x%x, result %d, len %d, seqno 0x%x\n",
2257 	       sec, usec, orig_cmdresp_no, cmdresp_result, resp->size,
2258 	       resp->seq_num);
2259 
2260 	if (!(orig_cmdresp_no & HostCmd_RET_BIT)) {
2261 		PRINTM(MERROR, "CMD_RESP: Invalid response to command!\n");
2262 		if (pioctl_buf)
2263 			pioctl_buf->status_code = MLAN_ERROR_FW_CMDRESP;
2264 		wlan_request_cmd_lock(pmadapter);
2265 		wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
2266 		pmadapter->curr_cmd = MNULL;
2267 		wlan_release_cmd_lock(pmadapter);
2268 		ret = MLAN_STATUS_FAILURE;
2269 		goto done;
2270 	}
2271 
2272 	if (pmadapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
2273 		pmadapter->curr_cmd->cmd_flag &= ~CMD_F_HOSTCMD;
2274 		if ((cmdresp_result == HostCmd_RESULT_OK) &&
2275 		    (cmdresp_no == HostCmd_CMD_802_11_HS_CFG_ENH))
2276 			ret = wlan_ret_802_11_hs_cfg(pmpriv, resp, pioctl_buf);
2277 	} else {
2278 		/* handle response */
2279 		ret = pmpriv->ops.process_cmdresp(pmpriv, cmdresp_no, resp,
2280 						  pioctl_buf);
2281 	}
2282 
2283 	/* Check init command response */
2284 	if (pmadapter->hw_status == WlanHardwareStatusInitializing ||
2285 	    pmadapter->hw_status == WlanHardwareStatusGetHwSpec) {
2286 		if (ret == MLAN_STATUS_FAILURE) {
2287 #if 0
2288             //ignore command error for WARM RESET
2289 			if (pmadapter->pwarm_reset_ioctl_req) {
2290 				/* warm reset failure */
2291 				pmadapter->pwarm_reset_ioctl_req->status_code =
2292 					MLAN_ERROR_CMD_RESP_FAIL;
2293 				pcb->moal_ioctl_complete(
2294 					pmadapter->pmoal_handle,
2295 					pmadapter->pwarm_reset_ioctl_req,
2296 					MLAN_STATUS_FAILURE);
2297 				pmadapter->pwarm_reset_ioctl_req = MNULL;
2298 				goto done;
2299 			}
2300 #endif
2301 			PRINTM(MERROR,
2302 			       "cmd 0x%02x failed during initialization\n",
2303 			       cmdresp_no);
2304 			wlan_init_fw_complete(pmadapter);
2305 			goto done;
2306 		}
2307 #ifdef STA_SUPPORT
2308 #ifdef PCIE
2309 		/* init adma write pointer */
2310 		if (IS_PCIE(pmadapter->card_type) &&
2311 		    cmdresp_no == HostCmd_CMD_FUNC_SHUTDOWN &&
2312 		    pmadapter->pwarm_reset_ioctl_req) {
2313 #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIENW62X)
2314 			if (pmadapter->pcard_pcie->reg->use_adma)
2315 #endif
2316 				wlan_pcie_init_fw(pmadapter);
2317 		}
2318 #endif
2319 #endif
2320 	}
2321 
2322 	wlan_request_cmd_lock(pmadapter);
2323 	if (pmadapter->curr_cmd) {
2324 		cmd_ctrl_node *free_cmd = pmadapter->curr_cmd;
2325 		pioctl_buf = (mlan_ioctl_req *)pmadapter->curr_cmd->pioctl_buf;
2326 		pmadapter->curr_cmd = MNULL;
2327 		if (pioctl_buf && (ret == MLAN_STATUS_SUCCESS))
2328 			pioctl_buf->status_code = MLAN_ERROR_NO_ERROR;
2329 		else if (pioctl_buf && (ret == MLAN_STATUS_FAILURE) &&
2330 			 !pioctl_buf->status_code)
2331 			pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
2332 
2333 		/* Clean up and put current command back to cmd_free_q */
2334 		wlan_insert_cmd_to_free_q(pmadapter, free_cmd);
2335 	}
2336 	wlan_release_cmd_lock(pmadapter);
2337 
2338 	if ((pmadapter->hw_status == WlanHardwareStatusInitializing) &&
2339 	    (pmadapter->last_init_cmd == cmdresp_no)) {
2340 		i = pmpriv->bss_index + 1;
2341 		while (i < pmadapter->priv_num &&
2342 		       (!(pmpriv_next = pmadapter->priv[i]) ||
2343 			pmpriv_next->bss_virtual ||
2344 			pmpriv_next->bss_type == MLAN_BSS_TYPE_DFS))
2345 			i++;
2346 		if (!pmpriv_next || i >= pmadapter->priv_num) {
2347 #ifdef STA_SUPPORT
2348 			if (pmadapter->pwarm_reset_ioctl_req) {
2349 				for (i = 0; i < pmadapter->priv_num; i++) {
2350 					if (pmadapter->priv[i]->curr_addr[0] ==
2351 					    0xff)
2352 						memmove(pmadapter,
2353 							pmadapter->priv[i]
2354 								->curr_addr,
2355 							pmadapter->permanent_addr,
2356 							MLAN_MAC_ADDR_LENGTH);
2357 				}
2358 				/* warm reset complete */
2359 				PRINTM(MMSG, "wlan: warm reset complete\n");
2360 				pmadapter->hw_status = WlanHardwareStatusReady;
2361 				pcb->moal_ioctl_complete(
2362 					pmadapter->pmoal_handle,
2363 					pmadapter->pwarm_reset_ioctl_req,
2364 					MLAN_STATUS_SUCCESS);
2365 				pmadapter->pwarm_reset_ioctl_req = MNULL;
2366 				goto done;
2367 			}
2368 #endif
2369 			pmadapter->hw_status = WlanHardwareStatusInitdone;
2370 		} else {
2371 			/* Issue init commands for the next interface */
2372 			ret = pmpriv_next->ops.init_cmd(pmpriv_next, MFALSE);
2373 		}
2374 	} else if ((pmadapter->hw_status == WlanHardwareStatusGetHwSpec) &&
2375 		   (HostCmd_CMD_GET_HW_SPEC == cmdresp_no)) {
2376 		pmadapter->hw_status = WlanHardwareStatusGetHwSpecdone;
2377 	}
2378 done:
2379 	LEAVE();
2380 	return ret;
2381 }
2382 
2383 /**
2384  *  @brief This function handles the timeout of command sending.
2385  *          It will re-send the same command again.
2386  *
2387  *  @param function_context   A pointer to function_context
2388  *  @return                   N/A
2389  */
wlan_cmd_timeout_func(t_void * function_context)2390 t_void wlan_cmd_timeout_func(t_void *function_context)
2391 {
2392 	mlan_adapter *pmadapter = (mlan_adapter *)function_context;
2393 	cmd_ctrl_node *pcmd_node = MNULL;
2394 	mlan_ioctl_req *pioctl_buf = MNULL;
2395 #ifdef DEBUG_LEVEL1
2396 	t_u32 sec = 0, usec = 0;
2397 #endif
2398 #if defined(SDIO) || defined(PCIE)
2399 	t_u8 i;
2400 #endif
2401 	mlan_private *pmpriv = MNULL;
2402 
2403 	ENTER();
2404 
2405 	pmadapter->cmd_timer_is_set = MFALSE;
2406 	if (!pmadapter->curr_cmd) {
2407 		if (pmadapter->ext_scan && pmadapter->ext_scan_enh &&
2408 		    pmadapter->scan_processing) {
2409 			PRINTM(MMSG, "Ext scan enh timeout\n");
2410 			pmadapter->ext_scan_timeout = MTRUE;
2411 			wlan_dump_info(pmadapter, REASON_CODE_EXT_SCAN_TIMEOUT);
2412 			goto exit;
2413 		}
2414 		PRINTM(MWARN, "CurCmd Empty\n");
2415 		goto exit;
2416 	}
2417 	pmadapter->num_cmd_timeout++;
2418 	pcmd_node = pmadapter->curr_cmd;
2419 	if (pcmd_node->pioctl_buf != MNULL) {
2420 		pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
2421 		pioctl_buf->status_code = MLAN_ERROR_CMD_TIMEOUT;
2422 	}
2423 
2424 	pmadapter->dbg.timeout_cmd_id =
2425 		pmadapter->dbg.last_cmd_id[pmadapter->dbg.last_cmd_index];
2426 	pmadapter->dbg.timeout_cmd_act =
2427 		pmadapter->dbg.last_cmd_act[pmadapter->dbg.last_cmd_index];
2428 	PRINTM_GET_SYS_TIME(MERROR, &sec, &usec);
2429 	PRINTM(MERROR, "Timeout cmd id (%lu.%06lu) = 0x%x, act = 0x%x\n", sec,
2430 	       usec, pmadapter->dbg.timeout_cmd_id,
2431 	       pmadapter->dbg.timeout_cmd_act);
2432 #if defined(SDIO) || defined(PCIE)
2433 	if (!IS_USB(pmadapter->card_type) && pcmd_node->cmdbuf) {
2434 		t_u8 *pcmd_buf;
2435 		pcmd_buf = pcmd_node->cmdbuf->pbuf +
2436 			   pcmd_node->cmdbuf->data_offset +
2437 			   pmadapter->ops.intf_header_len;
2438 		for (i = 0; i < 16; i++)
2439 			PRINTM(MERROR, "%02x ", *pcmd_buf++);
2440 		PRINTM(MERROR, "\n");
2441 	}
2442 #endif
2443 #ifdef PCIE
2444 	if (IS_PCIE(pmadapter->card_type))
2445 		pmadapter->ops.debug_dump(pmadapter);
2446 #endif
2447 	pmpriv = pcmd_node->priv;
2448 	if (pmpriv)
2449 		PRINTM(MERROR, "BSS type = %d BSS role= %d\n", pmpriv->bss_type,
2450 		       pmpriv->bss_role);
2451 	wlan_dump_info(pmadapter, REASON_CODE_CMD_TIMEOUT);
2452 
2453 	if (pmadapter->hw_status == WlanHardwareStatusInitializing ||
2454 	    pmadapter->hw_status == WlanHardwareStatusGetHwSpec)
2455 		wlan_init_fw_complete(pmadapter);
2456 	else {
2457 		/* Signal MOAL to perform extra handling for debugging */
2458 		if (pmpriv) {
2459 			wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DBG_DUMP,
2460 					MNULL);
2461 		} else {
2462 			wlan_recv_event(wlan_get_priv(pmadapter,
2463 						      MLAN_BSS_ROLE_ANY),
2464 					MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
2465 		}
2466 	}
2467 
2468 exit:
2469 	LEAVE();
2470 	return;
2471 }
2472 
2473 #ifdef STA_SUPPORT
2474 /**
2475  *  @brief Internal function used to flush the scan pending queue
2476  *
2477  *  @param pmadapter    A pointer to mlan_adapter structure
2478  *
2479  *  @return             N/A
2480  */
wlan_flush_scan_queue(pmlan_adapter pmadapter)2481 t_void wlan_flush_scan_queue(pmlan_adapter pmadapter)
2482 {
2483 	cmd_ctrl_node *pcmd_node = MNULL;
2484 	mlan_ioctl_req *pioctl_buf = MNULL;
2485 	HostCmd_DS_COMMAND *pcmd = MNULL;
2486 	t_u16 cmd_no = 0;
2487 	pmlan_callbacks pcb = &pmadapter->callbacks;
2488 	ENTER();
2489 
2490 	wlan_request_cmd_lock(pmadapter);
2491 	while ((pcmd_node = (cmd_ctrl_node *)util_peek_list(
2492 			pmadapter->pmoal_handle, &pmadapter->scan_pending_q,
2493 			MNULL, MNULL))) {
2494 		util_unlink_list(pmadapter->pmoal_handle,
2495 				 &pmadapter->scan_pending_q,
2496 				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
2497 		pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
2498 					      pcmd_node->cmdbuf->data_offset);
2499 		cmd_no = wlan_le16_to_cpu(pcmd->command);
2500 		PRINTM(MCMND, "flush scan queue: cmd 0x%02x\n", cmd_no);
2501 		if (pcmd_node->pioctl_buf &&
2502 		    cmd_no != HostCmd_CMD_802_11_SCAN &&
2503 		    cmd_no != HostCmd_CMD_802_11_SCAN_EXT) {
2504 			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
2505 			pcmd_node->pioctl_buf = MNULL;
2506 			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2507 			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
2508 						 pioctl_buf,
2509 						 MLAN_STATUS_FAILURE);
2510 		}
2511 		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
2512 	}
2513 
2514 	pmadapter->scan_processing = MFALSE;
2515 	wlan_release_cmd_lock(pmadapter);
2516 
2517 	LEAVE();
2518 }
2519 
2520 /**
2521  *  @brief Cancel pending SCAN ioctl cmd.
2522  *
2523  *  @param pmadapter    A pointer to mlan_adapter
2524  *  @param pioctl_req   A pointer to pmlan_ioctl_req
2525  *
2526  *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
2527  */
wlan_cancel_pending_scan_cmd(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2528 mlan_status wlan_cancel_pending_scan_cmd(pmlan_adapter pmadapter,
2529 					 pmlan_ioctl_req pioctl_req)
2530 {
2531 	pmlan_callbacks pcb = &pmadapter->callbacks;
2532 	cmd_ctrl_node *pcmd_node = MNULL;
2533 	mlan_ioctl_req *pioctl_buf = MNULL;
2534 	pmlan_private priv = MNULL;
2535 	mlan_status status = MLAN_STATUS_SUCCESS;
2536 	ENTER();
2537 
2538 	PRINTM(MIOCTL, "Cancel scan command\n");
2539 	wlan_request_cmd_lock(pmadapter);
2540 	/* IOCTL will be completed, avoid calling IOCTL complete again from
2541 	 * EVENT/CMDRESP */
2542 	if (pmadapter->pscan_ioctl_req) {
2543 		pioctl_buf = pmadapter->pscan_ioctl_req;
2544 		priv = pmadapter->priv[pioctl_buf->bss_index];
2545 		pmadapter->pscan_ioctl_req = MNULL;
2546 		pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2547 		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
2548 					 MLAN_STATUS_FAILURE);
2549 	}
2550 
2551 	if (pmadapter->curr_cmd && pmadapter->curr_cmd->pioctl_buf) {
2552 		pioctl_buf = (mlan_ioctl_req *)pmadapter->curr_cmd->pioctl_buf;
2553 		if (pioctl_buf->req_id == MLAN_IOCTL_SCAN) {
2554 			PRINTM(MIOCTL, "wlan_cancel_scan: current command\n");
2555 			pcmd_node = pmadapter->curr_cmd;
2556 			pcmd_node->pioctl_buf = MNULL;
2557 			pcmd_node->cmd_flag |= CMD_F_CANCELED;
2558 			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2559 			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
2560 						 pioctl_buf,
2561 						 MLAN_STATUS_FAILURE);
2562 		}
2563 	}
2564 	while ((pcmd_node = wlan_get_pending_scan_cmd(pmadapter)) != MNULL) {
2565 		PRINTM(MIOCTL,
2566 		       "wlan_cancel_scan: find scan command in cmd_pending_q\n");
2567 		util_unlink_list(pmadapter->pmoal_handle,
2568 				 &pmadapter->cmd_pending_q,
2569 				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
2570 		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
2571 	}
2572 	wlan_release_cmd_lock(pmadapter);
2573 	if (pmadapter->scan_processing &&
2574 	    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
2575 		if (priv) {
2576 			if (MLAN_STATUS_SUCCESS ==
2577 			    wlan_prepare_cmd(priv, HostCmd_CMD_802_11_SCAN_EXT,
2578 					     HostCmd_ACT_GEN_SET, 0, pioctl_req,
2579 					     MNULL)) {
2580 				wlan_recv_event(
2581 					priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
2582 					MNULL);
2583 				status = MLAN_STATUS_PENDING;
2584 			}
2585 		}
2586 	}
2587 	/* Cancel all pending scan command */
2588 	wlan_flush_scan_queue(pmadapter);
2589 	LEAVE();
2590 	return status;
2591 }
2592 #endif
2593 
2594 /**
2595  *  @brief Cancel all pending cmd.
2596  *
2597  *  @param pmadapter    A pointer to mlan_adapter
2598  *  @param flag         MTRUE/MFALSE
2599  *
2600  *  @return             N/A
2601  */
wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter,t_u8 flag)2602 t_void wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter, t_u8 flag)
2603 {
2604 	cmd_ctrl_node *pcmd_node = MNULL;
2605 	pmlan_callbacks pcb = &pmadapter->callbacks;
2606 	mlan_ioctl_req *pioctl_buf = MNULL;
2607 #ifdef STA_SUPPORT
2608 	pmlan_private priv = MNULL;
2609 #endif
2610 	ENTER();
2611 	/* Cancel current cmd */
2612 	wlan_request_cmd_lock(pmadapter);
2613 #ifdef STA_SUPPORT
2614 	/* IOCTL will be completed, avoid calling IOCTL complete again from
2615 	 * EVENT/CMDRESP */
2616 	if (pmadapter->pscan_ioctl_req) {
2617 		pioctl_buf = pmadapter->pscan_ioctl_req;
2618 		priv = pmadapter->priv[pioctl_buf->bss_index];
2619 		pmadapter->pscan_ioctl_req = MNULL;
2620 		pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2621 		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
2622 					 MLAN_STATUS_FAILURE);
2623 	}
2624 #endif
2625 	if (pmadapter->curr_cmd) {
2626 		pcmd_node = pmadapter->curr_cmd;
2627 		if (pcmd_node->pioctl_buf) {
2628 			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
2629 			pcmd_node->pioctl_buf = MNULL;
2630 			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2631 			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
2632 						 pioctl_buf,
2633 						 MLAN_STATUS_FAILURE);
2634 		}
2635 		if (flag) {
2636 			pmadapter->curr_cmd = MNULL;
2637 			wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
2638 		}
2639 	}
2640 
2641 	/* Cancel all pending command */
2642 	while ((pcmd_node = (cmd_ctrl_node *)util_peek_list(
2643 			pmadapter->pmoal_handle, &pmadapter->cmd_pending_q,
2644 			MNULL, MNULL))) {
2645 		util_unlink_list(pmadapter->pmoal_handle,
2646 				 &pmadapter->cmd_pending_q,
2647 				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
2648 		if (pcmd_node->pioctl_buf) {
2649 			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
2650 			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2651 			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
2652 						 pioctl_buf,
2653 						 MLAN_STATUS_FAILURE);
2654 			pcmd_node->pioctl_buf = MNULL;
2655 		}
2656 		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
2657 	}
2658 	wlan_release_cmd_lock(pmadapter);
2659 	/* Cancel all pending scan command */
2660 	wlan_flush_scan_queue(pmadapter);
2661 	/* Cancel all pending command in scan_cmd_pending_q command */
2662 	wlan_flush_ext_cmd_pending_queue(pmadapter);
2663 	LEAVE();
2664 }
2665 
2666 /**
2667  *  @brief Cancel specific bss's pending ioctl cmd.
2668  *
2669  *  @param pmadapter    A pointer to mlan_adapter
2670  *  @param bss_index    BSS index
2671  *
2672  *  @return             N/A
2673  */
wlan_cancel_bss_pending_cmd(pmlan_adapter pmadapter,t_u32 bss_index)2674 t_void wlan_cancel_bss_pending_cmd(pmlan_adapter pmadapter, t_u32 bss_index)
2675 {
2676 	pmlan_callbacks pcb = &pmadapter->callbacks;
2677 	cmd_ctrl_node *pcmd_node = MNULL;
2678 	mlan_ioctl_req *pioctl_buf = MNULL;
2679 #ifdef STA_SUPPORT
2680 	t_u8 flash_scan = MFALSE;
2681 #endif
2682 #ifdef STA_SUPPORT
2683 	pmlan_private priv = MNULL;
2684 #endif
2685 	ENTER();
2686 
2687 	PRINTM(MIOCTL, "MOAL Cancel BSS IOCTL: bss_index=%d\n", (int)bss_index);
2688 	wlan_request_cmd_lock(pmadapter);
2689 #ifdef STA_SUPPORT
2690 	if (pmadapter->pscan_ioctl_req &&
2691 	    (pmadapter->pscan_ioctl_req->bss_index == bss_index)) {
2692 		/* IOCTL will be completed, avoid calling IOCTL complete again
2693 		 * from EVENT/CMDRESP */
2694 		flash_scan = MTRUE;
2695 		pioctl_buf = pmadapter->pscan_ioctl_req;
2696 		priv = pmadapter->priv[pioctl_buf->bss_index];
2697 		pmadapter->pscan_ioctl_req = MNULL;
2698 		pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2699 		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
2700 					 MLAN_STATUS_FAILURE);
2701 	}
2702 #endif
2703 	if (pmadapter->curr_cmd && pmadapter->curr_cmd->pioctl_buf) {
2704 		pioctl_buf = (mlan_ioctl_req *)pmadapter->curr_cmd->pioctl_buf;
2705 		if (pioctl_buf->bss_index == bss_index) {
2706 			pcmd_node = pmadapter->curr_cmd;
2707 			pcmd_node->pioctl_buf = MNULL;
2708 			pcmd_node->cmd_flag |= CMD_F_CANCELED;
2709 #ifdef STA_SUPPORT
2710 			if (pioctl_buf->req_id == MLAN_IOCTL_SCAN)
2711 				flash_scan = MTRUE;
2712 #endif
2713 			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2714 			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
2715 						 pioctl_buf,
2716 						 MLAN_STATUS_FAILURE);
2717 		}
2718 	}
2719 	while ((pcmd_node = wlan_get_bss_pending_ioctl_cmd(
2720 			pmadapter, bss_index)) != MNULL) {
2721 		util_unlink_list(pmadapter->pmoal_handle,
2722 				 &pmadapter->cmd_pending_q,
2723 				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
2724 		pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
2725 		pcmd_node->pioctl_buf = MNULL;
2726 #ifdef STA_SUPPORT
2727 		if (pioctl_buf->req_id == MLAN_IOCTL_SCAN)
2728 			flash_scan = MTRUE;
2729 #endif
2730 		pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2731 		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
2732 					 MLAN_STATUS_FAILURE);
2733 		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
2734 	}
2735 	wlan_release_cmd_lock(pmadapter);
2736 #ifdef STA_SUPPORT
2737 	if (flash_scan) {
2738 		if (pmadapter->scan_processing &&
2739 		    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
2740 			if (priv) {
2741 				if (MLAN_STATUS_FAILURE ==
2742 				    wlan_prepare_cmd(
2743 					    priv, HostCmd_CMD_802_11_SCAN_EXT,
2744 					    HostCmd_ACT_GEN_SET, 0, MNULL,
2745 					    MNULL))
2746 					PRINTM(MERROR,
2747 					       "failed to prepare command");
2748 				wlan_recv_event(
2749 					priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
2750 					MNULL);
2751 			}
2752 		}
2753 		/* Cancel all pending scan command */
2754 		wlan_flush_scan_queue(pmadapter);
2755 	}
2756 #endif
2757 	LEAVE();
2758 	return;
2759 }
2760 
2761 /**
2762  *  @brief Cancel pending ioctl cmd.
2763  *
2764  *  @param pmadapter    A pointer to mlan_adapter
2765  *  @param pioctl_req   A pointer to mlan_ioctl_req buf
2766  *
2767  *  @return             N/A
2768  */
wlan_cancel_pending_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2769 t_void wlan_cancel_pending_ioctl(pmlan_adapter pmadapter,
2770 				 pmlan_ioctl_req pioctl_req)
2771 {
2772 	pmlan_callbacks pcb = &pmadapter->callbacks;
2773 	cmd_ctrl_node *pcmd_node = MNULL;
2774 	t_u8 find = MFALSE;
2775 #ifdef STA_SUPPORT
2776 	pmlan_private priv = MNULL;
2777 #endif
2778 
2779 	ENTER();
2780 
2781 	PRINTM(MIOCTL, "MOAL Cancel IOCTL: 0x%x sub_id=0x%x action=%d\n",
2782 	       pioctl_req->req_id, *((t_u32 *)pioctl_req->pbuf),
2783 	       (int)pioctl_req->action);
2784 
2785 	wlan_request_cmd_lock(pmadapter);
2786 #ifdef STA_SUPPORT
2787 	/* IOCTL will be completed, avoid calling IOCTL complete again from
2788 	 * EVENT/CMDRESP */
2789 	if (pmadapter->pscan_ioctl_req == pioctl_req) {
2790 		priv = pmadapter->priv[pioctl_req->bss_index];
2791 		pmadapter->pscan_ioctl_req = MNULL;
2792 		find = MTRUE;
2793 	}
2794 #endif
2795 	if ((pmadapter->curr_cmd) &&
2796 	    (pmadapter->curr_cmd->pioctl_buf == pioctl_req)) {
2797 		pcmd_node = pmadapter->curr_cmd;
2798 		pcmd_node->pioctl_buf = MNULL;
2799 		pcmd_node->cmd_flag |= CMD_F_CANCELED;
2800 		find = MTRUE;
2801 	}
2802 
2803 	while ((pcmd_node = wlan_get_pending_ioctl_cmd(pmadapter,
2804 						       pioctl_req)) != MNULL) {
2805 		util_unlink_list(pmadapter->pmoal_handle,
2806 				 &pmadapter->cmd_pending_q,
2807 				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
2808 		pcmd_node->pioctl_buf = MNULL;
2809 		find = MTRUE;
2810 		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
2811 	}
2812 	wlan_release_cmd_lock(pmadapter);
2813 #ifdef STA_SUPPORT
2814 	if (pioctl_req->req_id == MLAN_IOCTL_SCAN) {
2815 		if (pmadapter->scan_processing &&
2816 		    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
2817 			if (priv) {
2818 				if (MLAN_STATUS_FAILURE ==
2819 				    wlan_prepare_cmd(
2820 					    priv, HostCmd_CMD_802_11_SCAN_EXT,
2821 					    HostCmd_ACT_GEN_SET, 0, MNULL,
2822 					    MNULL))
2823 					PRINTM(MERROR,
2824 					       "Failed to prepare command");
2825 				wlan_recv_event(
2826 					priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
2827 					MNULL);
2828 			}
2829 		}
2830 		/* Cancel all pending scan command */
2831 		wlan_flush_scan_queue(pmadapter);
2832 	}
2833 #endif
2834 	if (find) {
2835 		pioctl_req->status_code = MLAN_ERROR_CMD_CANCEL;
2836 		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_req,
2837 					 MLAN_STATUS_FAILURE);
2838 	}
2839 
2840 	LEAVE();
2841 	return;
2842 }
2843 
2844 /**
2845  *  @brief This function convert mlan_wifi_rate to wifi_rate.
2846  *
2847  *  @param pmpriv       A pointer to mlan_private structure
2848  *  @param pmlan_rate          A pointer to mlan_wifi_rate structure
2849  *  @param prate   A pointer to wifi_rate
2850  *
2851  *  @return           N/A
2852  */
wlan_fill_hal_wifi_rate(pmlan_private pmpriv,mlan_wifi_rate * pmlan_rate,wifi_rate * prate)2853 t_void wlan_fill_hal_wifi_rate(pmlan_private pmpriv, mlan_wifi_rate *pmlan_rate,
2854 			       wifi_rate *prate)
2855 {
2856 	t_u8 index = 0;
2857 	t_u8 rate_info = 0;
2858 
2859 	ENTER();
2860 
2861 	prate->preamble = pmlan_rate->preamble;
2862 	prate->nss = pmlan_rate->nss;
2863 	prate->bw = pmlan_rate->bw;
2864 	prate->rateMcsIdx = pmlan_rate->rateMcsIdx;
2865 	prate->reserved = 0;
2866 	prate->bitrate = wlan_le32_to_cpu(pmlan_rate->bitrate);
2867 
2868 	if (!prate->bitrate) {
2869 		index = prate->rateMcsIdx;
2870 		index |= prate->nss << 4;
2871 		if (prate->preamble == WIFI_PREAMBLE_HT)
2872 			rate_info = MLAN_RATE_FORMAT_HT;
2873 		else if (prate->preamble == WIFI_PREAMBLE_VHT)
2874 			rate_info = MLAN_RATE_FORMAT_VHT;
2875 		else
2876 			rate_info = MLAN_RATE_FORMAT_LG;
2877 		rate_info |= prate->bw << 2;
2878 		PRINTM(MCMND, "index=0x%x rate_info=0x%x\n", index, rate_info);
2879 		/** For rateMcsIdx, OFDM/CCK rate code would be as per ieee std
2880 		 * in the units of 0.5mbps. HT/VHT it would be mcs index */
2881 		/** For bitrate, in 100kbps */
2882 		if (rate_info == MLAN_RATE_FORMAT_LG)
2883 			prate->bitrate = prate->rateMcsIdx * 5;
2884 		else
2885 			prate->bitrate =
2886 				wlan_index_to_data_rate(pmpriv->adapter, index,
2887 							rate_info, 0) *
2888 				5;
2889 		PRINTM(MCMND, "bitrate(in 100kbps)=%d\n", prate->bitrate);
2890 	}
2891 
2892 	LEAVE();
2893 }
2894 
2895 /**
2896  *  @brief Handle the version_ext resp
2897  *
2898  *  @param pmpriv       A pointer to mlan_private structure
2899  *  @param resp         A pointer to HostCmd_DS_COMMAND
2900  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
2901  *
2902  *  @return             MLAN_STATUS_SUCCESS
2903  */
wlan_ret_ver_ext(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)2904 mlan_status wlan_ret_ver_ext(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
2905 			     mlan_ioctl_req *pioctl_buf)
2906 {
2907 	HostCmd_DS_VERSION_EXT *ver_ext = &resp->params.verext;
2908 	mlan_ds_get_info *info;
2909 	ENTER();
2910 	if (pioctl_buf) {
2911 		info = (mlan_ds_get_info *)pioctl_buf->pbuf;
2912 		info->param.ver_ext.version_str_sel = ver_ext->version_str_sel;
2913 		memcpy_ext(pmpriv->adapter, info->param.ver_ext.version_str,
2914 			   ver_ext->version_str, sizeof(char) * 128,
2915 			   sizeof(char) * MLAN_MAX_VER_STR_LEN);
2916 	}
2917 	LEAVE();
2918 	return MLAN_STATUS_SUCCESS;
2919 }
2920 
2921 /**
2922  *  @brief Handle the rx mgmt forward registration resp
2923  *
2924  *  @param pmpriv       A pointer to mlan_private structure
2925  *  @param resp         A pointer to HostCmd_DS_COMMAND
2926  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
2927  *
2928  *  @return             MLAN_STATUS_SUCCESS
2929  */
wlan_ret_rx_mgmt_ind(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)2930 mlan_status wlan_ret_rx_mgmt_ind(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
2931 				 mlan_ioctl_req *pioctl_buf)
2932 {
2933 	mlan_ds_misc_cfg *misc = MNULL;
2934 	ENTER();
2935 
2936 	if (pioctl_buf) {
2937 		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
2938 		misc->param.mgmt_subtype_mask = wlan_le32_to_cpu(
2939 			resp->params.rx_mgmt_ind.mgmt_subtype_mask);
2940 	}
2941 
2942 	LEAVE();
2943 	return MLAN_STATUS_SUCCESS;
2944 }
2945 
2946 /**
2947  *  @brief This function checks conditions and prepares to
2948  *              send sleep confirm command to firmware if OK.
2949  *
2950  *  @param pmadapter    A pointer to mlan_adapter structure
2951  *
2952  *  @return             N/A
2953  */
wlan_check_ps_cond(mlan_adapter * pmadapter)2954 t_void wlan_check_ps_cond(mlan_adapter *pmadapter)
2955 {
2956 	ENTER();
2957 
2958 	if (!pmadapter->cmd_sent && !pmadapter->curr_cmd &&
2959 	    !pmadapter->keep_wakeup && !wlan_is_tx_pending(pmadapter) &&
2960 	    !IS_CARD_RX_RCVD(pmadapter)) {
2961 		wlan_dnld_sleep_confirm_cmd(pmadapter);
2962 	} else {
2963 		PRINTM(MCMND, "Delay Sleep Confirm (%s%s%s%s)\n",
2964 		       (pmadapter->cmd_sent) ? "D" : "",
2965 		       (pmadapter->curr_cmd) ? "C" : "",
2966 		       (wlan_is_tx_pending(pmadapter)) ? "T" : "",
2967 		       (IS_CARD_RX_RCVD(pmadapter)) ? "R" : "");
2968 	}
2969 
2970 	LEAVE();
2971 }
2972 
2973 /**
2974  *  @brief This function sends the HS_ACTIVATED event to the application
2975  *
2976  *  @param priv         A pointer to mlan_private structure
2977  *  @param activated    MTRUE if activated, MFALSE if de-activated
2978  *
2979  *  @return             N/A
2980  */
wlan_host_sleep_activated_event(pmlan_private priv,t_u8 activated)2981 t_void wlan_host_sleep_activated_event(pmlan_private priv, t_u8 activated)
2982 {
2983 	ENTER();
2984 
2985 	if (!priv) {
2986 		LEAVE();
2987 		return;
2988 	}
2989 
2990 	if (activated) {
2991 		if (priv->adapter->is_hs_configured) {
2992 			priv->adapter->hs_activated = MTRUE;
2993 			wlan_update_rxreorder_tbl(priv->adapter, MTRUE);
2994 			PRINTM(MEVENT, "hs_activated\n");
2995 			wlan_recv_event(priv, MLAN_EVENT_ID_DRV_HS_ACTIVATED,
2996 					MNULL);
2997 		} else
2998 			PRINTM(MWARN, "hs_activated: HS not configured !!!\n");
2999 	} else {
3000 		PRINTM(MEVENT, "hs_deactived\n");
3001 		priv->adapter->hs_activated = MFALSE;
3002 		wlan_recv_event(priv, MLAN_EVENT_ID_DRV_HS_DEACTIVATED, MNULL);
3003 	}
3004 
3005 	LEAVE();
3006 	return;
3007 }
3008 
3009 /**
3010  *  @brief This function sends the HS_WAKEUP event to the application
3011  *
3012  *  @param priv         A pointer to mlan_private structure
3013  *
3014  *  @return             N/A
3015  */
wlan_host_sleep_wakeup_event(pmlan_private priv)3016 t_void wlan_host_sleep_wakeup_event(pmlan_private priv)
3017 {
3018 	ENTER();
3019 
3020 	if (priv->adapter->is_hs_configured)
3021 		wlan_recv_event(priv, MLAN_EVENT_ID_FW_HS_WAKEUP, MNULL);
3022 	else
3023 		PRINTM(MWARN, "hs_wakeup: Host Sleep not configured !!!\n");
3024 
3025 	LEAVE();
3026 }
3027 
3028 /**
3029  *  @brief This function handles the command response of hs_cfg
3030  *
3031  *  @param pmpriv       A pointer to mlan_private structure
3032  *  @param resp         A pointer to HostCmd_DS_COMMAND
3033  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
3034  *
3035  *  @return             MLAN_STATUS_SUCCESS
3036  */
wlan_ret_802_11_hs_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)3037 mlan_status wlan_ret_802_11_hs_cfg(pmlan_private pmpriv,
3038 				   HostCmd_DS_COMMAND *resp,
3039 				   mlan_ioctl_req *pioctl_buf)
3040 {
3041 	pmlan_adapter pmadapter = pmpriv->adapter;
3042 	HostCmd_DS_802_11_HS_CFG_ENH *phs_cfg = &resp->params.opt_hs_cfg;
3043 
3044 	ENTER();
3045 
3046 	phs_cfg->params.hs_config.conditions =
3047 		wlan_le32_to_cpu(phs_cfg->params.hs_config.conditions);
3048 	phs_cfg->action = wlan_le16_to_cpu(phs_cfg->action);
3049 	PRINTM(MCMND,
3050 	       "CMD_RESP: HS_CFG cmd reply result=%#x,"
3051 	       " action=0x%x conditions=0x%x gpio=0x%x gap=0x%x\n",
3052 	       resp->result, phs_cfg->action,
3053 	       phs_cfg->params.hs_config.conditions,
3054 	       phs_cfg->params.hs_config.gpio, phs_cfg->params.hs_config.gap);
3055 	if ((phs_cfg->action == HS_ACTIVATE &&
3056 	     !pmadapter->pcard_info->supp_ps_handshake) ||
3057 	    pmadapter->pcard_info->supp_ps_handshake) {
3058 		/* clean up curr_cmd to allow suspend */
3059 		if (pioctl_buf)
3060 			pioctl_buf->status_code = MLAN_ERROR_NO_ERROR;
3061 		/* Clean up and put current command back to cmd_free_q */
3062 		wlan_request_cmd_lock(pmadapter);
3063 		wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
3064 		pmadapter->curr_cmd = MNULL;
3065 		wlan_release_cmd_lock(pmadapter);
3066 		if (!pmadapter->pcard_info->supp_ps_handshake) {
3067 			wlan_host_sleep_activated_event(pmpriv, MTRUE);
3068 			goto done;
3069 		}
3070 	}
3071 	if (phs_cfg->params.hs_config.conditions != HOST_SLEEP_CFG_CANCEL) {
3072 		pmadapter->is_hs_configured = MTRUE;
3073 		if (pmadapter->pcard_info->supp_ps_handshake)
3074 			wlan_host_sleep_activated_event(pmpriv, MTRUE);
3075 	} else {
3076 		pmadapter->is_hs_configured = MFALSE;
3077 		if (pmadapter->hs_activated)
3078 			wlan_host_sleep_activated_event(pmpriv, MFALSE);
3079 	}
3080 
3081 done:
3082 	LEAVE();
3083 	return MLAN_STATUS_SUCCESS;
3084 }
3085 
3086 /**
3087  *  @brief Perform hs related activities on receiving the power up interrupt
3088  *
3089  *  @param pmadapter  A pointer to the adapter structure
3090  *  @return           N/A
3091  */
wlan_process_hs_config(pmlan_adapter pmadapter)3092 t_void wlan_process_hs_config(pmlan_adapter pmadapter)
3093 {
3094 	ENTER();
3095 	PRINTM(MINFO, "Recevie interrupt/data in HS mode\n");
3096 	if (pmadapter->hs_cfg.gap == HOST_SLEEP_CFG_GAP_FF)
3097 		pmadapter->ops.wakeup_card(pmadapter, MTRUE);
3098 	LEAVE();
3099 	return;
3100 }
3101 
3102 /**
3103  *  @brief Check sleep confirm command response and set the state to ASLEEP
3104  *
3105  *  @param pmadapter  A pointer to the adapter structure
3106  *  @param pbuf       A pointer to the command response buffer
3107  *  @param upld_len   Command response buffer length
3108  *  @return           N/A
3109  */
wlan_process_sleep_confirm_resp(pmlan_adapter pmadapter,t_u8 * pbuf,t_u32 upld_len)3110 void wlan_process_sleep_confirm_resp(pmlan_adapter pmadapter, t_u8 *pbuf,
3111 				     t_u32 upld_len)
3112 {
3113 	HostCmd_DS_COMMAND *cmd;
3114 	pmlan_private pmpriv;
3115 
3116 	ENTER();
3117 
3118 	if (!upld_len) {
3119 		PRINTM(MERROR, "Command size is 0\n");
3120 		LEAVE();
3121 		return;
3122 	}
3123 	cmd = (HostCmd_DS_COMMAND *)pbuf;
3124 	cmd->result = wlan_le16_to_cpu(cmd->result);
3125 	cmd->command = wlan_le16_to_cpu(cmd->command);
3126 	cmd->seq_num = wlan_le16_to_cpu(cmd->seq_num);
3127 
3128 	pmpriv =
3129 		wlan_get_priv_by_id(pmadapter, HostCmd_GET_BSS_NO(cmd->seq_num),
3130 				    HostCmd_GET_BSS_TYPE(cmd->seq_num));
3131 	/* Update sequence number */
3132 	cmd->seq_num = HostCmd_GET_SEQ_NO(cmd->seq_num);
3133 	/* Clear RET_BIT from HostCmd */
3134 	cmd->command &= HostCmd_CMD_ID_MASK;
3135 	if (!pmpriv)
3136 		pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
3137 	if (cmd->command != HostCmd_CMD_802_11_PS_MODE_ENH) {
3138 		PRINTM(MERROR,
3139 		       "Received unexpected response for command %x, result = %x\n",
3140 		       cmd->command, cmd->result);
3141 		LEAVE();
3142 		return;
3143 	}
3144 	PRINTM_NETINTF(MEVENT, pmpriv);
3145 	PRINTM(MEVENT, "#\n");
3146 	if (cmd->result != MLAN_STATUS_SUCCESS) {
3147 		PRINTM(MERROR, "Sleep confirm command failed\n");
3148 		pmadapter->pm_wakeup_card_req = MFALSE;
3149 		pmadapter->ps_state = PS_STATE_AWAKE;
3150 		LEAVE();
3151 		return;
3152 	}
3153 	pmadapter->pm_wakeup_card_req = MTRUE;
3154 
3155 	if (pmadapter->is_hs_configured) {
3156 		wlan_host_sleep_activated_event(
3157 			wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY), MTRUE);
3158 	}
3159 	pmadapter->ps_state = PS_STATE_SLEEP;
3160 	LEAVE();
3161 }
3162 
3163 /**
3164  *  @brief This function prepares command of power mode
3165  *
3166  *  @param pmpriv       A pointer to mlan_private structure
3167  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
3168  *  @param cmd_action   the action: GET or SET
3169  *  @param ps_bitmap    PS bitmap
3170  *  @param pdata_buf    A pointer to data buffer
3171  *  @return             MLAN_STATUS_SUCCESS
3172  */
wlan_cmd_enh_power_mode(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_u16 ps_bitmap,t_void * pdata_buf)3173 mlan_status wlan_cmd_enh_power_mode(pmlan_private pmpriv,
3174 				    HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
3175 				    t_u16 ps_bitmap, t_void *pdata_buf)
3176 {
3177 	HostCmd_DS_802_11_PS_MODE_ENH *psmode_enh = &cmd->params.psmode_enh;
3178 	t_u8 *tlv = MNULL;
3179 	t_u16 cmd_size = 0;
3180 
3181 	ENTER();
3182 
3183 	PRINTM(MCMND, "PS Command: action = 0x%x, bitmap = 0x%x\n", cmd_action,
3184 	       ps_bitmap);
3185 
3186 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH);
3187 	if (cmd_action == DIS_AUTO_PS) {
3188 		psmode_enh->action = wlan_cpu_to_le16(DIS_AUTO_PS);
3189 		psmode_enh->params.ps_bitmap = wlan_cpu_to_le16(ps_bitmap);
3190 		cmd->size = wlan_cpu_to_le16(S_DS_GEN + AUTO_PS_FIX_SIZE);
3191 	} else if (cmd_action == GET_PS) {
3192 		psmode_enh->action = wlan_cpu_to_le16(GET_PS);
3193 		psmode_enh->params.ps_bitmap = wlan_cpu_to_le16(ps_bitmap);
3194 		cmd->size = wlan_cpu_to_le16(S_DS_GEN + AUTO_PS_FIX_SIZE);
3195 	} else if (cmd_action == EN_AUTO_PS) {
3196 		psmode_enh->action = wlan_cpu_to_le16(EN_AUTO_PS);
3197 		psmode_enh->params.auto_ps.ps_bitmap =
3198 			wlan_cpu_to_le16(ps_bitmap);
3199 		cmd_size = S_DS_GEN + AUTO_PS_FIX_SIZE;
3200 		tlv = (t_u8 *)cmd + cmd_size;
3201 		if (ps_bitmap & BITMAP_STA_PS) {
3202 			pmlan_adapter pmadapter = pmpriv->adapter;
3203 			MrvlIEtypes_ps_param_t *ps_tlv =
3204 				(MrvlIEtypes_ps_param_t *)tlv;
3205 			ps_param *ps_mode = &ps_tlv->param;
3206 			ps_tlv->header.type =
3207 				wlan_cpu_to_le16(TLV_TYPE_PS_PARAM);
3208 			ps_tlv->header.len = wlan_cpu_to_le16(
3209 				sizeof(MrvlIEtypes_ps_param_t) -
3210 				sizeof(MrvlIEtypesHeader_t));
3211 			cmd_size += sizeof(MrvlIEtypes_ps_param_t);
3212 			tlv += sizeof(MrvlIEtypes_ps_param_t);
3213 			ps_mode->null_pkt_interval =
3214 				wlan_cpu_to_le16(pmadapter->null_pkt_interval);
3215 			ps_mode->multiple_dtims =
3216 				wlan_cpu_to_le16(pmadapter->multiple_dtim);
3217 			ps_mode->bcn_miss_timeout =
3218 				wlan_cpu_to_le16(pmadapter->bcn_miss_time_out);
3219 			ps_mode->local_listen_interval = wlan_cpu_to_le16(
3220 				pmadapter->local_listen_interval);
3221 			ps_mode->delay_to_ps =
3222 				wlan_cpu_to_le16(pmadapter->delay_to_ps);
3223 			ps_mode->mode =
3224 				wlan_cpu_to_le16(pmadapter->enhanced_ps_mode);
3225 		}
3226 		if (ps_bitmap & BITMAP_BCN_TMO) {
3227 			MrvlIEtypes_bcn_timeout_t *bcn_tmo_tlv =
3228 				(MrvlIEtypes_bcn_timeout_t *)tlv;
3229 			mlan_ds_bcn_timeout *bcn_tmo =
3230 				(mlan_ds_bcn_timeout *)pdata_buf;
3231 			bcn_tmo_tlv->header.type =
3232 				wlan_cpu_to_le16(TLV_TYPE_BCN_TIMEOUT);
3233 			bcn_tmo_tlv->header.len = wlan_cpu_to_le16(
3234 				sizeof(MrvlIEtypes_bcn_timeout_t) -
3235 				sizeof(MrvlIEtypesHeader_t));
3236 			bcn_tmo_tlv->bcn_miss_tmo_window =
3237 				wlan_cpu_to_le16(bcn_tmo->bcn_miss_tmo_window);
3238 			bcn_tmo_tlv->bcn_miss_tmo_period =
3239 				wlan_cpu_to_le16(bcn_tmo->bcn_miss_tmo_period);
3240 			bcn_tmo_tlv->bcn_rq_tmo_window =
3241 				wlan_cpu_to_le16(bcn_tmo->bcn_rq_tmo_window);
3242 			bcn_tmo_tlv->bcn_rq_tmo_period =
3243 				wlan_cpu_to_le16(bcn_tmo->bcn_rq_tmo_period);
3244 			cmd_size += sizeof(MrvlIEtypes_bcn_timeout_t);
3245 			tlv += sizeof(MrvlIEtypes_bcn_timeout_t);
3246 
3247 			psmode_enh->params.auto_ps.ps_bitmap = wlan_cpu_to_le16(
3248 				(ps_bitmap & (~BITMAP_BCN_TMO)) |
3249 				BITMAP_STA_PS);
3250 		}
3251 		if (ps_bitmap & BITMAP_AUTO_DS) {
3252 			MrvlIEtypes_auto_ds_param_t *auto_ps_tlv =
3253 				(MrvlIEtypes_auto_ds_param_t *)tlv;
3254 			auto_ds_param *auto_ds = &auto_ps_tlv->param;
3255 			t_u16 idletime = 0;
3256 			auto_ps_tlv->header.type =
3257 				wlan_cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM);
3258 			auto_ps_tlv->header.len = wlan_cpu_to_le16(
3259 				sizeof(MrvlIEtypes_auto_ds_param_t) -
3260 				sizeof(MrvlIEtypesHeader_t));
3261 			cmd_size += sizeof(MrvlIEtypes_auto_ds_param_t);
3262 			tlv += sizeof(MrvlIEtypes_auto_ds_param_t);
3263 			if (pdata_buf)
3264 				idletime =
3265 					((mlan_ds_auto_ds *)pdata_buf)->idletime;
3266 			auto_ds->deep_sleep_timeout =
3267 				wlan_cpu_to_le16(idletime);
3268 		}
3269 #if defined(UAP_SUPPORT)
3270 		if (pdata_buf &&
3271 		    (ps_bitmap & (BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS))) {
3272 			mlan_ds_ps_mgmt *ps_mgmt = (mlan_ds_ps_mgmt *)pdata_buf;
3273 			MrvlIEtypes_sleep_param_t *sleep_tlv = MNULL;
3274 			MrvlIEtypes_inact_sleep_param_t *inact_tlv = MNULL;
3275 			if (ps_mgmt->flags & PS_FLAG_SLEEP_PARAM) {
3276 				sleep_tlv = (MrvlIEtypes_sleep_param_t *)tlv;
3277 				sleep_tlv->header.type = wlan_cpu_to_le16(
3278 					TLV_TYPE_AP_SLEEP_PARAM);
3279 				sleep_tlv->header.len = wlan_cpu_to_le16(
3280 					sizeof(MrvlIEtypes_sleep_param_t) -
3281 					sizeof(MrvlIEtypesHeader_t));
3282 				sleep_tlv->ctrl_bitmap = wlan_cpu_to_le32(
3283 					ps_mgmt->sleep_param.ctrl_bitmap);
3284 				sleep_tlv->min_sleep = wlan_cpu_to_le32(
3285 					ps_mgmt->sleep_param.min_sleep);
3286 				sleep_tlv->max_sleep = wlan_cpu_to_le32(
3287 					ps_mgmt->sleep_param.max_sleep);
3288 				cmd_size += sizeof(MrvlIEtypes_sleep_param_t);
3289 				tlv += sizeof(MrvlIEtypes_sleep_param_t);
3290 			}
3291 			if (ps_mgmt->flags & PS_FLAG_INACT_SLEEP_PARAM) {
3292 				inact_tlv =
3293 					(MrvlIEtypes_inact_sleep_param_t *)tlv;
3294 				inact_tlv->header.type = wlan_cpu_to_le16(
3295 					TLV_TYPE_AP_INACT_SLEEP_PARAM);
3296 				inact_tlv->header.len = wlan_cpu_to_le16(
3297 					sizeof(MrvlIEtypes_inact_sleep_param_t) -
3298 					sizeof(MrvlIEtypesHeader_t));
3299 				inact_tlv->inactivity_to = wlan_cpu_to_le32(
3300 					ps_mgmt->inact_param.inactivity_to);
3301 				inact_tlv->min_awake = wlan_cpu_to_le32(
3302 					ps_mgmt->inact_param.min_awake);
3303 				inact_tlv->max_awake = wlan_cpu_to_le32(
3304 					ps_mgmt->inact_param.max_awake);
3305 				cmd_size +=
3306 					sizeof(MrvlIEtypes_inact_sleep_param_t);
3307 				tlv += sizeof(MrvlIEtypes_inact_sleep_param_t);
3308 			}
3309 		}
3310 #endif
3311 		cmd->size = wlan_cpu_to_le16(cmd_size);
3312 	}
3313 
3314 	LEAVE();
3315 	return MLAN_STATUS_SUCCESS;
3316 }
3317 
3318 /**
3319  *  @brief This function handles the command response of ps_mode_enh
3320  *
3321  *  @param pmpriv       A pointer to mlan_private structure
3322  *  @param resp         A pointer to HostCmd_DS_COMMAND
3323  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
3324  *
3325  *  @return             MLAN_STATUS_SUCCESS
3326  */
wlan_ret_enh_power_mode(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)3327 mlan_status wlan_ret_enh_power_mode(pmlan_private pmpriv,
3328 				    HostCmd_DS_COMMAND *resp,
3329 				    mlan_ioctl_req *pioctl_buf)
3330 {
3331 	pmlan_adapter pmadapter = pmpriv->adapter;
3332 	MrvlIEtypesHeader_t *mrvl_tlv = MNULL;
3333 	MrvlIEtypes_auto_ds_param_t *auto_ds_tlv = MNULL;
3334 	HostCmd_DS_802_11_PS_MODE_ENH *ps_mode = &resp->params.psmode_enh;
3335 
3336 	ENTER();
3337 
3338 	ps_mode->action = wlan_le16_to_cpu(ps_mode->action);
3339 	PRINTM(MINFO, "CMD_RESP: PS_MODE cmd reply result=%#x action=0x%X\n",
3340 	       resp->result, ps_mode->action);
3341 	if (ps_mode->action == EN_AUTO_PS) {
3342 		ps_mode->params.auto_ps.ps_bitmap =
3343 			wlan_le16_to_cpu(ps_mode->params.auto_ps.ps_bitmap);
3344 		if (ps_mode->params.auto_ps.ps_bitmap & BITMAP_AUTO_DS) {
3345 			PRINTM(MCMND, "Enabled auto deep sleep\n");
3346 			pmpriv->adapter->is_deep_sleep = MTRUE;
3347 			mrvl_tlv = (MrvlIEtypesHeader_t *)((t_u8 *)ps_mode +
3348 							   AUTO_PS_FIX_SIZE);
3349 			while (wlan_le16_to_cpu(mrvl_tlv->type) !=
3350 			       TLV_TYPE_AUTO_DS_PARAM) {
3351 				mrvl_tlv =
3352 					(MrvlIEtypesHeader_t
3353 						 *)((t_u8 *)mrvl_tlv +
3354 						    wlan_le16_to_cpu(
3355 							    mrvl_tlv->len) +
3356 						    sizeof(MrvlIEtypesHeader_t));
3357 			}
3358 			auto_ds_tlv = (MrvlIEtypes_auto_ds_param_t *)mrvl_tlv;
3359 			pmpriv->adapter->idle_time = wlan_le16_to_cpu(
3360 				auto_ds_tlv->param.deep_sleep_timeout);
3361 		}
3362 		if (ps_mode->params.auto_ps.ps_bitmap & BITMAP_STA_PS) {
3363 			PRINTM(MCMND, "Enabled STA power save\n");
3364 			if (pmadapter->sleep_period.period) {
3365 				PRINTM(MCMND,
3366 				       "Setting uapsd/pps mode to TRUE\n");
3367 			}
3368 		}
3369 #if defined(UAP_SUPPORT)
3370 		if (ps_mode->params.auto_ps.ps_bitmap &
3371 		    (BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS)) {
3372 			pmadapter->ps_mode = Wlan802_11PowerModePSP;
3373 			PRINTM(MCMND, "Enabled uAP power save\n");
3374 		}
3375 #endif
3376 	} else if (ps_mode->action == DIS_AUTO_PS) {
3377 		ps_mode->params.ps_bitmap =
3378 			wlan_cpu_to_le16(ps_mode->params.ps_bitmap);
3379 		if (ps_mode->params.ps_bitmap & BITMAP_AUTO_DS) {
3380 			pmpriv->adapter->is_deep_sleep = MFALSE;
3381 			PRINTM(MCMND, "Disabled auto deep sleep\n");
3382 		}
3383 		if (ps_mode->params.ps_bitmap & BITMAP_STA_PS) {
3384 			PRINTM(MCMND, "Disabled STA power save\n");
3385 			if (pmadapter->sleep_period.period) {
3386 				pmadapter->delay_null_pkt = MFALSE;
3387 				pmadapter->tx_lock_flag = MFALSE;
3388 				pmadapter->pps_uapsd_mode = MFALSE;
3389 			}
3390 		}
3391 #if defined(UAP_SUPPORT)
3392 		if (ps_mode->params.ps_bitmap &
3393 		    (BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS)) {
3394 			pmadapter->ps_mode = Wlan802_11PowerModeCAM;
3395 			PRINTM(MCMND, "Disabled uAP power save\n");
3396 		}
3397 #endif
3398 	} else if (ps_mode->action == GET_PS) {
3399 		ps_mode->params.ps_bitmap =
3400 			wlan_le16_to_cpu(ps_mode->params.ps_bitmap);
3401 		if (ps_mode->params.auto_ps.ps_bitmap &
3402 		    (BITMAP_STA_PS | BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS))
3403 			pmadapter->ps_mode = Wlan802_11PowerModePSP;
3404 		else
3405 			pmadapter->ps_mode = Wlan802_11PowerModeCAM;
3406 		PRINTM(MCMND, "ps_bitmap=0x%x\n", ps_mode->params.ps_bitmap);
3407 		if (pioctl_buf) {
3408 			mlan_ds_pm_cfg *pm_cfg =
3409 				(mlan_ds_pm_cfg *)pioctl_buf->pbuf;
3410 			if (pm_cfg->sub_command == MLAN_OID_PM_CFG_IEEE_PS) {
3411 				if (ps_mode->params.auto_ps.ps_bitmap &
3412 				    BITMAP_STA_PS)
3413 					pm_cfg->param.ps_mode = 1;
3414 				else
3415 					pm_cfg->param.ps_mode = 0;
3416 			}
3417 #if defined(UAP_SUPPORT)
3418 			if (pm_cfg->sub_command == MLAN_OID_PM_CFG_PS_MODE) {
3419 				MrvlIEtypes_sleep_param_t *sleep_tlv = MNULL;
3420 				MrvlIEtypes_inact_sleep_param_t *inact_tlv =
3421 					MNULL;
3422 				MrvlIEtypesHeader_t *tlv = MNULL;
3423 				t_u16 tlv_type = 0;
3424 				t_u16 tlv_len = 0;
3425 				t_u16 tlv_buf_left = 0;
3426 				pm_cfg->param.ps_mgmt.flags = PS_FLAG_PS_MODE;
3427 				if (ps_mode->params.ps_bitmap &
3428 				    BITMAP_UAP_INACT_PS)
3429 					pm_cfg->param.ps_mgmt.ps_mode =
3430 						PS_MODE_INACTIVITY;
3431 				else if (ps_mode->params.ps_bitmap &
3432 					 BITMAP_UAP_DTIM_PS)
3433 					pm_cfg->param.ps_mgmt.ps_mode =
3434 						PS_MODE_PERIODIC_DTIM;
3435 				else
3436 					pm_cfg->param.ps_mgmt.ps_mode =
3437 						PS_MODE_DISABLE;
3438 				tlv_buf_left = resp->size -
3439 					       (S_DS_GEN + AUTO_PS_FIX_SIZE);
3440 				tlv = (MrvlIEtypesHeader_t *)((t_u8 *)ps_mode +
3441 							      AUTO_PS_FIX_SIZE);
3442 				while (tlv_buf_left >=
3443 				       sizeof(MrvlIEtypesHeader_t)) {
3444 					tlv_type = wlan_le16_to_cpu(tlv->type);
3445 					tlv_len = wlan_le16_to_cpu(tlv->len);
3446 					switch (tlv_type) {
3447 					case TLV_TYPE_AP_SLEEP_PARAM:
3448 						sleep_tlv =
3449 							(MrvlIEtypes_sleep_param_t
3450 								 *)tlv;
3451 						pm_cfg->param.ps_mgmt.flags |=
3452 							PS_FLAG_SLEEP_PARAM;
3453 						pm_cfg->param.ps_mgmt
3454 							.sleep_param
3455 							.ctrl_bitmap = wlan_le32_to_cpu(
3456 							sleep_tlv->ctrl_bitmap);
3457 						pm_cfg->param.ps_mgmt
3458 							.sleep_param
3459 							.min_sleep = wlan_le32_to_cpu(
3460 							sleep_tlv->min_sleep);
3461 						pm_cfg->param.ps_mgmt
3462 							.sleep_param
3463 							.max_sleep = wlan_le32_to_cpu(
3464 							sleep_tlv->max_sleep);
3465 						break;
3466 					case TLV_TYPE_AP_INACT_SLEEP_PARAM:
3467 						inact_tlv =
3468 							(MrvlIEtypes_inact_sleep_param_t
3469 								 *)tlv;
3470 						pm_cfg->param.ps_mgmt.flags |=
3471 							PS_FLAG_INACT_SLEEP_PARAM;
3472 						pm_cfg->param.ps_mgmt
3473 							.inact_param
3474 							.inactivity_to = wlan_le32_to_cpu(
3475 							inact_tlv->inactivity_to);
3476 						pm_cfg->param.ps_mgmt
3477 							.inact_param
3478 							.min_awake = wlan_le32_to_cpu(
3479 							inact_tlv->min_awake);
3480 						pm_cfg->param.ps_mgmt
3481 							.inact_param
3482 							.max_awake = wlan_le32_to_cpu(
3483 							inact_tlv->max_awake);
3484 						break;
3485 					}
3486 					tlv_buf_left -=
3487 						tlv_len +
3488 						sizeof(MrvlIEtypesHeader_t);
3489 					tlv = (MrvlIEtypesHeader_t
3490 						       *)((t_u8 *)tlv +
3491 							  tlv_len +
3492 							  sizeof(MrvlIEtypesHeader_t));
3493 				}
3494 			}
3495 #endif
3496 		}
3497 	}
3498 
3499 	LEAVE();
3500 	return MLAN_STATUS_SUCCESS;
3501 }
3502 
3503 /**
3504  *  @brief This function handles the command response of tx rate query
3505  *
3506  *  @param pmpriv       A pointer to mlan_private structure
3507  *  @param resp         A pointer to HostCmd_DS_COMMAND
3508  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
3509  *
3510  *  @return             MLAN_STATUS_SUCCESS
3511  */
wlan_ret_802_11_tx_rate_query(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)3512 mlan_status wlan_ret_802_11_tx_rate_query(pmlan_private pmpriv,
3513 					  HostCmd_DS_COMMAND *resp,
3514 					  mlan_ioctl_req *pioctl_buf)
3515 {
3516 	mlan_adapter *pmadapter = pmpriv->adapter;
3517 	mlan_ds_rate *rate = MNULL;
3518 	ENTER();
3519 
3520 	pmpriv->tx_rate = resp->params.tx_rate.tx_rate;
3521 	pmpriv->tx_rate_info = resp->params.tx_rate.tx_rate_info;
3522 	if (pmpriv->adapter->pcard_info->v14_fw_api) {
3523 		pmpriv->tx_rate_info = wlan_convert_v14_tx_rate_info(
3524 			pmpriv, pmpriv->tx_rate_info);
3525 		PRINTM(MINFO,
3526 		       "%s: v14_fw_api=%d tx_rate=%d tx_rate_info=0x%x->0x%x\n",
3527 		       __func__, pmpriv->adapter->pcard_info->v14_fw_api,
3528 		       pmpriv->tx_rate, resp->params.tx_rate.tx_rate_info,
3529 		       pmpriv->tx_rate_info);
3530 	}
3531 	if ((pmpriv->tx_rate_info & 0x3) == MLAN_RATE_FORMAT_HE)
3532 		pmpriv->ext_tx_rate_info =
3533 			resp->params.tx_rate.ext_tx_rate_info;
3534 	else
3535 		pmpriv->ext_tx_rate_info = 0;
3536 
3537 	if (!pmpriv->is_data_rate_auto) {
3538 		pmpriv->data_rate =
3539 			wlan_index_to_data_rate(pmadapter, pmpriv->tx_rate,
3540 						pmpriv->tx_rate_info,
3541 						pmpriv->ext_tx_rate_info);
3542 	}
3543 
3544 	if (pioctl_buf) {
3545 		rate = (mlan_ds_rate *)pioctl_buf->pbuf;
3546 		if (rate->sub_command == MLAN_OID_RATE_CFG) {
3547 			if (rate->param.rate_cfg.rate_type == MLAN_RATE_INDEX) {
3548 				if ((pmpriv->tx_rate_info & 0x3) ==
3549 					    MLAN_RATE_FORMAT_VHT ||
3550 				    ((pmpriv->tx_rate_info & 0x3) ==
3551 				     MLAN_RATE_FORMAT_HE))
3552 
3553 					/* VHT rate */
3554 					rate->param.rate_cfg.rate =
3555 						(pmpriv->tx_rate) & 0xF;
3556 				else if ((pmpriv->tx_rate_info & 0x3) ==
3557 					 MLAN_RATE_FORMAT_HT)
3558 					/* HT rate */
3559 					rate->param.rate_cfg.rate =
3560 						pmpriv->tx_rate +
3561 						MLAN_RATE_INDEX_MCS0;
3562 				else
3563 					/* LG rate */
3564 					/* For HostCmd_CMD_802_11_TX_RATE_QUERY,
3565 					 * there is a hole (0x4) in rate table
3566 					 * between HR/DSSS and OFDM rates,
3567 					 * so minus 1 for OFDM rate index */
3568 					rate->param.rate_cfg.rate =
3569 						(pmpriv->tx_rate >
3570 						 MLAN_RATE_INDEX_OFDM0) ?
3571 							pmpriv->tx_rate - 1 :
3572 							pmpriv->tx_rate;
3573 			} else {
3574 				/* rate_type = MLAN_RATE_VALUE */
3575 				rate->param.rate_cfg.rate =
3576 					wlan_index_to_data_rate(
3577 						pmadapter, pmpriv->tx_rate,
3578 						pmpriv->tx_rate_info,
3579 						pmpriv->ext_tx_rate_info);
3580 			}
3581 		} else if (rate->sub_command == MLAN_OID_GET_DATA_RATE) {
3582 			/* Tx rate info */
3583 			if ((pmpriv->tx_rate_info & 0x3) ==
3584 				    MLAN_RATE_FORMAT_VHT ||
3585 			    (pmpriv->tx_rate_info & 0x3) ==
3586 				    MLAN_RATE_FORMAT_HE) {
3587 				/* AX/VHT rate */
3588 				rate->param.data_rate.tx_rate_format =
3589 					pmpriv->tx_rate_info & 0x3;
3590 				rate->param.data_rate.tx_ht_bw =
3591 					(pmpriv->tx_rate_info & 0xC) >> 2;
3592 				if ((pmpriv->tx_rate_info & 0x3) ==
3593 				    MLAN_RATE_FORMAT_HE)
3594 					rate->param.data_rate.tx_ht_gi =
3595 						(pmpriv->tx_rate_info & 0x10) >>
3596 							4 |
3597 						(pmpriv->tx_rate_info & 0x80) >>
3598 							6;
3599 				else
3600 					rate->param.data_rate.tx_ht_gi =
3601 						(pmpriv->tx_rate_info & 0x10) >>
3602 						4;
3603 				rate->param.data_rate.tx_nss =
3604 					((pmpriv->tx_rate) >> 4) & 0x03;
3605 				rate->param.data_rate.tx_mcs_index =
3606 					(pmpriv->tx_rate) & 0xF;
3607 				if ((pmpriv->tx_rate_info & 0x3) ==
3608 					    MLAN_RATE_FORMAT_VHT ||
3609 				    (pmpriv->tx_rate_info & 0x3) ==
3610 					    MLAN_RATE_FORMAT_HE)
3611 					rate->param.data_rate.tx_data_rate =
3612 						wlan_index_to_data_rate(
3613 							pmadapter,
3614 							pmpriv->tx_rate,
3615 							pmpriv->tx_rate_info,
3616 							pmpriv->ext_tx_rate_info);
3617 			} else if ((pmpriv->tx_rate_info & 0x3) ==
3618 				   MLAN_RATE_FORMAT_HT) {
3619 				/* HT rate */
3620 				rate->param.data_rate.tx_rate_format =
3621 					MLAN_RATE_FORMAT_HT;
3622 				rate->param.data_rate.tx_ht_bw =
3623 					(pmpriv->tx_rate_info & 0xC) >> 2;
3624 
3625 				rate->param.data_rate.tx_ht_gi =
3626 					(pmpriv->tx_rate_info & 0x10) >> 4;
3627 				rate->param.data_rate.tx_mcs_index =
3628 					pmpriv->tx_rate;
3629 				rate->param.data_rate.tx_data_rate =
3630 					wlan_index_to_data_rate(
3631 						pmadapter, pmpriv->tx_rate,
3632 						pmpriv->tx_rate_info,
3633 						pmpriv->ext_tx_rate_info);
3634 			} else {
3635 				/* LG rate */
3636 				rate->param.data_rate.tx_rate_format =
3637 					MLAN_RATE_FORMAT_LG;
3638 				/* For HostCmd_CMD_802_11_TX_RATE_QUERY,
3639 				 * there is a hole in rate table
3640 				 * between HR/DSSS and OFDM rates,
3641 				 * so minus 1 for OFDM rate index */
3642 				rate->param.data_rate.tx_data_rate =
3643 					(pmpriv->tx_rate >
3644 					 MLAN_RATE_INDEX_OFDM0) ?
3645 						pmpriv->tx_rate - 1 :
3646 						pmpriv->tx_rate;
3647 			}
3648 
3649 			/* Rx rate info */
3650 			if ((pmpriv->rxpd_rate_info & 0x3) ==
3651 				    MLAN_RATE_FORMAT_VHT ||
3652 			    (pmpriv->rxpd_rate_info & 0x3) ==
3653 				    MLAN_RATE_FORMAT_HE) {
3654 				/* VHT rate */
3655 				rate->param.data_rate.rx_rate_format =
3656 					pmpriv->rxpd_rate_info & 0x3;
3657 				rate->param.data_rate.rx_ht_bw =
3658 					(pmpriv->rxpd_rate_info & 0xC) >> 2;
3659 				if ((pmpriv->rxpd_rate_info & 0x3) ==
3660 				    MLAN_RATE_FORMAT_HE)
3661 					rate->param.data_rate.rx_ht_gi =
3662 						(pmpriv->rxpd_rate_info &
3663 						 0x10) >>
3664 							4 |
3665 						(pmpriv->rxpd_rate_info &
3666 						 0x80) >>
3667 							6;
3668 				else
3669 					rate->param.data_rate.rx_ht_gi =
3670 						(pmpriv->rxpd_rate_info &
3671 						 0x10) >>
3672 						4;
3673 				rate->param.data_rate.rx_nss =
3674 					((pmpriv->rxpd_rate) >> 4) & 0x3;
3675 				rate->param.data_rate.rx_mcs_index =
3676 					(pmpriv->rxpd_rate) & 0xF;
3677 				if ((pmpriv->rxpd_rate_info & 0x3) ==
3678 					    MLAN_RATE_FORMAT_VHT ||
3679 				    (pmpriv->rxpd_rate_info & 0x3) ==
3680 					    MLAN_RATE_FORMAT_HE)
3681 					rate->param.data_rate.rx_data_rate =
3682 						wlan_index_to_data_rate(
3683 							pmadapter,
3684 							pmpriv->rxpd_rate,
3685 							pmpriv->rxpd_rate_info,
3686 							pmpriv->rxpd_rx_info);
3687 			} else if ((pmpriv->rxpd_rate_info & 0x3) ==
3688 				   MLAN_RATE_FORMAT_HT) {
3689 				/* HT rate */
3690 				rate->param.data_rate.rx_rate_format =
3691 					MLAN_RATE_FORMAT_HT;
3692 				rate->param.data_rate.rx_ht_bw =
3693 					(pmpriv->rxpd_rate_info & 0xC) >> 2;
3694 				rate->param.data_rate.rx_ht_gi =
3695 					(pmpriv->rxpd_rate_info & 0x10) >> 4;
3696 				rate->param.data_rate.rx_mcs_index =
3697 					pmpriv->rxpd_rate;
3698 				rate->param.data_rate.rx_data_rate =
3699 					wlan_index_to_data_rate(
3700 						pmadapter, pmpriv->rxpd_rate,
3701 						pmpriv->rxpd_rate_info, 0);
3702 			} else {
3703 				/* LG rate */
3704 				rate->param.data_rate.rx_rate_format =
3705 					MLAN_RATE_FORMAT_LG;
3706 				/* For rate index in RxPD,
3707 				 * there is a hole in rate table
3708 				 * between HR/DSSS and OFDM rates,
3709 				 * so minus 1 for OFDM rate index */
3710 				rate->param.data_rate.rx_data_rate =
3711 					(pmpriv->rxpd_rate >
3712 					 MLAN_RATE_INDEX_OFDM0) ?
3713 						pmpriv->rxpd_rate - 1 :
3714 						pmpriv->rxpd_rate;
3715 			}
3716 		}
3717 		pioctl_buf->data_read_written =
3718 			sizeof(mlan_data_rate) + MLAN_SUB_COMMAND_SIZE;
3719 	}
3720 	LEAVE();
3721 	return MLAN_STATUS_SUCCESS;
3722 }
3723 
3724 /**
3725  * @brief This function prepares command of robustcoex.
3726  *
3727  * @param pmpriv       A pointer to mlan_private structure
3728  * @param cmd          A pointer to HostCmd_DS_COMMAND structure
3729  * @param cmd_action   The action: GET or SET
3730  * @param pdata_buf    A pointer to data buffer
3731  *
3732  * @return             MLAN_STATUS_SUCCESS
3733  */
wlan_cmd_robustcoex(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_u16 * pdata_buf)3734 mlan_status wlan_cmd_robustcoex(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
3735 				t_u16 cmd_action, t_u16 *pdata_buf)
3736 {
3737 	HostCmd_DS_802_11_ROBUSTCOEX *rbstcx = &cmd->params.robustcoexparams;
3738 	mlan_ds_misc_robustcoex_params *robustcoex_params = MNULL;
3739 	MrvlIEtypes_RobustcoexSourceGPIO_t *tlv =
3740 		(MrvlIEtypes_RobustcoexSourceGPIO_t *)(rbstcx->tlv_buf);
3741 
3742 	ENTER();
3743 
3744 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_ROBUSTCOEX);
3745 	cmd->size = sizeof(HostCmd_DS_802_11_ROBUSTCOEX) + S_DS_GEN;
3746 	rbstcx->action = wlan_cpu_to_le16(cmd_action);
3747 	switch (cmd_action) {
3748 	case HostCmd_ACT_GEN_SET:
3749 		robustcoex_params = (mlan_ds_misc_robustcoex_params *)pdata_buf;
3750 		if (robustcoex_params->method == ROBUSTCOEX_GPIO_CFG) {
3751 			cmd->size += sizeof(MrvlIEtypes_RobustcoexSourceGPIO_t);
3752 			tlv->header.type =
3753 				wlan_cpu_to_le16(TLV_TYPE_ROBUSTCOEX);
3754 			tlv->header.len = wlan_cpu_to_le16(
3755 				sizeof(MrvlIEtypes_RobustcoexSourceGPIO_t) -
3756 				sizeof(MrvlIEtypesHeader_t));
3757 			tlv->enable = (t_u8)robustcoex_params->enable;
3758 			tlv->gpio_num = (t_u8)robustcoex_params->gpio_num;
3759 			tlv->gpio_polarity =
3760 				(t_u8)robustcoex_params->gpio_polarity;
3761 		}
3762 		break;
3763 	case HostCmd_ACT_GEN_GET:
3764 	default:
3765 		break;
3766 	}
3767 	cmd->size = wlan_cpu_to_le16(cmd->size);
3768 	LEAVE();
3769 	return MLAN_STATUS_SUCCESS;
3770 }
3771 
3772 #if defined(PCIE)
3773 /**
3774  * @brief This function enables SSU support.
3775  *
3776  * @param pmpriv       A pointer to mlan_private structure
3777  * @param cmd          A pointer to HostCmd_DS_COMMAND structure
3778  * @param cmd_action   The action: GET or SET
3779  * @param pdata_buf    A pointer to data buffer
3780  *
3781  * @return             MLAN_STATUS_SUCCESS
3782  */
wlan_cmd_ssu(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_u16 * pdata_buf)3783 mlan_status wlan_cmd_ssu(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
3784 			 t_u16 cmd_action, t_u16 *pdata_buf)
3785 {
3786 	HostCmd_DS_SSU_CFG *ssu_cfg_cmd = &cmd->params.ssu_params;
3787 	mlan_ds_ssu_params *ssu_params = MNULL;
3788 	mlan_status ret = MLAN_STATUS_SUCCESS;
3789 	mlan_adapter *pmadapter = pmpriv->adapter;
3790 
3791 	ENTER();
3792 
3793 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SSU);
3794 	cmd->size = sizeof(HostCmd_DS_SSU_CFG) + S_DS_GEN;
3795 	ssu_cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
3796 	switch (cmd_action) {
3797 	case HostCmd_ACT_GEN_SET:
3798 	case HostCmd_ACT_GEN_SET_DEFAULT:
3799 		ssu_params = (mlan_ds_ssu_params *)pdata_buf;
3800 		ssu_cfg_cmd->nskip = wlan_cpu_to_le32(ssu_params->nskip);
3801 		ssu_cfg_cmd->nsel = wlan_cpu_to_le32(ssu_params->nsel);
3802 		ssu_cfg_cmd->adcdownsample =
3803 			wlan_cpu_to_le32(ssu_params->adcdownsample);
3804 		ssu_cfg_cmd->mask_adc_pkt =
3805 			wlan_cpu_to_le32(ssu_params->mask_adc_pkt);
3806 		ssu_cfg_cmd->out_16bits =
3807 			wlan_cpu_to_le32(ssu_params->out_16bits);
3808 		ssu_cfg_cmd->spec_pwr_enable =
3809 			wlan_cpu_to_le32(ssu_params->spec_pwr_enable);
3810 		ssu_cfg_cmd->rate_deduction =
3811 			wlan_cpu_to_le32(ssu_params->rate_deduction);
3812 		ssu_cfg_cmd->n_pkt_avg =
3813 			wlan_cpu_to_le32(ssu_params->n_pkt_avg);
3814 		/* Initialize PCIE ring buffer */
3815 		ret = wlan_alloc_ssu_pcie_buf(pmadapter);
3816 		if (MLAN_STATUS_SUCCESS != ret) {
3817 			PRINTM(MERROR,
3818 			       "Failed to allocate PCIE host buffers for SSU\n");
3819 			LEAVE();
3820 			return MLAN_STATUS_FAILURE;
3821 		}
3822 		ssu_cfg_cmd->buffer_base_addr[0] =
3823 			wlan_cpu_to_le32((t_u32)pmadapter->ssu_buf->buf_pa);
3824 		ssu_cfg_cmd->buffer_base_addr[1] = wlan_cpu_to_le32(
3825 			(t_u32)((t_u64)(pmadapter->ssu_buf->buf_pa >> 32)));
3826 		ssu_cfg_cmd->buffer_pool_size =
3827 			wlan_cpu_to_le32(MLAN_SSU_BUF_SIZE);
3828 		break;
3829 	case HostCmd_ACT_GEN_GET:
3830 	default:
3831 		break;
3832 	}
3833 	cmd->size = wlan_cpu_to_le16(cmd->size);
3834 	LEAVE();
3835 	return MLAN_STATUS_SUCCESS;
3836 }
3837 #endif
3838 
3839 /**
3840  * @brief This function prepares command of dmcs config.
3841  *
3842  * @param pmpriv       A pointer to mlan_private structure
3843  * @param cmd          A pointer to HostCmd_DS_COMMAND structure
3844  * @param cmd_action   The action: GET or SET
3845  * @param pdata_buf    A pointer to data buffer
3846  *
3847  * @return             MLAN_STATUS_SUCCESS
3848  */
wlan_cmd_dmcs_config(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)3849 mlan_status wlan_cmd_dmcs_config(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
3850 				 t_u16 cmd_action, t_void *pdata_buf)
3851 {
3852 	HostCmd_DS_DMCS_CFG *dmcs = &cmd->params.dmcs;
3853 	mlan_ds_misc_mapping_policy *dmcs_params = MNULL;
3854 	t_u8 *mapping_policy = (t_u8 *)dmcs->tlv_buf;
3855 
3856 	ENTER();
3857 
3858 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_DMCS_CONFIG);
3859 	cmd->size = sizeof(HostCmd_DS_DMCS_CFG) + S_DS_GEN;
3860 	dmcs->action = wlan_cpu_to_le16(cmd_action);
3861 	dmcs_params = (mlan_ds_misc_mapping_policy *)pdata_buf;
3862 	dmcs->subcmd = wlan_cpu_to_le16(dmcs_params->subcmd);
3863 	switch (dmcs->subcmd) {
3864 	case 0:
3865 		cmd->size += sizeof(t_u8);
3866 		*mapping_policy = dmcs_params->mapping_policy;
3867 		break;
3868 	case 1:
3869 	default:
3870 		break;
3871 	}
3872 	cmd->size = wlan_cpu_to_le16(cmd->size);
3873 	LEAVE();
3874 	return MLAN_STATUS_SUCCESS;
3875 }
3876 
3877 /**
3878  *  @brief This function handles the command response of dmcs config
3879  *
3880  *  @param pmpriv       A pointer to mlan_private structure
3881  *  @param resp         A pointer to HostCmd_DS_COMMAND
3882  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
3883  *
3884  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3885  */
wlan_ret_dmcs_config(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)3886 mlan_status wlan_ret_dmcs_config(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
3887 				 mlan_ioctl_req *pioctl_buf)
3888 {
3889 	mlan_status ret = MLAN_STATUS_SUCCESS;
3890 	HostCmd_DS_DMCS_CFG *dmcs = &resp->params.dmcs;
3891 	MrvlIEtypes_DmcsStatus_t *dmcs_status;
3892 	mlan_ds_misc_cfg *cfg = MNULL;
3893 	t_u16 tlv_buf_left = 0;
3894 	t_u16 tlv_type = 0, tlv_len = 0;
3895 	MrvlIEtypesHeader_t *tlv = MNULL;
3896 	int i = 0;
3897 
3898 	ENTER();
3899 	if (pioctl_buf) {
3900 		cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
3901 		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)dmcs +
3902 					      sizeof(HostCmd_DS_DMCS_CFG));
3903 		tlv_buf_left =
3904 			resp->size - (sizeof(HostCmd_DS_DMCS_CFG) + S_DS_GEN);
3905 		while (tlv_buf_left > sizeof(MrvlIEtypesHeader_t)) {
3906 			tlv_type = wlan_le16_to_cpu(tlv->type);
3907 			tlv_len = wlan_le16_to_cpu(tlv->len);
3908 			if (tlv_buf_left <
3909 			    (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
3910 				PRINTM(MERROR,
3911 				       "Error while processing DMCS status tlv, bytes_left < TLV len\n");
3912 				ret = MLAN_STATUS_FAILURE;
3913 				break;
3914 			}
3915 			switch (tlv_type) {
3916 			case TLV_TYPE_DMCS_STATUS:
3917 				dmcs_status = (MrvlIEtypes_DmcsStatus_t *)tlv;
3918 				cfg->param.dmcs_status.mapping_policy =
3919 					dmcs_status->mapping_policy;
3920 				memset(pmpriv->adapter,
3921 				       &cfg->param.dmcs_status.radio_status, 0,
3922 				       sizeof(dmcsStatus_t));
3923 				for (i = 0; i < MAX_NUM_MAC; i++) {
3924 					memcpy_ext(
3925 						pmpriv->adapter,
3926 						&cfg->param.dmcs_status
3927 							 .radio_status[i],
3928 						&dmcs_status->radio_status[i],
3929 						sizeof(dmcsStatus_t),
3930 						sizeof(dmcsStatus_t));
3931 				}
3932 				break;
3933 			default:
3934 				break;
3935 			}
3936 			tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
3937 			tlv = (MrvlIEtypesHeader_t
3938 				       *)((t_u8 *)tlv + tlv_len +
3939 					  sizeof(MrvlIEtypesHeader_t));
3940 		}
3941 		pioctl_buf->data_read_written =
3942 			sizeof(mlan_ds_misc_dmcs_status);
3943 	}
3944 	LEAVE();
3945 	return ret;
3946 }
3947 
3948 /**
3949  *  @brief This function prepares command of tx_rate_cfg.
3950  *
3951  *  @param pmpriv       A pointer to mlan_private structure
3952  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
3953  *  @param cmd_action   The action: GET or SET
3954  *  @param pdata_buf    A pointer to data buffer
3955  *  @param pioctl_buf	A pointer to ioctl buffer
3956  *
3957  *  @return             MLAN_STATUS_SUCCESS
3958  */
wlan_cmd_tx_rate_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf,mlan_ioctl_req * pioctl_buf)3959 mlan_status wlan_cmd_tx_rate_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
3960 				 t_u16 cmd_action, t_void *pdata_buf,
3961 				 mlan_ioctl_req *pioctl_buf)
3962 {
3963 	HostCmd_DS_TX_RATE_CFG *rate_cfg =
3964 		(HostCmd_DS_TX_RATE_CFG *)&(cmd->params.tx_rate_cfg);
3965 	MrvlRateScope_t *rate_scope;
3966 	MrvlRateDropPattern_t *rate_drop;
3967 	MrvlIETypes_rate_setting_t *rate_setting_tlv;
3968 	mlan_ds_rate *ds_rate = MNULL;
3969 	t_u16 *pbitmap_rates = (t_u16 *)pdata_buf;
3970 
3971 	t_u32 i;
3972 
3973 	ENTER();
3974 
3975 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TX_RATE_CFG);
3976 
3977 	rate_cfg->action = wlan_cpu_to_le16(cmd_action);
3978 	rate_cfg->cfg_index = 0;
3979 
3980 	rate_scope = (MrvlRateScope_t *)rate_cfg->tlv_buf;
3981 	rate_scope->type = wlan_cpu_to_le16(TLV_TYPE_RATE_SCOPE);
3982 	rate_scope->length = wlan_cpu_to_le16(sizeof(MrvlRateScope_t) -
3983 					      sizeof(MrvlIEtypesHeader_t));
3984 	if (pbitmap_rates != MNULL) {
3985 		rate_scope->hr_dsss_rate_bitmap =
3986 			wlan_cpu_to_le16(pbitmap_rates[0]);
3987 		rate_scope->ofdm_rate_bitmap =
3988 			wlan_cpu_to_le16(pbitmap_rates[1]);
3989 		for (i = 0; i < NELEMENTS(rate_scope->ht_mcs_rate_bitmap); i++)
3990 			rate_scope->ht_mcs_rate_bitmap[i] =
3991 				wlan_cpu_to_le16(pbitmap_rates[2 + i]);
3992 		for (i = 0; i < NELEMENTS(rate_scope->vht_mcs_rate_bitmap); i++)
3993 			rate_scope->vht_mcs_rate_bitmap[i] = wlan_cpu_to_le16(
3994 				pbitmap_rates
3995 					[2 +
3996 					 NELEMENTS(
3997 						 rate_scope->ht_mcs_rate_bitmap) +
3998 					 i]);
3999 		if (IS_FW_SUPPORT_11AX(pmpriv->adapter)) {
4000 			for (i = 0;
4001 			     i < NELEMENTS(rate_scope->he_mcs_rate_bitmap); i++)
4002 				rate_scope->he_mcs_rate_bitmap
4003 					[i] = wlan_cpu_to_le16(
4004 					pbitmap_rates[2 +
4005 						      wlan_get_bitmap_index(
4006 							      rate_scope) +
4007 						      i]);
4008 		} else {
4009 			rate_scope->length = wlan_cpu_to_le16(
4010 				sizeof(MrvlRateScope_t) -
4011 				sizeof(rate_scope->he_mcs_rate_bitmap) -
4012 				sizeof(MrvlIEtypesHeader_t));
4013 		}
4014 	} else {
4015 		rate_scope->hr_dsss_rate_bitmap =
4016 			wlan_cpu_to_le16(pmpriv->bitmap_rates[0]);
4017 		rate_scope->ofdm_rate_bitmap =
4018 			wlan_cpu_to_le16(pmpriv->bitmap_rates[1]);
4019 		for (i = 0; i < NELEMENTS(rate_scope->ht_mcs_rate_bitmap); i++)
4020 			rate_scope->ht_mcs_rate_bitmap[i] =
4021 				wlan_cpu_to_le16(pmpriv->bitmap_rates[2 + i]);
4022 		for (i = 0; i < NELEMENTS(rate_scope->vht_mcs_rate_bitmap); i++)
4023 			rate_scope->vht_mcs_rate_bitmap[i] = wlan_cpu_to_le16(
4024 				pmpriv->bitmap_rates
4025 					[2 +
4026 					 NELEMENTS(
4027 						 rate_scope->ht_mcs_rate_bitmap) +
4028 					 i]);
4029 		if (IS_FW_SUPPORT_11AX(pmpriv->adapter)) {
4030 			for (i = 0;
4031 			     i < NELEMENTS(rate_scope->vht_mcs_rate_bitmap);
4032 			     i++)
4033 				rate_scope->he_mcs_rate_bitmap[i] =
4034 					wlan_cpu_to_le16(
4035 						pmpriv->bitmap_rates
4036 							[2 +
4037 							 wlan_get_bitmap_index(
4038 								 rate_scope) +
4039 							 i]);
4040 		} else {
4041 			rate_scope->length = wlan_cpu_to_le16(
4042 				sizeof(MrvlRateScope_t) -
4043 				sizeof(rate_scope->he_mcs_rate_bitmap) -
4044 				sizeof(MrvlIEtypesHeader_t));
4045 		}
4046 	}
4047 
4048 	rate_drop =
4049 		(MrvlRateDropPattern_t *)((t_u8 *)rate_scope +
4050 					  wlan_le16_to_cpu(rate_scope->length) +
4051 					  sizeof(MrvlIEtypesHeader_t));
4052 	rate_drop->type = wlan_cpu_to_le16(TLV_TYPE_RATE_DROP_PATTERN);
4053 	rate_drop->length = wlan_cpu_to_le16(sizeof(rate_drop->rate_drop_mode));
4054 	rate_drop->rate_drop_mode = 0;
4055 
4056 	cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_TX_RATE_CFG) +
4057 				     wlan_le16_to_cpu(rate_scope->length) +
4058 				     sizeof(MrvlIEtypesHeader_t) +
4059 				     sizeof(MrvlRateDropPattern_t));
4060 	if (pioctl_buf && pmpriv->adapter->pcard_info->v17_fw_api) {
4061 		ds_rate = (mlan_ds_rate *)pioctl_buf->pbuf;
4062 		rate_setting_tlv = (MrvlIETypes_rate_setting_t
4063 					    *)((t_u8 *)rate_drop +
4064 					       sizeof(MrvlRateDropPattern_t));
4065 		rate_setting_tlv->header.type =
4066 			wlan_cpu_to_le16(TLV_TYPE_TX_RATE_CFG);
4067 		rate_setting_tlv->header.len = wlan_cpu_to_le16(
4068 			sizeof(rate_setting_tlv->rate_setting));
4069 		rate_setting_tlv->rate_setting =
4070 			wlan_cpu_to_le16(ds_rate->param.rate_cfg.rate_setting);
4071 		PRINTM(MCMND, "he rate setting = %d\n",
4072 		       rate_setting_tlv->rate_setting);
4073 		cmd->size = wlan_cpu_to_le16(
4074 			S_DS_GEN + sizeof(HostCmd_DS_TX_RATE_CFG) +
4075 			wlan_le16_to_cpu(rate_scope->length) +
4076 			sizeof(MrvlIEtypesHeader_t) +
4077 			sizeof(MrvlRateDropPattern_t) +
4078 			sizeof(MrvlIETypes_rate_setting_t));
4079 	}
4080 	LEAVE();
4081 	return MLAN_STATUS_SUCCESS;
4082 }
4083 
4084 /**
4085  *  @brief This function handles the command response of tx_rate_cfg
4086  *
4087  *  @param pmpriv       A pointer to mlan_private structure
4088  *  @param resp         A pointer to HostCmd_DS_COMMAND
4089  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
4090  *
4091  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4092  */
wlan_ret_tx_rate_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)4093 mlan_status wlan_ret_tx_rate_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
4094 				 mlan_ioctl_req *pioctl_buf)
4095 {
4096 	mlan_adapter *pmadapter = pmpriv->adapter;
4097 	mlan_ds_rate *ds_rate = MNULL;
4098 	HostCmd_DS_TX_RATE_CFG *prate_cfg = MNULL;
4099 	MrvlRateScope_t *prate_scope;
4100 	MrvlIEtypesHeader_t *head = MNULL;
4101 	t_u16 tlv, tlv_buf_len = 0;
4102 	t_u8 *tlv_buf;
4103 	t_u32 i;
4104 	t_s32 index;
4105 	mlan_status ret = MLAN_STATUS_SUCCESS;
4106 	MrvlIETypes_rate_setting_t *rate_setting_tlv = MNULL;
4107 	t_u16 rate_setting = 0xffff;
4108 
4109 	ENTER();
4110 
4111 	if (resp == MNULL) {
4112 		LEAVE();
4113 		return MLAN_STATUS_FAILURE;
4114 	}
4115 	prate_cfg = (HostCmd_DS_TX_RATE_CFG *)&(resp->params.tx_rate_cfg);
4116 
4117 	tlv_buf = (t_u8 *)prate_cfg->tlv_buf;
4118 	tlv_buf_len = resp->size - (sizeof(HostCmd_DS_TX_RATE_CFG) + S_DS_GEN);
4119 
4120 	while (tlv_buf && tlv_buf_len > 0) {
4121 		tlv = (*tlv_buf);
4122 		tlv = tlv | (*(tlv_buf + 1) << 8);
4123 
4124 		switch (tlv) {
4125 		case TLV_TYPE_RATE_SCOPE:
4126 			prate_scope = (MrvlRateScope_t *)tlv_buf;
4127 			pmpriv->bitmap_rates[0] = wlan_le16_to_cpu(
4128 				prate_scope->hr_dsss_rate_bitmap);
4129 			pmpriv->bitmap_rates[1] =
4130 				wlan_le16_to_cpu(prate_scope->ofdm_rate_bitmap);
4131 			for (i = 0;
4132 			     i < NELEMENTS(prate_scope->ht_mcs_rate_bitmap);
4133 			     i++)
4134 				pmpriv->bitmap_rates[2 + i] = wlan_le16_to_cpu(
4135 					prate_scope->ht_mcs_rate_bitmap[i]);
4136 			for (i = 0;
4137 			     i < NELEMENTS(prate_scope->vht_mcs_rate_bitmap);
4138 			     i++)
4139 				pmpriv->bitmap_rates
4140 					[2 +
4141 					 sizeof(prate_scope->ht_mcs_rate_bitmap) /
4142 						 sizeof(t_u16) +
4143 					 i] =
4144 					wlan_le16_to_cpu(
4145 						prate_scope
4146 							->vht_mcs_rate_bitmap[i]);
4147 			if (IS_FW_SUPPORT_11AX(pmadapter)) {
4148 				for (i = 0;
4149 				     i <
4150 				     NELEMENTS(prate_scope->he_mcs_rate_bitmap);
4151 				     i++)
4152 					pmpriv->bitmap_rates
4153 						[2 +
4154 						 sizeof(prate_scope
4155 								->ht_mcs_rate_bitmap) /
4156 							 sizeof(t_u16) +
4157 						 sizeof(prate_scope
4158 								->vht_mcs_rate_bitmap) /
4159 							 sizeof(t_u16) +
4160 						 i] =
4161 						wlan_le16_to_cpu(
4162 							prate_scope
4163 								->he_mcs_rate_bitmap
4164 									[i]);
4165 			}
4166 			break;
4167 		case TLV_TYPE_TX_RATE_CFG:
4168 			rate_setting_tlv =
4169 				(MrvlIETypes_rate_setting_t *)tlv_buf;
4170 			rate_setting = rate_setting_tlv->rate_setting;
4171 			break;
4172 			/* Add RATE_DROP tlv here */
4173 		}
4174 
4175 		head = (MrvlIEtypesHeader_t *)tlv_buf;
4176 		head->len = wlan_le16_to_cpu(head->len);
4177 		tlv_buf += head->len + sizeof(MrvlIEtypesHeader_t);
4178 		tlv_buf_len -= (head->len + sizeof(MrvlIEtypesHeader_t));
4179 	}
4180 
4181 	pmpriv->is_data_rate_auto = wlan_is_rate_auto(pmpriv);
4182 
4183 	if (pmpriv->is_data_rate_auto) {
4184 		pmpriv->data_rate = 0;
4185 	} else {
4186 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_TX_RATE_QUERY,
4187 				       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
4188 	}
4189 
4190 	if (pioctl_buf) {
4191 		ds_rate = (mlan_ds_rate *)pioctl_buf->pbuf;
4192 		if (ds_rate == MNULL) {
4193 			PRINTM(MERROR, "Request buffer not found!\n");
4194 			LEAVE();
4195 			return MLAN_STATUS_FAILURE;
4196 		}
4197 		if (pmpriv->is_data_rate_auto) {
4198 			ds_rate->param.rate_cfg.is_rate_auto = MTRUE;
4199 			ds_rate->param.rate_cfg.rate_format =
4200 				MLAN_RATE_FORMAT_AUTO;
4201 		} else {
4202 			ds_rate->param.rate_cfg.is_rate_auto = MFALSE;
4203 			/* check the LG rate */
4204 			index = wlan_get_rate_index(
4205 				pmadapter, &pmpriv->bitmap_rates[0], 4);
4206 			if (index != -1) {
4207 				if ((index >= MLAN_RATE_BITMAP_OFDM0) &&
4208 				    (index <= MLAN_RATE_BITMAP_OFDM7))
4209 					index -= (MLAN_RATE_BITMAP_OFDM0 -
4210 						  MLAN_RATE_INDEX_OFDM0);
4211 				ds_rate->param.rate_cfg.rate_format =
4212 					MLAN_RATE_FORMAT_LG;
4213 				ds_rate->param.rate_cfg.rate = index;
4214 			}
4215 			/* check the HT rate */
4216 			index = wlan_get_rate_index(
4217 				pmadapter, &pmpriv->bitmap_rates[2], 16);
4218 			if (index != -1) {
4219 				ds_rate->param.rate_cfg.rate_format =
4220 					MLAN_RATE_FORMAT_HT;
4221 				ds_rate->param.rate_cfg.rate = index;
4222 			}
4223 			/* check the VHT rate */
4224 			index = wlan_get_rate_index(
4225 				pmadapter, &pmpriv->bitmap_rates[10], 16);
4226 			if (index != -1) {
4227 				ds_rate->param.rate_cfg.rate_format =
4228 					MLAN_RATE_FORMAT_VHT;
4229 				ds_rate->param.rate_cfg.rate = index % 16;
4230 				ds_rate->param.rate_cfg.nss = index / 16;
4231 				ds_rate->param.rate_cfg.nss += MLAN_RATE_NSS1;
4232 			}
4233 			/* check the HE rate */
4234 			if (IS_FW_SUPPORT_11AX(pmadapter)) {
4235 				index = wlan_get_rate_index(
4236 					pmadapter, &pmpriv->bitmap_rates[18],
4237 					16);
4238 				if (index != -1) {
4239 					ds_rate->param.rate_cfg.rate_format =
4240 						MLAN_RATE_FORMAT_HE;
4241 					ds_rate->param.rate_cfg.rate =
4242 						index % 16;
4243 					ds_rate->param.rate_cfg.nss =
4244 						index / 16;
4245 					ds_rate->param.rate_cfg.nss +=
4246 						MLAN_RATE_NSS1;
4247 				}
4248 			}
4249 			ds_rate->param.rate_cfg.rate_setting = rate_setting;
4250 			PRINTM(MINFO, "Rate index is %d\n",
4251 			       ds_rate->param.rate_cfg.rate);
4252 		}
4253 		for (i = 0; i < MAX_BITMAP_RATES_SIZE; i++) {
4254 			ds_rate->param.rate_cfg.bitmap_rates[i] =
4255 				pmpriv->bitmap_rates[i];
4256 		}
4257 	}
4258 
4259 	LEAVE();
4260 	return ret;
4261 }
4262 
4263 /**
4264  *  @brief  This function issues adapter specific commands
4265  *          to initialize firmware
4266  *
4267  *  @param pmadapter    A pointer to mlan_adapter structure
4268  *
4269  *  @return             MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
4270  */
wlan_adapter_get_hw_spec(pmlan_adapter pmadapter)4271 mlan_status wlan_adapter_get_hw_spec(pmlan_adapter pmadapter)
4272 {
4273 	mlan_status ret = MLAN_STATUS_SUCCESS;
4274 	pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
4275 
4276 	ENTER();
4277 #if defined(SDIO)
4278 	/*
4279 	 * This should be issued in the very first to config
4280 	 *   SDIO_GPIO interrupt mode.
4281 	 */
4282 	if (IS_SD(pmadapter->card_type) &&
4283 	    (wlan_set_sdio_gpio_int(priv) != MLAN_STATUS_SUCCESS)) {
4284 		ret = MLAN_STATUS_FAILURE;
4285 		goto done;
4286 	}
4287 #endif
4288 
4289 #ifdef PCIE
4290 	if (IS_PCIE(pmadapter->card_type) &&
4291 	    (MLAN_STATUS_SUCCESS != wlan_set_pcie_buf_config(priv))) {
4292 		ret = MLAN_STATUS_FAILURE;
4293 		goto done;
4294 	}
4295 #endif
4296 
4297 	ret = wlan_prepare_cmd(priv, HostCmd_CMD_FUNC_INIT, HostCmd_ACT_GEN_SET,
4298 			       0, MNULL, MNULL);
4299 	if (ret) {
4300 		ret = MLAN_STATUS_FAILURE;
4301 		goto done;
4302 	}
4303 	/** DPD data dnld cmd prepare */
4304 	if ((pmadapter->pdpd_data) && (pmadapter->dpd_data_len > 0)) {
4305 		ret = wlan_process_hostcmd_cfg(priv, CFG_TYPE_DPDFILE,
4306 					       pmadapter->pdpd_data,
4307 					       pmadapter->dpd_data_len);
4308 		if (ret) {
4309 			ret = MLAN_STATUS_FAILURE;
4310 			goto done;
4311 		}
4312 		pmadapter->pdpd_data = MNULL;
4313 		pmadapter->dpd_data_len = 0;
4314 	}
4315 	if ((pmadapter->ptxpwr_data) && (pmadapter->txpwr_data_len > 0)) {
4316 		ret = wlan_process_hostcmd_cfg(priv, CFG_TYPE_HOSTCMD,
4317 					       pmadapter->ptxpwr_data,
4318 					       pmadapter->txpwr_data_len);
4319 		if (ret) {
4320 			ret = MLAN_STATUS_FAILURE;
4321 			goto done;
4322 		}
4323 		pmadapter->ptxpwr_data = MNULL;
4324 		pmadapter->txpwr_data_len = 0;
4325 	}
4326 	if (!pmadapter->pdpd_data &&
4327 	    (pmadapter->dpd_data_len == UNKNOW_DPD_LENGTH)) {
4328 		ret = wlan_prepare_cmd(priv, HostCmd_CMD_CFG_DATA,
4329 				       HostCmd_ACT_GEN_GET, OID_TYPE_DPD, MNULL,
4330 				       MNULL);
4331 		if (ret) {
4332 			ret = MLAN_STATUS_FAILURE;
4333 			goto done;
4334 		}
4335 	}
4336 	/** Cal data dnld cmd prepare */
4337 	if ((pmadapter->pcal_data) && (pmadapter->cal_data_len > 0)) {
4338 		ret = wlan_prepare_cmd(priv, HostCmd_CMD_CFG_DATA,
4339 				       HostCmd_ACT_GEN_SET, OID_TYPE_CAL, MNULL,
4340 				       MNULL);
4341 		if (ret) {
4342 			ret = MLAN_STATUS_FAILURE;
4343 			goto done;
4344 		}
4345 		pmadapter->pcal_data = MNULL;
4346 		pmadapter->cal_data_len = 0;
4347 	}
4348 	/* Get FW region and cfp tables */
4349 	ret = wlan_prepare_cmd(priv, HostCmd_CMD_CHAN_REGION_CFG,
4350 			       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
4351 	if (ret) {
4352 		ret = MLAN_STATUS_FAILURE;
4353 		goto done;
4354 	}
4355 	/*
4356 	 * Get HW spec
4357 	 */
4358 	ret = wlan_prepare_cmd(priv, HostCmd_CMD_GET_HW_SPEC,
4359 			       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
4360 	if (ret) {
4361 		ret = MLAN_STATUS_FAILURE;
4362 		goto done;
4363 	}
4364 	ret = MLAN_STATUS_PENDING;
4365 done:
4366 	LEAVE();
4367 	return ret;
4368 }
4369 
4370 /**
4371  *  @brief  This function issues adapter specific commands
4372  *          to initialize firmware
4373  *
4374  *  @param pmadapter    A pointer to mlan_adapter structure
4375  *
4376  *  @return             MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
4377  */
wlan_adapter_init_cmd(pmlan_adapter pmadapter)4378 mlan_status wlan_adapter_init_cmd(pmlan_adapter pmadapter)
4379 {
4380 	mlan_status ret = MLAN_STATUS_SUCCESS;
4381 	pmlan_private pmpriv = MNULL;
4382 #ifdef STA_SUPPORT
4383 	pmlan_private pmpriv_sta = MNULL;
4384 #endif
4385 	ENTER();
4386 
4387 	pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
4388 #ifdef STA_SUPPORT
4389 	pmpriv_sta = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA);
4390 #endif
4391 
4392 #ifdef SDIO
4393 	if (IS_SD(pmadapter->card_type)) {
4394 	}
4395 #endif
4396 
4397 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RECONFIGURE_TX_BUFF,
4398 			       HostCmd_ACT_GEN_SET, 0, MNULL,
4399 			       &pmadapter->max_tx_buf_size);
4400 	if (ret) {
4401 		ret = MLAN_STATUS_FAILURE;
4402 		goto done;
4403 	}
4404 
4405 #if defined(STA_SUPPORT)
4406 	if (pmpriv_sta &&
4407 	    (pmpriv_sta->state_11d.user_enable_11d == ENABLE_11D)) {
4408 		/* Send command to FW to enable 11d */
4409 		ret = wlan_prepare_cmd(pmpriv_sta, HostCmd_CMD_802_11_SNMP_MIB,
4410 				       HostCmd_ACT_GEN_SET, Dot11D_i, MNULL,
4411 				       &pmpriv_sta->state_11d.user_enable_11d);
4412 		if (ret) {
4413 			ret = MLAN_STATUS_FAILURE;
4414 			goto done;
4415 		}
4416 	}
4417 #endif
4418 
4419 #ifdef STA_SUPPORT
4420 	if (pmpriv_sta && (pmadapter->ps_mode == Wlan802_11PowerModePSP)) {
4421 		ret = wlan_prepare_cmd(pmpriv_sta,
4422 				       HostCmd_CMD_802_11_PS_MODE_ENH,
4423 				       EN_AUTO_PS, BITMAP_STA_PS, MNULL, MNULL);
4424 		if (ret) {
4425 			ret = MLAN_STATUS_FAILURE;
4426 			goto done;
4427 		}
4428 	}
4429 #endif
4430 
4431 	if (pmadapter->init_auto_ds) {
4432 		mlan_ds_auto_ds auto_ds;
4433 		/* Enable auto deep sleep */
4434 		auto_ds.idletime = pmadapter->idle_time;
4435 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
4436 				       EN_AUTO_PS, BITMAP_AUTO_DS, MNULL,
4437 				       &auto_ds);
4438 		if (ret) {
4439 			ret = MLAN_STATUS_FAILURE;
4440 			goto done;
4441 		}
4442 	}
4443 
4444 #define DEF_AUTO_NULL_PKT_PERIOD 30
4445 	if (pmpriv_sta) {
4446 		t_u32 value = DEF_AUTO_NULL_PKT_PERIOD;
4447 		ret = wlan_prepare_cmd(pmpriv_sta, HostCmd_CMD_802_11_SNMP_MIB,
4448 				       HostCmd_ACT_GEN_SET, NullPktPeriod_i,
4449 				       MNULL, &value);
4450 		if (ret) {
4451 			ret = MLAN_STATUS_FAILURE;
4452 			goto done;
4453 		}
4454 	}
4455 	if (pmadapter->init_para.indrstcfg != 0xffffffff) {
4456 		mlan_ds_ind_rst_cfg ind_rst_cfg;
4457 		ind_rst_cfg.ir_mode = pmadapter->init_para.indrstcfg & 0xff;
4458 		ind_rst_cfg.gpio_pin =
4459 			(pmadapter->init_para.indrstcfg & 0xff00) >> 8;
4460 		ret = wlan_prepare_cmd(pmpriv,
4461 				       HostCmd_CMD_INDEPENDENT_RESET_CFG,
4462 				       HostCmd_ACT_GEN_SET, 0, MNULL,
4463 				       (t_void *)&ind_rst_cfg);
4464 		if (ret) {
4465 			ret = MLAN_STATUS_FAILURE;
4466 			goto done;
4467 		}
4468 	}
4469 
4470 	if (pmadapter->inact_tmo) {
4471 		ret = wlan_prepare_cmd(pmpriv,
4472 				       HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT,
4473 				       HostCmd_ACT_GEN_SET, 0, MNULL,
4474 				       &pmadapter->inact_tmo);
4475 		if (ret) {
4476 			ret = MLAN_STATUS_FAILURE;
4477 			goto done;
4478 		}
4479 	}
4480 	/* Send request to firmware */
4481 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_RF_ANTENNA,
4482 			       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
4483 	if (ret) {
4484 		ret = MLAN_STATUS_FAILURE;
4485 		goto done;
4486 	}
4487 	ret = MLAN_STATUS_PENDING;
4488 done:
4489 	LEAVE();
4490 	return ret;
4491 }
4492 
4493 #ifdef RX_PACKET_COALESCE
wlan_cmd_rx_pkt_coalesce_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)4494 mlan_status wlan_cmd_rx_pkt_coalesce_cfg(pmlan_private pmpriv,
4495 					 HostCmd_DS_COMMAND *cmd,
4496 					 t_u16 cmd_action, t_void *pdata_buf)
4497 {
4498 	mlan_ds_misc_rx_packet_coalesce *rx_pkt_cfg =
4499 		(mlan_ds_misc_rx_packet_coalesce *)pdata_buf;
4500 	HostCmd_DS_RX_PKT_COAL_CFG *prx_coal_cfg =
4501 		(HostCmd_DS_RX_PKT_COAL_CFG *)&cmd->params.rx_pkt_coal_cfg;
4502 
4503 	ENTER();
4504 
4505 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RX_PKT_COALESCE_CFG);
4506 	prx_coal_cfg->action = wlan_cpu_to_le16(cmd_action);
4507 
4508 	if (cmd_action == HostCmd_ACT_GEN_SET) {
4509 		prx_coal_cfg->packet_threshold =
4510 			wlan_cpu_to_le32(rx_pkt_cfg->packet_threshold);
4511 		prx_coal_cfg->delay = wlan_cpu_to_le16(rx_pkt_cfg->delay);
4512 		PRINTM(MCMND,
4513 		       "Set RX coal config: packet threshold=%d delay=%d\n",
4514 		       rx_pkt_cfg->packet_threshold, rx_pkt_cfg->delay);
4515 		cmd->size = wlan_cpu_to_le16(
4516 			S_DS_GEN + sizeof(HostCmd_DS_RX_PKT_COAL_CFG));
4517 	} else {
4518 		cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(cmd_action));
4519 	}
4520 
4521 	LEAVE();
4522 	return MLAN_STATUS_SUCCESS;
4523 }
4524 
4525 /**
4526  *  @brief This function handles the command response of RX_PACKET_COAL_CFG
4527  *
4528  *  @param pmpriv       A pointer to mlan_private structure
4529  *  @param resp         A pointer to HostCmd_DS_COMMAND
4530  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
4531  *
4532  *  @return             MLAN_STATUS_SUCCESS
4533  */
wlan_ret_rx_pkt_coalesce_cfg(pmlan_private pmpriv,const HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)4534 mlan_status wlan_ret_rx_pkt_coalesce_cfg(pmlan_private pmpriv,
4535 					 const HostCmd_DS_COMMAND *resp,
4536 					 mlan_ioctl_req *pioctl_buf)
4537 {
4538 	mlan_ds_misc_cfg *pcfg = MNULL;
4539 	const HostCmd_DS_RX_PKT_COAL_CFG *presp_cfg =
4540 		&resp->params.rx_pkt_coal_cfg;
4541 
4542 	ENTER();
4543 
4544 	if (pioctl_buf) {
4545 		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
4546 		pcfg->param.rx_coalesce.packet_threshold =
4547 			wlan_le32_to_cpu(presp_cfg->packet_threshold);
4548 		pcfg->param.rx_coalesce.delay =
4549 			wlan_le16_to_cpu(presp_cfg->delay);
4550 		PRINTM(MCMND,
4551 		       "Get rx pkt coalesce info: packet threshold=%d delay=%d\n",
4552 		       pcfg->param.rx_coalesce.packet_threshold,
4553 		       pcfg->param.rx_coalesce.delay);
4554 		pioctl_buf->buf_len = sizeof(mlan_ds_misc_rx_packet_coalesce);
4555 	}
4556 
4557 	LEAVE();
4558 	return MLAN_STATUS_SUCCESS;
4559 }
4560 
4561 #endif
4562 
4563 /**
4564  *  @brief This function download the vdll block.
4565  *
4566  *  @param pmadapter    A pointer to mlan_adapter structure
4567  *  @param block            A pointer to VDLL block
4568  *  @param block_len      The VDLL block length
4569  *
4570  *  @return             MLAN_STATUS_SUCCESS
4571  */
wlan_download_vdll_block(mlan_adapter * pmadapter,t_u8 * block,t_u16 block_len)4572 mlan_status wlan_download_vdll_block(mlan_adapter *pmadapter, t_u8 *block,
4573 				     t_u16 block_len)
4574 {
4575 	mlan_status status = MLAN_STATUS_FAILURE;
4576 	mlan_status ret = MLAN_STATUS_PENDING;
4577 #if defined(SDIO) || defined(PCIE)
4578 	pvdll_dnld_ctrl ctrl = &pmadapter->vdll_ctrl;
4579 #endif
4580 	mlan_buffer *pmbuf = MNULL;
4581 	mlan_private *pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
4582 	HostCmd_DS_GEN *cmd_hdr = MNULL;
4583 	t_u16 msg_len = block_len + sizeof(HostCmd_DS_GEN);
4584 #ifdef USB
4585 	t_u32 tmp;
4586 #endif
4587 	ENTER();
4588 #if defined(SDIO) || defined(PCIE)
4589 	if (!IS_USB(pmadapter->card_type)) {
4590 		pmbuf = ctrl->cmd_buf;
4591 		if (pmbuf)
4592 			pmbuf->data_offset += pmadapter->ops.intf_header_len;
4593 	}
4594 #endif
4595 #ifdef USB
4596 	if (IS_USB(pmadapter->card_type)) {
4597 		pmbuf = wlan_alloc_mlan_buffer(pmadapter,
4598 					       MRVDRV_SIZE_OF_CMD_BUFFER, 0,
4599 					       MOAL_MALLOC_BUFFER);
4600 		if (pmbuf) {
4601 			tmp = wlan_cpu_to_le32(MLAN_USB_TYPE_VDLL);
4602 			memcpy_ext(pmadapter,
4603 				   (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset),
4604 				   (t_u8 *)&tmp, MLAN_TYPE_LEN, MLAN_TYPE_LEN);
4605 			pmbuf->data_offset += MLAN_TYPE_LEN;
4606 		}
4607 	}
4608 #endif
4609 	if (!pmbuf) {
4610 		PRINTM(MERROR, "dnld vdll: Fail to alloc vdll buf");
4611 		goto done;
4612 	}
4613 	cmd_hdr = (HostCmd_DS_GEN *)(pmbuf->pbuf + pmbuf->data_offset);
4614 	cmd_hdr->command = wlan_cpu_to_le16(HostCmd_CMD_VDLL);
4615 	cmd_hdr->seq_num = wlan_cpu_to_le16(0xFF00);
4616 	cmd_hdr->size = wlan_cpu_to_le16(msg_len);
4617 
4618 	pmadapter->callbacks.moal_memcpy_ext(pmadapter->pmoal_handle,
4619 					     pmbuf->pbuf + pmbuf->data_offset +
4620 						     sizeof(HostCmd_DS_GEN),
4621 					     block, block_len, block_len);
4622 
4623 	pmbuf->data_len = msg_len;
4624 
4625 #if defined(SDIO) || defined(PCIE)
4626 	if (!IS_USB(pmadapter->card_type)) {
4627 		pmbuf->data_offset -= pmadapter->ops.intf_header_len;
4628 		pmbuf->data_len += pmadapter->ops.intf_header_len;
4629 	}
4630 #endif
4631 #ifdef USB
4632 	if (IS_USB(pmadapter->card_type)) {
4633 		pmbuf->data_offset -= MLAN_TYPE_LEN;
4634 		pmbuf->data_len += MLAN_TYPE_LEN;
4635 	}
4636 #endif
4637 	PRINTM_NETINTF(MCMND, pmpriv);
4638 	PRINTM(MCMND, "DNLD_VDLL : block_len=%d\n", block_len);
4639 
4640 	ret = pmadapter->ops.host_to_card(pmpriv, MLAN_TYPE_VDLL, pmbuf, MNULL);
4641 
4642 	if (ret == MLAN_STATUS_FAILURE)
4643 		PRINTM(MERROR, "DNLD_VDLL: Host to Card Failed\n");
4644 	else
4645 		status = MLAN_STATUS_SUCCESS;
4646 
4647 done:
4648 	if ((ret == MLAN_STATUS_FAILURE) || (ret == MLAN_STATUS_SUCCESS)) {
4649 #ifdef USB
4650 		if (IS_USB(pmadapter->card_type))
4651 			wlan_free_mlan_buffer(pmadapter, pmbuf);
4652 #endif
4653 	}
4654 	LEAVE();
4655 	return status;
4656 }
4657 
4658 /**
4659  *  @brief The function Get the VDLL image from moal
4660  *
4661  *  @param pmadapter    A pointer to mlan_adapter structure
4662  *  @param offset          offset
4663  *
4664  *  @return             MLAN_STATUS_SUCCESS
4665  *
4666  */
wlan_get_vdll_image(pmlan_adapter pmadapter,t_u32 vdll_len)4667 static mlan_status wlan_get_vdll_image(pmlan_adapter pmadapter, t_u32 vdll_len)
4668 {
4669 	mlan_status status = MLAN_STATUS_SUCCESS;
4670 	vdll_dnld_ctrl *ctrl = &pmadapter->vdll_ctrl;
4671 	pmlan_callbacks pcb = &pmadapter->callbacks;
4672 
4673 	ENTER();
4674 
4675 	if (ctrl->vdll_mem) {
4676 		PRINTM(MCMND, "VDLL mem is not empty: %p len=%d\n",
4677 		       ctrl->vdll_mem, ctrl->vdll_len);
4678 		goto done;
4679 	}
4680 	if (pcb->moal_vmalloc && pcb->moal_vfree)
4681 		status = pcb->moal_vmalloc(pmadapter->pmoal_handle, vdll_len,
4682 					   (t_u8 **)&ctrl->vdll_mem);
4683 	else
4684 		status = pcb->moal_malloc(pmadapter->pmoal_handle, vdll_len,
4685 					  MLAN_MEM_DEF,
4686 					  (t_u8 **)&ctrl->vdll_mem);
4687 
4688 	if (status != MLAN_STATUS_SUCCESS) {
4689 		PRINTM(MERROR, "VDLL: Fail to alloc vdll memory");
4690 		goto done;
4691 	}
4692 
4693 	if (MLAN_STATUS_SUCCESS !=
4694 	    pcb->moal_get_vdll_data(pmadapter->pmoal_handle, vdll_len,
4695 				    ctrl->vdll_mem)) {
4696 		PRINTM(MERROR, "VDLL: firmware image not available\n");
4697 		status = MLAN_STATUS_FAILURE;
4698 		if (pcb->moal_vmalloc && pcb->moal_vfree)
4699 			pcb->moal_vfree(pmadapter->pmoal_handle,
4700 					(t_u8 *)ctrl->vdll_mem);
4701 		else
4702 			pcb->moal_mfree(pmadapter->pmoal_handle,
4703 					(t_u8 *)ctrl->vdll_mem);
4704 		ctrl->vdll_mem = MNULL;
4705 		ctrl->vdll_len = 0;
4706 		goto done;
4707 	}
4708 	/*allocate a memory to store all VDLL images*/
4709 	ctrl->vdll_len = vdll_len;
4710 	PRINTM(MMSG, "VDLL image: len=%d\n", ctrl->vdll_len);
4711 done:
4712 	LEAVE();
4713 	return status;
4714 }
4715 
4716 /**
4717  *  @brief This function handle the multi_chan info event
4718  *
4719  *  @param pmpriv       A pointer to mlan_private structure
4720  *  @param pevent       A pointer to event buffer
4721  *
4722  *  @return             MLAN_STATUS_SUCCESS
4723  */
wlan_process_vdll_event(pmlan_private pmpriv,pmlan_buffer pevent)4724 mlan_status wlan_process_vdll_event(pmlan_private pmpriv, pmlan_buffer pevent)
4725 {
4726 	mlan_status status = MLAN_STATUS_SUCCESS;
4727 	vdll_ind *ind = MNULL;
4728 	t_u32 offset = 0;
4729 	t_u16 block_len = 0;
4730 	mlan_adapter *pmadapter = pmpriv->adapter;
4731 	vdll_dnld_ctrl *ctrl = &pmadapter->vdll_ctrl;
4732 
4733 	ENTER();
4734 	ind = (vdll_ind *)(pevent->pbuf + pevent->data_offset +
4735 			   sizeof(mlan_event_id));
4736 	switch (wlan_le16_to_cpu(ind->type)) {
4737 	case VDLL_IND_TYPE_REQ:
4738 		offset = wlan_le32_to_cpu(ind->offset);
4739 		block_len = wlan_le16_to_cpu(ind->block_len);
4740 		PRINTM(MEVENT, "VDLL_IND: type=%d offset = 0x%x, len = %d\n",
4741 		       wlan_le16_to_cpu(ind->type), offset, block_len);
4742 		if (offset <= ctrl->vdll_len) {
4743 			block_len = MIN(block_len, ctrl->vdll_len - offset);
4744 			if (!pmadapter->cmd_sent) {
4745 				status = wlan_download_vdll_block(
4746 					pmadapter, ctrl->vdll_mem + offset,
4747 					block_len);
4748 				if (status)
4749 					PRINTM(MERROR,
4750 					       "Fail to download VDLL block\n");
4751 			} else {
4752 				PRINTM(MCMND,
4753 				       "cmd_sent=1, delay download VDLL block\n");
4754 				ctrl->pending_block_len = block_len;
4755 				ctrl->pending_block = ctrl->vdll_mem + offset;
4756 			}
4757 		} else {
4758 			PRINTM(MERROR,
4759 			       "Invalid VDLL req: offset=0x%x, len=%d, vdll_len=%d\n",
4760 			       offset, block_len, ctrl->vdll_len);
4761 		}
4762 		break;
4763 
4764 	case VDLL_IND_TYPE_OFFSET:
4765 		offset = wlan_le32_to_cpu(ind->offset);
4766 		PRINTM(MEVENT, "VDLL_IND (OFFSET): offset=0x%x\n", offset);
4767 		wlan_get_vdll_image(pmadapter, offset);
4768 		break;
4769 	case VDLL_IND_TYPE_ERR_SIG:
4770 		PRINTM(MERROR, "VDLL_IND (SIG ERR).\n");
4771 		break;
4772 	case VDLL_IND_TYPE_ERR_ID:
4773 		PRINTM(MERROR, "VDLL_IND (ID ERR).\n");
4774 		break;
4775 	default:
4776 		PRINTM(MERROR, "unknow vdll ind type=%d\n", ind->type);
4777 		break;
4778 	}
4779 	LEAVE();
4780 	return status;
4781 }
4782 
4783 /**
4784  *  @brief This function handle the csi event
4785  *
4786  *  @param pmpriv       A pointer to mlan_private structure
4787  *
4788  *  @return             MLAN_STATUS_SUCCESS
4789  */
wlan_process_csi_event(pmlan_private pmpriv)4790 mlan_status wlan_process_csi_event(pmlan_private pmpriv)
4791 {
4792 	pmlan_adapter pmadapter = pmpriv->adapter;
4793 	mlan_status status;
4794 	t_u32 eventcause = pmadapter->event_cause;
4795 	t_u8 *evt_buf = MNULL;
4796 	pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event;
4797 	pmlan_callbacks pcb = &pmadapter->callbacks;
4798 	pmlan_event pevent;
4799 
4800 	ENTER();
4801 
4802 	/* Allocate memory for event buffer */
4803 	status = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
4804 				  MLAN_MEM_DEF, &evt_buf);
4805 	if ((status == MLAN_STATUS_SUCCESS) && evt_buf) {
4806 		t_u16 csi_sig;
4807 		pcsi_record_ds csi_record = (pcsi_record_ds)(
4808 			pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause));
4809 		/* Check CSI signature */
4810 		csi_sig = csi_record->CSI_Sign;
4811 		if (csi_sig != CSI_SIGNATURE) {
4812 			PRINTM(MERROR,
4813 			       "Wrong CSI signature 0x%04x. Should be 0x%04x",
4814 			       csi_sig, CSI_SIGNATURE);
4815 			status = MLAN_STATUS_FAILURE;
4816 		} else {
4817 			/* Send event to moal */
4818 			pevent = (pmlan_event)evt_buf;
4819 			pevent->bss_index = pmpriv->bss_index;
4820 			pevent->event_id = MLAN_EVENT_ID_CSI;
4821 			/* Event length is the CSI record length in byte */
4822 			pevent->event_len = csi_record->Len * 4;
4823 			if (pevent->event_len >
4824 			    pmbuf->data_len - sizeof(eventcause))
4825 				pevent->event_len =
4826 					pmbuf->data_len - sizeof(eventcause);
4827 			memcpy_ext(pmadapter, (t_u8 *)pevent->event_buf,
4828 				   csi_record, pevent->event_len,
4829 				   pevent->event_len);
4830 			wlan_recv_event(pmpriv, pevent->event_id, pevent);
4831 		}
4832 		pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf);
4833 	}
4834 
4835 	LEAVE();
4836 	return status;
4837 }
4838 
4839 /**
4840  *  @brief This function prepares command of get_hw_spec.
4841  *
4842  *  @param pmpriv       A pointer to mlan_private structure
4843  *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
4844  *
4845  *  @return             MLAN_STATUS_SUCCESS
4846  */
wlan_cmd_get_hw_spec(pmlan_private pmpriv,HostCmd_DS_COMMAND * pcmd)4847 mlan_status wlan_cmd_get_hw_spec(pmlan_private pmpriv, HostCmd_DS_COMMAND *pcmd)
4848 {
4849 	HostCmd_DS_GET_HW_SPEC *hw_spec = &pcmd->params.hw_spec;
4850 
4851 	ENTER();
4852 
4853 	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_GET_HW_SPEC);
4854 	pcmd->size =
4855 		wlan_cpu_to_le16(sizeof(HostCmd_DS_GET_HW_SPEC) + S_DS_GEN);
4856 	memcpy_ext(pmpriv->adapter, hw_spec->permanent_addr, pmpriv->curr_addr,
4857 		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
4858 
4859 	LEAVE();
4860 	return MLAN_STATUS_SUCCESS;
4861 }
4862 
4863 #ifdef SDIO
4864 /**
4865  *  @brief This function prepares command of sdio rx aggr command.
4866  *
4867  *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
4868  *  @param cmd_action   Command action: GET or SET
4869  *  @param pdata_buf    A pointer to new setting buf
4870 
4871  *  @return             MLAN_STATUS_SUCCESS
4872  */
wlan_cmd_sdio_rx_aggr_cfg(HostCmd_DS_COMMAND * pcmd,t_u16 cmd_action,t_void * pdata_buf)4873 mlan_status wlan_cmd_sdio_rx_aggr_cfg(HostCmd_DS_COMMAND *pcmd,
4874 				      t_u16 cmd_action, t_void *pdata_buf)
4875 {
4876 	HostCmd_DS_SDIO_SP_RX_AGGR_CFG *cfg = &pcmd->params.sdio_rx_aggr;
4877 
4878 	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_SDIO_SP_RX_AGGR_CFG);
4879 	pcmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_SDIO_SP_RX_AGGR_CFG) +
4880 				      S_DS_GEN);
4881 	cfg->action = cmd_action;
4882 	if (cmd_action == HostCmd_ACT_GEN_SET)
4883 		cfg->enable = *(t_u8 *)pdata_buf;
4884 	return MLAN_STATUS_SUCCESS;
4885 }
4886 
4887 /**
4888  *  @brief This function handles the command response of sdio rx aggr command
4889  *
4890  *  @param pmpriv       A pointer to mlan_private structure
4891  *  @param resp         A pointer to HostCmd_DS_COMMAND
4892  *
4893  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4894  */
wlan_ret_sdio_rx_aggr_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp)4895 mlan_status wlan_ret_sdio_rx_aggr_cfg(pmlan_private pmpriv,
4896 				      HostCmd_DS_COMMAND *resp)
4897 {
4898 	mlan_adapter *pmadapter = pmpriv->adapter;
4899 	HostCmd_DS_SDIO_SP_RX_AGGR_CFG *cfg = &resp->params.sdio_rx_aggr;
4900 
4901 	pmadapter->pcard_sd->sdio_rx_aggr_enable = cfg->enable;
4902 	pmadapter->pcard_sd->sdio_rx_block_size =
4903 		wlan_le16_to_cpu(cfg->sdio_block_size);
4904 	PRINTM(MMSG, "SDIO rx aggr: %d block_size=%d\n", cfg->enable,
4905 	       pmadapter->pcard_sd->sdio_rx_block_size);
4906 	if (!pmadapter->pcard_sd->sdio_rx_block_size)
4907 		pmadapter->pcard_sd->sdio_rx_aggr_enable = MFALSE;
4908 	if (pmadapter->pcard_sd->sdio_rx_aggr_enable) {
4909 		pmadapter->pcard_sd->max_sp_rx_size = SDIO_CMD53_MAX_SIZE;
4910 		wlan_re_alloc_sdio_rx_mpa_buffer(pmadapter);
4911 	}
4912 	return MLAN_STATUS_SUCCESS;
4913 }
4914 #endif
4915 
4916 /**
4917  *  @brief This function prepares command of set_cfg_data.
4918  *
4919  *  @param pmpriv       A pointer to mlan_private strcture
4920  *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
4921  *  @param cmd_action   Command action: GET or SET
4922  *  @param pdata_buf    A pointer to cal_data buf
4923  *
4924  *  @return             MLAN_STATUS_SUCCESS
4925  */
wlan_cmd_cfg_data(pmlan_private pmpriv,HostCmd_DS_COMMAND * pcmd,t_u16 cmd_action,t_u32 cmd_oid,t_void * pdata_buf)4926 mlan_status wlan_cmd_cfg_data(pmlan_private pmpriv, HostCmd_DS_COMMAND *pcmd,
4927 			      t_u16 cmd_action, t_u32 cmd_oid,
4928 			      t_void *pdata_buf)
4929 {
4930 	mlan_status ret = MLAN_STATUS_SUCCESS;
4931 	HostCmd_DS_802_11_CFG_DATA *pcfg_data = &(pcmd->params.cfg_data);
4932 	pmlan_adapter pmadapter = pmpriv->adapter;
4933 	t_u32 len = 0;
4934 	t_u32 data_offset;
4935 	t_u8 *temp_pcmd = (t_u8 *)pcmd;
4936 
4937 	ENTER();
4938 
4939 	data_offset = S_DS_GEN + sizeof(HostCmd_DS_802_11_CFG_DATA);
4940 
4941 	if ((cmd_oid == OID_TYPE_CAL) && (pmadapter->pcal_data) &&
4942 	    (pmadapter->cal_data_len > 0)) {
4943 		len = wlan_parse_cal_cfg((t_u8 *)pmadapter->pcal_data,
4944 					 pmadapter->cal_data_len,
4945 					 (t_u8 *)(temp_pcmd + data_offset));
4946 	}
4947 
4948 	pcfg_data->action = cmd_action;
4949 	pcfg_data->type = cmd_oid;
4950 	pcfg_data->data_len = len;
4951 
4952 	pcmd->command = HostCmd_CMD_CFG_DATA;
4953 	pcmd->size = pcfg_data->data_len + data_offset;
4954 
4955 	pcmd->command = wlan_cpu_to_le16(pcmd->command);
4956 	pcmd->size = wlan_cpu_to_le16(pcmd->size);
4957 
4958 	pcfg_data->action = wlan_cpu_to_le16(pcfg_data->action);
4959 	pcfg_data->type = wlan_cpu_to_le16(pcfg_data->type);
4960 	pcfg_data->data_len = wlan_cpu_to_le16(pcfg_data->data_len);
4961 
4962 	LEAVE();
4963 	return ret;
4964 }
4965 
4966 /**
4967  *  @brief This function handles the command response of set_cfg_data
4968  *
4969  *  @param pmpriv       A pointer to mlan_private structure
4970  *  @param resp         A pointer to HostCmd_DS_COMMAND
4971  *  @param pioctl_buf   A pointer to A pointer to mlan_ioctl_req
4972  *
4973  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4974  */
wlan_ret_cfg_data(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * resp,IN t_void * pioctl_buf)4975 mlan_status wlan_ret_cfg_data(IN pmlan_private pmpriv,
4976 			      IN HostCmd_DS_COMMAND *resp,
4977 			      IN t_void *pioctl_buf)
4978 {
4979 	mlan_status ret = MLAN_STATUS_SUCCESS;
4980 	t_u8 event_buf[100];
4981 	mlan_cmdresp_event *pevent = (mlan_cmdresp_event *)event_buf;
4982 	mlan_adapter *pmadapter = pmpriv->adapter;
4983 	HostCmd_DS_802_11_CFG_DATA *pcfg_data = &resp->params.cfg_data;
4984 	t_u16 action;
4985 	t_u16 type;
4986 
4987 	ENTER();
4988 
4989 	if (resp->result != HostCmd_RESULT_OK) {
4990 		PRINTM(MERROR, "CFG data cmd resp failed\n");
4991 		ret = MLAN_STATUS_FAILURE;
4992 	}
4993 
4994 	if (!pmadapter->pdpd_data &&
4995 	    (pmadapter->dpd_data_len == UNKNOW_DPD_LENGTH) &&
4996 	    pmadapter->hw_status == WlanHardwareStatusGetHwSpec) {
4997 		action = wlan_le16_to_cpu(pcfg_data->action);
4998 		type = wlan_le16_to_cpu(pcfg_data->type);
4999 		if (action == HostCmd_ACT_GEN_GET && (type == OID_TYPE_DPD)) {
5000 			pcfg_data->action =
5001 				wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
5002 			pevent->bss_index = pmpriv->bss_index;
5003 			pevent->event_id = MLAN_EVENT_ID_STORE_HOST_CMD_RESP;
5004 			pevent->resp = (t_u8 *)resp;
5005 			pevent->event_len = wlan_le16_to_cpu(resp->size);
5006 			wlan_recv_event(pmpriv,
5007 					MLAN_EVENT_ID_STORE_HOST_CMD_RESP,
5008 					(mlan_event *)pevent);
5009 		}
5010 	}
5011 
5012 	LEAVE();
5013 	return ret;
5014 }
5015 
5016 /**
5017  *  @brief This function prepares command of mac_control.
5018  *
5019  *  @param pmpriv       A pointer to mlan_private structure
5020  *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
5021  *  @param cmd_action   Command action
5022  *  @param pdata_buf    A pointer to command information buffer
5023  *
5024  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5025  */
wlan_cmd_mac_control(pmlan_private pmpriv,HostCmd_DS_COMMAND * pcmd,t_u16 cmd_action,t_void * pdata_buf)5026 mlan_status wlan_cmd_mac_control(pmlan_private pmpriv, HostCmd_DS_COMMAND *pcmd,
5027 				 t_u16 cmd_action, t_void *pdata_buf)
5028 {
5029 	HostCmd_DS_MAC_CONTROL *pmac = &pcmd->params.mac_ctrl;
5030 	t_u32 action = *((t_u32 *)pdata_buf);
5031 
5032 	ENTER();
5033 
5034 	if (cmd_action != HostCmd_ACT_GEN_SET) {
5035 		PRINTM(MERROR, "wlan_cmd_mac_control(): support SET only.\n");
5036 		LEAVE();
5037 		return MLAN_STATUS_FAILURE;
5038 	}
5039 
5040 	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_MAC_CONTROL);
5041 	pcmd->size =
5042 		wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_CONTROL) + S_DS_GEN);
5043 	pmac->action = wlan_cpu_to_le32(action);
5044 
5045 	LEAVE();
5046 	return MLAN_STATUS_SUCCESS;
5047 }
5048 
5049 /**
5050  *  @brief This function handles the command response of mac_control
5051  *
5052  *  @param pmpriv       A pointer to mlan_private structure
5053  *  @param resp         A pointer to HostCmd_DS_COMMAND
5054  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
5055  *
5056  *  @return             MLAN_STATUS_SUCCESS
5057  */
wlan_ret_mac_control(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)5058 mlan_status wlan_ret_mac_control(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
5059 				 mlan_ioctl_req *pioctl_buf)
5060 {
5061 	ENTER();
5062 	LEAVE();
5063 	return MLAN_STATUS_SUCCESS;
5064 }
5065 
5066 /**
5067  *  @brief This function handles the command response of get_hw_spec
5068  *
5069  *  @param pmpriv       A pointer to mlan_private structure
5070  *  @param resp         A pointer to HostCmd_DS_COMMAND
5071  *  @param pioctl_buf   A pointer to command buffer
5072  *
5073  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5074  */
wlan_ret_get_hw_spec(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,t_void * pioctl_buf)5075 mlan_status wlan_ret_get_hw_spec(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
5076 				 t_void *pioctl_buf)
5077 {
5078 	HostCmd_DS_GET_HW_SPEC *hw_spec = &resp->params.hw_spec;
5079 	mlan_adapter *pmadapter = pmpriv->adapter;
5080 	mlan_status ret = MLAN_STATUS_SUCCESS;
5081 	t_u32 i;
5082 	t_u16 left_len;
5083 	t_u16 tlv_type = 0;
5084 	t_u16 tlv_len = 0;
5085 	MrvlIEtypes_fw_ver_info_t *api_rev = MNULL;
5086 	t_u16 api_id = 0;
5087 	MrvlIEtypesHeader_t *tlv = MNULL;
5088 	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
5089 	MrvlIEtypes_Max_Conn_t *tlv_max_conn = MNULL;
5090 	MrvlIEtypes_Extension_t *ext_tlv = MNULL;
5091 	MrvlIEtypes_fw_cap_info_t *fw_cap_tlv = MNULL;
5092 
5093 	MrvlIEtypes_Secure_Boot_Uuid_t *sb_uuid_tlv = MNULL;
5094 
5095 	ENTER();
5096 
5097 	pmadapter->fw_cap_info = wlan_le32_to_cpu(hw_spec->fw_cap_info);
5098 	pmadapter->fw_cap_info &= pmadapter->init_para.dev_cap_mask;
5099 
5100 	PRINTM(MMSG, "fw_cap_info=0x%x, dev_cap_mask=0x%x\n",
5101 	       wlan_le32_to_cpu(hw_spec->fw_cap_info),
5102 	       pmadapter->init_para.dev_cap_mask);
5103 #ifdef STA_SUPPORT
5104 	if (IS_SUPPORT_MULTI_BANDS(pmadapter))
5105 		pmadapter->fw_bands = (t_u8)GET_FW_DEFAULT_BANDS(pmadapter);
5106 	else
5107 		pmadapter->fw_bands = BAND_B;
5108 
5109 	if ((pmadapter->fw_bands & BAND_A) && (pmadapter->fw_bands & BAND_GN))
5110 		pmadapter->fw_bands |= BAND_AN;
5111 	if (!(pmadapter->fw_bands & BAND_G) && (pmadapter->fw_bands & BAND_GN))
5112 		pmadapter->fw_bands &= ~BAND_GN;
5113 
5114 	pmadapter->config_bands = pmadapter->fw_bands;
5115 	for (i = 0; i < pmadapter->priv_num; i++) {
5116 		if (pmadapter->priv[i])
5117 			pmadapter->priv[i]->config_bands = pmadapter->fw_bands;
5118 	}
5119 
5120 	if (pmadapter->fw_bands & BAND_A) {
5121 		if (pmadapter->fw_bands & BAND_AN) {
5122 			pmadapter->config_bands |= BAND_AN;
5123 			for (i = 0; i < pmadapter->priv_num; i++) {
5124 				if (pmadapter->priv[i])
5125 					pmadapter->priv[i]->config_bands |=
5126 						BAND_AN;
5127 			}
5128 		}
5129 		if (pmadapter->fw_bands & BAND_AAC) {
5130 			pmadapter->config_bands |= BAND_AAC;
5131 			for (i = 0; i < pmadapter->priv_num; i++) {
5132 				if (pmadapter->priv[i])
5133 					pmadapter->priv[i]->config_bands |=
5134 						BAND_AAC;
5135 			}
5136 		}
5137 		if (pmadapter->fw_bands & BAND_GAC) {
5138 			pmadapter->config_bands |= BAND_GAC;
5139 			for (i = 0; i < pmadapter->priv_num; i++) {
5140 				if (pmadapter->priv[i])
5141 					pmadapter->priv[i]->config_bands |=
5142 						BAND_GAC;
5143 			}
5144 		}
5145 		pmadapter->adhoc_start_band = BAND_A;
5146 		pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A;
5147 	} else if (pmadapter->fw_bands & BAND_G) {
5148 		pmadapter->adhoc_start_band = BAND_G | BAND_B;
5149 		pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
5150 	} else if (pmadapter->fw_bands & BAND_B) {
5151 		pmadapter->adhoc_start_band = BAND_B;
5152 		pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
5153 	}
5154 #endif /* STA_SUPPORT */
5155 
5156 	pmadapter->fw_release_number =
5157 		wlan_le32_to_cpu(hw_spec->fw_release_number);
5158 	pmadapter->number_of_antenna =
5159 		wlan_le16_to_cpu(hw_spec->number_of_antenna) & 0x00ff;
5160 	pmadapter->antinfo =
5161 		(wlan_le16_to_cpu(hw_spec->number_of_antenna) & 0xff00) >> 8;
5162 	PRINTM(MCMND, "num_ant=%d, antinfo=0x%x\n",
5163 	       pmadapter->number_of_antenna, pmadapter->antinfo);
5164 
5165 	PRINTM(MINFO, "GET_HW_SPEC: fw_release_number- 0x%X\n",
5166 	       pmadapter->fw_release_number);
5167 	PRINTM(MINFO, "GET_HW_SPEC: Permanent addr- " MACSTR "\n",
5168 	       MAC2STR(hw_spec->permanent_addr));
5169 	PRINTM(MINFO, "GET_HW_SPEC: hw_if_version=0x%X  version=0x%X\n",
5170 	       wlan_le16_to_cpu(hw_spec->hw_if_version),
5171 	       wlan_le16_to_cpu(hw_spec->version));
5172 
5173 	if (pmpriv->curr_addr[0] == 0xff)
5174 		memmove(pmadapter, pmpriv->curr_addr, hw_spec->permanent_addr,
5175 			MLAN_MAC_ADDR_LENGTH);
5176 	memmove(pmadapter, pmadapter->permanent_addr, hw_spec->permanent_addr,
5177 		MLAN_MAC_ADDR_LENGTH);
5178 	pmadapter->hw_dot_11n_dev_cap =
5179 		wlan_le32_to_cpu(hw_spec->dot_11n_dev_cap);
5180 	pmadapter->hw_dev_mcs_support = hw_spec->dev_mcs_support;
5181 	for (i = 0; i < pmadapter->priv_num; i++) {
5182 		if (pmadapter->priv[i])
5183 			wlan_update_11n_cap(pmadapter->priv[i]);
5184 	}
5185 
5186 	wlan_show_dot11ndevcap(pmadapter, pmadapter->hw_dot_11n_dev_cap);
5187 	wlan_show_devmcssupport(pmadapter, pmadapter->hw_dev_mcs_support);
5188 #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
5189 	defined(PCIE9097) || defined(SD9097) || defined(USB9097) ||            \
5190 	defined(SDNW62X) || defined(PCIENW62X) || defined(USBNW62X)
5191 	pmadapter->user_htstream = pmadapter->hw_dev_mcs_support;
5192 	/** separate stream config for 2.4G and 5G, will be changed according to
5193 	 * antenna cfg*/
5194 	if (pmadapter->fw_bands & BAND_A)
5195 		pmadapter->user_htstream |= (pmadapter->user_htstream << 8);
5196 	PRINTM(MCMND, "user_htstream=0x%x\n", pmadapter->user_htstream);
5197 #endif
5198 
5199 	if (ISSUPP_BEAMFORMING(pmadapter->hw_dot_11n_dev_cap)) {
5200 		PRINTM(MCMND, "Enable Beamforming\n");
5201 		for (i = 0; i < pmadapter->priv_num; i++) {
5202 			if (pmadapter->priv[i])
5203 				pmadapter->priv[i]->tx_bf_cap =
5204 					pmadapter->pcard_info
5205 						->default_11n_tx_bf_cap;
5206 		}
5207 	}
5208 	pmadapter->hw_dot_11ac_dev_cap =
5209 		wlan_le32_to_cpu(hw_spec->Dot11acDevCap);
5210 	pmadapter->hw_dot_11ac_mcs_support =
5211 		wlan_le32_to_cpu(hw_spec->Dot11acMcsSupport);
5212 	for (i = 0; i < pmadapter->priv_num; i++) {
5213 		if (pmadapter->priv[i])
5214 			wlan_update_11ac_cap(pmadapter->priv[i]);
5215 	}
5216 	wlan_show_dot11acdevcap(pmadapter, pmadapter->hw_dot_11ac_dev_cap);
5217 	wlan_show_dot11acmcssupport(pmadapter,
5218 				    pmadapter->hw_dot_11ac_mcs_support);
5219 
5220 #ifdef SDIO
5221 	if (IS_SD(pmadapter->card_type)) {
5222 		pmadapter->pcard_sd->mp_end_port =
5223 			wlan_le16_to_cpu(hw_spec->mp_end_port);
5224 
5225 		for (i = 1; i <= (unsigned)(pmadapter->pcard_sd->max_ports -
5226 					    pmadapter->pcard_sd->mp_end_port);
5227 		     i++)
5228 			pmadapter->pcard_sd->mp_data_port_mask &=
5229 				~(1 << (pmadapter->pcard_sd->max_ports - i));
5230 	}
5231 #endif
5232 
5233 	pmadapter->max_mgmt_ie_index =
5234 		wlan_le16_to_cpu(hw_spec->mgmt_buf_count);
5235 	PRINTM(MCMND, "GET_HW_SPEC: mgmt IE count=%d\n",
5236 	       pmadapter->max_mgmt_ie_index);
5237 	if (!pmadapter->max_mgmt_ie_index ||
5238 	    pmadapter->max_mgmt_ie_index > MAX_MGMT_IE_INDEX)
5239 		pmadapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
5240 
5241 	pmadapter->region_code = wlan_le16_to_cpu(hw_spec->region_code);
5242 	for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
5243 		/* Use the region code to search for the index */
5244 		if (pmadapter->region_code == region_code_index[i])
5245 			break;
5246 	}
5247 	/* If it's unidentified region code, use the default */
5248 	if (i >= MRVDRV_MAX_REGION_CODE) {
5249 		pmadapter->region_code = MRVDRV_DEFAULT_REGION_CODE;
5250 		PRINTM(MWARN,
5251 		       "unidentified region code, use the default (0x%02x)\n",
5252 		       MRVDRV_DEFAULT_REGION_CODE);
5253 	}
5254 	/* Synchronize CFP code with region code */
5255 	pmadapter->cfp_code_bg = pmadapter->region_code;
5256 	pmadapter->cfp_code_a = pmadapter->region_code;
5257 
5258 	if (pmadapter->fw_cap_info & ENHANCE_EXT_SCAN_ENABLE)
5259 		pmadapter->ext_scan_enh = MTRUE;
5260 
5261 #ifdef SDIO
5262 	if (IS_SD(pmadapter->card_type)) {
5263 		if ((pmadapter->fw_cap_info & SDIO_SP_RX_AGGR_ENABLE) &&
5264 		    pmadapter->pcard_sd->sdio_rx_aggr_enable) {
5265 			t_u8 sdio_sp_rx_aggr = MTRUE;
5266 			ret = wlan_prepare_cmd(pmpriv,
5267 					       HostCmd_CMD_SDIO_SP_RX_AGGR_CFG,
5268 					       HostCmd_ACT_GEN_SET, 0, MNULL,
5269 					       &sdio_sp_rx_aggr);
5270 			if (ret) {
5271 				ret = MLAN_STATUS_FAILURE;
5272 				goto done;
5273 			}
5274 		} else {
5275 			pmadapter->pcard_sd->sdio_rx_aggr_enable = MFALSE;
5276 			PRINTM(MCMND, "FW: SDIO rx aggr disabled 0x%x\n",
5277 			       pmadapter->fw_cap_info);
5278 		}
5279 	}
5280 #endif
5281 
5282 	if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
5283 				 pmadapter->fw_bands)) {
5284 		if (pioctl_req)
5285 			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
5286 		ret = MLAN_STATUS_FAILURE;
5287 		goto done;
5288 	}
5289 #ifdef STA_SUPPORT
5290 	if (wlan_11d_set_universaltable(pmpriv, pmadapter->fw_bands)) {
5291 		if (pioctl_req)
5292 			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
5293 		ret = MLAN_STATUS_FAILURE;
5294 		goto done;
5295 	}
5296 #endif /* STA_SUPPORT */
5297 	if (pmadapter->fw_cap_info & FW_CAPINFO_ECSA) {
5298 		t_u8 ecsa_enable = MTRUE;
5299 		pmadapter->ecsa_enable = MTRUE;
5300 		PRINTM(MCMND, "pmadapter->ecsa_enable=%d\n",
5301 		       pmadapter->ecsa_enable);
5302 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB,
5303 				       HostCmd_ACT_GEN_SET, ECSAEnable_i, MNULL,
5304 				       &ecsa_enable);
5305 		if (ret) {
5306 			ret = MLAN_STATUS_FAILURE;
5307 			goto done;
5308 		}
5309 	}
5310 	if (pmadapter->fw_cap_info & FW_CAPINFO_GET_LOG) {
5311 		pmadapter->getlog_enable = MTRUE;
5312 		PRINTM(MCMND, "pmadapter->getlog_enable=%d\n",
5313 		       pmadapter->getlog_enable);
5314 	}
5315 
5316 	left_len = resp->size - sizeof(HostCmd_DS_GET_HW_SPEC) - S_DS_GEN;
5317 	tlv = (MrvlIEtypesHeader_t *)((t_u8 *)hw_spec +
5318 				      sizeof(HostCmd_DS_GET_HW_SPEC));
5319 	while (left_len > sizeof(MrvlIEtypesHeader_t)) {
5320 		tlv_type = wlan_le16_to_cpu(tlv->type);
5321 		tlv_len = wlan_le16_to_cpu(tlv->len);
5322 		switch (tlv_type) {
5323 		case TLV_TYPE_FW_VER_INFO:
5324 			api_rev = (MrvlIEtypes_fw_ver_info_t *)tlv;
5325 			api_id = wlan_le16_to_cpu(api_rev->api_id);
5326 			switch (api_id) {
5327 			case FW_API_VER_ID:
5328 				pmadapter->fw_ver = api_rev->major_ver;
5329 				pmadapter->fw_min_ver = api_rev->minor_ver;
5330 				PRINTM(MCMND, "fw ver=%d.%d\n",
5331 				       api_rev->major_ver, api_rev->minor_ver);
5332 				break;
5333 			case UAP_FW_API_VER_ID:
5334 				pmadapter->uap_fw_ver = api_rev->major_ver;
5335 				PRINTM(MCMND, "uap fw ver=%d.%d\n",
5336 				       api_rev->major_ver, api_rev->minor_ver);
5337 				break;
5338 			case CHANRPT_API_VER_ID:
5339 				pmadapter->chanrpt_param_bandcfg =
5340 					api_rev->minor_ver;
5341 				PRINTM(MCMND, "chanrpt api ver=%d.%d\n",
5342 				       api_rev->major_ver, api_rev->minor_ver);
5343 				break;
5344 			case FW_HOTFIX_VER_ID:
5345 				pmadapter->fw_hotfix_ver = api_rev->major_ver;
5346 				PRINTM(MCMND, "fw hotfix ver=%d\n",
5347 				       api_rev->major_ver);
5348 				break;
5349 			default:
5350 				break;
5351 			}
5352 			break;
5353 		case TLV_TYPE_MAX_CONN:
5354 			tlv_max_conn = (MrvlIEtypes_Max_Conn_t *)tlv;
5355 			PRINTM(MMSG, "max_p2p_conn = %d, max_sta_conn = %d\n",
5356 			       tlv_max_conn->max_p2p_conn,
5357 			       tlv_max_conn->max_sta_conn);
5358 			if (tlv_max_conn->max_p2p_conn &&
5359 			    tlv_max_conn->max_sta_conn)
5360 				pmadapter->max_sta_conn =
5361 					MIN(tlv_max_conn->max_sta_conn,
5362 					    tlv_max_conn->max_p2p_conn);
5363 			else if (tlv_max_conn->max_sta_conn)
5364 				pmadapter->max_sta_conn =
5365 					tlv_max_conn->max_sta_conn;
5366 			else if (tlv_max_conn->max_p2p_conn)
5367 				pmadapter->max_sta_conn =
5368 					tlv_max_conn->max_p2p_conn;
5369 			else
5370 				pmadapter->max_sta_conn = 0;
5371 			break;
5372 		case TLV_TYPE_EXTENSION_ID:
5373 			ext_tlv = (MrvlIEtypes_Extension_t *)tlv;
5374 			if (ext_tlv->ext_id == HE_CAPABILITY) {
5375 				ext_tlv->type = tlv_type;
5376 				ext_tlv->len = tlv_len;
5377 				wlan_update_11ax_cap(
5378 					pmadapter,
5379 					(MrvlIEtypes_Extension_t *)ext_tlv);
5380 			}
5381 			break;
5382 		case TLV_TYPE_FW_CAP_INFO:
5383 			fw_cap_tlv = (MrvlIEtypes_fw_cap_info_t *)tlv;
5384 			pmadapter->fw_cap_info =
5385 				wlan_le32_to_cpu(fw_cap_tlv->fw_cap_info);
5386 			pmadapter->fw_cap_ext =
5387 				wlan_le32_to_cpu(fw_cap_tlv->fw_cap_ext);
5388 			PRINTM(MCMND, "fw_cap_info=0x%x fw_cap_ext=0x%x\n",
5389 			       pmadapter->fw_cap_info, pmadapter->fw_cap_ext);
5390 			break;
5391 		case TLV_TYPE_SECURE_BOOT_UUID:
5392 			sb_uuid_tlv = (MrvlIEtypes_Secure_Boot_Uuid_t *)tlv;
5393 			pmadapter->uuid_lo = sb_uuid_tlv->uuid_lo;
5394 			pmadapter->uuid_hi = sb_uuid_tlv->uuid_hi;
5395 			PRINTM(MMSG, "uuid: %016llx%016llx\n",
5396 			       pmadapter->uuid_lo, pmadapter->uuid_hi);
5397 			break;
5398 		default:
5399 			break;
5400 		}
5401 		left_len -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
5402 		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
5403 					      sizeof(MrvlIEtypesHeader_t));
5404 	}
5405 done:
5406 	LEAVE();
5407 	return ret;
5408 }
5409 
5410 /**
5411  *  @brief This function prepares command of radio_control.
5412  *
5413  *  @param pmpriv       A pointer to mlan_private structure
5414  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
5415  *  @param cmd_action   The action: GET or SET
5416  *  @param pdata_buf    A pointer to data buffer
5417  *
5418  *  @return             MLAN_STATUS_SUCCESS
5419  */
wlan_cmd_802_11_radio_control(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)5420 mlan_status wlan_cmd_802_11_radio_control(pmlan_private pmpriv,
5421 					  HostCmd_DS_COMMAND *cmd,
5422 					  t_u16 cmd_action, t_void *pdata_buf)
5423 {
5424 	HostCmd_DS_802_11_RADIO_CONTROL *pradio_control = &cmd->params.radio;
5425 	t_u32 radio_ctl;
5426 	ENTER();
5427 	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_RADIO_CONTROL)) +
5428 				     S_DS_GEN);
5429 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RADIO_CONTROL);
5430 	pradio_control->action = wlan_cpu_to_le16(cmd_action);
5431 	memcpy_ext(pmpriv->adapter, &radio_ctl, pdata_buf, sizeof(t_u32),
5432 		   sizeof(radio_ctl));
5433 	pradio_control->control = wlan_cpu_to_le16((t_u16)radio_ctl);
5434 	LEAVE();
5435 	return MLAN_STATUS_SUCCESS;
5436 }
5437 
5438 /**
5439  *  @brief This function handles the command response of radio_control
5440  *
5441  *  @param pmpriv       A pointer to mlan_private structure
5442  *  @param resp         A pointer to HostCmd_DS_COMMAND
5443  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
5444  *
5445  *  @return             MLAN_STATUS_SUCCESS
5446  */
wlan_ret_802_11_radio_control(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)5447 mlan_status wlan_ret_802_11_radio_control(pmlan_private pmpriv,
5448 					  HostCmd_DS_COMMAND *resp,
5449 					  mlan_ioctl_req *pioctl_buf)
5450 {
5451 	HostCmd_DS_802_11_RADIO_CONTROL *pradio_ctrl =
5452 		(HostCmd_DS_802_11_RADIO_CONTROL *)&resp->params.radio;
5453 	mlan_ds_radio_cfg *radio_cfg = MNULL;
5454 	mlan_adapter *pmadapter = pmpriv->adapter;
5455 
5456 	ENTER();
5457 	pmadapter->radio_on = wlan_le16_to_cpu(pradio_ctrl->control);
5458 	if (pioctl_buf) {
5459 		radio_cfg = (mlan_ds_radio_cfg *)pioctl_buf->pbuf;
5460 		radio_cfg->param.radio_on_off = (t_u32)pmadapter->radio_on;
5461 		pioctl_buf->data_read_written = sizeof(mlan_ds_radio_cfg);
5462 	}
5463 	LEAVE();
5464 	return MLAN_STATUS_SUCCESS;
5465 }
5466 
5467 /**
5468  *  @brief This function prepares command of remain_on_channel.
5469  *
5470  *  @param pmpriv       A pointer to mlan_private structure
5471  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
5472  *  @param cmd_action   The action: GET or SET
5473  *  @param pdata_buf    A pointer to data buffer
5474  *
5475  *  @return             MLAN_STATUS_SUCCESS
5476  */
wlan_cmd_remain_on_channel(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)5477 mlan_status wlan_cmd_remain_on_channel(pmlan_private pmpriv,
5478 				       HostCmd_DS_COMMAND *cmd,
5479 				       t_u16 cmd_action, t_void *pdata_buf)
5480 {
5481 	HostCmd_DS_REMAIN_ON_CHANNEL *remain_channel =
5482 		&cmd->params.remain_on_chan;
5483 	mlan_ds_remain_chan *cfg = (mlan_ds_remain_chan *)pdata_buf;
5484 	ENTER();
5485 	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_REMAIN_ON_CHANNEL)) +
5486 				     S_DS_GEN);
5487 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_REMAIN_ON_CHANNEL);
5488 	remain_channel->action = cmd_action;
5489 	if (cmd_action == HostCmd_ACT_GEN_SET) {
5490 		if (cfg->remove) {
5491 			remain_channel->action = HostCmd_ACT_GEN_REMOVE;
5492 		} else {
5493 			remain_channel->bandcfg = cfg->bandcfg;
5494 			remain_channel->channel = cfg->channel;
5495 			remain_channel->remain_period =
5496 				wlan_cpu_to_le32(cfg->remain_period);
5497 		}
5498 	}
5499 	remain_channel->action = wlan_cpu_to_le16(remain_channel->action);
5500 
5501 	LEAVE();
5502 	return MLAN_STATUS_SUCCESS;
5503 }
5504 
5505 /**
5506  *  @brief This function handles the command response of remain_on_channel
5507  *
5508  *  @param pmpriv       A pointer to mlan_private structure
5509  *  @param resp         A pointer to HostCmd_DS_COMMAND
5510  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
5511  *
5512  *  @return             MLAN_STATUS_SUCCESS
5513  */
wlan_ret_remain_on_channel(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)5514 mlan_status wlan_ret_remain_on_channel(pmlan_private pmpriv,
5515 				       HostCmd_DS_COMMAND *resp,
5516 				       mlan_ioctl_req *pioctl_buf)
5517 {
5518 	HostCmd_DS_REMAIN_ON_CHANNEL *remain_channel =
5519 		&resp->params.remain_on_chan;
5520 	mlan_ds_radio_cfg *radio_cfg = MNULL;
5521 
5522 	ENTER();
5523 	if (pioctl_buf) {
5524 		radio_cfg = (mlan_ds_radio_cfg *)pioctl_buf->pbuf;
5525 		radio_cfg->param.remain_chan.status = remain_channel->status;
5526 		radio_cfg->param.remain_chan.bandcfg = remain_channel->bandcfg;
5527 		radio_cfg->param.remain_chan.channel = remain_channel->channel;
5528 		radio_cfg->param.remain_chan.remain_period =
5529 			wlan_le32_to_cpu(remain_channel->remain_period);
5530 		pioctl_buf->data_read_written = sizeof(mlan_ds_radio_cfg);
5531 	}
5532 	LEAVE();
5533 	return MLAN_STATUS_SUCCESS;
5534 }
5535 
5536 #ifdef WIFI_DIRECT_SUPPORT
5537 /**
5538  *  @brief This function prepares command of wifi direct mode.
5539  *
5540  *  @param pmpriv       A pointer to mlan_private structure
5541  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
5542  *  @param cmd_action   The action: GET or SET
5543  *  @param pdata_buf    A pointer to data buffer
5544  *
5545  *  @return             MLAN_STATUS_SUCCESS
5546  */
wlan_cmd_wifi_direct_mode(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)5547 mlan_status wlan_cmd_wifi_direct_mode(pmlan_private pmpriv,
5548 				      HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
5549 				      t_void *pdata_buf)
5550 {
5551 	HostCmd_DS_WIFI_DIRECT_MODE *wfd_mode = &cmd->params.wifi_direct_mode;
5552 	t_u16 mode = *((t_u16 *)pdata_buf);
5553 	ENTER();
5554 	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_WIFI_DIRECT_MODE)) +
5555 				     S_DS_GEN);
5556 	cmd->command = wlan_cpu_to_le16(HOST_CMD_WIFI_DIRECT_MODE_CONFIG);
5557 	wfd_mode->action = wlan_cpu_to_le16(cmd_action);
5558 	if (cmd_action == HostCmd_ACT_GEN_SET)
5559 		wfd_mode->mode = wlan_cpu_to_le16(mode);
5560 
5561 	LEAVE();
5562 	return MLAN_STATUS_SUCCESS;
5563 }
5564 
5565 /**
5566  *  @brief This function handles the command response of wifi direct mode
5567  *
5568  *  @param pmpriv       A pointer to mlan_private structure
5569  *  @param resp         A pointer to HostCmd_DS_COMMAND
5570  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
5571  *
5572  *  @return             MLAN_STATUS_SUCCESS
5573  */
wlan_ret_wifi_direct_mode(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)5574 mlan_status wlan_ret_wifi_direct_mode(pmlan_private pmpriv,
5575 				      HostCmd_DS_COMMAND *resp,
5576 				      mlan_ioctl_req *pioctl_buf)
5577 {
5578 	HostCmd_DS_WIFI_DIRECT_MODE *wfd_mode = &resp->params.wifi_direct_mode;
5579 	mlan_ds_bss *bss = MNULL;
5580 
5581 	ENTER();
5582 	if (pioctl_buf) {
5583 		bss = (mlan_ds_bss *)pioctl_buf->pbuf;
5584 		bss->param.wfd_mode = wlan_le16_to_cpu(wfd_mode->mode);
5585 		pioctl_buf->data_read_written = sizeof(mlan_ds_bss);
5586 	}
5587 	LEAVE();
5588 	return MLAN_STATUS_SUCCESS;
5589 }
5590 
5591 /**
5592  *  @brief This function prepares command of p2p_params_config.
5593  *
5594  *  @param pmpriv       A pointer to mlan_private structure
5595  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
5596  *  @param cmd_action   The action: GET or SET
5597  *  @param pdata_buf    A pointer to data buffer
5598  *
5599  *  @return             MLAN_STATUS_SUCCESS
5600  */
wlan_cmd_p2p_params_config(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)5601 mlan_status wlan_cmd_p2p_params_config(pmlan_private pmpriv,
5602 				       HostCmd_DS_COMMAND *cmd,
5603 				       t_u16 cmd_action, t_void *pdata_buf)
5604 {
5605 	HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG *p2p_config =
5606 		&cmd->params.p2p_params_config;
5607 	mlan_ds_wifi_direct_config *cfg =
5608 		(mlan_ds_wifi_direct_config *)pdata_buf;
5609 	MrvlIEtypes_NoA_setting_t *pnoa_tlv = MNULL;
5610 	MrvlIEtypes_OPP_PS_setting_t *popp_ps_tlv = MNULL;
5611 	t_u8 *tlv = MNULL;
5612 	ENTER();
5613 
5614 	cmd->size = sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG) + S_DS_GEN;
5615 	cmd->command = wlan_cpu_to_le16(HOST_CMD_P2P_PARAMS_CONFIG);
5616 	p2p_config->action = wlan_cpu_to_le16(cmd_action);
5617 	if (cmd_action == HostCmd_ACT_GEN_SET) {
5618 		tlv = (t_u8 *)p2p_config->tlv_buf;
5619 		if (cfg->flags & WIFI_DIRECT_NOA) {
5620 			pnoa_tlv = (MrvlIEtypes_NoA_setting_t *)tlv;
5621 			pnoa_tlv->header.type =
5622 				wlan_cpu_to_le16(TLV_TYPE_WIFI_DIRECT_NOA);
5623 			pnoa_tlv->header.len = wlan_cpu_to_le16(
5624 				sizeof(MrvlIEtypes_NoA_setting_t) -
5625 				sizeof(MrvlIEtypesHeader_t));
5626 			pnoa_tlv->enable = cfg->noa_enable;
5627 			pnoa_tlv->index = wlan_cpu_to_le16(cfg->index);
5628 			pnoa_tlv->noa_count = cfg->noa_count;
5629 			pnoa_tlv->noa_duration =
5630 				wlan_cpu_to_le32(cfg->noa_duration);
5631 			pnoa_tlv->noa_interval =
5632 				wlan_cpu_to_le32(cfg->noa_interval);
5633 			cmd->size += sizeof(MrvlIEtypes_NoA_setting_t);
5634 			tlv += sizeof(MrvlIEtypes_NoA_setting_t);
5635 			PRINTM(MCMND,
5636 			       "Set NOA: enable=%d index=%d, count=%d, duration=%d interval=%d\n",
5637 			       cfg->noa_enable, cfg->index, cfg->noa_count,
5638 			       (int)cfg->noa_duration, (int)cfg->noa_interval);
5639 		}
5640 		if (cfg->flags & WIFI_DIRECT_OPP_PS) {
5641 			popp_ps_tlv = (MrvlIEtypes_OPP_PS_setting_t *)tlv;
5642 			popp_ps_tlv->header.type =
5643 				wlan_cpu_to_le16(TLV_TYPE_WIFI_DIRECT_OPP_PS);
5644 			popp_ps_tlv->header.len = wlan_cpu_to_le16(
5645 				sizeof(MrvlIEtypes_OPP_PS_setting_t) -
5646 				sizeof(MrvlIEtypesHeader_t));
5647 
5648 			popp_ps_tlv->enable = cfg->ct_window;
5649 			popp_ps_tlv->enable |= cfg->opp_ps_enable << 7;
5650 			cmd->size += sizeof(MrvlIEtypes_OPP_PS_setting_t);
5651 			PRINTM(MCMND, "Set OPP_PS: enable=%d ct_win=%d\n",
5652 			       cfg->opp_ps_enable, cfg->ct_window);
5653 		}
5654 	} else if (cmd_action == HostCmd_ACT_GEN_GET) {
5655 		tlv = (t_u8 *)p2p_config->tlv_buf;
5656 		if (cfg->flags & WIFI_DIRECT_NOA) {
5657 			pnoa_tlv = (MrvlIEtypes_NoA_setting_t *)tlv;
5658 			pnoa_tlv->header.type =
5659 				wlan_cpu_to_le16(TLV_TYPE_WIFI_DIRECT_NOA);
5660 			pnoa_tlv->header.len = wlan_cpu_to_le16(
5661 				sizeof(MrvlIEtypes_NoA_setting_t) -
5662 				sizeof(MrvlIEtypesHeader_t));
5663 			cmd->size += sizeof(MrvlIEtypes_NoA_setting_t);
5664 			tlv += sizeof(MrvlIEtypes_NoA_setting_t);
5665 		}
5666 
5667 		if (cfg->flags & WIFI_DIRECT_OPP_PS) {
5668 			popp_ps_tlv = (MrvlIEtypes_OPP_PS_setting_t *)tlv;
5669 			popp_ps_tlv->header.type =
5670 				wlan_cpu_to_le16(TLV_TYPE_WIFI_DIRECT_OPP_PS);
5671 			popp_ps_tlv->header.len = wlan_cpu_to_le16(
5672 				sizeof(MrvlIEtypes_OPP_PS_setting_t) -
5673 				sizeof(MrvlIEtypesHeader_t));
5674 			cmd->size += sizeof(MrvlIEtypes_OPP_PS_setting_t);
5675 		}
5676 	}
5677 	cmd->size = wlan_cpu_to_le16(cmd->size);
5678 	LEAVE();
5679 	return MLAN_STATUS_SUCCESS;
5680 }
5681 
5682 /**
5683  *  @brief This function handles the command response of p2p_params_config
5684  *
5685  *  @param pmpriv       A pointer to mlan_private structure
5686  *  @param resp         A pointer to HostCmd_DS_COMMAND
5687  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
5688  *
5689  *  @return             MLAN_STATUS_SUCCESS
5690  */
wlan_ret_p2p_params_config(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)5691 mlan_status wlan_ret_p2p_params_config(pmlan_private pmpriv,
5692 				       HostCmd_DS_COMMAND *resp,
5693 				       mlan_ioctl_req *pioctl_buf)
5694 {
5695 	HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG *p2p_config =
5696 		&resp->params.p2p_params_config;
5697 	mlan_ds_misc_cfg *cfg = MNULL;
5698 	MrvlIEtypes_NoA_setting_t *pnoa_tlv = MNULL;
5699 	MrvlIEtypes_OPP_PS_setting_t *popp_ps_tlv = MNULL;
5700 	MrvlIEtypesHeader_t *tlv = MNULL;
5701 	t_u16 tlv_buf_left = 0;
5702 	t_u16 tlv_type = 0;
5703 	t_u16 tlv_len = 0;
5704 
5705 	ENTER();
5706 	if (wlan_le16_to_cpu(p2p_config->action) == HostCmd_ACT_GEN_GET) {
5707 		if (pioctl_buf) {
5708 			cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
5709 			tlv = (MrvlIEtypesHeader_t *)(p2p_config->tlv_buf);
5710 			tlv_buf_left =
5711 				resp->size -
5712 				(sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG) +
5713 				 S_DS_GEN);
5714 			while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
5715 				tlv_type = wlan_le16_to_cpu(tlv->type);
5716 				tlv_len = wlan_le16_to_cpu(tlv->len);
5717 				if (tlv_buf_left <
5718 				    (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
5719 					PRINTM(MERROR,
5720 					       "Error processing p2p param config TLVs, bytes left < TLV length\n");
5721 					break;
5722 				}
5723 				switch (tlv_type) {
5724 				case TLV_TYPE_WIFI_DIRECT_NOA:
5725 					pnoa_tlv = (MrvlIEtypes_NoA_setting_t *)
5726 						tlv;
5727 					cfg->param.p2p_config.flags |=
5728 						WIFI_DIRECT_NOA;
5729 					cfg->param.p2p_config.noa_enable =
5730 						pnoa_tlv->enable;
5731 					cfg->param.p2p_config.index =
5732 						wlan_le16_to_cpu(
5733 							pnoa_tlv->index);
5734 					cfg->param.p2p_config.noa_count =
5735 						pnoa_tlv->noa_count;
5736 					cfg->param.p2p_config.noa_duration =
5737 						wlan_le32_to_cpu(
5738 							pnoa_tlv->noa_duration);
5739 					cfg->param.p2p_config.noa_interval =
5740 						wlan_le32_to_cpu(
5741 							pnoa_tlv->noa_interval);
5742 					PRINTM(MCMND,
5743 					       "Get NOA: enable=%d index=%d, count=%d, duration=%d interval=%d\n",
5744 					       cfg->param.p2p_config.noa_enable,
5745 					       cfg->param.p2p_config.index,
5746 					       cfg->param.p2p_config.noa_count,
5747 					       (int)cfg->param.p2p_config
5748 						       .noa_duration,
5749 					       (int)cfg->param.p2p_config
5750 						       .noa_interval);
5751 					break;
5752 				case TLV_TYPE_WIFI_DIRECT_OPP_PS:
5753 					popp_ps_tlv =
5754 						(MrvlIEtypes_OPP_PS_setting_t *)
5755 							tlv;
5756 					cfg->param.p2p_config.flags |=
5757 						WIFI_DIRECT_OPP_PS;
5758 					cfg->param.p2p_config.opp_ps_enable =
5759 						(popp_ps_tlv->enable & 0x80) >>
5760 						7;
5761 					cfg->param.p2p_config.ct_window =
5762 						popp_ps_tlv->enable & 0x7f;
5763 					PRINTM(MCMND,
5764 					       "Get OPP_PS: enable=%d ct_win=%d\n",
5765 					       cfg->param.p2p_config
5766 						       .opp_ps_enable,
5767 					       cfg->param.p2p_config.ct_window);
5768 					break;
5769 				default:
5770 					break;
5771 				}
5772 				tlv_buf_left -=
5773 					tlv_len + sizeof(MrvlIEtypesHeader_t);
5774 				tlv = (MrvlIEtypesHeader_t
5775 					       *)((t_u8 *)tlv + tlv_len +
5776 						  sizeof(MrvlIEtypesHeader_t));
5777 			}
5778 			pioctl_buf->data_read_written =
5779 				sizeof(mlan_ds_wifi_direct_config);
5780 		}
5781 	}
5782 	LEAVE();
5783 	return MLAN_STATUS_SUCCESS;
5784 }
5785 #endif
5786 
5787 /**
5788  *  @brief This function prepares command of GPIO TSF LATCH.
5789  *
5790  *  @param pmpriv       A pointer to mlan_private structure
5791  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
5792  *  @param cmd_action   The action: GET or SET
5793  *  @param pioctl_buf   A pointer to mlan_ioctl_req buf
5794  *  @param pdata_buf    A pointer to data buffer
5795  *
5796  *  @return             MLAN_STATUS_SUCCESS
5797  */
wlan_cmd_gpio_tsf_latch(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,mlan_ioctl_req * pioctl_buf,t_void * pdata_buf)5798 mlan_status wlan_cmd_gpio_tsf_latch(pmlan_private pmpriv,
5799 				    HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
5800 				    mlan_ioctl_req *pioctl_buf,
5801 				    t_void *pdata_buf)
5802 {
5803 	HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG *gpio_tsf_config =
5804 		&cmd->params.gpio_tsf_latch;
5805 	mlan_ds_gpio_tsf_latch *cfg = (mlan_ds_gpio_tsf_latch *)pdata_buf;
5806 	mlan_ds_misc_cfg *misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
5807 
5808 	mlan_ds_tsf_info *tsf_info = (mlan_ds_tsf_info *)pdata_buf;
5809 	MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *gpio_tsf_latch_config = MNULL;
5810 	MrvlIEtypes_GPIO_TSF_LATCH_REPORT *gpio_tsf_latch_report = MNULL;
5811 	t_u8 *tlv = MNULL;
5812 	ENTER();
5813 
5814 	cmd->size = sizeof(HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG) + S_DS_GEN;
5815 	cmd->command = wlan_cpu_to_le16(HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG);
5816 	gpio_tsf_config->action = wlan_cpu_to_le16(cmd_action);
5817 	if (cmd_action == HostCmd_ACT_GEN_SET) {
5818 		tlv = (t_u8 *)gpio_tsf_config->tlv_buf;
5819 		if (misc_cfg->sub_command == MLAN_OID_MISC_GPIO_TSF_LATCH) {
5820 			gpio_tsf_latch_config =
5821 				(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *)tlv;
5822 			gpio_tsf_latch_config->header.type = wlan_cpu_to_le16(
5823 				TLV_TYPE_GPIO_TSF_LATCH_CONFIG);
5824 			gpio_tsf_latch_config->header.len = wlan_cpu_to_le16(
5825 				sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG) -
5826 				sizeof(MrvlIEtypesHeader_t));
5827 			gpio_tsf_latch_config->clock_sync_mode =
5828 				cfg->clock_sync_mode;
5829 			gpio_tsf_latch_config->clock_sync_Role =
5830 				cfg->clock_sync_Role;
5831 			gpio_tsf_latch_config->clock_sync_gpio_pin_number =
5832 				cfg->clock_sync_gpio_pin_number;
5833 			gpio_tsf_latch_config->clock_sync_gpio_level_toggle =
5834 				cfg->clock_sync_gpio_level_toggle;
5835 			gpio_tsf_latch_config->clock_sync_gpio_pulse_width =
5836 				wlan_cpu_to_le16(
5837 					cfg->clock_sync_gpio_pulse_width);
5838 			cmd->size += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG);
5839 			tlv += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG);
5840 			PRINTM(MCMND,
5841 			       "Set GPIO TSF latch config: Mode=%d Role=%d, GPIO Pin Number=%d, GPIO level/toggle=%d GPIO pulse width=%d\n",
5842 			       cfg->clock_sync_mode, cfg->clock_sync_Role,
5843 			       cfg->clock_sync_gpio_pin_number,
5844 			       cfg->clock_sync_gpio_level_toggle,
5845 			       (int)cfg->clock_sync_gpio_pulse_width);
5846 		}
5847 	} else if (cmd_action == HostCmd_ACT_GEN_GET) {
5848 		tlv = (t_u8 *)gpio_tsf_config->tlv_buf;
5849 		if (misc_cfg->sub_command == MLAN_OID_MISC_GPIO_TSF_LATCH) {
5850 			gpio_tsf_latch_config =
5851 				(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *)tlv;
5852 			gpio_tsf_latch_config->header.type = wlan_cpu_to_le16(
5853 				TLV_TYPE_GPIO_TSF_LATCH_CONFIG);
5854 			gpio_tsf_latch_config->header.len = wlan_cpu_to_le16(
5855 				sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG) -
5856 				sizeof(MrvlIEtypesHeader_t));
5857 			cmd->size += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG);
5858 			tlv += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG);
5859 		}
5860 
5861 		if (misc_cfg->sub_command == MLAN_OID_MISC_GET_TSF_INFO) {
5862 			gpio_tsf_latch_report =
5863 				(MrvlIEtypes_GPIO_TSF_LATCH_REPORT *)tlv;
5864 			gpio_tsf_latch_report->header.type = wlan_cpu_to_le16(
5865 				TLV_TYPE_GPIO_TSF_LATCH_REPORT);
5866 			gpio_tsf_latch_report->header.len = wlan_cpu_to_le16(
5867 				sizeof(MrvlIEtypes_GPIO_TSF_LATCH_REPORT) -
5868 				sizeof(MrvlIEtypesHeader_t));
5869 			gpio_tsf_latch_report->tsf_format =
5870 				wlan_cpu_to_le16(tsf_info->tsf_format);
5871 			PRINTM(MCMND, "Get TSF info: format=%d\n",
5872 			       tsf_info->tsf_format);
5873 			cmd->size += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_REPORT);
5874 		}
5875 	}
5876 	cmd->size = wlan_cpu_to_le16(cmd->size);
5877 	LEAVE();
5878 	return MLAN_STATUS_SUCCESS;
5879 }
5880 
5881 /**
5882  *  @brief This function handles the command response of GPIO TSF Latch
5883  *
5884  *  @param pmpriv       A pointer to mlan_private structure
5885  *  @param resp         A pointer to HostCmd_DS_COMMAND
5886  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
5887  *
5888  *  @return             MLAN_STATUS_SUCCESS
5889  */
wlan_ret_gpio_tsf_latch(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)5890 mlan_status wlan_ret_gpio_tsf_latch(pmlan_private pmpriv,
5891 				    HostCmd_DS_COMMAND *resp,
5892 				    mlan_ioctl_req *pioctl_buf)
5893 {
5894 	HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG *gpio_tsf_config =
5895 		&resp->params.gpio_tsf_latch;
5896 	mlan_ds_misc_cfg *cfg = MNULL;
5897 	MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *gpio_tsf_latch_config = MNULL;
5898 	MrvlIEtypes_GPIO_TSF_LATCH_REPORT *gpio_tsf_latch_report = MNULL;
5899 	MrvlIEtypesHeader_t *tlv = MNULL;
5900 	t_u16 tlv_buf_left = 0;
5901 	t_u16 tlv_type = 0;
5902 	t_u16 tlv_len = 0;
5903 
5904 	ENTER();
5905 	if (wlan_le16_to_cpu(gpio_tsf_config->action) == HostCmd_ACT_GEN_GET) {
5906 		if (pioctl_buf) {
5907 			cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
5908 			tlv = (MrvlIEtypesHeader_t *)(gpio_tsf_config->tlv_buf);
5909 			tlv_buf_left =
5910 				resp->size -
5911 				(sizeof(HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG) +
5912 				 S_DS_GEN);
5913 			while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
5914 				tlv_type = wlan_le16_to_cpu(tlv->type);
5915 				tlv_len = wlan_le16_to_cpu(tlv->len);
5916 				if (tlv_buf_left <
5917 				    (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
5918 					PRINTM(MERROR,
5919 					       "Error processing gpio tsf latch config TLVs, bytes left < TLV length\n");
5920 					break;
5921 				}
5922 				switch (tlv_type) {
5923 				case TLV_TYPE_GPIO_TSF_LATCH_CONFIG:
5924 					if (cfg->sub_command ==
5925 					    MLAN_OID_MISC_GPIO_TSF_LATCH) {
5926 						gpio_tsf_latch_config =
5927 							(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG
5928 								 *)tlv;
5929 						cfg->param.gpio_tsf_latch_config
5930 							.clock_sync_mode =
5931 							gpio_tsf_latch_config
5932 								->clock_sync_mode;
5933 						cfg->param.gpio_tsf_latch_config
5934 							.clock_sync_Role =
5935 							gpio_tsf_latch_config
5936 								->clock_sync_Role;
5937 						cfg->param.gpio_tsf_latch_config
5938 							.clock_sync_gpio_pin_number =
5939 							gpio_tsf_latch_config
5940 								->clock_sync_gpio_pin_number;
5941 						cfg->param.gpio_tsf_latch_config
5942 							.clock_sync_gpio_level_toggle =
5943 							gpio_tsf_latch_config
5944 								->clock_sync_gpio_level_toggle;
5945 						cfg->param.gpio_tsf_latch_config
5946 							.clock_sync_gpio_pulse_width =
5947 							wlan_le16_to_cpu(
5948 								gpio_tsf_latch_config
5949 									->clock_sync_gpio_pulse_width);
5950 						PRINTM(MCMND,
5951 						       "Get GPIO TSF latch config: Mode=%d Role=%d, GPIO Pin Number=%d, GPIO level/toggle=%d GPIO pulse width=%d\n",
5952 						       cfg->param
5953 							       .gpio_tsf_latch_config
5954 							       .clock_sync_mode,
5955 						       cfg->param
5956 							       .gpio_tsf_latch_config
5957 							       .clock_sync_Role,
5958 						       cfg->param
5959 							       .gpio_tsf_latch_config
5960 							       .clock_sync_gpio_pin_number,
5961 						       cfg->param
5962 							       .gpio_tsf_latch_config
5963 							       .clock_sync_gpio_level_toggle,
5964 						       (int)cfg->param
5965 							       .gpio_tsf_latch_config
5966 							       .clock_sync_gpio_pulse_width);
5967 					}
5968 					break;
5969 				case TLV_TYPE_GPIO_TSF_LATCH_REPORT:
5970 					if (cfg->sub_command ==
5971 					    MLAN_OID_MISC_GET_TSF_INFO) {
5972 						gpio_tsf_latch_report =
5973 							(MrvlIEtypes_GPIO_TSF_LATCH_REPORT
5974 								 *)tlv;
5975 						cfg->param.tsf_info
5976 							.tsf_format = wlan_le16_to_cpu(
5977 							gpio_tsf_latch_report
5978 								->tsf_format);
5979 						cfg->param.tsf_info
5980 							.tsf_info = wlan_le16_to_cpu(
5981 							gpio_tsf_latch_report
5982 								->tsf_info);
5983 						cfg->param.tsf_info
5984 							.tsf = wlan_le64_to_cpu(
5985 							gpio_tsf_latch_report
5986 								->tsf);
5987 						cfg->param.tsf_info
5988 							.tsf_offset = wlan_le16_to_cpu(
5989 							gpio_tsf_latch_report
5990 								->tsf_offset);
5991 						PRINTM(MCMND,
5992 						       "Get GPIO TSF latch report : format=%d\n info=%d tsf=%llu offset=%d",
5993 						       cfg->param.tsf_info
5994 							       .tsf_format,
5995 						       cfg->param.tsf_info
5996 							       .tsf_info,
5997 						       cfg->param.tsf_info.tsf,
5998 						       cfg->param.tsf_info
5999 							       .tsf_offset);
6000 					}
6001 					break;
6002 				default:
6003 					break;
6004 				}
6005 				tlv_buf_left -=
6006 					tlv_len + sizeof(MrvlIEtypesHeader_t);
6007 				tlv = (MrvlIEtypesHeader_t
6008 					       *)((t_u8 *)tlv + tlv_len +
6009 						  sizeof(MrvlIEtypesHeader_t));
6010 			}
6011 			if (cfg->sub_command == MLAN_OID_MISC_GPIO_TSF_LATCH)
6012 				pioctl_buf->data_read_written =
6013 					sizeof(mlan_ds_gpio_tsf_latch);
6014 			else if (cfg->sub_command == MLAN_OID_MISC_GET_TSF_INFO)
6015 				pioctl_buf->data_read_written =
6016 					sizeof(mlan_ds_tsf_info);
6017 		}
6018 	}
6019 	LEAVE();
6020 	return MLAN_STATUS_SUCCESS;
6021 }
6022 
6023 /**
6024  *  @brief This function prepares command of mimo switch configuration.
6025  *
6026  *  @param pmpriv       A pointer to mlan_private structure
6027  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
6028  *  @param pdata_buf    A pointer to data buffer
6029  *  @return             MLAN_STATUS_SUCCESS
6030  */
wlan_cmd_802_11_mimo_switch(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_void * pdata_buf)6031 mlan_status wlan_cmd_802_11_mimo_switch(pmlan_private pmpriv,
6032 					HostCmd_DS_COMMAND *cmd,
6033 					t_void *pdata_buf)
6034 {
6035 	HostCmd_DS_MIMO_SWITCH *mimo_switch_cmd = &cmd->params.mimo_switch;
6036 	mlan_ds_mimo_switch *pmimo_switch = (mlan_ds_mimo_switch *)pdata_buf;
6037 
6038 	ENTER();
6039 
6040 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_MIMO_SWITCH);
6041 	cmd->size =
6042 		wlan_cpu_to_le16((sizeof(HostCmd_DS_MIMO_SWITCH)) + S_DS_GEN);
6043 	mimo_switch_cmd->txpath_antmode = pmimo_switch->txpath_antmode;
6044 	mimo_switch_cmd->rxpath_antmode = pmimo_switch->rxpath_antmode;
6045 
6046 	LEAVE();
6047 	return MLAN_STATUS_SUCCESS;
6048 }
6049 
6050 /**
6051  *  @brief This function prepares command of hs wakeup reason.
6052  *
6053  *  @param pmpriv       A pointer to mlan_private structure
6054  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
6055  *  @param pdata_buf    A pointer to data buffer
6056  *  @return             MLAN_STATUS_SUCCESS
6057  */
wlan_cmd_hs_wakeup_reason(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_void * pdata_buf)6058 mlan_status wlan_cmd_hs_wakeup_reason(pmlan_private pmpriv,
6059 				      HostCmd_DS_COMMAND *cmd,
6060 				      t_void *pdata_buf)
6061 {
6062 	ENTER();
6063 
6064 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_HS_WAKEUP_REASON);
6065 	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_HS_WAKEUP_REASON)) +
6066 				     S_DS_GEN);
6067 
6068 	LEAVE();
6069 	return MLAN_STATUS_SUCCESS;
6070 }
6071 
6072 /**
6073  *  @brief This function handles the command response of
6074  *          hs wakeup reason
6075  *
6076  *  @param pmpriv       A pointer to mlan_private structure
6077  *  @param resp         A pointer to HostCmd_DS_COMMAND
6078  *  @param pioctl_buf   A pointer to command buffer
6079  *
6080  *  @return             MLAN_STATUS_SUCCESS
6081  */
wlan_ret_hs_wakeup_reason(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)6082 mlan_status wlan_ret_hs_wakeup_reason(pmlan_private pmpriv,
6083 				      HostCmd_DS_COMMAND *resp,
6084 				      mlan_ioctl_req *pioctl_buf)
6085 {
6086 	HostCmd_DS_HS_WAKEUP_REASON *hs_wakeup_reason =
6087 		(HostCmd_DS_HS_WAKEUP_REASON *)&resp->params.hs_wakeup_reason;
6088 	mlan_ds_pm_cfg *pm_cfg = MNULL;
6089 
6090 	ENTER();
6091 
6092 	pm_cfg = (mlan_ds_pm_cfg *)pioctl_buf->pbuf;
6093 	pm_cfg->param.wakeup_reason.hs_wakeup_reason =
6094 		wlan_le16_to_cpu(hs_wakeup_reason->wakeup_reason);
6095 	pioctl_buf->data_read_written = sizeof(mlan_ds_pm_cfg);
6096 
6097 	LEAVE();
6098 	return MLAN_STATUS_SUCCESS;
6099 }
6100 
6101 /**
6102  *  @brief This function prepares command of tx_rx_pkt_stats
6103  *
6104  *  @param pmpriv       A pointer to mlan_private structure
6105  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
6106  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
6107  *  @param pdata_buf    A pointer to information buffer
6108  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
6109  */
wlan_cmd_tx_rx_pkt_stats(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,pmlan_ioctl_req pioctl_buf,t_void * pdata_buf)6110 mlan_status wlan_cmd_tx_rx_pkt_stats(pmlan_private pmpriv,
6111 				     HostCmd_DS_COMMAND *cmd,
6112 				     pmlan_ioctl_req pioctl_buf,
6113 				     t_void *pdata_buf)
6114 {
6115 	HostCmd_DS_TX_RX_HISTOGRAM *ptx_rx_histogram =
6116 		&cmd->params.tx_rx_histogram;
6117 	mlan_ds_misc_tx_rx_histogram *ptx_rx_pkt_stats =
6118 		(mlan_ds_misc_tx_rx_histogram *)pdata_buf;
6119 	mlan_status ret = MLAN_STATUS_SUCCESS;
6120 
6121 	ENTER();
6122 
6123 	if (!ptx_rx_pkt_stats) {
6124 		ret = MLAN_STATUS_FAILURE;
6125 		goto done;
6126 	}
6127 	cmd->command = wlan_cpu_to_le16(HOST_CMD_TX_RX_PKT_STATS);
6128 	cmd->size =
6129 		wlan_cpu_to_le16(sizeof(HostCmd_DS_TX_RX_HISTOGRAM) + S_DS_GEN);
6130 
6131 	ptx_rx_histogram->enable = ptx_rx_pkt_stats->enable;
6132 	ptx_rx_histogram->action = wlan_cpu_to_le16(ptx_rx_pkt_stats->action);
6133 done:
6134 	LEAVE();
6135 	return ret;
6136 }
6137 /**
6138  *  @brief This function handles the command response of tx_rx_pkt_stats
6139  *
6140  *  @param pmpriv       A pointer to mlan_private structure
6141  *  @param resp         A pointer to HostCmd_DS_COMMAND
6142  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
6143  *
6144  *  @return             MLAN_STATUS_SUCCESS
6145  */
wlan_ret_tx_rx_pkt_stats(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)6146 mlan_status wlan_ret_tx_rx_pkt_stats(pmlan_private pmpriv,
6147 				     HostCmd_DS_COMMAND *resp,
6148 				     mlan_ioctl_req *pioctl_buf)
6149 {
6150 	HostCmd_DS_TX_RX_HISTOGRAM *ptx_rx_histogram =
6151 		&resp->params.tx_rx_histogram;
6152 	mlan_ds_misc_cfg *info;
6153 	t_u16 cmdsize = wlan_le16_to_cpu(resp->size), length;
6154 	t_u32 *pos, count = 0;
6155 
6156 	ENTER();
6157 
6158 	if (pioctl_buf) {
6159 		ptx_rx_histogram->action =
6160 			wlan_le16_to_cpu(ptx_rx_histogram->action);
6161 		info = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
6162 		length =
6163 			cmdsize - S_DS_GEN - sizeof(HostCmd_DS_TX_RX_HISTOGRAM);
6164 		if (length > 0) {
6165 			info->param.tx_rx_histogram.size = length;
6166 			memcpy_ext(pmpriv->adapter,
6167 				   info->param.tx_rx_histogram.value,
6168 				   (t_u8 *)ptx_rx_histogram +
6169 					   sizeof(HostCmd_DS_TX_RX_HISTOGRAM),
6170 				   length, info->param.tx_rx_histogram.size);
6171 			pos = (t_u32 *)info->param.tx_rx_histogram.value;
6172 			while (length - 4 * count) {
6173 				*pos = wlan_le32_to_cpu(*pos);
6174 				pos += 4;
6175 				count++;
6176 			}
6177 		}
6178 	}
6179 
6180 	LEAVE();
6181 	return MLAN_STATUS_SUCCESS;
6182 }
6183 
6184 /*
6185  *  @brief This function prepares command of cwmode control.
6186  *
6187  *  @param pmpriv       A pointer to mlan_private structure
6188  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
6189  *  @param cmd_action   The action: GET or SET
6190  *  @param pdata_buf    A pointer to data buffer
6191  *
6192  *  @return             MLAN_STATUS_SUCCESS
6193  */
wlan_cmd_cw_mode_ctrl(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)6194 mlan_status wlan_cmd_cw_mode_ctrl(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
6195 				  t_u16 cmd_action, t_void *pdata_buf)
6196 {
6197 	HostCmd_DS_CW_MODE_CTRL *cwmode_ctrl = &cmd->params.cwmode;
6198 	mlan_ds_cw_mode_ctrl *cw_mode = (mlan_ds_cw_mode_ctrl *)pdata_buf;
6199 	ENTER();
6200 	cmd->size =
6201 		wlan_cpu_to_le16((sizeof(HostCmd_DS_CW_MODE_CTRL)) + S_DS_GEN);
6202 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_CW_MODE_CTRL);
6203 	cwmode_ctrl->action = wlan_cpu_to_le16(cmd_action);
6204 
6205 	if (cmd_action == HostCmd_ACT_GEN_SET) {
6206 		cwmode_ctrl->mode = cw_mode->mode;
6207 		cwmode_ctrl->channel = cw_mode->channel;
6208 		cwmode_ctrl->chanInfo = cw_mode->chanInfo;
6209 		cwmode_ctrl->txPower = wlan_cpu_to_le16(cw_mode->txPower);
6210 		cwmode_ctrl->rateInfo = wlan_cpu_to_le32(cw_mode->rateInfo);
6211 		cwmode_ctrl->pktLength = wlan_cpu_to_le16(cw_mode->pktLength);
6212 	}
6213 	LEAVE();
6214 	return MLAN_STATUS_SUCCESS;
6215 }
6216 
6217 /*
6218  *  @brief This function handles the command response of cwmode_ctrl
6219  *
6220  *  @param pmpriv       A pointer to mlan_private structure
6221  *  @param resp         A pointer to HostCmd_DS_COMMAND
6222  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
6223  *
6224  *  @return             MLAN_STATUS_SUCCESS
6225  */
wlan_ret_cw_mode_ctrl(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)6226 mlan_status wlan_ret_cw_mode_ctrl(pmlan_private pmpriv,
6227 				  HostCmd_DS_COMMAND *resp,
6228 				  mlan_ioctl_req *pioctl_buf)
6229 {
6230 	HostCmd_DS_CW_MODE_CTRL *cwmode_resp = &resp->params.cwmode;
6231 	mlan_ds_misc_cfg *misc = MNULL;
6232 
6233 	ENTER();
6234 	if (pioctl_buf) {
6235 		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
6236 		misc->param.cwmode.mode = cwmode_resp->mode;
6237 		misc->param.cwmode.channel = cwmode_resp->channel;
6238 		misc->param.cwmode.chanInfo = cwmode_resp->chanInfo;
6239 		misc->param.cwmode.txPower =
6240 			wlan_le16_to_cpu(cwmode_resp->txPower);
6241 		misc->param.cwmode.rateInfo =
6242 			wlan_le32_to_cpu(cwmode_resp->rateInfo);
6243 		;
6244 		misc->param.cwmode.pktLength =
6245 			wlan_le16_to_cpu(cwmode_resp->pktLength);
6246 		;
6247 		pioctl_buf->data_read_written = sizeof(mlan_ds_misc_cfg);
6248 	}
6249 	LEAVE();
6250 	return MLAN_STATUS_SUCCESS;
6251 }
6252 
6253 /**
6254  *  @brief This function prepares command of rf_antenna.
6255  *
6256  *  @param pmpriv   A pointer to mlan_private structure
6257  *  @param cmd      A pointer to HostCmd_DS_COMMAND structure
6258  *  @param cmd_action   The action: GET or SET
6259  *  @param pdata_buf    A pointer to data buffer
6260  *
6261  *  @return         MLAN_STATUS_SUCCESS
6262  */
wlan_cmd_802_11_rf_antenna(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)6263 mlan_status wlan_cmd_802_11_rf_antenna(pmlan_private pmpriv,
6264 				       HostCmd_DS_COMMAND *cmd,
6265 				       t_u16 cmd_action, t_void *pdata_buf)
6266 {
6267 	HostCmd_DS_802_11_RF_ANTENNA *pantenna = &cmd->params.antenna;
6268 	mlan_ds_ant_cfg *ant_cfg = (mlan_ds_ant_cfg *)pdata_buf;
6269 	typedef struct _HostCmd_DS_802_11_RF_ANTENNA_1X1 {
6270 		/** Action */
6271 		t_u16 action;
6272 		/**  Antenna or 0xffff (diversity) */
6273 		t_u16 antenna_mode;
6274 		/** Evaluate time */
6275 		t_u16 evaluate_time;
6276 		/** Current antenna */
6277 		t_u16 current_antenna;
6278 	} HostCmd_DS_802_11_RF_ANTENNA_1X1;
6279 	HostCmd_DS_802_11_RF_ANTENNA_1X1 *pantenna_1x1 =
6280 		(HostCmd_DS_802_11_RF_ANTENNA_1X1 *)&cmd->params.antenna;
6281 	mlan_ds_ant_cfg_1x1 *ant_cfg_1x1 = (mlan_ds_ant_cfg_1x1 *)pdata_buf;
6282 
6283 	ENTER();
6284 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_ANTENNA);
6285 	if (!IS_STREAM_2X2(pmpriv->adapter->feature_control))
6286 		cmd->size = wlan_cpu_to_le16(
6287 			sizeof(HostCmd_DS_802_11_RF_ANTENNA_1X1) + S_DS_GEN);
6288 	else
6289 		cmd->size = wlan_cpu_to_le16(
6290 			sizeof(HostCmd_DS_802_11_RF_ANTENNA) + S_DS_GEN);
6291 
6292 	if (cmd_action == HostCmd_ACT_GEN_SET) {
6293 		if (IS_STREAM_2X2(pmpriv->adapter->feature_control)) {
6294 			pantenna->action_tx =
6295 				wlan_cpu_to_le16(HostCmd_ACT_SET_TX);
6296 			pantenna->tx_antenna_mode =
6297 				wlan_cpu_to_le16((t_u16)ant_cfg->tx_antenna);
6298 			pantenna->action_rx =
6299 				wlan_cpu_to_le16(HostCmd_ACT_SET_RX);
6300 			pantenna->rx_antenna_mode =
6301 				wlan_cpu_to_le16((t_u16)ant_cfg->rx_antenna);
6302 		} else {
6303 			pantenna_1x1->action =
6304 				wlan_cpu_to_le16(HostCmd_ACT_SET_BOTH);
6305 			pantenna_1x1->antenna_mode =
6306 				wlan_cpu_to_le16((t_u16)ant_cfg_1x1->antenna);
6307 			pantenna_1x1->evaluate_time = wlan_cpu_to_le16(
6308 				(t_u16)ant_cfg_1x1->evaluate_time);
6309 		}
6310 	} else {
6311 		if (IS_STREAM_2X2(pmpriv->adapter->feature_control)) {
6312 			pantenna->action_tx =
6313 				wlan_cpu_to_le16(HostCmd_ACT_GET_TX);
6314 			pantenna->action_rx =
6315 				wlan_cpu_to_le16(HostCmd_ACT_GET_RX);
6316 		} else {
6317 			pantenna_1x1->action =
6318 				wlan_cpu_to_le16(HostCmd_ACT_GET_BOTH);
6319 		}
6320 	}
6321 	LEAVE();
6322 	return MLAN_STATUS_SUCCESS;
6323 }
6324 
6325 /**
6326  *  @brief This function handles the command response of rf_antenna
6327  *
6328  *  @param pmpriv       A pointer to mlan_private structure
6329  *  @param resp         A pointer to HostCmd_DS_COMMAND
6330  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
6331  *
6332  *  @return             MLAN_STATUS_SUCCESS
6333  */
wlan_ret_802_11_rf_antenna(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)6334 mlan_status wlan_ret_802_11_rf_antenna(pmlan_private pmpriv,
6335 				       HostCmd_DS_COMMAND *resp,
6336 				       mlan_ioctl_req *pioctl_buf)
6337 {
6338 	HostCmd_DS_802_11_RF_ANTENNA *pantenna = &resp->params.antenna;
6339 	t_u16 tx_ant_mode = wlan_le16_to_cpu(pantenna->tx_antenna_mode);
6340 	t_u16 rx_ant_mode = wlan_le16_to_cpu(pantenna->rx_antenna_mode);
6341 #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
6342 	defined(PCIE9097) || defined(SD9097) || defined(USB9097) ||            \
6343 	defined(SDNW62X) || defined(PCIENW62X) || defined(USBNW62X)
6344 	mlan_adapter *pmadapter = pmpriv->adapter;
6345 #endif
6346 	typedef struct _HostCmd_DS_802_11_RF_ANTENNA_1X1 {
6347 		/** Action */
6348 		t_u16 action;
6349 		/**  Antenna or 0xffff (diversity) */
6350 		t_u16 antenna_mode;
6351 		/** Evaluate time */
6352 		t_u16 evaluate_time;
6353 		/** Current antenna */
6354 		t_u16 current_antenna;
6355 	} HostCmd_DS_802_11_RF_ANTENNA_1X1;
6356 	HostCmd_DS_802_11_RF_ANTENNA_1X1 *pantenna_1x1 =
6357 		(HostCmd_DS_802_11_RF_ANTENNA_1X1 *)&resp->params.antenna;
6358 	t_u16 ant_mode = wlan_le16_to_cpu(pantenna_1x1->antenna_mode);
6359 	t_u16 evaluate_time = wlan_le16_to_cpu(pantenna_1x1->evaluate_time);
6360 	t_u16 current_antenna = wlan_le16_to_cpu(pantenna_1x1->current_antenna);
6361 	mlan_ds_radio_cfg *radio = MNULL;
6362 
6363 	ENTER();
6364 
6365 	if (IS_STREAM_2X2(pmpriv->adapter->feature_control)) {
6366 		PRINTM(MCMND,
6367 		       "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x"
6368 		       " Rx action = 0x%x, Rx Mode = 0x%04x\n",
6369 		       wlan_le16_to_cpu(pantenna->action_tx), tx_ant_mode,
6370 		       wlan_le16_to_cpu(pantenna->action_rx), rx_ant_mode);
6371 #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
6372 	defined(PCIE9097) || defined(SD9097) || defined(USB9097) ||            \
6373 	defined(SDNW62X) || defined(PCIENW62X) || defined(USBNW62X)
6374 		if (IS_CARD9098(pmadapter->card_type) ||
6375 		    IS_CARDNW62X(pmadapter->card_type) ||
6376 		    IS_CARD9097(pmadapter->card_type)) {
6377 			tx_ant_mode &= 0x0303;
6378 			rx_ant_mode &= 0x0303;
6379 			/** 2G antcfg TX */
6380 			if (tx_ant_mode & 0x00FF) {
6381 				pmadapter->user_htstream &= ~0xF0;
6382 				pmadapter->user_htstream |=
6383 					(bitcount(tx_ant_mode & 0x00FF) << 4);
6384 			}
6385 			/* 5G antcfg tx */
6386 			if (tx_ant_mode & 0xFF00) {
6387 				pmadapter->user_htstream &= ~0xF000;
6388 				pmadapter->user_htstream |=
6389 					(bitcount(tx_ant_mode & 0xFF00) << 12);
6390 			}
6391 			/* 2G antcfg RX */
6392 			if (rx_ant_mode & 0x00FF) {
6393 				pmadapter->user_htstream &= ~0xF;
6394 				pmadapter->user_htstream |=
6395 					bitcount(rx_ant_mode & 0x00FF);
6396 			}
6397 			/* 5G antcfg RX */
6398 			if (rx_ant_mode & 0xFF00) {
6399 				pmadapter->user_htstream &= ~0xF00;
6400 				pmadapter->user_htstream |=
6401 					(bitcount(rx_ant_mode & 0xFF00) << 8);
6402 			}
6403 			PRINTM(MCMND,
6404 			       "user_htstream=0x%x, tx_antenna=0x%x rx_antenna=0x%x\n",
6405 			       pmadapter->user_htstream, tx_ant_mode,
6406 			       rx_ant_mode);
6407 		}
6408 #endif
6409 	} else
6410 		PRINTM(MINFO,
6411 		       "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x, Evaluate time = %d, Current antenna = %d\n",
6412 		       wlan_le16_to_cpu(pantenna_1x1->action), ant_mode,
6413 		       evaluate_time, current_antenna);
6414 
6415 	if (pioctl_buf) {
6416 		radio = (mlan_ds_radio_cfg *)pioctl_buf->pbuf;
6417 		if (IS_STREAM_2X2(pmpriv->adapter->feature_control)) {
6418 			radio->param.ant_cfg.tx_antenna = tx_ant_mode;
6419 			radio->param.ant_cfg.rx_antenna = rx_ant_mode;
6420 		} else {
6421 			radio->param.ant_cfg_1x1.antenna = ant_mode;
6422 			radio->param.ant_cfg_1x1.evaluate_time = evaluate_time;
6423 			radio->param.ant_cfg_1x1.current_antenna =
6424 				current_antenna;
6425 		}
6426 	}
6427 
6428 	LEAVE();
6429 	return MLAN_STATUS_SUCCESS;
6430 }
6431 
6432 /**
6433  *  @brief This function prepares command of reg_access.
6434  *
6435  *  @param priv         A pointer to mlan_priv register.
6436  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
6437  *  @param cmd_action   the action: GET or SET
6438  *  @param pdata_buf    A pointer to data buffer
6439  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
6440  */
wlan_cmd_reg_access(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)6441 mlan_status wlan_cmd_reg_access(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
6442 				t_u16 cmd_action, t_void *pdata_buf)
6443 {
6444 	mlan_ds_reg_rw *reg_rw;
6445 #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
6446 	defined(PCIE9097) || defined(USB9097) || defined(SDNW62X) ||           \
6447 	defined(PCIENW62X) || defined(USBNW62X) || defined(SD9097)
6448 	MrvlIEtypes_Reg_type_t *tlv;
6449 	mlan_adapter *pmadapter = pmpriv->adapter;
6450 #endif
6451 
6452 	ENTER();
6453 
6454 	reg_rw = (mlan_ds_reg_rw *)pdata_buf;
6455 	switch (cmd->command) {
6456 	case HostCmd_CMD_MAC_REG_ACCESS: {
6457 		HostCmd_DS_MAC_REG_ACCESS *mac_reg;
6458 		cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_REG_ACCESS) +
6459 					     S_DS_GEN);
6460 		mac_reg = (HostCmd_DS_MAC_REG_ACCESS *)&cmd->params.mac_reg;
6461 		mac_reg->action = wlan_cpu_to_le16(cmd_action);
6462 		mac_reg->offset = wlan_cpu_to_le16((t_u16)reg_rw->offset);
6463 		mac_reg->value = wlan_cpu_to_le32(reg_rw->value);
6464 #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
6465 	defined(PCIE9097) || defined(USB9097) || defined(SDNW62X) ||           \
6466 	defined(PCIENW62X) || defined(USBNW62X) || defined(SD9097)
6467 		if ((reg_rw->type == MLAN_REG_MAC2) &&
6468 		    (IS_CARD9098(pmadapter->card_type) ||
6469 		     IS_CARDNW62X(pmadapter->card_type) ||
6470 		     IS_CARD9097(pmadapter->card_type))) {
6471 			tlv = (MrvlIEtypes_Reg_type_t
6472 				       *)((t_u8 *)cmd +
6473 					  sizeof(HostCmd_DS_MAC_REG_ACCESS) +
6474 					  S_DS_GEN);
6475 			tlv->header.type =
6476 				wlan_cpu_to_le16(TLV_TYPE_REG_ACCESS_CTRL);
6477 			tlv->header.len = wlan_cpu_to_le16(sizeof(t_u8));
6478 			tlv->type = MLAN_REG_MAC2;
6479 			cmd->size = wlan_cpu_to_le16(
6480 				sizeof(HostCmd_DS_MAC_REG_ACCESS) + S_DS_GEN +
6481 				sizeof(MrvlIEtypes_Reg_type_t));
6482 		}
6483 #endif
6484 		break;
6485 	}
6486 	case HostCmd_CMD_REG_ACCESS: {
6487 		HostCmd_DS_REG_ACCESS *reg;
6488 		cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_REG_ACCESS) +
6489 					     S_DS_GEN);
6490 		reg = (HostCmd_DS_REG_ACCESS *)&cmd->params.reg;
6491 		reg->action = wlan_cpu_to_le16(cmd_action);
6492 		reg->reg_type = wlan_cpu_to_le16((t_u16)reg_rw->type);
6493 		reg->offset = wlan_cpu_to_le16((t_u16)reg_rw->offset);
6494 		reg->value = wlan_cpu_to_le32(reg_rw->value);
6495 		break;
6496 	}
6497 	case HostCmd_CMD_BBP_REG_ACCESS: {
6498 		HostCmd_DS_BBP_REG_ACCESS *bbp_reg;
6499 		cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_BBP_REG_ACCESS) +
6500 					     S_DS_GEN);
6501 		bbp_reg = (HostCmd_DS_BBP_REG_ACCESS *)&cmd->params.bbp_reg;
6502 		bbp_reg->action = wlan_cpu_to_le16(cmd_action);
6503 		bbp_reg->offset = wlan_cpu_to_le16((t_u16)reg_rw->offset);
6504 		bbp_reg->value = (t_u8)reg_rw->value;
6505 #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
6506 	defined(PCIE9097) || defined(USB9097) || defined(SDNW62X) ||           \
6507 	defined(PCIENW62X) || defined(USBNW62X) || defined(SD9097)
6508 		if ((reg_rw->type == MLAN_REG_BBP2) &&
6509 		    (IS_CARD9098(pmadapter->card_type) ||
6510 		     IS_CARDNW62X(pmadapter->card_type) ||
6511 		     IS_CARD9097(pmadapter->card_type))) {
6512 			tlv = (MrvlIEtypes_Reg_type_t
6513 				       *)((t_u8 *)cmd +
6514 					  sizeof(HostCmd_DS_BBP_REG_ACCESS) +
6515 					  S_DS_GEN);
6516 			tlv->header.type =
6517 				wlan_cpu_to_le16(TLV_TYPE_REG_ACCESS_CTRL);
6518 			tlv->header.len = wlan_cpu_to_le16(sizeof(t_u8));
6519 			tlv->type = MLAN_REG_BBP2;
6520 			cmd->size = wlan_cpu_to_le16(
6521 				sizeof(HostCmd_DS_BBP_REG_ACCESS) + S_DS_GEN +
6522 				sizeof(MrvlIEtypes_Reg_type_t));
6523 		}
6524 #endif
6525 		break;
6526 	}
6527 	case HostCmd_CMD_RF_REG_ACCESS: {
6528 		HostCmd_DS_RF_REG_ACCESS *rf_reg;
6529 		cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_RF_REG_ACCESS) +
6530 					     S_DS_GEN);
6531 		rf_reg = (HostCmd_DS_RF_REG_ACCESS *)&cmd->params.rf_reg;
6532 		rf_reg->action = wlan_cpu_to_le16(cmd_action);
6533 		rf_reg->offset = wlan_cpu_to_le16((t_u16)reg_rw->offset);
6534 		rf_reg->value = (t_u8)reg_rw->value;
6535 #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
6536 	defined(PCIE9097) || defined(USB9097) || defined(SDNW62X) ||           \
6537 	defined(PCIENW62X) || defined(USBNW62X) || defined(SD9097)
6538 		if ((reg_rw->type == MLAN_REG_RF2) &&
6539 		    (IS_CARD9098(pmadapter->card_type) ||
6540 		     IS_CARDNW62X(pmadapter->card_type) ||
6541 		     IS_CARD9097(pmadapter->card_type))) {
6542 			tlv = (MrvlIEtypes_Reg_type_t
6543 				       *)((t_u8 *)cmd +
6544 					  sizeof(HostCmd_DS_RF_REG_ACCESS) +
6545 					  S_DS_GEN);
6546 			tlv->header.type =
6547 				wlan_cpu_to_le16(TLV_TYPE_REG_ACCESS_CTRL);
6548 			tlv->header.len = wlan_cpu_to_le16(sizeof(t_u8));
6549 			tlv->type = MLAN_REG_RF2;
6550 			cmd->size = wlan_cpu_to_le16(
6551 				sizeof(HostCmd_DS_RF_REG_ACCESS) + S_DS_GEN +
6552 				sizeof(MrvlIEtypes_Reg_type_t));
6553 		}
6554 #endif
6555 		break;
6556 	}
6557 	case HostCmd_CMD_CAU_REG_ACCESS: {
6558 		HostCmd_DS_RF_REG_ACCESS *cau_reg;
6559 		cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_RF_REG_ACCESS) +
6560 					     S_DS_GEN);
6561 		cau_reg = (HostCmd_DS_RF_REG_ACCESS *)&cmd->params.rf_reg;
6562 		cau_reg->action = wlan_cpu_to_le16(cmd_action);
6563 		cau_reg->offset = wlan_cpu_to_le16((t_u16)reg_rw->offset);
6564 		cau_reg->value = (t_u8)reg_rw->value;
6565 		break;
6566 	}
6567 	case HostCmd_CMD_TARGET_ACCESS: {
6568 		HostCmd_DS_TARGET_ACCESS *target;
6569 		cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_TARGET_ACCESS) +
6570 					     S_DS_GEN);
6571 		target = (HostCmd_DS_TARGET_ACCESS *)&cmd->params.target;
6572 		target->action = wlan_cpu_to_le16(cmd_action);
6573 		target->csu_target = wlan_cpu_to_le16(MLAN_CSU_TARGET_PSU);
6574 		target->address = wlan_cpu_to_le16((t_u16)reg_rw->offset);
6575 		target->data = (t_u8)reg_rw->value;
6576 		break;
6577 	}
6578 	case HostCmd_CMD_802_11_EEPROM_ACCESS: {
6579 		mlan_ds_read_eeprom *rd_eeprom =
6580 			(mlan_ds_read_eeprom *)pdata_buf;
6581 		HostCmd_DS_802_11_EEPROM_ACCESS *cmd_eeprom =
6582 			(HostCmd_DS_802_11_EEPROM_ACCESS *)&cmd->params.eeprom;
6583 		cmd->size = wlan_cpu_to_le16(
6584 			sizeof(HostCmd_DS_802_11_EEPROM_ACCESS) + S_DS_GEN);
6585 		cmd_eeprom->action = wlan_cpu_to_le16(cmd_action);
6586 		cmd_eeprom->offset = wlan_cpu_to_le16(rd_eeprom->offset);
6587 		cmd_eeprom->byte_count =
6588 			wlan_cpu_to_le16(rd_eeprom->byte_count);
6589 		cmd_eeprom->value = 0;
6590 		break;
6591 	}
6592 	case HostCmd_CMD_BCA_REG_ACCESS: {
6593 		HostCmd_DS_BCA_REG_ACCESS *bca_reg;
6594 		cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_BCA_REG_ACCESS) +
6595 					     S_DS_GEN);
6596 		bca_reg = (HostCmd_DS_BCA_REG_ACCESS *)&cmd->params.bca_reg;
6597 		bca_reg->action = wlan_cpu_to_le16(cmd_action);
6598 		bca_reg->offset = wlan_cpu_to_le16((t_u16)reg_rw->offset);
6599 		bca_reg->value = wlan_cpu_to_le32(reg_rw->value);
6600 #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) ||                \
6601 	defined(PCIE9097) || defined(USB9097) || defined(SDNW62X) ||           \
6602 	defined(PCIENW62X) || defined(USBNW62X) || defined(SD9097)
6603 		if ((reg_rw->type == MLAN_REG_BCA2) &&
6604 		    (IS_CARD9098(pmadapter->card_type) ||
6605 		     IS_CARDNW62X(pmadapter->card_type) ||
6606 		     IS_CARD9097(pmadapter->card_type))) {
6607 			tlv = (MrvlIEtypes_Reg_type_t
6608 				       *)((t_u8 *)cmd +
6609 					  sizeof(HostCmd_DS_BCA_REG_ACCESS) +
6610 					  S_DS_GEN);
6611 			tlv->header.type =
6612 				wlan_cpu_to_le16(TLV_TYPE_REG_ACCESS_CTRL);
6613 			tlv->header.len = wlan_cpu_to_le16(sizeof(t_u8));
6614 			tlv->type = MLAN_REG_BCA2;
6615 			cmd->size = wlan_cpu_to_le16(
6616 				sizeof(HostCmd_DS_BCA_REG_ACCESS) + S_DS_GEN +
6617 				sizeof(MrvlIEtypes_Reg_type_t));
6618 		}
6619 #endif
6620 		break;
6621 	}
6622 	default:
6623 		LEAVE();
6624 		return MLAN_STATUS_FAILURE;
6625 	}
6626 	cmd->command = wlan_cpu_to_le16(cmd->command);
6627 
6628 	LEAVE();
6629 	return MLAN_STATUS_SUCCESS;
6630 }
6631 
6632 /**
6633  *  @brief This function handles the command response of reg_access
6634  *
6635  *  @param pmadapter    A pointer to mlan_adapter structure
6636  *  @param type         The type of reg access (MAC, BBP or RF)
6637  *  @param resp         A pointer to HostCmd_DS_COMMAND
6638  *  @param pioctl_buf   A pointer to command buffer
6639  *
6640  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
6641  */
wlan_ret_reg_access(mlan_adapter * pmadapter,t_u16 type,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)6642 mlan_status wlan_ret_reg_access(mlan_adapter *pmadapter, t_u16 type,
6643 				HostCmd_DS_COMMAND *resp,
6644 				mlan_ioctl_req *pioctl_buf)
6645 {
6646 	mlan_ds_reg_mem *reg_mem = MNULL;
6647 	mlan_ds_reg_rw *reg_rw = MNULL;
6648 
6649 	ENTER();
6650 
6651 	if (pioctl_buf) {
6652 		reg_mem = (mlan_ds_reg_mem *)pioctl_buf->pbuf;
6653 		reg_rw = &reg_mem->param.reg_rw;
6654 		switch (type) {
6655 		case HostCmd_CMD_MAC_REG_ACCESS: {
6656 			HostCmd_DS_MAC_REG_ACCESS *reg;
6657 			reg = (HostCmd_DS_MAC_REG_ACCESS *)&resp->params.mac_reg;
6658 			reg_rw->offset = (t_u32)wlan_le16_to_cpu(reg->offset);
6659 			reg_rw->value = wlan_le32_to_cpu(reg->value);
6660 			break;
6661 		}
6662 		case HostCmd_CMD_REG_ACCESS: {
6663 			HostCmd_DS_REG_ACCESS *reg;
6664 			reg = (HostCmd_DS_REG_ACCESS *)&resp->params.reg;
6665 			reg_rw->offset = (t_u32)wlan_le16_to_cpu(reg->offset);
6666 			reg_rw->value = wlan_le32_to_cpu(reg->value);
6667 			break;
6668 		}
6669 		case HostCmd_CMD_BBP_REG_ACCESS: {
6670 			HostCmd_DS_BBP_REG_ACCESS *reg;
6671 			reg = (HostCmd_DS_BBP_REG_ACCESS *)&resp->params.bbp_reg;
6672 			reg_rw->offset = (t_u32)wlan_le16_to_cpu(reg->offset);
6673 			reg_rw->value = (t_u32)reg->value;
6674 			break;
6675 		}
6676 
6677 		case HostCmd_CMD_RF_REG_ACCESS: {
6678 			HostCmd_DS_RF_REG_ACCESS *reg;
6679 			reg = (HostCmd_DS_RF_REG_ACCESS *)&resp->params.rf_reg;
6680 			reg_rw->offset = (t_u32)wlan_le16_to_cpu(reg->offset);
6681 			reg_rw->value = (t_u32)reg->value;
6682 			break;
6683 		}
6684 		case HostCmd_CMD_CAU_REG_ACCESS: {
6685 			HostCmd_DS_RF_REG_ACCESS *reg;
6686 			reg = (HostCmd_DS_RF_REG_ACCESS *)&resp->params.rf_reg;
6687 			reg_rw->offset = (t_u32)wlan_le16_to_cpu(reg->offset);
6688 			reg_rw->value = (t_u32)reg->value;
6689 			break;
6690 		}
6691 		case HostCmd_CMD_TARGET_ACCESS: {
6692 			HostCmd_DS_TARGET_ACCESS *reg;
6693 			reg = (HostCmd_DS_TARGET_ACCESS *)&resp->params.target;
6694 			reg_rw->offset = (t_u32)wlan_le16_to_cpu(reg->address);
6695 			reg_rw->value = (t_u32)reg->data;
6696 			break;
6697 		}
6698 		case HostCmd_CMD_802_11_EEPROM_ACCESS: {
6699 			mlan_ds_read_eeprom *eeprom = &reg_mem->param.rd_eeprom;
6700 			HostCmd_DS_802_11_EEPROM_ACCESS *cmd_eeprom =
6701 				(HostCmd_DS_802_11_EEPROM_ACCESS *)&resp->params
6702 					.eeprom;
6703 			cmd_eeprom->byte_count =
6704 				wlan_le16_to_cpu(cmd_eeprom->byte_count);
6705 			PRINTM(MINFO, "EEPROM read len=%x\n",
6706 			       cmd_eeprom->byte_count);
6707 			if (eeprom->byte_count < cmd_eeprom->byte_count) {
6708 				eeprom->byte_count = 0;
6709 				PRINTM(MINFO,
6710 				       "EEPROM read return length is too big\n");
6711 				pioctl_buf->status_code =
6712 					MLAN_ERROR_CMD_RESP_FAIL;
6713 				LEAVE();
6714 				return MLAN_STATUS_FAILURE;
6715 			}
6716 			eeprom->offset = wlan_le16_to_cpu(cmd_eeprom->offset);
6717 			eeprom->byte_count = cmd_eeprom->byte_count;
6718 			if (eeprom->byte_count > 0) {
6719 				memcpy_ext(pmadapter, &eeprom->value,
6720 					   &cmd_eeprom->value,
6721 					   eeprom->byte_count, MAX_EEPROM_DATA);
6722 				HEXDUMP("EEPROM", (char *)&eeprom->value,
6723 					MIN(MAX_EEPROM_DATA,
6724 					    eeprom->byte_count));
6725 			}
6726 			break;
6727 		}
6728 		case HostCmd_CMD_BCA_REG_ACCESS: {
6729 			HostCmd_DS_BCA_REG_ACCESS *reg;
6730 			reg = (HostCmd_DS_BCA_REG_ACCESS *)&resp->params.bca_reg;
6731 			reg_rw->offset = (t_u32)wlan_le16_to_cpu(reg->offset);
6732 			reg_rw->value = wlan_le32_to_cpu(reg->value);
6733 			break;
6734 		}
6735 		default:
6736 			pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
6737 			LEAVE();
6738 			return MLAN_STATUS_FAILURE;
6739 		}
6740 	}
6741 
6742 	LEAVE();
6743 	return MLAN_STATUS_SUCCESS;
6744 }
6745 
6746 /**
6747  *  @brief This function prepares command of mem_access.
6748  *
6749  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
6750  *  @param cmd_action   the action: GET or SET
6751  *  @param pdata_buf    A pointer to data buffer
6752  *  @return             MLAN_STATUS_SUCCESS
6753  */
wlan_cmd_mem_access(HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)6754 mlan_status wlan_cmd_mem_access(HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
6755 				t_void *pdata_buf)
6756 {
6757 	mlan_ds_mem_rw *mem_rw = (mlan_ds_mem_rw *)pdata_buf;
6758 	HostCmd_DS_MEM_ACCESS *mem_access =
6759 		(HostCmd_DS_MEM_ACCESS *)&cmd->params.mem;
6760 
6761 	ENTER();
6762 
6763 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MEM_ACCESS);
6764 	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_MEM_ACCESS) + S_DS_GEN);
6765 
6766 	mem_access->action = wlan_cpu_to_le16(cmd_action);
6767 	mem_access->addr = wlan_cpu_to_le32(mem_rw->addr);
6768 	mem_access->value = wlan_cpu_to_le32(mem_rw->value);
6769 
6770 	LEAVE();
6771 	return MLAN_STATUS_SUCCESS;
6772 }
6773 
6774 /**
6775  *  @brief This function handles the command response of mem_access
6776  *
6777  *  @param pmpriv       A pointer to mlan_private structure
6778  *  @param resp         A pointer to HostCmd_DS_COMMAND
6779  *  @param pioctl_buf   A pointer to command buffer
6780  *
6781  *  @return             MLAN_STATUS_SUCCESS
6782  */
wlan_ret_mem_access(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)6783 mlan_status wlan_ret_mem_access(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
6784 				mlan_ioctl_req *pioctl_buf)
6785 {
6786 	mlan_ds_reg_mem *reg_mem = MNULL;
6787 	mlan_ds_mem_rw *mem_rw = MNULL;
6788 	HostCmd_DS_MEM_ACCESS *mem = (HostCmd_DS_MEM_ACCESS *)&resp->params.mem;
6789 
6790 	ENTER();
6791 
6792 	if (pioctl_buf) {
6793 		reg_mem = (mlan_ds_reg_mem *)pioctl_buf->pbuf;
6794 		mem_rw = &reg_mem->param.mem_rw;
6795 
6796 		mem_rw->addr = wlan_le32_to_cpu(mem->addr);
6797 		mem_rw->value = wlan_le32_to_cpu(mem->value);
6798 	}
6799 
6800 	LEAVE();
6801 	return MLAN_STATUS_SUCCESS;
6802 }
6803 
6804 /**
6805  *
6806  *  @brief This function handles coex events generated by firmware
6807  *
6808  *  @param priv A pointer to mlan_private structure
6809  *  @param pevent   A pointer to event buf
6810  *
6811  *  @return     N/A
6812  */
wlan_bt_coex_wlan_param_update_event(pmlan_private priv,pmlan_buffer pevent)6813 void wlan_bt_coex_wlan_param_update_event(pmlan_private priv,
6814 					  pmlan_buffer pevent)
6815 {
6816 	pmlan_adapter pmadapter = priv->adapter;
6817 	MrvlIEtypesHeader_t *tlv = MNULL;
6818 	MrvlIETypes_BtCoexAggrWinSize_t *pCoexWinsize = MNULL;
6819 	MrvlIEtypes_BtCoexScanTime_t *pScantlv = MNULL;
6820 	t_s32 len = pevent->data_len - sizeof(t_u32);
6821 	t_u8 *pCurrent_ptr = pevent->pbuf + pevent->data_offset + sizeof(t_u32);
6822 	t_u16 tlv_type, tlv_len;
6823 
6824 	ENTER();
6825 
6826 	while (len >= (t_s32)sizeof(MrvlIEtypesHeader_t)) {
6827 		tlv = (MrvlIEtypesHeader_t *)pCurrent_ptr;
6828 		tlv_len = wlan_le16_to_cpu(tlv->len);
6829 		tlv_type = wlan_le16_to_cpu(tlv->type);
6830 		if ((tlv_len + (t_s32)sizeof(MrvlIEtypesHeader_t)) > len)
6831 			break;
6832 		switch (tlv_type) {
6833 		case TLV_BTCOEX_WL_AGGR_WINSIZE:
6834 			pCoexWinsize = (MrvlIETypes_BtCoexAggrWinSize_t *)tlv;
6835 			pmadapter->coex_win_size = pCoexWinsize->coex_win_size;
6836 			pmadapter->coex_tx_win_size = pCoexWinsize->tx_win_size;
6837 			pmadapter->coex_rx_win_size = pCoexWinsize->rx_win_size;
6838 			wlan_coex_ampdu_rxwinsize(pmadapter);
6839 			wlan_update_ampdu_txwinsize(pmadapter);
6840 			break;
6841 		case TLV_BTCOEX_WL_SCANTIME:
6842 			pScantlv = (MrvlIEtypes_BtCoexScanTime_t *)tlv;
6843 			pmadapter->coex_scan = pScantlv->coex_scan;
6844 			pmadapter->coex_min_scan_time =
6845 				wlan_le16_to_cpu(pScantlv->min_scan_time);
6846 			pmadapter->coex_max_scan_time =
6847 				wlan_le16_to_cpu(pScantlv->max_scan_time);
6848 			break;
6849 		default:
6850 			break;
6851 		}
6852 		len -= tlv_len + sizeof(MrvlIEtypesHeader_t);
6853 		pCurrent_ptr += tlv_len + sizeof(MrvlIEtypesHeader_t);
6854 	}
6855 	PRINTM(MEVENT,
6856 	       "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n",
6857 	       pmadapter->coex_scan, pmadapter->coex_min_scan_time,
6858 	       pmadapter->coex_win_size, pmadapter->coex_tx_win_size,
6859 	       pmadapter->coex_rx_win_size);
6860 
6861 	LEAVE();
6862 }
6863 
6864 /**
6865  *  @brief This function prepares command of supplicant pmk
6866  *
6867  *  @param pmpriv       A pointer to mlan_private structure
6868  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
6869  *  @param cmd_action   The action: GET or SET
6870  *  @param pdata_buf    A pointer to data buffer
6871  *
6872  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
6873  */
wlan_cmd_802_11_supplicant_pmk(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)6874 mlan_status wlan_cmd_802_11_supplicant_pmk(pmlan_private pmpriv,
6875 					   HostCmd_DS_COMMAND *cmd,
6876 					   t_u16 cmd_action, t_void *pdata_buf)
6877 {
6878 	MrvlIEtypes_PMK_t *ppmk_tlv = MNULL;
6879 	MrvlIEtypes_Passphrase_t *ppassphrase_tlv = MNULL;
6880 	MrvlIEtypes_SAE_Password_t *psae_password_tlv = MNULL;
6881 	MrvlIEtypes_SsIdParamSet_t *pssid_tlv = MNULL;
6882 	MrvlIEtypes_Bssid_t *pbssid_tlv = MNULL;
6883 	HostCmd_DS_802_11_SUPPLICANT_PMK *pesupplicant_psk =
6884 		&cmd->params.esupplicant_psk;
6885 	t_u8 *ptlv_buffer = (t_u8 *)pesupplicant_psk->tlv_buffer;
6886 	mlan_ds_sec_cfg *sec = (mlan_ds_sec_cfg *)pdata_buf;
6887 	mlan_ds_passphrase *psk = MNULL;
6888 	t_u8 zero_mac[] = {0, 0, 0, 0, 0, 0};
6889 	t_u8 ssid_flag = 0, bssid_flag = 0, pmk_flag = 0, passphrase_flag = 0;
6890 	t_u8 sae_password_flag = 0;
6891 	t_u8 zero[MLAN_MAX_KEY_LENGTH] = {0};
6892 	MrvlIEtypes_fw_roam_enable_t *proam_tlv = MNULL;
6893 	MrvlIEtypes_keyParams_t *key_tlv = MNULL;
6894 	int length = 0;
6895 	t_u8 userset_passphrase = 0;
6896 
6897 	ENTER();
6898 	if (sec->multi_passphrase)
6899 		psk = (mlan_ds_passphrase *)&sec->param
6900 			      .roam_passphrase[userset_passphrase];
6901 	else
6902 		psk = (mlan_ds_passphrase *)&sec->param.passphrase;
6903 	if (cmd_action == HostCmd_ACT_GEN_REMOVE) {
6904 		cmd->size =
6905 			sizeof(HostCmd_DS_802_11_SUPPLICANT_PMK) + S_DS_GEN - 1;
6906 		proam_tlv = (MrvlIEtypes_fw_roam_enable_t *)ptlv_buffer;
6907 		proam_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_ROAM);
6908 		proam_tlv->header.len = sizeof(MrvlIEtypes_fw_roam_enable_t) -
6909 					sizeof(MrvlIEtypesHeader_t);
6910 		proam_tlv->roam_enable = MTRUE;
6911 		ptlv_buffer +=
6912 			(proam_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
6913 		cmd->size +=
6914 			(proam_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
6915 		proam_tlv->header.len = wlan_cpu_to_le16(proam_tlv->header.len);
6916 
6917 		cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SUPPLICANT_PMK);
6918 		pesupplicant_psk->action = wlan_cpu_to_le16(cmd_action);
6919 		pesupplicant_psk->cache_result = 0;
6920 		cmd->size = wlan_cpu_to_le16(cmd->size);
6921 		LEAVE();
6922 		return MLAN_STATUS_SUCCESS;
6923 	}
6924 
6925 	// Parse the rest of the buf here
6926 	//  1) <ssid="valid ssid"> - This will get the passphrase, AKMP
6927 	//     for specified ssid, if none specified then it will get all.
6928 	//     Eg: iwpriv <mlanX> passphrase 0:ssid=nxp
6929 	//  2) <psk="psk">:<passphrase="passphare">:<bssid="00:50:43:ef:23:f3">
6930 	//     <ssid="valid ssid"> - passphrase and psk cannot be provided to
6931 	//     the same SSID, Takes one SSID at a time, If ssid= is present
6932 	//     the it should contain a passphrase or psk. If no arguments are
6933 	//     provided then AKMP=802.1x, and passphrase should be provided
6934 	//     after association.
6935 	//     End of each parameter should be followed by a ':'(except for the
6936 	//     last parameter) as the delimiter. If ':' has to be used in
6937 	//     an SSID then a '/' should be preceded to ':' as a escape.
6938 	//     Eg:iwpriv <mlanX> passphrase
6939 	//               "1:ssid=mrvl AP:psk=abcdefgh:bssid=00:50:43:ef:23:f3"
6940 	//     iwpriv <mlanX> passphrase
6941 	//            "1:ssid=nxp/: AP:psk=abcdefgd:bssid=00:50:43:ef:23:f3"
6942 	//     iwpriv <mlanX> passphrase "1:ssid=mrvlAP:psk=abcdefgd"
6943 	//  3) <ssid="valid ssid"> - This will clear the passphrase
6944 	//     for specified ssid, if none specified then it will clear all.
6945 	//     Eg: iwpriv <mlanX> passphrase 2:ssid=nxp
6946 	//
6947 	//
6948 	//    -1 is for t_u8 TlvBuffer[1] as this should not be included */
6949 	cmd->size = sizeof(HostCmd_DS_802_11_SUPPLICANT_PMK) + S_DS_GEN - 1;
6950 	if (psk && memcmp(pmpriv->adapter, (t_u8 *)&psk->bssid, zero_mac,
6951 			  sizeof(zero_mac))) {
6952 		pbssid_tlv = (MrvlIEtypes_Bssid_t *)ptlv_buffer;
6953 		pbssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_BSSID);
6954 		pbssid_tlv->header.len = MLAN_MAC_ADDR_LENGTH;
6955 		memcpy_ext(pmpriv->adapter, pbssid_tlv->bssid,
6956 			   (t_u8 *)&psk->bssid, MLAN_MAC_ADDR_LENGTH,
6957 			   MLAN_MAC_ADDR_LENGTH);
6958 		ptlv_buffer +=
6959 			(pbssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
6960 		cmd->size +=
6961 			(pbssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
6962 		pbssid_tlv->header.len =
6963 			wlan_cpu_to_le16(pbssid_tlv->header.len);
6964 		bssid_flag = 1;
6965 	}
6966 	if (psk && (psk->psk_type == MLAN_PSK_PMK)) {
6967 		ppmk_tlv = (MrvlIEtypes_PMK_t *)ptlv_buffer;
6968 		ppmk_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_PMK);
6969 		ppmk_tlv->header.len = MLAN_MAX_KEY_LENGTH;
6970 		memcpy_ext(pmpriv->adapter, ppmk_tlv->pmk, psk->psk.pmk.pmk,
6971 			   MLAN_MAX_KEY_LENGTH, MLAN_MAX_KEY_LENGTH);
6972 		ptlv_buffer +=
6973 			(ppmk_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
6974 		cmd->size +=
6975 			(ppmk_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
6976 		ppmk_tlv->header.len = wlan_cpu_to_le16(ppmk_tlv->header.len);
6977 		pmk_flag = 1;
6978 		if (memcmp(pmpriv->adapter, psk->psk.pmk.pmk_r0, zero,
6979 			   MLAN_MAX_KEY_LENGTH)) {
6980 			ppmk_tlv = (MrvlIEtypes_PMK_t *)ptlv_buffer;
6981 			ppmk_tlv->header.type =
6982 				wlan_cpu_to_le16(TLV_TYPE_PMK_R0);
6983 			ppmk_tlv->header.len = MLAN_MAX_KEY_LENGTH;
6984 			memcpy_ext(pmpriv->adapter, ppmk_tlv->pmk,
6985 				   psk->psk.pmk.pmk_r0, MLAN_MAX_KEY_LENGTH,
6986 				   MLAN_MAX_KEY_LENGTH);
6987 			ptlv_buffer += (ppmk_tlv->header.len +
6988 					sizeof(MrvlIEtypesHeader_t));
6989 			cmd->size += (ppmk_tlv->header.len +
6990 				      sizeof(MrvlIEtypesHeader_t));
6991 			ppmk_tlv->header.len =
6992 				wlan_cpu_to_le16(ppmk_tlv->header.len);
6993 		}
6994 		if (memcmp(pmpriv->adapter, psk->psk.pmk.pmk_r0_name, zero,
6995 			   MLAN_MAX_PMKR0_NAME_LENGTH)) {
6996 			ppmk_tlv = (MrvlIEtypes_PMK_t *)ptlv_buffer;
6997 			ppmk_tlv->header.type =
6998 				wlan_cpu_to_le16(TLV_TYPE_PMK_R0_NAME);
6999 			ppmk_tlv->header.len = MLAN_MAX_PMKR0_NAME_LENGTH;
7000 			memcpy_ext(pmpriv->adapter, ppmk_tlv->pmk,
7001 				   psk->psk.pmk.pmk_r0_name,
7002 				   MLAN_MAX_PMKR0_NAME_LENGTH,
7003 				   MLAN_MAX_PMKR0_NAME_LENGTH);
7004 			ptlv_buffer += (ppmk_tlv->header.len +
7005 					sizeof(MrvlIEtypesHeader_t));
7006 			cmd->size += (ppmk_tlv->header.len +
7007 				      sizeof(MrvlIEtypesHeader_t));
7008 			ppmk_tlv->header.len =
7009 				wlan_cpu_to_le16(ppmk_tlv->header.len);
7010 		}
7011 	}
7012 	if (pmpriv->adapter->fw_roaming &&
7013 	    (pmpriv->adapter->userset_passphrase ||
7014 	     (psk && psk->psk_type == MLAN_PSK_PMK))) {
7015 		proam_tlv = (MrvlIEtypes_fw_roam_enable_t *)ptlv_buffer;
7016 		proam_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_ROAM);
7017 		proam_tlv->header.len = sizeof(MrvlIEtypes_fw_roam_enable_t) -
7018 					sizeof(MrvlIEtypesHeader_t);
7019 		proam_tlv->roam_enable = MTRUE;
7020 		proam_tlv->userset_passphrase =
7021 			pmpriv->adapter->userset_passphrase;
7022 		ptlv_buffer +=
7023 			(proam_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
7024 		cmd->size +=
7025 			(proam_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
7026 		proam_tlv->header.len = wlan_cpu_to_le16(proam_tlv->header.len);
7027 	}
7028 	do {
7029 		if (pmpriv->adapter->userset_passphrase &&
7030 		    sec->multi_passphrase) {
7031 			key_tlv = (MrvlIEtypes_keyParams_t *)ptlv_buffer;
7032 			key_tlv->header.type = wlan_cpu_to_le16(
7033 				TLV_TYPE_ROAM_OFFLOAD_USER_SET_PMK);
7034 			ptlv_buffer += sizeof(MrvlIEtypesHeader_t);
7035 			cmd->size += sizeof(MrvlIEtypesHeader_t);
7036 			length = cmd->size;
7037 		}
7038 		if (psk->ssid.ssid_len) {
7039 			pssid_tlv = (MrvlIEtypes_SsIdParamSet_t *)ptlv_buffer;
7040 			pssid_tlv->header.type =
7041 				wlan_cpu_to_le16(TLV_TYPE_SSID);
7042 			pssid_tlv->header.len = (t_u16)MIN(MLAN_MAX_SSID_LENGTH,
7043 							   psk->ssid.ssid_len);
7044 			memcpy_ext(pmpriv->adapter, (t_u8 *)pssid_tlv->ssid,
7045 				   (t_u8 *)psk->ssid.ssid, psk->ssid.ssid_len,
7046 				   MLAN_MAX_SSID_LENGTH);
7047 			ptlv_buffer += (pssid_tlv->header.len +
7048 					sizeof(MrvlIEtypesHeader_t));
7049 			cmd->size += (pssid_tlv->header.len +
7050 				      sizeof(MrvlIEtypesHeader_t));
7051 			pssid_tlv->header.len =
7052 				wlan_cpu_to_le16(pssid_tlv->header.len);
7053 			ssid_flag = 1;
7054 		}
7055 		if (psk->psk_type == MLAN_PSK_PASSPHRASE) {
7056 			ppassphrase_tlv =
7057 				(MrvlIEtypes_Passphrase_t *)ptlv_buffer;
7058 			ppassphrase_tlv->header.type =
7059 				wlan_cpu_to_le16(TLV_TYPE_PASSPHRASE);
7060 			ppassphrase_tlv->header.len =
7061 				(t_u16)MIN(MLAN_MAX_PASSPHRASE_LENGTH,
7062 					   psk->psk.passphrase.passphrase_len);
7063 			memcpy_ext(pmpriv->adapter, ppassphrase_tlv->passphrase,
7064 				   psk->psk.passphrase.passphrase,
7065 				   psk->psk.passphrase.passphrase_len,
7066 				   MLAN_MAX_PASSPHRASE_LENGTH);
7067 			ptlv_buffer += (ppassphrase_tlv->header.len +
7068 					sizeof(MrvlIEtypesHeader_t));
7069 			cmd->size += (ppassphrase_tlv->header.len +
7070 				      sizeof(MrvlIEtypesHeader_t));
7071 			ppassphrase_tlv->header.len =
7072 				wlan_cpu_to_le16(ppassphrase_tlv->header.len);
7073 			passphrase_flag = 1;
7074 		}
7075 		if (psk->psk_type == MLAN_PSK_SAE_PASSWORD) {
7076 			psae_password_tlv =
7077 				(MrvlIEtypes_SAE_Password_t *)ptlv_buffer;
7078 			psae_password_tlv->header.type =
7079 				wlan_cpu_to_le16(TLV_TYPE_SAE_PASSWORD);
7080 			psae_password_tlv->header.len = (t_u16)MIN(
7081 				MLAN_MAX_SAE_PASSWORD_LENGTH,
7082 				psk->psk.sae_password.sae_password_len);
7083 			memcpy_ext(pmpriv->adapter,
7084 				   psae_password_tlv->sae_password,
7085 				   psk->psk.sae_password.sae_password,
7086 				   psk->psk.sae_password.sae_password_len,
7087 				   MLAN_MAX_SAE_PASSWORD_LENGTH);
7088 			ptlv_buffer += (psae_password_tlv->header.len +
7089 					sizeof(MrvlIEtypesHeader_t));
7090 			cmd->size += (psae_password_tlv->header.len +
7091 				      sizeof(MrvlIEtypesHeader_t));
7092 			psae_password_tlv->header.len =
7093 				wlan_cpu_to_le16(psae_password_tlv->header.len);
7094 			sae_password_flag = 1;
7095 		}
7096 		if (key_tlv)
7097 			key_tlv->header.len =
7098 				wlan_cpu_to_le16(cmd->size - length);
7099 		userset_passphrase++;
7100 		psk = (mlan_ds_passphrase *)&sec->param
7101 			      .roam_passphrase[userset_passphrase];
7102 	} while (psk && sec->multi_passphrase &&
7103 		 userset_passphrase < pmpriv->adapter->userset_passphrase);
7104 	pmpriv->adapter->userset_passphrase = 0;
7105 	if ((cmd_action == HostCmd_ACT_GEN_SET) &&
7106 	    ((ssid_flag || bssid_flag) && (!pmk_flag && !passphrase_flag) &&
7107 	     (!pmk_flag && !sae_password_flag))) {
7108 		PRINTM(MERROR,
7109 		       "Invalid case,ssid/bssid present without pmk, passphrase or sae password\n");
7110 		LEAVE();
7111 		return MLAN_STATUS_FAILURE;
7112 	}
7113 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SUPPLICANT_PMK);
7114 	pesupplicant_psk->action = wlan_cpu_to_le16(cmd_action);
7115 	pesupplicant_psk->cache_result = 0;
7116 	cmd->size = wlan_cpu_to_le16(cmd->size);
7117 	LEAVE();
7118 	return MLAN_STATUS_SUCCESS;
7119 }
7120 
7121 /**
7122  *  @brief Handle the supplicant pmk response
7123  *
7124  *  @param pmpriv       A pointer to mlan_private structure
7125  *  @param resp         A pointer to HostCmd_DS_COMMAND
7126  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
7127  *
7128  *  @return        MLAN_STATUS_SUCCESS MLAN_STATUS_FAILURE
7129  */
wlan_ret_802_11_supplicant_pmk(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)7130 mlan_status wlan_ret_802_11_supplicant_pmk(pmlan_private pmpriv,
7131 					   HostCmd_DS_COMMAND *resp,
7132 					   mlan_ioctl_req *pioctl_buf)
7133 {
7134 	HostCmd_DS_802_11_SUPPLICANT_PMK *supplicant_pmk_resp =
7135 		&resp->params.esupplicant_psk;
7136 	mlan_ds_sec_cfg *sec_buf = MNULL;
7137 	mlan_ds_sec_cfg *sec = MNULL;
7138 	mlan_adapter *pmadapter = pmpriv->adapter;
7139 	pmlan_callbacks pcb = &pmadapter->callbacks;
7140 	MrvlIEtypes_PMK_t *ppmk_tlv = MNULL;
7141 	MrvlIEtypes_Passphrase_t *passphrase_tlv = MNULL;
7142 	MrvlIEtypes_SAE_Password_t *psae_password_tlv = MNULL;
7143 	MrvlIEtypes_SsIdParamSet_t *pssid_tlv = MNULL;
7144 	MrvlIEtypes_Bssid_t *pbssid_tlv = MNULL;
7145 	t_u8 *tlv_buf = (t_u8 *)supplicant_pmk_resp->tlv_buffer;
7146 	t_u16 action = wlan_le16_to_cpu(supplicant_pmk_resp->action);
7147 	int tlv_buf_len = 0;
7148 	t_u16 tlv;
7149 	mlan_status ret = MLAN_STATUS_SUCCESS;
7150 
7151 	ENTER();
7152 	tlv_buf_len = resp->size -
7153 		      (sizeof(HostCmd_DS_802_11_SUPPLICANT_PMK) + S_DS_GEN - 1);
7154 
7155 	if (pioctl_buf) {
7156 		if (((mlan_ds_bss *)pioctl_buf->pbuf)->sub_command ==
7157 		    MLAN_OID_BSS_FIND_BSS) {
7158 			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
7159 					       sizeof(mlan_ds_sec_cfg),
7160 					       MLAN_MEM_DEF, (t_u8 **)&sec_buf);
7161 			if (ret || !sec_buf) {
7162 				PRINTM(MERROR, "Could not allocate sec_buf!\n");
7163 				LEAVE();
7164 				return ret;
7165 			}
7166 			sec = sec_buf;
7167 		} else {
7168 			sec = (mlan_ds_sec_cfg *)pioctl_buf->pbuf;
7169 		}
7170 		if (action == HostCmd_ACT_GEN_GET) {
7171 			while (tlv_buf_len > 0) {
7172 				tlv = (*tlv_buf) | (*(tlv_buf + 1) << 8);
7173 				if ((tlv != TLV_TYPE_SSID) &&
7174 				    (tlv != TLV_TYPE_BSSID) &&
7175 				    (tlv != TLV_TYPE_PASSPHRASE) &&
7176 				    (tlv != TLV_TYPE_PMK) &&
7177 				    (tlv != TLV_TYPE_SAE_PASSWORD))
7178 					break;
7179 				switch (tlv) {
7180 				case TLV_TYPE_SSID:
7181 					pssid_tlv =
7182 						(MrvlIEtypes_SsIdParamSet_t *)
7183 							tlv_buf;
7184 					pssid_tlv->header.len =
7185 						wlan_le16_to_cpu(
7186 							pssid_tlv->header.len);
7187 					memcpy_ext(
7188 						pmpriv->adapter,
7189 						sec->param.passphrase.ssid.ssid,
7190 						pssid_tlv->ssid,
7191 						pssid_tlv->header.len,
7192 						MLAN_MAX_SSID_LENGTH);
7193 					sec->param.passphrase.ssid.ssid_len =
7194 						MIN(MLAN_MAX_SSID_LENGTH,
7195 						    pssid_tlv->header.len);
7196 					tlv_buf += pssid_tlv->header.len +
7197 						   sizeof(MrvlIEtypesHeader_t);
7198 					tlv_buf_len -=
7199 						(pssid_tlv->header.len +
7200 						 sizeof(MrvlIEtypesHeader_t));
7201 					break;
7202 				case TLV_TYPE_BSSID:
7203 					pbssid_tlv =
7204 						(MrvlIEtypes_Bssid_t *)tlv_buf;
7205 					pbssid_tlv->header.len =
7206 						wlan_le16_to_cpu(
7207 							pbssid_tlv->header.len);
7208 					memcpy_ext(pmpriv->adapter,
7209 						   &sec->param.passphrase.bssid,
7210 						   pbssid_tlv->bssid,
7211 						   MLAN_MAC_ADDR_LENGTH,
7212 						   MLAN_MAC_ADDR_LENGTH);
7213 					tlv_buf += pbssid_tlv->header.len +
7214 						   sizeof(MrvlIEtypesHeader_t);
7215 					tlv_buf_len -=
7216 						(pbssid_tlv->header.len +
7217 						 sizeof(MrvlIEtypesHeader_t));
7218 					break;
7219 				case TLV_TYPE_PASSPHRASE:
7220 					passphrase_tlv =
7221 						(MrvlIEtypes_Passphrase_t *)
7222 							tlv_buf;
7223 					passphrase_tlv->header
7224 						.len = wlan_le16_to_cpu(
7225 						passphrase_tlv->header.len);
7226 					sec->param.passphrase.psk_type =
7227 						MLAN_PSK_PASSPHRASE;
7228 					sec->param.passphrase.psk.passphrase
7229 						.passphrase_len =
7230 						passphrase_tlv->header.len;
7231 					memcpy_ext(
7232 						pmpriv->adapter,
7233 						sec->param.passphrase.psk
7234 							.passphrase.passphrase,
7235 						passphrase_tlv->passphrase,
7236 						passphrase_tlv->header.len,
7237 						MLAN_MAX_PASSPHRASE_LENGTH);
7238 					tlv_buf += passphrase_tlv->header.len +
7239 						   sizeof(MrvlIEtypesHeader_t);
7240 					tlv_buf_len -=
7241 						(passphrase_tlv->header.len +
7242 						 sizeof(MrvlIEtypesHeader_t));
7243 					break;
7244 				case TLV_TYPE_SAE_PASSWORD:
7245 					psae_password_tlv =
7246 						(MrvlIEtypes_SAE_Password_t *)
7247 							tlv_buf;
7248 					psae_password_tlv->header
7249 						.len = wlan_le16_to_cpu(
7250 						psae_password_tlv->header.len);
7251 					sec->param.passphrase.psk_type =
7252 						MLAN_PSK_SAE_PASSWORD;
7253 					sec->param.passphrase.psk.sae_password
7254 						.sae_password_len =
7255 						psae_password_tlv->header.len;
7256 					memcpy_ext(
7257 						pmpriv->adapter,
7258 						sec->param.passphrase.psk
7259 							.sae_password
7260 							.sae_password,
7261 						psae_password_tlv->sae_password,
7262 						psae_password_tlv->header.len,
7263 						MLAN_MAX_SAE_PASSWORD_LENGTH);
7264 					tlv_buf +=
7265 						psae_password_tlv->header.len +
7266 						sizeof(MrvlIEtypesHeader_t);
7267 					tlv_buf_len -=
7268 						(psae_password_tlv->header.len +
7269 						 sizeof(MrvlIEtypesHeader_t));
7270 					break;
7271 				case TLV_TYPE_PMK:
7272 					ppmk_tlv = (MrvlIEtypes_PMK_t *)tlv_buf;
7273 					ppmk_tlv->header.len = wlan_le16_to_cpu(
7274 						ppmk_tlv->header.len);
7275 					sec->param.passphrase.psk_type =
7276 						MLAN_PSK_PMK;
7277 					memcpy_ext(pmpriv->adapter,
7278 						   sec->param.passphrase.psk.pmk
7279 							   .pmk,
7280 						   ppmk_tlv->pmk,
7281 						   ppmk_tlv->header.len,
7282 						   MLAN_MAX_KEY_LENGTH);
7283 					tlv_buf += ppmk_tlv->header.len +
7284 						   sizeof(MrvlIEtypesHeader_t);
7285 					tlv_buf_len -=
7286 						(ppmk_tlv->header.len +
7287 						 sizeof(MrvlIEtypesHeader_t));
7288 					break;
7289 				}
7290 			}
7291 #ifdef STA_SUPPORT
7292 			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA &&
7293 			    ((mlan_ds_bss *)pioctl_buf->pbuf)->sub_command ==
7294 				    MLAN_OID_BSS_FIND_BSS) {
7295 				wlan_set_ewpa_mode(pmpriv,
7296 						   &sec->param.passphrase);
7297 				ret = wlan_find_bss(pmpriv, pioctl_buf);
7298 			}
7299 #endif
7300 
7301 		} else if (action == HostCmd_ACT_GEN_SET) {
7302 			PRINTM(MINFO, "Esupp PMK set: enable ewpa query\n");
7303 			pmpriv->ewpa_query = MTRUE;
7304 		}
7305 		if (sec_buf)
7306 			pcb->moal_mfree(pmadapter->pmoal_handle,
7307 					(t_u8 *)sec_buf);
7308 	}
7309 
7310 	LEAVE();
7311 	return ret;
7312 }
7313 
7314 /**
7315  *  @brief This function prepares command of independent reset.
7316  *
7317  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
7318  *  @param cmd_action   the action: GET or SET
7319  *  @param pdata_buf    A pointer to data buffer
7320  *  @return             MLAN_STATUS_SUCCESS
7321  */
wlan_cmd_ind_rst_cfg(HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)7322 mlan_status wlan_cmd_ind_rst_cfg(HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
7323 				 t_void *pdata_buf)
7324 {
7325 	mlan_ds_ind_rst_cfg *pdata_ind_rst = (mlan_ds_ind_rst_cfg *)pdata_buf;
7326 	HostCmd_DS_INDEPENDENT_RESET_CFG *ind_rst_cfg =
7327 		(HostCmd_DS_INDEPENDENT_RESET_CFG *)&cmd->params.ind_rst_cfg;
7328 
7329 	ENTER();
7330 
7331 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_INDEPENDENT_RESET_CFG);
7332 	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_INDEPENDENT_RESET_CFG) +
7333 				     S_DS_GEN);
7334 
7335 	ind_rst_cfg->action = wlan_cpu_to_le16(cmd_action);
7336 	if (cmd_action == HostCmd_ACT_GEN_SET) {
7337 		ind_rst_cfg->ir_mode = pdata_ind_rst->ir_mode;
7338 		ind_rst_cfg->gpio_pin = pdata_ind_rst->gpio_pin;
7339 	}
7340 
7341 	LEAVE();
7342 	return MLAN_STATUS_SUCCESS;
7343 }
7344 
7345 /**
7346  *  @brief This function handles the command response of independent reset
7347  *
7348  *  @param pmpriv       A pointer to mlan_private structure
7349  *  @param resp         A pointer to HostCmd_DS_COMMAND
7350  *  @param pioctl_buf   A pointer to command buffer
7351  *
7352  *  @return             MLAN_STATUS_SUCCESS
7353  */
wlan_ret_ind_rst_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)7354 mlan_status wlan_ret_ind_rst_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
7355 				 mlan_ioctl_req *pioctl_buf)
7356 {
7357 	mlan_ds_misc_cfg *misc = MNULL;
7358 	const HostCmd_DS_INDEPENDENT_RESET_CFG *ind_rst_cfg =
7359 		(HostCmd_DS_INDEPENDENT_RESET_CFG *)&resp->params.ind_rst_cfg;
7360 
7361 	ENTER();
7362 
7363 	if (pioctl_buf) {
7364 		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
7365 
7366 		if (wlan_le16_to_cpu(ind_rst_cfg->action) ==
7367 		    HostCmd_ACT_GEN_GET) {
7368 			misc->param.ind_rst_cfg.ir_mode = ind_rst_cfg->ir_mode;
7369 			misc->param.ind_rst_cfg.gpio_pin =
7370 				ind_rst_cfg->gpio_pin;
7371 		}
7372 	}
7373 
7374 	LEAVE();
7375 	return MLAN_STATUS_SUCCESS;
7376 }
7377 
7378 /**
7379  *  @brief This function prepares command of ps inactivity timeout.
7380  *
7381  *  @param pmpriv      A pointer to mlan_private structure
7382  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
7383  *  @param cmd_action   the action: GET or SET
7384  *  @param pdata_buf    A pointer to data buffer
7385  *  @return             MLAN_STATUS_SUCCESS
7386  */
wlan_cmd_ps_inactivity_timeout(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)7387 mlan_status wlan_cmd_ps_inactivity_timeout(pmlan_private pmpriv,
7388 					   HostCmd_DS_COMMAND *cmd,
7389 					   t_u16 cmd_action, t_void *pdata_buf)
7390 {
7391 	t_u16 timeout = *((t_u16 *)pdata_buf);
7392 	HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT *ps_inact_tmo =
7393 		(HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT *)&cmd->params
7394 			.ps_inact_tmo;
7395 
7396 	ENTER();
7397 
7398 	cmd->command =
7399 		wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT);
7400 	cmd->size = wlan_cpu_to_le16(
7401 		sizeof(HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT) + S_DS_GEN);
7402 
7403 	ps_inact_tmo->action = wlan_cpu_to_le16(cmd_action);
7404 	if (cmd_action == HostCmd_ACT_GEN_SET)
7405 		ps_inact_tmo->inact_tmo = wlan_cpu_to_le16(timeout);
7406 
7407 	LEAVE();
7408 	return MLAN_STATUS_SUCCESS;
7409 }
7410 
7411 /**
7412  *  @brief This function prepares command of HostCmd_CMD_GET_TSF
7413  *
7414  *  @param pmpriv       A pointer to mlan_private structure
7415  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
7416  *  @param cmd_action   The action: GET
7417  *  @return             MLAN_STATUS_SUCCESS
7418  */
wlan_cmd_get_tsf(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action)7419 mlan_status wlan_cmd_get_tsf(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
7420 			     t_u16 cmd_action)
7421 {
7422 	ENTER();
7423 
7424 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_GET_TSF);
7425 	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_TSF)) + S_DS_GEN);
7426 
7427 	LEAVE();
7428 	return MLAN_STATUS_SUCCESS;
7429 }
7430 
7431 /**
7432  *  @brief This function handles the command response of HostCmd_CMD_GET_TSF
7433  *
7434  *  @param pmpriv       A pointer to mlan_private structure
7435  *  @param resp         A pointer to HostCmd_DS_COMMAND
7436  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
7437  *
7438  *  @return             MLAN_STATUS_SUCCESS
7439  */
wlan_ret_get_tsf(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)7440 mlan_status wlan_ret_get_tsf(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
7441 			     mlan_ioctl_req *pioctl_buf)
7442 {
7443 	mlan_ds_misc_cfg *misc_cfg = MNULL;
7444 	HostCmd_DS_TSF *tsf_pointer = (HostCmd_DS_TSF *)&resp->params.tsf;
7445 
7446 	ENTER();
7447 	if (pioctl_buf) {
7448 		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
7449 		misc_cfg->param.misc_tsf = wlan_le64_to_cpu(tsf_pointer->tsf);
7450 	}
7451 
7452 	LEAVE();
7453 	return MLAN_STATUS_SUCCESS;
7454 }
7455 
7456 /**
7457  *  @brief This function handles the command response of chan_region_cfg
7458  *
7459  *  @param pmpriv       A pointer to mlan_private structure
7460  *  @param resp         A pointer to HostCmd_DS_COMMAND
7461  *  @param pioctl_buf   A pointer to command buffer
7462  *
7463  *  @return             MLAN_STATUS_SUCCESS
7464  */
wlan_ret_chan_region_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)7465 mlan_status wlan_ret_chan_region_cfg(pmlan_private pmpriv,
7466 				     HostCmd_DS_COMMAND *resp,
7467 				     mlan_ioctl_req *pioctl_buf)
7468 {
7469 	mlan_adapter *pmadapter = pmpriv->adapter;
7470 	t_u16 action;
7471 	HostCmd_DS_CHAN_REGION_CFG *reg = MNULL;
7472 	t_u8 *tlv_buf = MNULL;
7473 	t_u16 tlv_buf_left;
7474 	mlan_ds_misc_cfg *misc_cfg = MNULL;
7475 	mlan_ds_misc_chnrgpwr_cfg *cfg = MNULL;
7476 	mlan_status ret = MLAN_STATUS_SUCCESS;
7477 
7478 	ENTER();
7479 
7480 	reg = (HostCmd_DS_CHAN_REGION_CFG *)&resp->params.reg_cfg;
7481 	if (!reg) {
7482 		ret = MLAN_STATUS_FAILURE;
7483 		goto done;
7484 	}
7485 
7486 	action = wlan_le16_to_cpu(reg->action);
7487 	if (action != HostCmd_ACT_GEN_GET) {
7488 		ret = MLAN_STATUS_FAILURE;
7489 		goto done;
7490 	}
7491 
7492 	tlv_buf = (t_u8 *)reg + sizeof(*reg);
7493 	tlv_buf_left = wlan_le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*reg);
7494 
7495 	/* Add FW cfp tables and region info */
7496 	wlan_add_fw_cfp_tables(pmpriv, tlv_buf, tlv_buf_left);
7497 	if (pmadapter->otp_region) {
7498 		wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
7499 				     pmadapter->fw_bands);
7500 	}
7501 	if (!pioctl_buf)
7502 		goto done;
7503 
7504 	if (!pioctl_buf->pbuf) {
7505 		ret = MLAN_STATUS_FAILURE;
7506 		goto done;
7507 	}
7508 
7509 	misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
7510 
7511 	if (misc_cfg->sub_command == MLAN_OID_MISC_GET_REGIONPWR_CFG) {
7512 		cfg = (mlan_ds_misc_chnrgpwr_cfg *)&(
7513 			misc_cfg->param.rgchnpwr_cfg);
7514 		cfg->length = wlan_le16_to_cpu(resp->size);
7515 		memcpy_ext(pmpriv->adapter, cfg->chnrgpwr_buf, (t_u8 *)resp,
7516 			   cfg->length, sizeof(cfg->chnrgpwr_buf));
7517 	} else {
7518 		memset(pmpriv->adapter, &misc_cfg->param.custom_reg_domain, 0,
7519 		       sizeof(mlan_ds_custom_reg_domain));
7520 		if (pmadapter->otp_region)
7521 			memcpy_ext(pmpriv->adapter,
7522 				   &misc_cfg->param.custom_reg_domain.region,
7523 				   pmadapter->otp_region,
7524 				   sizeof(otp_region_info_t),
7525 				   sizeof(otp_region_info_t));
7526 		if (pmadapter->cfp_otp_bg) {
7527 			misc_cfg->param.custom_reg_domain.num_bg_chan =
7528 				pmadapter->tx_power_table_bg_rows;
7529 			memcpy_ext(pmpriv->adapter,
7530 				   (t_u8 *)misc_cfg->param.custom_reg_domain
7531 					   .cfp_tbl,
7532 				   (t_u8 *)pmadapter->cfp_otp_bg,
7533 				   pmadapter->tx_power_table_bg_rows *
7534 					   sizeof(chan_freq_power_t),
7535 				   pmadapter->tx_power_table_bg_rows *
7536 					   sizeof(chan_freq_power_t));
7537 		}
7538 		if (pmadapter->cfp_otp_a) {
7539 			misc_cfg->param.custom_reg_domain.num_a_chan =
7540 				pmadapter->tx_power_table_a_rows;
7541 			memcpy_ext(pmpriv->adapter,
7542 				   (t_u8 *)misc_cfg->param.custom_reg_domain
7543 						   .cfp_tbl +
7544 					   pmadapter->tx_power_table_bg_rows *
7545 						   sizeof(chan_freq_power_t),
7546 				   (t_u8 *)pmadapter->cfp_otp_a,
7547 				   pmadapter->tx_power_table_a_rows *
7548 					   sizeof(chan_freq_power_t),
7549 				   pmadapter->tx_power_table_a_rows *
7550 					   sizeof(chan_freq_power_t));
7551 		}
7552 	}
7553 done:
7554 	LEAVE();
7555 	return ret;
7556 }
7557 
7558 /**
7559  *  @brief This function prepares command of packet aggragation
7560  *
7561  *  @param pmpriv       A pointer to mlan_private structure
7562  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
7563  *  @param cmd_action   the action: GET or SET
7564  *  @param pdata_buf    A pointer to data buffer
7565  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
7566  */
wlan_cmd_packet_aggr_ctrl(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)7567 mlan_status wlan_cmd_packet_aggr_ctrl(pmlan_private pmpriv,
7568 				      HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
7569 				      t_void *pdata_buf)
7570 {
7571 	HostCmd_DS_PACKET_AGGR_CTRL *aggr_ctrl = &cmd->params.aggr_ctrl;
7572 	mlan_ds_misc_aggr_ctrl *aggr = (mlan_ds_misc_aggr_ctrl *)pdata_buf;
7573 
7574 	ENTER();
7575 
7576 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_PACKET_AGGR_CTRL);
7577 	aggr_ctrl->action = wlan_cpu_to_le16(cmd_action);
7578 	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_PACKET_AGGR_CTRL) +
7579 				     S_DS_GEN);
7580 	aggr_ctrl->aggr_enable = 0;
7581 
7582 	if (aggr->tx.enable)
7583 		aggr_ctrl->aggr_enable |= MBIT(0);
7584 	aggr_ctrl->aggr_enable = wlan_cpu_to_le16(aggr_ctrl->aggr_enable);
7585 
7586 	LEAVE();
7587 	return MLAN_STATUS_SUCCESS;
7588 }
7589 
7590 /**
7591  *  @brief This function handles the command response of
7592  *  packet aggregation
7593  *
7594  *  @param pmpriv       A pointer to mlan_private structure
7595  *  @param resp         A pointer to HostCmd_DS_COMMAND
7596  *  @param pioctl_buf   A pointer to command buffer
7597  *
7598  *  @return             MLAN_STATUS_SUCCESS
7599  */
wlan_ret_packet_aggr_ctrl(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)7600 mlan_status wlan_ret_packet_aggr_ctrl(pmlan_private pmpriv,
7601 				      HostCmd_DS_COMMAND *resp,
7602 				      mlan_ioctl_req *pioctl_buf)
7603 {
7604 	mlan_ds_misc_cfg *misc = MNULL;
7605 	HostCmd_DS_PACKET_AGGR_CTRL *aggr_ctrl = &resp->params.aggr_ctrl;
7606 	mlan_ds_misc_aggr_ctrl *aggr = MNULL;
7607 #if defined(USB)
7608 	mlan_adapter *pmadapter = pmpriv->adapter;
7609 	t_u8 i;
7610 	t_u8 change = 0;
7611 	usb_tx_aggr_params *pusb_tx_aggr = MNULL;
7612 #endif
7613 
7614 	ENTER();
7615 
7616 	aggr_ctrl->aggr_enable = wlan_le16_to_cpu(aggr_ctrl->aggr_enable);
7617 	aggr_ctrl->tx_aggr_max_size =
7618 		wlan_le16_to_cpu(aggr_ctrl->tx_aggr_max_size);
7619 	aggr_ctrl->tx_aggr_max_num =
7620 		wlan_le16_to_cpu(aggr_ctrl->tx_aggr_max_num);
7621 	aggr_ctrl->tx_aggr_align = wlan_le16_to_cpu(aggr_ctrl->tx_aggr_align);
7622 	PRINTM(MCMND, "enable=0x%x, tx_size=%d, tx_num=%d, tx_align=%d\n",
7623 	       aggr_ctrl->aggr_enable, aggr_ctrl->tx_aggr_max_size,
7624 	       aggr_ctrl->tx_aggr_max_num, aggr_ctrl->tx_aggr_align);
7625 #if defined(USB)
7626 	if (IS_USB(pmadapter->card_type)) {
7627 		if (aggr_ctrl->aggr_enable & MBIT(0)) {
7628 			if (!pmadapter->pcard_usb->usb_tx_aggr[0]
7629 				     .aggr_ctrl.enable) {
7630 				pmadapter->pcard_usb->usb_tx_aggr[0]
7631 					.aggr_ctrl.enable = MTRUE;
7632 				change = MTRUE;
7633 			}
7634 
7635 		} else {
7636 			if (pmadapter->pcard_usb->usb_tx_aggr[0]
7637 				    .aggr_ctrl.enable) {
7638 				pmadapter->pcard_usb->usb_tx_aggr[0]
7639 					.aggr_ctrl.enable = MFALSE;
7640 				change = MTRUE;
7641 			}
7642 		}
7643 		pmadapter->pcard_usb->usb_tx_aggr[0].aggr_ctrl.aggr_mode =
7644 			MLAN_USB_AGGR_MODE_LEN_V2;
7645 		pmadapter->pcard_usb->usb_tx_aggr[0].aggr_ctrl.aggr_align =
7646 			aggr_ctrl->tx_aggr_align;
7647 		pmadapter->pcard_usb->usb_tx_aggr[0].aggr_ctrl.aggr_max =
7648 			aggr_ctrl->tx_aggr_max_size;
7649 		pmadapter->pcard_usb->usb_tx_aggr[0].aggr_ctrl.aggr_tmo =
7650 			MLAN_USB_TX_AGGR_TIMEOUT_MSEC * 1000;
7651 		if (change) {
7652 			wlan_reset_usb_tx_aggr(pmadapter);
7653 			for (i = 0; i < pmadapter->priv_num; ++i) {
7654 				if (pmadapter->priv[i]) {
7655 					pusb_tx_aggr =
7656 						wlan_get_usb_tx_aggr_params(
7657 							pmadapter,
7658 							pmadapter->priv[i]
7659 								->port);
7660 					if (pusb_tx_aggr &&
7661 					    pusb_tx_aggr->aggr_ctrl.aggr_mode ==
7662 						    MLAN_USB_AGGR_MODE_LEN_V2)
7663 						pmadapter->priv[i]->intf_hr_len =
7664 							MLAN_USB_TX_AGGR_HEADER;
7665 					else
7666 						pmadapter->priv[i]->intf_hr_len =
7667 							USB_INTF_HEADER_LEN;
7668 				}
7669 			}
7670 		}
7671 	}
7672 #endif
7673 	if (pioctl_buf) {
7674 		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
7675 		aggr = (mlan_ds_misc_aggr_ctrl *)&(misc->param.aggr_params);
7676 		if (aggr_ctrl->aggr_enable & MBIT(0))
7677 			aggr->tx.enable = MTRUE;
7678 		else
7679 			aggr->tx.enable = MFALSE;
7680 		aggr->tx.aggr_align = aggr_ctrl->tx_aggr_align;
7681 		aggr->tx.aggr_max_size = aggr_ctrl->tx_aggr_max_size;
7682 		aggr->tx.aggr_max_num = aggr_ctrl->tx_aggr_max_num;
7683 #if defined(USB)
7684 		if (IS_USB(pmadapter->card_type))
7685 			aggr->tx.aggr_tmo = pmadapter->pcard_usb->usb_tx_aggr[0]
7686 						    .aggr_ctrl.aggr_tmo;
7687 #endif
7688 	}
7689 	LEAVE();
7690 	return MLAN_STATUS_SUCCESS;
7691 }
7692 
7693 /**
7694  *  @brief This function sends fw dump event command to firmware.
7695  *
7696  *  @param pmpriv         A pointer to mlan_private structure
7697  *  @param cmd          Hostcmd ID
7698  *  @param cmd_action   Command action
7699  *  @param pdata_buf    A void pointer to information buffer
7700  *  @return             N/A
7701  */
wlan_cmd_fw_dump_event(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)7702 mlan_status wlan_cmd_fw_dump_event(pmlan_private pmpriv,
7703 				   HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
7704 				   t_void *pdata_buf)
7705 {
7706 	ENTER();
7707 
7708 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_FW_DUMP_EVENT);
7709 	cmd->size = S_DS_GEN;
7710 	cmd->size = wlan_cpu_to_le16(cmd->size);
7711 
7712 	LEAVE();
7713 	return MLAN_STATUS_SUCCESS;
7714 }
7715 
7716 /**
7717  *  @brief This function prepares command of get link layer statistics.
7718  *
7719  *  @param pmpriv       A pointer to mlan_private structure
7720  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
7721  *  @param cmd_action   the action: GET or SET
7722  *  @param pdata_buf    A pointer to data buffer
7723  *
7724  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
7725  *
7726  */
wlan_cmd_802_11_link_statistic(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,mlan_ioctl_req * pioctl_buf)7727 mlan_status wlan_cmd_802_11_link_statistic(pmlan_private pmpriv,
7728 					   HostCmd_DS_COMMAND *cmd,
7729 					   t_u16 cmd_action,
7730 					   mlan_ioctl_req *pioctl_buf)
7731 {
7732 	mlan_ds_get_info *info = (mlan_ds_get_info *)(pioctl_buf->pbuf);
7733 	HostCmd_DS_802_11_LINK_STATISTIC *ll_stat =
7734 		&cmd->params.get_link_statistic;
7735 	wifi_link_layer_params *ll_params = MNULL;
7736 
7737 	ENTER();
7738 
7739 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_LINK_STATS);
7740 	cmd->size = wlan_cpu_to_le16(S_DS_GEN +
7741 				     sizeof(HostCmd_DS_802_11_LINK_STATISTIC));
7742 	ll_stat->action = wlan_cpu_to_le16(cmd_action);
7743 
7744 	switch (cmd_action) {
7745 	case HostCmd_ACT_GEN_SET:
7746 		ll_params =
7747 			(wifi_link_layer_params *)info->param.link_statistic;
7748 		ll_stat->mpdu_size_threshold =
7749 			wlan_cpu_to_le32(ll_params->mpdu_size_threshold);
7750 		ll_stat->aggressive_statistics_gathering = wlan_cpu_to_le32(
7751 			ll_params->aggressive_statistics_gathering);
7752 		break;
7753 	case HostCmd_ACT_GEN_GET:
7754 		/** ll_stat->stat_type = wlan_cpu_to_le16(stat_type); */
7755 		break;
7756 	default:
7757 		break;
7758 	}
7759 
7760 	LEAVE();
7761 	return MLAN_STATUS_SUCCESS;
7762 }
7763 
7764 /**
7765  *  @brief This function fill link layer statistic from firmware
7766  *
7767  *  @param priv       					A pointer to
7768  * mlan_private structure
7769  *  @param link_statistic_ioctl_buf,    A pointer to fill ioctl buffer
7770  *  @param resp         				A pointer to
7771  * HostCmd_DS_COMMAND
7772  *
7773  *  @return             MLAN_STATUS_SUCCESS
7774  */
wlan_fill_link_statistic(mlan_private * priv,char * link_statistic_ioctl_buf,HostCmd_DS_COMMAND * resp)7775 static void wlan_fill_link_statistic(mlan_private *priv,
7776 				     char *link_statistic_ioctl_buf,
7777 				     HostCmd_DS_COMMAND *resp)
7778 {
7779 	char *link_statistic = link_statistic_ioctl_buf;
7780 	wifi_radio_stat *radio_stat = MNULL;
7781 	wifi_iface_stat *iface_stat = MNULL;
7782 	mlan_wifi_iface_stat *fw_ifaceStat = MNULL;
7783 	mlan_wifi_radio_stat *fw_radioStat = MNULL;
7784 	t_u32 num_radio = 0;
7785 	int i = 0, chan_idx = 0, peerIdx = 0, rate_idx = 0;
7786 	t_u16 left_len = 0, tlv_type = 0, tlv_len = 0;
7787 	MrvlIEtypesHeader_t *tlv = MNULL;
7788 	HostCmd_DS_802_11_LINK_STATISTIC *plink_stat =
7789 		(HostCmd_DS_802_11_LINK_STATISTIC *)&resp->params
7790 			.get_link_statistic;
7791 
7792 	/* TLV parse */
7793 	if (resp->size > (sizeof(HostCmd_DS_802_11_LINK_STATISTIC) - S_DS_GEN))
7794 		left_len = resp->size -
7795 			   sizeof(HostCmd_DS_802_11_LINK_STATISTIC) - S_DS_GEN;
7796 
7797 	tlv = (MrvlIEtypesHeader_t *)(plink_stat->value);
7798 	DBG_HEXDUMP(MDAT_D, "tlv:", (void *)tlv, 1024);
7799 	while (left_len > sizeof(MrvlIEtypesHeader_t)) {
7800 		tlv_type = wlan_le16_to_cpu(tlv->type);
7801 		tlv_len = wlan_le16_to_cpu(tlv->len);
7802 		switch (tlv_type) {
7803 		case TLV_TYPE_LL_STAT_IFACE:
7804 			fw_ifaceStat = (mlan_wifi_iface_stat
7805 						*)((t_u8 *)tlv +
7806 						   sizeof(MrvlIEtypesHeader_t));
7807 			break;
7808 		case TLV_TYPE_LL_STAT_RADIO:
7809 			fw_radioStat = (mlan_wifi_radio_stat
7810 						*)((t_u8 *)tlv +
7811 						   sizeof(MrvlIEtypesHeader_t));
7812 			num_radio = MAX_RADIO;
7813 			break;
7814 		default:
7815 			break;
7816 		}
7817 		left_len -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
7818 		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
7819 					      sizeof(MrvlIEtypesHeader_t));
7820 	}
7821 
7822 	if (!fw_ifaceStat || !fw_radioStat) {
7823 		PRINTM(MERROR, "!fw_ifaceStat || !fw_radioStat\n");
7824 		return;
7825 	}
7826 
7827 	*((t_u32 *)link_statistic) = num_radio;
7828 	link_statistic += sizeof(num_radio);
7829 
7830 	/* Fill radio stats array*/
7831 	for (i = 0; i < num_radio; i++) {
7832 		radio_stat = (wifi_radio_stat *)link_statistic;
7833 		link_statistic += sizeof(wifi_radio_stat);
7834 
7835 		radio_stat->radio = wlan_le32_to_cpu(fw_radioStat[i].radio);
7836 
7837 		radio_stat->on_time = wlan_le32_to_cpu(fw_radioStat[i].on_time);
7838 		radio_stat->tx_time = wlan_le32_to_cpu(fw_radioStat[i].tx_time);
7839 		radio_stat->reserved0 =
7840 			wlan_le32_to_cpu(fw_radioStat[i].reserved0);
7841 		radio_stat->rx_time = wlan_le32_to_cpu(fw_radioStat[i].rx_time);
7842 		radio_stat->on_time_scan =
7843 			wlan_le32_to_cpu(fw_radioStat[i].on_time_scan);
7844 		radio_stat->on_time_nbd =
7845 			wlan_le32_to_cpu(fw_radioStat[i].on_time_nbd);
7846 		radio_stat->on_time_gscan =
7847 			wlan_le32_to_cpu(fw_radioStat[i].on_time_gscan);
7848 		radio_stat->on_time_roam_scan =
7849 			wlan_le32_to_cpu(fw_radioStat[i].on_time_roam_scan);
7850 		radio_stat->on_time_pno_scan =
7851 			wlan_le32_to_cpu(fw_radioStat[i].on_time_pno_scan);
7852 		radio_stat->on_time_hs20 =
7853 			wlan_le32_to_cpu(fw_radioStat[i].on_time_hs20);
7854 
7855 		radio_stat->num_channels =
7856 			wlan_le32_to_cpu(fw_radioStat[i].num_channels);
7857 		for (chan_idx = 0; chan_idx < radio_stat->num_channels;
7858 		     chan_idx++) {
7859 			if (radio_stat->num_channels > MAX_NUM_CHAN) {
7860 				radio_stat->num_channels =
7861 					wlan_le32_to_cpu(MAX_NUM_CHAN);
7862 				PRINTM(MERROR,
7863 				       "%s : radio_stat->num_channels=%d\n",
7864 				       __func__, radio_stat->num_channels);
7865 				break;
7866 			}
7867 			radio_stat->channels[chan_idx].channel.width =
7868 				wlan_le32_to_cpu(fw_radioStat[i]
7869 							 .channels[chan_idx]
7870 							 .channel.width);
7871 			radio_stat->channels[chan_idx].channel.center_freq =
7872 				wlan_le32_to_cpu(fw_radioStat[i]
7873 							 .channels[chan_idx]
7874 							 .channel.center_freq);
7875 			radio_stat->channels[chan_idx].channel.center_freq0 =
7876 				wlan_le32_to_cpu(fw_radioStat[i]
7877 							 .channels[chan_idx]
7878 							 .channel.center_freq0);
7879 			radio_stat->channels[chan_idx].channel.center_freq1 =
7880 				wlan_le32_to_cpu(fw_radioStat[i]
7881 							 .channels[chan_idx]
7882 							 .channel.center_freq1);
7883 
7884 			radio_stat->channels[chan_idx]
7885 				.on_time = wlan_le32_to_cpu(
7886 				fw_radioStat[i].channels[chan_idx].on_time);
7887 			radio_stat->channels[chan_idx].cca_busy_time =
7888 				wlan_le32_to_cpu(fw_radioStat[i]
7889 							 .channels[chan_idx]
7890 							 .cca_busy_time);
7891 		}
7892 	}
7893 
7894 	/* Fill iface stats*/
7895 	iface_stat = (wifi_iface_stat *)link_statistic;
7896 
7897 	/* get wifi_interface_link_layer_info in driver, not in firmware */
7898 	if (priv->bss_role == MLAN_BSS_ROLE_STA) {
7899 		iface_stat->info.mode = MLAN_INTERFACE_STA;
7900 		if (priv->media_connected)
7901 			iface_stat->info.state = MLAN_ASSOCIATING;
7902 		else
7903 			iface_stat->info.state = MLAN_DISCONNECTED;
7904 		iface_stat->info.roaming = MLAN_ROAMING_IDLE;
7905 		iface_stat->info.capabilities = MLAN_CAPABILITY_QOS;
7906 		memcpy_ext(priv->adapter, iface_stat->info.ssid,
7907 			   priv->curr_bss_params.bss_descriptor.ssid.ssid,
7908 			   MLAN_MAX_SSID_LENGTH, MLAN_MAX_SSID_LENGTH);
7909 		memcpy_ext(priv->adapter, iface_stat->info.bssid,
7910 			   priv->curr_bss_params.bss_descriptor.mac_address,
7911 			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
7912 	} else {
7913 		iface_stat->info.mode = MLAN_INTERFACE_SOFTAP;
7914 		iface_stat->info.capabilities = MLAN_CAPABILITY_QOS;
7915 	}
7916 	memcpy_ext(priv->adapter, iface_stat->info.mac_addr, priv->curr_addr,
7917 		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
7918 	memcpy_ext(priv->adapter, iface_stat->info.ap_country_str,
7919 		   priv->adapter->country_code, COUNTRY_CODE_LEN,
7920 		   COUNTRY_CODE_LEN);
7921 	memcpy_ext(priv->adapter, iface_stat->info.country_str,
7922 		   priv->adapter->country_code, COUNTRY_CODE_LEN,
7923 		   COUNTRY_CODE_LEN);
7924 
7925 	iface_stat->beacon_rx = wlan_le32_to_cpu(fw_ifaceStat->beacon_rx);
7926 	iface_stat->average_tsf_offset =
7927 		wlan_le64_to_cpu(fw_ifaceStat->average_tsf_offset);
7928 	iface_stat->leaky_ap_detected =
7929 		wlan_le32_to_cpu(fw_ifaceStat->leaky_ap_detected);
7930 	iface_stat->leaky_ap_avg_num_frames_leaked =
7931 		wlan_le32_to_cpu(fw_ifaceStat->leaky_ap_avg_num_frames_leaked);
7932 	iface_stat->leaky_ap_guard_time =
7933 		wlan_le32_to_cpu(fw_ifaceStat->leaky_ap_guard_time);
7934 
7935 	/* Value of iface_stat should be Reaccumulate by each peer */
7936 	iface_stat->mgmt_rx = wlan_le32_to_cpu(fw_ifaceStat->mgmt_rx);
7937 	iface_stat->mgmt_action_rx =
7938 		wlan_le32_to_cpu(fw_ifaceStat->mgmt_action_rx);
7939 	iface_stat->mgmt_action_tx =
7940 		wlan_le32_to_cpu(fw_ifaceStat->mgmt_action_tx);
7941 
7942 	iface_stat->rssi_mgmt = wlan_le32_to_cpu(fw_ifaceStat->rssi_mgmt);
7943 	iface_stat->rssi_data = wlan_le32_to_cpu(fw_ifaceStat->rssi_data);
7944 	iface_stat->rssi_ack = wlan_le32_to_cpu(fw_ifaceStat->rssi_ack);
7945 
7946 	for (i = WMM_AC_BK; i <= WMM_AC_VO; i++) {
7947 		iface_stat->ac[i].ac = i;
7948 		iface_stat->ac[i].tx_mpdu =
7949 			wlan_le32_to_cpu(fw_ifaceStat->ac[i].tx_mpdu);
7950 		iface_stat->ac[i].rx_mpdu =
7951 			wlan_le32_to_cpu(fw_ifaceStat->ac[i].rx_mpdu);
7952 		iface_stat->ac[i].tx_mcast =
7953 			wlan_le32_to_cpu(fw_ifaceStat->ac[i].tx_mcast);
7954 		iface_stat->ac[i].rx_mcast =
7955 			wlan_le32_to_cpu(fw_ifaceStat->ac[i].rx_mcast);
7956 		iface_stat->ac[i].rx_ampdu =
7957 			wlan_le32_to_cpu(fw_ifaceStat->ac[i].rx_ampdu);
7958 		iface_stat->ac[i].tx_ampdu =
7959 			wlan_le32_to_cpu(fw_ifaceStat->ac[i].tx_ampdu);
7960 		iface_stat->ac[i].mpdu_lost =
7961 			wlan_le32_to_cpu(fw_ifaceStat->ac[i].mpdu_lost);
7962 		iface_stat->ac[i].retries =
7963 			wlan_le32_to_cpu(fw_ifaceStat->ac[i].retries);
7964 		iface_stat->ac[i].retries_short =
7965 			wlan_le32_to_cpu(fw_ifaceStat->ac[i].retries_short);
7966 		iface_stat->ac[i].retries_long =
7967 			wlan_le32_to_cpu(fw_ifaceStat->ac[i].retries_long);
7968 		iface_stat->ac[i].contention_time_min = wlan_le32_to_cpu(
7969 			fw_ifaceStat->ac[i].contention_time_min);
7970 		iface_stat->ac[i].contention_time_max = wlan_le32_to_cpu(
7971 			fw_ifaceStat->ac[i].contention_time_max);
7972 		iface_stat->ac[i].contention_time_avg = wlan_le32_to_cpu(
7973 			fw_ifaceStat->ac[i].contention_time_avg);
7974 		iface_stat->ac[i].contention_num_samples = wlan_le32_to_cpu(
7975 			fw_ifaceStat->ac[i].contention_num_samples);
7976 	}
7977 
7978 	/* LL_STAT V3: STA-solution: support maxium 1 peers for AP*/
7979 	iface_stat->num_peers = wlan_le32_to_cpu(fw_ifaceStat->num_peers);
7980 	for (peerIdx = 0; peerIdx < iface_stat->num_peers; peerIdx++) {
7981 		iface_stat->peer_info[peerIdx].type =
7982 			fw_ifaceStat->peer_info[peerIdx].type;
7983 		memcpy_ext(priv->adapter,
7984 			   iface_stat->peer_info[peerIdx].peer_mac_address,
7985 			   fw_ifaceStat->peer_info[peerIdx].peer_mac_address,
7986 			   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
7987 		iface_stat->peer_info[peerIdx].capabilities = wlan_le32_to_cpu(
7988 			fw_ifaceStat->peer_info[peerIdx].capabilities);
7989 		iface_stat->peer_info[peerIdx].num_rate = wlan_le32_to_cpu(
7990 			fw_ifaceStat->peer_info[peerIdx].num_rate);
7991 
7992 		PRINTM(MINFO,
7993 		       "bitrate  tx_mpdu  rx_mpdu  mpdu_lost retries retries_short retries_long\n");
7994 		for (rate_idx = 0;
7995 		     rate_idx < iface_stat->peer_info[peerIdx].num_rate;
7996 		     rate_idx++) {
7997 			wlan_fill_hal_wifi_rate(priv,
7998 						&fw_ifaceStat
7999 							 ->peer_info[peerIdx]
8000 							 .rate_stats[rate_idx]
8001 							 .rate,
8002 						&iface_stat->peer_info[peerIdx]
8003 							 .rate_stats[rate_idx]
8004 							 .rate);
8005 
8006 			iface_stat->peer_info[peerIdx]
8007 				.rate_stats[rate_idx]
8008 				.tx_mpdu = wlan_le32_to_cpu(
8009 				fw_ifaceStat->peer_info[peerIdx]
8010 					.rate_stats[rate_idx]
8011 					.tx_mpdu);
8012 			iface_stat->peer_info[peerIdx]
8013 				.rate_stats[rate_idx]
8014 				.rx_mpdu = wlan_le32_to_cpu(
8015 				fw_ifaceStat->peer_info[peerIdx]
8016 					.rate_stats[rate_idx]
8017 					.rx_mpdu);
8018 			iface_stat->peer_info[peerIdx]
8019 				.rate_stats[rate_idx]
8020 				.mpdu_lost = wlan_le32_to_cpu(
8021 				fw_ifaceStat->peer_info[peerIdx]
8022 					.rate_stats[rate_idx]
8023 					.mpdu_lost);
8024 			iface_stat->peer_info[peerIdx]
8025 				.rate_stats[rate_idx]
8026 				.retries = wlan_le32_to_cpu(
8027 				fw_ifaceStat->peer_info[peerIdx]
8028 					.rate_stats[rate_idx]
8029 					.retries);
8030 			iface_stat->peer_info[peerIdx]
8031 				.rate_stats[rate_idx]
8032 				.retries_short = wlan_le32_to_cpu(
8033 				fw_ifaceStat->peer_info[peerIdx]
8034 					.rate_stats[rate_idx]
8035 					.retries_short);
8036 			iface_stat->peer_info[peerIdx]
8037 				.rate_stats[rate_idx]
8038 				.retries_long = wlan_le32_to_cpu(
8039 				fw_ifaceStat->peer_info[peerIdx]
8040 					.rate_stats[rate_idx]
8041 					.retries_long);
8042 			PRINTM(MDAT_D,
8043 			       "0x%x  0x%x  0x%x  0x%x  0x%x  0x%x  0x%x\n",
8044 			       iface_stat->peer_info[peerIdx]
8045 				       .rate_stats[rate_idx]
8046 				       .rate.bitrate,
8047 			       iface_stat->peer_info[peerIdx]
8048 				       .rate_stats[rate_idx]
8049 				       .tx_mpdu,
8050 			       iface_stat->peer_info[peerIdx]
8051 				       .rate_stats[rate_idx]
8052 				       .rx_mpdu,
8053 			       iface_stat->peer_info[peerIdx]
8054 				       .rate_stats[rate_idx]
8055 				       .mpdu_lost,
8056 			       iface_stat->peer_info[peerIdx]
8057 				       .rate_stats[rate_idx]
8058 				       .retries,
8059 			       iface_stat->peer_info[peerIdx]
8060 				       .rate_stats[rate_idx]
8061 				       .retries_short,
8062 			       iface_stat->peer_info[peerIdx]
8063 				       .rate_stats[rate_idx]
8064 				       .retries_long);
8065 		}
8066 	}
8067 }
8068 
8069 /**
8070  *  @brief This function handles the command response of get_link_statistic
8071  *
8072  *  @param pmpriv       A pointer to mlan_private structure
8073  *  @param resp         A pointer to HostCmd_DS_COMMAND
8074  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
8075  *
8076  *  @return             MLAN_STATUS_SUCCESS
8077  */
wlan_ret_get_link_statistic(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)8078 mlan_status wlan_ret_get_link_statistic(pmlan_private pmpriv,
8079 					HostCmd_DS_COMMAND *resp,
8080 					mlan_ioctl_req *pioctl_buf)
8081 {
8082 	mlan_ds_get_info *info;
8083 	t_u8 *link_statistic = MNULL;
8084 	t_u16 action = wlan_le16_to_cpu(resp->params.get_link_statistic.action);
8085 
8086 	ENTER();
8087 
8088 	if (pioctl_buf) {
8089 		info = (mlan_ds_get_info *)pioctl_buf->pbuf;
8090 		link_statistic = info->param.link_statistic;
8091 
8092 		switch (action) {
8093 		case HostCmd_ACT_GEN_GET:
8094 			wlan_fill_link_statistic(pmpriv, link_statistic, resp);
8095 			break;
8096 		case HostCmd_ACT_GEN_SET:
8097 		case HostCmd_ACT_GEN_REMOVE:
8098 			/* nothing to do */
8099 			break;
8100 		default:
8101 			break;
8102 		}
8103 		/* Indicate ioctl complete */
8104 		pioctl_buf->data_read_written =
8105 			BUF_MAXLEN + MLAN_SUB_COMMAND_SIZE;
8106 	}
8107 
8108 	LEAVE();
8109 	return MLAN_STATUS_SUCCESS;
8110 }
8111 
8112 /**
8113  *  @brief This function sends boot sleep configure command to firmware.
8114  *
8115  *  @param pmpriv         A pointer to mlan_private structure
8116  *  @param cmd          Hostcmd ID
8117  *  @param cmd_action   Command action
8118  *  @param pdata_buf    A void pointer to information buffer
8119  *  @return             MLAN_STATUS_SUCCESS/ MLAN_STATUS_FAILURE
8120  */
wlan_cmd_boot_sleep(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)8121 mlan_status wlan_cmd_boot_sleep(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
8122 				t_u16 cmd_action, t_void *pdata_buf)
8123 {
8124 	HostCmd_DS_BOOT_SLEEP *boot_sleep = MNULL;
8125 	t_u16 enable = *(t_u16 *)pdata_buf;
8126 
8127 	ENTER();
8128 
8129 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_BOOT_SLEEP);
8130 	boot_sleep = &cmd->params.boot_sleep;
8131 	boot_sleep->action = wlan_cpu_to_le16(cmd_action);
8132 	boot_sleep->enable = wlan_cpu_to_le16(enable);
8133 
8134 	cmd->size = S_DS_GEN + sizeof(HostCmd_DS_BOOT_SLEEP);
8135 
8136 	LEAVE();
8137 	return MLAN_STATUS_SUCCESS;
8138 }
8139 
8140 /**
8141  *  @brief This function handles the command response of boot sleep cfg
8142  *
8143  *  @param pmpriv       A pointer to mlan_private structure
8144  *  @param resp         A pointer to HostCmd_DS_COMMAND
8145  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
8146  *
8147  *  @return        MLAN_STATUS_SUCCESS
8148  */
wlan_ret_boot_sleep(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)8149 mlan_status wlan_ret_boot_sleep(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
8150 				mlan_ioctl_req *pioctl_buf)
8151 {
8152 	HostCmd_DS_BOOT_SLEEP *boot_sleep = &resp->params.boot_sleep;
8153 	mlan_ds_misc_cfg *cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
8154 
8155 	ENTER();
8156 
8157 	cfg->param.boot_sleep = wlan_le16_to_cpu(boot_sleep->enable);
8158 	PRINTM(MCMND, "boot sleep cfg status %u", cfg->param.boot_sleep);
8159 
8160 	LEAVE();
8161 	return MLAN_STATUS_SUCCESS;
8162 }
8163 
8164 #if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
8165 
8166 /**
8167  *  @brief This function handles send crypto command
8168  *
8169  *  @param pmpriv         A pointer to mlan_private structure
8170  *  @param cmd          Hostcmd ID
8171  *  @param cmd_action   Command action
8172  *  @param pdata_buf    A void pointer to information buffer
8173  *
8174  *  @return        MLAN_STATUS_SUCCESS
8175  */
wlan_cmd_crypto(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_u16 * pdata_buf)8176 mlan_status wlan_cmd_crypto(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
8177 			    t_u16 cmd_action, t_u16 *pdata_buf)
8178 {
8179 	HostCmd_DS_CRYPTO *cry_cmd = &cmd->params.crypto_cmd;
8180 	mlan_ds_sup_cfg *cfg = (mlan_ds_sup_cfg *)pdata_buf;
8181 #if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
8182 	subcmd_prf_hmac_sha1_t *prf_hmac_sha1 = MNULL;
8183 	subcmd_hmac_sha1_t *hmac_sha1 = MNULL;
8184 	subcmd_hmac_sha256_t *hmac_sha256 = MNULL;
8185 	subcmd_sha256_t *sha256 = MNULL;
8186 	subcmd_rijndael_t *rijndael = MNULL;
8187 	subcmd_rc4_t *rc4 = MNULL;
8188 	subcmd_md5_t *md5 = MNULL;
8189 	subcmd_mrvl_f_t *mrvl_f = MNULL;
8190 	subcmd_sha256_kdf_t *sha256_kdf = MNULL;
8191 	t_u8 *ptlv = MNULL;
8192 	t_u8 tlv_bitmap = 0;
8193 	t_u32 i = 0;
8194 #endif
8195 	ENTER();
8196 
8197 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_CRYPTO);
8198 	cmd->size = S_DS_GEN + sizeof(HostCmd_DS_CRYPTO);
8199 	cry_cmd->action = wlan_cpu_to_le16(cmd_action);
8200 	cry_cmd->subCmdCode = cfg->sub_command;
8201 	switch (cfg->sub_command) {
8202 #if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
8203 	case HostCmd_CMD_CRYPTO_SUBCMD_PRF_HMAC_SHA1:
8204 		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
8205 			     BIT_TLV_TYPE_CRYPTO_KEY_PREFIX |
8206 			     BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
8207 		/* set subcmd start */
8208 		prf_hmac_sha1 = (subcmd_prf_hmac_sha1_t *)cry_cmd->subCmd;
8209 		prf_hmac_sha1->output_len = cfg->output_len;
8210 		/* set tlv start */
8211 		ptlv = prf_hmac_sha1->tlv;
8212 		cmd->size += sizeof(subcmd_prf_hmac_sha1_t);
8213 		break;
8214 	case HostCmd_CMD_CRYPTO_SUBCMD_HMAC_SHA1:
8215 		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
8216 			     BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
8217 		/* set subcmd start */
8218 		hmac_sha1 = (subcmd_hmac_sha1_t *)cry_cmd->subCmd;
8219 		hmac_sha1->output_len = cfg->output_len;
8220 		hmac_sha1->data_blks_nr = cfg->data_blks_nr;
8221 		/* set tlv start */
8222 		ptlv = hmac_sha1->tlv;
8223 		cmd->size += sizeof(subcmd_hmac_sha1_t);
8224 		break;
8225 	case HostCmd_CMD_CRYPTO_SUBCMD_HMAC_SHA256:
8226 		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
8227 			     BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
8228 		/* set subcmd start */
8229 		hmac_sha256 = (subcmd_hmac_sha256_t *)cry_cmd->subCmd;
8230 		hmac_sha256->output_len = cfg->output_len;
8231 		hmac_sha256->data_blks_nr = cfg->data_blks_nr;
8232 		/* set tlv start */
8233 		ptlv = hmac_sha256->tlv;
8234 		cmd->size += sizeof(subcmd_hmac_sha256_t);
8235 		break;
8236 	case HostCmd_CMD_CRYPTO_SUBCMD_SHA256:
8237 		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
8238 		/* set subcmd start */
8239 		sha256 = (subcmd_sha256_t *)cry_cmd->subCmd;
8240 		sha256->output_len = cfg->output_len;
8241 		sha256->data_blks_nr = cfg->data_blks_nr;
8242 		/* set tlv start */
8243 		ptlv = sha256->tlv;
8244 		cmd->size += sizeof(subcmd_sha256_t);
8245 		break;
8246 	case HostCmd_CMD_CRYPTO_SUBCMD_RIJNDAEL:
8247 		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
8248 			     BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
8249 		/* set subcmd start */
8250 		rijndael = (subcmd_rijndael_t *)cry_cmd->subCmd;
8251 		rijndael->sub_action_code = cfg->sub_action_code;
8252 		rijndael->output_len = cfg->output_len;
8253 		/* set tlv start */
8254 		ptlv = rijndael->tlv;
8255 		cmd->size += sizeof(subcmd_rijndael_t);
8256 		break;
8257 	case HostCmd_CMD_CRYPTO_SUBCMD_RC4:
8258 		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
8259 			     BIT_TLV_TYPE_CRYPTO_KEY_IV |
8260 			     BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
8261 		/* set subcmd start */
8262 		rc4 = (subcmd_rc4_t *)cry_cmd->subCmd;
8263 		rc4->skip_bytes = cfg->skip_bytes;
8264 		rc4->output_len = cfg->output_len;
8265 		/* set tlv start */
8266 		ptlv = rc4->tlv;
8267 		cmd->size += sizeof(subcmd_rc4_t);
8268 		break;
8269 	case HostCmd_CMD_CRYPTO_SUBCMD_MD5:
8270 		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
8271 			     BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
8272 		/* set subcmd start */
8273 		md5 = (subcmd_md5_t *)cry_cmd->subCmd;
8274 		md5->output_len = cfg->output_len;
8275 		/* set tlv start */
8276 		ptlv = md5->tlv;
8277 		cmd->size += sizeof(subcmd_md5_t);
8278 		break;
8279 	case HostCmd_CMD_CRYPTO_SUBCMD_MRVL_F:
8280 		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
8281 			     BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
8282 		/* set subcmd start */
8283 		mrvl_f = (subcmd_mrvl_f_t *)cry_cmd->subCmd;
8284 		mrvl_f->iterations = cfg->iteration;
8285 		mrvl_f->count = cfg->count;
8286 		mrvl_f->output_len = cfg->output_len;
8287 		/* set tlv start */
8288 		ptlv = mrvl_f->tlv;
8289 		cmd->size += sizeof(subcmd_mrvl_f_t);
8290 		break;
8291 	case HostCmd_CMD_CRYPTO_SUBCMD_SHA256_KDF:
8292 		tlv_bitmap = BIT_TLV_TYPE_CRYPTO_KEY |
8293 			     BIT_TLV_TYPE_CRYPTO_KEY_PREFIX |
8294 			     BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK;
8295 		/* set subcmd start */
8296 		sha256_kdf = (subcmd_sha256_kdf_t *)cry_cmd->subCmd;
8297 		sha256_kdf->output_len = cfg->output_len;
8298 		/* set tlv start */
8299 		ptlv = sha256_kdf->tlv;
8300 		cmd->size += sizeof(subcmd_sha256_kdf_t);
8301 		break;
8302 #endif
8303 	default:
8304 		break;
8305 	}
8306 #if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
8307 	/* add tlv */
8308 	if (tlv_bitmap & BIT_TLV_TYPE_CRYPTO_KEY) {
8309 		((MrvlIEParamSet_t *)ptlv)->Type =
8310 			wlan_cpu_to_le16(TLV_TYPE_CRYPTO_KEY);
8311 		((MrvlIEParamSet_t *)ptlv)->Length =
8312 			wlan_cpu_to_le16(cfg->key_len);
8313 		memcpy_ext(pmpriv->adapter,
8314 			   (t_u8 *)ptlv + sizeof(MrvlIEParamSet_t), cfg->key,
8315 			   cfg->key_len, cfg->key_len);
8316 		cmd->size += cfg->key_len + sizeof(MrvlIEParamSet_t);
8317 		ptlv += cfg->key_len + sizeof(MrvlIEParamSet_t);
8318 	}
8319 
8320 	if (tlv_bitmap & BIT_TLV_TYPE_CRYPTO_KEY_PREFIX) {
8321 		((MrvlIEParamSet_t *)ptlv)->Type =
8322 			wlan_cpu_to_le16(TLV_TYPE_CRYPTO_KEY_PREFIX);
8323 		((MrvlIEParamSet_t *)ptlv)->Length =
8324 			wlan_cpu_to_le16(cfg->key_prefix_len);
8325 		memcpy_ext(pmpriv->adapter, ptlv + sizeof(MrvlIEParamSet_t),
8326 			   cfg->key_prefix, cfg->key_prefix_len,
8327 			   cfg->key_prefix_len);
8328 		cmd->size += cfg->key_prefix_len + sizeof(MrvlIEParamSet_t);
8329 		ptlv += cfg->key_prefix_len + sizeof(MrvlIEParamSet_t);
8330 	}
8331 
8332 	if (tlv_bitmap & BIT_TLV_TYPE_CRYPTO_KEY_IV) {
8333 		((MrvlIEParamSet_t *)ptlv)->Type =
8334 			wlan_cpu_to_le16(TLV_TYPE_CRYPTO_KEY_IV);
8335 		((MrvlIEParamSet_t *)ptlv)->Length =
8336 			wlan_cpu_to_le16(cfg->key_iv_len);
8337 		memcpy_ext(pmpriv->adapter, ptlv + sizeof(MrvlIEParamSet_t),
8338 			   cfg->key_iv, cfg->key_iv_len, cfg->key_iv_len);
8339 		cmd->size += cfg->key_iv_len + sizeof(MrvlIEParamSet_t);
8340 		ptlv += cfg->key_iv_len + sizeof(MrvlIEParamSet_t);
8341 	}
8342 
8343 	if (tlv_bitmap & BIT_TLV_TYPE_CRYPTO_KEY_DATA_BLK) {
8344 		t_u16 data_blk_len = 0;
8345 		t_u8 *pdata_blk = MNULL;
8346 		for (i = 0; i < cfg->data_blks_nr; i++) {
8347 			data_blk_len = *(cfg->key_data_blk_len + i);
8348 			pdata_blk = *(cfg->key_data_blk + i);
8349 			((MrvlIEParamSet_t *)ptlv)->Type =
8350 				wlan_cpu_to_le16(TLV_TYPE_CRYPTO_KEY_DATA_BLK);
8351 			((MrvlIEParamSet_t *)ptlv)->Length =
8352 				wlan_cpu_to_le16(data_blk_len);
8353 			memcpy_ext(pmpriv->adapter,
8354 				   ptlv + sizeof(MrvlIEParamSet_t), pdata_blk,
8355 				   data_blk_len, data_blk_len);
8356 			cmd->size += data_blk_len + sizeof(MrvlIEParamSet_t);
8357 			ptlv += data_blk_len + sizeof(MrvlIEParamSet_t);
8358 		}
8359 	}
8360 #endif
8361 	HEXDUMP("HostCmd_DS_COMMAND wlan_cmd_crypto", cmd, cmd->size);
8362 
8363 	cmd->size = wlan_cpu_to_le16(cmd->size);
8364 	LEAVE();
8365 	return MLAN_STATUS_SUCCESS;
8366 }
8367 
8368 /**
8369  *  @brief This function handles the command response of crypto command
8370  *
8371  *  @param pmpriv       A pointer to mlan_private structure
8372  *  @param resp         A pointer to HostCmd_DS_COMMAND
8373  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
8374  *
8375  *  @return        MLAN_STATUS_SUCCESS
8376  */
wlan_ret_crypto(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)8377 mlan_status wlan_ret_crypto(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
8378 			    mlan_ioctl_req *pioctl_buf)
8379 {
8380 	HostCmd_DS_CRYPTO *crypto_cmd = &resp->params.crypto_cmd;
8381 #if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
8382 	mlan_adapter *pmadapter = pmpriv->adapter;
8383 	mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
8384 	mlan_ds_sup_cfg *cfg = (mlan_ds_sup_cfg *)pioctl_buf->pbuf;
8385 #endif
8386 
8387 	ENTER();
8388 #if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
8389 	if (!cfg) {
8390 		PRINTM(MERROR, "wlan_ret_crypto cfg is null \n");
8391 		goto done;
8392 	}
8393 	if (resp->result == HostCmd_RESULT_OK) {
8394 		/* copy the result */
8395 		memcpy_ext(pmpriv->adapter, cfg->output,
8396 			   (t_u8 *)crypto_cmd + sizeof(HostCmd_DS_CRYPTO) +
8397 				   sizeof(cfg->output_len),
8398 			   cfg->output_len, cfg->output_len);
8399 	}
8400 
8401 	/* Prevent the ioctl from completing when the cmd is freed */
8402 	if (cfg->call_back) {
8403 		pmadapter->curr_cmd->pioctl_buf = MNULL;
8404 		/* trigger wait q */
8405 		pcb->moal_notify_hostcmd_complete(pmadapter->pmoal_handle,
8406 						  pmpriv->bss_index);
8407 	}
8408 #endif
8409 done:
8410 	LEAVE();
8411 	return MLAN_STATUS_SUCCESS;
8412 }
8413 #endif
8414 
8415 /**
8416  *  @brief This function prepares command of mac_address.
8417  *
8418  *  @param pmpriv       A pointer to mlan_private structure
8419  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
8420  *  @param cmd_action   The action: GET or SET
8421  *
8422  *  @return             MLAN_STATUS_SUCCESS
8423  */
wlan_cmd_802_11_mac_address(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action)8424 mlan_status wlan_cmd_802_11_mac_address(pmlan_private pmpriv,
8425 					HostCmd_DS_COMMAND *cmd,
8426 					t_u16 cmd_action)
8427 {
8428 	ENTER();
8429 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS);
8430 	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_MAC_ADDRESS) +
8431 				     S_DS_GEN);
8432 	cmd->result = 0;
8433 
8434 	cmd->params.mac_addr.action = wlan_cpu_to_le16(cmd_action);
8435 
8436 	if (cmd_action == HostCmd_ACT_GEN_SET) {
8437 		memcpy_ext(pmpriv->adapter, cmd->params.mac_addr.mac_addr,
8438 			   pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH,
8439 			   MLAN_MAC_ADDR_LENGTH);
8440 		/* HEXDUMP("SET_CMD: MAC ADDRESS-", priv->CurrentAddr, 6); */
8441 	}
8442 	LEAVE();
8443 	return MLAN_STATUS_SUCCESS;
8444 }
8445 
8446 /**
8447  *  @brief This function handles the command response of mac_address
8448  *
8449  *  @param pmpriv       A pointer to mlan_private structure
8450  *  @param resp         A pointer to HostCmd_DS_COMMAND
8451  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
8452  *
8453  *  @return             MLAN_STATUS_SUCCESS
8454  */
wlan_ret_802_11_mac_address(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)8455 mlan_status wlan_ret_802_11_mac_address(pmlan_private pmpriv,
8456 					HostCmd_DS_COMMAND *resp,
8457 					mlan_ioctl_req *pioctl_buf)
8458 {
8459 	HostCmd_DS_802_11_MAC_ADDRESS *pmac_addr = &resp->params.mac_addr;
8460 	mlan_ds_bss *bss = MNULL;
8461 
8462 	ENTER();
8463 
8464 	memcpy_ext(pmpriv->adapter, pmpriv->curr_addr, pmac_addr->mac_addr,
8465 		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
8466 
8467 	PRINTM(MINFO, "MAC address: " MACSTR "\n", MAC2STR(pmpriv->curr_addr));
8468 	if (pioctl_buf) {
8469 		bss = (mlan_ds_bss *)pioctl_buf->pbuf;
8470 		memcpy_ext(pmpriv->adapter, &bss->param.mac_addr,
8471 			   pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH,
8472 			   MLAN_MAC_ADDR_LENGTH);
8473 		pioctl_buf->data_read_written =
8474 			MLAN_MAC_ADDR_LENGTH + MLAN_SUB_COMMAND_SIZE;
8475 	}
8476 	LEAVE();
8477 	return MLAN_STATUS_SUCCESS;
8478 }
8479 
8480 /**
8481  *  @brief This function prepares command of Rx abort cfg
8482  *
8483  *  @param pmpriv      A pointer to mlan_private structure
8484  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
8485  *  @param cmd_action   the action: GET or SET
8486  *  @param pdata_buf    A pointer to data buffer
8487  *  @return         MLAN_STATUS_SUCCESS
8488  */
wlan_cmd_rxabortcfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)8489 mlan_status wlan_cmd_rxabortcfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
8490 				t_u16 cmd_action, t_void *pdata_buf)
8491 {
8492 	HostCmd_DS_CMD_RX_ABORT_CFG *cfg_cmd =
8493 		(HostCmd_DS_CMD_RX_ABORT_CFG *)&cmd->params.rx_abort_cfg;
8494 	mlan_ds_misc_rx_abort_cfg *cfg = (mlan_ds_misc_rx_abort_cfg *)pdata_buf;
8495 
8496 	ENTER();
8497 
8498 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RX_ABORT_CFG);
8499 	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_RX_ABORT_CFG) +
8500 				     S_DS_GEN);
8501 	cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
8502 
8503 	if (cmd_action == HostCmd_ACT_GEN_SET) {
8504 		cfg_cmd->enable = (t_u8)cfg->enable;
8505 		cfg_cmd->rssi_threshold = (t_s8)cfg->rssi_threshold;
8506 	}
8507 
8508 	LEAVE();
8509 	return MLAN_STATUS_SUCCESS;
8510 }
8511 
8512 /**
8513  *  @brief This function handles the command response of Rx Abort Cfg
8514  *
8515  *  @param pmpriv       A pointer to mlan_private structure
8516  *  @param resp         A pointer to HostCmd_DS_COMMAND
8517  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
8518  *
8519  *  @return             MLAN_STATUS_SUCCESS
8520  */
wlan_ret_rxabortcfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)8521 mlan_status wlan_ret_rxabortcfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
8522 				mlan_ioctl_req *pioctl_buf)
8523 {
8524 	HostCmd_DS_CMD_RX_ABORT_CFG *cfg_cmd =
8525 		(HostCmd_DS_CMD_RX_ABORT_CFG *)&resp->params.rx_abort_cfg;
8526 	mlan_ds_misc_cfg *misc_cfg = MNULL;
8527 
8528 	ENTER();
8529 
8530 	if (pioctl_buf) {
8531 		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
8532 		misc_cfg->param.rx_abort_cfg.enable = (t_u8)cfg_cmd->enable;
8533 		misc_cfg->param.rx_abort_cfg.rssi_threshold =
8534 			(t_s8)cfg_cmd->rssi_threshold;
8535 	}
8536 	LEAVE();
8537 	return MLAN_STATUS_SUCCESS;
8538 }
8539 
8540 /**
8541  *  @brief This function prepares command of Rx abort cfg ext
8542  *
8543  *  @param pmpriv      A pointer to mlan_private structure
8544  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
8545  *  @param cmd_action   the action: GET or SET
8546  *  @param pdata_buf    A pointer to data buffer
8547  *  @return         MLAN_STATUS_SUCCESS
8548  */
wlan_cmd_rxabortcfg_ext(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)8549 mlan_status wlan_cmd_rxabortcfg_ext(pmlan_private pmpriv,
8550 				    HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
8551 				    t_void *pdata_buf)
8552 {
8553 	HostCmd_DS_CMD_RX_ABORT_CFG_EXT *cfg_cmd =
8554 		(HostCmd_DS_CMD_RX_ABORT_CFG_EXT *)&cmd->params.rx_abort_cfg_ext;
8555 	mlan_ds_misc_rx_abort_cfg_ext *cfg =
8556 		(mlan_ds_misc_rx_abort_cfg_ext *)pdata_buf;
8557 
8558 	ENTER();
8559 
8560 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RX_ABORT_CFG_EXT);
8561 	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_RX_ABORT_CFG_EXT) +
8562 				     S_DS_GEN);
8563 	cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
8564 
8565 	if (cmd_action == HostCmd_ACT_GEN_SET) {
8566 		cfg_cmd->enable = (t_u8)cfg->enable;
8567 		cfg_cmd->rssi_margin = (t_s8)cfg->rssi_margin;
8568 		cfg_cmd->ceil_rssi_threshold = (t_s8)cfg->ceil_rssi_threshold;
8569 	}
8570 
8571 	LEAVE();
8572 	return MLAN_STATUS_SUCCESS;
8573 }
8574 
8575 /**
8576  *  @brief This function handles the command response of Rx Abort Cfg ext
8577  *
8578  *  @param pmpriv       A pointer to mlan_private structure
8579  *  @param resp         A pointer to HostCmd_DS_COMMAND
8580  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
8581  *
8582  *  @return             MLAN_STATUS_SUCCESS
8583  */
wlan_ret_rxabortcfg_ext(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)8584 mlan_status wlan_ret_rxabortcfg_ext(pmlan_private pmpriv,
8585 				    HostCmd_DS_COMMAND *resp,
8586 				    mlan_ioctl_req *pioctl_buf)
8587 {
8588 	HostCmd_DS_CMD_RX_ABORT_CFG_EXT *cfg_cmd =
8589 		(HostCmd_DS_CMD_RX_ABORT_CFG_EXT *)&resp->params
8590 			.rx_abort_cfg_ext;
8591 	mlan_ds_misc_cfg *misc_cfg = MNULL;
8592 
8593 	ENTER();
8594 
8595 	if (pioctl_buf) {
8596 		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
8597 		misc_cfg->param.rx_abort_cfg_ext.enable = cfg_cmd->enable;
8598 		misc_cfg->param.rx_abort_cfg_ext.rssi_margin =
8599 			cfg_cmd->rssi_margin;
8600 		misc_cfg->param.rx_abort_cfg_ext.ceil_rssi_threshold =
8601 			cfg_cmd->ceil_rssi_threshold;
8602 	}
8603 	LEAVE();
8604 	return MLAN_STATUS_SUCCESS;
8605 }
8606 
8607 /**
8608  * @brief This function sets the hal/phy cfg params
8609  *
8610  * @param pmpriv       A pointer to mlan_private structure
8611  * @param cmd          A pointer to HostCmd_DS_COMMAND structure
8612  * @param cmd_action   The action: GET or SET
8613  * @param pdata_buf    A pointer to data buffer
8614  *
8615  * @return             MLAN_STATUS_SUCCESS
8616  */
wlan_cmd_hal_phy_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_u16 * pdata_buf)8617 mlan_status wlan_cmd_hal_phy_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
8618 				 t_u16 cmd_action, t_u16 *pdata_buf)
8619 {
8620 	HostCmd_DS_HAL_PHY_CFG *hal_phy_cfg_cmd =
8621 		&cmd->params.hal_phy_cfg_params;
8622 	mlan_ds_hal_phy_cfg_params *hal_phy_cfg_params = MNULL;
8623 
8624 	ENTER();
8625 
8626 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_HAL_PHY_CFG);
8627 	cmd->size = sizeof(HostCmd_DS_HAL_PHY_CFG) + S_DS_GEN;
8628 	hal_phy_cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
8629 	hal_phy_cfg_params = (mlan_ds_hal_phy_cfg_params *)pdata_buf;
8630 	hal_phy_cfg_cmd->dot11b_psd_mask_cfg =
8631 		hal_phy_cfg_params->dot11b_psd_mask_cfg;
8632 	cmd->size = wlan_cpu_to_le16(cmd->size);
8633 	LEAVE();
8634 	return MLAN_STATUS_SUCCESS;
8635 }
8636 
8637 /**
8638  *  @brief This function handles the command response of hal_phy_cfg
8639  *
8640  *  @param pmpriv       A pointer to mlan_private structure
8641  *  @param resp         A pointer to HostCmd_DS_COMMAND
8642  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
8643  *
8644  *  @return             MLAN_STATUS_SUCCESS
8645  */
wlan_ret_hal_phy_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)8646 mlan_status wlan_ret_hal_phy_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
8647 				 mlan_ioctl_req *pioctl_buf)
8648 {
8649 	HostCmd_DS_HAL_PHY_CFG *cfg_cmd =
8650 		(HostCmd_DS_HAL_PHY_CFG *)&resp->params.hal_phy_cfg_params;
8651 	mlan_ds_misc_cfg *misc_cfg = MNULL;
8652 
8653 	ENTER();
8654 
8655 	if (pioctl_buf) {
8656 		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
8657 		misc_cfg->param.hal_phy_cfg_params.dot11b_psd_mask_cfg =
8658 			cfg_cmd->dot11b_psd_mask_cfg;
8659 	}
8660 	LEAVE();
8661 	return MLAN_STATUS_SUCCESS;
8662 }
8663 
wlan_cmd_ips_config(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)8664 mlan_status wlan_cmd_ips_config(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
8665 				t_u16 cmd_action, t_void *pdata_buf)
8666 {
8667 	HostCmd_DS_IPS_CONFIG *ips_cfg = MNULL;
8668 	t_u32 enable = *(t_u32 *)pdata_buf;
8669 
8670 	ENTER();
8671 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_IPS_CONFIG);
8672 	ips_cfg = &cmd->params.ips_cfg;
8673 	ips_cfg->enable = wlan_cpu_to_le32(enable);
8674 	cmd->size = S_DS_GEN + sizeof(HostCmd_DS_IPS_CONFIG);
8675 	LEAVE();
8676 	return MLAN_STATUS_SUCCESS;
8677 }
8678 
wlan_ret_ips_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)8679 mlan_status wlan_ret_ips_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
8680 			     mlan_ioctl_req *pioctl_buf)
8681 {
8682 	ENTER();
8683 	LEAVE();
8684 	return MLAN_STATUS_SUCCESS;
8685 }
8686 
8687 /**
8688  *  @brief This function prepares command of Dot11mc unassoc ftm cfg
8689  *
8690  *  @param pmpriv      A pointer to mlan_private structure
8691  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
8692  *  @param cmd_action   the action: GET or SET
8693  *  @param pdata_buf    A pointer to data buffer
8694  *  @return         MLAN_STATUS_SUCCESS
8695  */
wlan_cmd_dot11mc_unassoc_ftm_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)8696 mlan_status wlan_cmd_dot11mc_unassoc_ftm_cfg(pmlan_private pmpriv,
8697 					     HostCmd_DS_COMMAND *cmd,
8698 					     t_u16 cmd_action,
8699 					     t_void *pdata_buf)
8700 {
8701 	HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG *cfg_cmd =
8702 		(HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG *)&cmd->params
8703 			.dot11mc_unassoc_ftm_cfg;
8704 	mlan_ds_misc_dot11mc_unassoc_ftm_cfg *cfg =
8705 		(mlan_ds_misc_dot11mc_unassoc_ftm_cfg *)pdata_buf;
8706 
8707 	ENTER();
8708 
8709 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_DOT11MC_UNASSOC_FTM_CFG);
8710 	cmd->size = wlan_cpu_to_le16(
8711 		sizeof(HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG) + S_DS_GEN);
8712 	cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
8713 
8714 	if (cmd_action == HostCmd_ACT_GEN_SET) {
8715 		cfg_cmd->state = wlan_cpu_to_le16(cfg->state);
8716 	}
8717 
8718 	LEAVE();
8719 	return MLAN_STATUS_SUCCESS;
8720 }
8721 
8722 /**
8723  *  @brief This function handles the command response of Dot11mc unassoc ftm cfg
8724  *
8725  *  @param pmpriv       A pointer to mlan_private structure
8726  *  @param resp         A pointer to HostCmd_DS_COMMAND
8727  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
8728  *
8729  *  @return             MLAN_STATUS_SUCCESS
8730  */
wlan_ret_dot11mc_unassoc_ftm_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)8731 mlan_status wlan_ret_dot11mc_unassoc_ftm_cfg(pmlan_private pmpriv,
8732 					     HostCmd_DS_COMMAND *resp,
8733 					     mlan_ioctl_req *pioctl_buf)
8734 {
8735 	HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG *cfg_cmd =
8736 		(HostCmd_DS_CMD_DOT11MC_UNASSOC_FTM_CFG *)&resp->params
8737 			.dot11mc_unassoc_ftm_cfg;
8738 	mlan_ds_misc_cfg *misc_cfg = MNULL;
8739 
8740 	ENTER();
8741 
8742 	if (pioctl_buf) {
8743 		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
8744 		misc_cfg->param.dot11mc_unassoc_ftm_cfg.state =
8745 			wlan_le16_to_cpu(cfg_cmd->state);
8746 	}
8747 	LEAVE();
8748 	return MLAN_STATUS_SUCCESS;
8749 }
8750 
8751 /**
8752  *  @brief This function prepares command of Tx ampdu prot mode
8753  *
8754  *  @param pmpriv      A pointer to mlan_private structure
8755  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
8756  *  @param cmd_action   the action: GET or SET
8757  *  @param pdata_buf    A pointer to data buffer
8758  *  @return         MLAN_STATUS_SUCCESS
8759  */
wlan_cmd_tx_ampdu_prot_mode(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)8760 mlan_status wlan_cmd_tx_ampdu_prot_mode(pmlan_private pmpriv,
8761 					HostCmd_DS_COMMAND *cmd,
8762 					t_u16 cmd_action, t_void *pdata_buf)
8763 {
8764 	HostCmd_DS_CMD_TX_AMPDU_PROT_MODE *cfg_cmd =
8765 		(HostCmd_DS_CMD_TX_AMPDU_PROT_MODE *)&cmd->params
8766 			.tx_ampdu_prot_mode;
8767 	mlan_ds_misc_tx_ampdu_prot_mode *cfg =
8768 		(mlan_ds_misc_tx_ampdu_prot_mode *)pdata_buf;
8769 
8770 	ENTER();
8771 
8772 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TX_AMPDU_PROT_MODE);
8773 	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_TX_AMPDU_PROT_MODE) +
8774 				     S_DS_GEN);
8775 	cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
8776 
8777 	if (cmd_action == HostCmd_ACT_GEN_SET) {
8778 		cfg_cmd->mode = wlan_cpu_to_le16(cfg->mode);
8779 	}
8780 
8781 	LEAVE();
8782 	return MLAN_STATUS_SUCCESS;
8783 }
8784 
8785 /**
8786  *  @brief This function handles the command response of Tx ampdu prot mode
8787  *
8788  *  @param pmpriv       A pointer to mlan_private structure
8789  *  @param resp         A pointer to HostCmd_DS_COMMAND
8790  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
8791  *
8792  *  @return             MLAN_STATUS_SUCCESS
8793  */
wlan_ret_tx_ampdu_prot_mode(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)8794 mlan_status wlan_ret_tx_ampdu_prot_mode(pmlan_private pmpriv,
8795 					HostCmd_DS_COMMAND *resp,
8796 					mlan_ioctl_req *pioctl_buf)
8797 {
8798 	HostCmd_DS_CMD_TX_AMPDU_PROT_MODE *cfg_cmd =
8799 		(HostCmd_DS_CMD_TX_AMPDU_PROT_MODE *)&resp->params
8800 			.tx_ampdu_prot_mode;
8801 	mlan_ds_misc_cfg *misc_cfg = MNULL;
8802 
8803 	ENTER();
8804 
8805 	if (pioctl_buf) {
8806 		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
8807 		misc_cfg->param.tx_ampdu_prot_mode.mode =
8808 			wlan_le16_to_cpu(cfg_cmd->mode);
8809 	}
8810 	LEAVE();
8811 	return MLAN_STATUS_SUCCESS;
8812 }
8813 
8814 /**
8815  *  @brief This function prepares command of Rate Adapt cfg
8816  *
8817  *  @param pmpriv      A pointer to mlan_private structure
8818  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
8819  *  @param cmd_action   the action: GET or SET
8820  *  @param pdata_buf    A pointer to data buffer
8821  *  @return         MLAN_STATUS_SUCCESS
8822  */
wlan_cmd_rate_adapt_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)8823 mlan_status wlan_cmd_rate_adapt_cfg(pmlan_private pmpriv,
8824 				    HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
8825 				    t_void *pdata_buf)
8826 {
8827 	HostCmd_DS_CMD_RATE_ADAPT_CFG *cfg_cmd =
8828 		(HostCmd_DS_CMD_RATE_ADAPT_CFG *)&cmd->params.rate_adapt_cfg;
8829 	mlan_ds_misc_rate_adapt_cfg *cfg =
8830 		(mlan_ds_misc_rate_adapt_cfg *)pdata_buf;
8831 
8832 	ENTER();
8833 
8834 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RATE_ADAPT_CFG);
8835 	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_RATE_ADAPT_CFG) +
8836 				     S_DS_GEN);
8837 	cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
8838 
8839 	if (cmd_action == HostCmd_ACT_GEN_SET) {
8840 		cfg_cmd->sr_rateadapt = (t_u8)cfg->sr_rateadapt;
8841 		cfg_cmd->ra_low_thresh = (t_u8)cfg->ra_low_thresh;
8842 		cfg_cmd->ra_high_thresh = (t_u8)cfg->ra_high_thresh;
8843 		cfg_cmd->ra_interval = wlan_cpu_to_le16(cfg->ra_interval);
8844 	}
8845 
8846 	LEAVE();
8847 	return MLAN_STATUS_SUCCESS;
8848 }
8849 
8850 /**
8851  *  @brief This function handles the command response of Rate Adapt Cfg
8852  *
8853  *  @param pmpriv       A pointer to mlan_private structure
8854  *  @param resp         A pointer to HostCmd_DS_COMMAND
8855  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
8856  *
8857  *  @return             MLAN_STATUS_SUCCESS
8858  */
wlan_ret_rate_adapt_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)8859 mlan_status wlan_ret_rate_adapt_cfg(pmlan_private pmpriv,
8860 				    HostCmd_DS_COMMAND *resp,
8861 				    mlan_ioctl_req *pioctl_buf)
8862 {
8863 	HostCmd_DS_CMD_RATE_ADAPT_CFG *cfg_cmd =
8864 		(HostCmd_DS_CMD_RATE_ADAPT_CFG *)&resp->params.rate_adapt_cfg;
8865 	mlan_ds_misc_cfg *misc_cfg = MNULL;
8866 
8867 	ENTER();
8868 
8869 	if (pioctl_buf) {
8870 		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
8871 		misc_cfg->param.rate_adapt_cfg.sr_rateadapt =
8872 			(t_u8)cfg_cmd->sr_rateadapt;
8873 		misc_cfg->param.rate_adapt_cfg.ra_low_thresh =
8874 			(t_u8)cfg_cmd->ra_low_thresh;
8875 		misc_cfg->param.rate_adapt_cfg.ra_high_thresh =
8876 			(t_u8)cfg_cmd->ra_high_thresh;
8877 		misc_cfg->param.rate_adapt_cfg.ra_interval =
8878 			wlan_le16_to_cpu(cfg_cmd->ra_interval);
8879 	}
8880 	LEAVE();
8881 	return MLAN_STATUS_SUCCESS;
8882 }
8883 
8884 /**
8885  *  @brief This function prepares command of CCK Desense cfg
8886  *
8887  *  @param pmpriv       A pointer to mlan_private structure
8888  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
8889  *  @param cmd_action   the action: GET or SET
8890  *  @param pdata_buf    A pointer to data buffer
8891  *  @return             MLAN_STATUS_SUCCESS
8892  */
wlan_cmd_cck_desense_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)8893 mlan_status wlan_cmd_cck_desense_cfg(pmlan_private pmpriv,
8894 				     HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
8895 				     t_void *pdata_buf)
8896 {
8897 	HostCmd_DS_CMD_CCK_DESENSE_CFG *cfg_cmd =
8898 		(HostCmd_DS_CMD_CCK_DESENSE_CFG *)&cmd->params.cck_desense_cfg;
8899 	mlan_ds_misc_cck_desense_cfg *cfg =
8900 		(mlan_ds_misc_cck_desense_cfg *)pdata_buf;
8901 
8902 	ENTER();
8903 
8904 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_CCK_DESENSE_CFG);
8905 	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_CCK_DESENSE_CFG) +
8906 				     S_DS_GEN);
8907 	cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
8908 
8909 	if (cmd_action == HostCmd_ACT_GEN_SET) {
8910 		cfg_cmd->mode = wlan_cpu_to_le16(cfg->mode);
8911 		cfg_cmd->margin = (t_s8)cfg->margin;
8912 		cfg_cmd->ceil_thresh = (t_s8)cfg->ceil_thresh;
8913 		cfg_cmd->num_on_intervals = (t_u8)cfg->num_on_intervals;
8914 		cfg_cmd->num_off_intervals = (t_u8)cfg->num_off_intervals;
8915 	}
8916 
8917 	LEAVE();
8918 	return MLAN_STATUS_SUCCESS;
8919 }
8920 
8921 /**
8922  *  @brief This function handles the command response of CCK Desense Cfg
8923  *
8924  *  @param pmpriv       A pointer to mlan_private structure
8925  *  @param resp         A pointer to HostCmd_DS_COMMAND
8926  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
8927  *
8928  *  @return             MLAN_STATUS_SUCCESS
8929  */
wlan_ret_cck_desense_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)8930 mlan_status wlan_ret_cck_desense_cfg(pmlan_private pmpriv,
8931 				     HostCmd_DS_COMMAND *resp,
8932 				     mlan_ioctl_req *pioctl_buf)
8933 {
8934 	HostCmd_DS_CMD_CCK_DESENSE_CFG *cfg_cmd =
8935 		(HostCmd_DS_CMD_CCK_DESENSE_CFG *)&resp->params.cck_desense_cfg;
8936 	mlan_ds_misc_cfg *misc_cfg = MNULL;
8937 
8938 	ENTER();
8939 
8940 	if (pioctl_buf) {
8941 		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
8942 		misc_cfg->param.cck_desense_cfg.mode =
8943 			wlan_le16_to_cpu(cfg_cmd->mode);
8944 		misc_cfg->param.cck_desense_cfg.margin = (t_s8)cfg_cmd->margin;
8945 		misc_cfg->param.cck_desense_cfg.ceil_thresh =
8946 			(t_s8)cfg_cmd->ceil_thresh;
8947 		misc_cfg->param.cck_desense_cfg.num_on_intervals =
8948 			(t_u8)cfg_cmd->num_on_intervals;
8949 		misc_cfg->param.cck_desense_cfg.num_off_intervals =
8950 			(t_u8)cfg_cmd->num_off_intervals;
8951 	}
8952 	LEAVE();
8953 	return MLAN_STATUS_SUCCESS;
8954 }
8955 
8956 /**
8957  *  @brief This function sends dynamic bandwidth command to firmware.
8958  *
8959  *  @param pmpriv         A pointer to mlan_private structure
8960  *  @param cmd          Hostcmd ID
8961  *  @param cmd_action   Command action
8962  *  @param pdata_buf    A void pointer to information buffer
8963  *  @return             N/A
8964  */
wlan_cmd_config_dyn_bw(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)8965 mlan_status wlan_cmd_config_dyn_bw(pmlan_private pmpriv,
8966 				   HostCmd_DS_COMMAND *cmd, t_u16 cmd_action,
8967 				   t_void *pdata_buf)
8968 {
8969 	HostCmd_DS_DYN_BW *dyn_bw_cmd = &cmd->params.dyn_bw;
8970 
8971 	ENTER();
8972 
8973 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_DYN_BW);
8974 	cmd->size = S_DS_GEN + sizeof(HostCmd_DS_DYN_BW);
8975 	dyn_bw_cmd->action = wlan_cpu_to_le16(cmd_action);
8976 	dyn_bw_cmd->dyn_bw = wlan_cpu_to_le16(*(t_u16 *)pdata_buf);
8977 	cmd->size = wlan_cpu_to_le16(cmd->size);
8978 
8979 	LEAVE();
8980 	return MLAN_STATUS_SUCCESS;
8981 }
8982 
8983 /**
8984  *  @brief This function handles the command response of dyn_bw
8985  *
8986  *  @param pmpriv       A pointer to mlan_private structure
8987  *  @param resp         A pointer to HostCmd_DS_COMMAND
8988  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
8989  *
8990  *  @return        MLAN_STATUS_SUCCESS
8991  */
wlan_ret_dyn_bw(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)8992 mlan_status wlan_ret_dyn_bw(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
8993 			    mlan_ioctl_req *pioctl_buf)
8994 {
8995 	mlan_ds_misc_cfg *cfg = MNULL;
8996 	HostCmd_DS_DYN_BW *dyn_bw = &resp->params.dyn_bw;
8997 
8998 	ENTER();
8999 	if (pioctl_buf &&
9000 	    (wlan_le16_to_cpu(dyn_bw->action) == HostCmd_ACT_GEN_GET)) {
9001 		cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
9002 		cfg->param.dyn_bw = wlan_le16_to_cpu(dyn_bw->dyn_bw);
9003 		PRINTM(MCMND, "Get dynamic bandwidth 0x%x\n",
9004 		       cfg->param.dyn_bw);
9005 	}
9006 	LEAVE();
9007 	return MLAN_STATUS_SUCCESS;
9008 }
9009 
9010 /**
9011  *  @brief This function prepares command of CHAN_TRPC_CONFIG
9012  *
9013  *  @param pmpriv       A pointer to mlan_private structure
9014  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
9015  *  @param cmd_action   the action: GET or SET
9016  *  @param pdata_buf    A pointer to data buffer
9017  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
9018  */
wlan_cmd_get_chan_trpc_config(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)9019 mlan_status wlan_cmd_get_chan_trpc_config(pmlan_private pmpriv,
9020 					  HostCmd_DS_COMMAND *cmd,
9021 					  t_u16 cmd_action, t_void *pdata_buf)
9022 {
9023 	HostCmd_DS_CHANNEL_TRPC_CONFIG *trpc_cfg = &cmd->params.ch_trpc_config;
9024 	mlan_ds_misc_chan_trpc_cfg *cfg =
9025 		(mlan_ds_misc_chan_trpc_cfg *)pdata_buf;
9026 
9027 	ENTER();
9028 
9029 	cmd->command = wlan_cpu_to_le16(HostCmd_CHANNEL_TRPC_CONFIG);
9030 	trpc_cfg->action = wlan_cpu_to_le16(cmd_action);
9031 	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CHANNEL_TRPC_CONFIG) +
9032 				     S_DS_GEN);
9033 	trpc_cfg->sub_band = wlan_cpu_to_le16(cfg->sub_band);
9034 	LEAVE();
9035 	return MLAN_STATUS_SUCCESS;
9036 }
9037 /**
9038  *  @brief This function prepares command of LOW_POWER_MODE_CFG
9039  *
9040  *  @param pmpriv       A pointer to mlan_private structure
9041  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
9042  *  @param cmd_action   the action: GET or SET
9043  *  @param pdata_buf    A pointer to data buffer
9044  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
9045  */
wlan_cmd_set_get_low_power_mode_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)9046 mlan_status wlan_cmd_set_get_low_power_mode_cfg(pmlan_private pmpriv,
9047 						HostCmd_DS_COMMAND *cmd,
9048 						t_u16 cmd_action,
9049 						t_void *pdata_buf)
9050 {
9051 	HostCmd_DS_LOW_POWER_MODE_CFG *lpm_cfg = &cmd->params.lpm_cfg;
9052 	t_u16 lpm = *(t_u16 *)pdata_buf;
9053 
9054 	ENTER();
9055 
9056 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_LOW_POWER_MODE_CFG);
9057 	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_LOW_POWER_MODE_CFG) +
9058 				     S_DS_GEN);
9059 	lpm_cfg->action = wlan_cpu_to_le16(cmd_action);
9060 
9061 	if (cmd_action == HostCmd_ACT_GEN_SET)
9062 		lpm_cfg->lpm = wlan_cpu_to_le16(lpm);
9063 
9064 	LEAVE();
9065 	return MLAN_STATUS_SUCCESS;
9066 }
9067 
9068 /**
9069  *  @brief This function handles the command response of low power mode
9070  *
9071  *  @param pmpriv       A pointer to mlan_private structure
9072  *  @param resp         A pointer to HostCmd_DS_COMMAND
9073  *  @param pioctl_buf   A pointer to command buffer
9074  *
9075  *  @return             MLAN_STATUS_SUCCESS
9076 
9077  */
wlan_ret_set_get_low_power_mode_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)9078 mlan_status wlan_ret_set_get_low_power_mode_cfg(pmlan_private pmpriv,
9079 						HostCmd_DS_COMMAND *resp,
9080 						mlan_ioctl_req *pioctl_buf)
9081 {
9082 	mlan_ds_power_cfg *cfg = MNULL;
9083 	HostCmd_DS_LOW_POWER_MODE_CFG *lpm_cfg = &resp->params.lpm_cfg;
9084 
9085 	ENTER();
9086 
9087 	if (pioctl_buf &&
9088 	    (wlan_le16_to_cpu(lpm_cfg->action) == HostCmd_ACT_GEN_GET)) {
9089 		cfg = (mlan_ds_power_cfg *)pioctl_buf->pbuf;
9090 		cfg->param.lpm = wlan_le16_to_cpu(lpm_cfg->lpm);
9091 		PRINTM(MCMND, "Get low power mode %d\n", cfg->param.lpm);
9092 	}
9093 
9094 	LEAVE();
9095 	return MLAN_STATUS_SUCCESS;
9096 }
9097 /**
9098  *  @brief This function handles the command response of
9099  *  packet aggregation
9100  *
9101  *  @param pmpriv       A pointer to mlan_private structure
9102  *  @param resp         A pointer to HostCmd_DS_COMMAND
9103  *  @param pioctl_buf   A pointer to command buffer
9104  *
9105  *  @return             MLAN_STATUS_SUCCESS
9106  */
wlan_ret_get_chan_trpc_config(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)9107 mlan_status wlan_ret_get_chan_trpc_config(pmlan_private pmpriv,
9108 					  HostCmd_DS_COMMAND *resp,
9109 					  mlan_ioctl_req *pioctl_buf)
9110 {
9111 	mlan_ds_misc_cfg *misc = MNULL;
9112 	HostCmd_DS_CHANNEL_TRPC_CONFIG *trpc_cfg = &resp->params.ch_trpc_config;
9113 	mlan_ds_misc_chan_trpc_cfg *cfg = MNULL;
9114 	mlan_adapter *pmadapter = pmpriv->adapter;
9115 
9116 	ENTER();
9117 	if (pioctl_buf) {
9118 		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
9119 		cfg = (mlan_ds_misc_chan_trpc_cfg *)&(misc->param.trpc_cfg);
9120 		cfg->sub_band = wlan_le16_to_cpu(trpc_cfg->sub_band);
9121 		cfg->length = wlan_le16_to_cpu(resp->size);
9122 		memcpy_ext(pmadapter, cfg->trpc_buf, (t_u8 *)resp, cfg->length,
9123 			   sizeof(cfg->trpc_buf));
9124 	}
9125 	LEAVE();
9126 	return MLAN_STATUS_SUCCESS;
9127 }
9128 
9129 /**
9130  *  @brief This function prepares command of mc_aggr_cfg
9131  *
9132  *  @param pmpriv      A pointer to mlan_private structure
9133  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
9134  *  @param cmd_action   the action: GET or SET
9135  *  @param pdata_buf    A pointer to data buffer
9136  *  @return         MLAN_STATUS_SUCCESS
9137  */
wlan_cmd_mc_aggr_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)9138 mlan_status wlan_cmd_mc_aggr_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
9139 				 t_u16 cmd_action, t_void *pdata_buf)
9140 {
9141 	HostCmd_DS_MC_AGGR_CFG *cfg_cmd =
9142 		(HostCmd_DS_MC_AGGR_CFG *)&cmd->params.mc_aggr_cfg;
9143 	mlan_ds_mc_aggr_cfg *cfg = (mlan_ds_mc_aggr_cfg *)pdata_buf;
9144 
9145 	ENTER();
9146 
9147 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MC_AGGR_CFG);
9148 	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_MC_AGGR_CFG) + S_DS_GEN);
9149 	cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
9150 
9151 	cfg_cmd->enable_bitmap = (t_u8)cfg->enable_bitmap;
9152 	cfg_cmd->mask_bitmap = (t_u8)cfg->mask_bitmap;
9153 	cfg_cmd->cts2self_offset = wlan_cpu_to_le16(cfg->cts2self_offset);
9154 	LEAVE();
9155 	return MLAN_STATUS_SUCCESS;
9156 }
9157 
9158 /**
9159  *  @brief This function handles the command response of mc_aggr_cfg
9160  *
9161  *  @param pmpriv       A pointer to mlan_private structure
9162  *  @param resp         A pointer to HostCmd_DS_COMMAND
9163  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
9164  *
9165  *  @return             MLAN_STATUS_SUCCESS
9166  */
wlan_ret_mc_aggr_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)9167 mlan_status wlan_ret_mc_aggr_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
9168 				 mlan_ioctl_req *pioctl_buf)
9169 {
9170 	HostCmd_DS_MC_AGGR_CFG *cfg_cmd =
9171 		(HostCmd_DS_MC_AGGR_CFG *)&resp->params.mc_aggr_cfg;
9172 	mlan_ds_misc_cfg *misc_cfg = MNULL;
9173 
9174 	ENTER();
9175 
9176 	if (pioctl_buf) {
9177 		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
9178 		misc_cfg->param.mc_aggr_cfg.enable_bitmap =
9179 			(t_u8)cfg_cmd->enable_bitmap;
9180 		misc_cfg->param.mc_aggr_cfg.mask_bitmap =
9181 			(t_u8)cfg_cmd->mask_bitmap;
9182 		misc_cfg->param.mc_aggr_cfg.cts2self_offset =
9183 			(t_u8)cfg_cmd->cts2self_offset;
9184 	}
9185 	LEAVE();
9186 	return MLAN_STATUS_SUCCESS;
9187 }
9188 
9189 /**
9190  *  @brief This function prepares command of ch_load
9191  *
9192  *  @param pmpriv      A pointer to mlan_private structure
9193  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
9194  *  @param cmd_action   the action: GET or SET
9195  *  @param pdata_buf    A pointer to data buffer
9196  *  @return         MLAN_STATUS_SUCCESS
9197  */
wlan_cmd_get_ch_load(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)9198 mlan_status wlan_cmd_get_ch_load(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
9199 				 t_u16 cmd_action, t_void *pdata_buf)
9200 {
9201 	HostCmd_DS_GET_CH_LOAD *cfg_cmd =
9202 		(HostCmd_DS_GET_CH_LOAD *)&cmd->params.ch_load;
9203 	mlan_ds_ch_load *cfg = (mlan_ds_ch_load *)pdata_buf;
9204 
9205 	ENTER();
9206 
9207 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_GET_CH_LOAD);
9208 	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_GET_CH_LOAD) + S_DS_GEN);
9209 	cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
9210 	cfg_cmd->ch_load = wlan_cpu_to_le16(cfg->ch_load_param);
9211 	cfg_cmd->noise = wlan_cpu_to_le16(cfg->noise);
9212 	cfg_cmd->rx_quality = wlan_cpu_to_le16(cfg->rx_quality);
9213 	cfg_cmd->duration = wlan_cpu_to_le16(cfg->duration);
9214 	LEAVE();
9215 	return MLAN_STATUS_SUCCESS;
9216 }
9217 
9218 /**
9219  *  @brief This function handles the command response of ch_load
9220  *
9221  *  @param pmpriv       A pointer to mlan_private structure
9222  *  @param resp         A pointer to HostCmd_DS_COMMAND
9223  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
9224  *
9225  *  @return             MLAN_STATUS_SUCCESS
9226  */
wlan_ret_ch_load(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)9227 mlan_status wlan_ret_ch_load(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
9228 			     mlan_ioctl_req *pioctl_buf)
9229 {
9230 	ENTER();
9231 	LEAVE();
9232 	return MLAN_STATUS_SUCCESS;
9233 }
9234 
9235 /**
9236  *  @brief This function prepares command of RANGE_EXT
9237  *
9238  *  @param pmpriv       A pointer to mlan_private structure
9239  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
9240  *  @param cmd_action   the action: GET or SET
9241  *  @param pdata_buf    A pointer to data buffer
9242  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
9243  */
wlan_cmd_range_ext(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)9244 mlan_status wlan_cmd_range_ext(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd,
9245 			       t_u16 cmd_action, t_void *pdata_buf)
9246 {
9247 	HostCmd_DS_RANGE_EXT *range_ext = &cmd->params.range_ext;
9248 	t_u8 mode = *(t_u8 *)pdata_buf;
9249 
9250 	ENTER();
9251 
9252 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RANGE_EXT);
9253 	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_RANGE_EXT) + S_DS_GEN);
9254 	range_ext->action = wlan_cpu_to_le16(cmd_action);
9255 
9256 	if (cmd_action == HostCmd_ACT_GEN_SET)
9257 		range_ext->mode = mode;
9258 
9259 	LEAVE();
9260 	return MLAN_STATUS_SUCCESS;
9261 }
9262 
9263 /**
9264  *  @brief This function handles the command response of RANGE_EXT
9265  *
9266  *  @param pmpriv       A pointer to mlan_private structure
9267  *  @param resp         A pointer to HostCmd_DS_COMMAND
9268  *  @param pioctl_buf   A pointer to command buffer
9269  *
9270  *  @return             MLAN_STATUS_SUCCESS
9271  */
wlan_ret_range_ext(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)9272 mlan_status wlan_ret_range_ext(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp,
9273 			       mlan_ioctl_req *pioctl_buf)
9274 {
9275 	mlan_ds_misc_cfg *misc_cfg = MNULL;
9276 	HostCmd_DS_RANGE_EXT *range_ext = &resp->params.range_ext;
9277 
9278 	ENTER();
9279 
9280 	if (pioctl_buf &&
9281 	    (wlan_le16_to_cpu(range_ext->action) == HostCmd_ACT_GEN_GET)) {
9282 		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
9283 		misc_cfg->param.range_ext_mode = range_ext->mode;
9284 		PRINTM(MCMND, "Get range ext mode %d\n",
9285 		       misc_cfg->param.range_ext_mode);
9286 	}
9287 
9288 	LEAVE();
9289 	return MLAN_STATUS_SUCCESS;
9290 }
9291 
9292 /**
9293  *  @brief This function prepares command of get_sensor_temp
9294  *
9295  *  @param pmpriv      A pointer to mlan_private structure
9296  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
9297  *  @param cmd_action   the action: GET or SET
9298  *  @param pdata_buf    A pointer to data buffer
9299  *  @return         MLAN_STATUS_SUCCESS
9300  */
wlan_cmd_get_sensor_temp(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action)9301 mlan_status wlan_cmd_get_sensor_temp(pmlan_private pmpriv,
9302 				     HostCmd_DS_COMMAND *cmd, t_u16 cmd_action)
9303 {
9304 	ENTER();
9305 
9306 	if (cmd_action != HostCmd_ACT_GEN_GET) {
9307 		PRINTM(MERROR, "wlan_cmd_get_sensor_temp: support GET only.\n");
9308 		LEAVE();
9309 		return MLAN_STATUS_FAILURE;
9310 	}
9311 
9312 	cmd->command = wlan_cpu_to_le16(HostCmd_DS_GET_SENSOR_TEMP);
9313 	cmd->size = wlan_cpu_to_le16(S_DS_GEN + 4);
9314 
9315 	LEAVE();
9316 	return MLAN_STATUS_SUCCESS;
9317 }
9318 /**
9319  *  @brief This function handles the command response of get_sensor_temp
9320  *
9321  *  @param pmpriv       A pointer to mlan_private structure
9322  *  @param resp         A pointer to HostCmd_DS_COMMAND
9323  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
9324  *
9325  *  @return             MLAN_STATUS_SUCCESS
9326  */
wlan_ret_get_sensor_temp(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)9327 mlan_status wlan_ret_get_sensor_temp(pmlan_private pmpriv,
9328 				     HostCmd_DS_COMMAND *resp,
9329 				     mlan_ioctl_req *pioctl_buf)
9330 {
9331 	mlan_ds_misc_cfg *pcfg = MNULL;
9332 	const HostCmd_DS_SENSOR_TEMP *pSensorT = &resp->params.temp_sensor;
9333 
9334 	ENTER();
9335 
9336 	if (pioctl_buf) {
9337 		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
9338 		pcfg->param.sensor_temp.temperature =
9339 			wlan_le32_to_cpu(pSensorT->temperature);
9340 		PRINTM(MCMND, "get SOC temperature %u C \n",
9341 		       pSensorT->temperature);
9342 	}
9343 
9344 	LEAVE();
9345 	return MLAN_STATUS_SUCCESS;
9346 }
9347