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