1 /** @file mlan_shim.c
2 *
3 * @brief This file contains APIs to MOAL module.
4 *
5 * Copyright (C) 2008-2017, Marvell International Ltd.
6 *
7 * This software file (the "File") is distributed by Marvell International
8 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
9 * (the "License"). You may use, redistribute and/or modify this File in
10 * accordance with the terms and conditions of the License, a copy of which
11 * is available by writing to the Free Software Foundation, Inc.,
12 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
13 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
14 *
15 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
17 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
18 * this warranty disclaimer.
19 */
20
21 /********************************************************
22 Change log:
23 10/13/2008: initial version
24 ********************************************************/
25
26 #include "mlan.h"
27 #ifdef STA_SUPPORT
28 #include "mlan_join.h"
29 #endif
30 #include "mlan_util.h"
31 #include "mlan_fw.h"
32 #include "mlan_main.h"
33 #include "mlan_wmm.h"
34 #include "mlan_sdio.h"
35 #ifdef UAP_SUPPORT
36 #include "mlan_uap.h"
37 #endif
38 #include "mlan_11h.h"
39 #include "mlan_11n_rxreorder.h"
40
41 /********************************************************
42 Local Variables
43 ********************************************************/
44
45 /********************************************************
46 Global Variables
47 ********************************************************/
48 #ifdef STA_SUPPORT
49 mlan_operations mlan_sta_ops = {
50 /* init cmd handler */
51 wlan_ops_sta_init_cmd,
52 /* ioctl handler */
53 wlan_ops_sta_ioctl,
54 /* cmd handler */
55 wlan_ops_sta_prepare_cmd,
56 /* cmdresp handler */
57 wlan_ops_sta_process_cmdresp,
58 /* rx handler */
59 wlan_ops_sta_process_rx_packet,
60 /* Event handler */
61 wlan_ops_sta_process_event,
62 /* txpd handler */
63 wlan_ops_sta_process_txpd,
64 /* BSS role: STA */
65 MLAN_BSS_ROLE_STA,
66 };
67 #endif
68 #ifdef UAP_SUPPORT
69 mlan_operations mlan_uap_ops = {
70 /* init cmd handler */
71 wlan_ops_uap_init_cmd,
72 /* ioctl handler */
73 wlan_ops_uap_ioctl,
74 /* cmd handler */
75 wlan_ops_uap_prepare_cmd,
76 /* cmdresp handler */
77 wlan_ops_uap_process_cmdresp,
78 /* rx handler */
79 wlan_ops_uap_process_rx_packet,
80 /* Event handler */
81 wlan_ops_uap_process_event,
82 /* txpd handler */
83 wlan_ops_uap_process_txpd,
84 /* BSS role: uAP */
85 MLAN_BSS_ROLE_UAP,
86 };
87 #endif
88
89 /** mlan function table */
90 mlan_operations *mlan_ops[] = {
91 #ifdef STA_SUPPORT
92 &mlan_sta_ops,
93 #endif
94 #ifdef UAP_SUPPORT
95 &mlan_uap_ops,
96 #endif
97 MNULL,
98 };
99
100 /** Global moal_assert callback */
101 t_void (*assert_callback) (IN t_void *pmoal_handle, IN t_u32 cond) = MNULL;
102 #ifdef DEBUG_LEVEL1
103 #ifdef DEBUG_LEVEL2
104 #define DEFAULT_DEBUG_MASK (0xffffffff)
105 #else
106 #define DEFAULT_DEBUG_MASK (MMSG | MFATAL | MERROR)
107 #endif
108
109 /** Global moal_print callback */
110 t_void (*print_callback) (IN t_void *pmoal_handle,
111 IN t_u32 level, IN char *pformat, IN ...
112 ) = MNULL;
113
114 /** Global moal_get_system_time callback */
115 mlan_status (*get_sys_time_callback) (IN t_void *pmoal_handle,
116 OUT t_u32 *psec,
117 OUT t_u32 *pusec) = MNULL;
118
119 /** Global driver debug mit masks */
120 t_u32 mlan_drvdbg = DEFAULT_DEBUG_MASK;
121 #endif
122
123 /********************************************************
124 Local Functions
125 *******************************************************/
126 /**
127 * @brief This function process pending ioctl
128 *
129 * @param pmadapter A pointer to mlan_adapter structure
130 *
131 */
132 void
wlan_process_pending_ioctl(mlan_adapter * pmadapter)133 wlan_process_pending_ioctl(mlan_adapter *pmadapter)
134 {
135 pmlan_ioctl_req pioctl_buf;
136 mlan_status status = MLAN_STATUS_SUCCESS;
137 pmlan_callbacks pcb;
138 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
139 mlan_ds_bss *bss = MNULL;
140 #endif
141 #ifdef STA_SUPPORT
142 mlan_ds_misc_cfg *misc = MNULL;
143 #endif
144 ENTER();
145
146 pcb = &pmadapter->callbacks;
147
148 while ((pioctl_buf =
149 (pmlan_ioctl_req)util_dequeue_list(pmadapter->pmoal_handle,
150 &pmadapter->ioctl_pending_q,
151 pcb->moal_spin_lock,
152 pcb->moal_spin_unlock))) {
153 switch (pioctl_buf->req_id) {
154 #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
155 case MLAN_IOCTL_BSS:
156 bss = (mlan_ds_bss *)pioctl_buf->pbuf;
157 if (bss->sub_command == MLAN_OID_BSS_ROLE) {
158 PRINTM(MCMND, "Role switch ioctl\n");
159 status = wlan_bss_ioctl_bss_role(pmadapter,
160 pioctl_buf);
161 }
162 break;
163 #endif
164 #ifdef STA_SUPPORT
165 case MLAN_IOCTL_MISC_CFG:
166 misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf;
167 if (misc->sub_command == MLAN_OID_MISC_WARM_RESET) {
168 PRINTM(MCMND, "Warm Reset ioctl\n");
169 status = wlan_misc_ioctl_warm_reset(pmadapter,
170 pioctl_buf);
171 }
172 break;
173 #endif
174 default:
175 break;
176 }
177 if (status != MLAN_STATUS_PENDING)
178 pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
179 pioctl_buf, status);
180 }
181 LEAVE();
182 }
183
184 /********************************************************
185 Global Functions
186 ********************************************************/
187
188 /**
189 * @brief This function registers MOAL to MLAN module.
190 *
191 * @param pmdevice A pointer to a mlan_device structure
192 * allocated in MOAL
193 * @param ppmlan_adapter A pointer to a t_void pointer to store
194 * mlan_adapter structure pointer as the context
195 *
196 * @return MLAN_STATUS_SUCCESS
197 * The registration succeeded.
198 * MLAN_STATUS_FAILURE
199 * The registration failed.
200 *
201 * mlan_status mlan_register (
202 * IN pmlan_device pmdevice,
203 * OUT t_void **ppmlan_adapter
204 * );
205 *
206 * Comments
207 * MOAL constructs mlan_device data structure to pass moal_handle and
208 * mlan_callback table to MLAN. MLAN returns mlan_adapter pointer to
209 * the ppmlan_adapter buffer provided by MOAL.
210 * Headers:
211 * declared in mlan_decl.h
212 * See Also
213 * mlan_unregister
214 */
215 mlan_status
mlan_register(IN pmlan_device pmdevice,OUT t_void ** ppmlan_adapter)216 mlan_register(IN pmlan_device pmdevice, OUT t_void **ppmlan_adapter)
217 {
218 mlan_status ret = MLAN_STATUS_SUCCESS;
219 pmlan_adapter pmadapter = MNULL;
220 pmlan_callbacks pcb = MNULL;
221 t_u8 i = 0;
222 t_u32 j = 0;
223
224 if (!pmdevice || !ppmlan_adapter) {
225 return MLAN_STATUS_FAILURE;
226 }
227 MASSERT(ppmlan_adapter);
228 MASSERT(pmdevice->callbacks.moal_print);
229 #ifdef DEBUG_LEVEL1
230 print_callback = pmdevice->callbacks.moal_print;
231 get_sys_time_callback = pmdevice->callbacks.moal_get_system_time;
232 #endif
233 assert_callback = pmdevice->callbacks.moal_assert;
234
235 ENTER();
236
237 MASSERT(pmdevice->callbacks.moal_malloc);
238 MASSERT(pmdevice->callbacks.moal_memset);
239 MASSERT(pmdevice->callbacks.moal_memmove);
240
241 if (!pmdevice->callbacks.moal_malloc ||
242 !pmdevice->callbacks.moal_memset ||
243 !pmdevice->callbacks.moal_memmove) {
244 LEAVE();
245 return MLAN_STATUS_FAILURE;
246 }
247
248 /* Allocate memory for adapter structure */
249 if (pmdevice->callbacks.moal_vmalloc && pmdevice->callbacks.moal_vfree)
250 ret = pmdevice->callbacks.moal_vmalloc(pmdevice->pmoal_handle,
251 sizeof(mlan_adapter),
252 (t_u8 **)&pmadapter);
253 else
254 ret = pmdevice->callbacks.moal_malloc(pmdevice->pmoal_handle,
255 sizeof(mlan_adapter),
256 MLAN_MEM_DEF,
257 (t_u8 **)&pmadapter);
258 if ((ret != MLAN_STATUS_SUCCESS) || !pmadapter) {
259 ret = MLAN_STATUS_FAILURE;
260 goto exit_register;
261 }
262
263 pmdevice->callbacks.moal_memset(pmdevice->pmoal_handle, pmadapter,
264 0, sizeof(mlan_adapter));
265
266 pcb = &pmadapter->callbacks;
267
268 /* Save callback functions */
269 pmdevice->callbacks.moal_memmove(pmadapter->pmoal_handle, pcb,
270 &pmdevice->callbacks,
271 sizeof(mlan_callbacks));
272
273 /* Assertion for all callback functions */
274 MASSERT(pcb->moal_get_hw_spec_complete);
275 MASSERT(pcb->moal_init_fw_complete);
276 MASSERT(pcb->moal_shutdown_fw_complete);
277 MASSERT(pcb->moal_send_packet_complete);
278 MASSERT(pcb->moal_recv_packet);
279 MASSERT(pcb->moal_recv_event);
280 MASSERT(pcb->moal_ioctl_complete);
281
282 MASSERT(pcb->moal_write_reg);
283 MASSERT(pcb->moal_read_reg);
284 MASSERT(pcb->moal_alloc_mlan_buffer);
285 MASSERT(pcb->moal_free_mlan_buffer);
286 MASSERT(pcb->moal_write_data_sync);
287 MASSERT(pcb->moal_read_data_sync);
288 MASSERT(pcb->moal_mfree);
289 MASSERT(pcb->moal_memcpy);
290 MASSERT(pcb->moal_memcmp);
291 MASSERT(pcb->moal_get_system_time);
292 MASSERT(pcb->moal_init_timer);
293 MASSERT(pcb->moal_free_timer);
294 MASSERT(pcb->moal_start_timer);
295 MASSERT(pcb->moal_stop_timer);
296 MASSERT(pcb->moal_init_lock);
297 MASSERT(pcb->moal_free_lock);
298 MASSERT(pcb->moal_spin_lock);
299 MASSERT(pcb->moal_spin_unlock);
300 MASSERT(pcb->moal_hist_data_add);
301 MASSERT(pcb->moal_updata_peer_signal);
302 MASSERT(pcb->moal_do_div);
303 /* Save pmoal_handle */
304 pmadapter->pmoal_handle = pmdevice->pmoal_handle;
305
306 if ((pmdevice->int_mode == INT_MODE_GPIO) && (pmdevice->gpio_pin == 0)) {
307 PRINTM(MERROR, "SDIO_GPIO_INT_CONFIG: Invalid GPIO Pin\n");
308 ret = MLAN_STATUS_FAILURE;
309 goto error;
310 }
311 pmadapter->init_para.int_mode = pmdevice->int_mode;
312 pmadapter->init_para.gpio_pin = pmdevice->gpio_pin;
313 /* card specific probing has been deferred until now .. */
314 ret = wlan_sdio_probe(pmadapter);
315 if (MLAN_STATUS_SUCCESS != ret) {
316 ret = MLAN_STATUS_FAILURE;
317 goto error;
318 }
319 #ifdef DEBUG_LEVEL1
320 mlan_drvdbg = pmdevice->drvdbg;
321 #endif
322
323 #ifdef MFG_CMD_SUPPORT
324 pmadapter->init_para.mfg_mode = pmdevice->mfg_mode;
325 #endif
326 #if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR)
327 pmadapter->max_segs = pmdevice->max_segs;
328 pmadapter->max_seg_size = pmdevice->max_seg_size;
329 #endif
330
331 #ifdef SDIO_MULTI_PORT_TX_AGGR
332 pmadapter->init_para.mpa_tx_cfg = pmdevice->mpa_tx_cfg;
333 #endif
334 #ifdef SDIO_MULTI_PORT_RX_AGGR
335 pmadapter->init_para.mpa_rx_cfg = pmdevice->mpa_rx_cfg;
336 #endif
337 pmadapter->sdio_rx_aggr_enable = pmdevice->sdio_rx_aggr_enable;
338 pmadapter->init_para.auto_ds = pmdevice->auto_ds;
339 pmadapter->init_para.ps_mode = pmdevice->ps_mode;
340 if (pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_2K ||
341 pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_4K ||
342 pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_8K)
343 pmadapter->init_para.max_tx_buf = pmdevice->max_tx_buf;
344 #ifdef STA_SUPPORT
345 pmadapter->init_para.cfg_11d = pmdevice->cfg_11d;
346 #else
347 pmadapter->init_para.cfg_11d = 0;
348 #endif
349 pmadapter->init_para.dfs_master_radar_det_en =
350 DFS_MASTER_RADAR_DETECT_EN;
351 pmadapter->init_para.dfs_slave_radar_det_en = DFS_SLAVE_RADAR_DETECT_EN;
352 pmadapter->init_para.dev_cap_mask = pmdevice->dev_cap_mask;
353 pmadapter->init_para.indrstcfg = pmdevice->indrstcfg;
354 pmadapter->rx_work_flag = pmdevice->rx_work;
355
356 pmadapter->fixed_beacon_buffer = pmdevice->fixed_beacon_buffer;
357
358 pmadapter->multiple_dtim = pmdevice->multi_dtim;
359 pmadapter->inact_tmo = pmdevice->inact_tmo;
360 pmadapter->init_para.drcs_chantime_mode = pmdevice->drcs_chantime_mode;
361 pmadapter->init_para.fw_region = pmdevice->fw_region;
362 pmadapter->hs_wake_interval = pmdevice->hs_wake_interval;
363 if (pmdevice->indication_gpio != 0xff) {
364 pmadapter->ind_gpio = pmdevice->indication_gpio & 0x0f;
365 pmadapter->level = (pmdevice->indication_gpio & 0xf0) >> 4;
366 if (pmadapter->level != 0 && pmadapter->level != 1) {
367 PRINTM(MERROR,
368 "Indication GPIO level is wrong and will use default value 0.\n");
369 pmadapter->level = 0;
370 }
371 }
372
373 pmadapter->priv_num = 0;
374 pmadapter->priv[0] = MNULL;
375
376 if (pcb->moal_vmalloc && pcb->moal_vfree)
377 ret = pcb->moal_vmalloc(pmadapter->pmoal_handle,
378 sizeof(mlan_private),
379 (t_u8 **)&pmadapter->priv[0]);
380 else
381 ret = pcb->moal_malloc(pmadapter->pmoal_handle,
382 sizeof(mlan_private), MLAN_MEM_DEF,
383 (t_u8 **)&pmadapter->priv[0]);
384 if (ret != MLAN_STATUS_SUCCESS || !pmadapter->priv[0]) {
385 ret = MLAN_STATUS_FAILURE;
386 goto error;
387 }
388
389 pmadapter->priv_num++;
390 memset(pmadapter, pmadapter->priv[0], 0, sizeof(mlan_private));
391
392 pmadapter->priv[0]->adapter = pmadapter;
393 pmadapter->priv[0]->bss_type = (t_u8)pmdevice->bss_attr[0].bss_type;
394 pmadapter->priv[0]->frame_type = (t_u8)pmdevice->bss_attr[0].frame_type;
395 pmadapter->priv[0]->bss_priority =
396 (t_u8)pmdevice->bss_attr[0].bss_priority;
397 if (pmdevice->bss_attr[0].bss_type == MLAN_BSS_TYPE_STA)
398 pmadapter->priv[0]->bss_role = MLAN_BSS_ROLE_STA;
399 else if (pmdevice->bss_attr[0].bss_type == MLAN_BSS_TYPE_UAP)
400 pmadapter->priv[0]->bss_role = MLAN_BSS_ROLE_UAP;
401 #ifdef WIFI_DIRECT_SUPPORT
402 else if (pmdevice->bss_attr[0].bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
403 pmadapter->priv[0]->bss_role = MLAN_BSS_ROLE_STA;
404 if (pmdevice->bss_attr[0].bss_virtual)
405 pmadapter->priv[0]->bss_virtual = MTRUE;
406 }
407 #endif
408 /* Save bss_index and bss_num */
409 pmadapter->priv[0]->bss_index = 0;
410 pmadapter->priv[0]->bss_num = (t_u8)pmdevice->bss_attr[0].bss_num;
411
412 /* init function table */
413 for (j = 0; mlan_ops[j]; j++) {
414 if (mlan_ops[j]->bss_role == GET_BSS_ROLE(pmadapter->priv[0])) {
415 memcpy(pmadapter, &pmadapter->priv[0]->ops, mlan_ops[j],
416 sizeof(mlan_operations));
417 }
418 }
419 /** back up bss_attr table */
420 memcpy(pmadapter, pmadapter->bss_attr, pmdevice->bss_attr,
421 sizeof(pmadapter->bss_attr));
422
423 /* Initialize lock variables */
424 if (wlan_init_lock_list(pmadapter) != MLAN_STATUS_SUCCESS) {
425 ret = MLAN_STATUS_FAILURE;
426 goto error;
427 }
428
429 /** init lock varible for first priv */
430 if (wlan_init_priv_lock_list(pmadapter, 0) != MLAN_STATUS_SUCCESS) {
431 ret = MLAN_STATUS_FAILURE;
432 goto error;
433 }
434
435 /* Allocate memory for member of adapter structure */
436 if (wlan_allocate_adapter(pmadapter)) {
437 ret = MLAN_STATUS_FAILURE;
438 goto error;
439 }
440
441 /* Initialize timers */
442 if (wlan_init_timer(pmadapter) != MLAN_STATUS_SUCCESS) {
443 ret = MLAN_STATUS_FAILURE;
444 goto error;
445 }
446 /* Return pointer of mlan_adapter to MOAL */
447 *ppmlan_adapter = pmadapter;
448
449 goto exit_register;
450
451 error:
452 PRINTM(MINFO, "Leave mlan_register with error\n");
453 /* Free timers */
454 wlan_free_timer(pmadapter);
455 /* Free adapter structure */
456 wlan_free_adapter(pmadapter);
457 /* Free lock variables */
458 wlan_free_lock_list(pmadapter);
459 for (i = 0; i < MLAN_MAX_BSS_NUM; i++) {
460 if (pmadapter->priv[i]) {
461 if (pcb->moal_vmalloc && pcb->moal_vfree)
462 pcb->moal_vfree(pmadapter->pmoal_handle,
463 (t_u8 *)pmadapter->priv[i]);
464 else
465 pcb->moal_mfree(pmadapter->pmoal_handle,
466 (t_u8 *)pmadapter->priv[i]);
467 }
468 }
469 if (pcb->moal_vmalloc && pcb->moal_vfree)
470 pcb->moal_vfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
471 else
472 pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
473
474 exit_register:
475 LEAVE();
476 return ret;
477 }
478
479 /**
480 * @brief This function unregisters MOAL from MLAN module.
481 *
482 * @param pmlan_adapter A pointer to a mlan_device structure
483 * allocated in MOAL
484 *
485 * @return MLAN_STATUS_SUCCESS
486 * The deregistration succeeded.
487 */
488 mlan_status
mlan_unregister(IN t_void * pmlan_adapter)489 mlan_unregister(IN t_void *pmlan_adapter
490 )
491 {
492 mlan_status ret = MLAN_STATUS_SUCCESS;
493 mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
494 pmlan_callbacks pcb;
495 t_s32 i = 0;
496
497 MASSERT(pmlan_adapter);
498
499 ENTER();
500
501 pcb = &pmadapter->callbacks;
502 /* Free adapter structure */
503 wlan_free_adapter(pmadapter);
504
505 /* Free timers */
506 wlan_free_timer(pmadapter);
507
508 /* Free lock variables */
509 wlan_free_lock_list(pmadapter);
510
511 /* Free private structures */
512 for (i = 0; i < pmadapter->priv_num; i++) {
513 if (pmadapter->priv[i]) {
514 if (pcb->moal_vmalloc && pcb->moal_vfree)
515 pcb->moal_vfree(pmadapter->pmoal_handle,
516 (t_u8 *)pmadapter->priv[i]);
517 else
518 pcb->moal_mfree(pmadapter->pmoal_handle,
519 (t_u8 *)pmadapter->priv[i]);
520 }
521 }
522
523 /* Free mlan_adapter */
524 if (pcb->moal_vmalloc && pcb->moal_vfree)
525 pcb->moal_vfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
526 else
527 pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pmadapter);
528
529 LEAVE();
530 return ret;
531 }
532
533 /**
534 * @brief This function downloads the firmware
535 *
536 * @param pmlan_adapter A pointer to a t_void pointer to store
537 * mlan_adapter structure pointer
538 * @param pmfw A pointer to firmware image
539 *
540 * @return MLAN_STATUS_SUCCESS
541 * The firmware download succeeded.
542 * MLAN_STATUS_FAILURE
543 * The firmware download failed.
544 */
545 mlan_status
mlan_dnld_fw(IN t_void * pmlan_adapter,IN pmlan_fw_image pmfw)546 mlan_dnld_fw(IN t_void *pmlan_adapter, IN pmlan_fw_image pmfw)
547 {
548 mlan_status ret = MLAN_STATUS_SUCCESS;
549 mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
550 t_u32 poll_num = 1;
551 t_u32 winner = 0;
552
553 ENTER();
554 MASSERT(pmlan_adapter);
555
556 /*when using GPIO wakeup, don't run the below code.
557 *if using GPIO wakeup, host will do handshake with FW
558 *to check if FW wake up and pull up SDIO line, then reload driver.
559 *So when using GPIO wakeup, don't need driver to do check wakeup status again.
560 *when using SDIO interface wakeup, run the below code;
561 *if using SDIO interface wakeup, driver need to do check wakeup status with FW.
562 */
563
564 /* Card specific probing */
565 ret = wlan_sdio_probe(pmadapter);
566 if (ret == MLAN_STATUS_FAILURE) {
567 PRINTM(MERROR, "WLAN SDIO probe failed\n", ret);
568 LEAVE();
569 return ret;
570 }
571
572 /* Check if firmware is already running */
573 ret = wlan_check_fw_status(pmadapter, poll_num);
574 if (ret == MLAN_STATUS_SUCCESS) {
575 if (pmfw->fw_reload) {
576 ret = wlan_reset_fw(pmadapter);
577 if (ret == MLAN_STATUS_FAILURE) {
578 PRINTM(MERROR, "FW reset failure!");
579 LEAVE();
580 return ret;
581 }
582 } else {
583 PRINTM(MMSG,
584 "WLAN FW already running! Skip FW download\n");
585 goto done;
586 }
587 }
588 poll_num = MAX_FIRMWARE_POLL_TRIES;
589
590 /* Check if other interface is downloading */
591 ret = wlan_check_winner_status(pmadapter, &winner);
592 if (ret == MLAN_STATUS_FAILURE) {
593 PRINTM(MFATAL, "WLAN read winner status failed!\n");
594 goto done;
595 }
596 if (winner) {
597 PRINTM(MMSG,
598 "WLAN is not the winner (0x%x). Skip FW download\n",
599 winner);
600 poll_num = MAX_MULTI_INTERFACE_POLL_TRIES;
601 goto poll_fw;
602 }
603
604 if (pmfw) {
605 /* Download helper/firmware */
606 ret = wlan_dnld_fw(pmadapter, pmfw);
607 if (ret != MLAN_STATUS_SUCCESS) {
608 PRINTM(MERROR, "wlan_dnld_fw fail ret=0x%x\n", ret);
609 LEAVE();
610 return ret;
611 }
612 }
613
614 poll_fw:
615 /* Check if the firmware is downloaded successfully or not */
616 ret = wlan_check_fw_status(pmadapter, poll_num);
617 if (ret != MLAN_STATUS_SUCCESS) {
618 PRINTM(MFATAL, "FW failed to be active in time!\n");
619 ret = MLAN_STATUS_FAILURE;
620 LEAVE();
621 return ret;
622 }
623 done:
624
625 /* re-enable host interrupt for mlan after fw dnld is successful */
626 wlan_enable_host_int(pmadapter);
627
628 LEAVE();
629 return ret;
630 }
631
632 /**
633 * @brief This function pass init param to MLAN
634 *
635 * @param pmlan_adapter A pointer to a t_void pointer to store
636 * mlan_adapter structure pointer
637 * @param pparam A pointer to mlan_init_param structure
638 *
639 * @return MLAN_STATUS_SUCCESS
640 *
641 */
642 mlan_status
mlan_set_init_param(IN t_void * pmlan_adapter,IN pmlan_init_param pparam)643 mlan_set_init_param(IN t_void *pmlan_adapter, IN pmlan_init_param pparam)
644 {
645 mlan_status ret = MLAN_STATUS_SUCCESS;
646 mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
647
648 ENTER();
649 MASSERT(pmlan_adapter);
650
651 /** Save DPD data in MLAN */
652 if ((pparam->pdpd_data_buf) && (pparam->dpd_data_len > 0)) {
653 pmadapter->pdpd_data = pparam->pdpd_data_buf;
654 pmadapter->dpd_data_len = pparam->dpd_data_len;
655 }
656 if (pparam->ptxpwr_data_buf && (pparam->txpwr_data_len > 0)) {
657 pmadapter->ptxpwr_data = pparam->ptxpwr_data_buf;
658 pmadapter->txpwr_data_len = pparam->txpwr_data_len;
659 }
660 /** Save cal data in MLAN */
661 if ((pparam->pcal_data_buf) && (pparam->cal_data_len > 0)) {
662 pmadapter->pcal_data = pparam->pcal_data_buf;
663 pmadapter->cal_data_len = pparam->cal_data_len;
664 }
665
666 LEAVE();
667 return ret;
668 }
669
670 /**
671 * @brief This function initializes the firmware
672 *
673 * @param pmlan_adapter A pointer to a t_void pointer to store
674 * mlan_adapter structure pointer
675 *
676 * @return MLAN_STATUS_SUCCESS
677 * The firmware initialization succeeded.
678 * MLAN_STATUS_PENDING
679 * The firmware initialization is pending.
680 * MLAN_STATUS_FAILURE
681 * The firmware initialization failed.
682 */
683 mlan_status
mlan_init_fw(IN t_void * pmlan_adapter)684 mlan_init_fw(IN t_void *pmlan_adapter
685 )
686 {
687 mlan_status ret = MLAN_STATUS_SUCCESS;
688 mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
689
690 ENTER();
691 MASSERT(pmlan_adapter);
692
693 pmadapter->hw_status = WlanHardwareStatusGetHwSpec;
694
695 /* Initialize firmware, may return PENDING */
696 ret = wlan_init_fw(pmadapter);
697 PRINTM(MINFO, "wlan_init_fw returned ret=0x%x\n", ret);
698
699 LEAVE();
700 return ret;
701 }
702
703 /**
704 * @brief Shutdown firmware
705 *
706 * @param pmlan_adapter A pointer to mlan_adapter structure
707 *
708 * @return MLAN_STATUS_SUCCESS
709 * The firmware shutdown call succeeded.
710 * MLAN_STATUS_PENDING
711 * The firmware shutdown call is pending.
712 * MLAN_STATUS_FAILURE
713 * The firmware shutdown call failed.
714 */
715 mlan_status
mlan_shutdown_fw(IN t_void * pmlan_adapter)716 mlan_shutdown_fw(IN t_void *pmlan_adapter
717 )
718 {
719 mlan_status ret = MLAN_STATUS_PENDING;
720 mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
721 pmlan_buffer pmbuf;
722 pmlan_ioctl_req pioctl_buf;
723 pmlan_callbacks pcb;
724 t_s32 i = 0;
725
726 ENTER();
727
728 MASSERT(pmlan_adapter);
729 /* MLAN already shutdown */
730 if (pmadapter->hw_status == WlanHardwareStatusNotReady) {
731 LEAVE();
732 return MLAN_STATUS_SUCCESS;
733 }
734
735 pmadapter->hw_status = WlanHardwareStatusClosing;
736 /* Wait for mlan_process to complete */
737 if (pmadapter->mlan_processing) {
738 PRINTM(MWARN, "MLAN main processing is still running\n");
739 LEAVE();
740 return ret;
741 }
742
743 /* Shut down MLAN */
744 PRINTM(MINFO, "Shutdown MLAN...\n");
745
746 /* Cancel all pending commands and complete ioctls */
747 wlan_cancel_all_pending_cmd(pmadapter);
748
749 /* Clean up priv structures */
750 for (i = 0; i < pmadapter->priv_num; i++) {
751 if (pmadapter->priv[i])
752 wlan_free_priv(pmadapter->priv[i]);
753 }
754
755 pcb = &pmadapter->callbacks;
756 /** cancel pending ioctl */
757 while ((pioctl_buf =
758 (pmlan_ioctl_req)util_dequeue_list(pmadapter->pmoal_handle,
759 &pmadapter->ioctl_pending_q,
760 pcb->moal_spin_lock,
761 pcb->moal_spin_unlock))) {
762 pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL;
763 pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf,
764 MLAN_STATUS_FAILURE);
765 }
766
767 while ((pmbuf = (pmlan_buffer)util_dequeue_list(pmadapter->pmoal_handle,
768 &pmadapter->
769 rx_data_queue,
770 pcb->moal_spin_lock,
771 pcb->
772 moal_spin_unlock))) {
773 wlan_free_mlan_buffer(pmadapter, pmbuf);
774 }
775 pmadapter->rx_pkts_queued = 0;
776
777 /* Notify completion */
778 ret = wlan_shutdown_fw_complete(pmadapter);
779
780 LEAVE();
781 return ret;
782 }
783
784 /**
785 * @brief queue main work
786 *
787 * @param pmadapter A pointer to mlan_adapter structure
788 *
789 * @return N/A
790 */
791 static t_void
mlan_queue_main_work(mlan_adapter * pmadapter)792 mlan_queue_main_work(mlan_adapter *pmadapter)
793 {
794 pmlan_callbacks pcb = &pmadapter->callbacks;
795 ENTER();
796 pcb->moal_spin_lock(pmadapter->pmoal_handle,
797 pmadapter->pmain_proc_lock);
798
799 /* Check if already processing */
800 if (pmadapter->mlan_processing) {
801 pmadapter->more_task_flag = MTRUE;
802 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
803 pmadapter->pmain_proc_lock);
804 } else {
805 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
806 pmadapter->pmain_proc_lock);
807 wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY),
808 MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL);
809 }
810 LEAVE();
811 return;
812 }
813
814 /**
815 * @brief queue rx_work
816 *
817 * @param pmadapter A pointer to mlan_adapter structure
818 *
819 * @return N/A
820 */
821 static t_void
mlan_queue_rx_work(mlan_adapter * pmadapter)822 mlan_queue_rx_work(mlan_adapter *pmadapter)
823 {
824 pmlan_callbacks pcb = &pmadapter->callbacks;
825 ENTER();
826
827 pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
828
829 /* Check if already processing */
830 if (pmadapter->mlan_rx_processing) {
831 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
832 pmadapter->prx_proc_lock);
833 } else {
834 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
835 pmadapter->prx_proc_lock);
836 wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY),
837 MLAN_EVENT_ID_DRV_DEFER_RX_WORK, MNULL);
838 }
839 LEAVE();
840 return;
841 }
842
843 /**
844 * @brief block main process
845 *
846 * @param pmadapter A pointer to mlan_adapter structure
847 * @param block MTRUE/MFALSE
848 *
849 * @return N/A
850 */
851 void
mlan_block_main_process(mlan_adapter * pmadapter,t_u8 block)852 mlan_block_main_process(mlan_adapter *pmadapter, t_u8 block)
853 {
854 pmlan_callbacks pcb = &pmadapter->callbacks;
855 pcb->moal_spin_lock(pmadapter->pmoal_handle,
856 pmadapter->pmain_proc_lock);
857 if (!block) {
858 pmadapter->main_lock_flag = MFALSE;
859 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
860 pmadapter->pmain_proc_lock);
861 } else {
862 pmadapter->main_lock_flag = MTRUE;
863 if (pmadapter->mlan_processing) {
864 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
865 pmadapter->pmain_proc_lock);
866 PRINTM(MEVENT, "wlan: wait main work done...\n");
867 wlan_recv_event(wlan_get_priv
868 (pmadapter, MLAN_BSS_ROLE_ANY),
869 MLAN_EVENT_ID_DRV_FLUSH_MAIN_WORK,
870 MNULL);
871 } else {
872 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
873 pmadapter->pmain_proc_lock);
874 }
875 }
876 }
877
878 /**
879 * @brief block rx process
880 *
881 * @param pmadapter A pointer to mlan_adapter structure
882 * @param block MTRUE/MFALSE;
883 *
884 * @return N/A
885 */
886 void
mlan_block_rx_process(mlan_adapter * pmadapter,t_u8 block)887 mlan_block_rx_process(mlan_adapter *pmadapter, t_u8 block)
888 {
889 pmlan_callbacks pcb = &pmadapter->callbacks;
890 pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
891 if (!block) {
892 pmadapter->rx_lock_flag = MFALSE;
893 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
894 pmadapter->prx_proc_lock);
895 } else {
896 pmadapter->rx_lock_flag = MTRUE;
897 if (pmadapter->mlan_rx_processing) {
898 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
899 pmadapter->prx_proc_lock);
900 PRINTM(MEVENT, "wlan: wait rx work done...\n");
901 wlan_recv_event(wlan_get_priv
902 (pmadapter, MLAN_BSS_ROLE_ANY),
903 MLAN_EVENT_ID_DRV_FLUSH_RX_WORK, MNULL);
904 } else {
905 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
906 pmadapter->prx_proc_lock);
907 }
908 }
909 }
910
911 /**
912 * @brief The receive process
913 *
914 * @param pmlan_adapter A pointer to mlan_adapter structure
915 * @param rx_pkts A pointer to save receive pkts number
916 *
917 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
918 */
919 mlan_status
mlan_rx_process(IN t_void * pmlan_adapter,IN t_u8 * rx_pkts)920 mlan_rx_process(IN t_void *pmlan_adapter, IN t_u8 *rx_pkts)
921 {
922 mlan_status ret = MLAN_STATUS_SUCCESS;
923 mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
924 pmlan_callbacks pcb;
925 pmlan_buffer pmbuf;
926 t_u8 limit = 0;
927 t_u8 rx_num = 0;
928
929 ENTER();
930
931 MASSERT(pmlan_adapter);
932 pcb = &pmadapter->callbacks;
933 pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
934 if (pmadapter->mlan_rx_processing || pmadapter->rx_lock_flag) {
935 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
936 pmadapter->prx_proc_lock);
937 goto exit_rx_proc;
938 } else {
939 pmadapter->mlan_rx_processing = MTRUE;
940 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
941 pmadapter->prx_proc_lock);
942 }
943 if (rx_pkts)
944 limit = *rx_pkts;
945 /* Check for Rx data */
946 while (MTRUE) {
947 if (pmadapter->flush_data) {
948 pmadapter->flush_data = MFALSE;
949 wlan_flush_rxreorder_tbl(pmadapter);
950 }
951 pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle,
952 pmadapter->rx_data_queue.
953 plock);
954 pmbuf = (pmlan_buffer)util_dequeue_list(pmadapter->pmoal_handle,
955 &pmadapter->
956 rx_data_queue, MNULL,
957 MNULL);
958 if (!pmbuf) {
959 pmadapter->callbacks.moal_spin_unlock(pmadapter->
960 pmoal_handle,
961 pmadapter->
962 rx_data_queue.
963 plock);
964 break;
965 }
966 pmadapter->rx_pkts_queued--;
967 rx_num++;
968 pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle,
969 pmadapter->rx_data_queue.
970 plock);
971 if (pmadapter->delay_task_flag &&
972 (pmadapter->rx_pkts_queued < LOW_RX_PENDING)) {
973 PRINTM(MEVENT, "Run\n");
974 pmadapter->delay_task_flag = MFALSE;
975 mlan_queue_main_work(pmadapter);
976 }
977 wlan_sdio_deaggr_rx_pkt(pmadapter, pmbuf);
978 if (limit && rx_num >= limit)
979 break;
980 }
981 if (rx_pkts)
982 *rx_pkts = rx_num;
983 pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
984 pmadapter->mlan_rx_processing = MFALSE;
985 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
986 pmadapter->prx_proc_lock);
987 exit_rx_proc:
988 LEAVE();
989 return ret;
990 }
991
992 /**
993 * @brief The main process
994 *
995 * @param pmlan_adapter A pointer to mlan_adapter structure
996 *
997 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
998 */
999 mlan_status
mlan_main_process(IN t_void * pmlan_adapter)1000 mlan_main_process(IN t_void *pmlan_adapter
1001 )
1002 {
1003 mlan_status ret = MLAN_STATUS_SUCCESS;
1004 mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
1005 pmlan_callbacks pcb;
1006
1007 ENTER();
1008
1009 MASSERT(pmlan_adapter);
1010
1011 pcb = &pmadapter->callbacks;
1012
1013 pcb->moal_spin_lock(pmadapter->pmoal_handle,
1014 pmadapter->pmain_proc_lock);
1015
1016 /* Check if already processing */
1017 if (pmadapter->mlan_processing || pmadapter->main_lock_flag) {
1018 pmadapter->more_task_flag = MTRUE;
1019 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
1020 pmadapter->pmain_proc_lock);
1021 goto exit_main_proc;
1022 } else {
1023 pmadapter->mlan_processing = MTRUE;
1024 pmadapter->main_process_cnt++;
1025 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
1026 pmadapter->pmain_proc_lock);
1027 }
1028 process_start:
1029 do {
1030 /* Is MLAN shutting down or not ready? */
1031 if ((pmadapter->hw_status == WlanHardwareStatusClosing) ||
1032 (pmadapter->hw_status == WlanHardwareStatusNotReady))
1033 break;
1034 if (pmadapter->pending_ioctl) {
1035 wlan_process_pending_ioctl(pmadapter);
1036 pmadapter->pending_ioctl = MFALSE;
1037 }
1038 if (pmadapter->rx_pkts_queued > HIGH_RX_PENDING) {
1039 PRINTM(MEVENT, "Pause\n");
1040 pmadapter->delay_task_flag = MTRUE;
1041 mlan_queue_rx_work(pmadapter);
1042 break;
1043 }
1044 /* Handle pending SDIO interrupts if any */
1045 if (pmadapter->sdio_ireg) {
1046 if (pmadapter->hs_activated == MTRUE)
1047 wlan_process_hs_config(pmadapter);
1048 wlan_process_int_status(pmadapter);
1049 if (pmadapter->data_received && pmadapter->rx_work_flag)
1050 mlan_queue_rx_work(pmadapter);
1051 }
1052
1053 /* Need to wake up the card ? */
1054 if ((pmadapter->ps_state == PS_STATE_SLEEP) &&
1055 (pmadapter->pm_wakeup_card_req &&
1056 !pmadapter->pm_wakeup_fw_try) &&
1057 (wlan_is_cmd_pending(pmadapter)
1058 || !wlan_bypass_tx_list_empty(pmadapter)
1059 || !wlan_wmm_lists_empty(pmadapter)
1060 )) {
1061 wlan_pm_wakeup_card(pmadapter);
1062 pmadapter->pm_wakeup_fw_try = MTRUE;
1063 continue;
1064 }
1065 if (IS_CARD_RX_RCVD(pmadapter)) {
1066 pmadapter->data_received = MFALSE;
1067 if (pmadapter->hs_activated == MTRUE) {
1068 pmadapter->is_hs_configured = MFALSE;
1069 wlan_host_sleep_activated_event(wlan_get_priv
1070 (pmadapter,
1071 MLAN_BSS_ROLE_ANY),
1072 MFALSE);
1073 }
1074 pmadapter->pm_wakeup_fw_try = MFALSE;
1075 if (pmadapter->ps_state == PS_STATE_SLEEP)
1076 pmadapter->ps_state = PS_STATE_AWAKE;
1077 } else {
1078 /* We have tried to wakeup the card already */
1079 if (pmadapter->pm_wakeup_fw_try)
1080 break;
1081 /* Check if we need to confirm Sleep Request received previously */
1082 if (pmadapter->ps_state == PS_STATE_PRE_SLEEP)
1083 if (!pmadapter->cmd_sent &&
1084 !pmadapter->curr_cmd)
1085 wlan_check_ps_cond(pmadapter);
1086 if (pmadapter->ps_state != PS_STATE_AWAKE ||
1087 (pmadapter->tx_lock_flag == MTRUE))
1088 break;
1089
1090 if (pmadapter->data_sent
1091 || wlan_is_tdls_link_chan_switching(pmadapter->
1092 tdls_status)
1093 || (wlan_bypass_tx_list_empty(pmadapter) &&
1094 wlan_wmm_lists_empty(pmadapter))
1095 || wlan_11h_radar_detected_tx_blocked(pmadapter)
1096 ) {
1097 if (pmadapter->cmd_sent || pmadapter->curr_cmd
1098 || !wlan_is_send_cmd_allowed(pmadapter->
1099 tdls_status) ||
1100 !wlan_is_cmd_pending(pmadapter)) {
1101 break;
1102 }
1103 }
1104 }
1105
1106 /* Check for Cmd Resp */
1107 if (pmadapter->cmd_resp_received) {
1108 pmadapter->cmd_resp_received = MFALSE;
1109 wlan_process_cmdresp(pmadapter);
1110
1111 /* call moal back when init_fw is done */
1112 if (pmadapter->hw_status == WlanHardwareStatusInitdone) {
1113 pmadapter->hw_status = WlanHardwareStatusReady;
1114 wlan_init_fw_complete(pmadapter);
1115 } else if (pmadapter->hw_status ==
1116 WlanHardwareStatusGetHwSpecdone) {
1117 pmadapter->hw_status =
1118 WlanHardwareStatusInitializing;
1119 wlan_get_hw_spec_complete(pmadapter);
1120 }
1121 }
1122
1123 /* Check for event */
1124 if (pmadapter->event_received) {
1125 pmadapter->event_received = MFALSE;
1126 wlan_process_event(pmadapter);
1127 }
1128
1129 /* Check if we need to confirm Sleep Request received previously */
1130 if (pmadapter->ps_state == PS_STATE_PRE_SLEEP)
1131 if (!pmadapter->cmd_sent && !pmadapter->curr_cmd)
1132 wlan_check_ps_cond(pmadapter);
1133
1134 /*
1135 * The ps_state may have been changed during processing of
1136 * Sleep Request event.
1137 */
1138 if ((pmadapter->ps_state == PS_STATE_SLEEP)
1139 || (pmadapter->ps_state == PS_STATE_PRE_SLEEP)
1140 || (pmadapter->ps_state == PS_STATE_SLEEP_CFM)
1141 || (pmadapter->tx_lock_flag == MTRUE)
1142 ) {
1143 continue;
1144 }
1145
1146 if (!pmadapter->cmd_sent && !pmadapter->curr_cmd
1147 && wlan_is_send_cmd_allowed(pmadapter->tdls_status)
1148 ) {
1149 if (wlan_exec_next_cmd(pmadapter) ==
1150 MLAN_STATUS_FAILURE) {
1151 ret = MLAN_STATUS_FAILURE;
1152 break;
1153 }
1154 }
1155
1156 if (!pmadapter->data_sent &&
1157 !wlan_11h_radar_detected_tx_blocked(pmadapter) &&
1158 !wlan_is_tdls_link_chan_switching(pmadapter->tdls_status) &&
1159 !wlan_bypass_tx_list_empty(pmadapter)) {
1160 PRINTM(MINFO, "mlan_send_pkt(): deq(bybass_txq)\n");
1161 wlan_process_bypass_tx(pmadapter);
1162 if (pmadapter->hs_activated == MTRUE) {
1163 pmadapter->is_hs_configured = MFALSE;
1164 wlan_host_sleep_activated_event(wlan_get_priv
1165 (pmadapter,
1166 MLAN_BSS_ROLE_ANY),
1167 MFALSE);
1168 }
1169 }
1170
1171 if (!pmadapter->data_sent && !wlan_wmm_lists_empty(pmadapter)
1172 && !wlan_11h_radar_detected_tx_blocked(pmadapter)
1173 && !wlan_is_tdls_link_chan_switching(pmadapter->tdls_status)
1174 ) {
1175 wlan_wmm_process_tx(pmadapter);
1176 if (pmadapter->hs_activated == MTRUE) {
1177 pmadapter->is_hs_configured = MFALSE;
1178 wlan_host_sleep_activated_event(wlan_get_priv
1179 (pmadapter,
1180 MLAN_BSS_ROLE_ANY),
1181 MFALSE);
1182 }
1183 }
1184
1185 #ifdef STA_SUPPORT
1186 if (pmadapter->delay_null_pkt && !pmadapter->cmd_sent &&
1187 !pmadapter->curr_cmd && !wlan_is_cmd_pending(pmadapter) &&
1188 wlan_bypass_tx_list_empty(pmadapter) &&
1189 wlan_wmm_lists_empty(pmadapter)) {
1190 if (wlan_send_null_packet
1191 (wlan_get_priv(pmadapter, MLAN_BSS_ROLE_STA),
1192 MRVDRV_TxPD_POWER_MGMT_NULL_PACKET |
1193 MRVDRV_TxPD_POWER_MGMT_LAST_PACKET)
1194 == MLAN_STATUS_SUCCESS) {
1195 pmadapter->delay_null_pkt = MFALSE;
1196 }
1197 break;
1198 }
1199 #endif
1200
1201 } while (MTRUE);
1202
1203 pcb->moal_spin_lock(pmadapter->pmoal_handle,
1204 pmadapter->pmain_proc_lock);
1205 if (pmadapter->more_task_flag == MTRUE) {
1206 pmadapter->more_task_flag = MFALSE;
1207 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
1208 pmadapter->pmain_proc_lock);
1209 goto process_start;
1210 }
1211 pmadapter->mlan_processing = MFALSE;
1212 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
1213 pmadapter->pmain_proc_lock);
1214
1215 exit_main_proc:
1216 if (pmadapter->hw_status == WlanHardwareStatusClosing)
1217 mlan_shutdown_fw(pmadapter);
1218 LEAVE();
1219 return ret;
1220 }
1221
1222 /**
1223 * @brief Function to send packet
1224 *
1225 * @param pmlan_adapter A pointer to mlan_adapter structure
1226 * @param pmbuf A pointer to mlan_buffer structure
1227 *
1228 * @return MLAN_STATUS_PENDING
1229 */
1230 mlan_status
mlan_send_packet(IN t_void * pmlan_adapter,IN pmlan_buffer pmbuf)1231 mlan_send_packet(IN t_void *pmlan_adapter, IN pmlan_buffer pmbuf)
1232 {
1233 mlan_status ret = MLAN_STATUS_PENDING;
1234 mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
1235 mlan_private *pmpriv;
1236 t_u16 eth_type = 0;
1237 t_u8 ra[MLAN_MAC_ADDR_LENGTH];
1238 tdlsStatus_e tdls_status;
1239
1240 ENTER();
1241 MASSERT(pmlan_adapter &&pmbuf);
1242
1243 if (!pmlan_adapter ||!pmbuf) {
1244 return MLAN_STATUS_FAILURE;
1245 }
1246
1247 MASSERT(pmbuf->bss_index < pmadapter->priv_num);
1248 pmbuf->flags |= MLAN_BUF_FLAG_MOAL_TX_BUF;
1249 pmpriv = pmadapter->priv[pmbuf->bss_index];
1250
1251 eth_type =
1252 mlan_ntohs(*(t_u16 *)&pmbuf->
1253 pbuf[pmbuf->data_offset +
1254 MLAN_ETHER_PKT_TYPE_OFFSET]);
1255 if (((pmadapter->priv[pmbuf->bss_index]->port_ctrl_mode == MTRUE) &&
1256 ((eth_type == MLAN_ETHER_PKT_TYPE_EAPOL)
1257 || (eth_type == MLAN_ETHER_PKT_TYPE_WAPI)
1258 ))
1259 || (eth_type == MLAN_ETHER_PKT_TYPE_TDLS_ACTION)
1260 || (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA)
1261
1262 ) {
1263 if (eth_type == MLAN_ETHER_PKT_TYPE_TDLS_ACTION) {
1264 memcpy(pmadapter, ra, pmbuf->pbuf + pmbuf->data_offset,
1265 MLAN_MAC_ADDR_LENGTH);
1266 tdls_status = wlan_get_tdls_link_status(pmpriv, ra);
1267 if (MTRUE == wlan_is_tdls_link_setup(tdls_status) ||
1268 !pmpriv->media_connected)
1269 pmbuf->flags |= MLAN_BUF_FLAG_TDLS;
1270 }
1271 PRINTM(MINFO, "mlan_send_pkt(): enq(bybass_txq)\n");
1272 wlan_add_buf_bypass_txqueue(pmadapter, pmbuf);
1273 } else {
1274 /* Transmit the packet */
1275 wlan_wmm_add_buf_txqueue(pmadapter, pmbuf);
1276 }
1277
1278 LEAVE();
1279 return ret;
1280 }
1281
1282 /**
1283 * @brief MLAN ioctl handler
1284 *
1285 * @param adapter A pointer to mlan_adapter structure
1286 * @param pioctl_req A pointer to ioctl request buffer
1287 *
1288 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail
1289 */
1290 mlan_status
mlan_ioctl(IN t_void * adapter,IN pmlan_ioctl_req pioctl_req)1291 mlan_ioctl(IN t_void *adapter, IN pmlan_ioctl_req pioctl_req)
1292 {
1293 mlan_status ret = MLAN_STATUS_SUCCESS;
1294 pmlan_adapter pmadapter = (pmlan_adapter)adapter;
1295 pmlan_private pmpriv = MNULL;
1296
1297 ENTER();
1298
1299 if (pioctl_req == MNULL) {
1300 PRINTM(MMSG, "Cancel all pending cmd!\n");
1301 wlan_cancel_all_pending_cmd(pmadapter);
1302 goto exit;
1303 }
1304 if (pioctl_req->action == MLAN_ACT_CANCEL) {
1305 wlan_cancel_pending_ioctl(pmadapter, pioctl_req);
1306 ret = MLAN_STATUS_SUCCESS;
1307 goto exit;
1308 }
1309 pmpriv = pmadapter->priv[pioctl_req->bss_index];
1310 ret = pmpriv->ops.ioctl(adapter, pioctl_req);
1311 exit:
1312 LEAVE();
1313 return ret;
1314 }
1315
1316 /**
1317 * @brief Packet receive completion callback handler
1318 *
1319 * @param pmlan_adapter A pointer to mlan_adapter structure
1320 * @param pmbuf A pointer to mlan_buffer structure
1321 * @param status Callback status
1322 *
1323 * @return MLAN_STATUS_SUCCESS
1324 */
1325 mlan_status
mlan_recv_packet_complete(IN t_void * pmlan_adapter,IN pmlan_buffer pmbuf,IN mlan_status status)1326 mlan_recv_packet_complete(IN t_void *pmlan_adapter,
1327 IN pmlan_buffer pmbuf, IN mlan_status status)
1328 {
1329 mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
1330
1331 ENTER();
1332 wlan_recv_packet_complete(pmadapter, pmbuf, status);
1333 LEAVE();
1334 return MLAN_STATUS_SUCCESS;
1335 }
1336
1337 /**
1338 * @brief select wmm queue
1339 *
1340 * @param pmlan_adapter A pointer to mlan_adapter structure
1341 * @param bss_num BSS number
1342 * @param tid TID
1343 *
1344 * @return wmm queue priority (0 - 3)
1345 */
1346 t_u8
mlan_select_wmm_queue(IN t_void * pmlan_adapter,IN t_u8 bss_num,IN t_u8 tid)1347 mlan_select_wmm_queue(IN t_void *pmlan_adapter, IN t_u8 bss_num, IN t_u8 tid)
1348 {
1349 mlan_adapter *pmadapter = (mlan_adapter *)pmlan_adapter;
1350 pmlan_private pmpriv = pmadapter->priv[bss_num];
1351 t_u8 ret;
1352 ENTER();
1353 ret = wlan_wmm_select_queue(pmpriv, tid);
1354 LEAVE();
1355 return ret;
1356 }
1357
1358 /**
1359 * @brief This function gets interrupt status.
1360 *
1361 */
1362 /**
1363 * @param adapter A pointer to mlan_adapter structure
1364 * @return N/A
1365 */
1366 mlan_status
mlan_interrupt(IN t_void * adapter)1367 mlan_interrupt(IN t_void *adapter)
1368 {
1369 mlan_adapter *pmadapter = (mlan_adapter *)adapter;
1370 mlan_status ret;
1371
1372 ENTER();
1373 ret = wlan_interrupt(pmadapter);
1374 LEAVE();
1375 return ret;
1376 }
1377
1378 /**
1379 * @brief This function wakeup firmware.
1380 *
1381 * @param adapter A pointer to mlan_adapter structure
1382 * @return N/A
1383 */
1384 t_void
mlan_pm_wakeup_card(IN t_void * adapter)1385 mlan_pm_wakeup_card(IN t_void *adapter)
1386 {
1387 mlan_adapter *pmadapter = (mlan_adapter *)adapter;
1388 ENTER();
1389 wlan_pm_wakeup_card(pmadapter);
1390 LEAVE();
1391 }
1392
1393 /**
1394 * @brief This function check main_process status.
1395 *
1396 * @param adapter A pointer to mlan_adapter structure
1397 * @return MTRUE/MFALSE
1398 */
1399 t_u8
mlan_is_main_process_running(IN t_void * adapter)1400 mlan_is_main_process_running(IN t_void *adapter)
1401 {
1402 mlan_adapter *pmadapter = (mlan_adapter *)adapter;
1403 pmlan_callbacks pcb = &pmadapter->callbacks;
1404 t_u8 ret = MFALSE;
1405 ENTER();
1406 pcb->moal_spin_lock(pmadapter->pmoal_handle,
1407 pmadapter->pmain_proc_lock);
1408
1409 /* Check if already processing */
1410 if (pmadapter->mlan_processing) {
1411 pmadapter->more_task_flag = MTRUE;
1412 ret = MTRUE;
1413 }
1414 pcb->moal_spin_unlock(pmadapter->pmoal_handle,
1415 pmadapter->pmain_proc_lock);
1416 LEAVE();
1417 return ret;
1418 }
1419