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