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