bdd30aa9ee7272201016ef2d68ad80828b3ec9de
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / mt5931 / os / linux / gl_bow.c
1 /*
2 ** $Id: @(#) gl_bow.c@@
3 */
4
5 /*! \file   gl_bow.c
6     \brief  Main routines of Linux driver interface for 802.11 PAL (BT 3.0 + HS)
7
8     This file contains the main routines of Linux driver for MediaTek Inc. 802.11
9     Wireless LAN Adapters.
10 */
11
12
13
14 /*
15 ** $Log: gl_bow.c $
16  *
17  * 02 16 2012 chinghwa.yu
18  * [WCXRP00000065] Update BoW design and settings
19  * [ALPS00235223] [Rose][ICS][Cross Feature][AEE-IPANIC]The device reboot automatically and then the "KE" pops up after you turn on the "Airplane mode".(once)
20  *
21  * [Root Cause]
22  * PAL operates BOW char dev poll after BOW char dev is registered.
23  *
24  * [Solution]
25  * Rejects PAL char device operation after BOW is unregistered or when wlan GLUE_FLAG_HALT is set.
26  *
27  * This is a workaround for BOW driver robustness, happens only in ICS.
28  *
29  * Root cause should be fixed by CR [ALPS00231570]
30  *
31  * 02 03 2012 chinghwa.yu
32  * [WCXRP00000065] Update BoW design and settings
33  * [ALPS00118114] [Rose][ICS][Free Test][Bluetooth]The "KE" pops up after you turn on the airplane mode.(5/5)
34  *
35  * [Root Cause]
36  * PAL operates BOW char dev poll after BOW char dev is registered.
37  *
38  * [Solution]
39  * Rejects PAL char device operation after BOW is unregistered.
40  *
41  * Happens only in ICS.
42  *
43  * Notified PAL owener to reivew MTKBT/PAL closing BOW char dev procedure.
44  *
45  * [Side Effect]
46  * None.
47  *
48  * 01 16 2012 chinghwa.yu
49  * [WCXRP00000065] Update BoW design and settings
50  * Support BOW for 5GHz band.
51  *
52  * 11 10 2011 cp.wu
53  * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer
54  * 1. eliminaite direct calls to printk in porting layer.
55  * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms.
56  *
57  * 10 25 2011 chinghwa.yu
58  * [WCXRP00000065] Update BoW design and settings
59  * Modify ampc0 char device for major number 151 for all MT6575 projects.
60  *
61  * 07 28 2011 cp.wu
62  * [WCXRP00000884] [MT6620 Wi-Fi][Driver] Deprecate ioctl interface by unlocked ioctl
63  * unlocked_ioctl returns as long instead of int.
64  *
65  * 07 28 2011 cp.wu
66  * [WCXRP00000884] [MT6620 Wi-Fi][Driver] Deprecate ioctl interface by unlocked ioctl
67  * migrate to unlocked ioctl interface
68  *
69  * 04 12 2011 chinghwa.yu
70  * [WCXRP00000065] Update BoW design and settings
71  * Add WMM IE for BOW initiator data.
72  *
73  * 04 10 2011 chinghwa.yu
74  * [WCXRP00000065] Update BoW design and settings
75  * Change Link disconnection event procedure for hotspot and change skb length check to 1514 bytes.
76  *
77  * 04 09 2011 chinghwa.yu
78  * [WCXRP00000065] Update BoW design and settings
79  * Change Link connection event procedure and change skb length check to 1512 bytes.
80  *
81  * 03 27 2011 chinghwa.yu
82  * [WCXRP00000065] Update BoW design and settings
83  * Support multiple physical link.
84  *
85  * 03 06 2011 chinghwa.yu
86  * [WCXRP00000065] Update BoW design and settings
87  * Sync BOW Driver to latest person development branch version..
88  *
89  * 03 03 2011 jeffrey.chang
90  * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue
91  * support concurrent network
92  *
93  * 03 03 2011 jeffrey.chang
94  * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue
95  * replace alloc_netdev to alloc_netdev_mq for BoW
96  *
97  * 03 03 2011 jeffrey.chang
98  * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue
99  * modify net device relative functions to support multiple H/W queues
100  *
101  * 02 15 2011 chinghwa.yu
102  * [WCXRP00000065] Update BoW design and settings
103  * Update net register and BOW for concurrent features.
104  *
105  * 02 10 2011 chinghwa.yu
106  * [WCXRP00000065] Update BoW design and settings
107  * Fix kernel API change issue.
108  * Before ALPS 2.2 (2.2 included), kfifo_alloc() is
109  * struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock);
110  * After ALPS 2.3, kfifo_alloc() is changed to
111  * int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask);
112  *
113  * 02 09 2011 cp.wu
114  * [WCXRP00000430] [MT6620 Wi-Fi][Firmware][Driver] Create V1.2 branch for MT6620E1 and MT6620E3
115  * create V1.2 driver branch based on label MT6620_WIFI_DRIVER_V1_2_110209_1031
116  * with BOW and P2P enabled as default
117  *
118  * 02 08 2011 chinghwa.yu
119  * [WCXRP00000065] Update BoW design and settings
120  * Replace kfifo_get and kfifo_put with kfifo_out and kfifo_in.
121  * Update BOW get MAC status, remove returning event for AIS network type.
122  *
123  * 01 12 2011 cp.wu
124  * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP
125  * implementation of separate BT_OVER_WIFI data path.
126  *
127  * 01 12 2011 cp.wu
128  * [WCXRP00000356] [MT6620 Wi-Fi][Driver] fill mac header length for security frames 'cause hardware header translation needs such information
129  * fill mac header length information for 802.1x frames.
130  *
131  * 11 11 2010 chinghwa.yu
132  * [WCXRP00000065] Update BoW design and settings
133  * Fix BoW timer assert issue.
134  *
135  * 09 14 2010 chinghwa.yu
136  * NULL
137  * Add bowRunEventAAAComplete.
138  *
139  * 09 14 2010 cp.wu
140  * NULL
141  * correct typo: POLLOUT instead of POLL_OUT
142  *
143  * 09 13 2010 cp.wu
144  * NULL
145  * add waitq for poll() and read().
146  *
147  * 08 24 2010 chinghwa.yu
148  * NULL
149  * Update BOW for the 1st time.
150  *
151  * 07 08 2010 cp.wu
152  *
153  * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
154  *
155  * 06 06 2010 kevin.huang
156  * [WPD00003832][MT6620 5931] Create driver base
157  * [MT6620 5931] Create driver base
158  *
159  * 05 05 2010 cp.wu
160  * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support
161  * change variable names for multiple physical link to match with coding convention
162  *
163  * 05 05 2010 cp.wu
164  * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support
165  * multiple BoW interfaces need to compare with peer address
166  *
167  * 04 28 2010 cp.wu
168  * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support
169  * change prefix for data structure used to communicate with 802.11 PAL
170  * to avoid ambiguous naming with firmware interface
171  *
172  * 04 28 2010 cp.wu
173  * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support
174  * fix kalIndicateBOWEvent.
175  *
176  * 04 27 2010 cp.wu
177  * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support
178  * add multiple physical link support
179  *
180  * 04 13 2010 cp.wu
181  * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support
182  * add framework for BT-over-Wi-Fi support.
183  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * 1) prPendingCmdInfo is replaced by queue for multiple handler capability
184  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * 2) command sequence number is now increased atomically
185  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * 3) private data could be hold and taken use for other purpose
186 **
187 */
188
189 /*******************************************************************************
190 *                         C O M P I L E R   F L A G S
191 ********************************************************************************
192 */
193
194 /*******************************************************************************
195 *                    E X T E R N A L   R E F E R E N C E S
196 ********************************************************************************
197 */
198 #include "gl_os.h"
199 #include "debug.h"
200 #include "wlan_lib.h"
201 #include "gl_wext.h"
202 #include "precomp.h"
203 #include <linux/poll.h>
204 #include "bss.h"
205
206 #if CFG_ENABLE_BT_OVER_WIFI
207
208 /*******************************************************************************
209 *                              C O N S T A N T S
210 ********************************************************************************
211 */
212 /* @FIXME if there is command/event with payload length > 28 */
213 #define MAX_BUFFER_SIZE         (64)
214
215 /*******************************************************************************
216 *                             D A T A   T Y P E S
217 ********************************************************************************
218 */
219
220 /*******************************************************************************
221 *                            P U B L I C   D A T A
222 ********************************************************************************
223 */
224
225 #if CFG_BOW_TEST
226     UINT_32 g_u4PrevSysTime = 0;
227     UINT_32 g_u4CurrentSysTime = 0;
228     UINT_32 g_arBowRevPalPacketTime[11];
229 #endif
230
231 /*******************************************************************************
232 *                           P R I V A T E   D A T A
233 ********************************************************************************
234 */
235
236 // forward declarations
237 static ssize_t
238 mt6620_ampc_read(
239     IN struct file *filp,
240     IN char __user *buf,
241     IN size_t size,
242     IN OUT loff_t *ppos);
243
244 static ssize_t
245 mt6620_ampc_write(
246     IN struct file *filp,
247     OUT const char __user *buf,
248     IN size_t size,
249     IN OUT loff_t *ppos);
250
251 static long
252 mt6620_ampc_ioctl(
253     IN struct file *filp,
254     IN unsigned int cmd,
255     IN OUT unsigned long arg);
256
257 static unsigned int
258 mt6620_ampc_poll(
259     IN struct file *filp,
260     IN poll_table *wait);
261
262 static int
263 mt6620_ampc_open(
264     IN struct inode *inodep,
265     IN struct file *filp);
266
267 static int
268 mt6620_ampc_release(
269     IN struct inode *inodep,
270     IN struct file *filp);
271
272
273 // character file operations
274 static const struct file_operations mt6620_ampc_fops = {
275     //.owner              = THIS_MODULE,
276     .read               = mt6620_ampc_read,
277     .write              = mt6620_ampc_write,
278     .unlocked_ioctl     = mt6620_ampc_ioctl,
279     .poll               = mt6620_ampc_poll,
280     .open               = mt6620_ampc_open,
281     .release            = mt6620_ampc_release,
282 };
283
284 /*******************************************************************************
285 *                                 M A C R O S
286 ********************************************************************************
287 */
288
289 /*******************************************************************************
290 *                   F U N C T I O N   D E C L A R A T I O N S
291 ********************************************************************************
292 */
293
294 /*******************************************************************************
295 *                              F U N C T I O N S
296 ********************************************************************************
297 */
298
299
300 /*----------------------------------------------------------------------------*/
301 /*!
302 * \brief Register for character device to communicate with 802.11 PAL
303 *
304 * \param[in] prGlueInfo      Pointer to glue info
305 *
306 * \return   TRUE
307 *           FALSE
308 */
309 /*----------------------------------------------------------------------------*/
310 BOOLEAN
311 glRegisterAmpc (
312     IN P_GLUE_INFO_T prGlueInfo
313     )
314 {
315     ASSERT(prGlueInfo);
316
317     if(prGlueInfo->rBowInfo.fgIsRegistered == TRUE) {
318         return FALSE;
319     }
320     else {
321 #if 0
322         // 1. allocate major number dynamically
323
324     if(alloc_chrdev_region(&(prGlueInfo->rBowInfo.u4DeviceNumber),
325                     0,  // first minor number
326                     1,  // number
327                     GLUE_BOW_DEVICE_NAME) !=0)
328
329             return FALSE;
330 #endif
331
332 #if 1
333
334 #if defined (CONFIG_AMPC_CDEV_NUM)
335     prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(CONFIG_AMPC_CDEV_NUM, 0);
336 #else
337     prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(226, 0);
338 #endif
339
340     if(register_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber,
341                     1,  // number
342                     GLUE_BOW_DEVICE_NAME) !=0)
343
344             return FALSE;
345 #endif
346
347         // 2. spin-lock initialization
348  //       spin_lock_init(&(prGlueInfo->rBowInfo.rSpinLock));
349
350         // 3. initialize kfifo
351 /*        prGlueInfo->rBowInfo.prKfifo = kfifo_alloc(GLUE_BOW_KFIFO_DEPTH,
352                 GFP_KERNEL,
353                 &(prGlueInfo->rBowInfo.rSpinLock));*/
354             if ((kfifo_alloc((struct kfifo *) &(prGlueInfo->rBowInfo.rKfifo), GLUE_BOW_KFIFO_DEPTH, GFP_KERNEL)))
355                 goto fail_kfifo_alloc;
356
357 //        if(prGlueInfo->rBowInfo.prKfifo == NULL)
358         if(&(prGlueInfo->rBowInfo.rKfifo) == NULL)
359             goto fail_kfifo_alloc;
360
361         // 4. initialize cdev
362         cdev_init(&(prGlueInfo->rBowInfo.cdev), &mt6620_ampc_fops);
363        // prGlueInfo->rBowInfo.cdev.owner = THIS_MODULE;
364         prGlueInfo->rBowInfo.cdev.ops = &mt6620_ampc_fops;
365
366         // 5. add character device
367         if(cdev_add(&(prGlueInfo->rBowInfo.cdev),
368                     prGlueInfo->rBowInfo.u4DeviceNumber,
369                     1))
370             goto fail_cdev_add;
371
372
373         // 6. in queue initialization
374         init_waitqueue_head(&(prGlueInfo->rBowInfo.outq));
375
376         // 7. finish
377         prGlueInfo->rBowInfo.fgIsRegistered = TRUE;
378         return TRUE;
379
380 fail_cdev_add:
381             kfifo_free(&(prGlueInfo->rBowInfo.rKfifo));
382 //        kfifo_free(prGlueInfo->rBowInfo.prKfifo);
383 fail_kfifo_alloc:
384         unregister_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1);
385         return FALSE;
386     }
387 } /* end of glRegisterAmpc */
388
389
390 /*----------------------------------------------------------------------------*/
391 /*!
392 * \brief Unregister character device for communicating with 802.11 PAL
393 *
394 * \param[in] prGlueInfo      Pointer to glue info
395 *
396 * \return   TRUE
397 *           FALSE
398 */
399 /*----------------------------------------------------------------------------*/
400 BOOLEAN
401 glUnregisterAmpc (
402     IN P_GLUE_INFO_T prGlueInfo
403     )
404 {
405     ASSERT(prGlueInfo);
406
407     if(prGlueInfo->rBowInfo.fgIsRegistered == FALSE) {
408         return FALSE;
409     }
410     else {
411         prGlueInfo->rBowInfo.fgIsRegistered = FALSE;
412
413         // 1. free netdev if necessary
414 #if CFG_BOW_SEPARATE_DATA_PATH
415         kalUninitBowDevice(prGlueInfo);
416 #endif
417
418         // 2. removal of character device
419         cdev_del(&(prGlueInfo->rBowInfo.cdev));
420
421         // 3. free kfifo
422 //        kfifo_free(prGlueInfo->rBowInfo.prKfifo);
423         kfifo_free(&(prGlueInfo->rBowInfo.rKfifo));
424 //        prGlueInfo->rBowInfo.prKfifo = NULL;
425 //        prGlueInfo->rBowInfo.rKfifo = NULL;
426
427         // 4. free device number
428         unregister_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1);
429
430         return TRUE;
431     }
432 } /* end of glUnregisterAmpc */
433
434
435 /*----------------------------------------------------------------------------*/
436 /*!
437 * \brief read handler for character device to communicate with 802.11 PAL
438 *
439 * \param[in]
440 * \return
441 *           Follows Linux Character Device Interface
442 *
443 */
444 /*----------------------------------------------------------------------------*/
445 static ssize_t
446 mt6620_ampc_read(
447     IN struct file *filp,
448     IN char __user *buf,
449     IN size_t size,
450     IN OUT loff_t *ppos)
451 {
452     UINT_8 aucBuffer[MAX_BUFFER_SIZE];
453     ssize_t retval;
454
455     P_GLUE_INFO_T prGlueInfo;
456     prGlueInfo = (P_GLUE_INFO_T)(filp->private_data);
457
458     ASSERT(prGlueInfo);
459
460     if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->u4Flag & GLUE_FLAG_HALT)) {
461         return -EFAULT;
462     }
463
464     // size check
465 //    if(kfifo_len(prGlueInfo->rBowInfo.prKfifo) >= size)
466     if(kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)) >= size)
467         retval = size;
468     else
469         retval = kfifo_len(&(prGlueInfo->rBowInfo.rKfifo));
470 //        retval = kfifo_len(prGlueInfo->rBowInfo.prKfifo);
471
472 //    kfifo_get(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval);
473 //    kfifo_out(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval);
474     if (!(kfifo_out(&(prGlueInfo->rBowInfo.rKfifo), aucBuffer, retval)))
475         retval = -EIO;
476
477     if(copy_to_user(buf, aucBuffer, retval))
478         retval = -EIO;
479
480     return retval;
481 }
482
483
484 /*----------------------------------------------------------------------------*/
485 /*!
486 * \brief write handler for character device to communicate with 802.11 PAL
487 *
488 * \param[in]
489 * \return
490 *           Follows Linux Character Device Interface
491 *
492 */
493 /*----------------------------------------------------------------------------*/
494 static ssize_t
495 mt6620_ampc_write(
496     IN struct file *filp,
497     OUT const char __user *buf,
498     IN size_t size,
499     IN OUT loff_t *ppos)
500 {
501 #if CFG_BOW_TEST
502     UINT_8 i;
503 #endif
504
505     UINT_8 aucBuffer[MAX_BUFFER_SIZE];
506     P_AMPC_COMMAND prCmd;
507     P_GLUE_INFO_T prGlueInfo;
508
509     prGlueInfo = (P_GLUE_INFO_T)(filp->private_data);
510     ASSERT(prGlueInfo);
511
512     if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->u4Flag & GLUE_FLAG_HALT)) {
513         return -EFAULT;
514     }
515
516     if(size > MAX_BUFFER_SIZE)
517         return -EINVAL;
518     else if(copy_from_user(aucBuffer, buf, size))
519         return -EIO;
520
521 #if CFG_BOW_TEST
522     DBGLOG(BOW, EVENT, ("AMP driver CMD buffer size : %d.\n", size));
523
524     for(i = 0; i < MAX_BUFFER_SIZE; i++)
525     {
526         DBGLOG(BOW, EVENT, ("AMP write content : 0x%x.\n", aucBuffer[i]));
527     }
528
529     DBGLOG(BOW, EVENT, ("BoW CMD write.\n"));
530 #endif
531
532     prCmd = (P_AMPC_COMMAND) aucBuffer;
533
534  #if CFG_BOW_TEST
535     DBGLOG(BOW, EVENT, ("AMP write content payload length : %d.\n", prCmd->rHeader.u2PayloadLength));
536
537     DBGLOG(BOW, EVENT, ("AMP write content header length : %d.\n", sizeof(AMPC_COMMAND_HEADER_T)));
538  #endif
539
540     // size check
541     if(prCmd->rHeader.u2PayloadLength + sizeof(AMPC_COMMAND_HEADER_T) != size)
542     {
543   #if CFG_BOW_TEST
544         DBGLOG(BOW, EVENT, ("Wrong CMD total length.\n"));
545   #endif
546
547         return -EINVAL;
548     }
549
550     if(wlanbowHandleCommand(prGlueInfo->prAdapter, prCmd) == WLAN_STATUS_SUCCESS)
551         return size;
552     else
553         return -EINVAL;
554 }
555
556
557 /*----------------------------------------------------------------------------*/
558 /*!
559 * \brief ioctl handler for character device to communicate with 802.11 PAL
560 *
561 * \param[in]
562 * \return
563 *           Follows Linux Character Device Interface
564 *
565 */
566 /*----------------------------------------------------------------------------*/
567 static long
568 mt6620_ampc_ioctl(
569     IN struct file *filp,
570     IN unsigned int cmd,
571     IN OUT unsigned long arg)
572 {
573     int err = 0;
574     P_GLUE_INFO_T prGlueInfo;
575     prGlueInfo = (P_GLUE_INFO_T)(filp->private_data);
576
577     ASSERT(prGlueInfo);
578
579     if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->u4Flag & GLUE_FLAG_HALT)) {
580         return -EFAULT;
581     }
582
583     // permission check
584     if(_IOC_DIR(cmd) & _IOC_READ)
585         err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
586     else if (_IOC_DIR(cmd) & _IOC_WRITE)
587         err =  !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
588     if (err)
589         return -EFAULT;
590
591     // no ioctl is implemented yet
592     return 0;
593 }
594
595
596 /*----------------------------------------------------------------------------*/
597 /*!
598 * \brief ioctl handler for character device to communicate with 802.11 PAL
599 *
600 * \param[in]
601 * \return
602 *           Follows Linux Character Device Interface
603 *
604 */
605 /*----------------------------------------------------------------------------*/
606 static unsigned int
607 mt6620_ampc_poll(
608     IN struct file *filp,
609     IN poll_table *wait)
610 {
611     unsigned int retval;
612     P_GLUE_INFO_T prGlueInfo;
613     prGlueInfo = (P_GLUE_INFO_T)(filp->private_data);
614
615     ASSERT(prGlueInfo);
616
617     if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->u4Flag & GLUE_FLAG_HALT)) {
618         return -EFAULT;
619     }
620
621     poll_wait(filp, &prGlueInfo->rBowInfo.outq, wait);
622
623     retval = (POLLOUT | POLLWRNORM); // always accepts incoming command packets
624
625 //    DBGLOG(BOW, EVENT, ("mt6620_ampc_pol, POLLOUT | POLLWRNORM, %x\n", retval));
626
627 //    if(kfifo_len(prGlueInfo->rBowInfo.prKfifo) > 0)
628     if(kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)) > 0)
629     {
630         retval |= (POLLIN | POLLRDNORM);
631
632 //        DBGLOG(BOW, EVENT, ("mt6620_ampc_pol, POLLIN | POLLRDNORM, %x\n", retval));
633
634     }
635
636     return retval;
637 }
638
639
640 /*----------------------------------------------------------------------------*/
641 /*!
642 * \brief open handler for character device to communicate with 802.11 PAL
643 *
644 * \param[in]
645 * \return
646 *           Follows Linux Character Device Interface
647 *
648 */
649 /*----------------------------------------------------------------------------*/
650 static int
651 mt6620_ampc_open(
652     IN struct inode *inodep,
653     IN struct file *filp)
654 {
655      P_GLUE_INFO_T  prGlueInfo;
656      P_GL_BOW_INFO  prBowInfo;
657
658      prBowInfo = container_of(inodep->i_cdev, GL_BOW_INFO, cdev);
659      ASSERT(prBowInfo);
660
661      prGlueInfo = container_of(prBowInfo, GLUE_INFO_T, rBowInfo);
662      ASSERT(prGlueInfo);
663
664      // set-up private data
665      filp->private_data = prGlueInfo;
666
667      return 0;
668 }
669
670
671 /*----------------------------------------------------------------------------*/
672 /*!
673 * \brief close handler for character device to communicate with 802.11 PAL
674 *
675 * \param[in]
676 * \return
677 *           Follows Linux Character Device Interface
678 *
679 */
680 /*----------------------------------------------------------------------------*/
681 static int
682 mt6620_ampc_release(
683     IN struct inode *inodep,
684     IN struct file *filp)
685 {
686     P_GLUE_INFO_T prGlueInfo;
687     prGlueInfo = (P_GLUE_INFO_T)(filp->private_data);
688
689     ASSERT(prGlueInfo);
690
691     return 0;
692 }
693
694
695 /*----------------------------------------------------------------------------*/
696 /*!
697 * \brief to indicate event for Bluetooth over Wi-Fi
698 *
699 * \param[in]
700 *           prGlueInfo
701 *           prEvent
702 * \return
703 *           none
704 */
705 /*----------------------------------------------------------------------------*/
706 VOID
707 kalIndicateBOWEvent(
708     IN P_GLUE_INFO_T        prGlueInfo,
709     IN P_AMPC_EVENT prEvent
710     )
711 {
712     size_t u4AvailSize, u4EventSize;
713
714     ASSERT(prGlueInfo);
715     ASSERT(prEvent);
716
717     // check device
718     if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->u4Flag & GLUE_FLAG_HALT)) {
719         return;
720     }
721
722 /*    u4AvailSize =
723         GLUE_BOW_KFIFO_DEPTH - kfifo_len(prGlueInfo->rBowInfo.prKfifo);*/
724
725     u4AvailSize =
726         GLUE_BOW_KFIFO_DEPTH - kfifo_len(&(prGlueInfo->rBowInfo.rKfifo));
727
728
729     u4EventSize =
730         prEvent->rHeader.u2PayloadLength + sizeof(AMPC_EVENT_HEADER_T);
731
732     // check kfifo availability
733     if(u4AvailSize < u4EventSize) {
734         DBGLOG(BOW, EVENT, ("[bow] no space for event: %d/%d\n",
735                 u4EventSize,
736                 u4AvailSize));
737         return;
738     }
739
740     // queue into kfifo
741 //    kfifo_put(prGlueInfo->rBowInfo.prKfifo, (PUINT_8)prEvent, u4EventSize);
742 //    kfifo_in(prGlueInfo->rBowInfo.prKfifo, (PUINT_8)prEvent, u4EventSize);
743     kfifo_in(&(prGlueInfo->rBowInfo.rKfifo), (PUINT_8)prEvent, u4EventSize);
744     wake_up_interruptible(&(prGlueInfo->rBowInfo.outq));
745
746     return;
747 }
748
749 /*----------------------------------------------------------------------------*/
750 /*!
751 * \brief to retrieve Bluetooth-over-Wi-Fi state from glue layer
752 *
753 * \param[in]
754 *           prGlueInfo
755 *           rPeerAddr
756 * \return
757 *           ENUM_BOW_DEVICE_STATE
758 */
759 /*----------------------------------------------------------------------------*/
760 ENUM_BOW_DEVICE_STATE
761 kalGetBowState (
762     IN P_GLUE_INFO_T        prGlueInfo,
763     IN UINT_8                     aucPeerAddress[6]
764     )
765 {
766     UINT_8 i;
767
768     ASSERT(prGlueInfo);
769
770 #if CFG_BOW_TEST
771     DBGLOG(BOW, EVENT, ("kalGetBowState.\n"));
772 #endif
773
774     for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++)
775     {
776         if(EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0)
777         {
778
779 #if CFG_BOW_TEST
780     DBGLOG(BOW, EVENT, ("kalGetBowState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", i,
781         aucPeerAddress[0],
782         aucPeerAddress[1],
783         aucPeerAddress[2],
784         aucPeerAddress[3],
785         aucPeerAddress[4],
786         aucPeerAddress[5]));
787
788     DBGLOG(BOW, EVENT, ("kalGetBowState, prGlueInfo->rBowInfo.aeState %x, %x.\n", i, prGlueInfo->rBowInfo.aeState[i]));
789
790 #endif
791
792             return prGlueInfo->rBowInfo.aeState[i];
793         }
794     }
795
796     return BOW_DEVICE_STATE_DISCONNECTED;
797 }
798
799
800 /*----------------------------------------------------------------------------*/
801 /*!
802 * \brief to set Bluetooth-over-Wi-Fi state in glue layer
803 *
804 * \param[in]
805 *           prGlueInfo
806 *           eBowState
807 *           rPeerAddr
808 * \return
809 *           none
810 */
811 /*----------------------------------------------------------------------------*/
812 BOOLEAN
813 kalSetBowState (
814     IN P_GLUE_INFO_T            prGlueInfo,
815     IN ENUM_BOW_DEVICE_STATE    eBowState,
816     IN UINT_8                                 aucPeerAddress[6]
817     )
818 {
819     UINT_8 i;
820
821     ASSERT(prGlueInfo);
822
823 #if CFG_BOW_TEST
824     DBGLOG(BOW, EVENT, ("kalSetBowState.\n"));
825
826     DBGLOG(BOW, EVENT, ("kalSetBowState, prGlueInfo->rBowInfo.arPeerAddr, %x:%x:%x:%x:%x:%x.\n",
827         prGlueInfo->rBowInfo.arPeerAddr[0],
828         prGlueInfo->rBowInfo.arPeerAddr[1],
829         prGlueInfo->rBowInfo.arPeerAddr[2],
830         prGlueInfo->rBowInfo.arPeerAddr[3],
831         prGlueInfo->rBowInfo.arPeerAddr[4],
832         prGlueInfo->rBowInfo.arPeerAddr[5]));
833
834     DBGLOG(BOW, EVENT, ("kalSetBowState, aucPeerAddress, %x:%x:%x:%x:%x:%x.\n",
835         aucPeerAddress[0],
836         aucPeerAddress[1],
837         aucPeerAddress[2],
838         aucPeerAddress[3],
839         aucPeerAddress[4],
840         aucPeerAddress[5]));
841 #endif
842
843     for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++)
844     {
845         if(EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0)
846         {
847             prGlueInfo->rBowInfo.aeState[i] = eBowState;
848
849 #if CFG_BOW_TEST
850     DBGLOG(BOW, EVENT, ("kalSetBowState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", i,
851         aucPeerAddress[0],
852         aucPeerAddress[1],
853         aucPeerAddress[2],
854         aucPeerAddress[3],
855         aucPeerAddress[4],
856         aucPeerAddress[5]));
857
858     DBGLOG(BOW, EVENT, ("kalSetBowState, prGlueInfo->rBowInfo.aeState %x, %x.\n", i, prGlueInfo->rBowInfo.aeState[i]));
859 #endif
860
861             return TRUE;
862         }
863     }
864
865     return FALSE;
866 }
867
868
869 /*----------------------------------------------------------------------------*/
870 /*!
871 * \brief to retrieve Bluetooth-over-Wi-Fi global state
872 *
873 * \param[in]
874 *           prGlueInfo
875 *
876 * \return
877 *           BOW_DEVICE_STATE_DISCONNECTED
878 *               in case there is no BoW connection or
879 *               BoW connection under initialization
880 *
881 *           BOW_DEVICE_STATE_STARTING
882 *               in case there is no BoW connection but
883 *               some BoW connection under initialization
884 *
885 *           BOW_DEVICE_STATE_CONNECTED
886 *               in case there is any BoW connection available
887 */
888 /*----------------------------------------------------------------------------*/
889 ENUM_BOW_DEVICE_STATE
890 kalGetBowGlobalState (
891     IN P_GLUE_INFO_T    prGlueInfo
892     )
893 {
894     UINT_32 i;
895
896     ASSERT(prGlueInfo);
897
898
899 //Henry, can reduce this logic to indentify state change
900
901     for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++) {
902         if(prGlueInfo->rBowInfo.aeState[i] == BOW_DEVICE_STATE_CONNECTED) {
903             return BOW_DEVICE_STATE_CONNECTED;
904         }
905     }
906
907     for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++) {
908         if(prGlueInfo->rBowInfo.aeState[i] == BOW_DEVICE_STATE_STARTING) {
909             return BOW_DEVICE_STATE_STARTING;
910         }
911     }
912
913     return BOW_DEVICE_STATE_DISCONNECTED;
914 }
915
916 /*----------------------------------------------------------------------------*/
917 /*!
918 * \brief to retrieve Bluetooth-over-Wi-Fi operating frequency
919 *
920 * \param[in]
921 *           prGlueInfo
922 *
923 * \return
924 *           in unit of KHz
925 */
926 /*----------------------------------------------------------------------------*/
927 UINT_32
928 kalGetBowFreqInKHz(
929     IN P_GLUE_INFO_T            prGlueInfo
930     )
931 {
932     ASSERT(prGlueInfo);
933
934     return prGlueInfo->rBowInfo.u4FreqInKHz;
935 }
936
937
938 /*----------------------------------------------------------------------------*/
939 /*!
940 * \brief to retrieve Bluetooth-over-Wi-Fi role
941 *
942 * \param[in]
943 *           prGlueInfo
944 *
945 * \return
946 *           0: Responder
947 *           1: Initiator
948 */
949 /*----------------------------------------------------------------------------*/
950 UINT_8
951 kalGetBowRole(
952     IN P_GLUE_INFO_T        prGlueInfo,
953     IN PARAM_MAC_ADDRESS    rPeerAddr
954     )
955 {
956     UINT_32 i;
957
958     ASSERT(prGlueInfo);
959
960     for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++) {
961         if(EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr[i], rPeerAddr) == 0) {
962             return prGlueInfo->rBowInfo.aucRole[i];
963         }
964     }
965
966     return 0;
967 }
968
969
970 /*----------------------------------------------------------------------------*/
971 /*!
972 * \brief to set Bluetooth-over-Wi-Fi role
973 *
974 * \param[in]
975 *           prGlueInfo
976 *           ucRole
977 *                   0: Responder
978 *                   1: Initiator
979 * \return
980 *           none
981 */
982 /*----------------------------------------------------------------------------*/
983 VOID
984 kalSetBowRole(
985     IN P_GLUE_INFO_T        prGlueInfo,
986     IN UINT_8               ucRole,
987     IN PARAM_MAC_ADDRESS    rPeerAddr
988     )
989 {
990     UINT_32 i;
991
992     ASSERT(prGlueInfo);
993     ASSERT(ucRole <= 1);
994
995     for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++) {
996         if(EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr[i], rPeerAddr) == 0) {
997             prGlueInfo->rBowInfo.aucRole[i] = ucRole; //Henry, 0 : Responder, 1 : Initiator
998         }
999     }
1000 }
1001
1002
1003 /*----------------------------------------------------------------------------*/
1004 /*!
1005 * \brief to get available Bluetooth-over-Wi-Fi physical link number
1006 *
1007 * \param[in]
1008 *           prGlueInfo
1009 * \return
1010 *           UINT_32
1011 *               how many physical links are aviailable
1012 */
1013 /*----------------------------------------------------------------------------*/
1014 UINT_8
1015 kalGetBowAvailablePhysicalLinkCount(
1016     IN P_GLUE_INFO_T        prGlueInfo
1017     )
1018 {
1019     UINT_8 i;
1020     UINT_8 ucLinkCount = 0;
1021
1022     ASSERT(prGlueInfo);
1023
1024     for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++) {
1025         if(prGlueInfo->rBowInfo.aeState[i] == BOW_DEVICE_STATE_DISCONNECTED) {
1026             ucLinkCount++;
1027         }
1028     }
1029
1030 #if 0//CFG_BOW_TEST
1031     DBGLOG(BOW, EVENT, ("kalGetBowAvailablePhysicalLinkCount, ucLinkCount, %c.\n", ucLinkCount));
1032 #endif
1033
1034     return ucLinkCount;
1035 }
1036
1037 #if CFG_BOW_SEPARATE_DATA_PATH
1038
1039 /* Net Device Hooks */
1040 /*----------------------------------------------------------------------------*/
1041 /*!
1042  * \brief A function for net_device open (ifup)
1043  *
1044  * \param[in] prDev      Pointer to struct net_device.
1045  *
1046  * \retval 0     The execution succeeds.
1047  * \retval < 0   The execution failed.
1048  */
1049 /*----------------------------------------------------------------------------*/
1050 static int
1051 bowOpen(
1052     IN struct net_device *prDev
1053     )
1054 {
1055     P_GLUE_INFO_T prGlueInfo = NULL;
1056     P_ADAPTER_T prAdapter = NULL;
1057
1058     ASSERT(prDev);
1059
1060     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
1061     ASSERT(prGlueInfo);
1062
1063     prAdapter = prGlueInfo->prAdapter;
1064     ASSERT(prAdapter);
1065
1066     /* 2. carrier on & start TX queue */
1067     netif_carrier_on(prDev);
1068     netif_tx_start_all_queues(prDev);
1069
1070     return 0; /* success */
1071 }
1072
1073
1074 /*----------------------------------------------------------------------------*/
1075 /*!
1076  * \brief A function for net_device stop (ifdown)
1077  *
1078  * \param[in] prDev      Pointer to struct net_device.
1079  *
1080  * \retval 0     The execution succeeds.
1081  * \retval < 0   The execution failed.
1082  */
1083 /*----------------------------------------------------------------------------*/
1084 static int
1085 bowStop(
1086     IN struct net_device *prDev
1087     )
1088 {
1089     P_GLUE_INFO_T prGlueInfo = NULL;
1090     P_ADAPTER_T prAdapter = NULL;
1091
1092     ASSERT(prDev);
1093
1094     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
1095     ASSERT(prGlueInfo);
1096
1097     prAdapter = prGlueInfo->prAdapter;
1098     ASSERT(prAdapter);
1099
1100     /* 1. stop TX queue */
1101     netif_tx_stop_all_queues(prDev);
1102
1103     /* 2. turn of carrier */
1104     if(netif_carrier_ok(prDev)) {
1105         netif_carrier_off(prDev);
1106     }
1107
1108     return 0;
1109 };
1110
1111
1112 /*----------------------------------------------------------------------------*/
1113 /*!
1114  * \brief This function is TX entry point of NET DEVICE.
1115  *
1116  * \param[in] prSkb  Pointer of the sk_buff to be sent
1117  * \param[in] prDev  Pointer to struct net_device
1118  *
1119  * \retval NETDEV_TX_OK - on success.
1120  * \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer.
1121  */
1122 /*----------------------------------------------------------------------------*/
1123 static int
1124 bowHardStartXmit(
1125     IN struct sk_buff *prSkb,
1126     IN struct net_device *prDev
1127     )
1128 {
1129     P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
1130
1131     P_QUE_ENTRY_T prQueueEntry = NULL;
1132     P_QUE_T prTxQueue = NULL;
1133     UINT_16 u2QueueIdx = 0;
1134     UINT_8 ucDSAP, ucSSAP, ucControl;
1135     UINT_8 aucOUI[3];
1136     PUINT_8 aucLookAheadBuf = NULL;
1137
1138 #if CFG_BOW_TEST
1139     UINT_32 i;
1140 #endif
1141
1142     GLUE_SPIN_LOCK_DECLARATION();
1143
1144     ASSERT(prSkb);
1145     ASSERT(prDev);
1146     ASSERT(prGlueInfo);
1147
1148     aucLookAheadBuf = prSkb->data;
1149
1150     ucDSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET];
1151     ucSSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 1];
1152     ucControl = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 2];
1153     aucOUI[0] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET];
1154     aucOUI[1] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 1];
1155     aucOUI[2] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 2];
1156
1157     if (!(ucDSAP == ETH_LLC_DSAP_SNAP &&
1158             ucSSAP == ETH_LLC_SSAP_SNAP &&
1159             ucControl == ETH_LLC_CONTROL_UNNUMBERED_INFORMATION &&
1160             aucOUI[0] == ETH_SNAP_BT_SIG_OUI_0 &&
1161             aucOUI[1] == ETH_SNAP_BT_SIG_OUI_1 &&
1162             aucOUI[2] == ETH_SNAP_BT_SIG_OUI_2) || (prSkb->len > 1514))
1163     {
1164
1165 #if CFG_BOW_TEST
1166         DBGLOG(BOW, TRACE, ("Invalid BOW packet, skip tx\n"));
1167 #endif
1168
1169         dev_kfree_skb(prSkb);
1170         return NETDEV_TX_OK;
1171      }
1172
1173     if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
1174         DBGLOG(BOW, TRACE, ("GLUE_FLAG_HALT skip tx\n"));
1175         dev_kfree_skb(prSkb);
1176         return NETDEV_TX_OK;
1177     }
1178
1179     prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb);
1180     prTxQueue = &prGlueInfo->rTxQueue;
1181
1182 #if CFG_BOW_TEST
1183     DBGLOG(BOW, TRACE, ("Tx sk_buff->len: %d\n", prSkb->len));
1184     DBGLOG(BOW, TRACE, ("Tx sk_buff->data_len: %d\n", prSkb->data_len));
1185     DBGLOG(BOW, TRACE, ("Tx sk_buff->data:\n"));
1186
1187     for(i = 0; i < prSkb->len; i++)
1188     {
1189         DBGLOG(BOW, TRACE, ("%4x", prSkb->data[i]));
1190
1191         if((i+1)%16 ==0)
1192         {
1193             DBGLOG(BOW, TRACE, ("\n"));
1194         }
1195     }
1196
1197     DBGLOG(BOW, TRACE, ("\n");
1198 #endif
1199
1200 #if CFG_BOW_TEST
1201 //    g_u4CurrentSysTime = (OS_SYSTIME)kalGetTimeTick();
1202
1203     g_u4CurrentSysTime = (OS_SYSTIME) jiffies_to_usecs(jiffies);
1204
1205     i = g_u4CurrentSysTime - g_u4PrevSysTime;
1206
1207     if ( (i >> 10) > 0)
1208     {
1209         i = 10;
1210     }
1211     else
1212     {
1213         i = i >> 7;
1214     }
1215
1216     g_arBowRevPalPacketTime[i]++;
1217
1218     g_u4PrevSysTime = g_u4CurrentSysTime;
1219
1220 #endif
1221
1222     if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb) == FALSE) {
1223         GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE);
1224         QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry);
1225         GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE);
1226
1227
1228         GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum);
1229         GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_BOW_INDEX][u2QueueIdx]);
1230
1231         if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_BOW_INDEX][u2QueueIdx] >= CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) {
1232             netif_stop_subqueue(prDev, u2QueueIdx);
1233         }
1234     }
1235     else {
1236         GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum);
1237     }
1238
1239     kalSetEvent(prGlueInfo);
1240
1241     /* For Linux, we'll always return OK FLAG, because we'll free this skb by ourself */
1242     return NETDEV_TX_OK;
1243 }
1244
1245
1246 // callbacks for netdevice
1247 static const struct net_device_ops bow_netdev_ops = {
1248     .ndo_open               = bowOpen,
1249     .ndo_stop               = bowStop,
1250     .ndo_start_xmit         = bowHardStartXmit,
1251 };
1252
1253 /*----------------------------------------------------------------------------*/
1254 /*!
1255 * \brief initialize net device for Bluetooth-over-Wi-Fi
1256 *
1257 * \param[in]
1258 *           prGlueInfo
1259 *           prDevName
1260 *
1261 * \return
1262 *           TRUE
1263 *           FALSE
1264 */
1265 /*----------------------------------------------------------------------------*/
1266 BOOLEAN
1267 kalInitBowDevice(
1268     IN P_GLUE_INFO_T        prGlueInfo,
1269     IN const char           *prDevName
1270     )
1271 {
1272     P_ADAPTER_T prAdapter;
1273     P_GL_HIF_INFO_T prHif;
1274     PARAM_MAC_ADDRESS rMacAddr;
1275
1276     ASSERT(prGlueInfo);
1277     ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE);
1278
1279     prAdapter = prGlueInfo->prAdapter;
1280     ASSERT(prAdapter);
1281
1282     prHif = &prGlueInfo->rHifInfo;
1283     ASSERT(prHif);
1284
1285     if(prGlueInfo->rBowInfo.fgIsNetRegistered == FALSE) {
1286         prGlueInfo->rBowInfo.prDevHandler = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), prDevName, ether_setup, CFG_MAX_TXQ_NUM);
1287
1288         if (!prGlueInfo->rBowInfo.prDevHandler) {
1289             return FALSE;
1290         }
1291         else {
1292             /* 1. setup netdev */
1293             /* 1.1 Point to shared glue structure */
1294             *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->rBowInfo.prDevHandler)) = prGlueInfo;
1295
1296             /* 1.2 fill hardware address */
1297             COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr);
1298             rMacAddr[0] |= 0x2; // change to local administrated address
1299             memcpy(prGlueInfo->rBowInfo.prDevHandler->dev_addr, rMacAddr, ETH_ALEN);
1300             memcpy(prGlueInfo->rBowInfo.prDevHandler->perm_addr, prGlueInfo->rBowInfo.prDevHandler->dev_addr, ETH_ALEN);
1301
1302             /* 1.3 register callback functions */
1303             prGlueInfo->rBowInfo.prDevHandler->netdev_ops = &bow_netdev_ops;
1304
1305 #if (MTK_WCN_HIF_SDIO == 0)
1306             SET_NETDEV_DEV(prGlueInfo->rBowInfo.prDevHandler, &(prHif->func->dev));
1307 #endif
1308
1309             register_netdev(prGlueInfo->rBowInfo.prDevHandler);
1310
1311             /* 2. net device initialize */
1312             netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler);
1313             netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler);
1314
1315             /* 3. finish */
1316             prGlueInfo->rBowInfo.fgIsNetRegistered = TRUE;
1317         }
1318     }
1319
1320     return TRUE;
1321 }
1322
1323
1324 /*----------------------------------------------------------------------------*/
1325 /*!
1326 * \brief uninitialize net device for Bluetooth-over-Wi-Fi
1327 *
1328 * \param[in]
1329 *           prGlueInfo
1330 *
1331 * \return
1332 *           TRUE
1333 *           FALSE
1334 */
1335 /*----------------------------------------------------------------------------*/
1336 BOOLEAN
1337 kalUninitBowDevice(
1338     IN P_GLUE_INFO_T        prGlueInfo
1339     )
1340 {
1341     ASSERT(prGlueInfo);
1342     //ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE);
1343
1344     if(prGlueInfo->rBowInfo.fgIsNetRegistered == TRUE) {
1345
1346         prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE;
1347
1348         if(netif_carrier_ok(prGlueInfo->rBowInfo.prDevHandler)) {
1349             netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler);
1350         }
1351
1352         netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler);
1353
1354         /* netdevice unregistration & free */
1355         unregister_netdev(prGlueInfo->rBowInfo.prDevHandler);
1356         free_netdev(prGlueInfo->rBowInfo.prDevHandler);
1357         prGlueInfo->rBowInfo.prDevHandler = NULL;
1358
1359         return TRUE;
1360
1361     }
1362     else {
1363         return FALSE;
1364     }
1365 }
1366
1367 #endif // CFG_BOW_SEPARATE_DATA_PATH
1368 #endif // CFG_ENABLE_BT_OVER_WIFI
1369