1 /** @file moal_shim.c
2 *
3 * @brief This file contains the callback functions registered to MLAN
4 *
5 *
6 * Copyright 2008-2022 NXP
7 *
8 * This software file (the File) is distributed by NXP
9 * under the terms of the GNU General Public License Version 2, June 1991
10 * (the License). You may use, redistribute and/or modify the File in
11 * accordance with the terms and conditions of the License, a copy of which
12 * is available by writing to the Free Software Foundation, Inc.,
13 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15 *
16 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
19 * this warranty disclaimer.
20 *
21 */
22
23 /********************************************************
24 Change log:
25 10/21/2008: initial version
26 ********************************************************/
27
28 #include "moal_main.h"
29 #ifdef USB
30 #include "moal_usb.h"
31 #endif
32 #ifdef SDIO
33 #include "moal_sdio.h"
34 #endif
35 #ifdef PCIE
36 #include "moal_pcie.h"
37 #endif
38 #ifdef UAP_SUPPORT
39 #include "moal_uap.h"
40 #endif
41 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
42 #include "moal_cfg80211.h"
43 #include "moal_cfg80211_util.h"
44 #endif
45 #include <asm/div64.h>
46
47 #if defined(PCIE) || defined(SDIO)
48 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 70)
49 #ifdef IMX_SUPPORT
50 #include <linux/busfreq-imx.h>
51 #endif
52 #endif
53
54 #include <linux/etherdevice.h>
55
56 #endif /*defined(PCIE) || defined(SDIO)*/
57
58 /********************************************************
59 Local Variables
60 ********************************************************/
61 /** moal_lock */
62 typedef struct _moal_lock {
63 /** Lock */
64 spinlock_t lock;
65 /** Flags */
66 unsigned long flags;
67 } moal_lock;
68
69 /********************************************************
70 Global Variables
71 ********************************************************/
72
73 extern int wifi_status;
74
75 /********************************************************
76 Local Functions
77 ********************************************************/
78
79 /********************************************************
80 Global Functions
81 ********************************************************/
82 /**
83 * @brief Alloc a buffer
84 *
85 * @param pmoal Pointer to the MOAL context
86 * @param size The size of the buffer to be allocated
87 * @param flag The type of the buffer to be allocated
88 * @param ppbuf Pointer to a buffer location to store buffer pointer
89 * allocated
90 *
91 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
92 */
moal_malloc(t_void * pmoal,t_u32 size,t_u32 flag,t_u8 ** ppbuf)93 mlan_status moal_malloc(t_void *pmoal, t_u32 size, t_u32 flag, t_u8 **ppbuf)
94 {
95 moal_handle *handle = (moal_handle *)pmoal;
96 gfp_t mem_flag = (in_interrupt() || in_atomic() || irqs_disabled()) ?
97 GFP_ATOMIC :
98 GFP_KERNEL;
99
100 if (flag & MLAN_MEM_FLAG_ATOMIC)
101 mem_flag = GFP_ATOMIC;
102
103 #ifdef USB
104 if (!IS_USB(handle->card_type))
105 #endif
106 {
107 if (flag & MLAN_MEM_DMA)
108 mem_flag |= GFP_DMA;
109 }
110 *ppbuf = kzalloc(size, mem_flag);
111 if (*ppbuf == NULL) {
112 PRINTM(MERROR, "%s: allocate memory (%d bytes) failed!\n",
113 __func__, (int)size);
114 return MLAN_STATUS_FAILURE;
115 }
116 atomic_inc(&handle->malloc_count);
117
118 return MLAN_STATUS_SUCCESS;
119 }
120
121 /**
122 * @brief Free a buffer
123 *
124 * @param pmoal Pointer to the MOAL context
125 * @param pbuf Pointer to the buffer to be freed
126 *
127 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
128 */
moal_mfree(t_void * pmoal,t_u8 * pbuf)129 mlan_status moal_mfree(t_void *pmoal, t_u8 *pbuf)
130 {
131 moal_handle *handle = (moal_handle *)pmoal;
132
133 if (!pbuf)
134 return MLAN_STATUS_FAILURE;
135 kfree(pbuf);
136 atomic_dec(&handle->malloc_count);
137 return MLAN_STATUS_SUCCESS;
138 }
139
140 /**
141 * @brief Alloc a vitual-address-continuous buffer
142 *
143 * @param pmoal Pointer to the MOAL context
144 * @param size The size of the buffer to be allocated
145 * @param ppbuf Pointer to a buffer location to store buffer pointer
146 * allocated
147 *
148 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
149 */
moal_vmalloc(t_void * pmoal,t_u32 size,t_u8 ** ppbuf)150 mlan_status moal_vmalloc(t_void *pmoal, t_u32 size, t_u8 **ppbuf)
151 {
152 moal_handle *handle = (moal_handle *)pmoal;
153
154 *ppbuf = vmalloc(size);
155 if (*ppbuf == NULL) {
156 PRINTM(MERROR, "%s: vmalloc (%d bytes) failed!", __func__,
157 (int)size);
158 return MLAN_STATUS_FAILURE;
159 }
160 atomic_inc(&handle->vmalloc_count);
161
162 return MLAN_STATUS_SUCCESS;
163 }
164
165 /**
166 * @brief Free a buffer allocated by vmalloc
167 *
168 * @param pmoal Pointer to the MOAL context
169 * @param pbuf Pointer to the buffer to be freed
170 *
171 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
172 */
moal_vfree(t_void * pmoal,t_u8 * pbuf)173 mlan_status moal_vfree(t_void *pmoal, t_u8 *pbuf)
174 {
175 moal_handle *handle = (moal_handle *)pmoal;
176
177 if (!pbuf)
178 return MLAN_STATUS_FAILURE;
179 vfree(pbuf);
180 atomic_dec(&handle->vmalloc_count);
181 return MLAN_STATUS_SUCCESS;
182 }
183
184 #ifdef PCIE
185 /**
186 * @brief Alloc a consistent block of memory
187 *
188 * @param pmoal Pointer to the MOAL context
189 * @param size The size of the buffer to be allocated
190 * @param ppbuf Pointer to a buffer location to store memory allocated
191 * @param pbuf_pa Pointer to a buffer location to store physical address
192 * of above memory
193 *
194 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
195 */
moal_malloc_consistent(t_void * pmoal,t_u32 size,t_u8 ** ppbuf,t_pu64 pbuf_pa)196 mlan_status moal_malloc_consistent(t_void *pmoal, t_u32 size, t_u8 **ppbuf,
197 t_pu64 pbuf_pa)
198 {
199 moal_handle *handle = (moal_handle *)pmoal;
200 pcie_service_card *card = (pcie_service_card *)handle->card;
201 dma_addr_t dma;
202 *pbuf_pa = 0;
203
204 if (!card)
205 return MLAN_STATUS_FAILURE;
206
207 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)
208 *ppbuf = (t_u8 *)dma_alloc_coherent(&card->dev->dev, size,
209 (dma_addr_t *)&dma, GFP_KERNEL);
210 #else
211 *ppbuf = (t_u8 *)pci_alloc_consistent(card->dev, size,
212 (dma_addr_t *)&dma);
213 #endif
214 if (*ppbuf == NULL) {
215 PRINTM(MERROR,
216 "%s: allocate consistent memory (%d bytes) failed!\n",
217 __func__, (int)size);
218 return MLAN_STATUS_FAILURE;
219 }
220 *pbuf_pa = (t_u64)dma;
221 atomic_inc(&handle->malloc_cons_count);
222
223 return MLAN_STATUS_SUCCESS;
224 }
225
226 /**
227 * @brief Free a consistent block of memory
228 *
229 * @param pmoal Pointer to the MOAL context
230 * @param size Size of them memory to be freed
231 * @param pbuf Pointer to the memory to be freed
232 * @param buf_pa Physical address of the memory to be freed
233 *
234 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
235 */
moal_mfree_consistent(t_void * pmoal,t_u32 size,t_u8 * pbuf,t_u64 buf_pa)236 mlan_status moal_mfree_consistent(t_void *pmoal, t_u32 size, t_u8 *pbuf,
237 t_u64 buf_pa)
238 {
239 moal_handle *handle = (moal_handle *)pmoal;
240 pcie_service_card *card = handle->card;
241
242 if (!pbuf || !card)
243 return MLAN_STATUS_FAILURE;
244
245 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)
246 dma_free_coherent(&card->dev->dev, size, pbuf, buf_pa);
247 #else
248 pci_free_consistent(card->dev, size, pbuf, buf_pa);
249 #endif
250 atomic_dec(&handle->malloc_cons_count);
251 return MLAN_STATUS_SUCCESS;
252 }
253
254 /**
255 * @brief Map a block of memory to device
256 *
257 * @param pmoal Pointer to the MOAL context
258 * @param pbuf Pointer to the buffer to be mapped
259 * @param pbuf_pa Pointer to store the physical address of buffer
260 * @param size Size of the buffer to be mapped
261 * @param flag Flags for mapping IO
262 *
263 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
264 */
moal_map_memory(t_void * pmoal,t_u8 * pbuf,t_u64 * pbuf_pa,t_u32 size,t_u32 flag)265 mlan_status moal_map_memory(t_void *pmoal, t_u8 *pbuf, t_u64 *pbuf_pa,
266 t_u32 size, t_u32 flag)
267 {
268 moal_handle *handle = (moal_handle *)pmoal;
269 pcie_service_card *card = (pcie_service_card *)handle->card;
270
271 dma_addr_t dma;
272
273 if (!card)
274 return MLAN_STATUS_FAILURE;
275
276 /* Init memory to device */
277 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)
278 dma = dma_map_single(&card->dev->dev, pbuf, size, flag);
279 if (dma_mapping_error(&card->dev->dev, dma)) {
280 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
281 dma = pci_map_single(card->dev, pbuf, size, flag);
282 if (pci_dma_mapping_error(card->dev, dma)) {
283 #else
284 dma = pci_map_single(card->dev, pbuf, size, flag);
285 if (pci_dma_mapping_error(dma)) {
286 #endif
287 PRINTM(MERROR, "Tx ring: failed to dma_map_single\n");
288 return MLAN_STATUS_FAILURE;
289 }
290
291 *pbuf_pa = dma;
292 return MLAN_STATUS_SUCCESS;
293 }
294
295 /**
296 * @brief Unmap a block of memory from device
297 *
298 * @param pmoal Pointer to the MOAL context
299 * @param pbuf Pointer to the buffer to unmap
300 * @param buf_pa Physical address of buffer to unmap
301 * @param size Size of the buffer to unmap
302 * @param flag Flags for mapping IO
303 *
304 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
305 */
306 mlan_status moal_unmap_memory(t_void *pmoal, t_u8 *pbuf, t_u64 buf_pa,
307 t_u32 size, t_u32 flag)
308 {
309 moal_handle *handle = (moal_handle *)pmoal;
310 pcie_service_card *card = (pcie_service_card *)handle->card;
311
312 if (!card)
313 return MLAN_STATUS_FAILURE;
314
315 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)
316 dma_unmap_single(&card->dev->dev, buf_pa, size, flag);
317 #else
318 pci_unmap_single(card->dev, buf_pa, size, flag);
319 #endif
320
321 return MLAN_STATUS_SUCCESS;
322 }
323 #endif /* PCIE */
324
325 /**
326 * @brief Fill memory with constant byte
327 *
328 * @param pmoal Pointer to the MOAL context
329 * @param pmem Pointer to the memory area
330 * @param byte A constant byte
331 * @param num Number of bytes to fill
332 *
333 * @return Pointer to the memory area
334 */
335 t_void *moal_memset(t_void *pmoal, t_void *pmem, t_u8 byte, t_u32 num)
336 {
337 t_void *p = pmem;
338
339 if (pmem && num)
340 p = memset(pmem, byte, num);
341
342 return p;
343 }
344
345 /**
346 * @brief Copy memory from one area to another
347 *
348 * @param pmoal Pointer to the MOAL context
349 * @param pdest Pointer to the dest memory
350 * @param psrc Pointer to the src memory
351 * @param num Number of bytes to move
352 *
353 * @return Pointer to the dest memory
354 */
355 t_void *moal_memcpy(t_void *pmoal, t_void *pdest, const t_void *psrc, t_u32 num)
356 {
357 t_void *p = pdest;
358
359 if (pdest && psrc && num)
360 p = memcpy(pdest, psrc, num);
361
362 return p;
363 }
364
365 /**
366 * @brief Copy memory from one area to another
367 *
368 * @param pmoal Pointer to the MOAL context
369 * @param pdest Pointer to the dest memory
370 * @param psrc Pointer to the src memory
371 * @param num Number of bytes to move
372 * @param dest_size size of dest memory.
373 *
374 * @return Pointer to the dest memory
375 */
376 t_void *moal_memcpy_ext(t_void *pmoal, t_void *pdest, const t_void *psrc,
377 t_u32 num, t_u32 dest_size)
378 {
379 t_void *p = pdest;
380 if (pdest && psrc && num && dest_size)
381 p = memcpy(pdest, psrc, MIN(num, dest_size));
382
383 return p;
384 }
385
386 /**
387 * @brief Move memory from one area to another
388 *
389 * @param pmoal Pointer to the MOAL context
390 * @param pdest Pointer to the dest memory
391 * @param psrc Pointer to the src memory
392 * @param num Number of bytes to move
393 *
394 * @return Pointer to the dest memory
395 */
396 t_void *moal_memmove(t_void *pmoal, t_void *pdest, const t_void *psrc,
397 t_u32 num)
398 {
399 t_void *p = pdest;
400
401 if (pdest && psrc && num)
402 p = memmove(pdest, psrc, num);
403
404 return p;
405 }
406
407 /**
408 * @brief Compare two memory areas
409 *
410 * @param pmoal Pointer to the MOAL context
411 * @param pmem1 Pointer to the first memory
412 * @param pmem2 Pointer to the second memory
413 * @param num Number of bytes to compare
414 *
415 * @return Compare result returns by memcmp
416 */
417 t_s32 moal_memcmp(t_void *pmoal, const t_void *pmem1, const t_void *pmem2,
418 t_u32 num)
419 {
420 t_s32 result;
421
422 result = memcmp(pmem1, pmem2, num);
423
424 return result;
425 }
426
427 /**
428 * @brief Delay function
429 *
430 * @param pmoal Pointer to the MOAL context
431 * @param delay delay in micro-second
432 *
433 * @return N/A
434 */
435 t_void moal_udelay(t_void *pmoal, t_u32 delay)
436 {
437 if (delay >= 1000)
438 msleep(delay / 1000);
439 if (delay % 1000)
440 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
441 usleep_range(delay % 1000 - 1, delay % 1000);
442 #else
443 udelay(delay % 1000);
444 #endif
445 }
446
447 /**
448 * @brief usleep_range function
449 *
450 * @param pmoal Pointer to the MOAL context
451 * @param min_delay minimal delay in micro-second
452 * @param max_delay delay in micro-second
453 *
454 * @return N/A
455 */
456 t_void moal_usleep_range(t_void *pmoal, t_u32 min_delay, t_u32 max_delay)
457 {
458 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
459 usleep_range(min_delay, max_delay);
460 #endif
461 }
462 /**
463 * @brief Retrieves the current system time
464 *
465 * @param pmoal Pointer to the MOAL context
466 * @param psec Pointer to buf for the seconds of system time
467 * @param pusec Pointer to buf the micro seconds of system time
468 *
469 * @return MLAN_STATUS_SUCCESS
470 */
471 mlan_status moal_get_system_time(t_void *pmoal, t_u32 *psec, t_u32 *pusec)
472 {
473 wifi_timeval t;
474
475 woal_get_monotonic_time(&t);
476 *psec = t.time_sec;
477 *pusec = t.time_usec;
478
479 return MLAN_STATUS_SUCCESS;
480 }
481
482 /**
483 * @brief Retrieves the current boot time
484 *
485 * @param pmoal Pointer to the MOAL context
486 * @param pnsec Pointer to buf for the Nanoseconds of boot time
487 *
488 * @return MLAN_STATUS_SUCCESS
489 */
490 mlan_status moal_get_boot_ktime(t_void *pmoal, t_u64 *pnsec)
491 {
492 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
493 ktime_t time;
494
495 time = ktime_get_with_offset(TK_OFFS_BOOT);
496 *pnsec = *(t_u64 *)&(time);
497 #endif
498 return MLAN_STATUS_SUCCESS;
499 }
500
501 /**
502 * @brief Initializes the timer
503 *
504 * @param pmoal Pointer to the MOAL context
505 * @param pptimer Pointer to the timer
506 * @param callback Pointer to callback function
507 * @param pcontext Pointer to context
508 *
509 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
510 */
511 mlan_status moal_init_timer(t_void *pmoal, t_void **pptimer,
512 IN t_void (*callback)(t_void *pcontext),
513 t_void *pcontext)
514 {
515 moal_drv_timer *timer = NULL;
516 gfp_t mem_flag = (in_interrupt() || in_atomic() || irqs_disabled()) ?
517 GFP_ATOMIC :
518 GFP_KERNEL;
519
520 timer = kmalloc(sizeof(moal_drv_timer), mem_flag);
521 if (timer == NULL)
522 return MLAN_STATUS_FAILURE;
523 woal_initialize_timer(timer, callback, pcontext);
524 *pptimer = (t_void *)timer;
525
526 return MLAN_STATUS_SUCCESS;
527 }
528
529 /**
530 * @brief Free the timer
531 *
532 * @param pmoal Pointer to the MOAL context
533 * @param ptimer Pointer to the timer
534 *
535 * @return MLAN_STATUS_SUCCESS
536 */
537 mlan_status moal_free_timer(t_void *pmoal, t_void *ptimer)
538 {
539 moal_drv_timer *timer = (moal_drv_timer *)ptimer;
540
541 if (timer) {
542 if ((timer->timer_is_canceled == MFALSE) &&
543 timer->time_period) {
544 PRINTM(MWARN,
545 "mlan try to free timer without stop timer!\n");
546 woal_cancel_timer(timer);
547 }
548 kfree(timer);
549 }
550
551 return MLAN_STATUS_SUCCESS;
552 }
553
554 /**
555 * @brief Start the timer
556 *
557 * @param pmoal Pointer to the MOAL context
558 * @param ptimer Pointer to the timer
559 * @param periodic Periodic timer
560 * @param msec Timer value in milliseconds
561 *
562 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
563 */
564 mlan_status moal_start_timer(t_void *pmoal, t_void *ptimer, t_u8 periodic,
565 t_u32 msec)
566 {
567 if (!ptimer)
568 return MLAN_STATUS_FAILURE;
569
570 ((moal_drv_timer *)ptimer)->timer_is_periodic = periodic;
571 woal_mod_timer((moal_drv_timer *)ptimer, msec);
572
573 return MLAN_STATUS_SUCCESS;
574 }
575
576 /**
577 * @brief Stop the timer
578 *
579 * @param pmoal Pointer to the MOAL context
580 * @param ptimer Pointer to the timer
581 *
582 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
583 */
584 mlan_status moal_stop_timer(t_void *pmoal, t_void *ptimer)
585 {
586 if (!ptimer)
587 return MLAN_STATUS_FAILURE;
588 woal_cancel_timer((moal_drv_timer *)ptimer);
589
590 return MLAN_STATUS_SUCCESS;
591 }
592
593 /**
594 * @brief Initializes the lock
595 *
596 * @param pmoal Pointer to the MOAL context
597 * @param pplock Pointer to the lock
598 *
599 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
600 */
601 mlan_status moal_init_lock(t_void *pmoal, t_void **pplock)
602 {
603 moal_handle *handle = (moal_handle *)pmoal;
604 moal_lock *mlock = NULL;
605
606 mlock = kmalloc(sizeof(moal_lock), GFP_ATOMIC);
607 if (!mlock)
608 return MLAN_STATUS_FAILURE;
609 spin_lock_init(&mlock->lock);
610 *pplock = (t_void *)mlock;
611
612 atomic_inc(&handle->lock_count);
613
614 return MLAN_STATUS_SUCCESS;
615 }
616
617 /**
618 * @brief Free the lock
619 *
620 * @param pmoal Pointer to the MOAL context
621 * @param plock Lock
622 *
623 * @return MLAN_STATUS_SUCCESS
624 */
625 mlan_status moal_free_lock(t_void *pmoal, t_void *plock)
626 {
627 moal_handle *handle = (moal_handle *)pmoal;
628 moal_lock *mlock = plock;
629
630 kfree(mlock);
631 if (mlock)
632 atomic_dec(&handle->lock_count);
633
634 return MLAN_STATUS_SUCCESS;
635 }
636
637 /**
638 * @brief Request a spin lock
639 *
640 * @param pmoal Pointer to the MOAL context
641 * @param plock Pointer to the lock
642 *
643 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
644 */
645 mlan_status moal_spin_lock(t_void *pmoal, t_void *plock)
646 __acquires(&plock->lock)
647 {
648 moal_lock *mlock = plock;
649 unsigned long flags = 0;
650 spin_lock_irqsave(&mlock->lock, flags);
651 mlock->flags = flags;
652 return MLAN_STATUS_SUCCESS;
653 }
654
655 /**
656 * @brief Request a spin_unlock
657 *
658 * @param pmoal Pointer to the MOAL context
659 * @param plock Pointer to the lock
660 *
661 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
662 */
663 mlan_status moal_spin_unlock(t_void *pmoal, t_void *plock)
664 __releases(&plock->lock)
665 {
666 moal_lock *mlock = (moal_lock *)plock;
667 spin_unlock_irqrestore(&mlock->lock, mlock->flags);
668 return MLAN_STATUS_SUCCESS;
669 }
670
671 /**
672 * @brief This function collects AMSDU TP statistics.
673 *
674 * @param pmoal Pointer to the MOAL context
675 * @param amsdu_process_delay amsdu process time
676 * @param amsdu_copy_delay amsdu copy time
677 *
678 * @return N/A
679 */
680 void moal_amsdu_tp_accounting(t_void *pmoal, t_s32 amsdu_process_delay,
681 t_s32 amsdu_copy_delay)
682 {
683 moal_handle *handle = (moal_handle *)pmoal;
684 handle->tp_acnt.rx_amsdu_delay[handle->tp_acnt.rx_amsdu_index] =
685 amsdu_process_delay;
686 handle->tp_acnt.rx_amsdu_copy_delay[handle->tp_acnt.rx_amsdu_index] =
687 amsdu_copy_delay;
688 handle->tp_acnt.rx_amsdu_index++;
689 if (handle->tp_acnt.rx_amsdu_index >= TXRX_MAX_SAMPLE)
690 handle->tp_acnt.rx_amsdu_index = 0;
691 }
692
693 /**
694 * @brief This function collects TP statistics.
695 *
696 * @param pmoal Pointer to the MOAL context
697 * @param buf pointer to the buffer of a packet
698 * @param drop_point Drop pointer user set
699 *
700 * @return N/A
701 */
702 void moal_tp_accounting(t_void *pmoal, void *buf, t_u32 drop_point)
703 {
704 struct sk_buff *skb = NULL;
705 moal_handle *handle = (moal_handle *)pmoal;
706 pmlan_buffer pmbuf = (pmlan_buffer)buf;
707 t_s32 delay;
708 wifi_timeval t;
709
710 if (drop_point < MAX_TP_ACCOUNT_DROP_POINT_NUM) {
711 if (drop_point == 4) {
712 handle->tp_acnt.tx_bytes[drop_point] += pmbuf->data_len;
713 } else {
714 skb = (struct sk_buff *)buf;
715 handle->tp_acnt.tx_bytes[drop_point] += skb->len;
716 }
717 handle->tp_acnt.tx_packets[drop_point]++;
718 } else if (drop_point <= RX_DROP_P5) {
719 t_u16 rx_len = 0;
720 if (drop_point == RX_DROP_P1 || drop_point == RX_DROP_P2)
721 rx_len = pmbuf->data_len -
722 *((t_u16 *)(pmbuf->pbuf + pmbuf->data_offset) +
723 2); // remove rx_pkt_offset
724 else if (drop_point == RX_DROP_P3) // aggr pkt
725 rx_len = pmbuf->data_len;
726 else if (drop_point == RX_DROP_P4) { // before to kernel
727 skb = (struct sk_buff *)buf;
728 rx_len = skb->len;
729 }
730 handle->tp_acnt
731 .rx_bytes[drop_point - MAX_TP_ACCOUNT_DROP_POINT_NUM] +=
732 rx_len;
733 handle->tp_acnt.rx_packets[drop_point -
734 MAX_TP_ACCOUNT_DROP_POINT_NUM]++;
735 } else if (drop_point == RX_TIME_PKT) {
736 woal_get_monotonic_time(&t);
737 /* deque - pcie receive */
738 delay = (t_s32)(pmbuf->extra_ts_sec - pmbuf->in_ts_sec) *
739 1000000;
740 delay += (t_s32)(pmbuf->extra_ts_usec - pmbuf->in_ts_usec);
741 handle->tp_acnt.rx_delay1_driver[handle->tp_acnt.rx_index] =
742 delay;
743 /* before netif_rx - deque */
744 delay = (t_s32)(pmbuf->out_ts_sec - pmbuf->extra_ts_sec) *
745 1000000;
746 delay += (t_s32)(pmbuf->out_ts_usec - pmbuf->extra_ts_usec);
747 handle->tp_acnt.rx_delay2_driver[handle->tp_acnt.rx_index] =
748 delay;
749 /* netif_rx to netif_rx return */
750 delay = (t_s32)(t.time_sec - pmbuf->out_ts_sec) * 1000000;
751 delay += (t_s32)(t.time_usec - pmbuf->out_ts_usec);
752 handle->tp_acnt.rx_delay_kernel[handle->tp_acnt.rx_index] =
753 delay;
754 handle->tp_acnt.rx_index++;
755 if (handle->tp_acnt.rx_index >= TXRX_MAX_SAMPLE)
756 handle->tp_acnt.rx_index = 0;
757 } else if (drop_point == TX_TIME_PKT) {
758 delay = (t_s32)(pmbuf->out_ts_sec - pmbuf->in_ts_sec) * 1000000;
759 delay += (t_s32)(pmbuf->out_ts_usec - pmbuf->in_ts_usec);
760 handle->tp_acnt.tx_delay_driver[handle->tp_acnt.tx_index] =
761 delay;
762 handle->tp_acnt.tx_index++;
763 if (handle->tp_acnt.tx_index >= TXRX_MAX_SAMPLE)
764 handle->tp_acnt.tx_index = 0;
765 }
766 }
767
768 void moal_tp_accounting_rx_param(t_void *pmoal, unsigned int type,
769 unsigned int rsvd1)
770 {
771 moal_handle *phandle = (moal_handle *)pmoal;
772 switch (type) {
773 case 0: // Rx interrupt
774 phandle->tp_acnt.rx_intr_cnt++;
775 break;
776 case 1: // rx_pkts_queued
777 phandle->tp_acnt.rx_pending = rsvd1;
778 break;
779 case 2: // paused
780 phandle->tp_acnt.rx_paused_cnt++;
781 break;
782 case 3: // tx interrupt count
783 phandle->tp_acnt.tx_intr_cnt++;
784 break;
785 case 4: // rx amsdu count
786 phandle->tp_acnt.rx_amsdu_cnt++;
787 phandle->tp_acnt.rx_amsdu_pkt_cnt += rsvd1;
788 break;
789 case 5: // tx amsdu count
790 phandle->tp_acnt.tx_amsdu_cnt++;
791 phandle->tp_acnt.tx_amsdu_pkt_cnt += rsvd1;
792 break;
793 case 6: // rxbd rdptr full count
794 phandle->tp_acnt.rx_rdptr_full_cnt++;
795 break;
796 case 7: // tx hard xmit skb realloc count
797 phandle->tp_acnt.tx_xmit_skb_realloc_cnt++;
798 break;
799 case 8: // tx stop queue count
800 phandle->tp_acnt.tx_stop_queue_cnt++;
801 break;
802
803 default:
804 break;
805 }
806 }
807
808 /**
809 * @brief This function reads one block of firmware data from MOAL
810 *
811 * @param pmoal Pointer to the MOAL context
812 * @param offset Offset from where the data will be copied
813 * @param len Length to be copied
814 * @param pbuf Buffer where the data will be copied
815 *
816 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
817 */
818 mlan_status moal_get_fw_data(t_void *pmoal, t_u32 offset, t_u32 len, t_u8 *pbuf)
819 {
820 moal_handle *handle = (moal_handle *)pmoal;
821
822 if (!pbuf || !len || !handle->firmware)
823 return MLAN_STATUS_FAILURE;
824
825 if (offset + len > handle->firmware->size)
826 return MLAN_STATUS_FAILURE;
827
828 moal_memcpy_ext(handle, pbuf, handle->firmware->data + offset, len,
829 len);
830
831 return MLAN_STATUS_SUCCESS;
832 }
833
834 /**
835 * @brief This function get vdll data from moal
836 *
837 * @param pmoal Pointer to the MOAL context
838 * @param len Length to be copied
839 * @param pbuf Buffer where the data will be copied
840 *
841 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
842 */
843 mlan_status moal_get_vdll_data(t_void *pmoal, t_u32 len, t_u8 *pbuf)
844 {
845 moal_handle *handle = (moal_handle *)pmoal;
846 mlan_status status = MLAN_STATUS_FAILURE;
847 t_u32 offset = 0;
848 t_u8 req_fw = MFALSE;
849
850 if (!handle->firmware) {
851 req_fw = MTRUE;
852 woal_vdll_req_fw(handle);
853 }
854
855 if (handle->firmware) {
856 if (len < handle->firmware->size) {
857 offset = handle->firmware->size - len;
858 moal_memcpy_ext(handle, pbuf,
859 handle->firmware->data + offset, len,
860 len);
861 status = MLAN_STATUS_SUCCESS;
862 } else {
863 PRINTM(MERROR, "Invalid VDLL length = %d, fw_len=%d\n",
864 len, (int)handle->firmware->size);
865 }
866 if (req_fw) {
867 release_firmware(handle->firmware);
868 handle->firmware = NULL;
869 }
870 }
871 return status;
872 }
873
874 /**
875 * @brief This function is called when MLAN completes the initialization
876 * firmware.
877 *
878 * @param pmoal Pointer to the MOAL context
879 * @param status The status code for mlan_init_fw request
880 * @param phw pointer to mlan_hw_info
881 * @param ptbl pointer to mplan_bss_tbl
882 * @return MLAN_STATUS_SUCCESS
883 */
884 mlan_status moal_get_hw_spec_complete(t_void *pmoal, mlan_status status,
885 mlan_hw_info *phw, pmlan_bss_tbl ptbl)
886 {
887 moal_handle *handle = (moal_handle *)pmoal;
888 int i;
889 t_u32 drv_mode = handle->params.drv_mode;
890
891 ENTER();
892 if (status == MLAN_STATUS_SUCCESS) {
893 PRINTM(MCMND, "Get Hw Spec done, fw_cap=0x%x\n", phw->fw_cap);
894 #ifdef PCIE9098
895 /** Special/Temporary handling to manage the driver version
896 * string to identify Seahawk/AW690 (skyhawk based) based on
897 * fw_cap_ext value set by Fw */
898 if (phw->fw_cap_ext & MBIT(31) &&
899 IS_PCIE9098(handle->card_type)) {
900 moal_memcpy_ext(handle, driver_version, CARD_PCIEAW690,
901 strlen(CARD_PCIEAW690),
902 strlen(driver_version));
903 moal_memcpy_ext(handle,
904 driver_version + strlen(INTF_CARDTYPE) +
905 strlen(KERN_VERSION),
906 V17, strlen(V17),
907 strlen(driver_version) -
908 strlen(INTF_CARDTYPE) -
909 strlen(KERN_VERSION));
910 moal_memcpy_ext(handle, handle->driver_version,
911 driver_version, strlen(driver_version),
912 MLAN_MAX_VER_STR_LEN - 1);
913 }
914 #endif
915 /** FW should only enable DFS on one mac */
916 if (!(phw->fw_cap & FW_CAPINFO_ZERO_DFS))
917 handle->params.drv_mode &= ~DRV_MODE_DFS;
918
919 if (!(phw->fw_cap & FW_CAPINFO_80211BGA))
920 handle->params.drv_mode &= ~DRV_MODE_WLAN;
921 if (!handle->params.drv_mode ||
922 MLAN_STATUS_SUCCESS !=
923 woal_update_drv_tbl(handle,
924 handle->params.drv_mode)) {
925 PRINTM(MERROR,
926 "Get_hw_spec_complete: Fail to update drv_tbl\n");
927 LEAVE();
928 return MLAN_STATUS_FAILURE;
929 }
930 memset(ptbl, 0, sizeof(mlan_bss_tbl));
931 for (i = 0; i < handle->drv_mode.intf_num; i++) {
932 ptbl->bss_attr[i].bss_type =
933 handle->drv_mode.bss_attr[i].bss_type;
934 ptbl->bss_attr[i].frame_type =
935 handle->drv_mode.bss_attr[i].frame_type;
936 ptbl->bss_attr[i].active =
937 handle->drv_mode.bss_attr[i].active;
938 ptbl->bss_attr[i].bss_priority =
939 handle->drv_mode.bss_attr[i].bss_priority;
940 ptbl->bss_attr[i].bss_num =
941 handle->drv_mode.bss_attr[i].bss_num;
942 ptbl->bss_attr[i].bss_virtual =
943 handle->drv_mode.bss_attr[i].bss_virtual;
944 }
945 PRINTM(MCMND, "org_drv_mode=0x%x drv_mode=0x%x\n", drv_mode,
946 handle->params.drv_mode);
947 }
948 LEAVE();
949 return MLAN_STATUS_SUCCESS;
950 }
951
952 /**
953 * @brief This function is called when MLAN completes the initialization
954 * firmware.
955 *
956 * @param pmoal Pointer to the MOAL context
957 * @param status The status code for mlan_init_fw request
958 *
959 * @return MLAN_STATUS_SUCCESS
960 */
961 mlan_status moal_init_fw_complete(t_void *pmoal, mlan_status status)
962 {
963 moal_handle *handle = (moal_handle *)pmoal;
964 ENTER();
965 if (status == MLAN_STATUS_SUCCESS)
966 handle->hardware_status = HardwareStatusReady;
967 handle->init_wait_q_woken = MTRUE;
968 wake_up(&handle->init_wait_q);
969 LEAVE();
970 return MLAN_STATUS_SUCCESS;
971 }
972
973 /**
974 * @brief This function is called when MLAN shutdown firmware is completed.
975 *
976 * @param pmoal Pointer to the MOAL context
977 * @param status The status code for mlan_shutdown request
978 *
979 * @return MLAN_STATUS_SUCCESS
980 */
981 mlan_status moal_shutdown_fw_complete(t_void *pmoal, mlan_status status)
982 {
983 moal_handle *handle = (moal_handle *)pmoal;
984 ENTER();
985 handle->hardware_status = HardwareStatusNotReady;
986 handle->init_wait_q_woken = MTRUE;
987 wake_up_interruptible(&handle->init_wait_q);
988 LEAVE();
989 return MLAN_STATUS_SUCCESS;
990 }
991
992 /**
993 * @brief This function is called when an MLAN IOCTL is completed.
994 *
995 * @param pmoal Pointer to the MOAL context
996 * @param pioctl_req pointer to structure mlan_ioctl_req
997 * @param status The status code for mlan_ioctl request
998 *
999 * @return MLAN_STATUS_SUCCESS
1000 */
1001 mlan_status moal_ioctl_complete(t_void *pmoal, pmlan_ioctl_req pioctl_req,
1002 mlan_status status)
1003 {
1004 moal_handle *handle = (moal_handle *)pmoal;
1005 moal_private *priv = NULL;
1006 wait_queue *wait;
1007 unsigned long flags = 0;
1008 ENTER();
1009
1010 if (!atomic_read(&handle->ioctl_pending))
1011 PRINTM(MERROR, "ERR: Unexpected IOCTL completed: %p\n",
1012 pioctl_req);
1013 else
1014 atomic_dec(&handle->ioctl_pending);
1015 priv = woal_bss_index_to_priv(handle, pioctl_req->bss_index);
1016 if (!priv) {
1017 PRINTM(MERROR,
1018 "IOCTL %p complete with NULL priv, bss_index=%d\n",
1019 pioctl_req, pioctl_req->bss_index);
1020 LEAVE();
1021 return MLAN_STATUS_SUCCESS;
1022 }
1023
1024 if (status != MLAN_STATUS_SUCCESS && status != MLAN_STATUS_COMPLETE)
1025 PRINTM(MERROR,
1026 "IOCTL failed: %p id=0x%x, sub_id=0x%x action=%d, status_code=0x%x\n",
1027 pioctl_req, pioctl_req->req_id,
1028 (*(t_u32 *)pioctl_req->pbuf), (int)pioctl_req->action,
1029 pioctl_req->status_code);
1030 else
1031 PRINTM(MIOCTL,
1032 "IOCTL completed: %p id=0x%x sub_id=0x%x, action=%d, status=%d, status_code=0x%x\n",
1033 pioctl_req, pioctl_req->req_id,
1034 (*(t_u32 *)pioctl_req->pbuf), (int)pioctl_req->action,
1035 status, pioctl_req->status_code);
1036
1037 spin_lock_irqsave(&handle->driver_lock, flags);
1038 wait = (wait_queue *)pioctl_req->reserved_1;
1039 if (wait) {
1040 wait->condition = MTRUE;
1041 wait->status = status;
1042 if (wait->wait_timeout) {
1043 wake_up(&wait->wait);
1044 } else {
1045 if ((status != MLAN_STATUS_SUCCESS) &&
1046 (pioctl_req->status_code ==
1047 MLAN_ERROR_CMD_TIMEOUT)) {
1048 PRINTM(MERROR, "IOCTL: command timeout\n");
1049 } else {
1050 wake_up_interruptible(&wait->wait);
1051 }
1052 }
1053 spin_unlock_irqrestore(&handle->driver_lock, flags);
1054 } else {
1055 spin_unlock_irqrestore(&handle->driver_lock, flags);
1056 if ((status == MLAN_STATUS_SUCCESS) &&
1057 (pioctl_req->action == MLAN_ACT_GET))
1058 woal_process_ioctl_resp(priv, pioctl_req);
1059 kfree(pioctl_req);
1060 }
1061 LEAVE();
1062 return MLAN_STATUS_SUCCESS;
1063 }
1064
1065 /**
1066 * @brief This function allocates mlan_buffer.
1067 *
1068 * @param pmoal Pointer to the MOAL context
1069 * @param size allocation size requested
1070 * @param pmbuf pointer to pointer to the allocated buffer
1071 *
1072 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1073 */
1074 mlan_status moal_alloc_mlan_buffer(t_void *pmoal, t_u32 size,
1075 pmlan_buffer *pmbuf)
1076 {
1077 *pmbuf = woal_alloc_mlan_buffer((moal_handle *)pmoal, size);
1078 if (NULL == *pmbuf)
1079 return MLAN_STATUS_FAILURE;
1080 return MLAN_STATUS_SUCCESS;
1081 }
1082
1083 /**
1084 * @brief This function frees mlan_buffer.
1085 *
1086 * @param pmoal Pointer to the MOAL context
1087 * @param pmbuf pointer to buffer to be freed
1088 *
1089 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1090 */
1091 mlan_status moal_free_mlan_buffer(t_void *pmoal, pmlan_buffer pmbuf)
1092 {
1093 if (!pmbuf)
1094 return MLAN_STATUS_FAILURE;
1095 woal_free_mlan_buffer((moal_handle *)pmoal, pmbuf);
1096 return MLAN_STATUS_SUCCESS;
1097 }
1098
1099 /**
1100 * @brief This function is called when MLAN complete send data packet.
1101 *
1102 * @param pmoal Pointer to the MOAL context
1103 * @param pmbuf Pointer to the mlan buffer structure
1104 * @param status The status code for mlan_send_packet request
1105 *
1106 * @return MLAN_STATUS_SUCCESS
1107 */
1108 mlan_status moal_send_packet_complete(t_void *pmoal, pmlan_buffer pmbuf,
1109 mlan_status status)
1110 {
1111 moal_private *priv = NULL;
1112 moal_handle *handle = (moal_handle *)pmoal;
1113 struct sk_buff *skb = NULL;
1114 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
1115 t_u32 index = 0;
1116 #endif
1117
1118 ENTER();
1119 if (pmbuf && pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) {
1120 woal_free_mlan_buffer(handle, pmbuf);
1121 atomic_dec(&handle->tx_pending);
1122 goto done;
1123 }
1124 if (pmbuf) {
1125 priv = woal_bss_index_to_priv(pmoal, pmbuf->bss_index);
1126 skb = (struct sk_buff *)pmbuf->pdesc;
1127 if (priv) {
1128 woal_set_trans_start(priv->netdev);
1129 if (skb) {
1130 if (status == MLAN_STATUS_SUCCESS) {
1131 priv->stats.tx_packets++;
1132 priv->stats.tx_bytes += skb->len;
1133 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
1134 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1135 woal_packet_fate_monitor(
1136 priv, PACKET_TYPE_TX,
1137 TX_PKT_FATE_SENT,
1138 FRAME_TYPE_ETHERNET_II, 0, 0,
1139 skb->data, skb->data_len);
1140 #endif
1141 #endif
1142 } else {
1143 priv->stats.tx_errors++;
1144 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
1145 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1146 woal_packet_fate_monitor(
1147 priv, PACKET_TYPE_TX,
1148 TX_PKT_FATE_DRV_DROP_OTHER,
1149 FRAME_TYPE_ETHERNET_II, 0, 0,
1150 skb->data, skb->data_len);
1151 #endif
1152 #endif
1153 }
1154 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
1155 index = skb_get_queue_mapping(skb);
1156 if (index < 4) {
1157 atomic_dec(&handle->tx_pending);
1158 if (atomic_dec_return(
1159 &priv->wmm_tx_pending[index]) ==
1160 LOW_TX_PENDING) {
1161 struct netdev_queue *txq =
1162 netdev_get_tx_queue(
1163 priv->netdev,
1164 index);
1165 if (netif_tx_queue_stopped(
1166 txq)) {
1167 netif_tx_wake_queue(
1168 txq);
1169 PRINTM(MINFO,
1170 "Wakeup Kernel Queue:%d\n",
1171 index);
1172 }
1173 }
1174 } else {
1175 PRINTM(MERROR,
1176 "Invalid queue index for skb\n");
1177 }
1178 #else /*#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)*/
1179 if (atomic_dec_return(&handle->tx_pending) <
1180 LOW_TX_PENDING) {
1181 int i;
1182 for (i = 0; i < handle->priv_num; i++) {
1183 #ifdef STA_SUPPORT
1184 if ((GET_BSS_ROLE(
1185 handle->priv[i]) ==
1186 MLAN_BSS_ROLE_STA) &&
1187 (handle->priv[i]
1188 ->media_connected ||
1189 priv->is_adhoc_link_sensed)) {
1190 woal_wake_queue(
1191 handle->priv[i]
1192 ->netdev);
1193 }
1194 #endif
1195 #ifdef UAP_SUPPORT
1196 if ((GET_BSS_ROLE(
1197 handle->priv[i]) ==
1198 MLAN_BSS_ROLE_UAP) &&
1199 (handle->priv[i]
1200 ->media_connected)) {
1201 woal_wake_queue(
1202 handle->priv[i]
1203 ->netdev);
1204 }
1205 #endif
1206 }
1207 }
1208 #endif /*#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)*/
1209 }
1210 }
1211 if (skb)
1212 dev_kfree_skb_any(skb);
1213 }
1214
1215 done:
1216 if ((atomic_read(&handle->tx_pending) == 0) &&
1217 !is_zero_timeval(handle->tx_time_start)) {
1218 woal_get_monotonic_time(&handle->tx_time_end);
1219 handle->tx_time +=
1220 (t_u64)(timeval_to_usec(handle->tx_time_end) -
1221 timeval_to_usec(handle->tx_time_start));
1222 PRINTM(MINFO,
1223 "%s : start_timeval=%d:%d end_timeval=%d:%d inter=%llu tx_time=%llu\n",
1224 __func__, handle->tx_time_start.time_sec,
1225 handle->tx_time_start.time_usec,
1226 handle->tx_time_end.time_sec,
1227 handle->tx_time_end.time_usec,
1228 (t_u64)(timeval_to_usec(handle->tx_time_end) -
1229 timeval_to_usec(handle->tx_time_start)),
1230 handle->tx_time);
1231 handle->tx_time_start.time_sec = 0;
1232 handle->tx_time_start.time_usec = 0;
1233 }
1234 LEAVE();
1235 return MLAN_STATUS_SUCCESS;
1236 }
1237
1238 #ifdef USB
1239 /**
1240 * @brief This function is called when MLAN complete receiving
1241 * data/event/command
1242 *
1243 * @param pmoal Pointer to the MOAL context
1244 * @param pmbuf Pointer to the mlan buffer structure
1245 * @param port Port number for receive
1246 * @param status The status code for mlan_receive request
1247 *
1248 * @return MLAN_STATUS_SUCCESS
1249 */
1250 mlan_status moal_recv_complete(t_void *pmoal, pmlan_buffer pmbuf, t_u32 port,
1251 mlan_status status)
1252 {
1253 moal_private *priv = NULL;
1254 moal_handle *handle = (moal_handle *)pmoal;
1255 struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
1256 ENTER();
1257
1258 if ((pmbuf && (pmbuf->flags & MLAN_BUF_FLAG_RX_DEAGGR)) || !pmbuf)
1259 atomic_dec(&handle->rx_pending);
1260
1261 if (pmbuf) {
1262 priv = woal_bss_index_to_priv(handle, pmbuf->bss_index);
1263 if (priv && (pmbuf->buf_type == MLAN_BUF_TYPE_DATA) &&
1264 (status == MLAN_STATUS_FAILURE)) {
1265 priv->stats.rx_dropped++;
1266 }
1267 /* Reuse the buffer in case of command/event */
1268 if (port == cardp->rx_cmd_ep)
1269 woal_submit_rx_urb(handle, port);
1270 else {
1271 woal_free_mlan_buffer(handle, pmbuf);
1272 if ((atomic_read(&handle->rx_pending) <
1273 USB_LOW_RX_PENDING) &&
1274 atomic_read(&cardp->rx_data_urb_pending) <
1275 MVUSB_RX_DATA_URB)
1276 woal_usb_submit_rx_data_urbs(handle);
1277 }
1278 } else if (port == cardp->rx_data_ep) {
1279 if ((atomic_read(&handle->rx_pending) < USB_LOW_RX_PENDING) &&
1280 atomic_read(&cardp->rx_data_urb_pending) <
1281 MVUSB_RX_DATA_URB)
1282 woal_usb_submit_rx_data_urbs(handle);
1283 }
1284 LEAVE();
1285 return MLAN_STATUS_SUCCESS;
1286 }
1287
1288 /**
1289 * @brief This function write a command/data packet to card.
1290 *
1291 * @param pmoal Pointer to the MOAL context
1292 * @param pmbuf Pointer to the mlan buffer structure
1293 * @param port Port number for sent
1294 *
1295 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE or
1296 * MLAN_STATUS_PENDING or MLAN_STATUS_RESOURCE
1297 */
1298 mlan_status moal_write_data_async(t_void *pmoal, pmlan_buffer pmbuf, t_u32 port)
1299 {
1300 moal_handle *handle = (moal_handle *)pmoal;
1301 mlan_status ret = MLAN_STATUS_SUCCESS;
1302 ENTER();
1303 if (handle->is_suspended == MTRUE) {
1304 PRINTM(MERROR,
1305 "write_data_async is not allowed while suspended\n");
1306 LEAVE();
1307 return MLAN_STATUS_FAILURE;
1308 }
1309 ret = woal_write_data_async((moal_handle *)pmoal, pmbuf, (t_u8)port);
1310 LEAVE();
1311 return ret;
1312 }
1313 #endif /* USB */
1314
1315 /**
1316 * @brief This function write a command/data packet to card.
1317 * This function blocks the call until it finishes
1318 *
1319 * @param pmoal Pointer to the MOAL context
1320 * @param pmbuf Pointer to the mlan buffer structure
1321 * @param port Port number for sent
1322 * @param timeout Timeout value in milliseconds (if 0 the wait is forever)
1323 *
1324 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1325 */
1326 mlan_status moal_write_data_sync(t_void *pmoal, pmlan_buffer pmbuf, t_u32 port,
1327 t_u32 timeout)
1328 {
1329 moal_handle *handle = (moal_handle *)pmoal;
1330 return handle->ops.write_data_sync(handle, pmbuf, port, timeout);
1331 }
1332
1333 /**
1334 * @brief This function read data packet/event/command from card.
1335 * This function blocks the call until it finish
1336 *
1337 * @param pmoal Pointer to the MOAL context
1338 * @param pmbuf Pointer to the mlan buffer structure
1339 * @param port Port number for read
1340 * @param timeout Timeout value in milliseconds (if 0 the wait is forever)
1341 *
1342 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1343 */
1344 mlan_status moal_read_data_sync(t_void *pmoal, pmlan_buffer pmbuf, t_u32 port,
1345 t_u32 timeout)
1346 {
1347 moal_handle *handle = (moal_handle *)pmoal;
1348 return handle->ops.read_data_sync(handle, pmbuf, port, timeout);
1349 }
1350
1351 #if defined(SDIO) || defined(PCIE)
1352 /**
1353 * @brief This function writes data into card register.
1354 *
1355 * @param pmoal Pointer to the MOAL context
1356 * @param reg register offset
1357 * @param data value
1358 *
1359 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1360 */
1361 mlan_status moal_write_reg(t_void *pmoal, t_u32 reg, t_u32 data)
1362 {
1363 int ret = MLAN_STATUS_FAILURE;
1364 moal_handle *handle = (moal_handle *)pmoal;
1365 if (handle->ops.write_reg)
1366 ret = handle->ops.write_reg(handle, reg, data);
1367 return ret;
1368 }
1369
1370 /**
1371 * @brief This function reads data from card register.
1372 *
1373 * @param pmoal Pointer to the MOAL context
1374 * @param reg register offset
1375 * @param data value
1376 *
1377 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1378 */
1379 mlan_status moal_read_reg(t_void *pmoal, t_u32 reg, t_u32 *data)
1380 {
1381 int ret = MLAN_STATUS_FAILURE;
1382 moal_handle *handle = (moal_handle *)pmoal;
1383 if (handle->ops.read_reg)
1384 ret = handle->ops.read_reg(handle, reg, data);
1385 return ret;
1386 }
1387
1388 #endif /* SDIO || PCIE */
1389
1390 #if defined(STA_CFG80211) && defined(UAP_CFG80211)
1391 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1392 /**
1393 * @brief This function uploads the packet to the network stack monitor
1394 * interface
1395 *
1396 * @param handle Pointer to the MOAL context
1397 * @param pmbuf Pointer to mlan_buffer
1398 *
1399 * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING/MLAN_STATUS_FAILURE
1400 */
1401 static mlan_status moal_recv_packet_to_mon_if(moal_handle *handle,
1402 pmlan_buffer pmbuf)
1403 {
1404 mlan_status status = MLAN_STATUS_SUCCESS;
1405 struct sk_buff *skb = NULL;
1406 struct radiotap_header *rth = NULL;
1407 radiotap_info rt_info = {};
1408 t_u8 format = 0;
1409 t_u8 bw = 0;
1410 t_u8 gi = 0;
1411 t_u8 ldpc = 0;
1412 t_u8 chan_num;
1413 t_u8 band = 0;
1414 struct ieee80211_hdr *dot11_hdr = NULL;
1415 t_u8 *payload = NULL;
1416 t_u32 vht_sig1 = 0;
1417 t_u32 vht_sig2 = 0;
1418 ENTER();
1419 if (!pmbuf->pdesc) {
1420 LEAVE();
1421 return status;
1422 }
1423
1424 skb = (struct sk_buff *)pmbuf->pdesc;
1425
1426 if ((handle->mon_if) && netif_running(handle->mon_if->mon_ndev)) {
1427 if (handle->mon_if->radiotap_enabled) {
1428 if (skb_headroom(skb) < sizeof(*rth)) {
1429 PRINTM(MERROR,
1430 "%s No space to add Radio TAP header\n",
1431 __func__);
1432 status = MLAN_STATUS_FAILURE;
1433 handle->mon_if->stats.rx_dropped++;
1434 goto done;
1435 }
1436 dot11_hdr =
1437 (struct ieee80211_hdr *)(pmbuf->pbuf +
1438 pmbuf->data_offset);
1439 moal_memcpy_ext(handle, &rt_info,
1440 pmbuf->pbuf + pmbuf->data_offset -
1441 sizeof(rt_info),
1442 sizeof(rt_info), sizeof(rt_info));
1443 ldpc = (rt_info.rate_info.rate_info & 0x20) >> 5;
1444 format = (rt_info.rate_info.rate_info & 0x18) >> 3;
1445 bw = (rt_info.rate_info.rate_info & 0x06) >> 1;
1446 gi = rt_info.rate_info.rate_info & 0x01;
1447 skb_push(skb, sizeof(*rth));
1448 rth = (struct radiotap_header *)skb->data;
1449 memset(skb->data, 0, sizeof(*rth));
1450 rth->hdr.it_version = PKTHDR_RADIOTAP_VERSION;
1451 rth->hdr.it_pad = 0;
1452 rth->hdr.it_len = cpu_to_le16(sizeof(*rth));
1453 rth->hdr.it_present = cpu_to_le32(
1454 (1 << IEEE80211_RADIOTAP_TSFT) |
1455 (1 << IEEE80211_RADIOTAP_FLAGS) |
1456 (1 << IEEE80211_RADIOTAP_CHANNEL) |
1457 (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
1458 (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
1459 (1 << IEEE80211_RADIOTAP_ANTENNA));
1460 /** Timstamp */
1461 rth->body.timestamp = woal_cpu_to_le64(jiffies);
1462 /** Flags */
1463 rth->body.flags = (rt_info.extra_info.flags &
1464 ~(RADIOTAP_FLAGS_USE_SGI_HT |
1465 RADIOTAP_FLAGS_WITH_FRAGMENT |
1466 RADIOTAP_FLAGS_WEP_ENCRYPTION |
1467 RADIOTAP_FLAGS_FAILED_FCS_CHECK));
1468 /** reverse fail fcs, 1 means pass FCS in FW, but means
1469 * fail FCS in radiotap */
1470 rth->body.flags |= (~rt_info.extra_info.flags) &
1471 RADIOTAP_FLAGS_FAILED_FCS_CHECK;
1472 if ((format == MLAN_RATE_FORMAT_HT) && (gi == 1))
1473 rth->body.flags |= RADIOTAP_FLAGS_USE_SGI_HT;
1474 if (ieee80211_is_mgmt(dot11_hdr->frame_control) ||
1475 ieee80211_is_data(dot11_hdr->frame_control)) {
1476 if ((ieee80211_has_morefrags(
1477 dot11_hdr->frame_control)) ||
1478 (!ieee80211_is_first_frag(
1479 dot11_hdr->seq_ctrl))) {
1480 rth->body.flags |=
1481 RADIOTAP_FLAGS_WITH_FRAGMENT;
1482 }
1483 }
1484 if (ieee80211_is_data(dot11_hdr->frame_control) &&
1485 ieee80211_has_protected(dot11_hdr->frame_control)) {
1486 payload = (t_u8 *)dot11_hdr +
1487 ieee80211_hdrlen(
1488 dot11_hdr->frame_control);
1489 if (!(*(payload + 3) & 0x20)) /** ExtIV bit
1490 shall be 0 for
1491 WEP frame */
1492 rth->body.flags |=
1493 RADIOTAP_FLAGS_WEP_ENCRYPTION;
1494 }
1495 /** Rate, t_u8 only apply for LG mode */
1496 if (format == MLAN_RATE_FORMAT_LG) {
1497 rth->hdr.it_present |= cpu_to_le32(
1498 1 << IEEE80211_RADIOTAP_RATE);
1499 rth->body.rate = rt_info.rate_info.bitrate;
1500 }
1501 /** Channel */
1502 rth->body.channel.flags = 0;
1503 if (rt_info.chan_num)
1504 chan_num = rt_info.chan_num;
1505 else
1506 chan_num =
1507 handle->mon_if->band_chan_cfg.channel;
1508 band = (chan_num <= 14) ? IEEE80211_BAND_2GHZ :
1509 IEEE80211_BAND_5GHZ;
1510 rth->body.channel.frequency = woal_cpu_to_le16(
1511 ieee80211_channel_to_frequency(chan_num, band));
1512 rth->body.channel.flags |=
1513 woal_cpu_to_le16((band == IEEE80211_BAND_2GHZ) ?
1514 CHANNEL_FLAGS_2GHZ :
1515 CHANNEL_FLAGS_5GHZ);
1516 if (rth->body.channel.flags &
1517 woal_cpu_to_le16(CHANNEL_FLAGS_2GHZ))
1518 rth->body.channel.flags |= woal_cpu_to_le16(
1519 CHANNEL_FLAGS_DYNAMIC_CCK_OFDM);
1520 else
1521 rth->body.channel.flags |=
1522 woal_cpu_to_le16(CHANNEL_FLAGS_OFDM);
1523 if (handle->mon_if->chandef.chan &&
1524 (handle->mon_if->chandef.chan->flags &
1525 (IEEE80211_CHAN_PASSIVE_SCAN |
1526 IEEE80211_CHAN_RADAR)))
1527 rth->body.channel.flags |= woal_cpu_to_le16(
1528 CHANNEL_FLAGS_ONLY_PASSIVSCAN_ALLOW);
1529 /** Antenna */
1530 rth->body.antenna_signal = -(rt_info.nf - rt_info.snr);
1531 rth->body.antenna_noise = -rt_info.nf;
1532 /* Convert FW antenna value to radiotap spec */
1533 rth->body.antenna = (t_u16)rt_info.antenna >> 1;
1534 /** MCS */
1535 if (format == MLAN_RATE_FORMAT_HT) {
1536 rth->hdr.it_present |= cpu_to_le32(
1537 1 << IEEE80211_RADIOTAP_MCS);
1538 rth->body.u.mcs.known =
1539 rt_info.extra_info.mcs_known;
1540 rth->body.u.mcs.flags =
1541 rt_info.extra_info.mcs_flags;
1542 /** MCS mcs */
1543 rth->body.u.mcs.known |=
1544 MCS_KNOWN_MCS_INDEX_KNOWN;
1545 rth->body.u.mcs.mcs =
1546 rt_info.rate_info.mcs_index;
1547 /** MCS bw */
1548 rth->body.u.mcs.known |= MCS_KNOWN_BANDWIDTH;
1549 rth->body.u.mcs.flags &= ~(0x03); /** Clear,
1550 20MHz as
1551 default */
1552 if (bw == 1)
1553 rth->body.u.mcs.flags |= RX_BW_40;
1554 /** MCS gi */
1555 rth->body.u.mcs.known |=
1556 MCS_KNOWN_GUARD_INTERVAL;
1557 rth->body.u.mcs.flags &= ~(1 << 2);
1558 if (gi)
1559 rth->body.u.mcs.flags |= gi << 2;
1560 /** MCS FEC */
1561 rth->body.u.mcs.known |= MCS_KNOWN_FEC_TYPE;
1562 rth->body.u.mcs.flags &= ~(1 << 4);
1563 if (ldpc)
1564 rth->body.u.mcs.flags |= ldpc << 4;
1565 }
1566 /** VHT */
1567 if (format == MLAN_RATE_FORMAT_VHT) {
1568 vht_sig1 = rt_info.extra_info.vht_sig1;
1569 vht_sig2 = rt_info.extra_info.vht_sig2;
1570 /** Present Flag */
1571 rth->hdr.it_present |= cpu_to_le32(
1572 1 << IEEE80211_RADIOTAP_VHT);
1573 /** STBC */
1574 rth->body.u.vht.known |=
1575 woal_cpu_to_le16(VHT_KNOWN_STBC);
1576 if (vht_sig1 & MBIT(3))
1577 rth->body.u.vht.flags |= VHT_FLAG_STBC;
1578 /** TXOP_PS_NA */
1579 /** TODO: Not support now */
1580 /** GI */
1581 rth->body.u.vht.known |=
1582 woal_cpu_to_le16(VHT_KNOWN_GI);
1583 if (vht_sig2 & MBIT(0))
1584 rth->body.u.vht.flags |= VHT_FLAG_SGI;
1585 /** SGI NSYM DIS */
1586 rth->body.u.vht.known |= woal_cpu_to_le16(
1587 VHT_KNOWN_SGI_NSYM_DIS);
1588 if (vht_sig2 & MBIT(1))
1589 rth->body.u.vht.flags |=
1590 VHT_FLAG_SGI_NSYM_M10_9;
1591 /** LDPC_EXTRA_OFDM_SYM */
1592 /** TODO: Not support now */
1593 /** BEAMFORMED */
1594 rth->body.u.vht.known |=
1595 woal_cpu_to_le16(VHT_KNOWN_BEAMFORMED);
1596 if (vht_sig2 & MBIT(8))
1597 rth->body.u.vht.flags |=
1598 VHT_FLAG_BEAMFORMED;
1599 /** BANDWIDTH */
1600 rth->body.u.vht.known |=
1601 woal_cpu_to_le16(VHT_KNOWN_BANDWIDTH);
1602 if (bw == 1)
1603 rth->body.u.vht.bandwidth = RX_BW_40;
1604 else if (bw == 2)
1605 rth->body.u.vht.bandwidth = RX_BW_80;
1606 /** GROUP_ID */
1607 rth->body.u.vht.known |=
1608 woal_cpu_to_le16(VHT_KNOWN_GROUP_ID);
1609 rth->body.u.vht.group_id =
1610 (vht_sig1 & (0x3F0)) >> 4;
1611 /** PARTIAL_AID */
1612 /** TODO: Not support now */
1613 /** mcs_nss */
1614 rth->body.u.vht.mcs_nss[0] = vht_sig2 & (0xF0);
1615 /* Convert FW NSS value to radiotap spec */
1616 rth->body.u.vht.mcs_nss[0] |=
1617 ((vht_sig1 & (0x1C00)) >> 10) + 1;
1618 /** coding */
1619 if (vht_sig2 & MBIT(2))
1620 rth->body.u.vht.coding |=
1621 VHT_CODING_LDPC_USER0;
1622 }
1623 }
1624 skb_set_mac_header(skb, 0);
1625 skb->ip_summed = CHECKSUM_UNNECESSARY;
1626 skb->pkt_type = PACKET_OTHERHOST;
1627 skb->protocol = htons(ETH_P_802_2);
1628 memset(skb->cb, 0, sizeof(skb->cb));
1629 skb->dev = handle->mon_if->mon_ndev;
1630
1631 handle->mon_if->stats.rx_bytes += skb->len;
1632 handle->mon_if->stats.rx_packets++;
1633
1634 if (in_interrupt())
1635 netif_rx(skb);
1636 else
1637 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)
1638 netif_rx(skb);
1639 #else
1640 netif_rx_ni(skb);
1641 #endif
1642
1643 status = MLAN_STATUS_PENDING;
1644 }
1645
1646 done:
1647
1648 LEAVE();
1649 return status;
1650 }
1651 #endif
1652 #endif
1653
1654 /**
1655 * @brief This function uploads amsdu packet to the network stack
1656 *
1657 * @param pmoal Pointer to the MOAL context
1658 * @param pmbuf Pointer to the mlan buffer structure
1659 *
1660 * @return MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE
1661 */
1662 mlan_status moal_recv_amsdu_packet(t_void *pmoal, pmlan_buffer pmbuf)
1663 {
1664 mlan_status status = MLAN_STATUS_FAILURE;
1665 struct sk_buff *skb = NULL;
1666 struct sk_buff *frame = NULL;
1667 int remaining;
1668 const struct ethhdr *eth;
1669 u8 dst[ETH_ALEN], src[ETH_ALEN];
1670 moal_handle *handle = (moal_handle *)pmoal;
1671 moal_private *priv = NULL;
1672 struct net_device *netdev = NULL;
1673 u8 *payload;
1674 mlan_buffer mbuf;
1675 t_u8 drop = 0;
1676 t_u8 rfc1042_eth_hdr[MLAN_MAC_ADDR_LENGTH] = {0xaa, 0xaa, 0x03,
1677 0x00, 0x00, 0x00};
1678
1679 wifi_timeval t1, t2;
1680 t_s32 delay;
1681 t_u32 in_ts_sec = 0;
1682 t_u32 in_ts_usec = 0;
1683
1684 ENTER();
1685 if (!pmbuf) {
1686 PRINTM(MERROR, "%s: pmbuf is null\n", __func__);
1687 goto done;
1688 }
1689
1690 memset(&mbuf, 0, sizeof(mlan_buffer));
1691 mbuf.bss_index = pmbuf->bss_index;
1692
1693 priv = woal_bss_index_to_priv(pmoal, pmbuf->bss_index);
1694 if (priv == NULL) {
1695 PRINTM(MERROR, "%s: priv is null\n", __func__);
1696 goto done;
1697 }
1698 netdev = priv->netdev;
1699 skb = (struct sk_buff *)pmbuf->pdesc;
1700 if (!skb)
1701 goto done;
1702
1703 skb_reserve(skb, pmbuf->data_offset);
1704 if (skb_tailroom(skb) < (int)pmbuf->data_len) {
1705 PRINTM(MERROR, "skb overflow: tail room=%d, data_len=%d\n",
1706 skb_tailroom(skb), pmbuf->data_len);
1707 goto done;
1708 }
1709 skb_put(skb, pmbuf->data_len);
1710
1711 // rx_trace 8
1712 if (handle->tp_acnt.on) {
1713 moal_tp_accounting(pmoal, skb, RX_DROP_P4);
1714 woal_get_monotonic_time(&t1);
1715 in_ts_sec = t1.time_sec;
1716 in_ts_usec = t1.time_usec;
1717 if (pmbuf->in_ts_sec) {
1718 pmbuf->out_ts_sec = t1.time_sec;
1719 pmbuf->out_ts_usec = t1.time_usec;
1720 }
1721 }
1722 if (handle->tp_acnt.drop_point == RX_DROP_P4) {
1723 status = MLAN_STATUS_PENDING;
1724 dev_kfree_skb(skb);
1725 goto done;
1726 }
1727
1728 while (skb != frame) {
1729 __be16 len;
1730 u8 padding;
1731 unsigned int subframe_len;
1732 eth = (struct ethhdr *)skb->data;
1733 len = ntohs(eth->h_proto);
1734 subframe_len = sizeof(struct ethhdr) + len;
1735 remaining = skb->len;
1736
1737 if (subframe_len > remaining) {
1738 PRINTM(MERROR,
1739 "Error in len: remaining = %d, subframe_len = %d\n",
1740 remaining, subframe_len);
1741 break;
1742 }
1743 memcpy(dst, eth->h_dest, ETH_ALEN);
1744 memcpy(src, eth->h_source, ETH_ALEN);
1745
1746 padding = (4 - subframe_len) & 0x3;
1747
1748 skb_pull(skb, sizeof(struct ethhdr));
1749
1750 if (remaining <= (subframe_len + padding)) {
1751 frame = skb;
1752 status = MLAN_STATUS_PENDING;
1753 } else {
1754 frame = skb_clone(skb, GFP_ATOMIC);
1755 skb_trim(frame, len);
1756 eth = (struct ethhdr *)skb_pull(skb, len + padding);
1757 if (!eth) {
1758 PRINTM(MERROR, "Invalid amsdu packet\n");
1759 break;
1760 }
1761 }
1762 skb_reset_network_header(frame);
1763 frame->dev = netdev;
1764 frame->priority = skb->priority;
1765 payload = frame->data;
1766 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
1767 if (ether_addr_equal(payload, rfc1042_eth_hdr)) {
1768 #else
1769 if (!memcmp(payload, rfc1042_eth_hdr,
1770 sizeof(rfc1042_eth_hdr))) {
1771 #endif
1772 /* Remove RFC1042 */
1773 skb_pull(frame, 6);
1774 memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
1775 memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
1776 } else {
1777 memcpy(skb_push(frame, sizeof(__be16)), &len,
1778 sizeof(__be16));
1779 memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN);
1780 memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
1781 }
1782 mbuf.pbuf = frame->data;
1783 mbuf.data_len = frame->len;
1784 mlan_process_deaggr_pkt(handle->pmlan_adapter, &mbuf, &drop);
1785 if (drop) {
1786 dev_kfree_skb(frame);
1787 continue;
1788 }
1789 frame->protocol = eth_type_trans(frame, netdev);
1790 frame->ip_summed = CHECKSUM_NONE;
1791 if (in_interrupt())
1792 netif_rx(frame);
1793 else {
1794 if (atomic_read(&handle->rx_pending) >
1795 MAX_RX_PENDING_THRHLD)
1796 netif_rx(frame);
1797 else {
1798 if (handle->params.net_rx == MTRUE) {
1799 local_bh_disable();
1800 netif_receive_skb(frame);
1801 local_bh_enable();
1802 } else {
1803 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)
1804 netif_rx(frame);
1805 #else
1806 netif_rx_ni(frame);
1807 #endif
1808 }
1809 }
1810 }
1811 }
1812 if (handle->tp_acnt.on) {
1813 if (pmbuf->in_ts_sec)
1814 moal_tp_accounting(handle, pmbuf, RX_TIME_PKT);
1815
1816 woal_get_monotonic_time(&t2);
1817 delay = (t_s32)(t2.time_sec - in_ts_sec) * 1000000;
1818 delay += (t_s32)(t2.time_usec - in_ts_usec);
1819 moal_amsdu_tp_accounting(pmoal, delay, 0);
1820 }
1821 done:
1822 if (status == MLAN_STATUS_PENDING)
1823 atomic_dec(&handle->mbufalloc_count);
1824 LEAVE();
1825 return status;
1826 }
1827
1828 /**
1829 * @brief This function uploads the packet to the network stack
1830 *
1831 * @param pmoal Pointer to the MOAL context
1832 * @param pmbuf Pointer to the mlan buffer structure
1833 *
1834 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1835 */
1836 mlan_status moal_recv_packet(t_void *pmoal, pmlan_buffer pmbuf)
1837 {
1838 mlan_status status = MLAN_STATUS_SUCCESS;
1839 moal_private *priv = NULL;
1840 struct sk_buff *skb = NULL;
1841 moal_handle *handle = (moal_handle *)pmoal;
1842 #if defined(USB) || defined(PCIE)
1843 t_u32 max_rx_data_size = MLAN_RX_DATA_BUF_SIZE;
1844 #endif
1845 dot11_rxcontrol rxcontrol;
1846 t_u8 rx_info_flag = MFALSE;
1847 int j;
1848 struct ethhdr *ethh = NULL;
1849 struct net_device *netdev = NULL;
1850
1851 ENTER();
1852 if (pmbuf) {
1853 #ifdef USB
1854 #ifdef STA_SUPPORT
1855 if (IS_USB(handle->card_type)) {
1856 struct usb_card_rec *cardp =
1857 (struct usb_card_rec *)handle->card;
1858 if (cardp->rx_deaggr_ctrl.enable) {
1859 max_rx_data_size =
1860 cardp->rx_deaggr_ctrl.aggr_max;
1861 if (cardp->rx_deaggr_ctrl.aggr_mode ==
1862 MLAN_USB_AGGR_MODE_NUM) {
1863 max_rx_data_size *=
1864 MAX(MLAN_USB_MAX_PKT_SIZE,
1865 cardp->rx_deaggr_ctrl
1866 .aggr_align);
1867 max_rx_data_size =
1868 MAX(max_rx_data_size,
1869 MLAN_RX_DATA_BUF_SIZE);
1870 }
1871 }
1872 }
1873 #endif
1874 #endif
1875
1876 priv = woal_bss_index_to_priv(pmoal, pmbuf->bss_index);
1877 skb = (struct sk_buff *)pmbuf->pdesc;
1878 if (priv) {
1879 if (skb) {
1880 skb_reserve(skb, pmbuf->data_offset);
1881 if (skb_tailroom(skb) < (int)pmbuf->data_len) {
1882 PRINTM(MERROR,
1883 "skb overflow: tail room=%d, data_len=%d\n",
1884 skb_tailroom(skb),
1885 pmbuf->data_len);
1886 status = MLAN_STATUS_FAILURE;
1887 priv->stats.rx_dropped++;
1888 goto done;
1889 }
1890 skb_put(skb, pmbuf->data_len);
1891 #if defined(STA_CFG80211) && defined(UAP_CFG80211)
1892 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1893 if (pmbuf->flags & MLAN_BUF_FLAG_NET_MONITOR) {
1894 status = moal_recv_packet_to_mon_if(
1895 pmoal, pmbuf);
1896 if (status == MLAN_STATUS_PENDING)
1897 atomic_dec(
1898 &handle->mbufalloc_count);
1899 goto done;
1900 }
1901 #endif
1902 #endif
1903 pmbuf->pdesc = NULL;
1904 pmbuf->pbuf = NULL;
1905 pmbuf->data_offset = pmbuf->data_len = 0;
1906 /* pkt been submit to kernel, no need to
1907 * free by mlan*/
1908 status = MLAN_STATUS_PENDING;
1909 atomic_dec(&handle->mbufalloc_count);
1910 } else {
1911 PRINTM(MERROR, "%s without skb attach!!!\n",
1912 __func__);
1913 #if defined(STA_CFG80211) && defined(UAP_CFG80211)
1914 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1915 /** drop the packet without skb in
1916 * monitor mode */
1917 if (pmbuf->flags & MLAN_BUF_FLAG_NET_MONITOR) {
1918 PRINTM(MINFO,
1919 "%s Drop packet without skb\n",
1920 __func__);
1921 status = MLAN_STATUS_FAILURE;
1922 priv->stats.rx_dropped++;
1923 goto done;
1924 }
1925 #endif
1926 #endif
1927 skb = dev_alloc_skb(pmbuf->data_len +
1928 MLAN_NET_IP_ALIGN);
1929 if (!skb) {
1930 PRINTM(MERROR, "%s fail to alloc skb\n",
1931 __func__);
1932 status = MLAN_STATUS_FAILURE;
1933 priv->stats.rx_dropped++;
1934 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
1935 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1936 woal_packet_fate_monitor(
1937 priv, PACKET_TYPE_RX,
1938 RX_PKT_FATE_DRV_DROP_NOBUFS,
1939 FRAME_TYPE_ETHERNET_II, 0, 0,
1940 (t_u8 *)(pmbuf->pbuf +
1941 pmbuf->data_offset),
1942 pmbuf->data_len);
1943 #endif
1944 #endif
1945 goto done;
1946 }
1947 skb_reserve(skb, MLAN_NET_IP_ALIGN);
1948 moal_memcpy_ext(handle, skb->data,
1949 (t_u8 *)(pmbuf->pbuf +
1950 pmbuf->data_offset),
1951 pmbuf->data_len,
1952 pmbuf->data_len);
1953 skb_put(skb, pmbuf->data_len);
1954 }
1955 ethh = (struct ethhdr *)(skb->data);
1956 if (ntohs(ethh->h_proto) == ETH_P_PAE)
1957 PRINTM(MEVENT,
1958 "wlan: %s Rx EAPOL pkt from " MACSTR
1959 "\n",
1960 priv->netdev->name,
1961 MAC2STR(ethh->h_source));
1962 if (!netdev)
1963 netdev = priv->netdev;
1964 skb->dev = netdev;
1965 skb->protocol = eth_type_trans(skb, netdev);
1966 skb->ip_summed = CHECKSUM_NONE;
1967
1968 #if defined(USB) || defined(PCIE)
1969 /* This is only required only in case of 11n and
1970 USB as we alloc if(skb_tailroom(skb) <
1971 pmbuf->data_len){ PRINTM(MERROR,"skb overflow:
1972 tail room=%d, data_len\n", skb_tailroom(skb),
1973 pmbuf->data_len); status = MLAN_STATUS_FAILURE;
1974 priv->stats.rx_dropped++;
1975 goto done;
1976 }
1977 * a buffer of 4K only if its 11N (to be able to
1978 receive 4K AMSDU
1979 * packets). In case of SD we allocate buffers
1980 based on the size
1981 * of packet and hence this is not needed.
1982 */
1983 /* Modifying the truesize here as our allocation
1984 * for each skb is 4K but we only receive 2K
1985 * packets and this cause the kernel to start
1986 * dropping packets in case where application
1987 * has allocated buffer based on 2K size i.e. if
1988 * there a 64K packet received (in IP fragments
1989 * and application allocates 64K to receive this
1990 * packet but this packet would almost double up
1991 * because we allocate each 1.5K fragment in 4K
1992 * and pass it up. As soon as the 64K limit hits
1993 * kernel will start to drop rest of the
1994 * fragments. Currently we fail the
1995 * Filesndl-ht.scr script for UDP, hence this
1996 * fix
1997 */
1998 if (!IS_SD(priv->phandle->card_type)) {
1999 if (skb->truesize > max_rx_data_size)
2000 skb->truesize +=
2001 (skb->len - max_rx_data_size);
2002 }
2003 #endif
2004 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
2005 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2006 if (!woal_filter_packet(priv, skb->data, skb->len, 0)) {
2007 PRINTM(MEVENT, "drop filtered packet %s\n",
2008 priv->netdev->name);
2009 status = MLAN_STATUS_FAILURE;
2010 priv->stats.rx_dropped++;
2011 woal_packet_fate_monitor(
2012 priv, PACKET_TYPE_RX,
2013 RX_PKT_FATE_DRV_DROP_FILTER,
2014 FRAME_TYPE_ETHERNET_II, 0, 0, skb->data,
2015 skb->len);
2016 dev_kfree_skb(skb);
2017 goto done;
2018 }
2019 #endif
2020 #endif
2021 priv->stats.rx_bytes += skb->len;
2022 priv->stats.rx_packets++;
2023 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
2024 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2025 woal_packet_fate_monitor(priv, PACKET_TYPE_RX,
2026 RX_PKT_FATE_SUCCESS,
2027 FRAME_TYPE_ETHERNET_II, 0, 0,
2028 skb->data, skb->len);
2029 #endif
2030 #endif
2031 #ifdef ANDROID_KERNEL
2032 if (handle->params.wakelock_timeout) {
2033 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
2034 __pm_wakeup_event(
2035 &handle->ws,
2036 handle->params.wakelock_timeout);
2037 #else
2038 wake_lock_timeout(
2039 &handle->wake_lock,
2040 msecs_to_jiffies(
2041 handle->params
2042 .wakelock_timeout));
2043 #endif
2044 }
2045 #endif
2046 if (priv->rx_protocols.protocol_num) {
2047 for (j = 0; j < priv->rx_protocols.protocol_num;
2048 j++) {
2049 if (htons((__force t_u16)
2050 skb->protocol) ==
2051 priv->rx_protocols.protocols[j])
2052 rx_info_flag = MTRUE;
2053 }
2054 }
2055 if (rx_info_flag &&
2056 (skb_tailroom(skb) > (int)sizeof(rxcontrol))) {
2057 memset(&rxcontrol, 0, sizeof(dot11_rxcontrol));
2058 rxcontrol.datarate = pmbuf->u.rx_info.data_rate;
2059 rxcontrol.channel = pmbuf->u.rx_info.channel;
2060 rxcontrol.antenna = pmbuf->u.rx_info.antenna;
2061 rxcontrol.rssi = pmbuf->u.rx_info.rssi;
2062 skb_put(skb, sizeof(dot11_rxcontrol));
2063 memmove(skb->data + sizeof(dot11_rxcontrol),
2064 skb->data,
2065 skb->len - sizeof(dot11_rxcontrol));
2066 moal_memcpy_ext(handle, skb->data, &rxcontrol,
2067 sizeof(dot11_rxcontrol),
2068 sizeof(dot11_rxcontrol));
2069 }
2070 // rx_trace 8
2071 if (priv->phandle->tp_acnt.on) {
2072 wifi_timeval t;
2073 moal_tp_accounting(handle, skb, RX_DROP_P4);
2074 if (pmbuf && pmbuf->in_ts_sec) {
2075 woal_get_monotonic_time(&t);
2076 pmbuf->out_ts_sec = t.time_sec;
2077 pmbuf->out_ts_usec = t.time_usec;
2078 }
2079 }
2080 if (priv->phandle->tp_acnt.drop_point == RX_DROP_P4) {
2081 status = MLAN_STATUS_PENDING;
2082 dev_kfree_skb(skb);
2083 } else if (in_interrupt())
2084 netif_rx(skb);
2085 else {
2086 if (atomic_read(&handle->rx_pending) >
2087 MAX_RX_PENDING_THRHLD)
2088 netif_rx(skb);
2089 else {
2090 if (handle->params.net_rx == MTRUE) {
2091 local_bh_disable();
2092 netif_receive_skb(skb);
2093 local_bh_enable();
2094 } else {
2095 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)
2096 netif_rx(skb);
2097 #else
2098 netif_rx_ni(skb);
2099 #endif
2100 }
2101 }
2102 }
2103 if (priv->phandle->tp_acnt.on) {
2104 if (pmbuf && pmbuf->in_ts_sec)
2105 moal_tp_accounting(handle, pmbuf,
2106 RX_TIME_PKT);
2107 }
2108 }
2109 }
2110 done:
2111 LEAVE();
2112 return status;
2113 }
2114
2115 #if defined(PCIE) || defined(SDIO)
2116 void woal_request_busfreq_pmqos_add(t_void *handle)
2117 {
2118 moal_handle *pmhandle = (moal_handle *)handle;
2119 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 70)
2120 #ifdef IMX_SUPPORT
2121 if (IS_PCIE(pmhandle->card_type)) {
2122 request_bus_freq(BUS_FREQ_HIGH);
2123 }
2124 #endif
2125 #endif
2126 if (moal_extflg_isset(pmhandle, EXT_PMQOS)) {
2127 #if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 6, 0)
2128 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
2129 #ifdef IMX_SUPPORT
2130 if (!pm_qos_request_active(&pmhandle->woal_pm_qos_req))
2131 pm_qos_add_request(&pmhandle->woal_pm_qos_req,
2132 PM_QOS_CPU_DMA_LATENCY, 0);
2133 else
2134 PRINTM(MERROR, "PM-QOS request already active\n");
2135 #endif
2136 #endif
2137 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)
2138 #ifdef IMX_SUPPORT
2139 if (!cpu_latency_qos_request_active(&pmhandle->woal_pm_qos_req))
2140 cpu_latency_qos_add_request(&pmhandle->woal_pm_qos_req,
2141 0);
2142 else
2143 PRINTM(MERROR, "PM-QOS request already active\n");
2144 #endif
2145 #endif
2146 }
2147 return;
2148 }
2149
2150 void woal_release_busfreq_pmqos_remove(t_void *handle)
2151 {
2152 moal_handle *pmhandle = (moal_handle *)handle;
2153 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 70)
2154 #ifdef IMX_SUPPORT
2155 if (IS_PCIE(pmhandle->card_type)) {
2156 release_bus_freq(BUS_FREQ_HIGH);
2157 }
2158 #endif
2159 #endif
2160
2161 if (moal_extflg_isset(pmhandle, EXT_PMQOS)) {
2162 #if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 6, 0)
2163 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
2164 #ifdef IMX_SUPPORT
2165 if (pm_qos_request_active(&pmhandle->woal_pm_qos_req))
2166 pm_qos_remove_request(&pmhandle->woal_pm_qos_req);
2167 else
2168 PRINTM(MERROR, "PM-QOS request already removed\n");
2169 #endif
2170 #endif
2171 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)
2172 #ifdef IMX_SUPPORT
2173 if (cpu_latency_qos_request_active(&pmhandle->woal_pm_qos_req))
2174 cpu_latency_qos_remove_request(
2175 &pmhandle->woal_pm_qos_req);
2176 else
2177 PRINTM(MERROR, "PM-QOS request already removed\n");
2178 #endif
2179 #endif
2180 }
2181 return;
2182 }
2183 #endif /*defined(PCIE) || defined(SDIO)*/
2184
2185 /**
2186 * @brief This function checks media_connected state for
2187 * BSS types UAP/STA/P2P_GO/GC
2188 *
2189 * @param pmoal Pointer to the MOAL context
2190 *
2191 */
2192 int woal_check_media_connected(t_void *pmoal)
2193 {
2194 int i;
2195 moal_handle *pmhandle = (moal_handle *)pmoal;
2196 moal_private *pmpriv = NULL;
2197 for (i = 0; i < pmhandle->priv_num; i++) {
2198 pmpriv = pmhandle->priv[i];
2199 if (!pmpriv)
2200 continue;
2201 if (pmpriv->media_connected == MTRUE) {
2202 return MTRUE;
2203 }
2204 }
2205 return MFALSE;
2206 }
2207
2208 /**
2209 * @brief This function checks connect and disconnect
2210 * events for BSS types UAP/STA/P2P_GO/GC
2211 *
2212 * @param pmoal Pointer to the MOAL context
2213 *
2214 */
2215 void moal_connection_status_check_pmqos(t_void *pmoal)
2216 {
2217 moal_handle *pmhandle = (moal_handle *)pmoal;
2218 if ((woal_check_media_connected(pmoal) == MTRUE)) {
2219 if (pmhandle->request_pm == MFALSE) {
2220 pmhandle->request_pm = MTRUE;
2221 #if defined(PCIE) || defined(SDIO)
2222 woal_request_busfreq_pmqos_add(pmhandle);
2223 #endif
2224 }
2225 } else {
2226 if (pmhandle->request_pm == MTRUE) {
2227 pmhandle->request_pm = MFALSE;
2228 #if defined(PCIE) || defined(SDIO)
2229 woal_release_busfreq_pmqos_remove(pmhandle);
2230 #endif
2231 }
2232 }
2233 }
2234
2235 #ifdef UAP_SUPPORT
2236 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
2237 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
2238 /**
2239 * @brief Handle RX MGMT PKT event
2240 *
2241 * @param priv A pointer moal_private structure
2242 * @param pkt A pointer to pkt
2243 * @param len length of pkt
2244 *
2245 * @return N/A
2246 */
2247 static void woal_rx_mgmt_pkt_event(moal_private *priv, t_u8 *pkt, t_u16 len)
2248 {
2249 struct woal_event *evt;
2250 unsigned long flags;
2251 moal_handle *handle = priv->phandle;
2252
2253 evt = kzalloc(sizeof(struct woal_event), GFP_ATOMIC);
2254 if (evt) {
2255 evt->priv = priv;
2256 evt->type = WOAL_EVENT_RX_MGMT_PKT;
2257 evt->evt.event_len = len;
2258 moal_memcpy_ext(priv->phandle, evt->evt.event_buf, pkt,
2259 evt->evt.event_len, sizeof(evt->evt.event_buf));
2260 INIT_LIST_HEAD(&evt->link);
2261 spin_lock_irqsave(&handle->evt_lock, flags);
2262 list_add_tail(&evt->link, &handle->evt_queue);
2263 spin_unlock_irqrestore(&handle->evt_lock, flags);
2264 queue_work(handle->evt_workqueue, &handle->evt_work);
2265 }
2266 }
2267 #endif
2268 #endif
2269 #endif
2270
2271 /**
2272 * @brief This function handles event receive
2273 *
2274 * @param pmoal Pointer to the MOAL context
2275 * @param pmevent Pointer to the mlan event structure
2276 *
2277 * @return MLAN_STATUS_SUCCESS
2278 */
2279 mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent)
2280 {
2281 #ifdef STA_SUPPORT
2282 int custom_len = 0;
2283 #ifdef STA_CFG80211
2284 unsigned long flags;
2285 #endif
2286 #endif
2287 moal_private *priv = NULL;
2288 #if defined(STA_SUPPORT) || defined(UAP_SUPPORT)
2289 moal_private *pmpriv = NULL;
2290 #endif
2291 #if defined(STA_WEXT) || defined(UAP_WEXT)
2292 #if defined(STA_SUPPORT) || defined(UAP_WEXT)
2293 #if defined(UAP_SUPPORT) || defined(STA_WEXT)
2294 union iwreq_data wrqu;
2295 #endif
2296 #endif
2297 #endif
2298 mlan_ds_ps_info pm_info;
2299 moal_handle *handle = (moal_handle *)pmoal;
2300 moal_handle *ref_handle = NULL;
2301
2302 #ifdef STA_CFG80211
2303 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2304 t_u8 enable = 1;
2305 #endif
2306 t_u8 *req_ie = NULL;
2307 t_u16 ie_len = 0;
2308 apinfo *pinfo = NULL, *req_tlv = NULL;
2309 MrvlIEtypesHeader_t *tlv = NULL;
2310 t_u16 tlv_type = 0, tlv_len = 0, tlv_buf_left = 0;
2311 #endif
2312 #ifdef STA_CFG80211
2313 t_u8 hw_test;
2314 #endif
2315 int cfg80211_wext;
2316
2317 #ifdef STA_CFG80211
2318 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2319 struct cfg80211_roam_info *roam_info = NULL;
2320 #endif
2321 #endif
2322 t_u16 csi_len;
2323 #ifdef STA_CFG80211
2324 t_u8 channel_status;
2325 moal_private *remain_priv = NULL;
2326 #endif
2327 #if defined(UAP_CFG80211) || defined(STA_CFG80211)
2328 chan_band_info *pchan_info = NULL;
2329 #endif
2330 t_u8 radar_detected;
2331 t_u8 bandwidth;
2332 t_u8 event_buf[64];
2333 t_u8 radar_chan;
2334 #ifdef UAP_CFG80211
2335 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2336 moal_private *cfg_priv = NULL;
2337 #endif
2338 #endif
2339 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
2340 #ifdef UAP_CFG80211
2341 unsigned long wait_time, wait_time_ms, timeout;
2342 #endif
2343 #endif
2344
2345 t_u8 auto_fw_dump = MFALSE;
2346 ENTER();
2347 if (pmevent->event_id == MLAN_EVENT_ID_FW_DUMP_INFO) {
2348 if (!handle->is_fw_dump_timer_set) {
2349 PRINTM(MMSG, "FW trigger fw dump\n");
2350 handle->is_fw_dump_timer_set = MTRUE;
2351 woal_mod_timer(&handle->fw_dump_timer, MOAL_TIMER_5S);
2352 }
2353 woal_store_firmware_dump(pmoal, pmevent);
2354 handle->driver_status = MTRUE;
2355 wifi_status = WIFI_STATUS_FW_DUMP;
2356 ref_handle = (moal_handle *)handle->pref_mac;
2357 if (ref_handle)
2358 ref_handle->driver_status = MTRUE;
2359 goto done;
2360 }
2361 if ((pmevent->event_id != MLAN_EVENT_ID_DRV_DEFER_RX_WORK) &&
2362 (pmevent->event_id != MLAN_EVENT_ID_DRV_DEFER_HANDLING) &&
2363 (pmevent->event_id != MLAN_EVENT_ID_DRV_MGMT_FRAME))
2364 PRINTM(MEVENT, "event id:0x%x\n", pmevent->event_id);
2365 #if defined(PCIE)
2366 if (pmevent->event_id == MLAN_EVENT_ID_SSU_DUMP_FILE) {
2367 goto done;
2368 }
2369 #endif /* SSU_SUPPORT */
2370 if (pmevent->event_id == MLAN_EVENT_ID_STORE_HOST_CMD_RESP) {
2371 goto done;
2372 }
2373 priv = woal_bss_index_to_priv(pmoal, pmevent->bss_index);
2374 if (priv == NULL) {
2375 PRINTM(MERROR, "%s: priv is null\n", __func__);
2376 goto done;
2377 }
2378 if (priv->netdev == NULL) {
2379 PRINTM(MERROR, "%s: netdev is null\n", __func__);
2380 goto done;
2381 }
2382
2383 cfg80211_wext = priv->phandle->params.cfg80211_wext;
2384 #ifdef STA_CFG80211
2385 hw_test = moal_extflg_isset(pmoal, EXT_HW_TEST);
2386 #endif
2387 switch (pmevent->event_id) {
2388 #ifdef STA_SUPPORT
2389 case MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED:
2390 priv->is_adhoc_link_sensed = MTRUE;
2391 if (!netif_carrier_ok(priv->netdev))
2392 netif_carrier_on(priv->netdev);
2393 woal_wake_queue(priv->netdev);
2394 #ifdef STA_WEXT
2395 if (IS_STA_WEXT(cfg80211_wext))
2396 woal_send_iwevcustom_event(priv,
2397 CUS_EVT_ADHOC_LINK_SENSED);
2398 #endif
2399 woal_broadcast_event(priv, CUS_EVT_ADHOC_LINK_SENSED,
2400 strlen(CUS_EVT_ADHOC_LINK_SENSED));
2401 break;
2402
2403 case MLAN_EVENT_ID_FW_ADHOC_LINK_LOST:
2404 woal_stop_queue(priv->netdev);
2405 if (netif_carrier_ok(priv->netdev))
2406 netif_carrier_off(priv->netdev);
2407 priv->is_adhoc_link_sensed = MFALSE;
2408 #ifdef STA_WEXT
2409 if (IS_STA_WEXT(cfg80211_wext))
2410 woal_send_iwevcustom_event(priv,
2411 CUS_EVT_ADHOC_LINK_LOST);
2412 #endif
2413 woal_broadcast_event(priv, CUS_EVT_ADHOC_LINK_LOST,
2414 strlen(CUS_EVT_ADHOC_LINK_LOST));
2415 break;
2416
2417 case MLAN_EVENT_ID_DRV_CONNECTED:
2418 #ifdef STA_WEXT
2419 if (IS_STA_WEXT(cfg80211_wext) &&
2420 pmevent->event_len == ETH_ALEN) {
2421 memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
2422 moal_memcpy_ext(priv->phandle, wrqu.ap_addr.sa_data,
2423 pmevent->event_buf, ETH_ALEN,
2424 sizeof(wrqu.ap_addr.sa_data));
2425 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2426 wireless_send_event(priv->netdev, SIOCGIWAP, &wrqu,
2427 NULL);
2428 }
2429 #endif
2430 #ifdef STA_CFG80211
2431 if (IS_STA_CFG80211(cfg80211_wext)) {
2432 moal_memcpy_ext(priv->phandle, priv->cfg_bssid,
2433 pmevent->event_buf, ETH_ALEN, ETH_ALEN);
2434 woal_set_scan_time(priv, ACTIVE_SCAN_CHAN_TIME,
2435 PASSIVE_SCAN_CHAN_TIME,
2436 MIN_SPECIFIC_SCAN_CHAN_TIME);
2437 }
2438 #endif
2439 custom_len = strlen(CUS_EVT_AP_CONNECTED);
2440 memmove(pmevent->event_buf + custom_len, pmevent->event_buf,
2441 pmevent->event_len);
2442 moal_memcpy_ext(priv->phandle, pmevent->event_buf,
2443 CUS_EVT_AP_CONNECTED, custom_len, custom_len);
2444 pmevent->event_len += custom_len;
2445 woal_broadcast_event(priv, pmevent->event_buf,
2446 pmevent->event_len);
2447 woal_update_dscp_mapping(priv);
2448 priv->media_connected = MTRUE;
2449 if (!netif_carrier_ok(priv->netdev))
2450 netif_carrier_on(priv->netdev);
2451 woal_wake_queue(priv->netdev);
2452 moal_connection_status_check_pmqos(pmoal);
2453 break;
2454
2455 case MLAN_EVENT_ID_DRV_ASSOC_SUCC_LOGGER:
2456 case MLAN_EVENT_ID_DRV_ASSOC_FAILURE_LOGGER:
2457 case MLAN_EVENT_ID_DRV_DISCONNECT_LOGGER:
2458 #ifdef STA_CFG80211
2459 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2460 if (IS_STA_CFG80211(cfg80211_wext))
2461 woal_ring_event_logger(priv, VERBOSE_RING_ID, pmevent);
2462 #endif
2463 #endif
2464 break;
2465
2466 case MLAN_EVENT_ID_DRV_SCAN_REPORT:
2467 PRINTM(MINFO, "Scan report\n");
2468
2469 if (priv->report_scan_result) {
2470 priv->report_scan_result = MFALSE;
2471 #ifdef STA_CFG80211
2472 if (IS_STA_CFG80211(cfg80211_wext)) {
2473 if (priv->phandle->scan_request) {
2474 PRINTM(MINFO,
2475 "Reporting scan results\n");
2476 woal_inform_bss_from_scan_result(
2477 priv, NULL, MOAL_NO_WAIT);
2478 if (!priv->phandle->first_scan_done) {
2479 priv->phandle->first_scan_done =
2480 MTRUE;
2481 woal_set_scan_time(
2482 priv,
2483 ACTIVE_SCAN_CHAN_TIME,
2484 PASSIVE_SCAN_CHAN_TIME,
2485 SPECIFIC_SCAN_CHAN_TIME);
2486 }
2487 spin_lock_irqsave(
2488 &priv->phandle->scan_req_lock,
2489 flags);
2490 if (priv->phandle->scan_request) {
2491 cancel_delayed_work(
2492 &priv->phandle
2493 ->scan_timeout_work);
2494 woal_cfg80211_scan_done(
2495 priv->phandle
2496 ->scan_request,
2497 MFALSE);
2498 priv->phandle->scan_request =
2499 NULL;
2500 }
2501 spin_unlock_irqrestore(
2502 &priv->phandle->scan_req_lock,
2503 flags);
2504 }
2505 }
2506 #endif /* STA_CFG80211 */
2507
2508 #ifdef STA_WEXT
2509 if (IS_STA_WEXT(cfg80211_wext)) {
2510 memset(&wrqu, 0, sizeof(union iwreq_data));
2511 wireless_send_event(priv->netdev, SIOCGIWSCAN,
2512 &wrqu, NULL);
2513 }
2514 #endif
2515 woal_broadcast_event(priv, (t_u8 *)&pmevent->event_id,
2516 sizeof(mlan_event_id));
2517 }
2518
2519 if (!is_zero_timeval(priv->phandle->scan_time_start)) {
2520 woal_get_monotonic_time(&priv->phandle->scan_time_end);
2521 priv->phandle->scan_time += (t_u64)(
2522 timeval_to_usec(priv->phandle->scan_time_end) -
2523 timeval_to_usec(
2524 priv->phandle->scan_time_start));
2525 PRINTM(MINFO,
2526 "%s : start_timeval=%d:%d end_timeval=%d:%d inter=%llu scan_time=%llu\n",
2527 __func__,
2528 priv->phandle->scan_time_start.time_sec,
2529 priv->phandle->scan_time_start.time_usec,
2530 priv->phandle->scan_time_end.time_sec,
2531 priv->phandle->scan_time_end.time_usec,
2532 (t_u64)(timeval_to_usec(
2533 priv->phandle->scan_time_end) -
2534 timeval_to_usec(
2535 priv->phandle->scan_time_start)),
2536 priv->phandle->scan_time);
2537 priv->phandle->scan_time_start.time_sec = 0;
2538 priv->phandle->scan_time_start.time_usec = 0;
2539 }
2540
2541 if (priv->phandle->scan_pending_on_block == MTRUE) {
2542 priv->phandle->scan_pending_on_block = MFALSE;
2543 priv->phandle->scan_priv = NULL;
2544 MOAL_REL_SEMAPHORE(&priv->phandle->async_sem);
2545 }
2546 break;
2547
2548 case MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM:
2549 memmove((pmevent->event_buf + strlen(CUS_EVT_OBSS_SCAN_PARAM) +
2550 1),
2551 pmevent->event_buf, pmevent->event_len);
2552 moal_memcpy_ext(priv->phandle, pmevent->event_buf,
2553 (t_u8 *)CUS_EVT_OBSS_SCAN_PARAM,
2554 strlen(CUS_EVT_OBSS_SCAN_PARAM),
2555 strlen(CUS_EVT_OBSS_SCAN_PARAM));
2556 pmevent->event_buf[strlen(CUS_EVT_OBSS_SCAN_PARAM)] = 0;
2557 woal_broadcast_event(priv, pmevent->event_buf,
2558 pmevent->event_len +
2559 strlen(CUS_EVT_OBSS_SCAN_PARAM));
2560
2561 #ifdef STA_WEXT
2562 if (IS_STA_WEXT(cfg80211_wext)) {
2563 memset(&wrqu, 0, sizeof(union iwreq_data));
2564 wrqu.data.pointer = (t_u8 __user *)pmevent->event_buf;
2565 wrqu.data.length = pmevent->event_len +
2566 strlen(CUS_EVT_OBSS_SCAN_PARAM) + 1;
2567 wireless_send_event(priv->netdev, IWEVCUSTOM, &wrqu,
2568 pmevent->event_buf);
2569 }
2570 #endif
2571 break;
2572 case MLAN_EVENT_ID_FW_BW_CHANGED:
2573 memmove((pmevent->event_buf + strlen(CUS_EVT_BW_CHANGED) + 1),
2574 pmevent->event_buf, pmevent->event_len);
2575 moal_memcpy_ext(priv->phandle, pmevent->event_buf,
2576 (t_u8 *)CUS_EVT_BW_CHANGED,
2577 strlen(CUS_EVT_BW_CHANGED),
2578 strlen(CUS_EVT_BW_CHANGED));
2579 pmevent->event_buf[strlen(CUS_EVT_BW_CHANGED)] = 0;
2580 woal_broadcast_event(priv, pmevent->event_buf,
2581 pmevent->event_len +
2582 strlen(CUS_EVT_BW_CHANGED));
2583
2584 #ifdef STA_WEXT
2585 if (IS_STA_WEXT(cfg80211_wext)) {
2586 memset(&wrqu, 0, sizeof(union iwreq_data));
2587 wrqu.data.pointer = (t_u8 __user *)pmevent->event_buf;
2588 wrqu.data.length = pmevent->event_len +
2589 strlen(CUS_EVT_BW_CHANGED) + 1;
2590 wireless_send_event(priv->netdev, IWEVCUSTOM, &wrqu,
2591 pmevent->event_buf);
2592 }
2593 #endif
2594 break;
2595
2596 case MLAN_EVENT_ID_FW_DISCONNECTED:
2597 woal_send_disconnect_to_system(priv,
2598 (t_u16)*pmevent->event_buf);
2599 #ifdef STA_CFG80211
2600 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
2601 priv->auth_flag = 0;
2602 priv->host_mlme = MFALSE;
2603 priv->auth_alg = 0xFFFF;
2604 #endif
2605 #endif
2606 #ifdef STA_WEXT
2607 /* Reset wireless stats signal info */
2608 if (IS_STA_WEXT(cfg80211_wext)) {
2609 priv->w_stats.qual.level = 0;
2610 priv->w_stats.qual.noise = 0;
2611 }
2612 #endif
2613 #ifdef REASSOCIATION
2614 if (priv->reassoc_on == MTRUE) {
2615 if (priv->auto_assoc_priv.auto_assoc_type_on &
2616 (0x1 << (AUTO_ASSOC_TYPE_DRV_RECONN - 1))) {
2617 PRINTM(MINFO,
2618 " auto assoc: trigger driver auto re-connect\n");
2619 priv->auto_assoc_priv.auto_assoc_trigger_flag =
2620 AUTO_ASSOC_TYPE_DRV_RECONN;
2621 priv->auto_assoc_priv.drv_reconnect.status =
2622 MTRUE;
2623 PRINTM(MINFO, "Reassoc: trigger the timer\n");
2624 priv->reassoc_required = MTRUE;
2625 priv->phandle->is_reassoc_timer_set = MTRUE;
2626 woal_mod_timer(&priv->phandle->reassoc_timer,
2627 REASSOC_TIMER_DEFAULT);
2628 }
2629 } else {
2630 priv->rate_index = AUTO_RATE;
2631 }
2632 #endif /* REASSOCIATION */
2633 moal_connection_status_check_pmqos(pmoal);
2634 break;
2635
2636 case MLAN_EVENT_ID_FW_MIC_ERR_UNI:
2637 #ifdef STA_WEXT
2638 if (IS_STA_WEXT(cfg80211_wext)) {
2639 #if WIRELESS_EXT >= 18
2640 woal_send_mic_error_event(priv,
2641 MLAN_EVENT_ID_FW_MIC_ERR_UNI);
2642 #else
2643 woal_send_iwevcustom_event(priv,
2644 CUS_EVT_MLME_MIC_ERR_UNI);
2645 #endif
2646 }
2647 #endif /* STA_WEXT */
2648 #ifdef STA_CFG80211
2649 if (IS_STA_CFG80211(cfg80211_wext)) {
2650 cfg80211_michael_mic_failure(priv->netdev,
2651 priv->cfg_bssid,
2652 NL80211_KEYTYPE_PAIRWISE,
2653 -1, NULL, GFP_KERNEL);
2654 }
2655 #endif
2656 woal_broadcast_event(priv, CUS_EVT_MLME_MIC_ERR_UNI,
2657 strlen(CUS_EVT_MLME_MIC_ERR_UNI));
2658 break;
2659 case MLAN_EVENT_ID_FW_MIC_ERR_MUL:
2660 #ifdef STA_WEXT
2661 if (IS_STA_WEXT(cfg80211_wext)) {
2662 #if WIRELESS_EXT >= 18
2663 woal_send_mic_error_event(priv,
2664 MLAN_EVENT_ID_FW_MIC_ERR_MUL);
2665 #else
2666 woal_send_iwevcustom_event(priv,
2667 CUS_EVT_MLME_MIC_ERR_MUL);
2668 #endif
2669 }
2670 #endif /* STA_WEXT */
2671 #ifdef STA_CFG80211
2672 if (IS_STA_CFG80211(cfg80211_wext)) {
2673 cfg80211_michael_mic_failure(priv->netdev,
2674 priv->cfg_bssid,
2675 NL80211_KEYTYPE_GROUP, -1,
2676 NULL, GFP_KERNEL);
2677 }
2678 #endif
2679 woal_broadcast_event(priv, CUS_EVT_MLME_MIC_ERR_MUL,
2680 strlen(CUS_EVT_MLME_MIC_ERR_MUL));
2681 break;
2682 case MLAN_EVENT_ID_FW_BCN_RSSI_LOW:
2683 #ifdef STA_WEXT
2684 if (IS_STA_WEXT(cfg80211_wext))
2685 woal_send_iwevcustom_event(priv,
2686 CUS_EVT_BEACON_RSSI_LOW);
2687 #endif
2688 #ifdef STA_CFG80211
2689 if (IS_STA_CFG80211(cfg80211_wext)) {
2690 #if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
2691 cfg80211_cqm_rssi_notify(
2692 priv->netdev,
2693 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
2694 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
2695 *(t_s16 *)pmevent->event_buf,
2696 #endif
2697 GFP_KERNEL);
2698 priv->last_event |= EVENT_BCN_RSSI_LOW;
2699 #endif
2700 if (!hw_test && priv->roaming_enabled)
2701 woal_config_bgscan_and_rssi(priv, MTRUE);
2702 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2703 woal_cfg80211_rssi_monitor_event(
2704 priv, *(t_s16 *)pmevent->event_buf);
2705 #endif
2706 }
2707 #endif
2708 woal_broadcast_event(priv, CUS_EVT_BEACON_RSSI_LOW,
2709 strlen(CUS_EVT_BEACON_RSSI_LOW));
2710 break;
2711 case MLAN_EVENT_ID_FW_BCN_RSSI_HIGH:
2712 #ifdef STA_WEXT
2713 if (IS_STA_WEXT(cfg80211_wext))
2714 woal_send_iwevcustom_event(priv,
2715 CUS_EVT_BEACON_RSSI_HIGH);
2716 #endif
2717 #ifdef STA_CFG80211
2718 if (IS_STA_CFG80211(cfg80211_wext)) {
2719 if (!priv->mrvl_rssi_low) {
2720 #if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
2721 cfg80211_cqm_rssi_notify(
2722 priv->netdev,
2723 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
2724 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
2725 *(t_s16 *)pmevent->event_buf,
2726 #endif
2727 GFP_KERNEL);
2728 #endif
2729 woal_set_rssi_threshold(
2730 priv, MLAN_EVENT_ID_FW_BCN_RSSI_HIGH,
2731 MOAL_NO_WAIT);
2732 }
2733 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2734 woal_cfg80211_rssi_monitor_event(
2735 priv, *(t_s16 *)pmevent->event_buf);
2736 #endif
2737 }
2738 #endif
2739 woal_broadcast_event(priv, CUS_EVT_BEACON_RSSI_HIGH,
2740 strlen(CUS_EVT_BEACON_RSSI_HIGH));
2741 break;
2742 case MLAN_EVENT_ID_FW_BCN_SNR_LOW:
2743 #ifdef STA_WEXT
2744 if (IS_STA_WEXT(cfg80211_wext))
2745 woal_send_iwevcustom_event(priv,
2746 CUS_EVT_BEACON_SNR_LOW);
2747 #endif
2748 woal_broadcast_event(priv, CUS_EVT_BEACON_SNR_LOW,
2749 strlen(CUS_EVT_BEACON_SNR_LOW));
2750 break;
2751 case MLAN_EVENT_ID_FW_BCN_SNR_HIGH:
2752 #ifdef STA_WEXT
2753 if (IS_STA_WEXT(cfg80211_wext))
2754 woal_send_iwevcustom_event(priv,
2755 CUS_EVT_BEACON_SNR_HIGH);
2756 #endif
2757 woal_broadcast_event(priv, CUS_EVT_BEACON_SNR_HIGH,
2758 strlen(CUS_EVT_BEACON_SNR_HIGH));
2759 break;
2760 case MLAN_EVENT_ID_FW_MAX_FAIL:
2761 #ifdef STA_WEXT
2762 if (IS_STA_WEXT(cfg80211_wext))
2763 woal_send_iwevcustom_event(priv, CUS_EVT_MAX_FAIL);
2764 #endif
2765 woal_broadcast_event(priv, CUS_EVT_MAX_FAIL,
2766 strlen(CUS_EVT_MAX_FAIL));
2767 break;
2768 case MLAN_EVENT_ID_FW_DATA_RSSI_LOW:
2769 #ifdef STA_WEXT
2770 if (IS_STA_WEXT(cfg80211_wext))
2771 woal_send_iwevcustom_event(priv, CUS_EVT_DATA_RSSI_LOW);
2772 #endif
2773 woal_broadcast_event(priv, CUS_EVT_DATA_RSSI_LOW,
2774 strlen(CUS_EVT_DATA_RSSI_LOW));
2775 break;
2776 case MLAN_EVENT_ID_FW_DATA_SNR_LOW:
2777 #ifdef STA_WEXT
2778 if (IS_STA_WEXT(cfg80211_wext))
2779 woal_send_iwevcustom_event(priv, CUS_EVT_DATA_SNR_LOW);
2780 #endif
2781 woal_broadcast_event(priv, CUS_EVT_DATA_SNR_LOW,
2782 strlen(CUS_EVT_DATA_SNR_LOW));
2783 break;
2784 case MLAN_EVENT_ID_FW_DATA_RSSI_HIGH:
2785 #ifdef STA_WEXT
2786 if (IS_STA_WEXT(cfg80211_wext))
2787 woal_send_iwevcustom_event(priv,
2788 CUS_EVT_DATA_RSSI_HIGH);
2789 #endif
2790 woal_broadcast_event(priv, CUS_EVT_DATA_RSSI_HIGH,
2791 strlen(CUS_EVT_DATA_RSSI_HIGH));
2792 break;
2793 case MLAN_EVENT_ID_FW_DATA_SNR_HIGH:
2794 #ifdef STA_WEXT
2795 if (IS_STA_WEXT(cfg80211_wext))
2796 woal_send_iwevcustom_event(priv, CUS_EVT_DATA_SNR_HIGH);
2797 #endif
2798 woal_broadcast_event(priv, CUS_EVT_DATA_SNR_HIGH,
2799 strlen(CUS_EVT_DATA_SNR_HIGH));
2800 break;
2801 case MLAN_EVENT_ID_FW_LINK_QUALITY:
2802 #ifdef STA_WEXT
2803 if (IS_STA_WEXT(cfg80211_wext))
2804 woal_send_iwevcustom_event(priv, CUS_EVT_LINK_QUALITY);
2805 #endif
2806 woal_broadcast_event(priv, CUS_EVT_LINK_QUALITY,
2807 strlen(CUS_EVT_LINK_QUALITY));
2808 break;
2809 case MLAN_EVENT_ID_FW_PORT_RELEASE:
2810 #ifdef STA_WEXT
2811 if (IS_STA_WEXT(cfg80211_wext))
2812 woal_send_iwevcustom_event(priv, CUS_EVT_PORT_RELEASE);
2813 #endif
2814 woal_broadcast_event(priv, CUS_EVT_PORT_RELEASE,
2815 strlen(CUS_EVT_PORT_RELEASE));
2816 break;
2817 case MLAN_EVENT_ID_FW_PRE_BCN_LOST:
2818 #ifdef STA_WEXT
2819 if (IS_STA_WEXT(cfg80211_wext))
2820 woal_send_iwevcustom_event(priv,
2821 CUS_EVT_PRE_BEACON_LOST);
2822 #endif
2823 #ifdef STA_CFG80211
2824 #if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
2825 if (IS_STA_CFG80211(cfg80211_wext)) {
2826 struct cfg80211_bss *bss = NULL;
2827 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
2828 bss = cfg80211_get_bss(priv->wdev->wiphy, NULL,
2829 priv->cfg_bssid, NULL, 0,
2830 IEEE80211_BSS_TYPE_ESS,
2831 IEEE80211_PRIVACY_ANY);
2832
2833 #else
2834 bss = cfg80211_get_bss(priv->wdev->wiphy, NULL,
2835 priv->cfg_bssid, NULL, 0,
2836 WLAN_CAPABILITY_ESS,
2837 WLAN_CAPABILITY_ESS);
2838 #endif
2839 if (bss) {
2840 cfg80211_unlink_bss(priv->wdev->wiphy, bss);
2841 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
2842 cfg80211_put_bss(priv->wdev->wiphy, bss);
2843 #else
2844 cfg80211_put_bss(bss);
2845 #endif
2846 }
2847 if (!hw_test && priv->roaming_enabled)
2848 woal_config_bgscan_and_rssi(priv, MFALSE);
2849 else {
2850 cfg80211_cqm_rssi_notify(
2851 priv->netdev,
2852 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
2853 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
2854 0,
2855 #endif
2856 GFP_KERNEL);
2857 }
2858 priv->last_event |= EVENT_PRE_BCN_LOST;
2859 }
2860 #endif
2861 #endif
2862 woal_broadcast_event(priv, CUS_EVT_PRE_BEACON_LOST,
2863 strlen(CUS_EVT_PRE_BEACON_LOST));
2864 break;
2865 case MLAN_EVENT_ID_FW_DEBUG_INFO:
2866 #ifdef STA_WEXT
2867 if (IS_STA_WEXT(cfg80211_wext))
2868 woal_send_iwevcustom_event(priv, pmevent->event_buf);
2869 #endif
2870 memmove((pmevent->event_buf + strlen(FW_DEBUG_INFO) + 1),
2871 pmevent->event_buf, pmevent->event_len);
2872 moal_memcpy_ext(priv->phandle, pmevent->event_buf,
2873 (t_u8 *)FW_DEBUG_INFO, strlen(FW_DEBUG_INFO),
2874 strlen(FW_DEBUG_INFO));
2875 pmevent->event_buf[strlen(FW_DEBUG_INFO)] = 0;
2876 woal_broadcast_event(priv, pmevent->event_buf,
2877 pmevent->event_len +
2878 strlen(FW_DEBUG_INFO) + 1);
2879 break;
2880 case MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE:
2881 #ifdef STA_WEXT
2882 if (IS_STA_WEXT(cfg80211_wext))
2883 woal_send_iwevcustom_event(
2884 priv, WMM_CONFIG_CHANGE_INDICATION);
2885 #endif
2886 woal_broadcast_event(priv, WMM_CONFIG_CHANGE_INDICATION,
2887 strlen(WMM_CONFIG_CHANGE_INDICATION));
2888 break;
2889
2890 case MLAN_EVENT_ID_DRV_REPORT_STRING:
2891 PRINTM(MINFO, "Report string %s\n", pmevent->event_buf);
2892 #ifdef STA_WEXT
2893 if (IS_STA_WEXT(cfg80211_wext))
2894 woal_send_iwevcustom_event(priv, pmevent->event_buf);
2895 #endif
2896 woal_broadcast_event(priv, pmevent->event_buf,
2897 strlen(pmevent->event_buf));
2898 break;
2899 case MLAN_EVENT_ID_FW_WEP_ICV_ERR:
2900 DBG_HEXDUMP(MCMD_D, "WEP ICV error", pmevent->event_buf,
2901 pmevent->event_len);
2902 #ifdef STA_WEXT
2903 if (IS_STA_WEXT(cfg80211_wext))
2904 woal_send_iwevcustom_event(priv, CUS_EVT_WEP_ICV_ERR);
2905 #endif
2906 woal_broadcast_event(priv, CUS_EVT_WEP_ICV_ERR,
2907 strlen(CUS_EVT_WEP_ICV_ERR));
2908 break;
2909
2910 case MLAN_EVENT_ID_DRV_DEFER_HANDLING:
2911 queue_work(priv->phandle->workqueue, &priv->phandle->main_work);
2912 break;
2913 case MLAN_EVENT_ID_DRV_FLUSH_RX_WORK:
2914 if (moal_extflg_isset(priv->phandle, EXT_NAPI)) {
2915 napi_synchronize(&priv->phandle->napi_rx);
2916 break;
2917 }
2918 flush_workqueue(priv->phandle->rx_workqueue);
2919 break;
2920 case MLAN_EVENT_ID_DRV_FLUSH_MAIN_WORK:
2921 flush_workqueue(priv->phandle->workqueue);
2922 break;
2923 case MLAN_EVENT_ID_DRV_DEFER_RX_WORK:
2924 if (moal_extflg_isset(priv->phandle, EXT_NAPI)) {
2925 napi_schedule(&priv->phandle->napi_rx);
2926 break;
2927 }
2928 queue_work(priv->phandle->rx_workqueue,
2929 &priv->phandle->rx_work);
2930 break;
2931 case MLAN_EVENT_ID_DRV_DBG_DUMP:
2932 priv->phandle->driver_status = MTRUE;
2933 ref_handle = (moal_handle *)priv->phandle->pref_mac;
2934 if (ref_handle)
2935 ref_handle->driver_status = MTRUE;
2936 #ifdef DEBUG_LEVEL1
2937 if (drvdbg & MFW_D)
2938 auto_fw_dump = MTRUE;
2939 #endif
2940
2941 woal_moal_debug_info(priv, NULL, MFALSE);
2942 if (!auto_fw_dump && !handle->fw_dump)
2943 woal_process_hang(priv->phandle);
2944 wifi_status = WIFI_STATUS_WIFI_HANG;
2945 break;
2946 case MLAN_EVENT_ID_DRV_WIFI_STATUS:
2947 wifi_status = *(t_u16 *)(pmevent->event_buf + sizeof(t_u32));
2948 break;
2949 case MLAN_EVENT_ID_FW_BG_SCAN:
2950 if (priv->media_connected == MTRUE)
2951 priv->bg_scan_start = MFALSE;
2952 priv->bg_scan_reported = MTRUE;
2953 #ifdef STA_WEXT
2954 if (IS_STA_WEXT(cfg80211_wext)) {
2955 memset(&wrqu, 0, sizeof(union iwreq_data));
2956 wireless_send_event(priv->netdev, SIOCGIWSCAN, &wrqu,
2957 NULL);
2958 }
2959 #endif
2960 #ifdef STA_CFG80211
2961 if (IS_STA_CFG80211(cfg80211_wext)) {
2962 priv->last_event |= EVENT_BG_SCAN_REPORT;
2963 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
2964 if (priv->sched_scanning &&
2965 !priv->phandle->cfg80211_suspend) {
2966 mlan_scan_resp scan_resp;
2967 if (MLAN_STATUS_SUCCESS ==
2968 woal_get_scan_table(priv, MOAL_NO_WAIT,
2969 &scan_resp))
2970 PRINTM(MIOCTL,
2971 "Triggered mlan get bgscan result\n");
2972 }
2973 #endif
2974 if (!hw_test && priv->roaming_enabled
2975 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
2976 && !priv->phandle->cfg80211_suspend
2977 #endif
2978 ) {
2979 priv->roaming_required = MTRUE;
2980 #ifdef ANDROID_KERNEL
2981 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
2982 __pm_wakeup_event(&priv->phandle->ws,
2983 ROAMING_WAKE_LOCK_TIMEOUT);
2984 #else
2985 wake_lock_timeout(
2986 &priv->phandle->wake_lock,
2987 msecs_to_jiffies(
2988 ROAMING_WAKE_LOCK_TIMEOUT));
2989 #endif
2990 #endif
2991 #ifdef REASSOCIATION
2992 wake_up_interruptible(
2993 &priv->phandle->reassoc_thread.wait_q);
2994 #endif
2995 } else {
2996 #if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
2997 if (priv->mrvl_rssi_low) {
2998 cfg80211_cqm_rssi_notify(
2999 priv->netdev,
3000 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
3001 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
3002 0,
3003 #endif
3004 GFP_KERNEL);
3005 }
3006 #endif
3007 }
3008 }
3009 #endif
3010 break;
3011 case MLAN_EVENT_ID_FW_BG_SCAN_STOPPED:
3012 #ifdef STA_CFG80211
3013 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
3014 if (IS_STA_CFG80211(cfg80211_wext)) {
3015 if (priv->sched_scanning)
3016 woal_bgscan_stop_event(priv);
3017 }
3018 #endif
3019 #endif
3020 break;
3021 case MLAN_EVENT_ID_DRV_BGSCAN_RESULT:
3022 #ifdef STA_CFG80211
3023 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
3024 if (IS_STA_CFG80211(cfg80211_wext)) {
3025 if (priv->sched_scanning &&
3026 !priv->phandle->cfg80211_suspend) {
3027 woal_inform_bss_from_scan_result(priv, NULL,
3028 MOAL_NO_WAIT);
3029 PRINTM(MMSG,
3030 "wlan: Report sched_scan result\n");
3031 woal_report_sched_scan_result(priv);
3032 priv->last_event = 0;
3033 PRINTM(MEVENT,
3034 "Reporting Sched_Scan results\n");
3035 }
3036 }
3037 #endif
3038 #endif
3039 break;
3040 #endif /* STA_SUPPORT */
3041
3042 case MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY:
3043 radar_detected = pmevent->event_buf[0];
3044 bandwidth = pmevent->event_buf[2];
3045 #ifdef UAP_SUPPORT
3046 if (priv->chan_rpt_req.chanNum && priv->chan_rpt_pending) {
3047 radar_chan = pmevent->event_buf[1];
3048 if (radar_detected) {
3049 snprintf(event_buf, sizeof(event_buf) - 1,
3050 "%s %d", CUS_EVT_RADAR_DETECTED,
3051 radar_chan);
3052 woal_broadcast_event(priv, event_buf,
3053 strlen(event_buf));
3054 } else {
3055 snprintf(event_buf, sizeof(event_buf) - 1,
3056 "%s %d", CUS_EVT_CAC_FINISHED,
3057 priv->chan_rpt_req.chanNum);
3058 woal_broadcast_event(priv, event_buf,
3059 strlen(event_buf));
3060 }
3061 if (priv->bss_type == MLAN_BSS_TYPE_DFS)
3062 woal_chan_event(priv, WOAL_EVENT_CHAN_RPT,
3063 priv->chan_rpt_req.chanNum,
3064 radar_detected);
3065 }
3066 #endif
3067
3068 #ifdef UAP_CFG80211
3069 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
3070 if (!IS_STA_OR_UAP_CFG80211(cfg80211_wext))
3071 break;
3072 if (priv->chan_rpt_req.chanNum && priv->chan_rpt_pending) {
3073 priv->chan_rpt_pending = MFALSE;
3074 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)
3075 if (priv->radar_background) {
3076 PRINTM(MEVENT,
3077 "%s radar found when background CAC \n",
3078 radar_detected ? "" : "No");
3079 if (radar_detected)
3080 cfg80211_background_radar_event(
3081 priv->phandle->wiphy,
3082 &priv->radar_background_chan,
3083 GFP_ATOMIC);
3084 break;
3085 }
3086 #endif
3087 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
3088 cfg_priv = woal_get_priv_with_wdev(priv->phandle);
3089 if (cfg_priv) {
3090 if (radar_detected)
3091 woal_update_channels_dfs_state(
3092 cfg_priv,
3093 priv->chan_rpt_req.chanNum,
3094 priv->chan_rpt_req.bandcfg
3095 .chanWidth,
3096 DFS_UNAVAILABLE);
3097 else
3098 woal_update_channels_dfs_state(
3099 cfg_priv,
3100 priv->chan_rpt_req.chanNum,
3101 priv->chan_rpt_req.bandcfg
3102 .chanWidth,
3103 DFS_AVAILABLE);
3104 }
3105 #endif
3106 break;
3107 }
3108
3109 if (priv->phandle->is_cac_timer_set) {
3110 PRINTM(MEVENT, "%s radar found when CAC \n",
3111 radar_detected ? "" : "No");
3112 moal_stop_timer(priv->phandle,
3113 &priv->phandle->cac_timer);
3114 priv->phandle->is_cac_timer_set = MFALSE;
3115 if (radar_detected) {
3116 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
3117 cfg80211_cac_event(priv->netdev,
3118 &priv->phandle->dfs_channel,
3119 NL80211_RADAR_CAC_ABORTED,
3120 GFP_KERNEL);
3121 #else
3122 cfg80211_cac_event(priv->netdev,
3123 NL80211_RADAR_CAC_ABORTED,
3124 GFP_KERNEL);
3125 #endif
3126 cfg80211_radar_event(
3127 priv->wdev->wiphy,
3128 &priv->phandle->dfs_channel,
3129 GFP_KERNEL);
3130 } else {
3131 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
3132 if (!priv->user_cac_period_msec) {
3133 // host and device timer isn't sync,add
3134 // delay to avoid kernel warning
3135 // WARN_ON(!time_after_eq(jiffies,
3136 // timeout)); mdelay(100); Using
3137 // optimized delay
3138 timeout =
3139 (priv->wdev->cac_start_time +
3140 msecs_to_jiffies(
3141 priv->wdev
3142 ->cac_time_ms));
3143 if (!time_after_eq(jiffies, timeout)) {
3144 /* Exact time to make host and
3145 * device timer in sync */
3146 wait_time = timeout - jiffies;
3147 wait_time_ms =
3148 jiffies_to_msecs(
3149 wait_time) +
3150 3;
3151 PRINTM(MEVENT,
3152 "Waiting for %ld ms for syncing\n",
3153 wait_time_ms);
3154 mdelay(wait_time_ms);
3155 }
3156 }
3157 #endif
3158
3159 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
3160 cfg80211_cac_event(priv->netdev,
3161 &priv->phandle->dfs_channel,
3162 NL80211_RADAR_CAC_FINISHED,
3163 GFP_KERNEL);
3164 #else
3165 cfg80211_cac_event(priv->netdev,
3166 NL80211_RADAR_CAC_FINISHED,
3167 GFP_KERNEL);
3168 #endif
3169 }
3170 memset(&priv->phandle->dfs_channel, 0,
3171 sizeof(struct cfg80211_chan_def));
3172 priv->phandle->cac_bss_index = 0xff;
3173 }
3174 #endif /* CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) */
3175 #endif /* UAP_CFG80211 */
3176 break;
3177 case MLAN_EVENT_ID_FW_RADAR_DETECTED:
3178 radar_chan = pmevent->event_buf[0];
3179 bandwidth = pmevent->event_buf[1];
3180 snprintf(event_buf, sizeof(event_buf) - 1, "%s %d",
3181 CUS_EVT_RADAR_DETECTED, radar_chan);
3182 woal_broadcast_event(priv, event_buf, strlen(event_buf));
3183 PRINTM(MEVENT, "Radar detected on channel %d\n", radar_chan);
3184
3185 #ifdef UAP_CFG80211
3186 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
3187 if (!IS_STA_OR_UAP_CFG80211(cfg80211_wext))
3188 break;
3189 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)
3190 if (priv->radar_background) {
3191 cfg80211_background_radar_event(
3192 priv->phandle->wiphy,
3193 &priv->radar_background_chan, GFP_ATOMIC);
3194 break;
3195 }
3196 #endif
3197 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
3198 cfg_priv = woal_get_priv_with_wdev(priv->phandle);
3199 if (cfg_priv)
3200 woal_update_channels_dfs_state(cfg_priv, radar_chan,
3201 bandwidth,
3202 DFS_UNAVAILABLE);
3203 #endif
3204 #ifdef UAP_SUPPORT
3205 if ((priv->target_chan && priv->bss_started &&
3206 (priv->target_chan != radar_chan)) ||
3207 priv->backup_chan) {
3208 PRINTM(MEVENT, "Move to target or backup chan %d %d\n",
3209 priv->target_chan, priv->backup_chan);
3210 woal_move_to_next_channel(priv);
3211 priv->target_chan = 0;
3212 break;
3213 }
3214 if (priv->bss_type == MLAN_BSS_TYPE_DFS) {
3215 woal_chan_event(priv, WOAL_EVENT_RADAR,
3216 priv->chan_rpt_req.chanNum, MTRUE);
3217 break;
3218 }
3219 #endif
3220 if (priv->phandle->is_cac_timer_set) {
3221 if (priv->bss_index == priv->phandle->cac_bss_index) {
3222 PRINTM(MEVENT, "radar detected during CAC \n");
3223 woal_cancel_timer(&priv->phandle->cac_timer);
3224 priv->phandle->is_cac_timer_set = MFALSE;
3225 /* downstream: cancel the unfinished CAC in
3226 * Firmware*/
3227 woal_11h_cancel_chan_report_ioctl(priv,
3228 MOAL_NO_WAIT);
3229 /* upstream: inform cfg80211 */
3230 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
3231 cfg80211_cac_event(priv->netdev,
3232 &priv->phandle->dfs_channel,
3233 NL80211_RADAR_CAC_ABORTED,
3234 GFP_KERNEL);
3235 #else
3236 cfg80211_cac_event(priv->netdev,
3237 NL80211_RADAR_CAC_ABORTED,
3238 GFP_KERNEL);
3239 #endif
3240 cfg80211_radar_event(
3241 priv->wdev->wiphy,
3242 &priv->phandle->dfs_channel,
3243 GFP_KERNEL);
3244
3245 memset(&priv->phandle->dfs_channel, 0,
3246 sizeof(priv->phandle->dfs_channel));
3247 priv->phandle->cac_bss_index = 0xff;
3248 } else {
3249 PRINTM(MERROR,
3250 " Radar event for incorrect inferface \n");
3251 }
3252 } else {
3253 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
3254 if (moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
3255 woal_cfg80211_dfs_vendor_event(
3256 priv, event_dfs_radar_detected,
3257 &priv->chan);
3258 else {
3259 #endif
3260 if (priv->uap_host_based && priv->bss_started)
3261 cfg80211_radar_event(priv->wdev->wiphy,
3262 &priv->chan,
3263 GFP_KERNEL);
3264 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
3265 }
3266 #endif
3267 }
3268 #endif /* CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0 */
3269 #endif /* UAP_CFG80211 */
3270 break;
3271 case MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN:
3272 #ifdef STA_WEXT
3273 if (IS_STA_WEXT(cfg80211_wext))
3274 woal_send_iwevcustom_event(priv,
3275 CUS_EVT_CHANNEL_SWITCH_ANN);
3276 #endif
3277 woal_broadcast_event(priv, CUS_EVT_CHANNEL_SWITCH_ANN,
3278 strlen(CUS_EVT_CHANNEL_SWITCH_ANN));
3279 break;
3280
3281 case MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE:
3282 #if defined(UAP_CFG80211) || defined(STA_CFG80211)
3283 pchan_info = (chan_band_info *)pmevent->event_buf;
3284 #ifdef UAP_SUPPORT
3285 if (priv->bss_role == MLAN_BSS_ROLE_UAP) {
3286 if (priv->uap_tx_blocked) {
3287 if (!netif_carrier_ok(priv->netdev))
3288 netif_carrier_on(priv->netdev);
3289 woal_start_queue(priv->netdev);
3290 priv->uap_tx_blocked = MFALSE;
3291 }
3292 priv->phandle->chsw_wait_q_woken = MTRUE;
3293 wake_up_interruptible(&priv->phandle->chsw_wait_q);
3294 }
3295 #endif
3296
3297 if (IS_STA_OR_UAP_CFG80211(cfg80211_wext)) {
3298 PRINTM(MMSG,
3299 "CSA/ECSA: Switch to new channel %d complete!\n",
3300 pchan_info->channel);
3301 #ifdef UAP_CFG80211
3302 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
3303 if (priv->csa_chan.chan &&
3304 (pchan_info->channel ==
3305 priv->csa_chan.chan->hw_value)) {
3306 moal_memcpy_ext(
3307 priv->phandle, &priv->chan,
3308 &priv->csa_chan,
3309 sizeof(struct cfg80211_chan_def),
3310 sizeof(struct cfg80211_chan_def));
3311 }
3312 #endif
3313 #endif
3314 if (priv->channel == pchan_info->channel)
3315 break;
3316 priv->channel = pchan_info->channel;
3317
3318 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
3319 if (MFALSE
3320 #ifdef UAP_CFG80211
3321 || priv->uap_host_based
3322 #endif
3323 #ifdef STA_CFG80211
3324 || priv->sme_current.ssid_len
3325 #endif
3326 ) {
3327 PRINTM(MEVENT,
3328 "CHAN_SWITCH: 11n=%d, chan=%d, center_chan=%d, band=%d, width=%d, 2Offset=%d\n",
3329 pchan_info->is_11n_enabled,
3330 pchan_info->channel,
3331 pchan_info->center_chan,
3332 pchan_info->bandcfg.chanBand,
3333 pchan_info->bandcfg.chanWidth,
3334 pchan_info->bandcfg.chan2Offset);
3335 woal_channel_switch_event(priv, pchan_info);
3336 }
3337 #endif
3338 }
3339 #endif
3340 break;
3341 case MLAN_EVENT_ID_FW_STOP_TX:
3342 woal_stop_queue(priv->netdev);
3343 if (netif_carrier_ok(priv->netdev))
3344 netif_carrier_off(priv->netdev);
3345 break;
3346 case MLAN_EVENT_ID_FW_START_TX:
3347 if (!netif_carrier_ok(priv->netdev))
3348 netif_carrier_on(priv->netdev);
3349 woal_wake_queue(priv->netdev);
3350 break;
3351 case MLAN_EVENT_ID_FW_HS_WAKEUP:
3352 /* simulate HSCFG_CANCEL command */
3353 woal_cancel_hs(priv, MOAL_NO_WAIT);
3354 #ifdef STA_SUPPORT
3355 pmpriv = woal_get_priv((moal_handle *)pmoal, MLAN_BSS_ROLE_STA);
3356 #ifdef STA_WEXT
3357 if (IS_STA_WEXT(cfg80211_wext) && pmpriv)
3358 woal_send_iwevcustom_event(pmpriv, CUS_EVT_HS_WAKEUP);
3359 #endif /* STA_WEXT */
3360 if (pmpriv)
3361 woal_broadcast_event(pmpriv, CUS_EVT_HS_WAKEUP,
3362 strlen(CUS_EVT_HS_WAKEUP));
3363 #endif /*STA_SUPPORT */
3364 #ifdef UAP_SUPPORT
3365 pmpriv = woal_get_priv((moal_handle *)pmoal, MLAN_BSS_ROLE_UAP);
3366 if (pmpriv) {
3367 pmevent->event_id = UAP_EVENT_ID_HS_WAKEUP;
3368 woal_broadcast_event(pmpriv, (t_u8 *)&pmevent->event_id,
3369 sizeof(t_u32));
3370 }
3371 #endif /* UAP_SUPPORT */
3372 break;
3373 case MLAN_EVENT_ID_DRV_HS_ACTIVATED:
3374 #ifdef STA_SUPPORT
3375 pmpriv = woal_get_priv((moal_handle *)pmoal, MLAN_BSS_ROLE_STA);
3376 #ifdef STA_WEXT
3377 if (IS_STA_WEXT(cfg80211_wext) && pmpriv)
3378 woal_send_iwevcustom_event(pmpriv,
3379 CUS_EVT_HS_ACTIVATED);
3380 #endif /* STA_WEXT */
3381 if (pmpriv)
3382 woal_broadcast_event(pmpriv, CUS_EVT_HS_ACTIVATED,
3383 strlen(CUS_EVT_HS_ACTIVATED));
3384 #endif /* STA_SUPPORT */
3385 #if defined(UAP_SUPPORT)
3386 pmpriv = woal_get_priv((moal_handle *)pmoal, MLAN_BSS_ROLE_UAP);
3387 if (pmpriv) {
3388 pmevent->event_id = UAP_EVENT_ID_DRV_HS_ACTIVATED;
3389 woal_broadcast_event(pmpriv, (t_u8 *)&pmevent->event_id,
3390 sizeof(t_u32));
3391 }
3392 #endif
3393 memset(&pm_info, 0, sizeof(mlan_ds_ps_info));
3394 if (priv->phandle->suspend_fail == MFALSE) {
3395 woal_get_pm_info(priv, &pm_info);
3396 if (pm_info.is_suspend_allowed == MTRUE) {
3397 priv->phandle->hs_activated = MTRUE;
3398 #ifdef MMC_PM_FUNC_SUSPENDED
3399 woal_wlan_is_suspended(priv->phandle);
3400 #endif
3401 }
3402 priv->phandle->hs_activate_wait_q_woken = MTRUE;
3403 wake_up(&priv->phandle->hs_activate_wait_q);
3404 }
3405 break;
3406 case MLAN_EVENT_ID_DRV_HS_DEACTIVATED:
3407 #ifdef STA_SUPPORT
3408 pmpriv = woal_get_priv((moal_handle *)pmoal, MLAN_BSS_ROLE_STA);
3409 #ifdef STA_WEXT
3410 if (IS_STA_WEXT(cfg80211_wext) && pmpriv)
3411 woal_send_iwevcustom_event(pmpriv,
3412 CUS_EVT_HS_DEACTIVATED);
3413 #endif /* STA_WEXT */
3414 if (pmpriv)
3415 woal_broadcast_event(pmpriv, CUS_EVT_HS_DEACTIVATED,
3416 strlen(CUS_EVT_HS_DEACTIVATED));
3417 #endif /* STA_SUPPORT */
3418 #if defined(UAP_SUPPORT)
3419 pmpriv = woal_get_priv((moal_handle *)pmoal, MLAN_BSS_ROLE_UAP);
3420 if (pmpriv) {
3421 pmevent->event_id = UAP_EVENT_ID_DRV_HS_DEACTIVATED;
3422 woal_broadcast_event(pmpriv, (t_u8 *)&pmevent->event_id,
3423 sizeof(t_u32));
3424 }
3425 #endif
3426 priv->phandle->hs_activated = MFALSE;
3427 break;
3428 #ifdef UAP_SUPPORT
3429 case MLAN_EVENT_ID_UAP_FW_BSS_START:
3430 woal_hist_data_reset(priv);
3431 priv->bss_started = MTRUE;
3432 priv->skip_cac = MFALSE;
3433 if (!netif_carrier_ok(priv->netdev))
3434 netif_carrier_on(priv->netdev);
3435 woal_start_queue(priv->netdev);
3436 moal_memcpy_ext(priv->phandle, priv->current_addr,
3437 pmevent->event_buf + 6, ETH_ALEN, ETH_ALEN);
3438 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)
3439 eth_hw_addr_set(priv->netdev, priv->current_addr);
3440 #else
3441 moal_memcpy_ext(priv->phandle, priv->netdev->dev_addr,
3442 priv->current_addr, ETH_ALEN, ETH_ALEN);
3443 #endif
3444 woal_broadcast_event(priv, pmevent->event_buf,
3445 pmevent->event_len);
3446 #ifdef STA_SUPPORT
3447 #ifdef STA_CFG80211
3448 pmpriv = woal_get_priv((moal_handle *)pmoal, MLAN_BSS_ROLE_STA);
3449 if (IS_STA_CFG80211(cfg80211_wext) && pmpriv)
3450 woal_set_scan_time(pmpriv, ACTIVE_SCAN_CHAN_TIME,
3451 PASSIVE_SCAN_CHAN_TIME,
3452 MIN_SPECIFIC_SCAN_CHAN_TIME);
3453 #endif
3454 #endif
3455 #ifdef UAP_CFG80211
3456 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
3457 if (priv->chan_under_nop) {
3458 PRINTM(MMSG,
3459 "Channel Under Nop: notify cfg80211 new channel=%d\n",
3460 priv->channel);
3461 #if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13)
3462 cfg80211_ch_switch_notify(priv->netdev, &priv->chan, 0);
3463 #else
3464 cfg80211_ch_switch_notify(priv->netdev, &priv->chan);
3465 #endif
3466 priv->chan_under_nop = MFALSE;
3467 }
3468 #endif
3469 #endif
3470 break;
3471 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
3472 case MLAN_EVENT_ID_DRV_UAP_CHAN_INFO:
3473 #ifdef UAP_CFG80211
3474 if (IS_UAP_CFG80211(cfg80211_wext)) {
3475 pchan_info = (chan_band_info *)pmevent->event_buf;
3476 PRINTM(MEVENT,
3477 "UAP: 11n=%d, chan=%d, center_chan=%d, band=%d, width=%d, 2Offset=%d\n",
3478 pchan_info->is_11n_enabled, pchan_info->channel,
3479 pchan_info->center_chan,
3480 pchan_info->bandcfg.chanBand,
3481 pchan_info->bandcfg.chanWidth,
3482 pchan_info->bandcfg.chan2Offset);
3483 if (priv->uap_host_based &&
3484 (priv->channel != pchan_info->channel))
3485 woal_channel_switch_event(priv, pchan_info);
3486 }
3487 #endif
3488 break;
3489 #endif
3490 case MLAN_EVENT_ID_UAP_FW_BSS_ACTIVE:
3491 priv->media_connected = MTRUE;
3492 if (!netif_carrier_ok(priv->netdev))
3493 netif_carrier_on(priv->netdev);
3494 woal_wake_queue(priv->netdev);
3495 woal_broadcast_event(priv, pmevent->event_buf,
3496 pmevent->event_len);
3497 moal_connection_status_check_pmqos(pmoal);
3498 break;
3499 case MLAN_EVENT_ID_UAP_FW_BSS_IDLE:
3500 priv->media_connected = MFALSE;
3501 woal_broadcast_event(priv, pmevent->event_buf,
3502 pmevent->event_len);
3503 moal_connection_status_check_pmqos(pmoal);
3504 break;
3505 case MLAN_EVENT_ID_UAP_FW_MIC_COUNTERMEASURES: {
3506 t_u16 status = 0;
3507 status = *(t_u16 *)(pmevent->event_buf + 4);
3508 if (status) {
3509 priv->media_connected = MFALSE;
3510 woal_stop_queue(priv->netdev);
3511 if (netif_carrier_ok(priv->netdev))
3512 netif_carrier_off(priv->netdev);
3513 } else {
3514 priv->media_connected = MTRUE;
3515 if (!netif_carrier_ok(priv->netdev))
3516 netif_carrier_on(priv->netdev);
3517 woal_wake_queue(priv->netdev);
3518 }
3519 woal_broadcast_event(priv, pmevent->event_buf,
3520 pmevent->event_len);
3521 } break;
3522 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
3523 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
3524 case MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED:
3525 if (IS_STA_OR_UAP_CFG80211(cfg80211_wext)) {
3526 PRINTM(MEVENT,
3527 "FW_REMAIN_ON_CHANNEL_EXPIRED cookie = %#llx\n",
3528 priv->phandle->cookie);
3529 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
3530 if (priv->host_mlme &&
3531 (priv->auth_flag & HOST_MLME_AUTH_PENDING)) {
3532 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
3533 if (priv->assoc_bss) {
3534 PRINTM(MEVENT,
3535 "wlan: HostMlme auth timeout\n");
3536 cfg80211_auth_timeout(
3537 priv->netdev,
3538 priv->assoc_bss->bssid);
3539 }
3540 #endif
3541 priv->auth_flag = 0;
3542 priv->host_mlme = MFALSE;
3543 priv->auth_alg = 0xFFFF;
3544 }
3545 #endif
3546 priv->phandle->remain_on_channel = MFALSE;
3547 if (priv->phandle->cookie &&
3548 !priv->phandle->is_remain_timer_set) {
3549 cfg80211_remain_on_channel_expired(
3550 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
3551 priv->netdev,
3552 #else
3553 priv->wdev,
3554 #endif
3555 priv->phandle->cookie,
3556 &priv->phandle->chan,
3557 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
3558 priv->phandle->channel_type,
3559 #endif
3560 GFP_ATOMIC);
3561 priv->phandle->cookie = 0;
3562 }
3563 }
3564 break;
3565 #endif
3566 #endif
3567 case MLAN_EVENT_ID_UAP_FW_STA_CONNECT:
3568 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
3569 if (IS_STA_OR_UAP_CFG80211(cfg80211_wext)) {
3570 struct station_info *sinfo = NULL;
3571 t_u8 addr[ETH_ALEN];
3572 sinfo = kzalloc(sizeof(struct station_info),
3573 GFP_ATOMIC);
3574 if (sinfo) {
3575 sinfo->filled = 0;
3576 sinfo->generation = 0;
3577 /* copy the station mac address */
3578 memset(addr, 0xFF, ETH_ALEN);
3579 moal_memcpy_ext(priv->phandle, addr,
3580 pmevent->event_buf, ETH_ALEN,
3581 ETH_ALEN);
3582 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
3583 if (pmevent->event_len > ETH_ALEN) {
3584 #if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
3585 /* set station info filled flag */
3586 sinfo->filled |=
3587 STATION_INFO_ASSOC_REQ_IES;
3588 #endif
3589 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 18, 0)
3590 sinfo->pertid = NULL;
3591 #endif
3592 /* get the assoc request ies and length
3593 */
3594 sinfo->assoc_req_ies =
3595 (const t_u8
3596 *)(pmevent->event_buf +
3597 ETH_ALEN);
3598 sinfo->assoc_req_ies_len =
3599 pmevent->event_len - ETH_ALEN;
3600 }
3601 #endif /* KERNEL_VERSION */
3602 if (priv->netdev && priv->wdev)
3603 cfg80211_new_sta(priv->netdev,
3604 (t_u8 *)addr, sinfo,
3605 GFP_KERNEL);
3606 kfree(sinfo);
3607 }
3608 }
3609 #endif /* UAP_CFG80211 */
3610 memmove((pmevent->event_buf + strlen(CUS_EVT_STA_CONNECTED) +
3611 1),
3612 pmevent->event_buf, pmevent->event_len);
3613 moal_memcpy_ext(priv->phandle, pmevent->event_buf,
3614 (t_u8 *)CUS_EVT_STA_CONNECTED,
3615 strlen(CUS_EVT_STA_CONNECTED),
3616 strlen(CUS_EVT_STA_CONNECTED));
3617 pmevent->event_buf[strlen(CUS_EVT_STA_CONNECTED)] = 0;
3618 woal_broadcast_event(priv, pmevent->event_buf,
3619 pmevent->event_len +
3620 strlen(CUS_EVT_STA_CONNECTED));
3621 #ifdef UAP_WEXT
3622 if (IS_UAP_WEXT(cfg80211_wext)) {
3623 memset(&wrqu, 0, sizeof(union iwreq_data));
3624 wrqu.data.pointer = (t_u8 __user *)pmevent->event_buf;
3625 if ((pmevent->event_len +
3626 strlen(CUS_EVT_STA_CONNECTED) + 1) > IW_CUSTOM_MAX)
3627 wrqu.data.length =
3628 ETH_ALEN +
3629 strlen(CUS_EVT_STA_CONNECTED) + 1;
3630 else
3631 wrqu.data.length =
3632 pmevent->event_len +
3633 strlen(CUS_EVT_STA_CONNECTED) + 1;
3634 wireless_send_event(priv->netdev, IWEVCUSTOM, &wrqu,
3635 pmevent->event_buf);
3636 }
3637 #endif /* UAP_WEXT */
3638 break;
3639 case MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT:
3640 #ifdef UAP_CFG80211
3641 if (IS_UAP_CFG80211(cfg80211_wext)) {
3642 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
3643 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
3644 /**Forward Deauth, Auth and disassoc frame to Host*/
3645 if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME)) {
3646 t_u16 reason_code = woal_le16_to_cpu(
3647 *(t_u16 *)pmevent->event_buf);
3648 PRINTM(MCMND, "deauth reason code =0x%x\n",
3649 reason_code);
3650 /** BIT 14 indicate deauth is initiated by FW */
3651 if (reason_code & MBIT(14))
3652 woal_host_mlme_disconnect(
3653 priv, 0,
3654 pmevent->event_buf + 2);
3655 } else
3656 #endif
3657 if (priv->netdev && priv->wdev)
3658 cfg80211_del_sta(priv->netdev,
3659 pmevent->event_buf + 2,
3660 GFP_KERNEL);
3661
3662 #endif /* KERNEL_VERSION */
3663 }
3664 #endif /* UAP_CFG80211 */
3665 memmove((pmevent->event_buf + strlen(CUS_EVT_STA_DISCONNECTED) +
3666 1),
3667 pmevent->event_buf, pmevent->event_len);
3668 moal_memcpy_ext(priv->phandle, pmevent->event_buf,
3669 (t_u8 *)CUS_EVT_STA_DISCONNECTED,
3670 strlen(CUS_EVT_STA_DISCONNECTED),
3671 strlen(CUS_EVT_STA_DISCONNECTED));
3672 pmevent->event_buf[strlen(CUS_EVT_STA_DISCONNECTED)] = 0;
3673 woal_broadcast_event(priv, pmevent->event_buf,
3674 pmevent->event_len +
3675 strlen(CUS_EVT_STA_DISCONNECTED));
3676
3677 #ifdef UAP_WEXT
3678 if (IS_UAP_WEXT(cfg80211_wext)) {
3679 memset(&wrqu, 0, sizeof(union iwreq_data));
3680 wrqu.data.pointer = (t_u8 __user *)pmevent->event_buf;
3681 wrqu.data.length = pmevent->event_len +
3682 strlen(CUS_EVT_STA_DISCONNECTED) + 1;
3683 wireless_send_event(priv->netdev, IWEVCUSTOM, &wrqu,
3684 pmevent->event_buf);
3685 }
3686 #endif /* UAP_WEXT */
3687 break;
3688 case MLAN_EVENT_ID_DRV_MGMT_FRAME:
3689 #ifdef UAP_WEXT
3690 if (IS_UAP_WEXT(cfg80211_wext)) {
3691 woal_broadcast_event(priv, pmevent->event_buf,
3692 pmevent->event_len);
3693 }
3694 #endif /* UAP_WEXT */
3695
3696 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
3697 if (IS_STA_OR_UAP_CFG80211(cfg80211_wext)) {
3698 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
3699 if (priv->netdev &&
3700 priv->netdev->ieee80211_ptr->wiphy->mgmt_stypes &&
3701 priv->mgmt_subtype_mask) {
3702 /* frmctl + durationid + addr1 + addr2 + addr3 +
3703 * seqctl */
3704 #define PACKET_ADDR4_POS (2 + 2 + 6 + 6 + 6 + 2)
3705 t_u8 *pkt;
3706 int freq =
3707 priv->phandle->remain_on_channel ?
3708 priv->phandle->chan.center_freq :
3709 woal_get_active_intf_freq(priv);
3710 if (!freq) {
3711 if (!priv->phandle->chan.center_freq) {
3712 PRINTM(MINFO,
3713 "Skip to report mgmt packet to cfg80211\n");
3714 break;
3715 }
3716 freq = priv->phandle->chan.center_freq;
3717 }
3718
3719 pkt = ((t_u8 *)pmevent->event_buf +
3720 sizeof(pmevent->event_id));
3721
3722 /* move addr4 */
3723 memmove(pkt + PACKET_ADDR4_POS,
3724 pkt + PACKET_ADDR4_POS + ETH_ALEN,
3725 pmevent->event_len -
3726 sizeof(pmevent->event_id) -
3727 PACKET_ADDR4_POS - ETH_ALEN);
3728 #ifdef WIFI_DIRECT_SUPPORT
3729 if (ieee80211_is_action(
3730 ((struct ieee80211_mgmt *)pkt)
3731 ->frame_control))
3732 woal_cfg80211_display_p2p_actframe(
3733 pkt,
3734 pmevent->event_len -
3735 sizeof(pmevent->event_id) -
3736 MLAN_MAC_ADDR_LENGTH,
3737 ieee80211_get_channel(
3738 priv->wdev->wiphy,
3739 freq),
3740 MFALSE);
3741 #endif
3742 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
3743 /**Forward Deauth, Auth and disassoc frame to
3744 * Host*/
3745 if (priv->host_mlme &&
3746 (GET_BSS_ROLE(priv) != MLAN_BSS_ROLE_UAP) &&
3747 (ieee80211_is_deauth(
3748 ((struct ieee80211_mgmt *)pkt)
3749 ->frame_control) ||
3750 ieee80211_is_auth(
3751 ((struct ieee80211_mgmt *)pkt)
3752 ->frame_control) ||
3753 ieee80211_is_disassoc(
3754 ((struct ieee80211_mgmt *)pkt)
3755 ->frame_control))) {
3756 if (ieee80211_is_auth(
3757 ((struct ieee80211_mgmt *)
3758 pkt)
3759 ->frame_control)) {
3760 PRINTM(MEVENT,
3761 "HostMlme %s: Received auth frame type = 0x%x\n",
3762 priv->netdev->name,
3763 priv->auth_alg);
3764
3765 if (priv->auth_flag &
3766 HOST_MLME_AUTH_PENDING) {
3767 if (priv->auth_alg !=
3768 WLAN_AUTH_SAE) {
3769 priv->auth_flag &=
3770 ~HOST_MLME_AUTH_PENDING;
3771 priv->auth_flag |=
3772 HOST_MLME_AUTH_DONE;
3773 priv->phandle
3774 ->host_mlme_priv =
3775 priv;
3776 queue_work(
3777 priv->phandle
3778 ->evt_workqueue,
3779 &priv->phandle
3780 ->host_mlme_work);
3781 }
3782 } else {
3783 PRINTM(MERROR,
3784 "HostMlme %s: Drop auth frame, auth_flag=0x%x auth_alg=0x%x\n",
3785 priv->netdev
3786 ->name,
3787 priv->auth_flag,
3788 priv->auth_alg);
3789 break;
3790 }
3791 } else {
3792 PRINTM(MEVENT,
3793 "HostMlme %s: Receive deauth/disassociate\n",
3794 priv->netdev->name);
3795 #if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13)
3796 if (!priv->wdev->connected) {
3797 #else
3798 if (!priv->wdev->current_bss) {
3799 #endif
3800 PRINTM(MEVENT,
3801 "HostMlme: Drop deauth/disassociate, current_bss = null\n");
3802 break;
3803 }
3804 priv->cfg_disconnect = MTRUE;
3805 woal_mgmt_frame_register(
3806 priv,
3807 IEEE80211_STYPE_DEAUTH,
3808 MFALSE);
3809 woal_mgmt_frame_register(
3810 priv,
3811 IEEE80211_STYPE_DISASSOC,
3812 MFALSE);
3813 woal_send_disconnect_to_system(
3814 priv,
3815 DEF_DEAUTH_REASON_CODE);
3816 priv->host_mlme = MFALSE;
3817 priv->auth_flag = 0;
3818 priv->auth_alg = 0xFFFF;
3819 }
3820 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
3821 woal_rx_mgmt_pkt_event(
3822 priv, pkt,
3823 pmevent->event_len -
3824 sizeof(pmevent->event_id) -
3825 MLAN_MAC_ADDR_LENGTH);
3826 #else
3827 if (ieee80211_is_deauth(
3828 ((struct ieee80211_mgmt *)
3829 pkt)
3830 ->frame_control))
3831 cfg80211_send_deauth(
3832 priv->netdev, pkt,
3833 pmevent->event_len -
3834 sizeof(pmevent->event_id) -
3835 MLAN_MAC_ADDR_LENGTH);
3836 else if (ieee80211_is_auth(
3837 ((struct ieee80211_mgmt
3838 *)pkt)
3839 ->frame_control))
3840 cfg80211_send_rx_auth(
3841 priv->netdev, pkt,
3842 pmevent->event_len -
3843 sizeof(pmevent->event_id) -
3844 MLAN_MAC_ADDR_LENGTH);
3845 else if (ieee80211_is_disassoc(
3846 ((struct ieee80211_mgmt
3847 *)pkt)
3848 ->frame_control))
3849 cfg80211_send_disassoc(
3850 priv->netdev, pkt,
3851 pmevent->event_len -
3852 sizeof(pmevent->event_id) -
3853 MLAN_MAC_ADDR_LENGTH);
3854
3855 #endif
3856 } else
3857 #endif
3858 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
3859 cfg80211_rx_mgmt(
3860 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
3861 priv->wdev,
3862 #else
3863 priv->netdev,
3864 #endif
3865 freq, 0,
3866 ((const t_u8 *)
3867 pmevent->event_buf) +
3868 sizeof(pmevent->event_id),
3869 pmevent->event_len -
3870 sizeof(pmevent->event_id) -
3871 MLAN_MAC_ADDR_LENGTH
3872 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
3873 ,
3874 0
3875 #endif
3876 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
3877 ,
3878 GFP_ATOMIC
3879 #endif
3880 );
3881 #else
3882 cfg80211_rx_mgmt(
3883 priv->netdev, freq,
3884 ((const t_u8 *)pmevent->event_buf) +
3885 sizeof(pmevent->event_id),
3886 pmevent->event_len -
3887 sizeof(pmevent->event_id) -
3888 MLAN_MAC_ADDR_LENGTH,
3889 GFP_ATOMIC);
3890 #endif
3891 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
3892 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
3893 woal_packet_fate_monitor(
3894 priv, PACKET_TYPE_RX,
3895 RX_PKT_FATE_SUCCESS,
3896 FRAME_TYPE_80211_MGMT, 0, 0,
3897 ((t_u8 *)pmevent->event_buf) +
3898 sizeof(pmevent->event_id),
3899 pmevent->event_len -
3900 sizeof(pmevent->event_id) -
3901 MLAN_MAC_ADDR_LENGTH);
3902 #endif
3903 #endif
3904 }
3905 #endif /* KERNEL_VERSION */
3906 }
3907 #endif /* STA_CFG80211 || UAP_CFG80211 */
3908 break;
3909 #endif /* UAP_SUPPORT */
3910 case MLAN_EVENT_ID_DRV_PASSTHRU:
3911 woal_broadcast_event(priv, pmevent->event_buf,
3912 pmevent->event_len);
3913 break;
3914 case MLAN_EVENT_ID_DRV_ASSOC_FAILURE_REPORT:
3915 PRINTM(MINFO, "Assoc result\n");
3916
3917 if (priv->media_connected) {
3918 PRINTM(MINFO, "Assoc_Rpt: Media Connected\n");
3919 if (!netif_carrier_ok(priv->netdev)) {
3920 PRINTM(MINFO, "Assoc_Rpt: Carrier On\n");
3921 netif_carrier_on(priv->netdev);
3922 }
3923 PRINTM(MINFO, "Assoc_Rpt: Queue Start\n");
3924 woal_wake_queue(priv->netdev);
3925 }
3926 break;
3927 case MLAN_EVENT_ID_DRV_MEAS_REPORT:
3928 /* We have received measurement report, wakeup measurement wait
3929 * queue */
3930 PRINTM(MINFO, "Measurement Report\n");
3931 /* Going out of CAC checking period */
3932 if (priv->phandle->cac_period == MTRUE) {
3933 priv->phandle->cac_period = MFALSE;
3934 if (priv->phandle->meas_wait_q_woken == MFALSE) {
3935 priv->phandle->meas_wait_q_woken = MTRUE;
3936 wake_up_interruptible(
3937 &priv->phandle->meas_wait_q);
3938 }
3939
3940 /* Execute delayed BSS START command */
3941 if (priv->phandle->delay_bss_start == MTRUE) {
3942 mlan_ioctl_req *req = NULL;
3943 mlan_ds_bss *bss = NULL;
3944
3945 /* Clear flag */
3946 priv->phandle->delay_bss_start = MFALSE;
3947
3948 PRINTM(MMSG,
3949 "Now CAC measure period end. Execute delayed BSS Start command.\n");
3950
3951 req = woal_alloc_mlan_ioctl_req(
3952 sizeof(mlan_ds_bss));
3953 if (!req) {
3954 PRINTM(MERROR,
3955 "Failed to allocate ioctl request buffer\n");
3956 goto done;
3957 }
3958 bss = (mlan_ds_bss *)req->pbuf;
3959 req->req_id = MLAN_IOCTL_BSS;
3960 req->action = MLAN_ACT_SET;
3961 bss->sub_command = MLAN_OID_BSS_START;
3962 moal_memcpy_ext(
3963 priv->phandle, &bss->param.ssid_bssid,
3964 &priv->phandle->delay_ssid_bssid,
3965 sizeof(mlan_ssid_bssid),
3966 sizeof(mlan_ssid_bssid));
3967
3968 if (woal_request_ioctl(priv, req,
3969 MOAL_NO_WAIT) !=
3970 MLAN_STATUS_PENDING) {
3971 PRINTM(MERROR,
3972 "Delayed BSS Start operation failed!\n");
3973 kfree(req);
3974 }
3975
3976 PRINTM(MMSG, "BSS START Complete!\n");
3977 }
3978 #ifdef UAP_SUPPORT
3979 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
3980 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
3981 if (priv->uap_host_based &&
3982 moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
3983 woal_cfg80211_dfs_vendor_event(
3984 priv, event_dfs_cac_finished,
3985 &priv->chan);
3986 #endif
3987 #endif
3988 #endif
3989 }
3990 break;
3991 case MLAN_EVENT_ID_DRV_TDLS_TEARDOWN_REQ:
3992 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
3993 #ifdef STA_CFG80211
3994 if (IS_STA_CFG80211(cfg80211_wext)) {
3995 tdls_tear_down_event *tdls_event =
3996 (tdls_tear_down_event *)pmevent->event_buf;
3997 cfg80211_tdls_oper_request(priv->netdev,
3998 tdls_event->peer_mac_addr,
3999 NL80211_TDLS_TEARDOWN,
4000 tdls_event->reason_code,
4001 GFP_KERNEL);
4002 }
4003 #endif
4004 #endif
4005 break;
4006 case MLAN_EVENT_ID_FW_TX_STATUS: {
4007 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
4008 unsigned long flag;
4009 tx_status_event *tx_status =
4010 (tx_status_event *)(pmevent->event_buf + 4);
4011 struct tx_status_info *tx_info = NULL;
4012 PRINTM(MINFO,
4013 "Receive Tx status: tx_token=%d, pkt_type=0x%x, status=%d tx_seq_num=%d\n",
4014 tx_status->tx_token_id, tx_status->packet_type,
4015 tx_status->status, priv->tx_seq_num);
4016 spin_lock_irqsave(&priv->tx_stat_lock, flag);
4017 tx_info = woal_get_tx_info(priv, tx_status->tx_token_id);
4018 if (tx_info) {
4019 bool ack;
4020 struct sk_buff *skb = (struct sk_buff *)tx_info->tx_skb;
4021 list_del(&tx_info->link);
4022 spin_unlock_irqrestore(&priv->tx_stat_lock, flag);
4023 if (!tx_status->status)
4024 ack = true;
4025 else
4026 ack = false;
4027 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
4028 if (priv->phandle->remain_on_channel &&
4029 tx_info->cancel_remain_on_channel) {
4030 remain_priv =
4031 priv->phandle->priv
4032 [priv->phandle->remain_bss_index];
4033 if (remain_priv) {
4034 woal_cfg80211_remain_on_channel_cfg(
4035 remain_priv, MOAL_NO_WAIT,
4036 MTRUE, &channel_status, NULL, 0,
4037 0);
4038 priv->phandle->remain_on_channel =
4039 MFALSE;
4040 }
4041 }
4042 #endif
4043 PRINTM(MEVENT, "Wlan: Tx status=%d\n", ack);
4044 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
4045 if (tx_info->tx_cookie) {
4046 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
4047 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
4048 cfg80211_mgmt_tx_status(priv->netdev,
4049 tx_info->tx_cookie,
4050 skb->data, skb->len,
4051 ack, GFP_ATOMIC);
4052 #else
4053 cfg80211_mgmt_tx_status(priv->wdev,
4054 tx_info->tx_cookie,
4055 skb->data, skb->len,
4056 ack, GFP_ATOMIC);
4057 #endif
4058 #endif
4059 }
4060 #if defined(STA_CFG80211) || defined(UAP_CFG80211)
4061 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
4062 woal_packet_fate_monitor(priv, PACKET_TYPE_TX,
4063 ack ? TX_PKT_FATE_ACKED :
4064 TX_PKT_FATE_SENT,
4065 FRAME_TYPE_80211_MGMT, 0, 0,
4066 skb->data, skb->len);
4067 #endif
4068 #endif
4069 #endif
4070 dev_kfree_skb_any(skb);
4071 kfree(tx_info);
4072 } else {
4073 spin_unlock_irqrestore(&priv->tx_stat_lock, flag);
4074 }
4075 #endif
4076 } break;
4077 case MLAN_EVENT_ID_DRV_FT_RESPONSE:
4078 if (priv->phandle->fw_roam_enable)
4079 break;
4080 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
4081 #ifdef STA_CFG80211
4082 if (IS_STA_CFG80211(cfg80211_wext)) {
4083 struct cfg80211_ft_event_params ft_event;
4084 if (priv->ft_pre_connect)
4085 break;
4086 memset(&ft_event, 0,
4087 sizeof(struct cfg80211_ft_event_params));
4088 PRINTM(MMSG,
4089 "wlan : FT response target AP " MACSTR "\n",
4090 MAC2STR((t_u8 *)pmevent->event_buf));
4091 DBG_HEXDUMP(MDAT_D, "FT-event ", pmevent->event_buf,
4092 pmevent->event_len);
4093 moal_memcpy_ext(priv->phandle, priv->target_ap_bssid,
4094 pmevent->event_buf, ETH_ALEN, ETH_ALEN);
4095 ft_event.target_ap = priv->target_ap_bssid;
4096 ft_event.ies = pmevent->event_buf + ETH_ALEN;
4097 ft_event.ies_len = pmevent->event_len - ETH_ALEN;
4098 /*TSPEC info is needed by RIC, However the TS operation
4099 * is configured by mlanutl*/
4100 /*So do not add RIC temporally*/
4101 /*when add RIC, 1. query TS status, 2. copy tspec from
4102 * addts command*/
4103 ft_event.ric_ies = NULL;
4104 ft_event.ric_ies_len = 0;
4105
4106 cfg80211_ft_event(priv->netdev, &ft_event);
4107 priv->ft_pre_connect = MTRUE;
4108
4109 if (priv->ft_roaming_triggered_by_driver ||
4110 !(priv->ft_cap & MBIT(0))) {
4111 priv->ft_wait_condition = MTRUE;
4112 wake_up(&priv->ft_wait_q);
4113 }
4114 }
4115 #endif
4116 #endif
4117 break;
4118 case MLAN_EVENT_ID_FW_ROAM_OFFLOAD_RESULT:
4119 #ifdef STA_CFG80211
4120 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
4121 woal_cfg80211_vendor_event(priv, event_set_key_mgmt_offload,
4122 &enable, sizeof(enable));
4123 #endif
4124 moal_memcpy_ext(priv->phandle, priv->cfg_bssid,
4125 pmevent->event_buf, ETH_ALEN, ETH_ALEN);
4126 tlv = (MrvlIEtypesHeader_t *)((t_u8 *)pmevent->event_buf +
4127 MLAN_MAC_ADDR_LENGTH);
4128 tlv_buf_left = pmevent->event_len - MLAN_MAC_ADDR_LENGTH;
4129 while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
4130 tlv_type = woal_le16_to_cpu(tlv->type);
4131 tlv_len = woal_le16_to_cpu(tlv->len);
4132
4133 if (tlv_buf_left <
4134 (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
4135 PRINTM(MERROR,
4136 "Error processing firmware roam success TLVs, bytes left < TLV length\n");
4137 break;
4138 }
4139
4140 switch (tlv_type) {
4141 case TLV_TYPE_APINFO:
4142 pinfo = (apinfo *)tlv;
4143 break;
4144 case TLV_TYPE_ASSOC_REQ_IE:
4145 req_tlv = (apinfo *)tlv;
4146 break;
4147 default:
4148 break;
4149 }
4150 tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
4151 tlv = (MrvlIEtypesHeader_t
4152 *)((t_u8 *)tlv + tlv_len +
4153 sizeof(MrvlIEtypesHeader_t));
4154 }
4155 if (!pinfo) {
4156 PRINTM(MERROR,
4157 "ERROR:AP info in roaming event buffer is NULL\n");
4158 goto done;
4159 }
4160 if (req_tlv) {
4161 req_ie = req_tlv->rsp_ie;
4162 ie_len = req_tlv->header.len;
4163 }
4164 woal_inform_bss_from_scan_result(priv, NULL, MOAL_NO_WAIT);
4165 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
4166 roam_info =
4167 kzalloc(sizeof(struct cfg80211_roam_info), GFP_ATOMIC);
4168 if (roam_info) {
4169 #if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_13)
4170 roam_info->links[0].bssid = priv->cfg_bssid;
4171 #else
4172 roam_info->bssid = priv->cfg_bssid;
4173 #endif
4174 roam_info->req_ie = req_ie;
4175 roam_info->req_ie_len = ie_len;
4176 roam_info->resp_ie = pinfo->rsp_ie;
4177 roam_info->resp_ie_len = pinfo->header.len;
4178 cfg80211_roamed(priv->netdev, roam_info, GFP_KERNEL);
4179 kfree(roam_info);
4180 }
4181 #else
4182 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
4183 cfg80211_roamed(priv->netdev, NULL, priv->cfg_bssid, req_ie,
4184 ie_len, pinfo->rsp_ie, pinfo->header.len,
4185 GFP_KERNEL);
4186 #else
4187 cfg80211_roamed(priv->netdev, priv->cfg_bssid, req_ie, ie_len,
4188 pinfo->rsp_ie, pinfo->header.len, GFP_KERNEL);
4189 #endif
4190 #endif
4191
4192 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
4193 woal_roam_ap_info(priv, pmevent->event_buf, pmevent->event_len);
4194 #endif
4195 #endif
4196 PRINTM(MMSG, "FW Roamed to bssid " MACSTR " successfully\n",
4197 MAC2STR(pmevent->event_buf));
4198 break;
4199 case MLAN_EVENT_ID_CSI:
4200 DBG_HEXDUMP(MEVT_D, "CSI dump", pmevent->event_buf,
4201 pmevent->event_len);
4202 #ifdef STA_CFG80211
4203 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
4204 if (priv->csi_enable)
4205 woal_cfg80211_event_csi_dump(priv, pmevent->event_buf,
4206 pmevent->event_len);
4207 #endif
4208 #endif
4209 /* Send Netlink event */
4210 custom_len = strlen(CUS_EVT_CSI) + sizeof(priv->csi_seq);
4211 csi_len = pmevent->event_len;
4212 memmove(pmevent->event_buf + custom_len, pmevent->event_buf,
4213 csi_len);
4214 moal_memcpy_ext(priv->phandle, pmevent->event_buf, CUS_EVT_CSI,
4215 strlen(CUS_EVT_CSI), strlen(CUS_EVT_CSI));
4216 moal_memcpy_ext(priv->phandle,
4217 pmevent->event_buf + strlen(CUS_EVT_CSI),
4218 (t_u8 *)(&(priv->csi_seq)),
4219 sizeof(priv->csi_seq), sizeof(priv->csi_seq));
4220 woal_broadcast_event(priv, pmevent->event_buf,
4221 custom_len + csi_len);
4222 priv->csi_seq++;
4223 break;
4224 default:
4225 break;
4226 }
4227 done:
4228 LEAVE();
4229 return MLAN_STATUS_SUCCESS;
4230 }
4231
4232 /**
4233 * @brief This function prints the debug message in mlan
4234 *
4235 * @param pmoal Pointer to the MOAL context
4236 * @param level debug level
4237 * @param pformat point to string format buf
4238 *
4239 * @return N/A
4240 */
4241 __attribute__((format(printf, 3, 4))) t_void
4242 moal_print(t_void *pmoal, t_u32 level, char *pformat, IN...)
4243 {
4244 #ifdef DEBUG_LEVEL1
4245 va_list args;
4246
4247 if (level & MHEX_DUMP) {
4248 t_u8 *buf = NULL;
4249 int len = 0;
4250
4251 va_start(args, pformat);
4252 buf = (t_u8 *)va_arg(args, t_u8 *);
4253 len = (int)va_arg(args, int);
4254 va_end(args);
4255
4256 #ifdef DEBUG_LEVEL2
4257 if (level & MINFO)
4258 HEXDUMP((char *)pformat, buf, len);
4259 else
4260 #endif /* DEBUG_LEVEL2 */
4261 {
4262 if (level & MERROR)
4263 DBG_HEXDUMP(MERROR, (char *)pformat, buf, len);
4264 if (level & MCMD_D)
4265 DBG_HEXDUMP(MCMD_D, (char *)pformat, buf, len);
4266 if (level & MDAT_D)
4267 DBG_HEXDUMP(MDAT_D, (char *)pformat, buf, len);
4268 if (level & MIF_D)
4269 DBG_HEXDUMP(MIF_D, (char *)pformat, buf, len);
4270 if (level & MFW_D)
4271 DBG_HEXDUMP(MFW_D, (char *)pformat, buf, len);
4272 if (level & MEVT_D)
4273 DBG_HEXDUMP(MEVT_D, (char *)pformat, buf, len);
4274 }
4275 } else {
4276 if (drvdbg & level) {
4277 va_start(args, pformat);
4278 vprintk(pformat, args);
4279 va_end(args);
4280 }
4281 }
4282 #endif /* DEBUG_LEVEL1 */
4283 }
4284
4285 /**
4286 * @brief This function prints the network interface name
4287 *
4288 * @param pmoal Pointer to the MOAL context
4289 * @param bss_index BSS index
4290 * @param level debug level
4291 *
4292 * @return N/A
4293 */
4294 t_void moal_print_netintf(t_void *pmoal, t_u32 bss_index, t_u32 level)
4295 {
4296 #ifdef DEBUG_LEVEL1
4297 moal_handle *phandle = (moal_handle *)pmoal;
4298
4299 if (phandle) {
4300 if ((bss_index < MLAN_MAX_BSS_NUM) &&
4301 phandle->priv[bss_index] &&
4302 phandle->priv[bss_index]->netdev) {
4303 if (drvdbg & level)
4304 printk("%s: ",
4305 phandle->priv[bss_index]->netdev->name);
4306 }
4307 }
4308 #endif /* DEBUG_LEVEL1 */
4309 }
4310
4311 /**
4312 * @brief This function asserts the existence of the passed argument
4313 *
4314 * @param pmoal A pointer to moal_private structure
4315 * @param cond Condition to check
4316 *
4317 * @return N/A
4318 */
4319 t_void moal_assert(t_void *pmoal, t_u32 cond)
4320 {
4321 if (!cond) {
4322 panic("Assert failed: Panic!");
4323 }
4324 }
4325
4326 /**
4327 * @brief This function save the histogram data
4328 *
4329 * @param pmoal A pointer to moal_private structure
4330 * @param bss_index BSS index
4331 * @param rx_rate rx rate index
4332 * @param snr snr
4333 * @param nflr noise floor
4334 * @param antenna antenna
4335 *
4336 * @return N/A
4337 */
4338 t_void moal_hist_data_add(t_void *pmoal, t_u32 bss_index, t_u16 rx_rate,
4339 t_s8 snr, t_s8 nflr, t_u8 antenna)
4340 {
4341 moal_private *priv = NULL;
4342 priv = woal_bss_index_to_priv(pmoal, bss_index);
4343 if (priv && antenna >= priv->phandle->card_info->histogram_table_num)
4344 antenna = 0;
4345 if (priv && priv->hist_data[antenna])
4346 woal_hist_data_add(priv, rx_rate, snr, nflr, antenna);
4347 }
4348
4349 /**
4350 * @brief This function update the peer signal
4351 *
4352 * @param pmoal A pointer to moal_private structure
4353 * @param bss_index BSS index
4354 * @param peer_addr peer address
4355 * @param snr snr
4356 * @param nflr noise floor
4357 *
4358 * @return N/A
4359 */
4360 t_void moal_updata_peer_signal(t_void *pmoal, t_u32 bss_index, t_u8 *peer_addr,
4361 t_s8 snr, t_s8 nflr)
4362 {
4363 moal_private *priv = NULL;
4364 struct tdls_peer *peer = NULL;
4365 unsigned long flags;
4366 priv = woal_bss_index_to_priv(pmoal, bss_index);
4367 if (priv && priv->enable_auto_tdls) {
4368 spin_lock_irqsave(&priv->tdls_lock, flags);
4369 list_for_each_entry (peer, &priv->tdls_list, link) {
4370 if (!memcmp(peer->peer_addr, peer_addr, ETH_ALEN)) {
4371 peer->rssi = nflr - snr;
4372 peer->rssi_jiffies = jiffies;
4373 break;
4374 }
4375 }
4376 spin_unlock_irqrestore(&priv->tdls_lock, flags);
4377 }
4378 }
4379
4380 /**
4381 * @brief Performs division of 64-bit num with base
4382 * @brief do_div does two things
4383 * @brief 1. modifies the 64-bit num in place with
4384 * @brief the quotient, i.e., num becomes quotient
4385 * @brief 2. do_div() returns the 32-bit reminder
4386 *
4387 * @param num dividend
4388 * @param base divisor
4389 * @return returns 64-bit quotient
4390 */
4391 t_u64 moal_do_div(t_u64 num, t_u32 base)
4392 {
4393 t_u64 val = num;
4394 do_div(val, base);
4395 return val;
4396 }
4397
4398 #if defined(DRV_EMBEDDED_AUTHENTICATOR) || defined(DRV_EMBEDDED_SUPPLICANT)
4399 /**
4400 * @brief Performs wait event
4401 *
4402 * @param pmoal t_void
4403 * @param bss_index index of priv
4404 * @return MLAN_STATUS_SUCCESS
4405 */
4406 mlan_status moal_wait_hostcmd_complete(t_void *pmoal, t_u32 bss_index)
4407 {
4408 mlan_status status = MLAN_STATUS_SUCCESS;
4409 moal_handle *handle = (moal_handle *)pmoal;
4410 moal_private *priv = woal_bss_index_to_priv(handle, bss_index);
4411 long time_left = 0;
4412
4413 ENTER();
4414
4415 if (!priv) {
4416 PRINTM(MERROR, "moal_wait_event: priv is null!\n");
4417 goto done;
4418 }
4419
4420 priv->hostcmd_wait_condition = MFALSE;
4421 time_left = wait_event_timeout(priv->hostcmd_wait_q,
4422 priv->hostcmd_wait_condition,
4423 MOAL_IOCTL_TIMEOUT);
4424
4425 if (!time_left) {
4426 PRINTM(MERROR, "moal_wait_event: wait timeout ");
4427 status = MLAN_STATUS_FAILURE;
4428 }
4429
4430 done:
4431 LEAVE();
4432 return status;
4433 }
4434
4435 /**
4436 * @brief wake up esa wait_q
4437 *
4438 * @param pmoal t_void
4439 * @param bss_index index of priv
4440 * @return MLAN_STATUS_SUCCESS
4441 */
4442 mlan_status moal_notify_hostcmd_complete(t_void *pmoal, t_u32 bss_index)
4443 {
4444 mlan_status status = MLAN_STATUS_SUCCESS;
4445 moal_handle *handle = (moal_handle *)pmoal;
4446 moal_private *priv = woal_bss_index_to_priv(handle, bss_index);
4447
4448 ENTER();
4449
4450 priv->hostcmd_wait_condition = MTRUE;
4451 wake_up(&priv->hostcmd_wait_q);
4452
4453 LEAVE();
4454 return status;
4455 }
4456 #endif
4457