xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/mvl88w8977/mlinux/moal_shim.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /** @file moal_shim.c
2   *
3   * @brief This file contains the callback functions registered to MLAN
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 /********************************************************
23 Change log:
24     10/21/2008: initial version
25 ********************************************************/
26 
27 #include	"moal_main.h"
28 #include	"moal_sdio.h"
29 #ifdef UAP_SUPPORT
30 #include    "moal_uap.h"
31 #endif
32 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
33 #include "moal_cfg80211.h"
34 #include "moal_cfgvendor.h"
35 #endif
36 extern int drv_mode;
37 #include <asm/div64.h>
38 
39 /********************************************************
40 		Local Variables
41 ********************************************************/
42 /** moal_lock */
43 typedef struct _moal_lock {
44 	/** Lock */
45 	spinlock_t lock;
46 	/** Flags */
47 	unsigned long flags;
48 } moal_lock;
49 
50 /********************************************************
51 		Global Variables
52 ********************************************************/
53 extern int cfg80211_wext;
54 
55 extern int hw_test;
56 
57 #ifdef ANDROID_KERNEL
58 extern int wakelock_timeout;
59 #endif
60 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
61 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
62 extern int dfs_offload;
63 #endif
64 #endif
65 
66 /** napi support*/
67 extern int napi;
68 
69 typedef MLAN_PACK_START struct {
70 	t_u32 t4;
71 	t_u8 t4_error;
72 	t_u32 t1;
73 	t_u8 t1_error;
74 	t_u64 egress_time;
75 } MLAN_PACK_END confirm_timestamps;
76 
77 /********************************************************
78 		Local Functions
79 ********************************************************/
80 
81 /********************************************************
82 		Global Functions
83 ********************************************************/
84 /**
85  *  @brief Alloc a buffer
86  *
87  *  @param pmoal_handle Pointer to the MOAL context
88  *  @param size     The size of the buffer to be allocated
89  *  @param flag     The type of the buffer to be allocated
90  *  @param ppbuf    Pointer to a buffer location to store buffer pointer allocated
91  *
92  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
93  */
94 mlan_status
moal_malloc(IN t_void * pmoal_handle,IN t_u32 size,IN t_u32 flag,OUT t_u8 ** ppbuf)95 moal_malloc(IN t_void *pmoal_handle,
96 	    IN t_u32 size, IN t_u32 flag, OUT t_u8 **ppbuf)
97 {
98 	moal_handle *handle = (moal_handle *)pmoal_handle;
99 	t_u32 mem_flag = (in_interrupt() || irqs_disabled() ||
100 			  !write_can_lock(&dev_base_lock)) ? GFP_ATOMIC :
101 		GFP_KERNEL;
102 
103 	if (flag & MLAN_MEM_DMA)
104 		mem_flag |= GFP_DMA;
105 
106 	*ppbuf = kzalloc(size, mem_flag);
107 	if (*ppbuf == NULL) {
108 		PRINTM(MERROR, "%s: allocate memory (%d bytes) failed!\n",
109 		       __func__, (int)size);
110 		return MLAN_STATUS_FAILURE;
111 	}
112 	atomic_inc(&handle->malloc_count);
113 
114 	return MLAN_STATUS_SUCCESS;
115 }
116 
117 /**
118  *  @brief Free a buffer
119  *
120  *  @param pmoal_handle Pointer to the MOAL context
121  *  @param pbuf     Pointer to the buffer to be freed
122  *
123  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
124  */
125 mlan_status
moal_mfree(IN t_void * pmoal_handle,IN t_u8 * pbuf)126 moal_mfree(IN t_void *pmoal_handle, IN t_u8 *pbuf)
127 {
128 	moal_handle *handle = (moal_handle *)pmoal_handle;
129 
130 	if (!pbuf)
131 		return MLAN_STATUS_FAILURE;
132 	kfree(pbuf);
133 	atomic_dec(&handle->malloc_count);
134 	return MLAN_STATUS_SUCCESS;
135 }
136 
137 /**
138  *  @brief Alloc a vitual-address-continuous buffer
139  *
140  *  @param pmoal_handle Pointer to the MOAL context
141  *  @param size     The size of the buffer to be allocated
142  *  @param ppbuf    Pointer to a buffer location to store buffer pointer allocated
143  *
144  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
145  */
146 mlan_status
moal_vmalloc(IN t_void * pmoal_handle,IN t_u32 size,OUT t_u8 ** ppbuf)147 moal_vmalloc(IN t_void *pmoal_handle, IN t_u32 size, OUT t_u8 **ppbuf)
148 {
149 	moal_handle *handle = (moal_handle *)pmoal_handle;
150 
151 	*ppbuf = vmalloc(size);
152 	if (*ppbuf == NULL) {
153 		PRINTM(MERROR, "%s: vmalloc (%d bytes) failed!", __func__,
154 		       (int)size);
155 		return MLAN_STATUS_FAILURE;
156 	}
157 	atomic_inc(&handle->vmalloc_count);
158 
159 	return MLAN_STATUS_SUCCESS;
160 }
161 
162 /**
163  *  @brief Free a buffer allocated by vmalloc
164  *
165  *  @param pmoal_handle Pointer to the MOAL context
166  *  @param pbuf     Pointer to the buffer to be freed
167  *
168  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
169  */
170 mlan_status
moal_vfree(IN t_void * pmoal_handle,IN t_u8 * pbuf)171 moal_vfree(IN t_void *pmoal_handle, IN t_u8 *pbuf)
172 {
173 	moal_handle *handle = (moal_handle *)pmoal_handle;
174 
175 	if (!pbuf)
176 		return MLAN_STATUS_FAILURE;
177 	vfree(pbuf);
178 	atomic_dec(&handle->vmalloc_count);
179 	return MLAN_STATUS_SUCCESS;
180 }
181 
182 /**
183  *  @brief Fill memory with constant byte
184  *
185  *  @param pmoal_handle Pointer to the MOAL context
186  *  @param pmem     Pointer to the memory area
187  *  @param byte     A constant byte
188  *  @param num      Number of bytes to fill
189  *
190  *  @return         Pointer to the memory area
191  */
192 t_void *
moal_memset(IN t_void * pmoal_handle,IN t_void * pmem,IN t_u8 byte,IN t_u32 num)193 moal_memset(IN t_void *pmoal_handle,
194 	    IN t_void *pmem, IN t_u8 byte, IN t_u32 num)
195 {
196 	t_void *p = pmem;
197 
198 	if (pmem && num)
199 		p = memset(pmem, byte, num);
200 
201 	return p;
202 }
203 
204 /**
205  *  @brief Copy memory from one area to another
206  *
207  *  @param pmoal_handle Pointer to the MOAL context
208  *  @param pdest    Pointer to the dest memory
209  *  @param psrc     Pointer to the src memory
210  *  @param num      Number of bytes to move
211  *
212  *  @return         Pointer to the dest memory
213  */
214 t_void *
moal_memcpy(IN t_void * pmoal_handle,IN t_void * pdest,IN const t_void * psrc,IN t_u32 num)215 moal_memcpy(IN t_void *pmoal_handle,
216 	    IN t_void *pdest, IN const t_void *psrc, IN t_u32 num)
217 {
218 	t_void *p = pdest;
219 
220 	if (pdest && psrc && num)
221 		p = memcpy(pdest, psrc, num);
222 
223 	return p;
224 }
225 
226 /**
227  *  @brief Move memory from one area to another
228  *
229  *  @param pmoal_handle Pointer to the MOAL context
230  *  @param pdest    Pointer to the dest memory
231  *  @param psrc     Pointer to the src memory
232  *  @param num      Number of bytes to move
233  *
234  *  @return         Pointer to the dest memory
235  */
236 t_void *
moal_memmove(IN t_void * pmoal_handle,IN t_void * pdest,IN const t_void * psrc,IN t_u32 num)237 moal_memmove(IN t_void *pmoal_handle,
238 	     IN t_void *pdest, IN const t_void *psrc, IN t_u32 num)
239 {
240 	t_void *p = pdest;
241 
242 	if (pdest && psrc && num)
243 		p = memmove(pdest, psrc, num);
244 
245 	return p;
246 }
247 
248 /**
249  *  @brief Compare two memory areas
250  *
251  *  @param pmoal_handle Pointer to the MOAL context
252  *  @param pmem1    Pointer to the first memory
253  *  @param pmem2    Pointer to the second memory
254  *  @param num      Number of bytes to compare
255  *
256  *  @return         Compare result returns by memcmp
257  */
258 t_s32
moal_memcmp(IN t_void * pmoal_handle,IN const t_void * pmem1,IN const t_void * pmem2,IN t_u32 num)259 moal_memcmp(IN t_void *pmoal_handle,
260 	    IN const t_void *pmem1, IN const t_void *pmem2, IN t_u32 num)
261 {
262 	t_s32 result;
263 
264 	result = memcmp(pmem1, pmem2, num);
265 
266 	return result;
267 }
268 
269 /**
270  *  @brief Delay function
271  *
272  *  @param pmoal_handle Pointer to the MOAL context
273  *  @param delay  delay in micro-second
274  *
275  *  @return       N/A
276  */
277 t_void
moal_udelay(IN t_void * pmoal_handle,IN t_u32 delay)278 moal_udelay(IN t_void *pmoal_handle, IN t_u32 delay)
279 {
280 	if (delay >= 1000)
281 		mdelay(delay / 1000);
282 	if (delay % 1000)
283 		udelay(delay % 1000);
284 }
285 
286 /**
287  *  @brief Retrieves the current system time
288  *
289  *  @param pmoal_handle Pointer to the MOAL context
290  *  @param psec     Pointer to buf for the seconds of system time
291  *  @param pusec    Pointer to buf the micro seconds of system time
292  *
293  *  @return         MLAN_STATUS_SUCCESS
294  */
295 mlan_status
moal_get_system_time(IN t_void * pmoal_handle,OUT t_u32 * psec,OUT t_u32 * pusec)296 moal_get_system_time(IN t_void *pmoal_handle, OUT t_u32 *psec, OUT t_u32 *pusec)
297 {
298 	struct timeval t;
299 
300 	do_gettimeofday(&t);
301 	*psec = (t_u32)t.tv_sec;
302 	*pusec = (t_u32)t.tv_usec;
303 
304 	return MLAN_STATUS_SUCCESS;
305 }
306 
307 /**
308  *  @brief Initializes the timer
309  *
310  *  @param pmoal_handle Pointer to the MOAL context
311  *  @param pptimer      Pointer to the timer
312  *  @param callback     Pointer to callback function
313  *  @param pcontext     Pointer to context
314  *
315  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
316  */
317 mlan_status
moal_init_timer(IN t_void * pmoal_handle,OUT t_void ** pptimer,IN t_void (* callback)(t_void * pcontext),IN t_void * pcontext)318 moal_init_timer(IN t_void *pmoal_handle,
319 		OUT t_void **pptimer,
320 		IN t_void (*callback) (t_void *pcontext), IN t_void *pcontext)
321 {
322 	moal_drv_timer *timer = NULL;
323 	t_u32 mem_flag = (in_interrupt() || irqs_disabled() ||
324 			  !write_can_lock(&dev_base_lock)) ? GFP_ATOMIC :
325 		GFP_KERNEL;
326 
327 	timer = kmalloc(sizeof(moal_drv_timer), mem_flag);
328 	if (timer == NULL)
329 		return MLAN_STATUS_FAILURE;
330 	woal_initialize_timer(timer, callback, pcontext);
331 	*pptimer = (t_void *)timer;
332 
333 	return MLAN_STATUS_SUCCESS;
334 }
335 
336 /**
337  *  @brief Free the timer
338  *
339  *  @param pmoal_handle Pointer to the MOAL context
340  *  @param ptimer   Pointer to the timer
341  *
342  *  @return         MLAN_STATUS_SUCCESS
343  */
344 mlan_status
moal_free_timer(IN t_void * pmoal_handle,IN t_void * ptimer)345 moal_free_timer(IN t_void *pmoal_handle, IN t_void *ptimer)
346 {
347 	moal_drv_timer *timer = (moal_drv_timer *)ptimer;
348 
349 	if (timer) {
350 		if ((timer->timer_is_canceled == MFALSE) && timer->time_period) {
351 			PRINTM(MWARN,
352 			       "mlan try to free timer without stop timer!\n");
353 			woal_cancel_timer(timer);
354 		}
355 		kfree(timer);
356 	}
357 
358 	return MLAN_STATUS_SUCCESS;
359 }
360 
361 /**
362  *  @brief Start the timer
363  *
364  *  @param pmoal_handle Pointer to the MOAL context
365  *  @param ptimer       Pointer to the timer
366  *  @param periodic     Periodic timer
367  *  @param msec         Timer value in milliseconds
368  *
369  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
370  */
371 mlan_status
moal_start_timer(IN t_void * pmoal_handle,IN t_void * ptimer,IN t_u8 periodic,IN t_u32 msec)372 moal_start_timer(IN t_void *pmoal_handle,
373 		 IN t_void *ptimer, IN t_u8 periodic, IN t_u32 msec)
374 {
375 	if (!ptimer)
376 		return MLAN_STATUS_FAILURE;
377 
378 	((moal_drv_timer *)ptimer)->timer_is_periodic = periodic;
379 	woal_mod_timer((moal_drv_timer *)ptimer, msec);
380 
381 	return MLAN_STATUS_SUCCESS;
382 }
383 
384 /**
385  *  @brief Stop the timer
386  *
387  *  @param pmoal_handle Pointer to the MOAL context
388  *  @param ptimer   Pointer to the timer
389  *
390  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
391  */
392 mlan_status
moal_stop_timer(IN t_void * pmoal_handle,IN t_void * ptimer)393 moal_stop_timer(IN t_void *pmoal_handle, IN t_void *ptimer)
394 {
395 	if (!ptimer)
396 		return MLAN_STATUS_FAILURE;
397 	woal_cancel_timer((moal_drv_timer *)ptimer);
398 
399 	return MLAN_STATUS_SUCCESS;
400 }
401 
402 /**
403  *  @brief Initializes the lock
404  *
405  *  @param pmoal_handle Pointer to the MOAL context
406  *  @param pplock   Pointer to the lock
407  *
408  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
409  */
410 mlan_status
moal_init_lock(IN t_void * pmoal_handle,OUT t_void ** pplock)411 moal_init_lock(IN t_void *pmoal_handle, OUT t_void **pplock)
412 {
413 	moal_handle *handle = (moal_handle *)pmoal_handle;
414 	moal_lock *mlock = NULL;
415 
416 	mlock = kmalloc(sizeof(moal_lock), GFP_ATOMIC);
417 	if (!mlock)
418 		return MLAN_STATUS_FAILURE;
419 	spin_lock_init(&mlock->lock);
420 	*pplock = (t_void *)mlock;
421 
422 	atomic_inc(&handle->lock_count);
423 
424 	return MLAN_STATUS_SUCCESS;
425 }
426 
427 /**
428  *  @brief Free the lock
429  *
430  *  @param pmoal_handle Pointer to the MOAL context
431  *  @param plock    Lock
432  *
433  *  @return         MLAN_STATUS_SUCCESS
434  */
435 mlan_status
moal_free_lock(IN t_void * pmoal_handle,IN t_void * plock)436 moal_free_lock(IN t_void *pmoal_handle, IN t_void *plock)
437 {
438 	moal_handle *handle = (moal_handle *)pmoal_handle;
439 	moal_lock *mlock = plock;
440 
441 	kfree(mlock);
442 	if (mlock)
443 		atomic_dec(&handle->lock_count);
444 
445 	return MLAN_STATUS_SUCCESS;
446 }
447 
448 /**
449  *  @brief Request a spin lock
450  *
451  *  @param pmoal_handle Pointer to the MOAL context
452  *  @param plock    Pointer to the lock
453  *
454  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
455  */
456 mlan_status
moal_spin_lock(IN t_void * pmoal_handle,IN t_void * plock)457 moal_spin_lock(IN t_void *pmoal_handle, IN t_void *plock)
458 {
459 	moal_lock *mlock = plock;
460 	unsigned long flags = 0;
461 
462 	if (mlock) {
463 		spin_lock_irqsave(&mlock->lock, flags);
464 		mlock->flags = flags;
465 		return MLAN_STATUS_SUCCESS;
466 	} else {
467 		return MLAN_STATUS_FAILURE;
468 	}
469 }
470 
471 /**
472  *  @brief Request a spin_unlock
473  *
474  *  @param pmoal_handle Pointer to the MOAL context
475  *  @param plock    Pointer to the lock
476  *
477  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
478  */
479 mlan_status
moal_spin_unlock(IN t_void * pmoal_handle,IN t_void * plock)480 moal_spin_unlock(IN t_void *pmoal_handle, IN t_void *plock)
481 {
482 	moal_lock *mlock = (moal_lock *)plock;
483 
484 	if (mlock) {
485 		spin_unlock_irqrestore(&mlock->lock, mlock->flags);
486 
487 		return MLAN_STATUS_SUCCESS;
488 	} else {
489 		return MLAN_STATUS_FAILURE;
490 	}
491 }
492 
493 /**
494  *  @brief This function reads one block of firmware data from MOAL
495  *
496  *  @param pmoal_handle Pointer to the MOAL context
497  *  @param offset       Offset from where the data will be copied
498  *  @param len          Length to be copied
499  *  @param pbuf         Buffer where the data will be copied
500  *
501  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
502  */
503 mlan_status
moal_get_fw_data(IN t_void * pmoal_handle,IN t_u32 offset,IN t_u32 len,OUT t_u8 * pbuf)504 moal_get_fw_data(IN t_void *pmoal_handle,
505 		 IN t_u32 offset, IN t_u32 len, OUT t_u8 *pbuf)
506 {
507 	moal_handle *handle = (moal_handle *)pmoal_handle;
508 
509 	if (!pbuf || !len)
510 		return MLAN_STATUS_FAILURE;
511 
512 	if (offset + len > handle->firmware->size)
513 		return MLAN_STATUS_FAILURE;
514 
515 	memcpy(pbuf, handle->firmware->data + offset, len);
516 
517 	return MLAN_STATUS_SUCCESS;
518 }
519 
520 /**
521  *  @brief This function is called when MLAN completes the initialization firmware.
522  *
523  *  @param pmoal_handle Pointer to the MOAL context
524  *  @param status   The status code for mlan_init_fw request
525  *  @param phw      pointer to mlan_hw_info
526  *  @param ptbl     pointer to mplan_bss_tbl
527  *  @return         MLAN_STATUS_SUCCESS
528  */
529 mlan_status
moal_get_hw_spec_complete(IN t_void * pmoal_handle,IN mlan_status status,IN mlan_hw_info * phw,IN pmlan_bss_tbl ptbl)530 moal_get_hw_spec_complete(IN t_void *pmoal_handle, IN mlan_status status,
531 			  IN mlan_hw_info * phw, IN pmlan_bss_tbl ptbl)
532 {
533 	ENTER();
534 	if (status == MLAN_STATUS_SUCCESS) {
535 		PRINTM(MCMND, "Get Hw Spec done, fw_cap=0x%x\n", phw->fw_cap);
536 	}
537 	LEAVE();
538 	return MLAN_STATUS_SUCCESS;
539 }
540 
541 /**
542  *  @brief This function is called when MLAN completes the initialization firmware.
543  *
544  *  @param pmoal_handle Pointer to the MOAL context
545  *  @param status   The status code for mlan_init_fw request
546  *
547  *  @return         MLAN_STATUS_SUCCESS
548  */
549 mlan_status
moal_init_fw_complete(IN t_void * pmoal_handle,IN mlan_status status)550 moal_init_fw_complete(IN t_void *pmoal_handle, IN mlan_status status)
551 {
552 	moal_handle *handle = (moal_handle *)pmoal_handle;
553 	ENTER();
554 	if (status == MLAN_STATUS_SUCCESS)
555 		handle->hardware_status = HardwareStatusReady;
556 	handle->init_wait_q_woken = MTRUE;
557 	wake_up_interruptible(&handle->init_wait_q);
558 	LEAVE();
559 	return MLAN_STATUS_SUCCESS;
560 }
561 
562 /**
563  *  @brief This function is called when MLAN shutdown firmware is completed.
564  *
565  *  @param pmoal_handle Pointer to the MOAL context
566  *  @param status   The status code for mlan_shutdown request
567  *
568  *  @return         MLAN_STATUS_SUCCESS
569  */
570 mlan_status
moal_shutdown_fw_complete(IN t_void * pmoal_handle,IN mlan_status status)571 moal_shutdown_fw_complete(IN t_void *pmoal_handle, IN mlan_status status)
572 {
573 	moal_handle *handle = (moal_handle *)pmoal_handle;
574 	ENTER();
575 	handle->hardware_status = HardwareStatusNotReady;
576 	handle->init_wait_q_woken = MTRUE;
577 	wake_up_interruptible(&handle->init_wait_q);
578 	LEAVE();
579 	return MLAN_STATUS_SUCCESS;
580 }
581 
582 /**
583  *  @brief This function is called when an MLAN IOCTL is completed.
584  *
585  *  @param pmoal_handle Pointer to the MOAL context
586  *  @param pioctl_req	pointer to structure mlan_ioctl_req
587  *  @param status   The status code for mlan_ioctl request
588  *
589  *  @return         MLAN_STATUS_SUCCESS
590  */
591 mlan_status
moal_ioctl_complete(IN t_void * pmoal_handle,IN pmlan_ioctl_req pioctl_req,IN mlan_status status)592 moal_ioctl_complete(IN t_void *pmoal_handle,
593 		    IN pmlan_ioctl_req pioctl_req, IN mlan_status status)
594 {
595 	moal_handle *handle = (moal_handle *)pmoal_handle;
596 	moal_private *priv = NULL;
597 	wait_queue *wait;
598 	unsigned long flags = 0;
599 	ENTER();
600 
601 	if (!atomic_read(&handle->ioctl_pending))
602 		PRINTM(MERROR, "ERR: Unexpected IOCTL completed: %p\n",
603 		       pioctl_req);
604 	else
605 		atomic_dec(&handle->ioctl_pending);
606 	priv = woal_bss_index_to_priv(handle, pioctl_req->bss_index);
607 	if (!priv) {
608 		PRINTM(MERROR,
609 		       "IOCTL %p complete with NULL priv, bss_index=%d\n",
610 		       pioctl_req, pioctl_req->bss_index);
611 		LEAVE();
612 		return MLAN_STATUS_SUCCESS;
613 	}
614 
615 	if (status != MLAN_STATUS_SUCCESS && status != MLAN_STATUS_COMPLETE)
616 		PRINTM(MERROR,
617 		       "IOCTL failed: %p id=0x%x, sub_id=0x%x action=%d, status_code=0x%x\n",
618 		       pioctl_req, pioctl_req->req_id,
619 		       (*(t_u32 *)pioctl_req->pbuf), (int)pioctl_req->action,
620 		       pioctl_req->status_code);
621 	else
622 		PRINTM(MIOCTL,
623 		       "IOCTL completed: %p id=0x%x sub_id=0x%x, action=%d,  status=%d, status_code=0x%x\n",
624 		       pioctl_req, pioctl_req->req_id,
625 		       (*(t_u32 *)pioctl_req->pbuf), (int)pioctl_req->action,
626 		       status, pioctl_req->status_code);
627 
628 	spin_lock_irqsave(&handle->driver_lock, flags);
629 	wait = (wait_queue *)pioctl_req->reserved_1;
630 	if (wait) {
631 		wait->condition = MTRUE;
632 		wait->status = status;
633 		if (wait->wait_timeout) {
634 			wake_up(&wait->wait);
635 		} else {
636 			if ((status != MLAN_STATUS_SUCCESS) &&
637 			    (pioctl_req->status_code ==
638 			     MLAN_ERROR_CMD_TIMEOUT)) {
639 				PRINTM(MERROR, "IOCTL: command timeout\n");
640 			} else {
641 				wake_up_interruptible(&wait->wait);
642 			}
643 		}
644 		spin_unlock_irqrestore(&handle->driver_lock, flags);
645 	} else {
646 		spin_unlock_irqrestore(&handle->driver_lock, flags);
647 		if ((status == MLAN_STATUS_SUCCESS) &&
648 		    (pioctl_req->action == MLAN_ACT_GET))
649 			woal_process_ioctl_resp(priv, pioctl_req);
650 		kfree(pioctl_req);
651 	}
652 	LEAVE();
653 	return MLAN_STATUS_SUCCESS;
654 }
655 
656 /**
657  *  @brief This function allocates mlan_buffer.
658  *
659  *  @param pmoal_handle Pointer to the MOAL context
660  *  @param size     allocation size requested
661  *  @param pmbuf    pointer to pointer to the allocated buffer
662  *
663  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
664  */
665 mlan_status
moal_alloc_mlan_buffer(IN t_void * pmoal_handle,IN t_u32 size,OUT pmlan_buffer * pmbuf)666 moal_alloc_mlan_buffer(IN t_void *pmoal_handle,
667 		       IN t_u32 size, OUT pmlan_buffer *pmbuf)
668 {
669 	*pmbuf = woal_alloc_mlan_buffer((moal_handle *)pmoal_handle, size);
670 	if (NULL == *pmbuf)
671 		return MLAN_STATUS_FAILURE;
672 	return MLAN_STATUS_SUCCESS;
673 }
674 
675 /**
676  *  @brief This function frees mlan_buffer.
677  *
678  *  @param pmoal_handle Pointer to the MOAL context
679  *  @param pmbuf    pointer to buffer to be freed
680  *
681  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
682  */
683 mlan_status
moal_free_mlan_buffer(IN t_void * pmoal_handle,IN pmlan_buffer pmbuf)684 moal_free_mlan_buffer(IN t_void *pmoal_handle, IN pmlan_buffer pmbuf)
685 {
686 	if (!pmbuf)
687 		return MLAN_STATUS_FAILURE;
688 	woal_free_mlan_buffer((moal_handle *)pmoal_handle, pmbuf);
689 	return MLAN_STATUS_SUCCESS;
690 }
691 
692 /**
693  *  @brief This function is called when MLAN complete send data packet.
694  *
695  *  @param pmoal_handle Pointer to the MOAL context
696  *  @param pmbuf    Pointer to the mlan buffer structure
697  *  @param status   The status code for mlan_send_packet request
698  *
699  *  @return         MLAN_STATUS_SUCCESS
700  */
701 mlan_status
moal_send_packet_complete(IN t_void * pmoal_handle,IN pmlan_buffer pmbuf,IN mlan_status status)702 moal_send_packet_complete(IN t_void *pmoal_handle,
703 			  IN pmlan_buffer pmbuf, IN mlan_status status)
704 {
705 	moal_private *priv = NULL;
706 	moal_handle *handle = (moal_handle *)pmoal_handle;
707 	struct sk_buff *skb = NULL;
708 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
709 	t_u32 index = 0;
710 #endif
711 
712 	ENTER();
713 	if (pmbuf && pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) {
714 		woal_free_mlan_buffer(handle, pmbuf);
715 		atomic_dec(&handle->tx_pending);
716 		LEAVE();
717 		return MLAN_STATUS_SUCCESS;
718 	}
719 	if (pmbuf) {
720 		priv = woal_bss_index_to_priv(pmoal_handle, pmbuf->bss_index);
721 		skb = (struct sk_buff *)pmbuf->pdesc;
722 		if (priv) {
723 			woal_set_trans_start(priv->netdev);
724 			if (skb) {
725 				if (status == MLAN_STATUS_SUCCESS) {
726 					priv->stats.tx_packets++;
727 					priv->stats.tx_bytes += skb->len;
728 				} else {
729 					priv->stats.tx_errors++;
730 				}
731 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
732 				index = skb_get_queue_mapping(skb);
733 				atomic_dec(&handle->tx_pending);
734 				if (atomic_dec_return
735 				    (&priv->wmm_tx_pending[index]) ==
736 				    LOW_TX_PENDING) {
737 					struct netdev_queue *txq =
738 						netdev_get_tx_queue(priv->
739 								    netdev,
740 								    index);
741 					if (netif_tx_queue_stopped(txq)) {
742 						netif_tx_wake_queue(txq);
743 						PRINTM(MINFO,
744 						       "Wakeup Kernel Queue:%d\n",
745 						       index);
746 					}
747 				}
748 #else /*#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) */
749 				if (atomic_dec_return(&handle->tx_pending) <
750 				    LOW_TX_PENDING) {
751 					int i;
752 					for (i = 0; i < handle->priv_num; i++) {
753 #ifdef STA_SUPPORT
754 						if ((GET_BSS_ROLE
755 						     (handle->priv[i]) ==
756 						     MLAN_BSS_ROLE_STA) &&
757 						    (handle->priv[i]->
758 						     media_connected ||
759 						     priv->
760 						     is_adhoc_link_sensed)) {
761 							woal_wake_queue(handle->
762 									priv
763 									[i]->
764 									netdev);
765 						}
766 #endif
767 #ifdef UAP_SUPPORT
768 						if ((GET_BSS_ROLE
769 						     (handle->priv[i]) ==
770 						     MLAN_BSS_ROLE_UAP) &&
771 						    (handle->priv[i]->
772 						     media_connected)) {
773 							woal_wake_queue(handle->
774 									priv
775 									[i]->
776 									netdev);
777 						}
778 #endif
779 					}
780 				}
781 #endif /*#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) */
782 			}
783 		}
784 		if (skb)
785 			dev_kfree_skb_any(skb);
786 	}
787 	LEAVE();
788 	return MLAN_STATUS_SUCCESS;
789 }
790 
791 /**
792  *  @brief This function write a command/data packet to card.
793  *         This function blocks the call until it finishes
794  *
795  *  @param pmoal_handle Pointer to the MOAL context
796  *  @param pmbuf    Pointer to the mlan buffer structure
797  *  @param port     Port number for sent
798  *  @param timeout  Timeout value in milliseconds (if 0 the wait is forever)
799  *
800  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
801  */
802 mlan_status
moal_write_data_sync(IN t_void * pmoal_handle,IN pmlan_buffer pmbuf,IN t_u32 port,IN t_u32 timeout)803 moal_write_data_sync(IN t_void *pmoal_handle,
804 		     IN pmlan_buffer pmbuf, IN t_u32 port, IN t_u32 timeout)
805 {
806 	return woal_write_data_sync((moal_handle *)pmoal_handle, pmbuf, port,
807 				    timeout);
808 }
809 
810 /**
811  *  @brief This function read data packet/event/command from card.
812  *         This function blocks the call until it finish
813  *
814  *  @param pmoal_handle Pointer to the MOAL context
815  *  @param pmbuf    Pointer to the mlan buffer structure
816  *  @param port     Port number for read
817  *  @param timeout  Timeout value in milliseconds (if 0 the wait is forever)
818  *
819  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
820  */
821 mlan_status
moal_read_data_sync(IN t_void * pmoal_handle,IN OUT pmlan_buffer pmbuf,IN t_u32 port,IN t_u32 timeout)822 moal_read_data_sync(IN t_void *pmoal_handle,
823 		    IN OUT pmlan_buffer pmbuf, IN t_u32 port, IN t_u32 timeout)
824 {
825 	return woal_read_data_sync((moal_handle *)pmoal_handle, pmbuf, port,
826 				   timeout);
827 }
828 
829 /**
830  *  @brief This function writes data into card register.
831  *
832  *  @param pmoal_handle Pointer to the MOAL context
833  *  @param reg          register offset
834  *  @param data         value
835  *
836  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
837  */
838 mlan_status
moal_write_reg(IN t_void * pmoal_handle,IN t_u32 reg,IN t_u32 data)839 moal_write_reg(IN t_void *pmoal_handle, IN t_u32 reg, IN t_u32 data)
840 {
841 	return woal_write_reg((moal_handle *)pmoal_handle, reg, data);
842 }
843 
844 /**
845  *  @brief This function reads data from card register.
846  *
847  *  @param pmoal_handle Pointer to the MOAL context
848  *  @param reg          register offset
849  *  @param data         value
850  *
851  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
852  */
853 mlan_status
moal_read_reg(IN t_void * pmoal_handle,IN t_u32 reg,OUT t_u32 * data)854 moal_read_reg(IN t_void *pmoal_handle, IN t_u32 reg, OUT t_u32 *data)
855 {
856 	return woal_read_reg((moal_handle *)pmoal_handle, reg, data);
857 }
858 
859 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
860 /**
861  *  @brief This function uploads the packet to the network stack monitor interface
862  *
863  *  @param handle Pointer to the MOAL context
864  *  @param pmbuf    Pointer to mlan_buffer
865  *
866  *  @return  MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING/MLAN_STATUS_FAILURE
867  */
868 mlan_status
moal_recv_packet_to_mon_if(IN moal_handle * handle,IN pmlan_buffer pmbuf)869 moal_recv_packet_to_mon_if(IN moal_handle *handle, IN pmlan_buffer pmbuf)
870 {
871 	mlan_status status = MLAN_STATUS_SUCCESS;
872 	struct sk_buff *skb = NULL;
873 	struct radiotap_header *rth = NULL;
874 	radiotap_info rt_info;
875 	t_u8 format = 0;
876 	t_u8 bw = 0;
877 	t_u8 gi = 0;
878 	t_u8 ldpc = 0;
879 	t_u8 chan_num;
880 	t_u8 band = 0;
881 	struct ieee80211_hdr *dot11_hdr = NULL;
882 	t_u8 *payload = NULL;
883 	ENTER();
884 	if (!pmbuf->pdesc) {
885 		LEAVE();
886 		return status;
887 	}
888 
889 	skb = (struct sk_buff *)pmbuf->pdesc;
890 
891 	if ((handle->mon_if) && netif_running(handle->mon_if->mon_ndev)) {
892 		if (handle->mon_if->radiotap_enabled) {
893 			if (skb_headroom(skb) < sizeof(*rth)) {
894 				PRINTM(MERROR,
895 				       "%s No space to add Radio TAP header\n",
896 				       __func__);
897 				status = MLAN_STATUS_FAILURE;
898 				handle->mon_if->stats.rx_dropped++;
899 				goto done;
900 			}
901 			dot11_hdr =
902 				(struct ieee80211_hdr *)(pmbuf->pbuf +
903 							 pmbuf->data_offset);
904 			memcpy(&rt_info,
905 			       pmbuf->pbuf + pmbuf->data_offset -
906 			       sizeof(rt_info), sizeof(rt_info));
907 			ldpc = (rt_info.rate_info.rate_info & 0x20) >> 5;
908 			format = (rt_info.rate_info.rate_info & 0x18) >> 3;
909 			bw = (rt_info.rate_info.rate_info & 0x06) >> 1;
910 			gi = rt_info.rate_info.rate_info & 0x01;
911 			skb_push(skb, sizeof(*rth));
912 			rth = (struct radiotap_header *)skb->data;
913 			memset(skb->data, 0, sizeof(*rth));
914 			rth->hdr.it_version = PKTHDR_RADIOTAP_VERSION;
915 			rth->hdr.it_pad = 0;
916 			rth->hdr.it_len = cpu_to_le16(sizeof(*rth));
917 			rth->hdr.it_present =
918 				cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
919 					    (1 << IEEE80211_RADIOTAP_FLAGS) |
920 					    (1 << IEEE80211_RADIOTAP_CHANNEL) |
921 					    (1 <<
922 					     IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
923 					    (1 <<
924 					     IEEE80211_RADIOTAP_DBM_ANTNOISE) |
925 					    (1 << IEEE80211_RADIOTAP_ANTENNA));
926 			//Timstamp
927 			rth->body.timestamp = cpu_to_le64(jiffies);
928 			//Flags
929 			rth->body.flags = (rt_info.extra_info.flags &
930 					   ~(RADIOTAP_FLAGS_USE_SGI_HT |
931 					     RADIOTAP_FLAGS_WITH_FRAGMENT |
932 					     RADIOTAP_FLAGS_WEP_ENCRYPTION |
933 					     RADIOTAP_FLAGS_FAILED_FCS_CHECK));
934 			//reverse fail fcs, 1 means pass FCS in FW, but means fail FCS in radiotap
935 			rth->body.flags |=
936 				(~rt_info.extra_info.
937 				 flags) & RADIOTAP_FLAGS_FAILED_FCS_CHECK;
938 			if ((format == MLAN_RATE_FORMAT_HT) && (gi == 1))
939 				rth->body.flags |= RADIOTAP_FLAGS_USE_SGI_HT;
940 			if (ieee80211_is_mgmt(dot11_hdr->frame_control) ||
941 			    ieee80211_is_data(dot11_hdr->frame_control)) {
942 				if ((ieee80211_has_morefrags
943 				     (dot11_hdr->frame_control)) ||
944 				    (!ieee80211_is_first_frag
945 				     (dot11_hdr->seq_ctrl))) {
946 					rth->body.flags |=
947 						RADIOTAP_FLAGS_WITH_FRAGMENT;
948 				}
949 			}
950 			if (ieee80211_is_data(dot11_hdr->frame_control) &&
951 			    ieee80211_has_protected(dot11_hdr->frame_control)) {
952 				payload =
953 					(t_u8 *)dot11_hdr +
954 					ieee80211_hdrlen(dot11_hdr->
955 							 frame_control);
956 				if (!(*(payload + 3) & 0x20))	//ExtIV bit shall be 0 for WEP frame
957 					rth->body.flags |=
958 						RADIOTAP_FLAGS_WEP_ENCRYPTION;
959 			}
960 			//Rate, t_u8 only apply for LG mode
961 			if (format == MLAN_RATE_FORMAT_LG) {
962 				rth->hdr.it_present |=
963 					cpu_to_le32(1 <<
964 						    IEEE80211_RADIOTAP_RATE);
965 				rth->body.rate = rt_info.rate_info.bitrate;
966 			}
967 			//Channel
968 			rth->body.channel.flags = 0;
969 			if (rt_info.chan_num)
970 				chan_num = rt_info.chan_num;
971 			else
972 				chan_num =
973 					handle->mon_if->band_chan_cfg.channel;
974 			band = (chan_num <=
975 				14) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
976 			rth->body.channel.frequency =
977 				cpu_to_le16(ieee80211_channel_to_frequency
978 					    (chan_num, band));
979 			rth->body.channel.flags |=
980 				cpu_to_le16((band ==
981 					     IEEE80211_BAND_2GHZ) ?
982 					    CHANNEL_FLAGS_2GHZ :
983 					    CHANNEL_FLAGS_5GHZ);
984 			if (rth->body.channel.
985 			    flags & cpu_to_le16(CHANNEL_FLAGS_2GHZ))
986 				rth->body.channel.flags |=
987 					cpu_to_le16
988 					(CHANNEL_FLAGS_DYNAMIC_CCK_OFDM);
989 			else
990 				rth->body.channel.flags |=
991 					cpu_to_le16(CHANNEL_FLAGS_OFDM);
992 			if (handle->mon_if->chandef.chan &&
993 			    (handle->mon_if->chandef.chan->
994 			     flags & (IEEE80211_CHAN_PASSIVE_SCAN |
995 				      IEEE80211_CHAN_RADAR)))
996 				rth->body.channel.flags |=
997 					cpu_to_le16
998 					(CHANNEL_FLAGS_ONLY_PASSIVSCAN_ALLOW);
999 			//Antenna
1000 			rth->body.antenna_signal = -(rt_info.nf - rt_info.snr);
1001 			rth->body.antenna_noise = -rt_info.nf;
1002 			rth->body.antenna = rt_info.antenna;
1003 			//MCS
1004 			if (format == MLAN_RATE_FORMAT_HT) {
1005 				rth->hdr.it_present |=
1006 					cpu_to_le32(1 <<
1007 						    IEEE80211_RADIOTAP_MCS);
1008 				rth->body.mcs.known =
1009 					rt_info.extra_info.mcs_known;
1010 				rth->body.mcs.flags =
1011 					rt_info.extra_info.mcs_flags;
1012 				//MCS mcs
1013 				rth->body.mcs.known |=
1014 					MCS_KNOWN_MCS_INDEX_KNOWN;
1015 				rth->body.mcs.mcs = rt_info.rate_info.mcs_index;
1016 				//MCS bw
1017 				rth->body.mcs.known |= MCS_KNOWN_BANDWIDTH;
1018 				rth->body.mcs.flags &= ~(0x03);	//Clear, 20MHz as default
1019 				if (bw == 1)
1020 					rth->body.mcs.flags |= RX_BW_40;
1021 				//MCS gi
1022 				rth->body.mcs.known |= MCS_KNOWN_GUARD_INTERVAL;
1023 				rth->body.mcs.flags &= ~(1 << 2);
1024 				if (gi)
1025 					rth->body.mcs.flags |= gi << 2;
1026 				//MCS FEC
1027 				rth->body.mcs.known |= MCS_KNOWN_FEC_TYPE;
1028 				rth->body.mcs.flags &= ~(1 << 4);
1029 				if (ldpc)
1030 					rth->body.mcs.flags |= ldpc << 4;
1031 			}
1032 		}
1033 		skb_set_mac_header(skb, 0);
1034 		skb->ip_summed = CHECKSUM_UNNECESSARY;
1035 		skb->pkt_type = PACKET_OTHERHOST;
1036 		skb->protocol = htons(ETH_P_802_2);
1037 		memset(skb->cb, 0, sizeof(skb->cb));
1038 		skb->dev = handle->mon_if->mon_ndev;
1039 
1040 		handle->mon_if->stats.rx_bytes += skb->len;
1041 		handle->mon_if->stats.rx_packets++;
1042 
1043 		if (in_interrupt())
1044 			netif_rx(skb);
1045 		else
1046 			netif_rx_ni(skb);
1047 
1048 		status = MLAN_STATUS_PENDING;
1049 	}
1050 
1051 done:
1052 
1053 	LEAVE();
1054 	return status;
1055 }
1056 #endif
1057 
1058 /**
1059  *  @brief This function uploads the packet to the network stack
1060  *
1061  *  @param pmoal_handle Pointer to the MOAL context
1062  *  @param pmbuf    Pointer to the mlan buffer structure
1063  *
1064  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1065  */
1066 mlan_status
moal_recv_packet(IN t_void * pmoal_handle,IN pmlan_buffer pmbuf)1067 moal_recv_packet(IN t_void *pmoal_handle, IN pmlan_buffer pmbuf)
1068 {
1069 	mlan_status status = MLAN_STATUS_SUCCESS;
1070 	moal_private *priv = NULL;
1071 	struct sk_buff *skb = NULL;
1072 	moal_handle *handle = (moal_handle *)pmoal_handle;
1073 	dot11_rxcontrol rxcontrol;
1074 	t_u8 rx_info_flag = MFALSE;
1075 	int j;
1076 	ENTER();
1077 	if (pmbuf) {
1078 
1079 		priv = woal_bss_index_to_priv(pmoal_handle, pmbuf->bss_index);
1080 		skb = (struct sk_buff *)pmbuf->pdesc;
1081 		if (priv) {
1082 			if (skb) {
1083 				skb_reserve(skb, pmbuf->data_offset);
1084 				skb_put(skb, pmbuf->data_len);
1085 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1086 				if (pmbuf->flags & MLAN_BUF_FLAG_NET_MONITOR) {
1087 					status = moal_recv_packet_to_mon_if
1088 						(pmoal_handle, pmbuf);
1089 					if (status == MLAN_STATUS_PENDING)
1090 						atomic_dec(&handle->
1091 							   mbufalloc_count);
1092 					goto done;
1093 				}
1094 #endif
1095 				pmbuf->pdesc = NULL;
1096 				pmbuf->pbuf = NULL;
1097 				pmbuf->data_offset = pmbuf->data_len = 0;
1098 				/* pkt been submit to kernel, no need to free by mlan */
1099 				status = MLAN_STATUS_PENDING;
1100 				atomic_dec(&handle->mbufalloc_count);
1101 			} else {
1102 				PRINTM(MERROR, "%s without skb attach!!!\n",
1103 				       __func__);
1104 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1105 		/** drop the packet without skb in monitor mode */
1106 				if (pmbuf->flags & MLAN_BUF_FLAG_NET_MONITOR) {
1107 					PRINTM(MINFO,
1108 					       "%s Drop packet without skb\n",
1109 					       __func__);
1110 					status = MLAN_STATUS_FAILURE;
1111 					priv->stats.rx_dropped++;
1112 					goto done;
1113 				}
1114 #endif
1115 				skb = dev_alloc_skb(pmbuf->data_len +
1116 						    MLAN_NET_IP_ALIGN);
1117 				if (!skb) {
1118 					PRINTM(MERROR, "%s fail to alloc skb\n",
1119 					       __func__);
1120 					status = MLAN_STATUS_FAILURE;
1121 					priv->stats.rx_dropped++;
1122 					goto done;
1123 				}
1124 				skb_reserve(skb, MLAN_NET_IP_ALIGN);
1125 				memcpy(skb->data,
1126 				       (t_u8 *)(pmbuf->pbuf +
1127 						pmbuf->data_offset),
1128 				       pmbuf->data_len);
1129 				skb_put(skb, pmbuf->data_len);
1130 
1131 			}
1132 			skb->dev = priv->netdev;
1133 			skb->protocol = eth_type_trans(skb, priv->netdev);
1134 			skb->ip_summed = CHECKSUM_NONE;
1135 
1136 			priv->stats.rx_bytes += skb->len;
1137 			priv->stats.rx_packets++;
1138 #ifdef ANDROID_KERNEL
1139 			if (wakelock_timeout) {
1140 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
1141 				__pm_wakeup_event(&handle->ws,
1142 						  wakelock_timeout);
1143 #else
1144 				wake_lock_timeout(&handle->wake_lock,
1145 						  wakelock_timeout);
1146 #endif
1147 			}
1148 #endif
1149 			if (priv->rx_protocols.protocol_num) {
1150 				for (j = 0; j < priv->rx_protocols.protocol_num;
1151 				     j++) {
1152 					if (htons(skb->protocol) ==
1153 					    priv->rx_protocols.protocols[j])
1154 						rx_info_flag = MTRUE;
1155 				}
1156 			}
1157 			if (rx_info_flag &&
1158 			    (skb_tailroom(skb) > sizeof(rxcontrol))) {
1159 				rxcontrol.datarate = pmbuf->u.rx_info.data_rate;
1160 				rxcontrol.channel = pmbuf->u.rx_info.channel;
1161 				rxcontrol.antenna = pmbuf->u.rx_info.antenna;
1162 				rxcontrol.rssi = pmbuf->u.rx_info.rssi;
1163 				skb_put(skb, sizeof(dot11_rxcontrol));
1164 				memmove(skb->data + sizeof(dot11_rxcontrol),
1165 					skb->data,
1166 					skb->len - sizeof(dot11_rxcontrol));
1167 				memcpy(skb->data, &rxcontrol,
1168 				       sizeof(dot11_rxcontrol));
1169 			}
1170 			if (in_interrupt())
1171 				netif_rx(skb);
1172 			else {
1173 				if (atomic_read(&handle->rx_pending) >
1174 				    MAX_RX_PENDING_THRHLD)
1175 					netif_rx(skb);
1176 				else
1177 					netif_rx_ni(skb);
1178 			}
1179 		}
1180 	}
1181 done:
1182 	LEAVE();
1183 	return status;
1184 }
1185 
1186 /**
1187  *  @brief This function handles event receive
1188  *
1189  *  @param pmoal_handle Pointer to the MOAL context
1190  *  @param pmevent  Pointer to the mlan event structure
1191  *
1192  *  @return         MLAN_STATUS_SUCCESS
1193  */
1194 mlan_status
moal_recv_event(IN t_void * pmoal_handle,IN pmlan_event pmevent)1195 moal_recv_event(IN t_void *pmoal_handle, IN pmlan_event pmevent)
1196 {
1197 #ifdef STA_SUPPORT
1198 	int custom_len = 0;
1199 #ifdef STA_CFG80211
1200 	unsigned long flags;
1201 #endif
1202 #endif
1203 	moal_private *priv = NULL;
1204 #if defined(STA_SUPPORT) || defined(UAP_SUPPORT)
1205 	moal_private *pmpriv = NULL;
1206 #endif
1207 #if defined(STA_WEXT) || defined(UAP_WEXT)
1208 #if defined(STA_SUPPORT) || defined(UAP_WEXT)
1209 #if defined(UAP_SUPPORT) || defined(STA_WEXT)
1210 	union iwreq_data wrqu;
1211 #endif
1212 #endif
1213 #endif
1214 #if defined(SDIO_SUSPEND_RESUME)
1215 	mlan_ds_ps_info pm_info;
1216 #endif
1217 	char event[512] = { 0 };
1218 	t_u8 category = 0;
1219 	t_u8 action_code = 0;
1220 	char *buf;
1221 	t_u8 peer_addr[ETH_ALEN];
1222 	moal_wnm_tm_msmt *tm_ind;
1223 	moal_wlan_802_11_header *header;
1224 	moal_timestamps *tsstamp;
1225 	t_u8 payload_len, i;
1226 	moal_ptp_context *ptp_context;
1227 	t_u8 *req_ie = NULL;
1228 	t_u16 ie_len = 0;
1229 	apinfo *pinfo = NULL, *req_tlv = NULL;
1230 	MrvlIEtypesHeader_t *tlv = NULL;
1231 	t_u16 tlv_type = 0, tlv_len = 0, tlv_buf_left = 0;
1232 #if defined(FW_ROAMING) || (defined(ROAMING_OFFLOAD) && defined(STA_CFG80211))
1233 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
1234 	struct cfg80211_roam_info roam_info;
1235 #endif
1236 #endif
1237 
1238 	ENTER();
1239 
1240 	if ((pmevent->event_id != MLAN_EVENT_ID_DRV_DEFER_RX_WORK) &&
1241 	    (pmevent->event_id != MLAN_EVENT_ID_DRV_DEFER_HANDLING) &&
1242 	    (pmevent->event_id != MLAN_EVENT_ID_DRV_MGMT_FRAME))
1243 		PRINTM(MEVENT, "event id:0x%x\n", pmevent->event_id);
1244 	if (pmevent->event_id == MLAN_EVENT_ID_FW_DUMP_INFO) {
1245 		woal_store_firmware_dump(pmoal_handle, pmevent);
1246 		goto done;
1247 	}
1248 	priv = woal_bss_index_to_priv(pmoal_handle, pmevent->bss_index);
1249 	if (priv == NULL) {
1250 		PRINTM(MERROR, "%s: priv is null\n", __func__);
1251 		goto done;
1252 	}
1253 	if (priv->netdev == NULL) {
1254 		PRINTM(MERROR, "%s: netdev is null\n", __func__);
1255 		goto done;
1256 	}
1257 	switch (pmevent->event_id) {
1258 #ifdef STA_SUPPORT
1259 	case MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED:
1260 		priv->is_adhoc_link_sensed = MTRUE;
1261 		if (!netif_carrier_ok(priv->netdev))
1262 			netif_carrier_on(priv->netdev);
1263 		woal_wake_queue(priv->netdev);
1264 #ifdef STA_WEXT
1265 		if (IS_STA_WEXT(cfg80211_wext))
1266 			woal_send_iwevcustom_event(priv,
1267 						   CUS_EVT_ADHOC_LINK_SENSED);
1268 #endif
1269 		woal_broadcast_event(priv, CUS_EVT_ADHOC_LINK_SENSED,
1270 				     strlen(CUS_EVT_ADHOC_LINK_SENSED));
1271 		break;
1272 
1273 	case MLAN_EVENT_ID_FW_ADHOC_LINK_LOST:
1274 		woal_stop_queue(priv->netdev);
1275 		if (netif_carrier_ok(priv->netdev))
1276 			netif_carrier_off(priv->netdev);
1277 		priv->is_adhoc_link_sensed = MFALSE;
1278 #ifdef STA_WEXT
1279 		if (IS_STA_WEXT(cfg80211_wext))
1280 			woal_send_iwevcustom_event(priv,
1281 						   CUS_EVT_ADHOC_LINK_LOST);
1282 #endif
1283 		woal_broadcast_event(priv, CUS_EVT_ADHOC_LINK_LOST,
1284 				     strlen(CUS_EVT_ADHOC_LINK_LOST));
1285 		break;
1286 
1287 	case MLAN_EVENT_ID_DRV_CONNECTED:
1288 #ifdef STA_WEXT
1289 		if (IS_STA_WEXT(cfg80211_wext) &&
1290 		    pmevent->event_len == ETH_ALEN) {
1291 			memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
1292 			memcpy(wrqu.ap_addr.sa_data, pmevent->event_buf,
1293 			       ETH_ALEN);
1294 			wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1295 			wireless_send_event(priv->netdev, SIOCGIWAP, &wrqu,
1296 					    NULL);
1297 		}
1298 #endif
1299 #ifdef STA_CFG80211
1300 		if (IS_STA_CFG80211(cfg80211_wext)) {
1301 			memcpy(priv->cfg_bssid, pmevent->event_buf, ETH_ALEN);
1302 			woal_set_scan_time(priv, ACTIVE_SCAN_CHAN_TIME,
1303 					   PASSIVE_SCAN_CHAN_TIME,
1304 					   MIN_SPECIFIC_SCAN_CHAN_TIME);
1305 		}
1306 #endif
1307 		custom_len = strlen(CUS_EVT_AP_CONNECTED);
1308 		memmove(pmevent->event_buf + custom_len, pmevent->event_buf,
1309 			pmevent->event_len);
1310 		memcpy(pmevent->event_buf, CUS_EVT_AP_CONNECTED, custom_len);
1311 		pmevent->event_len += custom_len;
1312 		woal_broadcast_event(priv, pmevent->event_buf,
1313 				     pmevent->event_len);
1314 		woal_update_dscp_mapping(priv);
1315 		priv->media_connected = MTRUE;
1316 		if (!netif_carrier_ok(priv->netdev))
1317 			netif_carrier_on(priv->netdev);
1318 		woal_wake_queue(priv->netdev);
1319 
1320 		break;
1321 
1322 	case MLAN_EVENT_ID_DRV_SCAN_REPORT:
1323 		PRINTM(MINFO, "Scan report\n");
1324 
1325 		if (priv->report_scan_result) {
1326 			priv->report_scan_result = MFALSE;
1327 #ifdef STA_CFG80211
1328 			if (IS_STA_CFG80211(cfg80211_wext)) {
1329 				if (priv->phandle->scan_request) {
1330 					PRINTM(MINFO,
1331 					       "Reporting scan results\n");
1332 					woal_inform_bss_from_scan_result(priv,
1333 									 NULL,
1334 									 MOAL_NO_WAIT);
1335 					if (!priv->phandle->first_scan_done) {
1336 						priv->phandle->first_scan_done =
1337 							MTRUE;
1338 						woal_set_scan_time(priv,
1339 								   ACTIVE_SCAN_CHAN_TIME,
1340 								   PASSIVE_SCAN_CHAN_TIME,
1341 								   SPECIFIC_SCAN_CHAN_TIME);
1342 					}
1343 					spin_lock_irqsave(&priv->phandle->
1344 							  scan_req_lock, flags);
1345 					if (priv->phandle->scan_request) {
1346 						woal_cfg80211_scan_done(priv->
1347 									phandle->
1348 									scan_request,
1349 									MFALSE);
1350 						priv->phandle->scan_request =
1351 							NULL;
1352 					}
1353 					spin_unlock_irqrestore(&priv->phandle->
1354 							       scan_req_lock,
1355 							       flags);
1356 				}
1357 			}
1358 #endif /* STA_CFG80211 */
1359 
1360 #ifdef STA_WEXT
1361 			if (IS_STA_WEXT(cfg80211_wext)) {
1362 				memset(&wrqu, 0, sizeof(union iwreq_data));
1363 				wireless_send_event(priv->netdev, SIOCGIWSCAN,
1364 						    &wrqu, NULL);
1365 			}
1366 #endif
1367 			woal_broadcast_event(priv, (t_u8 *)&pmevent->event_id,
1368 					     sizeof(mlan_event_id));
1369 
1370 		}
1371 		if (priv->phandle->scan_pending_on_block == MTRUE) {
1372 			priv->phandle->scan_pending_on_block = MFALSE;
1373 			priv->phandle->scan_priv = NULL;
1374 			MOAL_REL_SEMAPHORE(&priv->phandle->async_sem);
1375 		}
1376 		break;
1377 
1378 	case MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM:
1379 		memmove((pmevent->event_buf + strlen(CUS_EVT_OBSS_SCAN_PARAM) +
1380 			 1), pmevent->event_buf, pmevent->event_len);
1381 		memcpy(pmevent->event_buf, (t_u8 *)CUS_EVT_OBSS_SCAN_PARAM,
1382 		       strlen(CUS_EVT_OBSS_SCAN_PARAM));
1383 		pmevent->event_buf[strlen(CUS_EVT_OBSS_SCAN_PARAM)] = 0;
1384 		woal_broadcast_event(priv, pmevent->event_buf,
1385 				     pmevent->event_len +
1386 				     strlen(CUS_EVT_OBSS_SCAN_PARAM));
1387 
1388 #ifdef STA_WEXT
1389 		if (IS_STA_WEXT(cfg80211_wext)) {
1390 			memset(&wrqu, 0, sizeof(union iwreq_data));
1391 			wrqu.data.pointer = pmevent->event_buf;
1392 			wrqu.data.length =
1393 				pmevent->event_len +
1394 				strlen(CUS_EVT_OBSS_SCAN_PARAM) + 1;
1395 			wireless_send_event(priv->netdev, IWEVCUSTOM, &wrqu,
1396 					    pmevent->event_buf);
1397 		}
1398 #endif
1399 		break;
1400 	case MLAN_EVENT_ID_FW_BW_CHANGED:
1401 		memmove((pmevent->event_buf + strlen(CUS_EVT_BW_CHANGED) + 1),
1402 			pmevent->event_buf, pmevent->event_len);
1403 		memcpy(pmevent->event_buf, (t_u8 *)CUS_EVT_BW_CHANGED,
1404 		       strlen(CUS_EVT_BW_CHANGED));
1405 		pmevent->event_buf[strlen(CUS_EVT_BW_CHANGED)] = 0;
1406 		woal_broadcast_event(priv, pmevent->event_buf,
1407 				     pmevent->event_len +
1408 				     strlen(CUS_EVT_BW_CHANGED));
1409 
1410 #ifdef STA_WEXT
1411 		if (IS_STA_WEXT(cfg80211_wext)) {
1412 			memset(&wrqu, 0, sizeof(union iwreq_data));
1413 			wrqu.data.pointer = pmevent->event_buf;
1414 			wrqu.data.length =
1415 				pmevent->event_len +
1416 				strlen(CUS_EVT_BW_CHANGED) + 1;
1417 			wireless_send_event(priv->netdev, IWEVCUSTOM, &wrqu,
1418 					    pmevent->event_buf);
1419 		}
1420 #endif
1421 		break;
1422 
1423 	case MLAN_EVENT_ID_FW_DISCONNECTED:
1424 		woal_send_disconnect_to_system(priv);
1425 #ifdef STA_WEXT
1426 		/* Reset wireless stats signal info */
1427 		if (IS_STA_WEXT(cfg80211_wext)) {
1428 			priv->w_stats.qual.level = 0;
1429 			priv->w_stats.qual.noise = 0;
1430 		}
1431 #endif
1432 #ifdef REASSOCIATION
1433 		if (priv->reassoc_on == MTRUE) {
1434 			PRINTM(MINFO, "Reassoc: trigger the timer\n");
1435 			priv->reassoc_required = MTRUE;
1436 			priv->phandle->is_reassoc_timer_set = MTRUE;
1437 			woal_mod_timer(&priv->phandle->reassoc_timer,
1438 				       REASSOC_TIMER_DEFAULT);
1439 		} else {
1440 			priv->rate_index = AUTO_RATE;
1441 		}
1442 #endif /* REASSOCIATION */
1443 		break;
1444 
1445 	case MLAN_EVENT_ID_FW_MIC_ERR_UNI:
1446 #ifdef STA_WEXT
1447 		if (IS_STA_WEXT(cfg80211_wext)) {
1448 #if WIRELESS_EXT >= 18
1449 			woal_send_mic_error_event(priv,
1450 						  MLAN_EVENT_ID_FW_MIC_ERR_UNI);
1451 #else
1452 			woal_send_iwevcustom_event(priv,
1453 						   CUS_EVT_MLME_MIC_ERR_UNI);
1454 #endif
1455 		}
1456 #endif /* STA_WEXT */
1457 #ifdef STA_CFG80211
1458 		if (IS_STA_CFG80211(cfg80211_wext)) {
1459 			cfg80211_michael_mic_failure(priv->netdev,
1460 						     priv->cfg_bssid,
1461 						     NL80211_KEYTYPE_PAIRWISE,
1462 						     -1, NULL, GFP_KERNEL);
1463 		}
1464 #endif
1465 		woal_broadcast_event(priv, CUS_EVT_MLME_MIC_ERR_UNI,
1466 				     strlen(CUS_EVT_MLME_MIC_ERR_UNI));
1467 		break;
1468 	case MLAN_EVENT_ID_FW_MIC_ERR_MUL:
1469 #ifdef STA_WEXT
1470 		if (IS_STA_WEXT(cfg80211_wext)) {
1471 #if WIRELESS_EXT >= 18
1472 			woal_send_mic_error_event(priv,
1473 						  MLAN_EVENT_ID_FW_MIC_ERR_MUL);
1474 #else
1475 			woal_send_iwevcustom_event(priv,
1476 						   CUS_EVT_MLME_MIC_ERR_MUL);
1477 #endif
1478 		}
1479 #endif /* STA_WEXT */
1480 #ifdef STA_CFG80211
1481 		if (IS_STA_CFG80211(cfg80211_wext)) {
1482 			cfg80211_michael_mic_failure(priv->netdev,
1483 						     priv->cfg_bssid,
1484 						     NL80211_KEYTYPE_GROUP, -1,
1485 						     NULL, GFP_KERNEL);
1486 		}
1487 #endif
1488 		woal_broadcast_event(priv, CUS_EVT_MLME_MIC_ERR_MUL,
1489 				     strlen(CUS_EVT_MLME_MIC_ERR_MUL));
1490 		break;
1491 	case MLAN_EVENT_ID_FW_BCN_RSSI_LOW:
1492 #ifdef STA_WEXT
1493 		if (IS_STA_WEXT(cfg80211_wext))
1494 			woal_send_iwevcustom_event(priv,
1495 						   CUS_EVT_BEACON_RSSI_LOW);
1496 #endif
1497 #ifdef STA_CFG80211
1498 		if (IS_STA_CFG80211(cfg80211_wext)) {
1499 #if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
1500 			cfg80211_cqm_rssi_notify(priv->netdev,
1501 						 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
1502 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
1503 						 *(t_s16 *)pmevent->event_buf,
1504 #endif
1505 						 GFP_KERNEL);
1506 			priv->last_event |= EVENT_BCN_RSSI_LOW;
1507 #endif
1508 			if (!hw_test && priv->roaming_enabled)
1509 				woal_config_bgscan_and_rssi(priv, MTRUE);
1510 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1511 			woal_cfg80211_rssi_monitor_event(priv,
1512 							 *(t_s16 *)pmevent->
1513 							 event_buf);
1514 #endif
1515 		}
1516 #endif
1517 		woal_broadcast_event(priv, CUS_EVT_BEACON_RSSI_LOW,
1518 				     strlen(CUS_EVT_BEACON_RSSI_LOW));
1519 		break;
1520 	case MLAN_EVENT_ID_FW_BCN_RSSI_HIGH:
1521 #ifdef STA_WEXT
1522 		if (IS_STA_WEXT(cfg80211_wext))
1523 			woal_send_iwevcustom_event(priv,
1524 						   CUS_EVT_BEACON_RSSI_HIGH);
1525 #endif
1526 #ifdef STA_CFG80211
1527 		if (IS_STA_CFG80211(cfg80211_wext)) {
1528 			if (!priv->mrvl_rssi_low) {
1529 #if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
1530 				cfg80211_cqm_rssi_notify(priv->netdev,
1531 							 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
1532 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
1533 							 *(t_s16 *)pmevent->
1534 							 event_buf,
1535 #endif
1536 							 GFP_KERNEL);
1537 #endif
1538 				woal_set_rssi_threshold(priv,
1539 							MLAN_EVENT_ID_FW_BCN_RSSI_HIGH,
1540 							MOAL_NO_WAIT);
1541 			}
1542 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1543 			woal_cfg80211_rssi_monitor_event(priv,
1544 							 *(t_s16 *)pmevent->
1545 							 event_buf);
1546 #endif
1547 		}
1548 #endif
1549 		woal_broadcast_event(priv, CUS_EVT_BEACON_RSSI_HIGH,
1550 				     strlen(CUS_EVT_BEACON_RSSI_HIGH));
1551 		break;
1552 	case MLAN_EVENT_ID_FW_BCN_SNR_LOW:
1553 #ifdef STA_WEXT
1554 		if (IS_STA_WEXT(cfg80211_wext))
1555 			woal_send_iwevcustom_event(priv,
1556 						   CUS_EVT_BEACON_SNR_LOW);
1557 #endif
1558 		woal_broadcast_event(priv, CUS_EVT_BEACON_SNR_LOW,
1559 				     strlen(CUS_EVT_BEACON_SNR_LOW));
1560 		break;
1561 	case MLAN_EVENT_ID_FW_BCN_SNR_HIGH:
1562 #ifdef STA_WEXT
1563 		if (IS_STA_WEXT(cfg80211_wext))
1564 			woal_send_iwevcustom_event(priv,
1565 						   CUS_EVT_BEACON_SNR_HIGH);
1566 #endif
1567 		woal_broadcast_event(priv, CUS_EVT_BEACON_SNR_HIGH,
1568 				     strlen(CUS_EVT_BEACON_SNR_HIGH));
1569 		break;
1570 	case MLAN_EVENT_ID_FW_MAX_FAIL:
1571 #ifdef STA_WEXT
1572 		if (IS_STA_WEXT(cfg80211_wext))
1573 			woal_send_iwevcustom_event(priv, CUS_EVT_MAX_FAIL);
1574 #endif
1575 		woal_broadcast_event(priv, CUS_EVT_MAX_FAIL,
1576 				     strlen(CUS_EVT_MAX_FAIL));
1577 		break;
1578 	case MLAN_EVENT_ID_FW_DATA_RSSI_LOW:
1579 #ifdef STA_WEXT
1580 		if (IS_STA_WEXT(cfg80211_wext))
1581 			woal_send_iwevcustom_event(priv, CUS_EVT_DATA_RSSI_LOW);
1582 #endif
1583 		woal_broadcast_event(priv, CUS_EVT_DATA_RSSI_LOW,
1584 				     strlen(CUS_EVT_DATA_RSSI_LOW));
1585 		break;
1586 	case MLAN_EVENT_ID_FW_DATA_SNR_LOW:
1587 #ifdef STA_WEXT
1588 		if (IS_STA_WEXT(cfg80211_wext))
1589 			woal_send_iwevcustom_event(priv, CUS_EVT_DATA_SNR_LOW);
1590 #endif
1591 		woal_broadcast_event(priv, CUS_EVT_DATA_SNR_LOW,
1592 				     strlen(CUS_EVT_DATA_SNR_LOW));
1593 		break;
1594 	case MLAN_EVENT_ID_FW_DATA_RSSI_HIGH:
1595 #ifdef STA_WEXT
1596 		if (IS_STA_WEXT(cfg80211_wext))
1597 			woal_send_iwevcustom_event(priv,
1598 						   CUS_EVT_DATA_RSSI_HIGH);
1599 #endif
1600 		woal_broadcast_event(priv, CUS_EVT_DATA_RSSI_HIGH,
1601 				     strlen(CUS_EVT_DATA_RSSI_HIGH));
1602 		break;
1603 	case MLAN_EVENT_ID_FW_DATA_SNR_HIGH:
1604 #ifdef STA_WEXT
1605 		if (IS_STA_WEXT(cfg80211_wext))
1606 			woal_send_iwevcustom_event(priv, CUS_EVT_DATA_SNR_HIGH);
1607 #endif
1608 		woal_broadcast_event(priv, CUS_EVT_DATA_SNR_HIGH,
1609 				     strlen(CUS_EVT_DATA_SNR_HIGH));
1610 		break;
1611 	case MLAN_EVENT_ID_FW_LINK_QUALITY:
1612 #ifdef STA_WEXT
1613 		if (IS_STA_WEXT(cfg80211_wext))
1614 			woal_send_iwevcustom_event(priv, CUS_EVT_LINK_QUALITY);
1615 #endif
1616 		woal_broadcast_event(priv, CUS_EVT_LINK_QUALITY,
1617 				     strlen(CUS_EVT_LINK_QUALITY));
1618 		break;
1619 	case MLAN_EVENT_ID_FW_PORT_RELEASE:
1620 #ifdef STA_WEXT
1621 		if (IS_STA_WEXT(cfg80211_wext))
1622 			woal_send_iwevcustom_event(priv, CUS_EVT_PORT_RELEASE);
1623 #endif
1624 		woal_broadcast_event(priv, CUS_EVT_PORT_RELEASE,
1625 				     strlen(CUS_EVT_PORT_RELEASE));
1626 		break;
1627 	case MLAN_EVENT_ID_FW_PRE_BCN_LOST:
1628 #ifdef STA_WEXT
1629 		if (IS_STA_WEXT(cfg80211_wext))
1630 			woal_send_iwevcustom_event(priv,
1631 						   CUS_EVT_PRE_BEACON_LOST);
1632 #endif
1633 #ifdef STA_CFG80211
1634 #if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
1635 		if (IS_STA_CFG80211(cfg80211_wext)) {
1636 			struct cfg80211_bss *bss = NULL;
1637 			bss = cfg80211_get_bss(priv->wdev->wiphy, NULL,
1638 					       priv->cfg_bssid, NULL, 0,
1639 					       WLAN_CAPABILITY_ESS,
1640 					       WLAN_CAPABILITY_ESS);
1641 			if (bss)
1642 				cfg80211_unlink_bss(priv->wdev->wiphy, bss);
1643 			if (!hw_test && priv->roaming_enabled)
1644 				woal_config_bgscan_and_rssi(priv, MFALSE);
1645 			priv->last_event |= EVENT_PRE_BCN_LOST;
1646 		}
1647 #endif
1648 #endif
1649 		woal_broadcast_event(priv, CUS_EVT_PRE_BEACON_LOST,
1650 				     strlen(CUS_EVT_PRE_BEACON_LOST));
1651 		break;
1652 	case MLAN_EVENT_ID_FW_DEBUG_INFO:
1653 #ifdef STA_WEXT
1654 		if (IS_STA_WEXT(cfg80211_wext))
1655 			woal_send_iwevcustom_event(priv, pmevent->event_buf);
1656 #endif
1657 		woal_broadcast_event(priv, pmevent->event_buf,
1658 				     pmevent->event_len);
1659 		break;
1660 	case MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE:
1661 #ifdef STA_WEXT
1662 		if (IS_STA_WEXT(cfg80211_wext))
1663 			woal_send_iwevcustom_event(priv,
1664 						   WMM_CONFIG_CHANGE_INDICATION);
1665 #endif
1666 		woal_broadcast_event(priv, WMM_CONFIG_CHANGE_INDICATION,
1667 				     strlen(WMM_CONFIG_CHANGE_INDICATION));
1668 		break;
1669 
1670 	case MLAN_EVENT_ID_DRV_REPORT_STRING:
1671 		PRINTM(MINFO, "Report string %s\n", pmevent->event_buf);
1672 #ifdef STA_WEXT
1673 		if (IS_STA_WEXT(cfg80211_wext))
1674 			woal_send_iwevcustom_event(priv, pmevent->event_buf);
1675 #endif
1676 		woal_broadcast_event(priv, pmevent->event_buf,
1677 				     strlen(pmevent->event_buf));
1678 		break;
1679 	case MLAN_EVENT_ID_FW_WEP_ICV_ERR:
1680 		DBG_HEXDUMP(MCMD_D, "WEP ICV error", pmevent->event_buf,
1681 			    pmevent->event_len);
1682 #ifdef STA_WEXT
1683 		if (IS_STA_WEXT(cfg80211_wext))
1684 			woal_send_iwevcustom_event(priv, CUS_EVT_WEP_ICV_ERR);
1685 #endif
1686 		woal_broadcast_event(priv, CUS_EVT_WEP_ICV_ERR,
1687 				     strlen(CUS_EVT_WEP_ICV_ERR));
1688 		break;
1689 
1690 	case MLAN_EVENT_ID_DRV_DEFER_HANDLING:
1691 		queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
1692 		break;
1693 	case MLAN_EVENT_ID_DRV_FLUSH_RX_WORK:
1694 		if (napi) {
1695 			napi_synchronize(&priv->phandle->napi_rx);
1696 			break;
1697 		}
1698 		flush_workqueue(priv->phandle->rx_workqueue);
1699 		break;
1700 	case MLAN_EVENT_ID_DRV_FLUSH_MAIN_WORK:
1701 		flush_workqueue(priv->phandle->workqueue);
1702 		break;
1703 	case MLAN_EVENT_ID_DRV_DEFER_RX_WORK:
1704 		if (napi) {
1705 			napi_schedule(&priv->phandle->napi_rx);
1706 			break;
1707 		}
1708 		queue_work(priv->phandle->rx_workqueue,
1709 			   &priv->phandle->rx_work);
1710 		break;
1711 	case MLAN_EVENT_ID_DRV_DBG_DUMP:
1712 		priv->phandle->driver_state = MTRUE;
1713 		woal_moal_debug_info(priv, NULL, MFALSE);
1714 		woal_broadcast_event(priv, CUS_EVT_DRIVER_HANG,
1715 				     strlen(CUS_EVT_DRIVER_HANG));
1716 #ifdef STA_CFG80211
1717 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1718 		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext))
1719 			woal_cfg80211_vendor_event(priv, event_hang,
1720 						   CUS_EVT_DRIVER_HANG,
1721 						   strlen(CUS_EVT_DRIVER_HANG));
1722 #endif
1723 #endif
1724 		woal_process_hang(priv->phandle);
1725 		break;
1726 	case MLAN_EVENT_ID_FW_BG_SCAN:
1727 		if (priv->media_connected == MTRUE)
1728 			priv->bg_scan_start = MFALSE;
1729 		priv->bg_scan_reported = MTRUE;
1730 #ifdef STA_WEXT
1731 		if (IS_STA_WEXT(cfg80211_wext)) {
1732 			memset(&wrqu, 0, sizeof(union iwreq_data));
1733 			wireless_send_event(priv->netdev, SIOCGIWSCAN, &wrqu,
1734 					    NULL);
1735 		}
1736 #endif
1737 #ifdef STA_CFG80211
1738 		if (IS_STA_CFG80211(cfg80211_wext)) {
1739 			priv->last_event |= EVENT_BG_SCAN_REPORT;
1740 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
1741 			if (priv->sched_scanning &&
1742 			    !priv->phandle->cfg80211_suspend) {
1743 				mlan_scan_resp scan_resp;
1744 				woal_get_scan_table(priv, MOAL_NO_WAIT,
1745 						    &scan_resp);
1746 				PRINTM(MIOCTL,
1747 				       "Trigger mlan get bgscan result\n");
1748 			}
1749 #endif
1750 			if (!hw_test && priv->roaming_enabled
1751 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
1752 			    && !priv->phandle->cfg80211_suspend
1753 #endif
1754 				) {
1755 				priv->roaming_required = MTRUE;
1756 #ifdef ANDROID_KERNEL
1757 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
1758 				__pm_wakeup_event(&priv->phandle->ws,
1759 						  ROAMING_WAKE_LOCK_TIMEOUT);
1760 #else
1761 				wake_lock_timeout(&priv->phandle->wake_lock,
1762 						  ROAMING_WAKE_LOCK_TIMEOUT);
1763 #endif
1764 #endif
1765 				wake_up_interruptible(&priv->phandle->
1766 						      reassoc_thread.wait_q);
1767 			}
1768 		}
1769 #endif
1770 		break;
1771 	case MLAN_EVENT_ID_FW_BG_SCAN_STOPPED:
1772 #ifdef STA_CFG80211
1773 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
1774 		if (IS_STA_CFG80211(cfg80211_wext)) {
1775 			if (priv->sched_scanning) {
1776 				cfg80211_sched_scan_stopped(priv->wdev->wiphy
1777 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
1778 							    , 0
1779 #endif
1780 					);
1781 				PRINTM(MEVENT, "Sched_Scan stopped\n");
1782 				priv->sched_scanning = MFALSE;
1783 			}
1784 		}
1785 #endif
1786 #endif
1787 		break;
1788 	case MLAN_EVENT_ID_DRV_BGSCAN_RESULT:
1789 #ifdef STA_CFG80211
1790 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
1791 		if (IS_STA_CFG80211(cfg80211_wext)) {
1792 			if (priv->sched_scanning &&
1793 			    !priv->phandle->cfg80211_suspend) {
1794 				woal_inform_bss_from_scan_result(priv, NULL,
1795 								 MOAL_NO_WAIT);
1796 				cfg80211_sched_scan_results(priv->wdev->wiphy
1797 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
1798 							    , 0
1799 #endif
1800 					);
1801 				priv->last_event = 0;
1802 				PRINTM(MEVENT,
1803 				       "Reporting Sched_Scan results\n");
1804 			}
1805 		}
1806 #endif
1807 #endif
1808 		break;
1809 #ifdef UAP_CFG80211
1810 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
1811 	case MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY:
1812 		if (priv->phandle->is_cac_timer_set) {
1813 			t_u8 radar_detected = pmevent->event_buf[0];
1814 			PRINTM(MEVENT, "%s radar found when CAC \n",
1815 			       radar_detected ? "" : "No");
1816 			moal_stop_timer(priv->phandle,
1817 					&priv->phandle->cac_timer);
1818 			priv->phandle->is_cac_timer_set = MFALSE;
1819 			if (radar_detected) {
1820 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1821 				cfg80211_cac_event(priv->netdev,
1822 						   &priv->phandle->dfs_channel,
1823 						   NL80211_RADAR_CAC_ABORTED,
1824 						   GFP_KERNEL);
1825 #else
1826 				cfg80211_cac_event(priv->netdev,
1827 						   NL80211_RADAR_CAC_ABORTED,
1828 						   GFP_KERNEL);
1829 #endif
1830 				cfg80211_radar_event(priv->wdev->wiphy,
1831 						     &priv->phandle->
1832 						     dfs_channel, GFP_KERNEL);
1833 			} else {
1834 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1835 				cfg80211_cac_event(priv->netdev,
1836 						   &priv->phandle->dfs_channel,
1837 						   NL80211_RADAR_CAC_FINISHED,
1838 						   GFP_KERNEL);
1839 #else
1840 				cfg80211_cac_event(priv->netdev,
1841 						   NL80211_RADAR_CAC_FINISHED,
1842 						   GFP_KERNEL);
1843 #endif
1844 			}
1845 			memset(&priv->phandle->dfs_channel, 0,
1846 			       sizeof(struct cfg80211_chan_def));
1847 			priv->phandle->cac_bss_index = 0xff;
1848 		}
1849 		break;
1850 	case MLAN_EVENT_ID_FW_RADAR_DETECTED:
1851 		if (priv->phandle->is_cac_timer_set) {
1852 			if (priv->bss_index == priv->phandle->cac_bss_index) {
1853 				PRINTM(MEVENT, "radar detected during CAC \n");
1854 				woal_cancel_timer(&priv->phandle->cac_timer);
1855 				priv->phandle->is_cac_timer_set = MFALSE;
1856 				/* downstream: cancel the unfinished CAC in Firmware */
1857 				woal_11h_cancel_chan_report_ioctl(priv,
1858 								  MOAL_NO_WAIT);
1859 				/* upstream: inform cfg80211 */
1860 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1861 				cfg80211_cac_event(priv->netdev,
1862 						   &priv->phandle->dfs_channel,
1863 						   NL80211_RADAR_CAC_ABORTED,
1864 						   GFP_KERNEL);
1865 #else
1866 				cfg80211_cac_event(priv->netdev,
1867 						   NL80211_RADAR_CAC_ABORTED,
1868 						   GFP_KERNEL);
1869 #endif
1870 				cfg80211_radar_event(priv->wdev->wiphy,
1871 						     &priv->phandle->
1872 						     dfs_channel, GFP_KERNEL);
1873 
1874 				memset(&priv->phandle->dfs_channel, 0,
1875 				       sizeof(priv->phandle->dfs_channel));
1876 				priv->phandle->cac_bss_index = 0xff;
1877 			} else {
1878 				PRINTM(MERROR,
1879 				       " Radar event for incorrect inferface \n");
1880 			}
1881 		} else {
1882 			PRINTM(MEVENT, "radar detected during BSS active \n");
1883 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1884 			if (dfs_offload)
1885 				woal_cfg80211_dfs_vendor_event(priv,
1886 							       event_dfs_radar_detected,
1887 							       &priv->chan);
1888 			else
1889 #endif
1890 				cfg80211_radar_event(priv->wdev->wiphy,
1891 						     &priv->chan, GFP_KERNEL);
1892 		}
1893 		break;
1894 #endif
1895 #endif
1896 	case MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN:
1897 #ifdef STA_WEXT
1898 		if (IS_STA_WEXT(cfg80211_wext))
1899 			woal_send_iwevcustom_event(priv,
1900 						   CUS_EVT_CHANNEL_SWITCH_ANN);
1901 #endif
1902 		woal_broadcast_event(priv, CUS_EVT_CHANNEL_SWITCH_ANN,
1903 				     strlen(CUS_EVT_CHANNEL_SWITCH_ANN));
1904 		break;
1905 #endif /* STA_SUPPORT */
1906 	case MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE:
1907 #if defined(UAP_SUPPORT)
1908 		if (priv->bss_role == MLAN_BSS_ROLE_UAP) {
1909 #ifdef UAP_CFG80211
1910 			chan_band_info *pchan_info =
1911 				(chan_band_info *) pmevent->event_buf;
1912 			if (IS_UAP_CFG80211(cfg80211_wext)) {
1913 				PRINTM(MMSG,
1914 				       "CSA/ECSA: Switch to new channel %d complete!\n",
1915 				       pchan_info->channel);
1916 				priv->channel = pchan_info->channel;
1917 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3,12,0)
1918 				if (priv->csa_chan.chan &&
1919 				    (pchan_info->channel ==
1920 				     priv->csa_chan.chan->hw_value)) {
1921 					memcpy(&priv->chan, &priv->csa_chan,
1922 					       sizeof(struct
1923 						      cfg80211_chan_def));
1924 				}
1925 #endif
1926 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3,8,0)
1927 				if (priv->uap_host_based) {
1928 					PRINTM(MEVENT,
1929 					       "UAP: 11n=%d, chan=%d, center_chan=%d, band=%d, width=%d, 2Offset=%d\n",
1930 					       pchan_info->is_11n_enabled,
1931 					       pchan_info->channel,
1932 					       pchan_info->center_chan,
1933 					       pchan_info->bandcfg.chanBand,
1934 					       pchan_info->bandcfg.chanWidth,
1935 					       pchan_info->bandcfg.chan2Offset);
1936 					woal_cfg80211_notify_uap_channel(priv,
1937 									 pchan_info);
1938 				}
1939 #endif
1940 			}
1941 #endif
1942 		}
1943 		if (priv->uap_tx_blocked) {
1944 			if (!netif_carrier_ok(priv->netdev))
1945 				netif_carrier_on(priv->netdev);
1946 			woal_start_queue(priv->netdev);
1947 			priv->uap_tx_blocked = MFALSE;
1948 		}
1949 		priv->phandle->chsw_wait_q_woken = MTRUE;
1950 		wake_up_interruptible(&priv->phandle->chsw_wait_q);
1951 #endif
1952 		break;
1953 	case MLAN_EVENT_ID_FW_STOP_TX:
1954 		woal_stop_queue(priv->netdev);
1955 		if (netif_carrier_ok(priv->netdev))
1956 			netif_carrier_off(priv->netdev);
1957 		break;
1958 	case MLAN_EVENT_ID_FW_START_TX:
1959 		if (!netif_carrier_ok(priv->netdev))
1960 			netif_carrier_on(priv->netdev);
1961 		woal_wake_queue(priv->netdev);
1962 		break;
1963 	case MLAN_EVENT_ID_FW_HS_WAKEUP:
1964 		/* simulate HSCFG_CANCEL command */
1965 		woal_cancel_hs(priv, MOAL_NO_WAIT);
1966 #ifdef STA_SUPPORT
1967 		pmpriv = woal_get_priv((moal_handle *)pmoal_handle,
1968 				       MLAN_BSS_ROLE_STA);
1969 #ifdef STA_WEXT
1970 		if (IS_STA_WEXT(cfg80211_wext) && pmpriv)
1971 			woal_send_iwevcustom_event(pmpriv, CUS_EVT_HS_WAKEUP);
1972 #endif /* STA_WEXT */
1973 		if (pmpriv)
1974 			woal_broadcast_event(pmpriv, CUS_EVT_HS_WAKEUP,
1975 					     strlen(CUS_EVT_HS_WAKEUP));
1976 #endif /*STA_SUPPORT */
1977 #ifdef UAP_SUPPORT
1978 		pmpriv = woal_get_priv((moal_handle *)pmoal_handle,
1979 				       MLAN_BSS_ROLE_UAP);
1980 		if (pmpriv) {
1981 			pmevent->event_id = UAP_EVENT_ID_HS_WAKEUP;
1982 			woal_broadcast_event(pmpriv, (t_u8 *)&pmevent->event_id,
1983 					     sizeof(t_u32));
1984 		}
1985 #endif /* UAP_SUPPORT */
1986 		break;
1987 	case MLAN_EVENT_ID_DRV_HS_ACTIVATED:
1988 #ifdef STA_SUPPORT
1989 		pmpriv = woal_get_priv((moal_handle *)pmoal_handle,
1990 				       MLAN_BSS_ROLE_STA);
1991 #ifdef STA_WEXT
1992 		if (IS_STA_WEXT(cfg80211_wext) && pmpriv)
1993 			woal_send_iwevcustom_event(pmpriv,
1994 						   CUS_EVT_HS_ACTIVATED);
1995 #endif /* STA_WEXT */
1996 		if (pmpriv)
1997 			woal_broadcast_event(pmpriv, CUS_EVT_HS_ACTIVATED,
1998 					     strlen(CUS_EVT_HS_ACTIVATED));
1999 #endif /* STA_SUPPORT */
2000 #if defined(UAP_SUPPORT)
2001 		pmpriv = woal_get_priv((moal_handle *)pmoal_handle,
2002 				       MLAN_BSS_ROLE_UAP);
2003 		if (pmpriv) {
2004 			pmevent->event_id = UAP_EVENT_ID_DRV_HS_ACTIVATED;
2005 			woal_broadcast_event(pmpriv, (t_u8 *)&pmevent->event_id,
2006 					     sizeof(t_u32));
2007 		}
2008 #endif
2009 #if defined(SDIO_SUSPEND_RESUME)
2010 		if (priv->phandle->suspend_fail == MFALSE) {
2011 			woal_get_pm_info(priv, &pm_info);
2012 			if (pm_info.is_suspend_allowed == MTRUE) {
2013 				priv->phandle->hs_activated = MTRUE;
2014 #ifdef MMC_PM_FUNC_SUSPENDED
2015 				woal_wlan_is_suspended(priv->phandle);
2016 #endif
2017 			}
2018 			priv->phandle->hs_activate_wait_q_woken = MTRUE;
2019 			wake_up_interruptible(&priv->phandle->
2020 					      hs_activate_wait_q);
2021 		}
2022 #endif
2023 		break;
2024 	case MLAN_EVENT_ID_DRV_HS_DEACTIVATED:
2025 #ifdef STA_SUPPORT
2026 		pmpriv = woal_get_priv((moal_handle *)pmoal_handle,
2027 				       MLAN_BSS_ROLE_STA);
2028 #ifdef STA_WEXT
2029 		if (IS_STA_WEXT(cfg80211_wext) && pmpriv)
2030 			woal_send_iwevcustom_event(pmpriv,
2031 						   CUS_EVT_HS_DEACTIVATED);
2032 #endif /* STA_WEXT */
2033 		if (pmpriv)
2034 			woal_broadcast_event(pmpriv, CUS_EVT_HS_DEACTIVATED,
2035 					     strlen(CUS_EVT_HS_DEACTIVATED));
2036 #endif /* STA_SUPPORT */
2037 #if defined(UAP_SUPPORT)
2038 		pmpriv = woal_get_priv((moal_handle *)pmoal_handle,
2039 				       MLAN_BSS_ROLE_UAP);
2040 		if (pmpriv) {
2041 			pmevent->event_id = UAP_EVENT_ID_DRV_HS_DEACTIVATED;
2042 			woal_broadcast_event(pmpriv, (t_u8 *)&pmevent->event_id,
2043 					     sizeof(t_u32));
2044 		}
2045 #endif
2046 #if defined(SDIO_SUSPEND_RESUME)
2047 		priv->phandle->hs_activated = MFALSE;
2048 #endif
2049 		break;
2050 #ifdef UAP_SUPPORT
2051 	case MLAN_EVENT_ID_UAP_FW_BSS_START:
2052 		if (priv->hist_data)
2053 			woal_hist_data_reset(priv);
2054 		priv->bss_started = MTRUE;
2055 		priv->skip_cac = MFALSE;
2056 		if (!netif_carrier_ok(priv->netdev))
2057 			netif_carrier_on(priv->netdev);
2058 		woal_start_queue(priv->netdev);
2059 		memcpy(priv->current_addr, pmevent->event_buf + 6, ETH_ALEN);
2060 		memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN);
2061 		woal_broadcast_event(priv, pmevent->event_buf,
2062 				     pmevent->event_len);
2063 #ifdef STA_SUPPORT
2064 #ifdef STA_CFG80211
2065 		pmpriv = woal_get_priv((moal_handle *)pmoal_handle,
2066 				       MLAN_BSS_ROLE_STA);
2067 		if (IS_STA_CFG80211(cfg80211_wext) && pmpriv)
2068 			woal_set_scan_time(pmpriv, ACTIVE_SCAN_CHAN_TIME,
2069 					   PASSIVE_SCAN_CHAN_TIME,
2070 					   MIN_SPECIFIC_SCAN_CHAN_TIME);
2071 #endif
2072 #endif
2073 #ifdef UAP_CFG80211
2074 #if defined(DFS_TESTING_SUPPORT)
2075 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
2076 		if (priv->chan_under_nop) {
2077 			PRINTM(MMSG,
2078 			       "Channel Under Nop: notify cfg80211 new channel=%d\n",
2079 			       priv->channel);
2080 			cfg80211_ch_switch_notify(priv->netdev, &priv->chan);
2081 			priv->chan_under_nop = MFALSE;
2082 		}
2083 #endif
2084 #endif
2085 #endif
2086 		break;
2087 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
2088 	case MLAN_EVENT_ID_DRV_UAP_CHAN_INFO:
2089 #ifdef UAP_CFG80211
2090 		if (IS_UAP_CFG80211(cfg80211_wext)) {
2091 			chan_band_info *pchan_info =
2092 				(chan_band_info *) pmevent->event_buf;
2093 			PRINTM(MEVENT,
2094 			       "UAP: 11n=%d, chan=%d, center_chan=%d, band=%d, width=%d, 2Offset=%d\n",
2095 			       pchan_info->is_11n_enabled, pchan_info->channel,
2096 			       pchan_info->center_chan,
2097 			       pchan_info->bandcfg.chanBand,
2098 			       pchan_info->bandcfg.chanWidth,
2099 			       pchan_info->bandcfg.chan2Offset);
2100 			if (priv->uap_host_based &&
2101 			    (priv->channel != pchan_info->channel))
2102 				woal_cfg80211_notify_uap_channel(priv,
2103 								 pchan_info);
2104 		}
2105 #endif
2106 		break;
2107 #endif
2108 	case MLAN_EVENT_ID_UAP_FW_BSS_ACTIVE:
2109 		priv->media_connected = MTRUE;
2110 		if (!netif_carrier_ok(priv->netdev))
2111 			netif_carrier_on(priv->netdev);
2112 		woal_wake_queue(priv->netdev);
2113 		woal_broadcast_event(priv, pmevent->event_buf,
2114 				     pmevent->event_len);
2115 		break;
2116 	case MLAN_EVENT_ID_UAP_FW_BSS_IDLE:
2117 		priv->media_connected = MFALSE;
2118 		woal_broadcast_event(priv, pmevent->event_buf,
2119 				     pmevent->event_len);
2120 		break;
2121 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
2122 	case MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED:
2123 		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext)) {
2124 			PRINTM(MEVENT,
2125 			       "FW_REMAIN_ON_CHANNEL_EXPIRED cookie = %#llx\n",
2126 			       priv->phandle->cookie);
2127 			priv->phandle->remain_on_channel = MFALSE;
2128 			if (priv->phandle->cookie &&
2129 			    !priv->phandle->is_remain_timer_set) {
2130 				cfg80211_remain_on_channel_expired(
2131 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
2132 									  priv->
2133 									  netdev,
2134 #else
2135 									  priv->
2136 									  wdev,
2137 #endif
2138 									  priv->
2139 									  phandle->
2140 									  cookie,
2141 									  &priv->
2142 									  phandle->
2143 									  chan,
2144 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
2145 									  priv->
2146 									  phandle->
2147 									  channel_type,
2148 #endif
2149 									  GFP_ATOMIC);
2150 				priv->phandle->cookie = 0;
2151 			}
2152 		}
2153 		break;
2154 #endif
2155 	case MLAN_EVENT_ID_UAP_FW_STA_CONNECT:
2156 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
2157 		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext)) {
2158 			struct station_info sinfo;
2159 			t_u8 addr[ETH_ALEN];
2160 
2161 			sinfo.filled = 0;
2162 			sinfo.generation = 0;
2163 			/* copy the station mac address */
2164 			memset(addr, 0xFF, ETH_ALEN);
2165 			memcpy(addr, pmevent->event_buf, ETH_ALEN);
2166 		/** these field add in kernel 3.2, but some
2167 				 * kernel do have the pacth to support it,
2168 				 * like T3T and pxa978T 3.0.31 JB, these
2169 				 * patch are needed to support
2170 				 * wpa_supplicant 2.x */
2171 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 31)
2172 			if (pmevent->event_len > ETH_ALEN) {
2173 #if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
2174 				/* set station info filled flag */
2175 				sinfo.filled |= STATION_INFO_ASSOC_REQ_IES;
2176 #endif
2177 				/* get the assoc request ies and length */
2178 				sinfo.assoc_req_ies =
2179 					(const t_u8 *)(pmevent->event_buf +
2180 						       ETH_ALEN);
2181 				sinfo.assoc_req_ies_len =
2182 					pmevent->event_len - ETH_ALEN;
2183 
2184 			}
2185 #endif /* KERNEL_VERSION */
2186 			if (priv->netdev && priv->wdev)
2187 				cfg80211_new_sta(priv->netdev,
2188 						 (t_u8 *)addr, &sinfo,
2189 						 GFP_KERNEL);
2190 		}
2191 #endif /* UAP_CFG80211 */
2192 		memmove((pmevent->event_buf + strlen(CUS_EVT_STA_CONNECTED) +
2193 			 1), pmevent->event_buf, pmevent->event_len);
2194 		memcpy(pmevent->event_buf, (t_u8 *)CUS_EVT_STA_CONNECTED,
2195 		       strlen(CUS_EVT_STA_CONNECTED));
2196 		pmevent->event_buf[strlen(CUS_EVT_STA_CONNECTED)] = 0;
2197 		woal_broadcast_event(priv, pmevent->event_buf,
2198 				     pmevent->event_len +
2199 				     strlen(CUS_EVT_STA_CONNECTED));
2200 #ifdef UAP_WEXT
2201 		if (IS_UAP_WEXT(cfg80211_wext)) {
2202 			memset(&wrqu, 0, sizeof(union iwreq_data));
2203 			wrqu.data.pointer = pmevent->event_buf;
2204 			if ((pmevent->event_len +
2205 			     strlen(CUS_EVT_STA_CONNECTED) + 1) > IW_CUSTOM_MAX)
2206 				wrqu.data.length =
2207 					ETH_ALEN +
2208 					strlen(CUS_EVT_STA_CONNECTED) + 1;
2209 			else
2210 				wrqu.data.length =
2211 					pmevent->event_len +
2212 					strlen(CUS_EVT_STA_CONNECTED) + 1;
2213 			wireless_send_event(priv->netdev, IWEVCUSTOM, &wrqu,
2214 					    pmevent->event_buf);
2215 		}
2216 #endif /* UAP_WEXT */
2217 		break;
2218 	case MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT:
2219 #ifdef UAP_CFG80211
2220 		if (IS_UAP_CFG80211(cfg80211_wext)) {
2221 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
2222 			/* skip 2 bytes extra header will get the mac address */
2223 			if (priv->netdev && priv->wdev)
2224 				cfg80211_del_sta(priv->netdev,
2225 						 pmevent->event_buf + 2,
2226 						 GFP_KERNEL);
2227 #endif /* KERNEL_VERSION */
2228 		}
2229 #endif /* UAP_CFG80211 */
2230 		memmove((pmevent->event_buf + strlen(CUS_EVT_STA_DISCONNECTED) +
2231 			 1), pmevent->event_buf, pmevent->event_len);
2232 		memcpy(pmevent->event_buf, (t_u8 *)CUS_EVT_STA_DISCONNECTED,
2233 		       strlen(CUS_EVT_STA_DISCONNECTED));
2234 		pmevent->event_buf[strlen(CUS_EVT_STA_DISCONNECTED)] = 0;
2235 		woal_broadcast_event(priv, pmevent->event_buf,
2236 				     pmevent->event_len +
2237 				     strlen(CUS_EVT_STA_DISCONNECTED));
2238 
2239 #ifdef UAP_WEXT
2240 		if (IS_UAP_WEXT(cfg80211_wext)) {
2241 			memset(&wrqu, 0, sizeof(union iwreq_data));
2242 			wrqu.data.pointer = pmevent->event_buf;
2243 			wrqu.data.length =
2244 				pmevent->event_len +
2245 				strlen(CUS_EVT_STA_DISCONNECTED) + 1;
2246 			wireless_send_event(priv->netdev, IWEVCUSTOM, &wrqu,
2247 					    pmevent->event_buf);
2248 		}
2249 #endif /* UAP_WEXT */
2250 		break;
2251 	case MLAN_EVENT_ID_DRV_MGMT_FRAME:
2252 		buf = (t_u8 *)(pmevent->event_buf + sizeof(pmevent->event_id));
2253 		payload_len =
2254 			pmevent->event_len - sizeof(pmevent->event_id) -
2255 			sizeof(moal_timestamps);
2256 		category = *(buf + sizeof(moal_wlan_802_11_header));
2257 		action_code = *(buf + sizeof(moal_wlan_802_11_header) + 1);
2258 		header = (moal_wlan_802_11_header *) (buf);
2259 		tm_ind = (moal_wnm_tm_msmt *) (buf +
2260 					       sizeof(moal_wlan_802_11_header) +
2261 					       2);
2262 		tsstamp = (moal_timestamps *) ((t_u8 *)buf + payload_len);
2263 		memcpy(peer_addr, (t_u8 *)&header->addr2, ETH_ALEN);
2264 		if ((category == IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM) &&
2265 		    (action_code == 0x1)) {
2266 			sprintf(event,
2267 				"%s " FULL_MACSTR
2268 				" %u %u %u %u %u %u %u %u %u %u %lu %llu",
2269 				CUS_EVT_TM_FRAME_INDICATION,
2270 				FULL_MAC2STR(peer_addr), tm_ind->dialog_token,
2271 				tsstamp->t2, tsstamp->t2_err, tsstamp->t3,
2272 				tsstamp->t3_err, tm_ind->follow_up_dialog_token,
2273 				tm_ind->t1, tm_ind->t1_err, tm_ind->t4,
2274 				tm_ind->t4_err,
2275 				(unsigned long)tsstamp->t2 * 10L,
2276 				tsstamp->ingress_time);
2277 
2278 			if (payload_len >
2279 			    (sizeof(moal_wnm_tm_msmt) +
2280 			     sizeof(moal_wlan_802_11_header) + 2)) {
2281 				ptp_context =
2282 					(moal_ptp_context *) (buf +
2283 							      sizeof
2284 							      (moal_wlan_802_11_header)
2285 							      + 2 +
2286 							      sizeof
2287 							      (moal_wnm_tm_msmt));
2288 				sprintf(event + strlen(event), " %02x %02x",
2289 					ptp_context->vendor_specific,
2290 					ptp_context->length);
2291 				for (i = 0; i < ptp_context->length; i++)
2292 					sprintf(event + strlen(event), " %02x",
2293 						ptp_context->data[i]);
2294 			}
2295 			woal_broadcast_event(priv, event, strlen(event));
2296 		}
2297 #ifdef UAP_WEXT
2298 		if (IS_UAP_WEXT(cfg80211_wext)) {
2299 			woal_broadcast_event(priv, pmevent->event_buf,
2300 					     pmevent->event_len);
2301 		}
2302 #endif /* UAP_WEXT */
2303 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
2304 		if (IS_STA_OR_UAP_CFG80211(cfg80211_wext)) {
2305 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
2306 			if (priv->netdev
2307 			    && priv->netdev->ieee80211_ptr->wiphy->mgmt_stypes
2308 			    && priv->mgmt_subtype_mask) {
2309 				/* frmctl + durationid + addr1 + addr2 + addr3 + seqctl */
2310 #define PACKET_ADDR4_POS        (2 + 2 + 6 + 6 + 6 + 2)
2311 				t_u8 *pkt;
2312 				int freq =
2313 					priv->phandle->
2314 					remain_on_channel ? priv->phandle->chan.
2315 					center_freq :
2316 					woal_get_active_intf_freq(priv);
2317 				if (!freq) {
2318 					if (!priv->phandle->chan.center_freq) {
2319 						PRINTM(MINFO,
2320 						       "Skip to report mgmt packet to cfg80211\n");
2321 						break;
2322 					}
2323 					freq = priv->phandle->chan.center_freq;
2324 				}
2325 
2326 				pkt = ((t_u8 *)pmevent->event_buf
2327 				       + sizeof(pmevent->event_id));
2328 
2329 				/* move addr4 */
2330 				memmove(pkt + PACKET_ADDR4_POS,
2331 					pkt + PACKET_ADDR4_POS + ETH_ALEN,
2332 					pmevent->event_len -
2333 					sizeof(pmevent->event_id)
2334 					- PACKET_ADDR4_POS - ETH_ALEN);
2335 #ifdef WIFI_DIRECT_SUPPORT
2336 				if (ieee80211_is_action
2337 				    (((struct ieee80211_mgmt *)pkt)->
2338 				     frame_control))
2339 					woal_cfg80211_display_p2p_actframe(pkt,
2340 									   pmevent->
2341 									   event_len
2342 									   -
2343 									   sizeof
2344 									   (pmevent->
2345 									    event_id)
2346 									   -
2347 									   MLAN_MAC_ADDR_LENGTH,
2348 									   ieee80211_get_channel
2349 									   (priv->
2350 									    wdev->
2351 									    wiphy,
2352 									    freq),
2353 									   MFALSE);
2354 #endif
2355 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
2356 				cfg80211_rx_mgmt(
2357 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
2358 							priv->wdev,
2359 #else
2360 							priv->netdev,
2361 #endif
2362 							freq, 0,
2363 							((const t_u8 *)pmevent->
2364 							 event_buf) +
2365 							sizeof(pmevent->
2366 							       event_id),
2367 							pmevent->event_len -
2368 							sizeof(pmevent->
2369 							       event_id) -
2370 							MLAN_MAC_ADDR_LENGTH
2371 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
2372 							, 0
2373 #endif
2374 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
2375 							, GFP_ATOMIC
2376 #endif
2377 					);
2378 #else
2379 				cfg80211_rx_mgmt(priv->netdev, freq,
2380 						 ((const t_u8 *)pmevent->
2381 						  event_buf) +
2382 						 sizeof(pmevent->event_id),
2383 						 pmevent->event_len -
2384 						 sizeof(pmevent->event_id) -
2385 						 MLAN_MAC_ADDR_LENGTH,
2386 						 GFP_ATOMIC);
2387 #endif
2388 			}
2389 #endif /* KERNEL_VERSION */
2390 		}
2391 #endif /* STA_CFG80211 || UAP_CFG80211 */
2392 		break;
2393 #endif /* UAP_SUPPORT */
2394 	case MLAN_EVENT_ID_DRV_PASSTHRU:
2395 		woal_broadcast_event(priv, pmevent->event_buf,
2396 				     pmevent->event_len);
2397 		break;
2398 	case MLAN_EVENT_ID_DRV_ASSOC_FAILURE_REPORT:
2399 		PRINTM(MINFO, "Assoc result\n");
2400 
2401 		if (priv->media_connected) {
2402 			PRINTM(MINFO, "Assoc_Rpt: Media Connected\n");
2403 			if (!netif_carrier_ok(priv->netdev)) {
2404 				PRINTM(MINFO, "Assoc_Rpt: Carrier On\n");
2405 				netif_carrier_on(priv->netdev);
2406 			}
2407 			PRINTM(MINFO, "Assoc_Rpt: Queue Start\n");
2408 			woal_wake_queue(priv->netdev);
2409 		}
2410 		break;
2411 	case MLAN_EVENT_ID_DRV_MEAS_REPORT:
2412 		/* We have received measurement report, wakeup measurement wait queue */
2413 		PRINTM(MINFO, "Measurement Report\n");
2414 		/* Going out of CAC checking period */
2415 		if (priv->phandle->cac_period == MTRUE) {
2416 			priv->phandle->cac_period = MFALSE;
2417 			if (priv->phandle->meas_wait_q_woken == MFALSE) {
2418 				priv->phandle->meas_wait_q_woken = MTRUE;
2419 				wake_up_interruptible(&priv->phandle->
2420 						      meas_wait_q);
2421 			}
2422 
2423 			/* Execute delayed BSS START command */
2424 			if (priv->phandle->delay_bss_start == MTRUE) {
2425 				mlan_ioctl_req *req = NULL;
2426 				mlan_ds_bss *bss = NULL;
2427 
2428 				/* Clear flag */
2429 				priv->phandle->delay_bss_start = MFALSE;
2430 
2431 				PRINTM(MMSG,
2432 				       "Now CAC measure period end. Execute delayed BSS Start command.\n");
2433 
2434 				req = woal_alloc_mlan_ioctl_req(sizeof
2435 								(mlan_ds_bss));
2436 				if (!req) {
2437 					PRINTM(MERROR,
2438 					       "Failed to allocate ioctl request buffer\n");
2439 					goto done;
2440 				}
2441 				bss = (mlan_ds_bss *)req->pbuf;
2442 				req->req_id = MLAN_IOCTL_BSS;
2443 				req->action = MLAN_ACT_SET;
2444 				bss->sub_command = MLAN_OID_BSS_START;
2445 				memcpy(&bss->param.ssid_bssid,
2446 				       &priv->phandle->delay_ssid_bssid,
2447 				       sizeof(mlan_ssid_bssid));
2448 
2449 				if (woal_request_ioctl(priv, req, MOAL_NO_WAIT)
2450 				    != MLAN_STATUS_PENDING) {
2451 					PRINTM(MERROR,
2452 					       "Delayed BSS Start operation failed!\n");
2453 					kfree(req);
2454 				}
2455 
2456 				PRINTM(MMSG, "BSS START Complete!\n");
2457 			}
2458 #ifdef UAP_SUPPORT
2459 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
2460 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2461 			if (priv->uap_host_based && dfs_offload)
2462 				woal_cfg80211_dfs_vendor_event(priv,
2463 							       event_dfs_cac_finished,
2464 							       &priv->chan);
2465 #endif
2466 #endif
2467 #endif
2468 
2469 		}
2470 		break;
2471 	case MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ:
2472 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
2473 #ifdef STA_CFG80211
2474 		if (IS_STA_CFG80211(cfg80211_wext)) {
2475 			tdls_tear_down_event *tdls_event =
2476 				(tdls_tear_down_event *)pmevent->event_buf;
2477 			cfg80211_tdls_oper_request(priv->netdev,
2478 						   tdls_event->peer_mac_addr,
2479 						   NL80211_TDLS_TEARDOWN,
2480 						   tdls_event->reason_code,
2481 						   GFP_KERNEL);
2482 		}
2483 #endif
2484 #endif
2485 		break;
2486 	case MLAN_EVENT_ID_FW_TX_STATUS:
2487 		{
2488 			unsigned long flag;
2489 			tx_status_event *tx_status =
2490 				(tx_status_event *)(pmevent->event_buf + 4);
2491 			struct tx_status_info *tx_info = NULL;
2492 			t_u8 catagory = 0, action = 0, dialog_token = 0;
2493 			t_u8 peer_addr[6];
2494 			confirm_timestamps tsbuff = { 0 };
2495 
2496 			PRINTM(MINFO,
2497 			       "Receive Tx status: tx_token=%d, pkt_type=0x%x, status=%d tx_seq_num=%d\n",
2498 			       tx_status->tx_token_id, tx_status->packet_type,
2499 			       tx_status->status, priv->tx_seq_num);
2500 			spin_lock_irqsave(&priv->tx_stat_lock, flag);
2501 			tx_info =
2502 				woal_get_tx_info(priv, tx_status->tx_token_id);
2503 			if (tx_info) {
2504 				bool ack;
2505 				struct sk_buff *skb =
2506 					(struct sk_buff *)tx_info->tx_skb;
2507 				list_del(&tx_info->link);
2508 				spin_unlock_irqrestore(&priv->tx_stat_lock,
2509 						       flag);
2510 				if (!tx_status->status)
2511 					ack = true;
2512 				else
2513 					ack = false;
2514 				{
2515 					catagory =
2516 						((struct ieee80211_mgmt *)skb->
2517 						 data)->u.action.category;
2518 					action = *(&
2519 						   ((struct ieee80211_mgmt *)
2520 						    skb->data)->u.action.
2521 						   category + 1);
2522 					dialog_token = *(&((struct ieee80211_mgmt *)skb->data)->u.action.category + 2);	//dt is 2 bytes after category
2523 					memcpy(peer_addr,
2524 					       (t_u8
2525 						*)((struct ieee80211_mgmt *)
2526 						   skb->data)->da, 6);
2527 					PRINTM(MEVENT,
2528 					       "Wlan: Tx status=%d, cat = %d, act = %d, dt = %d\n",
2529 					       ack, catagory, action,
2530 					       dialog_token);
2531 					/* this is a tx done for timining measurement action frame
2532 					 * so we need to send the tx timestamp of txed frame back to supplicant
2533 					 * for this send the timestamps along with the tx_status event buffer */
2534 					if (catagory ==
2535 					    IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM
2536 					    && action == 0x1) {
2537 						/* create a timestamp buffer to send to host supplicant */
2538 
2539 						PRINTM(MEVENT,
2540 						       "Wlan: Tx t1=%lld, t4 = %lld, t1_error = %lld, t4_error=%lld\n",
2541 						       tx_status->t1_tstamp,
2542 						       tx_status->t4_tstamp,
2543 						       tx_status->t1_error,
2544 						       tx_status->t4_error);
2545 
2546 						/* for timestamps only use lower 32-bits as spec defines 11v timestamps as 32-bits */
2547 						tsbuff.t4 =
2548 							(u32)
2549 							woal_le32_to_cpu
2550 							(tx_status->t4_tstamp);
2551 						tsbuff.t1 =
2552 							(u32)
2553 							woal_le32_to_cpu
2554 							(tx_status->t1_tstamp);
2555 						tsbuff.t4_error =
2556 							(u8)tx_status->t4_error;
2557 						tsbuff.t1_error =
2558 							(u8)tx_status->t4_error;
2559 						tsbuff.egress_time =
2560 							(u64)
2561 							woal_le64_to_cpu
2562 							(tx_status->
2563 							 egress_time);
2564 
2565 						if (skb_tailroom(skb) <
2566 						    sizeof(confirm_timestamps))
2567 						{
2568 							struct sk_buff *new_skb
2569 								= NULL;
2570 							PRINTM(MWARN,
2571 							       "Tx Status: Insufficient skb tailroom %d\n",
2572 							       skb_tailroom
2573 							       (skb));
2574 							/* Insufficient skb tailroom - allocate a new skb */
2575 							new_skb =
2576 								skb_copy_expand
2577 								(skb, 0,
2578 								 sizeof
2579 								 (confirm_timestamps),
2580 								 GFP_ATOMIC);
2581 							if (unlikely(!new_skb)) {
2582 								PRINTM(MERROR,
2583 								       "Tx Status: Cannot allocate skb\n");
2584 								dev_kfree_skb_any
2585 									(skb);
2586 								goto done;
2587 							}
2588 							skb = new_skb;
2589 							PRINTM(MINFO,
2590 							       "new skb tailroom %d\n",
2591 							       skb_tailroom
2592 							       (skb));
2593 						}
2594 						if (tx_info->tx_cookie) {
2595 							memcpy(skb_put
2596 							       (skb,
2597 								sizeof
2598 								(confirm_timestamps)),
2599 							       &tsbuff,
2600 							       sizeof
2601 							       (confirm_timestamps));
2602 						} else {
2603 							sprintf(event,
2604 								"%s "
2605 								FULL_MACSTR
2606 								" %u %u %u %u %u %u %llu",
2607 								CUS_EVT_TIMING_MSMT_CONFIRM,
2608 								FULL_MAC2STR
2609 								(peer_addr),
2610 								dialog_token,
2611 								tsbuff.t1,
2612 								tsbuff.t1_error,
2613 								tsbuff.t4,
2614 								tsbuff.t4_error,
2615 								tsbuff.t1 * 10,
2616 								tsbuff.
2617 								egress_time);
2618 							woal_broadcast_event
2619 								(priv, event,
2620 								 sizeof(event));
2621 						}
2622 					}
2623 				}
2624 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
2625 				if (tx_info->tx_cookie) {
2626 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
2627 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
2628 					cfg80211_mgmt_tx_status(priv->netdev,
2629 								tx_info->
2630 								tx_cookie,
2631 								skb->data,
2632 								skb->len, ack,
2633 								GFP_ATOMIC);
2634 #else
2635 					cfg80211_mgmt_tx_status(priv->wdev,
2636 								tx_info->
2637 								tx_cookie,
2638 								skb->data,
2639 								skb->len, ack,
2640 								GFP_ATOMIC);
2641 #endif
2642 #endif
2643 				}
2644 #endif
2645 				dev_kfree_skb_any(skb);
2646 				kfree(tx_info);
2647 			} else
2648 				spin_unlock_irqrestore(&priv->tx_stat_lock,
2649 						       flag);
2650 		}
2651 		break;
2652 
2653 	case MLAN_EVENT_ID_DRV_FT_RESPONSE:
2654 		if (priv->phandle->fw_roam_enable)
2655 			break;
2656 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3,10,0)
2657 #ifdef STA_CFG80211
2658 		if (IS_STA_CFG80211(cfg80211_wext)) {
2659 			struct cfg80211_ft_event_params ft_event;
2660 			if (priv->ft_pre_connect)
2661 				break;
2662 			memset(&ft_event, 0,
2663 			       sizeof(struct cfg80211_ft_event_params));
2664 			PRINTM(MMSG,
2665 			       "wlan : FT response  target AP " MACSTR "\n",
2666 			       MAC2STR((t_u8 *)pmevent->event_buf));
2667 			DBG_HEXDUMP(MDAT_D, "FT-event ", pmevent->event_buf,
2668 				    pmevent->event_len);
2669 			memcpy(priv->target_ap_bssid, pmevent->event_buf,
2670 			       ETH_ALEN);
2671 			ft_event.target_ap = priv->target_ap_bssid;
2672 			ft_event.ies = pmevent->event_buf + ETH_ALEN;
2673 			ft_event.ies_len = pmevent->event_len - ETH_ALEN;
2674 			/*TSPEC info is needed by RIC, However the TS operation is configured by mlanutl */
2675 			/*So do not add RIC temporally */
2676 			/*when add RIC, 1. query TS status, 2. copy tspec from addts command */
2677 			ft_event.ric_ies = NULL;
2678 			ft_event.ric_ies_len = 0;
2679 
2680 			cfg80211_ft_event(priv->netdev, &ft_event);
2681 			priv->ft_pre_connect = MTRUE;
2682 
2683 			if (priv->ft_roaming_triggered_by_driver ||
2684 			    !(priv->ft_cap & MBIT(0))) {
2685 				priv->ft_wait_condition = MTRUE;
2686 				wake_up(&priv->ft_wait_q);
2687 			}
2688 		}
2689 #endif
2690 #endif
2691 		break;
2692 	case MLAN_EVENT_ID_FW_ROAM_OFFLOAD_RESULT:
2693 		memcpy(priv->cfg_bssid, pmevent->event_buf, ETH_ALEN);
2694 		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)pmevent->event_buf +
2695 					      MLAN_MAC_ADDR_LENGTH);
2696 		tlv_buf_left = pmevent->event_len - MLAN_MAC_ADDR_LENGTH;
2697 		while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
2698 			tlv_type = woal_le16_to_cpu(tlv->type);
2699 			tlv_len = woal_le16_to_cpu(tlv->len);
2700 
2701 			if (tlv_buf_left <
2702 			    (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
2703 				PRINTM(MERROR,
2704 				       "Error processing firmware roam success TLVs, bytes left < TLV length\n");
2705 				break;
2706 			}
2707 
2708 			switch (tlv_type) {
2709 			case TLV_TYPE_APINFO:
2710 				pinfo = (apinfo *) tlv;
2711 				break;
2712 			case TLV_TYPE_ASSOC_REQ_IE:
2713 				req_tlv = (apinfo *) tlv;
2714 				break;
2715 			default:
2716 				break;
2717 			}
2718 			tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
2719 			tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
2720 						      sizeof
2721 						      (MrvlIEtypesHeader_t));
2722 		}
2723 		if (!pinfo) {
2724 			PRINTM(MERROR,
2725 			       "ERROR:AP info in roaming event buffer is NULL\n");
2726 			goto done;
2727 		}
2728 		if (req_tlv) {
2729 			req_ie = req_tlv->rsp_ie;
2730 			ie_len = req_tlv->header.len;
2731 		}
2732 
2733 		woal_inform_bss_from_scan_result(priv, NULL, MOAL_NO_WAIT);
2734 #if defined(FW_ROAMING) || (defined(ROAMING_OFFLOAD) && defined(STA_CFG80211))
2735 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2736 		memset(&roam_info, 0, sizeof(struct cfg80211_roam_info));
2737 		roam_info.bssid = priv->cfg_bssid;
2738 		roam_info.req_ie = req_ie;
2739 		roam_info.req_ie_len = ie_len;
2740 		roam_info.resp_ie = pinfo->rsp_ie;
2741 		roam_info.resp_ie_len = pinfo->header.len;
2742 		cfg80211_roamed(priv->netdev, &roam_info, GFP_KERNEL);
2743 #else
2744 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
2745 		cfg80211_roamed(priv->netdev, NULL, priv->cfg_bssid, req_ie,
2746 				ie_len, pinfo->rsp_ie, pinfo->header.len,
2747 				GFP_KERNEL);
2748 #else
2749 		cfg80211_roamed(priv->netdev, priv->cfg_bssid, req_ie, ie_len,
2750 				pinfo->rsp_ie, pinfo->header.len, GFP_KERNEL);
2751 #endif
2752 #endif
2753 #ifdef STA_CFG80211
2754 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2755 		woal_roam_ap_info(priv, pmevent->event_buf, pmevent->event_len);
2756 #endif
2757 #endif
2758 #endif
2759 		PRINTM(MMSG, "FW Roamed to bssid " MACSTR " successfully\n",
2760 		       MAC2STR(priv->cfg_bssid));
2761 		break;
2762 	default:
2763 		break;
2764 	}
2765 done:
2766 	LEAVE();
2767 	return MLAN_STATUS_SUCCESS;
2768 }
2769 
2770 /**
2771  *  @brief This function prints the debug message in mlan
2772  *
2773  *  @param pmoal_handle Pointer to the MOAL context
2774  *  @param level    debug level
2775  *  @param pformat  point to string format buf
2776  *
2777  *  @return         N/A
2778  */
2779 t_void
moal_print(IN t_void * pmoal_handle,IN t_u32 level,IN char * pformat,IN...)2780 moal_print(IN t_void *pmoal_handle, IN t_u32 level, IN char *pformat, IN ...)
2781 {
2782 #ifdef	DEBUG_LEVEL1
2783 	va_list args;
2784 
2785 	if (level & MHEX_DUMP) {
2786 		t_u8 *buf = NULL;
2787 		int len = 0;
2788 
2789 		va_start(args, pformat);
2790 		buf = (t_u8 *)va_arg(args, t_u8 *);
2791 		len = (int)va_arg(args, int);
2792 		va_end(args);
2793 
2794 #ifdef DEBUG_LEVEL2
2795 		if (level & MINFO)
2796 			HEXDUMP((char *)pformat, buf, len);
2797 		else
2798 #endif /* DEBUG_LEVEL2 */
2799 		{
2800 			if (level & MERROR)
2801 				DBG_HEXDUMP(MERROR, (char *)pformat, buf, len);
2802 			if (level & MCMD_D)
2803 				DBG_HEXDUMP(MCMD_D, (char *)pformat, buf, len);
2804 			if (level & MDAT_D)
2805 				DBG_HEXDUMP(MDAT_D, (char *)pformat, buf, len);
2806 			if (level & MIF_D)
2807 				DBG_HEXDUMP(MIF_D, (char *)pformat, buf, len);
2808 			if (level & MFW_D)
2809 				DBG_HEXDUMP(MFW_D, (char *)pformat, buf, len);
2810 			if (level & MEVT_D)
2811 				DBG_HEXDUMP(MEVT_D, (char *)pformat, buf, len);
2812 		}
2813 	} else {
2814 		if (drvdbg & level) {
2815 			va_start(args, pformat);
2816 			vprintk(pformat, args);
2817 			va_end(args);
2818 		}
2819 	}
2820 #endif /* DEBUG_LEVEL1 */
2821 }
2822 
2823 /**
2824  *  @brief This function prints the network interface name
2825  *
2826  *  @param pmoal_handle Pointer to the MOAL context
2827  *  @param bss_index    BSS index
2828  *  @param level        debug level
2829  *
2830  *  @return            N/A
2831  */
2832 t_void
moal_print_netintf(IN t_void * pmoal_handle,IN t_u32 bss_index,IN t_u32 level)2833 moal_print_netintf(IN t_void *pmoal_handle, IN t_u32 bss_index, IN t_u32 level)
2834 {
2835 #ifdef DEBUG_LEVEL1
2836 	moal_handle *phandle = (moal_handle *)pmoal_handle;
2837 
2838 	if (phandle) {
2839 		if ((bss_index < MLAN_MAX_BSS_NUM) && phandle->priv[bss_index]
2840 		    && phandle->priv[bss_index]->netdev) {
2841 			if (drvdbg & level)
2842 				printk("%s: ",
2843 				       phandle->priv[bss_index]->netdev->name);
2844 		}
2845 	}
2846 #endif /* DEBUG_LEVEL1 */
2847 }
2848 
2849 /**
2850  *  @brief This function asserts the existence of the passed argument
2851  *
2852  *  @param pmoal_handle     A pointer to moal_private structure
2853  *  @param cond             Condition to check
2854  *
2855  *  @return                 N/A
2856  */
2857 t_void
moal_assert(IN t_void * pmoal_handle,IN t_u32 cond)2858 moal_assert(IN t_void *pmoal_handle, IN t_u32 cond)
2859 {
2860 	if (!cond) {
2861 		panic("Assert failed: Panic!");
2862 	}
2863 }
2864 
2865 /**
2866  *  @brief This function save the histogram data
2867  *
2868  *  @param pmoal_handle     A pointer to moal_private structure
2869  *  @param bss_index        BSS index
2870  *  @param rx_rate          rx rate index
2871  *  @param snr              snr
2872  *  @param nflr             noise floor
2873  *  @param antenna          antenna
2874  *
2875  *  @return                 N/A
2876  */
2877 t_void
moal_hist_data_add(IN t_void * pmoal_handle,IN t_u32 bss_index,IN t_u8 rx_rate,IN t_s8 snr,IN t_s8 nflr,IN t_u8 antenna)2878 moal_hist_data_add(IN t_void *pmoal_handle, IN t_u32 bss_index, IN t_u8 rx_rate,
2879 		   IN t_s8 snr, IN t_s8 nflr, IN t_u8 antenna)
2880 {
2881 	moal_private *priv = NULL;
2882 	priv = woal_bss_index_to_priv(pmoal_handle, bss_index);
2883 	if (priv && antenna >= priv->phandle->histogram_table_num)
2884 		antenna = 0;
2885 	if (priv && priv->hist_data[antenna])
2886 		woal_hist_data_add(priv, rx_rate, snr, nflr, antenna);
2887 }
2888 
2889 /**
2890  *  @brief This function update the peer signal
2891  *
2892  *  @param pmoal_handle     A pointer to moal_private structure
2893  *  @param bss_index        BSS index
2894  *  @param peer_addr        peer address
2895  *  @param snr              snr
2896  *  @param nflr             noise floor
2897  *
2898  *  @return                 N/A
2899  */
2900 t_void
moal_updata_peer_signal(IN t_void * pmoal_handle,IN t_u32 bss_index,IN t_u8 * peer_addr,IN t_s8 snr,IN t_s8 nflr)2901 moal_updata_peer_signal(IN t_void *pmoal_handle, IN t_u32 bss_index,
2902 			IN t_u8 *peer_addr, IN t_s8 snr, IN t_s8 nflr)
2903 {
2904 	moal_private *priv = NULL;
2905 	struct tdls_peer *peer = NULL;
2906 	unsigned long flags;
2907 	priv = woal_bss_index_to_priv(pmoal_handle, bss_index);
2908 	if (priv && priv->enable_auto_tdls) {
2909 		spin_lock_irqsave(&priv->tdls_lock, flags);
2910 		list_for_each_entry(peer, &priv->tdls_list, link) {
2911 			if (!memcmp(peer->peer_addr, peer_addr, ETH_ALEN)) {
2912 				peer->rssi = nflr - snr;
2913 				peer->rssi_jiffies = jiffies;
2914 				break;
2915 			}
2916 		}
2917 		spin_unlock_irqrestore(&priv->tdls_lock, flags);
2918 	}
2919 }
2920 
2921 /**
2922 *  @brief This function records host time in nano seconds
2923 *
2924 *  @return                 64 bit value of host time in nano seconds
2925 */
2926 s64
get_host_time_ns(void)2927 get_host_time_ns(void)
2928 {
2929 	struct timespec ts;
2930 	getnstimeofday(&ts);
2931 	return timespec_to_ns(&ts);
2932 }
2933 
2934 /**
2935  *  @brief Retrieves the current system time
2936  *
2937  *  @param time     Pointer for the seconds of system time
2938  *
2939  *  @return         MLAN_STATUS_SUCCESS
2940  */
2941 mlan_status
moal_get_host_time_ns(OUT t_u64 * time)2942 moal_get_host_time_ns(OUT t_u64 *time)
2943 {
2944 	struct timespec ts;
2945 	t_u64 hclk_val;
2946 
2947 	getnstimeofday(&ts);
2948 	hclk_val = (ts.tv_sec * 1000000000L) + ts.tv_nsec;
2949 	*time = hclk_val;
2950 	return MLAN_STATUS_SUCCESS;
2951 }
2952 
2953 /**
2954  *  @brief Performs division of 64-bit num with base
2955  *  @brief do_div does two things
2956  *  @brief 1. modifies the 64-bit num in place with
2957  *  @brief the quotient, i.e., num becomes quotient
2958  *  @brief 2. returns the 32-bit reminder
2959  *
2960  *  @param num   dividend
2961  *  @param base  divisor
2962  *  @return      returns quotient
2963  */
2964 t_u32
moal_do_div(IN t_u64 num,IN t_u32 base)2965 moal_do_div(IN t_u64 num, IN t_u32 base)
2966 {
2967 	return do_div(num, base);
2968 }
2969