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