Commit | Line | Data |
---|---|---|
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 | 26 | uint 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 | |
63 | const 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 | |
70 | const 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 | |
77 | const 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 | |
84 | const 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 | |
91 | const 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 | |
98 | const 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 | |
105 | const 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 | |
119 | void\r | |
120 | dhd_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 | |
135 | int\r | |
136 | dhd_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 | |
216 | void\r | |
217 | dhd_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 | |
277 | void\r | |
278 | dhd_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 |
325 | void\r |
326 | dhd_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 | |
413 | void\r | |
414 | dhd_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 | |
431 | void\r | |
432 | dhd_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 | |
440 | void\r | |
441 | dhd_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 | |
449 | int\r | |
450 | dhd_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 | |
462 | uint\r | |
463 | dhd_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 | |
475 | int\r | |
476 | dhd_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 | |
492 | int\r | |
96e81bc5 | 493 | dhd_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 | |
507 | int\r | |
508 | dhd_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 | |
543 | bool\r | |
544 | dhd_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 | |
564 | int\r | |
565 | dhd_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 | |
600 | void\r | |
80e122a3 | 601 | dhd_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 | |
623 | void\r | |
624 | dhd_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 | |
636 | void\r | |
637 | dhd_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 | |
680 | void\r | |
681 | dhd_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 | |
725 | void\r | |
726 | dhd_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 | |
754 | void\r | |
755 | dhd_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 | |
777 | void\r | |
778 | dhd_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 |
796 | void\r | |
797 | dhd_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 | |
812 | bool\r | |
813 | dhd_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 | |
826 | void\r | |
827 | dhd_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 | |
853 | void\r | |
854 | dhd_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 | |
867 | void\r | |
868 | dhd_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 | |
881 | void\r | |
882 | dhd_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 | |
898 | void\r | |
899 | dhd_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 *)&du_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 | 917 | void\r |
918 | dhd_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 |
931 | unsigned int\r |
932 | process_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 | 989 | void\r |
990 | dhd_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 | 1060 | int\r |
96e81bc5 | 1061 | dhd_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 | |
1546 | err:\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 | |
1556 | int\r | |
1557 | dhd_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 | |
1624 | int\r | |
1625 | dhd_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 | |
1646 | fail:\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 | |
1652 | void\r | |
1653 | dhd_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 | |
1666 | struct net_device *g_netdev;\r | |
1667 | #if defined(CONFIG_HAS_EARLYSUSPEND)\r | |
1668 | #include <linux/earlysuspend.h>\r | |
1669 | struct 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 |
1678 | struct sdio_early_suspend_info sdioinfo[4];\r | |
1679 | \r | |
1680 | void\r | |
1681 | dhd_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 | 1709 | bool wifi_ready = true;\r |
1710 | \r | |
693cd89a ML |
1711 | void\r |
1712 | dhd_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 | |
1751 | void\r | |
7a4fa002 | 1752 | dhd_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 | |
1764 | void\r | |
1765 | dhd_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 | |
1774 | void\r | |
1775 | dhd_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 | |
1787 | void\r | |
1788 | dhd_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 | |
1798 | void\r | |
1799 | dhd_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 | |
1818 | void\r | |
1819 | dhd_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 |