PD#91902:update ap6xxx module wifi driver as 1.88.45.4
[GitHub/LineageOS/G12/android_hardware_amlogic_kernel-modules_dhd-driver.git] / broadcm_40181 / dhd_config.c
CommitLineData
693cd89a
ML
1\r
2#include <typedefs.h>\r
3#include <osl.h>\r
4\r
5#include <bcmutils.h>\r
80e122a3 6#include <hndsoc.h>\r
693cd89a
ML
7#if defined(HW_OOB)\r
8#include <bcmdefs.h>\r
9#include <bcmsdh.h>\r
693cd89a
ML
10#include <sdio.h>\r
11#include <sbchipc.h>\r
12#endif\r
13\r
14#include <dhd_config.h>\r
15#include <dhd_dbg.h>\r
b614e5fd 16#include <wl_cfg80211.h>\r
693cd89a 17\r
80e122a3 18#ifdef CONFIG_HAS_WAKELOCK\r
19#include <linux/wakelock.h>\r
20#endif\r
21\r
568d3732 22/* message levels */\r
693cd89a
ML
23#define CONFIG_ERROR_LEVEL 0x0001\r
24#define CONFIG_TRACE_LEVEL 0x0002\r
568d3732 25\r
693cd89a 26uint config_msg_level = CONFIG_ERROR_LEVEL;\r
568d3732 27\r
693cd89a 28#define CONFIG_ERROR(x) \\r
568d3732 29 do { \\r
693cd89a
ML
30 if (config_msg_level & CONFIG_ERROR_LEVEL) { \\r
31 printk(KERN_ERR "CONFIG-ERROR) "); \\r
568d3732
LJ
32 printk x; \\r
33 } \\r
34 } while (0)\r
693cd89a 35#define CONFIG_TRACE(x) \\r
568d3732 36 do { \\r
693cd89a
ML
37 if (config_msg_level & CONFIG_TRACE_LEVEL) { \\r
38 printk(KERN_ERR "CONFIG-TRACE) "); \\r
568d3732
LJ
39 printk x; \\r
40 } \\r
693cd89a
ML
41 } while (0)\r
42\r
96e81bc5 43#define SBSDIO_CIS_SIZE_LIMIT 0x200 /* maximum bytes in one CIS */\r
44#define MAXSZ_BUF 1000\r
693cd89a
ML
45#define MAXSZ_CONFIG 4096\r
46\r
47#define BCM43362A0_CHIP_REV 0\r
48#define BCM43362A2_CHIP_REV 1\r
49#define BCM4330B2_CHIP_REV 4\r
96e81bc5 50#define BCM43340B0_CHIP_REV 2\r
693cd89a
ML
51#define BCM43341B0_CHIP_REV 2\r
52#define BCM43241B4_CHIP_REV 5\r
53#define BCM4335A0_CHIP_REV 2\r
54#define BCM4339A0_CHIP_REV 1\r
55\r
56#define FW_TYPE_STA 0\r
57#define FW_TYPE_APSTA 1\r
58#define FW_TYPE_P2P 2\r
59#define FW_TYPE_MFG 3\r
60#define FW_TYPE_G 0\r
61#define FW_TYPE_AG 1\r
62\r
63const static char *bcm4330b2_fw_name[] = {\r
64 "fw_bcm40183b2.bin",\r
65 "fw_bcm40183b2_apsta.bin",\r
66 "fw_bcm40183b2_p2p.bin",\r
67 "fw_bcm40183b2_mfg.bin"\r
68};\r
69\r
70const static char *bcm4330b2ag_fw_name[] = {\r
71 "fw_bcm40183b2_ag.bin",\r
72 "fw_bcm40183b2_ag_apsta.bin",\r
73 "fw_bcm40183b2_ag_p2p.bin",\r
74 "fw_bcm40183b2_ag_mfg.bin"\r
75};\r
76\r
77const static char *bcm43362a0_fw_name[] = {\r
78 "fw_bcm40181a0.bin",\r
79 "fw_bcm40181a0_apsta.bin",\r
80 "fw_bcm40181a0_p2p.bin",\r
81 "fw_bcm40181a0_mfg.bin"\r
82};\r
83\r
84const static char *bcm43362a2_fw_name[] = {\r
85 "fw_bcm40181a2.bin",\r
86 "fw_bcm40181a2_apsta.bin",\r
87 "fw_bcm40181a2_p2p.bin",\r
88 "fw_bcm40181a2_mfg.bin"\r
89};\r
90\r
91const static char *bcm43341b0ag_fw_name[] = {\r
92 "fw_bcm43341b0_ag.bin",\r
93 "fw_bcm43341b0_ag_apsta.bin",\r
94 "fw_bcm43341b0_ag_p2p.bin",\r
95 "fw_bcm43341b0_ag_mfg.bin"\r
96};\r
97\r
98const static char *bcm43241b4ag_fw_name[] = {\r
99 "fw_bcm43241b4_ag.bin",\r
100 "fw_bcm43241b4_ag_apsta.bin",\r
101 "fw_bcm43241b4_ag_p2p.bin",\r
102 "fw_bcm43241b4_ag_mfg.bin"\r
103};\r
104\r
105const static char *bcm4339a0ag_fw_name[] = {\r
106 "fw_bcm4339a0_ag.bin",\r
107 "fw_bcm4339a0_ag_apsta.bin",\r
108 "fw_bcm4339a0_ag_p2p.bin",\r
109 "fw_bcm4339a0_ag_mfg.bin"\r
110};\r
111\r
96e81bc5 112#define htod32(i) i
113#define htod16(i) i
114#define dtoh32(i) i
115#define dtoh16(i) i
116#define htodchanspec(i) i
117#define dtohchanspec(i) i\r
118\r
119void\r
120dhd_conf_free_mac_list(wl_mac_list_ctrl_t *mac_list)\r
121{\r
122 CONFIG_TRACE(("%s called\n", __FUNCTION__));\r
123\r
124 if (mac_list->m_mac_list_head) {\r
125 CONFIG_TRACE(("%s Free %p\n", __FUNCTION__, mac_list->m_mac_list_head));\r
126 if (mac_list->m_mac_list_head->mac) {\r
127 CONFIG_TRACE(("%s Free %p\n", __FUNCTION__, mac_list->m_mac_list_head->mac));\r
128 kfree(mac_list->m_mac_list_head->mac);\r
129 }\r
130 kfree(mac_list->m_mac_list_head);\r
131 }\r
132 mac_list->count = 0;\r
133}\r
134\r
135int\r
136dhd_conf_get_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, uint8 *mac)\r
137{\r
138 int i, err = -1;\r
139 uint8 *ptr = 0;\r
140 unsigned char tpl_code, tpl_link;\r
141 uint8 header[3] = {0x80, 0x07, 0x19};\r
142 uint8 *cis;\r
143\r
144 if (!(cis = MALLOC(dhd->osh, SBSDIO_CIS_SIZE_LIMIT))) {\r
145 CONFIG_ERROR(("%s: cis malloc failed\n", __FUNCTION__));\r
146 return err;\r
147 }\r
148 bzero(cis, SBSDIO_CIS_SIZE_LIMIT);\r
149\r
150 if ((err = bcmsdh_cis_read(sdh, 0, cis, SBSDIO_CIS_SIZE_LIMIT))) {\r
151 CONFIG_ERROR(("%s: cis read err %d\n", __FUNCTION__, err));\r
152 MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT);\r
153 return err;\r
154 }\r
155 err = -1; // reset err;\r
156 ptr = cis;\r
157 do {\r
158 /* 0xff means we're done */\r
159 tpl_code = *ptr;\r
160 ptr++;\r
161 if (tpl_code == 0xff)\r
162 break;\r
163\r
164 /* null entries have no link field or data */\r
165 if (tpl_code == 0x00)\r
166 continue;\r
167\r
168 tpl_link = *ptr;\r
169 ptr++;\r
170 /* a size of 0xff also means we're done */\r
171 if (tpl_link == 0xff)\r
172 break;\r
173 if (config_msg_level & CONFIG_TRACE_LEVEL) {\r
174 printf("%s: tpl_code=0x%02x, tpl_link=0x%02x, tag=0x%02x\n",\r
175 __FUNCTION__, tpl_code, tpl_link, *ptr);\r
176 printf("%s: value:", __FUNCTION__);\r
177 for (i=0; i<tpl_link-1; i++) {\r
178 printf("%02x ", ptr[i+1]);\r
179 if ((i+1)%16==0)\r
180 printf("\n");\r
181 }\r
182 printf("\n");\r
183 }\r
184\r
185 if (tpl_code == 0x80 && tpl_link == 0x07 && *ptr == 0x19)\r
186 break;\r
187\r
188 ptr += tpl_link;\r
189 } while (1);\r
190\r
191 if (tpl_code == 0x80 && tpl_link == 0x07 && *ptr == 0x19) {\r
192 /* Normal OTP */\r
193 memcpy(mac, ptr+1, 6);\r
194 err = 0;\r
195 } else {\r
196 ptr = cis;\r
197 /* Special OTP */\r
198 if (bcmsdh_reg_read(sdh, SI_ENUM_BASE, 4) == 0x16044330) {\r
199 for (i=0; i<SBSDIO_CIS_SIZE_LIMIT; i++) {\r
200 if (!memcmp(header, ptr, 3)) {\r
201 memcpy(mac, ptr+1, 6);\r
202 err = 0;\r
203 break;\r
204 }\r
205 ptr++;\r
206 }\r
207 }\r
208 }\r
209\r
210 ASSERT(cis);\r
211 MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT);\r
212\r
213 return err;\r
214}\r
215\r
216void\r
217dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, char *fw_path)\r
218{\r
219 int i, j;\r
220 uint8 mac[6]={0};\r
221 int fw_num=0, mac_num=0;\r
222 uint32 oui, nic;\r
223 wl_mac_list_t *mac_list;\r
224 wl_mac_range_t *mac_range;\r
225 char *pfw_name;\r
226 int fw_type, fw_type_new;\r
227\r
228 mac_list = dhd->conf->fw_by_mac.m_mac_list_head;\r
229 fw_num = dhd->conf->fw_by_mac.count;\r
230 if (!mac_list || !fw_num)\r
231 return;\r
232\r
233 if (dhd_conf_get_mac(dhd, sdh, mac)) {\r
234 CONFIG_ERROR(("%s: Can not read MAC address\n", __FUNCTION__));\r
235 return;\r
236 }\r
237 oui = (mac[0] << 16) | (mac[1] << 8) | (mac[2]);\r
238 nic = (mac[3] << 16) | (mac[4] << 8) | (mac[5]);\r
239\r
240 /* find out the last '/' */\r
241 i = strlen(fw_path);\r
242 while (i>0){\r
243 if (fw_path[i] == '/') break;\r
244 i--;\r
245 }\r
246 pfw_name = &fw_path[i+1];\r
247 fw_type = (strstr(pfw_name, "_mfg") ?\r
248 FW_TYPE_MFG : (strstr(pfw_name, "_apsta") ?\r
249 FW_TYPE_APSTA : (strstr(pfw_name, "_p2p") ?\r
250 FW_TYPE_P2P : FW_TYPE_STA)));\r
251\r
252 for (i=0; i<fw_num; i++) {\r
253 mac_num = mac_list[i].count;\r
254 mac_range = mac_list[i].mac;\r
255 fw_type_new = (strstr(mac_list[i].name, "_mfg") ?\r
256 FW_TYPE_MFG : (strstr(mac_list[i].name, "_apsta") ?\r
257 FW_TYPE_APSTA : (strstr(mac_list[i].name, "_p2p") ?\r
258 FW_TYPE_P2P : FW_TYPE_STA)));\r
259 if (fw_type != fw_type_new) {\r
260 printf("%s: fw_typ=%d != fw_type_new=%d\n", __FUNCTION__, fw_type, fw_type_new);\r
261 continue;\r
262 }\r
263 for (j=0; j<mac_num; j++) {\r
264 if (oui == mac_range[j].oui) {\r
265 if (nic >= mac_range[j].nic_start && nic <= mac_range[j].nic_end) {\r
266 strcpy(pfw_name, mac_list[i].name);\r
267 printf("%s: matched oui=0x%06X, nic=0x%06X\n",\r
268 __FUNCTION__, oui, nic);\r
269 printf("%s: fw_path=%s\n", __FUNCTION__, fw_path);\r
270 return;\r
271 }\r
272 }\r
273 }\r
274 }\r
275}\r
276\r
277void\r
278dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, char *nv_path)\r
279{\r
280 int i, j;\r
281 uint8 mac[6]={0};\r
282 int nv_num=0, mac_num=0;\r
283 uint32 oui, nic;\r
284 wl_mac_list_t *mac_list;\r
285 wl_mac_range_t *mac_range;\r
286 char *pnv_name;\r
287\r
288 mac_list = dhd->conf->nv_by_mac.m_mac_list_head;\r
289 nv_num = dhd->conf->nv_by_mac.count;\r
290 if (!mac_list || !nv_num)\r
291 return;\r
292\r
293 if (dhd_conf_get_mac(dhd, sdh, mac)) {\r
294 CONFIG_ERROR(("%s: Can not read MAC address\n", __FUNCTION__));\r
295 return;\r
296 }\r
297 oui = (mac[0] << 16) | (mac[1] << 8) | (mac[2]);\r
298 nic = (mac[3] << 16) | (mac[4] << 8) | (mac[5]);\r
299\r
300 /* find out the last '/' */\r
301 i = strlen(nv_path);\r
302 while (i>0){\r
303 if (nv_path[i] == '/') break;\r
304 i--;\r
305 }\r
306 pnv_name = &nv_path[i+1];\r
307\r
308 for (i=0; i<nv_num; i++) {\r
309 mac_num = mac_list[i].count;\r
310 mac_range = mac_list[i].mac;\r
311 for (j=0; j<mac_num; j++) {\r
312 if (oui == mac_range[j].oui) {\r
313 if (nic >= mac_range[j].nic_start && nic <= mac_range[j].nic_end) {\r
314 strcpy(pnv_name, mac_list[i].name);\r
315 printf("%s: matched oui=0x%06X, nic=0x%06X\n",\r
316 __FUNCTION__, oui, nic);\r
317 printf("%s: nv_path=%s\n", __FUNCTION__, nv_path);\r
318 return;\r
319 }\r
320 }\r
321 }\r
322 }\r
323}\r
324\r
693cd89a
ML
325void\r
326dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *dst, char *src)\r
327{\r
328 int fw_type, ag_type;\r
329 static uint chip, chiprev, first=1;\r
330 int i;\r
331\r
332 if (first) {\r
333 chip = dhd_bus_chip_id(dhd);\r
334 chiprev = dhd_bus_chiprev_id(dhd);\r
335 first = 0;\r
336 }\r
337\r
338 if (src[0] == '\0') {\r
339#ifdef CONFIG_BCMDHD_FW_PATH\r
340 bcm_strncpy_s(src, sizeof(fw_path), CONFIG_BCMDHD_FW_PATH, MOD_PARAM_PATHLEN-1);\r
341 if (src[0] == '\0')\r
342#endif\r
343 {\r
344 printf("src firmware path is null\n");\r
345 return;\r
346 }\r
347 }\r
348\r
349 strcpy(dst, src);\r
350#ifndef FW_PATH_AUTO_SELECT\r
351 return;\r
352#endif\r
353\r
354 /* find out the last '/' */\r
355 i = strlen(dst);\r
356 while (i>0){\r
357 if (dst[i] == '/') break;\r
358 i--;\r
359 }\r
360#ifdef BAND_AG\r
361 ag_type = FW_TYPE_AG;\r
362#else\r
363 ag_type = strstr(&dst[i], "_ag") ? FW_TYPE_AG : FW_TYPE_G;\r
364#endif\r
365 fw_type = (strstr(&dst[i], "_mfg") ?\r
366 FW_TYPE_MFG : (strstr(&dst[i], "_apsta") ?\r
367 FW_TYPE_APSTA : (strstr(&dst[i], "_p2p") ?\r
368 FW_TYPE_P2P : FW_TYPE_STA)));\r
369\r
370 switch (chip) {\r
371 case BCM4330_CHIP_ID:\r
372 if (ag_type == FW_TYPE_G) {\r
373 if (chiprev == BCM4330B2_CHIP_REV)\r
374 strcpy(&dst[i+1], bcm4330b2_fw_name[fw_type]);\r
375 break;\r
376 } else {\r
377 if (chiprev == BCM4330B2_CHIP_REV)\r
378 strcpy(&dst[i+1], bcm4330b2ag_fw_name[fw_type]);\r
379 break;\r
380 }\r
381 case BCM43362_CHIP_ID:\r
382 if (chiprev == BCM43362A0_CHIP_REV)\r
383 strcpy(&dst[i+1], bcm43362a0_fw_name[fw_type]);\r
384 else\r
385 strcpy(&dst[i+1], bcm43362a2_fw_name[fw_type]);\r
386 break;\r
96e81bc5 387 case BCM43340_CHIP_ID:\r
388 if (chiprev == BCM43340B0_CHIP_REV)\r
389 strcpy(&dst[i+1], bcm43341b0ag_fw_name[fw_type]);\r
390 break;\r
693cd89a
ML
391 case BCM43341_CHIP_ID:\r
392 if (chiprev == BCM43341B0_CHIP_REV)\r
393 strcpy(&dst[i+1], bcm43341b0ag_fw_name[fw_type]);\r
394 break;\r
395 case BCM4324_CHIP_ID:\r
396 if (chiprev == BCM43241B4_CHIP_REV)\r
397 strcpy(&dst[i+1], bcm43241b4ag_fw_name[fw_type]);\r
398 break;\r
399 case BCM4335_CHIP_ID:\r
400 if (chiprev == BCM4335A0_CHIP_REV)\r
401 strcpy(&dst[i+1], bcm4339a0ag_fw_name[fw_type]);\r
402 break;\r
403 case BCM4339_CHIP_ID:\r
404 if (chiprev == BCM4339A0_CHIP_REV)\r
405 strcpy(&dst[i+1], bcm4339a0ag_fw_name[fw_type]);\r
406 break;\r
407 }\r
408\r
409 printf("%s: firmware_path=%s\n", __FUNCTION__, dst);\r
410}\r
411\r
412#if defined(HW_OOB)\r
413void\r
414dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, uint chip)\r
415{\r
416 uint32 gpiocontrol, addr;\r
417\r
418 if (CHIPID(chip) == BCM43362_CHIP_ID) {\r
419 printf("%s: Enable HW OOB for 43362\n", __FUNCTION__);\r
420 addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, gpiocontrol);\r
421 gpiocontrol = bcmsdh_reg_read(sdh, addr, 4);\r
422 gpiocontrol |= 0x2;\r
423 bcmsdh_reg_write(sdh, addr, 4, gpiocontrol);\r
424 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10005, 0xf, NULL);\r
425 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10006, 0x0, NULL);\r
426 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10007, 0x2, NULL);\r
427 }\r
428}\r
429#endif\r
430\r
431void\r
432dhd_conf_set_fw_path(dhd_pub_t *dhd, char *fw_path)\r
433{\r
434 if (dhd->conf->fw_path[0]) {\r
435 strcpy(fw_path, dhd->conf->fw_path);\r
436 printf("%s: fw_path is changed to %s\n", __FUNCTION__, fw_path);\r
437 }\r
438}\r
439\r
440void\r
441dhd_conf_set_nv_path(dhd_pub_t *dhd, char *nv_path)\r
442{\r
443 if (dhd->conf->nv_path[0]) {\r
444 strcpy(nv_path, dhd->conf->nv_path);\r
445 printf("%s: nv_path is changed to %s\n", __FUNCTION__, nv_path);\r
446 }\r
447}\r
448\r
449int\r
450dhd_conf_set_band(dhd_pub_t *dhd)\r
451{\r
452 int bcmerror = -1;\r
453\r
7a4fa002 454 printf("%s: Set band %d\n", __FUNCTION__, dhd->conf->band);\r
693cd89a
ML
455 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_BAND, &dhd->conf->band,\r
456 sizeof(dhd->conf->band), TRUE, 0)) < 0)\r
7a4fa002 457 CONFIG_ERROR(("%s: WLC_SET_BAND setting failed %d\n", __FUNCTION__, bcmerror));\r
693cd89a
ML
458\r
459 return bcmerror;\r
460}\r
461\r
462uint\r
463dhd_conf_get_band(dhd_pub_t *dhd)\r
464{\r
7a4fa002 465 uint band = WLC_BAND_AUTO;\r
466\r
467 if (dhd && dhd->conf)\r
468 band = dhd->conf->band;\r
469 else\r
470 CONFIG_ERROR(("%s: dhd or conf is NULL\n", __FUNCTION__));\r
471\r
472 return band;\r
693cd89a
ML
473}\r
474\r
475int\r
476dhd_conf_set_country(dhd_pub_t *dhd)\r
477{\r
478 int bcmerror = -1;\r
479 char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */\r
96e81bc5 480\r
693cd89a
ML
481 memset(&dhd->dhd_cspec, 0, sizeof(wl_country_t));\r
482 printf("%s: Set country %s, revision %d\n", __FUNCTION__,\r
483 dhd->conf->cspec.ccode, dhd->conf->cspec.rev);\r
484 bcm_mkiovar("country", (char *)&dhd->conf->cspec,\r
485 sizeof(wl_country_t), iovbuf, sizeof(iovbuf));\r
486 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)\r
487 printf("%s: country code setting failed %d\n", __FUNCTION__, bcmerror);\r
488\r
489 return bcmerror;\r
490}\r
491\r
492int\r
96e81bc5 493dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec)\r
693cd89a
ML
494{\r
495 int bcmerror = -1;\r
693cd89a 496\r
96e81bc5 497 memset(cspec, 0, sizeof(wl_country_t));\r
498 bcm_mkiovar("country", NULL, 0, (char*)cspec, sizeof(wl_country_t));\r
499 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cspec, sizeof(wl_country_t), FALSE, 0)) < 0)\r
693cd89a
ML
500 printf("%s: country code getting failed %d\n", __FUNCTION__, bcmerror);\r
501 else\r
96e81bc5 502 printf("Country code: %s (%s/%d)\n", cspec->country_abbrev, cspec->ccode, cspec->rev);\r
503\r
504 return bcmerror;\r
505}\r
506\r
507int\r
508dhd_conf_fix_country(dhd_pub_t *dhd)\r
509{\r
510 int bcmerror = -1;\r
511 uint band;\r
512 wl_uint32_list_t *list;\r
513 u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)];\r
514\r
515 if (!(dhd && dhd->conf)) {\r
516 return bcmerror;\r
517 }\r
518
519 memset(valid_chan_list, 0, sizeof(valid_chan_list));\r
520 list = (wl_uint32_list_t *)(void *) valid_chan_list;
521 list->count = htod32(WL_NUMCHANNELS);
522 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VALID_CHANNELS, valid_chan_list, sizeof(valid_chan_list), FALSE, 0)) < 0) {\r
523 CONFIG_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, bcmerror));\r
524 }\r
525\r
526 band = dhd_conf_get_band(dhd);\r
527\r
528 if (bcmerror || ((band==WLC_BAND_AUTO || band==WLC_BAND_2G) &&\r
529 dtoh32(list->count)<11)) {\r
530 CONFIG_ERROR(("%s: bcmerror=%d, # of channels %d\n",\r
531 __FUNCTION__, bcmerror, dtoh32(list->count)));\r
532 if ((bcmerror = dhd_conf_set_country(dhd)) < 0) {\r
533 strcpy(dhd->conf->cspec.country_abbrev, "US");\r
534 dhd->conf->cspec.rev = 0;\r
535 strcpy(dhd->conf->cspec.ccode, "US");\r
536 dhd_conf_set_country(dhd);\r
537 }\r
538 }\r
693cd89a
ML
539\r
540 return bcmerror;\r
541}\r
542\r
543bool\r
544dhd_conf_match_channel(dhd_pub_t *dhd, uint32 channel)\r
545{\r
546 int i;\r
7a4fa002 547 bool match = false;\r
693cd89a 548\r
7a4fa002 549 if (dhd && dhd->conf) {\r
550 if (dhd->conf->channels.count == 0)\r
693cd89a 551 return true;\r
7a4fa002 552 for (i=0; i<dhd->conf->channels.count; i++) {\r
553 if (channel == dhd->conf->channels.channel[i])\r
554 match = true;\r
693cd89a 555 }\r
7a4fa002 556 } else {\r
557 match = true;\r
558 CONFIG_ERROR(("%s: dhd or conf is NULL\n", __FUNCTION__));\r
693cd89a
ML
559 }\r
560\r
7a4fa002 561 return match;\r
693cd89a
ML
562}\r
563\r
564int\r
565dhd_conf_set_roam(dhd_pub_t *dhd)\r
566{\r
567 int bcmerror = -1;\r
568 char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */\r
569\r
570 printf("%s: Set roam_off %d\n", __FUNCTION__, dhd->conf->roam_off);\r
571 dhd_roam_disable = dhd->conf->roam_off;\r
572 bcm_mkiovar("roam_off", (char *)&dhd->conf->roam_off, 4, iovbuf, sizeof(iovbuf));\r
573 dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);\r
574\r
575 if (!dhd->conf->roam_off || !dhd->conf->roam_off_suspend) {\r
576 printf("%s: Set roam_trigger %d\n", __FUNCTION__, dhd->conf->roam_trigger[0]);\r
577 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_TRIGGER, dhd->conf->roam_trigger,\r
578 sizeof(dhd->conf->roam_trigger), TRUE, 0)) < 0)\r
7a4fa002 579 CONFIG_ERROR(("%s: roam trigger setting failed %d\n", __FUNCTION__, bcmerror));\r
693cd89a
ML
580\r
581 printf("%s: Set roam_scan_period %d\n", __FUNCTION__, dhd->conf->roam_scan_period[0]);\r
582 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_SCAN_PERIOD, dhd->conf->roam_scan_period,\r
583 sizeof(dhd->conf->roam_scan_period), TRUE, 0)) < 0)\r
7a4fa002 584 CONFIG_ERROR(("%s: roam scan period setting failed %d\n", __FUNCTION__, bcmerror));\r
693cd89a
ML
585\r
586 printf("%s: Set roam_delta %d\n", __FUNCTION__, dhd->conf->roam_delta[0]);\r
587 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_DELTA, dhd->conf->roam_delta,\r
588 sizeof(dhd->conf->roam_delta), TRUE, 0)) < 0)\r
7a4fa002 589 CONFIG_ERROR(("%s: roam delta setting failed %d\n", __FUNCTION__, bcmerror));\r
693cd89a
ML
590\r
591 printf("%s: Set fullroamperiod %d\n", __FUNCTION__, dhd->conf->fullroamperiod);\r
592 bcm_mkiovar("fullroamperiod", (char *)&dhd->conf->fullroamperiod, 4, iovbuf, sizeof(iovbuf));\r
593 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)\r
7a4fa002 594 CONFIG_ERROR(("%s: roam fullscan period setting failed %d\n", __FUNCTION__, bcmerror));\r
693cd89a
ML
595 }\r
596\r
597 return bcmerror;\r
598}\r
599\r
600void\r
80e122a3 601dhd_conf_set_mimo_bw_cap(dhd_pub_t *dhd)\r
693cd89a
ML
602{\r
603 int bcmerror = -1;\r
604 char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */\r
96e81bc5 605 uint32 mimo_bw_cap;\r
606 uint chip;\r
693cd89a 607\r
96e81bc5 608 chip = dhd_bus_chip_id(dhd);\r
609 if (chip!=BCM43362_CHIP_ID && chip!=BCM4330_CHIP_ID) {\r
80e122a3 610 if (dhd->conf->mimo_bw_cap >= 0) {\r
611 mimo_bw_cap = (uint)dhd->conf->mimo_bw_cap;\r
7a4fa002 612 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, 0)) < 0)\r
613 CONFIG_ERROR(("%s: WLC_DOWN setting failed %d\n", __FUNCTION__, bcmerror));\r
96e81bc5 614 /* 0:HT20 in ALL, 1:HT40 in ALL, 2: HT20 in 2G HT40 in 5G */\r
615 printf("%s: Set mimo_bw_cap %d\n", __FUNCTION__, mimo_bw_cap);\r
568d3732 616 bcm_mkiovar("mimo_bw_cap", (char *)&mimo_bw_cap, 4, iovbuf, sizeof(iovbuf));\r
693cd89a 617 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)\r
7a4fa002 618 CONFIG_ERROR(("%s: mimo_bw_cap setting failed %d\n", __FUNCTION__, bcmerror));\r
80e122a3 619 }\r
7a4fa002 620 }\r
621}\r
622\r
623void\r
624dhd_conf_force_wme(dhd_pub_t *dhd)\r
625{\r
626 int bcmerror = -1;\r
627 char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */\r
628\r
629 if (dhd_bus_chip_id(dhd) == BCM43362_CHIP_ID && dhd->conf->force_wme_ac) {\r
630 bcm_mkiovar("force_wme_ac", (char *)&dhd->conf->force_wme_ac, 4, iovbuf, sizeof(iovbuf));\r
631 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)\r
632 CONFIG_ERROR(("%s: force_wme_ac setting failed %d\n", __FUNCTION__, bcmerror));\r
633 }\r
634}\r
635\r
636void\r
637dhd_conf_get_wme(dhd_pub_t *dhd, edcf_acparam_t *acp)\r
638{\r
639 int bcmerror = -1;\r
640 char iovbuf[WLC_IOCTL_SMLEN];\r
641 edcf_acparam_t *acparam;\r
642\r
643 bzero(iovbuf, sizeof(iovbuf));\r
644\r
645 /*\r
646 * Get current acparams, using buf as an input buffer.\r
647 * Return data is array of 4 ACs of wme params.\r
648 */\r
649 bcm_mkiovar("wme_ac_sta", NULL, 0, iovbuf, sizeof(iovbuf));\r
650 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) < 0) {\r
651 CONFIG_ERROR(("%s: wme_ac_sta getting failed %d\n", __FUNCTION__, bcmerror));\r
652 return;\r
653 }\r
654 memcpy((char*)acp, iovbuf, sizeof(edcf_acparam_t)*AC_COUNT);\r
655\r
656 acparam = &acp[AC_BK];\r
96e81bc5 657 CONFIG_TRACE(("%s: BK: aci %d aifsn %d ecwmin %d ecwmax %d size %d\n", __FUNCTION__,\r
7a4fa002 658 acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,\r
659 acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,\r
660 sizeof(acp)));\r
661 acparam = &acp[AC_BE];\r
96e81bc5 662 CONFIG_TRACE(("%s: BE: aci %d aifsn %d ecwmin %d ecwmax %d size %d\n", __FUNCTION__,\r
7a4fa002 663 acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,\r
664 acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,\r
665 sizeof(acp)));\r
666 acparam = &acp[AC_VI];\r
96e81bc5 667 CONFIG_TRACE(("%s: VI: aci %d aifsn %d ecwmin %d ecwmax %d size %d\n", __FUNCTION__,\r
7a4fa002 668 acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,\r
669 acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,\r
670 sizeof(acp)));\r
671 acparam = &acp[AC_VO];\r
96e81bc5 672 CONFIG_TRACE(("%s: VO: aci %d aifsn %d ecwmin %d ecwmax %d size %d\n", __FUNCTION__,\r
7a4fa002 673 acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,\r
674 acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,\r
675 sizeof(acp)));\r
676\r
677 return;\r
678}\r
679\r
680void\r
681dhd_conf_update_wme(dhd_pub_t *dhd, edcf_acparam_t *acparam_cur, int aci)\r
682{\r
683 int bcmerror = -1;\r
684 int aifsn, ecwmin, ecwmax;\r
685 edcf_acparam_t *acp;\r
686 char iovbuf[WLC_IOCTL_SMLEN];\r
687\r
688 /* Default value */\r
689 aifsn = acparam_cur->ACI&EDCF_AIFSN_MASK;\r
690 ecwmin = acparam_cur->ECW&EDCF_ECWMIN_MASK;\r
691 ecwmax = (acparam_cur->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT;\r
692\r
693 /* Modified value */\r
694 if (dhd->conf->wme.aifsn[aci] > 0)\r
695 aifsn = dhd->conf->wme.aifsn[aci];\r
696 if (dhd->conf->wme.cwmin[aci] > 0)\r
697 ecwmin = dhd->conf->wme.cwmin[aci];\r
698 if (dhd->conf->wme.cwmax[aci] > 0)\r
699 ecwmax = dhd->conf->wme.cwmax[aci];\r
700\r
701 /* Update */\r
702 acp = acparam_cur;\r
703 acp->ACI = (acp->ACI & ~EDCF_AIFSN_MASK) | (aifsn & EDCF_AIFSN_MASK);\r
704 acp->ECW = ((ecwmax << EDCF_ECWMAX_SHIFT) & EDCF_ECWMAX_MASK) | (acp->ECW & EDCF_ECWMIN_MASK);\r
705 acp->ECW = ((acp->ECW & EDCF_ECWMAX_MASK) | (ecwmin & EDCF_ECWMIN_MASK));\r
706\r
96e81bc5 707 CONFIG_TRACE(("%s: mod aci %d aifsn %d ecwmin %d ecwmax %d size %d\n", __FUNCTION__,\r
7a4fa002 708 acp->ACI, acp->ACI&EDCF_AIFSN_MASK,\r
709 acp->ECW&EDCF_ECWMIN_MASK, (acp->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,\r
710 sizeof(edcf_acparam_t)));\r
711\r
712 /*\r
713 * Now use buf as an output buffer.\r
714 * Put WME acparams after "wme_ac\0" in buf.\r
715 * NOTE: only one of the four ACs can be set at a time.\r
716 */\r
717 bcm_mkiovar("wme_ac_sta", (char*)acp, sizeof(edcf_acparam_t), iovbuf,\r
718 sizeof(iovbuf));\r
719 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) < 0) {\r
720 CONFIG_ERROR(("%s: wme_ac_sta setting failed %d\n", __FUNCTION__, bcmerror));\r
721 return;\r
722 }\r
723}\r
724\r
725void\r
726dhd_conf_set_wme(dhd_pub_t *dhd)\r
727{\r
728 edcf_acparam_t acparam_cur[AC_COUNT];\r
729\r
730 if (dhd && dhd->conf) {\r
731 if (!dhd->conf->force_wme_ac) {\r
732 CONFIG_TRACE(("%s: force_wme_ac is not enabled %d\n",\r
733 __FUNCTION__, dhd->conf->force_wme_ac));\r
734 return;\r
735 }\r
736\r
96e81bc5 737 CONFIG_TRACE(("%s: Before change:\n", __FUNCTION__));\r
7a4fa002 738 dhd_conf_get_wme(dhd, acparam_cur);\r
739\r
740 dhd_conf_update_wme(dhd, &acparam_cur[AC_BK], AC_BK);\r
741 dhd_conf_update_wme(dhd, &acparam_cur[AC_BE], AC_BE);\r
742 dhd_conf_update_wme(dhd, &acparam_cur[AC_VI], AC_VI);\r
743 dhd_conf_update_wme(dhd, &acparam_cur[AC_VO], AC_VO);\r
744\r
96e81bc5 745 CONFIG_TRACE(("%s: After change:\n", __FUNCTION__));\r
7a4fa002 746 dhd_conf_get_wme(dhd, acparam_cur);\r
747 } else {\r
748 CONFIG_ERROR(("%s: dhd or conf is NULL\n", __FUNCTION__));\r
749 }\r
750\r
751 return;\r
752}\r
753\r
754void\r
755dhd_conf_set_stbc(dhd_pub_t *dhd)\r
756{\r
757 int bcmerror = -1;\r
758 char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */\r
759 uint stbc = 0;\r
760\r
761 if (dhd_bus_chip_id(dhd) == BCM4324_CHIP_ID) {\r
762 if (dhd->conf->stbc >= 0) {\r
763 stbc = (uint)dhd->conf->stbc;\r
764 printf("%s: set stbc_tx %d\n", __FUNCTION__, stbc);\r
96e81bc5 765 bcm_mkiovar("stbc_tx", (char *)&stbc, 4, iovbuf, sizeof(iovbuf));\r
766 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)\r
7a4fa002 767 CONFIG_ERROR(("%s: stbc_tx setting failed %d\n", __FUNCTION__, bcmerror));\r
768\r
769 printf("%s: set stbc_rx %d\n", __FUNCTION__, stbc);\r
96e81bc5 770 bcm_mkiovar("stbc_rx", (char *)&stbc, 4, iovbuf, sizeof(iovbuf));\r
771 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)\r
7a4fa002 772 CONFIG_ERROR(("%s: stbc_rx setting failed %d\n", __FUNCTION__, bcmerror));\r
773 }\r
774 }\r
775}\r
776\r
777void\r
778dhd_conf_set_phyoclscdenable(dhd_pub_t *dhd)\r
779{\r
780 int bcmerror = -1;\r
781 char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */\r
782 uint phy_oclscdenable = 0;\r
783\r
784 if (dhd_bus_chip_id(dhd) == BCM4324_CHIP_ID) {\r
785 if (dhd->conf->phy_oclscdenable >= 0) {\r
786 phy_oclscdenable = (uint)dhd->conf->phy_oclscdenable;\r
787 printf("%s: set stbc_tx %d\n", __FUNCTION__, phy_oclscdenable);\r
96e81bc5 788 bcm_mkiovar("phy_oclscdenable", (char *)&phy_oclscdenable, 4, iovbuf, sizeof(iovbuf));\r
789 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)\r
7a4fa002 790 CONFIG_ERROR(("%s: stbc_tx setting failed %d\n", __FUNCTION__, bcmerror));\r
791 }\r
693cd89a
ML
792 }\r
793}\r
794\r
96e81bc5 795#ifdef PKT_FILTER_SUPPORT\r
796void\r
797dhd_conf_add_pkt_filter(dhd_pub_t *dhd)\r
798{\r
799 int i;\r
800\r
801 /*\r
802 All pkt: pkt_filter_add=99 0 0 0 0x000000000000 0xFFFFFFFFFFFF\r
803 Netbios pkt: 120 0 0 12 0xFFFF000000000000000000FF00000000000000000000000000FF 0x0800000000000000000000110000000000000000000000000089\r
804 */\r
805 for(i=0; i<dhd->conf->pkt_filter_add.count; i++) {\r
806 dhd->pktfilter[i+dhd->pktfilter_count] = dhd->conf->pkt_filter_add.filter[i];\r
807 printf("%s: %s\n", __FUNCTION__, dhd->pktfilter[i+dhd->pktfilter_count]);\r
808 }\r
809 dhd->pktfilter_count += i;\r
810}\r
811\r
812bool\r
813dhd_conf_del_pkt_filter(dhd_pub_t *dhd, uint32 id)\r
814{\r
815 int i;\r
816\r
817 for(i=0; i<dhd->conf->pkt_filter_del.count; i++) {\r
818 if (id == dhd->conf->pkt_filter_del.id[i]) {\r
819 printf("%s: %d\n", __FUNCTION__, dhd->conf->pkt_filter_del.id[i]);\r
820 return true;\r
821 }\r
822 }\r
823 return false;\r
824}\r
825\r
826void\r
827dhd_conf_discard_pkt_filter(dhd_pub_t *dhd)\r
828{\r
829 dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = NULL;\r
830 dhd->pktfilter[DHD_BROADCAST_FILTER_NUM] = "101 0 0 0 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF";\r
831 dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = "102 0 0 0 0xFFFFFF 0x01005E";\r
832 dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = "103 0 0 0 0xFFFF 0x3333";\r
833 dhd->pktfilter[DHD_MDNS_FILTER_NUM] = NULL;\r
834 /* Do not enable ARP to pkt filter if dhd_master_mode is false.*/\r
835 dhd->pktfilter[DHD_ARP_FILTER_NUM] = NULL;\r
836\r
837 /* IPv4 broadcast address XXX.XXX.XXX.255 */\r
838 dhd->pktfilter[dhd->pktfilter_count] = "110 0 0 12 0xFFFF00000000000000000000000000000000000000FF 0x080000000000000000000000000000000000000000FF";\r
839 dhd->pktfilter_count++;\r
840 /* discard IPv4 multicast address 224.0.0.0/4 */\r
841 dhd->pktfilter[dhd->pktfilter_count] = "111 0 0 12 0xFFFF00000000000000000000000000000000F0 0x080000000000000000000000000000000000E0";\r
842 dhd->pktfilter_count++;\r
843 /* discard IPv6 multicast address FF00::/8 */\r
844 dhd->pktfilter[dhd->pktfilter_count] = "112 0 0 12 0xFFFF000000000000000000000000000000000000000000000000FF 0x86DD000000000000000000000000000000000000000000000000FF";\r
845 dhd->pktfilter_count++;\r
80e122a3 846 /* discard Netbios pkt */\r
847 dhd->pktfilter[dhd->pktfilter_count] = "120 0 0 12 0xFFFF000000000000000000FF000000000000000000000000FFFF 0x0800000000000000000000110000000000000000000000000089";\r
848 dhd->pktfilter_count++;\r
96e81bc5 849\r
850}\r
851#endif /* PKT_FILTER_SUPPORT */\r
852\r
853void\r
854dhd_conf_set_srl(dhd_pub_t *dhd)\r
855{\r
856 int bcmerror = -1;\r
857 uint srl = 0;\r
858\r
859 if (dhd->conf->srl >= 0) {\r
860 srl = (uint)dhd->conf->srl;\r
861 printf("%s: set srl %d\n", __FUNCTION__, srl);\r
862 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_SRL, &srl , sizeof(srl), true, 0)) < 0)\r
863 CONFIG_ERROR(("%s: WLC_SET_SRL setting failed %d\n", __FUNCTION__, bcmerror));\r
864 }\r
865}\r
866\r
867void\r
868dhd_conf_set_lrl(dhd_pub_t *dhd)\r
869{\r
870 int bcmerror = -1;\r
871 uint lrl = 0;\r
872\r
873 if (dhd->conf->lrl >= 0) {\r
874 lrl = (uint)dhd->conf->lrl;\r
875 printf("%s: set lrl %d\n", __FUNCTION__, lrl);\r
876 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_LRL, &lrl , sizeof(lrl), true, 0)) < 0)\r
877 CONFIG_ERROR(("%s: WLC_SET_LRL setting failed %d\n", __FUNCTION__, bcmerror));\r
878 }\r
879}\r
880\r
881void\r
882dhd_conf_set_glom(dhd_pub_t *dhd)\r
883{\r
884 int bcmerror = -1;\r
885 char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */\r
886 uint32 bus_txglom = 0;\r
887\r
888 if (dhd->conf->bus_txglom) {\r
889 bus_txglom = (uint)dhd->conf->bus_txglom;\r
890 printf("%s: set bus:txglom %d\n", __FUNCTION__, bus_txglom);\r
891 bcm_mkiovar("bus:txglom", (char *)&bus_txglom, 4, iovbuf, sizeof(iovbuf));\r
892 dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);\r
893 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)\r
894 CONFIG_ERROR(("%s: bus:txglom setting failed %d\n", __FUNCTION__, bcmerror));\r
895 }\r
896}\r
897\r
898void\r
899dhd_conf_set_ampdu_ba_wsize(dhd_pub_t *dhd)\r
900{\r
901 int bcmerror = -1;\r
902 char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */\r
903 uint32 ampdu_ba_wsize = dhd->conf->ampdu_ba_wsize;\r
904\r
905 /* Set ampdu ba wsize */\r
906 if (dhd_bus_chip_id(dhd) == BCM4339_CHIP_ID && ampdu_ba_wsize > 0) {\r
907 printf("%s: set ampdu_ba_wsize %d\n", __FUNCTION__, ampdu_ba_wsize);\r
908 bcm_mkiovar("ampdu_ba_wsize", (char *)&ampdu_ba_wsize, 4, iovbuf, sizeof(iovbuf));\r
909 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,\r
910 sizeof(iovbuf), TRUE, 0)) < 0) {\r
911 DHD_ERROR(("%s Set ampdu_ba_wsize to %d failed %d\n",\r
912 __FUNCTION__, ampdu_ba_wsize, bcmerror));\r
913 }\r
914 }\r
915}\r
916\r
80e122a3 917void\r
918dhd_conf_set_spect(dhd_pub_t *dhd)\r
919{\r
920 int bcmerror = -1;\r
921 int spect = 0;\r
922\r
923 if (dhd->conf->spect >= 0) {\r
924 spect = (uint)dhd->conf->spect;\r
925 printf("%s: set spect %d\n", __FUNCTION__, spect);\r
926 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_SPECT_MANAGMENT, &spect , sizeof(spect), true, 0)) < 0)\r
927 CONFIG_ERROR(("%s: WLC_SET_SPECT_MANAGMENT setting failed %d\n", __FUNCTION__, bcmerror));\r
928 }\r
929}\r
930\r
693cd89a
ML
931unsigned int\r
932process_config_vars(char *varbuf, unsigned int len, char *pickbuf, char *param)\r
933{\r
96e81bc5 934 bool findNewline, changenewline=FALSE, pick=FALSE;\r
693cd89a
ML
935 int column;\r
936 unsigned int n, pick_column=0;\r
937\r
938 findNewline = FALSE;\r
939 column = 0;\r
940\r
941 for (n = 0; n < len; n++) {\r
942 if (varbuf[n] == '\r')\r
943 continue;\r
96e81bc5 944 if ((findNewline || changenewline) && varbuf[n] != '\n')\r
693cd89a
ML
945 continue;\r
946 findNewline = FALSE;\r
947 if (varbuf[n] == '#') {\r
948 findNewline = TRUE;\r
949 continue;\r
950 }\r
96e81bc5 951 if (varbuf[n] == '\\') {\r
952 changenewline = TRUE;\r
953 continue;\r
954 }\r
955 if (!changenewline && varbuf[n] == '\n') {\r
693cd89a
ML
956 if (column == 0)\r
957 continue;\r
958 column = 0;\r
959 continue;\r
960 }\r
96e81bc5 961 if (changenewline && varbuf[n] == '\n') {\r
962 changenewline = FALSE;\r
963 continue;\r
964 }\r
693cd89a
ML
965 if (!memcmp(&varbuf[n], param, strlen(param)) && column==0) {\r
966 pick = TRUE;\r
967 column = strlen(param);\r
968 n += column;\r
969 pick_column = 0;\r
970 } else {\r
971 if (pick && column==0)\r
972 pick = FALSE;\r
973 else\r
974 column++;\r
975 }\r
976 if (pick) {\r
96e81bc5 977 if (varbuf[n] == 0x9)\r
978 continue;\r
979 if (pick_column>0 && pickbuf[pick_column-1]==' ' && varbuf[n]==' ')\r
980 continue;\r
693cd89a
ML
981 pickbuf[pick_column] = varbuf[n];\r
982 pick_column++;\r
983 }\r
984 }\r
985\r
986 return pick_column;\r
987}\r
988\r
96e81bc5 989void\r
990dhd_conf_read_log_level(dhd_pub_t *dhd, char *bufp, uint len)\r
991{\r
992 uint len_val;\r
993 char pick[MAXSZ_BUF];\r
994\r
995 /* Process dhd_msglevel */\r
996 memset(pick, 0, MAXSZ_BUF);\r
997 len_val = process_config_vars(bufp, len, pick, "msglevel=");\r
998 if (len_val) {\r
999 dhd_msg_level = (int)simple_strtol(pick, NULL, 0);\r
1000 printf("%s: dhd_msg_level = 0x%X\n", __FUNCTION__, dhd_msg_level);\r
1001 }\r
1002 /* Process sd_msglevel */\r
1003 memset(pick, 0, MAXSZ_BUF);\r
1004 len_val = process_config_vars(bufp, len, pick, "sd_msglevel=");\r
1005 if (len_val) {\r
1006 sd_msglevel = (int)simple_strtol(pick, NULL, 0);\r
1007 printf("%s: sd_msglevel = 0x%X\n", __FUNCTION__, sd_msglevel);\r
1008 }\r
1009 /* Process android_msg_level */\r
1010 memset(pick, 0, MAXSZ_BUF);\r
1011 len_val = process_config_vars(bufp, len, pick, "android_msg_level=");\r
1012 if (len_val) {\r
1013 android_msg_level = (int)simple_strtol(pick, NULL, 0);\r
1014 printf("%s: android_msg_level = 0x%X\n", __FUNCTION__, android_msg_level);\r
1015 }\r
1016 /* Process config_msg_level */\r
1017 memset(pick, 0, MAXSZ_BUF);\r
1018 len_val = process_config_vars(bufp, len, pick, "config_msg_level=");\r
1019 if (len_val) {\r
1020 config_msg_level = (int)simple_strtol(pick, NULL, 0);\r
1021 printf("%s: config_msg_level = 0x%X\n", __FUNCTION__, config_msg_level);\r
1022 }\r
1023#ifdef WL_CFG80211\r
1024 /* Process wl_dbg_level */\r
1025 memset(pick, 0, MAXSZ_BUF);\r
1026 len_val = process_config_vars(bufp, len, pick, "wl_dbg_level=");\r
1027 if (len_val) {\r
1028 wl_dbg_level = (int)simple_strtol(pick, NULL, 0);\r
1029 printf("%s: wl_dbg_level = 0x%X\n", __FUNCTION__, wl_dbg_level);\r
1030 }\r
1031#endif\r
1032#if defined(WL_WIRELESS_EXT)\r
1033 /* Process iw_msg_level */\r
1034 memset(pick, 0, MAXSZ_BUF);\r
1035 len_val = process_config_vars(bufp, len, pick, "iw_msg_level=");\r
1036 if (len_val) {\r
1037 iw_msg_level = (int)simple_strtol(pick, NULL, 0);\r
1038 printf("%s: iw_msg_level = 0x%X\n", __FUNCTION__, iw_msg_level);\r
1039 }\r
1040#endif\r
1041}\r
1042\r
1043/*\r
1044 * [fw_by_mac]:\r
1045 * fw_by_mac=[fw_mac_num] \\r
1046 * [fw_name1] [mac_num1] [oui1-1] [nic_start1-1] [nic_end1-1] \\r
1047 * [oui1-1] [nic_start1-1] [nic_end1-1]... \\r
1048 * [oui1-n] [nic_start1-n] [nic_end1-n] \\r
1049 * [fw_name2] [mac_num2] [oui2-1] [nic_start2-1] [nic_end2-1] \\r
1050 * [oui2-1] [nic_start2-1] [nic_end2-1]... \\r
1051 * [oui2-n] [nic_start2-n] [nic_end2-n] \\r
1052 * Ex: fw_by_mac=2 \\r
1053 * fw_bcmdhd1.bin 2 0x0022F4 0xE85408 0xE8549D 0x983B16 0x3557A9 0x35582A \\r
1054 * fw_bcmdhd2.bin 3 0x0022F4 0xE85408 0xE8549D 0x983B16 0x3557A9 0x35582A \\r
1055 * 0x983B16 0x916157 0x916487\r
1056 * [nv_by_mac]: The same format as fw_by_mac\r
1057 *\r
1058*/\r
1059\r
693cd89a 1060int\r
96e81bc5 1061dhd_conf_read_config(dhd_pub_t *dhd)\r
693cd89a 1062{\r
96e81bc5 1063 int bcmerror = -1, i, j;\r
693cd89a
ML
1064 uint len, len_val;\r
1065 void * image = NULL;\r
1066 char * memblock = NULL;\r
1067 char *bufp, pick[MAXSZ_BUF], *pch, *pick_tmp;\r
1068 char *pconf_path;\r
1069 bool conf_file_exists;\r
96e81bc5 1070 wl_mac_list_t *mac_list;\r
1071 wl_mac_range_t *mac_range;\r
693cd89a
ML
1072\r
1073 pconf_path = dhd->conf_path;\r
1074\r
1075 conf_file_exists = ((pconf_path != NULL) && (pconf_path[0] != '\0'));\r
1076 if (!conf_file_exists)\r
1077 return (0);\r
1078\r
1079 if (conf_file_exists) {\r
1080 image = dhd_os_open_image(pconf_path);\r
1081 if (image == NULL) {\r
1082 printk("%s: Ignore config file %s\n", __FUNCTION__, pconf_path);\r
1083 goto err;\r
1084 }\r
1085 }\r
1086\r
1087 memblock = MALLOC(dhd->osh, MAXSZ_CONFIG);\r
1088 if (memblock == NULL) {\r
1089 CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
96e81bc5 1090 __FUNCTION__, MAXSZ_CONFIG));\r
693cd89a
ML
1091 goto err;\r
1092 }\r
1093\r
96e81bc5 1094 /* Read variables */\r
693cd89a
ML
1095 if (conf_file_exists) {\r
1096 len = dhd_os_get_image_block(memblock, MAXSZ_CONFIG, image);\r
1097 }\r
1098 if (len > 0 && len < MAXSZ_CONFIG) {\r
1099 bufp = (char *)memblock;\r
1100 bufp[len] = 0;\r
1101\r
96e81bc5 1102 /* Process log_level */\r
1103 dhd_conf_read_log_level(dhd, bufp, len);\r
1104\r
1105 /* Process fw_by_mac */\r
1106 memset(pick, 0, MAXSZ_BUF);\r
1107 len_val = process_config_vars(bufp, len, pick, "fw_by_mac=");\r
1108 if (len_val) {\r
1109 pick_tmp = pick;\r
1110 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1111 dhd->conf->fw_by_mac.count = (uint32)simple_strtol(pch, NULL, 0);\r
1112 if (!(mac_list = kmalloc(sizeof(wl_mac_list_t)*dhd->conf->fw_by_mac.count, GFP_KERNEL))) {\r
1113 dhd->conf->fw_by_mac.count = 0;\r
1114 CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));\r
1115 }\r
1116 printf("%s: fw_count=%d\n", __FUNCTION__, dhd->conf->fw_by_mac.count);\r
1117 dhd->conf->fw_by_mac.m_mac_list_head = mac_list;\r
1118 for (i=0; i<dhd->conf->fw_by_mac.count; i++) {\r
1119 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1120 strcpy(mac_list[i].name, pch);\r
1121 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1122 mac_list[i].count = (uint32)simple_strtol(pch, NULL, 0);\r
1123 printf("%s: name=%s, mac_count=%d\n", __FUNCTION__,\r
1124 mac_list[i].name, mac_list[i].count);\r
1125 if (!(mac_range = kmalloc(sizeof(wl_mac_range_t)*mac_list[i].count, GFP_KERNEL))) {\r
1126 mac_list[i].count = 0;\r
1127 CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));\r
1128 break;\r
1129 }\r
1130 mac_list[i].mac = mac_range;\r
1131 for (j=0; j<mac_list[i].count; j++) {\r
1132 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1133 mac_range[j].oui = (uint32)simple_strtol(pch, NULL, 0);\r
1134 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1135 mac_range[j].nic_start = (uint32)simple_strtol(pch, NULL, 0);\r
1136 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1137 mac_range[j].nic_end = (uint32)simple_strtol(pch, NULL, 0);\r
1138 printf("%s: oui=0x%06X, nic_start=0x%06X, nic_end=0x%06X\n",\r
1139 __FUNCTION__, mac_range[j].oui,\r
1140 mac_range[j].nic_start, mac_range[j].nic_end);\r
1141 }\r
1142 }\r
1143 }\r
1144\r
1145 /* Process nv_by_mac */\r
1146 memset(pick, 0, MAXSZ_BUF);\r
1147 len_val = process_config_vars(bufp, len, pick, "nv_by_mac=");\r
1148 if (len_val) {\r
1149 pick_tmp = pick;\r
1150 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1151 dhd->conf->nv_by_mac.count = (uint32)simple_strtol(pch, NULL, 0);\r
1152 if (!(mac_list = kmalloc(sizeof(wl_mac_list_t)*dhd->conf->nv_by_mac.count, GFP_KERNEL))) {\r
1153 dhd->conf->nv_by_mac.count = 0;\r
1154 CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));\r
1155 }\r
1156 printf("%s: nv_count=%d\n", __FUNCTION__, dhd->conf->nv_by_mac.count);\r
1157 dhd->conf->nv_by_mac.m_mac_list_head = mac_list;\r
1158 for (i=0; i<dhd->conf->nv_by_mac.count; i++) {\r
1159 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1160 strcpy(mac_list[i].name, pch);\r
1161 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1162 mac_list[i].count = (uint32)simple_strtol(pch, NULL, 0);\r
1163 printf("%s: name=%s, mac_count=%d\n", __FUNCTION__,\r
1164 mac_list[i].name, mac_list[i].count);\r
1165 if (!(mac_range = kmalloc(sizeof(wl_mac_range_t)*mac_list[i].count, GFP_KERNEL))) {\r
1166 mac_list[i].count = 0;\r
1167 CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));\r
1168 break;\r
1169 }\r
1170 mac_list[i].mac = mac_range;\r
1171 for (j=0; j<mac_list[i].count; j++) {\r
1172 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1173 mac_range[j].oui = (uint32)simple_strtol(pch, NULL, 0);\r
1174 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1175 mac_range[j].nic_start = (uint32)simple_strtol(pch, NULL, 0);\r
1176 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1177 mac_range[j].nic_end = (uint32)simple_strtol(pch, NULL, 0);\r
1178 printf("%s: oui=0x%06X, nic_start=0x%06X, nic_end=0x%06X\n",\r
1179 __FUNCTION__, mac_range[j].oui,\r
1180 mac_range[j].nic_start, mac_range[j].nic_end);\r
1181 }\r
1182 }\r
1183 }\r
1184\r
693cd89a
ML
1185 /* Process firmware path */\r
1186 memset(pick, 0, MAXSZ_BUF);\r
1187 len_val = process_config_vars(bufp, len, pick, "fw_path=");\r
1188 if (len_val) {\r
1189 memcpy(dhd->conf->fw_path, pick, len_val);\r
1190 printf("%s: fw_path = %s\n", __FUNCTION__, dhd->conf->fw_path);\r
1191 }\r
1192\r
1193 /* Process nvram path */\r
1194 memset(pick, 0, MAXSZ_BUF);\r
1195 len_val = process_config_vars(bufp, len, pick, "nv_path=");\r
1196 if (len_val) {\r
1197 memcpy(dhd->conf->nv_path, pick, len_val);\r
1198 printf("%s: nv_path = %s\n", __FUNCTION__, dhd->conf->nv_path);\r
1199 }\r
1200\r
1201 /* Process band */\r
1202 memset(pick, 0, MAXSZ_BUF);\r
1203 len_val = process_config_vars(bufp, len, pick, "band=");\r
1204 if (len_val) {\r
1205 if (!strncmp(pick, "b", len_val))\r
1206 dhd->conf->band = WLC_BAND_2G;\r
7a4fa002 1207 else if (!strncmp(pick, "a", len_val))\r
1208 dhd->conf->band = WLC_BAND_5G;\r
1209 else\r
1210 dhd->conf->band = WLC_BAND_AUTO;\r
693cd89a
ML
1211 printf("%s: band = %d\n", __FUNCTION__, dhd->conf->band);\r
1212 }\r
1213\r
96e81bc5 1214 /* Process bandwidth */\r
1215 memset(pick, 0, MAXSZ_BUF);\r
80e122a3 1216 len_val = process_config_vars(bufp, len, pick, "mimo_bw_cap=");\r
96e81bc5 1217 if (len_val) {\r
80e122a3 1218 dhd->conf->mimo_bw_cap = (uint)simple_strtol(pick, NULL, 10);\r
1219 printf("%s: mimo_bw_cap = %d\n", __FUNCTION__, dhd->conf->mimo_bw_cap);\r
96e81bc5 1220 }\r
1221\r
693cd89a
ML
1222 /* Process country code */\r
1223 memset(pick, 0, MAXSZ_BUF);\r
1224 len_val = process_config_vars(bufp, len, pick, "ccode=");\r
1225 if (len_val) {\r
1226 memset(&dhd->conf->cspec, 0, sizeof(wl_country_t));\r
1227 memcpy(dhd->conf->cspec.country_abbrev, pick, len_val);\r
1228 memcpy(dhd->conf->cspec.ccode, pick, len_val);\r
1229 memset(pick, 0, MAXSZ_BUF);\r
1230 len_val = process_config_vars(bufp, len, pick, "regrev=");\r
1231 if (len_val)\r
1232 dhd->conf->cspec.rev = (int32)simple_strtol(pick, NULL, 10);\r
1233 }\r
1234\r
1235 /* Process channels */\r
1236 memset(pick, 0, MAXSZ_BUF);\r
1237 len_val = process_config_vars(bufp, len, pick, "channels=");\r
1238 pick_tmp = pick;\r
1239 if (len_val) {\r
1240 pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
1241 i=0;\r
1242 while (pch != NULL && i<WL_NUMCHANNELS) {\r
1243 dhd->conf->channels.channel[i] = (uint32)simple_strtol(pch, NULL, 10);\r
1244 pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
1245 i++;\r
1246 }\r
1247 dhd->conf->channels.count = i;\r
1248 printf("%s: channels = ", __FUNCTION__);\r
1249 for (i=0; i<dhd->conf->channels.count; i++)\r
1250 printf("%d ", dhd->conf->channels.channel[i]);\r
1251 printf("\n");\r
1252 }\r
1253\r
1254 /* Process roam */\r
1255 memset(pick, 0, MAXSZ_BUF);\r
1256 len_val = process_config_vars(bufp, len, pick, "roam_off=");\r
1257 if (len_val) {\r
1258 if (!strncmp(pick, "0", len_val))\r
1259 dhd->conf->roam_off = 0;\r
1260 else\r
1261 dhd->conf->roam_off = 1;\r
1262 printf("%s: roam_off = %d\n", __FUNCTION__, dhd->conf->roam_off);\r
1263 }\r
1264\r
1265 memset(pick, 0, MAXSZ_BUF);\r
1266 len_val = process_config_vars(bufp, len, pick, "roam_off_suspend=");\r
1267 if (len_val) {\r
1268 if (!strncmp(pick, "0", len_val))\r
1269 dhd->conf->roam_off_suspend = 0;\r
1270 else\r
1271 dhd->conf->roam_off_suspend = 1;\r
1272 printf("%s: roam_off_suspend = %d\n", __FUNCTION__,\r
1273 dhd->conf->roam_off_suspend);\r
1274 }\r
1275\r
1276 if (!dhd->conf->roam_off || !dhd->conf->roam_off_suspend) {\r
1277 memset(pick, 0, MAXSZ_BUF);\r
1278 len_val = process_config_vars(bufp, len, pick, "roam_trigger=");\r
1279 if (len_val)\r
1280 dhd->conf->roam_trigger[0] = (int)simple_strtol(pick, NULL, 10);\r
1281 printf("%s: roam_trigger = %d\n", __FUNCTION__,\r
1282 dhd->conf->roam_trigger[0]);\r
1283\r
1284 memset(pick, 0, MAXSZ_BUF);\r
1285 len_val = process_config_vars(bufp, len, pick, "roam_scan_period=");\r
1286 if (len_val)\r
1287 dhd->conf->roam_scan_period[0] = (int)simple_strtol(pick, NULL, 10);\r
1288 printf("%s: roam_scan_period = %d\n", __FUNCTION__,\r
1289 dhd->conf->roam_scan_period[0]);\r
1290\r
1291 memset(pick, 0, MAXSZ_BUF);\r
1292 len_val = process_config_vars(bufp, len, pick, "roam_delta=");\r
1293 if (len_val)\r
1294 dhd->conf->roam_delta[0] = (int)simple_strtol(pick, NULL, 10);\r
1295 printf("%s: roam_delta = %d\n", __FUNCTION__, dhd->conf->roam_delta[0]);\r
1296\r
1297 memset(pick, 0, MAXSZ_BUF);\r
1298 len_val = process_config_vars(bufp, len, pick, "fullroamperiod=");\r
1299 if (len_val)\r
1300 dhd->conf->fullroamperiod = (int)simple_strtol(pick, NULL, 10);\r
1301 printf("%s: fullroamperiod = %d\n", __FUNCTION__,\r
1302 dhd->conf->fullroamperiod);\r
1303 }\r
1304\r
693cd89a
ML
1305 /* Process keep alive period */\r
1306 memset(pick, 0, MAXSZ_BUF);\r
1307 len_val = process_config_vars(bufp, len, pick, "keep_alive_period=");\r
1308 if (len_val) {\r
1309 dhd->conf->keep_alive_period = (int)simple_strtol(pick, NULL, 10);\r
1310 printf("%s: keep_alive_period = %d\n", __FUNCTION__,\r
1311 dhd->conf->keep_alive_period);\r
1312 }\r
1313\r
7a4fa002 1314 /* Process WMM parameters */\r
1315 memset(pick, 0, MAXSZ_BUF);\r
1316 len_val = process_config_vars(bufp, len, pick, "force_wme_ac=");\r
1317 if (len_val) {\r
1318 dhd->conf->force_wme_ac = (int)simple_strtol(pick, NULL, 10);\r
1319 printf("%s: force_wme_ac = %d\n", __FUNCTION__, dhd->conf->force_wme_ac);\r
1320 }\r
1321\r
1322 if (dhd->conf->force_wme_ac) {\r
1323 memset(pick, 0, MAXSZ_BUF);\r
1324 len_val = process_config_vars(bufp, len, pick, "bk_aifsn=");\r
1325 if (len_val) {\r
1326 dhd->conf->wme.aifsn[AC_BK] = (int)simple_strtol(pick, NULL, 10);\r
1327 printf("%s: AC_BK aifsn = %d\n", __FUNCTION__, dhd->conf->wme.aifsn[AC_BK]);\r
1328 }\r
1329\r
1330 memset(pick, 0, MAXSZ_BUF);\r
1331 len_val = process_config_vars(bufp, len, pick, "bk_cwmin=");\r
1332 if (len_val) {\r
1333 dhd->conf->wme.cwmin[AC_BK] = (int)simple_strtol(pick, NULL, 10);\r
1334 printf("%s: AC_BK cwmin = %d\n", __FUNCTION__, dhd->conf->wme.cwmin[AC_BK]);\r
1335 }\r
1336\r
1337 memset(pick, 0, MAXSZ_BUF);\r
1338 len_val = process_config_vars(bufp, len, pick, "bk_cwmax=");\r
1339 if (len_val) {\r
1340 dhd->conf->wme.cwmax[AC_BK] = (int)simple_strtol(pick, NULL, 10);\r
1341 printf("%s: AC_BK cwmax = %d\n", __FUNCTION__, dhd->conf->wme.cwmax[AC_BK]);\r
1342 }\r
1343\r
1344 memset(pick, 0, MAXSZ_BUF);\r
1345 len_val = process_config_vars(bufp, len, pick, "be_aifsn=");\r
1346 if (len_val) {\r
1347 dhd->conf->wme.aifsn[AC_BE] = (int)simple_strtol(pick, NULL, 10);\r
1348 printf("%s: AC_BE aifsn = %d\n", __FUNCTION__, dhd->conf->wme.aifsn[AC_BE]);\r
1349 }\r
1350\r
1351 memset(pick, 0, MAXSZ_BUF);\r
1352 len_val = process_config_vars(bufp, len, pick, "be_cwmin=");\r
1353 if (len_val) {\r
1354 dhd->conf->wme.cwmin[AC_BE] = (int)simple_strtol(pick, NULL, 10);\r
1355 printf("%s: AC_BE cwmin = %d\n", __FUNCTION__, dhd->conf->wme.cwmin[AC_BE]);\r
1356 }\r
1357\r
1358 memset(pick, 0, MAXSZ_BUF);\r
1359 len_val = process_config_vars(bufp, len, pick, "be_cwmax=");\r
1360 if (len_val) {\r
1361 dhd->conf->wme.cwmax[AC_BE] = (int)simple_strtol(pick, NULL, 10);\r
1362 printf("%s: AC_BE cwmax = %d\n", __FUNCTION__, dhd->conf->wme.cwmax[AC_BE]);\r
1363 }\r
1364\r
1365 memset(pick, 0, MAXSZ_BUF);\r
1366 len_val = process_config_vars(bufp, len, pick, "vi_aifsn=");\r
1367 if (len_val) {\r
1368 dhd->conf->wme.aifsn[AC_VI] = (int)simple_strtol(pick, NULL, 10);\r
1369 printf("%s: AC_VI aifsn = %d\n", __FUNCTION__, dhd->conf->wme.aifsn[AC_VI]);\r
1370 }\r
1371\r
1372 memset(pick, 0, MAXSZ_BUF);\r
1373 len_val = process_config_vars(bufp, len, pick, "vi_cwmin=");\r
1374 if (len_val) {\r
1375 dhd->conf->wme.cwmin[AC_VI] = (int)simple_strtol(pick, NULL, 10);\r
1376 printf("%s: AC_VI cwmin = %d\n", __FUNCTION__, dhd->conf->wme.cwmin[AC_VI]);\r
1377 }\r
1378\r
1379 memset(pick, 0, MAXSZ_BUF);\r
1380 len_val = process_config_vars(bufp, len, pick, "vi_cwmax=");\r
1381 if (len_val) {\r
1382 dhd->conf->wme.cwmax[AC_VI] = (int)simple_strtol(pick, NULL, 10);\r
1383 printf("%s: AC_VI cwmax = %d\n", __FUNCTION__, dhd->conf->wme.cwmax[AC_VI]);\r
1384 }\r
1385\r
1386 memset(pick, 0, MAXSZ_BUF);\r
1387 len_val = process_config_vars(bufp, len, pick, "vo_aifsn=");\r
1388 if (len_val) {\r
1389 dhd->conf->wme.aifsn[AC_VO] = (int)simple_strtol(pick, NULL, 10);\r
1390 printf("%s: AC_VO aifsn = %d\n", __FUNCTION__, dhd->conf->wme.aifsn[AC_VO]);\r
1391 }\r
1392\r
1393 memset(pick, 0, MAXSZ_BUF);\r
1394 len_val = process_config_vars(bufp, len, pick, "vo_cwmin=");\r
1395 if (len_val) {\r
1396 dhd->conf->wme.cwmin[AC_VO] = (int)simple_strtol(pick, NULL, 10);\r
1397 printf("%s: AC_VO cwmin = %d\n", __FUNCTION__, dhd->conf->wme.cwmin[AC_VO]);\r
1398 }\r
1399\r
1400 memset(pick, 0, MAXSZ_BUF);\r
1401 len_val = process_config_vars(bufp, len, pick, "vo_cwmax=");\r
1402 if (len_val) {\r
1403 dhd->conf->wme.cwmax[AC_VO] = (int)simple_strtol(pick, NULL, 10);\r
1404 printf("%s: AC_VO cwmax = %d\n", __FUNCTION__, dhd->conf->wme.cwmax[AC_VO]);\r
1405 }\r
1406 }\r
1407\r
1408 /* Process STBC parameters */\r
1409 memset(pick, 0, MAXSZ_BUF);\r
1410 len_val = process_config_vars(bufp, len, pick, "stbc=");\r
1411 if (len_val) {\r
1412 dhd->conf->stbc = (int)simple_strtol(pick, NULL, 10);\r
1413 printf("%s: stbc = %d\n", __FUNCTION__, dhd->conf->stbc);\r
1414 }\r
1415\r
1416 /* Process phy_oclscdenable parameters */\r
1417 memset(pick, 0, MAXSZ_BUF);\r
1418 len_val = process_config_vars(bufp, len, pick, "phy_oclscdenable=");\r
1419 if (len_val) {\r
1420 dhd->conf->phy_oclscdenable = (int)simple_strtol(pick, NULL, 10);\r
1421 printf("%s: phy_oclscdenable = %d\n", __FUNCTION__, dhd->conf->phy_oclscdenable);\r
1422 }\r
1423\r
96e81bc5 1424 /* Process dhd_doflow parameters */\r
1425 memset(pick, 0, MAXSZ_BUF);\r
1426 len_val = process_config_vars(bufp, len, pick, "dhd_doflow=");\r
1427 if (len_val) {\r
1428 if (!strncmp(pick, "0", len_val))\r
1429 dhd_doflow = FALSE;\r
1430 else\r
1431 dhd_doflow = TRUE;\r
1432 printf("%s: dhd_doflow = %d\n", __FUNCTION__, dhd_doflow);\r
1433 }\r
1434\r
1435 /* Process dhd_master_mode parameters */\r
1436 memset(pick, 0, MAXSZ_BUF);\r
1437 len_val = process_config_vars(bufp, len, pick, "dhd_master_mode=");\r
1438 if (len_val) {\r
1439 if (!strncmp(pick, "0", len_val))\r
1440 dhd_master_mode = FALSE;\r
1441 else\r
1442 dhd_master_mode = TRUE;\r
1443 printf("%s: dhd_master_mode = %d\n", __FUNCTION__, dhd_master_mode);\r
1444 }\r
1445\r
1446 /* Process pkt_filter_add */\r
1447 memset(pick, 0, MAXSZ_BUF);\r
1448 len_val = process_config_vars(bufp, len, pick, "pkt_filter_add=");\r
1449 pick_tmp = pick;\r
1450 if (len_val) {\r
1451 pch = bcmstrtok(&pick_tmp, ",.-", 0);\r
1452 i=0;\r
1453 while (pch != NULL && i<DHD_CONF_FILTER_MAX) {\r
1454 strcpy(&dhd->conf->pkt_filter_add.filter[i][0], pch);\r
1455 printf("%s: pkt_filter_add[%d][] = %s\n", __FUNCTION__, i, &dhd->conf->pkt_filter_add.filter[i][0]);\r
1456 pch = bcmstrtok(&pick_tmp, ",.-", 0);\r
1457 i++;\r
1458 }\r
1459 dhd->conf->pkt_filter_add.count = i;\r
1460 }\r
1461\r
1462 /* Process pkt_filter_del */\r
1463 memset(pick, 0, MAXSZ_BUF);\r
1464 len_val = process_config_vars(bufp, len, pick, "pkt_filter_del=");\r
1465 pick_tmp = pick;\r
1466 if (len_val) {\r
1467 pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
1468 i=0;\r
1469 while (pch != NULL && i<DHD_CONF_FILTER_MAX) {\r
1470 dhd->conf->pkt_filter_del.id[i] = (uint32)simple_strtol(pch, NULL, 10);\r
1471 pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
1472 i++;\r
1473 }\r
1474 dhd->conf->pkt_filter_del.count = i;\r
1475 printf("%s: pkt_filter_del id = ", __FUNCTION__);\r
1476 for (i=0; i<dhd->conf->pkt_filter_del.count; i++)\r
1477 printf("%d ", dhd->conf->pkt_filter_del.id[i]);\r
1478 printf("\n");\r
1479 }\r
1480\r
1481 /* Process srl parameters */\r
1482 memset(pick, 0, MAXSZ_BUF);\r
1483 len_val = process_config_vars(bufp, len, pick, "srl=");\r
1484 if (len_val) {\r
1485 dhd->conf->srl = (int)simple_strtol(pick, NULL, 10);\r
1486 printf("%s: srl = %d\n", __FUNCTION__, dhd->conf->srl);\r
1487 }\r
1488\r
1489 /* Process lrl parameters */\r
1490 memset(pick, 0, MAXSZ_BUF);\r
1491 len_val = process_config_vars(bufp, len, pick, "lrl=");\r
1492 if (len_val) {\r
1493 dhd->conf->lrl = (int)simple_strtol(pick, NULL, 10);\r
1494 printf("%s: lrl = %d\n", __FUNCTION__, dhd->conf->lrl);\r
1495 }\r
1496\r
1497 /* Process beacon timeout parameters */\r
1498 memset(pick, 0, MAXSZ_BUF);\r
1499 len_val = process_config_vars(bufp, len, pick, "bcn_timeout=");\r
1500 if (len_val) {\r
1501 dhd->conf->bcn_timeout= (int)simple_strtol(pick, NULL, 10);\r
1502 printf("%s: bcn_timeout = %d\n", __FUNCTION__, dhd->conf->bcn_timeout);\r
1503 }\r
1504\r
1505 /* Process bus_txglom */\r
1506 memset(pick, 0, MAXSZ_BUF);\r
1507 len_val = process_config_vars(bufp, len, pick, "bus_txglom=");\r
1508 if (len_val) {\r
1509 dhd->conf->bus_txglom = (int)simple_strtol(pick, NULL, 10);\r
1510 printf("%s: bus_txglom = %d\n", __FUNCTION__, dhd->conf->bus_txglom);\r
1511 }\r
1512\r
1513 /* Process ampdu_ba_wsize parameters */\r
1514 memset(pick, 0, MAXSZ_BUF);\r
1515 len_val = process_config_vars(bufp, len, pick, "ampdu_ba_wsize=");\r
1516 if (len_val) {\r
1517 dhd->conf->ampdu_ba_wsize = (int)simple_strtol(pick, NULL, 10);\r
1518 printf("%s: ampdu_ba_wsize = %d\n", __FUNCTION__, dhd->conf->ampdu_ba_wsize);\r
1519 }\r
1520\r
1521 /* Process kso parameters */\r
1522 memset(pick, 0, MAXSZ_BUF);\r
1523 len_val = process_config_vars(bufp, len, pick, "kso_enable=");\r
1524 if (len_val) {\r
1525 if (!strncmp(pick, "0", len_val))\r
1526 dhd->conf->kso_enable = FALSE;\r
1527 else\r
1528 dhd->conf->kso_enable = TRUE;\r
1529 printf("%s: kso_enable = %d\n", __FUNCTION__, dhd->conf->kso_enable);\r
1530 }\r
80e122a3 1531\r
1532 /* Process spect parameters */\r
1533 memset(pick, 0, MAXSZ_BUF);\r
1534 len_val = process_config_vars(bufp, len, pick, "spect=");\r
1535 if (len_val) {\r
1536 dhd->conf->spect = (int)simple_strtol(pick, NULL, 10);\r
1537 printf("%s: spect = %d\n", __FUNCTION__, dhd->conf->spect);\r
1538 }\r
96e81bc5 1539 \r
693cd89a
ML
1540 bcmerror = 0;\r
1541 } else {\r
1542 CONFIG_ERROR(("%s: error reading config file: %d\n", __FUNCTION__, len));\r
1543 bcmerror = BCME_SDIO_ERROR;\r
1544 }\r
1545\r
1546err:\r
1547 if (memblock)\r
1548 MFREE(dhd->osh, memblock, MAXSZ_CONFIG);\r
1549\r
1550 if (image)\r
1551 dhd_os_close_image(image);\r
1552\r
1553 return bcmerror;\r
1554}\r
1555\r
1556int\r
1557dhd_conf_preinit(dhd_pub_t *dhd)\r
1558{\r
7a4fa002 1559 CONFIG_TRACE(("%s: Enter\n", __FUNCTION__));\r
1560\r
96e81bc5 1561 dhd_conf_free_mac_list(&dhd->conf->fw_by_mac);\r
1562 dhd_conf_free_mac_list(&dhd->conf->nv_by_mac);\r
693cd89a
ML
1563 memset(dhd->conf, 0, sizeof(dhd_conf_t));\r
1564\r
1565 dhd->conf->band = WLC_BAND_AUTO;\r
80e122a3 1566 dhd->conf->mimo_bw_cap = -1;\r
96e81bc5 1567 if (dhd_bus_chip_id(dhd) == BCM43362_CHIP_ID ||\r
1568 dhd_bus_chip_id(dhd) == BCM4330_CHIP_ID) {\r
1569 strcpy(dhd->conf->cspec.country_abbrev, "ALL");\r
1570 strcpy(dhd->conf->cspec.ccode, "ALL");\r
1571 dhd->conf->cspec.rev = 0;\r
1572 } else {\r
1573 strcpy(dhd->conf->cspec.country_abbrev, "CN");\r
1574 strcpy(dhd->conf->cspec.ccode, "CN");\r
1575 dhd->conf->cspec.rev = 0;\r
1576 }\r
693cd89a
ML
1577 memset(&dhd->conf->channels, 0, sizeof(wl_channel_list_t));\r
1578 dhd->conf->roam_off = 1;\r
1579 dhd->conf->roam_off_suspend = 1;\r
1580#ifdef CUSTOM_ROAM_TRIGGER_SETTING\r
1581 dhd->conf->roam_trigger[0] = CUSTOM_ROAM_TRIGGER_SETTING;\r
1582#else\r
1583 dhd->conf->roam_trigger[0] = -65;\r
1584#endif\r
1585 dhd->conf->roam_trigger[1] = WLC_BAND_ALL;\r
1586 dhd->conf->roam_scan_period[0] = 10;\r
1587 dhd->conf->roam_scan_period[1] = WLC_BAND_ALL;\r
1588#ifdef CUSTOM_ROAM_DELTA_SETTING\r
1589 dhd->conf->roam_delta[0] = CUSTOM_ROAM_DELTA_SETTING;\r
1590#else\r
1591 dhd->conf->roam_delta[0] = 15;\r
1592#endif\r
1593 dhd->conf->roam_delta[1] = WLC_BAND_ALL;\r
568d3732 1594#ifdef FULL_ROAMING_SCAN_PERIOD_60_SEC\r
693cd89a 1595 dhd->conf->fullroamperiod = 60;\r
568d3732 1596#else /* FULL_ROAMING_SCAN_PERIOD_60_SEC */\r
693cd89a
ML
1597 dhd->conf->fullroamperiod = 120;\r
1598#endif /* FULL_ROAMING_SCAN_PERIOD_60_SEC */\r
693cd89a
ML
1599#ifdef CUSTOM_KEEP_ALIVE_SETTING\r
1600 dhd->conf->keep_alive_period = CUSTOM_KEEP_ALIVE_SETTING;\r
1601#else\r
1602 dhd->conf->keep_alive_period = 28000;\r
1603#endif\r
7a4fa002 1604 dhd->conf->force_wme_ac = 0;\r
1605 dhd->conf->stbc = -1;\r
1606 dhd->conf->phy_oclscdenable = -1;\r
96e81bc5 1607#ifdef PKT_FILTER_SUPPORT\r
1608 memset(&dhd->conf->pkt_filter_add, 0, sizeof(conf_pkt_filter_add_t));\r
1609 memset(&dhd->conf->pkt_filter_del, 0, sizeof(conf_pkt_filter_del_t));\r
1610#endif\r
1611 dhd->conf->srl = -1;\r
1612 dhd->conf->lrl = -1;\r
80e122a3 1613 dhd->conf->bcn_timeout = 8;\r
96e81bc5 1614 if (dhd_bus_chip_id(dhd) == BCM4339_CHIP_ID) {\r
1615 dhd->conf->bus_txglom = 8;\r
1616 dhd->conf->ampdu_ba_wsize = 40;\r
1617 }\r
1618 dhd->conf->kso_enable = TRUE;\r
80e122a3 1619 dhd->conf->spect = -1;\r
693cd89a
ML
1620\r
1621 return 0;\r
1622}\r
1623\r
1624int\r
1625dhd_conf_attach(dhd_pub_t *dhd)\r
1626{\r
1627 dhd_conf_t *conf;\r
1628\r
7a4fa002 1629 CONFIG_TRACE(("%s: Enter\n", __FUNCTION__));\r
1630\r
1631 if (dhd->conf != NULL) {\r
1632 printf("%s: config is attached before!\n", __FUNCTION__);\r
1633 return 0;\r
1634 }\r
693cd89a
ML
1635 /* Allocate private bus interface state */\r
1636 if (!(conf = MALLOC(dhd->osh, sizeof(dhd_conf_t)))) {\r
1637 CONFIG_ERROR(("%s: MALLOC failed\n", __FUNCTION__));\r
1638 goto fail;\r
1639 }\r
1640 memset(conf, 0, sizeof(dhd_conf_t));\r
1641\r
1642 dhd->conf = conf;\r
1643\r
1644 return 0;\r
1645\r
1646fail:\r
1647 if (conf != NULL)\r
1648 MFREE(dhd->osh, conf, sizeof(dhd_conf_t));\r
1649 return BCME_NOMEM;\r
1650}\r
1651\r
1652void\r
1653dhd_conf_detach(dhd_pub_t *dhd)\r
1654{\r
7a4fa002 1655 CONFIG_TRACE(("%s: Enter\n", __FUNCTION__));\r
1656\r
96e81bc5 1657 if (dhd->conf) {\r
1658 dhd_conf_free_mac_list(&dhd->conf->fw_by_mac);\r
1659 dhd_conf_free_mac_list(&dhd->conf->nv_by_mac);\r
693cd89a 1660 MFREE(dhd->osh, dhd->conf, sizeof(dhd_conf_t));\r
96e81bc5 1661 }\r
693cd89a
ML
1662 dhd->conf = NULL;\r
1663}\r
1664\r
1665#ifdef POWER_OFF_IN_SUSPEND\r
1666struct net_device *g_netdev;\r
1667#if defined(CONFIG_HAS_EARLYSUSPEND)\r
1668#include <linux/earlysuspend.h>\r
1669struct sdio_early_suspend_info {\r
1670 struct sdio_func *func;\r
1671 struct early_suspend sdio_early_suspend;\r
1672 struct work_struct tqueue;\r
1673 int do_late_resume;\r
80e122a3 1674#if defined(CONFIG_HAS_WAKELOCK)\r
1675 struct wake_lock power_wake_lock;\r
1676#endif\r
693cd89a
ML
1677};\r
1678struct sdio_early_suspend_info sdioinfo[4];\r
1679\r
1680void\r
1681dhd_conf_wifi_stop(struct net_device *dev)\r
1682{\r
1683 if (!dev) {\r
1684 CONFIG_ERROR(("%s: dev is null\n", __FUNCTION__));\r
1685 return;\r
1686 }\r
1687\r
1688 printk("%s in 1\n", __FUNCTION__);\r
1689 dhd_net_if_lock(dev);\r
1690 printk("%s in 2: g_wifi_on=%d, name=%s\n", __FUNCTION__, g_wifi_on, dev->name);\r
1691 if (g_wifi_on) {\r
7a4fa002 1692#ifdef WL_CFG80211\r
693cd89a
ML
1693 wl_cfg80211_user_sync(true);\r
1694 wl_cfg80211_stop();\r
7a4fa002 1695#endif\r
693cd89a
ML
1696 dhd_bus_devreset(bcmsdh_get_drvdata(), true);\r
1697 sdioh_stop(NULL);\r
80e122a3 1698 dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);\r
693cd89a 1699 g_wifi_on = FALSE;\r
7a4fa002 1700#ifdef WL_CFG80211\r
693cd89a 1701 wl_cfg80211_user_sync(false);\r
7a4fa002 1702#endif\r
693cd89a
ML
1703 }\r
1704 printk("%s out\n", __FUNCTION__);\r
1705 dhd_net_if_unlock(dev);\r
1706\r
1707}\r
1708\r
c5f4c307 1709bool wifi_ready = true;\r
1710\r
693cd89a
ML
1711void\r
1712dhd_conf_wifi_power(bool on)\r
1713{\r
b7dbfeaa 1714 extern struct wl_priv *wlcfg_drv_priv;\r
693cd89a
ML
1715 printk("%s: Enter %d\n", __FUNCTION__, on);\r
1716 if (on) {\r
7a4fa002 1717#ifdef WL_CFG80211\r
693cd89a 1718 wl_cfg80211_user_sync(true);\r
7a4fa002 1719#endif\r
c16464d0 1720 if(wl_android_wifi_on(g_netdev) < 0) {\r
1721 /* wifi on failed, send HANG message to tell wpa_supplicant to restart wifi*/\r
d51184b9 1722 if(g_netdev)\r
1723 net_os_send_hang_message(g_netdev);\r
c16464d0 1724 }\r
1725 else {\r
7a4fa002 1726#ifdef WL_CFG80211\r
c16464d0 1727 wl_cfg80211_send_disconnect();\r
7a4fa002 1728#endif\r
c16464d0 1729 if (wlcfg_drv_priv && wlcfg_drv_priv->p2p)\r
1730 wl_cfgp2p_start_p2p_device(NULL, NULL);\r
1731 else \r
1732 printk("======= ON : no p2p ======\n");\r
1733 }\r
7a4fa002 1734#ifdef WL_CFG80211\r
693cd89a 1735 wl_cfg80211_user_sync(false);\r
7a4fa002 1736#endif\r
c5f4c307 1737 wifi_ready = true;\r
693cd89a 1738 } else {\r
c5f4c307 1739 wifi_ready = false;\r
b7dbfeaa 1740 if (wlcfg_drv_priv && wlcfg_drv_priv->p2p) {\r
1741 wl_cfgp2p_clear_management_ie(wlcfg_drv_priv, 0);\r
1742 wl_cfgp2p_clear_management_ie(wlcfg_drv_priv, 1);\r
1743 wl_cfgp2p_stop_p2p_device(NULL, wlcfg_drv_priv->p2p_wdev);\r
1744 } else \r
1745 printk("======= OFF : no p2p ======\n");\r
693cd89a
ML
1746 dhd_conf_wifi_stop(g_netdev);\r
1747 }\r
c5f4c307 1748 printk("%s: Exit %d\n", __FUNCTION__, on);\r
693cd89a
ML
1749}\r
1750\r
1751void\r
7a4fa002 1752dhd_conf_power_workqueue(struct work_struct *work)\r
693cd89a 1753{\r
80e122a3 1754#if defined(CONFIG_HAS_WAKELOCK)\r
1755 struct sdio_early_suspend_info *sdioinfo =container_of(work, struct sdio_early_suspend_info, tqueue);\r
1756 wake_lock(&sdioinfo->power_wake_lock);\r
1757#endif\r
693cd89a 1758 dhd_conf_wifi_power(true);\r
80e122a3 1759#if defined(CONFIG_HAS_WAKELOCK)\r
1760 wake_unlock(&sdioinfo->power_wake_lock);\r
1761#endif\r
693cd89a
ML
1762}\r
1763\r
1764void\r
1765dhd_conf_early_suspend(struct early_suspend *h)\r
1766{\r
1767 struct sdio_early_suspend_info *sdioinfo = container_of(h, struct sdio_early_suspend_info, sdio_early_suspend);\r
1768\r
1769 printk("%s: Enter\n", __FUNCTION__);\r
96e81bc5 1770 if (sdioinfo->func->num == 2)\r
693cd89a
ML
1771 sdioinfo->do_late_resume = 0;\r
1772}\r
1773\r
1774void\r
1775dhd_conf_late_resume(struct early_suspend *h)\r
1776{\r
1777 struct sdio_early_suspend_info *sdioinfo = container_of(h, struct sdio_early_suspend_info, sdio_early_suspend);\r
1778\r
1779 printk("%s: Enter\n", __FUNCTION__);\r
1780 if(sdioinfo->func->num == 2 && sdioinfo->do_late_resume ){\r
1781 sdioinfo->do_late_resume = 0;\r
1782 schedule_work(&sdioinfo->tqueue);\r
1783 }\r
1784}\r
1785#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */\r
1786\r
1787void\r
1788dhd_conf_wifi_suspend(struct sdio_func *func)\r
1789{\r
1790#ifdef CONFIG_HAS_EARLYSUSPEND\r
1791 if (!sdioinfo[func->num].do_late_resume) {\r
1792 dhd_conf_wifi_power(false);\r
1793 sdioinfo[func->num].do_late_resume = 1;\r
1794 }\r
1795#endif\r
1796}\r
1797\r
1798void\r
1799dhd_conf_register_wifi_suspend(struct sdio_func *func)\r
1800{\r
1801#ifdef CONFIG_HAS_EARLYSUSPEND\r
1802 if (func->num == 2) {\r
1803 sdioinfo[func->num].func = func;\r
1804 sdioinfo[func->num].do_late_resume = 0;\r
c16464d0 1805 sdioinfo[func->num].sdio_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 30;\r
693cd89a
ML
1806 sdioinfo[func->num].sdio_early_suspend.suspend = dhd_conf_early_suspend;\r
1807 sdioinfo[func->num].sdio_early_suspend.resume = dhd_conf_late_resume;\r
1808 register_early_suspend(&sdioinfo[func->num].sdio_early_suspend);\r
7a4fa002 1809 INIT_WORK(&sdioinfo[func->num].tqueue, dhd_conf_power_workqueue);\r
80e122a3 1810#ifdef CONFIG_HAS_WAKELOCK\r
1811 wake_lock_init(&sdioinfo[func->num].power_wake_lock, WAKE_LOCK_SUSPEND, "wifi_power_wake");\r
1812 printk("init wifi power_wake lock\n");\r
1813#endif\r
693cd89a
ML
1814 }\r
1815#endif\r
1816}\r
1817\r
1818void\r
1819dhd_conf_unregister_wifi_suspend(struct sdio_func *func)\r
1820{\r
1821#ifdef CONFIG_HAS_EARLYSUSPEND\r
1822 if (func->num == 2) {\r
1823 if (sdioinfo[func->num].sdio_early_suspend.suspend) {\r
80e122a3 1824#ifdef CONFIG_HAS_WAKELOCK\r
1825 wake_lock_destroy(&sdioinfo[func->num].power_wake_lock);\r
1826#endif\r
693cd89a
ML
1827 unregister_early_suspend(&sdioinfo[func->num].sdio_early_suspend);\r
1828 sdioinfo[func->num].sdio_early_suspend.suspend = NULL;\r
1829 }\r
1830 }\r
1831#endif\r
1832}\r
1833#endif\r
1834\r