Commit | Line | Data |
---|---|---|
6fa3eb70 S |
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 */ | |
40712dd0 | 711 | #if CFG_TC1_FEATURE || defined(CONFIG_MTK_COMBO_AOSP_TETHERING_SUPPORT) |
6fa3eb70 S |
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 | |
40712dd0 | 2311 | #if CFG_TC1_FEATURE || defined(CONFIG_MTK_COMBO_AOSP_TETHERING_SUPPORT) |
6fa3eb70 S |
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; | |
4b9e9796 S |
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; | |
6fa3eb70 S |
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; | |
4b9e9796 | 2916 | eFailReason = BUS_INIT_FAIL; |
6fa3eb70 S |
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; | |
4b9e9796 | 2924 | eFailReason = NET_CREATE_FAIL; |
6fa3eb70 S |
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")); | |
4b9e9796 | 2952 | eFailReason = BUS_SET_IRQ_FAIL; |
6fa3eb70 S |
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); | |
4b9e9796 | 3046 | eFailReason = ADAPTER_START_FAIL; |
6fa3eb70 S |
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; | |
4b9e9796 | 3062 | eFailReason = ADAPTER_START_FAIL; |
6fa3eb70 S |
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")); | |
4b9e9796 | 3161 | eFailReason = NET_REGISTER_FAIL; |
6fa3eb70 S |
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")); | |
4b9e9796 | 3171 | eFailReason = PROC_INIT_FAIL; |
6fa3eb70 S |
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) | |
4b9e9796 S |
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 | } | |
6fa3eb70 S |
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) | |
4b9e9796 S |
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 | } | |
6fa3eb70 | 3254 | #endif |
4b9e9796 S |
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; | |
6fa3eb70 S |
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 |