1 /**
2 * @file mlan_misc.c
3 *
4 * @brief This file include miscellaneous functions for MLAN module
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/11/2009: initial version
25 ************************************************************/
26 #include "mlan.h"
27 #ifdef STA_SUPPORT
28 #include "mlan_join.h"
29 #endif /* STA_SUPPORT */
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_sdio.h"
36 #ifdef UAP_SUPPORT
37 #include "mlan_uap.h"
38 #endif
39 #ifdef DRV_EMBEDDED_AUTHENTICATOR
40 #include "authenticator_api.h"
41 #endif
42 /********************************************************
43 Local Variables
44 ********************************************************/
45
46 /********************************************************
47 Global Variables
48 ********************************************************/
49 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
50 extern mlan_operations *mlan_ops[];
51 #endif
52 extern t_u8 ac_to_tid[4][2];
53
54 /********************************************************
55 Local Functions
56 ********************************************************/
57
58 /** Custom IE auto index and mask */
59 #define MLAN_CUSTOM_IE_AUTO_IDX_MASK 0xffff
60 /** Custom IE mask for delete operation */
61 #define MLAN_CUSTOM_IE_DELETE_MASK 0
62 /** Custom IE mask for create new index */
63 #define MLAN_CUSTOM_IE_NEW_MASK 0x8000
64 /** Custom IE header size */
65 #define MLAN_CUSTOM_IE_HDR_SIZE (sizeof(custom_ie)-MAX_IE_SIZE)
66
67 /**
68 * @brief Check if current custom IE index is used on other interfaces.
69 *
70 * @param pmpriv A pointer to mlan_private structure
71 * @param idx index to check for in use
72 *
73 * @return MLAN_STATUS_SUCCESS --unused, otherwise used.
74 */
75 static mlan_status
wlan_is_custom_ie_index_unused(IN pmlan_private pmpriv,IN t_u16 idx)76 wlan_is_custom_ie_index_unused(IN pmlan_private pmpriv, IN t_u16 idx)
77 {
78 t_u8 i = 0;
79 pmlan_adapter pmadapter = pmpriv->adapter;
80 pmlan_private priv;
81 ENTER();
82
83 for (i = 0; i < pmadapter->priv_num; i++) {
84 priv = pmadapter->priv[i];
85 /* Check for other interfaces only */
86 if (priv && priv->bss_index != pmpriv->bss_index) {
87
88 if (priv->mgmt_ie[idx].mgmt_subtype_mask &&
89 priv->mgmt_ie[idx].ie_length) {
90 /* used entry found */
91 LEAVE();
92 return MLAN_STATUS_FAILURE;
93 }
94 }
95 }
96 LEAVE();
97 return MLAN_STATUS_SUCCESS;
98 }
99
100 /**
101 * @brief Get the custom IE index
102 *
103 * @param pmpriv A pointer to mlan_private structure
104 * @param pioctl_req A pointer to ioctl request buffer
105 * @param mask mask value for which the index to be returned
106 * @param ie_data a pointer to custom_ie structure
107 * @param idx will hold the computed index
108 *
109 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
110 */
111 static mlan_status
wlan_custom_ioctl_get_autoidx(IN pmlan_private pmpriv,IN pmlan_ioctl_req pioctl_req,IN t_u16 mask,IN custom_ie * ie_data,OUT t_u16 * idx)112 wlan_custom_ioctl_get_autoidx(IN pmlan_private pmpriv,
113 IN pmlan_ioctl_req pioctl_req,
114 IN t_u16 mask,
115 IN custom_ie *ie_data, OUT t_u16 *idx)
116 {
117 t_u16 index = 0, insert = MFALSE;
118 mlan_status ret = MLAN_STATUS_SUCCESS;
119
120 ENTER();
121 /* Determine the index where the IE needs to be inserted */
122 while (!insert) {
123 while (index <
124 MIN(pmpriv->adapter->max_mgmt_ie_index,
125 MAX_MGMT_IE_INDEX)) {
126 if (pmpriv->mgmt_ie[index].mgmt_subtype_mask ==
127 MLAN_CUSTOM_IE_AUTO_IDX_MASK) {
128 index++;
129 continue;
130 }
131 if (pmpriv->mgmt_ie[index].mgmt_subtype_mask == mask) {
132 /* Duplicate IE should be avoided */
133 if (pmpriv->mgmt_ie[index].ie_length) {
134 if (!memcmp
135 (pmpriv->adapter,
136 pmpriv->mgmt_ie[index].ie_buffer,
137 ie_data->ie_buffer,
138 pmpriv->mgmt_ie[index].
139 ie_length)) {
140 PRINTM(MINFO,
141 "IE with the same mask exists at index %d mask=0x%x\n",
142 index, mask);
143 *idx = MLAN_CUSTOM_IE_AUTO_IDX_MASK;
144 goto done;
145 }
146 }
147 /* Check if enough space is available */
148 if (pmpriv->mgmt_ie[index].ie_length +
149 ie_data->ie_length > MAX_IE_SIZE) {
150 index++;
151 continue;
152 }
153 insert = MTRUE;
154 break;
155 }
156 index++;
157 }
158 if (!insert) {
159 for (index = 0;
160 index < MIN(pmpriv->adapter->max_mgmt_ie_index,
161 MAX_MGMT_IE_INDEX); index++) {
162 if (pmpriv->mgmt_ie[index].ie_length == 0) {
163 /*
164 * Check if this index is in use
165 * by other interface If yes,
166 * move ahead to next index
167 */
168 if (MLAN_STATUS_SUCCESS ==
169 wlan_is_custom_ie_index_unused
170 (pmpriv, index)) {
171 insert = MTRUE;
172 break;
173 } else {
174 PRINTM(MINFO,
175 "Skipping IE index %d in use.\n",
176 index);
177 }
178 }
179 }
180 }
181 if (index == pmpriv->adapter->max_mgmt_ie_index && !insert) {
182 PRINTM(MERROR, "Failed to Set the IE buffer\n");
183 if (pioctl_req)
184 pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
185 ret = MLAN_STATUS_FAILURE;
186 goto done;
187 }
188 }
189
190 *idx = index;
191 done:
192 LEAVE();
193 return ret;
194 }
195
196 /**
197 * @brief Delete custom IE
198 *
199 * @param pmpriv A pointer to mlan_private structure
200 * @param pioctl_req A pointer to ioctl request buffer
201 * @param ie_data a pointer to custom_ie structure
202 * @param idx index supplied
203 *
204 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
205 */
206
207 static mlan_status
wlan_custom_ioctl_auto_delete(IN pmlan_private pmpriv,IN pmlan_ioctl_req pioctl_req,IN custom_ie * ie_data,IN t_u16 idx)208 wlan_custom_ioctl_auto_delete(IN pmlan_private pmpriv,
209 IN pmlan_ioctl_req pioctl_req,
210 IN custom_ie *ie_data, IN t_u16 idx)
211 {
212 mlan_status ret = MLAN_STATUS_SUCCESS;
213 pmlan_adapter pmadapter = pmpriv->adapter;
214 t_u16 index = 0, insert = MFALSE, del_len;
215 t_u8 del_ie[MAX_IE_SIZE], ie[MAX_IE_SIZE];
216 t_s32 cnt, tmp_len = 0;
217 t_u8 *tmp_ie;
218
219 ENTER();
220 memset(pmpriv->adapter, del_ie, 0, MAX_IE_SIZE);
221 memcpy(pmpriv->adapter, del_ie, ie_data->ie_buffer,
222 MIN(MAX_IE_SIZE, ie_data->ie_length));
223 del_len = MIN(MAX_IE_SIZE - 1, ie_data->ie_length);
224
225 if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == idx)
226 ie_data->ie_index = 0;
227
228 for (index = 0;
229 index < MIN(pmadapter->max_mgmt_ie_index, MAX_MGMT_IE_INDEX);
230 index++) {
231 if (MLAN_CUSTOM_IE_AUTO_IDX_MASK != idx)
232 index = idx;
233 tmp_ie = pmpriv->mgmt_ie[index].ie_buffer;
234 tmp_len = pmpriv->mgmt_ie[index].ie_length;
235 cnt = 0;
236 while (tmp_len) {
237 if (!memcmp(pmpriv->adapter, tmp_ie, del_ie, del_len)) {
238 memcpy(pmpriv->adapter, ie,
239 pmpriv->mgmt_ie[index].ie_buffer, cnt);
240 if (pmpriv->mgmt_ie[index].ie_length >
241 (cnt + del_len))
242 memcpy(pmpriv->adapter, &ie[cnt],
243 &pmpriv->mgmt_ie[index].
244 ie_buffer[MIN
245 ((MAX_IE_SIZE - 1),
246 (cnt + del_len))],
247 (pmpriv->mgmt_ie[index].
248 ie_length - (cnt + del_len)));
249 memset(pmpriv->adapter,
250 &pmpriv->mgmt_ie[index].ie_buffer, 0,
251 sizeof(pmpriv->mgmt_ie[index].
252 ie_buffer));
253 memcpy(pmpriv->adapter,
254 &pmpriv->mgmt_ie[index].ie_buffer, ie,
255 pmpriv->mgmt_ie[index].ie_length -
256 del_len);
257 pmpriv->mgmt_ie[index].ie_length -= del_len;
258 if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == idx)
259 /* set a bit to indicate caller about update */
260 ie_data->ie_index |=
261 (((t_u16)1) << index);
262 insert = MTRUE;
263 tmp_ie = pmpriv->mgmt_ie[index].ie_buffer;
264 tmp_len = pmpriv->mgmt_ie[index].ie_length;
265 cnt = 0;
266 continue;
267 }
268 tmp_ie++;
269 tmp_len--;
270 cnt++;
271 }
272 if (MLAN_CUSTOM_IE_AUTO_IDX_MASK != idx)
273 break;
274 }
275 if (index == pmadapter->max_mgmt_ie_index && !insert) {
276 PRINTM(MERROR, "Failed to Clear IE buffer\n");
277 if (pioctl_req)
278 pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
279 ret = MLAN_STATUS_FAILURE;
280 }
281 LEAVE();
282 return ret;
283 }
284
285 /********************************************************
286 Global Functions
287 ********************************************************/
288
289 /**
290 * @brief Get correlated time
291 *
292 * @param pmadapter A pointer to mlan_adapter structure
293 * @param pioctl_req A pointer to ioctl request buffer
294 *
295 * @return MLAN_STATUS_PENDING --success, otherwise fail
296 */
297 mlan_status
wlan_misc_get_correlated_time(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)298 wlan_misc_get_correlated_time(IN pmlan_adapter pmadapter,
299 IN pmlan_ioctl_req pioctl_req)
300 {
301 pmlan_private pmpriv = MNULL;
302 mlan_status ret = MLAN_STATUS_SUCCESS;
303 mlan_ds_misc_cfg *misc = MNULL;
304 mlan_ds_host_clock *host_clock = MNULL;
305
306 ENTER();
307 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
308 host_clock = &misc->param.host_clock;
309
310 if (pioctl_req != MNULL) {
311 pmpriv = pmadapter->priv[pioctl_req->bss_index];
312 } else {
313 PRINTM(MERROR, "MLAN IOCTL information is not present\n");
314 ret = MLAN_STATUS_FAILURE;
315 goto exit;
316 }
317
318 /* Send request to firmware */
319 ret = wlan_prepare_cmd(pmpriv,
320 HostCmd_CMD_HOST_CLOCK_CFG,
321 HostCmd_ACT_GEN_GET,
322 0, (t_void *)pioctl_req, (t_void *)host_clock);
323
324 if (ret == MLAN_STATUS_SUCCESS)
325 ret = MLAN_STATUS_PENDING;
326
327 exit:
328 LEAVE();
329 return ret;
330 }
331
332 /**
333 * @brief send host cmd
334 *
335 * @param pmadapter A pointer to mlan_adapter structure
336 * @param pioctl_req A pointer to ioctl request buffer
337 *
338 * @return MLAN_STATUS_PENDING --success, otherwise fail
339 */
340 mlan_status
wlan_misc_ioctl_host_cmd(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)341 wlan_misc_ioctl_host_cmd(IN pmlan_adapter pmadapter,
342 IN pmlan_ioctl_req pioctl_req)
343 {
344 mlan_status ret = MLAN_STATUS_SUCCESS;
345 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
346 mlan_ds_misc_cfg *misc = MNULL;
347
348 ENTER();
349
350 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
351
352 /* Send request to firmware */
353 ret = wlan_prepare_cmd(pmpriv,
354 0,
355 0,
356 0,
357 (t_void *)pioctl_req,
358 (t_void *)&misc->param.hostcmd);
359 if (ret == MLAN_STATUS_SUCCESS)
360 ret = MLAN_STATUS_PENDING;
361
362 LEAVE();
363 return ret;
364 }
365
366 /**
367 * @brief Send function init/shutdown command to firmware
368 *
369 * @param pmadapter A pointer to mlan_adapter structure
370 * @param pioctl_req A pointer to ioctl request buffer
371 *
372 * @return MLAN_STATUS_PENDING --success, otherwise fail
373 */
374 mlan_status
wlan_misc_ioctl_init_shutdown(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)375 wlan_misc_ioctl_init_shutdown(IN pmlan_adapter pmadapter,
376 IN pmlan_ioctl_req pioctl_req)
377 {
378 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
379 mlan_status ret = MLAN_STATUS_SUCCESS;
380 mlan_ds_misc_cfg *misc_cfg = MNULL;
381 t_u16 cmd;
382
383 ENTER();
384
385 misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
386 if (misc_cfg->param.func_init_shutdown == MLAN_FUNC_INIT)
387 cmd = HostCmd_CMD_FUNC_INIT;
388 else if (misc_cfg->param.func_init_shutdown == MLAN_FUNC_SHUTDOWN)
389 cmd = HostCmd_CMD_FUNC_SHUTDOWN;
390 else {
391 PRINTM(MERROR, "Unsupported parameter\n");
392 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
393 ret = MLAN_STATUS_FAILURE;
394 goto exit;
395 }
396
397 /* Send command to firmware */
398 ret = wlan_prepare_cmd(pmpriv,
399 cmd,
400 HostCmd_ACT_GEN_SET,
401 0, (t_void *)pioctl_req, MNULL);
402
403 if (ret == MLAN_STATUS_SUCCESS)
404 ret = MLAN_STATUS_PENDING;
405
406 exit:
407 LEAVE();
408 return ret;
409 }
410
411 /**
412 * @brief Get debug information
413 *
414 * @param pmadapter A pointer to mlan_adapter structure
415 * @param pioctl_req A pointer to ioctl request buffer
416 *
417 * @return MLAN_STATUS_SUCCESS --success
418 */
419 mlan_status
wlan_get_info_debug_info(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)420 wlan_get_info_debug_info(IN pmlan_adapter pmadapter,
421 IN pmlan_ioctl_req pioctl_req)
422 {
423 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
424 mlan_status ret = MLAN_STATUS_SUCCESS;
425 mlan_ds_get_info *info;
426 mlan_debug_info *debug_info = MNULL;
427 t_u32 i;
428 t_u8 *ptid;
429
430 ENTER();
431
432 info = (mlan_ds_get_info *)pioctl_req->pbuf;
433 debug_info = (mlan_debug_info *)info->param.debug_info;
434
435 if (pioctl_req->action == MLAN_ACT_GET) {
436 ptid = ac_to_tid[WMM_AC_BK];
437 debug_info->wmm_ac_bk =
438 pmpriv->wmm.packets_out[ptid[0]] +
439 pmpriv->wmm.packets_out[ptid[1]];
440 ptid = ac_to_tid[WMM_AC_BE];
441 debug_info->wmm_ac_be =
442 pmpriv->wmm.packets_out[ptid[0]] +
443 pmpriv->wmm.packets_out[ptid[1]];
444 ptid = ac_to_tid[WMM_AC_VI];
445 debug_info->wmm_ac_vi =
446 pmpriv->wmm.packets_out[ptid[0]] +
447 pmpriv->wmm.packets_out[ptid[1]];
448 ptid = ac_to_tid[WMM_AC_VO];
449 debug_info->wmm_ac_vo =
450 pmpriv->wmm.packets_out[ptid[0]] +
451 pmpriv->wmm.packets_out[ptid[1]];
452 debug_info->max_tx_buf_size = (t_u32)pmadapter->max_tx_buf_size;
453 debug_info->tx_buf_size = (t_u32)pmadapter->tx_buf_size;
454 debug_info->curr_tx_buf_size =
455 (t_u32)pmadapter->curr_tx_buf_size;
456 debug_info->rx_tbl_num =
457 wlan_get_rxreorder_tbl(pmpriv, debug_info->rx_tbl);
458 debug_info->tx_tbl_num =
459 wlan_get_txbastream_tbl(pmpriv, debug_info->tx_tbl);
460 debug_info->ralist_num =
461 wlan_get_ralist_info(pmpriv, debug_info->ralist);
462 debug_info->tdls_peer_num =
463 wlan_get_tdls_list(pmpriv, debug_info->tdls_peer_list);
464 debug_info->ps_mode = pmadapter->ps_mode;
465 debug_info->ps_state = pmadapter->ps_state;
466 #ifdef STA_SUPPORT
467 debug_info->is_deep_sleep = pmadapter->is_deep_sleep;
468 #endif /* STA_SUPPORT */
469 debug_info->pm_wakeup_card_req = pmadapter->pm_wakeup_card_req;
470 debug_info->pm_wakeup_fw_try = pmadapter->pm_wakeup_fw_try;
471 debug_info->pm_wakeup_in_secs = pmadapter->pm_wakeup_in_secs;
472 debug_info->is_hs_configured = pmadapter->is_hs_configured;
473 debug_info->hs_activated = pmadapter->hs_activated;
474 debug_info->pps_uapsd_mode = pmadapter->pps_uapsd_mode;
475 debug_info->sleep_pd = pmadapter->sleep_period.period;
476 debug_info->qos_cfg = pmpriv->wmm_qosinfo;
477 debug_info->tx_lock_flag = pmadapter->tx_lock_flag;
478 debug_info->port_open = pmpriv->port_open;
479 debug_info->bypass_pkt_count = pmadapter->bypass_pkt_count;
480 debug_info->scan_processing = pmadapter->scan_processing;
481 debug_info->mlan_processing = pmadapter->mlan_processing;
482 debug_info->main_lock_flag = pmadapter->main_lock_flag;
483 debug_info->main_process_cnt = pmadapter->main_process_cnt;
484 debug_info->delay_task_flag = pmadapter->delay_task_flag;
485 debug_info->num_cmd_host_to_card_failure
486 = pmadapter->dbg.num_cmd_host_to_card_failure;
487 debug_info->num_cmd_sleep_cfm_host_to_card_failure
488 = pmadapter->dbg.num_cmd_sleep_cfm_host_to_card_failure;
489 debug_info->num_tx_host_to_card_failure
490 = pmadapter->dbg.num_tx_host_to_card_failure;
491 debug_info->num_alloc_buffer_failure =
492 pmadapter->dbg.num_alloc_buffer_failure;
493 debug_info->num_pkt_dropped = pmadapter->dbg.num_pkt_dropped;
494
495 debug_info->num_cmdevt_card_to_host_failure
496 = pmadapter->dbg.num_cmdevt_card_to_host_failure;
497 debug_info->num_rx_card_to_host_failure
498 = pmadapter->dbg.num_rx_card_to_host_failure;
499 debug_info->num_int_read_failure =
500 pmadapter->dbg.num_int_read_failure;
501 debug_info->last_int_status = pmadapter->dbg.last_int_status;
502 debug_info->num_event_deauth = pmadapter->dbg.num_event_deauth;
503 debug_info->num_event_disassoc =
504 pmadapter->dbg.num_event_disassoc;
505 debug_info->num_event_link_lost =
506 pmadapter->dbg.num_event_link_lost;
507 debug_info->num_cmd_deauth = pmadapter->dbg.num_cmd_deauth;
508 debug_info->num_cmd_assoc_success =
509 pmadapter->dbg.num_cmd_assoc_success;
510 debug_info->num_cmd_assoc_failure =
511 pmadapter->dbg.num_cmd_assoc_failure;
512 debug_info->num_tx_timeout = pmadapter->dbg.num_tx_timeout;
513 debug_info->num_cmd_timeout = pmadapter->num_cmd_timeout;
514 debug_info->dbg_num_cmd_timeout =
515 pmadapter->dbg.num_cmd_timeout;
516 debug_info->timeout_cmd_id = pmadapter->dbg.timeout_cmd_id;
517 debug_info->timeout_cmd_act = pmadapter->dbg.timeout_cmd_act;
518 memcpy(pmadapter, debug_info->last_cmd_id,
519 pmadapter->dbg.last_cmd_id,
520 sizeof(pmadapter->dbg.last_cmd_id));
521 memcpy(pmadapter, debug_info->last_cmd_act,
522 pmadapter->dbg.last_cmd_act,
523 sizeof(pmadapter->dbg.last_cmd_act));
524 debug_info->last_cmd_index = pmadapter->dbg.last_cmd_index;
525 memcpy(pmadapter, debug_info->last_cmd_resp_id,
526 pmadapter->dbg.last_cmd_resp_id,
527 sizeof(pmadapter->dbg.last_cmd_resp_id));
528 debug_info->last_cmd_resp_index =
529 pmadapter->dbg.last_cmd_resp_index;
530 memcpy(pmadapter, debug_info->last_event,
531 pmadapter->dbg.last_event,
532 sizeof(pmadapter->dbg.last_event));
533 debug_info->last_event_index = pmadapter->dbg.last_event_index;
534 debug_info->num_no_cmd_node = pmadapter->dbg.num_no_cmd_node;
535 debug_info->pending_cmd =
536 (pmadapter->curr_cmd) ? pmadapter->dbg.
537 last_cmd_id[pmadapter->dbg.last_cmd_index] : 0;
538 debug_info->dnld_cmd_in_secs = pmadapter->dnld_cmd_in_secs;
539 debug_info->mp_rd_bitmap = pmadapter->mp_rd_bitmap;
540 debug_info->mp_wr_bitmap = pmadapter->mp_wr_bitmap;
541 debug_info->curr_rd_port = pmadapter->curr_rd_port;
542 debug_info->curr_wr_port = pmadapter->curr_wr_port;
543 debug_info->mp_invalid_update = pmadapter->mp_invalid_update;
544 debug_info->num_of_irq = pmadapter->num_of_irq;
545 memcpy(pmadapter, debug_info->mp_update, pmadapter->mp_update,
546 sizeof(pmadapter->mp_update));
547 #ifdef SDIO_MULTI_PORT_TX_AGGR
548 memcpy(pmadapter, debug_info->mpa_tx_count,
549 pmadapter->mpa_tx_count,
550 sizeof(pmadapter->mpa_tx_count));
551 debug_info->mpa_sent_last_pkt = pmadapter->mpa_sent_last_pkt;
552 debug_info->mpa_sent_no_ports = pmadapter->mpa_sent_no_ports;
553 debug_info->last_recv_wr_bitmap =
554 pmadapter->last_recv_wr_bitmap;
555 debug_info->last_mp_index = pmadapter->last_mp_index;
556 memcpy(pmadapter, debug_info->last_mp_wr_bitmap,
557 pmadapter->last_mp_wr_bitmap,
558 sizeof(pmadapter->last_mp_wr_bitmap));
559 memcpy(pmadapter, debug_info->last_mp_wr_ports,
560 pmadapter->last_mp_wr_ports,
561 sizeof(pmadapter->last_mp_wr_ports));
562 memcpy(pmadapter, debug_info->last_mp_wr_len,
563 pmadapter->last_mp_wr_len,
564 sizeof(pmadapter->last_mp_wr_len));
565 memcpy(pmadapter, debug_info->last_mp_wr_info,
566 pmadapter->last_mp_wr_info,
567 sizeof(pmadapter->last_mp_wr_info));
568 memcpy(pmadapter, debug_info->last_curr_wr_port,
569 pmadapter->last_curr_wr_port,
570 sizeof(pmadapter->last_curr_wr_port));
571 debug_info->mpa_buf = pmadapter->mpa_buf;
572 debug_info->mpa_buf_size = pmadapter->mpa_buf_size;
573 #endif /* SDIO_MULTI_PORT_TX_AGGR */
574 #ifdef SDIO_MULTI_PORT_RX_AGGR
575 debug_info->sdio_rx_aggr = pmadapter->sdio_rx_aggr_enable;
576 memcpy(pmadapter, debug_info->mpa_rx_count,
577 pmadapter->mpa_rx_count,
578 sizeof(pmadapter->mpa_rx_count));
579 #endif
580 debug_info->data_sent = pmadapter->data_sent;
581 debug_info->cmd_sent = pmadapter->cmd_sent;
582 debug_info->cmd_resp_received = pmadapter->cmd_resp_received;
583 debug_info->tx_pkts_queued =
584 util_scalar_read(pmadapter->pmoal_handle,
585 &pmpriv->wmm.tx_pkts_queued, MNULL,
586 MNULL);
587 #ifdef UAP_SUPPORT
588 debug_info->num_bridge_pkts =
589 util_scalar_read(pmadapter->pmoal_handle,
590 &pmadapter->pending_bridge_pkts,
591 pmadapter->callbacks.moal_spin_lock,
592 pmadapter->callbacks.moal_spin_unlock);
593 debug_info->num_drop_pkts = pmpriv->num_drop_pkts;
594 #endif
595 debug_info->mlan_processing = pmadapter->mlan_processing;
596 debug_info->mlan_rx_processing = pmadapter->mlan_rx_processing;
597 debug_info->rx_pkts_queued = pmadapter->rx_pkts_queued;
598 debug_info->mlan_adapter = pmadapter;
599 debug_info->mlan_adapter_size = sizeof(mlan_adapter);
600 debug_info->mlan_priv_num = pmadapter->priv_num;
601 for (i = 0; i < pmadapter->priv_num; i++) {
602 debug_info->mlan_priv[i] = pmadapter->priv[i];
603 debug_info->mlan_priv_size[i] = sizeof(mlan_private);
604 }
605 }
606
607 pioctl_req->data_read_written =
608 sizeof(mlan_debug_info) + MLAN_SUB_COMMAND_SIZE;
609
610 LEAVE();
611 return ret;
612 }
613
614 /**
615 * @brief Set/Get the MAC control configuration.
616 *
617 * @param pmadapter A pointer to mlan_adapter structure
618 * @param pioctl_req A pointer to ioctl request buffer
619 *
620 * @return MLAN_STATUS_PENDING -- success, otherwise fail
621 */
622 mlan_status
wlan_misc_ioctl_mac_control(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)623 wlan_misc_ioctl_mac_control(IN pmlan_adapter pmadapter,
624 IN pmlan_ioctl_req pioctl_req)
625 {
626 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
627 mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
628 mlan_status ret = MLAN_STATUS_SUCCESS;
629 t_u16 cmd_action = 0;
630
631 ENTER();
632
633 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
634
635 if (pioctl_req->action == MLAN_ACT_GET) {
636 misc->param.mac_ctrl = pmpriv->curr_pkt_filter;
637 } else {
638 pmpriv->curr_pkt_filter = misc->param.mac_ctrl;
639 cmd_action = HostCmd_ACT_GEN_SET;
640
641 /* Send command to firmware */
642 ret = wlan_prepare_cmd(pmpriv,
643 HostCmd_CMD_MAC_CONTROL,
644 cmd_action, 0,
645 (t_void *)pioctl_req,
646 &misc->param.mac_ctrl);
647
648 if (ret == MLAN_STATUS_SUCCESS)
649 ret = MLAN_STATUS_PENDING;
650 }
651
652 LEAVE();
653 return ret;
654 }
655
656 /**
657 * @brief This function wakes up the card.
658 *
659 * @param pmadapter A pointer to mlan_adapter structure
660 *
661 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
662 */
663 mlan_status
wlan_pm_wakeup_card(IN pmlan_adapter pmadapter)664 wlan_pm_wakeup_card(IN pmlan_adapter pmadapter)
665 {
666 mlan_status ret = MLAN_STATUS_SUCCESS;
667 t_u32 age_ts_usec;
668 pmlan_callbacks pcb = &pmadapter->callbacks;
669
670 ENTER();
671 PRINTM(MEVENT, "Wakeup device...\n");
672 pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
673 &pmadapter->pm_wakeup_in_secs,
674 &age_ts_usec);
675
676 if (pmadapter->fw_wakeup_method == WAKEUP_FW_THRU_GPIO) {
677 /* GPIO_PORT_TO_LOW(); */
678 } else
679 ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
680 HOST_TO_CARD_EVENT_REG,
681 HOST_POWER_UP);
682 LEAVE();
683 return ret;
684 }
685
686 /**
687 * @brief This function resets the PM setting of the card.
688 *
689 * @param pmadapter A pointer to mlan_adapter structure
690 *
691 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
692 */
693 mlan_status
wlan_pm_reset_card(IN pmlan_adapter pmadapter)694 wlan_pm_reset_card(IN pmlan_adapter pmadapter)
695 {
696 mlan_status ret = MLAN_STATUS_SUCCESS;
697 pmlan_callbacks pcb = &pmadapter->callbacks;
698
699 ENTER();
700
701 if (pmadapter->fw_wakeup_method == WAKEUP_FW_THRU_GPIO) {
702 /* GPIO_PORT_TO_HIGH(); */
703 } else
704 ret = pcb->moal_write_reg(pmadapter->pmoal_handle,
705 HOST_TO_CARD_EVENT_REG, 0);
706
707 LEAVE();
708 return ret;
709 }
710
711 /**
712 * @brief Set/Get HS configuration
713 *
714 * @param pmadapter A pointer to mlan_adapter structure
715 * @param pioctl_req A pointer to ioctl request buffer
716 *
717 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
718 */
719 mlan_status
wlan_pm_ioctl_hscfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)720 wlan_pm_ioctl_hscfg(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
721 {
722 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
723 mlan_ds_pm_cfg *pm = MNULL;
724 mlan_status status = MLAN_STATUS_SUCCESS;
725 t_u32 prev_cond = 0;
726
727 ENTER();
728
729 pm = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
730
731 switch (pioctl_req->action) {
732 case MLAN_ACT_SET:
733 #ifdef STA_SUPPORT
734 if (pmadapter->pps_uapsd_mode) {
735 PRINTM(MINFO,
736 "Host Sleep IOCTL is blocked in UAPSD/PPS mode\n");
737 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
738 status = MLAN_STATUS_FAILURE;
739 break;
740 }
741 #endif /* STA_SUPPORT */
742 if (pm->param.hs_cfg.is_invoke_hostcmd == MTRUE) {
743 if (pm->param.hs_cfg.conditions ==
744 HOST_SLEEP_CFG_CANCEL) {
745 if (pmadapter->is_hs_configured == MFALSE) {
746 /* Already cancelled */
747 break;
748 }
749 /* Save previous condition */
750 prev_cond = pmadapter->hs_cfg.conditions;
751 pmadapter->hs_cfg.conditions =
752 pm->param.hs_cfg.conditions;
753 } else if (pmadapter->hs_cfg.conditions ==
754 HOST_SLEEP_CFG_CANCEL) {
755 /* Return failure if no parameters for HS enable */
756 pioctl_req->status_code =
757 MLAN_ERROR_INVALID_PARAMETER;
758 status = MLAN_STATUS_FAILURE;
759 break;
760 }
761 status = wlan_prepare_cmd(pmpriv,
762 HostCmd_CMD_802_11_HS_CFG_ENH,
763 HostCmd_ACT_GEN_SET,
764 0, (t_void *)pioctl_req,
765 (t_void *)(&pmadapter->
766 hs_cfg));
767 if (status == MLAN_STATUS_SUCCESS)
768 status = MLAN_STATUS_PENDING;
769 if (pm->param.hs_cfg.conditions ==
770 HOST_SLEEP_CFG_CANCEL) {
771 /* Restore previous condition */
772 pmadapter->hs_cfg.conditions = prev_cond;
773 }
774 } else {
775 pmadapter->hs_cfg.conditions =
776 pm->param.hs_cfg.conditions;
777 pmadapter->hs_cfg.gpio = (t_u8)pm->param.hs_cfg.gpio;
778 pmadapter->hs_cfg.gap = (t_u8)pm->param.hs_cfg.gap;
779 pmadapter->param_type_ind =
780 (t_u8)pm->param.hs_cfg.param_type_ind;
781 pmadapter->ind_gpio = (t_u8)pm->param.hs_cfg.ind_gpio;
782 pmadapter->level = (t_u8)pm->param.hs_cfg.level;
783 pmadapter->param_type_ext =
784 (t_u8)pm->param.hs_cfg.param_type_ext;
785 pmadapter->event_force_ignore =
786 pm->param.hs_cfg.event_force_ignore;
787 pmadapter->event_use_ext_gap =
788 pm->param.hs_cfg.event_use_ext_gap;
789 pmadapter->ext_gap = pm->param.hs_cfg.ext_gap;
790 pmadapter->gpio_wave = pm->param.hs_cfg.gpio_wave;
791 pmadapter->hs_wake_interval =
792 pm->param.hs_cfg.hs_wake_interval;
793 }
794 break;
795 case MLAN_ACT_GET:
796 pm->param.hs_cfg.conditions = pmadapter->hs_cfg.conditions;
797 pm->param.hs_cfg.gpio = pmadapter->hs_cfg.gpio;
798 pm->param.hs_cfg.gap = pmadapter->hs_cfg.gap;
799 pm->param.hs_cfg.param_type_ind = pmadapter->param_type_ind;
800 pm->param.hs_cfg.ind_gpio = pmadapter->ind_gpio;
801 pm->param.hs_cfg.level = pmadapter->level;
802 pm->param.hs_cfg.param_type_ext = pmadapter->param_type_ext;
803 pm->param.hs_cfg.event_force_ignore =
804 pmadapter->event_force_ignore;
805 pm->param.hs_cfg.event_use_ext_gap =
806 pmadapter->event_use_ext_gap;
807 pm->param.hs_cfg.ext_gap = pmadapter->ext_gap;
808 pm->param.hs_cfg.gpio_wave = pmadapter->gpio_wave;
809 pm->param.hs_cfg.hs_wake_interval = pmadapter->hs_wake_interval;
810 break;
811 default:
812 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
813 status = MLAN_STATUS_FAILURE;
814 break;
815 }
816
817 LEAVE();
818 return status;
819 }
820
821 /**
822 * @brief Get/Set the firmware wakeup method
823 *
824 * @param pmadapter A pointer to mlan_adapter structure
825 * @param pioctl_req A pointer to ioctl request buffer
826 *
827 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
828 */
829 mlan_status
wlan_fw_wakeup_method(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)830 wlan_fw_wakeup_method(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
831 {
832 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
833 mlan_status ret = MLAN_STATUS_SUCCESS;
834 t_u16 cmd_action;
835 mlan_ds_pm_cfg *pmcfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
836
837 ENTER();
838
839 if (pioctl_req->action == MLAN_ACT_SET)
840 cmd_action = HostCmd_ACT_GEN_SET;
841 else
842 cmd_action = HostCmd_ACT_GEN_GET;
843
844 ret = wlan_prepare_cmd(pmpriv,
845 HostCmd_CMD_802_11_FW_WAKE_METHOD,
846 cmd_action,
847 0,
848 (t_void *)pioctl_req,
849 &pmcfg->param.fw_wakeup_params);
850
851 if (ret == MLAN_STATUS_SUCCESS)
852 ret = MLAN_STATUS_PENDING;
853 LEAVE();
854 return ret;
855 }
856
857 /**
858 * @brief Set Robustcoex gpiocfg
859 *
860 * @param pmadapter A pointer to mlan_adapter structure
861 * @param pioctl_req A pointer to ioctl request buffer
862 *
863 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
864 */
865 mlan_status
wlan_misc_robustcoex(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)866 wlan_misc_robustcoex(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
867 {
868 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
869 mlan_status ret = MLAN_STATUS_SUCCESS;
870 t_u16 cmd_action;
871 mlan_ds_misc_cfg *robust_coex_cfg =
872 (mlan_ds_misc_cfg *)pioctl_req->pbuf;
873
874 ENTER();
875
876 if (pioctl_req->action == MLAN_ACT_SET)
877 cmd_action = HostCmd_ACT_GEN_SET;
878 else
879 cmd_action = HostCmd_ACT_GEN_GET;
880
881 ret = wlan_prepare_cmd(pmpriv,
882 HostCmd_CMD_802_11_ROBUSTCOEX,
883 cmd_action,
884 0,
885 (t_void *)pioctl_req,
886 &robust_coex_cfg->param.robustcoexparams);
887
888 if (ret == MLAN_STATUS_SUCCESS)
889 ret = MLAN_STATUS_PENDING;
890 LEAVE();
891 return ret;
892 }
893
894 /**
895 * @brief This function allocates a mlan_buffer.
896 *
897 * @param pmadapter Pointer to mlan_adapter
898 * @param data_len Data length
899 * @param head_room head_room reserved in mlan_buffer
900 * @param malloc_flag flag to user moal_malloc
901 * @return mlan_buffer pointer or MNULL
902 */
903 pmlan_buffer
wlan_alloc_mlan_buffer(mlan_adapter * pmadapter,t_u32 data_len,t_u32 head_room,t_u32 malloc_flag)904 wlan_alloc_mlan_buffer(mlan_adapter *pmadapter, t_u32 data_len, t_u32 head_room,
905 t_u32 malloc_flag)
906 {
907 mlan_status ret = MLAN_STATUS_SUCCESS;
908 pmlan_buffer pmbuf = MNULL;
909 t_u32 buf_size = 0;
910 t_u8 *tmp_buf = MNULL;
911 pmlan_callbacks pcb = &pmadapter->callbacks;
912
913 ENTER();
914
915 /* make sure that the data length is at least SDIO block size */
916 data_len =
917 (data_len + MLAN_SDIO_BLOCK_SIZE -
918 1) / MLAN_SDIO_BLOCK_SIZE * MLAN_SDIO_BLOCK_SIZE;
919
920 /* head_room is not implemented for malloc mlan buffer */
921
922 switch (malloc_flag) {
923 case MOAL_MALLOC_BUFFER:
924 buf_size = sizeof(mlan_buffer) + data_len + DMA_ALIGNMENT;
925 ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size,
926 MLAN_MEM_DEF | MLAN_MEM_DMA,
927 (t_u8 **)&pmbuf);
928 if ((ret != MLAN_STATUS_SUCCESS) || !pmbuf) {
929 pmbuf = MNULL;
930 goto exit;
931 }
932 memset(pmadapter, pmbuf, 0, sizeof(mlan_buffer));
933
934 pmbuf->pdesc = MNULL;
935 /* Align address */
936 pmbuf->pbuf =
937 (t_u8 *)ALIGN_ADDR((t_u8 *)pmbuf + sizeof(mlan_buffer),
938 DMA_ALIGNMENT);
939 pmbuf->data_offset = 0;
940 pmbuf->data_len = data_len;
941 pmbuf->flags |= MLAN_BUF_FLAG_MALLOC_BUF;
942 break;
943
944 case MOAL_ALLOC_MLAN_BUFFER:
945 /* use moal_alloc_mlan_buffer, head_room supported */
946 ret = pcb->moal_alloc_mlan_buffer(pmadapter->pmoal_handle,
947 data_len + DMA_ALIGNMENT +
948 head_room, &pmbuf);
949 if ((ret != MLAN_STATUS_SUCCESS) || !pmbuf) {
950 PRINTM(MERROR, "Failed to allocate 'mlan_buffer'\n");
951 goto exit;
952 }
953 pmbuf->data_offset = head_room;
954 tmp_buf =
955 (t_u8 *)ALIGN_ADDR(pmbuf->pbuf + pmbuf->data_offset,
956 DMA_ALIGNMENT);
957 pmbuf->data_offset +=
958 (t_u32)(tmp_buf - (pmbuf->pbuf + pmbuf->data_offset));
959 pmbuf->data_len = data_len;
960 pmbuf->flags = 0;
961 break;
962 }
963
964 exit:
965 LEAVE();
966 return pmbuf;
967 }
968
969 /**
970 * @brief This function frees a mlan_buffer.
971 *
972 * @param pmadapter Pointer to mlan_adapter
973 * @param pmbuf Pointer to mlan_buffer
974 *
975 * @return N/A
976 */
977 t_void
wlan_free_mlan_buffer(mlan_adapter * pmadapter,pmlan_buffer pmbuf)978 wlan_free_mlan_buffer(mlan_adapter *pmadapter, pmlan_buffer pmbuf)
979 {
980 pmlan_callbacks pcb = &pmadapter->callbacks;
981 ENTER();
982
983 if (pcb && pmbuf) {
984 if (pmbuf->flags & MLAN_BUF_FLAG_BRIDGE_BUF)
985 util_scalar_decrement(pmadapter->pmoal_handle,
986 &pmadapter->pending_bridge_pkts,
987 pmadapter->callbacks.
988 moal_spin_lock,
989 pmadapter->callbacks.
990 moal_spin_unlock);
991 if (pmbuf->flags & MLAN_BUF_FLAG_MALLOC_BUF)
992 pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmbuf);
993 else
994 pcb->moal_free_mlan_buffer(pmadapter->pmoal_handle,
995 pmbuf);
996 }
997
998 LEAVE();
999 return;
1000 }
1001
1002 /**
1003 * @brief Delay function implementation
1004 *
1005 * @param pmadapter A pointer to mlan_adapter structure
1006 * @param delay Delay value
1007 * @param u Units of delay (sec, msec or usec)
1008 *
1009 * @return N/A
1010 */
1011 t_void
wlan_delay_func(mlan_adapter * pmadapter,t_u32 delay,t_delay_unit u)1012 wlan_delay_func(mlan_adapter *pmadapter, t_u32 delay, t_delay_unit u)
1013 {
1014 t_u32 now_tv_sec, now_tv_usec;
1015 t_u32 upto_tv_sec, upto_tv_usec;
1016 pmlan_callbacks pcb = &pmadapter->callbacks;
1017
1018 ENTER();
1019
1020 if (pcb->moal_udelay) {
1021 if (u == SEC)
1022 delay *= 1000000;
1023 else if (u == MSEC)
1024 delay *= 1000;
1025 pcb->moal_udelay(pmadapter->pmoal_handle, delay);
1026 } else {
1027
1028 pcb->moal_get_system_time(pmadapter->pmoal_handle, &upto_tv_sec,
1029 &upto_tv_usec);
1030
1031 switch (u) {
1032 case SEC:
1033 upto_tv_sec += delay;
1034 break;
1035 case MSEC:
1036 delay *= 1000;
1037 case USEC:
1038 upto_tv_sec += (delay / 1000000);
1039 upto_tv_usec += (delay % 1000000);
1040 break;
1041 }
1042
1043 do {
1044 pcb->moal_get_system_time(pmadapter->pmoal_handle,
1045 &now_tv_sec, &now_tv_usec);
1046 if (now_tv_sec > upto_tv_sec) {
1047 LEAVE();
1048 return;
1049 }
1050
1051 if ((now_tv_sec == upto_tv_sec) &&
1052 (now_tv_usec >= upto_tv_usec)) {
1053 LEAVE();
1054 return;
1055 }
1056 } while (MTRUE);
1057 }
1058
1059 LEAVE();
1060 return;
1061 }
1062
1063 /**
1064 * @brief Send coalescing status command to firmware
1065 *
1066 * @param pmadapter A pointer to mlan_adapter structure
1067 * @param pioctl_req A pointer to ioctl request buffer
1068 *
1069 * @return MLAN_STATUS_PENDING --success, otherwise fail
1070 */
1071 mlan_status
wlan_misc_ioctl_coalescing_status(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1072 wlan_misc_ioctl_coalescing_status(IN pmlan_adapter pmadapter,
1073 IN pmlan_ioctl_req pioctl_req)
1074 {
1075 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1076 mlan_status ret = MLAN_STATUS_SUCCESS;
1077 mlan_ds_misc_cfg *misc = MNULL;
1078 t_u16 cmd_action = 0;
1079
1080 ENTER();
1081
1082 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
1083
1084 if (pioctl_req->action == MLAN_ACT_SET)
1085 cmd_action = HostCmd_ACT_GEN_SET;
1086 else
1087 cmd_action = HostCmd_ACT_GEN_GET;
1088
1089 ret = wlan_prepare_cmd(pmpriv,
1090 HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
1091 cmd_action,
1092 0,
1093 (t_void *)pioctl_req,
1094 &misc->param.coalescing_status);
1095
1096 if (ret == MLAN_STATUS_SUCCESS)
1097 ret = MLAN_STATUS_PENDING;
1098
1099 LEAVE();
1100 return ret;
1101 }
1102
1103 /**
1104 * @brief BSS remove
1105 *
1106 * @param pmadapter A pointer to mlan_adapter structure
1107 * @param pioctl_req A pointer to ioctl request buffer
1108 *
1109 * @return MLAN_STATUS_PENDING --success, MLAN_STATUS_FAILURE
1110 */
1111 mlan_status
wlan_bss_ioctl_bss_remove(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1112 wlan_bss_ioctl_bss_remove(IN pmlan_adapter pmadapter,
1113 IN pmlan_ioctl_req pioctl_req)
1114 {
1115 ENTER();
1116 wlan_cancel_bss_pending_cmd(pmadapter, pioctl_req->bss_index);
1117 LEAVE();
1118 return MLAN_STATUS_SUCCESS;
1119 }
1120
1121 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
1122 /**
1123 * @brief Set/Get BSS role
1124 *
1125 * @param pmadapter A pointer to mlan_adapter structure
1126 * @param pioctl_req A pointer to ioctl request buffer
1127 *
1128 * @return MLAN_STATUS_PENDING --success, MLAN_STATUS_FAILURE
1129 */
1130 mlan_status
wlan_bss_ioctl_bss_role(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1131 wlan_bss_ioctl_bss_role(IN pmlan_adapter pmadapter,
1132 IN pmlan_ioctl_req pioctl_req)
1133 {
1134 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1135 mlan_ds_bss *bss = MNULL;
1136 mlan_status ret = MLAN_STATUS_SUCCESS;
1137 HostCmd_DS_VERSION_EXT dummy;
1138 #if defined(WIFI_DIRECT_SUPPORT)
1139 t_u8 bss_mode;
1140 #endif
1141 t_u8 i, global_band = 0;
1142 int j;
1143
1144 ENTER();
1145
1146 bss = (mlan_ds_bss *)pioctl_req->pbuf;
1147 if (pioctl_req->action == MLAN_ACT_GET) {
1148 bss->param.bss_role = GET_BSS_ROLE(pmpriv);
1149 } else {
1150 if (GET_BSS_ROLE(pmpriv) == bss->param.bss_role) {
1151 PRINTM(MIOCTL, "BSS ie already in the desired role!\n");
1152 goto done;
1153 }
1154 mlan_block_rx_process(pmadapter, MTRUE);
1155 /** Switch BSS role */
1156 wlan_free_priv(pmpriv);
1157
1158 pmpriv->bss_role = bss->param.bss_role;
1159 if (pmpriv->bss_type == MLAN_BSS_TYPE_UAP)
1160 pmpriv->bss_type = MLAN_BSS_TYPE_STA;
1161 else if (pmpriv->bss_type == MLAN_BSS_TYPE_STA)
1162 pmpriv->bss_type = MLAN_BSS_TYPE_UAP;
1163 /* Initialize private structures */
1164 wlan_init_priv(pmpriv);
1165 mlan_block_rx_process(pmadapter, MFALSE);
1166 /* Initialize function table */
1167 for (j = 0; mlan_ops[j]; j++) {
1168 if (mlan_ops[j]->bss_role == GET_BSS_ROLE(pmpriv)) {
1169 memcpy(pmadapter, &pmpriv->ops, mlan_ops[j],
1170 sizeof(mlan_operations));
1171 }
1172 }
1173
1174 for (i = 0; i < pmadapter->priv_num; i++) {
1175 if (pmadapter->priv[i] &&
1176 GET_BSS_ROLE(pmadapter->priv[i]) ==
1177 MLAN_BSS_ROLE_STA)
1178 global_band |= pmadapter->priv[i]->config_bands;
1179 }
1180
1181 if (global_band != pmadapter->config_bands) {
1182 if (wlan_set_regiontable
1183 (pmpriv, (t_u8)pmadapter->region_code,
1184 global_band | pmadapter->adhoc_start_band)) {
1185 pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
1186 LEAVE();
1187 return MLAN_STATUS_FAILURE;
1188 }
1189
1190 if (wlan_11d_set_universaltable
1191 (pmpriv,
1192 global_band | pmadapter->adhoc_start_band)) {
1193 pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
1194 LEAVE();
1195 return MLAN_STATUS_FAILURE;
1196 }
1197 pmadapter->config_bands = global_band;
1198 }
1199
1200 /* Issue commands to initialize firmware */
1201 #if defined(WIFI_DIRECT_SUPPORT)
1202 if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA)
1203 bss_mode = BSS_MODE_WIFIDIRECT_CLIENT;
1204 else
1205 bss_mode = BSS_MODE_WIFIDIRECT_GO;
1206 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SET_BSS_MODE,
1207 HostCmd_ACT_GEN_SET, 0, MNULL,
1208 &bss_mode);
1209 if (ret)
1210 goto done;
1211 #endif
1212 ret = pmpriv->ops.init_cmd(pmpriv, MFALSE);
1213 if (ret == MLAN_STATUS_FAILURE)
1214 goto done;
1215
1216 /* Issue dummy Get command to complete the ioctl */
1217 memset(pmadapter, &dummy, 0, sizeof(HostCmd_DS_VERSION_EXT));
1218 ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_VERSION_EXT,
1219 HostCmd_ACT_GEN_GET, 0,
1220 (t_void *)pioctl_req, (t_void *)&dummy);
1221 if (ret == MLAN_STATUS_SUCCESS)
1222 ret = MLAN_STATUS_PENDING;
1223 }
1224
1225 done:
1226 LEAVE();
1227 return ret;
1228 }
1229 #endif
1230
1231 /**
1232 * @brief Set the custom IE
1233 *
1234 * @param pmadapter A pointer to mlan_adapter structure
1235 * @param pioctl_req A pointer to ioctl request buffer
1236 * @param send_ioctl Flag to indicate if ioctl should be sent with cmd
1237 * (MTRUE if from moal/user, MFALSE if internal)
1238 *
1239 * @return MLAN_STATUS_PENDING --success, otherwise fail
1240 */
1241 mlan_status
wlan_misc_ioctl_custom_ie_list(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req,IN t_bool send_ioctl)1242 wlan_misc_ioctl_custom_ie_list(IN pmlan_adapter pmadapter,
1243 IN pmlan_ioctl_req pioctl_req,
1244 IN t_bool send_ioctl)
1245 {
1246 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1247 mlan_status ret = MLAN_STATUS_SUCCESS;
1248 mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
1249 custom_ie *ie_data = MNULL;
1250 t_u16 cmd_action = 0, index, mask, i, len, app_data_len;
1251 t_s32 ioctl_len;
1252 t_u8 *tmp_ie;
1253
1254 ENTER();
1255
1256 if ((misc->param.cust_ie.len == 0) ||
1257 (misc->param.cust_ie.len == sizeof(t_u16))) {
1258 pioctl_req->action = MLAN_ACT_GET;
1259 /* Get the IE */
1260 cmd_action = HostCmd_ACT_GEN_GET;
1261 } else {
1262 /* ioctl_len : ioctl length from application, start with
1263 * misc->param.cust_ie.len and reach upto 0 */
1264 ioctl_len = misc->param.cust_ie.len;
1265
1266 /* app_data_len : length from application, start with 0
1267 * and reach upto ioctl_len */
1268 app_data_len = sizeof(MrvlIEtypesHeader_t);
1269 misc->param.cust_ie.len = 0;
1270
1271 while (ioctl_len > 0) {
1272 ie_data = (custom_ie *)(((t_u8 *)&misc->param.cust_ie)
1273 + app_data_len);
1274 ioctl_len -=
1275 (ie_data->ie_length + MLAN_CUSTOM_IE_HDR_SIZE);
1276 app_data_len +=
1277 (ie_data->ie_length + MLAN_CUSTOM_IE_HDR_SIZE);
1278
1279 index = ie_data->ie_index;
1280 mask = ie_data->mgmt_subtype_mask;
1281
1282 /* Need to be Autohandled */
1283 if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == index) {
1284 /* Automatic Deletion */
1285 if (mask == MLAN_CUSTOM_IE_DELETE_MASK) {
1286 ret = wlan_custom_ioctl_auto_delete
1287 (pmpriv, pioctl_req, ie_data,
1288 index);
1289 /* if IE to delete is not found, return error */
1290 if (ret == MLAN_STATUS_FAILURE)
1291 goto done;
1292 index = ie_data->ie_index;
1293 memset(pmadapter, ie_data, 0,
1294 sizeof(custom_ie) *
1295 MAX_MGMT_IE_INDEX_TO_FW);
1296 len = 0;
1297 for (i = 0;
1298 i < pmadapter->max_mgmt_ie_index;
1299 i++) {
1300 /* Check if index is updated before sending to FW */
1301 if (index & ((t_u16)1) << i) {
1302 memcpy(pmadapter,
1303 (t_u8 *)ie_data +
1304 len, &i,
1305 sizeof(ie_data->
1306 ie_index));
1307 len += sizeof(ie_data->
1308 ie_index);
1309 memcpy(pmadapter,
1310 (t_u8 *)ie_data +
1311 len,
1312 &pmpriv->
1313 mgmt_ie[i].
1314 mgmt_subtype_mask,
1315 sizeof(ie_data->
1316 mgmt_subtype_mask));
1317 len += sizeof(ie_data->
1318 mgmt_subtype_mask);
1319 memcpy(pmadapter,
1320 (t_u8 *)ie_data +
1321 len,
1322 &pmpriv->
1323 mgmt_ie[i].
1324 ie_length,
1325 sizeof(ie_data->
1326 ie_length));
1327 len += sizeof(ie_data->
1328 ie_length);
1329 if (pmpriv->mgmt_ie[i].
1330 ie_length) {
1331 memcpy(pmadapter, (t_u8 *)ie_data + len, &pmpriv->mgmt_ie[i].ie_buffer, pmpriv->mgmt_ie[i].ie_length);
1332 len += pmpriv->
1333 mgmt_ie
1334 [i].
1335 ie_length;
1336 }
1337 }
1338 }
1339 misc->param.cust_ie.len += len;
1340 pioctl_req->action = MLAN_ACT_SET;
1341 cmd_action = HostCmd_ACT_GEN_SET;
1342 } else { /* Automatic Addition */
1343 if (MLAN_STATUS_FAILURE ==
1344 wlan_custom_ioctl_get_autoidx
1345 (pmpriv, pioctl_req, mask, ie_data,
1346 &index)) {
1347 PRINTM(MERROR,
1348 "Failed to Set the IE buffer\n");
1349 ret = MLAN_STATUS_FAILURE;
1350 goto done;
1351 }
1352 mask &= ~MLAN_CUSTOM_IE_NEW_MASK;
1353 if (MLAN_CUSTOM_IE_AUTO_IDX_MASK ==
1354 index) {
1355 ret = MLAN_STATUS_SUCCESS;
1356 goto done;
1357 }
1358 tmp_ie = (t_u8 *)&pmpriv->
1359 mgmt_ie[index].ie_buffer;
1360 memcpy(pmadapter,
1361 tmp_ie +
1362 pmpriv->mgmt_ie[index].ie_length,
1363 &ie_data->ie_buffer,
1364 ie_data->ie_length);
1365 pmpriv->mgmt_ie[index].ie_length +=
1366 ie_data->ie_length;
1367 pmpriv->mgmt_ie[index].ie_index = index;
1368 pmpriv->mgmt_ie[index].
1369 mgmt_subtype_mask = mask;
1370
1371 pioctl_req->action = MLAN_ACT_SET;
1372 cmd_action = HostCmd_ACT_GEN_SET;
1373 ie_data->ie_index = index;
1374 ie_data->ie_length =
1375 pmpriv->mgmt_ie[index].
1376 ie_length;
1377 memcpy(pmadapter, &ie_data->ie_buffer,
1378 &pmpriv->mgmt_ie[index].
1379 ie_buffer,
1380 pmpriv->mgmt_ie[index].
1381 ie_length);
1382 misc->param.cust_ie.len +=
1383 pmpriv->mgmt_ie[index].
1384 ie_length +
1385 MLAN_CUSTOM_IE_HDR_SIZE;
1386 }
1387 } else {
1388 if (index >= pmadapter->max_mgmt_ie_index) {
1389 PRINTM(MERROR,
1390 "Invalid custom IE index %d\n",
1391 index);
1392 ret = MLAN_STATUS_FAILURE;
1393 goto done;
1394 }
1395 /* Set/Clear the IE and save it */
1396 if (ie_data->mgmt_subtype_mask ==
1397 MLAN_CUSTOM_IE_DELETE_MASK &&
1398 ie_data->ie_length) {
1399 PRINTM(MINFO, "Clear the IE buffer\n");
1400 ret = wlan_custom_ioctl_auto_delete
1401 (pmpriv, pioctl_req, ie_data,
1402 index);
1403 /* if IE to delete is not found, return error */
1404 if (ret == MLAN_STATUS_FAILURE)
1405 goto done;
1406 memset(pmadapter, ie_data, 0,
1407 sizeof(custom_ie) *
1408 MAX_MGMT_IE_INDEX_TO_FW);
1409 memcpy(pmadapter, (t_u8 *)ie_data,
1410 &pmpriv->mgmt_ie[index],
1411 pmpriv->mgmt_ie[index].
1412 ie_length +
1413 MLAN_CUSTOM_IE_HDR_SIZE);
1414 } else {
1415 /*
1416 * Check if this index is being used on
1417 * any other interfaces. If yes, then
1418 * the request needs to be rejected.
1419 */
1420 ret = wlan_is_custom_ie_index_unused
1421 (pmpriv, index);
1422 if (ret == MLAN_STATUS_FAILURE) {
1423 PRINTM(MERROR,
1424 "IE index is used by other interface.\n");
1425 PRINTM(MERROR,
1426 "Set or delete on index %d is not allowed.\n",
1427 index);
1428 pioctl_req->status_code =
1429 MLAN_ERROR_IOCTL_FAIL;
1430 goto done;
1431 }
1432 PRINTM(MINFO, "Set the IE buffer\n");
1433 if (ie_data->mgmt_subtype_mask ==
1434 MLAN_CUSTOM_IE_DELETE_MASK)
1435 ie_data->ie_length = 0;
1436 else {
1437 if ((pmpriv->mgmt_ie[index].
1438 mgmt_subtype_mask ==
1439 ie_data->mgmt_subtype_mask)
1440 && (pmpriv->mgmt_ie[index].
1441 ie_length ==
1442 ie_data->ie_length) &&
1443 !memcmp(pmpriv->adapter,
1444 pmpriv->
1445 mgmt_ie[index].
1446 ie_buffer,
1447 ie_data->ie_buffer,
1448 ie_data->
1449 ie_length)) {
1450 PRINTM(MIOCTL,
1451 "same custom ie already configured!\n");
1452 if (ioctl_len <= 0 &&
1453 misc->param.cust_ie.
1454 len == 0) {
1455 goto done;
1456 } else {
1457 /* remove matching IE from app buffer */
1458 app_data_len -=
1459 ie_data->
1460 ie_length
1461 +
1462 MLAN_CUSTOM_IE_HDR_SIZE;
1463 memmove(pmadapter, (t_u8 *)ie_data, ie_data->ie_buffer + ie_data->ie_length, ioctl_len);
1464 continue;
1465 }
1466 }
1467 }
1468 memset(pmadapter,
1469 &pmpriv->mgmt_ie[index], 0,
1470 sizeof(custom_ie));
1471 memcpy(pmadapter,
1472 &pmpriv->mgmt_ie[index], ie_data,
1473 sizeof(custom_ie));
1474 }
1475
1476 misc->param.cust_ie.len +=
1477 pmpriv->mgmt_ie[index].ie_length +
1478 MLAN_CUSTOM_IE_HDR_SIZE;
1479 pioctl_req->action = MLAN_ACT_SET;
1480 cmd_action = HostCmd_ACT_GEN_SET;
1481 }
1482 }
1483 }
1484
1485 /* Send command to firmware */
1486 if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA) {
1487 ret = wlan_prepare_cmd(pmpriv,
1488 HostCmd_CMD_MGMT_IE_LIST,
1489 cmd_action,
1490 0,
1491 (send_ioctl) ? (t_void *)pioctl_req :
1492 MNULL, &misc->param.cust_ie);
1493 }
1494 #ifdef UAP_SUPPORT
1495 else if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP) {
1496 ret = wlan_prepare_cmd(pmpriv,
1497 HOST_CMD_APCMD_SYS_CONFIGURE,
1498 cmd_action,
1499 0,
1500 (send_ioctl) ? (t_void *)pioctl_req :
1501 MNULL,
1502 (send_ioctl) ? MNULL : &misc->param.
1503 cust_ie);
1504 }
1505 #endif
1506 if (ret == MLAN_STATUS_SUCCESS)
1507 ret = MLAN_STATUS_PENDING;
1508 done:
1509 LEAVE();
1510 return ret;
1511 }
1512
1513 /**
1514 * @brief Read/write adapter register
1515 *
1516 * @param pmadapter A pointer to mlan_adapter structure
1517 * @param pioctl_req A pointer to ioctl request buffer
1518 *
1519 * @return MLAN_STATUS_PENDING --success, otherwise fail
1520 */
1521 mlan_status
wlan_reg_mem_ioctl_reg_rw(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1522 wlan_reg_mem_ioctl_reg_rw(IN pmlan_adapter pmadapter,
1523 IN pmlan_ioctl_req pioctl_req)
1524 {
1525 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1526 mlan_ds_reg_mem *reg_mem = MNULL;
1527 mlan_status ret = MLAN_STATUS_SUCCESS;
1528 t_u16 cmd_action = 0, cmd_no;
1529
1530 ENTER();
1531
1532 reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
1533 if (pioctl_req->action == MLAN_ACT_GET)
1534 cmd_action = HostCmd_ACT_GEN_GET;
1535 else
1536 cmd_action = HostCmd_ACT_GEN_SET;
1537
1538 switch (reg_mem->param.reg_rw.type) {
1539 case MLAN_REG_MAC:
1540 cmd_no = HostCmd_CMD_MAC_REG_ACCESS;
1541 break;
1542 case MLAN_REG_BBP:
1543 cmd_no = HostCmd_CMD_BBP_REG_ACCESS;
1544 break;
1545 case MLAN_REG_RF:
1546 cmd_no = HostCmd_CMD_RF_REG_ACCESS;
1547 break;
1548 case MLAN_REG_CAU:
1549 cmd_no = HostCmd_CMD_CAU_REG_ACCESS;
1550 break;
1551 case MLAN_REG_PSU:
1552 cmd_no = HostCmd_CMD_TARGET_ACCESS;
1553 break;
1554 default:
1555 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1556 ret = MLAN_STATUS_FAILURE;
1557 goto exit;
1558 }
1559
1560 /* Send request to firmware */
1561 ret = wlan_prepare_cmd(pmpriv, cmd_no, cmd_action,
1562 0, (t_void *)pioctl_req,
1563 (t_void *)®_mem->param.reg_rw);
1564
1565 if (ret == MLAN_STATUS_SUCCESS)
1566 ret = MLAN_STATUS_PENDING;
1567
1568 exit:
1569 LEAVE();
1570 return ret;
1571 }
1572
1573 /**
1574 * @brief Read the EEPROM contents of the card
1575 *
1576 * @param pmadapter A pointer to mlan_adapter structure
1577 * @param pioctl_req A pointer to ioctl request buffer
1578 *
1579 * @return MLAN_STATUS_PENDING --success, otherwise fail
1580 */
1581 mlan_status
wlan_reg_mem_ioctl_read_eeprom(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1582 wlan_reg_mem_ioctl_read_eeprom(IN pmlan_adapter pmadapter,
1583 IN pmlan_ioctl_req pioctl_req)
1584 {
1585 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1586 mlan_ds_reg_mem *reg_mem = MNULL;
1587 mlan_status ret = MLAN_STATUS_SUCCESS;
1588 t_u16 cmd_action = 0;
1589
1590 ENTER();
1591
1592 reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
1593 if (pioctl_req->action == MLAN_ACT_GET)
1594 cmd_action = HostCmd_ACT_GEN_GET;
1595
1596 /* Send request to firmware */
1597 ret = wlan_prepare_cmd(pmpriv,
1598 HostCmd_CMD_802_11_EEPROM_ACCESS,
1599 cmd_action, 0, (t_void *)pioctl_req,
1600 (t_void *)®_mem->param.rd_eeprom);
1601
1602 if (ret == MLAN_STATUS_SUCCESS)
1603 ret = MLAN_STATUS_PENDING;
1604
1605 LEAVE();
1606 return ret;
1607 }
1608
1609 /**
1610 * @brief Read/write memory of device
1611 *
1612 * @param pmadapter A pointer to mlan_adapter structure
1613 * @param pioctl_req A pointer to ioctl request buffer
1614 *
1615 * @return MLAN_STATUS_PENDING --success, otherwise fail
1616 */
1617 mlan_status
wlan_reg_mem_ioctl_mem_rw(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1618 wlan_reg_mem_ioctl_mem_rw(IN pmlan_adapter pmadapter,
1619 IN pmlan_ioctl_req pioctl_req)
1620 {
1621 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1622 mlan_ds_reg_mem *reg_mem = MNULL;
1623 mlan_status ret = MLAN_STATUS_SUCCESS;
1624 t_u16 cmd_action = 0;
1625
1626 ENTER();
1627
1628 reg_mem = (mlan_ds_reg_mem *)pioctl_req->pbuf;
1629 if (pioctl_req->action == MLAN_ACT_GET)
1630 cmd_action = HostCmd_ACT_GEN_GET;
1631 else
1632 cmd_action = HostCmd_ACT_GEN_SET;
1633
1634 /* Send request to firmware */
1635 ret = wlan_prepare_cmd(pmpriv,
1636 HostCmd_CMD_MEM_ACCESS,
1637 cmd_action, 0,
1638 (t_void *)pioctl_req,
1639 (t_void *)®_mem->param.mem_rw);
1640
1641 if (ret == MLAN_STATUS_SUCCESS)
1642 ret = MLAN_STATUS_PENDING;
1643
1644 LEAVE();
1645 return ret;
1646 }
1647
1648 /**
1649 * @brief This function will check if station list is empty
1650 *
1651 * @param priv A pointer to mlan_private
1652 *
1653 * @return MFALSE/MTRUE
1654 */
1655 t_u8
wlan_is_station_list_empty(mlan_private * priv)1656 wlan_is_station_list_empty(mlan_private *priv)
1657 {
1658 ENTER();
1659 if (!(util_peek_list(priv->adapter->pmoal_handle,
1660 &priv->sta_list,
1661 priv->adapter->callbacks.moal_spin_lock,
1662 priv->adapter->callbacks.moal_spin_unlock))) {
1663 LEAVE();
1664 return MTRUE;
1665 }
1666 LEAVE();
1667 return MFALSE;
1668 }
1669
1670 /**
1671 * @brief This function will return the pointer to station entry in station list
1672 * table which matches the give mac address
1673 *
1674 * @param priv A pointer to mlan_private
1675 * @param mac mac address to find in station list table
1676 *
1677 * @return A pointer to structure sta_node
1678 */
1679 sta_node *
wlan_get_station_entry(mlan_private * priv,t_u8 * mac)1680 wlan_get_station_entry(mlan_private *priv, t_u8 *mac)
1681 {
1682 sta_node *sta_ptr;
1683
1684 ENTER();
1685
1686 if (!mac) {
1687 LEAVE();
1688 return MNULL;
1689 }
1690 sta_ptr = (sta_node *)util_peek_list(priv->adapter->pmoal_handle,
1691 &priv->sta_list,
1692 priv->adapter->callbacks.
1693 moal_spin_lock,
1694 priv->adapter->callbacks.
1695 moal_spin_unlock);
1696
1697 while (sta_ptr && (sta_ptr != (sta_node *)&priv->sta_list)) {
1698 if (!memcmp
1699 (priv->adapter, sta_ptr->mac_addr, mac,
1700 MLAN_MAC_ADDR_LENGTH)) {
1701 LEAVE();
1702 return sta_ptr;
1703 }
1704 sta_ptr = sta_ptr->pnext;
1705 }
1706 LEAVE();
1707 return MNULL;
1708 }
1709
1710 /**
1711 * @brief This function will add a pointer to station entry in station list
1712 * table with the give mac address, if it does not exist already
1713 *
1714 * @param priv A pointer to mlan_private
1715 * @param mac mac address to find in station list table
1716 *
1717 * @return A pointer to structure sta_node
1718 */
1719 sta_node *
wlan_add_station_entry(mlan_private * priv,t_u8 * mac)1720 wlan_add_station_entry(mlan_private *priv, t_u8 *mac)
1721 {
1722 sta_node *sta_ptr = MNULL;
1723 mlan_adapter *pmadapter = priv->adapter;
1724
1725 ENTER();
1726 pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
1727 priv->wmm.ra_list_spinlock);
1728
1729 sta_ptr = wlan_get_station_entry(priv, mac);
1730 if (sta_ptr)
1731 goto done;
1732 if (priv->adapter->callbacks.
1733 moal_malloc(priv->adapter->pmoal_handle, sizeof(sta_node),
1734 MLAN_MEM_DEF, (t_u8 **)&sta_ptr)) {
1735 PRINTM(MERROR, "Failed to allocate memory for station node\n");
1736 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
1737 priv->wmm.
1738 ra_list_spinlock);
1739 LEAVE();
1740 return MNULL;
1741 }
1742 memset(priv->adapter, sta_ptr, 0, sizeof(sta_node));
1743 memcpy(priv->adapter, sta_ptr->mac_addr, mac, MLAN_MAC_ADDR_LENGTH);
1744 util_enqueue_list_tail(priv->adapter->pmoal_handle, &priv->sta_list,
1745 (pmlan_linked_list)sta_ptr,
1746 priv->adapter->callbacks.moal_spin_lock,
1747 priv->adapter->callbacks.moal_spin_unlock);
1748 #ifdef DRV_EMBEDDED_AUTHENTICATOR
1749 if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
1750 IsAuthenticatorEnabled(priv->psapriv))
1751 authenticator_init_client(priv->psapriv,
1752 &sta_ptr->cm_connectioninfo, mac);
1753 #endif
1754 done:
1755 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
1756 priv->wmm.ra_list_spinlock);
1757 LEAVE();
1758 return sta_ptr;
1759 }
1760
1761 /**
1762 * @brief This function will delete a station entry from station list
1763 *
1764 *
1765 * @param priv A pointer to mlan_private
1766 * @param mac station's mac address
1767 *
1768 * @return N/A
1769 */
1770 t_void
wlan_delete_station_entry(mlan_private * priv,t_u8 * mac)1771 wlan_delete_station_entry(mlan_private *priv, t_u8 *mac)
1772 {
1773 sta_node *sta_ptr = MNULL;
1774 mlan_adapter *pmadapter = priv->adapter;
1775 ENTER();
1776 pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
1777 priv->wmm.ra_list_spinlock);
1778 sta_ptr = wlan_get_station_entry(priv, mac);
1779 if (sta_ptr) {
1780 #ifdef DRV_EMBEDDED_AUTHENTICATOR
1781 if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
1782 IsAuthenticatorEnabled(priv->psapriv))
1783 authenticator_free_client(priv->psapriv,
1784 sta_ptr->cm_connectioninfo);
1785 #endif
1786 util_unlink_list(priv->adapter->pmoal_handle, &priv->sta_list,
1787 (pmlan_linked_list)sta_ptr,
1788 priv->adapter->callbacks.moal_spin_lock,
1789 priv->adapter->callbacks.moal_spin_unlock);
1790 priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle,
1791 (t_u8 *)sta_ptr);
1792 }
1793 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
1794 priv->wmm.ra_list_spinlock);
1795 LEAVE();
1796 return;
1797 }
1798
1799 /**
1800 * @brief Clean up wapi station list
1801 *
1802 * @param priv Pointer to the mlan_private driver data struct
1803 *
1804 * @return N/A
1805 */
1806 t_void
wlan_delete_station_list(pmlan_private priv)1807 wlan_delete_station_list(pmlan_private priv)
1808 {
1809 sta_node *sta_ptr;
1810
1811 ENTER();
1812 while ((sta_ptr =
1813 (sta_node *)util_dequeue_list(priv->adapter->pmoal_handle,
1814 &priv->sta_list,
1815 priv->adapter->callbacks.
1816 moal_spin_lock,
1817 priv->adapter->callbacks.
1818 moal_spin_unlock))) {
1819 #ifdef DRV_EMBEDDED_AUTHENTICATOR
1820 if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) &&
1821 IsAuthenticatorEnabled(priv->psapriv))
1822 authenticator_free_client(priv->psapriv,
1823 sta_ptr->cm_connectioninfo);
1824 #endif
1825 priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle,
1826 (t_u8 *)sta_ptr);
1827 }
1828 LEAVE();
1829 return;
1830 }
1831
1832 /**
1833 * @brief Get tdls peer list
1834 *
1835 * @param priv A pointer to mlan_private structure
1836 * @param buf A pointer to tdls_peer_info buf
1837 * @return number of tdls peer
1838 */
1839 int
wlan_get_tdls_list(mlan_private * priv,tdls_peer_info * buf)1840 wlan_get_tdls_list(mlan_private *priv, tdls_peer_info *buf)
1841 {
1842 tdls_peer_info *peer_info = buf;
1843 sta_node *sta_ptr = MNULL;
1844 int count = 0;
1845 ENTER();
1846 if (priv->bss_type != MLAN_BSS_TYPE_STA) {
1847 LEAVE();
1848 return count;
1849 }
1850 sta_ptr = (sta_node *)util_peek_list(priv->adapter->pmoal_handle,
1851 &priv->sta_list,
1852 priv->adapter->callbacks.
1853 moal_spin_lock,
1854 priv->adapter->callbacks.
1855 moal_spin_unlock);
1856 if (!sta_ptr) {
1857 LEAVE();
1858 return count;
1859 }
1860 while (sta_ptr != (sta_node *)&priv->sta_list) {
1861 if (sta_ptr->status == TDLS_SETUP_COMPLETE) {
1862 peer_info->snr = sta_ptr->snr;
1863 peer_info->nf = sta_ptr->nf;
1864 memcpy(priv->adapter, peer_info->mac_addr,
1865 sta_ptr->mac_addr, MLAN_MAC_ADDR_LENGTH);
1866 memcpy(priv->adapter, peer_info->ht_cap,
1867 &sta_ptr->HTcap, sizeof(IEEEtypes_HTCap_t));
1868 memcpy(priv->adapter, peer_info->ext_cap,
1869 &sta_ptr->ExtCap, sizeof(IEEEtypes_ExtCap_t));
1870 peer_info++;
1871 count++;
1872 }
1873 sta_ptr = sta_ptr->pnext;
1874 if (count >= MLAN_MAX_TDLS_PEER_SUPPORTED)
1875 break;
1876 }
1877 LEAVE();
1878 return count;
1879 }
1880
1881 /**
1882 * @brief Set the TDLS configuration to FW.
1883 *
1884 * @param pmadapter A pointer to mlan_adapter structure
1885 * @param pioctl_req A pointer to ioctl request buffer
1886 *
1887 * @return MLAN_STATUS_PENDING --success, otherwise fail
1888 */
1889 mlan_status
wlan_misc_ioctl_tdls_config(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)1890 wlan_misc_ioctl_tdls_config(IN pmlan_adapter pmadapter,
1891 IN pmlan_ioctl_req pioctl_req)
1892 {
1893 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
1894 mlan_status ret = MLAN_STATUS_SUCCESS;
1895 mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
1896 tdls_all_config *tdls_all_cfg =
1897 (tdls_all_config *)misc->param.tdls_config.tdls_data;
1898 t_u8 event_buf[100];
1899 mlan_event *pevent = (mlan_event *)event_buf;
1900 tdls_tear_down_event *tdls_evt =
1901 (tdls_tear_down_event *)pevent->event_buf;
1902 sta_node *sta_ptr = MNULL;
1903 MrvlIEtypes_Data_t *pMrvlTlv = MNULL;
1904 t_u8 *pos = MNULL;
1905 t_u16 remain_len = 0;
1906
1907 ENTER();
1908
1909 if (misc->param.tdls_config.tdls_action == WLAN_TDLS_TEAR_DOWN_REQ) {
1910 sta_ptr =
1911 wlan_get_station_entry(pmpriv,
1912 tdls_all_cfg->u.tdls_tear_down.
1913 peer_mac_addr);
1914 if (sta_ptr && sta_ptr->external_tdls) {
1915 pevent->bss_index = pmpriv->bss_index;
1916 pevent->event_id = MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ;
1917 pevent->event_len = sizeof(tdls_tear_down_event);
1918 memcpy(pmpriv->adapter, (t_u8 *)tdls_evt->peer_mac_addr,
1919 tdls_all_cfg->u.tdls_tear_down.peer_mac_addr,
1920 MLAN_MAC_ADDR_LENGTH);
1921 tdls_evt->reason_code =
1922 tdls_all_cfg->u.tdls_tear_down.reason_code;
1923 wlan_recv_event(pmpriv,
1924 MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ,
1925 pevent);
1926 LEAVE();
1927 return ret;
1928 }
1929 }
1930 if (misc->param.tdls_config.tdls_action == WLAN_HOST_TDLS_CONFIG) {
1931 pmpriv->host_tdls_uapsd_support =
1932 tdls_all_cfg->u.host_tdls_cfg.uapsd_support;
1933 pmpriv->host_tdls_cs_support =
1934 tdls_all_cfg->u.host_tdls_cfg.cs_support;
1935 pos = tdls_all_cfg->u.host_tdls_cfg.tlv_buffer;
1936 remain_len = tdls_all_cfg->u.host_tdls_cfg.tlv_len;
1937 while (remain_len > sizeof(MrvlIEtypesHeader_t)) {
1938 remain_len -= sizeof(MrvlIEtypesHeader_t);
1939 pMrvlTlv = (MrvlIEtypes_Data_t *)pos;
1940 switch (pMrvlTlv->header.type) {
1941 case SUPPORTED_CHANNELS:
1942 pmpriv->chan_supp_len =
1943 (t_u8)pMrvlTlv->header.len;
1944 memset(pmadapter, pmpriv->chan_supp, 0,
1945 sizeof(pmpriv->chan_supp));
1946 memcpy(pmadapter, pmpriv->chan_supp,
1947 pMrvlTlv->data, MIN(pMrvlTlv->header.len,
1948 MAX_IE_SIZE));
1949 DBG_HEXDUMP(MCMD_D, "TDLS supported channel",
1950 pmpriv->chan_supp,
1951 pmpriv->chan_supp_len);
1952 break;
1953 case REGULATORY_CLASS:
1954 pmpriv->supp_regulatory_class_len =
1955 (t_u8)pMrvlTlv->header.len;
1956 memset(pmadapter, pmpriv->supp_regulatory_class,
1957 0,
1958 sizeof(pmpriv->supp_regulatory_class));
1959 memcpy(pmadapter, pmpriv->supp_regulatory_class,
1960 pMrvlTlv->data, MIN(pMrvlTlv->header.len,
1961 MAX_IE_SIZE));
1962 DBG_HEXDUMP(MCMD_D,
1963 "TDLS supported regulatory class",
1964 pmpriv->supp_regulatory_class,
1965 pmpriv->supp_regulatory_class_len);
1966 break;
1967 default:
1968 break;
1969 }
1970 remain_len -= pMrvlTlv->header.len;
1971 pos += sizeof(MrvlIEtypesHeader_t) +
1972 pMrvlTlv->header.len;
1973 }
1974 LEAVE();
1975 return ret;
1976 }
1977 pioctl_req->action = MLAN_ACT_SET;
1978
1979 /* Send command to firmware */
1980 ret = wlan_prepare_cmd(pmpriv,
1981 HostCmd_CMD_TDLS_CONFIG,
1982 HostCmd_ACT_GEN_SET,
1983 0,
1984 (t_void *)pioctl_req, &misc->param.tdls_config);
1985
1986 if (ret == MLAN_STATUS_SUCCESS)
1987 ret = MLAN_STATUS_PENDING;
1988 LEAVE();
1989 return ret;
1990 }
1991
1992 /**
1993 * @brief enable tdls config for cs and uapsd.
1994 *
1995 * @param pmpriv A pointer to mlan_private structure
1996 * @param enable MTRUE/MFALSE
1997 *
1998 * @return N/A
1999 */
2000 t_void
wlan_tdls_config(IN pmlan_private pmpriv,IN t_u8 enable)2001 wlan_tdls_config(IN pmlan_private pmpriv, IN t_u8 enable)
2002 {
2003 mlan_adapter *pmadapter = pmpriv->adapter;
2004 mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
2005 mlan_ds_misc_tdls_config *tdls_config = MNULL;
2006 tdls_all_config *tdls_all_cfg = MNULL;
2007 mlan_status ret = MLAN_STATUS_SUCCESS;
2008
2009 ENTER();
2010
2011 ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2012 sizeof(mlan_ds_misc_tdls_config), MLAN_MEM_DEF,
2013 (t_u8 **)&tdls_config);
2014 if (ret != MLAN_STATUS_SUCCESS || !tdls_config) {
2015 PRINTM(MERROR, "Memory allocation for tdls_config failed!\n");
2016 LEAVE();
2017 return;
2018 }
2019 memset(pmadapter, (t_u8 *)tdls_config, 0,
2020 sizeof(mlan_ds_misc_tdls_config));
2021 tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
2022 tdls_all_cfg->u.tdls_config.enable = enable;
2023 tdls_config->tdls_action = WLAN_TDLS_CONFIG;
2024 /* Send command to firmware */
2025 wlan_prepare_cmd(pmpriv,
2026 HostCmd_CMD_TDLS_CONFIG,
2027 HostCmd_ACT_GEN_SET, 0, MNULL, tdls_config);
2028 PRINTM(MCMND, "tdls_config: enable=%d\n", enable);
2029
2030 if (tdls_config)
2031 pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tdls_config);
2032
2033 LEAVE();
2034 }
2035
2036 /**
2037 * @brief set tdls channel switch parameters.
2038 *
2039 * @param pmpriv A pointer to mlan_private structure
2040 *
2041 * @return N/A
2042 */
2043 t_void
wlan_tdls_cs_param_config(IN pmlan_private pmpriv)2044 wlan_tdls_cs_param_config(IN pmlan_private pmpriv)
2045 {
2046 mlan_adapter *pmadapter = pmpriv->adapter;
2047 mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
2048 mlan_ds_misc_tdls_config *tdls_config = MNULL;
2049 tdls_all_config *tdls_all_cfg = MNULL;
2050 mlan_status ret = MLAN_STATUS_SUCCESS;
2051
2052 ENTER();
2053
2054 ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2055 sizeof(mlan_ds_misc_tdls_config), MLAN_MEM_DEF,
2056 (t_u8 **)&tdls_config);
2057 if (ret != MLAN_STATUS_SUCCESS || !tdls_config) {
2058 PRINTM(MERROR, "Memory allocation for tdls_config failed!\n");
2059 LEAVE();
2060 return;
2061 }
2062 memset(pmadapter, (t_u8 *)tdls_config, 0,
2063 sizeof(mlan_ds_misc_tdls_config));
2064
2065 tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
2066 tdls_config->tdls_action = WLAN_TDLS_CS_PARAMS;
2067 tdls_all_cfg->u.tdls_cs_params.unit_time = 2;
2068 tdls_all_cfg->u.tdls_cs_params.threshold_otherlink = 10;
2069 tdls_all_cfg->u.tdls_cs_params.threshold_directlink = 0;
2070
2071 /* Send command to firmware */
2072 wlan_prepare_cmd(pmpriv,
2073 HostCmd_CMD_TDLS_CONFIG,
2074 HostCmd_ACT_GEN_SET, 0, MNULL, tdls_config);
2075
2076 if (tdls_config)
2077 pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tdls_config);
2078
2079 LEAVE();
2080 }
2081
2082 /**
2083 * @brief start tdls channel switch
2084 *
2085 * @param pmpriv A pointer to mlan_private structure
2086 * @param peer_mac_addr A pointer to peer mac address
2087 * @param pioctl_buf A pointer to ioctl request buffer
2088 *
2089 * @return N/A
2090 */
2091 t_void
wlan_tdls_cs_start(IN pmlan_private pmpriv,IN t_u8 * peer_mac_addr,IN pmlan_ioctl_req pioctl_buf)2092 wlan_tdls_cs_start(IN pmlan_private pmpriv,
2093 IN t_u8 *peer_mac_addr, IN pmlan_ioctl_req pioctl_buf)
2094 {
2095 mlan_adapter *pmadapter = pmpriv->adapter;
2096 mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
2097 mlan_ds_misc_tdls_config *tdls_config = MNULL;
2098 tdls_all_config *tdls_all_cfg = MNULL;
2099 mlan_ds_misc_cfg *misc = MNULL;
2100 mlan_status ret = MLAN_STATUS_SUCCESS;
2101
2102 ENTER();
2103
2104 ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2105 sizeof(mlan_ds_misc_tdls_config), MLAN_MEM_DEF,
2106 (t_u8 **)&tdls_config);
2107 if (ret != MLAN_STATUS_SUCCESS || !tdls_config) {
2108 PRINTM(MERROR, "Memory allocation for tdls_config failed!\n");
2109 LEAVE();
2110 return;
2111 }
2112 memset(pmadapter, (t_u8 *)tdls_config, 0,
2113 sizeof(mlan_ds_misc_tdls_config));
2114
2115 if (pioctl_buf) {
2116 misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
2117 memcpy(pmpriv->adapter, tdls_config, &misc->param.tdls_config,
2118 sizeof(mlan_ds_misc_tdls_config));
2119 tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
2120 if (tdls_all_cfg->u.tdls_chan_switch.primary_channel > 14) {
2121 tdls_all_cfg->u.tdls_chan_switch.
2122 secondary_channel_offset =
2123 wlan_get_second_channel_offset(tdls_all_cfg->u.
2124 tdls_chan_switch.
2125 primary_channel);
2126 }
2127 PRINTM(MCMND, "Start TDLS CS: channel=%d\n",
2128 tdls_all_cfg->u.tdls_chan_switch.primary_channel);
2129 } else {
2130 tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
2131 tdls_config->tdls_action = WLAN_TDLS_INIT_CHAN_SWITCH;
2132 memcpy(pmpriv->adapter,
2133 tdls_all_cfg->u.tdls_chan_switch.peer_mac_addr,
2134 peer_mac_addr, MLAN_MAC_ADDR_LENGTH);
2135 tdls_all_cfg->u.tdls_chan_switch.primary_channel =
2136 pmpriv->tdls_cs_channel;
2137 if (pmpriv->tdls_cs_channel > 14) {
2138 tdls_all_cfg->u.tdls_chan_switch.band = BAND_5GHZ;
2139 tdls_all_cfg->u.tdls_chan_switch.
2140 secondary_channel_offset =
2141 wlan_get_second_channel_offset(pmpriv->
2142 tdls_cs_channel);
2143 } else {
2144 tdls_all_cfg->u.tdls_chan_switch.band = BAND_2GHZ;
2145 }
2146 PRINTM(MCMND, "Start TDLS CS: channel=%d\n",
2147 pmpriv->tdls_cs_channel);
2148 }
2149 tdls_all_cfg->u.tdls_chan_switch.switch_time = 10;
2150 tdls_all_cfg->u.tdls_chan_switch.switch_timeout = 16;
2151 tdls_all_cfg->u.tdls_chan_switch.regulatory_class = 12;
2152 tdls_all_cfg->u.tdls_chan_switch.periodicity = 1;
2153
2154 /* Send command to firmware */
2155 wlan_prepare_cmd(pmpriv,
2156 HostCmd_CMD_TDLS_CONFIG,
2157 HostCmd_ACT_GEN_SET, 0, MNULL, tdls_config);
2158
2159 if (tdls_config)
2160 pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tdls_config);
2161
2162 LEAVE();
2163 }
2164
2165 /**
2166 * @brief stop tdls channel switch
2167 *
2168 * @param pmpriv A pointer to mlan_private structure
2169 * @param peer_mac_addr A pointer to peer mac address
2170 * @return N/A
2171 */
2172 t_void
wlan_tdls_cs_stop(IN pmlan_private pmpriv,IN t_u8 * peer_mac_addr)2173 wlan_tdls_cs_stop(IN pmlan_private pmpriv, IN t_u8 *peer_mac_addr)
2174 {
2175 mlan_adapter *pmadapter = pmpriv->adapter;
2176 mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
2177 mlan_ds_misc_tdls_config *tdls_config = MNULL;
2178 tdls_all_config *tdls_all_cfg = MNULL;
2179 mlan_status ret = MLAN_STATUS_SUCCESS;
2180
2181 ENTER();
2182
2183 ret = pcb->moal_malloc(pmadapter->pmoal_handle,
2184 sizeof(mlan_ds_misc_tdls_config), MLAN_MEM_DEF,
2185 (t_u8 **)&tdls_config);
2186 if (ret != MLAN_STATUS_SUCCESS || !tdls_config) {
2187 PRINTM(MERROR, "Memory allocation for tdls_config failed!\n");
2188 LEAVE();
2189 return;
2190 }
2191 memset(pmadapter, (t_u8 *)tdls_config, 0,
2192 sizeof(mlan_ds_misc_tdls_config));
2193
2194 tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
2195 tdls_config->tdls_action = WLAN_TDLS_STOP_CHAN_SWITCH;
2196
2197 memcpy(pmpriv->adapter,
2198 tdls_all_cfg->u.tdls_stop_chan_switch.peer_mac_addr,
2199 peer_mac_addr, MLAN_MAC_ADDR_LENGTH);
2200 PRINTM(MCMND, "Stop TDLS CS\n");
2201 /* Send command to firmware */
2202 wlan_prepare_cmd(pmpriv,
2203 HostCmd_CMD_TDLS_CONFIG,
2204 HostCmd_ACT_GEN_SET, 0, MNULL, tdls_config);
2205
2206 if (tdls_config)
2207 pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)tdls_config);
2208
2209 LEAVE();
2210 }
2211
2212 /**
2213 * @brief Set/Get the TDLS off channel.
2214 *
2215 * @param pmadapter A pointer to mlan_adapter structure
2216 * @param pioctl_req A pointer to ioctl request buffer
2217 *
2218 * @return MLAN_STATUS_PENDING --success, otherwise fail
2219 */
2220 mlan_status
wlan_misc_ioctl_tdls_cs_channel(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2221 wlan_misc_ioctl_tdls_cs_channel(IN pmlan_adapter pmadapter,
2222 IN pmlan_ioctl_req pioctl_req)
2223 {
2224 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2225 mlan_status ret = MLAN_STATUS_SUCCESS;
2226 mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2227
2228 ENTER();
2229
2230 if (MLAN_ACT_GET == pioctl_req->action)
2231 misc->param.tdls_cs_channel = pmpriv->tdls_cs_channel;
2232 else if (MLAN_ACT_SET == pioctl_req->action) {
2233 pmpriv->tdls_cs_channel = misc->param.tdls_cs_channel;
2234
2235 }
2236 LEAVE();
2237 return ret;
2238 }
2239
2240 /**
2241 * @brief Set/Get the TDLS idle time.
2242 *
2243 * @param pmadapter A pointer to mlan_adapter structure
2244 * @param pioctl_req A pointer to ioctl request buffer
2245 *
2246 * @return MLAN_STATUS_PENDING --success, otherwise fail
2247 */
2248 mlan_status
wlan_misc_ioctl_tdls_idle_time(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2249 wlan_misc_ioctl_tdls_idle_time(IN pmlan_adapter pmadapter,
2250 IN pmlan_ioctl_req pioctl_req)
2251 {
2252 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2253 mlan_status ret = MLAN_STATUS_SUCCESS;
2254 mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2255
2256 ENTER();
2257
2258 if (MLAN_ACT_GET == pioctl_req->action) {
2259 misc->param.tdls_idle_time = pmpriv->tdls_idle_time;
2260 } else if (MLAN_ACT_SET == pioctl_req->action) {
2261 pmpriv->tdls_idle_time = misc->param.tdls_idle_time;
2262 }
2263 LEAVE();
2264 return ret;
2265 }
2266
2267 /**
2268 * @brief Set the TDLS operation to FW.
2269 *
2270 * @param pmadapter A pointer to mlan_adapter structure
2271 * @param pioctl_req A pointer to ioctl request buffer
2272 *
2273 * @return MLAN_STATUS_PENDING --success, otherwise fail
2274 */
2275 mlan_status
wlan_misc_ioctl_tdls_oper(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2276 wlan_misc_ioctl_tdls_oper(IN pmlan_adapter pmadapter,
2277 IN pmlan_ioctl_req pioctl_req)
2278 {
2279 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2280 mlan_status ret = MLAN_STATUS_SUCCESS;
2281 mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2282 mlan_ds_misc_tdls_oper *ptdls_oper = &misc->param.tdls_oper;
2283 t_u8 event_buf[100];
2284 mlan_event *ptdls_event = (mlan_event *)event_buf;
2285 tdls_tear_down_event *tdls_evt =
2286 (tdls_tear_down_event *)ptdls_event->event_buf;
2287 sta_node *sta_ptr = MNULL;
2288 t_u8 i = 0;
2289
2290 ENTER();
2291 sta_ptr = wlan_get_station_entry(pmpriv, ptdls_oper->peer_mac);
2292 switch (ptdls_oper->tdls_action) {
2293 case WLAN_TDLS_ENABLE_LINK:
2294 if (sta_ptr && (sta_ptr->status != TDLS_SETUP_FAILURE)) {
2295 PRINTM(MMSG, "TDLS: Enable link " MACSTR " success\n",
2296 MAC2STR(ptdls_oper->peer_mac));
2297 sta_ptr->status = TDLS_SETUP_COMPLETE;
2298 pmadapter->tdls_status = TDLS_IN_BASE_CHANNEL;
2299 if (!pmpriv->txaggrctrl)
2300 wlan_11n_send_delba_to_peer(pmpriv,
2301 pmpriv->
2302 curr_bss_params.
2303 bss_descriptor.
2304 mac_address);
2305 if (sta_ptr->HTcap.ieee_hdr.element_id == HT_CAPABILITY) {
2306 sta_ptr->is_11n_enabled = MTRUE;
2307 if (GETHT_MAXAMSDU
2308 (sta_ptr->HTcap.ht_cap.ht_cap_info))
2309 sta_ptr->max_amsdu =
2310 MLAN_TX_DATA_BUF_SIZE_8K;
2311 else
2312 sta_ptr->max_amsdu =
2313 MLAN_TX_DATA_BUF_SIZE_4K;
2314 for (i = 0; i < MAX_NUM_TID; i++) {
2315 if (sta_ptr->is_11n_enabled)
2316 sta_ptr->ampdu_sta[i] =
2317 pmpriv->
2318 aggr_prio_tbl[i].
2319 ampdu_user;
2320 else
2321 sta_ptr->ampdu_sta[i] =
2322 BA_STREAM_NOT_ALLOWED;
2323 }
2324 memset(pmpriv->adapter, sta_ptr->rx_seq, 0xff,
2325 sizeof(sta_ptr->rx_seq));
2326 }
2327 wlan_restore_tdls_packets(pmpriv, ptdls_oper->peer_mac,
2328 TDLS_SETUP_COMPLETE);
2329 if (ISSUPP_EXTCAP_TDLS_CHAN_SWITCH
2330 (sta_ptr->ExtCap.ext_cap)) {
2331 wlan_tdls_config(pmpriv, MTRUE);
2332 wlan_tdls_cs_param_config(pmpriv);
2333 /**tdls cs start*/
2334 if (pmpriv->tdls_cs_channel &&
2335 pmpriv->tdls_cs_channel !=
2336 pmpriv->curr_bss_params.bss_descriptor.
2337 channel)
2338 wlan_tdls_cs_start(pmpriv,
2339 ptdls_oper->peer_mac,
2340 MNULL);
2341 }
2342 } else {
2343 PRINTM(MMSG, "TDLS: Enable link " MACSTR " fail\n",
2344 MAC2STR(ptdls_oper->peer_mac));
2345 /*for supplicant 2.0, we need send event to request teardown,
2346 **for latest supplicant, we only need return fail, and supplicant will send teardown packet and disable tdls link*/
2347 if (sta_ptr) {
2348 ptdls_event->bss_index = pmpriv->bss_index;
2349 ptdls_event->event_id =
2350 MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ;
2351 ptdls_event->event_len =
2352 sizeof(tdls_tear_down_event);
2353 memcpy(pmpriv->adapter,
2354 (t_u8 *)tdls_evt->peer_mac_addr,
2355 ptdls_oper->peer_mac,
2356 MLAN_MAC_ADDR_LENGTH);
2357 tdls_evt->reason_code =
2358 MLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
2359 wlan_recv_event(pmpriv,
2360 MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ,
2361 ptdls_event);
2362 wlan_restore_tdls_packets(pmpriv,
2363 ptdls_oper->peer_mac,
2364 TDLS_TEAR_DOWN);
2365 if (sta_ptr->is_11n_enabled) {
2366 wlan_cleanup_reorder_tbl(pmpriv,
2367 ptdls_oper->
2368 peer_mac);
2369 wlan_11n_cleanup_txbastream_tbl(pmpriv,
2370 ptdls_oper->
2371 peer_mac);
2372 }
2373 wlan_delete_station_entry(pmpriv,
2374 ptdls_oper->peer_mac);
2375 if (MTRUE == wlan_is_station_list_empty(pmpriv))
2376 pmadapter->tdls_status = TDLS_NOT_SETUP;
2377 else
2378 pmadapter->tdls_status =
2379 TDLS_IN_BASE_CHANNEL;
2380 }
2381 ret = MLAN_STATUS_FAILURE;
2382 }
2383 wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
2384 MNULL);
2385 break;
2386 case WLAN_TDLS_DISABLE_LINK:
2387 /* Send command to firmware to delete tdls link */
2388 ret = wlan_prepare_cmd(pmpriv,
2389 HostCmd_CMD_TDLS_OPERATION,
2390 HostCmd_ACT_GEN_SET,
2391 0, (t_void *)pioctl_req, ptdls_oper);
2392 if (ret == MLAN_STATUS_SUCCESS)
2393 ret = MLAN_STATUS_PENDING;
2394 break;
2395 case WLAN_TDLS_CREATE_LINK:
2396 PRINTM(MIOCTL, "CREATE TDLS LINK\n");
2397 if (sta_ptr && sta_ptr->status == TDLS_SETUP_INPROGRESS) {
2398 PRINTM(MIOCTL, "We already create the link\n");
2399 break;
2400 }
2401 if (!sta_ptr)
2402 sta_ptr =
2403 wlan_add_station_entry(pmpriv,
2404 misc->param.tdls_oper.
2405 peer_mac);
2406 if (sta_ptr) {
2407 sta_ptr->status = TDLS_SETUP_INPROGRESS;
2408 sta_ptr->external_tdls = MTRUE;
2409 wlan_hold_tdls_packets(pmpriv,
2410 misc->param.tdls_oper.peer_mac);
2411 }
2412 ret = wlan_prepare_cmd(pmpriv,
2413 HostCmd_CMD_TDLS_OPERATION,
2414 HostCmd_ACT_GEN_SET,
2415 0, (t_void *)pioctl_req, ptdls_oper);
2416 if (ret == MLAN_STATUS_SUCCESS)
2417 ret = MLAN_STATUS_PENDING;
2418 break;
2419 case WLAN_TDLS_CONFIG_LINK:
2420 if (!sta_ptr || sta_ptr->status == TDLS_SETUP_FAILURE) {
2421 PRINTM(MERROR, "Can not CONFIG TDLS Link\n");
2422 ret = MLAN_STATUS_FAILURE;
2423 break;
2424 }
2425 ret = wlan_prepare_cmd(pmpriv,
2426 HostCmd_CMD_TDLS_OPERATION,
2427 HostCmd_ACT_GEN_SET,
2428 0, (t_void *)pioctl_req, ptdls_oper);
2429 if (ret == MLAN_STATUS_SUCCESS)
2430 ret = MLAN_STATUS_PENDING;
2431 break;
2432 case WLAN_TDLS_INIT_CHAN_SWITCH:
2433 if (sta_ptr &&
2434 ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(sta_ptr->ExtCap.ext_cap)) {
2435 wlan_tdls_config(pmpriv, MTRUE);
2436 wlan_tdls_cs_param_config(pmpriv);
2437 /**tdls cs start*/
2438 wlan_tdls_cs_start(pmpriv, ptdls_oper->peer_mac,
2439 pioctl_req);
2440 }
2441 wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
2442 MNULL);
2443 break;
2444 default:
2445 break;
2446 }
2447 LEAVE();
2448 return ret;
2449 }
2450
2451 /**
2452 * @brief Get AP's ext capability
2453 *
2454 * @param pmpriv A pointer to mlan_adapter structure
2455 * @param ext_cap A pointer to ExtCap_t structure
2456 *
2457 * @return MLAN_STATUS_PENDING --success, otherwise fail
2458 */
2459 void
wlan_get_ap_ext_cap(mlan_private * pmpriv,ExtCap_t * ext_cap)2460 wlan_get_ap_ext_cap(mlan_private *pmpriv, ExtCap_t *ext_cap)
2461 {
2462 pmlan_adapter pmadapter = pmpriv->adapter;
2463 BSSDescriptor_t *pbss_desc;
2464 pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
2465 memset(pmadapter, ext_cap, 0, sizeof(ExtCap_t));
2466 if (pbss_desc->pext_cap) {
2467 memcpy(pmadapter, (t_u8 *)ext_cap,
2468 (t_u8 *)pbss_desc->pext_cap + sizeof(IEEEtypes_Header_t),
2469 pbss_desc->pext_cap->ieee_hdr.len);
2470 }
2471 return;
2472 }
2473
2474 /**
2475 * @brief Set the TDLS operation to FW.
2476 *
2477 * @param pmadapter A pointer to mlan_adapter structure
2478 * @param pioctl_req A pointer to ioctl request buffer
2479 *
2480 * @return MLAN_STATUS_PENDING --success, otherwise fail
2481 */
2482 mlan_status
wlan_misc_ioctl_tdls_get_ies(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2483 wlan_misc_ioctl_tdls_get_ies(IN pmlan_adapter pmadapter,
2484 IN pmlan_ioctl_req pioctl_req)
2485 {
2486 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
2487 mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2488 mlan_ds_misc_tdls_ies *tdls_ies = &misc->param.tdls_ies;
2489 mlan_status ret = MLAN_STATUS_SUCCESS;
2490 BSSDescriptor_t *pbss_desc;
2491 t_u32 usr_dot_11n_dev_cap;
2492 IEEEtypes_ExtCap_t *ext_cap = MNULL;
2493 ExtCap_t ap_ext_cap;
2494 IEEEtypes_HTCap_t *ht_cap = MNULL;
2495 IEEEtypes_HTInfo_t *ht_info = MNULL;
2496 t_u8 supp_chan[] = { 1, 11 };
2497 t_u8 regulatory_class[] = { 1,
2498 /**current class*/
2499 1, 2, 3, 4, 12, 22, 23, 24, 25, 27, 28, 29, 30, 32, 33
2500 }; /**list regulatory class*/
2501 IEEEtypes_Generic_t *pSupp_chan = MNULL, *pRegulatory_class = MNULL;
2502 sta_node *sta_ptr = MNULL;
2503 ENTER();
2504
2505 /* We don't need peer information for TDLS setup */
2506 if (!(tdls_ies->flags & TDLS_IE_FLAGS_SETUP))
2507 sta_ptr = wlan_get_station_entry(pmpriv, tdls_ies->peer_mac);
2508 pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
2509 wlan_get_ap_ext_cap(pmpriv, &ap_ext_cap);
2510 if (pbss_desc->bss_band & BAND_A)
2511 usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_a;
2512 else
2513 usr_dot_11n_dev_cap = pmpriv->usr_dot_11n_dev_cap_bg;
2514
2515 /** fill the extcap */
2516 if (tdls_ies->flags & TDLS_IE_FLAGS_EXTCAP) {
2517 ext_cap = (IEEEtypes_ExtCap_t *)tdls_ies->ext_cap;
2518 ext_cap->ieee_hdr.element_id = EXT_CAPABILITY;
2519 ext_cap->ieee_hdr.len = sizeof(ExtCap_t);
2520 SET_EXTCAP_TDLS(ext_cap->ext_cap);
2521 RESET_EXTCAP_TDLS_UAPSD(ext_cap->ext_cap);
2522 RESET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap->ext_cap);
2523
2524 if (pmpriv->host_tdls_uapsd_support) {
2525 /* uapsd in tdls confirm frame */
2526 if (tdls_ies->flags & TDLS_IE_FLAGS_HTINFO) {
2527 if (sta_ptr &&
2528 ISSUPP_EXTCAP_TDLS_UAPSD(sta_ptr->ExtCap.
2529 ext_cap))
2530 SET_EXTCAP_TDLS_UAPSD(ext_cap->ext_cap);
2531 } else {
2532 SET_EXTCAP_TDLS_UAPSD(ext_cap->ext_cap);
2533 }
2534 }
2535 /* channel switch support */
2536 if (pmpriv->host_tdls_cs_support &&
2537 !IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ap_ext_cap)) {
2538 /* channel switch in tdls confirm frame */
2539 if (tdls_ies->flags & TDLS_IE_FLAGS_HTINFO) {
2540 if (sta_ptr &&
2541 ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(sta_ptr->
2542 ExtCap.
2543 ext_cap))
2544 SET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap->
2545 ext_cap);
2546 } else {
2547 SET_EXTCAP_TDLS_CHAN_SWITCH(ext_cap->ext_cap);
2548 }
2549 }
2550
2551 DBG_HEXDUMP(MCMD_D, "TDLS extcap", tdls_ies->ext_cap,
2552 sizeof(IEEEtypes_ExtCap_t));
2553 }
2554
2555 /** default qos info is 0xf, compare with peer device qos info for tdls confirm */
2556 if (tdls_ies->flags & TDLS_IE_FLAGS_QOS_INFO) {
2557 if (sta_ptr && sta_ptr->rate_len)
2558 tdls_ies->QosInfo = sta_ptr->qos_info & 0xf;
2559 PRINTM(MCMND, "TDLS Qos info=0x%x\n", tdls_ies->QosInfo);
2560 }
2561
2562 /** fill the htcap based on hwspec */
2563 if (tdls_ies->flags & TDLS_IE_FLAGS_HTCAP) {
2564 ht_cap = (IEEEtypes_HTCap_t *)tdls_ies->ht_cap;
2565 memset(pmadapter, ht_cap, 0, sizeof(IEEEtypes_HTCap_t));
2566 if ((sta_ptr &&
2567 !ISSUPP_EXTCAP_TDLS_CHAN_SWITCH(sta_ptr->ExtCap.ext_cap))
2568 || IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ap_ext_cap))
2569 wlan_fill_ht_cap_ie(pmpriv, ht_cap,
2570 pbss_desc->bss_band);
2571 else if (pmpriv->host_tdls_cs_support &&
2572 (pmadapter->fw_bands & BAND_A))
2573 wlan_fill_ht_cap_ie(pmpriv, ht_cap, BAND_A);
2574 else
2575 wlan_fill_ht_cap_ie(pmpriv, ht_cap,
2576 pbss_desc->bss_band);
2577 DBG_HEXDUMP(MCMD_D, "TDLS htcap", tdls_ies->ht_cap,
2578 sizeof(IEEEtypes_HTCap_t));
2579 }
2580 /** fill the htinfo */
2581 if (tdls_ies->flags & TDLS_IE_FLAGS_HTINFO) {
2582 ht_info = (IEEEtypes_HTInfo_t *)tdls_ies->ht_info;
2583 pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
2584 ht_info->ieee_hdr.element_id = HT_OPERATION;
2585 ht_info->ieee_hdr.len = sizeof(HTInfo_t);
2586 ht_info->ht_info.pri_chan = pbss_desc->channel;
2587 /* follow AP's channel bandwidth */
2588 if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) &&
2589 pbss_desc->pht_info &&
2590 ISALLOWED_CHANWIDTH40(pbss_desc->pht_info->ht_info.
2591 field2)) {
2592 ht_info->ht_info.field2 =
2593 pbss_desc->pht_info->ht_info.field2;
2594 } else {
2595 ht_info->ht_info.field2 =
2596 wlan_get_second_channel_offset(pbss_desc->
2597 channel);
2598 }
2599 if (sta_ptr)
2600 memcpy(pmadapter, &sta_ptr->HTInfo, tdls_ies->ht_info,
2601 sizeof(IEEEtypes_HTInfo_t));
2602 DBG_HEXDUMP(MCMD_D, "TDLS htinfo", tdls_ies->ht_info,
2603 sizeof(IEEEtypes_HTInfo_t));
2604 }
2605
2606 /** supported channels andl regulatory IE*/
2607 if (pmpriv->host_tdls_cs_support &&
2608 (tdls_ies->flags & TDLS_IE_FLAGS_SUPP_CS_IE)
2609 && !IS_EXTCAP_TDLS_CHLSWITCHPROHIB(ap_ext_cap)) {
2610 /** supported channels IE*/
2611 pSupp_chan = (IEEEtypes_Generic_t *)tdls_ies->supp_chan;
2612 pSupp_chan->ieee_hdr.element_id = SUPPORTED_CHANNELS;
2613 if (pmpriv->chan_supp_len) {
2614 pSupp_chan->ieee_hdr.len = pmpriv->chan_supp_len;
2615 memcpy(pmadapter, pSupp_chan->data, pmpriv->chan_supp,
2616 pmpriv->chan_supp_len);
2617 } else {
2618 pSupp_chan->ieee_hdr.len = sizeof(supp_chan);
2619 memcpy(pmadapter, pSupp_chan->data, supp_chan,
2620 sizeof(supp_chan));
2621 }
2622 DBG_HEXDUMP(MCMD_D, "TDLS supported channel",
2623 tdls_ies->supp_chan,
2624 pSupp_chan->ieee_hdr.len +
2625 sizeof(IEEEtypes_Header_t));
2626
2627 /**fill supported Regulatory Class IE*/
2628 pRegulatory_class =
2629 (IEEEtypes_Generic_t *)tdls_ies->regulatory_class;
2630 pRegulatory_class->ieee_hdr.element_id = REGULATORY_CLASS;
2631 if (pmpriv->supp_regulatory_class_len) {
2632 pRegulatory_class->ieee_hdr.len =
2633 pmpriv->supp_regulatory_class_len;
2634 memcpy(pmadapter, pRegulatory_class->data,
2635 pmpriv->supp_regulatory_class,
2636 pmpriv->supp_regulatory_class_len);
2637 } else {
2638 pRegulatory_class->ieee_hdr.len =
2639 sizeof(regulatory_class);
2640 memcpy(pmadapter, pRegulatory_class->data,
2641 regulatory_class, sizeof(regulatory_class));
2642 }
2643 DBG_HEXDUMP(MCMD_D, "TDLS supported regulatory class",
2644 tdls_ies->regulatory_class,
2645 pRegulatory_class->ieee_hdr.len +
2646 sizeof(IEEEtypes_Header_t));
2647 }
2648 LEAVE();
2649 return ret;
2650 }
2651
2652 /**
2653 * @brief Get extended version information
2654 *
2655 * @param pmadapter A pointer to mlan_adapter structure
2656 * @param pioctl_req A pointer to ioctl request buffer
2657 *
2658 * @return MLAN_STATUS_PENDING --success, otherwise fail
2659 */
2660 mlan_status
wlan_get_info_ver_ext(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2661 wlan_get_info_ver_ext(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
2662 {
2663 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
2664 mlan_ds_get_info *pinfo = (mlan_ds_get_info *)pioctl_req->pbuf;
2665 mlan_status ret = MLAN_STATUS_SUCCESS;
2666
2667 ENTER();
2668
2669 /* Send request to firmware */
2670 ret = wlan_prepare_cmd(pmpriv,
2671 HostCmd_CMD_VERSION_EXT,
2672 HostCmd_ACT_GEN_GET,
2673 0,
2674 (t_void *)pioctl_req,
2675 &pinfo->param.ver_ext.version_str_sel);
2676
2677 if (ret == MLAN_STATUS_SUCCESS)
2678 ret = MLAN_STATUS_PENDING;
2679
2680 LEAVE();
2681 return ret;
2682 }
2683
2684 #ifdef DEBUG_LEVEL1
2685 /**
2686 * @brief Set driver debug bit masks in order to enhance performance
2687 *
2688 * @param pmadapter A pointer to mlan_adapter structure
2689 * @param pioctl_req A pointer to ioctl request buffer
2690 *
2691 * @return MLAN_STATUS_PENDING --success, otherwise fail
2692 */
2693 mlan_status
wlan_set_drvdbg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2694 wlan_set_drvdbg(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
2695 {
2696 mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2697 mlan_status ret = MLAN_STATUS_SUCCESS;
2698
2699 ENTER();
2700
2701 /* Set driver debug bit masks */
2702 mlan_drvdbg = misc->param.drvdbg;
2703
2704 LEAVE();
2705 return ret;
2706 }
2707 #endif
2708
2709 /**
2710 * @brief Rx mgmt frame forward register
2711 *
2712 * @param pmadapter A pointer to mlan_adapter structure
2713 * @param pioctl_req A pointer to ioctl request buffer
2714 *
2715 * @return MLAN_STATUS_PENDING --success, otherwise fail
2716 */
2717 mlan_status
wlan_reg_rx_mgmt_ind(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2718 wlan_reg_rx_mgmt_ind(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
2719 {
2720 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
2721 mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2722 mlan_status ret = MLAN_STATUS_SUCCESS;
2723
2724 ENTER();
2725
2726 /* Set passthru mask for mgmt frame */
2727 pmpriv->mgmt_frame_passthru_mask = misc->param.mgmt_subtype_mask;
2728
2729 /* Send request to firmware */
2730 ret = wlan_prepare_cmd(pmpriv,
2731 HostCmd_CMD_RX_MGMT_IND,
2732 pioctl_req->action,
2733 0,
2734 (t_void *)pioctl_req,
2735 &misc->param.mgmt_subtype_mask);
2736
2737 if (ret == MLAN_STATUS_SUCCESS)
2738 ret = MLAN_STATUS_PENDING;
2739
2740 LEAVE();
2741 return ret;
2742 }
2743
2744 /**
2745 * @brief This function processes the 802.11 mgmt Frame
2746 *
2747 * @param priv A pointer to mlan_private
2748 *
2749 * @param payload A pointer to the received buffer
2750 * @param payload_len Length of the received buffer
2751 * @param prx_pd A pointer to RxPD
2752 *
2753 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
2754 */
2755 mlan_status
wlan_process_802dot11_mgmt_pkt(IN mlan_private * priv,IN t_u8 * payload,IN t_u32 payload_len,IN RxPD * prx_pd)2756 wlan_process_802dot11_mgmt_pkt(IN mlan_private *priv,
2757 IN t_u8 *payload,
2758 IN t_u32 payload_len, IN RxPD *prx_pd)
2759 {
2760 pmlan_adapter pmadapter = priv->adapter;
2761 pmlan_callbacks pcb = &pmadapter->callbacks;
2762 mlan_status ret = MLAN_STATUS_SUCCESS;
2763 wlan_802_11_header *pieee_pkt_hdr = MNULL;
2764 t_u16 sub_type = 0;
2765 t_u8 *event_buf = MNULL;
2766 mlan_event *pevent = MNULL;
2767 t_u8 unicast = 0;
2768 IEEE80211_MGMT *mgmt = MNULL;
2769 t_u8 category = 0;
2770 t_u8 action_code = 0;
2771 struct timestamps tstamps;
2772 ENTER();
2773 if (payload_len > (MAX_EVENT_SIZE - sizeof(mlan_event))) {
2774 PRINTM(MERROR, "Dropping large mgmt frame,len =%d\n",
2775 payload_len);
2776 LEAVE();
2777 return ret;
2778 }
2779 /* Check packet type-subtype and compare with mgmt_passthru_mask
2780 * If event is needed to host, just eventify it */
2781 pieee_pkt_hdr = (wlan_802_11_header *)payload;
2782 sub_type = IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE(pieee_pkt_hdr->frm_ctl);
2783 if (((1 << sub_type) & priv->mgmt_frame_passthru_mask) == 0) {
2784 PRINTM(MINFO, "Dropping mgmt frame for subtype %d snr=%d.\n",
2785 sub_type, prx_pd->snr);
2786 LEAVE();
2787 return ret;
2788 }
2789 switch (sub_type) {
2790 case SUBTYPE_ASSOC_REQUEST:
2791 case SUBTYPE_REASSOC_REQUEST:
2792 case SUBTYPE_DISASSOC:
2793 case SUBTYPE_DEAUTH:
2794 case SUBTYPE_AUTH:
2795 case SUBTYPE_PROBE_RESP:
2796 unicast = MTRUE;
2797 break;
2798 case SUBTYPE_ACTION:
2799 category = *(payload + sizeof(wlan_802_11_header));
2800 action_code = *(payload + sizeof(wlan_802_11_header) + 1);
2801 if (category == IEEE_MGMT_ACTION_CATEGORY_BLOCK_ACK) {
2802 PRINTM(MINFO,
2803 "Drop BLOCK ACK action frame: action_code=%d\n",
2804 action_code);
2805 LEAVE();
2806 return ret;
2807 }
2808 if ((category == IEEE_MGMT_ACTION_CATEGORY_PUBLIC) &&
2809 (action_code == BSS_20_40_COEX)) {
2810 PRINTM(MINFO,
2811 "Drop 20/40 BSS Coexistence Management frame\n");
2812 LEAVE();
2813 return ret;
2814 }
2815 if ((category == CATEGORY_PUBLIC) &&
2816 (action_code == TDLS_DISCOVERY_RESPONSE)) {
2817 pcb->moal_updata_peer_signal(pmadapter->pmoal_handle,
2818 priv->bss_index,
2819 pieee_pkt_hdr->addr2,
2820 prx_pd->snr, prx_pd->nf);
2821 PRINTM(MINFO,
2822 "Rx: TDLS discovery response, nf=%d, snr=%d\n",
2823 prx_pd->nf, prx_pd->snr);
2824 }
2825 if ((category == IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM) &&
2826 (action_code == 0x1)) {
2827 prx_pd->toa_tod_tstamps =
2828 wlan_le64_to_cpu(prx_pd->toa_tod_tstamps);
2829 tstamps.t3 = prx_pd->toa_tod_tstamps >> 32;
2830 tstamps.t2 = (t_u32)prx_pd->toa_tod_tstamps;
2831 tstamps.t2_err = 0;
2832 tstamps.t3_err = 0;
2833 tstamps.ingress_time = pmadapter->host_bbu_clk_delta;
2834 pcb->moal_do_div(tstamps.ingress_time, 10);
2835 tstamps.ingress_time += tstamps.t2; //t2, t3 is 10ns and delta is in 1 ns unit;
2836 PRINTM(MINFO, "T2: %d, T3: %d, ingress: %lu\n",
2837 tstamps.t2, tstamps.t3, tstamps.ingress_time);
2838 }
2839 unicast = MTRUE;
2840 break;
2841 default:
2842 break;
2843 }
2844 if (unicast == MTRUE) {
2845 if (memcmp
2846 (pmadapter, pieee_pkt_hdr->addr1, priv->curr_addr,
2847 MLAN_MAC_ADDR_LENGTH)) {
2848 PRINTM(MINFO,
2849 "Dropping mgmt frame for others: type=%d " MACSTR
2850 "\n", sub_type, MAC2STR(pieee_pkt_hdr->addr1));
2851 LEAVE();
2852 return ret;
2853 }
2854 }
2855 /* Allocate memory for event buffer */
2856 ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE,
2857 MLAN_MEM_DEF, &event_buf);
2858 if ((ret != MLAN_STATUS_SUCCESS) || !event_buf) {
2859 PRINTM(MERROR, "Could not allocate buffer for event buf\n");
2860 LEAVE();
2861 return MLAN_STATUS_FAILURE;
2862 }
2863 pevent = (pmlan_event)event_buf;
2864 pevent->bss_index = priv->bss_index;
2865 mgmt = (IEEE80211_MGMT *)payload;
2866 if (sub_type == SUBTYPE_ACTION &&
2867 mgmt->u.ft_resp.category == FT_CATEGORY &&
2868 mgmt->u.ft_resp.action == FT_ACTION_RESPONSE &&
2869 mgmt->u.ft_resp.status_code == 0) {
2870 PRINTM(MCMND, "FT Action response received\n");
2871 #define FT_ACTION_HEAD_LEN (24 + 6 +16)
2872 pevent->event_id = MLAN_EVENT_ID_DRV_FT_RESPONSE;
2873 pevent->event_len =
2874 payload_len + MLAN_MAC_ADDR_LENGTH - FT_ACTION_HEAD_LEN;
2875 memcpy(pmadapter, (t_u8 *)pevent->event_buf,
2876 &mgmt->u.ft_resp.target_ap_addr, MLAN_MAC_ADDR_LENGTH);
2877 memcpy(pmadapter,
2878 (t_u8 *)(pevent->event_buf + MLAN_MAC_ADDR_LENGTH),
2879 payload + FT_ACTION_HEAD_LEN,
2880 payload_len - FT_ACTION_HEAD_LEN);
2881 } else if (sub_type == SUBTYPE_AUTH &&
2882 mgmt->u.auth.auth_alg == MLAN_AUTH_MODE_FT &&
2883 mgmt->u.auth.auth_transaction == 2 &&
2884 mgmt->u.auth.status_code == 0) {
2885 PRINTM(MCMND, "FT auth response received \n");
2886 #define AUTH_PACKET_LEN (24 + 6 +6)
2887 pevent->event_id = MLAN_EVENT_ID_DRV_FT_RESPONSE;
2888 pevent->event_len =
2889 payload_len + MLAN_MAC_ADDR_LENGTH - AUTH_PACKET_LEN;
2890 memcpy(pmadapter, (t_u8 *)pevent->event_buf, mgmt->sa,
2891 MLAN_MAC_ADDR_LENGTH);
2892 memcpy(pmadapter,
2893 (t_u8 *)(pevent->event_buf + MLAN_MAC_ADDR_LENGTH),
2894 payload + AUTH_PACKET_LEN,
2895 payload_len - AUTH_PACKET_LEN);
2896 } else {
2897 pevent->event_id = MLAN_EVENT_ID_DRV_MGMT_FRAME;
2898 pevent->event_len = payload_len + sizeof(pevent->event_id);
2899 memcpy(pmadapter, (t_u8 *)pevent->event_buf,
2900 (t_u8 *)&pevent->event_id, sizeof(pevent->event_id));
2901 memcpy(pmadapter,
2902 (t_u8 *)(pevent->event_buf + sizeof(pevent->event_id)),
2903 payload, payload_len);
2904 //Append timestamp info at the end of event
2905 if ((category == IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM) &&
2906 (action_code == 0x1)) {
2907 memcpy(pmadapter,
2908 (t_u8 *)(pevent->event_buf +
2909 sizeof(pevent->event_id) + payload_len),
2910 &tstamps, sizeof(struct timestamps));
2911 pevent->event_len =
2912 payload_len + sizeof(pevent->event_id) +
2913 sizeof(struct timestamps);
2914 }
2915
2916 }
2917 wlan_recv_event(priv, pevent->event_id, pevent);
2918 if (event_buf)
2919 pcb->moal_mfree(pmadapter->pmoal_handle, event_buf);
2920 LEAVE();
2921 return MLAN_STATUS_SUCCESS;
2922 }
2923
2924 #ifdef STA_SUPPORT
2925 /**
2926 * @brief Extended capabilities configuration
2927 *
2928 * @param pmadapter A pointer to mlan_adapter structure
2929 * @param pioctl_req A pointer to ioctl request buffer
2930 *
2931 * @return MLAN_STATUS_PENDING --success, otherwise fail
2932 */
2933 mlan_status
wlan_misc_ext_capa_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)2934 wlan_misc_ext_capa_cfg(IN pmlan_adapter pmadapter,
2935 IN pmlan_ioctl_req pioctl_req)
2936 {
2937 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
2938 mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
2939 mlan_status ret = MLAN_STATUS_SUCCESS;
2940
2941 ENTER();
2942
2943 if (MLAN_ACT_GET == pioctl_req->action)
2944 memcpy(pmpriv->adapter, &misc->param.ext_cap, &pmpriv->ext_cap,
2945 sizeof(misc->param.ext_cap));
2946 else if (MLAN_ACT_SET == pioctl_req->action) {
2947 memcpy(pmpriv->adapter, &pmpriv->ext_cap, &misc->param.ext_cap,
2948 sizeof(misc->param.ext_cap));
2949 /* Save default Extended Capability */
2950 memcpy(pmpriv->adapter, &pmpriv->def_ext_cap, &pmpriv->ext_cap,
2951 sizeof(pmpriv->ext_cap));
2952 }
2953
2954 LEAVE();
2955 return ret;
2956 }
2957
2958 /**
2959 * @brief Check whether Extended Capabilities IE support
2960 *
2961 * @param pmpriv A pointer to mlan_private structure
2962 *
2963 * @return MTRUE or MFALSE;
2964 */
2965 t_u32
wlan_is_ext_capa_support(mlan_private * pmpriv)2966 wlan_is_ext_capa_support(mlan_private *pmpriv)
2967 {
2968 ENTER();
2969
2970 if (ISSUPP_EXTCAP_TDLS(pmpriv->ext_cap)
2971 || ISSUPP_EXTCAP_INTERWORKING(pmpriv->ext_cap)
2972 || ISSUPP_EXTCAP_BSS_TRANSITION(pmpriv->ext_cap)
2973 || ISSUPP_EXTCAP_QOS_MAP(pmpriv->ext_cap)
2974 ) {
2975 LEAVE();
2976 return MTRUE;
2977 } else {
2978 LEAVE();
2979 return MFALSE;
2980 }
2981 }
2982 #endif
2983
2984 #ifdef STA_SUPPORT
2985 /**
2986 * @brief Add Extended Capabilities IE
2987 *
2988 * @param pmpriv A pointer to mlan_private structure
2989 * @param pptlv_out A pointer to TLV to fill in
2990 *
2991 * @return N/A
2992 */
2993 void
wlan_add_ext_capa_info_ie(IN mlan_private * pmpriv,OUT t_u8 ** pptlv_out)2994 wlan_add_ext_capa_info_ie(IN mlan_private *pmpriv, OUT t_u8 **pptlv_out)
2995 {
2996 MrvlIETypes_ExtCap_t *pext_cap = MNULL;
2997
2998 ENTER();
2999
3000 pext_cap = (MrvlIETypes_ExtCap_t *)*pptlv_out;
3001 memset(pmpriv->adapter, pext_cap, 0, sizeof(MrvlIETypes_ExtCap_t));
3002 pext_cap->header.type = wlan_cpu_to_le16(EXT_CAPABILITY);
3003 pext_cap->header.len = wlan_cpu_to_le16(sizeof(ExtCap_t));
3004 if (pmpriv->adapter->ecsa_enable)
3005 SET_EXTCAP_EXT_CHANNEL_SWITCH(pmpriv->ext_cap);
3006 else
3007 RESET_EXTCAP_EXT_CHANNEL_SWITCH(pmpriv->ext_cap);
3008 SET_EXTCAP_FTMI(pmpriv->ext_cap);
3009 SET_EXTCAP_INTERNETWORKING(pmpriv->ext_cap);
3010 memcpy(pmpriv->adapter, &pext_cap->ext_cap, &pmpriv->ext_cap,
3011 sizeof(pmpriv->ext_cap));
3012 *pptlv_out += sizeof(MrvlIETypes_ExtCap_t);
3013
3014 LEAVE();
3015 }
3016 #endif
3017
3018 /**
3019 * @brief Get OTP user data
3020 *
3021 * @param pmadapter A pointer to mlan_adapter structure
3022 * @param pioctl_req A pointer to ioctl request buffer
3023 *
3024 * @return MLAN_STATUS_PENDING --success, otherwise fail
3025 */
3026 mlan_status
wlan_misc_otp_user_data(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3027 wlan_misc_otp_user_data(IN pmlan_adapter pmadapter,
3028 IN pmlan_ioctl_req pioctl_req)
3029 {
3030 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3031 mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
3032 mlan_status ret = MLAN_STATUS_FAILURE;
3033
3034 ENTER();
3035
3036 if (misc->param.otp_user_data.user_data_length > MAX_OTP_USER_DATA_LEN) {
3037 PRINTM(MERROR, "Invalid OTP user data length\n");
3038 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3039 LEAVE();
3040 return ret;
3041 }
3042
3043 ret = wlan_prepare_cmd(pmpriv,
3044 HostCmd_CMD_OTP_READ_USER_DATA,
3045 HostCmd_ACT_GEN_GET,
3046 0,
3047 (t_void *)pioctl_req,
3048 &misc->param.otp_user_data);
3049
3050 if (ret == MLAN_STATUS_SUCCESS)
3051 ret = MLAN_STATUS_PENDING;
3052
3053 LEAVE();
3054 return ret;
3055 }
3056
3057 /**
3058 * @brief This function will search for the specific ie
3059 *
3060 * @param priv A pointer to mlan_private
3061 * @param pevent A pointer to event buf
3062 * @param sta_ptr A pointer to sta_node
3063 *
3064 * @return N/A
3065 */
3066 void
wlan_check_sta_capability(pmlan_private priv,pmlan_buffer pevent,sta_node * sta_ptr)3067 wlan_check_sta_capability(pmlan_private priv, pmlan_buffer pevent,
3068 sta_node *sta_ptr)
3069 {
3070 t_u16 tlv_type, tlv_len;
3071 t_u16 frame_control, frame_sub_type = 0;
3072 t_u8 *assoc_req_ie = MNULL;
3073 t_u8 ie_len = 0, assoc_ie_len = 0;
3074 IEEEtypes_HTCap_t *pht_cap = MNULL;
3075 #ifdef UAP_SUPPORT
3076 t_u8 *ext_rate = MNULL, *erp = MNULL;
3077 #endif
3078
3079 int tlv_buf_left = pevent->data_len - ASSOC_EVENT_FIX_SIZE;
3080 MrvlIEtypesHeader_t *tlv = (MrvlIEtypesHeader_t *)
3081 (pevent->pbuf + pevent->data_offset + ASSOC_EVENT_FIX_SIZE);
3082 MrvlIETypes_MgmtFrameSet_t *mgmt_tlv = MNULL;
3083
3084 ENTER();
3085 while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) {
3086 tlv_type = wlan_le16_to_cpu(tlv->type);
3087 tlv_len = wlan_le16_to_cpu(tlv->len);
3088 if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) >
3089 (unsigned int)tlv_buf_left) {
3090 PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
3091 tlv_len, tlv_buf_left);
3092 break;
3093 }
3094 if (tlv_type == TLV_TYPE_MGMT_FRAME) {
3095 mgmt_tlv = (MrvlIETypes_MgmtFrameSet_t *)tlv;
3096 memcpy(priv->adapter, &frame_control,
3097 (t_u8 *)&(mgmt_tlv->frame_control),
3098 sizeof(frame_control));
3099 frame_sub_type =
3100 IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE
3101 (frame_control);
3102 if ((mgmt_tlv->frame_control.type == 0) &&
3103 ((frame_sub_type == SUBTYPE_BEACON)
3104 #ifdef UAP_SUPPORT
3105 || (frame_sub_type == SUBTYPE_ASSOC_REQUEST)
3106 || (frame_sub_type == SUBTYPE_REASSOC_REQUEST)
3107 #endif
3108 )) {
3109 if (frame_sub_type == SUBTYPE_BEACON)
3110 assoc_ie_len =
3111 sizeof(IEEEtypes_Beacon_t);
3112 #ifdef UAP_SUPPORT
3113 else if (frame_sub_type ==
3114 SUBTYPE_ASSOC_REQUEST)
3115 assoc_ie_len =
3116 sizeof(IEEEtypes_AssocRqst_t);
3117 else if (frame_sub_type ==
3118 SUBTYPE_REASSOC_REQUEST)
3119 assoc_ie_len =
3120 sizeof(IEEEtypes_ReAssocRqst_t);
3121 #endif
3122 ie_len = tlv_len -
3123 sizeof(IEEEtypes_FrameCtl_t) -
3124 assoc_ie_len;
3125 assoc_req_ie =
3126 (t_u8 *)tlv +
3127 sizeof(MrvlIETypes_MgmtFrameSet_t) +
3128 assoc_ie_len;
3129 sta_ptr->is_wmm_enabled =
3130 wlan_is_wmm_ie_present(priv->adapter,
3131 assoc_req_ie,
3132 ie_len);
3133 PRINTM(MCMND, "STA: is_wmm_enabled=%d\n",
3134 sta_ptr->is_wmm_enabled);
3135 pht_cap =
3136 (IEEEtypes_HTCap_t *)
3137 wlan_get_specific_ie(priv, assoc_req_ie,
3138 ie_len,
3139 HT_CAPABILITY);
3140 if (pht_cap) {
3141 PRINTM(MCMND, "STA supports 11n\n");
3142 sta_ptr->is_11n_enabled = MTRUE;
3143 memcpy(priv->adapter,
3144 (t_u8 *)&sta_ptr->HTcap, pht_cap,
3145 sizeof(IEEEtypes_HTCap_t));
3146 if (GETHT_MAXAMSDU
3147 (wlan_le16_to_cpu
3148 (pht_cap->ht_cap.ht_cap_info)))
3149 sta_ptr->max_amsdu =
3150 MLAN_TX_DATA_BUF_SIZE_8K;
3151 else
3152 sta_ptr->max_amsdu =
3153 MLAN_TX_DATA_BUF_SIZE_4K;
3154 } else {
3155 PRINTM(MCMND,
3156 "STA doesn't support 11n\n");
3157 }
3158 #ifdef UAP_SUPPORT
3159 /* Note: iphone6 does not have ERP_INFO */
3160 ext_rate =
3161 wlan_get_specific_ie(priv, assoc_req_ie,
3162 ie_len,
3163 EXTENDED_SUPPORTED_RATES);
3164 erp = wlan_get_specific_ie(priv, assoc_req_ie,
3165 ie_len, ERP_INFO);
3166 if (!ext_rate)
3167 PRINTM(MCMND,
3168 "STA doesn't support EXTENDED_SUPPORTED_RATES\n");
3169 if (!erp)
3170 PRINTM(MCMND,
3171 "STA doesn't support ERP_INFO\n");
3172 if (sta_ptr->is_11n_enabled) {
3173 if (priv->uap_channel <= 14)
3174 sta_ptr->bandmode = BAND_GN;
3175 else
3176 sta_ptr->bandmode = BAND_AN;
3177 } else if (ext_rate || erp) {
3178 if (priv->uap_channel <= 14)
3179 sta_ptr->bandmode = BAND_G;
3180 else
3181 sta_ptr->bandmode = BAND_A;
3182 } else
3183 sta_ptr->bandmode = BAND_B;
3184 #endif
3185 #ifdef DRV_EMBEDDED_AUTHENTICATOR
3186 if (IsAuthenticatorEnabled(priv->psapriv))
3187 authenticator_get_sta_security_info
3188 (priv->psapriv,
3189 sta_ptr->cm_connectioninfo,
3190 assoc_req_ie, ie_len);
3191 #endif
3192 break;
3193 }
3194 }
3195 tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len);
3196 tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
3197 sizeof(MrvlIEtypesHeader_t));
3198 }
3199 LEAVE();
3200
3201 return;
3202 }
3203
3204 /**
3205 * @brief check if WMM ie present.
3206 *
3207 * @param pmadapter A pointer to mlan_adapter structure
3208 * @param pbuf A pointer to IE buffer
3209 * @param buf_len IE buffer len
3210 *
3211 * @return MTRUE/MFALSE
3212 */
3213 t_u8
wlan_is_wmm_ie_present(pmlan_adapter pmadapter,t_u8 * pbuf,t_u16 buf_len)3214 wlan_is_wmm_ie_present(pmlan_adapter pmadapter, t_u8 *pbuf, t_u16 buf_len)
3215 {
3216 t_u16 bytes_left = buf_len;
3217 IEEEtypes_ElementId_e element_id;
3218 t_u8 *pcurrent_ptr = pbuf;
3219 t_u8 element_len;
3220 t_u16 total_ie_len;
3221 IEEEtypes_VendorSpecific_t *pvendor_ie;
3222 const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
3223 t_u8 find_wmm_ie = MFALSE;
3224
3225 ENTER();
3226
3227 /* Process variable IE */
3228 while (bytes_left >= 2) {
3229 element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
3230 element_len = *((t_u8 *)pcurrent_ptr + 1);
3231 total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
3232
3233 if (bytes_left < total_ie_len) {
3234 PRINTM(MERROR, "InterpretIE: Error in processing IE, "
3235 "bytes left < IE length\n");
3236 bytes_left = 0;
3237 continue;
3238 }
3239 switch (element_id) {
3240 case VENDOR_SPECIFIC_221:
3241 pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
3242 if (!memcmp
3243 (pmadapter, pvendor_ie->vend_hdr.oui, wmm_oui,
3244 sizeof(wmm_oui))) {
3245 find_wmm_ie = MTRUE;
3246 PRINTM(MINFO, "find WMM IE\n");
3247 }
3248 break;
3249 default:
3250 break;
3251 }
3252 pcurrent_ptr += element_len + 2;
3253 /* Need to account for IE ID and IE Len */
3254 bytes_left -= (element_len + 2);
3255 if (find_wmm_ie)
3256 break;
3257 }
3258
3259 LEAVE();
3260 return find_wmm_ie;
3261 }
3262
3263 /**
3264 * @brief This function will search for the specific ie
3265 *
3266 *
3267 * @param priv A pointer to mlan_private
3268 * @param ie_buf A pointer to ie_buf
3269 * @param ie_len total ie length
3270 * @param id ie's id
3271 *
3272 * @return ie's poiner or MNULL
3273 */
3274 t_u8 *
wlan_get_specific_ie(pmlan_private priv,t_u8 * ie_buf,t_u8 ie_len,IEEEtypes_ElementId_e id)3275 wlan_get_specific_ie(pmlan_private priv, t_u8 *ie_buf, t_u8 ie_len,
3276 IEEEtypes_ElementId_e id)
3277 {
3278 t_u32 bytes_left = ie_len;
3279 t_u8 *pcurrent_ptr = ie_buf;
3280 t_u16 total_ie_len;
3281 t_u8 *ie_ptr = MNULL;
3282 IEEEtypes_ElementId_e element_id;
3283 t_u8 element_len;
3284
3285 ENTER();
3286
3287 DBG_HEXDUMP(MCMD_D, "ie", ie_buf, ie_len);
3288 while (bytes_left >= 2) {
3289 element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
3290 element_len = *((t_u8 *)pcurrent_ptr + 1);
3291 total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
3292 if (bytes_left < total_ie_len) {
3293 PRINTM(MERROR, "InterpretIE: Error in processing IE, "
3294 "bytes left < IE length\n");
3295 break;
3296 }
3297 if (element_id == id) {
3298 PRINTM(MCMND, "Find IE: id=%d\n", id);
3299 DBG_HEXDUMP(MCMND, "IE", pcurrent_ptr, total_ie_len);
3300 ie_ptr = pcurrent_ptr;
3301 break;
3302 }
3303 pcurrent_ptr += element_len + 2;
3304 /* Need to account for IE ID and IE Len */
3305 bytes_left -= (element_len + 2);
3306 }
3307
3308 LEAVE();
3309
3310 return ie_ptr;
3311 }
3312
3313 /**
3314 * @brief Get pm info
3315 *
3316 * @param pmadapter A pointer to mlan_adapter structure
3317 * @param pioctl_req A pointer to ioctl request buffer
3318 *
3319 * @return MLAN_STATUS_SUCCESS --success
3320 */
3321 mlan_status
wlan_get_pm_info(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3322 wlan_get_pm_info(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
3323 {
3324 mlan_status ret = MLAN_STATUS_SUCCESS;
3325 mlan_ds_pm_cfg *pm_cfg = MNULL;
3326
3327 ENTER();
3328
3329 pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
3330 pm_cfg->param.ps_info.is_suspend_allowed = MTRUE;
3331 wlan_request_cmd_lock(pmadapter);
3332 if (util_peek_list(pmadapter->pmoal_handle, &pmadapter->cmd_pending_q,
3333 MNULL, MNULL) || pmadapter->curr_cmd
3334 || !wlan_bypass_tx_list_empty(pmadapter)
3335 || !wlan_wmm_lists_empty(pmadapter)
3336 || pmadapter->sdio_ireg) {
3337 pm_cfg->param.ps_info.is_suspend_allowed = MFALSE;
3338 PRINTM(MIOCTL,
3339 "PM: cmd_pending_q=%p,curr_cmd=%p,wmm_list_empty=%d, by_pass=%d sdio_ireg=0x%x\n",
3340 util_peek_list(pmadapter->pmoal_handle,
3341 &pmadapter->cmd_pending_q, MNULL, MNULL),
3342 pmadapter->curr_cmd, wlan_wmm_lists_empty(pmadapter),
3343 wlan_bypass_tx_list_empty(pmadapter),
3344 pmadapter->sdio_ireg);
3345 }
3346 wlan_release_cmd_lock(pmadapter);
3347 LEAVE();
3348 return ret;
3349 }
3350
3351 /**
3352 * @brief Get hs wakeup reason
3353 *
3354 * @param pmadapter A pointer to mlan_adapter structure
3355 * @param pioctl_req A pointer to ioctl request buffer
3356 *
3357 * @return MLAN_STATUS_SUCCESS --success
3358 */
3359 mlan_status
wlan_get_hs_wakeup_reason(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3360 wlan_get_hs_wakeup_reason(IN pmlan_adapter pmadapter,
3361 IN pmlan_ioctl_req pioctl_req)
3362 {
3363 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
3364 pmlan_ds_pm_cfg pm_cfg = MNULL;
3365 mlan_status ret = MLAN_STATUS_FAILURE;
3366
3367 ENTER();
3368
3369 pm_cfg = (mlan_ds_pm_cfg *)pioctl_req->pbuf;
3370
3371 /* Send command to firmware */
3372 ret = wlan_prepare_cmd(pmpriv,
3373 HostCmd_CMD_HS_WAKEUP_REASON,
3374 HostCmd_ACT_GEN_GET,
3375 0,
3376 (t_void *)pioctl_req,
3377 &pm_cfg->param.wakeup_reason);
3378
3379 if (ret == MLAN_STATUS_SUCCESS)
3380 ret = MLAN_STATUS_PENDING;
3381
3382 LEAVE();
3383 return ret;
3384
3385 }
3386
3387 /**
3388 * @brief Set/Get radio status
3389 *
3390 * @param pmadapter A pointer to mlan_adapter structure
3391 * @param pioctl_req A pointer to ioctl request buffer
3392 *
3393 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
3394 */
3395 mlan_status
wlan_radio_ioctl_radio_ctl(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3396 wlan_radio_ioctl_radio_ctl(IN pmlan_adapter pmadapter,
3397 IN pmlan_ioctl_req pioctl_req)
3398 {
3399 mlan_status ret = MLAN_STATUS_SUCCESS;
3400 mlan_ds_radio_cfg *radio_cfg = MNULL;
3401 t_u16 cmd_action = 0;
3402 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3403
3404 ENTER();
3405
3406 radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
3407 if (pioctl_req->action == MLAN_ACT_SET) {
3408 if (pmadapter->radio_on == radio_cfg->param.radio_on_off) {
3409 ret = MLAN_STATUS_SUCCESS;
3410 goto exit;
3411 } else {
3412 if (pmpriv->media_connected == MTRUE) {
3413 ret = MLAN_STATUS_FAILURE;
3414 goto exit;
3415 }
3416 cmd_action = HostCmd_ACT_GEN_SET;
3417 }
3418 } else
3419 cmd_action = HostCmd_ACT_GEN_GET;
3420
3421 /* Send request to firmware */
3422 ret = wlan_prepare_cmd(pmpriv,
3423 HostCmd_CMD_802_11_RADIO_CONTROL,
3424 cmd_action,
3425 0,
3426 (t_void *)pioctl_req,
3427 &radio_cfg->param.radio_on_off);
3428
3429 if (ret == MLAN_STATUS_SUCCESS)
3430 ret = MLAN_STATUS_PENDING;
3431
3432 exit:
3433 LEAVE();
3434 return ret;
3435 }
3436
3437 /**
3438 * @brief Set/Get antenna configuration
3439 *
3440 * @param pmadapter A pointer to mlan_adapter structure
3441 * @param pioctl_req A pointer to ioctl request buffer
3442 *
3443 * @return MLAN_STATUS_PENDING --success, otherwise fail
3444 */
3445 mlan_status
wlan_radio_ioctl_ant_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3446 wlan_radio_ioctl_ant_cfg(IN pmlan_adapter pmadapter,
3447 IN pmlan_ioctl_req pioctl_req)
3448 {
3449 mlan_status ret = MLAN_STATUS_SUCCESS;
3450 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3451 mlan_ds_radio_cfg *radio_cfg = MNULL;
3452 t_u16 cmd_action = 0;
3453 mlan_ds_ant_cfg_1x1 *ant_cfg;
3454
3455 ENTER();
3456
3457 radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
3458
3459 if (pioctl_req->action == MLAN_ACT_SET) {
3460 /* User input validation */
3461 if (!radio_cfg->param.ant_cfg_1x1.antenna ||
3462 ((radio_cfg->param.ant_cfg_1x1.antenna != RF_ANTENNA_AUTO)
3463 && (radio_cfg->param.ant_cfg_1x1.antenna & 0xFFFC))) {
3464 PRINTM(MERROR, "Invalid antenna setting\n");
3465 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3466 ret = MLAN_STATUS_FAILURE;
3467 goto exit;
3468 }
3469 cmd_action = HostCmd_ACT_GEN_SET;
3470 } else
3471 cmd_action = HostCmd_ACT_GEN_GET;
3472
3473 /* Cast it to t_u16, antenna mode for command HostCmd_CMD_802_11_RF_ANTENNA requires 2 bytes */
3474 ant_cfg = &radio_cfg->param.ant_cfg_1x1;
3475
3476 /* Send request to firmware */
3477 ret = wlan_prepare_cmd(pmpriv,
3478 HostCmd_CMD_802_11_RF_ANTENNA,
3479 cmd_action,
3480 0, (t_void *)pioctl_req, (t_void *)ant_cfg);
3481
3482 if (ret == MLAN_STATUS_SUCCESS)
3483 ret = MLAN_STATUS_PENDING;
3484
3485 exit:
3486 LEAVE();
3487 return ret;
3488 }
3489
3490 /**
3491 * @brief Get rate bitmap
3492 *
3493 * @param pmadapter A pointer to mlan_adapter structure
3494 * @param pioctl_req A pointer to ioctl request buffer
3495 *
3496 * @return MLAN_STATUS_PENDING --success, otherwise fail
3497 */
3498 static mlan_status
wlan_rate_ioctl_get_rate_bitmap(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3499 wlan_rate_ioctl_get_rate_bitmap(IN pmlan_adapter pmadapter,
3500 IN pmlan_ioctl_req pioctl_req)
3501 {
3502 mlan_status ret = MLAN_STATUS_SUCCESS;
3503 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3504
3505 ENTER();
3506
3507 /* Send request to firmware */
3508 ret = wlan_prepare_cmd(pmpriv,
3509 HostCmd_CMD_TX_RATE_CFG,
3510 HostCmd_ACT_GEN_GET,
3511 0, (t_void *)pioctl_req, MNULL);
3512 if (ret == MLAN_STATUS_SUCCESS)
3513 ret = MLAN_STATUS_PENDING;
3514
3515 LEAVE();
3516 return ret;
3517 }
3518
3519 /**
3520 * @brief Set rate bitmap
3521 *
3522 * @param pmadapter A pointer to mlan_adapter structure
3523 * @param pioctl_req A pointer to ioctl request buffer
3524 *
3525 * @return MLAN_STATUS_PENDING --success, otherwise fail
3526 */
3527 static mlan_status
wlan_rate_ioctl_set_rate_bitmap(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3528 wlan_rate_ioctl_set_rate_bitmap(IN pmlan_adapter pmadapter,
3529 IN pmlan_ioctl_req pioctl_req)
3530 {
3531 mlan_ds_rate *ds_rate = MNULL;
3532 mlan_status ret = MLAN_STATUS_FAILURE;
3533 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3534 t_u16 *bitmap_rates = MNULL;
3535
3536 ENTER();
3537
3538 ds_rate = (mlan_ds_rate *)pioctl_req->pbuf;
3539 bitmap_rates = ds_rate->param.rate_cfg.bitmap_rates;
3540
3541 PRINTM(MINFO, "RateBitmap=%04x%04x%04x%04x%04x%04x%04x%04x"
3542 "%04x%04x%04x%04x%04x%04x%04x%04x%04x%04x, "
3543 "IsRateAuto=%d, DataRate=%d\n",
3544 bitmap_rates[17], bitmap_rates[16],
3545 bitmap_rates[15], bitmap_rates[14],
3546 bitmap_rates[13], bitmap_rates[12],
3547 bitmap_rates[11], bitmap_rates[10],
3548 bitmap_rates[9], bitmap_rates[8],
3549 bitmap_rates[7], bitmap_rates[6],
3550 bitmap_rates[5], bitmap_rates[4],
3551 bitmap_rates[3], bitmap_rates[2],
3552 bitmap_rates[1], bitmap_rates[0],
3553 pmpriv->is_data_rate_auto, pmpriv->data_rate);
3554
3555 /* Send request to firmware */
3556 ret = wlan_prepare_cmd(pmpriv,
3557 HostCmd_CMD_TX_RATE_CFG,
3558 HostCmd_ACT_GEN_SET,
3559 0, (t_void *)pioctl_req, (t_void *)bitmap_rates);
3560 if (ret == MLAN_STATUS_SUCCESS)
3561 ret = MLAN_STATUS_PENDING;
3562
3563 LEAVE();
3564 return ret;
3565 }
3566
3567 /**
3568 * @brief Get rate value
3569 *
3570 * @param pmadapter A pointer to mlan_adapter structure
3571 * @param pioctl_req A pointer to ioctl request buffer
3572 *
3573 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
3574 */
3575 static mlan_status
wlan_rate_ioctl_get_rate_value(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3576 wlan_rate_ioctl_get_rate_value(IN pmlan_adapter pmadapter,
3577 IN pmlan_ioctl_req pioctl_req)
3578 {
3579 mlan_ds_rate *rate = MNULL;
3580 mlan_status ret = MLAN_STATUS_SUCCESS;
3581 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3582
3583 ENTER();
3584
3585 rate = (mlan_ds_rate *)pioctl_req->pbuf;
3586 rate->param.rate_cfg.is_rate_auto = pmpriv->is_data_rate_auto;
3587 pioctl_req->data_read_written =
3588 sizeof(mlan_rate_cfg_t) + MLAN_SUB_COMMAND_SIZE;
3589
3590 /* If not connected, set rate to the lowest in each band */
3591 if (pmpriv->media_connected != MTRUE) {
3592 if (pmpriv->config_bands & (BAND_B | BAND_G)) {
3593 /* Return the lowest supported rate for BG band */
3594 rate->param.rate_cfg.rate = SupportedRates_BG[0] & 0x7f;
3595 } else if (pmpriv->config_bands & (BAND_A | BAND_B)) {
3596 /* Return the lowest supported rate for A band */
3597 rate->param.rate_cfg.rate = SupportedRates_BG[0] & 0x7f;
3598 } else if (pmpriv->config_bands & BAND_A) {
3599 /* Return the lowest supported rate for A band */
3600 rate->param.rate_cfg.rate = SupportedRates_A[0] & 0x7f;
3601 } else if (pmpriv->config_bands & BAND_G) {
3602 /* Return the lowest supported rate for G band */
3603 rate->param.rate_cfg.rate = SupportedRates_G[0] & 0x7f;
3604 } else if (pmpriv->config_bands & BAND_B) {
3605 /* Return the lowest supported rate for B band */
3606 rate->param.rate_cfg.rate = SupportedRates_B[0] & 0x7f;
3607 } else if (pmpriv->config_bands & BAND_GN) {
3608 /* Return the lowest supported rate for N band */
3609 rate->param.rate_cfg.rate = SupportedRates_N[0] & 0x7f;
3610 } else {
3611 PRINTM(MMSG, "Invalid Band 0x%x\n",
3612 pmpriv->config_bands);
3613 }
3614
3615 } else {
3616 /* Send request to firmware */
3617 ret = wlan_prepare_cmd(pmpriv,
3618 HostCmd_CMD_802_11_TX_RATE_QUERY,
3619 HostCmd_ACT_GEN_GET,
3620 0, (t_void *)pioctl_req, MNULL);
3621 if (ret == MLAN_STATUS_SUCCESS)
3622 ret = MLAN_STATUS_PENDING;
3623 }
3624
3625 LEAVE();
3626 return ret;
3627 }
3628
3629 /**
3630 * @brief Set rate value
3631 *
3632 * @param pmadapter A pointer to mlan_adapter structure
3633 * @param pioctl_req A pointer to ioctl request buffer
3634 *
3635 * @return MLAN_STATUS_PENDING --success, otherwise fail
3636 */
3637 static mlan_status
wlan_rate_ioctl_set_rate_value(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3638 wlan_rate_ioctl_set_rate_value(IN pmlan_adapter pmadapter,
3639 IN pmlan_ioctl_req pioctl_req)
3640 {
3641 mlan_ds_rate *ds_rate = MNULL;
3642 WLAN_802_11_RATES rates;
3643 t_u8 *rate = MNULL;
3644 int rate_index = 0;
3645 t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
3646 t_u32 i = 0;
3647 mlan_status ret = MLAN_STATUS_SUCCESS;
3648 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3649
3650 ENTER();
3651
3652 ds_rate = (mlan_ds_rate *)pioctl_req->pbuf;
3653
3654 if (ds_rate->param.rate_cfg.is_rate_auto) {
3655 memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
3656 /* Support all HR/DSSS rates */
3657 bitmap_rates[0] = 0x000F;
3658 /* Support all OFDM rates */
3659 bitmap_rates[1] = 0x00FF;
3660 /* Rates talbe [0] HR/DSSS,[1] OFDM,[2..9] HT,[10..17] VHT */
3661 /* Support all HT-MCSs rate */
3662 for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates) - 3 - 8; i++)
3663 bitmap_rates[i + 2] = 0xFFFF;
3664 bitmap_rates[9] = 0x3FFF;
3665 /* Set to 0 as default value */
3666 for (i = 0; i < NELEMENTS(pmpriv->bitmap_rates) - 10; i++)
3667 bitmap_rates[i + 10] = 0x0;
3668 } else {
3669 memset(pmadapter, rates, 0, sizeof(rates));
3670 wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode,
3671 (pmpriv->bss_mode ==
3672 MLAN_BSS_MODE_INFRA) ? pmpriv->
3673 config_bands : pmadapter->
3674 adhoc_start_band, rates);
3675 rate = rates;
3676 for (i = 0; (rate[i] && i < WLAN_SUPPORTED_RATES); i++) {
3677 PRINTM(MINFO, "Rate=0x%X Wanted=0x%X\n", rate[i],
3678 ds_rate->param.rate_cfg.rate);
3679 if ((rate[i] & 0x7f) ==
3680 (ds_rate->param.rate_cfg.rate & 0x7f))
3681 break;
3682 }
3683 if (!rate[i] || (i == WLAN_SUPPORTED_RATES)) {
3684 PRINTM(MERROR, "The fixed data rate 0x%X is out "
3685 "of range\n", ds_rate->param.rate_cfg.rate);
3686 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3687 ret = MLAN_STATUS_FAILURE;
3688 goto exit;
3689 }
3690 memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
3691
3692 rate_index =
3693 wlan_data_rate_to_index(pmadapter,
3694 ds_rate->param.rate_cfg.rate);
3695
3696 /* Only allow b/g rates to be set */
3697 if (rate_index >= MLAN_RATE_INDEX_HRDSSS0 &&
3698 rate_index <= MLAN_RATE_INDEX_HRDSSS3)
3699 bitmap_rates[0] = 1 << rate_index;
3700 else {
3701 rate_index -= 1; /* There is a 0x00 in the table */
3702 if (rate_index >= MLAN_RATE_INDEX_OFDM0 &&
3703 rate_index <= MLAN_RATE_INDEX_OFDM7)
3704 bitmap_rates[1] =
3705 1 << (rate_index -
3706 MLAN_RATE_INDEX_OFDM0);
3707 }
3708 }
3709
3710 /* Send request to firmware */
3711 ret = wlan_prepare_cmd(pmpriv,
3712 HostCmd_CMD_TX_RATE_CFG,
3713 HostCmd_ACT_GEN_SET,
3714 0, (t_void *)pioctl_req, bitmap_rates);
3715 if (ret == MLAN_STATUS_SUCCESS)
3716 ret = MLAN_STATUS_PENDING;
3717
3718 exit:
3719 LEAVE();
3720 return ret;
3721 }
3722
3723 /**
3724 * @brief Get rate index
3725 *
3726 * @param pmadapter A pointer to mlan_adapter structure
3727 * @param pioctl_req A pointer to ioctl request buffer
3728 *
3729 * @return MLAN_STATUS_PENDING --success, otherwise fail
3730 */
3731 static mlan_status
wlan_rate_ioctl_get_rate_index(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3732 wlan_rate_ioctl_get_rate_index(IN pmlan_adapter pmadapter,
3733 IN pmlan_ioctl_req pioctl_req)
3734 {
3735 mlan_status ret = MLAN_STATUS_SUCCESS;
3736 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3737
3738 ENTER();
3739
3740 /* Send request to firmware */
3741 ret = wlan_prepare_cmd(pmpriv,
3742 HostCmd_CMD_TX_RATE_CFG,
3743 HostCmd_ACT_GEN_GET,
3744 0, (t_void *)pioctl_req, MNULL);
3745 if (ret == MLAN_STATUS_SUCCESS)
3746 ret = MLAN_STATUS_PENDING;
3747
3748 LEAVE();
3749 return ret;
3750 }
3751
3752 /**
3753 * @brief Set rate index
3754 *
3755 * @param pmadapter A pointer to mlan_adapter structure
3756 * @param pioctl_req A pointer to ioctl request buffer
3757 *
3758 * @return MLAN_STATUS_PENDING --success, otherwise fail
3759 */
3760 static mlan_status
wlan_rate_ioctl_set_rate_index(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3761 wlan_rate_ioctl_set_rate_index(IN pmlan_adapter pmadapter,
3762 IN pmlan_ioctl_req pioctl_req)
3763 {
3764 t_u32 rate_index;
3765 t_u32 rate_format;
3766 t_u32 i;
3767 mlan_ds_rate *ds_rate = MNULL;
3768 mlan_status ret = MLAN_STATUS_FAILURE;
3769 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3770 t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
3771
3772 ENTER();
3773
3774 ds_rate = (mlan_ds_rate *)pioctl_req->pbuf;
3775 rate_format = ds_rate->param.rate_cfg.rate_format;
3776 rate_index = ds_rate->param.rate_cfg.rate;
3777
3778 if (ds_rate->param.rate_cfg.is_rate_auto) {
3779 memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
3780 /* Rates talbe [0]: HR/DSSS;[1]: OFDM; [2..9] HT; */
3781 /* Support all HR/DSSS rates */
3782 bitmap_rates[0] = 0x000F;
3783 /* Support all OFDM rates */
3784 bitmap_rates[1] = 0x00FF;
3785 /* Support all HT-MCSs rate */
3786 for (i = 2; i < 9; i++)
3787 bitmap_rates[i] = 0xFFFF;
3788 bitmap_rates[9] = 0x3FFF;
3789 } else {
3790 PRINTM(MINFO, "Rate index is %d\n", rate_index);
3791 memset(pmadapter, bitmap_rates, 0, sizeof(bitmap_rates));
3792 if (rate_format == MLAN_RATE_FORMAT_LG) {
3793 /* Bitmap of HR/DSSS rates */
3794 if ((rate_index >= MLAN_RATE_INDEX_HRDSSS0) &&
3795 (rate_index <= MLAN_RATE_INDEX_HRDSSS3)) {
3796 bitmap_rates[0] = 1 << rate_index;
3797 ret = MLAN_STATUS_SUCCESS;
3798 /* Bitmap of OFDM rates */
3799 } else if ((rate_index >= MLAN_RATE_INDEX_OFDM0) &&
3800 (rate_index <= MLAN_RATE_INDEX_OFDM7)) {
3801 bitmap_rates[1] =
3802 1 << (rate_index -
3803 MLAN_RATE_INDEX_OFDM0);
3804 ret = MLAN_STATUS_SUCCESS;
3805 }
3806 } else if (rate_format == MLAN_RATE_FORMAT_HT) {
3807 if ((rate_index >= MLAN_RATE_INDEX_MCS0) &&
3808 (rate_index <= MLAN_RATE_INDEX_MCS32)) {
3809 bitmap_rates[2 + (rate_index / 16)] =
3810 1 << (rate_index % 16);
3811 ret = MLAN_STATUS_SUCCESS;
3812 }
3813 }
3814
3815 if (ret == MLAN_STATUS_FAILURE) {
3816 PRINTM(MERROR, "Invalid MCS index=%d. \n", rate_index);
3817 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
3818 LEAVE();
3819 return MLAN_STATUS_FAILURE;
3820 }
3821 }
3822
3823 PRINTM(MINFO, "RateBitmap=%04x%04x%04x%04x%04x%04x%04x%04x"
3824 "%04x%04x%04x%04x%04x%04x%04x%04x%04x%04x, "
3825 "IsRateAuto=%d, DataRate=%d\n",
3826 bitmap_rates[17], bitmap_rates[16],
3827 bitmap_rates[15], bitmap_rates[14],
3828 bitmap_rates[13], bitmap_rates[12],
3829 bitmap_rates[11], bitmap_rates[10],
3830 bitmap_rates[9], bitmap_rates[8],
3831 bitmap_rates[7], bitmap_rates[6],
3832 bitmap_rates[5], bitmap_rates[4],
3833 bitmap_rates[3], bitmap_rates[2],
3834 bitmap_rates[1], bitmap_rates[0],
3835 pmpriv->is_data_rate_auto, pmpriv->data_rate);
3836
3837 /* Send request to firmware */
3838 ret = wlan_prepare_cmd(pmpriv,
3839 HostCmd_CMD_TX_RATE_CFG,
3840 HostCmd_ACT_GEN_SET,
3841 0, (t_void *)pioctl_req, (t_void *)bitmap_rates);
3842 if (ret == MLAN_STATUS_SUCCESS)
3843 ret = MLAN_STATUS_PENDING;
3844
3845 LEAVE();
3846 return ret;
3847 }
3848
3849 /**
3850 * @brief Rate configuration command handler
3851 *
3852 * @param pmadapter A pointer to mlan_adapter structure
3853 * @param pioctl_req A pointer to ioctl request buffer
3854 *
3855 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
3856 */
3857 mlan_status
wlan_rate_ioctl_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3858 wlan_rate_ioctl_cfg(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
3859 {
3860 mlan_ds_rate *rate = MNULL;
3861 mlan_status status = MLAN_STATUS_SUCCESS;
3862
3863 ENTER();
3864
3865 rate = (mlan_ds_rate *)pioctl_req->pbuf;
3866 if (rate->param.rate_cfg.rate_type == MLAN_RATE_BITMAP) {
3867 if (pioctl_req->action == MLAN_ACT_GET)
3868 status = wlan_rate_ioctl_get_rate_bitmap(pmadapter,
3869 pioctl_req);
3870 else
3871 status = wlan_rate_ioctl_set_rate_bitmap(pmadapter,
3872 pioctl_req);
3873 } else if (rate->param.rate_cfg.rate_type == MLAN_RATE_VALUE) {
3874 if (pioctl_req->action == MLAN_ACT_GET)
3875 status = wlan_rate_ioctl_get_rate_value(pmadapter,
3876 pioctl_req);
3877 else
3878 status = wlan_rate_ioctl_set_rate_value(pmadapter,
3879 pioctl_req);
3880 } else {
3881 if (pioctl_req->action == MLAN_ACT_GET)
3882 status = wlan_rate_ioctl_get_rate_index(pmadapter,
3883 pioctl_req);
3884 else
3885 status = wlan_rate_ioctl_set_rate_index(pmadapter,
3886 pioctl_req);
3887 }
3888
3889 LEAVE();
3890 return status;
3891 }
3892
3893 /**
3894 * @brief Get data rates
3895 *
3896 * @param pmadapter A pointer to mlan_adapter structure
3897 * @param pioctl_req A pointer to ioctl request buffer
3898 *
3899 * @return MLAN_STATUS_PENDING --success, otherwise fail
3900 */
3901 mlan_status
wlan_rate_ioctl_get_data_rate(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3902 wlan_rate_ioctl_get_data_rate(IN pmlan_adapter pmadapter,
3903 IN pmlan_ioctl_req pioctl_req)
3904 {
3905 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3906 mlan_status ret = MLAN_STATUS_SUCCESS;
3907
3908 ENTER();
3909
3910 if (pioctl_req->action != MLAN_ACT_GET) {
3911 ret = MLAN_STATUS_FAILURE;
3912 goto exit;
3913 }
3914
3915 /* Send request to firmware */
3916 ret = wlan_prepare_cmd(pmpriv,
3917 HostCmd_CMD_802_11_TX_RATE_QUERY,
3918 HostCmd_ACT_GEN_GET,
3919 0, (t_void *)pioctl_req, MNULL);
3920 if (ret == MLAN_STATUS_SUCCESS)
3921 ret = MLAN_STATUS_PENDING;
3922
3923 exit:
3924 LEAVE();
3925 return ret;
3926 }
3927
3928 /**
3929 * @brief Set/Get remain on channel setting
3930 *
3931 * @param pmadapter A pointer to mlan_adapter structure
3932 * @param pioctl_req A pointer to ioctl request buffer
3933 *
3934 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
3935 */
3936 mlan_status
wlan_radio_ioctl_remain_chan_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3937 wlan_radio_ioctl_remain_chan_cfg(IN pmlan_adapter pmadapter,
3938 IN pmlan_ioctl_req pioctl_req)
3939 {
3940 mlan_status ret = MLAN_STATUS_SUCCESS;
3941 mlan_ds_radio_cfg *radio_cfg = MNULL;
3942 t_u16 cmd_action = 0;
3943 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3944
3945 ENTER();
3946
3947 radio_cfg = (mlan_ds_radio_cfg *)pioctl_req->pbuf;
3948 if (pioctl_req->action == MLAN_ACT_SET)
3949 cmd_action = HostCmd_ACT_GEN_SET;
3950 else
3951 cmd_action = HostCmd_ACT_GEN_GET;
3952
3953 /* Send request to firmware */
3954 ret = wlan_prepare_cmd(pmpriv,
3955 HostCmd_CMD_802_11_REMAIN_ON_CHANNEL,
3956 cmd_action,
3957 0,
3958 (t_void *)pioctl_req,
3959 &radio_cfg->param.remain_chan);
3960
3961 if (ret == MLAN_STATUS_SUCCESS)
3962 ret = MLAN_STATUS_PENDING;
3963
3964 LEAVE();
3965 return ret;
3966 }
3967
3968 #ifdef WIFI_DIRECT_SUPPORT
3969 /**
3970 * @brief Set/Get wifi_direct_mode
3971 *
3972 * @param pmadapter A pointer to mlan_adapter structure
3973 * @param pioctl_req A pointer to ioctl request buffer
3974 *
3975 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
3976 */
3977 mlan_status
wlan_bss_ioctl_wifi_direct_mode(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)3978 wlan_bss_ioctl_wifi_direct_mode(IN pmlan_adapter pmadapter,
3979 IN pmlan_ioctl_req pioctl_req)
3980 {
3981 mlan_status ret = MLAN_STATUS_SUCCESS;
3982 mlan_ds_bss *bss = MNULL;
3983
3984 t_u16 cmd_action = 0;
3985 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
3986
3987 ENTER();
3988
3989 bss = (mlan_ds_bss *)pioctl_req->pbuf;
3990
3991 if (pioctl_req->action == MLAN_ACT_SET)
3992 cmd_action = HostCmd_ACT_GEN_SET;
3993 else
3994 cmd_action = HostCmd_ACT_GEN_GET;
3995
3996 /* Send request to firmware */
3997 ret = wlan_prepare_cmd(pmpriv,
3998 HOST_CMD_WIFI_DIRECT_MODE_CONFIG,
3999 cmd_action,
4000 0, (t_void *)pioctl_req, &bss->param.wfd_mode);
4001
4002 if (ret == MLAN_STATUS_SUCCESS)
4003 ret = MLAN_STATUS_PENDING;
4004
4005 LEAVE();
4006 return ret;
4007 }
4008
4009 /**
4010 * @brief Set/Get p2p config
4011 *
4012 * @param pmadapter A pointer to mlan_adapter structure
4013 * @param pioctl_req A pointer to ioctl request buffer
4014 *
4015 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
4016 */
4017 mlan_status
wlan_misc_p2p_config(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4018 wlan_misc_p2p_config(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
4019 {
4020 mlan_status ret = MLAN_STATUS_SUCCESS;
4021 mlan_ds_misc_cfg *misc_cfg = MNULL;
4022 t_u16 cmd_action = 0;
4023 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4024
4025 ENTER();
4026
4027 misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4028 if (pioctl_req->action == MLAN_ACT_SET)
4029 cmd_action = HostCmd_ACT_GEN_SET;
4030 else
4031 cmd_action = HostCmd_ACT_GEN_GET;
4032
4033 /* Send request to firmware */
4034 ret = wlan_prepare_cmd(pmpriv,
4035 HOST_CMD_P2P_PARAMS_CONFIG,
4036 cmd_action,
4037 0,
4038 (t_void *)pioctl_req,
4039 &misc_cfg->param.p2p_config);
4040
4041 if (ret == MLAN_STATUS_SUCCESS)
4042 ret = MLAN_STATUS_PENDING;
4043
4044 LEAVE();
4045 return ret;
4046 }
4047 #endif
4048
4049 /**
4050 * @brief Set coalesce config
4051 *
4052 * @param pmadapter A pointer to mlan_adapter structure
4053 * @param pioctl_req A pointer to ioctl request buffer
4054 *
4055 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
4056 */
4057 mlan_status
wlan_misc_ioctl_coalesce_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4058 wlan_misc_ioctl_coalesce_cfg(IN pmlan_adapter pmadapter,
4059 IN pmlan_ioctl_req pioctl_req)
4060 {
4061 mlan_status ret = MLAN_STATUS_SUCCESS;
4062 mlan_ds_misc_cfg *misc_cfg = MNULL;
4063 t_u16 cmd_action = 0;
4064 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4065
4066 ENTER();
4067
4068 misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4069 if (pioctl_req->action == MLAN_ACT_SET)
4070 cmd_action = HostCmd_ACT_GEN_SET;
4071 else
4072 cmd_action = HostCmd_ACT_GEN_GET;
4073
4074 /* Send request to firmware */
4075 ret = wlan_prepare_cmd(pmpriv,
4076 HostCmd_CMD_COALESCE_CFG,
4077 cmd_action,
4078 0,
4079 (t_void *)pioctl_req,
4080 &misc_cfg->param.coalesce_cfg);
4081
4082 if (ret == MLAN_STATUS_SUCCESS)
4083 ret = MLAN_STATUS_PENDING;
4084
4085 LEAVE();
4086 return ret;
4087 }
4088
4089 /**
4090 * @brief Get/Set Tx control configuration
4091 *
4092 * @param pmadapter A pointer to mlan_adapter structure
4093 * @param pioctl_req A pointer to ioctl request buffer
4094 *
4095 * @return MLAN_STATUS_SUCCESS
4096 */
4097 mlan_status
wlan_misc_ioctl_txcontrol(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4098 wlan_misc_ioctl_txcontrol(IN pmlan_adapter pmadapter,
4099 IN pmlan_ioctl_req pioctl_req)
4100 {
4101 mlan_status ret = MLAN_STATUS_SUCCESS;
4102 mlan_ds_misc_cfg *misc = MNULL;
4103 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4104
4105 ENTER();
4106
4107 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4108 if (pioctl_req->action == MLAN_ACT_SET)
4109 pmpriv->pkt_tx_ctrl = misc->param.tx_control;
4110 else
4111 misc->param.tx_control = pmpriv->pkt_tx_ctrl;
4112
4113 LEAVE();
4114 return ret;
4115 }
4116
4117 #ifdef RX_PACKET_COALESCE
4118 /**
4119 * @brief Get/Set RX packet coalescing configuration
4120 *
4121 * @param pmadapter A pointer to mlan_adapter structure
4122 * @param pioctl_req A pointer to ioctl request buffer
4123 *
4124 * @return MLAN_STATUS_SUCCESS
4125 */
4126 mlan_status
wlan_misc_ioctl_rx_pkt_coalesce_config(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4127 wlan_misc_ioctl_rx_pkt_coalesce_config(IN pmlan_adapter pmadapter,
4128 IN pmlan_ioctl_req pioctl_req)
4129 {
4130 mlan_status ret = MLAN_STATUS_SUCCESS;
4131 mlan_ds_misc_cfg *misc = MNULL;
4132 t_u16 cmd_action = 0;
4133 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4134
4135 ENTER();
4136
4137 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4138
4139 if (pioctl_req->action == MLAN_ACT_SET)
4140 cmd_action = HostCmd_ACT_GEN_SET;
4141 else
4142 cmd_action = HostCmd_ACT_GEN_GET;
4143
4144 /* Send request to firmware */
4145 ret = wlan_prepare_cmd(pmpriv,
4146 HostCmd_CMD_RX_PKT_COALESCE_CFG,
4147 cmd_action,
4148 0,
4149 (t_void *)pioctl_req, &misc->param.rx_coalesce);
4150
4151 if (ret == MLAN_STATUS_SUCCESS)
4152 ret = MLAN_STATUS_PENDING;
4153
4154 LEAVE();
4155 return ret;
4156 }
4157 #endif
4158 /**
4159 * @brief Get/Set channel time and buffer weight configuration
4160 *
4161 * @param pmadapter A pointer to mlan_adapter structure
4162 * @param pioctl_req A pointer to ioctl request buffer
4163 *
4164 * @return MLAN_STATUS_SUCCESS
4165 */
4166 mlan_status
wlan_misc_ioctl_multi_chan_config(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4167 wlan_misc_ioctl_multi_chan_config(IN pmlan_adapter pmadapter,
4168 IN pmlan_ioctl_req pioctl_req)
4169 {
4170 mlan_status ret = MLAN_STATUS_SUCCESS;
4171 mlan_ds_misc_cfg *misc = MNULL;
4172 t_u16 cmd_action = 0;
4173 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4174
4175 ENTER();
4176
4177 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4178
4179 if (pioctl_req->action == MLAN_ACT_SET)
4180 cmd_action = HostCmd_ACT_GEN_SET;
4181 else
4182 cmd_action = HostCmd_ACT_GEN_GET;
4183
4184 /* Send request to firmware */
4185 ret = wlan_prepare_cmd(pmpriv,
4186 HostCmd_CMD_MULTI_CHAN_CONFIG,
4187 cmd_action,
4188 0,
4189 (t_void *)pioctl_req,
4190 &misc->param.multi_chan_cfg);
4191
4192 if (ret == MLAN_STATUS_SUCCESS)
4193 ret = MLAN_STATUS_PENDING;
4194
4195 LEAVE();
4196 return ret;
4197 }
4198
4199 /**
4200 * @brief Get/Set multi-channel policy setting
4201 *
4202 * @param pmadapter A pointer to mlan_adapter structure
4203 * @param pioctl_req A pointer to ioctl request buffer
4204 *
4205 * @return MLAN_STATUS_SUCCESS
4206 */
4207 mlan_status
wlan_misc_ioctl_multi_chan_policy(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4208 wlan_misc_ioctl_multi_chan_policy(IN pmlan_adapter pmadapter,
4209 IN pmlan_ioctl_req pioctl_req)
4210 {
4211 mlan_status ret = MLAN_STATUS_SUCCESS;
4212 mlan_ds_misc_cfg *misc = MNULL;
4213 t_u16 cmd_action = 0;
4214 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4215
4216 ENTER();
4217
4218 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4219
4220 if (pioctl_req->action == MLAN_ACT_SET) {
4221 if (pmadapter->dfs_repeater) {
4222 PRINTM(MMSG,
4223 "DFS-Repeater is on, can not enable DRCS\n");
4224 ret = MLAN_STATUS_FAILURE;
4225 goto fail;
4226 }
4227 cmd_action = HostCmd_ACT_GEN_SET;
4228 } else {
4229 cmd_action = HostCmd_ACT_GEN_GET;
4230 }
4231
4232 /* Send request to firmware */
4233 ret = wlan_prepare_cmd(pmpriv,
4234 HostCmd_CMD_MULTI_CHAN_POLICY,
4235 cmd_action,
4236 0,
4237 (t_void *)pioctl_req,
4238 &misc->param.multi_chan_policy);
4239
4240 if (ret == MLAN_STATUS_SUCCESS)
4241 ret = MLAN_STATUS_PENDING;
4242 fail:
4243 LEAVE();
4244 return ret;
4245 }
4246
4247 /**
4248 * @brief Get/Set DRCS configuration
4249 *
4250 * @param pmadapter A pointer to mlan_adapter structure
4251 * @param pioctl_req A pointer to ioctl request buffer
4252 *
4253 * @return MLAN_STATUS_SUCCESS
4254 */
4255 mlan_status
wlan_misc_ioctl_drcs_config(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4256 wlan_misc_ioctl_drcs_config(IN pmlan_adapter pmadapter,
4257 IN pmlan_ioctl_req pioctl_req)
4258 {
4259 mlan_status ret = MLAN_STATUS_SUCCESS;
4260 mlan_ds_misc_cfg *misc = MNULL;
4261 t_u16 cmd_action = 0;
4262 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4263
4264 ENTER();
4265
4266 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4267
4268 if (pioctl_req->action == MLAN_ACT_SET)
4269 cmd_action = HostCmd_ACT_GEN_SET;
4270 else
4271 cmd_action = HostCmd_ACT_GEN_GET;
4272
4273 /* Send request to firmware */
4274 ret = wlan_prepare_cmd(pmpriv,
4275 HostCmd_CMD_DRCS_CONFIG,
4276 cmd_action,
4277 0, (t_void *)pioctl_req, &misc->param.drcs_cfg);
4278
4279 if (ret == MLAN_STATUS_SUCCESS)
4280 ret = MLAN_STATUS_PENDING;
4281
4282 LEAVE();
4283 return ret;
4284 }
4285
4286 /**
4287 * @brief Is any uAP started or STA connected?
4288 *
4289 * @param pmadapter A pointer to mlan_adapter structure
4290 *
4291 * @return MTRUE/MFALSE
4292 */
4293 t_bool
wlan_check_interface_active(mlan_adapter * pmadapter)4294 wlan_check_interface_active(mlan_adapter *pmadapter)
4295 {
4296 t_bool ret = MFALSE;
4297 pmlan_private pmpriv;
4298 int i;
4299
4300 if (pmadapter == MNULL)
4301 return MFALSE;
4302
4303 for (i = 0; i < pmadapter->priv_num; i++) {
4304 pmpriv = pmadapter->priv[i];
4305 if (pmpriv) {
4306 #ifdef UAP_SUPPORT
4307 if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_UAP)
4308 ret = pmpriv->uap_bss_started;
4309 else
4310 #endif
4311 if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA)
4312 ret = pmpriv->media_connected;
4313 }
4314 if (ret)
4315 return MTRUE;
4316 }
4317
4318 return MFALSE;
4319 }
4320
4321 /**
4322 * @brief Get/Set DFS REPEATER mode
4323 *
4324 * @param pmadapter A pointer to mlan_adapter structure
4325 * @param pioctl_req A pointer to ioctl request buffer
4326 *
4327 * @return MLAN_STATUS_SUCCESS
4328 */
4329 mlan_status
wlan_misc_ioctl_dfs_repeater_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4330 wlan_misc_ioctl_dfs_repeater_cfg(IN pmlan_adapter pmadapter,
4331 IN pmlan_ioctl_req pioctl_req)
4332 {
4333 mlan_status ret = MLAN_STATUS_SUCCESS;
4334 mlan_ds_misc_cfg *misc = MNULL;
4335 t_u16 cmd_action = 0;
4336 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4337
4338 ENTER();
4339
4340 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4341
4342 if (pioctl_req->action == MLAN_ACT_SET) {
4343 /* Make sure no interface is active
4344 * before setting the dfs repeater mode
4345 */
4346 if (wlan_check_interface_active(pmadapter)) {
4347 PRINTM(MMSG, "DFS-Repeater active priv found,"
4348 " skip enabling the mode.\n");
4349 ret = MLAN_STATUS_FAILURE;
4350 goto done;
4351 }
4352
4353 /* If DRCS is on then we should not set
4354 * DFS-repeater mode */
4355 if (pmadapter->mc_policy) {
4356 PRINTM(MERROR,
4357 "DFS-repeater cannot be started when DRCS is on\n");
4358 ret = MLAN_STATUS_FAILURE;
4359 goto done;
4360 }
4361 cmd_action = HostCmd_ACT_GEN_SET;
4362 } else {
4363 cmd_action = HostCmd_ACT_GEN_GET;
4364 }
4365
4366 /* Send request to firmware */
4367 ret = wlan_prepare_cmd(pmpriv, HostCmd_DFS_REPEATER_MODE, cmd_action, 0,
4368 (t_void *)pioctl_req, &misc->param.dfs_repeater);
4369
4370 done:
4371 if (ret == MLAN_STATUS_SUCCESS)
4372 ret = MLAN_STATUS_PENDING;
4373
4374 LEAVE();
4375 return ret;
4376 }
4377
4378 /**
4379 * @brief Configure PMIC in Firmware
4380 *
4381 * @param pmadapter A pointer to mlan_adapter structure
4382 * @param pioctl_req A pointer to ioctl request buffer
4383 *
4384 * @return MLAN_STATUS_SUCCESS
4385 */
4386 mlan_status
wlan_misc_ioctl_pmic_configure(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4387 wlan_misc_ioctl_pmic_configure(IN pmlan_adapter pmadapter,
4388 IN pmlan_ioctl_req pioctl_req)
4389 {
4390 mlan_status ret = MLAN_STATUS_SUCCESS;
4391 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4392
4393 ENTER();
4394
4395 /* Send request to firmware */
4396 ret = wlan_prepare_cmd(pmpriv,
4397 HOST_CMD_PMIC_CONFIGURE,
4398 HostCmd_ACT_GEN_SET,
4399 0, (t_void *)pioctl_req, MNULL);
4400
4401 if (ret == MLAN_STATUS_SUCCESS)
4402 ret = MLAN_STATUS_PENDING;
4403
4404 LEAVE();
4405 return ret;
4406 }
4407
4408 /* @brief Set/Get CW Mode Level control
4409 *
4410 * @param pmadapter A pointer to mlan_adapter structure
4411 * @param pioctl_req A pointer to ioctl request buffer
4412 *
4413 * @return MLAN_STATUS_SUCCESS
4414 */
4415 mlan_status
wlan_misc_ioctl_cwmode_ctrl(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4416 wlan_misc_ioctl_cwmode_ctrl(IN pmlan_adapter pmadapter,
4417 IN pmlan_ioctl_req pioctl_req)
4418 {
4419 mlan_status ret = MLAN_STATUS_SUCCESS;
4420 mlan_ds_misc_cfg *misc = MNULL;
4421 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4422 t_u16 cmd_action = 0;
4423
4424 ENTER();
4425
4426 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4427
4428 if (pioctl_req->action == MLAN_ACT_SET)
4429 cmd_action = HostCmd_ACT_GEN_SET;
4430 else
4431 cmd_action = HostCmd_ACT_GEN_GET;
4432
4433 /* Send request to firmware */
4434 ret = wlan_prepare_cmd(pmpriv,
4435 HostCmd_CMD_CW_MODE_CTRL,
4436 cmd_action,
4437 0, (t_void *)pioctl_req, &misc->param.cwmode);
4438
4439 if (ret == MLAN_STATUS_SUCCESS)
4440 ret = MLAN_STATUS_PENDING;
4441
4442 LEAVE();
4443 return ret;
4444 }
4445
4446 /**
4447 * @brief Set/Get WPA passphrase for esupplicant
4448 *
4449 * @param pmadapter A pointer to mlan_adapter structure
4450 * @param pioctl_req A pointer to ioctl request buffer
4451 *
4452 * @return MLAN_STATUS_PENDING --success, otherwise fail
4453 */
4454 mlan_status
wlan_sec_ioctl_passphrase(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4455 wlan_sec_ioctl_passphrase(IN pmlan_adapter pmadapter,
4456 IN pmlan_ioctl_req pioctl_req)
4457 {
4458 mlan_status ret = MLAN_STATUS_SUCCESS;
4459 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4460 mlan_ds_sec_cfg *sec = MNULL;
4461 t_u16 cmd_action = 0;
4462 #ifdef STA_SUPPORT
4463 BSSDescriptor_t *pbss_desc;
4464 int i = 0;
4465 #endif
4466 ENTER();
4467
4468 sec = (mlan_ds_sec_cfg *)pioctl_req->pbuf;
4469 #ifdef DRV_EMBEDDED_SUPPLICANT
4470 if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA &&
4471 !IS_FW_SUPPORT_SUPPLICANT(pmpriv->adapter)) {
4472 if (sec->param.passphrase.psk_type == MLAN_PSK_QUERY)
4473 SupplicantQueryPassphrase(pmpriv->psapriv,
4474 (void *)&sec->param.
4475 passphrase);
4476 else if (sec->param.passphrase.psk_type == MLAN_PSK_CLEAR)
4477 SupplicantClearPMK(pmpriv->psapriv,
4478 (void *)&sec->param.passphrase);
4479 else
4480 SupplicantSetPassphrase(pmpriv->psapriv,
4481 (void *)&sec->param.passphrase);
4482
4483 LEAVE();
4484 return ret;
4485 }
4486 #endif
4487
4488 if (pioctl_req->action == MLAN_ACT_SET) {
4489 if (sec->param.passphrase.psk_type == MLAN_PSK_CLEAR)
4490 cmd_action = HostCmd_ACT_GEN_REMOVE;
4491 else
4492 cmd_action = HostCmd_ACT_GEN_SET;
4493 } else if (pioctl_req->action == MLAN_ACT_CLEAR) {
4494 cmd_action = HostCmd_ACT_GEN_REMOVE;
4495 } else {
4496 if (sec->param.passphrase.psk_type == MLAN_PSK_QUERY) {
4497 #ifdef STA_SUPPORT
4498 if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA &&
4499 sec->param.passphrase.ssid.ssid_len == 0) {
4500 i = wlan_find_bssid_in_list(pmpriv,
4501 (t_u8 *)&sec->param.
4502 passphrase.bssid,
4503 MLAN_BSS_MODE_AUTO);
4504 if (i >= 0) {
4505 pbss_desc = &pmadapter->pscan_table[i];
4506 memcpy(pmadapter,
4507 &sec->param.passphrase.ssid,
4508 &pbss_desc->ssid,
4509 sizeof(mlan_802_11_ssid));
4510 memset(pmadapter,
4511 &sec->param.passphrase.bssid, 0,
4512 MLAN_MAC_ADDR_LENGTH);
4513 PRINTM(MINFO,
4514 "PSK_QUERY: found ssid=%s\n",
4515 sec->param.passphrase.ssid.ssid);
4516 }
4517 } else
4518 #endif
4519 memset(pmadapter, &sec->param.passphrase.bssid,
4520 0, MLAN_MAC_ADDR_LENGTH);
4521 }
4522 cmd_action = HostCmd_ACT_GEN_GET;
4523 }
4524
4525 /* Send request to firmware */
4526 ret = wlan_prepare_cmd(pmpriv,
4527 HostCmd_CMD_SUPPLICANT_PMK,
4528 cmd_action,
4529 0, (t_void *)pioctl_req, (t_void *)sec);
4530 if (ret == MLAN_STATUS_SUCCESS)
4531 ret = MLAN_STATUS_PENDING;
4532
4533 LEAVE();
4534 return ret;
4535 }
4536
4537 /**
4538 * @brief Set per packet Txctl and Rxinfo configuration
4539 *
4540 * @param pmadapter A pointer to mlan_adapter structure
4541 * @param pioctl_req A pointer to ioctl request buffer
4542 *
4543 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
4544 */
4545 mlan_status
wlan_misc_per_pkt_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4546 wlan_misc_per_pkt_cfg(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
4547 {
4548 mlan_status ret = MLAN_STATUS_SUCCESS;
4549 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4550 mlan_ds_misc_cfg *misc = MNULL;
4551
4552 ENTER();
4553
4554 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4555 pmpriv->rx_pkt_info = MFALSE;
4556 if (misc->param.txrx_pkt_ctrl & RX_PKT_INFO)
4557 pmpriv->rx_pkt_info = MTRUE;
4558
4559 LEAVE();
4560 return ret;
4561 }
4562
4563 /**
4564 * @brief Set/Get region code
4565 *
4566 * @param pmadapter A pointer to mlan_adapter structure
4567 * @param pioctl_req A pointer to ioctl request buffer
4568 *
4569 * @return MLAN_STATUS_SUCCESS --success, otherwise fail
4570 */
4571 mlan_status
wlan_misc_ioctl_region(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4572 wlan_misc_ioctl_region(IN pmlan_adapter pmadapter,
4573 IN pmlan_ioctl_req pioctl_req)
4574 {
4575 mlan_status ret = MLAN_STATUS_SUCCESS;
4576 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4577 mlan_ds_misc_cfg *misc = MNULL;
4578 int i;
4579
4580 ENTER();
4581
4582 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4583 if (pioctl_req->action == MLAN_ACT_GET) {
4584 misc->param.region_code = pmadapter->region_code;
4585 } else {
4586 if (pmadapter->otp_region && pmadapter->otp_region->force_reg) {
4587 PRINTM(MERROR,
4588 "ForceRegionRule is set in the on-chip OTP"
4589 " memory\n");
4590 LEAVE();
4591 return MLAN_STATUS_FAILURE;
4592 }
4593 for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
4594 /* Use the region code to search for the index */
4595 if (misc->param.region_code == region_code_index[i]) {
4596 pmadapter->region_code =
4597 (t_u16)misc->param.region_code;
4598 break;
4599 }
4600 }
4601 /* It's unidentified region code */
4602 if (i >= MRVDRV_MAX_REGION_CODE) {
4603 PRINTM(MERROR, "Region Code not identified\n");
4604 pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4605 LEAVE();
4606 return MLAN_STATUS_FAILURE;
4607 }
4608 pmadapter->cfp_code_bg = misc->param.region_code;
4609 pmadapter->cfp_code_a = misc->param.region_code;
4610 if (wlan_set_regiontable(pmpriv, (t_u8)pmadapter->region_code,
4611 pmadapter->config_bands | pmadapter->
4612 adhoc_start_band)) {
4613 pioctl_req->status_code = MLAN_ERROR_IOCTL_FAIL;
4614 ret = MLAN_STATUS_FAILURE;
4615 }
4616 }
4617 pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE;
4618
4619 LEAVE();
4620 return ret;
4621 }
4622
4623 /**
4624 * @brief Configure GPIO independent reset
4625 *
4626 * @param pmadapter A pointer to mlan_adapter structure
4627 * @param pioctl_req A pointer to ioctl request buffer
4628 *
4629 * @return MLAN_STATUS_PENDING --success, otherwise fail
4630 */
4631 mlan_status
wlan_misc_ioctl_ind_rst_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4632 wlan_misc_ioctl_ind_rst_cfg(IN pmlan_adapter pmadapter,
4633 IN pmlan_ioctl_req pioctl_req)
4634 {
4635 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4636 mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4637 mlan_status ret = MLAN_STATUS_SUCCESS;
4638 t_u16 cmd_action = 0;
4639
4640 ENTER();
4641
4642 if (pioctl_req->action == MLAN_ACT_GET)
4643 cmd_action = HostCmd_ACT_GEN_GET;
4644 else
4645 cmd_action = HostCmd_ACT_GEN_SET;
4646
4647 /* Send request to firmware */
4648 ret = wlan_prepare_cmd(pmpriv,
4649 HostCmd_CMD_INDEPENDENT_RESET_CFG,
4650 cmd_action, 0,
4651 (t_void *)pioctl_req,
4652 (t_void *)&misc->param.ind_rst_cfg);
4653
4654 if (ret == MLAN_STATUS_SUCCESS)
4655 ret = MLAN_STATUS_PENDING;
4656
4657 LEAVE();
4658 return ret;
4659 }
4660
4661 /**
4662 * @brief Get timestamp from firmware
4663 *
4664 * @param pmadapter A pointer to mlan_adapter structure
4665 * @param pioctl_req A pointer to ioctl request buffer
4666 *
4667 * @return MLAN_STATUS_PENDING --success, otherwise fail
4668 */
4669 mlan_status
wlan_misc_ioctl_get_tsf(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4670 wlan_misc_ioctl_get_tsf(IN pmlan_adapter pmadapter,
4671 IN pmlan_ioctl_req pioctl_req)
4672 {
4673 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4674 mlan_status ret = MLAN_STATUS_SUCCESS;
4675 t_u16 cmd_action = 0;
4676
4677 ENTER();
4678
4679 if (pioctl_req->action == MLAN_ACT_GET)
4680 cmd_action = HostCmd_ACT_GEN_GET;
4681 else {
4682 PRINTM(MERROR, "No support set tsf!");
4683 return MLAN_STATUS_FAILURE;
4684 }
4685
4686 /* Send request to firmware */
4687 ret = wlan_prepare_cmd(pmpriv,
4688 HostCmd_CMD_GET_TSF,
4689 cmd_action, 0, (t_void *)pioctl_req, MNULL);
4690
4691 if (ret == MLAN_STATUS_SUCCESS)
4692 ret = MLAN_STATUS_PENDING;
4693
4694 LEAVE();
4695 return ret;
4696 }
4697
4698 /**
4699 * @brief Create custom regulatory cfg
4700 *
4701 * @param pmadapter A pointer to mlan_adapter structure
4702 * @param pioctl_req A pointer to ioctl request buffer
4703 *
4704 * @return MLAN_STATUS_PENDING --success, otherwise fail
4705 */
4706 mlan_status
wlan_misc_chan_reg_cfg(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4707 wlan_misc_chan_reg_cfg(IN pmlan_adapter pmadapter,
4708 IN pmlan_ioctl_req pioctl_req)
4709 {
4710 mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
4711 mlan_status ret = MLAN_STATUS_SUCCESS;
4712 t_u16 cmd_action = 0;
4713
4714 ENTER();
4715
4716 if (pioctl_req->action == MLAN_ACT_GET)
4717 cmd_action = HostCmd_ACT_GEN_GET;
4718 else {
4719 PRINTM(MERROR, "No support set channel region cfg!");
4720 return MLAN_STATUS_FAILURE;
4721 }
4722
4723 /* Send request to firmware */
4724 ret = wlan_prepare_cmd(pmpriv,
4725 HostCmd_CMD_CHAN_REGION_CFG,
4726 cmd_action, 0, (t_void *)pioctl_req, MNULL);
4727
4728 if (ret == MLAN_STATUS_SUCCESS)
4729 ret = MLAN_STATUS_PENDING;
4730
4731 LEAVE();
4732 return ret;
4733 }
4734
4735 /**
4736 * @brief Check operating class validation
4737 *
4738 * @param pmadapter A pointer to mlan_adapter structure
4739 * @param pioctl_req Pointer to the IOCTL request buffer
4740 *
4741 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4742 */
4743 mlan_status
wlan_misc_ioctl_operclass_validation(IN pmlan_adapter pmadapter,IN mlan_ioctl_req * pioctl_req)4744 wlan_misc_ioctl_operclass_validation(IN pmlan_adapter pmadapter,
4745 IN mlan_ioctl_req *pioctl_req)
4746 {
4747 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4748 mlan_ds_misc_cfg *misc = MNULL;
4749 t_u8 channel, oper_class;
4750 mlan_status ret = MLAN_STATUS_SUCCESS;
4751
4752 ENTER();
4753
4754 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4755 channel = misc->param.bw_chan_oper.channel;
4756 oper_class = misc->param.bw_chan_oper.oper_class;
4757 if (pioctl_req->action == MLAN_ACT_GET) {
4758 ret = wlan_check_operclass_validation(pmpriv, channel,
4759 oper_class);
4760 } else {
4761 PRINTM(MERROR, "Unsupported cmd_action\n");
4762 LEAVE();
4763 return MLAN_STATUS_FAILURE;
4764 }
4765
4766 LEAVE();
4767 return ret;
4768 }
4769
4770 /**
4771 * @brief Get non-global operating class
4772 *
4773 * @param pmadapter A pointer to mlan_adapter structure
4774 * @param pioctl_req Pointer to the IOCTL request buffer
4775 *
4776 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4777 */
4778 mlan_status
wlan_misc_ioctl_oper_class(IN pmlan_adapter pmadapter,IN mlan_ioctl_req * pioctl_req)4779 wlan_misc_ioctl_oper_class(IN pmlan_adapter pmadapter,
4780 IN mlan_ioctl_req *pioctl_req)
4781 {
4782 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4783 mlan_ds_misc_cfg *misc = MNULL;
4784 t_u8 channel, bandwidth, oper_class;
4785 mlan_status ret = MLAN_STATUS_SUCCESS;
4786
4787 ENTER();
4788
4789 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4790 channel = misc->param.bw_chan_oper.channel;
4791 switch (misc->param.bw_chan_oper.bandwidth) {
4792 case 20:
4793 bandwidth = BW_20MHZ;
4794 break;
4795 case 40:
4796 bandwidth = BW_40MHZ;
4797 break;
4798 case 80:
4799 bandwidth = BW_80MHZ;
4800 break;
4801 default:
4802 bandwidth = BW_20MHZ;
4803 break;
4804 }
4805
4806 if (pioctl_req->action == MLAN_ACT_GET) {
4807 ret = wlan_get_curr_oper_class(pmpriv, channel, bandwidth,
4808 &oper_class);
4809 misc->param.bw_chan_oper.oper_class = oper_class;
4810 } else {
4811 PRINTM(MERROR, "Unsupported cmd_action\n");
4812 LEAVE();
4813 return MLAN_STATUS_FAILURE;
4814 }
4815
4816 LEAVE();
4817 return ret;
4818 }
4819
4820 /**
4821 * @brief config dynamic bandwidth
4822 *
4823 * @param pmadapter A pointer to mlan_adapter structure
4824 * @param pioctl_req Pointer to the IOCTL request buffer
4825 *
4826 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4827 */
4828 mlan_status
wlan_misc_ioctl_fw_dump_event(IN pmlan_adapter pmadapter,IN mlan_ioctl_req * pioctl_req)4829 wlan_misc_ioctl_fw_dump_event(IN pmlan_adapter pmadapter,
4830 IN mlan_ioctl_req *pioctl_req)
4831 {
4832 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4833 mlan_ds_misc_cfg *misc = MNULL;
4834 t_u16 cmd_action = 0;
4835 mlan_status ret = MLAN_STATUS_SUCCESS;
4836
4837 ENTER();
4838
4839 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4840
4841 if (pioctl_req->action == MLAN_ACT_SET)
4842 cmd_action = HostCmd_ACT_GEN_SET;
4843 else if (pioctl_req->action == MLAN_ACT_GET)
4844 cmd_action = HostCmd_ACT_GEN_GET;
4845 else {
4846 PRINTM(MERROR, "Unsupported cmd_action\n");
4847 LEAVE();
4848 return MLAN_STATUS_FAILURE;
4849 }
4850
4851 /* Send request to firmware */
4852 ret = wlan_prepare_cmd(pmpriv,
4853 HostCmd_CMD_FW_DUMP_EVENT,
4854 cmd_action, 0, (t_void *)pioctl_req, MNULL);
4855
4856 if (ret == MLAN_STATUS_SUCCESS)
4857 ret = MLAN_STATUS_PENDING;
4858
4859 LEAVE();
4860 return ret;
4861 }
4862
4863 /**
4864 * @brief Set/Get the network monitor configuration.
4865 *
4866 * @param pmadapter A pointer to mlan_adapter structure
4867 * @param pioctl_req A pointer to ioctl request buffer
4868 *
4869 * @return MLAN_STATUS_PENDING --success, otherwise fail
4870 */
4871 mlan_status
wlan_misc_ioctl_net_monitor(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4872 wlan_misc_ioctl_net_monitor(IN pmlan_adapter pmadapter,
4873 IN pmlan_ioctl_req pioctl_req)
4874 {
4875 mlan_private *pmpriv;
4876 mlan_ds_misc_cfg *misc;
4877 mlan_status ret = MLAN_STATUS_SUCCESS;
4878 t_u16 cmd_action = 0;
4879
4880 ENTER();
4881
4882 if (!pioctl_req) {
4883 LEAVE();
4884 return MLAN_STATUS_FAILURE;
4885 }
4886 pmpriv = pmadapter->priv[pioctl_req->bss_index];
4887
4888 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4889
4890 if (misc->param.net_mon.enable_net_mon == CHANNEL_SPEC_SNIFFER_MODE) {
4891 /* Net monitor IOCTL not allowed in connected state */
4892 if (pmpriv->media_connected == MTRUE) {
4893 PRINTM(MERROR,
4894 "IOCTL not allowed in connected state\n");
4895 pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
4896 LEAVE();
4897 return MLAN_STATUS_FAILURE;
4898 }
4899 }
4900
4901 if (pioctl_req->action == MLAN_ACT_SET)
4902 cmd_action = HostCmd_ACT_GEN_SET;
4903 else
4904 cmd_action = HostCmd_ACT_GEN_GET;
4905
4906 /* Send command to firmware */
4907 ret = wlan_prepare_cmd(pmpriv,
4908 HostCmd_CMD_802_11_NET_MONITOR,
4909 cmd_action,
4910 0, (t_void *)pioctl_req, &misc->param.net_mon);
4911
4912 if (ret == MLAN_STATUS_SUCCESS)
4913 ret = MLAN_STATUS_PENDING;
4914
4915 LEAVE();
4916 return ret;
4917 }
4918
4919 /**
4920 * @brief config boot sleep
4921 *
4922 * @param pmadapter A pointer to mlan_adapter structure
4923 * @param pioctl_req Pointer to the IOCTL request buffer
4924 *
4925 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4926 */
4927 mlan_status
wlan_misc_bootsleep(IN pmlan_adapter pmadapter,IN pmlan_ioctl_req pioctl_req)4928 wlan_misc_bootsleep(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req)
4929 {
4930 pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index];
4931 mlan_ds_misc_cfg *misc = MNULL;
4932 t_u16 cmd_action = 0;
4933 mlan_status ret = MLAN_STATUS_SUCCESS;
4934
4935 ENTER();
4936
4937 misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf;
4938
4939 if (pioctl_req->action == MLAN_ACT_SET)
4940 cmd_action = HostCmd_ACT_GEN_SET;
4941 else if (pioctl_req->action == MLAN_ACT_GET)
4942 cmd_action = HostCmd_ACT_GEN_GET;
4943 else {
4944 PRINTM(MERROR, "Unsupported cmd_action 0x%x\n",
4945 pioctl_req->action);
4946 LEAVE();
4947 return MLAN_STATUS_FAILURE;
4948 }
4949
4950 /* Send request to firmware */
4951 ret = wlan_prepare_cmd(pmpriv,
4952 HostCmd_CMD_BOOT_SLEEP,
4953 cmd_action,
4954 0,
4955 (t_void *)pioctl_req, &misc->param.boot_sleep);
4956
4957 if (ret == MLAN_STATUS_SUCCESS)
4958 ret = MLAN_STATUS_PENDING;
4959
4960 LEAVE();
4961 return ret;
4962 }
4963