gl_bow.c 40 KB

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