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