xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/mvl88w8977/mlan/mlan_shim.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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