1 /** @file mlan_cmdevt.c
2  *
3  *  @brief  This file provides the handling of CMD/EVENT in MLAN
4  *
5  *  Copyright 2008-2024 NXP
6  *
7  *  SPDX-License-Identifier: BSD-3-Clause
8  *
9  */
10 
11 /*************************************************************
12 Change Log:
13     05/12/2009: initial version
14 ************************************************************/
15 #include <mlan_api.h>
16 
17 /* Additional WMSDK header files */
18 #include <wmerrno.h>
19 #include <osa.h>
20 
21 /* Always keep this include at the end of all include files */
22 #include <mlan_remap_mem_operations.h>
23 
24 /********************************************************
25                 Local Variables
26 ********************************************************/
27 
28 /*******************************************************
29                 Global Variables
30 ********************************************************/
31 
32 /********************************************************
33                 Local Functions
34 ********************************************************/
35 
36 /**
37  *  @brief This function prepare the command before sending to firmware.
38  *
39  *  @param pmpriv       A pointer to mlan_private structure
40  *  @param cmd_no       Command number
41  *  @param cmd_action   Command action: GET or SET
42  *  @param cmd_oid      Cmd oid: treated as sub command
43  *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
44  *  @param pdata_buf    A pointer to information buffer
45  *
46  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
47  */
wlan_prepare_cmd(IN mlan_private * pmpriv,IN t_u16 cmd_no,IN t_u16 cmd_action,IN t_u32 cmd_oid,IN t_void * pioctl_buf,IN t_void * pdata_buf)48 mlan_status wlan_prepare_cmd(IN mlan_private *pmpriv,
49                              IN t_u16 cmd_no,
50                              IN t_u16 cmd_action,
51                              IN t_u32 cmd_oid,
52                              IN t_void *pioctl_buf,
53                              IN t_void *pdata_buf)
54 {
55     /* Note: We send only one command at a time and do not need the linked
56        list based implementation used here. So we will call our own
57        implementation here.
58     */
59 
60     return wifi_prepare_and_send_cmd(pmpriv, cmd_no, cmd_action, cmd_oid, pioctl_buf, pdata_buf, pmpriv->bss_type,
61                                      NULL);
62 }
63 
64 #if CONFIG_11AX
65 /**
66  *  @brief Fetch bitmap rate index
67  *
68  *  @param rate_scope  A pointer to MrvlRateScope_t
69  *
70  *  @return            bitmap rate index
71  */
wlan_get_bitmap_index(MrvlRateScope_t * rate_scope)72 static t_u16 wlan_get_bitmap_index(MrvlRateScope_t *rate_scope)
73 {
74     t_u16 index = 0;
75     if (rate_scope != MNULL)
76     {
77         index += NELEMENTS(rate_scope->ht_mcs_rate_bitmap);
78         index += NELEMENTS(rate_scope->vht_mcs_rate_bitmap);
79     }
80     return index;
81 }
82 #endif
83 
84 /**
85  *  @brief This function prepares command of power mode
86  *
87  *  @param pmpriv		A pointer to mlan_private structure
88  *  @param cmd	   		A pointer to HostCmd_DS_COMMAND structure
89  *  @param cmd_action   the action: GET or SET
90  *  @param ps_bitmap    PS bitmap
91  *  @param pdata_buf    A pointer to data buffer
92  *  @return         MLAN_STATUS_SUCCESS
93  */
wlan_cmd_enh_power_mode(pmlan_private pmpriv,IN HostCmd_DS_COMMAND * cmd,IN ENH_PS_MODES cmd_action,IN t_u16 ps_bitmap,IN t_void * pdata_buf)94 mlan_status wlan_cmd_enh_power_mode(pmlan_private pmpriv,
95                                     IN HostCmd_DS_COMMAND *cmd,
96                                     IN ENH_PS_MODES cmd_action,
97                                     IN t_u16 ps_bitmap,
98                                     IN t_void *pdata_buf)
99 {
100     HostCmd_DS_802_11_PS_MODE_ENH *psmode_enh = &cmd->params.psmode_enh;
101     t_u8 *tlv                                 = MNULL;
102     t_u16 cmd_size                            = 0;
103 
104     ENTER();
105 
106     PRINTM(MCMND, "PS Command: action = 0x%x, bitmap = 0x%x\n", cmd_action, ps_bitmap);
107 
108     cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH);
109     if (cmd_action == DIS_AUTO_PS)
110     {
111         psmode_enh->action           = (ENH_PS_MODES)(wlan_cpu_to_le16(DIS_AUTO_PS));
112         psmode_enh->params.ps_bitmap = wlan_cpu_to_le16(ps_bitmap);
113         cmd->size                    = wlan_cpu_to_le16(S_DS_GEN + AUTO_PS_FIX_SIZE);
114     }
115 #if (CONFIG_WNM_PS)
116     else if (cmd_action == DIS_WNM_PS)
117     {
118         psmode_enh->action           = (ENH_PS_MODES)(wlan_cpu_to_le16(DIS_WNM_PS));
119         psmode_enh->params.ps_bitmap = wlan_cpu_to_le16(ps_bitmap);
120         cmd->size                    = wlan_cpu_to_le16(S_DS_GEN + AUTO_PS_FIX_SIZE);
121     }
122 #endif
123     else if (cmd_action == GET_PS)
124     {
125         psmode_enh->action           = (ENH_PS_MODES)(wlan_cpu_to_le16(GET_PS));
126         psmode_enh->params.ps_bitmap = wlan_cpu_to_le16(ps_bitmap);
127         cmd->size                    = wlan_cpu_to_le16(S_DS_GEN + AUTO_PS_FIX_SIZE);
128     }
129     else if (cmd_action == EXT_PS_PARAM)
130     {
131         psmode_enh->action                    = wlan_cpu_to_le16(EXT_PS_PARAM);
132         psmode_enh->params.ext_param.reserved = 0;
133         cmd->size                             = wlan_cpu_to_le16(S_DS_GEN + sizeof(t_u16) + sizeof(ext_ps_param));
134         psmode_enh->params.ext_param.param.header.type = wlan_cpu_to_le16(TLV_TYPE_PS_EXT_PARAM);
135         psmode_enh->params.ext_param.param.header.len  = sizeof(t_u32);
136         psmode_enh->params.ext_param.param.mode        = wlan_cpu_to_le32(*((t_u32 *)pdata_buf));
137     }
138     else if (cmd_action == EN_AUTO_PS)
139     {
140         psmode_enh->action                   = (ENH_PS_MODES)(wlan_cpu_to_le16(EN_AUTO_PS));
141         psmode_enh->params.auto_ps.ps_bitmap = wlan_cpu_to_le16(ps_bitmap);
142         cmd_size                             = S_DS_GEN + AUTO_PS_FIX_SIZE;
143         tlv                                  = (t_u8 *)cmd + cmd_size;
144         if ((ps_bitmap & BITMAP_STA_PS) != 0U)
145         {
146             pmlan_adapter pmadapter        = pmpriv->adapter;
147             MrvlIEtypes_ps_param_t *ps_tlv = (MrvlIEtypes_ps_param_t *)(void *)tlv;
148             ps_param *ps_mode              = (ps_param *)&ps_tlv->param;
149             ps_tlv->header.type            = wlan_cpu_to_le16(TLV_TYPE_PS_PARAM);
150             ps_tlv->header.len = wlan_cpu_to_le16(sizeof(MrvlIEtypes_ps_param_t) - sizeof(MrvlIEtypesHeader_t));
151             cmd_size += (t_u16)sizeof(MrvlIEtypes_ps_param_t);
152             tlv += (t_u8)sizeof(MrvlIEtypes_ps_param_t);
153             ps_mode->null_pkt_interval     = wlan_cpu_to_le16(pmadapter->null_pkt_interval);
154             ps_mode->multiple_dtims        = wlan_cpu_to_le16(pmadapter->multiple_dtim);
155             ps_mode->bcn_miss_timeout      = wlan_cpu_to_le16(pmadapter->bcn_miss_time_out);
156             ps_mode->local_listen_interval = wlan_cpu_to_le16(pmadapter->local_listen_interval);
157             ps_mode->adhoc_wake_period     = wlan_cpu_to_le16(pmadapter->adhoc_awake_period);
158             ps_mode->delay_to_ps           = wlan_cpu_to_le16(pmadapter->delay_to_ps);
159             ps_mode->mode                  = wlan_cpu_to_le16(pmadapter->enhanced_ps_mode);
160         }
161 
162         if ((ps_bitmap & BITMAP_AUTO_DS) != 0U)
163         {
164             MrvlIEtypes_auto_ds_param_t *auto_ps_tlv = (MrvlIEtypes_auto_ds_param_t *)(void *)tlv;
165             auto_ds_param *auto_ds                   = (auto_ds_param *)&auto_ps_tlv->param;
166             t_u16 idletime                           = 0;
167             auto_ps_tlv->header.type                 = wlan_cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM);
168             auto_ps_tlv->header.len =
169                 wlan_cpu_to_le16(sizeof(MrvlIEtypes_auto_ds_param_t) - sizeof(MrvlIEtypesHeader_t));
170             cmd_size += (t_u16)sizeof(MrvlIEtypes_auto_ds_param_t);
171             tlv += (t_u8)sizeof(MrvlIEtypes_auto_ds_param_t);
172             if (pdata_buf != NULL)
173             {
174                 idletime = ((mlan_ds_auto_ds *)pdata_buf)->idletime;
175             }
176             auto_ds->deep_sleep_timeout = wlan_cpu_to_le16(idletime);
177         }
178 
179 #if UAP_SUPPORT
180         if ((pdata_buf != MNULL) && (ps_bitmap & (BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS)))
181         {
182             mlan_ds_ps_mgmt *ps_mgmt                   = (mlan_ds_ps_mgmt *)pdata_buf;
183             MrvlIEtypes_sleep_param_t *sleep_tlv       = MNULL;
184             MrvlIEtypes_inact_sleep_param_t *inact_tlv = MNULL;
185             if ((ps_mgmt->flags & PS_FLAG_SLEEP_PARAM) != 0U)
186             {
187                 sleep_tlv              = (MrvlIEtypes_sleep_param_t *)(void *)tlv;
188                 sleep_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_AP_SLEEP_PARAM);
189                 sleep_tlv->header.len =
190                     wlan_cpu_to_le16(sizeof(MrvlIEtypes_sleep_param_t) - sizeof(MrvlIEtypesHeader_t));
191                 sleep_tlv->ctrl_bitmap = wlan_cpu_to_le32(ps_mgmt->sleep_param.ctrl_bitmap);
192                 sleep_tlv->min_sleep   = wlan_cpu_to_le32(ps_mgmt->sleep_param.min_sleep);
193                 sleep_tlv->max_sleep   = wlan_cpu_to_le32(ps_mgmt->sleep_param.max_sleep);
194                 cmd_size += (t_u16)sizeof(MrvlIEtypes_sleep_param_t);
195                 tlv += (t_u8)sizeof(MrvlIEtypes_sleep_param_t);
196             }
197             if ((ps_mgmt->flags & PS_FLAG_INACT_SLEEP_PARAM) != 0U)
198             {
199                 inact_tlv              = (MrvlIEtypes_inact_sleep_param_t *)(void *)tlv;
200                 inact_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_AP_INACT_SLEEP_PARAM);
201                 inact_tlv->header.len =
202                     wlan_cpu_to_le16(sizeof(MrvlIEtypes_inact_sleep_param_t) - sizeof(MrvlIEtypesHeader_t));
203                 inact_tlv->inactivity_to = wlan_cpu_to_le32(ps_mgmt->inact_param.inactivity_to);
204                 inact_tlv->min_awake     = wlan_cpu_to_le32(ps_mgmt->inact_param.min_awake);
205                 inact_tlv->max_awake     = wlan_cpu_to_le32(ps_mgmt->inact_param.max_awake);
206                 cmd_size += (t_u16)sizeof(MrvlIEtypes_inact_sleep_param_t);
207                 tlv += (t_u8)sizeof(MrvlIEtypes_inact_sleep_param_t);
208             }
209         }
210 #endif
211         cmd->size = wlan_cpu_to_le16(cmd_size);
212     }
213 #if (CONFIG_WNM_PS)
214     else if (cmd_action == EN_WNM_PS)
215     {
216         psmode_enh->action                   = wlan_cpu_to_le16(EN_WNM_PS);
217         psmode_enh->params.auto_ps.ps_bitmap = wlan_cpu_to_le16(ps_bitmap);
218         cmd_size                             = S_DS_GEN + AUTO_PS_FIX_SIZE;
219         tlv                                  = (t_u8 *)cmd + cmd_size;
220         if ((ps_bitmap & BITMAP_STA_PS) != 0)
221         {
222             if (pdata_buf != NULL)
223             {
224                 pmlan_adapter pmadapter                = pmpriv->adapter;
225                 MrvlIEtypes_wnm_ps_param_t *wnm_ps_tlv = (MrvlIEtypes_wnm_ps_param_t *)tlv;
226                 wnm_ps_param *wnm_ps                   = (wnm_ps_param *)&wnm_ps_tlv->param;
227                 t_u16 internal                         = 0;
228                 wnm_ps_tlv->header.type                = wlan_cpu_to_le16(TLV_TYPE_WNM_PARAM);
229                 wnm_ps_tlv->header.len =
230                     wlan_cpu_to_le16(sizeof(MrvlIEtypes_wnm_ps_param_t) - sizeof(MrvlIEtypesHeader_t));
231                 cmd_size += sizeof(MrvlIEtypes_wnm_ps_param_t);
232                 tlv += sizeof(MrvlIEtypes_wnm_ps_param_t);
233                 internal                      = *(t_u32 *)pdata_buf;
234                 wnm_ps->action                = 0;
235                 wnm_ps->null_pkt_interval     = wlan_cpu_to_le16(pmadapter->null_pkt_interval);
236                 wnm_ps->bcn_miss_timeout      = wlan_cpu_to_le16(pmadapter->bcn_miss_time_out);
237                 wnm_ps->local_listen_interval = wlan_cpu_to_le16(pmadapter->local_listen_interval);
238                 wnm_ps->ps_mode               = wlan_cpu_to_le16(pmadapter->enhanced_ps_mode);
239                 wnm_ps->delay_to_ps           = DELAY_TO_PS_WNM;
240                 wnm_ps->wnm_sleep_interval    = wlan_cpu_to_le16(internal);
241             }
242         }
243         cmd->size = wlan_cpu_to_le16(cmd_size);
244     }
245 #endif
246     else
247     { /* Do Nothing */
248     }
249 
250     LEAVE();
251     return MLAN_STATUS_SUCCESS;
252 }
253 
254 #ifdef SD8801
wlan_ret_802_11_tx_rate_query(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * resp,IN void * pioctl)255 mlan_status wlan_ret_802_11_tx_rate_query(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *resp, IN void *pioctl)
256 {
257     mlan_adapter *pmadapter = pmpriv->adapter;
258     wifi_ds_rate *rate      = MNULL;
259     ENTER();
260 
261     pmpriv->tx_rate = resp->params.tx_rate.tx_rate;
262 #if CONFIG_11N
263     pmpriv->tx_htinfo = resp->params.tx_rate.ht_info;
264 #endif
265     if (!pmpriv->is_data_rate_auto)
266     {
267 #if CONFIG_11N
268         pmpriv->data_rate = wlan_index_to_data_rate(pmadapter, pmpriv->tx_rate, pmpriv->tx_htinfo);
269 #else
270         pmpriv->data_rate = wlan_index_to_data_rate(pmadapter, pmpriv->tx_rate, 0);
271 #endif
272     }
273 
274     if (pioctl)
275     {
276         rate = (wifi_ds_rate *)pioctl;
277         if (rate->sub_command == WIFI_DS_RATE_CFG)
278         {
279 #if 0
280             if(rate->param.rate_cfg.rate_type == MLAN_RATE_INDEX) {
281 #endif
282 #if CONFIG_11N
283             if (pmpriv->tx_htinfo & MBIT(0))
284                 rate->param.rate_cfg.rate = pmpriv->tx_rate + MLAN_RATE_INDEX_MCS0;
285             else
286 #endif
287                 /* For HostCmd_CMD_802_11_TX_RATE_QUERY, there is a hole in rate table
288                  * between HR/DSSS and OFDM rates, so minus 1 for OFDM rate index */
289                 rate->param.rate_cfg.rate =
290                     (pmpriv->tx_rate > MLAN_RATE_INDEX_OFDM0) ? pmpriv->tx_rate - 1 : pmpriv->tx_rate;
291 #if 0
292             }
293             else {
294 #if CONFIG_11N
295                     rate->param.rate_cfg.rate = wlan_index_to_data_rate(pmadapter, pmpriv->tx_rate,
296                                                 pmpriv->tx_htinfo);
297 #else
298                     rate->param.rate_cfg.rate = wlan_index_to_data_rate(pmadapter, pmpriv->tx_rate, 0);
299 #endif
300             }
301 #endif
302         }
303         else if (rate->sub_command == WIFI_DS_GET_DATA_RATE)
304         {
305 #if CONFIG_11N
306             if (pmpriv->tx_htinfo & MBIT(0))
307             {
308                 rate->param.data_rate.tx_data_rate = pmpriv->tx_rate + MLAN_RATE_INDEX_MCS0;
309                 if (pmpriv->tx_htinfo & MBIT(1))
310                     rate->param.data_rate.tx_bw = MLAN_HT_BW40;
311                 else
312                     rate->param.data_rate.tx_bw = MLAN_HT_BW20;
313                 if (pmpriv->tx_htinfo & MBIT(2))
314                     rate->param.data_rate.tx_gi = MLAN_HT_SGI;
315                 else
316                     rate->param.data_rate.tx_gi = MLAN_HT_LGI;
317             }
318             else
319 #endif
320                 /* For HostCmd_CMD_802_11_TX_RATE_QUERY, there is a hole in rate table
321                    between HR/DSSS and OFDM rates, so minus 1 for OFDM rate index */
322                 rate->param.data_rate.tx_data_rate =
323                     (pmpriv->tx_rate > MLAN_RATE_INDEX_OFDM0) ? pmpriv->tx_rate - 1 : pmpriv->tx_rate;
324 #if CONFIG_11N
325             if (pmpriv->rxpd_htinfo & MBIT(0))
326             {
327                 rate->param.data_rate.rx_data_rate = pmpriv->rxpd_rate + MLAN_RATE_INDEX_MCS0;
328                 if (pmpriv->rxpd_htinfo & MBIT(1))
329                     rate->param.data_rate.rx_bw = MLAN_HT_BW40;
330                 else
331                     rate->param.data_rate.rx_bw = MLAN_HT_BW20;
332                 if (pmpriv->rxpd_htinfo & MBIT(2))
333                     rate->param.data_rate.rx_gi = MLAN_HT_SGI;
334                 else
335                     rate->param.data_rate.rx_gi = MLAN_HT_LGI;
336             }
337             else
338 #endif
339                 /* For rate index in RxPD, there is a hole in rate table
340                    between HR/DSSS and OFDM rates, so minus 1 for OFDM rate index */
341                 rate->param.data_rate.rx_data_rate =
342                     (pmpriv->rxpd_rate > MLAN_RATE_INDEX_OFDM0) ? pmpriv->rxpd_rate - 1 : pmpriv->rxpd_rate;
343         }
344     }
345     LEAVE();
346     return MLAN_STATUS_SUCCESS;
347 }
348 #else
349 /**
350  *  @brief This function handles the command response of tx rate query
351  *
352  *  @param pmpriv       A pointer to mlan_private structure
353  *  @param resp         A pointer to HostCmd_DS_COMMAND
354  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
355  *
356  *  @return             MLAN_STATUS_SUCCESS
357  */
wlan_ret_802_11_tx_rate_query(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * resp,IN void * pioctl)358 mlan_status wlan_ret_802_11_tx_rate_query(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *resp, IN void *pioctl)
359 {
360     mlan_adapter *pmadapter = pmpriv->adapter;
361     wifi_ds_rate *rate      = MNULL;
362     ENTER();
363 
364     pmpriv->tx_rate      = resp->params.tx_rate.tx_rate;
365     pmpriv->tx_rate_info = resp->params.tx_rate.tx_rate_info;
366 
367 #if CONFIG_11AX
368     if ((mlan_rate_format)(pmpriv->tx_rate_info & 0x3U) == MLAN_RATE_FORMAT_HE)
369         pmpriv->ext_tx_rate_info = resp->params.tx_rate.ext_tx_rate_info;
370 #endif
371 
372     if (!pmpriv->is_data_rate_auto)
373     {
374         pmpriv->data_rate = wlan_index_to_data_rate(pmadapter, pmpriv->tx_rate, pmpriv->tx_rate_info
375 #if CONFIG_11AX
376                                                     ,
377                                                     pmpriv->ext_tx_rate_info
378 #endif
379         );
380     }
381 
382     if (pioctl != NULL)
383     {
384         rate = (wifi_ds_rate *)pioctl;
385         if (rate->sub_command == WIFI_DS_RATE_CFG)
386         {
387 #if 0
388             if(rate->param.rate_cfg.rate_type == MLAN_RATE_INDEX) {
389 #endif
390 #if CONFIG_11AC
391             if ((mlan_rate_format)(pmpriv->tx_rate_info & 0x3U) == MLAN_RATE_FORMAT_VHT
392 #if CONFIG_11AX
393                 || ((mlan_rate_format)(pmpriv->tx_rate_info & 0x3U) == MLAN_RATE_FORMAT_HE)
394 #endif
395             )
396             {
397                 /* VHT rate */
398                 rate->param.rate_cfg.rate = (t_u32)((pmpriv->tx_rate) & 0xF);
399             }
400             else
401 #endif
402 #if CONFIG_11N
403                 if ((mlan_rate_format)(pmpriv->tx_rate_info & 0x3U) == MLAN_RATE_FORMAT_HT)
404             {
405                 /* HT rate */
406                 rate->param.rate_cfg.rate = pmpriv->tx_rate + MLAN_RATE_INDEX_MCS0;
407             }
408             else
409 #endif
410             {
411                 /* LG rate */
412                 /* For HostCmd_CMD_802_11_TX_RATE_QUERY,
413                  * there is a hole (0x4) in rate table
414                  * between HR/DSSS and OFDM rates,
415                  * so minus 1 for OFDM rate index */
416                 rate->param.rate_cfg.rate =
417                     (pmpriv->tx_rate > MLAN_RATE_INDEX_OFDM0) ? pmpriv->tx_rate - 1U : pmpriv->tx_rate;
418             }
419 #if 0
420             }
421             else {
422                 /* rate_type = MLAN_RATE_VALUE */
423                 rate->param.rate_cfg.rate = wlan_index_to_data_rate(pmadapter,
424                                                 pmpriv->tx_rate,
425                                                 pmpriv->tx_rate_info);
426             }
427 #endif
428         }
429         else if (rate->sub_command == WIFI_DS_GET_DATA_RATE)
430         {
431             /* Tx rate info */
432 #if CONFIG_11AC
433             if ((mlan_rate_format)(pmpriv->tx_rate_info & 0x3U) == MLAN_RATE_FORMAT_VHT
434 #if CONFIG_11AX
435                 || (mlan_rate_format)(pmpriv->tx_rate_info & 0x3U) == MLAN_RATE_FORMAT_HE
436 #endif
437             )
438             {
439                 /* VHT/HE rate */
440                 rate->param.data_rate.tx_rate_format = (mlan_rate_format)(pmpriv->tx_rate_info & 0x3U);
441                 rate->param.data_rate.tx_bw          = (t_u32)((pmpriv->tx_rate_info & 0xC) >> 2);
442 
443 #if CONFIG_11AX
444                 if ((mlan_rate_format)(pmpriv->tx_rate_info & 0x3U) == MLAN_RATE_FORMAT_HE)
445                     rate->param.data_rate.tx_gi =
446                         (pmpriv->tx_rate_info & 0x10) >> 4 | (pmpriv->tx_rate_info & 0x80) >> 6;
447                 else
448 #endif
449                     rate->param.data_rate.tx_gi = (t_u32)((pmpriv->tx_rate_info & 0x10) >> 4);
450                 rate->param.data_rate.tx_nss       = ((pmpriv->tx_rate) >> 4) & 0x03;
451                 rate->param.data_rate.tx_mcs_index = (t_u32)((pmpriv->tx_rate) & 0xF);
452                 rate->param.data_rate.tx_data_rate =
453                     wlan_index_to_data_rate(pmadapter, pmpriv->tx_rate, pmpriv->tx_rate_info
454 #if CONFIG_11AX
455                                             ,
456                                             pmpriv->ext_tx_rate_info
457 #endif
458                     );
459             }
460             else
461 #endif
462 #if CONFIG_11N
463                 if ((mlan_rate_format)(pmpriv->tx_rate_info & 0x3U) == MLAN_RATE_FORMAT_HT)
464             {
465                 /* HT rate */
466                 rate->param.data_rate.tx_rate_format = MLAN_RATE_FORMAT_HT;
467                 rate->param.data_rate.tx_bw          = (pmpriv->tx_rate_info & 0xCU) >> 2U;
468                 rate->param.data_rate.tx_gi          = (pmpriv->tx_rate_info & 0x10U) >> 4U;
469                 rate->param.data_rate.tx_mcs_index   = pmpriv->tx_rate;
470                 rate->param.data_rate.tx_data_rate =
471                     wlan_index_to_data_rate(pmadapter, pmpriv->tx_rate, pmpriv->tx_rate_info
472 #if CONFIG_11AX
473                                             ,
474                                             pmpriv->ext_tx_rate_info
475 #endif
476                     );
477             }
478             else
479 #endif
480             {
481                 /* LG rate */
482                 rate->param.data_rate.tx_rate_format = MLAN_RATE_FORMAT_LG;
483                 /* For HostCmd_CMD_802_11_TX_RATE_QUERY,
484                  * there is a hole in rate table
485                  * between HR/DSSS and OFDM rates,
486                  * so minus 1 for OFDM rate index */
487                 rate->param.data_rate.tx_data_rate =
488                     (pmpriv->tx_rate > MLAN_RATE_INDEX_OFDM0) ? pmpriv->tx_rate - 1U : pmpriv->tx_rate;
489             }
490 
491             /* Rx rate info */
492 #if CONFIG_11AC
493             if ((mlan_rate_format)(pmpriv->rxpd_rate_info & 0x3U) == MLAN_RATE_FORMAT_VHT
494 #if CONFIG_11AX
495                 || (pmpriv->rxpd_rate_info & 0x3) == MLAN_RATE_FORMAT_HE
496 #endif
497             )
498             {
499                 /* VHT/HE rate */
500                 rate->param.data_rate.rx_rate_format = (mlan_rate_format)(pmpriv->rxpd_rate_info & 0x3);
501                 rate->param.data_rate.rx_bw          = (t_u32)((pmpriv->rxpd_rate_info & 0xC) >> 2);
502 
503 #if CONFIG_11AX
504                 if ((pmpriv->rxpd_rate_info & 0x3) == MLAN_RATE_FORMAT_HE)
505                     rate->param.data_rate.rx_gi =
506                         (pmpriv->rxpd_rate_info & 0x10) >> 4 | (pmpriv->rxpd_rate_info & 0x80) >> 6;
507                 else
508 #endif
509                     rate->param.data_rate.rx_gi = (t_u32)((pmpriv->rxpd_rate_info & 0x10) >> 4);
510                 rate->param.data_rate.rx_nss       = ((pmpriv->rxpd_rate) >> 4) & 0x3;
511                 rate->param.data_rate.rx_mcs_index = (t_u32)((pmpriv->rxpd_rate) & 0xF);
512                 rate->param.data_rate.rx_data_rate =
513                     wlan_index_to_data_rate(pmadapter, pmpriv->rxpd_rate, pmpriv->rxpd_rate_info
514 #if CONFIG_11AX
515                                             ,
516                                             pmpriv->ext_tx_rate_info
517 #endif
518                     );
519             }
520             else
521 #endif
522 #if CONFIG_11N
523                 if ((pmpriv->rxpd_rate_info & 0x3) == MLAN_RATE_FORMAT_HT)
524             {
525                 /* HT rate */
526                 rate->param.data_rate.rx_rate_format = MLAN_RATE_FORMAT_HT;
527                 rate->param.data_rate.rx_bw          = (pmpriv->rxpd_rate_info & 0xCU) >> 2U;
528                 rate->param.data_rate.rx_gi          = (pmpriv->rxpd_rate_info & 0x10U) >> 4U;
529                 rate->param.data_rate.rx_mcs_index   = pmpriv->rxpd_rate;
530                 rate->param.data_rate.rx_data_rate =
531                     wlan_index_to_data_rate(pmadapter, pmpriv->rxpd_rate, pmpriv->rxpd_rate_info
532 #if CONFIG_11AX
533                                             ,
534                                             pmpriv->ext_tx_rate_info
535 #endif
536                     );
537             }
538             else
539 #endif
540             {
541                 /* LG rate */
542                 rate->param.data_rate.rx_rate_format = MLAN_RATE_FORMAT_LG;
543                 /* For rate index in RxPD,
544                  * there is a hole in rate table
545                  * between HR/DSSS and OFDM rates,
546                  * so minus 1 for OFDM rate index */
547                 rate->param.data_rate.rx_data_rate =
548                     (t_u32)((pmpriv->rxpd_rate > MLAN_RATE_INDEX_OFDM0) ? pmpriv->rxpd_rate - 1 : pmpriv->rxpd_rate);
549             }
550         }
551         else
552         { /* Do Nothing */
553         }
554     }
555     LEAVE();
556     return MLAN_STATUS_SUCCESS;
557 }
558 #endif
559 
560 /**
561  *  @brief This function prepares command of tx_rate_cfg.
562  *
563  *  @param pmpriv       A pointer to mlan_private structure
564  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
565  *  @param cmd_action   The action: GET or SET
566  *  @param pdata_buf    A pointer to data buffer
567  *
568  *  @return             MLAN_STATUS_SUCCESS
569  */
wlan_cmd_tx_rate_cfg(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * cmd,IN t_u16 cmd_action,IN t_void * pdata_buf,IN mlan_ioctl_req * pioctl_buf)570 mlan_status wlan_cmd_tx_rate_cfg(IN pmlan_private pmpriv,
571                                  IN HostCmd_DS_COMMAND *cmd,
572                                  IN t_u16 cmd_action,
573                                  IN t_void *pdata_buf,
574                                  IN mlan_ioctl_req *pioctl_buf)
575 {
576     HostCmd_DS_TX_RATE_CFG *rate_cfg = (HostCmd_DS_TX_RATE_CFG *)&cmd->params.tx_rate_cfg;
577     MrvlRateScope_t *rate_scope;
578     MrvlRateDropPattern_t *rate_drop;
579     MrvlIETypes_rate_setting_t *rate_setting_tlv;
580     mlan_ds_rate *ds_rate = MNULL;
581     t_u16 *pbitmap_rates  = (t_u16 *)pdata_buf;
582 
583     t_u32 i;
584 
585     ENTER();
586 
587     cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TX_RATE_CFG);
588 
589     rate_cfg->action    = wlan_cpu_to_le16(cmd_action);
590     rate_cfg->cfg_index = 0;
591 
592     rate_scope = (MrvlRateScope_t *)(void *)((t_u8 *)rate_cfg + sizeof(HostCmd_DS_TX_RATE_CFG));
593     // coverity[overrun-local:SUPPRESS]
594     rate_scope->type   = wlan_cpu_to_le16(TLV_TYPE_RATE_SCOPE);
595     rate_scope->length = wlan_cpu_to_le16(sizeof(MrvlRateScope_t) - sizeof(MrvlIEtypesHeader_t));
596     if (pbitmap_rates != MNULL)
597     {
598         rate_scope->hr_dsss_rate_bitmap = wlan_cpu_to_le16(pbitmap_rates[0]);
599         rate_scope->ofdm_rate_bitmap    = wlan_cpu_to_le16(pbitmap_rates[1]);
600         for (i = 0; i < NELEMENTS(rate_scope->ht_mcs_rate_bitmap); i++)
601         {
602             rate_scope->ht_mcs_rate_bitmap[i] = wlan_cpu_to_le16(pbitmap_rates[2U + i]);
603         }
604 #if CONFIG_11AC
605         for (i = 0; i < NELEMENTS(rate_scope->vht_mcs_rate_bitmap); i++)
606         {
607             rate_scope->vht_mcs_rate_bitmap[i] =
608                 wlan_cpu_to_le16(pbitmap_rates[2U + NELEMENTS(rate_scope->ht_mcs_rate_bitmap) + i]);
609         }
610 #endif
611 #if CONFIG_11AX
612         if (IS_FW_SUPPORT_11AX(pmpriv->adapter))
613         {
614             for (i = 0; i < NELEMENTS(rate_scope->he_mcs_rate_bitmap); i++)
615                 rate_scope->he_mcs_rate_bitmap[i] =
616                     wlan_cpu_to_le16(pbitmap_rates[2U + wlan_get_bitmap_index(rate_scope) + i]);
617         }
618         else
619         {
620             rate_scope->length = wlan_cpu_to_le16(sizeof(MrvlRateScope_t) - sizeof(rate_scope->he_mcs_rate_bitmap) -
621                                                   sizeof(MrvlIEtypesHeader_t));
622         }
623 #endif
624     }
625     else
626     {
627         rate_scope->hr_dsss_rate_bitmap = wlan_cpu_to_le16(pmpriv->bitmap_rates[0]);
628         rate_scope->ofdm_rate_bitmap    = wlan_cpu_to_le16(pmpriv->bitmap_rates[1]);
629         for (i = 0; i < NELEMENTS(rate_scope->ht_mcs_rate_bitmap); i++)
630         {
631             rate_scope->ht_mcs_rate_bitmap[i] = wlan_cpu_to_le16(pmpriv->bitmap_rates[2U + i]);
632         }
633 #if CONFIG_11AC
634         for (i = 0; i < NELEMENTS(rate_scope->vht_mcs_rate_bitmap); i++)
635         {
636             rate_scope->vht_mcs_rate_bitmap[i] =
637                 wlan_cpu_to_le16(pmpriv->bitmap_rates[2U + NELEMENTS(rate_scope->ht_mcs_rate_bitmap) + i]);
638         }
639 #endif
640 #if CONFIG_11AX
641         if (IS_FW_SUPPORT_11AX(pmpriv->adapter))
642         {
643             for (i = 0; i < NELEMENTS(rate_scope->he_mcs_rate_bitmap); i++)
644                 rate_scope->he_mcs_rate_bitmap[i] =
645                     wlan_cpu_to_le16(pmpriv->bitmap_rates[2U + wlan_get_bitmap_index(rate_scope) + i]);
646         }
647         else
648         {
649             rate_scope->length = wlan_cpu_to_le16(sizeof(MrvlRateScope_t) - sizeof(rate_scope->he_mcs_rate_bitmap) -
650                                                   sizeof(MrvlIEtypesHeader_t));
651         }
652 #endif
653     }
654 
655     rate_drop                 = (MrvlRateDropPattern_t *)(void *)((t_u8 *)rate_scope + sizeof(MrvlRateScope_t));
656     rate_drop->type           = wlan_cpu_to_le16(TLV_TYPE_RATE_DROP_PATTERN);
657     rate_drop->length         = wlan_cpu_to_le16(sizeof(rate_drop->rate_drop_mode));
658     rate_drop->rate_drop_mode = 0;
659 
660     cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_TX_RATE_CFG) + sizeof(MrvlRateScope_t) +
661                                  sizeof(MrvlRateDropPattern_t));
662 
663     if (pioctl_buf)
664     {
665         ds_rate          = (mlan_ds_rate *)pioctl_buf->pbuf;
666         rate_setting_tlv = (MrvlIETypes_rate_setting_t *)((t_u8 *)rate_drop + sizeof(MrvlRateDropPattern_t));
667         rate_setting_tlv->header.type  = wlan_cpu_to_le16(TLV_TYPE_TX_RATE_CFG);
668         rate_setting_tlv->header.len   = wlan_cpu_to_le16(sizeof(rate_setting_tlv->rate_setting));
669         rate_setting_tlv->rate_setting = wlan_cpu_to_le16(ds_rate->param.rate_cfg.rate_setting);
670         PRINTM(MCMND, "he rate setting = %d\n", rate_setting_tlv->rate_setting);
671         cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_TX_RATE_CFG) + sizeof(MrvlRateScope_t) +
672                                      sizeof(MrvlRateDropPattern_t) + sizeof(MrvlIETypes_rate_setting_t));
673     }
674 
675     LEAVE();
676     return MLAN_STATUS_SUCCESS;
677 }
678 
679 /**
680  *  @brief This function handles the command response of tx_rate_cfg
681  *
682  *  @param pmpriv       A pointer to mlan_private structure
683  *  @param resp         A pointer to HostCmd_DS_COMMAND
684  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
685  *
686  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
687  */
wlan_ret_tx_rate_cfg(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * resp,IN void * pioctl)688 mlan_status wlan_ret_tx_rate_cfg(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *resp, IN void *pioctl)
689 {
690     mlan_adapter *pmadapter           = pmpriv->adapter;
691     wifi_ds_rate *ds_rate             = MNULL;
692     HostCmd_DS_TX_RATE_CFG *prate_cfg = MNULL;
693     MrvlRateScope_t *prate_scope;
694     MrvlIEtypesHeader_t *head = MNULL;
695     t_u16 tlv;
696     t_u16 tlv_buf_len = 0;
697     t_u8 *tlv_buf;
698     t_u32 i;
699     t_s32 index;
700     mlan_status ret                              = MLAN_STATUS_SUCCESS;
701     MrvlIETypes_rate_setting_t *rate_setting_tlv = MNULL;
702     t_u16 rate_setting                           = 0xffff;
703 
704     ENTER();
705 
706     if (resp == MNULL)
707     {
708         LEAVE();
709         return MLAN_STATUS_FAILURE;
710     }
711     prate_cfg = (HostCmd_DS_TX_RATE_CFG *)&(resp->params.tx_rate_cfg);
712 
713     tlv_buf = (t_u8 *)((t_u8 *)prate_cfg) + sizeof(HostCmd_DS_TX_RATE_CFG);
714     if (tlv_buf != NULL)
715     {
716         tlv_buf_len = resp->size - (sizeof(HostCmd_DS_TX_RATE_CFG) + S_DS_GEN);
717         tlv_buf_len = wlan_le16_to_cpu(tlv_buf_len);
718     }
719 
720     while (tlv_buf_len > 0U)
721     {
722         // coverity[overrun-local:SUPPRESS]
723         tlv = (t_u16)(*tlv_buf);
724         tlv = tlv | (*(tlv_buf + 1) << 8);
725 
726         switch (tlv)
727         {
728             case TLV_TYPE_RATE_SCOPE:
729                 prate_scope             = (MrvlRateScope_t *)(void *)tlv_buf;
730                 pmpriv->bitmap_rates[0] = wlan_le16_to_cpu(prate_scope->hr_dsss_rate_bitmap);
731                 pmpriv->bitmap_rates[1] = wlan_le16_to_cpu(prate_scope->ofdm_rate_bitmap);
732                 for (i = 0; i < sizeof(prate_scope->ht_mcs_rate_bitmap) / sizeof(t_u16); i++)
733                 {
734                     pmpriv->bitmap_rates[2U + i] = wlan_le16_to_cpu(prate_scope->ht_mcs_rate_bitmap[i]);
735                 }
736 #if CONFIG_11AC
737                 for (i = 0; i < NELEMENTS(prate_scope->vht_mcs_rate_bitmap); i++)
738                 {
739                     pmpriv->bitmap_rates[2 + sizeof(prate_scope->ht_mcs_rate_bitmap) / sizeof(t_u16) + i] =
740                         wlan_le16_to_cpu(prate_scope->vht_mcs_rate_bitmap[i]);
741                 }
742 
743 #endif
744 #if CONFIG_11AX
745                 if (IS_FW_SUPPORT_11AX(pmadapter))
746                 {
747                     for (i = 0; i < NELEMENTS(prate_scope->he_mcs_rate_bitmap); i++)
748                     {
749                         pmpriv->bitmap_rates[2 + sizeof(prate_scope->ht_mcs_rate_bitmap) / sizeof(t_u16) +
750                                              sizeof(prate_scope->vht_mcs_rate_bitmap) / sizeof(t_u16) + i] =
751                             wlan_le16_to_cpu(prate_scope->he_mcs_rate_bitmap[i]);
752                     }
753                 }
754 #endif
755                 break;
756             case TLV_TYPE_TX_RATE_CFG:
757                 rate_setting_tlv = (MrvlIETypes_rate_setting_t *)tlv_buf;
758                 rate_setting     = rate_setting_tlv->rate_setting;
759                 break;
760                 /* Add RATE_DROP tlv here */
761             default:
762                 PRINTM(MINFO, "Unexpected TLV for rate cfg \n");
763                 break;
764         }
765 
766         head      = (MrvlIEtypesHeader_t *)(void *)tlv_buf;
767         head->len = wlan_le16_to_cpu(head->len);
768         tlv_buf += head->len + sizeof(MrvlIEtypesHeader_t);
769         tlv_buf_len -= (head->len + sizeof(MrvlIEtypesHeader_t));
770     }
771 
772     pmpriv->is_data_rate_auto = wlan_is_rate_auto(pmpriv);
773 
774     if (pmpriv->is_data_rate_auto != 0U)
775     {
776         pmpriv->data_rate = 0;
777         PRINTM(MINFO, "Rate is Auto\r\n");
778     }
779 
780     if (pioctl != NULL)
781     {
782         ds_rate = (wifi_ds_rate *)pioctl;
783         if (ds_rate == MNULL)
784         {
785             PRINTM(MERROR, "Request buffer not found!\n");
786             LEAVE();
787             return MLAN_STATUS_FAILURE;
788         }
789         if (pmpriv->is_data_rate_auto != 0U)
790         {
791             // ds_rate->param.rate_cfg.is_rate_auto = MTRUE;
792             ds_rate->param.rate_cfg.rate_format = MLAN_RATE_FORMAT_AUTO;
793         }
794         else
795         {
796             /* check the LG rate */
797             index = wlan_get_rate_index(pmadapter, &pmpriv->bitmap_rates[0], 4);
798             if (index != -1)
799             {
800                 if ((index >= MLAN_RATE_BITMAP_OFDM0) && (index <= MLAN_RATE_BITMAP_OFDM7))
801                 {
802                     index -= (MLAN_RATE_BITMAP_OFDM0 - MLAN_RATE_INDEX_OFDM0);
803                 }
804 
805                 ds_rate->param.rate_cfg.rate_format = MLAN_RATE_FORMAT_LG;
806                 ds_rate->param.rate_cfg.rate        = (t_u32)index;
807             }
808             /* check the HT rate */
809             index = wlan_get_rate_index(pmadapter, &pmpriv->bitmap_rates[2], 16);
810             if (index != -1)
811             {
812                 ds_rate->param.rate_cfg.rate_format = MLAN_RATE_FORMAT_HT;
813                 ds_rate->param.rate_cfg.rate        = (t_u32)index;
814             }
815 
816 #if CONFIG_11AC
817             /* check the VHT rate */
818             index = wlan_get_rate_index(pmadapter, &pmpriv->bitmap_rates[10], 16);
819 
820             if (index != -1)
821             {
822                 ds_rate->param.rate_cfg.rate_format = MLAN_RATE_FORMAT_VHT;
823                 ds_rate->param.rate_cfg.rate        = (t_u32)(index % 16);
824                 ds_rate->param.rate_cfg.nss         = (t_u32)(index / 16);
825                 ds_rate->param.rate_cfg.nss += MLAN_RATE_NSS1;
826             }
827 #endif
828 #if CONFIG_11AX
829             /* check the HE rate */
830             if (IS_FW_SUPPORT_11AX(pmadapter))
831             {
832                 index = wlan_get_rate_index(pmadapter, &pmpriv->bitmap_rates[18], 16);
833                 if (index != -1)
834                 {
835                     ds_rate->param.rate_cfg.rate_format = MLAN_RATE_FORMAT_HE;
836                     ds_rate->param.rate_cfg.rate        = index % 16;
837                     ds_rate->param.rate_cfg.nss         = index / 16;
838                     ds_rate->param.rate_cfg.nss += MLAN_RATE_NSS1;
839                 }
840             }
841 #endif
842             ds_rate->param.rate_cfg.rate_setting = rate_setting;
843             PRINTM(MINFO, "Rate index is %d\n", ds_rate->param.rate_cfg.rate);
844 
845             ds_rate->param.rate_cfg.rate_index = ds_rate->param.rate_cfg.rate;
846         }
847     }
848 
849     LEAVE();
850     return ret;
851 }
852 
853 /**
854  *  @brief This function prepares command of get_hw_spec.
855  *
856  *  @param pmpriv       A pointer to mlan_private structure
857  *  @param pcmd         A pointer to HostCmd_DS_COMMAND structure
858  *
859  *  @return             MLAN_STATUS_SUCCESS
860  */
wlan_cmd_get_hw_spec(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * pcmd)861 mlan_status wlan_cmd_get_hw_spec(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *pcmd)
862 {
863     HostCmd_DS_GET_HW_SPEC *hw_spec = &pcmd->params.hw_spec;
864 
865     ENTER();
866 
867     pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_GET_HW_SPEC);
868     pcmd->size    = wlan_cpu_to_le16(sizeof(HostCmd_DS_GET_HW_SPEC) + S_DS_GEN);
869     (void)__memcpy(pmpriv->adapter, hw_spec->permanent_addr, pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH);
870 
871     LEAVE();
872     return MLAN_STATUS_SUCCESS;
873 }
874 
875 /**
876  *  @brief This function prepares command of HostCmd_CMD_GET_TSF
877  *
878  *  @param pmpriv       A pointer to mlan_private structure
879  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
880  *  @param cmd_action   The action: GET
881  *  @return             MLAN_STATUS_SUCCESS
882  */
wlan_cmd_get_tsf(pmlan_private pmpriv,IN HostCmd_DS_COMMAND * cmd,IN t_u16 cmd_action)883 mlan_status wlan_cmd_get_tsf(pmlan_private pmpriv, IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action)
884 {
885     ENTER();
886 
887     cmd->command = wlan_cpu_to_le16(HostCmd_CMD_GET_TSF);
888     cmd->size    = wlan_cpu_to_le16((sizeof(HostCmd_DS_TSF)) + S_DS_GEN);
889 
890     LEAVE();
891     return MLAN_STATUS_SUCCESS;
892 }
893 
894 #if (CONFIG_WIFI_TX_PER_TRACK) || (CONFIG_TX_RX_HISTOGRAM)
895 /**
896  *  @brief This function prepares command of txrx_histogram and tx_pert, distinguish by cmd_action.
897  *
898  *  @param pmpriv       A pointer to mlan_private structure
899  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
900  *  @param cmd_action   The action: GET or SET
901  *  @param pdata_buf    A pointer to data buffer
902  *
903  *  @return             MLAN_STATUS_SUCCESS
904  */
wlan_cmd_txrx_pkt_stats(pmlan_private pmpriv,IN HostCmd_DS_COMMAND * cmd,IN t_u16 cmd_action,IN t_void * pdata_buf)905 mlan_status wlan_cmd_txrx_pkt_stats(pmlan_private pmpriv,
906                                     IN HostCmd_DS_COMMAND *cmd,
907                                     IN t_u16 cmd_action,
908                                     IN t_void *pdata_buf)
909 {
910 #if CONFIG_WIFI_TX_PER_TRACK
911     if (cmd_action == HostCmd_ACT_SET_TX_PER_TRACKING)
912     {
913         wlan_cmd_tx_pert(pmpriv, cmd, cmd_action, pdata_buf);
914     }
915 #endif
916 #if CONFIG_TX_RX_HISTOGRAM
917     if (cmd_action != HostCmd_ACT_SET_TX_PER_TRACKING)
918     {
919         wlan_cmd_txrx_histogram(pmpriv, cmd, pdata_buf);
920     }
921 #endif
922     return MLAN_STATUS_SUCCESS;
923 }
924 #endif
925 
926 #if CONFIG_WIFI_TX_PER_TRACK
927 /**
928  *  @brief This function prepares command of tx_pert.
929  *
930  *  @param pmpriv       A pointer to mlan_private structure
931  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
932  *  @param cmd_action   The action: GET or SET
933  *  @param pdata_buf    A pointer to data buffer
934  *
935  *  @return             MLAN_STATUS_SUCCESS
936  */
wlan_cmd_tx_pert(pmlan_private pmpriv,IN HostCmd_DS_COMMAND * cmd,IN t_u16 cmd_action,IN t_void * pdata_buf)937 mlan_status wlan_cmd_tx_pert(pmlan_private pmpriv,
938                              IN HostCmd_DS_COMMAND *cmd,
939                              IN t_u16 cmd_action,
940                              IN t_void *pdata_buf)
941 {
942     HostCmd_DS_TX_RX_PKT_STATS *pkt_stats = &cmd->params.pkt_stats;
943     MrvlTxPerTrackInfo_t *tx_pert         = NULL;
944     tx_pert_info *cfg                     = (tx_pert_info *)pdata_buf;
945 
946     ENTER();
947     cmd->command      = wlan_cpu_to_le16(HostCmd_CMD_TX_RX_PKT_STATS);
948     pkt_stats->action = wlan_cpu_to_le16(cmd_action);
949     pkt_stats->enable = cfg->tx_pert_check;
950     if (cmd_action == HostCmd_ACT_SET_TX_PER_TRACKING)
951     {
952         tx_pert = (MrvlTxPerTrackInfo_t *)((t_u8 *)pkt_stats + sizeof(HostCmd_DS_TX_RX_PKT_STATS));
953         // coverity[overrun-local:SUPPRESS]
954         tx_pert->type                 = wlan_cpu_to_le16(TLV_TYPE_TX_PER_TRACK);
955         tx_pert->length               = wlan_cpu_to_le16(sizeof(MrvlTxPerTrackInfo_t) - sizeof(MrvlIEtypesHeader_t));
956         tx_pert->tx_stat_check_period = cfg->tx_pert_check_peroid;
957         tx_pert->tx_stat_check_ratio  = cfg->tx_pert_check_ratio;
958         tx_pert->tx_stat_check_num    = wlan_cpu_to_le16(cfg->tx_pert_check_num);
959     }
960     cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_TX_RX_PKT_STATS) + sizeof(MrvlTxPerTrackInfo_t));
961 
962     LEAVE();
963     return MLAN_STATUS_SUCCESS;
964 }
965 #endif
966 
967 #if CONFIG_TX_RX_HISTOGRAM
968 /**
969  *  @brief This function prepares command of txrx_histogram.
970  *
971  *  @param pmpriv       A pointer to mlan_private structure
972  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
973  *  @param cmd_action   The action: GET or SET
974  *  @param pdata_buf    A pointer to data buffer
975  *
976  *  @return             MLAN_STATUS_SUCCESS
977  */
wlan_cmd_txrx_histogram(pmlan_private pmpriv,IN HostCmd_DS_COMMAND * cmd,IN t_void * pdata_buf)978 mlan_status wlan_cmd_txrx_histogram(pmlan_private pmpriv, IN HostCmd_DS_COMMAND *cmd, IN t_void *pdata_buf)
979 {
980     HostCmd_DS_TX_RX_HISTOGRAM *histogram = &cmd->params.histogram;
981     txrx_histogram_info *cfg              = (txrx_histogram_info *)pdata_buf;
982 
983     ENTER();
984     cmd->command      = wlan_cpu_to_le16(HostCmd_CMD_TX_RX_PKT_STATS);
985     histogram->action = cfg->action;
986     histogram->enable = cfg->enable;
987     cmd->size         = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_TX_RX_HISTOGRAM));
988 
989     LEAVE();
990     return MLAN_STATUS_SUCCESS;
991 }
992 #endif
993 
994 /** *  @brief This function gets the no 5G status
995  *
996  *  @param pmpriv       A pointer to mlan_private structure
997  *  @param resp         A pointer to HostCmd_DS_COMMAND
998  *
999  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1000  */
wlan_get_no_5G_status(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp)1001 static mlan_status wlan_get_no_5G_status(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp)
1002 {
1003     mlan_adapter *pmadapter = pmpriv->adapter;
1004     t_u16 left_len;
1005     t_u16 tlv_type                        = 0;
1006     t_u16 tlv_len                         = 0;
1007     MrvlIEtypesHeader_t *tlv              = MNULL;
1008     MrvlIEtypes_fw_cap_info_t *fw_cap_tlv = MNULL;
1009 
1010     left_len = resp->size - sizeof(HostCmd_DS_GET_HW_SPEC) - S_DS_GEN;
1011     tlv      = (MrvlIEtypesHeader_t *)((t_u8 *)resp + S_DS_GEN + sizeof(HostCmd_DS_GET_HW_SPEC));
1012     while (left_len > sizeof(MrvlIEtypesHeader_t))
1013     {
1014         tlv_type = wlan_le16_to_cpu(tlv->type);
1015         tlv_len  = wlan_le16_to_cpu(tlv->len);
1016         if (tlv_type == TLV_TYPE_FW_CAP_INFO)
1017         {
1018             fw_cap_tlv            = (MrvlIEtypes_fw_cap_info_t *)tlv;
1019             pmadapter->fw_cap_ext = wlan_le32_to_cpu(fw_cap_tlv->fw_cap_ext);
1020             break;
1021         }
1022         left_len -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
1023         tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len + sizeof(MrvlIEtypesHeader_t));
1024     }
1025 
1026     return MLAN_STATUS_SUCCESS;
1027 }
1028 
1029 /**
1030  *  @brief This function handles the command response of get_hw_spec
1031  *
1032  *  @param pmpriv       A pointer to mlan_private structure
1033  *  @param resp         A pointer to HostCmd_DS_COMMAND
1034  *  @param pioctl_buf   A pointer to command buffer
1035  *
1036  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1037  */
wlan_ret_get_hw_spec(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * resp,IN t_void * pioctl_buf)1038 mlan_status wlan_ret_get_hw_spec(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *resp, IN t_void *pioctl_buf)
1039 {
1040     HostCmd_DS_GET_HW_SPEC *hw_spec = &resp->params.hw_spec;
1041     mlan_adapter *pmadapter         = pmpriv->adapter;
1042     mlan_status ret                 = MLAN_STATUS_SUCCESS;
1043     t_u32 i;
1044     pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
1045     t_u16 left_len;
1046     t_u16 tlv_type           = 0;
1047     t_u16 tlv_len            = 0;
1048     MrvlIEtypesHeader_t *tlv = MNULL;
1049 #if CONFIG_11AX
1050     MrvlIEtypes_Extension_t *ext_tlv = MNULL;
1051 #ifdef RW610
1052     int he_tlv_idx = 0;
1053 #endif
1054 #endif
1055     MrvlIEtypes_fw_cap_info_t *fw_cap_tlv = MNULL;
1056     ENTER();
1057 
1058     pmadapter->fw_cap_info = wlan_le32_to_cpu(hw_spec->fw_cap_info);
1059     /* Get no 5G status to check whether need to disable 5G */
1060     wlan_get_no_5G_status(pmpriv, resp);
1061 #ifdef STA_SUPPORT
1062     if ((IS_SUPPORT_MULTI_BANDS(pmadapter)) != 0U)
1063     {
1064         pmadapter->fw_bands = (t_u16)GET_FW_DEFAULT_BANDS(pmadapter);
1065         if (ISSUPP_NO5G(pmadapter->fw_cap_ext))
1066         {
1067             pmadapter->fw_bands &= ~(BAND_A | BAND_AN | BAND_AAC);
1068         }
1069 #if !CONFIG_5GHz_SUPPORT
1070         /* fixme: Re-check if this is the correct way to disable 5 GHz. */
1071         pmadapter->fw_bands &= ~(BAND_A | BAND_AN | BAND_AAC);
1072 #endif /* CONFIG_5GHz_SUPPORT */
1073     }
1074     else
1075     {
1076         pmadapter->fw_bands = BAND_B;
1077     }
1078 
1079     pmadapter->config_bands = pmadapter->fw_bands;
1080     for (i = 0; i < pmadapter->priv_num; i++)
1081     {
1082         if (pmadapter->priv[i] != MNULL)
1083         {
1084             pmadapter->priv[i]->config_bands = pmadapter->fw_bands;
1085         }
1086     }
1087 
1088     if ((pmadapter->fw_bands & BAND_A) != 0U)
1089     {
1090         if ((pmadapter->fw_bands & BAND_GN) != 0U)
1091         {
1092             pmadapter->config_bands |= BAND_AN;
1093             for (i = 0; i < pmadapter->priv_num; i++)
1094             {
1095                 if (pmadapter->priv[i] != MNULL)
1096                 {
1097                     pmadapter->priv[i]->config_bands |= BAND_AN;
1098                 }
1099             }
1100 
1101             pmadapter->fw_bands |= BAND_AN;
1102         }
1103         if ((pmadapter->fw_bands & BAND_AAC) != 0U)
1104         {
1105             pmadapter->config_bands |= BAND_AAC;
1106             for (i = 0; i < pmadapter->priv_num; i++)
1107             {
1108                 if (pmadapter->priv[i] != MNULL)
1109                 {
1110                     pmadapter->priv[i]->config_bands |= BAND_AAC;
1111                 }
1112             }
1113         }
1114         if ((pmadapter->fw_bands & BAND_AN) != 0U)
1115         {
1116             pmadapter->adhoc_start_band  = (BAND_A | BAND_AN);
1117             pmadapter->adhoc_11n_enabled = MTRUE;
1118         }
1119         else
1120         {
1121             pmadapter->adhoc_start_band = BAND_A;
1122         }
1123         pmpriv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A;
1124     }
1125     else if ((pmadapter->fw_bands & BAND_GN) != 0U)
1126     {
1127         pmadapter->adhoc_start_band  = (BAND_G | BAND_B | BAND_GN);
1128         pmpriv->adhoc_channel        = DEFAULT_AD_HOC_CHANNEL;
1129         pmadapter->adhoc_11n_enabled = MTRUE;
1130     }
1131     else if ((pmadapter->fw_bands & BAND_G) != 0U)
1132     {
1133         pmadapter->adhoc_start_band = (BAND_G | BAND_B);
1134         pmpriv->adhoc_channel       = DEFAULT_AD_HOC_CHANNEL;
1135     }
1136     else if ((pmadapter->fw_bands & BAND_B) != 0U)
1137     {
1138         pmadapter->adhoc_start_band = BAND_B;
1139         pmpriv->adhoc_channel       = DEFAULT_AD_HOC_CHANNEL;
1140     }
1141     else
1142     {
1143         /* Do nothing */
1144     }
1145 #endif /* STA_SUPPORT */
1146 
1147     pmadapter->fw_release_number = hw_spec->fw_release_number;
1148     pmadapter->number_of_antenna = wlan_le16_to_cpu(hw_spec->number_of_antenna);
1149 
1150     PRINTM(MINFO, "GET_HW_SPEC: fw_release_number- 0x%X\n", wlan_le32_to_cpu(pmadapter->fw_release_number));
1151     PRINTM(MINFO, "GET_HW_SPEC: Permanent addr- %2x:%2x:%2x:%2x:%2x:%2x\n", hw_spec->permanent_addr[0],
1152            hw_spec->permanent_addr[1], hw_spec->permanent_addr[2], hw_spec->permanent_addr[3],
1153            hw_spec->permanent_addr[4], hw_spec->permanent_addr[5]);
1154     PRINTM(MINFO, "GET_HW_SPEC: hw_if_version=0x%X  version=0x%X\n", wlan_le16_to_cpu(hw_spec->hw_if_version),
1155            wlan_le16_to_cpu(hw_spec->version));
1156 
1157     if (pmpriv->curr_addr[0] == 0xffU)
1158     {
1159         (void)__memmove(pmadapter, pmpriv->curr_addr, hw_spec->permanent_addr, MLAN_MAC_ADDR_LENGTH);
1160 #if CONFIG_P2P
1161         (void)__memmove(pmadapter, pmpriv->curr_p2p_addr, hw_spec->permanent_addr, MLAN_MAC_ADDR_LENGTH);
1162         pmpriv->curr_p2p_addr[0] |= (0x01 << 1);
1163 #endif
1164     }
1165 
1166     pmadapter->hw_dot_11n_dev_cap     = wlan_le32_to_cpu(hw_spec->dot_11n_dev_cap);
1167     pmadapter->usr_dot_11n_dev_cap_bg = pmadapter->hw_dot_11n_dev_cap & DEFAULT_11N_CAP_MASK_BG;
1168     pmadapter->usr_dot_11n_dev_cap_a  = pmadapter->hw_dot_11n_dev_cap & DEFAULT_11N_CAP_MASK_A;
1169     pmadapter->usr_dev_mcs_support = pmadapter->hw_dev_mcs_support = hw_spec->dev_mcs_support;
1170     pmadapter->hw_mpdu_density                                     = GET_MPDU_DENSITY(hw_spec->hw_dev_cap);
1171     PRINTM(MCMND, "GET_HW_SPEC: hw_mpdu_density=%d dev_mcs_support=0x%x\n", pmadapter->hw_mpdu_density,
1172            hw_spec->dev_mcs_support);
1173 
1174     wlan_show_dot11ndevcap(pmadapter, pmadapter->hw_dot_11n_dev_cap);
1175     wlan_show_devmcssupport(pmadapter, pmadapter->hw_dev_mcs_support);
1176 
1177     pmadapter->hw_dot_11ac_dev_cap     = wlan_le32_to_cpu(hw_spec->Dot11acDevCap);
1178     pmadapter->hw_dot_11ac_mcs_support = wlan_le32_to_cpu(hw_spec->Dot11acMcsSupport);
1179 
1180     pmadapter->usr_dot_11ac_mcs_support = pmadapter->hw_dot_11ac_mcs_support;
1181 
1182     pmadapter->usr_dot_11ac_dev_cap_bg = pmadapter->hw_dot_11ac_dev_cap & ~DEFALUT_11AC_CAP_BEAMFORMING_RESET_MASK;
1183 #if CONFIG_5GHz_SUPPORT
1184     pmadapter->usr_dot_11ac_dev_cap_a = pmadapter->hw_dot_11ac_dev_cap & ~DEFALUT_11AC_CAP_BEAMFORMING_RESET_MASK;
1185 #endif
1186     pmadapter->usr_dot_11ac_bw = BW_FOLLOW_VHTCAP;
1187 
1188     pmadapter->mp_end_port = wlan_le16_to_cpu(hw_spec->mp_end_port);
1189 
1190 #ifndef RW610
1191     for (i = 1; i <= (unsigned)(MAX_PORT - pmadapter->mp_end_port); i++)
1192     {
1193         pmadapter->mp_data_port_mask &= ~(1U << (MAX_PORT - i));
1194     }
1195 #endif
1196 
1197 #ifdef OTP_CHANINFO
1198     if ((pmadapter->otp_region != MNULL) && (pmadapter->otp_region->force_reg == 0U))
1199     {
1200 #endif
1201 
1202         /* Set the region code to WWSM by default */
1203         pmadapter->region_code = hw_spec->region_code;
1204         for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++)
1205         {
1206             /* Use the region code to search for the index */
1207             if (pmadapter->region_code == region_code_index[i])
1208             {
1209                 break;
1210             }
1211         }
1212         /* If it's unidentified region code, use the default */
1213         if (i >= MRVDRV_MAX_REGION_CODE)
1214         {
1215             pmadapter->region_code = MRVDRV_DEFAULT_REGION_CODE;
1216             PRINTM(MWARN, "unidentified region code, use the default (0x%02x)\n", MRVDRV_DEFAULT_REGION_CODE);
1217         }
1218 
1219         /* Back up hw_region_code in case it is overwritten by the supplicant process*/
1220         pmadapter->hw_region_code = pmadapter->region_code;
1221 
1222         /* Synchronize CFP code with region code */
1223         pmadapter->cfp_code_bg = (t_u8)pmadapter->region_code;
1224         pmadapter->cfp_code_a  = (t_u8)pmadapter->region_code;
1225         /* Set country code */
1226         (void)__memcpy(pmadapter, pmadapter->country_code,
1227                 wlan_11d_code_2_region(pmadapter, (t_u8)pmadapter->region_code), COUNTRY_CODE_LEN - 1);
1228 #ifdef OTP_CHANINFO
1229     }
1230 #endif
1231     if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code, pmadapter->fw_bands) != MLAN_STATUS_SUCCESS)
1232     {
1233         if (pioctl_req != MNULL)
1234         {
1235             pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
1236         }
1237         ret = MLAN_STATUS_FAILURE;
1238         goto done;
1239     }
1240 #ifdef STA_SUPPORT
1241     if (wlan_11d_set_universaltable(pmpriv, pmadapter->fw_bands) != MLAN_STATUS_SUCCESS)
1242     {
1243         if (pioctl_req != MNULL)
1244         {
1245             pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
1246         }
1247         ret = MLAN_STATUS_FAILURE;
1248         goto done;
1249     }
1250 #endif /* STA_SUPPORT */
1251     left_len = resp->size - (t_u16)sizeof(HostCmd_DS_GET_HW_SPEC) - (t_u16)S_DS_GEN;
1252     tlv      = (MrvlIEtypesHeader_t *)(void *)((t_u8 *)(&resp->params) + sizeof(HostCmd_DS_GET_HW_SPEC));
1253     while (left_len > sizeof(MrvlIEtypesHeader_t))
1254     {
1255         tlv_type = wlan_le16_to_cpu(tlv->type);
1256         tlv_len  = wlan_le16_to_cpu(tlv->len);
1257         switch (tlv_type)
1258         {
1259 #if CONFIG_11AX
1260             case TLV_TYPE_EXTENSION_ID:
1261                 ext_tlv = (MrvlIEtypes_Extension_t *)tlv;
1262                 if (ext_tlv->ext_id == HE_CAPABILITY)
1263                 {
1264                     ext_tlv->type = tlv_type;
1265                     ext_tlv->len  = tlv_len;
1266 #ifndef RW610
1267                     wlan_update_11ax_cap(pmadapter, (MrvlIEtypes_Extension_t *)ext_tlv);
1268 #else
1269                     if ((he_tlv_idx == AX_2G_TLV_INDEX) || !ISSUPP_NO5G(pmadapter->fw_cap_ext))
1270                     {
1271                         wlan_update_11ax_cap(pmadapter, (MrvlIEtypes_Extension_t *)ext_tlv, he_tlv_idx);
1272                         he_tlv_idx++;
1273                     }
1274 #endif
1275                 }
1276                 break;
1277 #endif
1278             case TLV_TYPE_FW_CAP_INFO:
1279                 fw_cap_tlv             = (MrvlIEtypes_fw_cap_info_t *)(void *)tlv;
1280                 pmadapter->fw_cap_info = wlan_le32_to_cpu(fw_cap_tlv->fw_cap_info);
1281                 pmadapter->fw_cap_ext  = wlan_le32_to_cpu(fw_cap_tlv->fw_cap_ext);
1282                 PRINTM(MCMND, "fw_cap_info=0x%x fw_cap_ext=0x%x\n", pmadapter->fw_cap_info, pmadapter->fw_cap_ext);
1283                 break;
1284             default:
1285                 PRINTM(MINFO, "Unexpected TLV hw spec \n");
1286                 break;
1287         }
1288         left_len -= (t_u16)(sizeof(MrvlIEtypesHeader_t) + tlv_len);
1289         tlv = (MrvlIEtypesHeader_t *)(void *)((t_u8 *)tlv + tlv_len + sizeof(MrvlIEtypesHeader_t));
1290     }
1291 
1292 #if defined(SD8987) || defined(SD9177)
1293     pmadapter->cmd_tx_data = IS_FW_SUPPORT_CMD_TX_DATA(pmadapter) ? 0x01 : 0x00;
1294 #endif
1295 
1296 done:
1297     LEAVE();
1298     return ret;
1299 }
1300 
1301 /**
1302  *  @brief This function prepares command of remain_on_channel.
1303  *
1304  *  @param pmpriv       A pointer to mlan_private structure
1305  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
1306  *  @param cmd_action   The action: GET or SET
1307  *  @param pdata_buf    A pointer to data buffer
1308  *
1309  *  @return             MLAN_STATUS_SUCCESS
1310  */
wlan_cmd_remain_on_channel(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * cmd,IN t_u16 cmd_action,IN t_void * pdata_buf)1311 mlan_status wlan_cmd_remain_on_channel(IN pmlan_private pmpriv,
1312                                        IN HostCmd_DS_COMMAND *cmd,
1313                                        IN t_u16 cmd_action,
1314                                        IN t_void *pdata_buf)
1315 {
1316     HostCmd_DS_REMAIN_ON_CHANNEL *remain_channel = &cmd->params.remain_on_chan;
1317     mlan_ds_remain_chan *cfg                     = (mlan_ds_remain_chan *)pdata_buf;
1318     ENTER();
1319     cmd->size              = wlan_cpu_to_le16((sizeof(HostCmd_DS_REMAIN_ON_CHANNEL)) + S_DS_GEN);
1320     cmd->command           = wlan_cpu_to_le16(HostCmd_CMD_802_11_REMAIN_ON_CHANNEL);
1321     remain_channel->action = cmd_action;
1322     if (cmd_action == HostCmd_ACT_GEN_SET)
1323     {
1324         if (cfg->remove != 0U)
1325         {
1326             remain_channel->action = HostCmd_ACT_GEN_REMOVE;
1327         }
1328         else
1329         {
1330             remain_channel->status        = 0;
1331             remain_channel->reserved      = 0;
1332             remain_channel->bandcfg       = cfg->bandcfg;
1333             remain_channel->channel       = cfg->channel;
1334             remain_channel->remain_period = wlan_cpu_to_le32(cfg->remain_period);
1335         }
1336     }
1337     remain_channel->action = wlan_cpu_to_le16(remain_channel->action);
1338 
1339     LEAVE();
1340     return MLAN_STATUS_SUCCESS;
1341 }
1342 
1343 #ifdef OTP_CHANINFO
1344 /**
1345  *  @brief This function handles the command response of chan_region_cfg
1346  *
1347  *  @param pmpriv       A pointer to mlan_private structure
1348  *  @param resp         A pointer to HostCmd_DS_COMMAND
1349  *  @param pioctl_buf   A pointer to command buffer
1350  *
1351  *  @return             MLAN_STATUS_SUCCESS
1352  */
wlan_ret_chan_region_cfg(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * resp,IN mlan_ioctl_req * pioctl_buf)1353 mlan_status wlan_ret_chan_region_cfg(IN pmlan_private pmpriv,
1354                                      IN HostCmd_DS_COMMAND *resp,
1355                                      IN mlan_ioctl_req *pioctl_buf)
1356 {
1357     mlan_adapter *pmadapter = pmpriv->adapter;
1358     t_u16 action;
1359     HostCmd_DS_CHAN_REGION_CFG *reg = MNULL;
1360     t_u8 *tlv_buf                   = MNULL;
1361     t_u16 tlv_buf_left;
1362     mlan_ds_misc_cfg *misc_cfg     = MNULL;
1363     mlan_ds_misc_chnrgpwr_cfg *cfg = MNULL;
1364     mlan_status ret                = MLAN_STATUS_SUCCESS;
1365 
1366     ENTER();
1367 
1368     reg = (HostCmd_DS_CHAN_REGION_CFG *)(void *)&resp->params;
1369     if (reg == MNULL)
1370     {
1371         ret = MLAN_STATUS_FAILURE;
1372         goto done;
1373     }
1374 
1375     action = wlan_le16_to_cpu(reg->action);
1376     if (action != HostCmd_ACT_GEN_GET)
1377     {
1378         ret = MLAN_STATUS_FAILURE;
1379         goto done;
1380     }
1381 
1382     tlv_buf      = (t_u8 *)reg + sizeof(*reg);
1383     tlv_buf_left = (t_u16)(wlan_le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*reg));
1384 
1385     /* Add FW cfp tables and region info */
1386     wlan_add_fw_cfp_tables(pmpriv, tlv_buf, tlv_buf_left);
1387 
1388     if (pioctl_buf == MNULL)
1389     {
1390         goto done;
1391     }
1392 
1393     if (pioctl_buf->pbuf == MNULL)
1394     {
1395         ret = MLAN_STATUS_FAILURE;
1396         goto done;
1397     }
1398 
1399     misc_cfg = (mlan_ds_misc_cfg *)(void *)pioctl_buf->pbuf;
1400 
1401     if (misc_cfg->sub_command == MLAN_OID_MISC_GET_REGIONPWR_CFG)
1402     {
1403         cfg         = (mlan_ds_misc_chnrgpwr_cfg *)&(misc_cfg->param.rgchnpwr_cfg);
1404         cfg->length = wlan_le16_to_cpu(resp->size);
1405         (void)__memcpy(pmpriv->adapter, cfg->chnrgpwr_buf, (t_u8 *)resp, cfg->length);
1406     }
1407     else
1408     {
1409         (void)__memset(pmpriv->adapter, &misc_cfg->param.custom_reg_domain, 0, sizeof(mlan_ds_custom_reg_domain));
1410         if (pmadapter->otp_region != MNULL)
1411         {
1412             (void)__memcpy(pmpriv->adapter, &misc_cfg->param.custom_reg_domain.region, pmadapter->otp_region,
1413                            sizeof(otp_region_info_t));
1414         }
1415         if (pmadapter->cfp_otp_bg != MNULL)
1416         {
1417             misc_cfg->param.custom_reg_domain.num_bg_chan = pmadapter->tx_power_table_bg_rows;
1418             (void)__memcpy(pmpriv->adapter, (t_u8 *)misc_cfg->param.custom_reg_domain.cfp_tbl,
1419                            (t_u8 *)pmadapter->cfp_otp_bg,
1420                            pmadapter->tx_power_table_bg_rows * sizeof(chan_freq_power_t));
1421         }
1422 #if CONFIG_5GHz_SUPPORT
1423         if (pmadapter->cfp_otp_a != MNULL)
1424         {
1425             misc_cfg->param.custom_reg_domain.num_a_chan = pmadapter->tx_power_table_a_rows;
1426             (void)__memcpy(pmpriv->adapter,
1427                            (t_u8 *)misc_cfg->param.custom_reg_domain.cfp_tbl +
1428                                pmadapter->tx_power_table_bg_rows * sizeof(chan_freq_power_t),
1429                            (t_u8 *)pmadapter->cfp_otp_a, pmadapter->tx_power_table_a_rows * sizeof(chan_freq_power_t));
1430         }
1431 #endif
1432     }
1433 done:
1434     LEAVE();
1435     return ret;
1436 }
1437 #endif
1438 
1439 #if CONFIG_COMPRESS_TX_PWTBL
wlan_cmd_region_power_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)1440 mlan_status wlan_cmd_region_power_cfg(pmlan_private pmpriv,
1441                                       HostCmd_DS_COMMAND *cmd,
1442                                       t_u16 cmd_action,
1443                                       t_void *pdata_buf)
1444 {
1445     t_u16 buf_len;
1446 
1447     ENTER();
1448 
1449     cmd->command = wlan_cpu_to_le16(HostCmd_CMD_REGION_POWER_CFG);
1450     if (cmd_action == HostCmd_ACT_GEN_SET)
1451     {
1452         buf_len = cmd->size - S_DS_GEN;
1453         __memcpy(pmpriv->adapter, (t_u8 *)cmd + S_DS_GEN, pdata_buf, buf_len);
1454     }
1455 
1456     LEAVE();
1457     return MLAN_STATUS_SUCCESS;
1458 }
1459 #endif
1460 
1461 #if CONFIG_RX_ABORT_CFG
1462 /**
1463  *  @brief This function sends rx abort cfg command to firmware.
1464  *
1465  *  @param pmpriv       A pointer to mlan_private structure
1466  *  @param cmd          Hostcmd ID
1467  *  @param cmd_action   Command action
1468  *  @param pdata_buf    A void pointer to information buffer
1469  *  @return             N/A
1470  */
wlan_cmd_rx_abort_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)1471 mlan_status wlan_cmd_rx_abort_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_void *pdata_buf)
1472 {
1473     HostCmd_DS_RX_ABORT_CFG *rx_abort_cfg = &cmd->params.rx_abort_cfg;
1474     (void)memset(cmd, 0x00, sizeof(HostCmd_DS_COMMAND));
1475     rx_abort_cfg_t *cfg = (rx_abort_cfg_t *)pdata_buf;
1476 
1477     ENTER();
1478 
1479     cmd->command         = wlan_cpu_to_le16(HostCmd_CMD_RX_ABORT_CFG);
1480     cmd->size            = wlan_cpu_to_le16(sizeof(HostCmd_DS_RX_ABORT_CFG) + S_DS_GEN);
1481     rx_abort_cfg->action = wlan_cpu_to_le16(cmd_action);
1482 
1483     if (rx_abort_cfg->action == HostCmd_ACT_GEN_SET)
1484     {
1485         rx_abort_cfg->enable         = cfg->enable;
1486         rx_abort_cfg->rssi_threshold = (t_s8)cfg->rssi_threshold;
1487     }
1488 
1489     LEAVE();
1490     return MLAN_STATUS_SUCCESS;
1491 }
1492 #endif
1493 
1494 #if CONFIG_RX_ABORT_CFG_EXT
1495 /**
1496  *  @brief This function sends rx abort cfg ext command to firmware.
1497  *
1498  *  @param pmpriv       A pointer to mlan_private structure
1499  *  @param cmd          Hostcmd ID
1500  *  @param cmd_action   Command action
1501  *  @param pdata_buf    A void pointer to information buffer
1502  *  @return             N/A
1503  */
wlan_cmd_rx_abort_cfg_ext(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)1504 mlan_status wlan_cmd_rx_abort_cfg_ext(pmlan_private pmpriv,
1505                                       HostCmd_DS_COMMAND *cmd,
1506                                       t_u16 cmd_action,
1507                                       t_void *pdata_buf)
1508 {
1509     HostCmd_DS_RX_ABORT_CFG_EXT *rx_abort_cfg_ext = (HostCmd_DS_RX_ABORT_CFG_EXT *)&cmd->params.rx_abort_cfg_ext;
1510     rx_abort_cfg_ext_t *cfg                       = (rx_abort_cfg_ext_t *)pdata_buf;
1511 
1512     ENTER();
1513 
1514     cmd->command             = wlan_cpu_to_le16(HostCmd_CMD_RX_ABORT_CFG_EXT);
1515     cmd->size                = wlan_cpu_to_le16(sizeof(HostCmd_DS_RX_ABORT_CFG_EXT) + S_DS_GEN);
1516     rx_abort_cfg_ext->action = wlan_cpu_to_le16(cmd_action);
1517 
1518     if (rx_abort_cfg_ext->action == HostCmd_ACT_GEN_SET)
1519     {
1520         rx_abort_cfg_ext->enable               = cfg->enable;
1521         rx_abort_cfg_ext->rssi_margin          = (t_s8)cfg->rssi_margin;
1522         rx_abort_cfg_ext->ceil_rssi_threshold  = (t_s8)cfg->ceil_rssi_threshold;
1523         rx_abort_cfg_ext->floor_rssi_threshold = (t_s8)cfg->floor_rssi_threshold;
1524     }
1525 
1526     LEAVE();
1527     return MLAN_STATUS_SUCCESS;
1528 }
1529 #endif
1530 
1531 #if CONFIG_CCK_DESENSE_CFG
1532 /**
1533  *  @brief This function sends cck desense cfg command to firmware.
1534  *
1535  *  @param pmpriv       A pointer to mlan_private structure
1536  *  @param cmd          Hostcmd ID
1537  *  @param cmd_action   Command action
1538  *  @param pdata_buf    A void pointer to information buffer
1539  *  @return             N/A
1540  */
wlan_cmd_cck_desense_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)1541 mlan_status wlan_cmd_cck_desense_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_void *pdata_buf)
1542 {
1543     HostCmd_DS_CCK_DESENSE_CFG *cfg_cmd = (HostCmd_DS_CCK_DESENSE_CFG *)&cmd->params.cck_desense_cfg;
1544     cck_desense_cfg_t *cfg              = (cck_desense_cfg_t *)pdata_buf;
1545 
1546     ENTER();
1547 
1548     cmd->command    = wlan_cpu_to_le16(HostCmd_CMD_CCK_DESENSE_CFG);
1549     cmd->size       = wlan_cpu_to_le16(sizeof(HostCmd_DS_CCK_DESENSE_CFG) + S_DS_GEN);
1550     cfg_cmd->action = wlan_cpu_to_le16(cmd_action);
1551 
1552     if (cmd_action == HostCmd_ACT_GEN_SET)
1553     {
1554         cfg_cmd->mode              = wlan_cpu_to_le16(cfg->mode);
1555         cfg_cmd->margin            = (t_s8)cfg->margin;
1556         cfg_cmd->ceil_thresh       = (t_s8)cfg->ceil_thresh;
1557         cfg_cmd->num_on_intervals  = (t_u8)cfg->num_on_intervals;
1558         cfg_cmd->num_off_intervals = (t_u8)cfg->num_off_intervals;
1559     }
1560 
1561     LEAVE();
1562     return MLAN_STATUS_SUCCESS;
1563 }
1564 #endif
1565 
1566 #if CONFIG_WIFI_CLOCKSYNC
1567 /**
1568  *  @brief This function prepares command of GPIO TSF LATCH.
1569  *
1570  *  @param pmpriv       A pointer to mlan_private structure
1571  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
1572  *  @param cmd_action   The action: GET or SET
1573  *  @param pioctl_buf   A pointer to mlan_ioctl_req buf
1574  *  @param pdata_buf    A pointer to data buffer
1575  *
1576  *  @return             MLAN_STATUS_SUCCESS
1577  */
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)1578 mlan_status wlan_cmd_gpio_tsf_latch(
1579     pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, mlan_ioctl_req *pioctl_buf, t_void *pdata_buf)
1580 {
1581     HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG *gpio_tsf_config = &cmd->params.gpio_tsf_latch;
1582     mlan_ds_gpio_tsf_latch *cfg                             = (mlan_ds_gpio_tsf_latch *)pdata_buf;
1583     mlan_ds_misc_cfg *misc_cfg                              = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
1584 
1585     mlan_ds_tsf_info *tsf_info                               = (mlan_ds_tsf_info *)pdata_buf;
1586     MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *gpio_tsf_latch_config = MNULL;
1587     MrvlIEtypes_GPIO_TSF_LATCH_REPORT *gpio_tsf_latch_report = MNULL;
1588     t_u8 *tlv                                                = MNULL;
1589     ENTER();
1590 
1591     cmd->size               = sizeof(HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG) + S_DS_GEN;
1592     cmd->command            = wlan_cpu_to_le16(HostCmd_GPIO_TSF_LATCH_PARAM_CONFIG);
1593     gpio_tsf_config->action = wlan_cpu_to_le16(cmd_action);
1594     if (cmd_action == HostCmd_ACT_GEN_SET)
1595     {
1596         tlv = (t_u8 *)gpio_tsf_config->tlv_buf;
1597         if (misc_cfg->sub_command == (t_u32)MLAN_OID_MISC_GPIO_TSF_LATCH)
1598         {
1599             gpio_tsf_latch_config              = (MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *)tlv;
1600             gpio_tsf_latch_config->header.type = wlan_cpu_to_le16(TLV_TYPE_GPIO_TSF_LATCH_CONFIG);
1601             gpio_tsf_latch_config->header.len =
1602                 wlan_cpu_to_le16(sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG) - sizeof(MrvlIEtypesHeader_t));
1603             gpio_tsf_latch_config->clock_sync_mode              = cfg->clock_sync_mode;
1604             gpio_tsf_latch_config->clock_sync_Role              = cfg->clock_sync_Role;
1605             gpio_tsf_latch_config->clock_sync_gpio_pin_number   = cfg->clock_sync_gpio_pin_number;
1606             gpio_tsf_latch_config->clock_sync_gpio_level_toggle = cfg->clock_sync_gpio_level_toggle;
1607             gpio_tsf_latch_config->clock_sync_gpio_pulse_width  = wlan_cpu_to_le16(cfg->clock_sync_gpio_pulse_width);
1608             cmd->size += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG);
1609             tlv += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG);
1610             PRINTM(
1611                 MCMND,
1612                 "Set GPIO TSF latch config: \r\nMode=%d Role=%d, \r\nGPIO Pin Number=%d, \r\nGPIO level/toggle=%d GPIO "
1613                 "pulse "
1614                 "width=%d\n\r",
1615                 cfg->clock_sync_mode, cfg->clock_sync_Role, cfg->clock_sync_gpio_pin_number,
1616                 cfg->clock_sync_gpio_level_toggle, (int)cfg->clock_sync_gpio_pulse_width);
1617         }
1618     }
1619     else if (cmd_action == HostCmd_ACT_GEN_GET)
1620     {
1621         tlv = (t_u8 *)gpio_tsf_config->tlv_buf;
1622         if (misc_cfg->sub_command == (t_u32)MLAN_OID_MISC_GPIO_TSF_LATCH)
1623         {
1624             gpio_tsf_latch_config              = (MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *)tlv;
1625             gpio_tsf_latch_config->header.type = wlan_cpu_to_le16(TLV_TYPE_GPIO_TSF_LATCH_CONFIG);
1626             gpio_tsf_latch_config->header.len =
1627                 wlan_cpu_to_le16(sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG) - sizeof(MrvlIEtypesHeader_t));
1628             cmd->size += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG);
1629             tlv += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG);
1630         }
1631 
1632         if (misc_cfg->sub_command == (t_u32)MLAN_OID_MISC_GET_TSF_INFO)
1633         {
1634             gpio_tsf_latch_report = (MrvlIEtypes_GPIO_TSF_LATCH_REPORT *)tlv;
1635             (void)memset(gpio_tsf_latch_report, 0, sizeof(MrvlIEtypes_GPIO_TSF_LATCH_REPORT));
1636             gpio_tsf_latch_report->header.type = wlan_cpu_to_le16(TLV_TYPE_GPIO_TSF_LATCH_REPORT);
1637             gpio_tsf_latch_report->header.len =
1638                 wlan_cpu_to_le16(sizeof(MrvlIEtypes_GPIO_TSF_LATCH_REPORT) - sizeof(MrvlIEtypesHeader_t));
1639             gpio_tsf_latch_report->tsf_format = wlan_cpu_to_le16(tsf_info->tsf_format);
1640             PRINTM(MCMND, "Get TSF info: format=%d\n\r", tsf_info->tsf_format);
1641             cmd->size += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_REPORT);
1642         }
1643     }
1644     cmd->size = wlan_cpu_to_le16(cmd->size);
1645     LEAVE();
1646     return MLAN_STATUS_SUCCESS;
1647 }
1648 
1649 /**
1650  *  @brief This function handles the command response of GPIO TSF Latch
1651  *
1652  *  @param pmpriv       A pointer to mlan_private structure
1653  *  @param resp         A pointer to HostCmd_DS_COMMAND
1654  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
1655  *
1656  *  @return             MLAN_STATUS_SUCCESS
1657  */
wlan_ret_gpio_tsf_latch(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)1658 mlan_status wlan_ret_gpio_tsf_latch(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
1659 {
1660     HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG *gpio_tsf_config  = &resp->params.gpio_tsf_latch;
1661     mlan_ds_misc_cfg *cfg                                    = MNULL;
1662     MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *gpio_tsf_latch_config = MNULL;
1663     MrvlIEtypes_GPIO_TSF_LATCH_REPORT *gpio_tsf_latch_report = MNULL;
1664     MrvlIEtypesHeader_t *tlv                                 = MNULL;
1665     t_u16 tlv_buf_left                                       = 0;
1666     t_u16 tlv_type                                           = 0;
1667     t_u16 tlv_len                                            = 0;
1668 
1669     ENTER();
1670     if (wlan_le16_to_cpu(gpio_tsf_config->action) == HostCmd_ACT_GEN_GET)
1671     {
1672         if (pioctl_buf)
1673         {
1674             cfg          = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
1675             tlv          = (MrvlIEtypesHeader_t *)(gpio_tsf_config->tlv_buf);
1676             tlv_buf_left = resp->size - (sizeof(HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG) + S_DS_GEN);
1677             while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t))
1678             {
1679                 tlv_type = wlan_le16_to_cpu(tlv->type);
1680                 tlv_len  = wlan_le16_to_cpu(tlv->len);
1681                 if (tlv_buf_left < (tlv_len + sizeof(MrvlIEtypesHeader_t)))
1682                 {
1683                     PRINTM(MCMND, "Error processing gpio tsf latch config TLVs, bytes left < TLV length\n");
1684                     break;
1685                 }
1686                 switch (tlv_type)
1687                 {
1688                     case TLV_TYPE_GPIO_TSF_LATCH_CONFIG:
1689                         if (cfg->sub_command == (t_u32)MLAN_OID_MISC_GPIO_TSF_LATCH)
1690                         {
1691                             gpio_tsf_latch_config                            = (MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *)tlv;
1692                             cfg->param.gpio_tsf_latch_config.clock_sync_mode = gpio_tsf_latch_config->clock_sync_mode;
1693                             cfg->param.gpio_tsf_latch_config.clock_sync_Role = gpio_tsf_latch_config->clock_sync_Role;
1694                             cfg->param.gpio_tsf_latch_config.clock_sync_gpio_pin_number =
1695                                 gpio_tsf_latch_config->clock_sync_gpio_pin_number;
1696                             cfg->param.gpio_tsf_latch_config.clock_sync_gpio_level_toggle =
1697                                 gpio_tsf_latch_config->clock_sync_gpio_level_toggle;
1698                             cfg->param.gpio_tsf_latch_config.clock_sync_gpio_pulse_width =
1699                                 wlan_le16_to_cpu(gpio_tsf_latch_config->clock_sync_gpio_pulse_width);
1700                             PRINTM(
1701                                 MCMND,
1702                                 "Get GPIO TSF latch config: Mode=%d Role=%d, GPIO Pin Number=%d, GPIO level/toggle=%d "
1703                                 "GPIO pulse width=%d\n\r",
1704                                 cfg->param.gpio_tsf_latch_config.clock_sync_mode,
1705                                 cfg->param.gpio_tsf_latch_config.clock_sync_Role,
1706                                 cfg->param.gpio_tsf_latch_config.clock_sync_gpio_pin_number,
1707                                 cfg->param.gpio_tsf_latch_config.clock_sync_gpio_level_toggle,
1708                                 (int)cfg->param.gpio_tsf_latch_config.clock_sync_gpio_pulse_width);
1709                         }
1710                         break;
1711                     case TLV_TYPE_GPIO_TSF_LATCH_REPORT:
1712                         if (cfg->sub_command == (t_u32)MLAN_OID_MISC_GET_TSF_INFO)
1713                         {
1714                             gpio_tsf_latch_report          = (MrvlIEtypes_GPIO_TSF_LATCH_REPORT *)tlv;
1715                             cfg->param.tsf_info.tsf_format = wlan_le16_to_cpu(gpio_tsf_latch_report->tsf_format);
1716                             cfg->param.tsf_info.tsf_info   = wlan_le16_to_cpu(gpio_tsf_latch_report->tsf_info);
1717                             cfg->param.tsf_info.tsf        = wlan_le64_to_cpu(gpio_tsf_latch_report->tsf);
1718                             cfg->param.tsf_info.tsf_offset = wlan_le16_to_cpu(gpio_tsf_latch_report->tsf_offset);
1719                             PRINTM(MCMND, "Get GPIO TSF latch report : format=%d\n info=%d tsf=%llu offset=%d\r\n",
1720                                    cfg->param.tsf_info.tsf_format, cfg->param.tsf_info.tsf_info,
1721                                    cfg->param.tsf_info.tsf, cfg->param.tsf_info.tsf_offset);
1722                         }
1723                         break;
1724                     default:
1725                         wifi_d("gpio tsf latch: Unknown tlv type");
1726                         break;
1727                 }
1728                 tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
1729                 tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len + sizeof(MrvlIEtypesHeader_t));
1730             }
1731             if (cfg->sub_command == (t_u32)MLAN_OID_MISC_GPIO_TSF_LATCH)
1732                 pioctl_buf->data_read_written = sizeof(mlan_ds_gpio_tsf_latch);
1733             else if (cfg->sub_command == (t_u32)MLAN_OID_MISC_GET_TSF_INFO)
1734                 pioctl_buf->data_read_written = sizeof(mlan_ds_tsf_info);
1735         }
1736     }
1737     LEAVE();
1738     return MLAN_STATUS_SUCCESS;
1739 }
1740 #endif /* CONFIG_WIFI_CLOCKSYNC */
1741 
1742 #if CONFIG_MULTI_CHAN
1743 /**
1744  *  @brief This function prepares the command MULTI_CHAN_CFG
1745  *
1746  *  @param pmpriv       A pointer to mlan_private structure
1747  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
1748  *  @param cmd_action   Command action: GET or SET
1749  *  @param pdata_buf    A pointer to new setting buf
1750  *
1751  *  @return             MLAN_STATUS_SUCCESS
1752  */
wlan_cmd_multi_chan_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)1753 mlan_status wlan_cmd_multi_chan_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_void *pdata_buf)
1754 {
1755     mlan_ds_multi_chan_cfg *multi_chan_cfg = (mlan_ds_multi_chan_cfg *)pdata_buf;
1756     HostCmd_DS_MULTI_CHAN_CFG *pmchan_cfg  = (HostCmd_DS_MULTI_CHAN_CFG *)&cmd->params.multi_chan_cfg;
1757 
1758     ENTER();
1759 
1760     cmd->command       = wlan_cpu_to_le16(HostCmd_CMD_MULTI_CHAN_CONFIG);
1761     pmchan_cfg->action = wlan_cpu_to_le16(cmd_action);
1762 
1763     if (cmd_action == HostCmd_ACT_GEN_SET)
1764     {
1765         pmchan_cfg->buffer_weight = multi_chan_cfg->buffer_weight;
1766         pmchan_cfg->channel_time  = wlan_cpu_to_le32(multi_chan_cfg->channel_time);
1767         PRINTM(MCMND, "Set multi-channel: buffer_weight=%d channel_time=%d\n", multi_chan_cfg->buffer_weight,
1768                multi_chan_cfg->channel_time);
1769         cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_MULTI_CHAN_CFG));
1770     }
1771     else
1772     {
1773         cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(cmd_action));
1774     }
1775 
1776     LEAVE();
1777     return MLAN_STATUS_SUCCESS;
1778 }
1779 
1780 /**
1781  *  @brief This function handles the command response of MULTI_CHAN_CFG
1782  *
1783  *  @param pmpriv       A pointer to mlan_private structure
1784  *  @param resp         A pointer to HostCmd_DS_COMMAND
1785  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
1786  *
1787  *  @return             MLAN_STATUS_SUCCESS
1788  */
wlan_ret_multi_chan_cfg(pmlan_private pmpriv,const HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)1789 mlan_status wlan_ret_multi_chan_cfg(pmlan_private pmpriv, const HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
1790 {
1791     mlan_ds_misc_cfg *pcfg                     = MNULL;
1792     const HostCmd_DS_MULTI_CHAN_CFG *presp_cfg = &resp->params.multi_chan_cfg;
1793 
1794     ENTER();
1795 
1796     if (pioctl_buf)
1797     {
1798         pcfg                                     = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
1799         pcfg->param.multi_chan_cfg.channel_time  = wlan_le32_to_cpu(presp_cfg->channel_time);
1800         pcfg->param.multi_chan_cfg.buffer_weight = presp_cfg->buffer_weight;
1801         pcfg->param.multi_chan_cfg.tlv_len = resp->size - (sizeof(HostCmd_DS_GEN) + sizeof(HostCmd_DS_MULTI_CHAN_CFG));
1802         PRINTM(MCMND, "Get multi-channel: buffer_weight=%d channel_time=%d tlv_len=%d\n",
1803                pcfg->param.multi_chan_cfg.buffer_weight, pcfg->param.multi_chan_cfg.channel_time,
1804                pcfg->param.multi_chan_cfg.tlv_len);
1805         __memcpy(pmpriv->adapter, pcfg->param.multi_chan_cfg.tlv_buf, presp_cfg->tlv_buf,
1806                  pcfg->param.multi_chan_cfg.tlv_len);
1807         pioctl_buf->buf_len = sizeof(mlan_ds_multi_chan_cfg) + pcfg->param.multi_chan_cfg.tlv_len;
1808     }
1809 
1810     LEAVE();
1811     return MLAN_STATUS_SUCCESS;
1812 }
1813 
1814 /**
1815  *  @brief This function prepares the command MULTI_CHAN_POLICY
1816  *
1817  *  @param pmpriv       A pointer to mlan_private structure
1818  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
1819  *  @param cmd_action   Command action: GET or SET
1820  *  @param pdata_buf    A pointer to new setting buf
1821  *
1822  *  @return             MLAN_STATUS_SUCCESS
1823  */
wlan_cmd_multi_chan_policy(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)1824 mlan_status wlan_cmd_multi_chan_policy(pmlan_private pmpriv,
1825                                        HostCmd_DS_COMMAND *cmd,
1826                                        t_u16 cmd_action,
1827                                        t_void *pdata_buf)
1828 {
1829     t_u16 policy                                     = 0;
1830     HostCmd_DS_MULTI_CHAN_POLICY *pmulti_chan_policy = (HostCmd_DS_MULTI_CHAN_POLICY *)&cmd->params.multi_chan_policy;
1831 
1832     ENTER();
1833 
1834     cmd->command               = wlan_cpu_to_le16(HostCmd_CMD_MULTI_CHAN_POLICY);
1835     pmulti_chan_policy->action = wlan_cpu_to_le16(cmd_action);
1836     cmd->size                  = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_MULTI_CHAN_POLICY));
1837     if (cmd_action == HostCmd_ACT_GEN_SET)
1838     {
1839         policy                     = *((t_u16 *)pdata_buf);
1840         pmulti_chan_policy->policy = wlan_cpu_to_le16(policy);
1841         PRINTM(MCMND, "Set multi-channel policy: %d\n", policy);
1842     }
1843     LEAVE();
1844     return MLAN_STATUS_SUCCESS;
1845 }
1846 
1847 /**
1848  *  @brief This function handles the command response of MULTI_CHAN_POLICY
1849  *
1850  *  @param pmpriv       A pointer to mlan_private structure
1851  *  @param resp         A pointer to HostCmd_DS_COMMAND
1852  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
1853  *
1854  *  @return             MLAN_STATUS_SUCCESS
1855  */
wlan_ret_multi_chan_policy(pmlan_private pmpriv,const HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)1856 mlan_status wlan_ret_multi_chan_policy(pmlan_private pmpriv, const HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
1857 {
1858     mlan_ds_misc_cfg *pcfg                        = MNULL;
1859     const HostCmd_DS_MULTI_CHAN_POLICY *presp_cfg = &resp->params.multi_chan_policy;
1860 
1861     ENTER();
1862 
1863     if (pioctl_buf)
1864     {
1865         pcfg                          = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
1866         pcfg->param.multi_chan_policy = wlan_le16_to_cpu(presp_cfg->policy);
1867 
1868         if (pioctl_buf->action == HostCmd_ACT_GEN_SET)
1869         {
1870             if (pcfg->param.multi_chan_policy)
1871                 pmpriv->adapter->mc_policy = MTRUE;
1872             else
1873                 pmpriv->adapter->mc_policy = MFALSE;
1874         }
1875     }
1876 
1877     LEAVE();
1878     return MLAN_STATUS_SUCCESS;
1879 }
1880 
1881 /**
1882  *  @brief This function prepares the command DRCD_CFG
1883  *
1884  *  @param pmpriv       A pointer to mlan_private structure
1885  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
1886  *  @param cmd_action   Command action: GET or SET
1887  *  @param pdata_buf    A pointer to new setting buf
1888  *
1889  *  @return             MLAN_STATUS_SUCCESS
1890  */
wlan_cmd_drcs_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)1891 mlan_status wlan_cmd_drcs_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_void *pdata_buf)
1892 {
1893     mlan_ds_drcs_cfg *drcs_cfg                      = (mlan_ds_drcs_cfg *)pdata_buf;
1894     HostCmd_DS_DRCS_CFG *pdrcs_cfg                  = (HostCmd_DS_DRCS_CFG *)&cmd->params.drcs_cfg;
1895     MrvlTypes_DrcsTimeSlice_t *channel_time_slicing = &pdrcs_cfg->time_slicing;
1896 
1897     ENTER();
1898 
1899     cmd->command      = wlan_cpu_to_le16(HostCmd_CMD_DRCS_CONFIG);
1900     pdrcs_cfg->action = wlan_cpu_to_le16(cmd_action);
1901 
1902     if (cmd_action == HostCmd_ACT_GEN_SET)
1903     {
1904         channel_time_slicing->header.type = wlan_cpu_to_le16(MRVL_DRCS_TIME_SLICE_TLV_ID);
1905         channel_time_slicing->header.len =
1906             wlan_cpu_to_le16(sizeof(MrvlTypes_DrcsTimeSlice_t) - sizeof(MrvlIEtypesHeader_t));
1907         channel_time_slicing->chan_idx   = wlan_cpu_to_le16(drcs_cfg->chan_idx);
1908         channel_time_slicing->chantime   = drcs_cfg->chantime;
1909         channel_time_slicing->switchtime = drcs_cfg->switchtime;
1910         channel_time_slicing->undozetime = drcs_cfg->undozetime;
1911         channel_time_slicing->mode       = drcs_cfg->mode;
1912         PRINTM(MCMND, "Set multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
1913                channel_time_slicing->chan_idx, channel_time_slicing->chantime, channel_time_slicing->switchtime,
1914                channel_time_slicing->undozetime, channel_time_slicing->mode);
1915         cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_DRCS_CFG));
1916         /* Set two channels different parameters */
1917         if (0x3 != channel_time_slicing->chan_idx)
1918         {
1919             drcs_cfg++;
1920             channel_time_slicing              = pdrcs_cfg->drcs_buf;
1921             channel_time_slicing->header.type = wlan_cpu_to_le16(MRVL_DRCS_TIME_SLICE_TLV_ID);
1922             channel_time_slicing->header.len =
1923                 wlan_cpu_to_le16(sizeof(MrvlTypes_DrcsTimeSlice_t) - sizeof(MrvlIEtypesHeader_t));
1924             channel_time_slicing->chan_idx   = wlan_cpu_to_le16(drcs_cfg->chan_idx);
1925             channel_time_slicing->chantime   = drcs_cfg->chantime;
1926             channel_time_slicing->switchtime = drcs_cfg->switchtime;
1927             channel_time_slicing->undozetime = drcs_cfg->undozetime;
1928             channel_time_slicing->mode       = drcs_cfg->mode;
1929             PRINTM(MCMND, "Set multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
1930                    channel_time_slicing->chan_idx, channel_time_slicing->chantime, channel_time_slicing->switchtime,
1931                    channel_time_slicing->undozetime, channel_time_slicing->mode);
1932             cmd->size += wlan_cpu_to_le16(sizeof(MrvlTypes_DrcsTimeSlice_t));
1933         }
1934     }
1935     else
1936     {
1937         cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(cmd_action));
1938     }
1939 
1940     LEAVE();
1941     return MLAN_STATUS_SUCCESS;
1942 }
1943 
1944 /**
1945  *  @brief This function handles the command response of DRCS_CFG
1946  *
1947  *  @param pmpriv       A pointer to mlan_private structure
1948  *  @param resp         A pointer to HostCmd_DS_COMMAND
1949  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
1950  *
1951  *  @return             MLAN_STATUS_SUCCESS
1952  */
wlan_ret_drcs_cfg(pmlan_private pmpriv,const HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)1953 mlan_status wlan_ret_drcs_cfg(pmlan_private pmpriv, const HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
1954 {
1955     mlan_ds_misc_cfg *pcfg                                 = MNULL;
1956     const HostCmd_DS_DRCS_CFG *presp_cfg                   = &resp->params.drcs_cfg;
1957     const MrvlTypes_DrcsTimeSlice_t *channel_time_slicing  = &presp_cfg->time_slicing;
1958     const MrvlTypes_DrcsTimeSlice_t *channel_time_slicing1 = MNULL;
1959     mlan_ds_drcs_cfg *drcs_cfg1                            = MNULL;
1960 
1961     ENTER();
1962 
1963     if (pioctl_buf)
1964     {
1965         pcfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
1966         if (wlan_le16_to_cpu(channel_time_slicing->header.type) != MRVL_DRCS_TIME_SLICE_TLV_ID ||
1967             wlan_le16_to_cpu(channel_time_slicing->header.len) !=
1968                 sizeof(MrvlTypes_DrcsTimeSlice_t) - sizeof(MrvlIEtypesHeader_t))
1969         {
1970             LEAVE();
1971             return MLAN_STATUS_FAILURE;
1972         }
1973         pcfg->param.drcs_cfg[0].chan_idx   = wlan_le16_to_cpu(channel_time_slicing->chan_idx);
1974         pcfg->param.drcs_cfg[0].chantime   = channel_time_slicing->chantime;
1975         pcfg->param.drcs_cfg[0].switchtime = channel_time_slicing->switchtime;
1976         pcfg->param.drcs_cfg[0].undozetime = channel_time_slicing->undozetime;
1977         pcfg->param.drcs_cfg[0].mode       = channel_time_slicing->mode;
1978         PRINTM(MCMND, "multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
1979                pcfg->param.drcs_cfg[0].chan_idx, channel_time_slicing->chantime, channel_time_slicing->switchtime,
1980                channel_time_slicing->undozetime, channel_time_slicing->mode);
1981         pioctl_buf->buf_len = sizeof(mlan_ds_drcs_cfg);
1982         /*Channel for chan_idx 1 and 2 have different parameters*/
1983         if (0x3 != pcfg->param.drcs_cfg[0].chan_idx)
1984         {
1985             channel_time_slicing1 = presp_cfg->drcs_buf;
1986             if (wlan_le16_to_cpu(channel_time_slicing1->header.type) != MRVL_DRCS_TIME_SLICE_TLV_ID ||
1987                 wlan_le16_to_cpu(channel_time_slicing1->header.len) !=
1988                     sizeof(MrvlTypes_DrcsTimeSlice_t) - sizeof(MrvlIEtypesHeader_t))
1989             {
1990                 LEAVE();
1991                 return MLAN_STATUS_FAILURE;
1992             }
1993             drcs_cfg1             = (mlan_ds_drcs_cfg *)&pcfg->param.drcs_cfg[1];
1994             drcs_cfg1->chan_idx   = wlan_le16_to_cpu(channel_time_slicing1->chan_idx);
1995             drcs_cfg1->chantime   = channel_time_slicing1->chantime;
1996             drcs_cfg1->switchtime = channel_time_slicing1->switchtime;
1997             drcs_cfg1->undozetime = channel_time_slicing1->undozetime;
1998             drcs_cfg1->mode       = channel_time_slicing1->mode;
1999             PRINTM(MCMND, "multi-channel: chan_idx=%d chantime=%d switchtime=%d undozetime=%d mode=%d\n",
2000                    drcs_cfg1->chan_idx, drcs_cfg1->chantime, drcs_cfg1->switchtime, drcs_cfg1->undozetime,
2001                    drcs_cfg1->mode);
2002             pioctl_buf->buf_len += sizeof(mlan_ds_drcs_cfg);
2003         }
2004     }
2005 
2006     LEAVE();
2007     return MLAN_STATUS_SUCCESS;
2008 }
2009 #endif
2010 
2011 #if CONFIG_1AS
2012 /**
2013  *  @brief This function prepares command of sending host_clock_cfg.
2014  *
2015  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
2016  *  @param cmd_action   the action: GET or SET
2017  *  @param pdata_buf    A pointer to data buffer
2018  *  @return             MLAN_STATUS_SUCCESS
2019  */
wlan_cmd_host_clock_cfg(HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)2020 mlan_status wlan_cmd_host_clock_cfg(HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_void *pdata_buf)
2021 {
2022     mlan_ds_host_clock *hostclk           = (mlan_ds_host_clock *)pdata_buf;
2023     HostCmd_DS_HOST_CLOCK_CFG *host_clock = (HostCmd_DS_HOST_CLOCK_CFG *)&cmd->params.host_clock_cfg;
2024 
2025     ENTER();
2026 
2027     cmd->command = wlan_cpu_to_le16(HostCmd_CMD_HOST_CLOCK_CFG);
2028     cmd->size    = wlan_cpu_to_le16(sizeof(HostCmd_DS_HOST_CLOCK_CFG) + S_DS_GEN);
2029 
2030     host_clock->action = wlan_cpu_to_le16(cmd_action);
2031     host_clock->time   = wlan_cpu_to_le64(hostclk->time);
2032 
2033     LEAVE();
2034     return MLAN_STATUS_SUCCESS;
2035 }
2036 
2037 /**
2038  *  @brief This function handles the command response of host_clock_cfg
2039  *
2040  *  @param pmpriv       A pointer to mlan_private structure
2041  *  @param resp         A pointer to HostCmd_DS_COMMAND
2042  *  @param pioctl_buf   A pointer to command buffer
2043  *
2044  *  @return             MLAN_STATUS_SUCCESS
2045  */
wlan_ret_host_clock_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)2046 mlan_status wlan_ret_host_clock_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
2047 {
2048     mlan_ds_misc_cfg *cfg                 = MNULL;
2049     mlan_ds_host_clock *hostclk           = MNULL;
2050     HostCmd_DS_HOST_CLOCK_CFG *host_clock = (HostCmd_DS_HOST_CLOCK_CFG *)&resp->params.host_clock_cfg;
2051     // mlan_adapter *pmadapter = pmpriv->adapter;
2052     // pmlan_callbacks pcb = &pmadapter->callbacks;
2053     // t_u64 cmd_rtt;
2054 
2055     ENTER();
2056 
2057     if (pioctl_buf)
2058     {
2059         cfg     = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
2060         hostclk = &cfg->param.host_clock;
2061 
2062         hostclk->time = wlan_le64_to_cpu(host_clock->time);
2063         // cmd_rtt = pcb->moal_do_div(pmadapter->d2 - pmadapter->d1, 2);
2064         // PRINTM(MINFO, "HW time: %ld, Host Time: %ld, RTT: %ld\n",
2065         // host_clock->hw_time, hostclk->time, cmd_rtt);
2066         hostclk->fw_time = wlan_le64_to_cpu(host_clock->hw_time) /*- cmd_rtt*/; // Not adjusting
2067                                                                                 // cmd_rtt gave
2068                                                                                 // better results
2069                                                                                 // with 802.1as
2070         hostclk->host_bbu_clk_delta = hostclk->time - hostclk->fw_time;
2071         // pmadapter->host_bbu_clk_delta = hostclk->host_bbu_clk_delta;
2072 
2073         /* Indicate ioctl complete */
2074         // pioctl_buf->data_read_written =
2075         // sizeof(mlan_ds_misc_cfg) + MLAN_SUB_COMMAND_SIZE;
2076     }
2077 
2078     LEAVE();
2079     return MLAN_STATUS_SUCCESS;
2080 }
2081 #endif
2082 
2083 #if CONFIG_FW_VDLL
2084 
2085 extern const unsigned char wlan_fw_bin[];
2086 extern unsigned int wlan_fw_bin_len;
2087 
2088 /**
2089  *  @brief This function download the vdll block.
2090  *
2091  *  @param pmadapter    A pointer to mlan_adapter structure
2092  *  @param block            A pointer to VDLL block
2093  *  @param block_len      The VDLL block length
2094  *
2095  *  @return             MLAN_STATUS_SUCCESS
2096  */
wlan_download_vdll_block(mlan_adapter * pmadapter,t_u8 * block,t_u16 block_len)2097 mlan_status wlan_download_vdll_block(mlan_adapter *pmadapter, t_u8 *block, t_u16 block_len)
2098 {
2099     mlan_status status   = MLAN_STATUS_FAILURE;
2100     int ret              = -WM_FAIL;
2101     pvdll_dnld_ctrl ctrl = &pmadapter->vdll_ctrl;
2102     t_u16 msg_len        = block_len + sizeof(HostCmd_DS_GEN);
2103     HostCmd_DS_GEN *cmd_hdr;
2104 
2105     ENTER();
2106 
2107     if ((msg_len > WIFI_FW_CMDBUF_SIZE) || (ctrl == NULL))
2108     {
2109         wevt_d("VDLL block mem greater than cmd buf/vdll struct not inited");
2110         goto done;
2111     }
2112 
2113     cmd_hdr = (HostCmd_DS_GEN *)ctrl->cmd_buf;
2114 
2115     cmd_hdr->command = wlan_cpu_to_le16(HostCmd_CMD_VDLL);
2116     cmd_hdr->seq_num = wlan_cpu_to_le16(0xFF00);
2117     cmd_hdr->size    = wlan_cpu_to_le16(msg_len);
2118 
2119     (void)__memcpy(pmadapter, ctrl->cmd_buf + sizeof(HostCmd_DS_GEN), block, block_len);
2120 
2121 #if CONFIG_FW_VDLL_DEBUG
2122     wevt_d("DNLD_VDLL : block_len=%d", block_len);
2123 #endif
2124 
2125     ret = wifi_wait_for_vdllcmdresp(NULL);
2126 
2127     if (ret == -WM_FAIL)
2128     {
2129         wevt_d("DNLD_VDLL: Host to Card Failed");
2130     }
2131     else
2132     {
2133         status = MLAN_STATUS_SUCCESS;
2134     }
2135 
2136 done:
2137     LEAVE();
2138     return status;
2139 }
2140 
2141 /**
2142  *  @brief The function Get the VDLL image from moal
2143  *
2144  *  @param pmadapter    A pointer to mlan_adapter structure
2145  *  @param offset          offset
2146  *
2147  *  @return             MLAN_STATUS_SUCCESS
2148  *
2149  */
wlan_get_vdll_image(pmlan_adapter pmadapter,t_u32 vdll_len)2150 static mlan_status wlan_get_vdll_image(pmlan_adapter pmadapter, t_u32 vdll_len)
2151 {
2152     /*Since f/w is already in .h in RT so we will use the offsets directly*/
2153 
2154     vdll_dnld_ctrl *ctrl = &pmadapter->vdll_ctrl;
2155     ENTER();
2156     if (ctrl != NULL)
2157     {
2158         ctrl->vdll_mem = (t_u8 *)(pmadapter->fw_start_addr + (wlan_fw_bin_len - vdll_len));
2159         ctrl->vdll_len = vdll_len;
2160         ctrl->cmd_buf  = (t_u8 *)wifi_get_vdllcommand_buffer();
2161     }
2162     LEAVE();
2163     return MLAN_STATUS_SUCCESS;
2164 }
2165 
2166 /**
2167  *  @brief This function handle the multi_chan info event
2168  *
2169  *  @param pmpriv       A pointer to mlan_private structure
2170  *  @param pevent       A pointer to event buffer
2171  *
2172  *  @return             MLAN_STATUS_SUCCESS
2173  */
wlan_process_vdll_event(pmlan_private pmpriv,t_u8 * pevent)2174 mlan_status wlan_process_vdll_event(pmlan_private pmpriv, t_u8 *pevent)
2175 {
2176     mlan_status status      = MLAN_STATUS_SUCCESS;
2177     vdll_ind *ind           = MNULL;
2178     t_u32 offset            = 0;
2179     t_u16 block_len         = 0;
2180     mlan_adapter *pmadapter = pmpriv->adapter;
2181     vdll_dnld_ctrl *ctrl    = &pmadapter->vdll_ctrl;
2182 
2183     ENTER();
2184     ind = (vdll_ind *)(pevent + sizeof(mlan_event_id));
2185 
2186     switch (wlan_le16_to_cpu(ind->type))
2187     {
2188         case VDLL_IND_TYPE_REQ:
2189             offset    = wlan_le32_to_cpu(ind->offset);
2190             block_len = wlan_le16_to_cpu(ind->block_len);
2191 #if CONFIG_FW_VDLL_DEBUG
2192             wevt_d("VDLL_IND: type=%d offset = 0x%x, len = %d, vdll_len=0x%x", wlan_le16_to_cpu(ind->type), offset,
2193                    block_len, ctrl->vdll_len);
2194 #endif
2195             if (offset <= ctrl->vdll_len)
2196             {
2197                 block_len = MIN(block_len, ctrl->vdll_len - offset);
2198                 status    = wlan_download_vdll_block(pmadapter, ctrl->vdll_mem + offset, block_len);
2199                 if (status)
2200                 {
2201                     wevt_d("Fail to download VDLL block");
2202                 }
2203                 if (pmadapter->vdll_in_progress == MFALSE)
2204                 {
2205                     (void)pmadapter->callbacks.moal_start_timer(pmadapter->pmoal_handle, pmadapter->vdll_timer, MFALSE,
2206                                                                 2000);
2207                     pmadapter->vdll_in_progress = MTRUE;
2208                 }
2209                 else
2210                 {
2211                     (void)pmadapter->callbacks.moal_reset_timer(pmadapter->pmoal_handle, pmadapter->vdll_timer);
2212                 }
2213             }
2214             else
2215             {
2216                 wevt_d("Invalid VDLL req: offset=0x%x, len=%d, vdll_len=0x%x", offset, block_len, ctrl->vdll_len);
2217             }
2218             break;
2219 
2220         case VDLL_IND_TYPE_OFFSET:
2221             offset = wlan_le32_to_cpu(ind->offset);
2222 #if CONFIG_FW_VDLL_DEBUG
2223             wevt_d("VDLL_IND (OFFSET): vdll_len=0x%x", offset);
2224 #endif
2225             wlan_get_vdll_image(pmadapter, offset);
2226             break;
2227         case VDLL_IND_TYPE_ERR_SIG:
2228             wevt_d("VDLL_IND (SIG ERR).");
2229             break;
2230         case VDLL_IND_TYPE_ERR_ID:
2231             wevt_d("VDLL_IND (ID ERR).");
2232             break;
2233 #if defined(SD9177)
2234         case VDLL_IND_TYPE_ERR_SECURE:
2235             wevt_d("VDLL_IND (SECURE ERR).");
2236             break;
2237         case VDLL_IND_TYPE_COMPLETE:
2238             wevt_d("VDLL_IND (ID COMPLETE).");
2239             break;
2240 #elif defined(SD8978) || defined(SD8987) || defined(SD8997)
2241         case VDLL_IND_TYPE_INTF_RESET:
2242             wevt_d("VDLLV2_IND (INTF RESET).");
2243             sd_wifi_reset_ports();
2244             break;
2245 #endif
2246         default:
2247             wevt_d("unknown vdll ind type=%d", ind->type);
2248             break;
2249     }
2250     LEAVE();
2251     return status;
2252 }
2253 #endif /* CONFIG_FW_VDLL */
2254 
2255 #if (CONFIG_WIFI_IND_RESET) && (CONFIG_WIFI_IND_DNLD)
2256 /**
2257  *  @brief This function prepares command of independent reset.
2258  *
2259  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
2260  *  @param cmd_action   the action: GET or SET
2261  *  @param pdata_buf    A pointer to data buffer
2262  *  @return             MLAN_STATUS_SUCCESS
2263  */
wlan_cmd_ind_rst_cfg(HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)2264 mlan_status wlan_cmd_ind_rst_cfg(HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_void *pdata_buf)
2265 {
2266     mlan_ds_ind_rst_cfg *pdata_ind_rst            = (mlan_ds_ind_rst_cfg *)pdata_buf;
2267     HostCmd_DS_INDEPENDENT_RESET_CFG *ind_rst_cfg = (HostCmd_DS_INDEPENDENT_RESET_CFG *)&cmd->params.ind_rst_cfg;
2268 
2269     ENTER();
2270 
2271     cmd->command = wlan_cpu_to_le16(HostCmd_CMD_INDEPENDENT_RESET_CFG);
2272     cmd->size    = wlan_cpu_to_le16(sizeof(HostCmd_DS_INDEPENDENT_RESET_CFG) + S_DS_GEN);
2273 
2274     ind_rst_cfg->action = wlan_cpu_to_le16(cmd_action);
2275     if (cmd_action == HostCmd_ACT_GEN_SET)
2276     {
2277         ind_rst_cfg->ir_mode  = pdata_ind_rst->ir_mode;
2278         ind_rst_cfg->gpio_pin = pdata_ind_rst->gpio_pin;
2279     }
2280 
2281     LEAVE();
2282     return MLAN_STATUS_SUCCESS;
2283 }
2284 /**
2285  *  @brief This function handles the command response of independent reset
2286  *
2287  *  @param pmpriv       A pointer to mlan_private structure
2288  *  @param resp         A pointer to HostCmd_DS_COMMAND
2289  *  @param pioctl_buf   A pointer to command buffer
2290  *
2291  *  @return             MLAN_STATUS_SUCCESS
2292  */
wlan_ret_ind_rst_cfg(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)2293 mlan_status wlan_ret_ind_rst_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
2294 {
2295     mlan_ds_misc_cfg *misc                              = MNULL;
2296     const HostCmd_DS_INDEPENDENT_RESET_CFG *ind_rst_cfg = (HostCmd_DS_INDEPENDENT_RESET_CFG *)&resp->params.ind_rst_cfg;
2297 
2298     ENTER();
2299 
2300     if (pioctl_buf)
2301     {
2302         misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
2303 
2304         if (wlan_le16_to_cpu(ind_rst_cfg->action) == HostCmd_ACT_GEN_GET)
2305         {
2306             misc->param.ind_rst_cfg.ir_mode  = ind_rst_cfg->ir_mode;
2307             misc->param.ind_rst_cfg.gpio_pin = ind_rst_cfg->gpio_pin;
2308         }
2309     }
2310 
2311     LEAVE();
2312     return MLAN_STATUS_SUCCESS;
2313 }
2314 #endif
2315 
2316 /**
2317  *  @brief This function sends boot sleep configure command to firmware.
2318  *
2319  *  @param pmpriv         A pointer to mlan_private structure
2320  *  @param cmd          Hostcmd ID
2321  *  @param cmd_action   Command action
2322  *  @param pdata_buf    A void pointer to information buffer
2323  *  @return             MLAN_STATUS_SUCCESS/ MLAN_STATUS_FAILURE
2324  */
wlan_cmd_boot_sleep(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)2325 mlan_status wlan_cmd_boot_sleep(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_void *pdata_buf)
2326 {
2327     HostCmd_DS_BOOT_SLEEP *boot_sleep = MNULL;
2328     t_u16 enable                      = *(t_u16 *)pdata_buf;
2329 
2330     ENTER();
2331 
2332     cmd->command       = wlan_cpu_to_le16(HostCmd_CMD_BOOT_SLEEP);
2333     boot_sleep         = &cmd->params.boot_sleep;
2334     boot_sleep->action = wlan_cpu_to_le16(cmd_action);
2335     boot_sleep->enable = wlan_cpu_to_le16(enable);
2336 
2337     cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_BOOT_SLEEP));
2338 
2339     LEAVE();
2340     return MLAN_STATUS_SUCCESS;
2341 }
2342 
2343 /**
2344  *  @brief This function handles the command response of boot sleep cfg
2345  *
2346  *  @param pmpriv       A pointer to mlan_private structure
2347  *  @param resp         A pointer to HostCmd_DS_COMMAND
2348  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
2349  *
2350  *  @return        MLAN_STATUS_SUCCESS
2351  */
wlan_ret_boot_sleep(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)2352 mlan_status wlan_ret_boot_sleep(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
2353 {
2354     HostCmd_DS_BOOT_SLEEP *boot_sleep = &resp->params.boot_sleep;
2355     mlan_ds_misc_cfg *cfg             = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
2356 
2357     ENTER();
2358 
2359     cfg->param.boot_sleep = wlan_le16_to_cpu(boot_sleep->enable);
2360     PRINTM(MCMND, "boot sleep cfg status %u", cfg->param.boot_sleep);
2361     LEAVE();
2362     return MLAN_STATUS_SUCCESS;
2363 }
2364 
2365 /**
2366  *  @brief This function prepares command of hs wakeup reason.
2367  *
2368  *  @param pmpriv       A pointer to mlan_private structure
2369  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
2370  *  @param pdata_buf    A pointer to data buffer
2371  *  @return             MLAN_STATUS_SUCCESS
2372  */
wlan_cmd_hs_wakeup_reason(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_void * pdata_buf)2373 mlan_status wlan_cmd_hs_wakeup_reason(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd, t_void *pdata_buf)
2374 {
2375     ENTER();
2376 
2377     cmd->command = wlan_cpu_to_le16(HostCmd_CMD_HS_WAKEUP_REASON);
2378     cmd->size    = wlan_cpu_to_le16((sizeof(HostCmd_DS_HS_WAKEUP_REASON)) + S_DS_GEN);
2379 
2380     LEAVE();
2381     return MLAN_STATUS_SUCCESS;
2382 }
2383 
2384 /**
2385  *  @brief This function handles the command response of
2386  *          hs wakeup reason
2387  *
2388  *  @param pmpriv       A pointer to mlan_private structure
2389  *  @param resp         A pointer to HostCmd_DS_COMMAND
2390  *  @param pioctl_buf   A pointer to command buffer
2391  *
2392  *  @return             MLAN_STATUS_SUCCESS
2393  */
wlan_ret_hs_wakeup_reason(pmlan_private pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)2394 mlan_status wlan_ret_hs_wakeup_reason(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf)
2395 {
2396     HostCmd_DS_HS_WAKEUP_REASON *hs_wakeup_reason = (HostCmd_DS_HS_WAKEUP_REASON *)&resp->params.hs_wakeup_reason;
2397     mlan_ds_pm_cfg *pm_cfg                        = MNULL;
2398 
2399     ENTER();
2400 
2401     pm_cfg                                       = (mlan_ds_pm_cfg *)pioctl_buf->pbuf;
2402     pm_cfg->param.wakeup_reason.hs_wakeup_reason = wlan_le16_to_cpu(hs_wakeup_reason->wakeup_reason);
2403     pioctl_buf->data_read_written                = sizeof(mlan_ds_pm_cfg);
2404 
2405     LEAVE();
2406     return MLAN_STATUS_SUCCESS;
2407 }
2408 
2409 /**
2410  *  @brief This function prepares command of TX_FRAME
2411  *
2412  *  @param pmpriv      A pointer to mlan_private structure
2413  *  @param cmd          A pointer to HostCmd_DS_COMMAND structure
2414  *  @param cmd_action   the action: GET or SET
2415  *  @param pdata_buf    A pointer to data buffer
2416  *  @return         MLAN_STATUS_SUCCESS
2417  */
wlan_cmd_tx_frame(pmlan_private pmpriv,HostCmd_DS_COMMAND * cmd,t_u16 cmd_action,t_void * pdata_buf)2418 mlan_status wlan_cmd_tx_frame(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, t_void *pdata_buf)
2419 {
2420     t_u16 cmd_size                          = 0;
2421     HostCmd_DS_80211_TX_FRAME *tx_frame_cmd = &cmd->params.tx_frame;
2422     mlan_ds_misc_tx_frame *tx_frame         = (mlan_ds_misc_tx_frame *)pdata_buf;
2423     TxPD *plocal_tx_pd                      = (TxPD *)tx_frame_cmd->buffer;
2424     t_u32 pkt_type                          = 0;
2425     t_u32 tx_control                        = 0;
2426     t_u8 *pdata                             = tx_frame->tx_buf;
2427     t_u16 data_len                          = tx_frame->data_len;
2428 
2429     ENTER();
2430     cmd->command         = wlan_cpu_to_le16(HostCmd_CMD_802_11_TX_FRAME);
2431     cmd_size             = sizeof(HostCmd_DS_80211_TX_FRAME) + S_DS_GEN;
2432     tx_frame_cmd->action = 0;
2433     tx_frame_cmd->status = 0;
2434     (void)__memcpy(pmpriv->adapter, &tx_frame_cmd->band_config, (t_u8 *)&tx_frame->bandcfg, sizeof(t_u8));
2435     tx_frame_cmd->channel = tx_frame->channel;
2436 
2437     if (tx_frame->buf_type == MLAN_BUF_TYPE_RAW_DATA)
2438     {
2439         (void)__memcpy(pmpriv->adapter, &pkt_type, tx_frame->tx_buf, sizeof(pkt_type));
2440         (void)__memcpy(pmpriv->adapter, &tx_control, tx_frame->tx_buf + sizeof(pkt_type), sizeof(tx_control));
2441         data_len -= sizeof(pkt_type) + sizeof(tx_control);
2442         pdata += sizeof(pkt_type) + sizeof(tx_control);
2443     }
2444     (void)__memcpy(pmpriv->adapter, tx_frame_cmd->buffer + sizeof(TxPD), pdata, data_len);
2445 
2446     (void)__memset(pmpriv->adapter, plocal_tx_pd, 0, sizeof(TxPD));
2447     plocal_tx_pd->bss_num       = GET_BSS_NUM(pmpriv);
2448     plocal_tx_pd->bss_type      = pmpriv->bss_type;
2449     plocal_tx_pd->tx_pkt_length = (t_u16)data_len;
2450     plocal_tx_pd->priority      = (t_u8)tx_frame->priority;
2451     plocal_tx_pd->tx_pkt_offset = sizeof(TxPD);
2452     plocal_tx_pd->pkt_delay_2ms = 0xff;
2453 
2454     if (tx_frame->buf_type == MLAN_BUF_TYPE_RAW_DATA)
2455     {
2456         plocal_tx_pd->tx_pkt_type = (t_u16)pkt_type;
2457         plocal_tx_pd->tx_control  = tx_control;
2458     }
2459 
2460     if (tx_frame->flags & MLAN_BUF_FLAG_TX_STATUS)
2461     {
2462 #ifdef TXPD_RXPD_V3
2463         plocal_tx_pd->tx_control_1 |= tx_frame->tx_seq_num << 8;
2464 #else
2465         plocal_tx_pd->tx_token_id = (t_u8)tx_frame->tx_seq_num;
2466 #endif
2467         plocal_tx_pd->flags |= MRVDRV_TxPD_FLAGS_TX_PACKET_STATUS;
2468     }
2469 
2470     endian_convert_TxPD(plocal_tx_pd);
2471     cmd_size += sizeof(TxPD) + data_len;
2472     cmd->size = wlan_cpu_to_le16(cmd_size);
2473 
2474     LEAVE();
2475     return MLAN_STATUS_SUCCESS;
2476 }
2477