2 * Copyright (C) 2011-2014 MediaTek Inc.
4 * This program is free software: you can redistribute it and/or modify it under the terms of the
5 * GNU General Public License version 2 as published by the Free Software Foundation.
7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9 * See the GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License along with this program.
12 * If not, see <http://www.gnu.org/licenses/>.
16 ** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_init.c#7 $
20 \brief Main routines of Linux driver
22 This file contains the main routines of Linux driver for MediaTek Inc. 802.11
23 Wireless LAN Adapters.
32 ** add path for reassociation
34 * 07 17 2012 yuche.tsai
38 * 07 17 2012 yuche.tsai
40 * Fix compile error for JB.
42 * 07 17 2012 yuche.tsai
44 * Let netdev bring up.
46 * 07 17 2012 yuche.tsai
48 * Compile no error before trial run.
50 * 06 13 2012 yuche.tsai
52 * Update maintrunk driver.
53 * Add support for driver compose assoc request frame.
55 * 05 25 2012 yuche.tsai
60 * [WCXRP00001237] [MT6620 Wi-Fi][Driver] Show MAC address and MAC address source for ACS's convenience
61 * show MAC address & source while initiliazation
65 * EXPORT_SYMBOL(rsnParseCheckForWFAInfoElem);.
69 * Snc CFG80211 modification for ICS migration from branch 2.2.
73 * Sync CFG80211 modification from branch 2,2.
77 * Enable CFG80211 Support.
79 * 12 22 2011 george.huang
80 * [WCXRP00000905] [MT6628 Wi-Fi][FW] Code refinement for ROM/ RAM module dependency
81 * using global variable instead of stack for setting wlanoidSetNetworkAddress(), due to buffer may be released before TX thread handling
83 * 11 18 2011 yuche.tsai
85 * CONFIG P2P support RSSI query, default turned off.
87 * 11 14 2011 yuche.tsai
88 * [WCXRP00001107] [Volunteer Patch][Driver] Large Network Type index assert in FW issue.
89 * Fix large network type index assert in FW issue.
93 * Fix compiling warning
95 * 11 11 2011 yuche.tsai
97 * Fix work thread cancel issue.
100 * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer
101 * 1. eliminaite direct calls to printk in porting layer.
102 * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms.
104 * 10 06 2011 eddie.chen
105 * [WCXRP00001027] [MT6628 Wi-Fi][Firmware/Driver] Tx fragmentation
106 * Add rlmDomainGetChnlList symbol.
108 * 09 22 2011 cm.chang
110 * Safer writng stype to avoid unitialized regitry structure
112 * 09 21 2011 cm.chang
113 * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code
114 * Avoid possible structure alignment problem
116 * 09 20 2011 chinglan.wang
117 * [WCXRP00000989] [WiFi Direct] [Driver] Add a new io control API to start the formation for the sigma test.
120 * 09 08 2011 cm.chang
121 * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code
122 * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM
124 * 08 31 2011 cm.chang
125 * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code
129 * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time
130 * expose scnQuerySparseChannel() for P2P-FSM.
133 * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time
134 * sparse channel detection:
135 * driver: collect sparse channel information with scan-done event
137 * 08 02 2011 yuche.tsai
138 * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting device issue.
139 * Fix GO send deauth frame issue.
142 * [WCXRP00000839] [MT6620 Wi-Fi][Driver] Add the dumpMemory8 and dumpMemory32 EXPORT_SYMBOL
143 * Add the dumpMemory8 symbol export for debug mode.
145 * 07 06 2011 terry.wu
146 * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment
147 * Improve BoW connection establishment speed.
149 * 07 05 2011 yuche.tsai
150 * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue
151 * Export one symbol for enhancement.
153 * 06 13 2011 eddie.chen
154 * [WCXRP00000779] [MT6620 Wi-Fi][DRV] Add tx rx statistics in linux and use netif_rx_ni
155 * Add tx rx statistics and netif_rx_ni.
158 * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM
159 * invoke CMD_ID_SET_EDGE_TXPWR_LIMIT when there is valid data exist in NVRAM content.
162 * [WCXRP00000734] [MT6620 Wi-Fi][Driver] Pass PHY_PARAM in NVRAM to firmware domain
163 * pass PHY_PARAM in NVRAM from driver to firmware.
165 * 05 09 2011 jeffrey.chang
166 * [WCXRP00000710] [MT6620 Wi-Fi] Support pattern filter update function on IP address change
167 * support ARP filter through kernel notifier
169 * 05 03 2011 chinghwa.yu
170 * [WCXRP00000065] Update BoW design and settings
171 * Use kalMemAlloc to allocate event buffer for kalIndicateBOWEvent.
173 * 04 27 2011 george.huang
174 * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter
175 * Support P2P ARP filter setting on early suspend/ late resume
177 * 04 18 2011 terry.wu
178 * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED
179 * Remove flag CFG_WIFI_DIRECT_MOVED.
181 * 04 15 2011 chinghwa.yu
182 * [WCXRP00000065] Update BoW design and settings
183 * Add BOW short range mode.
185 * 04 14 2011 yuche.tsai
186 * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case.
187 * Modify some driver connection flow or behavior to pass Sigma test more easier..
189 * 04 12 2011 cm.chang
190 * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency
193 * 04 11 2011 george.huang
194 * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode
195 * export wlan functions to p2p
198 * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver
199 * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile settting for PC Linux driver
202 * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
203 * glBusFreeIrq() should use the same pvCookie as glBusSetIrq() or request_irq()/free_irq() won't work as a pair.
205 * 04 08 2011 eddie.chen
206 * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma
210 * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
211 * 1. do not check for pvData inside wlanNetCreate() due to it is NULL for eHPI port
212 * 2. update perm_addr as well for MAC address
213 * 3. not calling check_mem_region() anymore for eHPI
214 * 4. correct MSC_CS macro for 0-based notation
217 * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events
221 * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events
222 * implement kernel-to-userspace communication via generic netlink socket for whole-chip resetting mechanism
225 * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
226 * apply multi-queue operation only for linux kernel > 2.6.26
229 * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build
230 * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment.
233 * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
234 * portability for compatible with linux 2.6.12.
237 * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
238 * improve portability for awareness of early version of linux kernel and wireless extension.
241 * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
242 * portability improvement
244 * 03 18 2011 jeffrey.chang
245 * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue
246 * remove early suspend functions
249 * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period
250 * reverse order to prevent probing racing.
253 * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period
254 * 1. pre-allocate physical continuous buffer while module is being loaded
255 * 2. use pre-allocated physical continuous buffer for TX/RX DMA transfer
257 * The windows part remained the same as before, but added similiar APIs to hide the difference.
259 * 03 15 2011 jeffrey.chang
260 * [WCXRP00000558] [MT6620 Wi-Fi][MT6620 Wi-Fi][Driver] refine the queue selection algorithm for WMM
261 * refine the queue_select function
264 * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3
265 * deprecate configuration used by MT6620 E2
267 * 03 10 2011 terry.wu
268 * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration
269 * Remove unnecessary assert and message.
271 * 03 08 2011 terry.wu
272 * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration
273 * Export nicQmUpdateWmmParms.
275 * 03 03 2011 jeffrey.chang
276 * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue
277 * support concurrent network
279 * 03 03 2011 jeffrey.chang
280 * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue
281 * modify net device relative functions to support multiple H/W queues
283 * 02 24 2011 george.huang
284 * [WCXRP00000495] [MT6620 Wi-Fi][FW] Support pattern filter for unwanted ARP frames
285 * Support ARP filter during suspended
288 * [WCXRP00000482] [MT6620 Wi-Fi][Driver] Simplify logic for checking NVRAM existence in driver domain
289 * simplify logic for checking NVRAM existence only once.
291 * 02 17 2011 terry.wu
292 * [WCXRP00000459] [MT6620 Wi-Fi][Driver] Fix deference null pointer problem in wlanRemove
293 * Fix deference a null pointer problem in wlanRemove.
295 * 02 16 2011 jeffrey.chang
299 * 02 16 2011 jeffrey.chang
301 * Add query ipv4 and ipv6 address during early suspend and late resume
303 * 02 15 2011 jeffrey.chang
305 * to support early suspend in android
307 * 02 11 2011 yuche.tsai
308 * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode.
309 * Add one more export symbol.
311 * 02 10 2011 yuche.tsai
312 * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode.
313 * Add RX deauthentication & disassociation process under Hot-Spot mode.
315 * 02 09 2011 terry.wu
316 * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules
317 * Halt p2p module init and exit until TxThread finished p2p register and unregister.
319 * 02 08 2011 george.huang
320 * [WCXRP00000422] [MT6620 Wi-Fi][Driver] support query power mode OID handler
321 * Support querying power mode OID.
323 * 02 08 2011 yuche.tsai
324 * [WCXRP00000421] [Volunteer Patch][MT6620][Driver] Fix incorrect SSID length Issue
325 * Export Deactivation Network.
327 * 02 01 2011 jeffrey.chang
328 * [WCXRP00000414] KAL Timer is not unregistered when driver not loaded
329 * Unregister the KAL timer during driver unloading
331 * 01 26 2011 cm.chang
332 * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument
333 * Allocate system RAM if fixed message or mgmt buffer is not available
336 * [WCXRP00000371] [MT6620 Wi-Fi][Driver] make linux glue layer portable for Android 2.3.1 with Linux 2.6.35.7
337 * add compile option to check linux version 2.6.35 for different usage of system API to improve portability
340 * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP
341 * implementation of separate BT_OVER_WIFI data path.
344 * [WCXRP00000349] [MT6620 Wi-Fi][Driver] make kalIoctl() of linux port as a thread safe API to avoid potential issues due to multiple access
345 * use mutex to protect kalIoctl() for thread safe.
348 * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands
349 * separate kalMemAlloc() into virtually-continous and physically-continous type to ease slab system pressure
352 * [WCXRP00000265] [MT6620 Wi-Fi][Driver] Remove set_mac_address routine from legacy Wi-Fi Android driver
353 * remove set MAC address. MAC address is always loaded from NVRAM instead.
355 * 12 10 2010 kevin.huang
356 * [WCXRP00000128] [MT6620 Wi-Fi][Driver] Add proc support to Android Driver for debug and driver status check
357 * Add Linux Proc Support
359 * 11 01 2010 yarco.yang
360 * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform
361 * Add GPIO debug function
364 * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module
365 * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead
366 * 2) Remove CNM CH-RECOVER event handling
367 * 3) cfg read/write API renamed with kal prefix for unified naming rules.
370 * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command
371 * 1) update NVRAM content template to ver 1.02
372 * 2) add compile option for querying NIC capability (default: off)
373 * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting
374 * 4) correct auto-rate compiler error under linux (treat warning as error)
375 * 5) simplify usage of NVRAM and REG_INFO_T
376 * 6) add version checking between driver and firmware
378 * 10 21 2010 chinghwa.yu
379 * [WCXRP00000065] Update BoW design and settings
382 * 10 19 2010 jeffrey.chang
383 * [WCXRP00000120] [MT6620 Wi-Fi][Driver] Refine linux kernel module to the license of MTK propietary and enable MTK HIF by default
384 * Refine linux kernel module to the license of MTK and enable MTK HIF
386 * 10 18 2010 jeffrey.chang
387 * [WCXRP00000106] [MT6620 Wi-Fi][Driver] Enable setting multicast callback in Android
391 * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android
392 * complete implementation of Android NVRAM access
394 * 09 27 2010 chinghwa.yu
395 * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings
396 * Update BCM/BoW design and settings.
399 * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item
400 * use firmware reported mac address right after wlanAdapterStart() as permanent address
402 * 09 21 2010 kevin.huang
403 * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning
404 * Eliminate Linux Compile Warning
406 * 09 03 2010 kevin.huang
408 * Refine #include sequence and solve recursive/nested #include issue
412 * adding the wapi support for integration test.
414 * 08 18 2010 yarco.yang
416 * 1. Fixed HW checksum offload function not work under Linux issue.
417 * 2. Add debug message.
419 * 08 16 2010 yarco.yang
423 * 08 02 2010 jeffrey.chang
425 * 1) modify tx service thread to avoid busy looping
426 * 2) add spin lock declartion for linux build
428 * 07 29 2010 jeffrey.chang
430 * fix memory leak for module unloading
432 * 07 28 2010 jeffrey.chang
434 * 1) remove unused spinlocks
435 * 2) enable encyption ioctls
436 * 3) fix scan ioctl which may cause supplicant to hang
438 * 07 23 2010 jeffrey.chang
440 * bug fix: allocate regInfo when disabling firmware download
442 * 07 23 2010 jeffrey.chang
444 * use glue layer api to decrease or increase counter atomically
446 * 07 22 2010 jeffrey.chang
450 * 07 19 2010 jeffrey.chang
452 * modify cmd/data path for new design
456 * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
458 * 06 06 2010 kevin.huang
459 * [WPD00003832][MT6620 5931] Create driver base
460 * [MT6620 5931] Create driver base
462 * 05 26 2010 jeffrey.chang
463 * [WPD00003826]Initial import for Linux port
464 * 1) Modify set mac address code
465 * 2) remove power managment macro
468 * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
469 * implement basic wi-fi direct framework
471 * 05 07 2010 jeffrey.chang
472 * [WPD00003826]Initial import for Linux port
473 * prevent supplicant accessing driver during resume
476 * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
477 * add basic framework for implementating P2P driver hook.
479 * 04 27 2010 jeffrey.chang
480 * [WPD00003826]Initial import for Linux port
481 * 1) fix firmware download bug
482 * 2) remove query statistics for acelerating firmware download
484 * 04 27 2010 jeffrey.chang
485 * [WPD00003826]Initial import for Linux port
486 * follow Linux's firmware framework, and remove unused kal API
488 * 04 21 2010 jeffrey.chang
489 * [WPD00003826]Initial import for Linux port
490 * add for private ioctl support
492 * 04 19 2010 jeffrey.chang
493 * [WPD00003826]Initial import for Linux port
494 * Query statistics from firmware
496 * 04 19 2010 jeffrey.chang
497 * [WPD00003826]Initial import for Linux port
498 * modify tcp/ip checksum offload flags
500 * 04 16 2010 jeffrey.chang
501 * [WPD00003826]Initial import for Linux port
502 * fix tcp/ip checksum offload bug
505 * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support
506 * add framework for BT-over-Wi-Fi support.
507 * * * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability
508 * * * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically
509 * * * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose
511 * 04 09 2010 jeffrey.chang
512 * [WPD00003826]Initial import for Linux port
515 * 04 07 2010 jeffrey.chang
516 * [WPD00003826]Initial import for Linux port
517 * Set MAC address from firmware
520 * [WPD00001943]Create WiFi test driver framework on WinXP
521 * rWlanInfo should be placed at adapter rather than glue due to most operations
522 * * * * * * are done in adapter layer.
524 * 04 07 2010 jeffrey.chang
525 * [WPD00003826]Initial import for Linux port
526 * (1)improve none-glue code portability
527 * * (2) disable set Multicast address during atomic context
529 * 04 06 2010 jeffrey.chang
530 * [WPD00003826]Initial import for Linux port
531 * adding debug module
534 * [WPD00003816][MT6620 Wi-Fi] Adding the security support
535 * modify the wapi related code for new driver's design.
537 * 03 30 2010 jeffrey.chang
538 * [WPD00003826]Initial import for Linux port
539 * emulate NDIS Pending OID facility
541 * 03 26 2010 jeffrey.chang
542 * [WPD00003826]Initial import for Linux port
543 * fix f/w download start and load address by using config.h
545 * 03 26 2010 jeffrey.chang
546 * [WPD00003826]Initial import for Linux port
547 * [WPD00003826] Initial import for Linux port
548 * adding firmware download support
550 * 03 24 2010 jeffrey.chang
551 * [WPD00003826]Initial import for Linux port
552 * initial import for Linux port
553 ** \main\maintrunk.MT5921\52 2009-10-27 22:49:59 GMT mtk01090
554 ** Fix compile error for Linux EHPI driver
555 ** \main\maintrunk.MT5921\51 2009-10-20 17:38:22 GMT mtk01090
556 ** Refine driver unloading and clean up procedure. Block requests, stop main thread and clean up queued requests, and then stop hw.
557 ** \main\maintrunk.MT5921\50 2009-10-08 10:33:11 GMT mtk01090
558 ** Avoid accessing private data of net_device directly. Replace with netdev_priv(). Add more checking for input parameters and pointers.
559 ** \main\maintrunk.MT5921\49 2009-09-28 20:19:05 GMT mtk01090
560 ** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel.
561 ** \main\maintrunk.MT5921\48 2009-09-03 13:58:46 GMT mtk01088
562 ** remove non-used code
563 ** \main\maintrunk.MT5921\47 2009-09-03 11:40:25 GMT mtk01088
564 ** adding the module parameter for wapi
565 ** \main\maintrunk.MT5921\46 2009-08-18 22:56:41 GMT mtk01090
566 ** Add Linux SDIO (with mmc core) support.
567 ** Add Linux 2.6.21, 2.6.25, 2.6.26.
568 ** Fix compile warning in Linux.
569 ** \main\maintrunk.MT5921\45 2009-07-06 20:53:00 GMT mtk01088
570 ** adding the code to check the wapi 1x frame
571 ** \main\maintrunk.MT5921\44 2009-06-23 23:18:55 GMT mtk01090
572 ** Add build option BUILD_USE_EEPROM and compile option CFG_SUPPORT_EXT_CONFIG for NVRAM support
573 ** \main\maintrunk.MT5921\43 2009-02-16 23:46:51 GMT mtk01461
574 ** Revise the order of increasing u4TxPendingFrameNum because of CFG_TX_RET_TX_CTRL_EARLY
575 ** \main\maintrunk.MT5921\42 2009-01-22 13:11:59 GMT mtk01088
576 ** set the tid and 1x value at same packet reserved field
577 ** \main\maintrunk.MT5921\41 2008-10-20 22:43:53 GMT mtk01104
578 ** Fix wrong variable name "prDev" in wlanStop()
579 ** \main\maintrunk.MT5921\40 2008-10-16 15:37:10 GMT mtk01461
580 ** add handle WLAN_STATUS_SUCCESS in wlanHardStartXmit() for CFG_TX_RET_TX_CTRL_EARLY
581 ** \main\maintrunk.MT5921\39 2008-09-25 15:56:21 GMT mtk01461
582 ** Update driver for Code review
583 ** \main\maintrunk.MT5921\38 2008-09-05 17:25:07 GMT mtk01461
584 ** Update Driver for Code Review
585 ** \main\maintrunk.MT5921\37 2008-09-02 10:57:06 GMT mtk01461
586 ** Update driver for code review
587 ** \main\maintrunk.MT5921\36 2008-08-05 01:53:28 GMT mtk01461
588 ** Add support for linux statistics
589 ** \main\maintrunk.MT5921\35 2008-08-04 16:52:58 GMT mtk01461
590 ** Fix ASSERT if removing module in BG_SSID_SCAN state
591 ** \main\maintrunk.MT5921\34 2008-06-13 22:52:24 GMT mtk01461
592 ** Revise status code handling in wlanHardStartXmit() for WLAN_STATUS_SUCCESS
593 ** \main\maintrunk.MT5921\33 2008-05-30 18:56:53 GMT mtk01461
594 ** Not use wlanoidSetCurrentAddrForLinux()
595 ** \main\maintrunk.MT5921\32 2008-05-30 14:39:40 GMT mtk01461
596 ** Remove WMM Assoc Flag
597 ** \main\maintrunk.MT5921\31 2008-05-23 10:26:40 GMT mtk01084
598 ** modify wlanISR interface
599 ** \main\maintrunk.MT5921\30 2008-05-03 18:52:36 GMT mtk01461
600 ** Fix Unset Broadcast filter when setMulticast
601 ** \main\maintrunk.MT5921\29 2008-05-03 15:17:26 GMT mtk01461
602 ** Move Query Media Status to GLUE
603 ** \main\maintrunk.MT5921\28 2008-04-24 22:48:21 GMT mtk01461
604 ** Revise set multicast function by using windows oid style for LP own back
605 ** \main\maintrunk.MT5921\27 2008-04-24 12:00:08 GMT mtk01461
606 ** Fix multicast setting in Linux and add comment
607 ** \main\maintrunk.MT5921\26 2008-03-28 10:40:22 GMT mtk01461
608 ** Fix set mac address func in Linux
609 ** \main\maintrunk.MT5921\25 2008-03-26 15:37:26 GMT mtk01461
610 ** Add set MAC Address
611 ** \main\maintrunk.MT5921\24 2008-03-26 14:24:53 GMT mtk01461
612 ** For Linux, set net_device has feature with checksum offload by default
613 ** \main\maintrunk.MT5921\23 2008-03-11 14:50:52 GMT mtk01461
615 ** \main\maintrunk.MT5921\22 2008-02-29 15:35:20 GMT mtk01088
616 ** add 1x decide code for sw port control
617 ** \main\maintrunk.MT5921\21 2008-02-21 15:01:54 GMT mtk01461
618 ** Rearrange the set off place of GLUE spin lock in HardStartXmit
619 ** \main\maintrunk.MT5921\20 2008-02-12 23:26:50 GMT mtk01461
620 ** Add debug option - Packet Order for Linux and add debug level - Event
621 ** \main\maintrunk.MT5921\19 2007-12-11 00:11:12 GMT mtk01461
622 ** Fix SPIN_LOCK protection
623 ** \main\maintrunk.MT5921\18 2007-11-30 17:02:25 GMT mtk01425
624 ** 1. Set Rx multicast packets mode before setting the address list
625 ** \main\maintrunk.MT5921\17 2007-11-26 19:44:24 GMT mtk01461
626 ** Add OS_TIMESTAMP to packet
627 ** \main\maintrunk.MT5921\16 2007-11-21 15:47:20 GMT mtk01088
628 ** fixed the unload module issue
629 ** \main\maintrunk.MT5921\15 2007-11-07 18:37:38 GMT mtk01461
630 ** Fix compile warnning
631 ** \main\maintrunk.MT5921\14 2007-11-02 01:03:19 GMT mtk01461
632 ** Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning
633 ** \main\maintrunk.MT5921\13 2007-10-30 10:42:33 GMT mtk01425
634 ** 1. Refine for multicast list
635 ** \main\maintrunk.MT5921\12 2007-10-25 18:08:13 GMT mtk01461
636 ** Add VOIP SCAN Support & Refine Roaming
637 ** Revision 1.4 2007/07/05 07:25:33 MTK01461
638 ** Add Linux initial code, modify doc, add 11BB, RF init code
640 ** Revision 1.3 2007/06/27 02:18:50 MTK01461
641 ** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API
643 ** Revision 1.2 2007/06/25 06:16:24 MTK01461
644 ** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API
648 /*******************************************************************************
649 * C O M P I L E R F L A G S
650 ********************************************************************************
653 /*******************************************************************************
654 * E X T E R N A L R E F E R E N C E S
655 ********************************************************************************
659 #include "wlan_lib.h"
661 #include "gl_cfg80211.h"
663 #if CFG_SUPPORT_AGPS_ASSIST
666 #if defined(CONFIG_MTK_TC1_FEATURE)
667 #include <tc1_partition.h>
670 /*******************************************************************************
672 ********************************************************************************
674 //#define MAX_IOREQ_NUM 10
676 BOOLEAN fgIsUnderSuspend
= false;
678 struct semaphore g_halt_sem
;
679 int g_u4HaltFlag
= 0;
681 #if CFG_ENABLE_WIFI_DIRECT
682 spinlock_t g_p2p_lock
;
683 int g_u4P2PEnding
= 0;
684 int g_u4P2POnOffing
= 0;
688 /*******************************************************************************
690 ********************************************************************************
692 /* Tasklet mechanism is like buttom-half in Linux. We just want to
693 * send a signal to OS for interrupt defer processing. All resources
694 * are NOT allowed reentry, so txPacket, ISR-DPC and ioctl must avoid preempty.
696 typedef struct _WLANDEV_INFO_T
{
697 struct net_device
*prDev
;
698 } WLANDEV_INFO_T
, *P_WLANDEV_INFO_T
;
700 /*******************************************************************************
701 * P U B L I C D A T A
702 ********************************************************************************
705 MODULE_AUTHOR(NIC_AUTHOR
);
706 MODULE_DESCRIPTION(NIC_DESC
);
707 MODULE_SUPPORTED_DEVICE(NIC_NAME
);
708 MODULE_LICENSE("GPL");
710 #define NIC_INF_NAME "wlan%d" /* interface name */
712 #define NIC_INF_NAME_IN_AP_MODE "legacy%d"
713 extern volatile int wlan_if_changed
;
716 /* support to change debug module info dynamically */
717 UINT_8 aucDebugModule
[DBG_MODULE_NUM
];
718 UINT_32 u4DebugModule
= 0;
721 //4 2007/06/26, mikewu, now we don't use this, we just fix the number of wlan device to 1
722 static WLANDEV_INFO_T arWlanDevInfo
[CFG_MAX_WLAN_DEVICES
] = {{0}};
723 static UINT_32 u4WlanDevNum
= 0; /* How many NICs coexist now */
725 /*******************************************************************************
726 * P R I V A T E D A T A
727 ********************************************************************************
729 #if CFG_ENABLE_WIFI_DIRECT
730 static SUB_MODULE_HANDLER rSubModHandler
[SUB_MODULE_NUM
] = {{NULL
}};
733 #define CHAN2G(_channel, _freq, _flags) \
735 .band = IEEE80211_BAND_2GHZ, \
736 .center_freq = (_freq), \
737 .hw_value = (_channel), \
739 .max_antenna_gain = 0, \
742 static struct ieee80211_channel mtk_2ghz_channels
[] = {
759 #define CHAN5G(_channel, _flags) \
761 .band = IEEE80211_BAND_5GHZ, \
762 .center_freq = 5000 + (5 * (_channel)), \
763 .hw_value = (_channel), \
765 .max_antenna_gain = 0, \
768 static struct ieee80211_channel mtk_5ghz_channels
[] = {
769 CHAN5G(34, 0), CHAN5G(36, 0),
770 CHAN5G(38, 0), CHAN5G(40, 0),
771 CHAN5G(42, 0), CHAN5G(44, 0),
772 CHAN5G(46, 0), CHAN5G(48, 0),
773 CHAN5G(52, 0), CHAN5G(56, 0),
774 CHAN5G(60, 0), CHAN5G(64, 0),
775 CHAN5G(100, 0), CHAN5G(104, 0),
776 CHAN5G(108, 0), CHAN5G(112, 0),
777 CHAN5G(116, 0), CHAN5G(120, 0),
778 CHAN5G(124, 0), CHAN5G(128, 0),
779 CHAN5G(132, 0), CHAN5G(136, 0),
780 CHAN5G(140, 0), CHAN5G(149, 0),
781 CHAN5G(153, 0), CHAN5G(157, 0),
782 CHAN5G(161, 0), CHAN5G(165, 0),
783 CHAN5G(169, 0), CHAN5G(173, 0),
784 CHAN5G(184, 0), CHAN5G(188, 0),
785 CHAN5G(192, 0), CHAN5G(196, 0),
786 CHAN5G(200, 0), CHAN5G(204, 0),
787 CHAN5G(208, 0), CHAN5G(212, 0),
791 /* for cfg80211 - rate table */
792 static struct ieee80211_rate mtk_rates
[] = {
793 RATETAB_ENT(10, 0x1000, 0),
794 RATETAB_ENT(20, 0x1001, 0),
795 RATETAB_ENT(55, 0x1002, 0),
796 RATETAB_ENT(110, 0x1003, 0), /* 802.11b */
797 RATETAB_ENT(60, 0x2000, 0),
798 RATETAB_ENT(90, 0x2001, 0),
799 RATETAB_ENT(120, 0x2002, 0),
800 RATETAB_ENT(180, 0x2003, 0),
801 RATETAB_ENT(240, 0x2004, 0),
802 RATETAB_ENT(360, 0x2005, 0),
803 RATETAB_ENT(480, 0x2006, 0),
804 RATETAB_ENT(540, 0x2007, 0), /* 802.11a/g */
807 #define mtk_a_rates (mtk_rates + 4)
808 #define mtk_a_rates_size (sizeof(mtk_rates) / sizeof(mtk_rates[0]) - 4)
809 #define mtk_g_rates (mtk_rates + 0)
810 #define mtk_g_rates_size (sizeof(mtk_rates) / sizeof(mtk_rates[0]) - 0)
812 #define MT6620_MCS_INFO \
814 .rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0},\
816 .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \
819 #define MT6620_HT_CAP \
821 .ht_supported = true, \
822 .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 \
823 | IEEE80211_HT_CAP_SM_PS \
824 | IEEE80211_HT_CAP_GRN_FLD \
825 | IEEE80211_HT_CAP_SGI_20 \
826 | IEEE80211_HT_CAP_SGI_40, \
827 .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \
828 .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, \
829 .mcs = MT6620_MCS_INFO, \
832 /* public for both Legacy Wi-Fi / P2P access */
833 struct ieee80211_supported_band mtk_band_2ghz
= {
834 .band
= IEEE80211_BAND_2GHZ
,
835 .channels
= mtk_2ghz_channels
,
836 .n_channels
= ARRAY_SIZE(mtk_2ghz_channels
),
837 .bitrates
= mtk_g_rates
,
838 .n_bitrates
= mtk_g_rates_size
,
839 .ht_cap
= MT6620_HT_CAP
,
842 /* public for both Legacy Wi-Fi / P2P access */
843 struct ieee80211_supported_band mtk_band_5ghz
= {
844 .band
= IEEE80211_BAND_5GHZ
,
845 .channels
= mtk_5ghz_channels
,
846 .n_channels
= ARRAY_SIZE(mtk_5ghz_channels
),
847 .bitrates
= mtk_a_rates
,
848 .n_bitrates
= mtk_a_rates_size
,
849 .ht_cap
= MT6620_HT_CAP
,
852 static const UINT_32 mtk_cipher_suites
[] = {
853 /* keep WEP first, it may be removed below */
854 WLAN_CIPHER_SUITE_WEP40
,
855 WLAN_CIPHER_SUITE_WEP104
,
856 WLAN_CIPHER_SUITE_TKIP
,
857 WLAN_CIPHER_SUITE_CCMP
,
859 /* keep last -- depends on hw flags! */
860 WLAN_CIPHER_SUITE_AES_CMAC
863 static struct cfg80211_ops mtk_wlan_ops
= {
864 .change_virtual_intf
= mtk_cfg80211_change_iface
,
865 .add_key
= mtk_cfg80211_add_key
,
866 .get_key
= mtk_cfg80211_get_key
,
867 .del_key
= mtk_cfg80211_del_key
,
868 .set_default_key
= mtk_cfg80211_set_default_key
,
869 .set_default_mgmt_key
= mtk_cfg80211_set_default_mgmt_key
,
870 .get_station
= mtk_cfg80211_get_station
,
871 .change_station
= mtk_cfg80211_change_station
,
872 .add_station
= mtk_cfg80211_add_station
,
873 .del_station
= mtk_cfg80211_del_station
,
874 .scan
= mtk_cfg80211_scan
,
875 .connect
= mtk_cfg80211_connect
,
876 .disconnect
= mtk_cfg80211_disconnect
,
877 .join_ibss
= mtk_cfg80211_join_ibss
,
878 .leave_ibss
= mtk_cfg80211_leave_ibss
,
879 .set_power_mgmt
= mtk_cfg80211_set_power_mgmt
,
880 .set_pmksa
= mtk_cfg80211_set_pmksa
,
881 .del_pmksa
= mtk_cfg80211_del_pmksa
,
882 .flush_pmksa
= mtk_cfg80211_flush_pmksa
,
883 .assoc
= mtk_cfg80211_assoc
,
885 /* Action Frame TX/RX */
886 .remain_on_channel
= mtk_cfg80211_remain_on_channel
,
887 .cancel_remain_on_channel
= mtk_cfg80211_cancel_remain_on_channel
,
888 .mgmt_tx
= mtk_cfg80211_mgmt_tx
,
889 // .mgmt_tx_cancel_wait = mtk_cfg80211_mgmt_tx_cancel_wait,
890 .mgmt_frame_register
= mtk_cfg80211_mgmt_frame_register
,
891 #ifdef CONFIG_NL80211_TESTMODE
892 .testmode_cmd
= mtk_cfg80211_testmode_cmd
,
894 #if (CFG_SUPPORT_TDLS == 1)
895 .tdls_mgmt
= TdlsexCfg80211TdlsMgmt
,
896 .tdls_oper
= TdlsexCfg80211TdlsOper
897 #endif /* CFG_SUPPORT_TDLS */
901 /* There isn't a lot of sense in it, but you can transmit anything you like */
902 static const struct ieee80211_txrx_stypes
903 mtk_cfg80211_ais_default_mgmt_stypes
[NUM_NL80211_IFTYPES
] = {
904 [NL80211_IFTYPE_ADHOC
] = {
906 .rx
= BIT(IEEE80211_STYPE_ACTION
>> 4)
908 [NL80211_IFTYPE_STATION
] = {
910 .rx
= BIT(IEEE80211_STYPE_ACTION
>> 4) |
911 BIT(IEEE80211_STYPE_PROBE_REQ
>> 4)
913 [NL80211_IFTYPE_AP
] = {
915 .rx
= BIT(IEEE80211_STYPE_PROBE_REQ
>> 4) |
916 BIT(IEEE80211_STYPE_ACTION
>> 4)
918 [NL80211_IFTYPE_AP_VLAN
] = {
921 .rx
= BIT(IEEE80211_STYPE_ASSOC_REQ
>> 4) |
922 BIT(IEEE80211_STYPE_REASSOC_REQ
>> 4) |
923 BIT(IEEE80211_STYPE_PROBE_REQ
>> 4) |
924 BIT(IEEE80211_STYPE_DISASSOC
>> 4) |
925 BIT(IEEE80211_STYPE_AUTH
>> 4) |
926 BIT(IEEE80211_STYPE_DEAUTH
>> 4) |
927 BIT(IEEE80211_STYPE_ACTION
>> 4)
929 [NL80211_IFTYPE_P2P_CLIENT
] = {
931 .rx
= BIT(IEEE80211_STYPE_ACTION
>> 4) |
932 BIT(IEEE80211_STYPE_PROBE_REQ
>> 4)
934 [NL80211_IFTYPE_P2P_GO
] = {
936 .rx
= BIT(IEEE80211_STYPE_PROBE_REQ
>> 4) |
937 BIT(IEEE80211_STYPE_ACTION
>> 4)
942 /*******************************************************************************
944 ********************************************************************************
947 /*******************************************************************************
948 * F U N C T I O N D E C L A R A T I O N S
949 ********************************************************************************
952 /*******************************************************************************
954 ********************************************************************************
957 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
958 /*----------------------------------------------------------------------------*/
960 * \brief Override the implementation of select queue
962 * \param[in] dev Pointer to struct net_device
963 * \param[in] skb Pointer to struct skb_buff
967 /*----------------------------------------------------------------------------*/
968 unsigned int _cfg80211_classify8021d(struct sk_buff
*skb
)
970 unsigned int dscp
= 0;
972 /* skb->priority values from 256->263 are magic values
973 * directly indicate a specific 802.1d priority. This is
974 * to allow 802.1d priority to be passed directly in from
978 if (skb
->priority
>= 256 && skb
->priority
<= 263) {
979 return skb
->priority
- 256;
981 switch (skb
->protocol
) {
982 case htons(ETH_P_IP
):
983 dscp
= ip_hdr(skb
)->tos
& 0xfc;
990 static const UINT_16 au16Wlan1dToQueueIdx
[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
994 struct net_device
*dev
,
997 skb
->priority
= _cfg80211_classify8021d(skb
);
999 return au16Wlan1dToQueueIdx
[skb
->priority
];
1003 /*----------------------------------------------------------------------------*/
1005 * \brief Load NVRAM data and translate it into REG_INFO_T
1007 * \param[in] prGlueInfo Pointer to struct GLUE_INFO_T
1008 * \param[out] prRegInfo Pointer to struct REG_INFO_T
1012 /*----------------------------------------------------------------------------*/
1015 IN P_GLUE_INFO_T prGlueInfo
,
1016 OUT P_REG_INFO_T prRegInfo
1026 if((!prGlueInfo
) || (!prRegInfo
)) {
1030 if(kalCfgDataRead16(prGlueInfo
,
1031 sizeof(WIFI_CFG_PARAM_STRUCT
) - sizeof(UINT_16
),
1032 (PUINT_16
)aucTmp
) == TRUE
) {
1033 prGlueInfo
->fgNvramAvailable
= TRUE
;
1036 #if !defined(CONFIG_MTK_TC1_FEATURE)
1037 for (i
= 0 ; i
< sizeof(PARAM_MAC_ADDR_LEN
) ; i
+= sizeof(UINT_16
)) {
1038 kalCfgDataRead16(prGlueInfo
,
1039 OFFSET_OF(WIFI_CFG_PARAM_STRUCT
, aucMacAddress
) + i
,
1040 (PUINT_16
) (((PUINT_8
)prRegInfo
->aucMacAddr
) + i
));
1043 TC1_FAC_NAME(FacReadWifiMacAddr
)((unsigned char *)prRegInfo
->aucMacAddr
);
1046 // load country code
1047 kalCfgDataRead16(prGlueInfo
,
1048 OFFSET_OF(WIFI_CFG_PARAM_STRUCT
, aucCountryCode
[0]),
1051 // cast to wide characters
1052 prRegInfo
->au2CountryCode
[0] = (UINT_16
) aucTmp
[0];
1053 prRegInfo
->au2CountryCode
[1] = (UINT_16
) aucTmp
[1];
1055 // load default normal TX power
1056 for (i
= 0 ; i
< sizeof(TX_PWR_PARAM_T
) ; i
+= sizeof(UINT_16
)) {
1057 kalCfgDataRead16(prGlueInfo
,
1058 OFFSET_OF(WIFI_CFG_PARAM_STRUCT
, rTxPwr
) + i
,
1059 (PUINT_16
) (((PUINT_8
)&(prRegInfo
->rTxPwr
)) + i
));
1062 // load feature flags
1063 kalCfgDataRead16(prGlueInfo
,
1064 OFFSET_OF(WIFI_CFG_PARAM_STRUCT
, ucTxPwrValid
),
1066 prRegInfo
->ucTxPwrValid
= aucTmp
[0];
1067 prRegInfo
->ucSupport5GBand
= aucTmp
[1];
1069 kalCfgDataRead16(prGlueInfo
,
1070 OFFSET_OF(WIFI_CFG_PARAM_STRUCT
, uc2G4BwFixed20M
),
1072 prRegInfo
->uc2G4BwFixed20M
= aucTmp
[0];
1073 prRegInfo
->uc5GBwFixed20M
= aucTmp
[1];
1075 kalCfgDataRead16(prGlueInfo
,
1076 OFFSET_OF(WIFI_CFG_PARAM_STRUCT
, ucEnable5GBand
),
1078 prRegInfo
->ucEnable5GBand
= aucTmp
[0];
1080 /* load EFUSE overriding part */
1081 for (i
= 0 ; i
< sizeof(prRegInfo
->aucEFUSE
) ; i
+= sizeof(UINT_16
)) {
1082 kalCfgDataRead16(prGlueInfo
,
1083 OFFSET_OF(WIFI_CFG_PARAM_STRUCT
, aucEFUSE
) + i
,
1084 (PUINT_16
) (((PUINT_8
)&(prRegInfo
->aucEFUSE
)) + i
));
1087 /* load band edge tx power control */
1088 kalCfgDataRead16(prGlueInfo
,
1089 OFFSET_OF(WIFI_CFG_PARAM_STRUCT
, fg2G4BandEdgePwrUsed
),
1091 prRegInfo
->fg2G4BandEdgePwrUsed
= (BOOLEAN
)aucTmp
[0];
1093 prRegInfo
->cBandEdgeMaxPwrCCK
= (INT_8
)aucTmp
[1];
1095 kalCfgDataRead16(prGlueInfo
,
1096 OFFSET_OF(WIFI_CFG_PARAM_STRUCT
, cBandEdgeMaxPwrOFDM20
),
1098 prRegInfo
->cBandEdgeMaxPwrOFDM20
= (INT_8
)aucTmp
[0];
1099 prRegInfo
->cBandEdgeMaxPwrOFDM40
= (INT_8
)aucTmp
[1];
1102 /* load regulation subbands */
1103 kalCfgDataRead16(prGlueInfo
,
1104 OFFSET_OF(WIFI_CFG_PARAM_STRUCT
, ucRegChannelListMap
),
1106 prRegInfo
->eRegChannelListMap
= (ENUM_REG_CH_MAP_T
) aucTmp
[0];
1107 prRegInfo
->ucRegChannelListIndex
= aucTmp
[1];
1109 if (prRegInfo
->eRegChannelListMap
== REG_CH_MAP_CUSTOMIZED
) {
1110 for (i
= 0 ; i
< MAX_SUBBAND_NUM
; i
++) {
1111 pucDest
= (PUINT_8
) &prRegInfo
->rDomainInfo
.rSubBand
[i
];
1112 for (j
= 0; j
< 6; j
+= sizeof(UINT_16
)) {
1113 kalCfgDataRead16(prGlueInfo
,
1114 OFFSET_OF(WIFI_CFG_PARAM_STRUCT
, aucRegSubbandInfo
)
1118 *pucDest
++ = aucTmp
[0];
1119 *pucDest
++ = aucTmp
[1];
1123 /* load RSSI compensation */
1124 kalCfgDataRead16(prGlueInfo
,
1125 OFFSET_OF(WIFI_CFG_PARAM_STRUCT
, uc2GRssiCompensation
),
1127 prRegInfo
->uc2GRssiCompensation
= aucTmp
[0];
1128 prRegInfo
->uc5GRssiCompensation
= aucTmp
[1];
1130 kalCfgDataRead16(prGlueInfo
,
1131 OFFSET_OF(WIFI_CFG_PARAM_STRUCT
, fgRssiCompensationValidbit
),
1133 prRegInfo
->fgRssiCompensationValidbit
= aucTmp
[0];
1134 prRegInfo
->ucRxAntennanumber
= aucTmp
[1];
1137 prGlueInfo
->fgNvramAvailable
= FALSE
;
1144 #if CFG_ENABLE_WIFI_DIRECT
1145 /*----------------------------------------------------------------------------*/
1147 * \brief called by txthread, run sub module init function
1149 * \param[in] prGlueInfo Pointer to struct GLUE_INFO_T
1153 /*----------------------------------------------------------------------------*/
1156 P_GLUE_INFO_T prGlueInfo
1159 /*now, we only have p2p module*/
1160 if(rSubModHandler
[P2P_MODULE
].fgIsInited
== FALSE
) {
1161 rSubModHandler
[P2P_MODULE
].subModInit(prGlueInfo
);
1162 rSubModHandler
[P2P_MODULE
].fgIsInited
= TRUE
;
1167 /*----------------------------------------------------------------------------*/
1169 * \brief called by txthread, run sub module exit function
1171 * \param[in] prGlueInfo Pointer to struct GLUE_INFO_T
1175 /*----------------------------------------------------------------------------*/
1178 P_GLUE_INFO_T prGlueInfo
1181 /*now, we only have p2p module*/
1182 if(rSubModHandler
[P2P_MODULE
].fgIsInited
== TRUE
) {
1183 rSubModHandler
[P2P_MODULE
].subModExit(prGlueInfo
);
1184 rSubModHandler
[P2P_MODULE
].fgIsInited
= FALSE
;
1188 /*----------------------------------------------------------------------------*/
1190 * \brief set sub module init flag, force TxThread to run sub modle init
1192 * \param[in] prGlueInfo Pointer to struct GLUE_INFO_T
1196 /*----------------------------------------------------------------------------*/
1199 P_GLUE_INFO_T prGlueInfo
1202 //4 Mark HALT, notify main thread to finish current job
1203 prGlueInfo
->ulFlag
|= GLUE_FLAG_SUB_MOD_INIT
;
1204 /* wake up main thread */
1205 wake_up_interruptible(&prGlueInfo
->waitq
);
1206 /* wait main thread finish sub module INIT*/
1207 wait_for_completion_interruptible(&prGlueInfo
->rSubModComp
);
1210 if(prGlueInfo
->prAdapter
->fgIsP2PRegistered
) {
1211 p2pNetRegister(prGlueInfo
);
1218 /*----------------------------------------------------------------------------*/
1220 * \brief set sub module exit flag, force TxThread to run sub modle exit
1222 * \param[in] prGlueInfo Pointer to struct GLUE_INFO_T
1226 /*----------------------------------------------------------------------------*/
1229 P_GLUE_INFO_T prGlueInfo
1233 if(prGlueInfo
->prAdapter
->fgIsP2PRegistered
) {
1234 p2pNetUnregister(prGlueInfo
);
1238 //4 Mark HALT, notify main thread to finish current job
1239 prGlueInfo
->ulFlag
|= GLUE_FLAG_SUB_MOD_EXIT
;
1240 /* wake up main thread */
1241 wake_up_interruptible(&prGlueInfo
->waitq
);
1242 /* wait main thread finish sub module EXIT */
1243 wait_for_completion_interruptible(&prGlueInfo
->rSubModComp
);
1249 /*----------------------------------------------------------------------------*/
1251 * \brief set by sub module, indicate sub module is already inserted
1253 * \param[in] rSubModInit, function pointer point to sub module init function
1254 * \param[in] rSubModExit, function pointer point to sub module exit function
1255 * \param[in] eSubModIdx, sub module index
1259 /*----------------------------------------------------------------------------*/
1261 wlanSubModRegisterInitExit(
1262 SUB_MODULE_INIT rSubModInit
,
1263 SUB_MODULE_EXIT rSubModExit
,
1264 ENUM_SUB_MODULE_IDX_T eSubModIdx
1267 rSubModHandler
[eSubModIdx
].subModInit
= rSubModInit
;
1268 rSubModHandler
[eSubModIdx
].subModExit
= rSubModExit
;
1269 rSubModHandler
[eSubModIdx
].fgIsInited
= FALSE
;
1273 /*----------------------------------------------------------------------------*/
1275 * \brief check wlan is launched or not
1279 * \return TRUE, wlan is already started
1280 * FALSE, wlan is not started yet
1282 /*----------------------------------------------------------------------------*/
1288 struct net_device
*prDev
= NULL
;
1289 P_GLUE_INFO_T prGlueInfo
= NULL
;
1291 //4 <0> Sanity check
1292 ASSERT(u4WlanDevNum
<= CFG_MAX_WLAN_DEVICES
);
1293 if (0 == u4WlanDevNum
) {
1297 prDev
= arWlanDevInfo
[u4WlanDevNum
-1].prDev
;
1300 if (NULL
== prDev
) {
1304 prGlueInfo
= *((P_GLUE_INFO_T
*) netdev_priv(prDev
));
1306 if (NULL
== prGlueInfo
) {
1310 return prGlueInfo
->prAdapter
->fgIsWlanLaunched
;
1315 /*----------------------------------------------------------------------------*/
1317 * \brief Export wlan GLUE_INFO_T pointer to p2p module
1319 * \param[in] prGlueInfo Pointer to struct GLUE_INFO_T
1321 * \return TRUE: get GlueInfo pointer successfully
1322 * FALSE: wlan is not started yet
1324 /*---------------------------------------------------------------------------*/
1327 P_GLUE_INFO_T
*prGlueInfoExpAddr
1330 struct net_device
*prDev
= NULL
;
1331 P_GLUE_INFO_T prGlueInfo
= NULL
;
1333 if (0 == u4WlanDevNum
) {
1337 prDev
= arWlanDevInfo
[u4WlanDevNum
-1].prDev
;
1338 if (NULL
== prDev
) {
1342 prGlueInfo
= *((P_GLUE_INFO_T
*) netdev_priv(prDev
));
1343 if (NULL
== prGlueInfo
) {
1347 if(FALSE
== prGlueInfo
->prAdapter
->fgIsWlanLaunched
) {
1351 *prGlueInfoExpAddr
= prGlueInfo
;
1358 /*----------------------------------------------------------------------------*/
1360 * \brief Release prDev from wlandev_array and free tasklet object related to it.
1362 * \param[in] prDev Pointer to struct net_device
1366 /*----------------------------------------------------------------------------*/
1369 struct net_device
*prDev
1376 for (i
= 0; i
< CFG_MAX_WLAN_DEVICES
; i
++) {
1377 if (arWlanDevInfo
[i
].prDev
== prDev
) {
1378 arWlanDevInfo
[i
].prDev
= NULL
;
1384 } /* end of wlanClearDevIdx() */
1387 /*----------------------------------------------------------------------------*/
1389 * \brief Allocate an unique interface index, net_device::ifindex member for this
1390 * wlan device. Store the net_device in wlandev_array, and initialize
1391 * tasklet object related to it.
1393 * \param[in] prDev Pointer to struct net_device
1395 * \retval >= 0 The device number.
1396 * \retval -1 Fail to get index.
1398 /*----------------------------------------------------------------------------*/
1401 struct net_device
*prDev
1408 for (i
= 0; i
< CFG_MAX_WLAN_DEVICES
; i
++) {
1409 if (arWlanDevInfo
[i
].prDev
== (struct net_device
*) NULL
) {
1410 /* Reserve 2 bytes space to store one digit of
1411 * device number and NULL terminator.
1413 arWlanDevInfo
[i
].prDev
= prDev
;
1420 } /* end of wlanGetDevIdx() */
1422 /*----------------------------------------------------------------------------*/
1424 * \brief A method of struct net_device, a primary SOCKET interface to configure
1425 * the interface lively. Handle an ioctl call on one of our devices.
1426 * Everything Linux ioctl specific is done here. Then we pass the contents
1427 * of the ifr->data to the request message handler.
1429 * \param[in] prDev Linux kernel netdevice
1431 * \param[in] prIFReq Our private ioctl request structure, typed for the generic
1432 * struct ifreq so we can use ptr to function
1434 * \param[in] cmd Command ID
1436 * \retval WLAN_STATUS_SUCCESS The IOCTL command is executed successfully.
1437 * \retval OTHER The execution of IOCTL command is failed.
1439 /*----------------------------------------------------------------------------*/
1442 struct net_device
*prDev
,
1443 struct ifreq
*prIFReq
,
1447 P_GLUE_INFO_T prGlueInfo
= NULL
;
1450 /* Verify input parameters for the following functions */
1451 ASSERT(prDev
&& prIFReq
);
1452 if (!prDev
|| !prIFReq
) {
1453 DBGLOG(INIT
, WARN
, ("%s Invalid input data\n", __FUNCTION__
));
1457 prGlueInfo
= *((P_GLUE_INFO_T
*) netdev_priv(prDev
));
1460 DBGLOG(INIT
, WARN
, ("%s No glue info\n", __FUNCTION__
));
1464 if (prGlueInfo
->u4ReadyFlag
== 0) {
1468 //printk ("ioctl %x\n", i4Cmd);
1470 if (i4Cmd
== SIOCGIWPRIV
) {
1471 /* 0x8B0D, get private ioctl table */
1472 ret
= wext_get_priv(prDev
, prIFReq
);
1474 else if ((i4Cmd
>= SIOCIWFIRST
) && (i4Cmd
< SIOCIWFIRSTPRIV
)) {
1475 /* 0x8B00 ~ 0x8BDF, wireless extension region */
1476 ret
= wext_support_ioctl(prDev
, prIFReq
, i4Cmd
);
1478 else if ((i4Cmd
>= SIOCIWFIRSTPRIV
) && (i4Cmd
< SIOCIWLASTPRIV
)) {
1479 /* 0x8BE0 ~ 0x8BFF, private ioctl region */
1480 ret
= priv_support_ioctl(prDev
, prIFReq
, i4Cmd
);
1483 DBGLOG(INIT
, WARN
, ("Unexpected ioctl command: 0x%04x\n", i4Cmd
));
1484 /* return 0 for safe? */
1488 } /* end of wlanDoIOCTL() */
1490 /*----------------------------------------------------------------------------*/
1492 * \brief This function is to set multicast list and set rx mode.
1494 * \param[in] prDev Pointer to struct net_device
1498 /*----------------------------------------------------------------------------*/
1500 static struct delayed_work workq
;
1501 static struct net_device
*gPrDev
;
1502 static BOOLEAN fgIsWorkMcStart
= FALSE
;
1503 static BOOLEAN fgIsWorkMcEverInit
= FALSE
;
1506 wlanSetMulticastList (struct net_device
*prDev
)
1509 schedule_delayed_work(&workq
, 0);
1512 /* FIXME: Since we cannot sleep in the wlanSetMulticastList, we arrange
1513 * another workqueue for sleeping. We don't want to block
1514 * tx_thread, so we can't let tx_thread to do this */
1517 wlanSetMulticastListWorkQueue (struct work_struct
*work
) {
1519 P_GLUE_INFO_T prGlueInfo
= NULL
;
1520 UINT_32 u4PacketFilter
= 0;
1521 UINT_32 u4SetInfoLen
;
1522 struct net_device
*prDev
= gPrDev
;
1524 fgIsWorkMcStart
= TRUE
;
1526 DBGLOG(INIT
, INFO
, ("wlanSetMulticastListWorkQueue start...\n"));
1530 fgIsWorkMcStart
= FALSE
;
1535 prGlueInfo
= (NULL
!= prDev
) ? *((P_GLUE_INFO_T
*) netdev_priv(prDev
)) : NULL
;
1538 if (!prDev
|| !prGlueInfo
) {
1539 DBGLOG(INIT
, WARN
, ("abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n",
1540 prDev
, prGlueInfo
));
1541 fgIsWorkMcStart
= FALSE
;
1546 if (prDev
->flags
& IFF_PROMISC
) {
1547 u4PacketFilter
|= PARAM_PACKET_FILTER_PROMISCUOUS
;
1550 if (prDev
->flags
& IFF_BROADCAST
) {
1551 u4PacketFilter
|= PARAM_PACKET_FILTER_BROADCAST
;
1554 if (prDev
->flags
& IFF_MULTICAST
) {
1555 if ((prDev
->flags
& IFF_ALLMULTI
) ||
1556 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
1557 (netdev_mc_count(prDev
) > MAX_NUM_GROUP_ADDR
)) {
1559 (prDev
->mc_count
> MAX_NUM_GROUP_ADDR
)) {
1562 u4PacketFilter
|= PARAM_PACKET_FILTER_ALL_MULTICAST
;
1565 u4PacketFilter
|= PARAM_PACKET_FILTER_MULTICAST
;
1571 if (kalIoctl(prGlueInfo
,
1572 wlanoidSetCurrentPacketFilter
,
1574 sizeof(u4PacketFilter
),
1579 &u4SetInfoLen
) != WLAN_STATUS_SUCCESS
) {
1580 fgIsWorkMcStart
= FALSE
;
1585 if (u4PacketFilter
& PARAM_PACKET_FILTER_MULTICAST
) {
1586 /* Prepare multicast address list */
1587 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
1588 struct netdev_hw_addr
*ha
;
1590 struct dev_mc_list
*prMcList
;
1592 PUINT_8 prMCAddrList
= NULL
;
1597 fgIsWorkMcStart
= FALSE
;
1602 prMCAddrList
= kalMemAlloc(MAX_NUM_GROUP_ADDR
* ETH_ALEN
, VIR_MEM_TYPE
);
1604 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
1605 netdev_for_each_mc_addr(ha
, prDev
) {
1606 if(i
< MAX_NUM_GROUP_ADDR
) {
1607 memcpy((prMCAddrList
+ i
* ETH_ALEN
), ha
->addr
, ETH_ALEN
);
1612 for (i
= 0, prMcList
= prDev
->mc_list
;
1613 (prMcList
) && (i
< prDev
->mc_count
) && (i
< MAX_NUM_GROUP_ADDR
);
1614 i
++, prMcList
= prMcList
->next
) {
1615 memcpy((prMCAddrList
+ i
* ETH_ALEN
), prMcList
->dmi_addr
, ETH_ALEN
);
1621 kalIoctl(prGlueInfo
,
1622 wlanoidSetMulticastList
,
1631 kalMemFree(prMCAddrList
, VIR_MEM_TYPE
, MAX_NUM_GROUP_ADDR
* ETH_ALEN
);
1634 fgIsWorkMcStart
= FALSE
;
1635 DBGLOG(INIT
, INFO
, ("wlanSetMulticastListWorkQueue end\n"));
1637 } /* end of wlanSetMulticastList() */
1640 /* FIXME: Since we cannot sleep in the wlanSetMulticastList, we arrange
1641 * another workqueue for sleeping. We don't want to block
1642 * tx_thread, so we can't let tx_thread to do this */
1645 p2pSetMulticastListWorkQueueWrapper (P_GLUE_INFO_T prGlueInfo
) {
1650 DBGLOG(INIT
, WARN
, ("abnormal dev or skb: prGlueInfo(0x%p)\n",
1655 #if CFG_ENABLE_WIFI_DIRECT
1656 if(prGlueInfo
->prAdapter
->fgIsP2PRegistered
) {
1657 mtk_p2p_wext_set_Multicastlist(prGlueInfo
);
1662 } /* end of p2pSetMulticastListWorkQueueWrapper() */
1666 /*----------------------------------------------------------------------------*/
1668 * \brief This function is TX entry point of NET DEVICE.
1670 * \param[in] prSkb Pointer of the sk_buff to be sent
1671 * \param[in] prDev Pointer to struct net_device
1673 * \retval NETDEV_TX_OK - on success.
1674 * \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer.
1676 /*----------------------------------------------------------------------------*/
1679 struct sk_buff
*prSkb
,
1680 struct net_device
*prDev
1683 P_GLUE_INFO_T prGlueInfo
= *((P_GLUE_INFO_T
*) netdev_priv(prDev
));
1685 P_QUE_ENTRY_T prQueueEntry
= NULL
;
1686 P_QUE_T prTxQueue
= NULL
;
1687 UINT_16 u2QueueIdx
= 0;
1688 #if (CFG_SUPPORT_TDLS_DBG == 1)
1689 UINT16 u2Identifier
= 0;
1696 GLUE_SPIN_LOCK_DECLARATION();
1702 #if (CFG_SUPPORT_TDLS_DBG == 1)
1704 UINT8
*pkt
= prSkb
->data
;
1705 if ((*(pkt
+12) == 0x08) && (*(pkt
+13) == 0x00))
1708 u2Identifier
= ((*(pkt
+18)) << 8) | (*(pkt
+19));
1709 // u2TdlsTxSeq[u4TdlsTxSeqId ++] = u2Identifier;
1710 printk("<s> %d\n", u2Identifier
);
1714 /* check if WiFi is halt */
1715 if (prGlueInfo
->ulFlag
& GLUE_FLAG_HALT
) {
1716 DBGLOG(INIT
, INFO
, ("GLUE_FLAG_HALT skip tx\n"));
1717 dev_kfree_skb(prSkb
);
1718 return NETDEV_TX_OK
;
1721 #if CFG_SUPPORT_HOTSPOT_2_0
1722 if (prGlueInfo
->fgIsDad
) {
1723 //kalPrint("[Passpoint R2] Due to ipv4_dad...TX is forbidden\n");
1724 dev_kfree_skb(prSkb
);
1725 return NETDEV_TX_OK
;
1727 if (prGlueInfo
->fgIs6Dad
) {
1728 //kalPrint("[Passpoint R2] Due to ipv6_dad...TX is forbidden\n");
1729 dev_kfree_skb(prSkb
);
1730 return NETDEV_TX_OK
;
1734 STATS_TX_TIME_ARRIVE(prSkb
);
1735 prQueueEntry
= (P_QUE_ENTRY_T
) GLUE_GET_PKT_QUEUE_ENTRY(prSkb
);
1736 prTxQueue
= &prGlueInfo
->rTxQueue
;
1739 DBGLOG(BOW
, TRACE
, ("sk_buff->len: %d\n", prSkb
->len
));
1740 DBGLOG(BOW
, TRACE
, ("sk_buff->data_len: %d\n", prSkb
->data_len
));
1741 DBGLOG(BOW
, TRACE
, ("sk_buff->data:\n"));
1743 for(i
= 0; i
< prSkb
->len
; i
++)
1745 DBGLOG(BOW
, TRACE
, ("%4x", prSkb
->data
[i
]));
1749 DBGLOG(BOW
, TRACE
, ("\n"));
1753 DBGLOG(BOW
, TRACE
, ("\n"));
1756 if (wlanProcessSecurityFrame(prGlueInfo
->prAdapter
, (P_NATIVE_PACKET
) prSkb
) == FALSE
) {
1758 /* non-1x packets */
1760 #if CFG_DBG_GPIO_PINS
1762 /* TX request from OS */
1763 mtk_wcn_stp_debug_gpio_assert(IDX_TX_REQ
, DBG_TIE_LOW
);
1765 mtk_wcn_stp_debug_gpio_assert(IDX_TX_REQ
, DBG_TIE_HIGH
);
1769 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
1770 u2QueueIdx
= skb_get_queue_mapping(prSkb
);
1771 ASSERT(u2QueueIdx
< CFG_MAX_TXQ_NUM
);
1774 #if CFG_ENABLE_PKT_LIFETIME_PROFILE
1775 GLUE_SET_PKT_ARRIVAL_TIME(prSkb
, kalGetTimeTick());
1777 GLUE_INC_REF_CNT(prGlueInfo
->i4TxPendingFrameNum
);
1778 GLUE_INC_REF_CNT(prGlueInfo
->ai4TxPendingFrameNumPerQueue
[NETWORK_TYPE_AIS_INDEX
][u2QueueIdx
]);
1780 GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo
, SPIN_LOCK_TX_QUE
);
1781 QUEUE_INSERT_TAIL(prTxQueue
, prQueueEntry
);
1782 GLUE_RELEASE_SPIN_LOCK(prGlueInfo
, SPIN_LOCK_TX_QUE
);
1784 // GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum);
1785 // GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx]);
1787 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
1788 if (prGlueInfo
->ai4TxPendingFrameNumPerQueue
[NETWORK_TYPE_AIS_INDEX
][u2QueueIdx
] >= CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD
) {
1789 netif_stop_subqueue(prDev
, u2QueueIdx
);
1791 #if (CONF_HIF_LOOPBACK_AUTO == 1)
1792 prGlueInfo
->rHifInfo
.HifLoopbkFlg
|= 0x01;
1793 #endif /* CONF_HIF_LOOPBACK_AUTO */
1796 if (prGlueInfo
->i4TxPendingFrameNum
>= CFG_TX_STOP_NETIF_QUEUE_THRESHOLD
) {
1797 netif_stop_queue(prDev
);
1799 #if (CONF_HIF_LOOPBACK_AUTO == 1)
1800 prGlueInfo
->rHifInfo
.HifLoopbkFlg
|= 0x01;
1801 #endif /* CONF_HIF_LOOPBACK_AUTO */
1805 //printk("is security frame\n");
1807 GLUE_INC_REF_CNT(prGlueInfo
->i4TxPendingSecurityFrameNum
);
1810 DBGLOG(TX
, EVENT
, ("\n+++++ pending frame %d len = %d +++++\n", prGlueInfo
->i4TxPendingFrameNum
, prSkb
->len
));
1811 prGlueInfo
->rNetDevStats
.tx_bytes
+= prSkb
->len
;
1812 prGlueInfo
->rNetDevStats
.tx_packets
++;
1814 /* set GLUE_FLAG_TXREQ_BIT */
1816 //pr->u4Flag |= GLUE_FLAG_TXREQ;
1817 //wake_up_interruptible(&prGlueInfo->waitq);
1818 kalSetEvent(prGlueInfo
);
1821 /* For Linux, we'll always return OK FLAG, because we'll free this skb by ourself */
1822 return NETDEV_TX_OK
;
1823 } /* end of wlanHardStartXmit() */
1826 /*----------------------------------------------------------------------------*/
1828 * \brief A method of struct net_device, to get the network interface statistical
1831 * Whenever an application needs to get statistics for the interface, this method
1832 * is called. This happens, for example, when ifconfig or netstat -i is run.
1834 * \param[in] prDev Pointer to struct net_device.
1836 * \return net_device_stats buffer pointer.
1838 /*----------------------------------------------------------------------------*/
1839 struct net_device_stats
*
1841 IN
struct net_device
*prDev
1844 P_GLUE_INFO_T prGlueInfo
= *((P_GLUE_INFO_T
*) netdev_priv(prDev
));
1847 WLAN_STATUS rStatus
;
1848 UINT_32 u4XmitError
= 0;
1849 UINT_32 u4XmitOk
= 0;
1850 UINT_32 u4RecvError
= 0;
1851 UINT_32 u4RecvOk
= 0;
1856 /* @FIX ME: need a more clear way to do this */
1859 rStatus
= kalIoctl(prGlueInfo
,
1860 wlanoidQueryXmitError
,
1868 rStatus
= kalIoctl(prGlueInfo
,
1876 rStatus
= kalIoctl(prGlueInfo
,
1884 rStatus
= kalIoctl(prGlueInfo
,
1885 wlanoidQueryRcvError
,
1892 prGlueInfo
->rNetDevStats
.rx_packets
= u4RecvOk
;
1893 prGlueInfo
->rNetDevStats
.tx_packets
= u4XmitOk
;
1894 prGlueInfo
->rNetDevStats
.tx_errors
= u4XmitError
;
1895 prGlueInfo
->rNetDevStats
.rx_errors
= u4RecvError
;
1896 //prGlueInfo->rNetDevStats.rx_bytes = rCustomNetDevStats.u4RxBytes;
1897 //prGlueInfo->rNetDevStats.tx_bytes = rCustomNetDevStats.u4TxBytes;
1898 //prGlueInfo->rNetDevStats.rx_errors = rCustomNetDevStats.u4RxErrors;
1899 //prGlueInfo->rNetDevStats.multicast = rCustomNetDevStats.u4Multicast;
1901 //prGlueInfo->rNetDevStats.rx_packets = 0;
1902 //prGlueInfo->rNetDevStats.tx_packets = 0;
1903 prGlueInfo
->rNetDevStats
.tx_errors
= 0;
1904 prGlueInfo
->rNetDevStats
.rx_errors
= 0;
1905 //prGlueInfo->rNetDevStats.rx_bytes = 0;
1906 //prGlueInfo->rNetDevStats.tx_bytes = 0;
1907 prGlueInfo
->rNetDevStats
.rx_errors
= 0;
1908 prGlueInfo
->rNetDevStats
.multicast
= 0;
1910 return &prGlueInfo
->rNetDevStats
;
1912 } /* end of wlanGetStats() */
1914 /*----------------------------------------------------------------------------*/
1916 * \brief A function for prDev->init
1918 * \param[in] prDev Pointer to struct net_device.
1920 * \retval 0 The execution of wlanInit succeeds.
1921 * \retval -ENXIO No such device.
1923 /*----------------------------------------------------------------------------*/
1926 struct net_device
*prDev
1929 P_GLUE_INFO_T prGlueInfo
= NULL
;
1931 if (fgIsWorkMcEverInit
== FALSE
)
1937 prGlueInfo
= *((P_GLUE_INFO_T
*) netdev_priv(prDev
));
1938 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12)
1939 INIT_DELAYED_WORK(&workq
, wlanSetMulticastListWorkQueue
);
1941 INIT_DELAYED_WORK(&workq
, wlanSetMulticastListWorkQueue
, NULL
);
1944 fgIsWorkMcEverInit
= TRUE
;
1947 return 0; /* success */
1948 } /* end of wlanInit() */
1951 /*----------------------------------------------------------------------------*/
1953 * \brief A function for prDev->uninit
1955 * \param[in] prDev Pointer to struct net_device.
1959 /*----------------------------------------------------------------------------*/
1962 struct net_device
*prDev
1966 } /* end of wlanUninit() */
1969 /*----------------------------------------------------------------------------*/
1971 * \brief A function for prDev->open
1973 * \param[in] prDev Pointer to struct net_device.
1975 * \retval 0 The execution of wlanOpen succeeds.
1976 * \retval < 0 The execution of wlanOpen failed.
1978 /*----------------------------------------------------------------------------*/
1981 struct net_device
*prDev
1986 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
1987 netif_tx_start_all_queues(prDev
);
1989 netif_start_queue(prDev
);
1992 return 0; /* success */
1993 } /* end of wlanOpen() */
1996 /*----------------------------------------------------------------------------*/
1998 * \brief A function for prDev->stop
2000 * \param[in] prDev Pointer to struct net_device.
2002 * \retval 0 The execution of wlanStop succeeds.
2003 * \retval < 0 The execution of wlanStop failed.
2005 /*----------------------------------------------------------------------------*/
2008 struct net_device
*prDev
2011 P_GLUE_INFO_T prGlueInfo
= NULL
;
2012 struct cfg80211_scan_request
*prScanRequest
= NULL
;
2013 GLUE_SPIN_LOCK_DECLARATION();
2017 prGlueInfo
= *((P_GLUE_INFO_T
*) netdev_priv(prDev
));
2020 GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo
, SPIN_LOCK_NET_DEV
);
2021 if(prGlueInfo
->prScanRequest
!= NULL
) {
2022 prScanRequest
= prGlueInfo
->prScanRequest
;
2023 prGlueInfo
->prScanRequest
= NULL
;
2025 GLUE_RELEASE_SPIN_LOCK(prGlueInfo
, SPIN_LOCK_NET_DEV
);
2028 cfg80211_scan_done(prScanRequest
, TRUE
);
2031 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
2032 netif_tx_stop_all_queues(prDev
);
2034 netif_stop_queue(prDev
);
2037 return 0; /* success */
2038 } /* end of wlanStop() */
2041 /*----------------------------------------------------------------------------*/
2043 * \brief Update Channel table for cfg80211 for Wi-Fi Direct based on current country code
2045 * \param[in] prGlueInfo Pointer to glue info
2049 /*----------------------------------------------------------------------------*/
2051 wlanUpdateChannelTable(
2052 P_GLUE_INFO_T prGlueInfo
2056 UINT_8 ucNumOfChannel
;
2057 RF_CHANNEL_INFO_T aucChannelList
[ARRAY_SIZE(mtk_2ghz_channels
) + ARRAY_SIZE(mtk_5ghz_channels
)];
2059 // 1. Disable all channel
2060 for(i
= 0; i
< ARRAY_SIZE(mtk_2ghz_channels
); i
++) {
2061 mtk_2ghz_channels
[i
].flags
|= IEEE80211_CHAN_DISABLED
;
2062 mtk_2ghz_channels
[i
].orig_flags
|= IEEE80211_CHAN_DISABLED
;
2065 for(i
= 0; i
< ARRAY_SIZE(mtk_5ghz_channels
); i
++) {
2066 mtk_5ghz_channels
[i
].flags
|= IEEE80211_CHAN_DISABLED
;
2067 mtk_5ghz_channels
[i
].orig_flags
|= IEEE80211_CHAN_DISABLED
;
2070 // 2. Get current domain channel list
2071 rlmDomainGetChnlList(prGlueInfo
->prAdapter
,
2073 ARRAY_SIZE(mtk_2ghz_channels
) + ARRAY_SIZE(mtk_5ghz_channels
),
2077 // 3. Enable specific channel based on domain channel list
2078 for(i
= 0; i
< ucNumOfChannel
; i
++) {
2079 switch(aucChannelList
[i
].eBand
) {
2081 for(j
= 0 ; j
< ARRAY_SIZE(mtk_2ghz_channels
) ; j
++) {
2082 if(mtk_2ghz_channels
[j
].hw_value
== aucChannelList
[i
].ucChannelNum
) {
2083 mtk_2ghz_channels
[j
].flags
&= ~IEEE80211_CHAN_DISABLED
;
2084 mtk_2ghz_channels
[j
].orig_flags
&= ~IEEE80211_CHAN_DISABLED
;
2091 for(j
= 0 ; j
< ARRAY_SIZE(mtk_5ghz_channels
) ; j
++) {
2092 if(mtk_5ghz_channels
[j
].hw_value
== aucChannelList
[i
].ucChannelNum
) {
2093 mtk_5ghz_channels
[j
].flags
&= ~IEEE80211_CHAN_DISABLED
;
2094 mtk_5ghz_channels
[j
].orig_flags
&= ~IEEE80211_CHAN_DISABLED
;
2109 /*----------------------------------------------------------------------------*/
2111 * \brief Register the device to the kernel and return the index.
2113 * \param[in] prDev Pointer to struct net_device.
2115 * \retval 0 The execution of wlanNetRegister succeeds.
2116 * \retval < 0 The execution of wlanNetRegister failed.
2118 /*----------------------------------------------------------------------------*/
2121 struct wireless_dev
*prWdev
2124 P_GLUE_INFO_T prGlueInfo
;
2125 INT_32 i4DevIdx
= -1;
2135 prGlueInfo
= (P_GLUE_INFO_T
) wiphy_priv(prWdev
->wiphy
);
2137 if ((i4DevIdx
= wlanGetDevIdx(prWdev
->netdev
)) < 0) {
2138 DBGLOG(INIT
, ERROR
, ("wlanNetRegister: net_device number exceeds.\n"));
2142 /* adjust channel support status */
2143 wlanUpdateChannelTable((P_GLUE_INFO_T
) wiphy_priv(prWdev
->wiphy
));
2145 if (wiphy_register(prWdev
->wiphy
) < 0) {
2146 DBGLOG(INIT
, ERROR
, ("wlanNetRegister: wiphy context is not registered.\n"));
2147 wlanClearDevIdx(prWdev
->netdev
);
2151 if(register_netdev(prWdev
->netdev
) < 0) {
2152 DBGLOG(INIT
, ERROR
, ("wlanNetRegister: net_device context is not registered.\n"));
2154 wiphy_unregister(prWdev
->wiphy
);
2155 wlanClearDevIdx(prWdev
->netdev
);
2159 if(i4DevIdx
!= -1) {
2160 prGlueInfo
->fgIsRegistered
= TRUE
;
2165 return i4DevIdx
; /* success */
2166 } /* end of wlanNetRegister() */
2169 /*----------------------------------------------------------------------------*/
2171 * \brief Unregister the device from the kernel
2173 * \param[in] prWdev Pointer to struct net_device.
2177 /*----------------------------------------------------------------------------*/
2180 struct wireless_dev
*prWdev
2183 P_GLUE_INFO_T prGlueInfo
;
2186 DBGLOG(INIT
, ERROR
, ("wlanNetUnregister: The device context is NULL\n"));
2190 prGlueInfo
= (P_GLUE_INFO_T
) wiphy_priv(prWdev
->wiphy
);
2192 wlanClearDevIdx(prWdev
->netdev
);
2193 unregister_netdev(prWdev
->netdev
);
2194 wiphy_unregister(prWdev
->wiphy
);
2196 prGlueInfo
->fgIsRegistered
= FALSE
;
2198 DBGLOG(INIT
, INFO
, ("unregister wireless_dev(0x%p)\n", prWdev
));
2201 } /* end of wlanNetUnregister() */
2204 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
2205 static const struct net_device_ops wlan_netdev_ops
= {
2206 .ndo_open
= wlanOpen
,
2207 .ndo_stop
= wlanStop
,
2208 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
2209 .ndo_set_rx_mode
= wlanSetMulticastList
,
2211 .ndo_set_multicast_list
= wlanSetMulticastList
,
2213 .ndo_get_stats
= wlanGetStats
,
2214 .ndo_do_ioctl
= wlanDoIOCTL
,
2215 .ndo_start_xmit
= wlanHardStartXmit
,
2216 .ndo_init
= wlanInit
,
2217 .ndo_uninit
= wlanUninit
,
2218 .ndo_select_queue
= wlanSelectQueue
,
2223 static const struct wiphy_wowlan_support wlan_wowlan_support
= {
2224 .flags
= WIPHY_WOWLAN_DISCONNECT
| WIPHY_WOWLAN_ANY
,
2227 /*----------------------------------------------------------------------------*/
2229 * \brief A method for creating Linux NET4 struct net_device object and the
2230 * private data(prGlueInfo and prAdapter). Setup the IO address to the HIF.
2231 * Assign the function pointer to the net_device object
2233 * \param[in] pvData Memory address for the device
2235 * \retval Not null The wireless_dev object.
2236 * \retval NULL Fail to create wireless_dev object
2238 /*----------------------------------------------------------------------------*/
2239 static struct lock_class_key rSpinKey
[SPIN_LOCK_NUM
];
2240 static struct wireless_dev
*
2245 struct wireless_dev
*prWdev
= NULL
;
2246 P_GLUE_INFO_T prGlueInfo
= NULL
;
2247 P_ADAPTER_T prAdapter
= NULL
;
2249 struct device
*prDev
;
2251 //4 <1.1> Create wireless_dev
2252 prWdev
= kzalloc(sizeof(struct wireless_dev
), GFP_KERNEL
);
2253 DBGLOG(INIT
, INFO
, ("wireless_dev prWdev(0x%p) allocated\n", prWdev
));
2255 DBGLOG(INIT
, ERROR
, ("Allocating memory to wireless_dev context failed\n"));
2259 //4 <1.2> Create wiphy
2260 prWdev
->wiphy
= wiphy_new(&mtk_wlan_ops
, sizeof(GLUE_INFO_T
));
2261 DBGLOG(INIT
, INFO
, ("wiphy (0x%p) allocated\n", prWdev
->wiphy
));
2262 if (!prWdev
->wiphy
) {
2263 DBGLOG(INIT
, ERROR
, ("Allocating memory to wiphy device failed\n"));
2268 //4 <1.3> co-relate wiphy & prDev
2269 #if MTK_WCN_HIF_SDIO
2270 mtk_wcn_hif_sdio_get_dev(*((MTK_WCN_HIF_SDIO_CLTCTX
*)pvData
), &prDev
);
2272 // prDev = &((struct sdio_func *) pvData)->dev; //samp
2273 prDev
= pvData
; //samp
2276 printk(KERN_ALERT DRV_NAME
"unable to get struct dev for wlan\n");
2278 set_wiphy_dev(prWdev
->wiphy
, prDev
);
2280 //4 <1.4> configure wireless_dev & wiphy
2281 prWdev
->iftype
= NL80211_IFTYPE_STATION
;
2282 prWdev
->wiphy
->max_scan_ssids
= 1; /* FIXME: for combo scan */
2283 prWdev
->wiphy
->max_scan_ie_len
= 512;
2284 prWdev
->wiphy
->interface_modes
= BIT(NL80211_IFTYPE_STATION
) | BIT(NL80211_IFTYPE_ADHOC
);
2285 prWdev
->wiphy
->bands
[IEEE80211_BAND_2GHZ
] = &mtk_band_2ghz
;
2286 //for the WPS probe request suband issue
2287 //prWdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mtk_band_5ghz;
2288 prWdev
->wiphy
->bands
[IEEE80211_BAND_5GHZ
] = NULL
;
2289 prWdev
->wiphy
->signal_type
= CFG80211_SIGNAL_TYPE_MBM
;
2290 prWdev
->wiphy
->cipher_suites
= (const u32
*)mtk_cipher_suites
;
2291 prWdev
->wiphy
->n_cipher_suites
= ARRAY_SIZE(mtk_cipher_suites
);
2292 prWdev
->wiphy
->flags
= WIPHY_FLAG_CUSTOM_REGULATORY
| WIPHY_FLAG_SUPPORTS_FW_ROAM
| WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
;
2293 #if (CFG_SUPPORT_TDLS == 1)
2294 TDLSEX_WIPHY_FLAGS_INIT(prWdev
->wiphy
->flags
);
2295 #endif /* CFG_SUPPORT_TDLS */
2296 prWdev
->wiphy
->max_remain_on_channel_duration
= 5000;
2297 prWdev
->wiphy
->mgmt_stypes
= mtk_cfg80211_ais_default_mgmt_stypes
;
2299 kalMemCopy(&prWdev
->wiphy
->wowlan
, &wlan_wowlan_support
,
2300 sizeof(struct wiphy_wowlan_support
));
2302 //4 <2> Create Glue structure
2303 prGlueInfo
= (P_GLUE_INFO_T
) wiphy_priv(prWdev
->wiphy
);
2305 DBGLOG(INIT
, ERROR
, ("Allocating memory to glue layer failed\n"));
2309 //4 <3> Initial Glue structure
2310 //4 <3.1> Create net device
2312 if (wlan_if_changed
) {
2313 prGlueInfo
->prDevHandler
= alloc_netdev_mq(sizeof(P_GLUE_INFO_T
), NIC_INF_NAME_IN_AP_MODE
, ether_setup
, CFG_MAX_TXQ_NUM
);
2315 prGlueInfo
->prDevHandler
= alloc_netdev_mq(sizeof(P_GLUE_INFO_T
), NIC_INF_NAME
, ether_setup
, CFG_MAX_TXQ_NUM
);
2318 prGlueInfo
->prDevHandler
= alloc_netdev_mq(sizeof(P_GLUE_INFO_T
), NIC_INF_NAME
, ether_setup
, CFG_MAX_TXQ_NUM
);
2321 DBGLOG(INIT
, INFO
, ("net_device prDev(0x%p) allocated\n", prGlueInfo
->prDevHandler
));
2322 if (!prGlueInfo
->prDevHandler
) {
2323 DBGLOG(INIT
, ERROR
, ("Allocating memory to net_device context failed\n"));
2327 //4 <3.1.1> initialize net device varaiables
2328 *((P_GLUE_INFO_T
*) netdev_priv(prGlueInfo
->prDevHandler
)) = prGlueInfo
;
2330 prGlueInfo
->prDevHandler
->netdev_ops
= &wlan_netdev_ops
;
2331 #ifdef CONFIG_WIRELESS_EXT
2332 prGlueInfo
->prDevHandler
->wireless_handlers
= &wext_handler_def
;
2334 netif_carrier_off(prGlueInfo
->prDevHandler
);
2335 netif_tx_stop_all_queues(prGlueInfo
->prDevHandler
);
2337 //4 <3.1.2> co-relate with wiphy bi-directionally
2338 prGlueInfo
->prDevHandler
->ieee80211_ptr
= prWdev
;
2339 #if CFG_TCP_IP_CHKSUM_OFFLOAD
2340 prGlueInfo
->prDevHandler
->features
= NETIF_F_HW_CSUM
;
2342 prWdev
->netdev
= prGlueInfo
->prDevHandler
;
2344 //4 <3.1.3> co-relate net device & prDev
2345 SET_NETDEV_DEV(prGlueInfo
->prDevHandler
, wiphy_dev(prWdev
->wiphy
));
2347 //4 <3.2> initiali glue variables
2348 prGlueInfo
->eParamMediaStateIndicated
= PARAM_MEDIA_STATE_DISCONNECTED
;
2349 prGlueInfo
->ePowerState
= ParamDeviceStateD0
;
2350 prGlueInfo
->fgIsMacAddrOverride
= FALSE
;
2351 prGlueInfo
->fgIsRegistered
= FALSE
;
2352 prGlueInfo
->prScanRequest
= NULL
;
2354 #if CFG_SUPPORT_HOTSPOT_2_0
2356 prGlueInfo
->fgIsDad
= FALSE
;
2357 prGlueInfo
->fgIs6Dad
= FALSE
;
2358 kalMemZero(prGlueInfo
->aucDADipv4
,4);
2359 kalMemZero(prGlueInfo
->aucDADipv6
,16);
2362 init_completion(&prGlueInfo
->rScanComp
);
2363 init_completion(&prGlueInfo
->rHaltComp
);
2364 init_completion(&prGlueInfo
->rPendComp
);
2365 #if CFG_ENABLE_WIFI_DIRECT
2366 init_completion(&prGlueInfo
->rSubModComp
);
2369 /* initialize timer for OID timeout checker */
2370 kalOsTimerInitialize(prGlueInfo
, kalTimeoutHandler
);
2372 for (i
= 0; i
< SPIN_LOCK_NUM
; i
++) {
2373 spin_lock_init(&prGlueInfo
->rSpinLock
[i
]);
2374 lockdep_set_class(&prGlueInfo
->rSpinLock
[i
], &rSpinKey
[i
]);
2377 /* initialize semaphore for ioctl */
2378 sema_init(&prGlueInfo
->ioctl_sem
, 1);
2380 /* initialize semaphore for ioctl */
2381 sema_init(&g_halt_sem
, 1);
2384 //4 <4> Create Adapter structure
2385 prAdapter
= (P_ADAPTER_T
) wlanAdapterCreate(prGlueInfo
);
2388 DBGLOG(INIT
, ERROR
, ("Allocating memory to adapter failed\n"));
2392 prGlueInfo
->prAdapter
= prAdapter
;
2394 #ifdef CONFIG_CFG80211_WEXT
2395 //4 <5> Use wireless extension to replace IOCTL
2396 prWdev
->wiphy
->wext
= &wext_handler_def
;
2399 goto netcreate_done
;
2402 if (NULL
!= prAdapter
) {
2403 wlanAdapterDestroy(prAdapter
);
2407 if (NULL
!= prGlueInfo
->prDevHandler
) {
2408 free_netdev(prGlueInfo
->prDevHandler
);
2409 prGlueInfo
->prDevHandler
= NULL
;
2412 if (NULL
!= prWdev
->wiphy
) {
2413 wiphy_free(prWdev
->wiphy
);
2414 prWdev
->wiphy
= NULL
;
2417 if (NULL
!= prWdev
) {
2418 /* Free net_device and private data, which are allocated by
2428 } /* end of wlanNetCreate() */
2431 /*----------------------------------------------------------------------------*/
2433 * \brief Destroying the struct net_device object and the private data.
2435 * \param[in] prWdev Pointer to struct wireless_dev.
2439 /*----------------------------------------------------------------------------*/
2442 struct wireless_dev
*prWdev
2445 P_GLUE_INFO_T prGlueInfo
= NULL
;
2450 DBGLOG(INIT
, ERROR
, ("wlanNetDestroy: The device context is NULL\n"));
2454 /* prGlueInfo is allocated with net_device */
2455 prGlueInfo
= (P_GLUE_INFO_T
) wiphy_priv(prWdev
->wiphy
);
2458 /* destroy kal OS timer */
2459 kalCancelTimer(prGlueInfo
);
2461 glClearHifInfo(prGlueInfo
);
2463 wlanAdapterDestroy(prGlueInfo
->prAdapter
);
2464 prGlueInfo
->prAdapter
= NULL
;
2466 /* Free net_device and private data prGlueInfo, which are allocated by alloc_netdev().
2468 free_netdev(prWdev
->netdev
);
2469 wiphy_free(prWdev
->wiphy
);
2474 } /* end of wlanNetDestroy() */
2477 UINT_8 g_aucBufIpAddr
[32] = {0};
2479 void wlanHandleSystemSuspend(void)
2481 struct net_device
*prDev
= NULL
;
2482 P_GLUE_INFO_T prGlueInfo
= NULL
;
2483 UINT_8 ip
[4] = { 0 };
2484 UINT_32 u4NumIPv4
= 0;
2486 UINT_8 ip6
[16] = { 0 }; // FIX ME: avoid to allocate large memory in stack
2487 UINT_32 u4NumIPv6
= 0;
2490 P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr
;
2492 DBGLOG(INIT
, INFO
, ("*********wlan System Suspend************\n"));
2494 // <1> Sanity check and acquire the net_device
2495 ASSERT(u4WlanDevNum
<= CFG_MAX_WLAN_DEVICES
);
2496 if(u4WlanDevNum
== 0){
2497 DBGLOG(INIT
, ERROR
, ("wlanEarlySuspend u4WlanDevNum==0 invalid!!\n"));
2500 prDev
= arWlanDevInfo
[u4WlanDevNum
-1].prDev
;
2503 fgIsUnderSuspend
= true;
2505 // <2> get the IPv4 address
2506 if(!prDev
|| !(prDev
->ip_ptr
)||\
2507 !((struct in_device
*)(prDev
->ip_ptr
))->ifa_list
||\
2508 !(&(((struct in_device
*)(prDev
->ip_ptr
))->ifa_list
->ifa_local
))){
2509 DBGLOG(INIT
, INFO
, ("ip is not avaliable.\n"));
2513 // <3> acquire the prGlueInfo
2514 prGlueInfo
= *((P_GLUE_INFO_T
*) netdev_priv(prDev
));
2517 // <4> copy the IPv4 address
2518 kalMemCopy(ip
, &(((struct in_device
*)(prDev
->ip_ptr
))->ifa_list
->ifa_local
), sizeof(ip
));
2519 DBGLOG(INIT
, INFO
, ("ip is %d.%d.%d.%d\n",
2520 ip
[0],ip
[1],ip
[2],ip
[3]));
2522 // todo: traverse between list to find whole sets of IPv4 addresses
2523 if (!((ip
[0] == 0) &&
2531 // <5> get the IPv6 address
2532 if(!prDev
|| !(prDev
->ip6_ptr
)||\
2533 !((struct in_device
*)(prDev
->ip6_ptr
))->ifa_list
||\
2534 !(&(((struct in_device
*)(prDev
->ip6_ptr
))->ifa_list
->ifa_local
))){
2535 DBGLOG(INIT
, INFO
, ("ipv6 is not avaliable.\n"));
2538 // <6> copy the IPv6 address
2539 kalMemCopy(ip6
, &(((struct in_device
*)(prDev
->ip6_ptr
))->ifa_list
->ifa_local
), sizeof(ip6
));
2540 DBGLOG(INIT
, INFO
, ("ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n",
2541 ip6
[0],ip6
[1],ip6
[2],ip6
[3],
2542 ip6
[4],ip6
[5],ip6
[6],ip6
[7],
2543 ip6
[8],ip6
[9],ip6
[10],ip6
[11],
2544 ip6
[12],ip6
[13],ip6
[14],ip6
[15]
2547 // todo: traverse between list to find whole sets of IPv6 addresses
2548 if (!((ip6
[0] == 0) &&
2559 // <7> set up the ARP filter
2561 WLAN_STATUS rStatus
= WLAN_STATUS_FAILURE
;
2562 UINT_32 u4SetInfoLen
= 0;
2563 // UINT_8 aucBuf[32] = {0};
2564 UINT_32 u4Len
= OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST
, arAddress
);
2565 P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList
= (P_PARAM_NETWORK_ADDRESS_LIST
)g_aucBufIpAddr
;//aucBuf;
2566 P_PARAM_NETWORK_ADDRESS prParamNetAddr
= prParamNetAddrList
->arAddress
;
2568 kalMemZero(g_aucBufIpAddr
, sizeof(g_aucBufIpAddr
));
2570 prParamNetAddrList
->u4AddressCount
= u4NumIPv4
+ u4NumIPv6
;
2571 prParamNetAddrList
->u2AddressType
= PARAM_PROTOCOL_ID_TCP_IP
;
2572 for (i
= 0; i
< u4NumIPv4
; i
++) {
2573 prParamNetAddr
->u2AddressLength
= sizeof(PARAM_NETWORK_ADDRESS_IP
);//4;;
2574 prParamNetAddr
->u2AddressType
= PARAM_PROTOCOL_ID_TCP_IP
;;
2576 kalMemCopy(prParamNetAddr
->aucAddress
, ip
, sizeof(ip
));
2577 prParamNetAddr
= (P_PARAM_NETWORK_ADDRESS
)((UINT_32
)prParamNetAddr
+ sizeof(ip
));
2578 u4Len
+= OFFSET_OF(PARAM_NETWORK_ADDRESS
, aucAddress
) + sizeof(ip
);
2580 prParamIpAddr
= (P_PARAM_NETWORK_ADDRESS_IP
)prParamNetAddr
->aucAddress
;
2581 kalMemCopy(&prParamIpAddr
->in_addr
, ip
, sizeof(ip
));
2582 prParamNetAddr
= (P_PARAM_NETWORK_ADDRESS
)((ULONG
)prParamNetAddr
+ sizeof(PARAM_NETWORK_ADDRESS
));
2583 u4Len
+= OFFSET_OF(PARAM_NETWORK_ADDRESS
, aucAddress
) + sizeof(PARAM_NETWORK_ADDRESS
);
2587 for (i
= 0; i
< u4NumIPv6
; i
++) {
2588 prParamNetAddr
->u2AddressLength
= 6;;
2589 prParamNetAddr
->u2AddressType
= PARAM_PROTOCOL_ID_TCP_IP
;;
2590 kalMemCopy(prParamNetAddr
->aucAddress
, ip6
, sizeof(ip6
));
2591 prParamNetAddr
= (P_PARAM_NETWORK_ADDRESS
)((ULONG
)prParamNetAddr
+ sizeof(ip6
));
2592 u4Len
+= OFFSET_OF(PARAM_NETWORK_ADDRESS
, aucAddress
) + sizeof(ip6
);
2595 ASSERT(u4Len
<= sizeof(g_aucBufIpAddr
/*aucBuf*/));
2597 rStatus
= kalIoctl(prGlueInfo
,
2598 wlanoidSetNetworkAddress
,
2599 (PVOID
)prParamNetAddrList
,
2607 if (rStatus
!= WLAN_STATUS_SUCCESS
) {
2608 DBGLOG(INIT
, INFO
, ("set HW pattern filter fail 0x%x\n", rStatus
));
2613 void wlanHandleSystemResume(void)
2615 struct net_device
*prDev
= NULL
;
2616 P_GLUE_INFO_T prGlueInfo
= NULL
;
2617 WLAN_STATUS rStatus
= WLAN_STATUS_FAILURE
;
2618 UINT_8 ip
[4] = { 0 };
2620 UINT_8 ip6
[16] = { 0 }; // FIX ME: avoid to allocate large memory in stack
2622 EVENT_AIS_BSS_INFO_T rParam
;
2623 UINT_32 u4BufLen
= 0;
2625 DBGLOG(INIT
, INFO
, ("*********wlan System Resume************\n"));
2627 // <1> Sanity check and acquire the net_device
2628 ASSERT(u4WlanDevNum
<= CFG_MAX_WLAN_DEVICES
);
2629 if(u4WlanDevNum
== 0){
2630 DBGLOG(INIT
, ERROR
, ("wlanLateResume u4WlanDevNum==0 invalid!!\n"));
2633 prDev
= arWlanDevInfo
[u4WlanDevNum
-1].prDev
;
2636 fgIsUnderSuspend
= false;
2639 DBGLOG(INIT
, INFO
, ("prDev == NULL!!! \n"));
2643 // <3> acquire the prGlueInfo
2644 prGlueInfo
= *((P_GLUE_INFO_T
*) netdev_priv(prDev
));
2649 We will receive the event in rx, we will check if the status is the same in driver
2650 and FW, if not the same, trigger disconnetion procedure.
2653 kalMemZero(&rParam
, sizeof(EVENT_AIS_BSS_INFO_T
));
2655 rStatus
= kalIoctl(prGlueInfo
,
2656 wlanoidQueryBSSInfo
,
2658 sizeof(EVENT_AIS_BSS_INFO_T
),
2664 if (rStatus
!= WLAN_STATUS_SUCCESS
) {
2665 DBGLOG(INIT
, ERROR
, ("Query BSSinfo fail 0x%x!!\n", rStatus
));
2667 DBGLOG(INIT
, INFO
, ("Status[%d], Mode[%d], Active[%d]\\n", rParam
.eConnectionState
, rParam
.eCurrentOPMode
, rParam
.fgIsNetActive
));
2671 // <2> get the IPv4 address
2672 if(!(prDev
->ip_ptr
)||\
2673 !((struct in_device
*)(prDev
->ip_ptr
))->ifa_list
||\
2674 !(&(((struct in_device
*)(prDev
->ip_ptr
))->ifa_list
->ifa_local
))){
2675 DBGLOG(INIT
, INFO
, ("ip is not avaliable.\n"));
2679 // <4> copy the IPv4 address
2680 kalMemCopy(ip
, &(((struct in_device
*)(prDev
->ip_ptr
))->ifa_list
->ifa_local
), sizeof(ip
));
2681 DBGLOG(INIT
, INFO
, ("ip is %d.%d.%d.%d\n",
2682 ip
[0],ip
[1],ip
[2],ip
[3]));
2685 // <5> get the IPv6 address
2686 if(!prDev
|| !(prDev
->ip6_ptr
)||\
2687 !((struct in_device
*)(prDev
->ip6_ptr
))->ifa_list
||\
2688 !(&(((struct in_device
*)(prDev
->ip6_ptr
))->ifa_list
->ifa_local
))){
2689 DBGLOG(INIT
, INFO
, ("ipv6 is not avaliable.\n"));
2692 // <6> copy the IPv6 address
2693 kalMemCopy(ip6
, &(((struct in_device
*)(prDev
->ip6_ptr
))->ifa_list
->ifa_local
), sizeof(ip6
));
2694 DBGLOG(INIT
, INFO
, ("ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n",
2695 ip6
[0],ip6
[1],ip6
[2],ip6
[3],
2696 ip6
[4],ip6
[5],ip6
[6],ip6
[7],
2697 ip6
[8],ip6
[9],ip6
[10],ip6
[11],
2698 ip6
[12],ip6
[13],ip6
[14],ip6
[15]
2701 // <7> clear the ARP filter
2703 WLAN_STATUS rStatus
= WLAN_STATUS_FAILURE
;
2704 UINT_32 u4SetInfoLen
= 0;
2705 // UINT_8 aucBuf[32] = {0};
2706 UINT_32 u4Len
= sizeof(PARAM_NETWORK_ADDRESS_LIST
);
2707 P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList
= (P_PARAM_NETWORK_ADDRESS_LIST
)g_aucBufIpAddr
;//aucBuf;
2709 kalMemZero(g_aucBufIpAddr
, sizeof(g_aucBufIpAddr
));
2711 prParamNetAddrList
->u4AddressCount
= 0;
2712 prParamNetAddrList
->u2AddressType
= PARAM_PROTOCOL_ID_TCP_IP
;
2714 ASSERT(u4Len
<= sizeof(g_aucBufIpAddr
/*aucBuf*/));
2715 rStatus
= kalIoctl(prGlueInfo
,
2716 wlanoidSetNetworkAddress
,
2717 (PVOID
)prParamNetAddrList
,
2725 if (rStatus
!= WLAN_STATUS_SUCCESS
) {
2726 DBGLOG(INIT
, INFO
, ("set HW pattern filter fail 0x%x\n", rStatus
));
2730 #endif //! CONFIG_X86
2732 extern void wlanRegisterNotifier(void);
2733 extern void wlanUnregisterNotifier(void);
2736 typedef int (*set_p2p_mode
)(struct net_device
*netdev
, PARAM_CUSTOM_P2P_SET_STRUC_T p2pmode
);
2737 typedef void (*set_dbg_level
)(unsigned char modules
[DBG_MODULE_NUM
]);
2739 extern void register_set_p2p_mode_handler(set_p2p_mode handler
);
2740 extern void register_set_dbg_level_handler(set_dbg_level handler
);
2743 set_p2p_mode_handler(
2744 struct net_device
*netdev
,
2745 PARAM_CUSTOM_P2P_SET_STRUC_T p2pmode
2749 P_GLUE_INFO_T prGlueInfo
= *((P_GLUE_INFO_T
*)netdev_priv(netdev
));
2750 PARAM_CUSTOM_P2P_SET_STRUC_T rSetP2P
;
2751 WLAN_STATUS rWlanStatus
= WLAN_STATUS_SUCCESS
;
2752 UINT_32 u4BufLen
= 0;
2754 rSetP2P
.u4Enable
= p2pmode
.u4Enable
;
2755 rSetP2P
.u4Mode
= p2pmode
.u4Mode
;
2757 if(!rSetP2P
.u4Enable
) {
2758 p2pNetUnregister(prGlueInfo
, TRUE
);
2761 rWlanStatus
= kalIoctl(prGlueInfo
,
2764 sizeof(PARAM_CUSTOM_P2P_SET_STRUC_T
),
2770 printk("set_p2p_mode_handler ret = %d\n", rWlanStatus
);
2771 if(rSetP2P
.u4Enable
) {
2772 p2pNetRegister(prGlueInfo
, TRUE
);
2779 P_GLUE_INFO_T prGlueInfo
= *((P_GLUE_INFO_T
*)netdev_priv(netdev
));
2780 extern BOOLEAN fgIsResetting
;
2781 extern int g_u4HaltFlag
;
2782 extern spinlock_t g_p2p_lock
;
2783 extern int g_u4P2PEnding
;
2784 extern int g_u4P2POnOffing
;
2785 PARAM_CUSTOM_P2P_SET_STRUC_T rSetP2P
;
2786 WLAN_STATUS rWlanStatus
= WLAN_STATUS_SUCCESS
;
2787 BOOLEAN fgIsP2PEnding
;
2788 UINT_32 u4BufLen
= 0;
2789 GLUE_SPIN_LOCK_DECLARATION();
2791 DBGLOG(INIT
, INFO
, ("%u %u\n", (UINT_32
)p2pmode
.u4Enable
, (UINT_32
)p2pmode
.u4Mode
));
2793 /* avoid remove & p2p off command simultaneously */
2794 GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock
);
2795 fgIsP2PEnding
= g_u4P2PEnding
;
2796 g_u4P2POnOffing
= 1;
2797 GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock
);
2799 if (fgIsP2PEnding
== 1) {
2800 /* skip the command if we are removing */
2801 GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock
);
2802 g_u4P2POnOffing
= 0;
2803 GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock
);
2807 rSetP2P
.u4Enable
= p2pmode
.u4Enable
;
2808 rSetP2P
.u4Mode
= p2pmode
.u4Mode
;
2810 if ((!rSetP2P
.u4Enable
) && (fgIsResetting
== FALSE
)) {
2811 p2pNetUnregister(prGlueInfo
, TRUE
);
2814 /* move out to caller to avoid kalIoctrl & suspend/resume deadlock problem ALPS00844864 */
2817 1. System enters suspend/resume but not yet enter wlanearlysuspend()
2818 or wlanlateresume();
2820 2. System switches to do PRIV_CMD_P2P_MODE and execute kalIoctl()
2821 and get g_halt_sem then do glRegisterEarlySuspend() or
2822 glUnregisterEarlySuspend();
2824 But system suspend/resume procedure is not yet finished so we
2827 3. System switches back to do suspend/resume procedure and execute
2828 kalIoctl(). But driver does not yet release g_halt_sem so system
2829 suspend in wlanearlysuspend() or wlanlateresume();
2831 ==> deadlock occurs.
2834 rWlanStatus
= kalIoctl(prGlueInfo
,
2836 (PVOID
)&rSetP2P
, /* pu4IntBuf[0] is used as input SubCmd */
2837 sizeof(PARAM_CUSTOM_P2P_SET_STRUC_T
),
2843 /* Need to check fgIsP2PRegistered, in case of whole chip reset.
2844 * in this case, kalIOCTL return success always,
2845 * and prGlueInfo->prP2pInfo may be NULL */
2846 if ((rSetP2P
.u4Enable
) && (prGlueInfo
->prAdapter
->fgIsP2PRegistered
) &&
2847 (fgIsResetting
== FALSE
)) {
2848 p2pNetRegister(prGlueInfo
, TRUE
);
2851 GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock
);
2852 g_u4P2POnOffing
= 0;
2853 GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock
);
2859 set_dbg_level_handler(
2860 unsigned char dbg_lvl
[DBG_MODULE_NUM
]
2863 kalMemCopy(aucDebugModule
, dbg_lvl
, sizeof(aucDebugModule
));
2864 kalPrint("[wlan] change debug level");
2867 /*----------------------------------------------------------------------------*/
2869 * \brief Wlan probe function. This function probes and initializes the device.
2871 * \param[in] pvData data passed by bus driver init function
2873 * _HIF_SDIO: sdio bus driver handle
2876 * \retval negative value Failed
2878 /*----------------------------------------------------------------------------*/
2884 struct wireless_dev
*prWdev
= NULL
;
2885 P_WLANDEV_INFO_T prWlandevInfo
= NULL
;
2886 INT_32 i4DevIdx
= 0;
2887 P_GLUE_INFO_T prGlueInfo
= NULL
;
2888 P_ADAPTER_T prAdapter
= NULL
;
2889 INT_32 i4Status
= 0;
2890 BOOLEAN bRet
= FALSE
;
2891 enum probe_fail_reason
{
2901 eFailReason
= FAIL_REASON_NUM
;
2903 //4 <1> Initialize the IO port of the interface
2904 /* GeorgeKuo: pData has different meaning for _HIF_XXX:
2905 * _HIF_EHPI: pointer to memory base variable, which will be
2906 * initialized by glBusInit().
2907 * _HIF_SDIO: bus driver handle
2910 bRet
= glBusInit(pvData
);
2912 /* Cannot get IO address from interface */
2913 if (FALSE
== bRet
) {
2914 DBGLOG(INIT
, ERROR
, (KERN_ALERT
"wlanProbe: glBusInit() fail\n"));
2916 eFailReason
= BUS_INIT_FAIL
;
2920 //4 <2> Create network device, Adapter, KalInfo, prDevHandler(netdev)
2921 if ((prWdev
= wlanNetCreate(pvData
)) == NULL
) {
2922 DBGLOG(INIT
, ERROR
, ("wlanProbe: No memory for dev and its private\n"));
2924 eFailReason
= NET_CREATE_FAIL
;
2928 //4 <2.5> Set the ioaddr to HIF Info
2929 prGlueInfo
= (P_GLUE_INFO_T
) wiphy_priv(prWdev
->wiphy
);
2930 gPrDev
= prGlueInfo
->prDevHandler
;
2931 glSetHifInfo(prGlueInfo
, (ULONG
) pvData
);
2933 KAL_WAKE_LOCK_INIT(prAdapter
, &prGlueInfo
->rAhbIsrWakeLock
, "WLAN AHB ISR");
2935 /* main thread is created in this function */
2936 init_waitqueue_head(&prGlueInfo
->waitq
);
2939 QUEUE_INITIALIZE(&prGlueInfo
->rCmdQueue
);
2940 QUEUE_INITIALIZE(&prGlueInfo
->rTxQueue
);
2943 //prGlueInfo->main_thread = kthread_run(tx_thread, prGlueInfo->prDevHandler, "tx_thread");
2946 prWlandevInfo
= &arWlanDevInfo
[i4DevIdx
];
2948 i4Status
= glBusSetIrq(prWdev
->netdev
, NULL
, *((P_GLUE_INFO_T
*) netdev_priv(prWdev
->netdev
)));
2950 if (i4Status
!= WLAN_STATUS_SUCCESS
) {
2951 DBGLOG(INIT
, ERROR
, ("wlanProbe: Set IRQ error\n"));
2952 eFailReason
= BUS_SET_IRQ_FAIL
;
2956 prGlueInfo
->i4DevIdx
= i4DevIdx
;
2958 prAdapter
= prGlueInfo
->prAdapter
;
2960 prGlueInfo
->u4ReadyFlag
= 0;
2962 #if CFG_TCP_IP_CHKSUM_OFFLOAD
2963 prAdapter
->u4CSUMFlags
= (CSUM_OFFLOAD_EN_TX_TCP
| CSUM_OFFLOAD_EN_TX_UDP
| CSUM_OFFLOAD_EN_TX_IP
);
2965 #if CFG_SUPPORT_CFG_FILE
2967 PUINT_8 pucConfigBuf
;
2968 UINT_32 u4ConfigReadLen
;
2969 wlanCfgInit(prAdapter
,NULL
,0,0);
2970 pucConfigBuf
= (PUINT_8
) kalMemAlloc(WLAN_CFG_FILE_BUF_SIZE
, VIR_MEM_TYPE
);
2971 kalMemZero(pucConfigBuf
, WLAN_CFG_FILE_BUF_SIZE
);
2972 u4ConfigReadLen
= 0;
2973 printk("CFG_FILE: Read File...\n");
2975 if(kalReadToFile("/data/misc/wifi.cfg",
2976 pucConfigBuf
, WLAN_CFG_FILE_BUF_SIZE
, &u4ConfigReadLen
) == 0){
2977 printk(KERN_ERR
"CFG_FILE: Read /data/misc/wifi.cfg \n");
2980 else if(kalReadToFile("/data/misc/wifi/wifi.cfg",
2981 pucConfigBuf
, WLAN_CFG_FILE_BUF_SIZE
, &u4ConfigReadLen
) == 0){
2982 printk(KERN_ERR
"CFG_FILE: Read /data/misc/wifi/wifi.cfg \n");
2984 else if(kalReadToFile("/etc/firmware/wifi.cfg",
2985 pucConfigBuf
, WLAN_CFG_FILE_BUF_SIZE
, &u4ConfigReadLen
) == 0){
2986 printk(KERN_ERR
"CFG_FILE: Read /etc/firmware/wifi.cfg \n");
2989 if(pucConfigBuf
[0] != '\0' && u4ConfigReadLen
>0) {
2990 wlanCfgInit(prAdapter
,pucConfigBuf
,u4ConfigReadLen
,0);
2992 kalMemFree(pucConfigBuf
, VIR_MEM_TYPE
, WLAN_CFG_FILE_BUF_SIZE
);
2993 } /* pucConfigBuf */
2996 //4 <5> Start Device
2998 #if CFG_ENABLE_FW_DOWNLOAD
2999 DBGLOG(INIT
, TRACE
, ("start to download firmware...\n"));
3001 /* before start adapter, we need to open and load firmware */
3003 UINT_32 u4FwSize
= 0;
3004 PVOID prFwBuffer
= NULL
;
3005 P_REG_INFO_T prRegInfo
= &prGlueInfo
->rRegInfo
;
3007 //P_REG_INFO_T prRegInfo = (P_REG_INFO_T) kmalloc(sizeof(REG_INFO_T), GFP_KERNEL);
3008 kalMemSet(prRegInfo
, 0, sizeof(REG_INFO_T
));
3009 prRegInfo
->u4StartAddress
= CFG_FW_START_ADDRESS
;
3010 prRegInfo
->u4LoadAddress
= CFG_FW_LOAD_ADDRESS
;
3012 // Load NVRAM content to REG_INFO_T
3013 glLoadNvram(prGlueInfo
, prRegInfo
);
3014 #if CFG_SUPPORT_CFG_FILE
3015 wlanCfgApply(prAdapter
);
3018 //kalMemCopy(&prGlueInfo->rRegInfo, prRegInfo, sizeof(REG_INFO_T));
3020 prRegInfo
->u4PowerMode
= CFG_INIT_POWER_SAVE_PROF
;
3021 prRegInfo
->fgEnArpFilter
= TRUE
;
3023 if (kalFirmwareImageMapping(prGlueInfo
, &prFwBuffer
, &u4FwSize
) == NULL
) {
3025 DBGLOG(INIT
, TRACE
, ("kalFirmwareImageMapping fail!\n"));
3029 if (wlanAdapterStart(prAdapter
, prRegInfo
, prFwBuffer
, u4FwSize
) != WLAN_STATUS_SUCCESS
) {
3034 kalFirmwareImageUnmapping(prGlueInfo
, NULL
, prFwBuffer
);
3039 DBGLOG(INIT
, TRACE
, ("download firmware status = %d\n", i4Status
));
3042 /* dump HIF/DMA registers */
3043 HifRegDump(prGlueInfo
->prAdapter
);
3044 if (prGlueInfo
->rHifInfo
.DmaOps
->DmaRegDump
!= NULL
)
3045 prGlueInfo
->rHifInfo
.DmaOps
->DmaRegDump(&prGlueInfo
->rHifInfo
);
3046 eFailReason
= ADAPTER_START_FAIL
;
3051 //P_REG_INFO_T prRegInfo = (P_REG_INFO_T) kmalloc(sizeof(REG_INFO_T), GFP_KERNEL);
3052 kalMemSet(&prGlueInfo
->rRegInfo
, 0, sizeof(REG_INFO_T
));
3053 P_REG_INFO_T prRegInfo
= &prGlueInfo
->rRegInfo
;
3055 // Load NVRAM content to REG_INFO_T
3056 glLoadNvram(prGlueInfo
, prRegInfo
);
3058 prRegInfo
->u4PowerMode
= CFG_INIT_POWER_SAVE_PROF
;
3060 if (wlanAdapterStart(prAdapter
, prRegInfo
, NULL
, 0) != WLAN_STATUS_SUCCESS
) {
3062 eFailReason
= ADAPTER_START_FAIL
;
3066 if (TRUE
== prAdapter
->fgEnable5GBand
)
3067 prWdev
->wiphy
->bands
[IEEE80211_BAND_5GHZ
] = &mtk_band_5ghz
;
3069 prGlueInfo
->main_thread
= kthread_run(tx_thread
, prGlueInfo
->prDevHandler
, "tx_thread");
3071 #if CFG_SUPPORT_ROAMING_ENC
3072 /* adjust roaming threshold */
3074 WLAN_STATUS rStatus
= WLAN_STATUS_FAILURE
;
3075 CMD_ROAMING_INFO_T rRoamingInfo
;
3076 UINT_32 u4SetInfoLen
= 0;
3078 prAdapter
->fgIsRoamingEncEnabled
= TRUE
;
3080 /* suggestion from Tsaiyuan.Hsu */
3081 kalMemZero(&rRoamingInfo
, sizeof(CMD_ROAMING_INFO_T
));
3082 rRoamingInfo
.fgIsFastRoamingApplied
= TRUE
;
3084 DBGLOG(INIT
, INFO
, ("Enable roaming enhance function\n"));
3086 rStatus
= kalIoctl(prGlueInfo
,
3087 wlanoidSetRoamingInfo
,
3089 sizeof(rRoamingInfo
),
3096 if (rStatus
!= WLAN_STATUS_SUCCESS
)
3097 DBGLOG(INIT
, WARN
, ("set roaming advance info fail 0x%x\n", rStatus
));
3099 #endif /* CFG_SUPPORT_ROAMING_ENC */
3101 /* set MAC address */
3103 WLAN_STATUS rStatus
= WLAN_STATUS_FAILURE
;
3104 struct sockaddr MacAddr
;
3105 UINT_32 u4SetInfoLen
= 0;
3107 rStatus
= kalIoctl(prGlueInfo
,
3108 wlanoidQueryCurrentAddr
,
3117 if (rStatus
!= WLAN_STATUS_SUCCESS
) {
3118 DBGLOG(INIT
, WARN
, ("set MAC addr fail 0x%x\n", rStatus
));
3119 prGlueInfo
->u4ReadyFlag
= 0;
3121 memcpy(prGlueInfo
->prDevHandler
->dev_addr
, &MacAddr
.sa_data
, ETH_ALEN
);
3122 memcpy(prGlueInfo
->prDevHandler
->perm_addr
, prGlueInfo
->prDevHandler
->dev_addr
, ETH_ALEN
);
3125 prGlueInfo
->u4ReadyFlag
= 1;
3126 #if CFG_SHOW_MACADDR_SOURCE
3127 DBGLOG(INIT
, INFO
, ("MAC address: "MACSTR
, MAC2STR(&MacAddr
.sa_data
)));
3133 #if CFG_TCP_IP_CHKSUM_OFFLOAD
3134 /* set HW checksum offload */
3136 WLAN_STATUS rStatus
= WLAN_STATUS_FAILURE
;
3137 UINT_32 u4CSUMFlags
= CSUM_OFFLOAD_EN_ALL
;
3138 UINT_32 u4SetInfoLen
= 0;
3140 rStatus
= kalIoctl(prGlueInfo
,
3141 wlanoidSetCSUMOffload
,
3142 (PVOID
)&u4CSUMFlags
,
3150 if (rStatus
!= WLAN_STATUS_SUCCESS
) {
3151 DBGLOG(INIT
, WARN
, ("set HW checksum offload fail 0x%x\n", rStatus
));
3156 //4 <3> Register the card
3157 DBGLOG(INIT
, TRACE
, ("wlanNetRegister...\n"));
3158 if ((i4DevIdx
= wlanNetRegister(prWdev
)) < 0){
3160 DBGLOG(INIT
, ERROR
, ("wlanProbe: Cannot register the net_device context to the kernel\n"));
3161 eFailReason
= NET_REGISTER_FAIL
;
3165 wlanRegisterNotifier();
3166 //4 <6> Initialize /proc filesystem
3167 #ifdef WLAN_INCLUDE_PROC
3168 DBGLOG(INIT
, TRACE
, ("init procfs...\n"));
3169 if ( (i4Status
= procInitProcfs(prDev
, NIC_DEVICE_ID_LOW
)) < 0) {
3170 DBGLOG(INIT
, ERROR
, ("wlanProbe: init procfs failed\n"));
3171 eFailReason
= PROC_INIT_FAIL
;
3174 #endif /* WLAN_INCLUDE_PROC */
3176 #if CFG_ENABLE_BT_OVER_WIFI
3177 prGlueInfo
->rBowInfo
.fgIsNetRegistered
= FALSE
;
3178 prGlueInfo
->rBowInfo
.fgIsRegistered
= FALSE
;
3179 glRegisterAmpc(prGlueInfo
);
3182 #if CFG_ENABLE_WIFI_DIRECT
3183 DBGLOG(INIT
, TRACE
, ("wlanSubModInit...\n"));
3185 /* wlan is launched */
3186 prGlueInfo
->prAdapter
->fgIsWlanLaunched
= TRUE
;
3187 /* if p2p module is inserted, notify tx_thread to init p2p network */
3188 if(rSubModHandler
[P2P_MODULE
].subModInit
) {
3189 wlanSubModInit(prGlueInfo
);
3191 /* register set_p2p_mode handler to mtk_wmt_wifi */
3192 register_set_p2p_mode_handler(set_p2p_mode_handler
);
3194 #if CFG_SPM_WORKAROUND_FOR_HOTSPOT
3195 if (glIsChipNeedWakelock(prGlueInfo
))
3196 KAL_WAKE_LOCK_INIT(prGlueInfo
->prAdapter
, &prGlueInfo
->prAdapter
->rApWakeLock
, "WLAN AP");
3201 if (i4Status
!= WLAN_STATUS_SUCCESS
)
3203 switch (eFailReason
)
3205 case PROC_INIT_FAIL
:
3206 wlanNetUnregister(prWdev
);
3207 case NET_REGISTER_FAIL
:
3208 set_bit(GLUE_FLAG_HALT_BIT
, &prGlueInfo
->ulFlag
);
3209 /* wake up main thread */
3210 wake_up_interruptible(&prGlueInfo
->waitq
);
3211 /* wait main thread stops */
3212 wait_for_completion_interruptible(&prGlueInfo
->rHaltComp
);
3213 KAL_WAKE_LOCK_DESTROY(prGlueInfo
->prAdapter
, &prGlueInfo
->rAhbIsrWakeLock
);
3214 wlanAdapterStop(prAdapter
);
3215 case ADAPTER_START_FAIL
:
3217 glBusFreeIrq(prWdev
->netdev
, *((P_GLUE_INFO_T
*) netdev_priv(prWdev
->netdev
)));
3218 case BUS_SET_IRQ_FAIL
:
3219 KAL_WAKE_LOCK_DESTROY(prAdapter
, &prGlueInfo
->rAhbIsrWakeLock
);
3220 wlanNetDestroy(prWdev
);
3221 case NET_CREATE_FAIL
:
3228 #if CFG_ENABLE_WIFI_DIRECT
3230 GLUE_SPIN_LOCK_DECLARATION();
3232 GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock
);
3234 GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock
);
3237 #if CFG_SUPPORT_AGPS_ASSIST
3238 if (i4Status
== WLAN_STATUS_SUCCESS
)
3239 kalIndicateAgpsNotify(prAdapter
, AGPS_EVENT_WLAN_ON
, NULL
, 0);
3241 #if (CFG_SUPPORT_MET_PROFILING == 1)
3243 int iMetInitRet
= WLAN_STATUS_FAILURE
;
3244 if (i4Status
== WLAN_STATUS_SUCCESS
)
3246 DBGLOG(INIT
, TRACE
, ("init MET procfs...\n"));
3247 iMetInitRet
= kalMetInitProcfs(prGlueInfo
);
3248 if (iMetInitRet
< 0)
3250 DBGLOG(INIT
, ERROR
, ("wlanProbe: init MET procfs failed\n"));
3255 if (i4Status
== WLAN_STATUS_SUCCESS
) {
3257 DBGLOG(INIT
, TRACE
, ("wlanProbe ok\n"));
3260 DBGLOG(INIT
, ERROR
, ("wlanProbe failed\n"));
3264 } /* end of wlanProbe() */
3267 /*----------------------------------------------------------------------------*/
3269 * \brief A method to stop driver operation and release all resources. Following
3270 * this call, no frame should go up or down through this interface.
3274 /*----------------------------------------------------------------------------*/
3280 struct net_device
*prDev
= NULL
;
3281 P_WLANDEV_INFO_T prWlandevInfo
= NULL
;
3282 P_GLUE_INFO_T prGlueInfo
= NULL
;
3283 P_ADAPTER_T prAdapter
= NULL
;
3285 DBGLOG(INIT
, INFO
, ("Remove wlan!\n"));
3288 //4 <0> Sanity check
3289 ASSERT(u4WlanDevNum
<= CFG_MAX_WLAN_DEVICES
);
3290 if (0 == u4WlanDevNum
) {
3291 DBGLOG(INIT
, INFO
, ("0 == u4WlanDevNum\n"));
3294 /* unregister set_p2p_mode handler to mtk_wmt_wifi */
3295 register_set_p2p_mode_handler(NULL
);
3297 prDev
= arWlanDevInfo
[u4WlanDevNum
-1].prDev
;
3298 prWlandevInfo
= &arWlanDevInfo
[u4WlanDevNum
-1];
3301 if (NULL
== prDev
) {
3302 DBGLOG(INIT
, INFO
, ("NULL == prDev\n"));
3306 prGlueInfo
= *((P_GLUE_INFO_T
*) netdev_priv(prDev
));
3308 if (NULL
== prGlueInfo
) {
3309 DBGLOG(INIT
, INFO
, ("NULL == prGlueInfo\n"));
3314 #if CFG_ENABLE_WIFI_DIRECT
3315 /* avoid remove & p2p off command simultaneously */
3317 BOOLEAN fgIsP2POnOffing
;
3318 GLUE_SPIN_LOCK_DECLARATION();
3320 GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock
);
3322 fgIsP2POnOffing
= g_u4P2POnOffing
;
3323 GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock
);
3325 DBGLOG(INIT
, INFO
, ("waiting for fgIsP2POnOffing...\n"));
3327 /* History: cannot use down() here, sometimes we cannot come back here */
3328 /* waiting for p2p off command finishes, we cannot skip the remove */
3330 if (fgIsP2POnOffing
== 0)
3332 GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock
);
3333 fgIsP2POnOffing
= g_u4P2POnOffing
;
3334 GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock
);
3339 #if CFG_ENABLE_BT_OVER_WIFI
3340 if(prGlueInfo
->rBowInfo
.fgIsNetRegistered
) {
3341 bowNotifyAllLinkDisconnected(prGlueInfo
->prAdapter
);
3342 /* wait 300ms for BoW module to send deauth */
3347 //4 <1> Stopping handling interrupt and free IRQ
3348 DBGLOG(INIT
, INFO
, ("free IRQ...\n"));
3349 glBusFreeIrq(prDev
, *((P_GLUE_INFO_T
*) netdev_priv(prDev
)));
3351 kalMemSet(&(prGlueInfo
->prAdapter
->rWlanInfo
), 0, sizeof(WLAN_INFO_T
));
3353 g_u4HaltFlag
= 1; /* before flush_delayed_work() */
3354 if (fgIsWorkMcStart
== TRUE
) {
3355 DBGLOG(INIT
, INFO
, ("flush_delayed_work...\n"));
3356 flush_delayed_work(&workq
); /* flush_delayed_work_sync is deprecated */
3359 DBGLOG(INIT
, INFO
, ("down g_halt_sem...\n"));
3361 #if CFG_SPM_WORKAROUND_FOR_HOTSPOT
3362 if (glIsChipNeedWakelock(prGlueInfo
))
3363 KAL_WAKE_LOCK_DESTROY(prGlueInfo
->prAdapter
, &prGlueInfo
->prAdapter
->rApWakeLock
);
3366 // flush_delayed_work_sync(&workq);
3367 // flush_delayed_work(&workq); /* flush_delayed_work_sync is deprecated */
3369 //4 <2> Mark HALT, notify main thread to stop, and clean up queued requests
3370 // prGlueInfo->u4Flag |= GLUE_FLAG_HALT;
3371 set_bit(GLUE_FLAG_HALT_BIT
, &prGlueInfo
->ulFlag
);
3372 DBGLOG(INIT
, INFO
, ("waiting for tx_thread stop...\n"));
3374 /* wake up main thread */
3375 wake_up_interruptible(&prGlueInfo
->waitq
);
3377 DBGLOG(INIT
, INFO
, ("wait_for_completion_interruptible\n"));
3379 /* wait main thread stops */
3380 wait_for_completion_interruptible(&prGlueInfo
->rHaltComp
);
3382 DBGLOG(INIT
, INFO
, ("mtk_sdiod stopped\n"));
3384 KAL_WAKE_LOCK_DESTROY(prGlueInfo
->prAdapter
, &prGlueInfo
->prAdapter
->rTxThreadWakeLock
);
3385 KAL_WAKE_LOCK_DESTROY(prGlueInfo
->prAdapter
, &prGlueInfo
->rAhbIsrWakeLock
);
3387 //prGlueInfo->rHifInfo.main_thread = NULL;
3388 prGlueInfo
->main_thread
= NULL
;
3390 #if CFG_ENABLE_BT_OVER_WIFI
3391 if(prGlueInfo
->rBowInfo
.fgIsRegistered
) {
3392 glUnregisterAmpc(prGlueInfo
);
3396 //4 <3> Remove /proc filesystem.
3397 #ifdef WLAN_INCLUDE_PROC
3398 procRemoveProcfs(prDev
, NIC_DEVICE_ID_LOW
);
3399 #endif /* WLAN_INCLUDE_PROC */
3401 #if (CFG_SUPPORT_MET_PROFILING == 1)
3402 kalMetRemoveProcfs();
3405 /* Force to do DMA reset */
3406 DBGLOG(INIT
, INFO
, ("glResetHif\n"));
3407 glResetHif(prGlueInfo
);
3409 //4 <4> wlanAdapterStop
3410 prAdapter
= prGlueInfo
->prAdapter
;
3411 #if CFG_SUPPORT_AGPS_ASSIST
3412 kalIndicateAgpsNotify(prAdapter
, AGPS_EVENT_WLAN_OFF
, NULL
, 0);
3415 wlanAdapterStop(prAdapter
);
3416 DBGLOG(INIT
, INFO
, ("Number of Stalled Packets = %d\n", prGlueInfo
->i4TxPendingFrameNum
));
3418 #if CFG_ENABLE_WIFI_DIRECT
3419 prGlueInfo
->prAdapter
->fgIsWlanLaunched
= FALSE
;
3420 if(prGlueInfo
->prAdapter
->fgIsP2PRegistered
) {
3421 DBGLOG(INIT
, INFO
, ("p2pNetUnregister...\n"));
3422 p2pNetUnregister(prGlueInfo
, FALSE
);
3423 DBGLOG(INIT
, INFO
, ("p2pRemove...\n"));
3424 p2pRemove(prGlueInfo
);
3428 //4 <5> Release the Bus
3429 glBusRelease(prDev
);
3433 //4 <6> Unregister the card
3434 wlanNetUnregister(prDev
->ieee80211_ptr
);
3436 //4 <7> Destroy the device
3437 wlanNetDestroy(prDev
->ieee80211_ptr
);
3440 DBGLOG(INIT
, INFO
, ("wlanUnregisterNotifier...\n"));
3441 wlanUnregisterNotifier();
3443 DBGLOG(INIT
, INFO
, ("wlanRemove ok\n"));
3445 } /* end of wlanRemove() */
3447 /*----------------------------------------------------------------------------*/
3449 * \brief Driver entry point when the driver is configured as a Linux Module, and
3450 * is called once at module load time, by the user-level modutils
3451 * application: insmod or modprobe.
3455 /*----------------------------------------------------------------------------*/
3456 //1 Module Entry Point
3457 static int initWlan(void)
3461 DBGLOG(INIT
, INFO
, ("initWlan\n"));
3463 spin_lock_init(&g_p2p_lock
);
3465 /* memory pre-allocation */
3468 ret
= ((glRegisterBus(wlanProbe
, wlanRemove
) == WLAN_STATUS_SUCCESS
) ? 0: -EIO
);
3471 kalUninitIOBuffer();
3475 #if (CFG_CHIP_RESET_SUPPORT)
3479 /* register set_dbg_level handler to mtk_wmt_wifi */
3480 register_set_dbg_level_handler(set_dbg_level_handler
);
3482 /* Set the initial DEBUG CLASS of each module */
3484 for (i
= 0; i
< DBG_MODULE_NUM
; i
++) {
3485 aucDebugModule
[i
] = DBG_CLASS_MASK
; //enable all
3488 // Initial debug level is D1
3489 for (i
= 0; i
< DBG_MODULE_NUM
; i
++) {
3490 aucDebugModule
[i
] = DBG_CLASS_ERROR
| \
3497 aucDebugModule
[DBG_TX_IDX
] &= ~(DBG_CLASS_EVENT
| \
3500 aucDebugModule
[DBG_RX_IDX
] &= ~(DBG_CLASS_EVENT
| \
3503 aucDebugModule
[DBG_REQ_IDX
] &= ~(DBG_CLASS_EVENT
| \
3506 aucDebugModule
[DBG_INTR_IDX
] = 0;
3507 aucDebugModule
[DBG_MEM_IDX
] = 0;
3511 } /* end of initWlan() */
3514 /*----------------------------------------------------------------------------*/
3516 * \brief Driver exit point when the driver as a Linux Module is removed. Called
3517 * at module unload time, by the user level modutils application: rmmod.
3518 * This is our last chance to clean up after ourselves.
3522 /*----------------------------------------------------------------------------*/
3523 //1 Module Leave Point
3524 static VOID
exitWlan(void)
3526 DBGLOG(INIT
, INFO
, ("exitWlan\n"));
3528 /* unregister set_dbg_level handler to mtk_wmt_wifi */
3529 register_set_dbg_level_handler(NULL
);
3531 #if CFG_CHIP_RESET_SUPPORT
3535 glUnregisterBus(wlanRemove
);
3537 /* free pre-allocated memory */
3538 kalUninitIOBuffer();
3540 DBGLOG(INIT
, INFO
, ("exitWlan\n"));
3543 } /* end of exitWlan() */
3546 #ifdef MTK_WCN_REMOVE_KERNEL_MODULE
3547 int mtk_wcn_wlan_soc_init(void)
3552 void mtk_wcn_wlan_soc_exit(void)
3557 EXPORT_SYMBOL(mtk_wcn_wlan_soc_init
);
3558 EXPORT_SYMBOL(mtk_wcn_wlan_soc_exit
);
3560 module_init(initWlan
);
3561 module_exit(exitWlan
);