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