add rk3288 pinctrl dts code
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / mt5931 / os / linux / gl_init.c
1 /*
2 ** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_init.c#7 $
3 */
4
5 /*! \file   gl_init.c
6     \brief  Main routines of Linux driver
7
8     This file contains the main routines of Linux driver for MediaTek Inc. 802.11
9     Wireless LAN Adapters.
10 */
11
12
13
14 /*
15 ** $Log: gl_init.c $
16  *
17  * 07 17 2012 yuche.tsai
18  * NULL
19  * Fix compile error.
20  *
21  * 07 17 2012 yuche.tsai
22  * NULL
23  * Fix compile error for JB.
24  *
25  * 07 17 2012 yuche.tsai
26  * NULL
27  * Let netdev bring up.
28  *
29  * 07 17 2012 yuche.tsai
30  * NULL
31  * Compile no error before trial run.
32  *
33  * 06 13 2012 yuche.tsai
34  * NULL
35  * Update maintrunk driver.
36  * Add support for driver compose assoc request frame.
37  *
38  * 05 25 2012 yuche.tsai
39  * NULL
40  * Fix reset KE issue.
41  *
42  * 05 11 2012 cp.wu
43  * [WCXRP00001237] [MT6620 Wi-Fi][Driver] Show MAC address and MAC address source for ACS's convenience
44  * show MAC address & source while initiliazation
45  *
46  * 03 02 2012 terry.wu
47  * NULL
48  * EXPORT_SYMBOL(rsnParseCheckForWFAInfoElem);.
49  *
50  * 03 02 2012 terry.wu
51  * NULL
52  * Snc CFG80211 modification for ICS migration from branch 2.2.
53  *
54  * 03 02 2012 terry.wu
55  * NULL
56  * Sync CFG80211 modification from branch 2,2.
57  *
58  * 03 02 2012 terry.wu
59  * NULL
60  * Enable CFG80211 Support.
61  *
62  * 12 22 2011 george.huang
63  * [WCXRP00000905] [MT6628 Wi-Fi][FW] Code refinement for ROM/ RAM module dependency
64  * using global variable instead of stack for setting wlanoidSetNetworkAddress(), due to buffer may be released before TX thread handling
65  *
66  * 11 18 2011 yuche.tsai
67  * NULL
68  * CONFIG P2P support RSSI query, default turned off.
69  *
70  * 11 14 2011 yuche.tsai
71  * [WCXRP00001107] [Volunteer Patch][Driver] Large Network Type index assert in FW issue.
72  * Fix large network type index assert in FW issue.
73  *
74  * 11 14 2011 cm.chang
75  * NULL
76  * Fix compiling warning
77  *
78  * 11 11 2011 yuche.tsai
79  * NULL
80  * Fix work thread cancel issue.
81  *
82  * 11 10 2011 cp.wu
83  * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer
84  * 1. eliminaite direct calls to printk in porting layer.
85  * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms.
86  *
87  * 10 06 2011 eddie.chen
88  * [WCXRP00001027] [MT6628 Wi-Fi][Firmware/Driver] Tx fragmentation
89  * Add rlmDomainGetChnlList symbol.
90  *
91  * 09 22 2011 cm.chang
92  * NULL
93  * Safer writng stype to avoid unitialized regitry structure
94  *
95  * 09 21 2011 cm.chang
96  * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code
97  * Avoid possible structure alignment problem
98  *
99  * 09 20 2011 chinglan.wang
100  * [WCXRP00000989] [WiFi Direct] [Driver] Add a new io control API to start the formation for the sigma test.
101  * .
102  *
103  * 09 08 2011 cm.chang
104  * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code
105  * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM
106  *
107  * 08 31 2011 cm.chang
108  * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code
109  * .
110  *
111  * 08 11 2011 cp.wu
112  * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time
113  * expose scnQuerySparseChannel() for P2P-FSM.
114  *
115  * 08 11 2011 cp.wu
116  * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time
117  * sparse channel detection:
118  * driver: collect sparse channel information with scan-done event
119  *
120  * 08 02 2011 yuche.tsai
121  * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting device issue.
122  * Fix GO send deauth frame issue.
123  *
124  * 07 07 2011 wh.su
125  * [WCXRP00000839] [MT6620 Wi-Fi][Driver] Add the dumpMemory8 and dumpMemory32 EXPORT_SYMBOL
126  * Add the dumpMemory8 symbol export for debug mode.
127  *
128  * 07 06 2011 terry.wu
129  * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment
130  * Improve BoW connection establishment speed.
131  *
132  * 07 05 2011 yuche.tsai
133  * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue
134  * Export one symbol for enhancement.
135  *
136  * 06 13 2011 eddie.chen
137  * [WCXRP00000779] [MT6620 Wi-Fi][DRV]  Add tx rx statistics in linux and use netif_rx_ni
138  * Add tx rx statistics and netif_rx_ni.
139  *
140  * 05 27 2011 cp.wu
141  * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM
142  * invoke CMD_ID_SET_EDGE_TXPWR_LIMIT when there is valid data exist in NVRAM content.
143  *
144  * 05 18 2011 cp.wu
145  * [WCXRP00000734] [MT6620 Wi-Fi][Driver] Pass PHY_PARAM in NVRAM to firmware domain
146  * pass PHY_PARAM in NVRAM from driver to firmware.
147  *
148  * 05 09 2011 jeffrey.chang
149  * [WCXRP00000710] [MT6620 Wi-Fi] Support pattern filter update function on IP address change
150  * support ARP filter through kernel notifier
151  *
152  * 05 03 2011 chinghwa.yu
153  * [WCXRP00000065] Update BoW design and settings
154  * Use kalMemAlloc to allocate event buffer for kalIndicateBOWEvent.
155  *
156  * 04 27 2011 george.huang
157  * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter
158  * Support P2P ARP filter setting on early suspend/ late resume
159  *
160  * 04 18 2011 terry.wu
161  * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED
162  * Remove flag CFG_WIFI_DIRECT_MOVED.
163  *
164  * 04 15 2011 chinghwa.yu
165  * [WCXRP00000065] Update BoW design and settings
166  * Add BOW short range mode.
167  *
168  * 04 14 2011 yuche.tsai
169  * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case.
170  * Modify some driver connection flow or behavior to pass Sigma test more easier..
171  *
172  * 04 12 2011 cm.chang
173  * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency
174  * .
175  *
176  * 04 11 2011 george.huang
177  * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode
178  * export wlan functions to p2p
179  *
180  * 04 08 2011 pat.lu
181  * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver
182  * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile settting for PC Linux driver
183  *
184  * 04 08 2011 cp.wu
185  * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
186  * glBusFreeIrq() should use the same pvCookie as glBusSetIrq() or request_irq()/free_irq() won't work as a pair.
187  *
188  * 04 08 2011 eddie.chen
189  * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma
190  * Fix for sigma
191  *
192  * 04 06 2011 cp.wu
193  * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
194  * 1. do not check for pvData inside wlanNetCreate() due to it is NULL for eHPI  port
195  * 2. update perm_addr as well for MAC address
196  * 3. not calling check_mem_region() anymore for eHPI
197  * 4. correct MSC_CS macro for 0-based notation
198  *
199  * 03 29 2011 cp.wu
200  * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events
201  * fix typo.
202  *
203  * 03 29 2011 cp.wu
204  * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for RESET_START and RESET_END events
205  * implement kernel-to-userspace communication via generic netlink socket for whole-chip resetting mechanism
206  *
207  * 03 23 2011 cp.wu
208  * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
209  * apply multi-queue operation only for linux kernel > 2.6.26
210  *
211  * 03 22 2011 pat.lu
212  * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build
213  * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment.
214  *
215  * 03 21 2011 cp.wu
216  * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
217  * portability for compatible with linux 2.6.12.
218  *
219  * 03 21 2011 cp.wu
220  * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
221  * improve portability for awareness of early version of linux kernel and wireless extension.
222  *
223  * 03 21 2011 cp.wu
224  * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
225  * portability improvement
226  *
227  * 03 18 2011 jeffrey.chang
228  * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue
229  * remove early suspend functions
230  *
231  * 03 17 2011 cp.wu
232  * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period
233  * reverse order to prevent probing racing.
234  *
235  * 03 16 2011 cp.wu
236  * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period
237  * 1. pre-allocate physical continuous buffer while module is being loaded
238  * 2. use pre-allocated physical continuous buffer for TX/RX DMA transfer
239  *
240  * The windows part remained the same as before, but added similiar APIs to hide the difference.
241  *
242  * 03 15 2011 jeffrey.chang
243  * [WCXRP00000558] [MT6620 Wi-Fi][MT6620 Wi-Fi][Driver] refine the queue selection algorithm for WMM
244  * refine the queue_select function
245  *
246  * 03 10 2011 cp.wu
247  * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3
248  * deprecate configuration used by MT6620 E2
249  *
250  * 03 10 2011 terry.wu
251  * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration
252  * Remove unnecessary assert and message.
253  *
254  * 03 08 2011 terry.wu
255  * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration
256  * Export nicQmUpdateWmmParms.
257  *
258  * 03 03 2011 jeffrey.chang
259  * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue
260  * support concurrent network
261  *
262  * 03 03 2011 jeffrey.chang
263  * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue
264  * modify net device relative functions to support multiple H/W queues
265  *
266  * 02 24 2011 george.huang
267  * [WCXRP00000495] [MT6620 Wi-Fi][FW] Support pattern filter for unwanted ARP frames
268  * Support ARP filter during suspended
269  *
270  * 02 21 2011 cp.wu
271  * [WCXRP00000482] [MT6620 Wi-Fi][Driver] Simplify logic for checking NVRAM existence in driver domain
272  * simplify logic for checking NVRAM existence only once.
273  *
274  * 02 17 2011 terry.wu
275  * [WCXRP00000459] [MT6620 Wi-Fi][Driver] Fix deference null pointer problem in wlanRemove
276  * Fix deference a null pointer problem in wlanRemove.
277  *
278  * 02 16 2011 jeffrey.chang
279  * NULL
280  * fix compilig error
281  *
282  * 02 16 2011 jeffrey.chang
283  * NULL
284  * Add query ipv4 and ipv6 address during early suspend and late resume
285  *
286  * 02 15 2011 jeffrey.chang
287  * NULL
288  * to support early suspend in android
289  *
290  * 02 11 2011 yuche.tsai
291  * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode.
292  * Add one more export symbol.
293  *
294  * 02 10 2011 yuche.tsai
295  * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode.
296  * Add RX deauthentication & disassociation process under Hot-Spot mode.
297  *
298  * 02 09 2011 terry.wu
299  * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules
300  * Halt p2p module init and exit until TxThread finished p2p register and unregister.
301  *
302  * 02 08 2011 george.huang
303  * [WCXRP00000422] [MT6620 Wi-Fi][Driver] support query power mode OID handler
304  * Support querying power mode OID.
305  *
306  * 02 08 2011 yuche.tsai
307  * [WCXRP00000421] [Volunteer Patch][MT6620][Driver] Fix incorrect SSID length Issue
308  * Export Deactivation Network.
309  *
310  * 02 01 2011 jeffrey.chang
311  * [WCXRP00000414] KAL Timer is not unregistered when driver not loaded
312  * Unregister the KAL timer during driver unloading
313  *
314  * 01 26 2011 cm.chang
315  * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument
316  * Allocate system RAM if fixed message or mgmt buffer is not available
317  *
318  * 01 19 2011 cp.wu
319  * [WCXRP00000371] [MT6620 Wi-Fi][Driver] make linux glue layer portable for Android 2.3.1 with Linux 2.6.35.7
320  * add compile option to check linux version 2.6.35 for different usage of system API to improve portability
321  *
322  * 01 12 2011 cp.wu
323  * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP
324  * implementation of separate BT_OVER_WIFI data path.
325  *
326  * 01 10 2011 cp.wu
327  * [WCXRP00000349] [MT6620 Wi-Fi][Driver] make kalIoctl() of linux port as a thread safe API to avoid potential issues due to multiple access
328  * use mutex to protect kalIoctl() for thread safe.
329  *
330  * 01 04 2011 cp.wu
331  * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease physically continous memory demands
332  * separate kalMemAlloc() into virtually-continous and physically-continous type to ease slab system pressure
333  *
334  * 12 15 2010 cp.wu
335  * [WCXRP00000265] [MT6620 Wi-Fi][Driver] Remove set_mac_address routine from legacy Wi-Fi Android driver
336  * remove set MAC address. MAC address is always loaded from NVRAM instead.
337  *
338  * 12 10 2010 kevin.huang
339  * [WCXRP00000128] [MT6620 Wi-Fi][Driver] Add proc support to Android Driver for debug and driver status check
340  * Add Linux Proc Support
341  *
342  * 11 01 2010 yarco.yang
343  * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform
344  * Add GPIO debug function
345  *
346  * 11 01 2010 cp.wu
347  * [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
348  * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead
349  * 2) Remove CNM CH-RECOVER event handling
350  * 3) cfg read/write API renamed with kal prefix for unified naming rules.
351  *
352  * 10 26 2010 cp.wu
353  * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command
354  * 1) update NVRAM content template to ver 1.02
355  * 2) add compile option for querying NIC capability (default: off)
356  * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting
357  * 4) correct auto-rate compiler error under linux (treat warning as error)
358  * 5) simplify usage of NVRAM and REG_INFO_T
359  * 6) add version checking between driver and firmware
360  *
361  * 10 21 2010 chinghwa.yu
362  * [WCXRP00000065] Update BoW design and settings
363  * .
364  *
365  * 10 19 2010 jeffrey.chang
366  * [WCXRP00000120] [MT6620 Wi-Fi][Driver] Refine linux kernel module to the license of MTK propietary and enable MTK HIF by default
367  * Refine linux kernel module to the license of MTK and enable MTK HIF
368  *
369  * 10 18 2010 jeffrey.chang
370  * [WCXRP00000106] [MT6620 Wi-Fi][Driver] Enable setting multicast  callback in Android
371  * .
372  *
373  * 10 18 2010 cp.wu
374  * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android
375  * complete implementation of Android NVRAM access
376  *
377  * 09 27 2010 chinghwa.yu
378  * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings
379  * Update BCM/BoW design and settings.
380  *
381  * 09 23 2010 cp.wu
382  * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item
383  * use firmware reported mac address right after wlanAdapterStart() as permanent address
384  *
385  * 09 21 2010 kevin.huang
386  * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning
387  * Eliminate Linux Compile Warning
388  *
389  * 09 03 2010 kevin.huang
390  * NULL
391  * Refine #include sequence and solve recursive/nested #include issue
392  *
393  * 09 01 2010 wh.su
394  * NULL
395  * adding the wapi support for integration test.
396  *
397  * 08 18 2010 yarco.yang
398  * NULL
399  * 1. Fixed HW checksum offload function not work under Linux issue.
400  * 2. Add debug message.
401  *
402  * 08 16 2010 yarco.yang
403  * NULL
404  * Support Linux x86
405  *
406  * 08 02 2010 jeffrey.chang
407  * NULL
408  * 1) modify tx service thread to avoid busy looping
409  * 2) add spin lock declartion for linux build
410  *
411  * 07 29 2010 jeffrey.chang
412  * NULL
413  * fix memory leak for module unloading
414  *
415  * 07 28 2010 jeffrey.chang
416  * NULL
417  * 1) remove unused spinlocks
418  * 2) enable encyption ioctls
419  * 3) fix scan ioctl which may cause supplicant to hang
420  *
421  * 07 23 2010 jeffrey.chang
422  *
423  * bug fix: allocate regInfo when disabling firmware download
424  *
425  * 07 23 2010 jeffrey.chang
426  *
427  * use glue layer api to decrease or increase counter atomically
428  *
429  * 07 22 2010 jeffrey.chang
430  *
431  * add new spinlock
432  *
433  * 07 19 2010 jeffrey.chang
434  *
435  * modify cmd/data path for new design
436  *
437  * 07 08 2010 cp.wu
438  *
439  * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
440  *
441  * 06 06 2010 kevin.huang
442  * [WPD00003832][MT6620 5931] Create driver base
443  * [MT6620 5931] Create driver base
444  *
445  * 05 26 2010 jeffrey.chang
446  * [WPD00003826]Initial import for Linux port
447  * 1) Modify set mac address code
448  * 2) remove power managment macro
449  *
450  * 05 10 2010 cp.wu
451  * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
452  * implement basic wi-fi direct framework
453  *
454  * 05 07 2010 jeffrey.chang
455  * [WPD00003826]Initial import for Linux port
456  * prevent supplicant accessing driver during resume
457  *
458  * 05 07 2010 cp.wu
459  * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
460  * add basic framework for implementating P2P driver hook.
461  *
462  * 04 27 2010 jeffrey.chang
463  * [WPD00003826]Initial import for Linux port
464  * 1) fix firmware download bug
465  * 2) remove query statistics for acelerating firmware download
466  *
467  * 04 27 2010 jeffrey.chang
468  * [WPD00003826]Initial import for Linux port
469  * follow Linux's firmware framework, and remove unused kal API
470  *
471  * 04 21 2010 jeffrey.chang
472  * [WPD00003826]Initial import for Linux port
473  * add for private ioctl support
474  *
475  * 04 19 2010 jeffrey.chang
476  * [WPD00003826]Initial import for Linux port
477  * Query statistics from firmware
478  *
479  * 04 19 2010 jeffrey.chang
480  * [WPD00003826]Initial import for Linux port
481  * modify tcp/ip checksum offload flags
482  *
483  * 04 16 2010 jeffrey.chang
484  * [WPD00003826]Initial import for Linux port
485  * fix tcp/ip checksum offload bug
486  *
487  * 04 13 2010 cp.wu
488  * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support
489  * add framework for BT-over-Wi-Fi support.
490  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * 1) prPendingCmdInfo is replaced by queue for multiple handler capability
491  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * 2) command sequence number is now increased atomically
492  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * 3) private data could be hold and taken use for other purpose
493  *
494  * 04 09 2010 jeffrey.chang
495  * [WPD00003826]Initial import for Linux port
496  * fix spinlock usage
497  *
498  * 04 07 2010 jeffrey.chang
499  * [WPD00003826]Initial import for Linux port
500  * Set MAC address from firmware
501  *
502  * 04 07 2010 cp.wu
503  * [WPD00001943]Create WiFi test driver framework on WinXP
504  * rWlanInfo should be placed at adapter rather than glue due to most operations
505  *  *  *  *  *  * are done in adapter layer.
506  *
507  * 04 07 2010 jeffrey.chang
508  * [WPD00003826]Initial import for Linux port
509  * (1)improve none-glue code portability
510  *  * (2) disable set Multicast address during atomic context
511  *
512  * 04 06 2010 jeffrey.chang
513  * [WPD00003826]Initial import for Linux port
514  * adding debug module
515  *
516  * 03 31 2010 wh.su
517  * [WPD00003816][MT6620 Wi-Fi] Adding the security support
518  * modify the wapi related code for new driver's design.
519  *
520  * 03 30 2010 jeffrey.chang
521  * [WPD00003826]Initial import for Linux port
522  * emulate NDIS Pending OID facility
523  *
524  * 03 26 2010 jeffrey.chang
525  * [WPD00003826]Initial import for Linux port
526  * fix f/w download start and load address by using config.h
527  *
528  * 03 26 2010 jeffrey.chang
529  * [WPD00003826]Initial import for Linux port
530  * [WPD00003826] Initial import for Linux port
531  * adding firmware download support
532  *
533  * 03 24 2010 jeffrey.chang
534  * [WPD00003826]Initial import for Linux port
535  * initial import for Linux port
536 **  \main\maintrunk.MT5921\52 2009-10-27 22:49:59 GMT mtk01090
537 **  Fix compile error for Linux EHPI driver
538 **  \main\maintrunk.MT5921\51 2009-10-20 17:38:22 GMT mtk01090
539 **  Refine driver unloading and clean up procedure. Block requests, stop main thread and clean up queued requests, and then stop hw.
540 **  \main\maintrunk.MT5921\50 2009-10-08 10:33:11 GMT mtk01090
541 **  Avoid accessing private data of net_device directly. Replace with netdev_priv(). Add more checking for input parameters and pointers.
542 **  \main\maintrunk.MT5921\49 2009-09-28 20:19:05 GMT mtk01090
543 **  Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel.
544 **  \main\maintrunk.MT5921\48 2009-09-03 13:58:46 GMT mtk01088
545 **  remove non-used code
546 **  \main\maintrunk.MT5921\47 2009-09-03 11:40:25 GMT mtk01088
547 **  adding the module parameter for wapi
548 **  \main\maintrunk.MT5921\46 2009-08-18 22:56:41 GMT mtk01090
549 **  Add Linux SDIO (with mmc core) support.
550 **  Add Linux 2.6.21, 2.6.25, 2.6.26.
551 **  Fix compile warning in Linux.
552 **  \main\maintrunk.MT5921\45 2009-07-06 20:53:00 GMT mtk01088
553 **  adding the code to check the wapi 1x frame
554 **  \main\maintrunk.MT5921\44 2009-06-23 23:18:55 GMT mtk01090
555 **  Add build option BUILD_USE_EEPROM and compile option CFG_SUPPORT_EXT_CONFIG for NVRAM support
556 **  \main\maintrunk.MT5921\43 2009-02-16 23:46:51 GMT mtk01461
557 **  Revise the order of increasing u4TxPendingFrameNum because of  CFG_TX_RET_TX_CTRL_EARLY
558 **  \main\maintrunk.MT5921\42 2009-01-22 13:11:59 GMT mtk01088
559 **  set the tid and 1x value at same packet reserved field
560 **  \main\maintrunk.MT5921\41 2008-10-20 22:43:53 GMT mtk01104
561 **  Fix wrong variable name "prDev" in wlanStop()
562 **  \main\maintrunk.MT5921\40 2008-10-16 15:37:10 GMT mtk01461
563 **  add handle WLAN_STATUS_SUCCESS in wlanHardStartXmit() for CFG_TX_RET_TX_CTRL_EARLY
564 **  \main\maintrunk.MT5921\39 2008-09-25 15:56:21 GMT mtk01461
565 **  Update driver for Code review
566 **  \main\maintrunk.MT5921\38 2008-09-05 17:25:07 GMT mtk01461
567 **  Update Driver for Code Review
568 **  \main\maintrunk.MT5921\37 2008-09-02 10:57:06 GMT mtk01461
569 **  Update driver for code review
570 **  \main\maintrunk.MT5921\36 2008-08-05 01:53:28 GMT mtk01461
571 **  Add support for linux statistics
572 **  \main\maintrunk.MT5921\35 2008-08-04 16:52:58 GMT mtk01461
573 **  Fix ASSERT if removing module in BG_SSID_SCAN state
574 **  \main\maintrunk.MT5921\34 2008-06-13 22:52:24 GMT mtk01461
575 **  Revise status code handling in wlanHardStartXmit() for WLAN_STATUS_SUCCESS
576 **  \main\maintrunk.MT5921\33 2008-05-30 18:56:53 GMT mtk01461
577 **  Not use wlanoidSetCurrentAddrForLinux()
578 **  \main\maintrunk.MT5921\32 2008-05-30 14:39:40 GMT mtk01461
579 **  Remove WMM Assoc Flag
580 **  \main\maintrunk.MT5921\31 2008-05-23 10:26:40 GMT mtk01084
581 **  modify wlanISR interface
582 **  \main\maintrunk.MT5921\30 2008-05-03 18:52:36 GMT mtk01461
583 **  Fix Unset Broadcast filter when setMulticast
584 **  \main\maintrunk.MT5921\29 2008-05-03 15:17:26 GMT mtk01461
585 **  Move Query Media Status to GLUE
586 **  \main\maintrunk.MT5921\28 2008-04-24 22:48:21 GMT mtk01461
587 **  Revise set multicast function by using windows oid style for LP own back
588 **  \main\maintrunk.MT5921\27 2008-04-24 12:00:08 GMT mtk01461
589 **  Fix multicast setting in Linux and add comment
590 **  \main\maintrunk.MT5921\26 2008-03-28 10:40:22 GMT mtk01461
591 **  Fix set mac address func in Linux
592 **  \main\maintrunk.MT5921\25 2008-03-26 15:37:26 GMT mtk01461
593 **  Add set MAC Address
594 **  \main\maintrunk.MT5921\24 2008-03-26 14:24:53 GMT mtk01461
595 **  For Linux, set net_device has feature with checksum offload by default
596 **  \main\maintrunk.MT5921\23 2008-03-11 14:50:52 GMT mtk01461
597 **  Fix typo
598 **  \main\maintrunk.MT5921\22 2008-02-29 15:35:20 GMT mtk01088
599 **  add 1x decide code for sw port control
600 **  \main\maintrunk.MT5921\21 2008-02-21 15:01:54 GMT mtk01461
601 **  Rearrange the set off place of GLUE spin lock in HardStartXmit
602 **  \main\maintrunk.MT5921\20 2008-02-12 23:26:50 GMT mtk01461
603 **  Add debug option - Packet Order for Linux and add debug level - Event
604 **  \main\maintrunk.MT5921\19 2007-12-11 00:11:12 GMT mtk01461
605 **  Fix SPIN_LOCK protection
606 **  \main\maintrunk.MT5921\18 2007-11-30 17:02:25 GMT mtk01425
607 **  1. Set Rx multicast packets mode before setting the address list
608 **  \main\maintrunk.MT5921\17 2007-11-26 19:44:24 GMT mtk01461
609 **  Add OS_TIMESTAMP to packet
610 **  \main\maintrunk.MT5921\16 2007-11-21 15:47:20 GMT mtk01088
611 **  fixed the unload module issue
612 **  \main\maintrunk.MT5921\15 2007-11-07 18:37:38 GMT mtk01461
613 **  Fix compile warnning
614 **  \main\maintrunk.MT5921\14 2007-11-02 01:03:19 GMT mtk01461
615 **  Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning
616 **  \main\maintrunk.MT5921\13 2007-10-30 10:42:33 GMT mtk01425
617 **  1. Refine for multicast list
618 **  \main\maintrunk.MT5921\12 2007-10-25 18:08:13 GMT mtk01461
619 **  Add VOIP SCAN Support  & Refine Roaming
620 ** Revision 1.4  2007/07/05 07:25:33  MTK01461
621 ** Add Linux initial code, modify doc, add 11BB, RF init code
622 **
623 ** Revision 1.3  2007/06/27 02:18:50  MTK01461
624 ** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API
625 **
626 ** Revision 1.2  2007/06/25 06:16:24  MTK01461
627 ** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API
628 **
629 */
630
631 /*******************************************************************************
632 *                         C O M P I L E R   F L A G S
633 ********************************************************************************
634 */
635
636 /*******************************************************************************
637 *                    E X T E R N A L   R E F E R E N C E S
638 ********************************************************************************
639 */
640 #include "gl_os.h"
641 #include "debug.h"
642 #include "wlan_lib.h"
643 #include "gl_wext.h"
644 #include "gl_cfg80211.h"
645 #include "precomp.h"
646
647 #if defined(CONFIG_WIFI_CONTROL_FUNC)
648 #include <linux/platform_device.h>
649 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
650 #include <linux/wlan_plat.h>
651 #else
652 #include <linux/wifi_tiwlan.h>
653 #endif
654 #endif /* CONFIG_WIFI_CONTROL_FUNC */
655
656 /*******************************************************************************
657 *                              C O N S T A N T S
658 ********************************************************************************
659 */
660 //#define MAX_IOREQ_NUM   10
661 #if 1//def RK2818
662     int driver_start_ok = 0;
663 #endif
664
665 BOOLEAN fgIsUnderEarlierSuspend = false;
666
667 struct semaphore g_halt_sem;
668 int g_u4HaltFlag = 0;
669
670
671 /*******************************************************************************
672 *                             D A T A   T Y P E S
673 ********************************************************************************
674 */
675 /* Tasklet mechanism is like buttom-half in Linux. We just want to
676  * send a signal to OS for interrupt defer processing. All resources
677  * are NOT allowed reentry, so txPacket, ISR-DPC and ioctl must avoid preempty.
678  */
679 typedef struct _WLANDEV_INFO_T {
680     struct net_device *prDev;
681 } WLANDEV_INFO_T, *P_WLANDEV_INFO_T;
682
683 /*******************************************************************************
684 *                            P U B L I C   D A T A
685 ********************************************************************************
686 */
687
688 MODULE_AUTHOR(NIC_AUTHOR);
689 MODULE_DESCRIPTION(NIC_DESC);
690 MODULE_SUPPORTED_DEVICE(NIC_NAME);
691
692 /* WCNCR 00002676, 
693 keep OS wake up for 100ms after sdio interrupt happen,
694 make sure that RX & TX procedure isn't suspended
695 */
696 KAL_WAKE_LOCK_T isr_wakelock;
697
698 #if 0
699     MODULE_LICENSE("MTK Propietary");
700 #else
701     MODULE_LICENSE("GPL");
702 #endif
703
704 #define NIC_INF_NAME    "wlan%d" /* interface name */
705
706 #if DBG
707     UINT_8  aucDebugModule[DBG_MODULE_NUM];
708     UINT_32 u4DebugModule = 0;
709 #endif /* DBG */
710
711 //4 2007/06/26, mikewu, now we don't use this, we just fix the number of wlan device to 1
712 static WLANDEV_INFO_T arWlanDevInfo[CFG_MAX_WLAN_DEVICES] = {{0}};
713 static UINT_32 u4WlanDevNum = 0; /* How many NICs coexist now */
714
715 /*******************************************************************************
716 *                           P R I V A T E   D A T A
717 ********************************************************************************
718 */
719 #if CFG_ENABLE_WIFI_DIRECT
720 static SUB_MODULE_HANDLER rSubModHandler[SUB_MODULE_NUM] = {{NULL}};
721 #endif
722
723 #define CHAN2G(_channel, _freq, _flags)         \
724     {                                           \
725     .band               = IEEE80211_BAND_2GHZ,  \
726     .center_freq        = (_freq),              \
727     .hw_value           = (_channel),           \
728     .flags              = (_flags),             \
729     .max_antenna_gain   = 0,                    \
730     .max_power          = 30,                   \
731     }
732 static struct ieee80211_channel mtk_2ghz_channels[] = {
733     CHAN2G(1, 2412, 0),
734     CHAN2G(2, 2417, 0),
735     CHAN2G(3, 2422, 0),
736     CHAN2G(4, 2427, 0),
737     CHAN2G(5, 2432, 0),
738     CHAN2G(6, 2437, 0),
739     CHAN2G(7, 2442, 0),
740     CHAN2G(8, 2447, 0),
741     CHAN2G(9, 2452, 0),
742     CHAN2G(10, 2457, 0),
743     CHAN2G(11, 2462, 0),
744     CHAN2G(12, 2467, 0),
745     CHAN2G(13, 2472, 0),
746     CHAN2G(14, 2484, 0),
747 };
748
749 #define CHAN5G(_channel, _flags)                    \
750     {                                               \
751     .band               = IEEE80211_BAND_5GHZ,      \
752     .center_freq        = 5000 + (5 * (_channel)),  \
753     .hw_value           = (_channel),               \
754     .flags              = (_flags),                 \
755     .max_antenna_gain   = 0,                        \
756     .max_power          = 30,                       \
757     }
758 static struct ieee80211_channel mtk_5ghz_channels[] = {
759     CHAN5G(34, 0),      CHAN5G(36, 0),
760     CHAN5G(38, 0),      CHAN5G(40, 0),
761     CHAN5G(42, 0),      CHAN5G(44, 0),
762     CHAN5G(46, 0),      CHAN5G(48, 0),
763     CHAN5G(52, 0),      CHAN5G(56, 0),
764     CHAN5G(60, 0),      CHAN5G(64, 0),
765     CHAN5G(100, 0),     CHAN5G(104, 0),
766     CHAN5G(108, 0),     CHAN5G(112, 0),
767     CHAN5G(116, 0),     CHAN5G(120, 0),
768     CHAN5G(124, 0),     CHAN5G(128, 0),
769     CHAN5G(132, 0),     CHAN5G(136, 0),
770     CHAN5G(140, 0),     CHAN5G(149, 0),
771     CHAN5G(153, 0),     CHAN5G(157, 0),
772     CHAN5G(161, 0),     CHAN5G(165, 0),
773     CHAN5G(169, 0),     CHAN5G(173, 0),
774     CHAN5G(184, 0),     CHAN5G(188, 0),
775     CHAN5G(192, 0),     CHAN5G(196, 0),
776     CHAN5G(200, 0),     CHAN5G(204, 0),
777     CHAN5G(208, 0),     CHAN5G(212, 0),
778     CHAN5G(216, 0),
779 };
780
781 /* for cfg80211 - rate table */
782 static struct ieee80211_rate mtk_rates[] = {
783     RATETAB_ENT(10,   0x1000,   0),
784     RATETAB_ENT(20,   0x1001,   0),
785     RATETAB_ENT(55,   0x1002,   0),
786     RATETAB_ENT(110,  0x1003,   0), /* 802.11b */
787     RATETAB_ENT(60,   0x2000,   0),
788     RATETAB_ENT(90,   0x2001,   0),
789     RATETAB_ENT(120,  0x2002,   0),
790     RATETAB_ENT(180,  0x2003,   0),
791     RATETAB_ENT(240,  0x2004,   0),
792     RATETAB_ENT(360,  0x2005,   0),
793     RATETAB_ENT(480,  0x2006,   0),
794     RATETAB_ENT(540,  0x2007,   0), /* 802.11a/g */
795 };
796
797 #define mtk_a_rates         (mtk_rates + 4)
798 #define mtk_a_rates_size    (sizeof(mtk_rates) / sizeof(mtk_rates[0]) - 4)
799 #define mtk_g_rates         (mtk_rates + 0)
800 #define mtk_g_rates_size    (sizeof(mtk_rates) / sizeof(mtk_rates[0]) - 0)
801
802 #define MT6620_MCS_INFO                                 \
803 {                                                       \
804     .rx_mask        = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0},\
805     .rx_highest     = 0,                                \
806     .tx_params      = IEEE80211_HT_MCS_TX_DEFINED,      \
807 }
808
809 #define MT6620_HT_CAP                                   \
810 {                                                       \
811     .ht_supported   = true,                             \
812     .cap            = IEEE80211_HT_CAP_SUP_WIDTH_20_40  \
813                     | IEEE80211_HT_CAP_SM_PS            \
814                     | IEEE80211_HT_CAP_GRN_FLD          \
815                     | IEEE80211_HT_CAP_SGI_20           \
816                     | IEEE80211_HT_CAP_SGI_40,          \
817     .ampdu_factor   = IEEE80211_HT_MAX_AMPDU_64K,       \
818     .ampdu_density  = IEEE80211_HT_MPDU_DENSITY_NONE,   \
819     .mcs            = MT6620_MCS_INFO,                  \
820 }
821
822 /* public for both Legacy Wi-Fi / P2P access */
823 struct ieee80211_supported_band mtk_band_2ghz = {
824     .band       = IEEE80211_BAND_2GHZ,
825     .channels   = mtk_2ghz_channels,
826     .n_channels = ARRAY_SIZE(mtk_2ghz_channels),
827     .bitrates   = mtk_g_rates,
828     .n_bitrates = mtk_g_rates_size,
829     .ht_cap     = MT6620_HT_CAP,
830 };
831
832 /* public for both Legacy Wi-Fi / P2P access */
833 struct ieee80211_supported_band mtk_band_5ghz = {
834     .band       = IEEE80211_BAND_5GHZ,
835     .channels   = mtk_5ghz_channels,
836     .n_channels = ARRAY_SIZE(mtk_5ghz_channels),
837     .bitrates   = mtk_a_rates,
838     .n_bitrates = mtk_a_rates_size,
839     .ht_cap     = MT6620_HT_CAP,
840 };
841
842 static const UINT_32 mtk_cipher_suites[] = {
843     /* keep WEP first, it may be removed below */
844     WLAN_CIPHER_SUITE_WEP40,
845     WLAN_CIPHER_SUITE_WEP104,
846     WLAN_CIPHER_SUITE_TKIP,
847     WLAN_CIPHER_SUITE_CCMP,
848     
849     /* keep last -- depends on hw flags! */
850     WLAN_CIPHER_SUITE_AES_CMAC
851 };
852
853 static struct cfg80211_ops mtk_wlan_ops = {
854     .change_virtual_intf    = mtk_cfg80211_change_iface,
855     .add_key                = mtk_cfg80211_add_key,
856     .get_key                = mtk_cfg80211_get_key,
857     .del_key                = mtk_cfg80211_del_key,
858     .set_default_key        = mtk_cfg80211_set_default_key,
859     .get_station            = mtk_cfg80211_get_station,
860     .scan                   = mtk_cfg80211_scan,
861     .connect                = mtk_cfg80211_connect,
862     .disconnect             = mtk_cfg80211_disconnect,
863     .join_ibss              = mtk_cfg80211_join_ibss,
864     .leave_ibss             = mtk_cfg80211_leave_ibss,
865     .set_power_mgmt         = mtk_cfg80211_set_power_mgmt,
866     .set_pmksa              = mtk_cfg80211_set_pmksa,
867     .del_pmksa              = mtk_cfg80211_del_pmksa,
868     .flush_pmksa            = mtk_cfg80211_flush_pmksa,
869
870     /* Action Frame TX/RX */
871     .remain_on_channel          = mtk_cfg80211_remain_on_channel,
872     .cancel_remain_on_channel   = mtk_cfg80211_cancel_remain_on_channel,
873     .mgmt_tx                    = mtk_cfg80211_mgmt_tx,
874     .mgmt_tx_cancel_wait        = mtk_cfg80211_mgmt_tx_cancel_wait,
875     #ifdef CONFIG_NL80211_TESTMODE
876     .testmode_cmd               = mtk_cfg80211_testmode_cmd,
877     #endif
878 };
879
880 /*******************************************************************************
881 *                                 M A C R O S
882 ********************************************************************************
883 */
884
885 /*******************************************************************************
886 *                   F U N C T I O N   D E C L A R A T I O N S
887 ********************************************************************************
888 */
889
890 #if defined(CONFIG_HAS_EARLYSUSPEND)
891 extern int glRegisterEarlySuspend(
892     struct early_suspend        *prDesc,
893     early_suspend_callback      wlanSuspend,
894     late_resume_callback        wlanResume);
895
896 extern int glUnregisterEarlySuspend(struct early_suspend *prDesc);
897 #endif
898
899 /*******************************************************************************
900 *                              F U N C T I O N S
901 ********************************************************************************
902 */
903
904 /**
905  * Functions for Android WiFi card detection
906  */
907 #if defined(CONFIG_WIFI_CONTROL_FUNC)
908
909 static int g_wifidev_registered = 0;
910 static struct semaphore wifi_control_sem;
911 static struct wifi_platform_data *wifi_control_data = NULL;
912 static struct resource *wifi_irqres = NULL;
913
914 static int wifi_add_dev(void);
915 static void wifi_del_dev(void);
916
917 #define ANDROID_ERR(x) printk x
918 #define ANDROID_TRACE(x) printk x
919
920 int wl_android_wifictrl_func_add(void)
921 {
922         int ret = 0;
923         sema_init(&wifi_control_sem, 0);
924
925         ret = wifi_add_dev();
926         if (ret) {
927                 ANDROID_ERR(("%s: platform_driver_register failed\n", __FUNCTION__));
928                 return ret;
929         }
930         g_wifidev_registered = 1;
931
932         /* Waiting callback after platform_driver_register is done or exit with error */
933         if (down_timeout(&wifi_control_sem,  msecs_to_jiffies(1000)) != 0) {
934                 ret = -EINVAL;
935                 ANDROID_ERR(("%s: platform_driver_register timeout\n", __FUNCTION__));
936         }
937
938         printk("wl_android_wifictrl_func_add success.\n");
939         return ret;
940 }
941
942 void wl_android_wifictrl_func_del(void)
943 {
944         if (g_wifidev_registered)
945         {
946                 wifi_del_dev();
947                 g_wifidev_registered = 0;
948         }
949 }
950
951 int wifi_set_power(int on, unsigned long msec)
952 {
953         ANDROID_ERR(("%s = %d\n", __FUNCTION__, on));
954         if (wifi_control_data && wifi_control_data->set_power) {
955                 wifi_control_data->set_power(on);
956         }
957         if (msec)
958                 msleep(msec);
959         return 0;
960 }
961
962 int wifi_set_reset(int on, unsigned long msec)
963 {
964         ANDROID_ERR(("%s = %d\n", __FUNCTION__, on));
965         if (wifi_control_data && wifi_control_data->set_reset) {
966                 wifi_control_data->set_reset(on);
967         }
968         if (msec)
969                 msleep(msec);
970         return 0;
971 }
972
973 static int wifi_set_carddetect(int on)
974 {
975         ANDROID_ERR(("%s = %d\n", __FUNCTION__, on));
976         if (wifi_control_data && wifi_control_data->set_carddetect) {
977                 wifi_control_data->set_carddetect(on);
978         }
979         return 0;
980 }
981
982 static int wifi_probe(struct platform_device *pdev)
983 {
984         struct wifi_platform_data *wifi_ctrl =
985                 (struct wifi_platform_data *)(pdev->dev.platform_data);
986
987         ANDROID_ERR(("## %s\n", __FUNCTION__));
988         wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
989         if (wifi_irqres == NULL)
990                 wifi_irqres = platform_get_resource_byname(pdev,
991                         IORESOURCE_IRQ, "bcm4329_wlan_irq");
992         wifi_control_data = wifi_ctrl;
993
994         //wifi_set_power(0, 0);
995         //wifi_set_reset(0, 10);
996
997         wifi_set_power(1, 0);
998         //wifi_set_reset(1, 12);        /* Power On */
999         
1000         wifi_set_carddetect(1); /* CardDetect (0->1) */
1001
1002         up(&wifi_control_sem);
1003         return 0;
1004 }
1005
1006 static int wifi_remove(struct platform_device *pdev)
1007 {
1008         struct wifi_platform_data *wifi_ctrl =
1009                 (struct wifi_platform_data *)(pdev->dev.platform_data);
1010
1011         ANDROID_ERR(("## %s\n", __FUNCTION__));
1012         wifi_control_data = wifi_ctrl;
1013
1014         wifi_set_power(0, 0);   /* Power Off */
1015         //wifi_set_reset(0, 0);
1016         
1017         wifi_set_carddetect(0); /* CardDetect (1->0) */
1018
1019         return 0;
1020 }
1021
1022 static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
1023 {
1024         ANDROID_TRACE(("##> %s\n", __FUNCTION__));
1025         return 0;
1026 }
1027
1028 static int wifi_resume(struct platform_device *pdev)
1029 {
1030         ANDROID_TRACE(("##> %s\n", __FUNCTION__));
1031         return 0;
1032 }
1033
1034 static struct platform_driver wifi_device = {
1035         .probe          = wifi_probe,
1036         .remove         = wifi_remove,
1037         .suspend        = wifi_suspend,
1038         .resume         = wifi_resume,
1039         .driver         = {
1040         .name   = "bcmdhd_wlan",
1041         }
1042 };
1043
1044 static struct platform_driver wifi_device_legacy = {
1045         .probe          = wifi_probe,
1046         .remove         = wifi_remove,
1047         .suspend        = wifi_suspend,
1048         .resume         = wifi_resume,
1049         .driver         = {
1050         .name   = "bcm4329_wlan",
1051         }
1052 };
1053
1054 static int wifi_add_dev(void)
1055 {
1056         ANDROID_TRACE(("## Calling platform_driver_register\n"));
1057         platform_driver_register(&wifi_device);
1058         platform_driver_register(&wifi_device_legacy);
1059         return 0;
1060 }
1061
1062 static void wifi_del_dev(void)
1063 {
1064         ANDROID_TRACE(("## Unregister platform_driver_register\n"));
1065         platform_driver_unregister(&wifi_device);
1066         platform_driver_unregister(&wifi_device_legacy);
1067 }
1068 #endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */
1069
1070 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
1071 /*----------------------------------------------------------------------------*/
1072 /*!
1073 * \brief Override the implementation of select queue
1074 *
1075 * \param[in] dev Pointer to struct net_device
1076 * \param[in] skb Pointer to struct skb_buff
1077 *
1078 * \return (none)
1079 */
1080 /*----------------------------------------------------------------------------*/
1081 unsigned int _cfg80211_classify8021d(struct sk_buff *skb)
1082 {
1083     unsigned int dscp = 0;
1084
1085     /* skb->priority values from 256->263 are magic values
1086      * directly indicate a specific 802.1d priority.  This is
1087      * to allow 802.1d priority to be passed directly in from
1088      * tags
1089      */
1090
1091     if (skb->priority >= 256 && skb->priority <= 263) {
1092         return skb->priority - 256;
1093     }
1094     switch (skb->protocol) {
1095         case htons(ETH_P_IP):
1096             dscp = ip_hdr(skb)->tos & 0xfc;
1097             break;
1098     }
1099     return dscp >> 5;
1100 }
1101
1102
1103 static const UINT_16 au16Wlan1dToQueueIdx[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
1104
1105 static UINT_16
1106 wlanSelectQueue(
1107     struct net_device *dev,
1108     struct sk_buff *skb)
1109 {
1110     skb->priority = _cfg80211_classify8021d(skb);
1111
1112     return au16Wlan1dToQueueIdx[skb->priority];
1113 }
1114 #endif
1115
1116
1117 /*----------------------------------------------------------------------------*/
1118 /*!
1119 * \brief Load NVRAM data and translate it into REG_INFO_T
1120 *
1121 * \param[in]  prGlueInfo Pointer to struct GLUE_INFO_T
1122 * \param[out] prRegInfo  Pointer to struct REG_INFO_T
1123 *
1124 * \return (none)
1125 */
1126 /*----------------------------------------------------------------------------*/
1127 static void
1128 glLoadNvram (
1129     IN  P_GLUE_INFO_T   prGlueInfo,
1130     OUT P_REG_INFO_T    prRegInfo
1131     )
1132 {
1133     UINT_32 i, j;
1134     UINT_8 aucTmp[2];
1135     PUINT_8 pucDest;
1136
1137     ASSERT(prGlueInfo);
1138     ASSERT(prRegInfo);
1139
1140     if((!prGlueInfo) || (!prRegInfo)) {
1141         return;
1142     }
1143
1144     if(kalCfgDataRead16(prGlueInfo,
1145             sizeof(WIFI_CFG_PARAM_STRUCT) - sizeof(UINT_16),
1146             (PUINT_16)aucTmp) == TRUE) {
1147         prGlueInfo->fgNvramAvailable = TRUE;
1148
1149         // load MAC Address
1150         for (i = 0 ; i < sizeof(PARAM_MAC_ADDR_LEN) ; i += sizeof(UINT_16)) {
1151             kalCfgDataRead16(prGlueInfo,
1152                     OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucMacAddress) + i,
1153                     (PUINT_16) (((PUINT_8)prRegInfo->aucMacAddr) + i));
1154         }
1155
1156         // load country code
1157         kalCfgDataRead16(prGlueInfo,
1158                 OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucCountryCode[0]),
1159                     (PUINT_16)aucTmp);
1160
1161         // cast to wide characters
1162         prRegInfo->au2CountryCode[0] = (UINT_16) aucTmp[0];
1163         prRegInfo->au2CountryCode[1] = (UINT_16) aucTmp[1];
1164
1165         // load default normal TX power
1166         for (i = 0 ; i < sizeof(TX_PWR_PARAM_T) ; i += sizeof(UINT_16)) {
1167             kalCfgDataRead16(prGlueInfo,
1168                     OFFSET_OF(WIFI_CFG_PARAM_STRUCT, rTxPwr) + i,
1169                     (PUINT_16) (((PUINT_8)&(prRegInfo->rTxPwr)) + i));
1170         }
1171
1172         // load feature flags
1173         kalCfgDataRead16(prGlueInfo,
1174                 OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucTxPwrValid),
1175                 (PUINT_16)aucTmp);
1176         prRegInfo->ucTxPwrValid     = aucTmp[0];
1177         prRegInfo->ucSupport5GBand  = aucTmp[1];
1178
1179         kalCfgDataRead16(prGlueInfo,
1180                 OFFSET_OF(WIFI_CFG_PARAM_STRUCT, uc2G4BwFixed20M),
1181                 (PUINT_16)aucTmp);
1182         prRegInfo->uc2G4BwFixed20M  = aucTmp[0];
1183         prRegInfo->uc5GBwFixed20M   = aucTmp[1];
1184
1185         kalCfgDataRead16(prGlueInfo,
1186                 OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucEnable5GBand),
1187                 (PUINT_16)aucTmp);
1188         prRegInfo->ucEnable5GBand   = aucTmp[0];
1189
1190         /* load EFUSE overriding part */
1191         for (i = 0 ; i < sizeof(prRegInfo->aucEFUSE) ; i += sizeof(UINT_16)) {
1192             kalCfgDataRead16(prGlueInfo,
1193                     OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucEFUSE) + i,
1194                     (PUINT_16) (((PUINT_8)&(prRegInfo->aucEFUSE)) + i));
1195         }
1196
1197         /* load band edge tx power control */
1198         kalCfgDataRead16(prGlueInfo,
1199                 OFFSET_OF(WIFI_CFG_PARAM_STRUCT, fg2G4BandEdgePwrUsed),
1200                 (PUINT_16)aucTmp);
1201         prRegInfo->fg2G4BandEdgePwrUsed = (BOOLEAN)aucTmp[0];
1202         if (aucTmp[0]) {
1203             prRegInfo->cBandEdgeMaxPwrCCK   = (INT_8)aucTmp[1];
1204
1205             kalCfgDataRead16(prGlueInfo,
1206                     OFFSET_OF(WIFI_CFG_PARAM_STRUCT, cBandEdgeMaxPwrOFDM20),
1207                     (PUINT_16)aucTmp);
1208             prRegInfo->cBandEdgeMaxPwrOFDM20    = (INT_8)aucTmp[0];
1209             prRegInfo->cBandEdgeMaxPwrOFDM40    = (INT_8)aucTmp[1];
1210         }
1211
1212         /* load regulation subbands */
1213         kalCfgDataRead16(prGlueInfo,
1214                 OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucRegChannelListMap),
1215                 (PUINT_16)aucTmp);
1216         prRegInfo->eRegChannelListMap = (ENUM_REG_CH_MAP_T) aucTmp[0];
1217         prRegInfo->ucRegChannelListIndex = aucTmp[1];
1218
1219         if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) {
1220             for (i = 0 ; i < MAX_SUBBAND_NUM; i++) {
1221                 pucDest = (PUINT_8) &prRegInfo->rDomainInfo.rSubBand[i];
1222                 for (j = 0; j < 6; j += sizeof(UINT_16)) {
1223                     kalCfgDataRead16(prGlueInfo,
1224                             OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucRegSubbandInfo)
1225                             + (i * 6 + j),
1226                             (PUINT_16)aucTmp);
1227
1228                     *pucDest++ = aucTmp[0];
1229                     *pucDest++ = aucTmp[1];
1230                 }
1231             }
1232         }
1233     }
1234     else {
1235         prGlueInfo->fgNvramAvailable = FALSE;
1236     }
1237
1238     return;
1239 }
1240
1241
1242 #if CFG_ENABLE_WIFI_DIRECT
1243 /*----------------------------------------------------------------------------*/
1244 /*!
1245 * \brief called by txthread, run sub module init function
1246 *
1247 * \param[in]  prGlueInfo Pointer to struct GLUE_INFO_T
1248 *
1249 * \return (none)
1250 */
1251 /*----------------------------------------------------------------------------*/
1252 VOID
1253 wlanSubModRunInit(
1254     P_GLUE_INFO_T prGlueInfo
1255     )
1256 {
1257     /*now, we only have p2p module*/
1258     if(rSubModHandler[P2P_MODULE].fgIsInited == FALSE) {
1259         rSubModHandler[P2P_MODULE].subModInit(prGlueInfo);
1260         rSubModHandler[P2P_MODULE].fgIsInited = TRUE;
1261     }
1262
1263 }
1264
1265 /*----------------------------------------------------------------------------*/
1266 /*!
1267 * \brief called by txthread, run sub module exit function
1268 *
1269 * \param[in]  prGlueInfo Pointer to struct GLUE_INFO_T
1270 *
1271 * \return (none)
1272 */
1273 /*----------------------------------------------------------------------------*/
1274 VOID
1275 wlanSubModRunExit(
1276     P_GLUE_INFO_T prGlueInfo
1277     )
1278 {
1279     /*now, we only have p2p module*/
1280     if(rSubModHandler[P2P_MODULE].fgIsInited == TRUE) {
1281         rSubModHandler[P2P_MODULE].subModExit(prGlueInfo);
1282         rSubModHandler[P2P_MODULE].fgIsInited = FALSE;
1283     }
1284 }
1285
1286 /*----------------------------------------------------------------------------*/
1287 /*!
1288 * \brief set sub module init flag, force TxThread to run sub modle init
1289 *
1290 * \param[in]  prGlueInfo Pointer to struct GLUE_INFO_T
1291 *
1292 * \return (none)
1293 */
1294 /*----------------------------------------------------------------------------*/
1295 BOOLEAN
1296 wlanSubModInit(
1297     P_GLUE_INFO_T prGlueInfo
1298     )
1299 {
1300     //4  Mark HALT, notify main thread to finish current job
1301     prGlueInfo->u4Flag |= GLUE_FLAG_SUB_MOD_INIT;
1302     /* wake up main thread */
1303     wake_up_interruptible(&prGlueInfo->waitq);
1304     /* wait main thread  finish sub module INIT*/
1305     wait_for_completion_interruptible(&prGlueInfo->rSubModComp);
1306
1307 #if 0
1308     if(prGlueInfo->prAdapter->fgIsP2PRegistered) {
1309         p2pNetRegister(prGlueInfo);
1310     }
1311 #endif
1312
1313     return TRUE;
1314 }
1315
1316 /*----------------------------------------------------------------------------*/
1317 /*!
1318 * \brief set sub module exit flag, force TxThread to run sub modle exit
1319 *
1320 * \param[in]  prGlueInfo Pointer to struct GLUE_INFO_T
1321 *
1322 * \return (none)
1323 */
1324 /*----------------------------------------------------------------------------*/
1325 BOOLEAN
1326 wlanSubModExit(
1327     P_GLUE_INFO_T prGlueInfo
1328     )
1329 {
1330 #if 0
1331     if(prGlueInfo->prAdapter->fgIsP2PRegistered) {
1332         p2pNetUnregister(prGlueInfo);
1333     }
1334 #endif
1335
1336     //4  Mark HALT, notify main thread to finish current job
1337     prGlueInfo->u4Flag |= GLUE_FLAG_SUB_MOD_EXIT;
1338     /* wake up main thread */
1339     wake_up_interruptible(&prGlueInfo->waitq);
1340     /* wait main thread finish sub module EXIT */
1341     wait_for_completion_interruptible(&prGlueInfo->rSubModComp);
1342
1343     return TRUE;
1344 }
1345
1346
1347 /*----------------------------------------------------------------------------*/
1348 /*!
1349 * \brief set by sub module, indicate sub module is already inserted
1350 *
1351 * \param[in]  rSubModInit, function pointer point to sub module init function
1352 * \param[in]  rSubModExit,  function pointer point to sub module exit function
1353 * \param[in]  eSubModIdx,  sub module index
1354 *
1355 * \return (none)
1356 */
1357 /*----------------------------------------------------------------------------*/
1358 VOID
1359 wlanSubModRegisterInitExit(
1360     SUB_MODULE_INIT rSubModInit,
1361     SUB_MODULE_EXIT rSubModExit,
1362     ENUM_SUB_MODULE_IDX_T eSubModIdx
1363     )
1364 {
1365     rSubModHandler[eSubModIdx].subModInit = rSubModInit;
1366     rSubModHandler[eSubModIdx].subModExit = rSubModExit;
1367     rSubModHandler[eSubModIdx].fgIsInited = FALSE;
1368 }
1369
1370 #if 0
1371 /*----------------------------------------------------------------------------*/
1372 /*!
1373 * \brief check wlan is launched or not
1374 *
1375 * \param[in]  (none)
1376 *
1377 * \return TRUE, wlan is already started
1378 *             FALSE, wlan is not started yet
1379 */
1380 /*----------------------------------------------------------------------------*/
1381 BOOLEAN
1382 wlanIsLaunched(
1383     VOID
1384     )
1385 {
1386     struct net_device *prDev = NULL;
1387     P_GLUE_INFO_T prGlueInfo = NULL;
1388
1389     //4 <0> Sanity check
1390     ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES);
1391     if (0 == u4WlanDevNum) {
1392         return FALSE;
1393     }
1394
1395     prDev = arWlanDevInfo[u4WlanDevNum-1].prDev;
1396
1397     ASSERT(prDev);
1398     if (NULL == prDev) {
1399         return FALSE;
1400     }
1401
1402     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
1403     ASSERT(prGlueInfo);
1404     if (NULL == prGlueInfo) {
1405         return FALSE;
1406     }
1407
1408     return prGlueInfo->prAdapter->fgIsWlanLaunched;
1409 }
1410
1411 #endif
1412
1413 /*----------------------------------------------------------------------------*/
1414 /*!
1415 * \brief Export wlan GLUE_INFO_T pointer to p2p module
1416 *
1417 * \param[in]  prGlueInfo Pointer to struct GLUE_INFO_T
1418 *
1419 * \return TRUE: get GlueInfo pointer successfully
1420 *            FALSE: wlan is not started yet
1421 */
1422 /*---------------------------------------------------------------------------*/
1423 BOOLEAN
1424 wlanExportGlueInfo(
1425     P_GLUE_INFO_T *prGlueInfoExpAddr
1426     )
1427 {
1428     struct net_device *prDev = NULL;
1429     P_GLUE_INFO_T prGlueInfo = NULL;
1430
1431     if (0 == u4WlanDevNum) {
1432         return FALSE;
1433     }
1434
1435     prDev = arWlanDevInfo[u4WlanDevNum-1].prDev;
1436     if (NULL == prDev) {
1437         return FALSE;
1438     }
1439
1440     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
1441     if (NULL == prGlueInfo) {
1442         return FALSE;
1443     }
1444
1445     if(FALSE == prGlueInfo->prAdapter->fgIsWlanLaunched) {
1446         return FALSE;
1447     }
1448
1449     *prGlueInfoExpAddr = prGlueInfo;
1450     return TRUE;
1451 }
1452
1453 #endif
1454
1455
1456 /*----------------------------------------------------------------------------*/
1457 /*!
1458 * \brief Release prDev from wlandev_array and free tasklet object related to it.
1459 *
1460 * \param[in] prDev  Pointer to struct net_device
1461 *
1462 * \return (none)
1463 */
1464 /*----------------------------------------------------------------------------*/
1465 static void
1466 wlanClearDevIdx (
1467     struct net_device *prDev
1468     )
1469 {
1470     int i;
1471
1472     ASSERT(prDev);
1473
1474     for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) {
1475         if (arWlanDevInfo[i].prDev == prDev) {
1476             arWlanDevInfo[i].prDev = NULL;
1477             u4WlanDevNum--;
1478         }
1479     }
1480
1481     return;
1482 } /* end of wlanClearDevIdx() */
1483
1484
1485 /*----------------------------------------------------------------------------*/
1486 /*!
1487 * \brief Allocate an unique interface index, net_device::ifindex member for this
1488 *        wlan device. Store the net_device in wlandev_array, and initialize
1489 *        tasklet object related to it.
1490 *
1491 * \param[in] prDev  Pointer to struct net_device
1492 *
1493 * \retval >= 0      The device number.
1494 * \retval -1        Fail to get index.
1495 */
1496 /*----------------------------------------------------------------------------*/
1497 static int
1498 wlanGetDevIdx (
1499     struct net_device *prDev
1500     )
1501 {
1502     int i;
1503
1504     ASSERT(prDev);
1505
1506     for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) {
1507         if (arWlanDevInfo[i].prDev == (struct net_device *) NULL) {
1508             /* Reserve 2 bytes space to store one digit of
1509              * device number and NULL terminator.
1510              */
1511             arWlanDevInfo[i].prDev = prDev;
1512             u4WlanDevNum++;
1513             return i;
1514         }
1515     }
1516
1517     return -1;
1518 } /* end of wlanGetDevIdx() */
1519
1520 /*----------------------------------------------------------------------------*/
1521 /*!
1522 * \brief A method of struct net_device, a primary SOCKET interface to configure
1523 *        the interface lively. Handle an ioctl call on one of our devices.
1524 *        Everything Linux ioctl specific is done here. Then we pass the contents
1525 *        of the ifr->data to the request message handler.
1526 *
1527 * \param[in] prDev      Linux kernel netdevice
1528 *
1529 * \param[in] prIFReq    Our private ioctl request structure, typed for the generic
1530 *                       struct ifreq so we can use ptr to function
1531 *
1532 * \param[in] cmd        Command ID
1533 *
1534 * \retval WLAN_STATUS_SUCCESS The IOCTL command is executed successfully.
1535 * \retval OTHER The execution of IOCTL command is failed.
1536 */
1537 /*----------------------------------------------------------------------------*/
1538 int
1539 wlanDoIOCTL(
1540     struct net_device *prDev,
1541     struct ifreq *prIFReq,
1542     int i4Cmd
1543     )
1544 {
1545     P_GLUE_INFO_T prGlueInfo = NULL;
1546     int ret = 0;
1547
1548     /* Verify input parameters for the following functions */
1549     ASSERT(prDev && prIFReq);
1550     if (!prDev || !prIFReq) {
1551         DBGLOG(INIT, WARN, ("%s Invalid input data\n", __FUNCTION__));
1552         return -EINVAL;
1553     }
1554
1555     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
1556     ASSERT(prGlueInfo);
1557     if (!prGlueInfo) {
1558         DBGLOG(INIT, WARN, ("%s No glue info\n", __FUNCTION__));
1559         return -EFAULT;
1560     }
1561
1562     if (prGlueInfo->u4ReadyFlag == 0) {
1563         return -EINVAL;
1564     }
1565
1566     printk ("ioctl %x\n", i4Cmd);
1567
1568     if (i4Cmd == SIOCGIWPRIV) {
1569         /* 0x8B0D, get private ioctl table */
1570         ret = wext_get_priv(prDev, prIFReq);
1571     }
1572     else if ((i4Cmd >= SIOCIWFIRST) && (i4Cmd < SIOCIWFIRSTPRIV)) {
1573         /* 0x8B00 ~ 0x8BDF, wireless extension region */
1574         ret = wext_support_ioctl(prDev, prIFReq, i4Cmd);
1575     }
1576     else if ((i4Cmd >= SIOCIWFIRSTPRIV) && (i4Cmd < SIOCIWLASTPRIV)) {
1577         /* 0x8BE0 ~ 0x8BFF, private ioctl region */
1578         ret = priv_support_ioctl(prDev, prIFReq, i4Cmd);
1579     }
1580     else {
1581         DBGLOG(INIT, WARN, ("Unexpected ioctl command: 0x%04x\n", i4Cmd));
1582         /* return 0 for safe? */
1583     }
1584
1585     return ret;
1586 } /* end of wlanDoIOCTL() */
1587
1588 /*----------------------------------------------------------------------------*/
1589 /*!
1590 * \brief This function is to set multicast list and set rx mode.
1591 *
1592 * \param[in] prDev  Pointer to struct net_device
1593 *
1594 * \return (none)
1595 */
1596 /*----------------------------------------------------------------------------*/
1597
1598 static struct delayed_work workq;
1599 static struct net_device *gPrDev;
1600
1601 static void
1602 wlanSetMulticastList (struct net_device *prDev)
1603 {
1604     gPrDev = prDev;
1605     schedule_delayed_work(&workq, 0);
1606 }
1607
1608 /* FIXME: Since we cannot sleep in the wlanSetMulticastList, we arrange
1609  * another workqueue for sleeping. We don't want to block
1610  * tx_thread, so we can't let tx_thread to do this */
1611
1612 static void
1613 wlanSetMulticastListWorkQueue (struct work_struct *work) {
1614
1615     P_GLUE_INFO_T prGlueInfo = NULL;
1616     UINT_32 u4PacketFilter = 0;
1617     UINT_32 u4SetInfoLen;
1618     struct net_device *prDev = gPrDev;
1619
1620     down(&g_halt_sem);
1621     if (g_u4HaltFlag) {
1622         up(&g_halt_sem);
1623         return;
1624     }
1625
1626     prGlueInfo = (NULL != prDev) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL;
1627     ASSERT(prDev);
1628     ASSERT(prGlueInfo);
1629     if (!prDev || !prGlueInfo) {
1630         DBGLOG(INIT, WARN, ("abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n",
1631             prDev, prGlueInfo));
1632         up(&g_halt_sem);
1633         return;
1634     }
1635
1636     if (prDev->flags & IFF_PROMISC) {
1637         u4PacketFilter |= PARAM_PACKET_FILTER_PROMISCUOUS;
1638     }
1639
1640     if (prDev->flags & IFF_BROADCAST) {
1641         u4PacketFilter |= PARAM_PACKET_FILTER_BROADCAST;
1642     }
1643
1644     if (prDev->flags & IFF_MULTICAST) {
1645         if ((prDev->flags & IFF_ALLMULTI) ||
1646 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
1647             (netdev_mc_count(prDev) > MAX_NUM_GROUP_ADDR)) {
1648 #else
1649             (prDev->mc_count > MAX_NUM_GROUP_ADDR)) {
1650 #endif
1651
1652             u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST;
1653         }
1654         else {
1655             u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST;
1656         }
1657     }
1658
1659     up(&g_halt_sem);
1660
1661     if (kalIoctl(prGlueInfo,
1662             wlanoidSetCurrentPacketFilter,
1663             &u4PacketFilter,
1664             sizeof(u4PacketFilter),
1665             FALSE,
1666             FALSE,
1667             TRUE,
1668             FALSE,
1669             &u4SetInfoLen) != WLAN_STATUS_SUCCESS) {
1670         return;
1671     }
1672
1673
1674     if (u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) {
1675         /* Prepare multicast address list */
1676 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
1677         struct netdev_hw_addr *ha;
1678 #else
1679         struct dev_mc_list *prMcList;
1680 #endif
1681         PUINT_8 prMCAddrList = NULL;
1682         UINT_32 i = 0;
1683
1684         down(&g_halt_sem);
1685         if (g_u4HaltFlag) {
1686             up(&g_halt_sem);
1687             return;
1688         }
1689
1690         prMCAddrList = kalMemAlloc(MAX_NUM_GROUP_ADDR * ETH_ALEN, VIR_MEM_TYPE);
1691
1692 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
1693         netdev_for_each_mc_addr(ha, prDev) {
1694             if(i < MAX_NUM_GROUP_ADDR) {
1695                 memcpy((prMCAddrList + i * ETH_ALEN), ha->addr, ETH_ALEN);
1696                 i++;
1697             }
1698         }
1699 #else
1700         for (i = 0, prMcList = prDev->mc_list;
1701              (prMcList) && (i < prDev->mc_count) && (i < MAX_NUM_GROUP_ADDR);
1702              i++, prMcList = prMcList->next) {
1703             memcpy((prMCAddrList + i * ETH_ALEN), prMcList->dmi_addr, ETH_ALEN);
1704         }
1705 #endif
1706
1707         up(&g_halt_sem);
1708
1709         kalIoctl(prGlueInfo,
1710             wlanoidSetMulticastList,
1711             prMCAddrList,
1712             (i * ETH_ALEN),
1713             FALSE,
1714             FALSE,
1715             TRUE,
1716             FALSE,
1717             &u4SetInfoLen);
1718
1719         kalMemFree(prMCAddrList, VIR_MEM_TYPE, MAX_NUM_GROUP_ADDR * ETH_ALEN);
1720     }
1721
1722     return;
1723 } /* end of wlanSetMulticastList() */
1724
1725
1726 /* FIXME: Since we cannot sleep in the wlanSetMulticastList, we arrange
1727  * another workqueue for sleeping. We don't want to block
1728  * tx_thread, so we can't let tx_thread to do this */
1729
1730 void
1731 p2pSetMulticastListWorkQueueWrapper (P_GLUE_INFO_T prGlueInfo) {
1732
1733     ASSERT(prGlueInfo);
1734
1735     if (!prGlueInfo) {
1736         DBGLOG(INIT, WARN, ("abnormal dev or skb: prGlueInfo(0x%p)\n",
1737             prGlueInfo));
1738         return;
1739     }
1740
1741 #if CFG_ENABLE_WIFI_DIRECT
1742     if(prGlueInfo->prAdapter->fgIsP2PRegistered) {
1743         mtk_p2p_wext_set_Multicastlist(prGlueInfo);
1744     }
1745 #endif
1746
1747     return;
1748 } /* end of p2pSetMulticastListWorkQueueWrapper() */
1749
1750
1751
1752 /*----------------------------------------------------------------------------*/
1753 /*!
1754 * \brief This function is TX entry point of NET DEVICE.
1755 *
1756 * \param[in] prSkb  Pointer of the sk_buff to be sent
1757 * \param[in] prDev  Pointer to struct net_device
1758 *
1759 * \retval NETDEV_TX_OK - on success.
1760 * \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer.
1761 */
1762 /*----------------------------------------------------------------------------*/
1763 int
1764 wlanHardStartXmit(
1765     struct sk_buff *prSkb,
1766     struct net_device *prDev
1767     )
1768 {
1769     P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
1770
1771     P_QUE_ENTRY_T prQueueEntry = NULL;
1772     P_QUE_T prTxQueue = NULL;
1773     UINT_16 u2QueueIdx = 0;
1774
1775 #if CFG_BOW_TEST
1776     UINT_32 i;
1777 #endif
1778
1779     GLUE_SPIN_LOCK_DECLARATION();
1780
1781     ASSERT(prSkb);
1782     ASSERT(prDev);
1783     ASSERT(prGlueInfo);
1784
1785     if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
1786         DBGLOG(INIT, INFO, ("GLUE_FLAG_HALT skip tx\n"));
1787         dev_kfree_skb(prSkb);
1788         return NETDEV_TX_OK;
1789     }
1790
1791     prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb);
1792     prTxQueue = &prGlueInfo->rTxQueue;
1793
1794 #if CFG_BOW_TEST
1795     DBGLOG(BOW, TRACE, ("sk_buff->len: %d\n", prSkb->len));
1796     DBGLOG(BOW, TRACE, ("sk_buff->data_len: %d\n", prSkb->data_len));
1797     DBGLOG(BOW, TRACE, ("sk_buff->data:\n"));
1798
1799     for(i = 0; i < prSkb->len && i < 64; i++)
1800     {
1801         LOG_FUNC("%02x ", prSkb->data[i]);
1802
1803         if((i+1)%16 ==0)
1804         {
1805             LOG_FUNC("\n");
1806         }
1807     }
1808
1809     LOG_FUNC("\n");
1810 #endif
1811
1812     if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb) == FALSE) {
1813
1814     #if CFG_DBG_GPIO_PINS
1815         {
1816             /* TX request from OS */
1817             mtk_wcn_stp_debug_gpio_assert(IDX_TX_REQ, DBG_TIE_LOW);
1818             kalUdelay(1);
1819             mtk_wcn_stp_debug_gpio_assert(IDX_TX_REQ, DBG_TIE_HIGH);
1820         }
1821     #endif
1822
1823 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
1824         u2QueueIdx = skb_get_queue_mapping(prSkb);
1825         ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM);
1826 #endif
1827
1828         GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE);
1829         QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry);
1830         GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE);
1831
1832         GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum);
1833         GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx]);
1834
1835 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
1836         if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx] >= CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) {
1837             netif_stop_subqueue(prDev, u2QueueIdx);
1838         }
1839 #else
1840         if (prGlueInfo->i4TxPendingFrameNum >= CFG_TX_STOP_NETIF_QUEUE_THRESHOLD) {
1841             netif_stop_queue(prDev);
1842         }
1843 #endif
1844     } else {
1845         //printk("is security frame\n");
1846
1847         GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum);
1848     }
1849
1850     DBGLOG(TX, EVENT, ("\n+++++ pending frame %d len = %d +++++\n", prGlueInfo->i4TxPendingFrameNum, prSkb->len));
1851     prGlueInfo->rNetDevStats.tx_bytes += prSkb->len;
1852     prGlueInfo->rNetDevStats.tx_packets++;
1853
1854     //pr->u4Flag |= GLUE_FLAG_TXREQ;
1855     //wake_up_interruptible(&prGlueInfo->waitq);
1856     kalSetEvent(prGlueInfo);
1857
1858
1859     /* For Linux, we'll always return OK FLAG, because we'll free this skb by ourself */
1860     return NETDEV_TX_OK;
1861 } /* end of wlanHardStartXmit() */
1862
1863
1864 /*----------------------------------------------------------------------------*/
1865 /*!
1866 * \brief A method of struct net_device, to get the network interface statistical
1867 *        information.
1868 *
1869 * Whenever an application needs to get statistics for the interface, this method
1870 * is called. This happens, for example, when ifconfig or netstat -i is run.
1871 *
1872 * \param[in] prDev      Pointer to struct net_device.
1873 *
1874 * \return net_device_stats buffer pointer.
1875 */
1876 /*----------------------------------------------------------------------------*/
1877 struct net_device_stats *
1878 wlanGetStats (
1879     IN struct net_device *prDev
1880     )
1881 {
1882     P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
1883
1884     #if 0
1885     WLAN_STATUS rStatus;
1886     UINT_32 u4XmitError = 0;
1887     UINT_32 u4XmitOk = 0;
1888     UINT_32 u4RecvError = 0;
1889     UINT_32 u4RecvOk = 0;
1890     UINT_32 u4BufLen;
1891
1892     ASSERT(prDev);
1893
1894     /* @FIX ME: need a more clear way to do this */
1895
1896
1897     rStatus = kalIoctl(prGlueInfo,
1898             wlanoidQueryXmitError,
1899             &u4XmitError,
1900             sizeof(UINT_32),
1901             TRUE,
1902             TRUE,
1903             TRUE,
1904                          &u4BufLen);
1905
1906     rStatus = kalIoctl(prGlueInfo,
1907             wlanoidQueryXmitOk,
1908             &u4XmitOk,
1909             sizeof(UINT_32),
1910             TRUE,
1911             TRUE,
1912             TRUE,
1913             &u4BufLen);
1914     rStatus = kalIoctl(prGlueInfo,
1915             wlanoidQueryRcvOk,
1916             &u4RecvOk,
1917             sizeof(UINT_32),
1918             TRUE,
1919             TRUE,
1920             TRUE,
1921             &u4BufLen);
1922     rStatus = kalIoctl(prGlueInfo,
1923             wlanoidQueryRcvError,
1924             &u4RecvError,
1925             sizeof(UINT_32),
1926             TRUE,
1927             TRUE,
1928             TRUE,
1929             &u4BufLen);
1930     prGlueInfo->rNetDevStats.rx_packets = u4RecvOk;
1931     prGlueInfo->rNetDevStats.tx_packets = u4XmitOk;
1932     prGlueInfo->rNetDevStats.tx_errors  = u4XmitError;
1933     prGlueInfo->rNetDevStats.rx_errors  = u4RecvError;
1934     //prGlueInfo->rNetDevStats.rx_bytes   = rCustomNetDevStats.u4RxBytes;
1935     //prGlueInfo->rNetDevStats.tx_bytes   = rCustomNetDevStats.u4TxBytes;
1936     //prGlueInfo->rNetDevStats.rx_errors  = rCustomNetDevStats.u4RxErrors;
1937     //prGlueInfo->rNetDevStats.multicast  = rCustomNetDevStats.u4Multicast;
1938     #endif
1939     //prGlueInfo->rNetDevStats.rx_packets = 0;
1940     //prGlueInfo->rNetDevStats.tx_packets = 0;
1941     prGlueInfo->rNetDevStats.tx_errors  = 0;
1942     prGlueInfo->rNetDevStats.rx_errors  = 0;
1943     //prGlueInfo->rNetDevStats.rx_bytes   = 0;
1944     //prGlueInfo->rNetDevStats.tx_bytes   = 0;
1945     prGlueInfo->rNetDevStats.rx_errors  = 0;
1946     prGlueInfo->rNetDevStats.multicast  = 0;
1947
1948     return &prGlueInfo->rNetDevStats;
1949
1950 } /* end of wlanGetStats() */
1951
1952 /*----------------------------------------------------------------------------*/
1953 /*!
1954 * \brief A function for prDev->init
1955 *
1956 * \param[in] prDev      Pointer to struct net_device.
1957 *
1958 * \retval 0         The execution of wlanInit succeeds.
1959 * \retval -ENXIO    No such device.
1960 */
1961 /*----------------------------------------------------------------------------*/
1962 static int
1963 wlanInit(
1964     struct net_device *prDev
1965     )
1966 {
1967     P_GLUE_INFO_T prGlueInfo = NULL;
1968
1969     if (!prDev) {
1970         return -ENXIO;
1971     }
1972
1973     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
1974 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12)
1975     INIT_DELAYED_WORK(&workq, wlanSetMulticastListWorkQueue);
1976 #else
1977     INIT_DELAYED_WORK(&workq, wlanSetMulticastListWorkQueue, NULL);
1978 #endif
1979
1980     return 0; /* success */
1981 } /* end of wlanInit() */
1982
1983 void mtk_init_delayed_work(struct delayed_work *work, void *func) 
1984 {
1985 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 12)
1986     INIT_DELAYED_WORK(work, func);
1987 #else
1988     INIT_DELAYED_WORK(work, func, NULL);
1989 #endif
1990 }
1991 EXPORT_SYMBOL(mtk_init_delayed_work);
1992
1993 /*----------------------------------------------------------------------------*/
1994 /*!
1995 * \brief A function for prDev->uninit
1996 *
1997 * \param[in] prDev      Pointer to struct net_device.
1998 *
1999 * \return (none)
2000 */
2001 /*----------------------------------------------------------------------------*/
2002 static void
2003 wlanUninit(
2004     struct net_device *prDev
2005     )
2006 {
2007     return;
2008 } /* end of wlanUninit() */
2009
2010
2011 /*----------------------------------------------------------------------------*/
2012 /*!
2013 * \brief A function for prDev->open
2014 *
2015 * \param[in] prDev      Pointer to struct net_device.
2016 *
2017 * \retval 0     The execution of wlanOpen succeeds.
2018 * \retval < 0   The execution of wlanOpen failed.
2019 */
2020 /*----------------------------------------------------------------------------*/
2021 static int
2022 wlanOpen(
2023     struct net_device *prDev
2024     )
2025 {
2026     ASSERT(prDev);
2027
2028 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
2029     netif_tx_start_all_queues(prDev);
2030 #else
2031     netif_start_queue(prDev);
2032 #endif
2033
2034     return 0; /* success */
2035 } /* end of wlanOpen() */
2036
2037
2038 /*----------------------------------------------------------------------------*/
2039 /*!
2040 * \brief A function for prDev->stop
2041 *
2042 * \param[in] prDev      Pointer to struct net_device.
2043 *
2044 * \retval 0     The execution of wlanStop succeeds.
2045 * \retval < 0   The execution of wlanStop failed.
2046 */
2047 /*----------------------------------------------------------------------------*/
2048 static int
2049 wlanStop(
2050     struct net_device *prDev
2051     )
2052 {
2053     P_GLUE_INFO_T prGlueInfo = NULL;
2054     struct cfg80211_scan_request *prScanRequest = NULL;
2055     GLUE_SPIN_LOCK_DECLARATION();
2056
2057     ASSERT(prDev);
2058
2059     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
2060
2061     /* CFG80211 down */
2062     GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV);
2063     if(prGlueInfo->prScanRequest != NULL) {
2064         prScanRequest = prGlueInfo->prScanRequest;
2065         prGlueInfo->prScanRequest = NULL;
2066     }
2067     GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV);
2068
2069     if(prScanRequest) {
2070         cfg80211_scan_done(prScanRequest, TRUE);
2071     }
2072
2073 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 26)
2074     netif_tx_stop_all_queues(prDev);
2075 #else
2076     netif_stop_queue(prDev);
2077 #endif
2078
2079     return 0; /* success */
2080 } /* end of wlanStop() */
2081
2082
2083 /*----------------------------------------------------------------------------*/
2084 /*!
2085  * \brief Update Channel table for cfg80211 for Wi-Fi Direct based on current country code
2086  *
2087  * \param[in] prGlueInfo      Pointer to glue info
2088  *
2089  * \return   none
2090  */
2091 /*----------------------------------------------------------------------------*/
2092 VOID
2093 wlanUpdateChannelTable(
2094     P_GLUE_INFO_T prGlueInfo
2095     )
2096 {
2097     UINT_8 i, j;
2098     UINT_8 ucNumOfChannel;
2099     RF_CHANNEL_INFO_T aucChannelList[ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels)];
2100
2101     // 1. Disable all channel
2102     for(i = 0; i < ARRAY_SIZE(mtk_2ghz_channels); i++) {
2103         mtk_2ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED;
2104     }
2105
2106     for(i = 0; i < ARRAY_SIZE(mtk_5ghz_channels); i++) {
2107         mtk_5ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED;
2108     }
2109
2110     // 2. Get current domain channel list
2111     rlmDomainGetChnlList(prGlueInfo->prAdapter,
2112             BAND_NULL,
2113             ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels),
2114             &ucNumOfChannel,
2115             aucChannelList);
2116
2117     // 3. Enable specific channel based on domain channel list
2118     for(i = 0; i < ucNumOfChannel; i++) {
2119         switch(aucChannelList[i].eBand) {
2120         case BAND_2G4:
2121             for(j = 0 ; j < ARRAY_SIZE(mtk_2ghz_channels) ; j++) {
2122                 if(mtk_2ghz_channels[j].hw_value == aucChannelList[i].ucChannelNum) {
2123                     mtk_2ghz_channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
2124                     break;
2125                 }
2126             }
2127             break;
2128             
2129         case BAND_5G:
2130             for(j = 0 ; j < ARRAY_SIZE(mtk_5ghz_channels) ; j++) {
2131                 if(mtk_5ghz_channels[j].hw_value == aucChannelList[i].ucChannelNum) {
2132                     mtk_5ghz_channels[j].flags &= ~IEEE80211_CHAN_DISABLED;
2133                     break;
2134                 }
2135             }
2136             break;
2137             
2138         default:
2139             break;
2140         }
2141     }
2142
2143     return;
2144 }
2145
2146
2147 /*----------------------------------------------------------------------------*/
2148 /*!
2149 * \brief Register the device to the kernel and return the index.
2150 *
2151 * \param[in] prDev      Pointer to struct net_device.
2152 *
2153 * \retval 0     The execution of wlanNetRegister succeeds.
2154 * \retval < 0   The execution of wlanNetRegister failed.
2155 */
2156 /*----------------------------------------------------------------------------*/
2157 static INT_32
2158 wlanNetRegister(
2159     struct wireless_dev *prWdev
2160     )
2161 {
2162     P_GLUE_INFO_T prGlueInfo;
2163     INT_32 i4DevIdx = -1;
2164
2165     ASSERT(prWdev);
2166
2167
2168     do {
2169         if (!prWdev) {
2170             break;
2171         }
2172
2173         prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy);
2174
2175         if ((i4DevIdx = wlanGetDevIdx(prWdev->netdev)) < 0) {
2176             DBGLOG(INIT, ERROR, ("wlanNetRegister: net_device number exceeds.\n"));
2177             break;
2178         }
2179
2180         /* adjust channel support status */
2181         wlanUpdateChannelTable((P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy));
2182
2183         if (wiphy_register(prWdev->wiphy) < 0) {
2184             DBGLOG(INIT, ERROR, ("wlanNetRegister: wiphy context is not registered.\n"));
2185             wlanClearDevIdx(prWdev->netdev);
2186             i4DevIdx = -1;
2187         }
2188
2189         if(register_netdev(prWdev->netdev) < 0) {
2190             DBGLOG(INIT, ERROR, ("wlanNetRegister: net_device context is not registered.\n"));
2191
2192             wiphy_unregister(prWdev->wiphy);
2193             wlanClearDevIdx(prWdev->netdev);
2194             i4DevIdx = -1;
2195         }
2196
2197         if(i4DevIdx != -1) {
2198             prGlueInfo->fgIsRegistered = TRUE;
2199         }
2200     }
2201     while(FALSE);
2202
2203     return i4DevIdx; /* success */
2204 } /* end of wlanNetRegister() */
2205
2206
2207 /*----------------------------------------------------------------------------*/
2208 /*!
2209 * \brief Unregister the device from the kernel
2210 *
2211 * \param[in] prWdev      Pointer to struct net_device.
2212 *
2213 * \return (none)
2214 */
2215 /*----------------------------------------------------------------------------*/
2216 static VOID
2217 wlanNetUnregister(
2218     struct wireless_dev *prWdev
2219     )
2220 {
2221     P_GLUE_INFO_T prGlueInfo;
2222
2223     if (!prWdev) {
2224         DBGLOG(INIT, ERROR, ("wlanNetUnregister: The device context is NULL\n"));
2225         return;
2226     }
2227
2228     prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy);
2229
2230     wlanClearDevIdx(prWdev->netdev);
2231     unregister_netdev(prWdev->netdev);
2232     wiphy_unregister(prWdev->wiphy);
2233
2234     prGlueInfo->fgIsRegistered = FALSE;
2235
2236     DBGLOG(INIT, INFO, ("unregister wireless_dev(0x%p)\n", prWdev));
2237
2238     return;
2239 } /* end of wlanNetUnregister() */
2240
2241
2242 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
2243 static const struct net_device_ops wlan_netdev_ops = {
2244         .ndo_open               = wlanOpen,
2245         .ndo_stop               = wlanStop,
2246 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
2247     .ndo_set_rx_mode = wlanSetMulticastList,
2248 #else
2249         .ndo_set_multicast_list = wlanSetMulticastList,
2250 #endif
2251         .ndo_get_stats          = wlanGetStats,
2252         .ndo_do_ioctl           = wlanDoIOCTL,
2253         .ndo_start_xmit         = wlanHardStartXmit,
2254         .ndo_init               = wlanInit,
2255         .ndo_uninit             = wlanUninit,
2256     .ndo_select_queue = wlanSelectQueue,
2257 };
2258 #endif
2259
2260 /*----------------------------------------------------------------------------*/
2261 /*!
2262 * \brief A method for creating Linux NET4 struct net_device object and the
2263 *        private data(prGlueInfo and prAdapter). Setup the IO address to the HIF.
2264 *        Assign the function pointer to the net_device object
2265 *
2266 * \param[in] pvData     Memory address for the device
2267 *
2268 * \retval Not null      The wireless_dev object.
2269 * \retval NULL          Fail to create wireless_dev object
2270 */
2271 /*----------------------------------------------------------------------------*/
2272 static struct wireless_dev *
2273 wlanNetCreate(
2274     PVOID pvData
2275     )
2276 {
2277     struct wireless_dev *prWdev = NULL;
2278     P_GLUE_INFO_T prGlueInfo =  NULL;
2279     P_ADAPTER_T prAdapter = NULL;
2280     UINT_32 i;
2281     struct device *prDev;
2282
2283     //4 <1.1> Create wireless_dev
2284     prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
2285     DBGLOG(INIT, INFO, ("wireless_dev prWdev(0x%p) allocated\n", prWdev));
2286     if (!prWdev) {
2287         DBGLOG(INIT, ERROR, ("Allocating memory to wireless_dev context failed\n"));
2288         return NULL;
2289     }
2290
2291     //4 <1.2> Create wiphy
2292     prWdev->wiphy = wiphy_new(&mtk_wlan_ops, sizeof(GLUE_INFO_T));
2293     DBGLOG(INIT, INFO, ("wiphy (0x%p) allocated\n", prWdev->wiphy));
2294     if (!prWdev->wiphy) {
2295         DBGLOG(INIT, ERROR, ("Allocating memory to wiphy device failed\n"));
2296         kfree(prWdev);
2297         return NULL;
2298     }
2299
2300     //4 <1.3> co-relate wiphy & prDev
2301 #if MTK_WCN_HIF_SDIO
2302     mtk_wcn_hif_sdio_get_dev(*((MTK_WCN_HIF_SDIO_CLTCTX *)pvData), &prDev);
2303 #else
2304     prDev = & ((struct sdio_func *) pvData)->dev;       //mark skynine add "&"
2305 #endif
2306     if (!prDev) {
2307         printk(KERN_ALERT DRV_NAME "unable to get struct dev for wlan\n");
2308     }
2309     set_wiphy_dev(prWdev->wiphy, prDev);
2310
2311     //4 <1.4> configure wireless_dev & wiphy
2312     prWdev->iftype = NL80211_IFTYPE_STATION;
2313     prWdev->wiphy->max_scan_ssids   = 1;    /* FIXME: for combo scan */
2314     prWdev->wiphy->max_scan_ie_len = 512;
2315     prWdev->wiphy->interface_modes  = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
2316     prWdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &mtk_band_2ghz;
2317     prWdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mtk_band_5ghz;
2318     prWdev->wiphy->signal_type      = CFG80211_SIGNAL_TYPE_MBM;
2319     prWdev->wiphy->cipher_suites    = (const u32 *)mtk_cipher_suites;
2320     prWdev->wiphy->n_cipher_suites  = ARRAY_SIZE(mtk_cipher_suites);
2321     #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) 
2322     prWdev->wiphy->flags            = WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_SUPPORTS_FW_ROAM;
2323     #else
2324     prWdev->wiphy->flags            = WIPHY_FLAG_CUSTOM_REGULATORY;
2325     #endif      
2326     //4 <2> Create Glue structure
2327     prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy);
2328     if (!prGlueInfo) {
2329         DBGLOG(INIT, ERROR, ("Allocating memory to glue layer failed\n"));
2330         goto netcreate_err;
2331     }
2332
2333     //4 <3> Initial Glue structure
2334     //4 <3.1> create net device 
2335     prGlueInfo->prDevHandler = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME, ether_setup, CFG_MAX_TXQ_NUM);
2336
2337     DBGLOG(INIT, INFO, ("net_device prDev(0x%p) allocated\n", prGlueInfo->prDevHandler));
2338     if (!prGlueInfo->prDevHandler) {
2339         DBGLOG(INIT, ERROR, ("Allocating memory to net_device context failed\n"));
2340         goto netcreate_err;
2341     }
2342
2343     //4 <3.1.1> initialize net device varaiables
2344     *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prDevHandler)) = prGlueInfo;
2345
2346     prGlueInfo->prDevHandler->netdev_ops = &wlan_netdev_ops;
2347 #ifdef CONFIG_WIRELESS_EXT
2348     prGlueInfo->prDevHandler->wireless_handlers = &wext_handler_def;
2349 #endif
2350     netif_carrier_off(prGlueInfo->prDevHandler);
2351     netif_tx_stop_all_queues(prGlueInfo->prDevHandler);
2352
2353     //4 <3.1.2> co-relate with wiphy bi-directionally
2354     prGlueInfo->prDevHandler->ieee80211_ptr = prWdev;
2355     prWdev->netdev = prGlueInfo->prDevHandler;
2356
2357     //4 <3.1.3> co-relate net device & prDev
2358     SET_NETDEV_DEV(prGlueInfo->prDevHandler, wiphy_dev(prWdev->wiphy));
2359
2360     //4 <3.2> initiali glue variables 
2361     prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED;
2362     prGlueInfo->ePowerState = ParamDeviceStateD0;
2363     prGlueInfo->fgIsMacAddrOverride = FALSE;
2364     prGlueInfo->fgIsRegistered = FALSE;
2365     prGlueInfo->prScanRequest = NULL;
2366
2367     init_completion(&prGlueInfo->rScanComp);
2368     init_completion(&prGlueInfo->rHaltComp);
2369     init_completion(&prGlueInfo->rPendComp);
2370 #if CFG_ENABLE_WIFI_DIRECT
2371     init_completion(&prGlueInfo->rSubModComp);
2372 #endif
2373
2374     /* initialize timer for OID timeout checker */
2375     kalOsTimerInitialize(prGlueInfo, kalTimeoutHandler);
2376
2377     for (i = 0; i < SPIN_LOCK_NUM; i++) {
2378         spin_lock_init(&prGlueInfo->rSpinLock[i]);
2379     }
2380
2381     /* initialize semaphore for ioctl */
2382     sema_init(&prGlueInfo->ioctl_sem, 1);
2383
2384     /* initialize semaphore for ioctl */
2385     sema_init(&g_halt_sem, 1);
2386     g_u4HaltFlag = 0;
2387
2388     //4 <4> Create Adapter structure
2389     prAdapter = (P_ADAPTER_T) wlanAdapterCreate(prGlueInfo);
2390
2391     if (!prAdapter) {
2392         DBGLOG(INIT, ERROR, ("Allocating memory to adapter failed\n"));
2393         goto netcreate_err;
2394     }
2395
2396     prGlueInfo->prAdapter = prAdapter;
2397
2398 #ifdef CONFIG_CFG80211_WEXT
2399     //4 <5> Use wireless extension to replace IOCTL
2400     prWdev->wiphy->wext = &wext_handler_def;
2401 #endif
2402
2403     goto netcreate_done;
2404
2405 netcreate_err:
2406     if (NULL != prAdapter) {
2407         wlanAdapterDestroy(prAdapter);
2408         prAdapter = NULL;
2409     }
2410
2411     if (NULL != prGlueInfo->prDevHandler) {
2412         free_netdev(prGlueInfo->prDevHandler);
2413         prGlueInfo->prDevHandler = NULL;
2414     }
2415
2416     if (NULL != prWdev->wiphy) {
2417         wiphy_free(prWdev->wiphy);
2418         prWdev->wiphy = NULL;
2419     }
2420
2421     if (NULL != prWdev) {
2422         /* Free net_device and private data, which are allocated by
2423          * alloc_netdev().
2424          */
2425         kfree(prWdev);
2426         prWdev = NULL;
2427     }
2428
2429 netcreate_done:
2430
2431     return prWdev;
2432 } /* end of wlanNetCreate() */
2433
2434
2435 /*----------------------------------------------------------------------------*/
2436 /*!
2437 * \brief Destroying the struct net_device object and the private data.
2438 *
2439 * \param[in] prWdev      Pointer to struct wireless_dev.
2440 *
2441 * \return (none)
2442 */
2443 /*----------------------------------------------------------------------------*/
2444 static VOID
2445 wlanNetDestroy(
2446     struct wireless_dev *prWdev
2447     )
2448 {
2449     P_GLUE_INFO_T prGlueInfo = NULL;
2450
2451     ASSERT(prWdev);
2452
2453     if (!prWdev) {
2454         DBGLOG(INIT, ERROR, ("wlanNetDestroy: The device context is NULL\n"));
2455         return;
2456     }
2457
2458     /* prGlueInfo is allocated with net_device */
2459     prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy);
2460     ASSERT(prGlueInfo);
2461
2462     /* destroy kal OS timer */
2463     kalCancelTimer(prGlueInfo);
2464
2465     glClearHifInfo(prGlueInfo);
2466
2467     wlanAdapterDestroy(prGlueInfo->prAdapter);
2468     prGlueInfo->prAdapter = NULL;
2469
2470     /* Free net_device and private data, which are allocated by alloc_netdev().
2471      */
2472     free_netdev(prWdev->netdev);
2473     wiphy_free(prWdev->wiphy);
2474
2475     kfree(prWdev);
2476
2477     return;
2478 } /* end of wlanNetDestroy() */
2479
2480 #ifndef CONFIG_X86
2481 UINT_8 g_aucBufIpAddr[32] = {0};
2482
2483 static void wlanEarlySuspend(void)
2484 {
2485     struct net_device *prDev = NULL;
2486     P_GLUE_INFO_T prGlueInfo = NULL;
2487     UINT_8  ip[4] = { 0 };
2488     UINT_32 u4NumIPv4 = 0;
2489 #ifdef  CONFIG_IPV6
2490     UINT_8  ip6[16] = { 0 };     // FIX ME: avoid to allocate large memory in stack
2491     UINT_32 u4NumIPv6 = 0;
2492 #endif
2493     UINT_32 i;
2494     P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr;
2495
2496     DBGLOG(INIT, INFO, ("*********wlanEarlySuspend************\n"));
2497
2498     // <1> Sanity check and acquire the net_device
2499     ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES);
2500     if(u4WlanDevNum == 0){
2501         DBGLOG(INIT, ERROR, ("wlanEarlySuspend u4WlanDevNum==0 invalid!!\n"));
2502         return;
2503     }
2504     prDev = arWlanDevInfo[u4WlanDevNum-1].prDev;
2505     ASSERT(prDev);
2506
2507 fgIsUnderEarlierSuspend = true;
2508
2509     // <2> get the IPv4 address
2510     if(!prDev || !(prDev->ip_ptr)||\
2511         !((struct in_device *)(prDev->ip_ptr))->ifa_list||\
2512         !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))){
2513         DBGLOG(INIT, INFO, ("ip is not avaliable.\n"));
2514         return;
2515     }
2516
2517     // <3> acquire the prGlueInfo
2518     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
2519     ASSERT(prGlueInfo);
2520
2521     // <4> copy the IPv4 address
2522     kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip));
2523     DBGLOG(INIT, INFO, ("ip is %d.%d.%d.%d\n",
2524             ip[0],ip[1],ip[2],ip[3]));
2525
2526     // todo: traverse between list to find whole sets of IPv4 addresses
2527     if (!((ip[0] == 0) &&
2528          (ip[1] == 0) &&
2529          (ip[2] == 0) &&
2530          (ip[3] == 0))) {
2531         u4NumIPv4++;
2532     }
2533
2534 #ifdef  CONFIG_IPV6
2535     // <5> get the IPv6 address
2536     if(!prDev || !(prDev->ip6_ptr)||\
2537         !((struct in_device *)(prDev->ip6_ptr))->ifa_list||\
2538         !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))){
2539         DBGLOG(INIT, INFO, ("ipv6 is not avaliable.\n"));
2540         return;
2541     }
2542     // <6> copy the IPv6 address
2543     kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6));
2544     DBGLOG(INIT, INFO, ("ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n",
2545             ip6[0],ip6[1],ip6[2],ip6[3],
2546             ip6[4],ip6[5],ip6[6],ip6[7],
2547             ip6[8],ip6[9],ip6[10],ip6[11],
2548             ip6[12],ip6[13],ip6[14],ip6[15]
2549             ));
2550
2551     // todo: traverse between list to find whole sets of IPv6 addresses
2552     if (!((ip6[0] == 0) &&
2553          (ip6[1] == 0) &&
2554          (ip6[2] == 0) &&
2555          (ip6[3] == 0) &&
2556          (ip6[4] == 0) &&
2557          (ip6[5] == 0))) {
2558         //u4NumIPv6++;
2559     }
2560
2561 #endif
2562
2563     // <7> set up the ARP filter
2564     {
2565         WLAN_STATUS rStatus = WLAN_STATUS_FAILURE;
2566         UINT_32 u4SetInfoLen = 0;
2567 //        UINT_8 aucBuf[32] = {0};
2568         UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress);
2569         P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST)g_aucBufIpAddr;//aucBuf;
2570         P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress;
2571
2572         kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr));
2573
2574         prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6;
2575         prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;
2576         for (i = 0; i < u4NumIPv4; i++) {
2577             prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP);//4;;
2578             prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;;
2579 #if 0
2580             kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip));
2581             prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip));
2582             u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip);
2583 #else
2584             prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP)prParamNetAddr->aucAddress;
2585             kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip));
2586             prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS));
2587             u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS);
2588 #endif
2589         }
2590 #ifdef  CONFIG_IPV6
2591         for (i = 0; i < u4NumIPv6; i++) {
2592             prParamNetAddr->u2AddressLength = 6;;
2593             prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;;
2594             kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6));
2595             prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip6));
2596             u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6);
2597        }
2598 #endif
2599         ASSERT(u4Len <= sizeof(g_aucBufIpAddr/*aucBuf*/));
2600
2601         rStatus = kalIoctl(prGlueInfo,
2602                 wlanoidSetNetworkAddress,
2603                 (PVOID)prParamNetAddrList,
2604                 u4Len,
2605                 FALSE,
2606                 FALSE,
2607                 TRUE,
2608                 FALSE,
2609                 &u4SetInfoLen);
2610
2611         if (rStatus != WLAN_STATUS_SUCCESS) {
2612             DBGLOG(INIT, INFO, ("set HW pattern filter fail 0x%lx\n", rStatus));
2613         }
2614     }
2615 }
2616
2617 static void wlanLateResume(void)
2618 {
2619     struct net_device *prDev = NULL;
2620     P_GLUE_INFO_T prGlueInfo = NULL;
2621     UINT_8  ip[4] = { 0 };
2622 #ifdef  CONFIG_IPV6
2623     UINT_8  ip6[16] = { 0 };     // FIX ME: avoid to allocate large memory in stack
2624 #endif
2625
2626     DBGLOG(INIT, INFO, ("*********wlanLateResume************\n"));
2627
2628     // <1> Sanity check and acquire the net_device
2629     ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES);
2630
2631     if(u4WlanDevNum == 0){
2632         DBGLOG(INIT, ERROR, ("wlanLateResume u4WlanDevNum==0 invalid!!\n"));
2633         return;
2634     }
2635     prDev = arWlanDevInfo[u4WlanDevNum-1].prDev;
2636     ASSERT(prDev);
2637
2638 fgIsUnderEarlierSuspend = false;
2639
2640     // <2> get the IPv4 address
2641     if(!prDev || !(prDev->ip_ptr)||\
2642         !((struct in_device *)(prDev->ip_ptr))->ifa_list||\
2643         !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))){
2644         DBGLOG(INIT, INFO, ("ip is not avaliable.\n"));
2645         return;
2646     }
2647
2648     // <3> acquire the prGlueInfo
2649     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
2650     ASSERT(prGlueInfo);
2651
2652     // <4> copy the IPv4 address
2653     kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip));
2654     DBGLOG(INIT, INFO, ("ip is %d.%d.%d.%d\n",
2655             ip[0],ip[1],ip[2],ip[3]));
2656
2657 #ifdef  CONFIG_IPV6
2658     // <5> get the IPv6 address
2659     if(!prDev || !(prDev->ip6_ptr)||\
2660         !((struct in_device *)(prDev->ip6_ptr))->ifa_list||\
2661         !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))){
2662         DBGLOG(INIT, INFO, ("ipv6 is not avaliable.\n"));
2663         return;
2664     }
2665     // <6> copy the IPv6 address
2666     kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6));
2667     DBGLOG(INIT, INFO, ("ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n",
2668             ip6[0],ip6[1],ip6[2],ip6[3],
2669             ip6[4],ip6[5],ip6[6],ip6[7],
2670             ip6[8],ip6[9],ip6[10],ip6[11],
2671             ip6[12],ip6[13],ip6[14],ip6[15]
2672             ));
2673 #endif
2674     // <7> clear the ARP filter
2675     {
2676         WLAN_STATUS rStatus = WLAN_STATUS_FAILURE;
2677         UINT_32 u4SetInfoLen = 0;
2678 //        UINT_8 aucBuf[32] = {0};
2679         UINT_32 u4Len = sizeof(PARAM_NETWORK_ADDRESS_LIST);
2680         P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST)g_aucBufIpAddr;//aucBuf;
2681
2682         kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr));
2683
2684         prParamNetAddrList->u4AddressCount = 0;
2685         prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;
2686
2687         ASSERT(u4Len <= sizeof(g_aucBufIpAddr/*aucBuf*/));
2688         rStatus = kalIoctl(prGlueInfo,
2689                 wlanoidSetNetworkAddress,
2690                 (PVOID)prParamNetAddrList,
2691                 u4Len,
2692                 FALSE,
2693                 FALSE,
2694                 TRUE,
2695                 FALSE,
2696                 &u4SetInfoLen);
2697
2698         if (rStatus != WLAN_STATUS_SUCCESS) {
2699             DBGLOG(INIT, INFO, ("set HW pattern filter fail 0x%lx\n", rStatus));
2700         }
2701     }
2702 }
2703
2704 #if defined(CONFIG_HAS_EARLYSUSPEND)
2705 static struct early_suspend mt6620_early_suspend_desc = {
2706     .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN,
2707 };
2708
2709 static void wlan_early_suspend(struct early_suspend *h)
2710 {
2711     DBGLOG(INIT, INFO, ("*********wlan_early_suspend************\n"));
2712     wlanEarlySuspend();
2713 }
2714
2715 static void wlan_late_resume(struct early_suspend *h)
2716 {
2717     DBGLOG(INIT, INFO, ("*********wlan_late_resume************\n"));
2718     wlanLateResume();
2719 }
2720 #endif //defined(CONFIG_HAS_EARLYSUSPEND)
2721 #endif //! CONFIG_X86
2722
2723 extern void wlanRegisterNotifier(void);
2724 extern void wlanUnregisterNotifier(void);
2725
2726 /*----------------------------------------------------------------------------*/
2727 /*!
2728 * \brief Wlan probe function. This function probes and initializes the device.
2729 *
2730 * \param[in] pvData     data passed by bus driver init function
2731 *                           _HIF_EHPI: NULL
2732 *                           _HIF_SDIO: sdio bus driver handle
2733 *
2734 * \retval 0 Success
2735 * \retval negative value Failed
2736 */
2737 /*----------------------------------------------------------------------------*/
2738 static INT_32
2739 wlanProbe(
2740     PVOID pvData
2741     )
2742 {
2743     struct wireless_dev *prWdev = NULL;
2744     P_WLANDEV_INFO_T prWlandevInfo = NULL;
2745     INT_32 i4DevIdx = 0;
2746     P_GLUE_INFO_T prGlueInfo = NULL;
2747     P_ADAPTER_T prAdapter = NULL;
2748     INT_32 i4Status = 0;
2749     BOOL bRet = FALSE;
2750
2751
2752     do {
2753 #if DBG
2754         int i;
2755         /* Initialize DEBUG CLASS of each module */
2756         for (i = 0; i < DBG_MODULE_NUM; i++) {
2757             aucDebugModule[i] = DBG_CLASS_ERROR | \
2758                                 DBG_CLASS_WARN | \
2759                                 DBG_CLASS_STATE | \
2760                                 DBG_CLASS_TRACE | \
2761                                 DBG_CLASS_EVENT;
2762             //aucDebugModule[i] = 0;
2763         }
2764 #if 0
2765         aucDebugModule[DBG_INIT_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
2766         aucDebugModule[DBG_ARB_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
2767         aucDebugModule[DBG_JOIN_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
2768         //aucDebugModule[DBG_RX_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
2769         aucDebugModule[DBG_TX_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
2770         aucDebugModule[DBG_NIC_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
2771         aucDebugModule[DBG_HAL_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
2772         aucDebugModule[DBG_KEVIN_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO | DBG_CLASS_TEMP;
2773         aucDebugModule[DBG_SCAN_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
2774         aucDebugModule[DBG_REQ_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
2775         //aucDebugModule[DBG_MGT_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
2776         aucDebugModule[DBG_RSN_IDX] |= DBG_CLASS_TRACE;
2777         aucDebugModule[DBG_ROAMING_IDX] |= DBG_CLASS_TRACE | DBG_CLASS_INFO;
2778 #endif
2779 #endif /* DBG */
2780
2781         //4 <1> Initialize the IO port of the interface
2782         /*  GeorgeKuo: pData has different meaning for _HIF_XXX:
2783          * _HIF_EHPI: pointer to memory base variable, which will be
2784          *      initialized by glBusInit().
2785          * _HIF_SDIO: bus driver handle
2786          */
2787
2788         bRet = glBusInit(pvData);
2789
2790         /* Cannot get IO address from interface */
2791         if (FALSE == bRet) {
2792             DBGLOG(INIT, ERROR, (KERN_ALERT "wlanProbe: glBusInit() fail\n"));
2793             i4Status = -EIO;
2794             break;
2795         }
2796
2797         //4 <2> Create network device, Adapter, KalInfo, prDevHandler(netdev)
2798         if ((prWdev = wlanNetCreate(pvData)) == NULL) {
2799             DBGLOG(INIT, ERROR, ("wlanProbe: No memory for dev and its private\n"));
2800             i4Status = -ENOMEM;
2801             break;
2802         }
2803
2804         //4 <2.5> Set the ioaddr to HIF Info
2805         prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy);
2806         gPrDev = prGlueInfo->prDevHandler;
2807         glSetHifInfo(prGlueInfo, (UINT_32) pvData);
2808
2809
2810         /* main thread is created in this function */
2811         init_waitqueue_head(&prGlueInfo->waitq);
2812         //
2813
2814         QUEUE_INITIALIZE(&prGlueInfo->rCmdQueue);
2815         QUEUE_INITIALIZE(&prGlueInfo->rTxQueue);
2816
2817
2818
2819         //prGlueInfo->main_thread = kthread_run(tx_thread, prGlueInfo->prDevHandler, "tx_thread");
2820
2821         //4 <4> Setup IRQ
2822         prWlandevInfo = &arWlanDevInfo[i4DevIdx];
2823
2824         //i4Status = glBusSetIrq(prWdev->netdev, NULL, *((P_GLUE_INFO_T *) netdev_priv(prWdev->netdev)));
2825
2826         if (i4Status != WLAN_STATUS_SUCCESS) {
2827             DBGLOG(INIT, ERROR, ("wlanProbe: Set IRQ error\n"));
2828             break;
2829         }
2830
2831         prGlueInfo->i4DevIdx = i4DevIdx;
2832
2833         prAdapter = prGlueInfo->prAdapter;
2834
2835         prGlueInfo->u4ReadyFlag = 0;
2836
2837 #if CFG_TCP_IP_CHKSUM_OFFLOAD
2838         prAdapter->u4CSUMFlags = (CSUM_OFFLOAD_EN_TX_TCP | CSUM_OFFLOAD_EN_TX_UDP | CSUM_OFFLOAD_EN_TX_IP);
2839 #endif
2840
2841         //4 <5> Start Device
2842         //
2843 #if CFG_ENABLE_FW_DOWNLOAD
2844         /* before start adapter, we need to open and load firmware */
2845         {
2846             UINT_32 u4FwSize = 0;
2847             PVOID prFwBuffer = NULL;
2848             P_REG_INFO_T prRegInfo = &prGlueInfo->rRegInfo;
2849
2850             //P_REG_INFO_T prRegInfo = (P_REG_INFO_T) kmalloc(sizeof(REG_INFO_T), GFP_KERNEL);
2851             kalMemSet(prRegInfo, 0, sizeof(REG_INFO_T));
2852             prRegInfo->u4StartAddress = CFG_FW_START_ADDRESS;
2853             prRegInfo->u4LoadAddress =  CFG_FW_LOAD_ADDRESS;
2854
2855             // Load NVRAM content to REG_INFO_T
2856             glLoadNvram(prGlueInfo, prRegInfo);
2857
2858             //kalMemCopy(&prGlueInfo->rRegInfo, prRegInfo, sizeof(REG_INFO_T));
2859
2860             prRegInfo->u4PowerMode = CFG_INIT_POWER_SAVE_PROF;
2861             prRegInfo->fgEnArpFilter = TRUE;
2862
2863             if (kalFirmwareImageMapping(prGlueInfo, &prFwBuffer, &u4FwSize) == NULL) {
2864                 i4Status = -EIO;
2865                 goto bailout;
2866             } else {
2867                 if (wlanAdapterStart(prAdapter, prRegInfo,  prFwBuffer, u4FwSize) != WLAN_STATUS_SUCCESS) {
2868                     i4Status = -EIO;
2869                 }
2870             }
2871
2872             kalFirmwareImageUnmapping(prGlueInfo, NULL, prFwBuffer);
2873
2874 bailout:
2875             //kfree(prRegInfo);
2876
2877             if (i4Status < 0) {
2878                 break;
2879             }
2880         }
2881 #else
2882         //P_REG_INFO_T prRegInfo = (P_REG_INFO_T) kmalloc(sizeof(REG_INFO_T), GFP_KERNEL);
2883         kalMemSet(&prGlueInfo->rRegInfo, 0, sizeof(REG_INFO_T));
2884         P_REG_INFO_T prRegInfo = &prGlueInfo->rRegInfo;
2885
2886         // Load NVRAM content to REG_INFO_T
2887         glLoadNvram(prGlueInfo, prRegInfo);
2888
2889         prRegInfo->u4PowerMode = CFG_INIT_POWER_SAVE_PROF;
2890
2891         if (wlanAdapterStart(prAdapter, prRegInfo, NULL, 0) != WLAN_STATUS_SUCCESS) {
2892             i4Status = -EIO;
2893             break;
2894         }
2895 #endif
2896         prGlueInfo->main_thread = kthread_run(tx_thread, prGlueInfo->prDevHandler, "tx_thread");
2897
2898         /* set MAC address */
2899         {
2900             WLAN_STATUS rStatus = WLAN_STATUS_FAILURE;
2901             struct sockaddr MacAddr;
2902             UINT_32 u4SetInfoLen = 0;
2903
2904             rStatus = kalIoctl(prGlueInfo,
2905                     wlanoidQueryCurrentAddr,
2906                     &MacAddr.sa_data,
2907                     PARAM_MAC_ADDR_LEN,
2908                     TRUE,
2909                     TRUE,
2910                     TRUE,
2911                     FALSE,
2912                     &u4SetInfoLen);
2913
2914             if (rStatus != WLAN_STATUS_SUCCESS) {
2915                 DBGLOG(INIT, WARN, ("set MAC addr fail 0x%lx\n", rStatus));
2916                 prGlueInfo->u4ReadyFlag = 0;
2917             } else {
2918                 memcpy(prGlueInfo->prDevHandler->dev_addr, &MacAddr.sa_data, ETH_ALEN);
2919                 memcpy(prGlueInfo->prDevHandler->perm_addr, prGlueInfo->prDevHandler->dev_addr, ETH_ALEN);
2920
2921                 /* card is ready */
2922                 prGlueInfo->u4ReadyFlag = 1;
2923 #if CFG_SHOW_MACADDR_SOURCE
2924                 DBGLOG(INIT, INFO, ("MAC address: "MACSTR, MAC2STR(&MacAddr.sa_data)));
2925 #endif
2926             }
2927         }
2928
2929
2930 #if CFG_TCP_IP_CHKSUM_OFFLOAD
2931         /* set HW checksum offload */
2932         {
2933             WLAN_STATUS rStatus = WLAN_STATUS_FAILURE;
2934             UINT_32 u4CSUMFlags = CSUM_OFFLOAD_EN_ALL;
2935             UINT_32 u4SetInfoLen = 0;
2936
2937             rStatus = kalIoctl(prGlueInfo,
2938                     wlanoidSetCSUMOffload,
2939                     (PVOID)&u4CSUMFlags,
2940                     sizeof(UINT_32),
2941                     FALSE,
2942                     FALSE,
2943                     TRUE,
2944                     FALSE,
2945                     &u4SetInfoLen);
2946
2947             if (rStatus != WLAN_STATUS_SUCCESS) {
2948                 DBGLOG(INIT, WARN, ("set HW checksum offload fail 0x%lx\n", rStatus));
2949             }
2950         }
2951 #endif
2952
2953         //4 <3> Register the card
2954         if ((i4DevIdx = wlanNetRegister(prWdev)) < 0){
2955             i4Status = -ENXIO;
2956             DBGLOG(INIT, ERROR, ("wlanProbe: Cannot register the net_device context to the kernel\n"));
2957             break;
2958         }
2959
2960         glRegisterEarlySuspend(&mt6620_early_suspend_desc, wlan_early_suspend, wlan_late_resume);
2961         wlanRegisterNotifier();
2962         //4 <6> Initialize /proc filesystem
2963 #ifdef WLAN_INCLUDE_PROC
2964         if ( (i4Status = procInitProcfs(prDev, NIC_DEVICE_ID_LOW)) < 0) {
2965             DBGLOG(INIT, ERROR, ("wlanProbe: init procfs failed\n"));
2966             break;
2967         }
2968 #endif /* WLAN_INCLUDE_PROC */
2969
2970 #if CFG_ENABLE_BT_OVER_WIFI
2971         prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE;
2972         prGlueInfo->rBowInfo.fgIsRegistered = FALSE;
2973         glRegisterAmpc(prGlueInfo);
2974 #endif
2975
2976 #if CFG_ENABLE_WIFI_DIRECT
2977         /*wlan is launched*/
2978         prGlueInfo->prAdapter->fgIsWlanLaunched = TRUE;
2979         /*if p2p module is inserted, notify tx_thread to init p2p network*/
2980         if(rSubModHandler[P2P_MODULE].subModInit) {
2981             wlanSubModInit(prGlueInfo);
2982         }
2983 #endif
2984     }
2985     while (FALSE);
2986
2987 #if 1//def RK2818       
2988         if (i4Status < 0)
2989                 driver_start_ok = -1;
2990         else
2991                 driver_start_ok = 1;
2992 #endif
2993
2994     return i4Status;
2995 } /* end of wlanProbe() */
2996
2997
2998 /*----------------------------------------------------------------------------*/
2999 /*!
3000 * \brief A method to stop driver operation and release all resources. Following
3001 *        this call, no frame should go up or down through this interface.
3002 *
3003 * \return (none)
3004 */
3005 /*----------------------------------------------------------------------------*/
3006 static VOID
3007 wlanRemove(
3008     VOID
3009     )
3010 {
3011     struct net_device *prDev = NULL;
3012     P_WLANDEV_INFO_T prWlandevInfo = NULL;
3013     P_GLUE_INFO_T prGlueInfo = NULL;
3014     P_ADAPTER_T prAdapter = NULL;
3015
3016     DBGLOG(INIT, INFO, ("Remove wlan!\n"));
3017
3018
3019     //4 <0> Sanity check
3020     ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES);
3021     if (0 == u4WlanDevNum) {
3022         DBGLOG(INIT, INFO, ("0 == u4WlanDevNum\n"));
3023         return;
3024     }
3025
3026     prDev = arWlanDevInfo[u4WlanDevNum-1].prDev;
3027     prWlandevInfo = &arWlanDevInfo[u4WlanDevNum-1];
3028
3029     ASSERT(prDev);
3030     if (NULL == prDev) {
3031         DBGLOG(INIT, INFO, ("NULL == prDev\n"));
3032         return;
3033     }
3034
3035     prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
3036     ASSERT(prGlueInfo);
3037     if (NULL == prGlueInfo) {
3038         DBGLOG(INIT, INFO, ("NULL == prGlueInfo\n"));
3039         free_netdev(prDev);
3040         return;
3041     }
3042
3043
3044 #if CFG_ENABLE_WIFI_DIRECT
3045     prGlueInfo->prAdapter->fgIsWlanLaunched = FALSE;
3046     if(prGlueInfo->prAdapter->fgIsP2PRegistered) {
3047         p2pNetUnregister(prGlueInfo, FALSE);
3048         p2pRemove(prGlueInfo);
3049     }
3050
3051 #if 0
3052     prGlueInfo->prAdapter->fgIsWlanLaunched = FALSE;
3053     //if(prGlueInfo->prAdapter->fgIsP2PRegistered) {
3054     if (prGlueInfo->prP2PInfo) {
3055         //p2pRemove(prGlueInfo);
3056         if (prGlueInfo->prP2PInfo->prDevHandler) {
3057             free_netdev(prGlueInfo->prP2PInfo->prDevHandler);
3058             prGlueInfo->prP2PInfo->prDevHandler = NULL;
3059
3060         }
3061
3062
3063         if(!p2PFreeInfo(prGlueInfo)) {
3064            printk(KERN_ALERT DRV_NAME "Free memory for p2p FAILED\n");
3065            ASSERT(0);
3066            return;
3067         }
3068     }
3069 #endif
3070 #endif
3071
3072 #if CFG_ENABLE_BT_OVER_WIFI
3073     if(prGlueInfo->rBowInfo.fgIsNetRegistered) {
3074         bowNotifyAllLinkDisconnected(prGlueInfo->prAdapter);
3075         /*wait 300ms for BoW module to send deauth*/
3076         kalMsleep(300);
3077     }
3078 #endif
3079
3080     //4 <1> Stopping handling interrupt and free IRQ
3081     glBusFreeIrq(prDev, *((P_GLUE_INFO_T *) netdev_priv(prDev)));
3082
3083     kalMemSet(&(prGlueInfo->prAdapter->rWlanInfo), 0, sizeof(WLAN_INFO_T));
3084
3085     flush_delayed_work_sync(&workq);
3086
3087     down(&g_halt_sem);
3088     g_u4HaltFlag = 1;
3089
3090     //4 <2> Mark HALT, notify main thread to stop, and clean up queued requests
3091     prGlueInfo->u4Flag |= GLUE_FLAG_HALT;
3092     /* wake up main thread */
3093     wake_up_interruptible(&prGlueInfo->waitq);
3094     /* wait main thread stops */
3095     wait_for_completion_interruptible(&prGlueInfo->rHaltComp);
3096
3097     DBGLOG(INIT, INFO, ("mtk_sdiod stopped\n"));
3098
3099     //prGlueInfo->rHifInfo.main_thread = NULL;
3100     prGlueInfo->main_thread = NULL;
3101
3102 #if CFG_ENABLE_BT_OVER_WIFI
3103     if(prGlueInfo->rBowInfo.fgIsRegistered) {
3104         glUnregisterAmpc(prGlueInfo);
3105     }
3106 #endif
3107
3108
3109     //4 <3> Remove /proc filesystem.
3110 #ifdef WLAN_INCLUDE_PROC
3111     procRemoveProcfs(prDev, NIC_DEVICE_ID_LOW);
3112 #endif /* WLAN_INCLUDE_PROC */
3113
3114     //4 <4> wlanAdapterStop
3115     prAdapter = prGlueInfo->prAdapter;
3116
3117     wlanAdapterStop(prAdapter);
3118     DBGLOG(INIT, INFO, ("Number of Stalled Packets = %ld\n", prGlueInfo->i4TxPendingFrameNum));
3119
3120     //4 <5> Release the Bus
3121     glBusRelease(prDev);
3122
3123     up(&g_halt_sem);
3124
3125     //4 <6> Unregister the card
3126     wlanNetUnregister(prDev->ieee80211_ptr);
3127
3128     //4 <7> Destroy the device
3129     wlanNetDestroy(prDev->ieee80211_ptr);
3130     prDev = NULL;
3131
3132     glUnregisterEarlySuspend(&mt6620_early_suspend_desc);
3133     wlanUnregisterNotifier();
3134     return;
3135 } /* end of wlanRemove() */
3136
3137 /*----------------------------------------------------------------------------*/
3138 /*!
3139 * \brief Driver entry point when the driver is configured as a Linux Module, and
3140 *        is called once at module load time, by the user-level modutils
3141 *        application: insmod or modprobe.
3142 *
3143 * \retval 0     Success
3144 */
3145 /*----------------------------------------------------------------------------*/
3146 //1 Module Entry Point
3147
3148 #include "wifi_version.h"
3149
3150 extern void initRssiHistory(void);
3151 extern void initScanRssiHistory(void);
3152 extern VOID exitWlan(void);
3153 /*static */int initWlan(void)
3154 {
3155         int ret = 0, timeout = 0;
3156         int count = 3;
3157         driver_start_ok = 0;
3158
3159 #if RSSI_ENHANCE
3160         initRssiHistory();
3161         initScanRssiHistory();
3162 #endif
3163 retry_initwlan:
3164         
3165     //printk("=======================================================\n");
3166     //printk("==== Launching Wi-Fi driver! (Powered by Rockchip) ====\n");
3167     //printk("=======================================================\n");
3168     printk("MT5931 SDIO WiFi driver (Powered by Rockchip,Ver %s) init.\n", MT5931_DRV_VERSION);
3169
3170     DBGLOG(INIT, INFO, ("initWlan\n"));
3171
3172
3173 #if defined(CONFIG_WIFI_CONTROL_FUNC)
3174     if (wl_android_wifictrl_func_add() < 0) {
3175         ret = -1;
3176         goto fail;
3177     }
3178 #endif 
3179
3180     /* memory pre-allocation */
3181     kalInitIOBuffer();
3182
3183     //return ((glRegisterBus(wlanProbe, wlanRemove) == WLAN_STATUS_SUCCESS) ? 0: -EIO);
3184     ret = ((glRegisterBus(wlanProbe, wlanRemove) == WLAN_STATUS_SUCCESS) ? 0: -EIO);
3185
3186     if (ret == -EIO) {
3187         kalUninitIOBuffer();
3188         ret = -1;
3189         goto fail;
3190     }
3191
3192 #if (CFG_CHIP_RESET_SUPPORT)
3193     glResetInit();
3194 #endif
3195
3196     /*WCNCR00002676, keep OS wake up for 100ms*/
3197     KAL_WAKE_LOCK_INIT(NULL, &isr_wakelock, "WLAN TIME 2");
3198
3199         /*for (timeout = 50; timeout >=0; timeout--)
3200     {
3201                 if (driver_start_ok == 1)
3202                         return ret;
3203         msleep(100);
3204     }   
3205         if (timeout <= 0 && count > 0)
3206     {
3207                 count--;
3208                 if (driver_start_ok == 0)
3209                 printk("No WiFi function card has been attached (5s). retry!\n");
3210                 else if (driver_start_ok < 0)
3211                 printk("wifi driver probe processing fail. retry!\n");
3212                 exitWlan();
3213                 goto retry_initwlan;
3214     }*/
3215
3216     return ret;
3217      
3218 fail:
3219         
3220 #if defined(CONFIG_WIFI_CONTROL_FUNC)
3221         wl_android_wifictrl_func_del();
3222 #endif 
3223     
3224     return ret;
3225 } /* end of initWlan() */
3226
3227
3228 /*----------------------------------------------------------------------------*/
3229 /*!
3230 * \brief Driver exit point when the driver as a Linux Module is removed. Called
3231 *        at module unload time, by the user level modutils application: rmmod.
3232 *        This is our last chance to clean up after ourselves.
3233 *
3234 * \return (none)
3235 */
3236 /*----------------------------------------------------------------------------*/
3237 //1 Module Leave Point
3238 /*static */VOID exitWlan(void)
3239 {
3240     //printk("=======================================================\n");  
3241     //printk("== Dis-launching Wi-Fi driver! (Powered by Rockchip) ==\n");  
3242     //printk("=======================================================\n");
3243
3244     //printk("remove %p\n", wlanRemove);
3245 #if CFG_CHIP_RESET_SUPPORT
3246     glResetUninit();
3247 #endif
3248
3249     glUnregisterBus(wlanRemove);
3250
3251     /*WCNCR00002676*/
3252     KAL_WAKE_LOCK_DESTROY(NULL, &isr_wakelock);
3253     
3254     /* free pre-allocated memory */
3255     kalUninitIOBuffer();
3256
3257 #if defined(CONFIG_WIFI_CONTROL_FUNC)
3258         wl_android_wifictrl_func_del();
3259 #endif /* CONFIG_WIFI_CONTROL_FUNC */
3260
3261     DBGLOG(INIT, INFO, ("exitWlan\n"));
3262
3263     return;
3264 } /* end of exitWlan() */
3265
3266 int rockchip_wifi_init_module(void)
3267 {
3268         initWlan();
3269 }
3270
3271 int rockchip_wifi_exit_module(void)
3272 {
3273         exitWlan();
3274 }
3275
3276 EXPORT_SYMBOL(rockchip_wifi_init_module);
3277 EXPORT_SYMBOL(rockchip_wifi_exit_module);
3278
3279 //module_init(initWlan);
3280 //module_exit(exitWlan);
3281 #if 0
3282 /* export necessary symbol for p2p driver using */
3283 #if CFG_ENABLE_WIFI_DIRECT
3284 EXPORT_SYMBOL(wlanSubModRegisterInitExit);
3285 EXPORT_SYMBOL(wlanSubModExit);
3286 EXPORT_SYMBOL(wlanSubModInit);
3287
3288 EXPORT_SYMBOL(nicPmIndicateBssCreated);
3289 EXPORT_SYMBOL(rlmProcessAssocRsp);
3290 EXPORT_SYMBOL(kalSetEvent);
3291 EXPORT_SYMBOL(rlmBssInitForAPandIbss);
3292 EXPORT_SYMBOL(kalEnqueueCommand);
3293 EXPORT_SYMBOL(nicIncreaseTxSeqNum);
3294 EXPORT_SYMBOL(nicCmdEventQueryAddress);
3295 EXPORT_SYMBOL(bssCreateStaRecFromBssDesc);
3296 EXPORT_SYMBOL(rlmBssAborted);
3297 EXPORT_SYMBOL(cnmStaRecResetStatus);
3298 EXPORT_SYMBOL(mqmProcessAssocRsp);
3299 EXPORT_SYMBOL(nicTxReturnMsduInfo);
3300 EXPORT_SYMBOL(nicTxEnqueueMsdu);
3301 EXPORT_SYMBOL(wlanProcessSecurityFrame);
3302 EXPORT_SYMBOL(nicChannelNum2Freq);
3303 EXPORT_SYMBOL(nicUpdateBss);
3304 EXPORT_SYMBOL(wlanSendSetQueryCmd);
3305 EXPORT_SYMBOL(cnmStaRecAlloc);
3306 EXPORT_SYMBOL(cnmTimerInitTimer);
3307 EXPORT_SYMBOL(rateGetRateSetFromIEs);
3308 EXPORT_SYMBOL(nicOidCmdTimeoutCommon);
3309 EXPORT_SYMBOL(cnmStaRecChangeState);
3310 EXPORT_SYMBOL(rateGetDataRatesFromRateSet);
3311 EXPORT_SYMBOL(cnmMgtPktAlloc);
3312 EXPORT_SYMBOL(cnmMgtPktFree);
3313 EXPORT_SYMBOL(wextSrchDesiredWPAIE);
3314 EXPORT_SYMBOL(nicRxReturnRFB);
3315 EXPORT_SYMBOL(cnmTimerStartTimer);
3316 EXPORT_SYMBOL(cmdBufAllocateCmdInfo);
3317 EXPORT_SYMBOL(cnmGetStaRecByAddress);
3318 EXPORT_SYMBOL(nicMediaStateChange);
3319 EXPORT_SYMBOL(bssUpdateBeaconContent);
3320 EXPORT_SYMBOL(kalIoctl);
3321 EXPORT_SYMBOL(nicActivateNetwork);
3322 EXPORT_SYMBOL(nicDeactivateNetwork);
3323 EXPORT_SYMBOL(kalRandomNumber);
3324 EXPORT_SYMBOL(nicCmdEventSetCommon);
3325 EXPORT_SYMBOL(cnmTimerStopTimer);
3326 EXPORT_SYMBOL(nicIncreaseCmdSeqNum);
3327 EXPORT_SYMBOL(authSendDeauthFrame);
3328 EXPORT_SYMBOL(cnmMemAlloc);
3329 EXPORT_SYMBOL(nicPmIndicateBssAbort);
3330 EXPORT_SYMBOL(nicCmdEventSetIpAddress);
3331 EXPORT_SYMBOL(mboxSendMsg);
3332 EXPORT_SYMBOL(scanSearchBssDescByBssid);
3333 EXPORT_SYMBOL(bssRemoveStaRecFromClientList);
3334 EXPORT_SYMBOL(assocProcessRxDisassocFrame);
3335 EXPORT_SYMBOL(authProcessRxDeauthFrame);
3336 EXPORT_SYMBOL(cnmStaRecFree);
3337 EXPORT_SYMBOL(rNonHTPhyAttributes);
3338 EXPORT_SYMBOL(rNonHTApModeAttributes);
3339 EXPORT_SYMBOL(cnmMemFree);
3340 EXPORT_SYMBOL(wlanExportGlueInfo);
3341 EXPORT_SYMBOL(bssInitForAP);
3342 EXPORT_SYMBOL(nicPmIndicateBssConnected);
3343 EXPORT_SYMBOL(rlmRspGenerateHtOpIE);
3344 EXPORT_SYMBOL(bssGenerateExtSuppRate_IE);
3345 EXPORT_SYMBOL(rlmRspGenerateErpIE);
3346 EXPORT_SYMBOL(rlmRspGenerateHtCapIE);
3347 EXPORT_SYMBOL(cnmGetStaRecByIndex);
3348 EXPORT_SYMBOL(rsnGenerateWpaNoneIE);
3349 EXPORT_SYMBOL(rlmRspGenerateExtCapIE);
3350 EXPORT_SYMBOL(rsnGenerateRSNIE);
3351 EXPORT_SYMBOL(rsnParseRsnIE);
3352 #if CFG_SUPPORT_WPS
3353 EXPORT_SYMBOL(wextSrchDesiredWPSIE);
3354 #endif
3355 EXPORT_SYMBOL(mboxDummy);
3356 EXPORT_SYMBOL(saaFsmRunEventStart);
3357 EXPORT_SYMBOL(saaFsmRunEventAbort);
3358 EXPORT_SYMBOL(cnmP2PIsPermitted);
3359 EXPORT_SYMBOL(cnmBss40mBwPermitted);
3360 EXPORT_SYMBOL(mqmGenerateWmmParamIE);
3361 EXPORT_SYMBOL(cnmPreferredChannel);
3362 EXPORT_SYMBOL(bssAddStaRecToClientList);
3363 EXPORT_SYMBOL(nicQmUpdateWmmParms);
3364 EXPORT_SYMBOL(qmFreeAllByNetType);
3365 EXPORT_SYMBOL(wlanQueryInformation);
3366 EXPORT_SYMBOL(nicConfigPowerSaveProfile);
3367 EXPORT_SYMBOL(scanSearchExistingBssDesc);
3368 EXPORT_SYMBOL(scanAllocateBssDesc);
3369 EXPORT_SYMBOL(wlanProcessCommandQueue);
3370 EXPORT_SYMBOL(wlanAcquirePowerControl);
3371 EXPORT_SYMBOL(wlanReleasePowerControl);
3372 EXPORT_SYMBOL(wlanReleasePendingCMDbyNetwork);
3373 #if DBG
3374 EXPORT_SYMBOL(aucDebugModule);
3375 EXPORT_SYMBOL(fgIsBusAccessFailed);
3376 EXPORT_SYMBOL(allocatedMemSize);
3377 EXPORT_SYMBOL(dumpMemory8);
3378 EXPORT_SYMBOL(dumpMemory32);
3379 #endif
3380 EXPORT_SYMBOL(rlmDomainIsLegalChannel);
3381 EXPORT_SYMBOL(scnQuerySparseChannel);
3382 EXPORT_SYMBOL(rlmDomainGetChnlList);
3383 EXPORT_SYMBOL(p2pSetMulticastListWorkQueueWrapper);
3384 EXPORT_SYMBOL(nicUpdateRSSI);
3385 EXPORT_SYMBOL(nicCmdEventQueryLinkQuality);
3386 EXPORT_SYMBOL(kalGetMediaStateIndicated);
3387 EXPORT_SYMBOL(nicFreq2ChannelNum);
3388 EXPORT_SYMBOL(assocSendDisAssocFrame);
3389 EXPORT_SYMBOL(nicUpdateBeaconIETemplate);
3390 EXPORT_SYMBOL(rsnParseCheckForWFAInfoElem);
3391 EXPORT_SYMBOL(kalClearMgmtFramesByNetType);
3392 EXPORT_SYMBOL(kalClearSecurityFramesByNetType);
3393 EXPORT_SYMBOL(nicFreePendingTxMsduInfoByNetwork);
3394 EXPORT_SYMBOL(bssComposeBeaconProbeRespFrameHeaderAndFF);
3395 EXPORT_SYMBOL(bssBuildBeaconProbeRespFrameCommonIEs);
3396 EXPORT_SYMBOL(wlanoidSetWapiAssocInfo);
3397 EXPORT_SYMBOL(wlanoidSetWSCAssocInfo);
3398 #endif
3399 #endif