2 ** $Id: @(#) gl_bow.c@@
6 \brief Main routines of Linux driver interface for 802.11 PAL (BT 3.0 + HS)
8 This file contains the main routines of Linux driver for MediaTek Inc. 802.11
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)
22 * PAL operates BOW char dev poll after BOW char dev is registered.
25 * Rejects PAL char device operation after BOW is unregistered or when wlan GLUE_FLAG_HALT is set.
27 * This is a workaround for BOW driver robustness, happens only in ICS.
29 * Root cause should be fixed by CR [ALPS00231570]
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)
36 * PAL operates BOW char dev poll after BOW char dev is registered.
39 * Rejects PAL char device operation after BOW is unregistered.
41 * Happens only in ICS.
43 * Notified PAL owener to reivew MTKBT/PAL closing BOW char dev procedure.
48 * 01 16 2012 chinghwa.yu
49 * [WCXRP00000065] Update BoW design and settings
50 * Support BOW for 5GHz band.
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.
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.
62 * [WCXRP00000884] [MT6620 Wi-Fi][Driver] Deprecate ioctl interface by unlocked ioctl
63 * unlocked_ioctl returns as long instead of int.
66 * [WCXRP00000884] [MT6620 Wi-Fi][Driver] Deprecate ioctl interface by unlocked ioctl
67 * migrate to unlocked ioctl interface
69 * 04 12 2011 chinghwa.yu
70 * [WCXRP00000065] Update BoW design and settings
71 * Add WMM IE for BOW initiator data.
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.
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.
81 * 03 27 2011 chinghwa.yu
82 * [WCXRP00000065] Update BoW design and settings
83 * Support multiple physical link.
85 * 03 06 2011 chinghwa.yu
86 * [WCXRP00000065] Update BoW design and settings
87 * Sync BOW Driver to latest person development branch version..
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
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
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
101 * 02 15 2011 chinghwa.yu
102 * [WCXRP00000065] Update BoW design and settings
103 * Update net register and BOW for concurrent features.
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);
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
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.
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.
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.
131 * 11 11 2010 chinghwa.yu
132 * [WCXRP00000065] Update BoW design and settings
133 * Fix BoW timer assert issue.
135 * 09 14 2010 chinghwa.yu
137 * Add bowRunEventAAAComplete.
141 * correct typo: POLLOUT instead of POLL_OUT
145 * add waitq for poll() and read().
147 * 08 24 2010 chinghwa.yu
149 * Update BOW for the 1st time.
153 * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
155 * 06 06 2010 kevin.huang
156 * [WPD00003832][MT6620 5931] Create driver base
157 * [MT6620 5931] Create driver base
160 * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support
161 * change variable names for multiple physical link to match with coding convention
164 * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support
165 * multiple BoW interfaces need to compare with peer address
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
173 * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support
174 * fix kalIndicateBOWEvent.
177 * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support
178 * add multiple physical link support
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
189 /*******************************************************************************
190 * C O M P I L E R F L A G S
191 ********************************************************************************
194 /*******************************************************************************
195 * E X T E R N A L R E F E R E N C E S
196 ********************************************************************************
200 #include "wlan_lib.h"
203 #include <linux/poll.h>
206 #if CFG_ENABLE_BT_OVER_WIFI
208 /*******************************************************************************
210 ********************************************************************************
212 /* @FIXME if there is command/event with payload length > 28 */
213 #define MAX_BUFFER_SIZE (64)
215 /*******************************************************************************
217 ********************************************************************************
220 /*******************************************************************************
221 * P U B L I C D A T A
222 ********************************************************************************
226 UINT_32 g_u4PrevSysTime = 0;
227 UINT_32 g_u4CurrentSysTime = 0;
228 UINT_32 g_arBowRevPalPacketTime[11];
231 /*******************************************************************************
232 * P R I V A T E D A T A
233 ********************************************************************************
236 // forward declarations
239 IN struct file *filp,
242 IN OUT loff_t *ppos);
246 IN struct file *filp,
247 OUT const char __user *buf,
249 IN OUT loff_t *ppos);
253 IN struct file *filp,
255 IN OUT unsigned long arg);
259 IN struct file *filp,
260 IN poll_table *wait);
264 IN struct inode *inodep,
265 IN struct file *filp);
269 IN struct inode *inodep,
270 IN struct file *filp);
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,
284 /*******************************************************************************
286 ********************************************************************************
289 /*******************************************************************************
290 * F U N C T I O N D E C L A R A T I O N S
291 ********************************************************************************
294 /*******************************************************************************
296 ********************************************************************************
300 /*----------------------------------------------------------------------------*/
302 * \brief Register for character device to communicate with 802.11 PAL
304 * \param[in] prGlueInfo Pointer to glue info
309 /*----------------------------------------------------------------------------*/
312 IN P_GLUE_INFO_T prGlueInfo
317 if(prGlueInfo->rBowInfo.fgIsRegistered == TRUE) {
322 // 1. allocate major number dynamically
324 if(alloc_chrdev_region(&(prGlueInfo->rBowInfo.u4DeviceNumber),
325 0, // first minor number
327 GLUE_BOW_DEVICE_NAME) !=0)
334 #if defined (CONFIG_AMPC_CDEV_NUM)
335 prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(CONFIG_AMPC_CDEV_NUM, 0);
337 prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(226, 0);
340 if(register_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber,
342 GLUE_BOW_DEVICE_NAME) !=0)
347 // 2. spin-lock initialization
348 // spin_lock_init(&(prGlueInfo->rBowInfo.rSpinLock));
350 // 3. initialize kfifo
351 /* prGlueInfo->rBowInfo.prKfifo = kfifo_alloc(GLUE_BOW_KFIFO_DEPTH,
353 &(prGlueInfo->rBowInfo.rSpinLock));*/
354 if ((kfifo_alloc((struct kfifo *) &(prGlueInfo->rBowInfo.rKfifo), GLUE_BOW_KFIFO_DEPTH, GFP_KERNEL)))
355 goto fail_kfifo_alloc;
357 // if(prGlueInfo->rBowInfo.prKfifo == NULL)
358 if(&(prGlueInfo->rBowInfo.rKfifo) == NULL)
359 goto fail_kfifo_alloc;
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;
366 // 5. add character device
367 if(cdev_add(&(prGlueInfo->rBowInfo.cdev),
368 prGlueInfo->rBowInfo.u4DeviceNumber,
373 // 6. in queue initialization
374 init_waitqueue_head(&(prGlueInfo->rBowInfo.outq));
377 prGlueInfo->rBowInfo.fgIsRegistered = TRUE;
381 kfifo_free(&(prGlueInfo->rBowInfo.rKfifo));
382 // kfifo_free(prGlueInfo->rBowInfo.prKfifo);
384 unregister_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1);
387 } /* end of glRegisterAmpc */
390 /*----------------------------------------------------------------------------*/
392 * \brief Unregister character device for communicating with 802.11 PAL
394 * \param[in] prGlueInfo Pointer to glue info
399 /*----------------------------------------------------------------------------*/
402 IN P_GLUE_INFO_T prGlueInfo
407 if(prGlueInfo->rBowInfo.fgIsRegistered == FALSE) {
411 prGlueInfo->rBowInfo.fgIsRegistered = FALSE;
413 // 1. free netdev if necessary
414 #if CFG_BOW_SEPARATE_DATA_PATH
415 kalUninitBowDevice(prGlueInfo);
418 // 2. removal of character device
419 cdev_del(&(prGlueInfo->rBowInfo.cdev));
422 // kfifo_free(prGlueInfo->rBowInfo.prKfifo);
423 kfifo_free(&(prGlueInfo->rBowInfo.rKfifo));
424 // prGlueInfo->rBowInfo.prKfifo = NULL;
425 // prGlueInfo->rBowInfo.rKfifo = NULL;
427 // 4. free device number
428 unregister_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1);
432 } /* end of glUnregisterAmpc */
435 /*----------------------------------------------------------------------------*/
437 * \brief read handler for character device to communicate with 802.11 PAL
441 * Follows Linux Character Device Interface
444 /*----------------------------------------------------------------------------*/
447 IN struct file *filp,
452 UINT_8 aucBuffer[MAX_BUFFER_SIZE];
455 P_GLUE_INFO_T prGlueInfo;
456 prGlueInfo = (P_GLUE_INFO_T)(filp->private_data);
460 if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->u4Flag & GLUE_FLAG_HALT)) {
465 // if(kfifo_len(prGlueInfo->rBowInfo.prKfifo) >= size)
466 if(kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)) >= size)
469 retval = kfifo_len(&(prGlueInfo->rBowInfo.rKfifo));
470 // retval = kfifo_len(prGlueInfo->rBowInfo.prKfifo);
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)))
477 if(copy_to_user(buf, aucBuffer, retval))
484 /*----------------------------------------------------------------------------*/
486 * \brief write handler for character device to communicate with 802.11 PAL
490 * Follows Linux Character Device Interface
493 /*----------------------------------------------------------------------------*/
496 IN struct file *filp,
497 OUT const char __user *buf,
505 UINT_8 aucBuffer[MAX_BUFFER_SIZE];
506 P_AMPC_COMMAND prCmd;
507 P_GLUE_INFO_T prGlueInfo;
509 prGlueInfo = (P_GLUE_INFO_T)(filp->private_data);
512 if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->u4Flag & GLUE_FLAG_HALT)) {
516 if(size > MAX_BUFFER_SIZE)
518 else if(copy_from_user(aucBuffer, buf, size))
522 DBGLOG(BOW, EVENT, ("AMP driver CMD buffer size : %d.\n", size));
524 for(i = 0; i < MAX_BUFFER_SIZE; i++)
526 DBGLOG(BOW, EVENT, ("AMP write content : 0x%x.\n", aucBuffer[i]));
529 DBGLOG(BOW, EVENT, ("BoW CMD write.\n"));
532 prCmd = (P_AMPC_COMMAND) aucBuffer;
535 DBGLOG(BOW, EVENT, ("AMP write content payload length : %d.\n", prCmd->rHeader.u2PayloadLength));
537 DBGLOG(BOW, EVENT, ("AMP write content header length : %d.\n", sizeof(AMPC_COMMAND_HEADER_T)));
541 if(prCmd->rHeader.u2PayloadLength + sizeof(AMPC_COMMAND_HEADER_T) != size)
544 DBGLOG(BOW, EVENT, ("Wrong CMD total length.\n"));
550 if(wlanbowHandleCommand(prGlueInfo->prAdapter, prCmd) == WLAN_STATUS_SUCCESS)
557 /*----------------------------------------------------------------------------*/
559 * \brief ioctl handler for character device to communicate with 802.11 PAL
563 * Follows Linux Character Device Interface
566 /*----------------------------------------------------------------------------*/
569 IN struct file *filp,
571 IN OUT unsigned long arg)
574 P_GLUE_INFO_T prGlueInfo;
575 prGlueInfo = (P_GLUE_INFO_T)(filp->private_data);
579 if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->u4Flag & GLUE_FLAG_HALT)) {
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));
591 // no ioctl is implemented yet
596 /*----------------------------------------------------------------------------*/
598 * \brief ioctl handler for character device to communicate with 802.11 PAL
602 * Follows Linux Character Device Interface
605 /*----------------------------------------------------------------------------*/
608 IN struct file *filp,
612 P_GLUE_INFO_T prGlueInfo;
613 prGlueInfo = (P_GLUE_INFO_T)(filp->private_data);
617 if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->u4Flag & GLUE_FLAG_HALT)) {
621 poll_wait(filp, &prGlueInfo->rBowInfo.outq, wait);
623 retval = (POLLOUT | POLLWRNORM); // always accepts incoming command packets
625 // DBGLOG(BOW, EVENT, ("mt6620_ampc_pol, POLLOUT | POLLWRNORM, %x\n", retval));
627 // if(kfifo_len(prGlueInfo->rBowInfo.prKfifo) > 0)
628 if(kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)) > 0)
630 retval |= (POLLIN | POLLRDNORM);
632 // DBGLOG(BOW, EVENT, ("mt6620_ampc_pol, POLLIN | POLLRDNORM, %x\n", retval));
640 /*----------------------------------------------------------------------------*/
642 * \brief open handler for character device to communicate with 802.11 PAL
646 * Follows Linux Character Device Interface
649 /*----------------------------------------------------------------------------*/
652 IN struct inode *inodep,
653 IN struct file *filp)
655 P_GLUE_INFO_T prGlueInfo;
656 P_GL_BOW_INFO prBowInfo;
658 prBowInfo = container_of(inodep->i_cdev, GL_BOW_INFO, cdev);
661 prGlueInfo = container_of(prBowInfo, GLUE_INFO_T, rBowInfo);
664 // set-up private data
665 filp->private_data = prGlueInfo;
671 /*----------------------------------------------------------------------------*/
673 * \brief close handler for character device to communicate with 802.11 PAL
677 * Follows Linux Character Device Interface
680 /*----------------------------------------------------------------------------*/
683 IN struct inode *inodep,
684 IN struct file *filp)
686 P_GLUE_INFO_T prGlueInfo;
687 prGlueInfo = (P_GLUE_INFO_T)(filp->private_data);
695 /*----------------------------------------------------------------------------*/
697 * \brief to indicate event for Bluetooth over Wi-Fi
705 /*----------------------------------------------------------------------------*/
708 IN P_GLUE_INFO_T prGlueInfo,
709 IN P_AMPC_EVENT prEvent
712 size_t u4AvailSize, u4EventSize;
718 if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->u4Flag & GLUE_FLAG_HALT)) {
723 GLUE_BOW_KFIFO_DEPTH - kfifo_len(prGlueInfo->rBowInfo.prKfifo);*/
726 GLUE_BOW_KFIFO_DEPTH - kfifo_len(&(prGlueInfo->rBowInfo.rKfifo));
730 prEvent->rHeader.u2PayloadLength + sizeof(AMPC_EVENT_HEADER_T);
732 // check kfifo availability
733 if(u4AvailSize < u4EventSize) {
734 DBGLOG(BOW, EVENT, ("[bow] no space for event: %d/%d\n",
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));
749 /*----------------------------------------------------------------------------*/
751 * \brief to retrieve Bluetooth-over-Wi-Fi state from glue layer
757 * ENUM_BOW_DEVICE_STATE
759 /*----------------------------------------------------------------------------*/
760 ENUM_BOW_DEVICE_STATE
762 IN P_GLUE_INFO_T prGlueInfo,
763 IN UINT_8 aucPeerAddress[6]
771 DBGLOG(BOW, EVENT, ("kalGetBowState.\n"));
774 for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++)
776 if(EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0)
780 DBGLOG(BOW, EVENT, ("kalGetBowState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", i,
788 DBGLOG(BOW, EVENT, ("kalGetBowState, prGlueInfo->rBowInfo.aeState %x, %x.\n", i, prGlueInfo->rBowInfo.aeState[i]));
792 return prGlueInfo->rBowInfo.aeState[i];
796 return BOW_DEVICE_STATE_DISCONNECTED;
800 /*----------------------------------------------------------------------------*/
802 * \brief to set Bluetooth-over-Wi-Fi state in glue layer
811 /*----------------------------------------------------------------------------*/
814 IN P_GLUE_INFO_T prGlueInfo,
815 IN ENUM_BOW_DEVICE_STATE eBowState,
816 IN UINT_8 aucPeerAddress[6]
824 DBGLOG(BOW, EVENT, ("kalSetBowState.\n"));
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]));
834 DBGLOG(BOW, EVENT, ("kalSetBowState, aucPeerAddress, %x:%x:%x:%x:%x:%x.\n",
843 for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++)
845 if(EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0)
847 prGlueInfo->rBowInfo.aeState[i] = eBowState;
850 DBGLOG(BOW, EVENT, ("kalSetBowState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", i,
858 DBGLOG(BOW, EVENT, ("kalSetBowState, prGlueInfo->rBowInfo.aeState %x, %x.\n", i, prGlueInfo->rBowInfo.aeState[i]));
869 /*----------------------------------------------------------------------------*/
871 * \brief to retrieve Bluetooth-over-Wi-Fi global state
877 * BOW_DEVICE_STATE_DISCONNECTED
878 * in case there is no BoW connection or
879 * BoW connection under initialization
881 * BOW_DEVICE_STATE_STARTING
882 * in case there is no BoW connection but
883 * some BoW connection under initialization
885 * BOW_DEVICE_STATE_CONNECTED
886 * in case there is any BoW connection available
888 /*----------------------------------------------------------------------------*/
889 ENUM_BOW_DEVICE_STATE
890 kalGetBowGlobalState (
891 IN P_GLUE_INFO_T prGlueInfo
899 //Henry, can reduce this logic to indentify state change
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;
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;
913 return BOW_DEVICE_STATE_DISCONNECTED;
916 /*----------------------------------------------------------------------------*/
918 * \brief to retrieve Bluetooth-over-Wi-Fi operating frequency
926 /*----------------------------------------------------------------------------*/
929 IN P_GLUE_INFO_T prGlueInfo
934 return prGlueInfo->rBowInfo.u4FreqInKHz;
938 /*----------------------------------------------------------------------------*/
940 * \brief to retrieve Bluetooth-over-Wi-Fi role
949 /*----------------------------------------------------------------------------*/
952 IN P_GLUE_INFO_T prGlueInfo,
953 IN PARAM_MAC_ADDRESS rPeerAddr
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];
970 /*----------------------------------------------------------------------------*/
972 * \brief to set Bluetooth-over-Wi-Fi role
982 /*----------------------------------------------------------------------------*/
985 IN P_GLUE_INFO_T prGlueInfo,
987 IN PARAM_MAC_ADDRESS rPeerAddr
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
1003 /*----------------------------------------------------------------------------*/
1005 * \brief to get available Bluetooth-over-Wi-Fi physical link number
1011 * how many physical links are aviailable
1013 /*----------------------------------------------------------------------------*/
1015 kalGetBowAvailablePhysicalLinkCount(
1016 IN P_GLUE_INFO_T prGlueInfo
1020 UINT_8 ucLinkCount = 0;
1024 for(i = 0 ; i < CFG_BOW_PHYSICAL_LINK_NUM ; i++) {
1025 if(prGlueInfo->rBowInfo.aeState[i] == BOW_DEVICE_STATE_DISCONNECTED) {
1031 DBGLOG(BOW, EVENT, ("kalGetBowAvailablePhysicalLinkCount, ucLinkCount, %c.\n", ucLinkCount));
1037 #if CFG_BOW_SEPARATE_DATA_PATH
1039 /* Net Device Hooks */
1040 /*----------------------------------------------------------------------------*/
1042 * \brief A function for net_device open (ifup)
1044 * \param[in] prDev Pointer to struct net_device.
1046 * \retval 0 The execution succeeds.
1047 * \retval < 0 The execution failed.
1049 /*----------------------------------------------------------------------------*/
1052 IN struct net_device *prDev
1055 P_GLUE_INFO_T prGlueInfo = NULL;
1056 P_ADAPTER_T prAdapter = NULL;
1060 prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
1063 prAdapter = prGlueInfo->prAdapter;
1066 /* 2. carrier on & start TX queue */
1067 netif_carrier_on(prDev);
1068 netif_tx_start_all_queues(prDev);
1070 return 0; /* success */
1074 /*----------------------------------------------------------------------------*/
1076 * \brief A function for net_device stop (ifdown)
1078 * \param[in] prDev Pointer to struct net_device.
1080 * \retval 0 The execution succeeds.
1081 * \retval < 0 The execution failed.
1083 /*----------------------------------------------------------------------------*/
1086 IN struct net_device *prDev
1089 P_GLUE_INFO_T prGlueInfo = NULL;
1090 P_ADAPTER_T prAdapter = NULL;
1094 prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
1097 prAdapter = prGlueInfo->prAdapter;
1100 /* 1. stop TX queue */
1101 netif_tx_stop_all_queues(prDev);
1103 /* 2. turn of carrier */
1104 if(netif_carrier_ok(prDev)) {
1105 netif_carrier_off(prDev);
1112 /*----------------------------------------------------------------------------*/
1114 * \brief This function is TX entry point of NET DEVICE.
1116 * \param[in] prSkb Pointer of the sk_buff to be sent
1117 * \param[in] prDev Pointer to struct net_device
1119 * \retval NETDEV_TX_OK - on success.
1120 * \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer.
1122 /*----------------------------------------------------------------------------*/
1125 IN struct sk_buff *prSkb,
1126 IN struct net_device *prDev
1129 P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
1131 P_QUE_ENTRY_T prQueueEntry = NULL;
1132 P_QUE_T prTxQueue = NULL;
1133 UINT_16 u2QueueIdx = 0;
1134 UINT_8 ucDSAP, ucSSAP, ucControl;
1136 PUINT_8 aucLookAheadBuf = NULL;
1142 GLUE_SPIN_LOCK_DECLARATION();
1148 aucLookAheadBuf = prSkb->data;
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];
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))
1166 DBGLOG(BOW, TRACE, ("Invalid BOW packet, skip tx\n"));
1169 dev_kfree_skb(prSkb);
1170 return NETDEV_TX_OK;
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;
1179 prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb);
1180 prTxQueue = &prGlueInfo->rTxQueue;
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"));
1187 for(i = 0; i < prSkb->len; i++)
1189 DBGLOG(BOW, TRACE, ("%4x", prSkb->data[i]));
1193 DBGLOG(BOW, TRACE, ("\n"));
1197 DBGLOG(BOW, TRACE, ("\n");
1201 // g_u4CurrentSysTime = (OS_SYSTIME)kalGetTimeTick();
1203 g_u4CurrentSysTime = (OS_SYSTIME) jiffies_to_usecs(jiffies);
1205 i = g_u4CurrentSysTime - g_u4PrevSysTime;
1216 g_arBowRevPalPacketTime[i]++;
1218 g_u4PrevSysTime = g_u4CurrentSysTime;
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);
1228 GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum);
1229 GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_BOW_INDEX][u2QueueIdx]);
1231 if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_BOW_INDEX][u2QueueIdx] >= CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) {
1232 netif_stop_subqueue(prDev, u2QueueIdx);
1236 GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum);
1239 kalSetEvent(prGlueInfo);
1241 /* For Linux, we'll always return OK FLAG, because we'll free this skb by ourself */
1242 return NETDEV_TX_OK;
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,
1253 /*----------------------------------------------------------------------------*/
1255 * \brief initialize net device for Bluetooth-over-Wi-Fi
1265 /*----------------------------------------------------------------------------*/
1268 IN P_GLUE_INFO_T prGlueInfo,
1269 IN const char *prDevName
1272 P_ADAPTER_T prAdapter;
1273 P_GL_HIF_INFO_T prHif;
1274 PARAM_MAC_ADDRESS rMacAddr;
1277 ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE);
1279 prAdapter = prGlueInfo->prAdapter;
1282 prHif = &prGlueInfo->rHifInfo;
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);
1288 if (!prGlueInfo->rBowInfo.prDevHandler) {
1292 /* 1. setup netdev */
1293 /* 1.1 Point to shared glue structure */
1294 *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->rBowInfo.prDevHandler)) = prGlueInfo;
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);
1302 /* 1.3 register callback functions */
1303 prGlueInfo->rBowInfo.prDevHandler->netdev_ops = &bow_netdev_ops;
1305 #if (MTK_WCN_HIF_SDIO == 0)
1306 SET_NETDEV_DEV(prGlueInfo->rBowInfo.prDevHandler, &(prHif->func->dev));
1309 register_netdev(prGlueInfo->rBowInfo.prDevHandler);
1311 /* 2. net device initialize */
1312 netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler);
1313 netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler);
1316 prGlueInfo->rBowInfo.fgIsNetRegistered = TRUE;
1324 /*----------------------------------------------------------------------------*/
1326 * \brief uninitialize net device for Bluetooth-over-Wi-Fi
1335 /*----------------------------------------------------------------------------*/
1338 IN P_GLUE_INFO_T prGlueInfo
1342 //ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE);
1344 if(prGlueInfo->rBowInfo.fgIsNetRegistered == TRUE) {
1346 prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE;
1348 if(netif_carrier_ok(prGlueInfo->rBowInfo.prDevHandler)) {
1349 netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler);
1352 netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler);
1354 /* netdevice unregistration & free */
1355 unregister_netdev(prGlueInfo->rBowInfo.prDevHandler);
1356 free_netdev(prGlueInfo->rBowInfo.prDevHandler);
1357 prGlueInfo->rBowInfo.prDevHandler = NULL;
1367 #endif // CFG_BOW_SEPARATE_DATA_PATH
1368 #endif // CFG_ENABLE_BT_OVER_WIFI