xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/mvl88w8977/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  *  Copyright (C) 2009-2017, Marvell International Ltd.
7  *
8  *  This software file (the "File") is distributed by Marvell International
9  *  Ltd. under the terms of the GNU General Public License Version 2, June 1991
10  *  (the "License").  You may use, redistribute and/or modify this File in
11  *  accordance with the terms and conditions of the License, a copy of which
12  *  is available by writing to the Free Software Foundation, Inc.,
13  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14  *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15  *
16  *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17  *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18  *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
19  *  this warranty disclaimer.
20  */
21 
22 /*************************************************************
23 Change Log:
24     05/12/2009: initial version
25 ************************************************************/
26 #include "mlan.h"
27 #ifdef STA_SUPPORT
28 #include "mlan_join.h"
29 #endif
30 #include "mlan_util.h"
31 #include "mlan_fw.h"
32 #include "mlan_main.h"
33 #include "mlan_wmm.h"
34 #include "mlan_11n.h"
35 #include "mlan_11h.h"
36 #include "mlan_sdio.h"
37 
38 /********************************************************
39 			Local Variables
40 ********************************************************/
41 
42 /*******************************************************
43 			Global Variables
44 ********************************************************/
45 
46 /********************************************************
47 			Local Functions
48 ********************************************************/
49 #ifdef STA_SUPPORT
50 /**
51  *  @brief This function inserts scan command node to scan_pending_q.
52  *
53  *  @param pmpriv       A pointer to mlan_private structure
54  *  @param pcmd_node    A pointer to cmd_ctrl_node structure
55  *  @return             N/A
56  */
57 static t_void
wlan_queue_scan_cmd(IN mlan_private * pmpriv,IN cmd_ctrl_node * pcmd_node)58 wlan_queue_scan_cmd(IN mlan_private *pmpriv, IN cmd_ctrl_node *pcmd_node)
59 {
60 	mlan_adapter *pmadapter = pmpriv->adapter;
61 
62 	ENTER();
63 
64 	if (pcmd_node == MNULL)
65 		goto done;
66 	pcmd_node->cmd_flag |= CMD_F_SCAN;
67 
68 	util_enqueue_list_tail(pmadapter->pmoal_handle,
69 			       &pmadapter->scan_pending_q,
70 			       (pmlan_linked_list)pcmd_node, MNULL, MNULL);
71 
72 done:
73 	LEAVE();
74 }
75 
76 /**
77  *  @brief Internal function used to flush the scan pending queue
78  *
79  *  @param pmadapter    A pointer to mlan_adapter structure
80  *
81  *  @return             N/A
82  */
83 void
wlan_check_scan_queue(IN pmlan_adapter pmadapter)84 wlan_check_scan_queue(IN pmlan_adapter pmadapter)
85 {
86 	cmd_ctrl_node *pcmd_node = MNULL;
87 	t_u16 num = 0;
88 
89 	pcmd_node =
90 		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
91 						&pmadapter->scan_pending_q,
92 						MNULL, MNULL);
93 	if (!pcmd_node) {
94 		PRINTM(MERROR, "No pending scan command\n");
95 		return;
96 	}
97 	while (pcmd_node != (cmd_ctrl_node *)&pmadapter->scan_pending_q) {
98 		num++;
99 		pcmd_node = pcmd_node->pnext;
100 	}
101 	PRINTM(MERROR, "num_pending_scan=%d\n", num);
102 }
103 #endif
104 
105 /**
106  *  @brief This function will dump the pending commands id
107  *
108  *  @param pmadapter    A pointer to mlan_adapter
109  *
110  *  @return             N/A
111  */
112 static void
wlan_dump_pending_commands(pmlan_adapter pmadapter)113 wlan_dump_pending_commands(pmlan_adapter pmadapter)
114 {
115 	cmd_ctrl_node *pcmd_node = MNULL;
116 	HostCmd_DS_COMMAND *pcmd;
117 
118 	ENTER();
119 	wlan_request_cmd_lock(pmadapter);
120 	pcmd_node =
121 		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
122 						&pmadapter->cmd_pending_q,
123 						MNULL, MNULL);
124 	if (!pcmd_node) {
125 		wlan_release_cmd_lock(pmadapter);
126 		LEAVE();
127 		return;
128 	}
129 	while (pcmd_node != (cmd_ctrl_node *)&pmadapter->cmd_pending_q) {
130 		pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
131 					      pcmd_node->cmdbuf->data_offset);
132 		PRINTM(MERROR, "pending command id: 0x%x ioctl_buf=%p\n",
133 		       wlan_le16_to_cpu(pcmd->command), pcmd_node->pioctl_buf);
134 		pcmd_node = pcmd_node->pnext;
135 	}
136 #ifdef STA_SUPPORT
137 	wlan_check_scan_queue(pmadapter);
138 #endif
139 	wlan_release_cmd_lock(pmadapter);
140 	LEAVE();
141 	return;
142 }
143 
144 #define REASON_CODE_NO_CMD_NODE     1
145 #define REASON_CODE_CMD_TIMEOUT     2
146 #define REASON_CODE_CMD_TO_CARD_FAILURE 3
147 #define REASON_CODE_EXT_SCAN_TIMEOUT    4
148 /**
149  *  @brief This function dump debug info
150  *
151  *  @param pmadapter    A pointer to mlan_adapter
152  *  @param reason        Reason code
153  *
154  *  @return     N/A
155  */
156 t_void
wlan_dump_info(mlan_adapter * pmadapter,t_u8 reason)157 wlan_dump_info(mlan_adapter *pmadapter, t_u8 reason)
158 {
159 	cmd_ctrl_node *pcmd_node = MNULL;
160 #ifdef DEBUG_LEVEL1
161 	t_u32 sec = 0, usec = 0;
162 #endif
163 	t_u8 i;
164 #ifdef SDIO_MULTI_PORT_TX_AGGR
165 	t_u8 j;
166 	t_u8 mp_aggr_pkt_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT;
167 #endif
168 	t_u16 cmd_id, cmd_act;
169 	mlan_private *pmpriv = MNULL;
170 
171 	ENTER();
172 
173 	PRINTM(MERROR, "------------Dump info-----------\n", reason);
174 	switch (reason) {
175 	case REASON_CODE_NO_CMD_NODE:
176 		pmadapter->dbg.num_no_cmd_node++;
177 		PRINTM(MERROR, "No Free command node\n");
178 		break;
179 	case REASON_CODE_CMD_TIMEOUT:
180 		PRINTM(MERROR, "Commmand Timeout\n");
181 		break;
182 	case REASON_CODE_CMD_TO_CARD_FAILURE:
183 		PRINTM(MERROR, "Command to card failure\n");
184 		break;
185 	case REASON_CODE_EXT_SCAN_TIMEOUT:
186 		PRINTM(MERROR, "EXT_SCAN_STATUS event Timeout\n");
187 		break;
188 	default:
189 		break;
190 	}
191 	if ((reason == REASON_CODE_NO_CMD_NODE) &&
192 	    (pmadapter->dbg.num_no_cmd_node > 1)) {
193 		if (pmadapter->dbg.num_no_cmd_node >= 5)
194 			wlan_recv_event(wlan_get_priv
195 					(pmadapter, MLAN_BSS_ROLE_ANY),
196 					MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
197 		LEAVE();
198 		return;
199 	}
200 	wlan_dump_pending_commands(pmadapter);
201 	if (reason != REASON_CODE_CMD_TIMEOUT) {
202 		if (!pmadapter->curr_cmd) {
203 			PRINTM(MERROR, "CurCmd Empty\n");
204 		} else {
205 			pcmd_node = pmadapter->curr_cmd;
206 			cmd_id = pmadapter->dbg.last_cmd_id[pmadapter->dbg.
207 							    last_cmd_index];
208 			cmd_act =
209 				pmadapter->dbg.last_cmd_act[pmadapter->dbg.
210 							    last_cmd_index];
211 			PRINTM_GET_SYS_TIME(MERROR, &sec, &usec);
212 			PRINTM(MERROR,
213 			       "Current cmd id (%lu.%06lu) = 0x%x, act = 0x%x\n",
214 			       sec, usec, cmd_id, cmd_act);
215 			if (pcmd_node->cmdbuf) {
216 				t_u8 *pcmd_buf;
217 				pcmd_buf =
218 					pcmd_node->cmdbuf->pbuf +
219 					pcmd_node->cmdbuf->data_offset +
220 					INTF_HEADER_LEN;
221 				for (i = 0; i < 16; i++)
222 					PRINTM(MERROR, "%02x ", *pcmd_buf++);
223 				PRINTM(MERROR, "\n");
224 			}
225 			pmpriv = pcmd_node->priv;
226 			if (pmpriv)
227 				PRINTM(MERROR, "BSS type = %d BSS role= %d\n",
228 				       pmpriv->bss_type, pmpriv->bss_role);
229 		}
230 	}
231 	PRINTM(MERROR, "mlan_processing =%d\n", pmadapter->mlan_processing);
232 	PRINTM(MERROR, "main_lock_flag =%d\n", pmadapter->main_lock_flag);
233 	PRINTM(MERROR, "main_process_cnt =%d\n", pmadapter->main_process_cnt);
234 	PRINTM(MERROR, "delay_task_flag =%d\n", pmadapter->delay_task_flag);
235 	PRINTM(MERROR, "mlan_rx_processing =%d\n",
236 	       pmadapter->mlan_rx_processing);
237 	PRINTM(MERROR, "rx_pkts_queued=%d\n", pmadapter->rx_pkts_queued);
238 	PRINTM(MERROR, "more_task_flag = %d\n", pmadapter->more_task_flag);
239 	PRINTM(MERROR, "num_cmd_timeout = %d\n", pmadapter->num_cmd_timeout);
240 	PRINTM(MERROR, "dbg.num_cmd_timeout = %d\n",
241 	       pmadapter->dbg.num_cmd_timeout);
242 	PRINTM(MERROR, "last_cmd_index = %d\n", pmadapter->dbg.last_cmd_index);
243 	PRINTM(MERROR, "last_cmd_id = ");
244 	for (i = 0; i < DBG_CMD_NUM; i++)
245 		PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_id[i]);
246 	PRINTM(MERROR, "\n");
247 	PRINTM(MERROR, "last_cmd_act = ");
248 	for (i = 0; i < DBG_CMD_NUM; i++)
249 		PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_act[i]);
250 	PRINTM(MERROR, "\n");
251 	PRINTM(MERROR, "last_cmd_resp_index = %d\n",
252 	       pmadapter->dbg.last_cmd_resp_index);
253 	PRINTM(MERROR, "last_cmd_resp_id = ");
254 	for (i = 0; i < DBG_CMD_NUM; i++)
255 		PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_resp_id[i]);
256 	PRINTM(MERROR, "\n");
257 	PRINTM(MERROR, "last_event_index = %d\n",
258 	       pmadapter->dbg.last_event_index);
259 	PRINTM(MERROR, "last_event = ");
260 	for (i = 0; i < DBG_CMD_NUM; i++)
261 		PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_event[i]);
262 	PRINTM(MERROR, "\n");
263 
264 	PRINTM(MERROR, "num_data_h2c_failure = %d\n",
265 	       pmadapter->dbg.num_tx_host_to_card_failure);
266 	PRINTM(MERROR, "num_cmd_h2c_failure = %d\n",
267 	       pmadapter->dbg.num_cmd_host_to_card_failure);
268 	PRINTM(MERROR, "num_data_c2h_failure = %d\n",
269 	       pmadapter->dbg.num_rx_card_to_host_failure);
270 	PRINTM(MERROR, "num_cmdevt_c2h_failure = %d\n",
271 	       pmadapter->dbg.num_cmdevt_card_to_host_failure);
272 	PRINTM(MERROR, "num_int_read_failure = %d\n",
273 	       pmadapter->dbg.num_int_read_failure);
274 	PRINTM(MERROR, "last_int_status = %d\n",
275 	       pmadapter->dbg.last_int_status);
276 	PRINTM(MERROR, "num_alloc_buffer_failure = %d\n",
277 	       pmadapter->dbg.num_alloc_buffer_failure);
278 	PRINTM(MERROR, "num_pkt_dropped = %d\n",
279 	       pmadapter->dbg.num_pkt_dropped);
280 	PRINTM(MERROR, "num_no_cmd_node = %d\n",
281 	       pmadapter->dbg.num_no_cmd_node);
282 	PRINTM(MERROR, "num_event_deauth = %d\n",
283 	       pmadapter->dbg.num_event_deauth);
284 	PRINTM(MERROR, "num_event_disassoc = %d\n",
285 	       pmadapter->dbg.num_event_disassoc);
286 	PRINTM(MERROR, "num_event_link_lost = %d\n",
287 	       pmadapter->dbg.num_event_link_lost);
288 	PRINTM(MERROR, "num_cmd_deauth = %d\n", pmadapter->dbg.num_cmd_deauth);
289 	PRINTM(MERROR, "num_cmd_assoc_success = %d\n",
290 	       pmadapter->dbg.num_cmd_assoc_success);
291 	PRINTM(MERROR, "num_cmd_assoc_failure = %d\n",
292 	       pmadapter->dbg.num_cmd_assoc_failure);
293 	PRINTM(MERROR, "cmd_resp_received=%d\n", pmadapter->cmd_resp_received);
294 	PRINTM(MERROR, "event_received=%d\n", pmadapter->event_received);
295 
296 	PRINTM(MERROR, "max_tx_buf_size=%d\n", pmadapter->max_tx_buf_size);
297 	PRINTM(MERROR, "tx_buf_size=%d\n", pmadapter->tx_buf_size);
298 	PRINTM(MERROR, "curr_tx_buf_size=%d\n", pmadapter->curr_tx_buf_size);
299 
300 	PRINTM(MERROR, "data_sent=%d cmd_sent=%d\n", pmadapter->data_sent,
301 	       pmadapter->cmd_sent);
302 
303 	PRINTM(MERROR, "ps_mode=%d ps_state=%d\n", pmadapter->ps_mode,
304 	       pmadapter->ps_state);
305 	PRINTM(MERROR, "wakeup_dev_req=%d wakeup_tries=%d\n",
306 	       pmadapter->pm_wakeup_card_req, pmadapter->pm_wakeup_fw_try);
307 	PRINTM(MERROR, "hs_configured=%d hs_activated=%d\n",
308 	       pmadapter->is_hs_configured, pmadapter->hs_activated);
309 	PRINTM(MERROR, "pps_uapsd_mode=%d sleep_pd=%d\n",
310 	       pmadapter->pps_uapsd_mode, pmadapter->sleep_period.period);
311 	PRINTM(MERROR, "tx_lock_flag = %d\n", pmadapter->tx_lock_flag);
312 	PRINTM(MERROR, "scan_processing = %d\n", pmadapter->scan_processing);
313 	PRINTM(MERROR, "mp_rd_bitmap=0x%x curr_rd_port=0x%x\n",
314 	       pmadapter->mp_rd_bitmap, pmadapter->curr_rd_port);
315 	PRINTM(MERROR, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n",
316 	       pmadapter->mp_wr_bitmap, pmadapter->curr_wr_port);
317 	PRINTM(MERROR, "mp_invalid_update=%d\n", pmadapter->mp_invalid_update);
318 #ifdef SDIO_MULTI_PORT_TX_AGGR
319 	PRINTM(MERROR, "last_recv_wr_bitmap=0x%x last_mp_index=%d\n",
320 	       pmadapter->last_recv_wr_bitmap, pmadapter->last_mp_index);
321 	for (i = 0; i < SDIO_MP_DBG_NUM; i++) {
322 		PRINTM(MERROR,
323 		       "mp_wr_bitmap: 0x%x mp_wr_ports=0x%x len=%d curr_wr_port=0x%x\n",
324 		       pmadapter->last_mp_wr_bitmap[i],
325 		       pmadapter->last_mp_wr_ports[i],
326 		       pmadapter->last_mp_wr_len[i],
327 		       pmadapter->last_curr_wr_port[i]);
328 		for (j = 0; j < mp_aggr_pkt_limit; j++) {
329 			PRINTM(MERROR, "0x%02x ",
330 			       pmadapter->last_mp_wr_info[i *
331 							  mp_aggr_pkt_limit +
332 							  j]);
333 		}
334 		PRINTM(MERROR, "\n");
335 	}
336 #endif
337 	for (i = 0; i < pmadapter->priv_num; ++i) {
338 		if (pmadapter->priv[i])
339 			wlan_dump_ralist(pmadapter->priv[i]);
340 	}
341 	if (reason != REASON_CODE_CMD_TIMEOUT) {
342 		if ((pmadapter->dbg.num_no_cmd_node >= 5)
343 		    || (pmadapter->pm_wakeup_card_req &&
344 			pmadapter->pm_wakeup_fw_try)
345 		    || (reason == REASON_CODE_EXT_SCAN_TIMEOUT)
346 			) {
347 			if (pmpriv)
348 				wlan_recv_event(pmpriv,
349 						MLAN_EVENT_ID_DRV_DBG_DUMP,
350 						MNULL);
351 			else
352 				wlan_recv_event(wlan_get_priv
353 						(pmadapter, MLAN_BSS_ROLE_ANY),
354 						MLAN_EVENT_ID_DRV_DBG_DUMP,
355 						MNULL);
356 		}
357 	}
358 	PRINTM(MERROR, "-------- Dump info End---------\n", reason);
359 	LEAVE();
360 	return;
361 }
362 
363 /**
364  *  @brief This function convert a given character to hex
365  *
366  *  @param chr        Character to be converted
367  *
368  *  @return           The converted hex if chr is a valid hex, else 0
369  */
370 static t_u32
wlan_hexval(t_u8 chr)371 wlan_hexval(t_u8 chr)
372 {
373 	if (chr >= '0' && chr <= '9')
374 		return chr - '0';
375 	if (chr >= 'A' && chr <= 'F')
376 		return chr - 'A' + 10;
377 	if (chr >= 'a' && chr <= 'f')
378 		return chr - 'a' + 10;
379 
380 	return 0;
381 }
382 
383 /**
384  *  @brief This function convert a given string to hex
385  *
386  *  @param a            A pointer to string to be converted
387  *
388  *  @return             The converted hex value if param a is a valid hex, else 0
389  */
390 int
wlan_atox(t_u8 * a)391 wlan_atox(t_u8 *a)
392 {
393 	int i = 0;
394 
395 	ENTER();
396 
397 	while (wlan_isxdigit(*a))
398 		i = i * 16 + wlan_hexval(*a++);
399 
400 	LEAVE();
401 	return i;
402 }
403 
404 /**
405  *  @brief This function parse cal data from ASCII to hex
406  *
407  *  @param src          A pointer to source data
408  *  @param len          Source data length
409  *  @param dst          A pointer to a buf to store the parsed data
410  *
411  *  @return             The parsed hex data length
412  */
413 static t_u32
wlan_parse_cal_cfg(t_u8 * src,t_size len,t_u8 * dst)414 wlan_parse_cal_cfg(t_u8 *src, t_size len, t_u8 *dst)
415 {
416 	t_u8 *ptr;
417 	t_u8 *dptr;
418 
419 	ENTER();
420 	ptr = src;
421 	dptr = dst;
422 
423 	while (ptr - src < len) {
424 		if (*ptr && (wlan_isspace(*ptr) || *ptr == '\t')) {
425 			ptr++;
426 			continue;
427 		}
428 
429 		if (wlan_isxdigit(*ptr)) {
430 			*dptr++ = wlan_atox(ptr);
431 			ptr += 2;
432 		} else {
433 			ptr++;
434 		}
435 	}
436 	LEAVE();
437 	return dptr - dst;
438 }
439 
440 /**
441  *  @brief This function finds first occurrence of a char in a string
442  *
443  *  @param s            A pointer to the string to be searched
444  *  @param c            The character to search for
445  *
446  *  @return             Location of the first occurrence of the char
447  *                      if found, else NULL
448  */
449 t_u8 *
wlan_strchr(t_u8 * s,int c)450 wlan_strchr(t_u8 *s, int c)
451 {
452 	t_u8 *pos = s;
453 	while (*pos != '\0') {
454 		if (*pos == (t_u8)c)
455 			return pos;
456 		pos++;
457 	}
458 	return MNULL;
459 }
460 
461 /**
462  *    @brief WOAL parse ASCII format raw data to hex format
463  *
464  *    @param pmpriv       MOAL handle
465  *    @param data         Source data
466  *    @param size         data length
467  *    @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
468  */
469 static t_u32
wlan_process_hostcmd_cfg(IN pmlan_private pmpriv,t_u8 * data,t_size size)470 wlan_process_hostcmd_cfg(IN pmlan_private pmpriv, t_u8 *data, t_size size)
471 {
472 	mlan_status ret = MLAN_STATUS_SUCCESS;
473 	t_u8 *pos = data;
474 	t_u8 *intf_s, *intf_e;
475 	t_u8 *buf = MNULL;
476 	t_u8 *ptr = MNULL;
477 	t_u32 cmd_len = 0;
478 	t_u8 start_raw = MFALSE;
479 	mlan_ds_misc_cmd *hostcmd;
480 	mlan_adapter *pmadapter = pmpriv->adapter;
481 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
482 
483 	ENTER();
484 	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
485 			       sizeof(mlan_ds_misc_cmd), MLAN_MEM_DEF,
486 			       (t_u8 **)&hostcmd);
487 	if (ret || !hostcmd) {
488 		PRINTM(MERROR, "Could not allocate buffer space!\n");
489 		LEAVE();
490 		return ret;
491 	}
492 	buf = hostcmd->cmd;
493 	ptr = buf;
494 	while ((pos - data) < size) {
495 		while (*pos == ' ' || *pos == '\t')
496 			pos++;
497 		if (*pos == '#') {	/* Line comment */
498 			while (*pos != '\n')
499 				pos++;
500 			pos++;
501 		}
502 		if ((*pos == '\r' && *(pos + 1) == '\n') ||
503 		    *pos == '\n' || *pos == '\0') {
504 			pos++;
505 			continue;	/* Needn't process this line */
506 		}
507 
508 		if (*pos == '}') {
509 			cmd_len = *((t_u16 *)(buf + sizeof(t_u16)));
510 			hostcmd->len = cmd_len;
511 			ret = wlan_prepare_cmd(pmpriv, 0, 0, 0, MNULL,
512 					       (t_void *)hostcmd);
513 			memset(pmadapter, buf, 0, MLAN_SIZE_OF_CMD_BUFFER);
514 			ptr = buf;
515 			start_raw = MFALSE;
516 			pos++;
517 			continue;
518 		}
519 
520 		if (start_raw == MFALSE) {
521 			intf_s = wlan_strchr(pos, '=');
522 			if (intf_s)
523 				intf_e = wlan_strchr(intf_s, '{');
524 			else
525 				intf_e = MNULL;
526 
527 			if (intf_s && intf_e) {
528 				start_raw = MTRUE;
529 				pos = intf_e + 1;
530 				continue;
531 			}
532 		}
533 
534 		if (start_raw) {
535 			/* Raw data block exists */
536 			while (*pos != '\n') {
537 				if ((*pos <= 'f' && *pos >= 'a') ||
538 				    (*pos <= 'F' && *pos >= 'A') ||
539 				    (*pos <= '9' && *pos >= '0')) {
540 					*ptr++ = wlan_atox(pos);
541 					pos += 2;
542 				} else
543 					pos++;
544 			}
545 		}
546 	}
547 	pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)hostcmd);
548 	LEAVE();
549 	return ret;
550 }
551 
552 /**
553  *  @brief This function initializes the command node.
554  *
555  *  @param pmpriv       A pointer to mlan_private structure
556  *  @param pcmd_node    A pointer to cmd_ctrl_node structure
557  *  @param cmd_oid      Cmd oid: treated as sub command
558  *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
559  *  @param pdata_buf    A pointer to information buffer
560  *
561  *  @return             N/A
562  */
563 static void
wlan_init_cmd_node(IN pmlan_private pmpriv,IN cmd_ctrl_node * pcmd_node,IN t_u32 cmd_oid,IN t_void * pioctl_buf,IN t_void * pdata_buf)564 wlan_init_cmd_node(IN pmlan_private pmpriv,
565 		   IN cmd_ctrl_node *pcmd_node,
566 		   IN t_u32 cmd_oid,
567 		   IN t_void *pioctl_buf, IN t_void *pdata_buf)
568 {
569 	mlan_adapter *pmadapter = pmpriv->adapter;
570 
571 	ENTER();
572 
573 	if (pcmd_node == MNULL) {
574 		LEAVE();
575 		return;
576 	}
577 	pcmd_node->priv = pmpriv;
578 	pcmd_node->cmd_oid = cmd_oid;
579 	pcmd_node->pioctl_buf = pioctl_buf;
580 	pcmd_node->pdata_buf = pdata_buf;
581 
582 	pcmd_node->cmdbuf = pcmd_node->pmbuf;
583 
584 	/* Make sure head_ptr for cmd buf is Align */
585 	pcmd_node->cmdbuf->data_offset = 0;
586 	memset(pmadapter, pcmd_node->cmdbuf->pbuf, 0,
587 	       MRVDRV_SIZE_OF_CMD_BUFFER);
588 
589 	/* Prepare mlan_buffer for command sending */
590 	pcmd_node->cmdbuf->buf_type = MLAN_BUF_TYPE_CMD;
591 	pcmd_node->cmdbuf->data_offset += INTF_HEADER_LEN;
592 
593 	LEAVE();
594 }
595 
596 /**
597  *  @brief This function gets a free command node if available in
598  *              command free queue.
599  *
600  *  @param pmadapter        A pointer to mlan_adapter structure
601  *
602  *  @return cmd_ctrl_node   A pointer to cmd_ctrl_node structure or MNULL
603  */
604 static cmd_ctrl_node *
wlan_get_cmd_node(mlan_adapter * pmadapter)605 wlan_get_cmd_node(mlan_adapter *pmadapter)
606 {
607 	cmd_ctrl_node *pcmd_node;
608 
609 	ENTER();
610 
611 	if (pmadapter == MNULL) {
612 		LEAVE();
613 		return MNULL;
614 	}
615 	wlan_request_cmd_lock(pmadapter);
616 	if (util_peek_list(pmadapter->pmoal_handle, &pmadapter->cmd_free_q,
617 			   MNULL, MNULL)) {
618 		pcmd_node =
619 			(cmd_ctrl_node *)util_dequeue_list(pmadapter->
620 							   pmoal_handle,
621 							   &pmadapter->
622 							   cmd_free_q, MNULL,
623 							   MNULL);
624 	} else {
625 		PRINTM(MERROR,
626 		       "GET_CMD_NODE: cmd_ctrl_node is not available\n");
627 		pcmd_node = MNULL;
628 	}
629 	wlan_release_cmd_lock(pmadapter);
630 	LEAVE();
631 	return pcmd_node;
632 }
633 
634 /**
635  *  @brief This function cleans command node.
636  *
637  *  @param pmadapter    A pointer to mlan_adapter structure
638  *  @param pcmd_node    A pointer to cmd_ctrl_node structure
639  *
640  *  @return             N/A
641  */
642 static t_void
wlan_clean_cmd_node(pmlan_adapter pmadapter,cmd_ctrl_node * pcmd_node)643 wlan_clean_cmd_node(pmlan_adapter pmadapter, cmd_ctrl_node *pcmd_node)
644 {
645 	ENTER();
646 
647 	if (pcmd_node == MNULL) {
648 		LEAVE();
649 		return;
650 	}
651 	pcmd_node->cmd_oid = 0;
652 	pcmd_node->cmd_flag = 0;
653 	pcmd_node->pioctl_buf = MNULL;
654 	pcmd_node->pdata_buf = MNULL;
655 
656 	if (pcmd_node->respbuf) {
657 		wlan_free_mlan_buffer(pmadapter, pcmd_node->respbuf);
658 		pcmd_node->respbuf = MNULL;
659 	}
660 
661 	LEAVE();
662 	return;
663 }
664 
665 #ifdef STA_SUPPORT
666 /**
667  *  @brief This function will return the pointer to the first entry in
668  *          pending cmd which is scan command
669  *
670  *  @param pmadapter    A pointer to mlan_adapter
671  *
672  *  @return             A pointer to first entry match pioctl_req
673  */
674 static cmd_ctrl_node *
wlan_get_pending_scan_cmd(pmlan_adapter pmadapter)675 wlan_get_pending_scan_cmd(pmlan_adapter pmadapter)
676 {
677 	cmd_ctrl_node *pcmd_node = MNULL;
678 
679 	ENTER();
680 
681 	pcmd_node =
682 		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
683 						&pmadapter->cmd_pending_q,
684 						MNULL, MNULL);
685 	if (!pcmd_node) {
686 		LEAVE();
687 		return MNULL;
688 	}
689 	while (pcmd_node != (cmd_ctrl_node *)&pmadapter->cmd_pending_q) {
690 		if (pcmd_node->cmd_flag & CMD_F_SCAN) {
691 			LEAVE();
692 			return pcmd_node;
693 		}
694 		pcmd_node = pcmd_node->pnext;
695 	}
696 	LEAVE();
697 	return MNULL;
698 }
699 #endif
700 
701 /**
702  *  @brief This function will return the pointer to the first entry in
703  *          pending cmd which matches the given pioctl_req
704  *
705  *  @param pmadapter    A pointer to mlan_adapter
706  *  @param pioctl_req   A pointer to mlan_ioctl_req buf
707  *
708  *  @return             A pointer to first entry match pioctl_req
709  */
710 static cmd_ctrl_node *
wlan_get_pending_ioctl_cmd(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)711 wlan_get_pending_ioctl_cmd(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
712 {
713 	cmd_ctrl_node *pcmd_node = MNULL;
714 
715 	ENTER();
716 
717 	pcmd_node =
718 		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
719 						&pmadapter->cmd_pending_q,
720 						MNULL, MNULL);
721 	if (!pcmd_node) {
722 		LEAVE();
723 		return MNULL;
724 	}
725 	while (pcmd_node != (cmd_ctrl_node *)&pmadapter->cmd_pending_q) {
726 		if (pcmd_node->pioctl_buf &&
727 		    (pcmd_node->pioctl_buf == pioctl_req)) {
728 			LEAVE();
729 			return pcmd_node;
730 		}
731 		pcmd_node = pcmd_node->pnext;
732 	}
733 	LEAVE();
734 	return MNULL;
735 }
736 
737 /**
738  *  @brief This function will return the pointer to the first entry in
739  *          pending cmd which matches the given bss_index
740  *
741  *  @param pmadapter    A pointer to mlan_adapter
742  *  @param bss_index    bss_index
743  *
744  *  @return             A pointer to first entry match pioctl_req
745  */
746 static cmd_ctrl_node *
wlan_get_bss_pending_ioctl_cmd(pmlan_adapter pmadapter,t_u32 bss_index)747 wlan_get_bss_pending_ioctl_cmd(pmlan_adapter pmadapter, t_u32 bss_index)
748 {
749 	cmd_ctrl_node *pcmd_node = MNULL;
750 	mlan_ioctl_req *pioctl_buf = MNULL;
751 	ENTER();
752 
753 	pcmd_node =
754 		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
755 						&pmadapter->cmd_pending_q,
756 						MNULL, MNULL);
757 	if (!pcmd_node) {
758 		LEAVE();
759 		return MNULL;
760 	}
761 	while (pcmd_node != (cmd_ctrl_node *)&pmadapter->cmd_pending_q) {
762 		if (pcmd_node->pioctl_buf) {
763 			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
764 			if (pioctl_buf->bss_index == bss_index) {
765 				LEAVE();
766 				return pcmd_node;
767 			}
768 		}
769 		pcmd_node = pcmd_node->pnext;
770 	}
771 	LEAVE();
772 	return MNULL;
773 }
774 
775 /**
776  *  @brief This function handles the command response of host_cmd
777  *
778  *  @param pmpriv       A pointer to mlan_private structure
779  *  @param resp         A pointer to HostCmd_DS_COMMAND
780  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
781  *
782  *  @return        MLAN_STATUS_SUCCESS
783  */
784 static mlan_status
wlan_ret_host_cmd(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * resp,IN mlan_ioctl_req * pioctl_buf)785 wlan_ret_host_cmd(IN pmlan_private pmpriv,
786 		  IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
787 {
788 	mlan_ds_misc_cfg *misc;
789 	t_u16 size = wlan_le16_to_cpu(resp->size);
790 
791 	ENTER();
792 
793 	PRINTM(MINFO, "host command response size = %d\n", size);
794 	size = MIN(size, MRVDRV_SIZE_OF_CMD_BUFFER);
795 	if (pioctl_buf) {
796 		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
797 		misc->param.hostcmd.len = size;
798 		memcpy(pmpriv->adapter, misc->param.hostcmd.cmd, (void *)resp,
799 		       size);
800 	}
801 
802 	LEAVE();
803 	return MLAN_STATUS_SUCCESS;
804 }
805 
806 /**
807  *  @brief This function sends host command to firmware.
808  *
809  *  @param pmpriv       A pointer to mlan_private structure
810  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
811  *  @param pdata_buf    A pointer to data buffer
812  *  @return             MLAN_STATUS_SUCCESS
813  */
814 static mlan_status
wlan_cmd_host_cmd(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * cmd,IN t_void * pdata_buf)815 wlan_cmd_host_cmd(IN pmlan_private pmpriv,
816 		  IN HostCmd_DS_COMMAND *cmd, IN t_void *pdata_buf)
817 {
818 	mlan_ds_misc_cmd *pcmd_ptr = (mlan_ds_misc_cmd *)pdata_buf;
819 
820 	ENTER();
821 
822 	/* Copy the HOST command to command buffer */
823 	memcpy(pmpriv->adapter, (void *)cmd, pcmd_ptr->cmd,
824 	       MIN(MRVDRV_SIZE_OF_CMD_BUFFER, pcmd_ptr->len));
825 	PRINTM(MINFO, "Host command size = %d\n", pcmd_ptr->len);
826 	LEAVE();
827 	return MLAN_STATUS_SUCCESS;
828 }
829 
830 /**
831  *  @brief This function downloads a command to firmware.
832  *
833  *  @param pmpriv       A pointer to mlan_private structure
834  *  @param pcmd_node    A pointer to cmd_ctrl_node structure
835  *
836  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
837  */
838 static mlan_status
wlan_dnld_cmd_to_fw(IN mlan_private * pmpriv,IN cmd_ctrl_node * pcmd_node)839 wlan_dnld_cmd_to_fw(IN mlan_private *pmpriv, IN cmd_ctrl_node *pcmd_node)
840 {
841 
842 	mlan_adapter *pmadapter = pmpriv->adapter;
843 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
844 	mlan_status ret = MLAN_STATUS_SUCCESS;
845 	HostCmd_DS_COMMAND *pcmd;
846 	mlan_ioctl_req *pioctl_buf = MNULL;
847 	t_u16 cmd_code;
848 	t_u16 cmd_size;
849 	t_u32 age_ts_usec;
850 #ifdef DEBUG_LEVEL1
851 	t_u32 sec = 0, usec = 0;
852 #endif
853 
854 	ENTER();
855 
856 	if (pcmd_node)
857 		if (pcmd_node->pioctl_buf != MNULL)
858 			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
859 	if (!pmadapter || !pcmd_node) {
860 		if (pioctl_buf)
861 			pioctl_buf->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
862 		ret = MLAN_STATUS_FAILURE;
863 		goto done;
864 	}
865 
866 	pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
867 				      pcmd_node->cmdbuf->data_offset);
868 
869 	/* Sanity test */
870 	if (pcmd == MNULL || pcmd->size == 0) {
871 		PRINTM(MERROR,
872 		       "DNLD_CMD: pcmd is null or command size is zero, "
873 		       "Not sending\n");
874 		if (pioctl_buf)
875 			pioctl_buf->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
876 		wlan_request_cmd_lock(pmadapter);
877 		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
878 		wlan_release_cmd_lock(pmadapter);
879 		ret = MLAN_STATUS_FAILURE;
880 		goto done;
881 	}
882 
883 	/* Set command sequence number */
884 	pmadapter->seq_num++;
885 	pcmd->seq_num =
886 		wlan_cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO
887 				 (pmadapter->seq_num, pcmd_node->priv->bss_num,
888 				  pcmd_node->priv->bss_type));
889 	cmd_code = wlan_le16_to_cpu(pcmd->command);
890 	cmd_size = wlan_le16_to_cpu(pcmd->size);
891 
892 	pcmd_node->cmdbuf->data_len = cmd_size;
893 
894 	wlan_request_cmd_lock(pmadapter);
895 	pmadapter->curr_cmd = pcmd_node;
896 	wlan_release_cmd_lock(pmadapter);
897 
898 	/* Save the last command id and action to debug log */
899 	pmadapter->dbg.last_cmd_index =
900 		(pmadapter->dbg.last_cmd_index + 1) % DBG_CMD_NUM;
901 	pmadapter->dbg.last_cmd_id[pmadapter->dbg.last_cmd_index] = cmd_code;
902 	pmadapter->dbg.last_cmd_act[pmadapter->dbg.last_cmd_index] =
903 		wlan_le16_to_cpu(*(t_u16 *)((t_u8 *)pcmd + S_DS_GEN));
904 	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
905 						  &pmadapter->dnld_cmd_in_secs,
906 						  &age_ts_usec);
907 
908 	if (pcmd->command == HostCmd_CMD_HOST_CLOCK_CFG) {
909 		HostCmd_DS_HOST_CLOCK_CFG *host_clock =
910 			(HostCmd_DS_HOST_CLOCK_CFG *) & pcmd->params.
911 			host_clock_cfg;
912 		pmadapter->callbacks.moal_get_host_time_ns(&pmadapter->d1);
913 		PRINTM(MINFO, "WIFI_TS: d1: %llu\n", pmadapter->d1);
914 		/* Overwrite the time to be given to FW */
915 		host_clock->time = wlan_cpu_to_le64(pmadapter->d1);
916 	}
917 
918 	PRINTM_GET_SYS_TIME(MCMND, &sec, &usec);
919 	PRINTM_NETINTF(MCMND, pmpriv);
920 	PRINTM(MCMND,
921 	       "DNLD_CMD (%lu.%06lu): 0x%x, act 0x%x, len %d, seqno 0x%x\n",
922 	       sec, usec, cmd_code,
923 	       wlan_le16_to_cpu(*(t_u16 *)((t_u8 *)pcmd + S_DS_GEN)), cmd_size,
924 	       wlan_le16_to_cpu(pcmd->seq_num));
925 	DBG_HEXDUMP(MCMD_D, "DNLD_CMD", (t_u8 *)pcmd, cmd_size);
926 
927 	/* Send the command to lower layer */
928 
929 	pcmd_node->cmdbuf->data_offset -= INTF_HEADER_LEN;
930 	pcmd_node->cmdbuf->data_len += INTF_HEADER_LEN;
931 	/* Extra header for SDIO is added here */
932 	ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_CMD,
933 				     pcmd_node->cmdbuf, MNULL);
934 
935 	if (ret == MLAN_STATUS_FAILURE) {
936 		PRINTM(MERROR, "DNLD_CMD: Host to Card Failed\n");
937 		if (pcmd_node->pioctl_buf) {
938 			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
939 			pioctl_buf->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
940 		}
941 
942 		wlan_request_cmd_lock(pmadapter);
943 		wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
944 		pmadapter->curr_cmd = MNULL;
945 		wlan_release_cmd_lock(pmadapter);
946 		if (pmadapter->dbg.last_cmd_index)
947 			pmadapter->dbg.last_cmd_index--;
948 		else
949 			pmadapter->dbg.last_cmd_index = DBG_CMD_NUM - 1;
950 
951 		pmadapter->dbg.num_cmd_host_to_card_failure++;
952 		wlan_dump_info(pmadapter, REASON_CODE_CMD_TO_CARD_FAILURE);
953 		ret = MLAN_STATUS_FAILURE;
954 		goto done;
955 	}
956 
957 	/* Clear BSS_NO_BITS from HostCmd */
958 	cmd_code &= HostCmd_CMD_ID_MASK;
959 
960 	/* For the command who has no command response, we should return here */
961 	if (cmd_code == HostCmd_CMD_FW_DUMP_EVENT
962 	    || cmd_code == HostCmd_CMD_SOFT_RESET) {
963 		if (pcmd_node->pioctl_buf) {
964 			PRINTM(MMSG,
965 			       "CMD(0x%x) has no cmd resp: free curr_cmd and do ioctl_complete\n",
966 			       cmd_code);
967 			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
968 			wlan_request_cmd_lock(pmadapter);
969 			wlan_insert_cmd_to_free_q(pmadapter,
970 						  pmadapter->curr_cmd);
971 			pmadapter->curr_cmd = MNULL;
972 			wlan_release_cmd_lock(pmadapter);
973 		}
974 		goto done;
975 	}
976 
977 	/* Setup the timer after transmit command */
978 	pcb->moal_start_timer(pmadapter->pmoal_handle,
979 			      pmadapter->pmlan_cmd_timer, MFALSE,
980 			      MRVDRV_TIMER_10S * 2);
981 
982 	pmadapter->cmd_timer_is_set = MTRUE;
983 
984 	ret = MLAN_STATUS_SUCCESS;
985 
986 done:
987 	LEAVE();
988 	return ret;
989 }
990 
991 /**
992  *  @brief This function sends sleep confirm command to firmware.
993  *
994  *  @param pmadapter  A pointer to mlan_adapter structure
995  *
996  *  @return           MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
997  */
998 static mlan_status
wlan_dnld_sleep_confirm_cmd(mlan_adapter * pmadapter)999 wlan_dnld_sleep_confirm_cmd(mlan_adapter *pmadapter)
1000 {
1001 	mlan_status ret = MLAN_STATUS_SUCCESS;
1002 	static t_u32 i;
1003 	t_u16 cmd_len = 0;
1004 	opt_sleep_confirm_buffer *sleep_cfm_buf =
1005 		(opt_sleep_confirm_buffer *)(pmadapter->psleep_cfm->pbuf +
1006 					     pmadapter->psleep_cfm->
1007 					     data_offset);
1008 	mlan_private *pmpriv = MNULL;
1009 
1010 	ENTER();
1011 
1012 	pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
1013 	if (!pmpriv) {
1014 		LEAVE();
1015 		return MLAN_STATUS_FAILURE;
1016 	}
1017 	cmd_len = sizeof(OPT_Confirm_Sleep);
1018 	pmadapter->seq_num++;
1019 	sleep_cfm_buf->ps_cfm_sleep.seq_num =
1020 		wlan_cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO
1021 				 (pmadapter->seq_num, pmpriv->bss_num,
1022 				  pmpriv->bss_type));
1023 	DBG_HEXDUMP(MCMD_D, "SLEEP_CFM", &sleep_cfm_buf->ps_cfm_sleep,
1024 		    sizeof(OPT_Confirm_Sleep));
1025 
1026 	/* Send sleep confirm command to firmware */
1027 
1028 	pmadapter->psleep_cfm->data_len = cmd_len + INTF_HEADER_LEN;
1029 	ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_CMD,
1030 				     pmadapter->psleep_cfm, MNULL);
1031 
1032 	if (ret == MLAN_STATUS_FAILURE) {
1033 		PRINTM(MERROR, "SLEEP_CFM: failed\n");
1034 		pmadapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++;
1035 		goto done;
1036 	} else {
1037 		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
1038 			pmadapter->ps_state = PS_STATE_SLEEP_CFM;
1039 #ifdef STA_SUPPORT
1040 		if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
1041 			if (!sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl) {
1042 				/* Response is not needed for sleep confirm command */
1043 				pmadapter->ps_state = PS_STATE_SLEEP;
1044 			} else {
1045 				pmadapter->ps_state = PS_STATE_SLEEP_CFM;
1046 			}
1047 
1048 			if (!sleep_cfm_buf->ps_cfm_sleep.sleep_cfm.resp_ctrl
1049 			    && (pmadapter->is_hs_configured &&
1050 				!pmadapter->sleep_period.period)) {
1051 				pmadapter->pm_wakeup_card_req = MTRUE;
1052 				wlan_host_sleep_activated_event(wlan_get_priv
1053 								(pmadapter,
1054 								 MLAN_BSS_ROLE_STA),
1055 								MTRUE);
1056 			}
1057 		}
1058 #endif /* STA_SUPPORT */
1059 
1060 #define NUM_SC_PER_LINE         16
1061 		if (++i % NUM_SC_PER_LINE == 0)
1062 			PRINTM(MEVENT, "+\n");
1063 		else
1064 			PRINTM(MEVENT, "+");
1065 	}
1066 
1067 done:
1068 	LEAVE();
1069 	return ret;
1070 }
1071 
1072 /********************************************************
1073 			Global Functions
1074 ********************************************************/
1075 
1076 /**
1077  *  @brief Event handler
1078  *
1079  *  @param priv     A pointer to mlan_private structure
1080  *  @param event_id Event ID
1081  *  @param pmevent  Event buffer
1082  *
1083  *  @return         MLAN_STATUS_SUCCESS
1084  */
1085 mlan_status
wlan_recv_event(pmlan_private priv,mlan_event_id event_id,t_void * pmevent)1086 wlan_recv_event(pmlan_private priv, mlan_event_id event_id, t_void *pmevent)
1087 {
1088 	pmlan_callbacks pcb = MNULL;
1089 
1090 	ENTER();
1091 
1092 	if (!priv) {
1093 		LEAVE();
1094 		return MLAN_STATUS_FAILURE;
1095 	}
1096 	pcb = &priv->adapter->callbacks;
1097 
1098 	if (pmevent)
1099 		/* The caller has provided the event. */
1100 		pcb->moal_recv_event(priv->adapter->pmoal_handle,
1101 				     (pmlan_event)pmevent);
1102 	else {
1103 		mlan_event mevent;
1104 
1105 		memset(priv->adapter, &mevent, 0, sizeof(mlan_event));
1106 		mevent.bss_index = priv->bss_index;
1107 		mevent.event_id = event_id;
1108 		mevent.event_len = 0;
1109 
1110 		pcb->moal_recv_event(priv->adapter->pmoal_handle, &mevent);
1111 	}
1112 
1113 	LEAVE();
1114 	return MLAN_STATUS_SUCCESS;
1115 }
1116 
1117 /**
1118  *  @brief This function allocates the command buffer and links
1119  *          it to command free queue.
1120  *
1121  *  @param pmadapter    A pointer to mlan_adapter structure
1122  *
1123  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1124  */
1125 mlan_status
wlan_alloc_cmd_buffer(IN mlan_adapter * pmadapter)1126 wlan_alloc_cmd_buffer(IN mlan_adapter *pmadapter)
1127 {
1128 	mlan_status ret = MLAN_STATUS_SUCCESS;
1129 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
1130 	cmd_ctrl_node *pcmd_array = MNULL;
1131 	t_u32 buf_size;
1132 	t_u32 i;
1133 
1134 	ENTER();
1135 
1136 	/* Allocate and initialize cmd_ctrl_node */
1137 	buf_size = sizeof(cmd_ctrl_node) * MRVDRV_NUM_OF_CMD_BUFFER;
1138 	ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size,
1139 			       MLAN_MEM_DEF | MLAN_MEM_DMA,
1140 			       (t_u8 **)&pcmd_array);
1141 	if (ret != MLAN_STATUS_SUCCESS || !pcmd_array) {
1142 		PRINTM(MERROR,
1143 		       "ALLOC_CMD_BUF: Failed to allocate pcmd_array\n");
1144 		ret = MLAN_STATUS_FAILURE;
1145 		goto done;
1146 	}
1147 
1148 	pmadapter->cmd_pool = pcmd_array;
1149 	memset(pmadapter, pmadapter->cmd_pool, 0, buf_size);
1150 
1151 	/* Allocate and initialize command buffers */
1152 	for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1153 		pcmd_array[i].pmbuf = wlan_alloc_mlan_buffer(pmadapter,
1154 							     MRVDRV_SIZE_OF_CMD_BUFFER,
1155 							     0,
1156 							     MOAL_MALLOC_BUFFER);
1157 		if (!pcmd_array[i].pmbuf) {
1158 			PRINTM(MERROR,
1159 			       "ALLOC_CMD_BUF: Failed to allocate command buffer\n");
1160 			ret = MLAN_STATUS_FAILURE;
1161 			goto done;
1162 		}
1163 	}
1164 	wlan_request_cmd_lock(pmadapter);
1165 	for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++)
1166 		wlan_insert_cmd_to_free_q(pmadapter, &pcmd_array[i]);
1167 	wlan_release_cmd_lock(pmadapter);
1168 	ret = MLAN_STATUS_SUCCESS;
1169 done:
1170 	LEAVE();
1171 	return ret;
1172 }
1173 
1174 /**
1175  *  @brief This function frees the command buffer.
1176  *
1177  *  @param pmadapter    A pointer to mlan_adapter structure
1178  *
1179  *  @return             MLAN_STATUS_SUCCESS
1180  */
1181 mlan_status
wlan_free_cmd_buffer(IN mlan_adapter * pmadapter)1182 wlan_free_cmd_buffer(IN mlan_adapter *pmadapter)
1183 {
1184 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
1185 	cmd_ctrl_node *pcmd_array;
1186 	t_u32 i;
1187 
1188 	ENTER();
1189 
1190 	/* Need to check if cmd pool is allocated or not */
1191 	if (pmadapter->cmd_pool == MNULL) {
1192 		PRINTM(MINFO, "FREE_CMD_BUF: cmd_pool is Null\n");
1193 		goto done;
1194 	}
1195 
1196 	pcmd_array = pmadapter->cmd_pool;
1197 
1198 	/* Release shared memory buffers */
1199 	for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
1200 		if (pcmd_array[i].pmbuf) {
1201 			PRINTM(MINFO, "Free all the command buffer.\n");
1202 			wlan_free_mlan_buffer(pmadapter, pcmd_array[i].pmbuf);
1203 			pcmd_array[i].pmbuf = MNULL;
1204 		}
1205 		if (pcmd_array[i].respbuf) {
1206 			wlan_free_mlan_buffer(pmadapter, pcmd_array[i].respbuf);
1207 			pcmd_array[i].respbuf = MNULL;
1208 		}
1209 	}
1210 	/* Release cmd_ctrl_node */
1211 	if (pmadapter->cmd_pool) {
1212 		PRINTM(MINFO, "Free command pool.\n");
1213 		pcb->moal_mfree(pmadapter->pmoal_handle,
1214 				(t_u8 *)pmadapter->cmd_pool);
1215 		pmadapter->cmd_pool = MNULL;
1216 	}
1217 
1218 done:
1219 	LEAVE();
1220 	return MLAN_STATUS_SUCCESS;
1221 }
1222 
1223 /**
1224  *  @brief This function handles events generated by firmware
1225  *
1226  *  @param pmadapter    A pointer to mlan_adapter structure
1227  *
1228  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1229  */
1230 mlan_status
wlan_process_event(pmlan_adapter pmadapter)1231 wlan_process_event(pmlan_adapter pmadapter)
1232 {
1233 	mlan_status ret = MLAN_STATUS_SUCCESS;
1234 	pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
1235 	pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event;
1236 	t_u32 eventcause = pmadapter->event_cause;
1237 #ifdef DEBUG_LEVEL1
1238 	t_u32 in_ts_sec = 0, in_ts_usec = 0;
1239 #endif
1240 	ENTER();
1241 
1242 	/* Save the last event to debug log */
1243 	pmadapter->dbg.last_event_index =
1244 		(pmadapter->dbg.last_event_index + 1) % DBG_CMD_NUM;
1245 	pmadapter->dbg.last_event[pmadapter->dbg.last_event_index] =
1246 		(t_u16)eventcause;
1247 
1248 	if ((eventcause & EVENT_ID_MASK) == EVENT_RADAR_DETECTED) {
1249 		if (wlan_11h_dfs_event_preprocessing(pmadapter) ==
1250 		    MLAN_STATUS_SUCCESS) {
1251 			memcpy(pmadapter, (t_u8 *)&eventcause,
1252 			       pmbuf->pbuf + pmbuf->data_offset,
1253 			       sizeof(eventcause));
1254 		} else {
1255 			PRINTM(MERROR, "Error processing DFS Event: 0x%x\n",
1256 			       eventcause);
1257 			goto done;
1258 		}
1259 	}
1260 	/* Get BSS number and corresponding priv */
1261 	priv = wlan_get_priv_by_id(pmadapter, EVENT_GET_BSS_NUM(eventcause),
1262 				   EVENT_GET_BSS_TYPE(eventcause));
1263 	if (!priv)
1264 		priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
1265 	if (!priv) {
1266 		ret = MLAN_STATUS_FAILURE;
1267 		goto done;
1268 	}
1269 
1270 	/* Clear BSS_NO_BITS from event */
1271 	eventcause &= EVENT_ID_MASK;
1272 	pmadapter->event_cause = eventcause;
1273 
1274 	if (pmbuf) {
1275 		pmbuf->bss_index = priv->bss_index;
1276 		memcpy(pmadapter,
1277 		       pmbuf->pbuf + pmbuf->data_offset,
1278 		       (t_u8 *)&eventcause, sizeof(eventcause));
1279 	}
1280 
1281 	if (MTRUE
1282 	    && (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE)
1283 		) {
1284 		PRINTM_GET_SYS_TIME(MEVENT, &in_ts_sec, &in_ts_usec);
1285 		PRINTM_NETINTF(MEVENT, priv);
1286 		PRINTM(MEVENT, "%lu.%06lu : Event: 0x%x\n", in_ts_sec,
1287 		       in_ts_usec, eventcause);
1288 	}
1289 
1290 	ret = priv->ops.process_event(priv);
1291 done:
1292 	pmadapter->event_cause = 0;
1293 	pmadapter->pmlan_buffer_event = MNULL;
1294 	if (pmbuf)
1295 		wlan_free_mlan_buffer(pmadapter, pmbuf);
1296 
1297 	LEAVE();
1298 	return ret;
1299 }
1300 
1301 /**
1302  *  @brief This function requests a lock on command queue.
1303  *
1304  *  @param pmadapter    A pointer to mlan_adapter structure
1305  *
1306  *  @return             N/A
1307  */
1308 t_void
wlan_request_cmd_lock(IN mlan_adapter * pmadapter)1309 wlan_request_cmd_lock(IN mlan_adapter *pmadapter)
1310 {
1311 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
1312 
1313 	ENTER();
1314 
1315 	/* Call MOAL spin lock callback function */
1316 	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmlan_cmd_lock);
1317 
1318 	LEAVE();
1319 	return;
1320 }
1321 
1322 /**
1323  *  @brief This function releases a lock on command queue.
1324  *
1325  *  @param pmadapter    A pointer to mlan_adapter structure
1326  *
1327  *  @return             N/A
1328  */
1329 t_void
wlan_release_cmd_lock(IN mlan_adapter * pmadapter)1330 wlan_release_cmd_lock(IN mlan_adapter *pmadapter)
1331 {
1332 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
1333 
1334 	ENTER();
1335 
1336 	/* Call MOAL spin unlock callback function */
1337 	pcb->moal_spin_unlock(pmadapter->pmoal_handle,
1338 			      pmadapter->pmlan_cmd_lock);
1339 
1340 	LEAVE();
1341 	return;
1342 }
1343 
1344 /**
1345  *  @brief This function prepare the command before sending to firmware.
1346  *
1347  *  @param pmpriv       A pointer to mlan_private structure
1348  *  @param cmd_no       Command number
1349  *  @param cmd_action   Command action: GET or SET
1350  *  @param cmd_oid      Cmd oid: treated as sub command
1351  *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
1352  *  @param pdata_buf    A pointer to information buffer
1353  *
1354  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1355  */
1356 mlan_status
wlan_prepare_cmd(IN mlan_private * pmpriv,IN t_u16 cmd_no,IN t_u16 cmd_action,IN t_u32 cmd_oid,IN t_void * pioctl_buf,IN t_void * pdata_buf)1357 wlan_prepare_cmd(IN mlan_private *pmpriv,
1358 		 IN t_u16 cmd_no,
1359 		 IN t_u16 cmd_action,
1360 		 IN t_u32 cmd_oid, IN t_void *pioctl_buf, IN t_void *pdata_buf)
1361 {
1362 	mlan_status ret = MLAN_STATUS_SUCCESS;
1363 	mlan_adapter *pmadapter = MNULL;
1364 	cmd_ctrl_node *pcmd_node = MNULL;
1365 	HostCmd_DS_COMMAND *cmd_ptr = MNULL;
1366 	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
1367 
1368 	ENTER();
1369 
1370 	if (!pmpriv) {
1371 		LEAVE();
1372 		return MLAN_STATUS_FAILURE;
1373 	}
1374 	pmadapter = pmpriv->adapter;
1375 
1376 	/* Sanity test */
1377 	if (!pmadapter || pmadapter->surprise_removed) {
1378 		PRINTM(MERROR, "PREP_CMD: Card is Removed\n");
1379 		if (pioctl_req)
1380 			pioctl_req->status_code = MLAN_ERROR_FW_NOT_READY;
1381 		ret = MLAN_STATUS_FAILURE;
1382 		goto done;
1383 	}
1384 
1385 	if (pmadapter->hw_status == WlanHardwareStatusReset) {
1386 		if ((cmd_no != HostCmd_CMD_FUNC_INIT)
1387 			) {
1388 			PRINTM(MERROR, "PREP_CMD: FW is in reset state\n");
1389 			if (pioctl_req)
1390 				pioctl_req->status_code =
1391 					MLAN_ERROR_FW_NOT_READY;
1392 			ret = MLAN_STATUS_FAILURE;
1393 			goto done;
1394 		}
1395 	}
1396 
1397 	/* Get a new command node */
1398 	pcmd_node = wlan_get_cmd_node(pmadapter);
1399 
1400 	if (pcmd_node == MNULL) {
1401 		PRINTM(MERROR, "PREP_CMD: No free cmd node\n");
1402 		wlan_dump_info(pmadapter, REASON_CODE_NO_CMD_NODE);
1403 		if (pioctl_req)
1404 			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
1405 		ret = MLAN_STATUS_FAILURE;
1406 		goto done;
1407 	}
1408     /** reset num no cmd node */
1409 	pmadapter->dbg.num_no_cmd_node = 0;
1410 
1411 	/* Initialize the command node */
1412 	wlan_init_cmd_node(pmpriv, pcmd_node, cmd_oid, pioctl_buf, pdata_buf);
1413 
1414 	if (pcmd_node->cmdbuf == MNULL) {
1415 		PRINTM(MERROR, "PREP_CMD: No free cmd buf\n");
1416 		if (pioctl_req)
1417 			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
1418 		ret = MLAN_STATUS_FAILURE;
1419 		goto done;
1420 	}
1421 
1422 	cmd_ptr =
1423 		(HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
1424 				       pcmd_node->cmdbuf->data_offset);
1425 	cmd_ptr->command = cmd_no;
1426 	cmd_ptr->result = 0;
1427 
1428 	/* Prepare command */
1429 	if (cmd_no)
1430 		ret = pmpriv->ops.prepare_cmd(pmpriv, cmd_no, cmd_action,
1431 					      cmd_oid, pioctl_buf, pdata_buf,
1432 					      cmd_ptr);
1433 	else {
1434 		ret = wlan_cmd_host_cmd(pmpriv, cmd_ptr, pdata_buf);
1435 		pcmd_node->cmd_flag |= CMD_F_HOSTCMD;
1436 	}
1437 
1438 	/* Return error, since the command preparation failed */
1439 	if (ret != MLAN_STATUS_SUCCESS) {
1440 		PRINTM(MERROR, "PREP_CMD: Command 0x%x preparation failed\n",
1441 		       cmd_no);
1442 		pcmd_node->pioctl_buf = MNULL;
1443 		if (pioctl_req)
1444 			pioctl_req->status_code = MLAN_ERROR_CMD_DNLD_FAIL;
1445 		wlan_request_cmd_lock(pmadapter);
1446 		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
1447 		wlan_release_cmd_lock(pmadapter);
1448 		ret = MLAN_STATUS_FAILURE;
1449 		goto done;
1450 	}
1451 
1452 	wlan_request_cmd_lock(pmadapter);
1453 	/* Send command */
1454 #ifdef STA_SUPPORT
1455 	if (cmd_no == HostCmd_CMD_802_11_SCAN
1456 	    || cmd_no == HostCmd_CMD_802_11_SCAN_EXT) {
1457 		if (cmd_no == HostCmd_CMD_802_11_SCAN_EXT &&
1458 		    pmadapter->ext_scan && pmadapter->ext_scan_enh
1459 		    && pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
1460 			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
1461 						     MFALSE);
1462 		} else
1463 			wlan_queue_scan_cmd(pmpriv, pcmd_node);
1464 	} else {
1465 #endif
1466 		if ((cmd_no == HostCmd_CMD_802_11_HS_CFG_ENH) &&
1467 		    (cmd_action == HostCmd_ACT_GEN_SET) &&
1468 		    (pmadapter->hs_cfg.conditions == HOST_SLEEP_CFG_CANCEL))
1469 			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
1470 						     MFALSE);
1471 		else
1472 			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
1473 						     MTRUE);
1474 #ifdef STA_SUPPORT
1475 	}
1476 #endif
1477 	wlan_release_cmd_lock(pmadapter);
1478 done:
1479 	LEAVE();
1480 	return ret;
1481 }
1482 
1483 /**
1484  *  @brief This function inserts command node to cmd_free_q
1485  *              after cleaning it.
1486  *
1487  *  @param pmadapter    A pointer to mlan_adapter structure
1488  *  @param pcmd_node    A pointer to cmd_ctrl_node structure
1489  *
1490  *  @return             N/A
1491  */
1492 t_void
wlan_insert_cmd_to_free_q(IN mlan_adapter * pmadapter,IN cmd_ctrl_node * pcmd_node)1493 wlan_insert_cmd_to_free_q(IN mlan_adapter *pmadapter,
1494 			  IN cmd_ctrl_node *pcmd_node)
1495 {
1496 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
1497 	mlan_ioctl_req *pioctl_req = MNULL;
1498 	ENTER();
1499 
1500 	if (pcmd_node == MNULL)
1501 		goto done;
1502 	if (pcmd_node->pioctl_buf) {
1503 		pioctl_req = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
1504 		if (pioctl_req->status_code != MLAN_ERROR_NO_ERROR)
1505 			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
1506 						 pioctl_req,
1507 						 MLAN_STATUS_FAILURE);
1508 		else
1509 			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
1510 						 pioctl_req,
1511 						 MLAN_STATUS_SUCCESS);
1512 	}
1513 	/* Clean the node */
1514 	wlan_clean_cmd_node(pmadapter, pcmd_node);
1515 
1516 	/* Insert node into cmd_free_q */
1517 	util_enqueue_list_tail(pmadapter->pmoal_handle, &pmadapter->cmd_free_q,
1518 			       (pmlan_linked_list)pcmd_node, MNULL, MNULL);
1519 done:
1520 	LEAVE();
1521 }
1522 
1523 /**
1524  *  @brief This function queues the command to cmd list.
1525  *
1526  *  @param pmadapter    A pointer to mlan_adapter structure
1527  *  @param pcmd_node    A pointer to cmd_ctrl_node structure
1528  *  @param add_tail      Specify if the cmd needs to be queued in the header or tail
1529  *
1530  *  @return             N/A
1531  */
1532 t_void
wlan_insert_cmd_to_pending_q(IN mlan_adapter * pmadapter,IN cmd_ctrl_node * pcmd_node,IN t_u32 add_tail)1533 wlan_insert_cmd_to_pending_q(IN mlan_adapter *pmadapter,
1534 			     IN cmd_ctrl_node *pcmd_node, IN t_u32 add_tail)
1535 {
1536 	HostCmd_DS_COMMAND *pcmd = MNULL;
1537 	t_u16 command;
1538 
1539 	ENTER();
1540 
1541 	if (pcmd_node == MNULL) {
1542 		PRINTM(MERROR, "QUEUE_CMD: pcmd_node is MNULL\n");
1543 		goto done;
1544 	}
1545 
1546 	pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
1547 				      pcmd_node->cmdbuf->data_offset);
1548 
1549 	command = wlan_le16_to_cpu(pcmd->command);
1550 
1551 	/* Exit_PS command needs to be queued in the header always. */
1552 	if (command == HostCmd_CMD_802_11_PS_MODE_ENH) {
1553 		HostCmd_DS_802_11_PS_MODE_ENH *pm = &pcmd->params.psmode_enh;
1554 		if (wlan_le16_to_cpu(pm->action) == DIS_AUTO_PS) {
1555 			if (pmadapter->ps_state != PS_STATE_AWAKE)
1556 				add_tail = MFALSE;
1557 		}
1558 	}
1559 
1560 	if (add_tail) {
1561 		util_enqueue_list_tail(pmadapter->pmoal_handle,
1562 				       &pmadapter->cmd_pending_q,
1563 				       (pmlan_linked_list)pcmd_node,
1564 				       MNULL, MNULL);
1565 	} else {
1566 		util_enqueue_list_head(pmadapter->pmoal_handle,
1567 				       &pmadapter->cmd_pending_q,
1568 				       (pmlan_linked_list)pcmd_node,
1569 				       MNULL, MNULL);
1570 	}
1571 
1572 	PRINTM_NETINTF(MCMND, pcmd_node->priv);
1573 	PRINTM(MCMND, "QUEUE_CMD: cmd=0x%x is queued\n", command);
1574 
1575 done:
1576 	LEAVE();
1577 	return;
1578 }
1579 
1580 /**
1581  *  @brief This function executes next command in command
1582  *      pending queue. It will put firmware back to PS mode
1583  *      if applicable.
1584  *
1585  *  @param pmadapter     A pointer to mlan_adapter structure
1586  *
1587  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1588  */
1589 mlan_status
wlan_exec_next_cmd(mlan_adapter * pmadapter)1590 wlan_exec_next_cmd(mlan_adapter *pmadapter)
1591 {
1592 	mlan_private *priv = MNULL;
1593 	cmd_ctrl_node *pcmd_node = MNULL;
1594 	mlan_status ret = MLAN_STATUS_SUCCESS;
1595 	HostCmd_DS_COMMAND *pcmd;
1596 
1597 	ENTER();
1598 
1599 	/* Sanity test */
1600 	if (pmadapter == MNULL) {
1601 		PRINTM(MERROR, "EXEC_NEXT_CMD: pmadapter is MNULL\n");
1602 		ret = MLAN_STATUS_FAILURE;
1603 		goto done;
1604 	}
1605 	/* Check if already in processing */
1606 	if (pmadapter->curr_cmd) {
1607 		PRINTM(MERROR,
1608 		       "EXEC_NEXT_CMD: there is command in processing!\n");
1609 		ret = MLAN_STATUS_FAILURE;
1610 		goto done;
1611 	}
1612 
1613 	wlan_request_cmd_lock(pmadapter);
1614 	/* Check if any command is pending */
1615 	pcmd_node =
1616 		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
1617 						&pmadapter->cmd_pending_q,
1618 						MNULL, MNULL);
1619 
1620 	if (pcmd_node) {
1621 		pcmd = (HostCmd_DS_COMMAND *)(pcmd_node->cmdbuf->pbuf +
1622 					      pcmd_node->cmdbuf->data_offset);
1623 		priv = pcmd_node->priv;
1624 
1625 		if (pmadapter->ps_state != PS_STATE_AWAKE) {
1626 			PRINTM(MERROR,
1627 			       "Cannot send command in sleep state, this should not happen\n");
1628 			wlan_release_cmd_lock(pmadapter);
1629 			goto done;
1630 		}
1631 
1632 		util_unlink_list(pmadapter->pmoal_handle,
1633 				 &pmadapter->cmd_pending_q,
1634 				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
1635 		wlan_release_cmd_lock(pmadapter);
1636 		ret = wlan_dnld_cmd_to_fw(priv, pcmd_node);
1637 		priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
1638 		/* Any command sent to the firmware when host is in sleep mode, should de-configure host sleep */
1639 		/* We should skip the host sleep configuration command itself though */
1640 		if (priv &&
1641 		    (pcmd->command !=
1642 		     wlan_cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH))) {
1643 			if (pmadapter->hs_activated == MTRUE) {
1644 				pmadapter->is_hs_configured = MFALSE;
1645 				wlan_host_sleep_activated_event(priv, MFALSE);
1646 			}
1647 		}
1648 		goto done;
1649 	} else {
1650 		wlan_release_cmd_lock(pmadapter);
1651 	}
1652 	ret = MLAN_STATUS_SUCCESS;
1653 done:
1654 	LEAVE();
1655 	return ret;
1656 }
1657 
1658 /**
1659  *  @brief This function handles the command response
1660  *
1661  *  @param pmadapter    A pointer to mlan_adapter structure
1662  *
1663  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1664  */
1665 mlan_status
wlan_process_cmdresp(mlan_adapter * pmadapter)1666 wlan_process_cmdresp(mlan_adapter *pmadapter)
1667 {
1668 	HostCmd_DS_COMMAND *resp = MNULL;
1669 	mlan_private *pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
1670 	mlan_private *pmpriv_next = MNULL;
1671 	mlan_status ret = MLAN_STATUS_SUCCESS;
1672 	t_u16 orig_cmdresp_no;
1673 	t_u16 cmdresp_no;
1674 	t_u16 cmdresp_result;
1675 	mlan_ioctl_req *pioctl_buf = MNULL;
1676 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
1677 #ifdef DEBUG_LEVEL1
1678 	t_u32 sec = 0, usec = 0;
1679 #endif
1680 	t_u32 i;
1681 
1682 	ENTER();
1683 
1684 	/* Now we got response from FW, cancel the command timer */
1685 	if (pmadapter->cmd_timer_is_set) {
1686 		/* Cancel command timeout timer */
1687 		pcb->moal_stop_timer(pmadapter->pmoal_handle,
1688 				     pmadapter->pmlan_cmd_timer);
1689 		/* Cancel command timeout timer */
1690 		pmadapter->cmd_timer_is_set = MFALSE;
1691 	}
1692 
1693 	if (pmadapter->curr_cmd)
1694 		if (pmadapter->curr_cmd->pioctl_buf != MNULL) {
1695 			pioctl_buf =
1696 				(mlan_ioctl_req *)pmadapter->curr_cmd->
1697 				pioctl_buf;
1698 		}
1699 
1700 	if (!pmadapter->curr_cmd || !pmadapter->curr_cmd->respbuf) {
1701 		resp = (HostCmd_DS_COMMAND *)pmadapter->upld_buf;
1702 		resp->command = wlan_le16_to_cpu(resp->command);
1703 		PRINTM(MERROR, "CMD_RESP: No curr_cmd, 0x%x\n", resp->command);
1704 		if (pioctl_buf)
1705 			pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
1706 		ret = MLAN_STATUS_FAILURE;
1707 		goto done;
1708 	}
1709 
1710 	pmadapter->num_cmd_timeout = 0;
1711 
1712 	DBG_HEXDUMP(MCMD_D, "CMD_RESP",
1713 		    pmadapter->curr_cmd->respbuf->pbuf +
1714 		    pmadapter->curr_cmd->respbuf->data_offset,
1715 		    pmadapter->curr_cmd->respbuf->data_len);
1716 
1717 	resp = (HostCmd_DS_COMMAND *)(pmadapter->curr_cmd->respbuf->pbuf +
1718 				      pmadapter->curr_cmd->respbuf->
1719 				      data_offset);
1720 	wlan_request_cmd_lock(pmadapter);
1721 	if (pmadapter->curr_cmd->cmd_flag & CMD_F_CANCELED) {
1722 		cmd_ctrl_node *free_cmd = pmadapter->curr_cmd;
1723 		pmadapter->curr_cmd = MNULL;
1724 		PRINTM(MCMND, "CMD_RESP: 0x%x been canceled!\n",
1725 		       wlan_le16_to_cpu(resp->command));
1726 		if (pioctl_buf)
1727 			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
1728 		wlan_insert_cmd_to_free_q(pmadapter, free_cmd);
1729 		wlan_release_cmd_lock(pmadapter);
1730 		ret = MLAN_STATUS_FAILURE;
1731 		goto done;
1732 	} else {
1733 		wlan_release_cmd_lock(pmadapter);
1734 	}
1735 	if (pmadapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
1736 		/* Copy original response back to response buffer */
1737 		wlan_ret_host_cmd(pmpriv, resp, pioctl_buf);
1738 	}
1739 	orig_cmdresp_no = wlan_le16_to_cpu(resp->command);
1740 	resp->size = wlan_le16_to_cpu(resp->size);
1741 	resp->seq_num = wlan_le16_to_cpu(resp->seq_num);
1742 	resp->result = wlan_le16_to_cpu(resp->result);
1743 
1744 	/* Get BSS number and corresponding priv */
1745 	pmpriv = wlan_get_priv_by_id(pmadapter,
1746 				     HostCmd_GET_BSS_NO(resp->seq_num),
1747 				     HostCmd_GET_BSS_TYPE(resp->seq_num));
1748 	if (!pmpriv)
1749 		pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
1750 	/* Clear RET_BIT from HostCmd */
1751 	resp->command = (orig_cmdresp_no & HostCmd_CMD_ID_MASK);
1752 	cmdresp_no = resp->command;
1753 
1754 	cmdresp_result = resp->result;
1755 
1756 	if (resp->command == HostCmd_CMD_HOST_CLOCK_CFG) {
1757 		/* d2 needs to be fast - is there a way to avoid callback? */
1758 		if (pmpriv) {
1759 			pcb->moal_get_host_time_ns(&pmadapter->d2);
1760 			PRINTM(MINFO,
1761 			       "WIFI_TS: RTT for Host_CLOCK_CFG= %d ns\n",
1762 			       pmadapter->d2 - pmadapter->d1);
1763 		}
1764 	}
1765 
1766 	/* Save the last command response to debug log */
1767 	pmadapter->dbg.last_cmd_resp_index =
1768 		(pmadapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM;
1769 	pmadapter->dbg.last_cmd_resp_id[pmadapter->dbg.last_cmd_resp_index] =
1770 		orig_cmdresp_no;
1771 
1772 	PRINTM_GET_SYS_TIME(MCMND, &sec, &usec);
1773 	PRINTM_NETINTF(MCMND, pmadapter->curr_cmd->priv);
1774 	PRINTM(MCMND,
1775 	       "CMD_RESP (%lu.%06lu): 0x%x, result %d, len %d, seqno 0x%x\n",
1776 	       sec, usec, orig_cmdresp_no, cmdresp_result, resp->size,
1777 	       resp->seq_num);
1778 
1779 	if (!(orig_cmdresp_no & HostCmd_RET_BIT)) {
1780 		PRINTM(MERROR, "CMD_RESP: Invalid response to command!\n");
1781 		if (pioctl_buf)
1782 			pioctl_buf->status_code = MLAN_ERROR_FW_CMDRESP;
1783 		wlan_request_cmd_lock(pmadapter);
1784 		wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
1785 		pmadapter->curr_cmd = MNULL;
1786 		wlan_release_cmd_lock(pmadapter);
1787 		ret = MLAN_STATUS_FAILURE;
1788 		goto done;
1789 	}
1790 
1791 	if (pmadapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
1792 		pmadapter->curr_cmd->cmd_flag &= ~CMD_F_HOSTCMD;
1793 		if ((cmdresp_result == HostCmd_RESULT_OK)
1794 		    && (cmdresp_no == HostCmd_CMD_802_11_HS_CFG_ENH))
1795 			ret = wlan_ret_802_11_hs_cfg(pmpriv, resp, pioctl_buf);
1796 	} else {
1797 		/* handle response */
1798 		ret = pmpriv->ops.process_cmdresp(pmpriv, cmdresp_no, resp,
1799 						  pioctl_buf);
1800 	}
1801 
1802 	/* Check init command response */
1803 	if (pmadapter->hw_status == WlanHardwareStatusInitializing ||
1804 	    pmadapter->hw_status == WlanHardwareStatusGetHwSpec) {
1805 		if (ret == MLAN_STATUS_FAILURE) {
1806 #if defined(STA_SUPPORT)
1807 			if (pmadapter->pwarm_reset_ioctl_req) {
1808 				/* warm reset failure */
1809 				pmadapter->pwarm_reset_ioctl_req->status_code =
1810 					MLAN_ERROR_CMD_RESP_FAIL;
1811 				pcb->moal_ioctl_complete(pmadapter->
1812 							 pmoal_handle,
1813 							 pmadapter->
1814 							 pwarm_reset_ioctl_req,
1815 							 MLAN_STATUS_FAILURE);
1816 				pmadapter->pwarm_reset_ioctl_req = MNULL;
1817 				goto done;
1818 			}
1819 #endif
1820 			PRINTM(MERROR,
1821 			       "cmd 0x%02x failed during initialization\n",
1822 			       cmdresp_no);
1823 			wlan_init_fw_complete(pmadapter);
1824 			goto done;
1825 		}
1826 	}
1827 
1828 	wlan_request_cmd_lock(pmadapter);
1829 	if (pmadapter->curr_cmd) {
1830 		cmd_ctrl_node *free_cmd = pmadapter->curr_cmd;
1831 		pioctl_buf = (mlan_ioctl_req *)pmadapter->curr_cmd->pioctl_buf;
1832 		pmadapter->curr_cmd = MNULL;
1833 		if (pioctl_buf && (ret == MLAN_STATUS_SUCCESS))
1834 			pioctl_buf->status_code = MLAN_ERROR_NO_ERROR;
1835 		else if (pioctl_buf && (ret == MLAN_STATUS_FAILURE) &&
1836 			 !pioctl_buf->status_code)
1837 			pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
1838 
1839 		/* Clean up and put current command back to cmd_free_q */
1840 		wlan_insert_cmd_to_free_q(pmadapter, free_cmd);
1841 	}
1842 	wlan_release_cmd_lock(pmadapter);
1843 
1844 	if ((pmadapter->hw_status == WlanHardwareStatusInitializing) &&
1845 	    (pmadapter->last_init_cmd == cmdresp_no)) {
1846 		i = pmpriv->bss_index + 1;
1847 		while (i < pmadapter->priv_num &&
1848 		       (!(pmpriv_next = pmadapter->priv[i])
1849 			|| pmpriv_next->bss_virtual))
1850 			i++;
1851 		if (!pmpriv_next || i >= pmadapter->priv_num) {
1852 
1853 #if defined(STA_SUPPORT)
1854 			if (pmadapter->pwarm_reset_ioctl_req) {
1855 				/* warm reset complete */
1856 				pmadapter->hw_status = WlanHardwareStatusReady;
1857 				pcb->moal_ioctl_complete(pmadapter->
1858 							 pmoal_handle,
1859 							 pmadapter->
1860 							 pwarm_reset_ioctl_req,
1861 							 MLAN_STATUS_SUCCESS);
1862 				pmadapter->pwarm_reset_ioctl_req = MNULL;
1863 				goto done;
1864 			}
1865 #endif
1866 			pmadapter->hw_status = WlanHardwareStatusInitdone;
1867 		} else {
1868 			/* Issue init commands for the next interface */
1869 			ret = pmpriv_next->ops.init_cmd(pmpriv_next, MFALSE);
1870 		}
1871 	} else if ((pmadapter->hw_status == WlanHardwareStatusGetHwSpec) &&
1872 		   (HostCmd_CMD_GET_HW_SPEC == cmdresp_no)) {
1873 		pmadapter->hw_status = WlanHardwareStatusGetHwSpecdone;
1874 	}
1875 done:
1876 	LEAVE();
1877 	return ret;
1878 }
1879 
1880 /**
1881  *  @brief This function handles the timeout of command sending.
1882  *          It will re-send the same command again.
1883  *
1884  *  @param function_context   A pointer to function_context
1885  *  @return                   N/A
1886  */
1887 t_void
wlan_cmd_timeout_func(t_void * function_context)1888 wlan_cmd_timeout_func(t_void *function_context)
1889 {
1890 	mlan_adapter *pmadapter = (mlan_adapter *)function_context;
1891 	cmd_ctrl_node *pcmd_node = MNULL;
1892 	mlan_ioctl_req *pioctl_buf = MNULL;
1893 #ifdef DEBUG_LEVEL1
1894 	t_u32 sec = 0, usec = 0;
1895 #endif
1896 	t_u8 i;
1897 	mlan_private *pmpriv = MNULL;
1898 
1899 	ENTER();
1900 
1901 	pmadapter->cmd_timer_is_set = MFALSE;
1902 	if (!pmadapter->curr_cmd) {
1903 		if (pmadapter->ext_scan && pmadapter->ext_scan_enh &&
1904 		    pmadapter->scan_processing) {
1905 			PRINTM(MMSG, "Ext scan enh timeout\n");
1906 			pmadapter->ext_scan_timeout = MTRUE;
1907 			wlan_dump_info(pmadapter, REASON_CODE_EXT_SCAN_TIMEOUT);
1908 			goto exit;
1909 		}
1910 		PRINTM(MWARN, "CurCmd Empty\n");
1911 		goto exit;
1912 	}
1913 	pmadapter->num_cmd_timeout++;
1914 	pmadapter->dbg.num_cmd_timeout++;
1915 	pcmd_node = pmadapter->curr_cmd;
1916 	if (pcmd_node->pioctl_buf != MNULL) {
1917 		pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
1918 		pioctl_buf->status_code = MLAN_ERROR_CMD_TIMEOUT;
1919 	}
1920 
1921 	pmadapter->dbg.timeout_cmd_id =
1922 		pmadapter->dbg.last_cmd_id[pmadapter->dbg.last_cmd_index];
1923 	pmadapter->dbg.timeout_cmd_act =
1924 		pmadapter->dbg.last_cmd_act[pmadapter->dbg.last_cmd_index];
1925 	PRINTM_GET_SYS_TIME(MERROR, &sec, &usec);
1926 	PRINTM(MERROR, "Timeout cmd id (%lu.%06lu) = 0x%x, act = 0x%x\n", sec,
1927 	       usec, pmadapter->dbg.timeout_cmd_id,
1928 	       pmadapter->dbg.timeout_cmd_act);
1929 	if (pcmd_node->cmdbuf) {
1930 		t_u8 *pcmd_buf;
1931 		pcmd_buf =
1932 			pcmd_node->cmdbuf->pbuf +
1933 			pcmd_node->cmdbuf->data_offset + INTF_HEADER_LEN;
1934 		for (i = 0; i < 16; i++)
1935 			PRINTM(MERROR, "%02x ", *pcmd_buf++);
1936 		PRINTM(MERROR, "\n");
1937 	}
1938 
1939 	pmpriv = pcmd_node->priv;
1940 	if (pmpriv)
1941 		PRINTM(MERROR, "BSS type = %d BSS role= %d\n", pmpriv->bss_type,
1942 		       pmpriv->bss_role);
1943 	wlan_dump_info(pmadapter, REASON_CODE_CMD_TIMEOUT);
1944 
1945 	if (pmadapter->hw_status == WlanHardwareStatusInitializing ||
1946 	    pmadapter->hw_status == WlanHardwareStatusGetHwSpec)
1947 		wlan_init_fw_complete(pmadapter);
1948 	else {
1949 		/* Signal MOAL to perform extra handling for debugging */
1950 		if (pmpriv) {
1951 			wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DBG_DUMP,
1952 					MNULL);
1953 		} else {
1954 			wlan_recv_event(wlan_get_priv
1955 					(pmadapter, MLAN_BSS_ROLE_ANY),
1956 					MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL);
1957 		}
1958 	}
1959 
1960 exit:
1961 	LEAVE();
1962 	return;
1963 }
1964 
1965 #ifdef STA_SUPPORT
1966 /**
1967  *  @brief Internal function used to flush the scan pending queue
1968  *
1969  *  @param pmadapter    A pointer to mlan_adapter structure
1970  *
1971  *  @return             N/A
1972  */
1973 t_void
wlan_flush_scan_queue(IN pmlan_adapter pmadapter)1974 wlan_flush_scan_queue(IN pmlan_adapter pmadapter)
1975 {
1976 
1977 	cmd_ctrl_node *pcmd_node = MNULL;
1978 
1979 	ENTER();
1980 
1981 	wlan_request_cmd_lock(pmadapter);
1982 	while ((pcmd_node =
1983 		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
1984 						&pmadapter->scan_pending_q,
1985 						MNULL, MNULL))) {
1986 		util_unlink_list(pmadapter->pmoal_handle,
1987 				 &pmadapter->scan_pending_q,
1988 				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
1989 		pcmd_node->pioctl_buf = MNULL;
1990 		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
1991 	}
1992 
1993 	pmadapter->scan_processing = MFALSE;
1994 	wlan_release_cmd_lock(pmadapter);
1995 
1996 	LEAVE();
1997 }
1998 
1999 /**
2000  *  @brief Cancel pending SCAN ioctl cmd.
2001  *
2002  *  @param pmadapter    A pointer to mlan_adapter
2003  *  @param pioctl_req   A pointer to pmlan_ioctl_req
2004  *
2005  *  @return             MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING
2006  */
2007 mlan_status
wlan_cancel_pending_scan_cmd(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2008 wlan_cancel_pending_scan_cmd(pmlan_adapter pmadapter,
2009 			     pmlan_ioctl_req pioctl_req)
2010 {
2011 	pmlan_callbacks pcb = &pmadapter->callbacks;
2012 	cmd_ctrl_node *pcmd_node = MNULL;
2013 	mlan_ioctl_req *pioctl_buf = MNULL;
2014 	pmlan_private priv = MNULL;
2015 	mlan_status status = MLAN_STATUS_SUCCESS;
2016 	ENTER();
2017 
2018 	PRINTM(MIOCTL, "Cancel scan command\n");
2019 	wlan_request_cmd_lock(pmadapter);
2020 	/* IOCTL will be completed, avoid calling IOCTL complete again from EVENT/CMDRESP */
2021 	if (pmadapter->pscan_ioctl_req) {
2022 		pioctl_buf = pmadapter->pscan_ioctl_req;
2023 		priv = pmadapter->priv[pioctl_buf->bss_index];
2024 		pmadapter->pscan_ioctl_req = MNULL;
2025 		pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2026 		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
2027 					 MLAN_STATUS_FAILURE);
2028 	}
2029 
2030 	if (pmadapter->curr_cmd && pmadapter->curr_cmd->pioctl_buf) {
2031 		pioctl_buf = (mlan_ioctl_req *)pmadapter->curr_cmd->pioctl_buf;
2032 		if (pioctl_buf->req_id == MLAN_IOCTL_SCAN) {
2033 			PRINTM(MIOCTL, "wlan_cancel_scan: current command\n");
2034 			pcmd_node = pmadapter->curr_cmd;
2035 			pcmd_node->pioctl_buf = MNULL;
2036 			pcmd_node->cmd_flag |= CMD_F_CANCELED;
2037 			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2038 			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
2039 						 pioctl_buf,
2040 						 MLAN_STATUS_FAILURE);
2041 		}
2042 	}
2043 	while ((pcmd_node = wlan_get_pending_scan_cmd(pmadapter)) != MNULL) {
2044 		PRINTM(MIOCTL,
2045 		       "wlan_cancel_scan: find scan command in cmd_pending_q\n");
2046 		util_unlink_list(pmadapter->pmoal_handle,
2047 				 &pmadapter->cmd_pending_q,
2048 				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
2049 		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
2050 	}
2051 	wlan_release_cmd_lock(pmadapter);
2052 	if (pmadapter->scan_processing &&
2053 	    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
2054 		if (priv) {
2055 			wlan_prepare_cmd(priv, HostCmd_CMD_802_11_SCAN_EXT,
2056 					 HostCmd_ACT_GEN_SET, 0, pioctl_req,
2057 					 MNULL);
2058 			wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
2059 					MNULL);
2060 			status = MLAN_STATUS_PENDING;
2061 		}
2062 	} else
2063 		/* Cancel all pending scan command */
2064 		wlan_flush_scan_queue(pmadapter);
2065 	LEAVE();
2066 	return status;
2067 }
2068 #endif
2069 
2070 /**
2071  *  @brief Cancel all pending cmd.
2072  *
2073  *  @param pmadapter    A pointer to mlan_adapter
2074  *
2075  *  @return             N/A
2076  */
2077 t_void
wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter)2078 wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter)
2079 {
2080 	cmd_ctrl_node *pcmd_node = MNULL;
2081 	pmlan_callbacks pcb = &pmadapter->callbacks;
2082 	mlan_ioctl_req *pioctl_buf = MNULL;
2083 #ifdef STA_SUPPORT
2084 	pmlan_private priv = MNULL;
2085 #endif
2086 	ENTER();
2087 	/* Cancel current cmd */
2088 	wlan_request_cmd_lock(pmadapter);
2089 #ifdef STA_SUPPORT
2090 	/* IOCTL will be completed, avoid calling IOCTL complete again from EVENT/CMDRESP */
2091 	if (pmadapter->pscan_ioctl_req) {
2092 		pioctl_buf = pmadapter->pscan_ioctl_req;
2093 		priv = pmadapter->priv[pioctl_buf->bss_index];
2094 		pmadapter->pscan_ioctl_req = MNULL;
2095 		pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2096 		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
2097 					 MLAN_STATUS_FAILURE);
2098 	}
2099 #endif
2100 	if (pmadapter->curr_cmd) {
2101 		pcmd_node = pmadapter->curr_cmd;
2102 		pmadapter->curr_cmd = MNULL;
2103 		if (pcmd_node->pioctl_buf) {
2104 			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
2105 			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2106 			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
2107 						 pioctl_buf,
2108 						 MLAN_STATUS_FAILURE);
2109 			pcmd_node->pioctl_buf = MNULL;
2110 		}
2111 		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
2112 	}
2113 
2114 	/* Cancel all pending command */
2115 	while ((pcmd_node =
2116 		(cmd_ctrl_node *)util_peek_list(pmadapter->pmoal_handle,
2117 						&pmadapter->cmd_pending_q,
2118 						MNULL, MNULL))) {
2119 		util_unlink_list(pmadapter->pmoal_handle,
2120 				 &pmadapter->cmd_pending_q,
2121 				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
2122 		if (pcmd_node->pioctl_buf) {
2123 			pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
2124 			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2125 			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
2126 						 pioctl_buf,
2127 						 MLAN_STATUS_FAILURE);
2128 			pcmd_node->pioctl_buf = MNULL;
2129 		}
2130 		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
2131 	}
2132 	wlan_release_cmd_lock(pmadapter);
2133 #ifdef STA_SUPPORT
2134 	if (pmadapter->scan_processing &&
2135 	    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
2136 		if (priv) {
2137 			wlan_prepare_cmd(priv, HostCmd_CMD_802_11_SCAN_EXT,
2138 					 HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
2139 			wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
2140 					MNULL);
2141 		}
2142 	} else
2143 		/* Cancel all pending scan command */
2144 		wlan_flush_scan_queue(pmadapter);
2145 #endif
2146 	LEAVE();
2147 }
2148 
2149 /**
2150  *  @brief Cancel specific bss's pending ioctl cmd.
2151  *
2152  *  @param pmadapter    A pointer to mlan_adapter
2153  *  @param bss_index    BSS index
2154  *
2155  *  @return             N/A
2156  */
2157 t_void
wlan_cancel_bss_pending_cmd(pmlan_adapter pmadapter,t_u32 bss_index)2158 wlan_cancel_bss_pending_cmd(pmlan_adapter pmadapter, t_u32 bss_index)
2159 {
2160 	pmlan_callbacks pcb = &pmadapter->callbacks;
2161 	cmd_ctrl_node *pcmd_node = MNULL;
2162 	mlan_ioctl_req *pioctl_buf = MNULL;
2163 #ifdef STA_SUPPORT
2164 	t_u8 flash_scan = MFALSE;
2165 #endif
2166 #ifdef STA_SUPPORT
2167 	pmlan_private priv = MNULL;
2168 #endif
2169 	ENTER();
2170 
2171 	PRINTM(MIOCTL, "MOAL Cancel BSS IOCTL: bss_index=%d\n", (int)bss_index);
2172 	wlan_request_cmd_lock(pmadapter);
2173 #ifdef STA_SUPPORT
2174 	if (pmadapter->pscan_ioctl_req &&
2175 	    (pmadapter->pscan_ioctl_req->bss_index == bss_index)) {
2176 		/* IOCTL will be completed, avoid calling IOCTL complete again from EVENT/CMDRESP */
2177 		flash_scan = MTRUE;
2178 		pioctl_buf = pmadapter->pscan_ioctl_req;
2179 		priv = pmadapter->priv[pioctl_buf->bss_index];
2180 		pmadapter->pscan_ioctl_req = MNULL;
2181 		pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2182 		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
2183 					 MLAN_STATUS_FAILURE);
2184 	}
2185 #endif
2186 	if (pmadapter->curr_cmd && pmadapter->curr_cmd->pioctl_buf) {
2187 		pioctl_buf = (mlan_ioctl_req *)pmadapter->curr_cmd->pioctl_buf;
2188 		if (pioctl_buf->bss_index == bss_index) {
2189 			pcmd_node = pmadapter->curr_cmd;
2190 			pcmd_node->pioctl_buf = MNULL;
2191 			pcmd_node->cmd_flag |= CMD_F_CANCELED;
2192 #ifdef STA_SUPPORT
2193 			if (pioctl_buf->req_id == MLAN_IOCTL_SCAN)
2194 				flash_scan = MTRUE;
2195 #endif
2196 			pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2197 			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
2198 						 pioctl_buf,
2199 						 MLAN_STATUS_FAILURE);
2200 		}
2201 	}
2202 	while ((pcmd_node =
2203 		wlan_get_bss_pending_ioctl_cmd(pmadapter,
2204 					       bss_index)) != MNULL) {
2205 		util_unlink_list(pmadapter->pmoal_handle,
2206 				 &pmadapter->cmd_pending_q,
2207 				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
2208 		pioctl_buf = (mlan_ioctl_req *)pcmd_node->pioctl_buf;
2209 		pcmd_node->pioctl_buf = MNULL;
2210 #ifdef STA_SUPPORT
2211 		if (pioctl_buf->req_id == MLAN_IOCTL_SCAN)
2212 			flash_scan = MTRUE;
2213 #endif
2214 		pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
2215 		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
2216 					 MLAN_STATUS_FAILURE);
2217 		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
2218 	}
2219 	wlan_release_cmd_lock(pmadapter);
2220 #ifdef STA_SUPPORT
2221 	if (flash_scan) {
2222 		if (pmadapter->scan_processing &&
2223 		    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
2224 			if (priv) {
2225 				wlan_prepare_cmd(priv,
2226 						 HostCmd_CMD_802_11_SCAN_EXT,
2227 						 HostCmd_ACT_GEN_SET, 0, MNULL,
2228 						 MNULL);
2229 				wlan_recv_event(priv,
2230 						MLAN_EVENT_ID_DRV_DEFER_HANDLING,
2231 						MNULL);
2232 			}
2233 		} else
2234 			/* Cancel all pending scan command */
2235 			wlan_flush_scan_queue(pmadapter);
2236 	}
2237 #endif
2238 	LEAVE();
2239 	return;
2240 }
2241 
2242 /**
2243  *  @brief Cancel pending ioctl cmd.
2244  *
2245  *  @param pmadapter    A pointer to mlan_adapter
2246  *  @param pioctl_req   A pointer to mlan_ioctl_req buf
2247  *
2248  *  @return             N/A
2249  */
2250 t_void
wlan_cancel_pending_ioctl(pmlan_adapter pmadapter,pmlan_ioctl_req pioctl_req)2251 wlan_cancel_pending_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
2252 {
2253 	pmlan_callbacks pcb = &pmadapter->callbacks;
2254 	cmd_ctrl_node *pcmd_node = MNULL;
2255 	t_u8 find = MFALSE;
2256 #ifdef STA_SUPPORT
2257 	pmlan_private priv = MNULL;
2258 #endif
2259 
2260 	ENTER();
2261 
2262 	PRINTM(MIOCTL, "MOAL Cancel IOCTL: 0x%x sub_id=0x%x action=%d\n",
2263 	       pioctl_req->req_id, *((t_u32 *)pioctl_req->pbuf),
2264 	       (int)pioctl_req->action);
2265 
2266 	wlan_request_cmd_lock(pmadapter);
2267 #ifdef STA_SUPPORT
2268 	/* IOCTL will be completed, avoid calling IOCTL complete again from EVENT/CMDRESP */
2269 	if (pmadapter->pscan_ioctl_req == pioctl_req) {
2270 		priv = pmadapter->priv[pioctl_req->bss_index];
2271 		pmadapter->pscan_ioctl_req = MNULL;
2272 		find = MTRUE;
2273 	}
2274 #endif
2275 	if ((pmadapter->curr_cmd) &&
2276 	    (pmadapter->curr_cmd->pioctl_buf == pioctl_req)) {
2277 		pcmd_node = pmadapter->curr_cmd;
2278 		pcmd_node->pioctl_buf = MNULL;
2279 		pcmd_node->cmd_flag |= CMD_F_CANCELED;
2280 		find = MTRUE;
2281 	}
2282 
2283 	while ((pcmd_node =
2284 		wlan_get_pending_ioctl_cmd(pmadapter, pioctl_req)) != MNULL) {
2285 		util_unlink_list(pmadapter->pmoal_handle,
2286 				 &pmadapter->cmd_pending_q,
2287 				 (pmlan_linked_list)pcmd_node, MNULL, MNULL);
2288 		pcmd_node->pioctl_buf = MNULL;
2289 		find = MTRUE;
2290 		wlan_insert_cmd_to_free_q(pmadapter, pcmd_node);
2291 	}
2292 	wlan_release_cmd_lock(pmadapter);
2293 #ifdef STA_SUPPORT
2294 	if (pioctl_req->req_id == MLAN_IOCTL_SCAN) {
2295 		if (pmadapter->scan_processing &&
2296 		    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) {
2297 			if (priv) {
2298 				wlan_prepare_cmd(priv,
2299 						 HostCmd_CMD_802_11_SCAN_EXT,
2300 						 HostCmd_ACT_GEN_SET, 0, MNULL,
2301 						 MNULL);
2302 				wlan_recv_event(priv,
2303 						MLAN_EVENT_ID_DRV_DEFER_HANDLING,
2304 						MNULL);
2305 			}
2306 		} else
2307 			/* Cancel all pending scan command */
2308 			wlan_flush_scan_queue(pmadapter);
2309 	}
2310 #endif
2311 	if (find) {
2312 		pioctl_req->status_code = MLAN_ERROR_CMD_CANCEL;
2313 		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_req,
2314 					 MLAN_STATUS_FAILURE);
2315 	}
2316 
2317 	LEAVE();
2318 	return;
2319 }
2320 
2321 /**
2322  *  @brief Handle the version_ext resp
2323  *
2324  *  @param pmpriv       A pointer to mlan_private structure
2325  *  @param resp         A pointer to HostCmd_DS_COMMAND
2326  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
2327  *
2328  *  @return             MLAN_STATUS_SUCCESS
2329  */
2330 mlan_status
wlan_ret_ver_ext(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * resp,IN mlan_ioctl_req * pioctl_buf)2331 wlan_ret_ver_ext(IN pmlan_private pmpriv,
2332 		 IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
2333 {
2334 	HostCmd_DS_VERSION_EXT *ver_ext = &resp->params.verext;
2335 	mlan_ds_get_info *info;
2336 	ENTER();
2337 	if (pioctl_buf) {
2338 		info = (mlan_ds_get_info *)pioctl_buf->pbuf;
2339 		info->param.ver_ext.version_str_sel = ver_ext->version_str_sel;
2340 		memcpy(pmpriv->adapter, info->param.ver_ext.version_str,
2341 		       ver_ext->version_str, sizeof(char) * 128);
2342 	}
2343 	LEAVE();
2344 	return MLAN_STATUS_SUCCESS;
2345 }
2346 
2347 /**
2348  *  @brief Handle the rx mgmt forward registration resp
2349  *
2350  *  @param pmpriv       A pointer to mlan_private structure
2351  *  @param resp         A pointer to HostCmd_DS_COMMAND
2352  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
2353  *
2354  *  @return             MLAN_STATUS_SUCCESS
2355  */
2356 mlan_status
wlan_ret_rx_mgmt_ind(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * resp,IN mlan_ioctl_req * pioctl_buf)2357 wlan_ret_rx_mgmt_ind(IN pmlan_private pmpriv,
2358 		     IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
2359 {
2360 	mlan_ds_misc_cfg *misc = MNULL;
2361 	ENTER();
2362 
2363 	if (pioctl_buf) {
2364 		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
2365 		misc->param.mgmt_subtype_mask =
2366 			wlan_le32_to_cpu(resp->params.rx_mgmt_ind.
2367 					 mgmt_subtype_mask);
2368 	}
2369 
2370 	LEAVE();
2371 	return MLAN_STATUS_SUCCESS;
2372 }
2373 
2374 /**
2375  *  @brief This function checks conditions and prepares to
2376  *              send sleep confirm command to firmware if OK.
2377  *
2378  *  @param pmadapter    A pointer to mlan_adapter structure
2379  *
2380  *  @return             N/A
2381  */
2382 t_void
wlan_check_ps_cond(mlan_adapter * pmadapter)2383 wlan_check_ps_cond(mlan_adapter *pmadapter)
2384 {
2385 	ENTER();
2386 
2387 	if (!pmadapter->cmd_sent &&
2388 	    !pmadapter->curr_cmd && !IS_CARD_RX_RCVD(pmadapter)) {
2389 		wlan_dnld_sleep_confirm_cmd(pmadapter);
2390 	} else {
2391 		PRINTM(MCMND, "Delay Sleep Confirm (%s%s%s)\n",
2392 		       (pmadapter->cmd_sent) ? "D" : "",
2393 		       (pmadapter->curr_cmd) ? "C" : "",
2394 		       (IS_CARD_RX_RCVD(pmadapter)) ? "R" : "");
2395 	}
2396 
2397 	LEAVE();
2398 }
2399 
2400 /**
2401  *  @brief This function sends the HS_ACTIVATED event to the application
2402  *
2403  *  @param priv         A pointer to mlan_private structure
2404  *  @param activated    MTRUE if activated, MFALSE if de-activated
2405  *
2406  *  @return             N/A
2407  */
2408 t_void
wlan_host_sleep_activated_event(pmlan_private priv,t_u8 activated)2409 wlan_host_sleep_activated_event(pmlan_private priv, t_u8 activated)
2410 {
2411 	ENTER();
2412 
2413 	if (!priv) {
2414 		LEAVE();
2415 		return;
2416 	}
2417 
2418 	if (activated) {
2419 		if (priv->adapter->is_hs_configured) {
2420 			priv->adapter->hs_activated = MTRUE;
2421 			wlan_update_rxreorder_tbl(priv->adapter, MTRUE);
2422 			PRINTM(MEVENT, "hs_activated\n");
2423 			wlan_recv_event(priv, MLAN_EVENT_ID_DRV_HS_ACTIVATED,
2424 					MNULL);
2425 		} else
2426 			PRINTM(MWARN, "hs_activated: HS not configured !!!\n");
2427 	} else {
2428 		PRINTM(MEVENT, "hs_deactived\n");
2429 		priv->adapter->hs_activated = MFALSE;
2430 		wlan_recv_event(priv, MLAN_EVENT_ID_DRV_HS_DEACTIVATED, MNULL);
2431 	}
2432 
2433 	LEAVE();
2434 	return;
2435 }
2436 
2437 /**
2438  *  @brief This function sends the HS_WAKEUP event to the application
2439  *
2440  *  @param priv         A pointer to mlan_private structure
2441  *
2442  *  @return             N/A
2443  */
2444 t_void
wlan_host_sleep_wakeup_event(pmlan_private priv)2445 wlan_host_sleep_wakeup_event(pmlan_private priv)
2446 {
2447 	ENTER();
2448 
2449 	if (priv->adapter->is_hs_configured)
2450 		wlan_recv_event(priv, MLAN_EVENT_ID_FW_HS_WAKEUP, MNULL);
2451 	else
2452 		PRINTM(MWARN, "hs_wakeup: Host Sleep not configured !!!\n");
2453 
2454 	LEAVE();
2455 }
2456 
2457 /**
2458  *  @brief This function handles the command response of hs_cfg
2459  *
2460  *  @param pmpriv       A pointer to mlan_private structure
2461  *  @param resp         A pointer to HostCmd_DS_COMMAND
2462  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
2463  *
2464  *  @return             MLAN_STATUS_SUCCESS
2465  */
2466 mlan_status
wlan_ret_802_11_hs_cfg(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * resp,IN mlan_ioctl_req * pioctl_buf)2467 wlan_ret_802_11_hs_cfg(IN pmlan_private pmpriv,
2468 		       IN HostCmd_DS_COMMAND *resp,
2469 		       IN mlan_ioctl_req *pioctl_buf)
2470 {
2471 	pmlan_adapter pmadapter = pmpriv->adapter;
2472 	HostCmd_DS_802_11_HS_CFG_ENH *phs_cfg = &resp->params.opt_hs_cfg;
2473 
2474 	ENTER();
2475 
2476 	if (wlan_le16_to_cpu(phs_cfg->action) == HS_ACTIVATE) {
2477 		/* clean up curr_cmd to allow suspend */
2478 		if (pioctl_buf)
2479 			pioctl_buf->status_code = MLAN_ERROR_NO_ERROR;
2480 		/* Clean up and put current command back to cmd_free_q */
2481 		wlan_request_cmd_lock(pmadapter);
2482 		wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd);
2483 		pmadapter->curr_cmd = MNULL;
2484 		wlan_release_cmd_lock(pmadapter);
2485 		wlan_host_sleep_activated_event(pmpriv, MTRUE);
2486 		goto done;
2487 	} else {
2488 		phs_cfg->params.hs_config.conditions =
2489 			wlan_le32_to_cpu(phs_cfg->params.hs_config.conditions);
2490 		PRINTM(MCMND,
2491 		       "CMD_RESP: HS_CFG cmd reply result=%#x,"
2492 		       " conditions=0x%x gpio=0x%x gap=0x%x\n", resp->result,
2493 		       phs_cfg->params.hs_config.conditions,
2494 		       phs_cfg->params.hs_config.gpio,
2495 		       phs_cfg->params.hs_config.gap);
2496 	}
2497 	if (phs_cfg->params.hs_config.conditions != HOST_SLEEP_CFG_CANCEL) {
2498 		pmadapter->is_hs_configured = MTRUE;
2499 	} else {
2500 		pmadapter->is_hs_configured = MFALSE;
2501 		if (pmadapter->hs_activated)
2502 			wlan_host_sleep_activated_event(pmpriv, MFALSE);
2503 	}
2504 
2505 done:
2506 	LEAVE();
2507 	return MLAN_STATUS_SUCCESS;
2508 }
2509 
2510 /**
2511  *  @brief Perform hs related activities on receiving the power up interrupt
2512  *
2513  *  @param pmadapter  A pointer to the adapter structure
2514  *  @return           N/A
2515  */
2516 t_void
wlan_process_hs_config(pmlan_adapter pmadapter)2517 wlan_process_hs_config(pmlan_adapter pmadapter)
2518 {
2519 	ENTER();
2520 	PRINTM(MINFO, "Recevie interrupt/data in HS mode\n");
2521 	if (pmadapter->hs_cfg.gap == HOST_SLEEP_CFG_GAP_FF)
2522 		wlan_pm_wakeup_card(pmadapter);
2523 	LEAVE();
2524 	return;
2525 }
2526 
2527 /**
2528  *  @brief Check sleep confirm command response and set the state to ASLEEP
2529  *
2530  *  @param pmadapter  A pointer to the adapter structure
2531  *  @param pbuf       A pointer to the command response buffer
2532  *  @param upld_len   Command response buffer length
2533  *  @return           N/A
2534  */
2535 void
wlan_process_sleep_confirm_resp(pmlan_adapter pmadapter,t_u8 * pbuf,t_u32 upld_len)2536 wlan_process_sleep_confirm_resp(pmlan_adapter pmadapter, t_u8 *pbuf,
2537 				t_u32 upld_len)
2538 {
2539 	HostCmd_DS_COMMAND *cmd;
2540 
2541 	ENTER();
2542 
2543 	if (!upld_len) {
2544 		PRINTM(MERROR, "Command size is 0\n");
2545 		LEAVE();
2546 		return;
2547 	}
2548 	cmd = (HostCmd_DS_COMMAND *)pbuf;
2549 	cmd->result = wlan_le16_to_cpu(cmd->result);
2550 	cmd->command = wlan_le16_to_cpu(cmd->command);
2551 	cmd->seq_num = wlan_le16_to_cpu(cmd->seq_num);
2552 
2553 	/* Update sequence number */
2554 	cmd->seq_num = HostCmd_GET_SEQ_NO(cmd->seq_num);
2555 	/* Clear RET_BIT from HostCmd */
2556 	cmd->command &= HostCmd_CMD_ID_MASK;
2557 
2558 	if (cmd->command != HostCmd_CMD_802_11_PS_MODE_ENH) {
2559 		PRINTM(MERROR,
2560 		       "Received unexpected response for command %x, result = %x\n",
2561 		       cmd->command, cmd->result);
2562 		LEAVE();
2563 		return;
2564 	}
2565 	PRINTM(MEVENT, "#\n");
2566 	if (cmd->result != MLAN_STATUS_SUCCESS) {
2567 		PRINTM(MERROR, "Sleep confirm command failed\n");
2568 		pmadapter->pm_wakeup_card_req = MFALSE;
2569 		pmadapter->ps_state = PS_STATE_AWAKE;
2570 		LEAVE();
2571 		return;
2572 	}
2573 	pmadapter->pm_wakeup_card_req = MTRUE;
2574 
2575 	if (pmadapter->is_hs_configured) {
2576 		wlan_host_sleep_activated_event(wlan_get_priv
2577 						(pmadapter, MLAN_BSS_ROLE_ANY),
2578 						MTRUE);
2579 	}
2580 	pmadapter->ps_state = PS_STATE_SLEEP;
2581 	LEAVE();
2582 }
2583 
2584 /**
2585  *  @brief This function prepares command of power mode
2586  *
2587  *  @param pmpriv       A pointer to mlan_private structure
2588  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
2589  *  @param cmd_action   the action: GET or SET
2590  *  @param ps_bitmap    PS bitmap
2591  *  @param pdata_buf    A pointer to data buffer
2592  *  @return             MLAN_STATUS_SUCCESS
2593  */
2594 mlan_status
wlan_cmd_enh_power_mode(pmlan_private pmpriv,IN HostCmd_DS_COMMAND * cmd,IN t_u16 cmd_action,IN t_u16 ps_bitmap,IN t_void * pdata_buf)2595 wlan_cmd_enh_power_mode(pmlan_private pmpriv,
2596 			IN HostCmd_DS_COMMAND *cmd,
2597 			IN t_u16 cmd_action,
2598 			IN t_u16 ps_bitmap, IN t_void *pdata_buf)
2599 {
2600 	HostCmd_DS_802_11_PS_MODE_ENH *psmode_enh = &cmd->params.psmode_enh;
2601 	t_u8 *tlv = MNULL;
2602 	t_u16 cmd_size = 0;
2603 
2604 	ENTER();
2605 
2606 	PRINTM(MCMND, "PS Command: action = 0x%x, bitmap = 0x%x\n", cmd_action,
2607 	       ps_bitmap);
2608 
2609 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH);
2610 	if (cmd_action == DIS_AUTO_PS) {
2611 		psmode_enh->action = wlan_cpu_to_le16(DIS_AUTO_PS);
2612 		psmode_enh->params.ps_bitmap = wlan_cpu_to_le16(ps_bitmap);
2613 		cmd->size = wlan_cpu_to_le16(S_DS_GEN + AUTO_PS_FIX_SIZE);
2614 	} else if (cmd_action == GET_PS) {
2615 		psmode_enh->action = wlan_cpu_to_le16(GET_PS);
2616 		psmode_enh->params.ps_bitmap = wlan_cpu_to_le16(ps_bitmap);
2617 		cmd->size = wlan_cpu_to_le16(S_DS_GEN + AUTO_PS_FIX_SIZE);
2618 	} else if (cmd_action == EN_AUTO_PS) {
2619 		psmode_enh->action = wlan_cpu_to_le16(EN_AUTO_PS);
2620 		psmode_enh->params.auto_ps.ps_bitmap =
2621 			wlan_cpu_to_le16(ps_bitmap);
2622 		cmd_size = S_DS_GEN + AUTO_PS_FIX_SIZE;
2623 		tlv = (t_u8 *)cmd + cmd_size;
2624 		if (ps_bitmap & BITMAP_STA_PS) {
2625 			pmlan_adapter pmadapter = pmpriv->adapter;
2626 			MrvlIEtypes_ps_param_t *ps_tlv =
2627 				(MrvlIEtypes_ps_param_t *)tlv;
2628 			ps_param *ps_mode = &ps_tlv->param;
2629 			ps_tlv->header.type =
2630 				wlan_cpu_to_le16(TLV_TYPE_PS_PARAM);
2631 			ps_tlv->header.len =
2632 				wlan_cpu_to_le16(sizeof(MrvlIEtypes_ps_param_t)
2633 						 - sizeof(MrvlIEtypesHeader_t));
2634 			cmd_size += sizeof(MrvlIEtypes_ps_param_t);
2635 			tlv += sizeof(MrvlIEtypes_ps_param_t);
2636 			ps_mode->null_pkt_interval =
2637 				wlan_cpu_to_le16(pmadapter->null_pkt_interval);
2638 			ps_mode->multiple_dtims =
2639 				wlan_cpu_to_le16(pmadapter->multiple_dtim);
2640 			ps_mode->bcn_miss_timeout =
2641 				wlan_cpu_to_le16(pmadapter->bcn_miss_time_out);
2642 			ps_mode->local_listen_interval =
2643 				wlan_cpu_to_le16(pmadapter->
2644 						 local_listen_interval);
2645 			ps_mode->adhoc_wake_period =
2646 				wlan_cpu_to_le16(pmadapter->adhoc_awake_period);
2647 			ps_mode->delay_to_ps =
2648 				wlan_cpu_to_le16(pmadapter->delay_to_ps);
2649 			ps_mode->mode =
2650 				wlan_cpu_to_le16(pmadapter->enhanced_ps_mode);
2651 		}
2652 		if (ps_bitmap & BITMAP_BCN_TMO) {
2653 			MrvlIEtypes_bcn_timeout_t *bcn_tmo_tlv =
2654 				(MrvlIEtypes_bcn_timeout_t *) tlv;
2655 			mlan_ds_bcn_timeout *bcn_tmo =
2656 				(mlan_ds_bcn_timeout *) pdata_buf;
2657 			bcn_tmo_tlv->header.type =
2658 				wlan_cpu_to_le16(TLV_TYPE_BCN_TIMEOUT);
2659 			bcn_tmo_tlv->header.len =
2660 				wlan_cpu_to_le16(sizeof
2661 						 (MrvlIEtypes_bcn_timeout_t) -
2662 						 sizeof(MrvlIEtypesHeader_t));
2663 			bcn_tmo_tlv->bcn_miss_tmo_window =
2664 				wlan_cpu_to_le16(bcn_tmo->bcn_miss_tmo_window);
2665 			bcn_tmo_tlv->bcn_miss_tmo_period =
2666 				wlan_cpu_to_le16(bcn_tmo->bcn_miss_tmo_period);
2667 			bcn_tmo_tlv->bcn_rq_tmo_window =
2668 				wlan_cpu_to_le16(bcn_tmo->bcn_rq_tmo_window);
2669 			bcn_tmo_tlv->bcn_rq_tmo_period =
2670 				wlan_cpu_to_le16(bcn_tmo->bcn_rq_tmo_period);
2671 			cmd_size += sizeof(MrvlIEtypes_bcn_timeout_t);
2672 			tlv += sizeof(MrvlIEtypes_bcn_timeout_t);
2673 
2674 			psmode_enh->params.auto_ps.ps_bitmap =
2675 				wlan_cpu_to_le16((ps_bitmap & (~BITMAP_BCN_TMO))
2676 						 | BITMAP_STA_PS);
2677 		}
2678 		if (ps_bitmap & BITMAP_AUTO_DS) {
2679 			MrvlIEtypes_auto_ds_param_t *auto_ps_tlv =
2680 				(MrvlIEtypes_auto_ds_param_t *)tlv;
2681 			auto_ds_param *auto_ds = &auto_ps_tlv->param;
2682 			t_u16 idletime = 0;
2683 			auto_ps_tlv->header.type =
2684 				wlan_cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM);
2685 			auto_ps_tlv->header.len =
2686 				wlan_cpu_to_le16(sizeof
2687 						 (MrvlIEtypes_auto_ds_param_t) -
2688 						 sizeof(MrvlIEtypesHeader_t));
2689 			cmd_size += sizeof(MrvlIEtypes_auto_ds_param_t);
2690 			tlv += sizeof(MrvlIEtypes_auto_ds_param_t);
2691 			if (pdata_buf)
2692 				idletime =
2693 					((mlan_ds_auto_ds *)pdata_buf)->
2694 					idletime;
2695 			auto_ds->deep_sleep_timeout =
2696 				wlan_cpu_to_le16(idletime);
2697 		}
2698 #if defined(UAP_SUPPORT)
2699 		if (pdata_buf &&
2700 		    (ps_bitmap & (BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS))) {
2701 			mlan_ds_ps_mgmt *ps_mgmt = (mlan_ds_ps_mgmt *)pdata_buf;
2702 			MrvlIEtypes_sleep_param_t *sleep_tlv = MNULL;
2703 			MrvlIEtypes_inact_sleep_param_t *inact_tlv = MNULL;
2704 			if (ps_mgmt->flags & PS_FLAG_SLEEP_PARAM) {
2705 				sleep_tlv = (MrvlIEtypes_sleep_param_t *)tlv;
2706 				sleep_tlv->header.type =
2707 					wlan_cpu_to_le16
2708 					(TLV_TYPE_AP_SLEEP_PARAM);
2709 				sleep_tlv->header.len =
2710 					wlan_cpu_to_le16(sizeof
2711 							 (MrvlIEtypes_sleep_param_t)
2712 							 -
2713 							 sizeof
2714 							 (MrvlIEtypesHeader_t));
2715 				sleep_tlv->ctrl_bitmap =
2716 					wlan_cpu_to_le32(ps_mgmt->sleep_param.
2717 							 ctrl_bitmap);
2718 				sleep_tlv->min_sleep =
2719 					wlan_cpu_to_le32(ps_mgmt->sleep_param.
2720 							 min_sleep);
2721 				sleep_tlv->max_sleep =
2722 					wlan_cpu_to_le32(ps_mgmt->sleep_param.
2723 							 max_sleep);
2724 				cmd_size += sizeof(MrvlIEtypes_sleep_param_t);
2725 				tlv += sizeof(MrvlIEtypes_sleep_param_t);
2726 			}
2727 			if (ps_mgmt->flags & PS_FLAG_INACT_SLEEP_PARAM) {
2728 				inact_tlv =
2729 					(MrvlIEtypes_inact_sleep_param_t *)tlv;
2730 				inact_tlv->header.type =
2731 					wlan_cpu_to_le16
2732 					(TLV_TYPE_AP_INACT_SLEEP_PARAM);
2733 				inact_tlv->header.len =
2734 					wlan_cpu_to_le16(sizeof
2735 							 (MrvlIEtypes_inact_sleep_param_t)
2736 							 -
2737 							 sizeof
2738 							 (MrvlIEtypesHeader_t));
2739 				inact_tlv->inactivity_to =
2740 					wlan_cpu_to_le32(ps_mgmt->inact_param.
2741 							 inactivity_to);
2742 				inact_tlv->min_awake =
2743 					wlan_cpu_to_le32(ps_mgmt->inact_param.
2744 							 min_awake);
2745 				inact_tlv->max_awake =
2746 					wlan_cpu_to_le32(ps_mgmt->inact_param.
2747 							 max_awake);
2748 				cmd_size +=
2749 					sizeof(MrvlIEtypes_inact_sleep_param_t);
2750 				tlv += sizeof(MrvlIEtypes_inact_sleep_param_t);
2751 			}
2752 		}
2753 #endif
2754 		cmd->size = wlan_cpu_to_le16(cmd_size);
2755 	}
2756 
2757 	LEAVE();
2758 	return MLAN_STATUS_SUCCESS;
2759 }
2760 
2761 /**
2762  *  @brief This function handles the command response of ps_mode_enh
2763  *
2764  *  @param pmpriv       A pointer to mlan_private structure
2765  *  @param resp         A pointer to HostCmd_DS_COMMAND
2766  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
2767  *
2768  *  @return             MLAN_STATUS_SUCCESS
2769  */
2770 mlan_status
wlan_ret_enh_power_mode(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * resp,IN mlan_ioctl_req * pioctl_buf)2771 wlan_ret_enh_power_mode(IN pmlan_private pmpriv,
2772 			IN HostCmd_DS_COMMAND *resp,
2773 			IN mlan_ioctl_req *pioctl_buf)
2774 {
2775 	pmlan_adapter pmadapter = pmpriv->adapter;
2776 	MrvlIEtypesHeader_t *mrvl_tlv = MNULL;
2777 	MrvlIEtypes_auto_ds_param_t *auto_ds_tlv = MNULL;
2778 	HostCmd_DS_802_11_PS_MODE_ENH *ps_mode = &resp->params.psmode_enh;
2779 
2780 	ENTER();
2781 
2782 	ps_mode->action = wlan_le16_to_cpu(ps_mode->action);
2783 	PRINTM(MINFO, "CMD_RESP: PS_MODE cmd reply result=%#x action=0x%X\n",
2784 	       resp->result, ps_mode->action);
2785 	if (ps_mode->action == EN_AUTO_PS) {
2786 		ps_mode->params.auto_ps.ps_bitmap =
2787 			wlan_le16_to_cpu(ps_mode->params.auto_ps.ps_bitmap);
2788 		if (ps_mode->params.auto_ps.ps_bitmap & BITMAP_AUTO_DS) {
2789 			PRINTM(MCMND, "Enabled auto deep sleep\n");
2790 			pmpriv->adapter->is_deep_sleep = MTRUE;
2791 			mrvl_tlv =
2792 				(MrvlIEtypesHeader_t *)((t_u8 *)ps_mode +
2793 							AUTO_PS_FIX_SIZE);
2794 			while (wlan_le16_to_cpu(mrvl_tlv->type) !=
2795 			       TLV_TYPE_AUTO_DS_PARAM) {
2796 				mrvl_tlv =
2797 					(MrvlIEtypesHeader_t *)((t_u8 *)mrvl_tlv
2798 								+
2799 								wlan_le16_to_cpu
2800 								(mrvl_tlv->len)
2801 								+
2802 								sizeof
2803 								(MrvlIEtypesHeader_t));
2804 			}
2805 			auto_ds_tlv = (MrvlIEtypes_auto_ds_param_t *)mrvl_tlv;
2806 			pmpriv->adapter->idle_time =
2807 				wlan_le16_to_cpu(auto_ds_tlv->param.
2808 						 deep_sleep_timeout);
2809 		}
2810 		if (ps_mode->params.auto_ps.ps_bitmap & BITMAP_STA_PS) {
2811 			PRINTM(MCMND, "Enabled STA power save\n");
2812 			if (pmadapter->sleep_period.period) {
2813 				PRINTM(MCMND,
2814 				       "Setting uapsd/pps mode to TRUE\n");
2815 			}
2816 		}
2817 #if defined(UAP_SUPPORT)
2818 		if (ps_mode->params.auto_ps.
2819 		    ps_bitmap & (BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS)) {
2820 			pmadapter->ps_mode = Wlan802_11PowerModePSP;
2821 			PRINTM(MCMND, "Enabled uAP power save\n");
2822 		}
2823 #endif
2824 	} else if (ps_mode->action == DIS_AUTO_PS) {
2825 		ps_mode->params.ps_bitmap =
2826 			wlan_cpu_to_le16(ps_mode->params.ps_bitmap);
2827 		if (ps_mode->params.ps_bitmap & BITMAP_AUTO_DS) {
2828 			pmpriv->adapter->is_deep_sleep = MFALSE;
2829 			PRINTM(MCMND, "Disabled auto deep sleep\n");
2830 		}
2831 		if (ps_mode->params.ps_bitmap & BITMAP_STA_PS) {
2832 			PRINTM(MCMND, "Disabled STA power save\n");
2833 			if (pmadapter->sleep_period.period) {
2834 				pmadapter->delay_null_pkt = MFALSE;
2835 				pmadapter->tx_lock_flag = MFALSE;
2836 				pmadapter->pps_uapsd_mode = MFALSE;
2837 			}
2838 		}
2839 #if defined(UAP_SUPPORT)
2840 		if (ps_mode->params.
2841 		    ps_bitmap & (BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS)) {
2842 			pmadapter->ps_mode = Wlan802_11PowerModeCAM;
2843 			PRINTM(MCMND, "Disabled uAP power save\n");
2844 		}
2845 #endif
2846 	} else if (ps_mode->action == GET_PS) {
2847 		ps_mode->params.ps_bitmap =
2848 			wlan_le16_to_cpu(ps_mode->params.ps_bitmap);
2849 		if (ps_mode->params.auto_ps.
2850 		    ps_bitmap & (BITMAP_STA_PS | BITMAP_UAP_INACT_PS |
2851 				 BITMAP_UAP_DTIM_PS))
2852 			pmadapter->ps_mode = Wlan802_11PowerModePSP;
2853 		else
2854 			pmadapter->ps_mode = Wlan802_11PowerModeCAM;
2855 		PRINTM(MCMND, "ps_bitmap=0x%x\n", ps_mode->params.ps_bitmap);
2856 		if (pioctl_buf) {
2857 			mlan_ds_pm_cfg *pm_cfg =
2858 				(mlan_ds_pm_cfg *)pioctl_buf->pbuf;
2859 			if (pm_cfg->sub_command == MLAN_OID_PM_CFG_IEEE_PS) {
2860 				if (ps_mode->params.auto_ps.
2861 				    ps_bitmap & BITMAP_STA_PS)
2862 					pm_cfg->param.ps_mode = 1;
2863 				else
2864 					pm_cfg->param.ps_mode = 0;
2865 			}
2866 #if defined(UAP_SUPPORT)
2867 			if (pm_cfg->sub_command == MLAN_OID_PM_CFG_PS_MODE) {
2868 				MrvlIEtypes_sleep_param_t *sleep_tlv = MNULL;
2869 				MrvlIEtypes_inact_sleep_param_t *inact_tlv =
2870 					MNULL;
2871 				MrvlIEtypesHeader_t *tlv = MNULL;
2872 				t_u16 tlv_type = 0;
2873 				t_u16 tlv_len = 0;
2874 				t_u16 tlv_buf_left = 0;
2875 				pm_cfg->param.ps_mgmt.flags = PS_FLAG_PS_MODE;
2876 				if (ps_mode->params.
2877 				    ps_bitmap & BITMAP_UAP_INACT_PS)
2878 					pm_cfg->param.ps_mgmt.ps_mode =
2879 						PS_MODE_INACTIVITY;
2880 				else if (ps_mode->params.
2881 					 ps_bitmap & BITMAP_UAP_DTIM_PS)
2882 					pm_cfg->param.ps_mgmt.ps_mode =
2883 						PS_MODE_PERIODIC_DTIM;
2884 				else
2885 					pm_cfg->param.ps_mgmt.ps_mode =
2886 						PS_MODE_DISABLE;
2887 				tlv_buf_left =
2888 					resp->size - (S_DS_GEN +
2889 						      AUTO_PS_FIX_SIZE);
2890 				tlv = (MrvlIEtypesHeader_t *)((t_u8 *)ps_mode +
2891 							      AUTO_PS_FIX_SIZE);
2892 				while (tlv_buf_left >=
2893 				       sizeof(MrvlIEtypesHeader_t)) {
2894 					tlv_type = wlan_le16_to_cpu(tlv->type);
2895 					tlv_len = wlan_le16_to_cpu(tlv->len);
2896 					switch (tlv_type) {
2897 					case TLV_TYPE_AP_SLEEP_PARAM:
2898 						sleep_tlv =
2899 							(MrvlIEtypes_sleep_param_t
2900 							 *)tlv;
2901 						pm_cfg->param.ps_mgmt.flags |=
2902 							PS_FLAG_SLEEP_PARAM;
2903 						pm_cfg->param.ps_mgmt.
2904 							sleep_param.
2905 							ctrl_bitmap =
2906 							wlan_le32_to_cpu
2907 							(sleep_tlv->
2908 							 ctrl_bitmap);
2909 						pm_cfg->param.ps_mgmt.
2910 							sleep_param.min_sleep =
2911 							wlan_le32_to_cpu
2912 							(sleep_tlv->min_sleep);
2913 						pm_cfg->param.ps_mgmt.
2914 							sleep_param.max_sleep =
2915 							wlan_le32_to_cpu
2916 							(sleep_tlv->max_sleep);
2917 						break;
2918 					case TLV_TYPE_AP_INACT_SLEEP_PARAM:
2919 						inact_tlv =
2920 							(MrvlIEtypes_inact_sleep_param_t
2921 							 *)tlv;
2922 						pm_cfg->param.ps_mgmt.flags |=
2923 							PS_FLAG_INACT_SLEEP_PARAM;
2924 						pm_cfg->param.ps_mgmt.
2925 							inact_param.
2926 							inactivity_to =
2927 							wlan_le32_to_cpu
2928 							(inact_tlv->
2929 							 inactivity_to);
2930 						pm_cfg->param.ps_mgmt.
2931 							inact_param.min_awake =
2932 							wlan_le32_to_cpu
2933 							(inact_tlv->min_awake);
2934 						pm_cfg->param.ps_mgmt.
2935 							inact_param.max_awake =
2936 							wlan_le32_to_cpu
2937 							(inact_tlv->max_awake);
2938 						break;
2939 					}
2940 					tlv_buf_left -=
2941 						tlv_len +
2942 						sizeof(MrvlIEtypesHeader_t);
2943 					tlv = (MrvlIEtypesHeader_t *)((t_u8 *)
2944 								      tlv +
2945 								      tlv_len +
2946 								      sizeof
2947 								      (MrvlIEtypesHeader_t));
2948 				}
2949 			}
2950 #endif
2951 		}
2952 	}
2953 
2954 	LEAVE();
2955 	return MLAN_STATUS_SUCCESS;
2956 }
2957 
2958 /**
2959  *  @brief This function handles the command response of tx rate query
2960  *
2961  *  @param pmpriv       A pointer to mlan_private structure
2962  *  @param resp         A pointer to HostCmd_DS_COMMAND
2963  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
2964  *
2965  *  @return             MLAN_STATUS_SUCCESS
2966  */
2967 mlan_status
wlan_ret_802_11_tx_rate_query(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * resp,IN mlan_ioctl_req * pioctl_buf)2968 wlan_ret_802_11_tx_rate_query(IN pmlan_private pmpriv,
2969 			      IN HostCmd_DS_COMMAND *resp,
2970 			      IN mlan_ioctl_req *pioctl_buf)
2971 {
2972 	mlan_adapter *pmadapter = pmpriv->adapter;
2973 	mlan_ds_rate *rate = MNULL;
2974 	ENTER();
2975 
2976 	pmpriv->tx_rate = resp->params.tx_rate.tx_rate;
2977 	pmpriv->tx_rate_info = resp->params.tx_rate.tx_rate_info;
2978 
2979 	if (!pmpriv->is_data_rate_auto) {
2980 		pmpriv->data_rate = wlan_index_to_data_rate(pmadapter,
2981 							    pmpriv->tx_rate,
2982 							    pmpriv->
2983 							    tx_rate_info);
2984 	}
2985 
2986 	if (pioctl_buf) {
2987 		rate = (mlan_ds_rate *)pioctl_buf->pbuf;
2988 		if (rate->sub_command == MLAN_OID_RATE_CFG) {
2989 			if (rate->param.rate_cfg.rate_type == MLAN_RATE_INDEX) {
2990 				if ((pmpriv->tx_rate_info & 0x3) ==
2991 				    MLAN_RATE_FORMAT_HT)
2992 					/* HT rate */
2993 					rate->param.rate_cfg.rate =
2994 						pmpriv->tx_rate +
2995 						MLAN_RATE_INDEX_MCS0;
2996 				else
2997 					/* LG rate */
2998 					/* For HostCmd_CMD_802_11_TX_RATE_QUERY,
2999 					 * there is a hole (0x4) in rate table
3000 					 * between HR/DSSS and OFDM rates,
3001 					 * so minus 1 for OFDM rate index */
3002 					rate->param.rate_cfg.rate =
3003 						(pmpriv->tx_rate >
3004 						 MLAN_RATE_INDEX_OFDM0) ?
3005 						pmpriv->tx_rate -
3006 						1 : pmpriv->tx_rate;
3007 			} else {
3008 				/* rate_type = MLAN_RATE_VALUE */
3009 				rate->param.rate_cfg.rate =
3010 					wlan_index_to_data_rate(pmadapter,
3011 								pmpriv->tx_rate,
3012 								pmpriv->
3013 								tx_rate_info);
3014 			}
3015 		} else if (rate->sub_command == MLAN_OID_GET_DATA_RATE) {
3016 			/* Tx rate info */
3017 			if ((pmpriv->tx_rate_info & 0x3) == MLAN_RATE_FORMAT_HT) {
3018 				/* HT rate */
3019 				rate->param.data_rate.tx_rate_format =
3020 					MLAN_RATE_FORMAT_HT;
3021 				rate->param.data_rate.tx_ht_bw =
3022 					(pmpriv->tx_rate_info & 0xC) >> 2;
3023 				rate->param.data_rate.tx_ht_gi =
3024 					(pmpriv->tx_rate_info & 0x10) >> 4;
3025 				rate->param.data_rate.tx_mcs_index =
3026 					pmpriv->tx_rate;
3027 				rate->param.data_rate.tx_data_rate =
3028 					wlan_index_to_data_rate(pmadapter,
3029 								pmpriv->tx_rate,
3030 								pmpriv->
3031 								tx_rate_info);
3032 			} else {
3033 				/* LG rate */
3034 				rate->param.data_rate.tx_rate_format =
3035 					MLAN_RATE_FORMAT_LG;
3036 				/* For HostCmd_CMD_802_11_TX_RATE_QUERY,
3037 				 * there is a hole in rate table
3038 				 * between HR/DSSS and OFDM rates,
3039 				 * so minus 1 for OFDM rate index */
3040 				rate->param.data_rate.tx_data_rate =
3041 					(pmpriv->tx_rate >
3042 					 MLAN_RATE_INDEX_OFDM0) ? pmpriv->
3043 					tx_rate - 1 : pmpriv->tx_rate;
3044 			}
3045 
3046 			/* Rx rate info */
3047 			if ((pmpriv->rxpd_rate_info & 0x3) ==
3048 			    MLAN_RATE_FORMAT_HT) {
3049 				/* HT rate */
3050 				rate->param.data_rate.rx_rate_format =
3051 					MLAN_RATE_FORMAT_HT;
3052 				rate->param.data_rate.rx_ht_bw =
3053 					(pmpriv->rxpd_rate_info & 0xC) >> 2;
3054 				rate->param.data_rate.rx_ht_gi =
3055 					(pmpriv->rxpd_rate_info & 0x10) >> 4;
3056 				rate->param.data_rate.rx_mcs_index =
3057 					pmpriv->rxpd_rate;
3058 				rate->param.data_rate.rx_data_rate =
3059 					wlan_index_to_data_rate(pmadapter,
3060 								pmpriv->
3061 								rxpd_rate,
3062 								pmpriv->
3063 								rxpd_rate_info);
3064 			} else {
3065 				/* LG rate */
3066 				rate->param.data_rate.rx_rate_format =
3067 					MLAN_RATE_FORMAT_LG;
3068 				/* For rate index in RxPD,
3069 				 * there is a hole in rate table
3070 				 * between HR/DSSS and OFDM rates,
3071 				 * so minus 1 for OFDM rate index */
3072 				rate->param.data_rate.rx_data_rate =
3073 					(pmpriv->rxpd_rate >
3074 					 MLAN_RATE_INDEX_OFDM0) ? pmpriv->
3075 					rxpd_rate - 1 : pmpriv->rxpd_rate;
3076 			}
3077 		}
3078 		pioctl_buf->data_read_written = sizeof(mlan_data_rate) +
3079 			MLAN_SUB_COMMAND_SIZE;
3080 	}
3081 	LEAVE();
3082 	return MLAN_STATUS_SUCCESS;
3083 }
3084 
3085 /**
3086  * @brief This function prepares command of fw_wakeup_method.
3087  *
3088  * @param pmpriv       A pointer to mlan_private structure
3089  * @param cmd          A pointer to HostCmd_DS_COMMAND structure
3090  * @param cmd_action   The action: GET or SET
3091  * @param pdata_buf    A pointer to data buffer
3092  *
3093  * @return             MLAN_STATUS_SUCCESS
3094  */
3095 mlan_status
wlan_cmd_802_11_fw_wakeup_method(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * cmd,IN t_u16 cmd_action,IN t_u16 * pdata_buf)3096 wlan_cmd_802_11_fw_wakeup_method(IN pmlan_private pmpriv,
3097 				 IN HostCmd_DS_COMMAND *cmd,
3098 				 IN t_u16 cmd_action, IN t_u16 *pdata_buf)
3099 {
3100 	HostCmd_DS_802_11_FW_WAKEUP_METHOD *fwwm = &cmd->params.fwwakeupmethod;
3101 	mlan_fw_wakeup_params *fw_wakeup_params = MNULL;
3102 	MrvlIEtypes_WakeupSourceGPIO_t *tlv =
3103 		(MrvlIEtypes_WakeupSourceGPIO_t *) ((t_u8 *)fwwm +
3104 						    sizeof
3105 						    (HostCmd_DS_802_11_FW_WAKEUP_METHOD));
3106 
3107 	ENTER();
3108 
3109 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_FW_WAKE_METHOD);
3110 	cmd->size = sizeof(HostCmd_DS_802_11_FW_WAKEUP_METHOD) + S_DS_GEN;
3111 	fwwm->action = wlan_cpu_to_le16(cmd_action);
3112 	switch (cmd_action) {
3113 	case HostCmd_ACT_GEN_SET:
3114 		fw_wakeup_params = (mlan_fw_wakeup_params *) pdata_buf;
3115 		fwwm->method = wlan_cpu_to_le16(fw_wakeup_params->method);
3116 
3117 		if (fw_wakeup_params->method == WAKEUP_FW_THRU_GPIO) {
3118 			cmd->size += sizeof(MrvlIEtypes_WakeupSourceGPIO_t);
3119 			tlv->header.type =
3120 				wlan_cpu_to_le16
3121 				(TLV_TYPE_HS_WAKEUP_SOURCE_GPIO);
3122 			tlv->header.len =
3123 				wlan_cpu_to_le16(sizeof
3124 						 (MrvlIEtypes_WakeupSourceGPIO_t)
3125 						 - sizeof(MrvlIEtypesHeader_t));
3126 			tlv->ind_gpio = (t_u8)fw_wakeup_params->gpio_pin;
3127 		}
3128 
3129 		break;
3130 	case HostCmd_ACT_GEN_GET:
3131 	default:
3132 		fwwm->method = wlan_cpu_to_le16(WAKEUP_FW_UNCHANGED);
3133 		break;
3134 	}
3135 	cmd->size = wlan_cpu_to_le16(cmd->size);
3136 	LEAVE();
3137 	return MLAN_STATUS_SUCCESS;
3138 }
3139 
3140 /**
3141  *  @brief This function handles the command response of fw_wakeup_method
3142  *
3143  *  @param pmpriv       A pointer to mlan_private structure
3144  *  @param resp         A pointer to HostCmd_DS_COMMAND
3145  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
3146  *
3147  *  @return             MLAN_STATUS_SUCCESS
3148  */
3149 mlan_status
wlan_ret_fw_wakeup_method(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * resp,IN mlan_ioctl_req * pioctl_buf)3150 wlan_ret_fw_wakeup_method(IN pmlan_private pmpriv,
3151 			  IN HostCmd_DS_COMMAND *resp,
3152 			  IN mlan_ioctl_req *pioctl_buf)
3153 {
3154 	HostCmd_DS_802_11_FW_WAKEUP_METHOD *fwwm = &resp->params.fwwakeupmethod;
3155 	t_u16 action;
3156 	MrvlIEtypes_WakeupSourceGPIO_t *gpio_tlv =
3157 		(MrvlIEtypes_WakeupSourceGPIO_t *) ((t_u8 *)fwwm +
3158 						    sizeof
3159 						    (HostCmd_DS_802_11_FW_WAKEUP_METHOD));
3160 	mlan_ds_pm_cfg *pmcfg = MNULL;
3161 
3162 	ENTER();
3163 
3164 	action = wlan_le16_to_cpu(fwwm->action);
3165 
3166 	pmpriv->adapter->fw_wakeup_method = wlan_le16_to_cpu(fwwm->method);
3167 	pmpriv->adapter->fw_wakeup_gpio_pin = 0;
3168 
3169 	if ((resp->size -
3170 	     (sizeof(HostCmd_DS_802_11_FW_WAKEUP_METHOD) + S_DS_GEN))
3171 	    == sizeof(MrvlIEtypes_WakeupSourceGPIO_t)) {
3172 		pmpriv->adapter->fw_wakeup_gpio_pin = gpio_tlv->ind_gpio;
3173 	}
3174 	PRINTM(MCMND, "FW wakeup method=%d, gpio=%d\n",
3175 	       pmpriv->adapter->fw_wakeup_method,
3176 	       pmpriv->adapter->fw_wakeup_gpio_pin);
3177 
3178 	if (pioctl_buf) {
3179 		pmcfg = (mlan_ds_pm_cfg *)pioctl_buf->pbuf;
3180 		pmcfg->param.fw_wakeup_params.method =
3181 			pmpriv->adapter->fw_wakeup_method;
3182 		pmcfg->param.fw_wakeup_params.gpio_pin =
3183 			pmpriv->adapter->fw_wakeup_gpio_pin;
3184 	}
3185 	LEAVE();
3186 	return MLAN_STATUS_SUCCESS;
3187 }
3188 
3189 /**
3190  * @brief This function prepares command of robustcoex.
3191  *
3192  * @param pmpriv       A pointer to mlan_private structure
3193  * @param cmd          A pointer to HostCmd_DS_COMMAND structure
3194  * @param cmd_action   The action: GET or SET
3195  * @param pdata_buf    A pointer to data buffer
3196  *
3197  * @return             MLAN_STATUS_SUCCESS
3198  */
3199 mlan_status
wlan_cmd_robustcoex(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * cmd,IN t_u16 cmd_action,IN t_u16 * pdata_buf)3200 wlan_cmd_robustcoex(IN pmlan_private pmpriv,
3201 		    IN HostCmd_DS_COMMAND *cmd,
3202 		    IN t_u16 cmd_action, IN t_u16 *pdata_buf)
3203 {
3204 	HostCmd_DS_802_11_ROBUSTCOEX *rbstcx = &cmd->params.robustcoexparams;
3205 	mlan_ds_misc_robustcoex_params *robustcoex_params = MNULL;
3206 	MrvlIEtypes_RobustcoexSourceGPIO_t *tlv =
3207 		(MrvlIEtypes_RobustcoexSourceGPIO_t *) ((t_u8 *)rbstcx +
3208 							sizeof
3209 							(HostCmd_DS_802_11_ROBUSTCOEX));
3210 
3211 	ENTER();
3212 
3213 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_ROBUSTCOEX);
3214 	cmd->size = sizeof(HostCmd_DS_802_11_ROBUSTCOEX) + S_DS_GEN;
3215 	rbstcx->action = wlan_cpu_to_le16(cmd_action);
3216 	switch (cmd_action) {
3217 	case HostCmd_ACT_GEN_SET:
3218 		robustcoex_params =
3219 			(mlan_ds_misc_robustcoex_params *) pdata_buf;
3220 		if (robustcoex_params->method == ROBUSTCOEX_GPIO_CFG) {
3221 			cmd->size += sizeof(MrvlIEtypes_RobustcoexSourceGPIO_t);
3222 			tlv->header.type =
3223 				wlan_cpu_to_le16(TLV_TYPE_ROBUSTCOEX);
3224 			tlv->header.len =
3225 				wlan_cpu_to_le16(sizeof
3226 						 (MrvlIEtypes_RobustcoexSourceGPIO_t)
3227 						 - sizeof(MrvlIEtypesHeader_t));
3228 			tlv->enable = (t_u8)robustcoex_params->enable;
3229 			tlv->gpio_num = (t_u8)robustcoex_params->gpio_num;
3230 			tlv->gpio_polarity =
3231 				(t_u8)robustcoex_params->gpio_polarity;
3232 		}
3233 		break;
3234 	case HostCmd_ACT_GEN_GET:
3235 	default:
3236 		break;
3237 	}
3238 	cmd->size = wlan_cpu_to_le16(cmd->size);
3239 	LEAVE();
3240 	return MLAN_STATUS_SUCCESS;
3241 }
3242 
3243 /**
3244  *  @brief This function prepares command of tx_rate_cfg.
3245  *
3246  *  @param pmpriv       A pointer to mlan_private structure
3247  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
3248  *  @param cmd_action   The action: GET or SET
3249  *  @param pdata_buf    A pointer to data buffer
3250  *
3251  *  @return             MLAN_STATUS_SUCCESS
3252  */
3253 mlan_status
wlan_cmd_tx_rate_cfg(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * cmd,IN t_u16 cmd_action,IN t_void * pdata_buf)3254 wlan_cmd_tx_rate_cfg(IN pmlan_private pmpriv,
3255 		     IN HostCmd_DS_COMMAND *cmd,
3256 		     IN t_u16 cmd_action, IN t_void *pdata_buf)
3257 {
3258 	HostCmd_DS_TX_RATE_CFG *rate_cfg =
3259 		(HostCmd_DS_TX_RATE_CFG *)&(cmd->params.tx_rate_cfg);
3260 	MrvlRateScope_t *rate_scope;
3261 	MrvlRateDropPattern_t *rate_drop;
3262 	t_u16 *pbitmap_rates = (t_u16 *)pdata_buf;
3263 
3264 	t_u32 i;
3265 
3266 	ENTER();
3267 
3268 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TX_RATE_CFG);
3269 
3270 	rate_cfg->action = wlan_cpu_to_le16(cmd_action);
3271 
3272 	rate_scope = (MrvlRateScope_t *)((t_u8 *)rate_cfg +
3273 					 sizeof(HostCmd_DS_TX_RATE_CFG));
3274 	rate_scope->type = wlan_cpu_to_le16(TLV_TYPE_RATE_SCOPE);
3275 	rate_scope->length = wlan_cpu_to_le16(sizeof(MrvlRateScope_t) -
3276 					      sizeof(MrvlIEtypesHeader_t));
3277 	if (pbitmap_rates != MNULL) {
3278 		rate_scope->hr_dsss_rate_bitmap =
3279 			wlan_cpu_to_le16(pbitmap_rates[0]);
3280 		rate_scope->ofdm_rate_bitmap =
3281 			wlan_cpu_to_le16(pbitmap_rates[1]);
3282 		for (i = 0; i < NELEMENTS(rate_scope->ht_mcs_rate_bitmap); i++)
3283 			rate_scope->ht_mcs_rate_bitmap[i] =
3284 				wlan_cpu_to_le16(pbitmap_rates[2 + i]);
3285 	} else {
3286 		rate_scope->hr_dsss_rate_bitmap =
3287 			wlan_cpu_to_le16(pmpriv->bitmap_rates[0]);
3288 		rate_scope->ofdm_rate_bitmap =
3289 			wlan_cpu_to_le16(pmpriv->bitmap_rates[1]);
3290 		for (i = 0; i < NELEMENTS(rate_scope->ht_mcs_rate_bitmap); i++)
3291 			rate_scope->ht_mcs_rate_bitmap[i] =
3292 				wlan_cpu_to_le16(pmpriv->bitmap_rates[2 + i]);
3293 	}
3294 
3295 	rate_drop = (MrvlRateDropPattern_t *)((t_u8 *)rate_scope +
3296 					      sizeof(MrvlRateScope_t));
3297 	rate_drop->type = wlan_cpu_to_le16(TLV_TYPE_RATE_DROP_PATTERN);
3298 	rate_drop->length = wlan_cpu_to_le16(sizeof(rate_drop->rate_drop_mode));
3299 	rate_drop->rate_drop_mode = 0;
3300 
3301 	cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_TX_RATE_CFG) +
3302 				     sizeof(MrvlRateScope_t) +
3303 				     sizeof(MrvlRateDropPattern_t));
3304 
3305 	LEAVE();
3306 	return MLAN_STATUS_SUCCESS;
3307 }
3308 
3309 /**
3310  *  @brief This function handles the command response of tx_rate_cfg
3311  *
3312  *  @param pmpriv       A pointer to mlan_private structure
3313  *  @param resp         A pointer to HostCmd_DS_COMMAND
3314  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
3315  *
3316  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3317  */
3318 mlan_status
wlan_ret_tx_rate_cfg(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * resp,IN mlan_ioctl_req * pioctl_buf)3319 wlan_ret_tx_rate_cfg(IN pmlan_private pmpriv,
3320 		     IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
3321 {
3322 	mlan_adapter *pmadapter = pmpriv->adapter;
3323 	mlan_ds_rate *ds_rate = MNULL;
3324 	HostCmd_DS_TX_RATE_CFG *prate_cfg = MNULL;
3325 	MrvlRateScope_t *prate_scope;
3326 	MrvlIEtypesHeader_t *head = MNULL;
3327 	t_u16 tlv, tlv_buf_len = 0;
3328 	t_u8 *tlv_buf;
3329 	t_u32 i;
3330 	t_s32 index;
3331 	mlan_status ret = MLAN_STATUS_SUCCESS;
3332 
3333 	ENTER();
3334 
3335 	if (resp == MNULL) {
3336 		LEAVE();
3337 		return MLAN_STATUS_FAILURE;
3338 	}
3339 	prate_cfg = (HostCmd_DS_TX_RATE_CFG *)&(resp->params.tx_rate_cfg);
3340 
3341 	tlv_buf = (t_u8 *)((t_u8 *)prate_cfg) + sizeof(HostCmd_DS_TX_RATE_CFG);
3342 	if (tlv_buf) {
3343 		tlv_buf_len = *(t_u16 *)(tlv_buf + sizeof(t_u16));
3344 		tlv_buf_len = wlan_le16_to_cpu(tlv_buf_len);
3345 	}
3346 
3347 	while (tlv_buf && tlv_buf_len > 0) {
3348 		tlv = (*tlv_buf);
3349 		tlv = tlv | (*(tlv_buf + 1) << 8);
3350 
3351 		switch (tlv) {
3352 		case TLV_TYPE_RATE_SCOPE:
3353 			prate_scope = (MrvlRateScope_t *)tlv_buf;
3354 			pmpriv->bitmap_rates[0] =
3355 				wlan_le16_to_cpu(prate_scope->
3356 						 hr_dsss_rate_bitmap);
3357 			pmpriv->bitmap_rates[1] =
3358 				wlan_le16_to_cpu(prate_scope->ofdm_rate_bitmap);
3359 			for (i = 0;
3360 			     i < NELEMENTS(prate_scope->ht_mcs_rate_bitmap);
3361 			     i++)
3362 				pmpriv->bitmap_rates[2 + i] =
3363 					wlan_le16_to_cpu(prate_scope->
3364 							 ht_mcs_rate_bitmap[i]);
3365 			break;
3366 			/* Add RATE_DROP tlv here */
3367 		}
3368 
3369 		head = (MrvlIEtypesHeader_t *)tlv_buf;
3370 		head->len = wlan_le16_to_cpu(head->len);
3371 		tlv_buf += head->len + sizeof(MrvlIEtypesHeader_t);
3372 		tlv_buf_len -= head->len;
3373 	}
3374 
3375 	pmpriv->is_data_rate_auto = wlan_is_rate_auto(pmpriv);
3376 
3377 	if (pmpriv->is_data_rate_auto) {
3378 		pmpriv->data_rate = 0;
3379 	} else {
3380 		ret = wlan_prepare_cmd(pmpriv,
3381 				       HostCmd_CMD_802_11_TX_RATE_QUERY,
3382 				       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
3383 
3384 	}
3385 
3386 	if (pioctl_buf) {
3387 		ds_rate = (mlan_ds_rate *)pioctl_buf->pbuf;
3388 		if (ds_rate == MNULL) {
3389 			PRINTM(MERROR, "Request buffer not found!\n");
3390 			LEAVE();
3391 			return MLAN_STATUS_FAILURE;
3392 		}
3393 		if (pmpriv->is_data_rate_auto) {
3394 			ds_rate->param.rate_cfg.is_rate_auto = MTRUE;
3395 			ds_rate->param.rate_cfg.rate_format =
3396 				MLAN_RATE_FORMAT_AUTO;
3397 		} else {
3398 			ds_rate->param.rate_cfg.is_rate_auto = MFALSE;
3399 			/* check the LG rate */
3400 			index = wlan_get_rate_index(pmadapter,
3401 						    &pmpriv->bitmap_rates[0],
3402 						    4);
3403 			if (index != -1) {
3404 				if ((index >= MLAN_RATE_BITMAP_OFDM0) &&
3405 				    (index <= MLAN_RATE_BITMAP_OFDM7))
3406 					index -= (MLAN_RATE_BITMAP_OFDM0 -
3407 						  MLAN_RATE_INDEX_OFDM0);
3408 				ds_rate->param.rate_cfg.rate_format =
3409 					MLAN_RATE_FORMAT_LG;
3410 				ds_rate->param.rate_cfg.rate = index;
3411 			}
3412 			/* check the HT rate */
3413 			index = wlan_get_rate_index(pmadapter,
3414 						    &pmpriv->bitmap_rates[2],
3415 						    16);
3416 			if (index != -1) {
3417 				ds_rate->param.rate_cfg.rate_format =
3418 					MLAN_RATE_FORMAT_HT;
3419 				ds_rate->param.rate_cfg.rate = index;
3420 			}
3421 			PRINTM(MINFO, "Rate index is %d\n",
3422 			       ds_rate->param.rate_cfg.rate);
3423 		}
3424 		for (i = 0; i < MAX_BITMAP_RATES_SIZE; i++) {
3425 			ds_rate->param.rate_cfg.bitmap_rates[i] =
3426 				pmpriv->bitmap_rates[i];
3427 		}
3428 
3429 	}
3430 
3431 	LEAVE();
3432 	return ret;
3433 }
3434 
3435 /**
3436  *  @brief  This function issues adapter specific commands
3437  *          to initialize firmware
3438  *
3439  *  @param pmadapter    A pointer to mlan_adapter structure
3440  *
3441  *  @return             MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
3442  */
3443 mlan_status
wlan_adapter_get_hw_spec(IN pmlan_adapter pmadapter)3444 wlan_adapter_get_hw_spec(IN pmlan_adapter pmadapter)
3445 {
3446 	mlan_status ret = MLAN_STATUS_SUCCESS;
3447 	pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
3448 	/*
3449 	 * This should be issued in the very first to config
3450 	 *   SDIO_GPIO interrupt mode.
3451 	 */
3452 	if (wlan_set_sdio_gpio_int(priv) != MLAN_STATUS_SUCCESS) {
3453 		ret = MLAN_STATUS_FAILURE;
3454 		goto done;
3455 	}
3456 
3457 	ret = wlan_prepare_cmd(priv, HostCmd_CMD_FUNC_INIT,
3458 			       HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
3459 	if (ret) {
3460 		ret = MLAN_STATUS_FAILURE;
3461 		goto done;
3462 	}
3463 
3464     /** DPD data dnld cmd prepare */
3465 	if ((pmadapter->pdpd_data) && (pmadapter->dpd_data_len > 0)) {
3466 		ret = wlan_prepare_cmd(priv, HostCmd_CMD_CFG_DATA,
3467 				       HostCmd_ACT_GEN_SET, OID_TYPE_DPD, MNULL,
3468 				       MNULL);
3469 		if (ret) {
3470 			ret = MLAN_STATUS_FAILURE;
3471 			goto done;
3472 		}
3473 		pmadapter->pdpd_data = MNULL;
3474 		pmadapter->dpd_data_len = 0;
3475 	}
3476 	if ((pmadapter->ptxpwr_data) && (pmadapter->txpwr_data_len > 0)) {
3477 		ret = wlan_process_hostcmd_cfg(priv, pmadapter->ptxpwr_data,
3478 					       pmadapter->txpwr_data_len);
3479 		if (ret) {
3480 			ret = MLAN_STATUS_FAILURE;
3481 			goto done;
3482 		}
3483 		pmadapter->ptxpwr_data = MNULL;
3484 		pmadapter->txpwr_data_len = 0;
3485 	}
3486     /** Cal data dnld cmd prepare */
3487 	if ((pmadapter->pcal_data) && (pmadapter->cal_data_len > 0)) {
3488 		ret = wlan_prepare_cmd(priv, HostCmd_CMD_CFG_DATA,
3489 				       HostCmd_ACT_GEN_SET, OID_TYPE_CAL, MNULL,
3490 				       MNULL);
3491 		if (ret) {
3492 			ret = MLAN_STATUS_FAILURE;
3493 			goto done;
3494 		}
3495 		pmadapter->pcal_data = MNULL;
3496 		pmadapter->cal_data_len = 0;
3497 	}
3498 	/* Get FW region and cfp tables */
3499 	if (pmadapter->init_para.fw_region) {
3500 		ret = wlan_prepare_cmd(priv, HostCmd_CMD_CHAN_REGION_CFG,
3501 				       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
3502 		if (ret) {
3503 			ret = MLAN_STATUS_FAILURE;
3504 			goto done;
3505 		}
3506 	}
3507 	/*
3508 	 * Get HW spec
3509 	 */
3510 	ret = wlan_prepare_cmd(priv, HostCmd_CMD_GET_HW_SPEC,
3511 			       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
3512 	if (ret) {
3513 		ret = MLAN_STATUS_FAILURE;
3514 		goto done;
3515 	}
3516 	ret = MLAN_STATUS_PENDING;
3517 done:
3518 	LEAVE();
3519 	return ret;
3520 }
3521 
3522 /**
3523  *  @brief  This function issues adapter specific commands
3524  *          to initialize firmware
3525  *
3526  *  @param pmadapter    A pointer to mlan_adapter structure
3527  *
3528  *  @return             MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
3529  */
3530 mlan_status
wlan_adapter_init_cmd(IN pmlan_adapter pmadapter)3531 wlan_adapter_init_cmd(IN pmlan_adapter pmadapter)
3532 {
3533 	mlan_status ret = MLAN_STATUS_SUCCESS;
3534 	pmlan_private pmpriv = MNULL;
3535 #ifdef STA_SUPPORT
3536 	pmlan_private pmpriv_sta = MNULL;
3537 #endif
3538 
3539 	ENTER();
3540 
3541 	pmpriv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY);
3542 #ifdef STA_SUPPORT
3543 	pmpriv_sta = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA);
3544 #endif
3545 
3546 	/* Get fw wakeup method */
3547 	if (pmpriv) {
3548 		ret = wlan_prepare_cmd(pmpriv,
3549 				       HostCmd_CMD_802_11_FW_WAKE_METHOD,
3550 				       HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
3551 		if (ret) {
3552 			ret = MLAN_STATUS_FAILURE;
3553 			goto done;
3554 		}
3555 	}
3556 #if defined(SYSKT_MULTI) && defined(OOB_WAKEUP) || defined(SUSPEND_SDIO_PULL_DOWN)
3557 	/* Send request to firmware */
3558 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SDIO_PULL_CTRL,
3559 			       HostCmd_ACT_GEN_SET, 0, MNULL, MNULL);
3560 	if (ret) {
3561 		ret = MLAN_STATUS_FAILURE;
3562 		goto done;
3563 	}
3564 }
3565 #endif
3566 
3567     /* Reconfigure tx buf size */
3568 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_RECONFIGURE_TX_BUFF,
3569 		       HostCmd_ACT_GEN_SET, 0, MNULL,
3570 		       &pmadapter->max_tx_buf_size);
3571 if (ret) {
3572 	ret = MLAN_STATUS_FAILURE;
3573 	goto done;
3574 }
3575 #if defined(STA_SUPPORT)
3576 if (pmpriv_sta && (pmpriv_sta->state_11d.user_enable_11d == ENABLE_11D)) {
3577 	/* Send command to FW to enable 11d */
3578 	ret = wlan_prepare_cmd(pmpriv_sta,
3579 			       HostCmd_CMD_802_11_SNMP_MIB,
3580 			       HostCmd_ACT_GEN_SET,
3581 			       Dot11D_i,
3582 			       MNULL, &pmpriv_sta->state_11d.user_enable_11d);
3583 	if (ret) {
3584 		ret = MLAN_STATUS_FAILURE;
3585 		goto done;
3586 	}
3587 }
3588 #endif
3589 
3590 #if defined(STA_SUPPORT)
3591 if (pmpriv_sta && (pmadapter->ps_mode == Wlan802_11PowerModePSP)) {
3592 	ret = wlan_prepare_cmd(pmpriv_sta, HostCmd_CMD_802_11_PS_MODE_ENH,
3593 			       EN_AUTO_PS, BITMAP_STA_PS, MNULL, MNULL);
3594 	if (ret) {
3595 		ret = MLAN_STATUS_FAILURE;
3596 		goto done;
3597 	}
3598 }
3599 #endif
3600 
3601 if (pmadapter->init_auto_ds) {
3602 	mlan_ds_auto_ds auto_ds;
3603 	/* Enable auto deep sleep */
3604 	auto_ds.idletime = pmadapter->idle_time;
3605 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH,
3606 			       EN_AUTO_PS, BITMAP_AUTO_DS, MNULL, &auto_ds);
3607 	if (ret) {
3608 		ret = MLAN_STATUS_FAILURE;
3609 		goto done;
3610 	}
3611 }
3612 #define DEF_AUTO_NULL_PKT_PERIOD    30
3613 if (pmpriv_sta) {
3614 	t_u32 value = DEF_AUTO_NULL_PKT_PERIOD;
3615 	ret = wlan_prepare_cmd(pmpriv_sta,
3616 			       HostCmd_CMD_802_11_SNMP_MIB,
3617 			       HostCmd_ACT_GEN_SET,
3618 			       NullPktPeriod_i, MNULL, &value);
3619 	if (ret) {
3620 		ret = MLAN_STATUS_FAILURE;
3621 		goto done;
3622 	}
3623 }
3624 if (pmadapter->init_para.indrstcfg != 0xffffffff) {
3625 	mlan_ds_ind_rst_cfg ind_rst_cfg;
3626 	ind_rst_cfg.ir_mode = pmadapter->init_para.indrstcfg & 0xff;
3627 	ind_rst_cfg.gpio_pin = (pmadapter->init_para.indrstcfg & 0xff00) >> 8;
3628 	ret = wlan_prepare_cmd(pmpriv,
3629 			       HostCmd_CMD_INDEPENDENT_RESET_CFG,
3630 			       HostCmd_ACT_GEN_SET,
3631 			       0, MNULL, (t_void *)&ind_rst_cfg);
3632 	if (ret) {
3633 		ret = MLAN_STATUS_FAILURE;
3634 		goto done;
3635 	}
3636 }
3637 
3638 if (pmadapter->inact_tmo) {
3639 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT,
3640 			       HostCmd_ACT_GEN_SET, 0, MNULL,
3641 			       &pmadapter->inact_tmo);
3642 	if (ret) {
3643 		ret = MLAN_STATUS_FAILURE;
3644 		goto done;
3645 	}
3646 }
3647 if (pmadapter->init_para.drcs_chantime_mode) {
3648 	mlan_ds_drcs_cfg drcs_init_cfg[2];
3649 	drcs_init_cfg[0].chan_idx = 0x1;
3650 	drcs_init_cfg[0].chantime =
3651 		(t_u8)(pmadapter->init_para.drcs_chantime_mode >> 8);
3652 	/* switchtime use default value in fw */
3653 	drcs_init_cfg[0].switchtime = 10;
3654 	drcs_init_cfg[0].undozetime = 5;
3655 	drcs_init_cfg[0].mode = (t_u8)(pmadapter->init_para.drcs_chantime_mode);
3656 	drcs_init_cfg[1].chan_idx = 0x2;
3657 	drcs_init_cfg[1].chantime =
3658 		(t_u8)(pmadapter->init_para.drcs_chantime_mode >> 24);
3659 	/* switchtime use default value in fw */
3660 	drcs_init_cfg[1].switchtime = 10;
3661 	drcs_init_cfg[1].undozetime = 5;
3662 	drcs_init_cfg[1].mode =
3663 		(t_u8)(pmadapter->init_para.drcs_chantime_mode >> 16);
3664 	ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_DRCS_CONFIG,
3665 			       HostCmd_ACT_GEN_SET, 0, MNULL,
3666 			       (t_void *)drcs_init_cfg);
3667 	if (ret) {
3668 		ret = MLAN_STATUS_FAILURE;
3669 		goto done;
3670 	}
3671 }
3672 ret = MLAN_STATUS_PENDING;
3673 done:
3674 LEAVE();
3675 return ret;
3676 }
3677 
3678 #ifdef RX_PACKET_COALESCE
3679 /**
3680  *  @brief This function prepares command of rx_pkt_coalesce_cfg
3681  *
3682  *  @param pmpriv       A pointer to mlan_private structure
3683  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
3684  *  @param cmd_action   The action: GET or SET
3685  *  @param pdata_buf    A pointer to data buffer
3686  *
3687  *  @return             MLAN_STATUS_SUCCESS
3688  */
3689 
3690 mlan_status
3691 wlan_cmd_rx_pkt_coalesce_cfg(IN pmlan_private pmpriv,
3692 			     IN HostCmd_DS_COMMAND *cmd,
3693 			     IN t_u16 cmd_action, IN t_void *pdata_buf)
3694 {
3695 
3696 	mlan_ds_misc_rx_packet_coalesce *rx_pkt_cfg =
3697 		(mlan_ds_misc_rx_packet_coalesce *)pdata_buf;
3698 	HostCmd_DS_RX_PKT_COAL_CFG *prx_coal_cfg =
3699 		(HostCmd_DS_RX_PKT_COAL_CFG *)&cmd->params.rx_pkt_coal_cfg;
3700 
3701 	ENTER();
3702 
3703 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_RX_PKT_COALESCE_CFG);
3704 	prx_coal_cfg->action = wlan_cpu_to_le16(cmd_action);
3705 
3706 	if (cmd_action == HostCmd_ACT_GEN_SET) {
3707 		prx_coal_cfg->packet_threshold =
3708 			wlan_cpu_to_le32(rx_pkt_cfg->packet_threshold);
3709 		prx_coal_cfg->delay = wlan_cpu_to_le16(rx_pkt_cfg->delay);
3710 		PRINTM(MCMND,
3711 		       "Set RX coal config: packet threshold=%d delay=%d\n",
3712 		       rx_pkt_cfg->packet_threshold, rx_pkt_cfg->delay);
3713 		cmd->size =
3714 			wlan_cpu_to_le16(S_DS_GEN +
3715 					 sizeof(HostCmd_DS_RX_PKT_COAL_CFG));
3716 	} else {
3717 		cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(cmd_action));
3718 	}
3719 
3720 	LEAVE();
3721 	return MLAN_STATUS_SUCCESS;
3722 
3723 }
3724 
3725 /**
3726  *  @brief This function handles the command response of RX_PACKET_COAL_CFG
3727  *
3728  *  @param pmpriv       A pointer to mlan_private structure
3729  *  @param resp         A pointer to HostCmd_DS_COMMAND
3730  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
3731  *
3732  *  @return             MLAN_STATUS_SUCCESS
3733  */
3734 mlan_status
3735 wlan_ret_rx_pkt_coalesce_cfg(IN pmlan_private pmpriv,
3736 			     const IN HostCmd_DS_COMMAND *resp,
3737 			     OUT mlan_ioctl_req *pioctl_buf)
3738 {
3739 	mlan_ds_misc_cfg *pcfg = MNULL;
3740 	const HostCmd_DS_RX_PKT_COAL_CFG *presp_cfg =
3741 		&resp->params.rx_pkt_coal_cfg;
3742 
3743 	ENTER();
3744 
3745 	if (pioctl_buf) {
3746 		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
3747 		pcfg->param.rx_coalesce.packet_threshold =
3748 			wlan_le32_to_cpu(presp_cfg->packet_threshold);
3749 		pcfg->param.rx_coalesce.delay =
3750 			wlan_le16_to_cpu(presp_cfg->delay);
3751 		PRINTM(MCMND,
3752 		       "Get rx pkt coalesce info: packet threshold=%d delay=%d\n",
3753 		       pcfg->param.rx_coalesce.packet_threshold,
3754 		       pcfg->param.rx_coalesce.delay);
3755 		pioctl_buf->buf_len = sizeof(mlan_ds_misc_rx_packet_coalesce);
3756 	}
3757 
3758 	LEAVE();
3759 	return MLAN_STATUS_SUCCESS;
3760 }
3761 
3762 #endif
3763 /**
3764  *  @brief This function handle the multi_chan info event
3765  *
3766  *  @param pmpriv       A pointer to mlan_private structure
3767  *  @param pevent       A pointer to event buffer
3768  *
3769  *  @return             MLAN_STATUS_SUCCESS
3770  */
3771 mlan_status
3772 wlan_handle_event_multi_chan_info(IN pmlan_private pmpriv, pmlan_buffer pevent)
3773 {
3774 	pmlan_adapter pmadapter = pmpriv->adapter;
3775 	t_u32 interfaces = 0;
3776 	MrvlIEtypes_multi_chan_info_t *pmulti_chan_info = MNULL;
3777 	MrvlIEtypes_multi_chan_group_info_t *pmulti_chan_grp_info = MNULL;
3778 	int tlv_buf_left = pevent->data_len - sizeof(mlan_event_id);
3779 	t_u16 tlv_type, tlv_len;
3780 	mlan_status ret = MLAN_STATUS_SUCCESS;
3781 	pmlan_private intf_priv = MNULL;
3782 	int num_intf = 0, bss_type = 0, bss_num = 0;
3783 	MrvlIEtypesHeader_t *tlv = MNULL;
3784 
3785 	ENTER();
3786 
3787 	PRINTM(MEVENT, "multi channel event\n");
3788 	pmulti_chan_info =
3789 		(MrvlIEtypes_multi_chan_info_t *)(pevent->pbuf +
3790 						  pevent->data_offset +
3791 						  sizeof(mlan_event_id));
3792 	if (tlv_buf_left < sizeof(MrvlIEtypes_multi_chan_info_t) ||
3793 	    wlan_le16_to_cpu(pmulti_chan_info->header.type) !=
3794 	    TLV_TYPE_MULTI_CHAN_INFO) {
3795 		PRINTM(MERROR, "Invalid multi channel event\n");
3796 		goto done;
3797 	}
3798 
3799 	pmadapter->mc_status = wlan_le16_to_cpu(pmulti_chan_info->status);
3800 	PRINTM(MEVENT, "mc_status=%d\n", pmadapter->mc_status);
3801 	tlv_buf_left -= sizeof(MrvlIEtypes_multi_chan_info_t);
3802 	tlv = (MrvlIEtypesHeader_t *)pmulti_chan_info->tlv_buffer;
3803 
3804 	while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
3805 		tlv_type = wlan_le16_to_cpu(tlv->type);
3806 		tlv_len = wlan_le16_to_cpu(tlv->len);
3807 		if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
3808 		    (unsigned int)tlv_buf_left) {
3809 			PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
3810 			       tlv_len, tlv_buf_left);
3811 			break;
3812 		}
3813 		if (tlv_type != TLV_TYPE_MULTI_CHAN_GROUP_INFO_TLV_ID) {
3814 			PRINTM(MERROR, "wrong tlv type:0x%x\n", tlv_type);
3815 			break;
3816 		}
3817 		pmulti_chan_grp_info =
3818 			(MrvlIEtypes_multi_chan_group_info_t *)tlv;
3819 		PRINTM(MEVENT, "mc_info: groupid=%d chan=%d, numintf=%d\n",
3820 		       pmulti_chan_grp_info->chan_group_id,
3821 		       pmulti_chan_grp_info->chan_band_info.chan_num,
3822 		       pmulti_chan_grp_info->num_intf);
3823 		num_intf = pmulti_chan_grp_info->num_intf;
3824 		for (interfaces = 0; interfaces < num_intf; interfaces++) {
3825 			bss_type =
3826 				pmulti_chan_grp_info->
3827 				bss_type_numlist[interfaces] >> 4;
3828 			bss_num =
3829 				pmulti_chan_grp_info->
3830 				bss_type_numlist[interfaces] & BSS_NUM_MASK;
3831 			PRINTM(MEVENT, "intf%d: bss_type=%d bss_num=%d\n",
3832 			       interfaces, bss_type, bss_num);
3833 			intf_priv =
3834 				wlan_get_priv_by_id(pmadapter, bss_num,
3835 						    bss_type);
3836 			if (intf_priv) {
3837 			} else {
3838 				PRINTM(MERROR,
3839 				       "Invalid bss_type, bss_num in multi_channel event\n");
3840 			}
3841 		}
3842 
3843 		tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
3844 		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
3845 					      sizeof(MrvlIEtypesHeader_t));
3846 	}
3847 
3848 done:
3849 	LEAVE();
3850 	return ret;
3851 }
3852 
3853 /**
3854  *  @brief This function prepares the command MULTI_CHAN_CFG
3855  *
3856  *  @param pmpriv       A pointer to mlan_private structure
3857  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
3858  *  @param cmd_action   Command action: GET or SET
3859  *  @param pdata_buf    A pointer to new setting buf
3860  *
3861  *  @return             MLAN_STATUS_SUCCESS
3862  */
3863 mlan_status
3864 wlan_cmd_multi_chan_cfg(IN pmlan_private pmpriv,
3865 			IN HostCmd_DS_COMMAND *cmd,
3866 			IN t_u16 cmd_action, IN t_void *pdata_buf)
3867 {
3868 	mlan_ds_multi_chan_cfg *multi_chan_cfg =
3869 		(mlan_ds_multi_chan_cfg *)pdata_buf;
3870 	HostCmd_DS_MULTI_CHAN_CFG *pmchan_cfg =
3871 		(HostCmd_DS_MULTI_CHAN_CFG *)&cmd->params.multi_chan_cfg;
3872 
3873 	ENTER();
3874 
3875 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MULTI_CHAN_CONFIG);
3876 	pmchan_cfg->action = wlan_cpu_to_le16(cmd_action);
3877 
3878 	if (cmd_action == HostCmd_ACT_GEN_SET) {
3879 		pmchan_cfg->buffer_weight = multi_chan_cfg->buffer_weight;
3880 		pmchan_cfg->channel_time =
3881 			wlan_cpu_to_le32(multi_chan_cfg->channel_time);
3882 		PRINTM(MCMND,
3883 		       "Set multi-channel: buffer_weight=%d channel_time=%d\n",
3884 		       multi_chan_cfg->buffer_weight,
3885 		       multi_chan_cfg->channel_time);
3886 		cmd->size =
3887 			wlan_cpu_to_le16(S_DS_GEN +
3888 					 sizeof(HostCmd_DS_MULTI_CHAN_CFG));
3889 	} else {
3890 		cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(cmd_action));
3891 	}
3892 
3893 	LEAVE();
3894 	return MLAN_STATUS_SUCCESS;
3895 }
3896 
3897 /**
3898  *  @brief This function handles the command response of MULTI_CHAN_CFG
3899  *
3900  *  @param pmpriv       A pointer to mlan_private structure
3901  *  @param resp         A pointer to HostCmd_DS_COMMAND
3902  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
3903  *
3904  *  @return             MLAN_STATUS_SUCCESS
3905  */
3906 mlan_status
3907 wlan_ret_multi_chan_cfg(IN pmlan_private pmpriv,
3908 			const IN HostCmd_DS_COMMAND *resp,
3909 			OUT mlan_ioctl_req *pioctl_buf)
3910 {
3911 	mlan_ds_misc_cfg *pcfg = MNULL;
3912 	const HostCmd_DS_MULTI_CHAN_CFG *presp_cfg =
3913 		&resp->params.multi_chan_cfg;
3914 
3915 	ENTER();
3916 
3917 	if (pioctl_buf) {
3918 		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
3919 		pcfg->param.multi_chan_cfg.channel_time =
3920 			wlan_le32_to_cpu(presp_cfg->channel_time);
3921 		pcfg->param.multi_chan_cfg.buffer_weight =
3922 			presp_cfg->buffer_weight;
3923 		pcfg->param.multi_chan_cfg.tlv_len =
3924 			resp->size - (sizeof(HostCmd_DS_GEN) +
3925 				      sizeof(HostCmd_DS_MULTI_CHAN_CFG));
3926 		PRINTM(MCMND,
3927 		       "Get multi-channel: buffer_weight=%d channel_time=%d tlv_len=%d\n",
3928 		       pcfg->param.multi_chan_cfg.buffer_weight,
3929 		       pcfg->param.multi_chan_cfg.channel_time,
3930 		       pcfg->param.multi_chan_cfg.tlv_len);
3931 		memcpy(pmpriv->adapter, pcfg->param.multi_chan_cfg.tlv_buf,
3932 		       presp_cfg->tlv_buf, pcfg->param.multi_chan_cfg.tlv_len);
3933 		pioctl_buf->buf_len =
3934 			sizeof(mlan_ds_multi_chan_cfg) +
3935 			pcfg->param.multi_chan_cfg.tlv_len;
3936 	}
3937 
3938 	LEAVE();
3939 	return MLAN_STATUS_SUCCESS;
3940 }
3941 
3942 /**
3943  *  @brief This function prepares the command MULTI_CHAN_POLICY
3944  *
3945  *  @param pmpriv       A pointer to mlan_private structure
3946  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
3947  *  @param cmd_action   Command action: GET or SET
3948  *  @param pdata_buf    A pointer to new setting buf
3949  *
3950  *  @return             MLAN_STATUS_SUCCESS
3951  */
3952 mlan_status
3953 wlan_cmd_multi_chan_policy(IN pmlan_private pmpriv,
3954 			   IN HostCmd_DS_COMMAND *cmd,
3955 			   IN t_u16 cmd_action, IN t_void *pdata_buf)
3956 {
3957 	t_u16 policy = 0;
3958 	HostCmd_DS_MULTI_CHAN_POLICY *pmulti_chan_policy =
3959 		(HostCmd_DS_MULTI_CHAN_POLICY *)&cmd->params.multi_chan_policy;
3960 
3961 	ENTER();
3962 
3963 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MULTI_CHAN_POLICY);
3964 	pmulti_chan_policy->action = wlan_cpu_to_le16(cmd_action);
3965 	cmd->size =
3966 		wlan_cpu_to_le16(S_DS_GEN +
3967 				 sizeof(HostCmd_DS_MULTI_CHAN_POLICY));
3968 	if (cmd_action == HostCmd_ACT_GEN_SET) {
3969 		policy = *((t_u16 *)pdata_buf);
3970 		pmulti_chan_policy->policy = wlan_cpu_to_le16(policy);
3971 		PRINTM(MCMND, "Set multi-channel policy: %d\n", policy);
3972 	}
3973 	LEAVE();
3974 	return MLAN_STATUS_SUCCESS;
3975 }
3976 
3977 /**
3978  *  @brief This function handles the command response of MULTI_CHAN_POLICY
3979  *
3980  *  @param pmpriv       A pointer to mlan_private structure
3981  *  @param resp         A pointer to HostCmd_DS_COMMAND
3982  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
3983  *
3984  *  @return             MLAN_STATUS_SUCCESS
3985  */
3986 mlan_status
3987 wlan_ret_multi_chan_policy(IN pmlan_private pmpriv,
3988 			   const IN HostCmd_DS_COMMAND *resp,
3989 			   OUT mlan_ioctl_req *pioctl_buf)
3990 {
3991 	mlan_ds_misc_cfg *pcfg = MNULL;
3992 	const HostCmd_DS_MULTI_CHAN_POLICY *presp_cfg =
3993 		&resp->params.multi_chan_policy;
3994 
3995 	ENTER();
3996 
3997 	if (pioctl_buf) {
3998 		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
3999 		pcfg->param.multi_chan_policy =
4000 			wlan_le16_to_cpu(presp_cfg->policy);
4001 
4002 		if (pioctl_buf->action == HostCmd_ACT_GEN_SET) {
4003 			if (pcfg->param.multi_chan_policy)
4004 				pmpriv->adapter->mc_policy = MTRUE;
4005 			else
4006 				pmpriv->adapter->mc_policy = MFALSE;
4007 		}
4008 	}
4009 
4010 	LEAVE();
4011 	return MLAN_STATUS_SUCCESS;
4012 }
4013 
4014 /**
4015  *  @brief This function prepares the command DRCD_CFG
4016  *
4017  *  @param pmpriv       A pointer to mlan_private structure
4018  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
4019  *  @param cmd_action   Command action: GET or SET
4020  *  @param pdata_buf    A pointer to new setting buf
4021  *
4022  *  @return             MLAN_STATUS_SUCCESS
4023  */
4024 mlan_status
4025 wlan_cmd_drcs_cfg(IN pmlan_private pmpriv,
4026 		  IN HostCmd_DS_COMMAND *cmd,
4027 		  IN t_u16 cmd_action, IN t_void *pdata_buf)
4028 {
4029 	mlan_ds_drcs_cfg *drcs_cfg = (mlan_ds_drcs_cfg *) pdata_buf;
4030 	HostCmd_DS_DRCS_CFG *pdrcs_cfg =
4031 		(HostCmd_DS_DRCS_CFG *) & cmd->params.drcs_cfg;
4032 	MrvlTypes_DrcsTimeSlice_t *channel_time_slicing =
4033 		&pdrcs_cfg->time_slicing;
4034 
4035 	ENTER();
4036 
4037 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_DRCS_CONFIG);
4038 	pdrcs_cfg->action = wlan_cpu_to_le16(cmd_action);
4039 
4040 	if (cmd_action == HostCmd_ACT_GEN_SET) {
4041 		channel_time_slicing->header.type =
4042 			wlan_cpu_to_le16(MRVL_DRCS_TIME_SLICE_TLV_ID);
4043 		channel_time_slicing->header.len =
4044 			wlan_cpu_to_le16(sizeof(MrvlTypes_DrcsTimeSlice_t) -
4045 					 sizeof(MrvlIEtypesHeader_t));
4046 		channel_time_slicing->chan_idx =
4047 			wlan_cpu_to_le16(drcs_cfg->chan_idx);
4048 		channel_time_slicing->chantime = drcs_cfg->chantime;
4049 		channel_time_slicing->switchtime = drcs_cfg->switchtime;
4050 		channel_time_slicing->undozetime = drcs_cfg->undozetime;
4051 		channel_time_slicing->mode = drcs_cfg->mode;
4052 		PRINTM(MCMND,
4053 		       "Set multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
4054 		       channel_time_slicing->chan_idx,
4055 		       channel_time_slicing->chantime,
4056 		       channel_time_slicing->switchtime,
4057 		       channel_time_slicing->undozetime,
4058 		       channel_time_slicing->mode);
4059 		cmd->size =
4060 			wlan_cpu_to_le16(S_DS_GEN +
4061 					 sizeof(HostCmd_DS_DRCS_CFG));
4062 		/* Set two channels different parameters */
4063 		if (0x3 != channel_time_slicing->chan_idx) {
4064 			drcs_cfg++;
4065 			channel_time_slicing = pdrcs_cfg->drcs_buf;
4066 			channel_time_slicing->header.type =
4067 				wlan_cpu_to_le16(MRVL_DRCS_TIME_SLICE_TLV_ID);
4068 			channel_time_slicing->header.len =
4069 				wlan_cpu_to_le16(sizeof
4070 						 (MrvlTypes_DrcsTimeSlice_t) -
4071 						 sizeof(MrvlIEtypesHeader_t));
4072 			channel_time_slicing->chan_idx =
4073 				wlan_cpu_to_le16(drcs_cfg->chan_idx);
4074 			channel_time_slicing->chantime = drcs_cfg->chantime;
4075 			channel_time_slicing->switchtime = drcs_cfg->switchtime;
4076 			channel_time_slicing->undozetime = drcs_cfg->undozetime;
4077 			channel_time_slicing->mode = drcs_cfg->mode;
4078 			PRINTM(MCMND,
4079 			       "Set multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
4080 			       channel_time_slicing->chan_idx,
4081 			       channel_time_slicing->chantime,
4082 			       channel_time_slicing->switchtime,
4083 			       channel_time_slicing->undozetime,
4084 			       channel_time_slicing->mode);
4085 			cmd->size +=
4086 				wlan_cpu_to_le16(sizeof
4087 						 (MrvlTypes_DrcsTimeSlice_t));
4088 		}
4089 	} else {
4090 		cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(cmd_action));
4091 	}
4092 
4093 	LEAVE();
4094 	return MLAN_STATUS_SUCCESS;
4095 }
4096 
4097 /**
4098  *  @brief This function handles the command response of DRCS_CFG
4099  *
4100  *  @param pmpriv       A pointer to mlan_private structure
4101  *  @param resp         A pointer to HostCmd_DS_COMMAND
4102  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
4103  *
4104  *  @return             MLAN_STATUS_SUCCESS
4105  */
4106 mlan_status
4107 wlan_ret_drcs_cfg(IN pmlan_private pmpriv,
4108 		  const IN HostCmd_DS_COMMAND *resp,
4109 		  OUT mlan_ioctl_req *pioctl_buf)
4110 {
4111 	mlan_ds_misc_cfg *pcfg = MNULL;
4112 	const HostCmd_DS_DRCS_CFG *presp_cfg = &resp->params.drcs_cfg;
4113 	const MrvlTypes_DrcsTimeSlice_t *channel_time_slicing =
4114 		&presp_cfg->time_slicing;
4115 	const MrvlTypes_DrcsTimeSlice_t *channel_time_slicing1 = MNULL;
4116 	mlan_ds_drcs_cfg *drcs_cfg1 = MNULL;
4117 
4118 	ENTER();
4119 
4120 	if (pioctl_buf) {
4121 		pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
4122 		if (wlan_le16_to_cpu(channel_time_slicing->header.type) !=
4123 		    MRVL_DRCS_TIME_SLICE_TLV_ID ||
4124 		    wlan_le16_to_cpu(channel_time_slicing->header.len) !=
4125 		    sizeof(MrvlTypes_DrcsTimeSlice_t) -
4126 		    sizeof(MrvlIEtypesHeader_t)) {
4127 			LEAVE();
4128 			return MLAN_STATUS_FAILURE;
4129 		}
4130 		pcfg->param.drcs_cfg[0].chan_idx =
4131 			wlan_le16_to_cpu(channel_time_slicing->chan_idx);
4132 		pcfg->param.drcs_cfg[0].chantime =
4133 			channel_time_slicing->chantime;
4134 		pcfg->param.drcs_cfg[0].switchtime =
4135 			channel_time_slicing->switchtime;
4136 		pcfg->param.drcs_cfg[0].undozetime =
4137 			channel_time_slicing->undozetime;
4138 		pcfg->param.drcs_cfg[0].mode = channel_time_slicing->mode;
4139 		PRINTM(MCMND,
4140 		       "multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
4141 		       pcfg->param.drcs_cfg[0].chan_idx,
4142 		       channel_time_slicing->chantime,
4143 		       channel_time_slicing->switchtime,
4144 		       channel_time_slicing->undozetime,
4145 		       channel_time_slicing->mode);
4146 		pioctl_buf->buf_len = sizeof(mlan_ds_drcs_cfg);
4147 		/*Channel for chan_idx 1 and 2 have different parameters */
4148 		if (0x3 != pcfg->param.drcs_cfg[0].chan_idx) {
4149 			channel_time_slicing1 = presp_cfg->drcs_buf;
4150 			if (wlan_le16_to_cpu(channel_time_slicing1->header.type)
4151 			    != MRVL_DRCS_TIME_SLICE_TLV_ID ||
4152 			    wlan_le16_to_cpu(channel_time_slicing1->header.
4153 					     len) !=
4154 			    sizeof(MrvlTypes_DrcsTimeSlice_t) -
4155 			    sizeof(MrvlIEtypesHeader_t)) {
4156 				LEAVE();
4157 				return MLAN_STATUS_FAILURE;
4158 			}
4159 			drcs_cfg1 =
4160 				(mlan_ds_drcs_cfg *) & pcfg->param.drcs_cfg[1];
4161 			drcs_cfg1->chan_idx =
4162 				wlan_le16_to_cpu(channel_time_slicing1->
4163 						 chan_idx);
4164 			drcs_cfg1->chantime = channel_time_slicing1->chantime;
4165 			drcs_cfg1->switchtime =
4166 				channel_time_slicing1->switchtime;
4167 			drcs_cfg1->undozetime =
4168 				channel_time_slicing1->undozetime;
4169 			drcs_cfg1->mode = channel_time_slicing1->mode;
4170 			PRINTM(MCMND,
4171 			       "multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
4172 			       drcs_cfg1->chan_idx, drcs_cfg1->chantime,
4173 			       drcs_cfg1->switchtime, drcs_cfg1->undozetime,
4174 			       drcs_cfg1->mode);
4175 			pioctl_buf->buf_len += sizeof(mlan_ds_drcs_cfg);
4176 		}
4177 	}
4178 
4179 	LEAVE();
4180 	return MLAN_STATUS_SUCCESS;
4181 }
4182 
4183 /**
4184  *  @brief This function prepares command of get_hw_spec.
4185  *
4186  *  @param pmpriv       A pointer to mlan_private structure
4187  *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
4188  *
4189  *  @return             MLAN_STATUS_SUCCESS
4190  */
4191 mlan_status
4192 wlan_cmd_get_hw_spec(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *pcmd)
4193 {
4194 	HostCmd_DS_GET_HW_SPEC *hw_spec = &pcmd->params.hw_spec;
4195 
4196 	ENTER();
4197 
4198 	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_GET_HW_SPEC);
4199 	pcmd->size =
4200 		wlan_cpu_to_le16(sizeof(HostCmd_DS_GET_HW_SPEC) + S_DS_GEN);
4201 	memcpy(pmpriv->adapter, hw_spec->permanent_addr, pmpriv->curr_addr,
4202 	       MLAN_MAC_ADDR_LENGTH);
4203 
4204 	LEAVE();
4205 	return MLAN_STATUS_SUCCESS;
4206 }
4207 
4208 /**
4209  *  @brief This function prepares command of sdio rx aggr command.
4210  *
4211  *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
4212  *  @param cmd_action   Command action: GET or SET
4213  *  @param pdata_buf    A pointer to new setting buf
4214 
4215  *  @return             MLAN_STATUS_SUCCESS
4216  */
4217 mlan_status
4218 wlan_cmd_sdio_rx_aggr_cfg(IN HostCmd_DS_COMMAND *pcmd,
4219 			  IN t_u16 cmd_action, IN t_void *pdata_buf)
4220 {
4221 	HostCmd_DS_SDIO_SP_RX_AGGR_CFG *cfg = &pcmd->params.sdio_rx_aggr;
4222 
4223 	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_SDIO_SP_RX_AGGR_CFG);
4224 	pcmd->size =
4225 		wlan_cpu_to_le16(sizeof(HostCmd_DS_SDIO_SP_RX_AGGR_CFG) +
4226 				 S_DS_GEN);
4227 	cfg->action = cmd_action;
4228 	if (cmd_action == HostCmd_ACT_GEN_SET)
4229 		cfg->enable = *(t_u8 *)pdata_buf;
4230 	return MLAN_STATUS_SUCCESS;
4231 }
4232 
4233 /**
4234  *  @brief This function handles the command response of sdio rx aggr command
4235  *
4236  *  @param pmpriv       A pointer to mlan_private structure
4237  *  @param resp         A pointer to HostCmd_DS_COMMAND
4238  *
4239  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4240  */
4241 mlan_status
4242 wlan_ret_sdio_rx_aggr_cfg(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *resp)
4243 {
4244 	mlan_adapter *pmadapter = pmpriv->adapter;
4245 	HostCmd_DS_SDIO_SP_RX_AGGR_CFG *cfg = &resp->params.sdio_rx_aggr;
4246 
4247 	pmadapter->sdio_rx_aggr_enable = cfg->enable;
4248 	pmadapter->sdio_rx_block_size = wlan_le16_to_cpu(cfg->sdio_block_size);
4249 	PRINTM(MMSG, "SDIO rx aggr: %d block_size=%d\n",
4250 	       cfg->enable, pmadapter->sdio_rx_block_size);
4251 	if (!pmadapter->sdio_rx_block_size)
4252 		pmadapter->sdio_rx_aggr_enable = MFALSE;
4253 	if (pmadapter->sdio_rx_aggr_enable) {
4254 		pmadapter->max_sp_rx_size = SDIO_CMD53_MAX_SIZE;
4255 		wlan_re_alloc_sdio_rx_mpa_buffer(pmadapter);
4256 	}
4257 	return MLAN_STATUS_SUCCESS;
4258 }
4259 
4260 /**
4261  *  @brief This function prepares command of set_cfg_data.
4262  *
4263  *  @param pmpriv       A pointer to mlan_private strcture
4264  *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
4265  *  @param cmd_action   Command action: GET or SET
4266  *  @param pdata_buf    A pointer to cal_data buf
4267  *
4268  *  @return             MLAN_STATUS_SUCCESS
4269  */
4270 mlan_status
4271 wlan_cmd_cfg_data(IN pmlan_private pmpriv,
4272 		  IN HostCmd_DS_COMMAND *pcmd,
4273 		  IN t_u16 cmd_action, IN t_u32 cmd_oid, IN t_void *pdata_buf)
4274 {
4275 	mlan_status ret = MLAN_STATUS_SUCCESS;
4276 	HostCmd_DS_802_11_CFG_DATA *pcfg_data = &(pcmd->params.cfg_data);
4277 	pmlan_adapter pmadapter = pmpriv->adapter;
4278 	t_u32 len;
4279 	t_u32 data_offset;
4280 	t_u8 *temp_pcmd = (t_u8 *)pcmd;
4281 
4282 	ENTER();
4283 
4284 	data_offset = S_DS_GEN + sizeof(HostCmd_DS_802_11_CFG_DATA);
4285 
4286 	if ((cmd_oid == OID_TYPE_CAL) && (pmadapter->pcal_data) &&
4287 	    (pmadapter->cal_data_len > 0)) {
4288 		len = wlan_parse_cal_cfg((t_u8 *)pmadapter->pcal_data,
4289 					 pmadapter->cal_data_len,
4290 					 (t_u8 *)(temp_pcmd + data_offset));
4291 	} else if ((cmd_oid == OID_TYPE_DPD) && (pmadapter->pdpd_data) &&
4292 		   (pmadapter->dpd_data_len > 0)) {
4293 		len = wlan_parse_cal_cfg((t_u8 *)pmadapter->pdpd_data,
4294 					 pmadapter->dpd_data_len,
4295 					 (t_u8 *)(temp_pcmd + data_offset));
4296 	} else {
4297 		ret = MLAN_STATUS_FAILURE;
4298 		goto done;
4299 	}
4300 
4301 	pcfg_data->action = cmd_action;
4302 	pcfg_data->type = cmd_oid;
4303 	pcfg_data->data_len = len;
4304 
4305 	pcmd->command = HostCmd_CMD_CFG_DATA;
4306 	pcmd->size = pcfg_data->data_len + data_offset;
4307 
4308 	pcmd->command = wlan_cpu_to_le16(pcmd->command);
4309 	pcmd->size = wlan_cpu_to_le16(pcmd->size);
4310 
4311 	pcfg_data->action = wlan_cpu_to_le16(pcfg_data->action);
4312 	pcfg_data->type = wlan_cpu_to_le16(pcfg_data->type);
4313 	pcfg_data->data_len = wlan_cpu_to_le16(pcfg_data->data_len);
4314 
4315 done:
4316 	LEAVE();
4317 	return ret;
4318 }
4319 
4320 /**
4321  *  @brief This function handles the command response of set_cfg_data
4322  *
4323  *  @param pmpriv       A pointer to mlan_private structure
4324  *  @param resp         A pointer to HostCmd_DS_COMMAND
4325  *  @param pioctl_buf   A pointer to A pointer to mlan_ioctl_req
4326  *
4327  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4328  */
4329 mlan_status
4330 wlan_ret_cfg_data(IN pmlan_private pmpriv,
4331 		  IN HostCmd_DS_COMMAND *resp, IN t_void *pioctl_buf)
4332 {
4333 	mlan_status ret = MLAN_STATUS_SUCCESS;
4334 
4335 	ENTER();
4336 
4337 	if (resp->result != HostCmd_RESULT_OK) {
4338 		PRINTM(MERROR, "CFG data cmd resp failed\n");
4339 		ret = MLAN_STATUS_FAILURE;
4340 	}
4341 	LEAVE();
4342 	return ret;
4343 }
4344 
4345 /**
4346  *  @brief This function prepares command of mac_control.
4347  *
4348  *  @param pmpriv       A pointer to mlan_private structure
4349  *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
4350  *  @param cmd_action   Command action
4351  *  @param pdata_buf    A pointer to command information buffer
4352  *
4353  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4354  */
4355 mlan_status
4356 wlan_cmd_mac_control(IN pmlan_private pmpriv,
4357 		     IN HostCmd_DS_COMMAND *pcmd,
4358 		     IN t_u16 cmd_action, IN t_void *pdata_buf)
4359 {
4360 	HostCmd_DS_MAC_CONTROL *pmac = &pcmd->params.mac_ctrl;
4361 	t_u32 action = *((t_u32 *)pdata_buf);
4362 
4363 	ENTER();
4364 
4365 	if (cmd_action != HostCmd_ACT_GEN_SET) {
4366 		PRINTM(MERROR, "wlan_cmd_mac_control(): support SET only.\n");
4367 		LEAVE();
4368 		return MLAN_STATUS_FAILURE;
4369 	}
4370 
4371 	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_MAC_CONTROL);
4372 	pcmd->size =
4373 		wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_CONTROL) + S_DS_GEN);
4374 	pmac->action = wlan_cpu_to_le32(action);
4375 
4376 	LEAVE();
4377 	return MLAN_STATUS_SUCCESS;
4378 }
4379 
4380 /**
4381  *  @brief This function handles the command response of mac_control
4382  *
4383  *  @param pmpriv       A pointer to mlan_private structure
4384  *  @param resp         A pointer to HostCmd_DS_COMMAND
4385  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
4386  *
4387  *  @return             MLAN_STATUS_SUCCESS
4388  */
4389 mlan_status
4390 wlan_ret_mac_control(IN pmlan_private pmpriv,
4391 		     IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
4392 {
4393 	ENTER();
4394 	LEAVE();
4395 	return MLAN_STATUS_SUCCESS;
4396 }
4397 
4398 /**
4399  *  @brief This function handles the command response of get_hw_spec
4400  *
4401  *  @param pmpriv       A pointer to mlan_private structure
4402  *  @param resp         A pointer to HostCmd_DS_COMMAND
4403  *  @param pioctl_buf   A pointer to command buffer
4404  *
4405  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4406  */
4407 mlan_status
4408 wlan_ret_get_hw_spec(IN pmlan_private pmpriv,
4409 		     IN HostCmd_DS_COMMAND *resp, IN t_void *pioctl_buf)
4410 {
4411 	HostCmd_DS_GET_HW_SPEC *hw_spec = &resp->params.hw_spec;
4412 	mlan_adapter *pmadapter = pmpriv->adapter;
4413 	mlan_status ret = MLAN_STATUS_SUCCESS;
4414 	t_u32 i;
4415 	t_u16 left_len;
4416 	t_u16 tlv_type = 0;
4417 	t_u16 tlv_len = 0;
4418 	MrvlIEtypes_fw_ver_info_t *api_rev = MNULL;
4419 	t_u16 api_id = 0;
4420 	MrvlIEtypesHeader_t *tlv = MNULL;
4421 	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
4422 	MrvlIEtypes_Max_Conn_t *tlv_max_conn = MNULL;
4423 
4424 	ENTER();
4425 
4426 	pmadapter->fw_cap_info = wlan_le32_to_cpu(hw_spec->fw_cap_info);
4427 	pmadapter->fw_cap_info &= pmadapter->init_para.dev_cap_mask;
4428 
4429 	PRINTM(MMSG, "fw_cap_info=0x%x, dev_cap_mask=0x%x\n",
4430 	       wlan_le32_to_cpu(hw_spec->fw_cap_info),
4431 	       pmadapter->init_para.dev_cap_mask);
4432 #ifdef STA_SUPPORT
4433 	if (IS_SUPPORT_MULTI_BANDS(pmadapter))
4434 		pmadapter->fw_bands = (t_u8)GET_FW_DEFAULT_BANDS(pmadapter);
4435 	else
4436 		pmadapter->fw_bands = BAND_B;
4437 
4438 	pmadapter->config_bands = pmadapter->fw_bands;
4439 	for (i = 0; i < pmadapter->priv_num; i++) {
4440 		if (pmadapter->priv[i])
4441 			pmadapter->priv[i]->config_bands = pmadapter->fw_bands;
4442 	}
4443 
4444 	if (pmadapter->fw_bands & BAND_A) {
4445 		if (pmadapter->fw_bands & BAND_GN) {
4446 			pmadapter->config_bands |= BAND_AN;
4447 			for (i = 0; i < pmadapter->priv_num; i++) {
4448 				if (pmadapter->priv[i])
4449 					pmadapter->priv[i]->config_bands |=
4450 						BAND_AN;
4451 			}
4452 
4453 			pmadapter->fw_bands |= BAND_AN;
4454 		}
4455 		if ((pmadapter->fw_bands & BAND_AN)
4456 			) {
4457 			pmadapter->adhoc_start_band = BAND_A | BAND_AN;
4458 			pmadapter->adhoc_11n_enabled = MTRUE;
4459 		} else
4460 			pmadapter->adhoc_start_band = BAND_A;
4461 		pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A;
4462 	} else if ((pmadapter->fw_bands & BAND_GN)
4463 		) {
4464 		pmadapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN;
4465 		pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
4466 		pmadapter->adhoc_11n_enabled = MTRUE;
4467 	} else if (pmadapter->fw_bands & BAND_G) {
4468 		pmadapter->adhoc_start_band = BAND_G | BAND_B;
4469 		pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
4470 	} else if (pmadapter->fw_bands & BAND_B) {
4471 		pmadapter->adhoc_start_band = BAND_B;
4472 		pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL;
4473 	}
4474 #endif /* STA_SUPPORT */
4475 
4476 	pmadapter->fw_release_number =
4477 		wlan_le32_to_cpu(hw_spec->fw_release_number);
4478 	pmadapter->number_of_antenna =
4479 		wlan_le16_to_cpu(hw_spec->number_of_antenna) & 0x00ff;
4480 	pmadapter->antinfo =
4481 		(wlan_le16_to_cpu(hw_spec->number_of_antenna) & 0xff00) >> 8;
4482 	PRINTM(MCMND, "num_ant=%d, antinfo=0x%x\n",
4483 	       pmadapter->number_of_antenna, pmadapter->antinfo);
4484 
4485 	PRINTM(MINFO, "GET_HW_SPEC: fw_release_number- 0x%X\n",
4486 	       pmadapter->fw_release_number);
4487 	PRINTM(MINFO, "GET_HW_SPEC: Permanent addr- " MACSTR "\n",
4488 	       MAC2STR(hw_spec->permanent_addr));
4489 	PRINTM(MINFO, "GET_HW_SPEC: hw_if_version=0x%X  version=0x%X\n",
4490 	       wlan_le16_to_cpu(hw_spec->hw_if_version),
4491 	       wlan_le16_to_cpu(hw_spec->version));
4492 
4493 	if (pmpriv->curr_addr[0] == 0xff)
4494 		memmove(pmadapter, pmpriv->curr_addr, hw_spec->permanent_addr,
4495 			MLAN_MAC_ADDR_LENGTH);
4496 	memmove(pmadapter, pmadapter->permanent_addr, hw_spec->permanent_addr,
4497 		MLAN_MAC_ADDR_LENGTH);
4498 	pmadapter->hw_dot_11n_dev_cap =
4499 		wlan_le32_to_cpu(hw_spec->dot_11n_dev_cap);
4500 	pmadapter->hw_dev_mcs_support = hw_spec->dev_mcs_support;
4501 	for (i = 0; i < pmadapter->priv_num; i++) {
4502 		if (pmadapter->priv[i])
4503 			wlan_update_11n_cap(pmadapter->priv[i]);
4504 	}
4505 
4506 	wlan_show_dot11ndevcap(pmadapter, pmadapter->hw_dot_11n_dev_cap);
4507 	wlan_show_devmcssupport(pmadapter, pmadapter->hw_dev_mcs_support);
4508 	if (ISSUPP_BEAMFORMING(pmadapter->hw_dot_11n_dev_cap)) {
4509 		PRINTM(MCMND, "Enable Beamforming\n");
4510 		for (i = 0; i < pmadapter->priv_num; i++) {
4511 			if (pmadapter->priv[i])
4512 				pmadapter->priv[i]->tx_bf_cap =
4513 					DEFAULT_11N_TX_BF_CAP;
4514 		}
4515 	}
4516 	pmadapter->mp_end_port = wlan_le16_to_cpu(hw_spec->mp_end_port);
4517 
4518 	for (i = 1; i <= (unsigned)(MAX_PORT - pmadapter->mp_end_port); i++)
4519 		pmadapter->mp_data_port_mask &= ~(1 << (MAX_PORT - i));
4520 
4521 	pmadapter->max_mgmt_ie_index =
4522 		wlan_le16_to_cpu(hw_spec->mgmt_buf_count);
4523 	PRINTM(MINFO, "GET_HW_SPEC: mgmt IE count=%d\n",
4524 	       pmadapter->max_mgmt_ie_index);
4525 	if (!pmadapter->max_mgmt_ie_index)
4526 		pmadapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
4527 
4528 	pmadapter->region_code = wlan_le16_to_cpu(hw_spec->region_code);
4529 	for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
4530 		/* Use the region code to search for the index */
4531 		if (pmadapter->region_code == region_code_index[i])
4532 			break;
4533 	}
4534 	/* If it's unidentified region code, use the default */
4535 	if (i >= MRVDRV_MAX_REGION_CODE) {
4536 		pmadapter->region_code = MRVDRV_DEFAULT_REGION_CODE;
4537 		PRINTM(MWARN,
4538 		       "unidentified region code, use the default (0x%02x)\n",
4539 		       MRVDRV_DEFAULT_REGION_CODE);
4540 	}
4541 	/* Synchronize CFP code with region code */
4542 	pmadapter->cfp_code_bg = pmadapter->region_code;
4543 	pmadapter->cfp_code_a = pmadapter->region_code;
4544 
4545 	if (pmadapter->fw_cap_info & ENHANCE_EXT_SCAN_ENABLE)
4546 		pmadapter->ext_scan_enh = MTRUE;
4547 
4548 	if ((pmadapter->fw_cap_info & SDIO_SP_RX_AGGR_ENABLE) &&
4549 	    pmadapter->sdio_rx_aggr_enable) {
4550 		t_u8 sdio_sp_rx_aggr = MTRUE;
4551 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SDIO_SP_RX_AGGR_CFG,
4552 				       HostCmd_ACT_GEN_SET, 0, MNULL,
4553 				       &sdio_sp_rx_aggr);
4554 		if (ret) {
4555 			ret = MLAN_STATUS_FAILURE;
4556 			goto done;
4557 		}
4558 	} else {
4559 		pmadapter->sdio_rx_aggr_enable = MFALSE;
4560 		PRINTM(MCMND, "FW: SDIO rx aggr disabled 0x%x\n",
4561 		       pmadapter->fw_cap_info);
4562 	}
4563 
4564 	if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
4565 				 pmadapter->fw_bands)) {
4566 		if (pioctl_req)
4567 			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
4568 		ret = MLAN_STATUS_FAILURE;
4569 		goto done;
4570 	}
4571 #ifdef STA_SUPPORT
4572 	if (wlan_11d_set_universaltable(pmpriv, pmadapter->fw_bands)) {
4573 		if (pioctl_req)
4574 			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
4575 		ret = MLAN_STATUS_FAILURE;
4576 		goto done;
4577 	}
4578 #endif /* STA_SUPPORT */
4579 	if (pmadapter->fw_cap_info & FW_CAPINFO_ECSA) {
4580 		t_u8 ecsa_enable = MTRUE;
4581 		pmadapter->ecsa_enable = MTRUE;
4582 		PRINTM(MCMND, "pmadapter->ecsa_enable=%d\n",
4583 		       pmadapter->ecsa_enable);
4584 		ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB,
4585 				       HostCmd_ACT_GEN_SET, ECSAEnable_i, MNULL,
4586 				       &ecsa_enable);
4587 		if (ret) {
4588 			ret = MLAN_STATUS_FAILURE;
4589 			goto done;
4590 		}
4591 	}
4592 	if (pmadapter->fw_cap_info & FW_CAPINFO_GET_LOG) {
4593 		pmadapter->getlog_enable = MTRUE;
4594 		PRINTM(MCMND, "pmadapter->getlog_enable=%d\n",
4595 		       pmadapter->getlog_enable);
4596 	}
4597 
4598 	left_len = resp->size - sizeof(HostCmd_DS_GET_HW_SPEC) - S_DS_GEN;
4599 	tlv = (MrvlIEtypesHeader_t *)((t_u8 *)hw_spec +
4600 				      sizeof(HostCmd_DS_GET_HW_SPEC));
4601 	while (left_len > sizeof(MrvlIEtypesHeader_t)) {
4602 		tlv_type = wlan_le16_to_cpu(tlv->type);
4603 		tlv_len = wlan_le16_to_cpu(tlv->len);
4604 		switch (tlv_type) {
4605 		case TLV_TYPE_FW_VER_INFO:
4606 			api_rev = (MrvlIEtypes_fw_ver_info_t *) tlv;
4607 			api_id = wlan_le16_to_cpu(api_rev->api_id);
4608 			switch (api_id) {
4609 			case FW_API_VER_ID:
4610 				pmadapter->fw_ver = api_rev->major_ver;
4611 				pmadapter->fw_min_ver = api_rev->minor_ver;
4612 				PRINTM(MCMND, "fw ver=%d.%d\n",
4613 				       api_rev->major_ver, api_rev->minor_ver);
4614 				break;
4615 			case UAP_FW_API_VER_ID:
4616 				pmadapter->uap_fw_ver = api_rev->major_ver;
4617 				PRINTM(MCMND, "uap fw ver=%d.%d\n",
4618 				       api_rev->major_ver, api_rev->minor_ver);
4619 				break;
4620 			case CHANRPT_API_VER_ID:
4621 				pmadapter->chanrpt_param_bandcfg =
4622 					api_rev->minor_ver;
4623 				PRINTM(MCMND, "chanrpt api ver=%d.%d\n",
4624 				       api_rev->major_ver, api_rev->minor_ver);
4625 				break;
4626 			default:
4627 				break;
4628 			}
4629 			break;
4630 		case TLV_TYPE_MAX_CONN:
4631 			tlv_max_conn = (MrvlIEtypes_Max_Conn_t *) tlv;
4632 			PRINTM(MMSG, "max_p2p_conn = %d, max_sta_conn = %d\n",
4633 			       tlv_max_conn->max_p2p_conn,
4634 			       tlv_max_conn->max_sta_conn);
4635 			if (tlv_max_conn->max_p2p_conn &&
4636 			    tlv_max_conn->max_sta_conn)
4637 				pmadapter->max_sta_conn =
4638 					MIN(tlv_max_conn->max_sta_conn,
4639 					    tlv_max_conn->max_p2p_conn);
4640 			else if (tlv_max_conn->max_sta_conn)
4641 				pmadapter->max_sta_conn =
4642 					tlv_max_conn->max_sta_conn;
4643 			else if (tlv_max_conn->max_p2p_conn)
4644 				pmadapter->max_sta_conn =
4645 					tlv_max_conn->max_p2p_conn;
4646 			else
4647 				pmadapter->max_sta_conn = 0;
4648 			break;
4649 		default:
4650 			break;
4651 		}
4652 		left_len -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
4653 		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
4654 					      sizeof(MrvlIEtypesHeader_t));
4655 	}
4656 done:
4657 	LEAVE();
4658 	return ret;
4659 }
4660 
4661 /**
4662  *  @brief This function prepares command of radio_control.
4663  *
4664  *  @param pmpriv       A pointer to mlan_private structure
4665  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
4666  *  @param cmd_action   The action: GET or SET
4667  *  @param pdata_buf    A pointer to data buffer
4668  *
4669  *  @return             MLAN_STATUS_SUCCESS
4670  */
4671 mlan_status
4672 wlan_cmd_802_11_radio_control(IN pmlan_private pmpriv,
4673 			      IN HostCmd_DS_COMMAND *cmd,
4674 			      IN t_u16 cmd_action, IN t_void *pdata_buf)
4675 {
4676 	HostCmd_DS_802_11_RADIO_CONTROL *pradio_control = &cmd->params.radio;
4677 	t_u32 radio_ctl;
4678 	ENTER();
4679 	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_RADIO_CONTROL))
4680 				     + S_DS_GEN);
4681 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RADIO_CONTROL);
4682 	pradio_control->action = wlan_cpu_to_le16(cmd_action);
4683 	memcpy(pmpriv->adapter, &radio_ctl, pdata_buf, sizeof(t_u32));
4684 	pradio_control->control = wlan_cpu_to_le16((t_u16)radio_ctl);
4685 	LEAVE();
4686 	return MLAN_STATUS_SUCCESS;
4687 }
4688 
4689 /**
4690  *  @brief This function handles the command response of radio_control
4691  *
4692  *  @param pmpriv       A pointer to mlan_private structure
4693  *  @param resp         A pointer to HostCmd_DS_COMMAND
4694  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
4695  *
4696  *  @return             MLAN_STATUS_SUCCESS
4697  */
4698 mlan_status
4699 wlan_ret_802_11_radio_control(IN pmlan_private pmpriv,
4700 			      IN HostCmd_DS_COMMAND *resp,
4701 			      IN mlan_ioctl_req *pioctl_buf)
4702 {
4703 	HostCmd_DS_802_11_RADIO_CONTROL *pradio_ctrl =
4704 		(HostCmd_DS_802_11_RADIO_CONTROL *)&resp->params.radio;
4705 	mlan_ds_radio_cfg *radio_cfg = MNULL;
4706 	mlan_adapter *pmadapter = pmpriv->adapter;
4707 
4708 	ENTER();
4709 	pmadapter->radio_on = wlan_le16_to_cpu(pradio_ctrl->control);
4710 	if (pioctl_buf) {
4711 		radio_cfg = (mlan_ds_radio_cfg *)pioctl_buf->pbuf;
4712 		radio_cfg->param.radio_on_off = (t_u32)pmadapter->radio_on;
4713 		pioctl_buf->data_read_written = sizeof(mlan_ds_radio_cfg);
4714 	}
4715 	LEAVE();
4716 	return MLAN_STATUS_SUCCESS;
4717 }
4718 
4719 /**
4720  *  @brief This function prepares command of remain_on_channel.
4721  *
4722  *  @param pmpriv       A pointer to mlan_private structure
4723  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
4724  *  @param cmd_action   The action: GET or SET
4725  *  @param pdata_buf    A pointer to data buffer
4726  *
4727  *  @return             MLAN_STATUS_SUCCESS
4728  */
4729 mlan_status
4730 wlan_cmd_remain_on_channel(IN pmlan_private pmpriv,
4731 			   IN HostCmd_DS_COMMAND *cmd,
4732 			   IN t_u16 cmd_action, IN t_void *pdata_buf)
4733 {
4734 	HostCmd_DS_REMAIN_ON_CHANNEL *remain_channel =
4735 		&cmd->params.remain_on_chan;
4736 	mlan_ds_remain_chan *cfg = (mlan_ds_remain_chan *)pdata_buf;
4737 	ENTER();
4738 	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_REMAIN_ON_CHANNEL))
4739 				     + S_DS_GEN);
4740 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_REMAIN_ON_CHANNEL);
4741 	remain_channel->action = cmd_action;
4742 	if (cmd_action == HostCmd_ACT_GEN_SET) {
4743 		if (cfg->remove) {
4744 			remain_channel->action = HostCmd_ACT_GEN_REMOVE;
4745 		} else {
4746 			remain_channel->bandcfg = cfg->bandcfg;
4747 			remain_channel->channel = cfg->channel;
4748 			remain_channel->remain_period =
4749 				wlan_cpu_to_le32(cfg->remain_period);
4750 		}
4751 	}
4752 	remain_channel->action = wlan_cpu_to_le16(remain_channel->action);
4753 
4754 	LEAVE();
4755 	return MLAN_STATUS_SUCCESS;
4756 }
4757 
4758 /**
4759  *  @brief This function handles the command response of remain_on_channel
4760  *
4761  *  @param pmpriv       A pointer to mlan_private structure
4762  *  @param resp         A pointer to HostCmd_DS_COMMAND
4763  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
4764  *
4765  *  @return             MLAN_STATUS_SUCCESS
4766  */
4767 mlan_status
4768 wlan_ret_remain_on_channel(IN pmlan_private pmpriv,
4769 			   IN HostCmd_DS_COMMAND *resp,
4770 			   IN mlan_ioctl_req *pioctl_buf)
4771 {
4772 	HostCmd_DS_REMAIN_ON_CHANNEL *remain_channel =
4773 		&resp->params.remain_on_chan;
4774 	mlan_ds_radio_cfg *radio_cfg = MNULL;
4775 
4776 	ENTER();
4777 	if (pioctl_buf) {
4778 		radio_cfg = (mlan_ds_radio_cfg *)pioctl_buf->pbuf;
4779 		radio_cfg->param.remain_chan.status = remain_channel->status;
4780 		radio_cfg->param.remain_chan.bandcfg = remain_channel->bandcfg;
4781 		radio_cfg->param.remain_chan.channel = remain_channel->channel;
4782 		radio_cfg->param.remain_chan.remain_period =
4783 			wlan_le32_to_cpu(remain_channel->remain_period);
4784 		pioctl_buf->data_read_written = sizeof(mlan_ds_radio_cfg);
4785 	}
4786 	LEAVE();
4787 	return MLAN_STATUS_SUCCESS;
4788 }
4789 
4790 #ifdef WIFI_DIRECT_SUPPORT
4791 
4792 /**
4793  *  @brief This function prepares command of wifi direct mode.
4794  *
4795  *  @param pmpriv       A pointer to mlan_private structure
4796  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
4797  *  @param cmd_action   The action: GET or SET
4798  *  @param pdata_buf    A pointer to data buffer
4799  *
4800  *  @return             MLAN_STATUS_SUCCESS
4801  */
4802 mlan_status
4803 wlan_cmd_wifi_direct_mode(IN pmlan_private pmpriv,
4804 			  IN HostCmd_DS_COMMAND *cmd,
4805 			  IN t_u16 cmd_action, IN t_void *pdata_buf)
4806 {
4807 	HostCmd_DS_WIFI_DIRECT_MODE *wfd_mode = &cmd->params.wifi_direct_mode;
4808 	t_u16 mode = *((t_u16 *)pdata_buf);
4809 	ENTER();
4810 	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_WIFI_DIRECT_MODE))
4811 				     + S_DS_GEN);
4812 	cmd->command = wlan_cpu_to_le16(HOST_CMD_WIFI_DIRECT_MODE_CONFIG);
4813 	wfd_mode->action = wlan_cpu_to_le16(cmd_action);
4814 	if (cmd_action == HostCmd_ACT_GEN_SET)
4815 		wfd_mode->mode = wlan_cpu_to_le16(mode);
4816 
4817 	LEAVE();
4818 	return MLAN_STATUS_SUCCESS;
4819 }
4820 
4821 /**
4822  *  @brief This function handles the command response of wifi direct mode
4823  *
4824  *  @param pmpriv       A pointer to mlan_private structure
4825  *  @param resp         A pointer to HostCmd_DS_COMMAND
4826  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
4827  *
4828  *  @return             MLAN_STATUS_SUCCESS
4829  */
4830 mlan_status
4831 wlan_ret_wifi_direct_mode(IN pmlan_private pmpriv,
4832 			  IN HostCmd_DS_COMMAND *resp,
4833 			  IN mlan_ioctl_req *pioctl_buf)
4834 {
4835 	HostCmd_DS_WIFI_DIRECT_MODE *wfd_mode = &resp->params.wifi_direct_mode;
4836 	mlan_ds_bss *bss = MNULL;
4837 
4838 	ENTER();
4839 	if (pioctl_buf) {
4840 		bss = (mlan_ds_bss *)pioctl_buf->pbuf;
4841 		bss->param.wfd_mode = wlan_le16_to_cpu(wfd_mode->mode);
4842 		pioctl_buf->data_read_written = sizeof(mlan_ds_bss);
4843 	}
4844 	LEAVE();
4845 	return MLAN_STATUS_SUCCESS;
4846 }
4847 
4848 /**
4849  *  @brief This function prepares command of p2p_params_config.
4850  *
4851  *  @param pmpriv       A pointer to mlan_private structure
4852  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
4853  *  @param cmd_action   The action: GET or SET
4854  *  @param pdata_buf    A pointer to data buffer
4855  *
4856  *  @return             MLAN_STATUS_SUCCESS
4857  */
4858 mlan_status
4859 wlan_cmd_p2p_params_config(IN pmlan_private pmpriv,
4860 			   IN HostCmd_DS_COMMAND *cmd,
4861 			   IN t_u16 cmd_action, IN t_void *pdata_buf)
4862 {
4863 	HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG *p2p_config =
4864 		&cmd->params.p2p_params_config;
4865 	mlan_ds_wifi_direct_config *cfg =
4866 		(mlan_ds_wifi_direct_config *)pdata_buf;
4867 	MrvlIEtypes_NoA_setting_t *pnoa_tlv = MNULL;
4868 	MrvlIEtypes_OPP_PS_setting_t *popp_ps_tlv = MNULL;
4869 	t_u8 *tlv = MNULL;
4870 	ENTER();
4871 
4872 	cmd->size = sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG) + S_DS_GEN;
4873 	cmd->command = wlan_cpu_to_le16(HOST_CMD_P2P_PARAMS_CONFIG);
4874 	p2p_config->action = wlan_cpu_to_le16(cmd_action);
4875 	if (cmd_action == HostCmd_ACT_GEN_SET) {
4876 		tlv = (t_u8 *)p2p_config +
4877 			sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG);
4878 		if (cfg->flags & WIFI_DIRECT_NOA) {
4879 			pnoa_tlv = (MrvlIEtypes_NoA_setting_t *)tlv;
4880 			pnoa_tlv->header.type =
4881 				wlan_cpu_to_le16(TLV_TYPE_WIFI_DIRECT_NOA);
4882 			pnoa_tlv->header.len =
4883 				wlan_cpu_to_le16(sizeof
4884 						 (MrvlIEtypes_NoA_setting_t) -
4885 						 sizeof(MrvlIEtypesHeader_t));
4886 			pnoa_tlv->enable = cfg->noa_enable;
4887 			pnoa_tlv->index = wlan_cpu_to_le16(cfg->index);
4888 			pnoa_tlv->noa_count = cfg->noa_count;
4889 			pnoa_tlv->noa_duration =
4890 				wlan_cpu_to_le32(cfg->noa_duration);
4891 			pnoa_tlv->noa_interval =
4892 				wlan_cpu_to_le32(cfg->noa_interval);
4893 			cmd->size += sizeof(MrvlIEtypes_NoA_setting_t);
4894 			tlv += sizeof(MrvlIEtypes_NoA_setting_t);
4895 			PRINTM(MCMND,
4896 			       "Set NOA: enable=%d index=%d, count=%d, duration=%d interval=%d\n",
4897 			       cfg->noa_enable, cfg->index, cfg->noa_count,
4898 			       (int)cfg->noa_duration, (int)cfg->noa_interval);
4899 		}
4900 		if (cfg->flags & WIFI_DIRECT_OPP_PS) {
4901 			popp_ps_tlv = (MrvlIEtypes_OPP_PS_setting_t *)tlv;
4902 			popp_ps_tlv->header.type =
4903 				wlan_cpu_to_le16(TLV_TYPE_WIFI_DIRECT_OPP_PS);
4904 			popp_ps_tlv->header.len =
4905 				wlan_cpu_to_le16(sizeof
4906 						 (MrvlIEtypes_OPP_PS_setting_t)
4907 						 - sizeof(MrvlIEtypesHeader_t));
4908 
4909 			popp_ps_tlv->enable = cfg->ct_window;
4910 			popp_ps_tlv->enable |= cfg->opp_ps_enable << 7;
4911 			cmd->size += sizeof(MrvlIEtypes_OPP_PS_setting_t);
4912 			PRINTM(MCMND, "Set OPP_PS: enable=%d ct_win=%d\n",
4913 			       cfg->opp_ps_enable, cfg->ct_window);
4914 		}
4915 	} else if (cmd_action == HostCmd_ACT_GEN_GET) {
4916 		tlv = (t_u8 *)p2p_config +
4917 			sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG);
4918 		if (cfg->flags & WIFI_DIRECT_NOA) {
4919 			pnoa_tlv = (MrvlIEtypes_NoA_setting_t *)tlv;
4920 			pnoa_tlv->header.type =
4921 				wlan_cpu_to_le16(TLV_TYPE_WIFI_DIRECT_NOA);
4922 			pnoa_tlv->header.len =
4923 				wlan_cpu_to_le16(sizeof
4924 						 (MrvlIEtypes_NoA_setting_t) -
4925 						 sizeof(MrvlIEtypesHeader_t));
4926 			cmd->size += sizeof(MrvlIEtypes_NoA_setting_t);
4927 			tlv += sizeof(MrvlIEtypes_NoA_setting_t);
4928 		}
4929 
4930 		if (cfg->flags & WIFI_DIRECT_OPP_PS) {
4931 			popp_ps_tlv = (MrvlIEtypes_OPP_PS_setting_t *)tlv;
4932 			popp_ps_tlv->header.type =
4933 				wlan_cpu_to_le16(TLV_TYPE_WIFI_DIRECT_OPP_PS);
4934 			popp_ps_tlv->header.len =
4935 				wlan_cpu_to_le16(sizeof
4936 						 (MrvlIEtypes_OPP_PS_setting_t)
4937 						 - sizeof(MrvlIEtypesHeader_t));
4938 			cmd->size += sizeof(MrvlIEtypes_OPP_PS_setting_t);
4939 		}
4940 	}
4941 	cmd->size = wlan_cpu_to_le16(cmd->size);
4942 	LEAVE();
4943 	return MLAN_STATUS_SUCCESS;
4944 }
4945 
4946 /**
4947  *  @brief This function handles the command response of p2p_params_config
4948  *
4949  *  @param pmpriv       A pointer to mlan_private structure
4950  *  @param resp         A pointer to HostCmd_DS_COMMAND
4951  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
4952  *
4953  *  @return             MLAN_STATUS_SUCCESS
4954  */
4955 mlan_status
4956 wlan_ret_p2p_params_config(IN pmlan_private pmpriv,
4957 			   IN HostCmd_DS_COMMAND *resp,
4958 			   IN mlan_ioctl_req *pioctl_buf)
4959 {
4960 	HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG *p2p_config =
4961 		&resp->params.p2p_params_config;
4962 	mlan_ds_misc_cfg *cfg = MNULL;
4963 	MrvlIEtypes_NoA_setting_t *pnoa_tlv = MNULL;
4964 	MrvlIEtypes_OPP_PS_setting_t *popp_ps_tlv = MNULL;
4965 	MrvlIEtypesHeader_t *tlv = MNULL;
4966 	t_u16 tlv_buf_left = 0;
4967 	t_u16 tlv_type = 0;
4968 	t_u16 tlv_len = 0;
4969 
4970 	ENTER();
4971 	if (wlan_le16_to_cpu(p2p_config->action) == HostCmd_ACT_GEN_GET) {
4972 		if (pioctl_buf) {
4973 			cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
4974 			tlv = (MrvlIEtypesHeader_t *)((t_u8 *)p2p_config +
4975 						      sizeof
4976 						      (HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG));
4977 			tlv_buf_left =
4978 				resp->size -
4979 				(sizeof(HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG) +
4980 				 S_DS_GEN);
4981 			while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
4982 				tlv_type = wlan_le16_to_cpu(tlv->type);
4983 				tlv_len = wlan_le16_to_cpu(tlv->len);
4984 				if (tlv_buf_left <
4985 				    (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
4986 					PRINTM(MERROR,
4987 					       "Error processing p2p param config TLVs, bytes left < TLV length\n");
4988 					break;
4989 				}
4990 				switch (tlv_type) {
4991 				case TLV_TYPE_WIFI_DIRECT_NOA:
4992 					pnoa_tlv =
4993 						(MrvlIEtypes_NoA_setting_t *)
4994 						tlv;
4995 					cfg->param.p2p_config.flags |=
4996 						WIFI_DIRECT_NOA;
4997 					cfg->param.p2p_config.noa_enable =
4998 						pnoa_tlv->enable;
4999 					cfg->param.p2p_config.index =
5000 						wlan_le16_to_cpu(pnoa_tlv->
5001 								 index);
5002 					cfg->param.p2p_config.noa_count =
5003 						pnoa_tlv->noa_count;
5004 					cfg->param.p2p_config.noa_duration =
5005 						wlan_le32_to_cpu(pnoa_tlv->
5006 								 noa_duration);
5007 					cfg->param.p2p_config.noa_interval =
5008 						wlan_le32_to_cpu(pnoa_tlv->
5009 								 noa_interval);
5010 					PRINTM(MCMND,
5011 					       "Get NOA: enable=%d index=%d, count=%d, duration=%d interval=%d\n",
5012 					       cfg->param.p2p_config.noa_enable,
5013 					       cfg->param.p2p_config.index,
5014 					       cfg->param.p2p_config.noa_count,
5015 					       (int)cfg->param.p2p_config.
5016 					       noa_duration,
5017 					       (int)cfg->param.p2p_config.
5018 					       noa_interval);
5019 					break;
5020 				case TLV_TYPE_WIFI_DIRECT_OPP_PS:
5021 					popp_ps_tlv =
5022 						(MrvlIEtypes_OPP_PS_setting_t *)
5023 						tlv;
5024 					cfg->param.p2p_config.flags |=
5025 						WIFI_DIRECT_OPP_PS;
5026 					cfg->param.p2p_config.opp_ps_enable =
5027 						(popp_ps_tlv->
5028 						 enable & 0x80) >> 7;
5029 					cfg->param.p2p_config.ct_window =
5030 						popp_ps_tlv->enable & 0x7f;
5031 					PRINTM(MCMND,
5032 					       "Get OPP_PS: enable=%d ct_win=%d\n",
5033 					       cfg->param.p2p_config.
5034 					       opp_ps_enable,
5035 					       cfg->param.p2p_config.ct_window);
5036 					break;
5037 				default:
5038 					break;
5039 				}
5040 				tlv_buf_left -=
5041 					tlv_len + sizeof(MrvlIEtypesHeader_t);
5042 				tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv +
5043 							      tlv_len +
5044 							      sizeof
5045 							      (MrvlIEtypesHeader_t));
5046 			}
5047 			pioctl_buf->data_read_written =
5048 				sizeof(mlan_ds_wifi_direct_config);
5049 		}
5050 	}
5051 	LEAVE();
5052 	return MLAN_STATUS_SUCCESS;
5053 }
5054 #endif
5055 
5056 /**
5057  *  @brief This function prepares command of hs wakeup reason.
5058  *
5059  *  @param pmpriv       A pointer to mlan_private structure
5060  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
5061  *  @param pdata_buf    A pointer to data buffer
5062  *  @return             MLAN_STATUS_SUCCESS
5063  */
5064 mlan_status
5065 wlan_cmd_hs_wakeup_reason(IN pmlan_private pmpriv,
5066 			  IN HostCmd_DS_COMMAND *cmd, IN t_void *pdata_buf)
5067 {
5068 	ENTER();
5069 
5070 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_HS_WAKEUP_REASON);
5071 	cmd->size =
5072 		wlan_cpu_to_le16((sizeof(HostCmd_DS_HS_WAKEUP_REASON)) +
5073 				 S_DS_GEN);
5074 
5075 	LEAVE();
5076 	return MLAN_STATUS_SUCCESS;
5077 }
5078 
5079 /**
5080  *  @brief This function handles the command response of
5081  *          hs wakeup reason
5082  *
5083  *  @param pmpriv       A pointer to mlan_private structure
5084  *  @param resp         A pointer to HostCmd_DS_COMMAND
5085  *  @param pioctl_buf   A pointer to command buffer
5086  *
5087  *  @return             MLAN_STATUS_SUCCESS
5088  */
5089 mlan_status
5090 wlan_ret_hs_wakeup_reason(IN pmlan_private pmpriv,
5091 			  IN HostCmd_DS_COMMAND *resp,
5092 			  IN mlan_ioctl_req *pioctl_buf)
5093 {
5094 	HostCmd_DS_HS_WAKEUP_REASON *hs_wakeup_reason =
5095 		(HostCmd_DS_HS_WAKEUP_REASON *)&resp->params.hs_wakeup_reason;
5096 	mlan_ds_pm_cfg *pm_cfg = MNULL;
5097 
5098 	ENTER();
5099 
5100 	pm_cfg = (mlan_ds_pm_cfg *)pioctl_buf->pbuf;
5101 	pm_cfg->param.wakeup_reason.hs_wakeup_reason =
5102 		wlan_le16_to_cpu(hs_wakeup_reason->wakeup_reason);
5103 	pioctl_buf->data_read_written = sizeof(mlan_ds_pm_cfg);
5104 
5105 	LEAVE();
5106 	return MLAN_STATUS_SUCCESS;
5107 }
5108 
5109 /*
5110  *  @brief This function prepares command of cwmode control.
5111  *
5112  *  @param pmpriv       A pointer to mlan_private structure
5113  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
5114  *  @param cmd_action   The action: GET or SET
5115  *  @param pdata_buf    A pointer to data buffer
5116  *
5117  *  @return             MLAN_STATUS_SUCCESS
5118  */
5119 mlan_status
5120 wlan_cmd_cw_mode_ctrl(IN pmlan_private pmpriv,
5121 		      IN HostCmd_DS_COMMAND *cmd,
5122 		      IN t_u16 cmd_action, IN t_void *pdata_buf)
5123 {
5124 	HostCmd_DS_CW_MODE_CTRL *cwmode_ctrl = &cmd->params.cwmode;
5125 	mlan_ds_cw_mode_ctrl *cw_mode = (mlan_ds_cw_mode_ctrl *) pdata_buf;
5126 	ENTER();
5127 	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_CW_MODE_CTRL))
5128 				     + S_DS_GEN);
5129 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_CW_MODE_CTRL);
5130 	cwmode_ctrl->action = wlan_cpu_to_le16(cmd_action);
5131 
5132 	if (cmd_action == HostCmd_ACT_GEN_SET) {
5133 		cwmode_ctrl->mode = cw_mode->mode;
5134 		cwmode_ctrl->channel = cw_mode->channel;
5135 		cwmode_ctrl->chanInfo = cw_mode->chanInfo;
5136 		cwmode_ctrl->txPower = wlan_cpu_to_le16(cw_mode->txPower);
5137 		cwmode_ctrl->rateInfo = wlan_cpu_to_le32(cw_mode->rateInfo);
5138 		cwmode_ctrl->pktLength = wlan_cpu_to_le16(cw_mode->pktLength);
5139 	}
5140 	LEAVE();
5141 	return MLAN_STATUS_SUCCESS;
5142 }
5143 
5144 /*
5145  *  @brief This function handles the command response of cwmode_ctrl
5146  *
5147  *  @param pmpriv       A pointer to mlan_private structure
5148  *  @param resp         A pointer to HostCmd_DS_COMMAND
5149  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
5150  *
5151  *  @return             MLAN_STATUS_SUCCESS
5152  */
5153 mlan_status
5154 wlan_ret_cw_mode_ctrl(IN pmlan_private pmpriv,
5155 		      IN HostCmd_DS_COMMAND *resp,
5156 		      IN mlan_ioctl_req *pioctl_buf)
5157 {
5158 	HostCmd_DS_CW_MODE_CTRL *cwmode_resp = &resp->params.cwmode;
5159 	mlan_ds_misc_cfg *misc = MNULL;
5160 
5161 	ENTER();
5162 	if (pioctl_buf) {
5163 		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
5164 		misc->param.cwmode.mode = cwmode_resp->mode;
5165 		misc->param.cwmode.channel = cwmode_resp->channel;
5166 		misc->param.cwmode.chanInfo = cwmode_resp->chanInfo;
5167 		misc->param.cwmode.txPower =
5168 			wlan_le16_to_cpu(cwmode_resp->txPower);
5169 		misc->param.cwmode.rateInfo =
5170 			wlan_le32_to_cpu(cwmode_resp->rateInfo);;
5171 		misc->param.cwmode.pktLength =
5172 			wlan_le16_to_cpu(cwmode_resp->pktLength);;
5173 		pioctl_buf->data_read_written = sizeof(mlan_ds_misc_cfg);
5174 	}
5175 	LEAVE();
5176 	return MLAN_STATUS_SUCCESS;
5177 }
5178 
5179 /**
5180  *  @brief This function prepares command of rf_antenna.
5181  *
5182  *  @param pmpriv   A pointer to mlan_private structure
5183  *  @param cmd      A pointer to HostCmd_DS_COMMAND structure
5184  *  @param cmd_action   The action: GET or SET
5185  *  @param pdata_buf    A pointer to data buffer
5186  *
5187  *  @return         MLAN_STATUS_SUCCESS
5188  */
5189 mlan_status
5190 wlan_cmd_802_11_rf_antenna(IN pmlan_private pmpriv,
5191 			   IN HostCmd_DS_COMMAND *cmd,
5192 			   IN t_u16 cmd_action, IN t_void *pdata_buf)
5193 {
5194 	HostCmd_DS_802_11_RF_ANTENNA *pantenna = &cmd->params.antenna;
5195 	mlan_ds_ant_cfg_1x1 *ant_cfg_1x1 = (mlan_ds_ant_cfg_1x1 *) pdata_buf;
5196 
5197 	ENTER();
5198 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_ANTENNA);
5199 	cmd->size =
5200 		wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RF_ANTENNA) +
5201 				 S_DS_GEN);
5202 
5203 	if (cmd_action == HostCmd_ACT_GEN_SET) {
5204 		pantenna->action = wlan_cpu_to_le16(HostCmd_ACT_SET_BOTH);
5205 		pantenna->antenna_mode =
5206 			wlan_cpu_to_le16((t_u16)ant_cfg_1x1->antenna);
5207 		pantenna->evaluate_time =
5208 			wlan_cpu_to_le16((t_u16)ant_cfg_1x1->evaluate_time);
5209 	} else {
5210 		pantenna->action = wlan_cpu_to_le16(HostCmd_ACT_GET_BOTH);
5211 	}
5212 	LEAVE();
5213 	return MLAN_STATUS_SUCCESS;
5214 }
5215 
5216 /**
5217  *  @brief This function handles the command response of rf_antenna
5218  *
5219  *  @param pmpriv       A pointer to mlan_private structure
5220  *  @param resp         A pointer to HostCmd_DS_COMMAND
5221  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
5222  *
5223  *  @return             MLAN_STATUS_SUCCESS
5224  */
5225 mlan_status
5226 wlan_ret_802_11_rf_antenna(IN pmlan_private pmpriv,
5227 			   IN HostCmd_DS_COMMAND *resp,
5228 			   IN mlan_ioctl_req *pioctl_buf)
5229 {
5230 	HostCmd_DS_802_11_RF_ANTENNA *pantenna = &resp->params.antenna;
5231 	t_u16 ant_mode = wlan_le16_to_cpu(pantenna->antenna_mode);
5232 	t_u16 evaluate_time = wlan_le16_to_cpu(pantenna->evaluate_time);
5233 	t_u16 current_antenna = wlan_le16_to_cpu(pantenna->current_antenna);
5234 	mlan_ds_radio_cfg *radio = MNULL;
5235 
5236 	ENTER();
5237 
5238 	PRINTM(MINFO,
5239 	       "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x, Evaluate time = %d, Current antenna = %d\n",
5240 	       wlan_le16_to_cpu(pantenna->action), ant_mode, evaluate_time,
5241 	       current_antenna);
5242 
5243 	if (pioctl_buf) {
5244 		radio = (mlan_ds_radio_cfg *)pioctl_buf->pbuf;
5245 		radio->param.ant_cfg_1x1.antenna = ant_mode;
5246 		radio->param.ant_cfg_1x1.evaluate_time = evaluate_time;
5247 		radio->param.ant_cfg_1x1.current_antenna = current_antenna;
5248 	}
5249 
5250 	LEAVE();
5251 	return MLAN_STATUS_SUCCESS;
5252 }
5253 
5254 /**
5255  *  @brief This function prepares command of reg_access.
5256  *
5257  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
5258  *  @param cmd_action   the action: GET or SET
5259  *  @param pdata_buf    A pointer to data buffer
5260  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5261  */
5262 mlan_status
5263 wlan_cmd_reg_access(IN HostCmd_DS_COMMAND *cmd,
5264 		    IN t_u16 cmd_action, IN t_void *pdata_buf)
5265 {
5266 	mlan_ds_reg_rw *reg_rw;
5267 
5268 	ENTER();
5269 
5270 	reg_rw = (mlan_ds_reg_rw *)pdata_buf;
5271 	switch (cmd->command) {
5272 	case HostCmd_CMD_MAC_REG_ACCESS:
5273 		{
5274 			HostCmd_DS_MAC_REG_ACCESS *mac_reg;
5275 			cmd->size =
5276 				wlan_cpu_to_le16(sizeof
5277 						 (HostCmd_DS_MAC_REG_ACCESS) +
5278 						 S_DS_GEN);
5279 			mac_reg =
5280 				(HostCmd_DS_MAC_REG_ACCESS *)&cmd->params.
5281 				mac_reg;
5282 			mac_reg->action = wlan_cpu_to_le16(cmd_action);
5283 			mac_reg->offset =
5284 				wlan_cpu_to_le16((t_u16)reg_rw->offset);
5285 			mac_reg->value = wlan_cpu_to_le32(reg_rw->value);
5286 			break;
5287 		}
5288 	case HostCmd_CMD_BBP_REG_ACCESS:
5289 		{
5290 			HostCmd_DS_BBP_REG_ACCESS *bbp_reg;
5291 			cmd->size =
5292 				wlan_cpu_to_le16(sizeof
5293 						 (HostCmd_DS_BBP_REG_ACCESS) +
5294 						 S_DS_GEN);
5295 			bbp_reg =
5296 				(HostCmd_DS_BBP_REG_ACCESS *)&cmd->params.
5297 				bbp_reg;
5298 			bbp_reg->action = wlan_cpu_to_le16(cmd_action);
5299 			bbp_reg->offset =
5300 				wlan_cpu_to_le16((t_u16)reg_rw->offset);
5301 			bbp_reg->value = (t_u8)reg_rw->value;
5302 			break;
5303 		}
5304 	case HostCmd_CMD_RF_REG_ACCESS:
5305 		{
5306 			HostCmd_DS_RF_REG_ACCESS *rf_reg;
5307 			cmd->size =
5308 				wlan_cpu_to_le16(sizeof
5309 						 (HostCmd_DS_RF_REG_ACCESS) +
5310 						 S_DS_GEN);
5311 			rf_reg = (HostCmd_DS_RF_REG_ACCESS *)&cmd->params.
5312 				rf_reg;
5313 			rf_reg->action = wlan_cpu_to_le16(cmd_action);
5314 			rf_reg->offset =
5315 				wlan_cpu_to_le16((t_u16)reg_rw->offset);
5316 			rf_reg->value = (t_u8)reg_rw->value;
5317 			break;
5318 		}
5319 	case HostCmd_CMD_CAU_REG_ACCESS:
5320 		{
5321 			HostCmd_DS_RF_REG_ACCESS *cau_reg;
5322 			cmd->size =
5323 				wlan_cpu_to_le16(sizeof
5324 						 (HostCmd_DS_RF_REG_ACCESS) +
5325 						 S_DS_GEN);
5326 			cau_reg =
5327 				(HostCmd_DS_RF_REG_ACCESS *)&cmd->params.rf_reg;
5328 			cau_reg->action = wlan_cpu_to_le16(cmd_action);
5329 			cau_reg->offset =
5330 				wlan_cpu_to_le16((t_u16)reg_rw->offset);
5331 			cau_reg->value = (t_u8)reg_rw->value;
5332 			break;
5333 		}
5334 	case HostCmd_CMD_TARGET_ACCESS:
5335 		{
5336 			HostCmd_DS_TARGET_ACCESS *target;
5337 			cmd->size =
5338 				wlan_cpu_to_le16(sizeof
5339 						 (HostCmd_DS_TARGET_ACCESS) +
5340 						 S_DS_GEN);
5341 			target = (HostCmd_DS_TARGET_ACCESS *)&cmd->params.
5342 				target;
5343 			target->action = wlan_cpu_to_le16(cmd_action);
5344 			target->csu_target =
5345 				wlan_cpu_to_le16(MLAN_CSU_TARGET_PSU);
5346 			target->address =
5347 				wlan_cpu_to_le16((t_u16)reg_rw->offset);
5348 			target->data = (t_u8)reg_rw->value;
5349 			break;
5350 		}
5351 	case HostCmd_CMD_802_11_EEPROM_ACCESS:
5352 		{
5353 			mlan_ds_read_eeprom *rd_eeprom =
5354 				(mlan_ds_read_eeprom *)pdata_buf;
5355 			HostCmd_DS_802_11_EEPROM_ACCESS *cmd_eeprom =
5356 				(HostCmd_DS_802_11_EEPROM_ACCESS *)&cmd->params.
5357 				eeprom;
5358 			cmd->size =
5359 				wlan_cpu_to_le16(sizeof
5360 						 (HostCmd_DS_802_11_EEPROM_ACCESS)
5361 						 + S_DS_GEN);
5362 			cmd_eeprom->action = wlan_cpu_to_le16(cmd_action);
5363 			cmd_eeprom->offset =
5364 				wlan_cpu_to_le16(rd_eeprom->offset);
5365 			cmd_eeprom->byte_count =
5366 				wlan_cpu_to_le16(rd_eeprom->byte_count);
5367 			cmd_eeprom->value = 0;
5368 			break;
5369 		}
5370 	default:
5371 		LEAVE();
5372 		return MLAN_STATUS_FAILURE;
5373 	}
5374 	cmd->command = wlan_cpu_to_le16(cmd->command);
5375 
5376 	LEAVE();
5377 	return MLAN_STATUS_SUCCESS;
5378 }
5379 
5380 /**
5381  *  @brief This function handles the command response of reg_access
5382  *
5383  *  @param pmadapter    A pointer to mlan_adapter structure
5384  *  @param type         The type of reg access (MAC, BBP or RF)
5385  *  @param resp         A pointer to HostCmd_DS_COMMAND
5386  *  @param pioctl_buf   A pointer to command buffer
5387  *
5388  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5389  */
5390 mlan_status
5391 wlan_ret_reg_access(mlan_adapter *pmadapter,
5392 		    t_u16 type,
5393 		    IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
5394 {
5395 	mlan_ds_reg_mem *reg_mem = MNULL;
5396 	mlan_ds_reg_rw *reg_rw = MNULL;
5397 
5398 	ENTER();
5399 
5400 	if (pioctl_buf) {
5401 		reg_mem = (mlan_ds_reg_mem *)pioctl_buf->pbuf;
5402 		reg_rw = &reg_mem->param.reg_rw;
5403 		switch (type) {
5404 		case HostCmd_CMD_MAC_REG_ACCESS:
5405 			{
5406 				HostCmd_DS_MAC_REG_ACCESS *reg;
5407 				reg = (HostCmd_DS_MAC_REG_ACCESS *)&resp->
5408 					params.mac_reg;
5409 				reg_rw->offset =
5410 					(t_u32)wlan_le16_to_cpu(reg->offset);
5411 				reg_rw->value = wlan_le32_to_cpu(reg->value);
5412 				break;
5413 			}
5414 		case HostCmd_CMD_BBP_REG_ACCESS:
5415 			{
5416 				HostCmd_DS_BBP_REG_ACCESS *reg;
5417 				reg = (HostCmd_DS_BBP_REG_ACCESS *)&resp->
5418 					params.bbp_reg;
5419 				reg_rw->offset =
5420 					(t_u32)wlan_le16_to_cpu(reg->offset);
5421 				reg_rw->value = (t_u32)reg->value;
5422 				break;
5423 			}
5424 
5425 		case HostCmd_CMD_RF_REG_ACCESS:
5426 			{
5427 				HostCmd_DS_RF_REG_ACCESS *reg;
5428 				reg = (HostCmd_DS_RF_REG_ACCESS *)&resp->params.
5429 					rf_reg;
5430 				reg_rw->offset =
5431 					(t_u32)wlan_le16_to_cpu(reg->offset);
5432 				reg_rw->value = (t_u32)reg->value;
5433 				break;
5434 			}
5435 		case HostCmd_CMD_CAU_REG_ACCESS:
5436 			{
5437 				HostCmd_DS_RF_REG_ACCESS *reg;
5438 				reg = (HostCmd_DS_RF_REG_ACCESS *)&resp->params.
5439 					rf_reg;
5440 				reg_rw->offset =
5441 					(t_u32)wlan_le16_to_cpu(reg->offset);
5442 				reg_rw->value = (t_u32)reg->value;
5443 				break;
5444 			}
5445 		case HostCmd_CMD_TARGET_ACCESS:
5446 			{
5447 				HostCmd_DS_TARGET_ACCESS *reg;
5448 				reg = (HostCmd_DS_TARGET_ACCESS *)&resp->params.
5449 					target;
5450 				reg_rw->offset =
5451 					(t_u32)wlan_le16_to_cpu(reg->address);
5452 				reg_rw->value = (t_u32)reg->data;
5453 				break;
5454 			}
5455 		case HostCmd_CMD_802_11_EEPROM_ACCESS:
5456 			{
5457 				mlan_ds_read_eeprom *eeprom =
5458 					&reg_mem->param.rd_eeprom;
5459 				HostCmd_DS_802_11_EEPROM_ACCESS *cmd_eeprom =
5460 					(HostCmd_DS_802_11_EEPROM_ACCESS *)
5461 					&resp->params.eeprom;
5462 				cmd_eeprom->byte_count =
5463 					wlan_le16_to_cpu(cmd_eeprom->
5464 							 byte_count);
5465 				PRINTM(MINFO, "EEPROM read len=%x\n",
5466 				       cmd_eeprom->byte_count);
5467 				if (eeprom->byte_count < cmd_eeprom->byte_count) {
5468 					eeprom->byte_count = 0;
5469 					PRINTM(MINFO,
5470 					       "EEPROM read return length is too big\n");
5471 					pioctl_buf->status_code =
5472 						MLAN_ERROR_CMD_RESP_FAIL;
5473 					LEAVE();
5474 					return MLAN_STATUS_FAILURE;
5475 				}
5476 				eeprom->offset =
5477 					wlan_le16_to_cpu(cmd_eeprom->offset);
5478 				eeprom->byte_count = cmd_eeprom->byte_count;
5479 				if (eeprom->byte_count > 0) {
5480 					memcpy(pmadapter, &eeprom->value,
5481 					       &cmd_eeprom->value,
5482 					       MIN(MAX_EEPROM_DATA,
5483 						   eeprom->byte_count));
5484 					HEXDUMP("EEPROM",
5485 						(char *)&eeprom->value,
5486 						MIN(MAX_EEPROM_DATA,
5487 						    eeprom->byte_count));
5488 				}
5489 				break;
5490 			}
5491 		default:
5492 			pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL;
5493 			LEAVE();
5494 			return MLAN_STATUS_FAILURE;
5495 		}
5496 	}
5497 
5498 	LEAVE();
5499 	return MLAN_STATUS_SUCCESS;
5500 }
5501 
5502 /**
5503  *  @brief This function prepares command of mem_access.
5504  *
5505  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
5506  *  @param cmd_action   the action: GET or SET
5507  *  @param pdata_buf    A pointer to data buffer
5508  *  @return             MLAN_STATUS_SUCCESS
5509  */
5510 mlan_status
5511 wlan_cmd_mem_access(IN HostCmd_DS_COMMAND *cmd,
5512 		    IN t_u16 cmd_action, IN t_void *pdata_buf)
5513 {
5514 	mlan_ds_mem_rw *mem_rw = (mlan_ds_mem_rw *)pdata_buf;
5515 	HostCmd_DS_MEM_ACCESS *mem_access =
5516 		(HostCmd_DS_MEM_ACCESS *)&cmd->params.mem;
5517 
5518 	ENTER();
5519 
5520 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MEM_ACCESS);
5521 	cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_MEM_ACCESS) + S_DS_GEN);
5522 
5523 	mem_access->action = wlan_cpu_to_le16(cmd_action);
5524 	mem_access->addr = wlan_cpu_to_le32(mem_rw->addr);
5525 	mem_access->value = wlan_cpu_to_le32(mem_rw->value);
5526 
5527 	LEAVE();
5528 	return MLAN_STATUS_SUCCESS;
5529 }
5530 
5531 /**
5532  *  @brief This function handles the command response of mem_access
5533  *
5534  *  @param pmpriv       A pointer to mlan_private structure
5535  *  @param resp         A pointer to HostCmd_DS_COMMAND
5536  *  @param pioctl_buf   A pointer to command buffer
5537  *
5538  *  @return             MLAN_STATUS_SUCCESS
5539  */
5540 mlan_status
5541 wlan_ret_mem_access(IN pmlan_private pmpriv,
5542 		    IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
5543 {
5544 	mlan_ds_reg_mem *reg_mem = MNULL;
5545 	mlan_ds_mem_rw *mem_rw = MNULL;
5546 	HostCmd_DS_MEM_ACCESS *mem = (HostCmd_DS_MEM_ACCESS *)&resp->params.mem;
5547 
5548 	ENTER();
5549 
5550 	if (pioctl_buf) {
5551 		reg_mem = (mlan_ds_reg_mem *)pioctl_buf->pbuf;
5552 		mem_rw = &reg_mem->param.mem_rw;
5553 
5554 		mem_rw->addr = wlan_le32_to_cpu(mem->addr);
5555 		mem_rw->value = wlan_le32_to_cpu(mem->value);
5556 	}
5557 
5558 	LEAVE();
5559 	return MLAN_STATUS_SUCCESS;
5560 }
5561 
5562 /**
5563 *
5564 *  @brief This function handles coex events generated by firmware
5565 *
5566 *  @param priv A pointer to mlan_private structure
5567 *  @param pevent   A pointer to event buf
5568 *
5569 *  @return     N/A
5570 */
5571 void
5572 wlan_bt_coex_wlan_param_update_event(pmlan_private priv, pmlan_buffer pevent)
5573 {
5574 	pmlan_adapter pmadapter = priv->adapter;
5575 	MrvlIEtypesHeader_t *tlv = MNULL;
5576 	MrvlIETypes_BtCoexAggrWinSize_t *pCoexWinsize = MNULL;
5577 	MrvlIEtypes_BtCoexScanTime_t *pScantlv = MNULL;
5578 	t_s32 len = pevent->data_len - sizeof(t_u32);
5579 	t_u8 *pCurrent_ptr = pevent->pbuf + pevent->data_offset + sizeof(t_u32);
5580 	t_u16 tlv_type, tlv_len;
5581 
5582 	ENTER();
5583 
5584 	while (len >= sizeof(MrvlIEtypesHeader_t)) {
5585 		tlv = (MrvlIEtypesHeader_t *)pCurrent_ptr;
5586 		tlv_len = wlan_le16_to_cpu(tlv->len);
5587 		tlv_type = wlan_le16_to_cpu(tlv->type);
5588 		if ((tlv_len + sizeof(MrvlIEtypesHeader_t)) > len)
5589 			break;
5590 		switch (tlv_type) {
5591 		case TLV_BTCOEX_WL_AGGR_WINSIZE:
5592 			pCoexWinsize = (MrvlIETypes_BtCoexAggrWinSize_t *) tlv;
5593 			pmadapter->coex_win_size = pCoexWinsize->coex_win_size;
5594 			pmadapter->coex_tx_win_size = pCoexWinsize->tx_win_size;
5595 			pmadapter->coex_rx_win_size = pCoexWinsize->rx_win_size;
5596 			wlan_coex_ampdu_rxwinsize(pmadapter);
5597 			wlan_update_ampdu_txwinsize(pmadapter);
5598 			break;
5599 		case TLV_BTCOEX_WL_SCANTIME:
5600 			pScantlv = (MrvlIEtypes_BtCoexScanTime_t *) tlv;
5601 			pmadapter->coex_scan = pScantlv->coex_scan;
5602 			pmadapter->coex_min_scan_time =
5603 				wlan_le16_to_cpu(pScantlv->min_scan_time);
5604 			pmadapter->coex_max_scan_time =
5605 				wlan_le16_to_cpu(pScantlv->max_scan_time);
5606 			break;
5607 		default:
5608 			break;
5609 		}
5610 		len -= tlv_len + sizeof(MrvlIEtypesHeader_t);
5611 		pCurrent_ptr += tlv_len + sizeof(MrvlIEtypesHeader_t);
5612 	}
5613 	PRINTM(MEVENT,
5614 	       "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n",
5615 	       pmadapter->coex_scan, pmadapter->coex_min_scan_time,
5616 	       pmadapter->coex_win_size, pmadapter->coex_tx_win_size,
5617 	       pmadapter->coex_rx_win_size);
5618 
5619 	LEAVE();
5620 }
5621 
5622 /**
5623  *  @brief This function prepares command of supplicant pmk
5624  *
5625  *  @param pmpriv       A pointer to mlan_private structure
5626  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
5627  *  @param cmd_action   The action: GET or SET
5628  *  @param pdata_buf    A pointer to data buffer
5629  *
5630  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5631  */
5632 mlan_status
5633 wlan_cmd_802_11_supplicant_pmk(IN pmlan_private pmpriv,
5634 			       IN HostCmd_DS_COMMAND *cmd,
5635 			       IN t_u16 cmd_action, IN t_void *pdata_buf)
5636 {
5637 	MrvlIEtypes_PMK_t *ppmk_tlv = MNULL;
5638 	MrvlIEtypes_Passphrase_t *ppassphrase_tlv = MNULL;
5639 	MrvlIEtypes_SsIdParamSet_t *pssid_tlv = MNULL;
5640 	MrvlIEtypes_Bssid_t *pbssid_tlv = MNULL;
5641 	HostCmd_DS_802_11_SUPPLICANT_PMK *pesupplicant_psk =
5642 		&cmd->params.esupplicant_psk;
5643 	t_u8 *ptlv_buffer = (t_u8 *)pesupplicant_psk->tlv_buffer;
5644 	mlan_ds_sec_cfg *sec = (mlan_ds_sec_cfg *)pdata_buf;
5645 	mlan_ds_passphrase *psk = MNULL;
5646 	t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
5647 	t_u8 ssid_flag = 0, bssid_flag = 0, pmk_flag = 0, passphrase_flag = 0;
5648 	t_u8 zero[MLAN_MAX_KEY_LENGTH] = { 0 };
5649 	MrvlIEtypes_fw_roam_enable_t *proam_tlv = MNULL;
5650 	MrvlIEtypes_keyParams_t *key_tlv = MNULL;
5651 	int length = 0;
5652 	t_u8 userset_passphrase = 0;
5653 
5654 	ENTER();
5655 	if (sec->multi_passphrase)
5656 		psk = (mlan_ds_passphrase *)&sec->param.
5657 			roam_passphrase[userset_passphrase];
5658 	else
5659 		psk = (mlan_ds_passphrase *)&sec->param.passphrase;
5660 	if (cmd_action == HostCmd_ACT_GEN_REMOVE) {
5661 		cmd->size =
5662 			sizeof(HostCmd_DS_802_11_SUPPLICANT_PMK) + S_DS_GEN - 1;
5663 		proam_tlv = (MrvlIEtypes_fw_roam_enable_t *) ptlv_buffer;
5664 		proam_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_ROAM);
5665 		proam_tlv->header.len =
5666 			sizeof(MrvlIEtypes_fw_roam_enable_t) -
5667 			sizeof(MrvlIEtypesHeader_t);
5668 		proam_tlv->roam_enable = MTRUE;
5669 		ptlv_buffer +=
5670 			(proam_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
5671 		cmd->size +=
5672 			(proam_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
5673 		proam_tlv->header.len = wlan_cpu_to_le16(proam_tlv->header.len);
5674 
5675 		cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SUPPLICANT_PMK);
5676 		pesupplicant_psk->action = wlan_cpu_to_le16(cmd_action);
5677 		pesupplicant_psk->cache_result = 0;
5678 		cmd->size = wlan_cpu_to_le16(cmd->size);
5679 		LEAVE();
5680 		return MLAN_STATUS_SUCCESS;
5681 	}
5682 
5683 	/*
5684 	 * Parse the rest of the buf here
5685 	 *  1) <ssid="valid ssid"> - This will get the passphrase, AKMP
5686 	 *     for specified ssid, if none specified then it will get all.
5687 	 *     Eg: iwpriv <mlanX> passphrase 0:ssid=marvell
5688 	 *  2) <psk="psk">:<passphrase="passphare">:<bssid="00:50:43:ef:23:f3">
5689 	 *     <ssid="valid ssid"> - passphrase and psk cannot be provided to
5690 	 *     the same SSID, Takes one SSID at a time, If ssid= is present
5691 	 *     the it should contain a passphrase or psk. If no arguments are
5692 	 *     provided then AKMP=802.1x, and passphrase should be provided
5693 	 *     after association.
5694 	 *     End of each parameter should be followed by a ':'(except for the
5695 	 *     last parameter) as the delimiter. If ':' has to be used in
5696 	 *     an SSID then a '/' should be preceded to ':' as a escape.
5697 	 *     Eg:iwpriv <mlanX> passphrase
5698 	 *               "1:ssid=mrvl AP:psk=abcdefgh:bssid=00:50:43:ef:23:f3"
5699 	 *     iwpriv <mlanX> passphrase
5700 	 *            "1:ssid=mrvl/: AP:psk=abcdefgd:bssid=00:50:43:ef:23:f3"
5701 	 *     iwpriv <mlanX> passphrase "1:ssid=mrvlAP:psk=abcdefgd"
5702 	 *  3) <ssid="valid ssid"> - This will clear the passphrase
5703 	 *     for specified ssid, if none specified then it will clear all.
5704 	 *     Eg: iwpriv <mlanX> passphrase 2:ssid=marvell
5705 	 */
5706 
5707 	/* -1 is for t_u8 TlvBuffer[1] as this should not be included */
5708 	cmd->size = sizeof(HostCmd_DS_802_11_SUPPLICANT_PMK) + S_DS_GEN - 1;
5709 	if (psk &&
5710 	    memcmp(pmpriv->adapter, (t_u8 *)&psk->bssid, zero_mac,
5711 		   sizeof(zero_mac))) {
5712 		pbssid_tlv = (MrvlIEtypes_Bssid_t *)ptlv_buffer;
5713 		pbssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_BSSID);
5714 		pbssid_tlv->header.len = MLAN_MAC_ADDR_LENGTH;
5715 		memcpy(pmpriv->adapter, pbssid_tlv->bssid, (t_u8 *)&psk->bssid,
5716 		       MLAN_MAC_ADDR_LENGTH);
5717 		ptlv_buffer +=
5718 			(pbssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
5719 		cmd->size +=
5720 			(pbssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
5721 		pbssid_tlv->header.len =
5722 			wlan_cpu_to_le16(pbssid_tlv->header.len);
5723 		bssid_flag = 1;
5724 	}
5725 	if (psk && (psk->psk_type == MLAN_PSK_PMK)) {
5726 		ppmk_tlv = (MrvlIEtypes_PMK_t *)ptlv_buffer;
5727 		ppmk_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_PMK);
5728 		ppmk_tlv->header.len = MLAN_MAX_KEY_LENGTH;
5729 		memcpy(pmpriv->adapter, ppmk_tlv->pmk, psk->psk.pmk.pmk,
5730 		       MLAN_MAX_KEY_LENGTH);
5731 		ptlv_buffer +=
5732 			(ppmk_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
5733 		cmd->size +=
5734 			(ppmk_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
5735 		ppmk_tlv->header.len = wlan_cpu_to_le16(ppmk_tlv->header.len);
5736 		pmk_flag = 1;
5737 		if (memcmp
5738 		    (pmpriv->adapter, psk->psk.pmk.pmk_r0, zero,
5739 		     MLAN_MAX_KEY_LENGTH)) {
5740 			ppmk_tlv = (MrvlIEtypes_PMK_t *)ptlv_buffer;
5741 			ppmk_tlv->header.type =
5742 				wlan_cpu_to_le16(TLV_TYPE_PMK_R0);
5743 			ppmk_tlv->header.len = MLAN_MAX_KEY_LENGTH;
5744 			memcpy(pmpriv->adapter, ppmk_tlv->pmk,
5745 			       psk->psk.pmk.pmk_r0, MLAN_MAX_KEY_LENGTH);
5746 			ptlv_buffer +=
5747 				(ppmk_tlv->header.len +
5748 				 sizeof(MrvlIEtypesHeader_t));
5749 			cmd->size +=
5750 				(ppmk_tlv->header.len +
5751 				 sizeof(MrvlIEtypesHeader_t));
5752 			ppmk_tlv->header.len =
5753 				wlan_cpu_to_le16(ppmk_tlv->header.len);
5754 		}
5755 		if (memcmp
5756 		    (pmpriv->adapter, psk->psk.pmk.pmk_r0_name, zero,
5757 		     MLAN_MAX_PMKR0_NAME_LENGTH)) {
5758 			ppmk_tlv = (MrvlIEtypes_PMK_t *)ptlv_buffer;
5759 			ppmk_tlv->header.type =
5760 				wlan_cpu_to_le16(TLV_TYPE_PMK_R0_NAME);
5761 			ppmk_tlv->header.len = MLAN_MAX_PMKR0_NAME_LENGTH;
5762 			memcpy(pmpriv->adapter, ppmk_tlv->pmk,
5763 			       psk->psk.pmk.pmk_r0_name,
5764 			       MLAN_MAX_PMKR0_NAME_LENGTH);
5765 			ptlv_buffer +=
5766 				(ppmk_tlv->header.len +
5767 				 sizeof(MrvlIEtypesHeader_t));
5768 			cmd->size +=
5769 				(ppmk_tlv->header.len +
5770 				 sizeof(MrvlIEtypesHeader_t));
5771 			ppmk_tlv->header.len =
5772 				wlan_cpu_to_le16(ppmk_tlv->header.len);
5773 		}
5774 	}
5775 	if (pmpriv->adapter->fw_roaming &&
5776 	    (pmpriv->adapter->userset_passphrase ||
5777 	     psk->psk_type == MLAN_PSK_PMK)) {
5778 		proam_tlv = (MrvlIEtypes_fw_roam_enable_t *) ptlv_buffer;
5779 		proam_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_ROAM);
5780 		proam_tlv->header.len =
5781 			sizeof(MrvlIEtypes_fw_roam_enable_t) -
5782 			sizeof(MrvlIEtypesHeader_t);
5783 		proam_tlv->roam_enable = MTRUE;
5784 		proam_tlv->userset_passphrase =
5785 			pmpriv->adapter->userset_passphrase;
5786 		ptlv_buffer +=
5787 			(proam_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
5788 		cmd->size +=
5789 			(proam_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
5790 		proam_tlv->header.len = wlan_cpu_to_le16(proam_tlv->header.len);
5791 	}
5792 	do {
5793 		if (pmpriv->adapter->userset_passphrase &&
5794 		    sec->multi_passphrase) {
5795 			key_tlv = (MrvlIEtypes_keyParams_t *) ptlv_buffer;
5796 			key_tlv->header.type =
5797 				wlan_cpu_to_le16
5798 				(TLV_TYPE_ROAM_OFFLOAD_USER_SET_PMK);
5799 			ptlv_buffer += sizeof(MrvlIEtypesHeader_t);
5800 			cmd->size += sizeof(MrvlIEtypesHeader_t);
5801 			length = cmd->size;
5802 		}
5803 		if (psk->ssid.ssid_len) {
5804 			pssid_tlv = (MrvlIEtypes_SsIdParamSet_t *)ptlv_buffer;
5805 			pssid_tlv->header.type =
5806 				wlan_cpu_to_le16(TLV_TYPE_SSID);
5807 			pssid_tlv->header.len =
5808 				(t_u16)MIN(MLAN_MAX_SSID_LENGTH,
5809 					   psk->ssid.ssid_len);
5810 			memcpy(pmpriv->adapter, (t_u8 *)pssid_tlv->ssid,
5811 			       (t_u8 *)psk->ssid.ssid, MIN(MLAN_MAX_SSID_LENGTH,
5812 							   psk->ssid.ssid_len));
5813 			ptlv_buffer +=
5814 				(pssid_tlv->header.len +
5815 				 sizeof(MrvlIEtypesHeader_t));
5816 			cmd->size +=
5817 				(pssid_tlv->header.len +
5818 				 sizeof(MrvlIEtypesHeader_t));
5819 			pssid_tlv->header.len =
5820 				wlan_cpu_to_le16(pssid_tlv->header.len);
5821 			ssid_flag = 1;
5822 		}
5823 		if (psk->psk_type == MLAN_PSK_PASSPHRASE) {
5824 			ppassphrase_tlv =
5825 				(MrvlIEtypes_Passphrase_t *)ptlv_buffer;
5826 			ppassphrase_tlv->header.type =
5827 				wlan_cpu_to_le16(TLV_TYPE_PASSPHRASE);
5828 			ppassphrase_tlv->header.len =
5829 				(t_u16)MIN(MLAN_MAX_PASSPHRASE_LENGTH,
5830 					   psk->psk.passphrase.passphrase_len);
5831 			memcpy(pmpriv->adapter, ppassphrase_tlv->passphrase,
5832 			       psk->psk.passphrase.passphrase,
5833 			       MIN(MLAN_MAX_PASSPHRASE_LENGTH,
5834 				   psk->psk.passphrase.passphrase_len));
5835 			ptlv_buffer +=
5836 				(ppassphrase_tlv->header.len +
5837 				 sizeof(MrvlIEtypesHeader_t));
5838 			cmd->size +=
5839 				(ppassphrase_tlv->header.len +
5840 				 sizeof(MrvlIEtypesHeader_t));
5841 			ppassphrase_tlv->header.len =
5842 				wlan_cpu_to_le16(ppassphrase_tlv->header.len);
5843 			passphrase_flag = 1;
5844 		}
5845 		if (key_tlv)
5846 			key_tlv->header.len =
5847 				wlan_cpu_to_le16(cmd->size - length);
5848 		userset_passphrase++;
5849 		psk = (mlan_ds_passphrase *)&sec->param.
5850 			roam_passphrase[userset_passphrase];
5851 	} while (psk && sec->multi_passphrase &&
5852 		 userset_passphrase < pmpriv->adapter->userset_passphrase);
5853 	pmpriv->adapter->userset_passphrase = 0;
5854 	if ((cmd_action == HostCmd_ACT_GEN_SET) &&
5855 	    ((ssid_flag || bssid_flag) && (!pmk_flag && !passphrase_flag))) {
5856 		PRINTM(MERROR,
5857 		       "Invalid case,ssid/bssid present without pmk or passphrase\n");
5858 		LEAVE();
5859 		return MLAN_STATUS_FAILURE;
5860 	}
5861 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SUPPLICANT_PMK);
5862 	pesupplicant_psk->action = wlan_cpu_to_le16(cmd_action);
5863 	pesupplicant_psk->cache_result = 0;
5864 	cmd->size = wlan_cpu_to_le16(cmd->size);
5865 	LEAVE();
5866 	return MLAN_STATUS_SUCCESS;
5867 }
5868 
5869 /**
5870  *  @brief Handle the supplicant pmk response
5871  *
5872  *  @param pmpriv       A pointer to mlan_private structure
5873  *  @param resp         A pointer to HostCmd_DS_COMMAND
5874  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
5875  *
5876  *  @return        MLAN_STATUS_SUCCESS MLAN_STATUS_FAILURE
5877  */
5878 mlan_status
5879 wlan_ret_802_11_supplicant_pmk(IN pmlan_private pmpriv,
5880 			       IN HostCmd_DS_COMMAND *resp,
5881 			       IN mlan_ioctl_req *pioctl_buf)
5882 {
5883 	HostCmd_DS_802_11_SUPPLICANT_PMK *supplicant_pmk_resp =
5884 		&resp->params.esupplicant_psk;
5885 	mlan_ds_sec_cfg sec_buf;
5886 	mlan_ds_sec_cfg *sec = MNULL;
5887 	MrvlIEtypes_PMK_t *ppmk_tlv = MNULL;
5888 	MrvlIEtypes_Passphrase_t *passphrase_tlv = MNULL;
5889 	MrvlIEtypes_SsIdParamSet_t *pssid_tlv = MNULL;
5890 	MrvlIEtypes_Bssid_t *pbssid_tlv = MNULL;
5891 	t_u8 *tlv_buf = (t_u8 *)supplicant_pmk_resp->tlv_buffer;
5892 	t_u16 action = wlan_le16_to_cpu(supplicant_pmk_resp->action);
5893 	int tlv_buf_len = 0;
5894 	t_u16 tlv;
5895 	mlan_status ret = MLAN_STATUS_SUCCESS;
5896 
5897 	ENTER();
5898 	tlv_buf_len = resp->size - (sizeof(HostCmd_DS_802_11_SUPPLICANT_PMK) +
5899 				    S_DS_GEN - 1);
5900 	if (pioctl_buf) {
5901 		if (((mlan_ds_bss *)pioctl_buf->pbuf)->sub_command ==
5902 		    MLAN_OID_BSS_FIND_BSS)
5903 			sec = &sec_buf;
5904 		else
5905 			sec = (mlan_ds_sec_cfg *)pioctl_buf->pbuf;
5906 		if (action == HostCmd_ACT_GEN_GET) {
5907 			while (tlv_buf_len > 0) {
5908 				tlv = (*tlv_buf) | (*(tlv_buf + 1) << 8);
5909 				if ((tlv != TLV_TYPE_SSID) &&
5910 				    (tlv != TLV_TYPE_BSSID) &&
5911 				    (tlv != TLV_TYPE_PASSPHRASE)
5912 				    && (tlv != TLV_TYPE_PMK))
5913 					break;
5914 				switch (tlv) {
5915 				case TLV_TYPE_SSID:
5916 					pssid_tlv =
5917 						(MrvlIEtypes_SsIdParamSet_t *)
5918 						tlv_buf;
5919 					pssid_tlv->header.len =
5920 						wlan_le16_to_cpu(pssid_tlv->
5921 								 header.len);
5922 					memcpy(pmpriv->adapter,
5923 					       sec->param.passphrase.ssid.ssid,
5924 					       pssid_tlv->ssid,
5925 					       MIN(MLAN_MAX_SSID_LENGTH,
5926 						   pssid_tlv->header.len));
5927 					sec->param.passphrase.ssid.ssid_len =
5928 						MIN(MLAN_MAX_SSID_LENGTH,
5929 						    pssid_tlv->header.len);
5930 					tlv_buf +=
5931 						pssid_tlv->header.len +
5932 						sizeof(MrvlIEtypesHeader_t);
5933 					tlv_buf_len -=
5934 						(pssid_tlv->header.len +
5935 						 sizeof(MrvlIEtypesHeader_t));
5936 					break;
5937 				case TLV_TYPE_BSSID:
5938 					pbssid_tlv =
5939 						(MrvlIEtypes_Bssid_t *)tlv_buf;
5940 					pbssid_tlv->header.len =
5941 						wlan_le16_to_cpu(pbssid_tlv->
5942 								 header.len);
5943 					memcpy(pmpriv->adapter,
5944 					       &sec->param.passphrase.bssid,
5945 					       pbssid_tlv->bssid,
5946 					       MLAN_MAC_ADDR_LENGTH);
5947 					tlv_buf +=
5948 						pbssid_tlv->header.len +
5949 						sizeof(MrvlIEtypesHeader_t);
5950 					tlv_buf_len -=
5951 						(pbssid_tlv->header.len +
5952 						 sizeof(MrvlIEtypesHeader_t));
5953 					break;
5954 				case TLV_TYPE_PASSPHRASE:
5955 					passphrase_tlv =
5956 						(MrvlIEtypes_Passphrase_t *)
5957 						tlv_buf;
5958 					passphrase_tlv->header.len =
5959 						wlan_le16_to_cpu
5960 						(passphrase_tlv->header.len);
5961 					sec->param.passphrase.psk_type =
5962 						MLAN_PSK_PASSPHRASE;
5963 					sec->param.passphrase.psk.passphrase.
5964 						passphrase_len =
5965 						passphrase_tlv->header.len;
5966 					memcpy(pmpriv->adapter,
5967 					       sec->param.passphrase.psk.
5968 					       passphrase.passphrase,
5969 					       passphrase_tlv->passphrase,
5970 					       MIN(MLAN_MAX_PASSPHRASE_LENGTH,
5971 						   passphrase_tlv->header.len));
5972 					tlv_buf +=
5973 						passphrase_tlv->header.len +
5974 						sizeof(MrvlIEtypesHeader_t);
5975 					tlv_buf_len -=
5976 						(passphrase_tlv->header.len +
5977 						 sizeof(MrvlIEtypesHeader_t));
5978 					break;
5979 				case TLV_TYPE_PMK:
5980 					ppmk_tlv = (MrvlIEtypes_PMK_t *)tlv_buf;
5981 					ppmk_tlv->header.len =
5982 						wlan_le16_to_cpu(ppmk_tlv->
5983 								 header.len);
5984 					sec->param.passphrase.psk_type =
5985 						MLAN_PSK_PMK;
5986 					memcpy(pmpriv->adapter,
5987 					       sec->param.passphrase.psk.pmk.
5988 					       pmk, ppmk_tlv->pmk,
5989 					       MIN(MLAN_MAX_KEY_LENGTH,
5990 						   ppmk_tlv->header.len));
5991 					tlv_buf +=
5992 						ppmk_tlv->header.len +
5993 						sizeof(MrvlIEtypesHeader_t);
5994 					tlv_buf_len -=
5995 						(ppmk_tlv->header.len +
5996 						 sizeof(MrvlIEtypesHeader_t));
5997 					break;
5998 
5999 				}
6000 			}
6001 #ifdef STA_SUPPORT
6002 			if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA &&
6003 			    ((mlan_ds_bss *)pioctl_buf->pbuf)->sub_command ==
6004 			    MLAN_OID_BSS_FIND_BSS) {
6005 				wlan_set_ewpa_mode(pmpriv,
6006 						   &sec->param.passphrase);
6007 				ret = wlan_find_bss(pmpriv, pioctl_buf);
6008 			}
6009 #endif
6010 		} else if (action == HostCmd_ACT_GEN_SET) {
6011 			PRINTM(MINFO, "Esupp PMK set: enable ewpa query\n");
6012 			pmpriv->ewpa_query = MTRUE;
6013 		}
6014 	}
6015 
6016 	LEAVE();
6017 	return ret;
6018 }
6019 
6020 /**
6021  *  @brief This function prepares command of independent reset.
6022  *
6023  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
6024  *  @param cmd_action   the action: GET or SET
6025  *  @param pdata_buf    A pointer to data buffer
6026  *  @return             MLAN_STATUS_SUCCESS
6027  */
6028 mlan_status
6029 wlan_cmd_ind_rst_cfg(IN HostCmd_DS_COMMAND *cmd,
6030 		     IN t_u16 cmd_action, IN t_void *pdata_buf)
6031 {
6032 	mlan_ds_ind_rst_cfg *pdata_ind_rst = (mlan_ds_ind_rst_cfg *) pdata_buf;
6033 	HostCmd_DS_INDEPENDENT_RESET_CFG *ind_rst_cfg =
6034 		(HostCmd_DS_INDEPENDENT_RESET_CFG *) & cmd->params.ind_rst_cfg;
6035 
6036 	ENTER();
6037 
6038 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_INDEPENDENT_RESET_CFG);
6039 	cmd->size =
6040 		wlan_cpu_to_le16(sizeof(HostCmd_DS_INDEPENDENT_RESET_CFG) +
6041 				 S_DS_GEN);
6042 
6043 	ind_rst_cfg->action = wlan_cpu_to_le16(cmd_action);
6044 	if (cmd_action == HostCmd_ACT_GEN_SET) {
6045 		ind_rst_cfg->ir_mode = pdata_ind_rst->ir_mode;
6046 		ind_rst_cfg->gpio_pin = pdata_ind_rst->gpio_pin;
6047 	}
6048 
6049 	LEAVE();
6050 	return MLAN_STATUS_SUCCESS;
6051 }
6052 
6053 /**
6054  *  @brief This function handles the command response of independent reset
6055  *
6056  *  @param pmpriv       A pointer to mlan_private structure
6057  *  @param resp         A pointer to HostCmd_DS_COMMAND
6058  *  @param pioctl_buf   A pointer to command buffer
6059  *
6060  *  @return             MLAN_STATUS_SUCCESS
6061  */
6062 mlan_status
6063 wlan_ret_ind_rst_cfg(IN pmlan_private pmpriv,
6064 		     IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
6065 {
6066 	mlan_ds_misc_cfg *misc = MNULL;
6067 	const HostCmd_DS_INDEPENDENT_RESET_CFG *ind_rst_cfg =
6068 		(HostCmd_DS_INDEPENDENT_RESET_CFG *) & resp->params.ind_rst_cfg;
6069 
6070 	ENTER();
6071 
6072 	if (pioctl_buf) {
6073 		misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
6074 
6075 		if (wlan_le16_to_cpu(ind_rst_cfg->action) ==
6076 		    HostCmd_ACT_GEN_GET) {
6077 			misc->param.ind_rst_cfg.ir_mode = ind_rst_cfg->ir_mode;
6078 			misc->param.ind_rst_cfg.gpio_pin =
6079 				ind_rst_cfg->gpio_pin;
6080 		}
6081 	}
6082 
6083 	LEAVE();
6084 	return MLAN_STATUS_SUCCESS;
6085 }
6086 
6087 /**
6088  *  @brief This function prepares command of ps inactivity timeout.
6089  *
6090  *  @param pmpriv      A pointer to mlan_private structure
6091  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
6092  *  @param cmd_action   the action: GET or SET
6093  *  @param pdata_buf    A pointer to data buffer
6094  *  @return             MLAN_STATUS_SUCCESS
6095  */
6096 mlan_status
6097 wlan_cmd_ps_inactivity_timeout(IN pmlan_private pmpriv,
6098 			       IN HostCmd_DS_COMMAND *cmd,
6099 			       IN t_u16 cmd_action, IN t_void *pdata_buf)
6100 {
6101 	t_u16 timeout = *((t_u16 *)pdata_buf);
6102 	HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT *ps_inact_tmo =
6103 		(HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT *) & cmd->params.
6104 		ps_inact_tmo;
6105 
6106 	ENTER();
6107 
6108 	cmd->command =
6109 		wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT);
6110 	cmd->size =
6111 		wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_PS_INACTIVITY_TIMEOUT)
6112 				 + S_DS_GEN);
6113 
6114 	ps_inact_tmo->action = wlan_cpu_to_le16(cmd_action);
6115 	if (cmd_action == HostCmd_ACT_GEN_SET)
6116 		ps_inact_tmo->inact_tmo = wlan_cpu_to_le16(timeout);
6117 
6118 	LEAVE();
6119 	return MLAN_STATUS_SUCCESS;
6120 }
6121 
6122 /**
6123  *  @brief This function prepares command of HostCmd_CMD_GET_TSF
6124  *
6125  *  @param pmpriv       A pointer to mlan_private structure
6126  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
6127  *  @param cmd_action   The action: GET
6128  *  @return             MLAN_STATUS_SUCCESS
6129  */
6130 mlan_status
6131 wlan_cmd_get_tsf(pmlan_private pmpriv,
6132 		 IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action)
6133 {
6134 	ENTER();
6135 
6136 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_GET_TSF);
6137 	cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_TSF)) + S_DS_GEN);
6138 
6139 	LEAVE();
6140 	return MLAN_STATUS_SUCCESS;
6141 }
6142 
6143 /**
6144  *  @brief This function handles the command response of HostCmd_CMD_GET_TSF
6145  *
6146  *  @param pmpriv       A pointer to mlan_private structure
6147  *  @param resp         A pointer to HostCmd_DS_COMMAND
6148  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
6149  *
6150  *  @return             MLAN_STATUS_SUCCESS
6151  */
6152 mlan_status
6153 wlan_ret_get_tsf(IN pmlan_private pmpriv,
6154 		 IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
6155 {
6156 	mlan_ds_misc_cfg *misc_cfg = MNULL;
6157 	HostCmd_DS_TSF *tsf_pointer = (HostCmd_DS_TSF *) & resp->params.tsf;
6158 
6159 	ENTER();
6160 	if (pioctl_buf) {
6161 		misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
6162 		misc_cfg->param.misc_tsf = wlan_le64_to_cpu(tsf_pointer->tsf);
6163 	}
6164 
6165 	LEAVE();
6166 	return MLAN_STATUS_SUCCESS;
6167 }
6168 
6169 /**
6170  *  @brief This function prepares command of sending host_clock_cfg.
6171  *
6172  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
6173  *  @param cmd_action   the action: GET or SET
6174  *  @param pdata_buf    A pointer to data buffer
6175  *  @return             MLAN_STATUS_SUCCESS
6176  */
6177 mlan_status
6178 wlan_cmd_host_clock_cfg(IN HostCmd_DS_COMMAND *cmd,
6179 			IN t_u16 cmd_action, IN t_void *pdata_buf)
6180 {
6181 	mlan_ds_host_clock *hostclk = (mlan_ds_host_clock *) pdata_buf;
6182 	HostCmd_DS_HOST_CLOCK_CFG *host_clock =
6183 		(HostCmd_DS_HOST_CLOCK_CFG *) & cmd->params.host_clock_cfg;
6184 
6185 	ENTER();
6186 
6187 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_HOST_CLOCK_CFG);
6188 	cmd->size =
6189 		wlan_cpu_to_le16(sizeof(HostCmd_DS_HOST_CLOCK_CFG) + S_DS_GEN);
6190 
6191 	host_clock->action = wlan_cpu_to_le16(cmd_action);
6192 	host_clock->time = wlan_cpu_to_le64(hostclk->time);
6193 
6194 	LEAVE();
6195 	return MLAN_STATUS_SUCCESS;
6196 }
6197 
6198 /**
6199  *  @brief This function handles the command response of host_clock_cfg
6200  *
6201  *  @param pmpriv       A pointer to mlan_private structure
6202  *  @param resp         A pointer to HostCmd_DS_COMMAND
6203  *  @param pioctl_buf   A pointer to command buffer
6204  *
6205  *  @return             MLAN_STATUS_SUCCESS
6206  */
6207 mlan_status
6208 wlan_ret_host_clock_cfg(IN pmlan_private pmpriv,
6209 			IN HostCmd_DS_COMMAND *resp,
6210 			IN mlan_ioctl_req *pioctl_buf)
6211 {
6212 	mlan_ds_misc_cfg *cfg = MNULL;
6213 	mlan_ds_host_clock *hostclk = MNULL;
6214 	HostCmd_DS_HOST_CLOCK_CFG *host_clock =
6215 		(HostCmd_DS_HOST_CLOCK_CFG *) & resp->params.host_clock_cfg;
6216 	mlan_adapter *pmadapter = pmpriv->adapter;
6217 	t_u64 cmd_rtt;
6218 
6219 	ENTER();
6220 
6221 	if (pioctl_buf) {
6222 		cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
6223 		hostclk = &cfg->param.host_clock;
6224 
6225 		hostclk->time = wlan_le64_to_cpu(host_clock->time);
6226 		hostclk->fw_time = wlan_le64_to_cpu(host_clock->time);
6227 		cmd_rtt = (pmadapter->d2 - pmadapter->d1) / 2;
6228 		pmadapter->host_bbu_clk_delta =
6229 			wlan_le64_to_cpu(host_clock->host_bbu_clk_delta);
6230 		PRINTM(MINFO, "HW time: %ld, Host Time: %ld, RTT: %ld\n",
6231 		       host_clock->hw_time, hostclk->time, cmd_rtt);
6232 		hostclk->fw_time = wlan_le64_to_cpu(host_clock->hw_time) /*- cmd_rtt*/ ;	// Not adjusting cmd_rtt gave better results with 802.1as
6233 		hostclk->host_bbu_clk_delta = pmadapter->host_bbu_clk_delta;
6234 
6235 		/* Indicate ioctl complete */
6236 		pioctl_buf->data_read_written =
6237 			sizeof(mlan_ds_misc_cfg) + MLAN_SUB_COMMAND_SIZE;
6238 	}
6239 
6240 	LEAVE();
6241 	return MLAN_STATUS_SUCCESS;
6242 }
6243 
6244 /**
6245  *  @brief This function handles the command response of chan_region_cfg
6246  *
6247  *  @param pmpriv       A pointer to mlan_private structure
6248  *  @param resp         A pointer to HostCmd_DS_COMMAND
6249  *  @param pioctl_buf   A pointer to command buffer
6250  *
6251  *  @return             MLAN_STATUS_SUCCESS
6252  */
6253 mlan_status
6254 wlan_ret_chan_region_cfg(IN pmlan_private pmpriv,
6255 			 IN HostCmd_DS_COMMAND *resp,
6256 			 IN mlan_ioctl_req *pioctl_buf)
6257 {
6258 	t_u16 action;
6259 	t_u16 tlv, tlv_buf_len, tlv_buf_left;
6260 	MrvlIEtypesHeader_t *head;
6261 	HostCmd_DS_CHAN_REGION_CFG *reg = MNULL;
6262 	t_u8 *tlv_buf = MNULL;
6263 	mlan_ds_misc_cfg *misc_cfg = MNULL;
6264 	mlan_status ret = MLAN_STATUS_SUCCESS;
6265 
6266 	ENTER();
6267 
6268 	reg = (HostCmd_DS_CHAN_REGION_CFG *) & resp->params.reg_cfg;
6269 	if (!reg) {
6270 		ret = MLAN_STATUS_FAILURE;
6271 		goto done;
6272 	}
6273 
6274 	action = wlan_le16_to_cpu(reg->action);
6275 	if (action != HostCmd_ACT_GEN_GET) {
6276 		ret = MLAN_STATUS_FAILURE;
6277 		goto done;
6278 	}
6279 
6280 	tlv_buf = (t_u8 *)reg + sizeof(*reg);
6281 	tlv_buf_left = wlan_le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*reg);
6282 
6283 	/* Add FW cfp tables and region info */
6284 	wlan_add_fw_cfp_tables(pmpriv, tlv_buf, tlv_buf_left);
6285 
6286 	if (!pioctl_buf)
6287 		goto done;
6288 
6289 	if (!pioctl_buf->pbuf) {
6290 		ret = MLAN_STATUS_FAILURE;
6291 		goto done;
6292 	}
6293 
6294 	misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
6295 
6296 	while (tlv_buf_left >= sizeof(*head)) {
6297 		head = (MrvlIEtypesHeader_t *)tlv_buf;
6298 		tlv = wlan_le16_to_cpu(head->type);
6299 		tlv_buf_len = wlan_le16_to_cpu(head->len);
6300 
6301 		if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
6302 			break;
6303 
6304 		switch (tlv) {
6305 		case TLV_TYPE_CHAN_ATTR_CFG:
6306 			DBG_HEXDUMP(MCMD_D, "CHAN:",
6307 				    (t_u8 *)head + sizeof(*head), tlv_buf_left);
6308 			if (tlv_buf_len >
6309 			    misc_cfg->param.custom_reg_domain.cfg_len) {
6310 				tlv_buf_len =
6311 					misc_cfg->param.custom_reg_domain.
6312 					cfg_len;
6313 			}
6314 			misc_cfg->param.custom_reg_domain.cfg_len = tlv_buf_len;
6315 			memcpy(pmpriv->adapter,
6316 			       misc_cfg->param.custom_reg_domain.cfg_buf,
6317 			       (t_u8 *)head + sizeof(*head), tlv_buf_len);
6318 			pioctl_buf->data_read_written = tlv_buf_len;
6319 			break;
6320 		}
6321 
6322 		tlv_buf += (sizeof(*head) + tlv_buf_len);
6323 		tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
6324 	}
6325 done:
6326 	LEAVE();
6327 	return ret;
6328 }
6329 
6330 #if defined(SYSKT_MULTI) && defined(OOB_WAKEUP) || defined(SUSPEND_SDIO_PULL_DOWN)
6331 /**
6332  *  @brief This function prepares command of sdio_pull_ctl
6333  *
6334  *  @param pmpriv       A pointer to mlan_private structure
6335  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
6336  *  @param cmd_action   The action: GET or SET
6337  *  @return             MLAN_STATUS_SUCCESS
6338  */
6339 mlan_status
6340 wlan_cmd_sdio_pull_ctl(pmlan_private pmpriv,
6341 		       IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action)
6342 {
6343 	HostCmd_DS_SDIO_PULL_CTRL *pull_ctrl = &cmd->params.sdio_pull_ctl;
6344 
6345 	ENTER();
6346 
6347 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SDIO_PULL_CTRL);
6348 	cmd->size =
6349 		wlan_cpu_to_le16((sizeof(HostCmd_DS_SDIO_PULL_CTRL)) +
6350 				 S_DS_GEN);
6351 
6352 	memset(pmpriv->adapter, pull_ctrl, 0,
6353 	       sizeof(HostCmd_DS_SDIO_PULL_CTRL));
6354 	pull_ctrl->action = wlan_cpu_to_le16(cmd_action);
6355 	if (cmd_action == HostCmd_ACT_GEN_SET) {
6356 		pull_ctrl->pull_up = wlan_cpu_to_le16(DEFAULT_PULLUP_DELAY);
6357 		pull_ctrl->pull_down = wlan_cpu_to_le16(DEFAULT_PULLDOWN_DELAY);
6358 		pull_ctrl->gpio_pullup_req = DEFAULT_GPIO_PULLUP_REQ;
6359 		pull_ctrl->gpio_pullup_ack = DEFAULT_GPIO_ACK_PULLUP;
6360 	}
6361 	LEAVE();
6362 	return MLAN_STATUS_SUCCESS;
6363 }
6364 #endif
6365 
6366 /**
6367  *  @brief This function sends fw dump event command to firmware.
6368  *
6369  *  @param pmpriv         A pointer to mlan_private structure
6370  *  @param cmd            HostCmd_DS_COMMAND structure
6371  *  @param cmd_action     the action: GET or SET
6372  *  @param pdata_buf      A void pointer to information buffer
6373  *  @return               N/A
6374  */
6375 mlan_status
6376 wlan_cmd_fw_dump_event(IN pmlan_private pmpriv,
6377 		       IN HostCmd_DS_COMMAND *cmd,
6378 		       IN t_u16 cmd_action, IN t_void *pdata_buf)
6379 {
6380 	ENTER();
6381 
6382 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_FW_DUMP_EVENT);
6383 	cmd->size = S_DS_GEN;
6384 	cmd->size = wlan_cpu_to_le16(cmd->size);
6385 
6386 	LEAVE();
6387 	return MLAN_STATUS_SUCCESS;
6388 }
6389 
6390 /**
6391  *  @brief This function sends boot sleep configure command to firmware.
6392  *
6393  *  @param pmpriv         A pointer to mlan_private structure
6394  *  @param cmd          Hostcmd ID
6395  *  @param cmd_action   Command action
6396  *  @param pdata_buf    A void pointer to information buffer
6397  *  @return             MLAN_STATUS_SUCCESS/ MLAN_STATUS_FAILURE
6398  */
6399 mlan_status
6400 wlan_cmd_boot_sleep(IN pmlan_private pmpriv,
6401 		    IN HostCmd_DS_COMMAND *cmd,
6402 		    IN t_u16 cmd_action, IN t_void *pdata_buf)
6403 {
6404 	HostCmd_DS_BOOT_SLEEP *boot_sleep = MNULL;
6405 	t_u16 enable = *(t_u16 *)pdata_buf;
6406 
6407 	ENTER();
6408 
6409 	cmd->command = wlan_cpu_to_le16(HostCmd_CMD_BOOT_SLEEP);
6410 	boot_sleep = &cmd->params.boot_sleep;
6411 	boot_sleep->action = wlan_cpu_to_le16(cmd_action);
6412 	boot_sleep->enable = wlan_cpu_to_le16(enable);
6413 
6414 	cmd->size = S_DS_GEN + sizeof(HostCmd_DS_BOOT_SLEEP);
6415 
6416 	LEAVE();
6417 	return MLAN_STATUS_SUCCESS;
6418 }
6419 
6420 /**
6421  *  @brief This function handles the command response of boot sleep cfg
6422  *
6423  *  @param pmpriv       A pointer to mlan_private structure
6424  *  @param resp         A pointer to HostCmd_DS_COMMAND
6425  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
6426  *
6427  *  @return        MLAN_STATUS_SUCCESS
6428  */
6429 mlan_status
6430 wlan_ret_boot_sleep(IN pmlan_private pmpriv,
6431 		    IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf)
6432 {
6433 	HostCmd_DS_BOOT_SLEEP *boot_sleep = &resp->params.boot_sleep;
6434 	mlan_ds_misc_cfg *cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
6435 
6436 	ENTER();
6437 
6438 	cfg->param.boot_sleep = wlan_le16_to_cpu(boot_sleep->enable);
6439 	PRINTM(MCMND, "boot sleep cfg status %u", cfg->param.boot_sleep);
6440 
6441 	LEAVE();
6442 	return MLAN_STATUS_SUCCESS;
6443 }
6444