1
2 #include <typedefs.h>
3 #include <osl.h>
4
5 #include <bcmutils.h>
6 #include <hndsoc.h>
7 #include <bcmsdbus.h>
8 #if defined(HW_OOB) || defined(FORCE_WOWLAN)
9 #include <bcmdefs.h>
10 #include <bcmsdh.h>
11 #include <sdio.h>
12 #include <sbchipc.h>
13 #endif
14
15 #include <dhd_config.h>
16 #include <dhd_dbg.h>
17
18 /* message levels */
19 #define CONFIG_ERROR_LEVEL 0x0001
20 #define CONFIG_TRACE_LEVEL 0x0002
21
22 uint config_msg_level = CONFIG_ERROR_LEVEL;
23
24 #define CONFIG_ERROR(x) \
25 do { \
26 if (config_msg_level & CONFIG_ERROR_LEVEL) { \
27 printk(KERN_ERR "CONFIG-ERROR) "); \
28 printk x; \
29 } \
30 } while (0)
31 #define CONFIG_TRACE(x) \
32 do { \
33 if (config_msg_level & CONFIG_TRACE_LEVEL) { \
34 printk(KERN_ERR "CONFIG-TRACE) "); \
35 printk x; \
36 } \
37 } while (0)
38
39 #define MAXSZ_BUF 1000
40 #define MAXSZ_CONFIG 4096
41
42 #define htod32(i) i
43 #define htod16(i) i
44 #define dtoh32(i) i
45 #define dtoh16(i) i
46 #define htodchanspec(i) i
47 #define dtohchanspec(i) i
48
49 #define MAX_EVENT_BUF_NUM 16
50 typedef struct eventmsg_buf {
51 u16 num;
52 struct {
53 u16 type;
54 bool set;
55 } event[MAX_EVENT_BUF_NUM];
56 } eventmsg_buf_t;
57
58 typedef struct cihp_name_map_t {
59 uint chip;
60 uint chiprev;
61 uint ag_type;
62 bool clm;
63 char *chip_name;
64 char *module_name;
65 } cihp_name_map_t;
66
67 /* Map of WLC_E events to connection failure strings */
68 #define DONT_CARE 9999
69 const cihp_name_map_t chip_name_map[] = {
70 /* ChipID Chiprev AG CLM ChipName ModuleName */
71 #ifdef BCMSDIO
72 {BCM43362_CHIP_ID, 0, DONT_CARE, FALSE, "bcm40181a0", ""},
73 {BCM43362_CHIP_ID, 1, DONT_CARE, FALSE, "bcm40181a2", ""},
74 {BCM4330_CHIP_ID, 4, FW_TYPE_G, FALSE, "bcm40183b2", ""},
75 {BCM4330_CHIP_ID, 4, FW_TYPE_AG, FALSE, "bcm40183b2_ag", ""},
76 {BCM43430_CHIP_ID, 0, DONT_CARE, FALSE, "bcm43438a0", ""},
77 {BCM43430_CHIP_ID, 1, DONT_CARE, FALSE, "bcm43438a1", ""},
78 {BCM43430_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43436b0", ""},
79 {BCM43012_CHIP_ID, 1, DONT_CARE, TRUE, "bcm43013b0", ""},
80 {BCM4334_CHIP_ID, 3, DONT_CARE, FALSE, "bcm4334b1_ag", ""},
81 {BCM43340_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43341b0_ag", ""},
82 {BCM43341_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43341b0_ag", ""},
83 {BCM4324_CHIP_ID, 5, DONT_CARE, FALSE, "bcm43241b4_ag", ""},
84 {BCM4335_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4339a0_ag", ""},
85 {BCM4339_CHIP_ID, 1, DONT_CARE, FALSE, "bcm4339a0_ag", ""},
86 {BCM4345_CHIP_ID, 6, DONT_CARE, FALSE, "bcm43455c0_ag", ""},
87 {BCM43454_CHIP_ID, 6, DONT_CARE, FALSE, "bcm43455c0_ag", ""},
88 {BCM4345_CHIP_ID, 9, DONT_CARE, FALSE, "bcm43456c5_ag", ""},
89 {BCM43454_CHIP_ID, 9, DONT_CARE, FALSE, "bcm43456c5_ag", ""},
90 {BCM4354_CHIP_ID, 1, DONT_CARE, FALSE, "bcm4354a1_ag", ""},
91 {BCM4354_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_ag", ""},
92 {BCM4356_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_ag", ""},
93 {BCM4371_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_ag", ""},
94 {BCM43569_CHIP_ID, 3, DONT_CARE, FALSE, "bcm4358a3_ag", ""},
95 {BCM4359_CHIP_ID, 5, DONT_CARE, FALSE, "bcm4359b1_ag", ""},
96 {BCM4359_CHIP_ID, 9, DONT_CARE, FALSE, "bcm4359c0_ag", ""},
97 {BCM4362_CHIP_ID, 0, DONT_CARE, TRUE, "bcm43752a0_ag", ""},
98 #endif
99 #ifdef BCMPCIE
100 {BCM4354_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_pcie_ag", ""},
101 {BCM4356_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_pcie_ag", ""},
102 {BCM4359_CHIP_ID, 9, DONT_CARE, FALSE, "bcm4359c0_pcie_ag", ""},
103 {BCM4362_CHIP_ID, 0, DONT_CARE, TRUE, "bcm43752a0_pcie_ag", ""},
104 #endif
105 #ifdef BCMDBUS
106 {BCM43143_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43143b0", ""},
107 {BCM43242_CHIP_ID, 1, DONT_CARE, FALSE, "bcm43242a1_ag", ""},
108 {BCM43569_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4358u_ag", ""},
109 #endif
110 };
111
112 #ifdef BCMSDIO
113 void
dhd_conf_free_mac_list(wl_mac_list_ctrl_t * mac_list)114 dhd_conf_free_mac_list(wl_mac_list_ctrl_t *mac_list)
115 {
116 int i;
117
118 CONFIG_TRACE(("%s called\n", __FUNCTION__));
119 if (mac_list->m_mac_list_head) {
120 for (i = 0; i < mac_list->count; i++) {
121 if (mac_list->m_mac_list_head[i].mac) {
122 CONFIG_TRACE(("%s Free mac %p\n", __FUNCTION__, mac_list->m_mac_list_head[i].mac));
123 kfree(mac_list->m_mac_list_head[i].mac);
124 }
125 }
126 CONFIG_TRACE(("%s Free m_mac_list_head %p\n", __FUNCTION__, mac_list->m_mac_list_head));
127 kfree(mac_list->m_mac_list_head);
128 }
129 mac_list->count = 0;
130 }
131
132 void
dhd_conf_free_chip_nv_path_list(wl_chip_nv_path_list_ctrl_t * chip_nv_list)133 dhd_conf_free_chip_nv_path_list(wl_chip_nv_path_list_ctrl_t *chip_nv_list)
134 {
135 CONFIG_TRACE(("%s called\n", __FUNCTION__));
136
137 if (chip_nv_list->m_chip_nv_path_head) {
138 CONFIG_TRACE(("%s Free %p\n", __FUNCTION__, chip_nv_list->m_chip_nv_path_head));
139 kfree(chip_nv_list->m_chip_nv_path_head);
140 }
141 chip_nv_list->count = 0;
142 }
143
144 #if defined(HW_OOB) || defined(FORCE_WOWLAN)
145 void
dhd_conf_set_hw_oob_intr(bcmsdh_info_t * sdh,uint chip)146 dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, uint chip)
147 {
148 uint32 gpiocontrol, addr;
149
150 if (CHIPID(chip) == BCM43362_CHIP_ID) {
151 printf("%s: Enable HW OOB for 43362\n", __FUNCTION__);
152 addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, gpiocontrol);
153 gpiocontrol = bcmsdh_reg_read(sdh, addr, 4);
154 gpiocontrol |= 0x2;
155 bcmsdh_reg_write(sdh, addr, 4, gpiocontrol);
156 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10005, 0xf, NULL);
157 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10006, 0x0, NULL);
158 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10007, 0x2, NULL);
159 }
160 }
161 #endif
162
163 #define SBSDIO_CIS_SIZE_LIMIT 0x200
164 #define F0_BLOCK_SIZE 32
165 int
dhd_conf_set_blksize(bcmsdh_info_t * sdh)166 dhd_conf_set_blksize(bcmsdh_info_t *sdh)
167 {
168 int err = 0;
169 uint fn, numfn;
170 int32 blksize = 0, cur_blksize = 0;
171 uint8 cisd;
172
173 numfn = bcmsdh_query_iofnum(sdh);
174
175 for (fn = 0; fn <= numfn; fn++) {
176 if (!fn)
177 blksize = F0_BLOCK_SIZE;
178 else {
179 bcmsdh_cisaddr_read(sdh, fn, &cisd, 24);
180 blksize = cisd;
181 bcmsdh_cisaddr_read(sdh, fn, &cisd, 25);
182 blksize |= cisd << 8;
183 }
184 #ifdef CUSTOM_SDIO_F2_BLKSIZE
185 if (fn == 2 && blksize > CUSTOM_SDIO_F2_BLKSIZE) {
186 blksize = CUSTOM_SDIO_F2_BLKSIZE;
187 }
188 #endif
189 bcmsdh_iovar_op(sdh, "sd_blocksize", &fn, sizeof(int32),
190 &cur_blksize, sizeof(int32), FALSE);
191 if (cur_blksize != blksize) {
192 printf("%s: fn=%d, blksize=%d, cur_blksize=%d\n", __FUNCTION__,
193 fn, blksize, cur_blksize);
194 blksize |= (fn<<16);
195 if (bcmsdh_iovar_op(sdh, "sd_blocksize", NULL, 0, &blksize,
196 sizeof(blksize), TRUE) != BCME_OK) {
197 DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize"));
198 err = -1;
199 }
200 }
201 }
202
203 return err;
204 }
205
206 int
dhd_conf_get_mac(dhd_pub_t * dhd,bcmsdh_info_t * sdh,uint8 * mac)207 dhd_conf_get_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, uint8 *mac)
208 {
209 int i, err = -1;
210 uint8 *ptr = 0;
211 unsigned char tpl_code, tpl_link = '\0';
212 uint8 header[3] = {0x80, 0x07, 0x19};
213 uint8 *cis;
214
215 cis = MALLOC(dhd->osh, SBSDIO_CIS_SIZE_LIMIT);
216 if (!cis) {
217 CONFIG_ERROR(("%s: cis malloc failed\n", __FUNCTION__));
218 return err;
219 }
220 bzero(cis, SBSDIO_CIS_SIZE_LIMIT);
221
222 err = bcmsdh_cis_read(sdh, 0, cis, SBSDIO_CIS_SIZE_LIMIT);
223 if (err) {
224 CONFIG_ERROR(("%s: cis read err %d\n", __FUNCTION__, err));
225 MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT);
226 return err;
227 }
228 err = -1; // reset err;
229 ptr = cis;
230 do {
231 /* 0xff means we're done */
232 tpl_code = *ptr;
233 ptr++;
234 if (tpl_code == 0xff)
235 break;
236
237 /* null entries have no link field or data */
238 if (tpl_code == 0x00)
239 continue;
240
241 tpl_link = *ptr;
242 ptr++;
243 /* a size of 0xff also means we're done */
244 if (tpl_link == 0xff)
245 break;
246 if (config_msg_level & CONFIG_TRACE_LEVEL) {
247 printf("%s: tpl_code=0x%02x, tpl_link=0x%02x, tag=0x%02x\n",
248 __FUNCTION__, tpl_code, tpl_link, *ptr);
249 printk("%s: value:", __FUNCTION__);
250 for (i = 0; i < tpl_link - 1; i++) {
251 printk("%02x ", ptr[i+1]);
252 if ((i+1) % 16 == 0)
253 printk("\n");
254 }
255 printk("\n");
256 }
257
258 if (tpl_code == 0x80 && tpl_link == 0x07 && *ptr == 0x19)
259 break;
260
261 ptr += tpl_link;
262 } while (1);
263
264 if (tpl_code == 0x80 && tpl_link == 0x07 && *ptr == 0x19) {
265 /* Normal OTP */
266 memcpy(mac, ptr+1, 6);
267 err = 0;
268 } else {
269 ptr = cis;
270 /* Special OTP */
271 if (bcmsdh_reg_read(sdh, SI_ENUM_BASE, 4) == 0x16044330) {
272 for (i = 0; i < SBSDIO_CIS_SIZE_LIMIT; i++) {
273 if (!memcmp(header, ptr, 3)) {
274 memcpy(mac, ptr+3, 6);
275 err = 0;
276 break;
277 }
278 ptr++;
279 }
280 }
281 }
282
283 ASSERT(cis);
284 MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT);
285
286 return err;
287 }
288
289 void
dhd_conf_set_fw_name_by_mac(dhd_pub_t * dhd,bcmsdh_info_t * sdh,char * fw_path)290 dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, char *fw_path)
291 {
292 int i, j;
293 uint8 mac[6] = {0};
294 int fw_num = 0, mac_num = 0;
295 uint32 oui, nic;
296 wl_mac_list_t *mac_list;
297 wl_mac_range_t *mac_range;
298 int fw_type, fw_type_new;
299 char *name_ptr;
300
301 mac_list = dhd->conf->fw_by_mac.m_mac_list_head;
302 fw_num = dhd->conf->fw_by_mac.count;
303 if (!mac_list || !fw_num)
304 return;
305
306 if (dhd_conf_get_mac(dhd, sdh, mac)) {
307 CONFIG_ERROR(("%s: Can not read MAC address\n", __FUNCTION__));
308 return;
309 }
310 oui = (mac[0] << 16) | (mac[1] << 8) | (mac[2]);
311 nic = (mac[3] << 16) | (mac[4] << 8) | (mac[5]);
312
313 /* find out the last '/' */
314 i = strlen(fw_path);
315 while (i > 0) {
316 if (fw_path[i] == '/') {
317 i++;
318 break;
319 }
320 i--;
321 }
322 name_ptr = &fw_path[i];
323
324 if (strstr(name_ptr, "_apsta"))
325 fw_type = FW_TYPE_APSTA;
326 else if (strstr(name_ptr, "_p2p"))
327 fw_type = FW_TYPE_P2P;
328 else if (strstr(name_ptr, "_mesh"))
329 fw_type = FW_TYPE_MESH;
330 else if (strstr(name_ptr, "_es"))
331 fw_type = FW_TYPE_ES;
332 else if (strstr(name_ptr, "_mfg"))
333 fw_type = FW_TYPE_MFG;
334 else
335 fw_type = FW_TYPE_STA;
336
337 for (i = 0; i < fw_num; i++) {
338 mac_num = mac_list[i].count;
339 mac_range = mac_list[i].mac;
340 if (strstr(mac_list[i].name, "_apsta"))
341 fw_type_new = FW_TYPE_APSTA;
342 else if (strstr(mac_list[i].name, "_p2p"))
343 fw_type_new = FW_TYPE_P2P;
344 else if (strstr(mac_list[i].name, "_mesh"))
345 fw_type_new = FW_TYPE_MESH;
346 else if (strstr(mac_list[i].name, "_es"))
347 fw_type_new = FW_TYPE_ES;
348 else if (strstr(mac_list[i].name, "_mfg"))
349 fw_type_new = FW_TYPE_MFG;
350 else
351 fw_type_new = FW_TYPE_STA;
352 if (fw_type != fw_type_new) {
353 printf("%s: fw_typ=%d != fw_type_new=%d\n", __FUNCTION__, fw_type, fw_type_new);
354 continue;
355 }
356 for (j = 0; j < mac_num; j++) {
357 if (oui == mac_range[j].oui) {
358 if (nic >= mac_range[j].nic_start && nic <= mac_range[j].nic_end) {
359 strcpy(name_ptr, mac_list[i].name);
360 printf("%s: matched oui=0x%06X, nic=0x%06X\n",
361 __FUNCTION__, oui, nic);
362 printf("%s: fw_path=%s\n", __FUNCTION__, fw_path);
363 return;
364 }
365 }
366 }
367 }
368 }
369
370 void
dhd_conf_set_nv_name_by_mac(dhd_pub_t * dhd,bcmsdh_info_t * sdh,char * nv_path)371 dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, char *nv_path)
372 {
373 int i, j;
374 uint8 mac[6] = {0};
375 int nv_num = 0, mac_num = 0;
376 uint32 oui, nic;
377 wl_mac_list_t *mac_list;
378 wl_mac_range_t *mac_range;
379 char *pnv_name;
380
381 mac_list = dhd->conf->nv_by_mac.m_mac_list_head;
382 nv_num = dhd->conf->nv_by_mac.count;
383 if (!mac_list || !nv_num)
384 return;
385
386 if (dhd_conf_get_mac(dhd, sdh, mac)) {
387 CONFIG_ERROR(("%s: Can not read MAC address\n", __FUNCTION__));
388 return;
389 }
390 oui = (mac[0] << 16) | (mac[1] << 8) | (mac[2]);
391 nic = (mac[3] << 16) | (mac[4] << 8) | (mac[5]);
392
393 /* find out the last '/' */
394 i = strlen(nv_path);
395 while (i > 0) {
396 if (nv_path[i] == '/')
397 break;
398 i--;
399 }
400 pnv_name = &nv_path[i+1];
401
402 for (i = 0; i < nv_num; i++) {
403 mac_num = mac_list[i].count;
404 mac_range = mac_list[i].mac;
405 for (j = 0; j < mac_num; j++) {
406 if (oui == mac_range[j].oui) {
407 if (nic >= mac_range[j].nic_start && nic <= mac_range[j].nic_end) {
408 strcpy(pnv_name, mac_list[i].name);
409 printf("%s: matched oui=0x%06X, nic=0x%06X\n",
410 __FUNCTION__, oui, nic);
411 printf("%s: nv_path=%s\n", __FUNCTION__, nv_path);
412 return;
413 }
414 }
415 }
416 }
417 }
418 #endif
419
420 void
dhd_conf_free_country_list(conf_country_list_t * country_list)421 dhd_conf_free_country_list(conf_country_list_t *country_list)
422 {
423 int i;
424
425 CONFIG_TRACE(("%s called\n", __FUNCTION__));
426 for (i = 0; i < country_list->count; i++) {
427 if (country_list->cspec[i]) {
428 CONFIG_TRACE(("%s Free cspec %p\n", __FUNCTION__, country_list->cspec[i]));
429 kfree(country_list->cspec[i]);
430 }
431 }
432 country_list->count = 0;
433 }
434
435 void
dhd_conf_set_fw_name_by_chip(dhd_pub_t * dhd,char * fw_path)436 dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path)
437 {
438 int fw_type, ag_type;
439 uint chip, chiprev;
440 int i;
441 char *name_ptr;
442
443 chip = dhd->conf->chip;
444 chiprev = dhd->conf->chiprev;
445
446 if (fw_path[0] == '\0') {
447 #ifdef CONFIG_BCMDHD_FW_PATH
448 bcm_strncpy_s(fw_path, MOD_PARAM_PATHLEN-1, CONFIG_BCMDHD_FW_PATH, MOD_PARAM_PATHLEN-1);
449 if (fw_path[0] == '\0')
450 #endif
451 {
452 printf("firmware path is null\n");
453 return;
454 }
455 }
456 #ifndef FW_PATH_AUTO_SELECT
457 return;
458 #endif
459
460 /* find out the last '/' */
461 i = strlen(fw_path);
462 while (i > 0) {
463 if (fw_path[i] == '/') {
464 i++;
465 break;
466 }
467 i--;
468 }
469 name_ptr = &fw_path[i];
470 #ifdef BAND_AG
471 ag_type = FW_TYPE_AG;
472 #else
473 ag_type = strstr(name_ptr, "_ag") ? FW_TYPE_AG : FW_TYPE_G;
474 #endif
475 if (strstr(name_ptr, "_apsta"))
476 fw_type = FW_TYPE_APSTA;
477 else if (strstr(name_ptr, "_p2p"))
478 fw_type = FW_TYPE_P2P;
479 else if (strstr(name_ptr, "_mesh"))
480 fw_type = FW_TYPE_MESH;
481 else if (strstr(name_ptr, "_es"))
482 fw_type = FW_TYPE_ES;
483 else if (strstr(name_ptr, "_mfg"))
484 fw_type = FW_TYPE_MFG;
485 else
486 fw_type = FW_TYPE_STA;
487
488 for (i = 0; i < sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) {
489 const cihp_name_map_t *row = &chip_name_map[i];
490 if (row->chip == chip && row->chiprev == chiprev &&
491 (row->ag_type == ag_type || row->ag_type == DONT_CARE)) {
492 strcpy(name_ptr, "fw_");
493 strcat(fw_path, row->chip_name);
494 #ifdef BCMUSBDEV_COMPOSITE
495 strcat(fw_path, "_cusb");
496 #endif
497 if (fw_type == FW_TYPE_APSTA)
498 strcat(fw_path, "_apsta.bin");
499 else if (fw_type == FW_TYPE_P2P)
500 strcat(fw_path, "_p2p.bin");
501 else if (fw_type == FW_TYPE_MESH)
502 strcat(fw_path, "_mesh.bin");
503 else if (fw_type == FW_TYPE_ES)
504 strcat(fw_path, "_es.bin");
505 else if (fw_type == FW_TYPE_MFG)
506 strcat(fw_path, "_mfg.bin");
507 else
508 strcat(fw_path, ".bin");
509 }
510 }
511
512 dhd->conf->fw_type = fw_type;
513
514 CONFIG_TRACE(("%s: firmware_path=%s\n", __FUNCTION__, fw_path));
515 }
516
517 void
dhd_conf_set_clm_name_by_chip(dhd_pub_t * dhd,char * clm_path)518 dhd_conf_set_clm_name_by_chip(dhd_pub_t *dhd, char *clm_path)
519 {
520 uint chip, chiprev;
521 int i;
522 char *name_ptr;
523
524 chip = dhd->conf->chip;
525 chiprev = dhd->conf->chiprev;
526
527 if (clm_path[0] == '\0') {
528 printf("clm path is null\n");
529 return;
530 }
531
532 /* find out the last '/' */
533 i = strlen(clm_path);
534 while (i > 0) {
535 if (clm_path[i] == '/') {
536 i++;
537 break;
538 }
539 i--;
540 }
541 name_ptr = &clm_path[i];
542
543 for (i = 0; i < sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) {
544 const cihp_name_map_t *row = &chip_name_map[i];
545 if (row->chip == chip && row->chiprev == chiprev && row->clm) {
546 strcpy(name_ptr, "clm_");
547 strcat(clm_path, row->chip_name);
548 strcat(clm_path, ".blob");
549 }
550 }
551
552 CONFIG_TRACE(("%s: clm_path=%s\n", __FUNCTION__, clm_path));
553 }
554
555 void
dhd_conf_set_nv_name_by_chip(dhd_pub_t * dhd,char * nv_path)556 dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path)
557 {
558 uint chip, chiprev;
559 int i;
560 char *name_ptr;
561
562 chip = dhd->conf->chip;
563 chiprev = dhd->conf->chiprev;
564
565 if (nv_path[0] == '\0') {
566 #ifdef CONFIG_BCMDHD_NVRAM_PATH
567 bcm_strncpy_s(nv_path, MOD_PARAM_PATHLEN-1, CONFIG_BCMDHD_NVRAM_PATH, MOD_PARAM_PATHLEN-1);
568 if (nv_path[0] == '\0')
569 #endif
570 {
571 printf("nvram path is null\n");
572 return;
573 }
574 }
575
576 /* find out the last '/' */
577 i = strlen(nv_path);
578 while (i > 0) {
579 if (nv_path[i] == '/') {
580 i++;
581 break;
582 }
583 i--;
584 }
585 name_ptr = &nv_path[i];
586
587 for (i = 0; i < sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) {
588 const cihp_name_map_t *row = &chip_name_map[i];
589 if (row->chip == chip && row->chiprev == chiprev && strlen(row->module_name)) {
590 strcpy(name_ptr, "nvram_");
591 strcat(name_ptr, row->module_name);
592 #ifdef BCMUSBDEV_COMPOSITE
593 strcat(name_ptr, "_cusb");
594 #endif
595 strcat(name_ptr, ".txt");
596 }
597 }
598
599 for (i = 0; i < dhd->conf->nv_by_chip.count; i++) {
600 if (chip == dhd->conf->nv_by_chip.m_chip_nv_path_head[i].chip &&
601 chiprev == dhd->conf->nv_by_chip.m_chip_nv_path_head[i].chiprev) {
602 strcpy(name_ptr, dhd->conf->nv_by_chip.m_chip_nv_path_head[i].name);
603 break;
604 }
605 }
606
607 CONFIG_TRACE(("%s: nvram_path=%s\n", __FUNCTION__, nv_path));
608 }
609
610 void
dhd_conf_set_path(dhd_pub_t * dhd,char * dst_name,char * dst_path,char * src_path)611 dhd_conf_set_path(dhd_pub_t *dhd, char *dst_name, char *dst_path, char *src_path)
612 {
613 int i;
614
615 if (src_path[0] == '\0') {
616 printf("src_path is null\n");
617 return;
618 } else
619 strcpy(dst_path, src_path);
620
621 /* find out the last '/' */
622 i = strlen(dst_path);
623 while (i > 0) {
624 if (dst_path[i] == '/') {
625 i++;
626 break;
627 }
628 i--;
629 }
630 strcpy(&dst_path[i], dst_name);
631
632 CONFIG_TRACE(("%s: dst_path=%s\n", __FUNCTION__, dst_path));
633 }
634
635 #ifdef CONFIG_PATH_AUTO_SELECT
636 void
dhd_conf_set_conf_name_by_chip(dhd_pub_t * dhd,char * conf_path)637 dhd_conf_set_conf_name_by_chip(dhd_pub_t *dhd, char *conf_path)
638 {
639 uint chip, chiprev;
640 int i;
641 char *name_ptr;
642
643 chip = dhd->conf->chip;
644 chiprev = dhd->conf->chiprev;
645
646 if (conf_path[0] == '\0') {
647 printf("config path is null\n");
648 return;
649 }
650
651 /* find out the last '/' */
652 i = strlen(conf_path);
653 while (i > 0) {
654 if (conf_path[i] == '/') {
655 i++;
656 break;
657 }
658 i--;
659 }
660 name_ptr = &conf_path[i];
661
662 for (i = 0; i < sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) {
663 const cihp_name_map_t *row = &chip_name_map[i];
664 if (row->chip == chip && row->chiprev == chiprev) {
665 strcpy(name_ptr, "config_");
666 strcat(conf_path, row->chip_name);
667 strcat(conf_path, ".txt");
668 }
669 }
670
671 CONFIG_TRACE(("%s: config_path=%s\n", __FUNCTION__, conf_path));
672 }
673 #endif
674
675 int
dhd_conf_set_intiovar(dhd_pub_t * dhd,uint cmd,char * name,int val,int def,bool down)676 dhd_conf_set_intiovar(dhd_pub_t *dhd, uint cmd, char *name, int val,
677 int def, bool down)
678 {
679 int ret = -1;
680 char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */
681
682 if (val >= def) {
683 if (down) {
684 ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, 0);
685 if (ret)
686 CONFIG_ERROR(("%s: WLC_DOWN setting failed %d\n", __FUNCTION__, ret));
687 }
688 if (cmd == WLC_SET_VAR) {
689 CONFIG_TRACE(("%s: set %s %d\n", __FUNCTION__, name, val));
690 bcm_mkiovar(name, (char *)&val, sizeof(val), iovbuf, sizeof(iovbuf));
691 ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
692 if (ret)
693 CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, name, ret));
694 } else {
695 CONFIG_TRACE(("%s: set %s %d %d\n", __FUNCTION__, name, cmd, val));
696 ret = dhd_wl_ioctl_cmd(dhd, cmd, &val, sizeof(val), TRUE, 0);
697 if (ret)
698 CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, name, ret));
699 }
700 }
701
702 return ret;
703 }
704
705 int
dhd_conf_set_bufiovar(dhd_pub_t * dhd,int ifidx,uint cmd,char * name,char * buf,int len,bool down)706 dhd_conf_set_bufiovar(dhd_pub_t *dhd, int ifidx, uint cmd, char *name,
707 char *buf, int len, bool down)
708 {
709 char iovbuf[WLC_IOCTL_SMLEN];
710 int ret = -1;
711
712 if (down) {
713 ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, ifidx);
714 if (ret)
715 CONFIG_ERROR(("%s: WLC_DOWN setting failed %d\n", __FUNCTION__, ret));
716 }
717
718 if (cmd == WLC_SET_VAR) {
719 bcm_mkiovar(name, buf, len, iovbuf, sizeof(iovbuf));
720 ret = dhd_wl_ioctl_cmd(dhd, cmd, iovbuf, sizeof(iovbuf), TRUE, ifidx);
721 if (ret)
722 CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, name, ret));
723 } else {
724 ret = dhd_wl_ioctl_cmd(dhd, cmd, buf, len, TRUE, ifidx);
725 if (ret)
726 CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, name, ret));
727 }
728
729 return ret;
730 }
731
732 int
dhd_conf_get_iovar(dhd_pub_t * dhd,int ifidx,int cmd,char * name,char * buf,int len)733 dhd_conf_get_iovar(dhd_pub_t *dhd, int ifidx, int cmd, char *name,
734 char *buf, int len)
735 {
736 char iovbuf[WLC_IOCTL_SMLEN];
737 int ret = -1;
738
739 if (cmd == WLC_GET_VAR) {
740 if (bcm_mkiovar(name, NULL, 0, iovbuf, sizeof(iovbuf))) {
741 ret = dhd_wl_ioctl_cmd(dhd, cmd, iovbuf, sizeof(iovbuf), FALSE, ifidx);
742 if (!ret) {
743 memcpy(buf, iovbuf, len);
744 } else {
745 CONFIG_ERROR(("%s: get iovar %s failed %d\n", __FUNCTION__, name, ret));
746 }
747 } else {
748 CONFIG_ERROR(("%s: mkiovar %s failed\n", __FUNCTION__, name));
749 }
750 } else {
751 ret = dhd_wl_ioctl_cmd(dhd, cmd, buf, len, FALSE, 0);
752 if (ret < 0)
753 CONFIG_ERROR(("%s: get iovar %s failed %d\n", __FUNCTION__, name, ret));
754 }
755
756 return ret;
757 }
758
759 uint
dhd_conf_get_band(dhd_pub_t * dhd)760 dhd_conf_get_band(dhd_pub_t *dhd)
761 {
762 int band = -1;
763
764 if (dhd && dhd->conf)
765 band = dhd->conf->band;
766 else
767 CONFIG_ERROR(("%s: dhd or conf is NULL\n", __FUNCTION__));
768
769 return band;
770 }
771
772 int
dhd_conf_get_country(dhd_pub_t * dhd,wl_country_t * cspec)773 dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec)
774 {
775 int bcmerror = -1;
776
777 memset(cspec, 0, sizeof(wl_country_t));
778 bcm_mkiovar("country", NULL, 0, (char *)cspec, sizeof(wl_country_t));
779 bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cspec, sizeof(wl_country_t), FALSE, 0);
780 if (bcmerror < 0)
781 CONFIG_ERROR(("%s: country code getting failed %d\n", __FUNCTION__, bcmerror));
782
783 return bcmerror;
784 }
785
786 int
dhd_conf_map_country_list(dhd_pub_t * dhd,wl_country_t * cspec)787 dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec)
788 {
789 int bcmerror = -1, i;
790 struct dhd_conf *conf = dhd->conf;
791 conf_country_list_t *country_list = &conf->country_list;
792
793 for (i = 0; i < country_list->count; i++) {
794 if (!strncmp(cspec->country_abbrev, country_list->cspec[i]->country_abbrev, 2)) {
795 memcpy(cspec->ccode, country_list->cspec[i]->ccode, WLC_CNTRY_BUF_SZ);
796 cspec->rev = country_list->cspec[i]->rev;
797 bcmerror = 0;
798 }
799 }
800
801 if (!bcmerror)
802 printf("%s: %s/%d\n", __FUNCTION__, cspec->ccode, cspec->rev);
803
804 return bcmerror;
805 }
806
807 int
dhd_conf_set_country(dhd_pub_t * dhd,wl_country_t * cspec)808 dhd_conf_set_country(dhd_pub_t *dhd, wl_country_t *cspec)
809 {
810 int bcmerror = -1;
811
812 memset(&dhd->dhd_cspec, 0, sizeof(wl_country_t));
813
814 printf("%s: set country %s, revision %d\n", __FUNCTION__, cspec->ccode, cspec->rev);
815 bcmerror = dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "country", (char *)cspec,
816 sizeof(wl_country_t), FALSE);
817 dhd_conf_get_country(dhd, cspec);
818 printf("Country code: %s (%s/%d)\n", cspec->country_abbrev, cspec->ccode, cspec->rev);
819
820 return bcmerror;
821 }
822
823 int
dhd_conf_fix_country(dhd_pub_t * dhd)824 dhd_conf_fix_country(dhd_pub_t *dhd)
825 {
826 int bcmerror = -1;
827 uint band;
828 wl_uint32_list_t *list;
829 u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)];
830 wl_country_t cspec;
831
832 if (!(dhd && dhd->conf)) {
833 return bcmerror;
834 }
835
836 memset(valid_chan_list, 0, sizeof(valid_chan_list));
837 list = (wl_uint32_list_t *)(void *) valid_chan_list;
838 list->count = htod32(WL_NUMCHANNELS);
839 bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VALID_CHANNELS, valid_chan_list, sizeof(valid_chan_list), FALSE, 0);
840 if (bcmerror < 0) {
841 CONFIG_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, bcmerror));
842 }
843
844 band = dhd_conf_get_band(dhd);
845
846 if (bcmerror || ((band == WLC_BAND_AUTO || band == WLC_BAND_2G) &&
847 dtoh32(list->count)<11)) {
848 CONFIG_ERROR(("%s: bcmerror=%d, # of channels %d\n",
849 __FUNCTION__, bcmerror, dtoh32(list->count)));
850 dhd_conf_map_country_list(dhd, &dhd->conf->cspec);
851 bcmerror = dhd_conf_set_country(dhd, &dhd->conf->cspec);
852 if (bcmerror < 0) {
853 strcpy(cspec.country_abbrev, "US");
854 cspec.rev = 0;
855 strcpy(cspec.ccode, "US");
856 dhd_conf_map_country_list(dhd, &cspec);
857 dhd_conf_set_country(dhd, &cspec);
858 }
859 }
860
861 return bcmerror;
862 }
863
864 bool
dhd_conf_match_channel(dhd_pub_t * dhd,uint32 channel)865 dhd_conf_match_channel(dhd_pub_t *dhd, uint32 channel)
866 {
867 int i;
868 bool match = false;
869
870 if (dhd && dhd->conf) {
871 if (dhd->conf->channels.count == 0)
872 return true;
873 for (i = 0; i < dhd->conf->channels.count; i++) {
874 if (channel == dhd->conf->channels.channel[i])
875 match = true;
876 }
877 } else {
878 match = true;
879 CONFIG_ERROR(("%s: dhd or conf is NULL\n", __FUNCTION__));
880 }
881
882 return match;
883 }
884
885 int
dhd_conf_set_roam(dhd_pub_t * dhd)886 dhd_conf_set_roam(dhd_pub_t *dhd)
887 {
888 int bcmerror = -1;
889 struct dhd_conf *conf = dhd->conf;
890
891 dhd_roam_disable = conf->roam_off;
892 dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "roam_off", dhd->conf->roam_off, 0, FALSE);
893
894 if (!conf->roam_off || !conf->roam_off_suspend) {
895 printf("%s: set roam_trigger %d\n", __FUNCTION__, conf->roam_trigger[0]);
896 dhd_conf_set_bufiovar(dhd, 0, WLC_SET_ROAM_TRIGGER, "WLC_SET_ROAM_TRIGGER",
897 (char *)conf->roam_trigger, sizeof(conf->roam_trigger), FALSE);
898
899 printf("%s: set roam_scan_period %d\n", __FUNCTION__, conf->roam_scan_period[0]);
900 dhd_conf_set_bufiovar(dhd, 0, WLC_SET_ROAM_SCAN_PERIOD, "WLC_SET_ROAM_SCAN_PERIOD",
901 (char *)conf->roam_scan_period, sizeof(conf->roam_scan_period), FALSE);
902
903 printf("%s: set roam_delta %d\n", __FUNCTION__, conf->roam_delta[0]);
904 dhd_conf_set_bufiovar(dhd, 0, WLC_SET_ROAM_DELTA, "WLC_SET_ROAM_DELTA",
905 (char *)conf->roam_delta, sizeof(conf->roam_delta), FALSE);
906
907 dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "fullroamperiod", dhd->conf->fullroamperiod, 1, FALSE);
908 }
909
910 return bcmerror;
911 }
912
913 void
dhd_conf_add_to_eventbuffer(struct eventmsg_buf * ev,u16 event,bool set)914 dhd_conf_add_to_eventbuffer(struct eventmsg_buf *ev, u16 event, bool set)
915 {
916 if (!ev || (event > WLC_E_LAST))
917 return;
918
919 if (ev->num < MAX_EVENT_BUF_NUM) {
920 ev->event[ev->num].type = event;
921 ev->event[ev->num].set = set;
922 ev->num++;
923 } else {
924 CONFIG_ERROR(("evenbuffer doesn't support > %u events. Update"
925 " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM));
926 ASSERT(0);
927 }
928 }
929
930 s32
dhd_conf_apply_eventbuffer(dhd_pub_t * dhd,eventmsg_buf_t * ev)931 dhd_conf_apply_eventbuffer(dhd_pub_t *dhd, eventmsg_buf_t *ev)
932 {
933 char eventmask[WL_EVENTING_MASK_LEN];
934 int i, ret = 0;
935
936 if (!ev || (!ev->num))
937 return -EINVAL;
938
939 /* Read event_msgs mask */
940 ret = dhd_conf_get_iovar(dhd, 0, WLC_GET_VAR, "event_msgs", eventmask,
941 sizeof(eventmask));
942 if (unlikely(ret)) {
943 CONFIG_ERROR(("Get event_msgs error (%d)\n", ret));
944 goto exit;
945 }
946
947 /* apply the set bits */
948 for (i = 0; i < ev->num; i++) {
949 if (ev->event[i].set)
950 setbit(eventmask, ev->event[i].type);
951 else
952 clrbit(eventmask, ev->event[i].type);
953 }
954
955 /* Write updated Event mask */
956 ret = dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "event_msgs", eventmask,
957 sizeof(eventmask), FALSE);
958 if (unlikely(ret)) {
959 CONFIG_ERROR(("Set event_msgs error (%d)\n", ret));
960 }
961
962 exit:
963 return ret;
964 }
965
966 int
dhd_conf_enable_roam_offload(dhd_pub_t * dhd,int enable)967 dhd_conf_enable_roam_offload(dhd_pub_t *dhd, int enable)
968 {
969 int err;
970 eventmsg_buf_t ev_buf;
971
972 if (dhd->conf->roam_off_suspend)
973 return 0;
974
975 err = dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "roam_offload", enable, 0, FALSE);
976 if (err)
977 return err;
978
979 bzero(&ev_buf, sizeof(eventmsg_buf_t));
980 dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_PSK_SUP, !enable);
981 dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_REQ_IE, !enable);
982 dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_RESP_IE, !enable);
983 dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_REASSOC, !enable);
984 dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_JOIN, !enable);
985 dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_ROAM, !enable);
986 err = dhd_conf_apply_eventbuffer(dhd, &ev_buf);
987
988 CONFIG_TRACE(("%s: roam_offload %d\n", __FUNCTION__, enable));
989
990 return err;
991 }
992
993 void
dhd_conf_set_bw_cap(dhd_pub_t * dhd)994 dhd_conf_set_bw_cap(dhd_pub_t *dhd)
995 {
996 struct {
997 u32 band;
998 u32 bw_cap;
999 } param = {0, 0};
1000
1001 if (dhd->conf->bw_cap[0] >= 0) {
1002 memset(¶m, 0, sizeof(param));
1003 param.band = WLC_BAND_2G;
1004 param.bw_cap = (uint)dhd->conf->bw_cap[0];
1005 printf("%s: set bw_cap 2g 0x%x\n", __FUNCTION__, param.bw_cap);
1006 dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "bw_cap", (char *)¶m, sizeof(param), TRUE);
1007 }
1008
1009 if (dhd->conf->bw_cap[1] >= 0) {
1010 memset(¶m, 0, sizeof(param));
1011 param.band = WLC_BAND_5G;
1012 param.bw_cap = (uint)dhd->conf->bw_cap[1];
1013 printf("%s: set bw_cap 5g 0x%x\n", __FUNCTION__, param.bw_cap);
1014 dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "bw_cap", (char *)¶m, sizeof(param), TRUE);
1015 }
1016 }
1017
1018 void
dhd_conf_get_wme(dhd_pub_t * dhd,int ifidx,int mode,edcf_acparam_t * acp)1019 dhd_conf_get_wme(dhd_pub_t *dhd, int ifidx, int mode, edcf_acparam_t *acp)
1020 {
1021 int bcmerror = -1;
1022 char iovbuf[WLC_IOCTL_SMLEN];
1023 edcf_acparam_t *acparam;
1024
1025 bzero(iovbuf, sizeof(iovbuf));
1026
1027 /*
1028 * Get current acparams, using buf as an input buffer.
1029 * Return data is array of 4 ACs of wme params.
1030 */
1031 if (mode == 0)
1032 bcm_mkiovar("wme_ac_sta", NULL, 0, iovbuf, sizeof(iovbuf));
1033 else
1034 bcm_mkiovar("wme_ac_ap", NULL, 0, iovbuf, sizeof(iovbuf));
1035 bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, ifidx);
1036 if (bcmerror < 0) {
1037 CONFIG_ERROR(("%s: wme_ac_sta getting failed %d\n", __FUNCTION__, bcmerror));
1038 return;
1039 }
1040 memcpy((char *)acp, iovbuf, sizeof(edcf_acparam_t)*AC_COUNT);
1041
1042 acparam = &acp[AC_BK];
1043 CONFIG_TRACE(("%s: BK: aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n",
1044 __FUNCTION__,
1045 acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,
1046 acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,
1047 acparam->TXOP));
1048 acparam = &acp[AC_BE];
1049 CONFIG_TRACE(("%s: BE: aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n",
1050 __FUNCTION__,
1051 acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,
1052 acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,
1053 acparam->TXOP));
1054 acparam = &acp[AC_VI];
1055 CONFIG_TRACE(("%s: VI: aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n",
1056 __FUNCTION__,
1057 acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,
1058 acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,
1059 acparam->TXOP));
1060 acparam = &acp[AC_VO];
1061 CONFIG_TRACE(("%s: VO: aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n",
1062 __FUNCTION__,
1063 acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,
1064 acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,
1065 acparam->TXOP));
1066
1067 return;
1068 }
1069
1070 void
dhd_conf_update_wme(dhd_pub_t * dhd,int ifidx,int mode,edcf_acparam_t * acparam_cur,int aci)1071 dhd_conf_update_wme(dhd_pub_t *dhd, int ifidx, int mode,
1072 edcf_acparam_t *acparam_cur, int aci)
1073 {
1074 int aifsn, ecwmin, ecwmax, txop;
1075 edcf_acparam_t *acp;
1076 struct dhd_conf *conf = dhd->conf;
1077 wme_param_t *wme;
1078
1079 if (mode == 0)
1080 wme = &conf->wme_sta;
1081 else
1082 wme = &conf->wme_ap;
1083
1084 /* Default value */
1085 aifsn = acparam_cur->ACI&EDCF_AIFSN_MASK;
1086 ecwmin = acparam_cur->ECW&EDCF_ECWMIN_MASK;
1087 ecwmax = (acparam_cur->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT;
1088 txop = acparam_cur->TXOP;
1089
1090 /* Modified value */
1091 if (wme->aifsn[aci] > 0)
1092 aifsn = wme->aifsn[aci];
1093 if (wme->ecwmin[aci] > 0)
1094 ecwmin = wme->ecwmin[aci];
1095 if (wme->ecwmax[aci] > 0)
1096 ecwmax = wme->ecwmax[aci];
1097 if (wme->txop[aci] > 0)
1098 txop = wme->txop[aci];
1099
1100 if (!(wme->aifsn[aci] || wme->ecwmin[aci] ||
1101 wme->ecwmax[aci] || wme->txop[aci]))
1102 return;
1103
1104 /* Update */
1105 acp = acparam_cur;
1106 acp->ACI = (acp->ACI & ~EDCF_AIFSN_MASK) | (aifsn & EDCF_AIFSN_MASK);
1107 acp->ECW = ((ecwmax << EDCF_ECWMAX_SHIFT) & EDCF_ECWMAX_MASK) | (acp->ECW & EDCF_ECWMIN_MASK);
1108 acp->ECW = ((acp->ECW & EDCF_ECWMAX_MASK) | (ecwmin & EDCF_ECWMIN_MASK));
1109 acp->TXOP = txop;
1110
1111 printf("%s: wme_ac %s aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n",
1112 __FUNCTION__, mode?"ap":"sta",
1113 acp->ACI, acp->ACI&EDCF_AIFSN_MASK,
1114 acp->ECW&EDCF_ECWMIN_MASK, (acp->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,
1115 acp->TXOP);
1116
1117 /*
1118 * Now use buf as an output buffer.
1119 * Put WME acparams after "wme_ac\0" in buf.
1120 * NOTE: only one of the four ACs can be set at a time.
1121 */
1122 if (mode == 0)
1123 dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_VAR, "wme_ac_sta", (char *)acp,
1124 sizeof(edcf_acparam_t), FALSE);
1125 else
1126 dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_VAR, "wme_ac_ap", (char *)acp,
1127 sizeof(edcf_acparam_t), FALSE);
1128 }
1129
1130 void
dhd_conf_set_wme(dhd_pub_t * dhd,int ifidx,int mode)1131 dhd_conf_set_wme(dhd_pub_t *dhd, int ifidx, int mode)
1132 {
1133 edcf_acparam_t acparam_cur[AC_COUNT];
1134
1135 if (dhd && dhd->conf) {
1136 if (!dhd->conf->force_wme_ac) {
1137 CONFIG_TRACE(("%s: force_wme_ac is not enabled %d\n",
1138 __FUNCTION__, dhd->conf->force_wme_ac));
1139 return;
1140 }
1141
1142 CONFIG_TRACE(("%s: Before change:\n", __FUNCTION__));
1143 dhd_conf_get_wme(dhd, ifidx, mode, acparam_cur);
1144
1145 dhd_conf_update_wme(dhd, ifidx, mode, &acparam_cur[AC_BK], AC_BK);
1146 dhd_conf_update_wme(dhd, ifidx, mode, &acparam_cur[AC_BE], AC_BE);
1147 dhd_conf_update_wme(dhd, ifidx, mode, &acparam_cur[AC_VI], AC_VI);
1148 dhd_conf_update_wme(dhd, ifidx, mode, &acparam_cur[AC_VO], AC_VO);
1149
1150 CONFIG_TRACE(("%s: After change:\n", __FUNCTION__));
1151 dhd_conf_get_wme(dhd, ifidx, mode, acparam_cur);
1152 } else {
1153 CONFIG_ERROR(("%s: dhd or conf is NULL\n", __FUNCTION__));
1154 }
1155
1156 return;
1157 }
1158
1159 void
dhd_conf_set_mchan_bw(dhd_pub_t * dhd,int p2p_mode,int miracast_mode)1160 dhd_conf_set_mchan_bw(dhd_pub_t *dhd, int p2p_mode, int miracast_mode)
1161 {
1162 int i;
1163 struct dhd_conf *conf = dhd->conf;
1164 bool set = true;
1165
1166 for (i = 0; i < MCHAN_MAX_NUM; i++) {
1167 set = true;
1168 set &= (conf->mchan[i].bw >= 0);
1169 set &= ((conf->mchan[i].p2p_mode == -1) | (conf->mchan[i].p2p_mode == p2p_mode));
1170 set &= ((conf->mchan[i].miracast_mode == -1) | (conf->mchan[i].miracast_mode == miracast_mode));
1171 if (set) {
1172 dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "mchan_bw", conf->mchan[i].bw, 0, FALSE);
1173 }
1174 }
1175
1176 return;
1177 }
1178
1179 #ifdef PKT_FILTER_SUPPORT
1180 void
dhd_conf_add_pkt_filter(dhd_pub_t * dhd)1181 dhd_conf_add_pkt_filter(dhd_pub_t *dhd)
1182 {
1183 int i, j;
1184 char str[16];
1185 #define MACS "%02x%02x%02x%02x%02x%02x"
1186
1187 /*
1188 * Filter in less pkt: ARP(0x0806, ID is 105), BRCM(0x886C), 802.1X(0x888E)
1189 * 1) dhd_master_mode=1
1190 * 2) pkt_filter_del=100, 102, 103, 104, 105
1191 * 3) pkt_filter_add=131 0 0 12 0xFFFF 0x886C, 132 0 0 12 0xFFFF 0x888E
1192 * 4) magic_pkt_filter_add=141 0 1 12
1193 */
1194 for (i = 0; i < dhd->conf->pkt_filter_add.count; i++) {
1195 dhd->pktfilter[i+dhd->pktfilter_count] = dhd->conf->pkt_filter_add.filter[i];
1196 printf("%s: %s\n", __FUNCTION__, dhd->pktfilter[i+dhd->pktfilter_count]);
1197 }
1198 dhd->pktfilter_count += i;
1199
1200 if (dhd->conf->magic_pkt_filter_add) {
1201 strcat(dhd->conf->magic_pkt_filter_add, " 0x");
1202 strcat(dhd->conf->magic_pkt_filter_add, "FFFFFFFFFFFF");
1203 for (j = 0; j < 16; j++)
1204 strcat(dhd->conf->magic_pkt_filter_add, "FFFFFFFFFFFF");
1205 strcat(dhd->conf->magic_pkt_filter_add, " 0x");
1206 strcat(dhd->conf->magic_pkt_filter_add, "FFFFFFFFFFFF");
1207 sprintf(str, MACS, MAC2STRDBG(dhd->mac.octet));
1208 for (j = 0; j < 16; j++)
1209 strncat(dhd->conf->magic_pkt_filter_add, str, 12);
1210 dhd->pktfilter[dhd->pktfilter_count] = dhd->conf->magic_pkt_filter_add;
1211 dhd->pktfilter_count += 1;
1212 }
1213 }
1214
1215 bool
dhd_conf_del_pkt_filter(dhd_pub_t * dhd,uint32 id)1216 dhd_conf_del_pkt_filter(dhd_pub_t *dhd, uint32 id)
1217 {
1218 int i;
1219
1220 if (dhd && dhd->conf) {
1221 for (i = 0; i < dhd->conf->pkt_filter_del.count; i++) {
1222 if (id == dhd->conf->pkt_filter_del.id[i]) {
1223 printf("%s: %d\n", __FUNCTION__, dhd->conf->pkt_filter_del.id[i]);
1224 return true;
1225 }
1226 }
1227 return false;
1228 }
1229 return false;
1230 }
1231
1232 void
dhd_conf_discard_pkt_filter(dhd_pub_t * dhd)1233 dhd_conf_discard_pkt_filter(dhd_pub_t *dhd)
1234 {
1235 dhd->pktfilter_count = 6;
1236 dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = NULL;
1237 dhd->pktfilter[DHD_BROADCAST_FILTER_NUM] = "101 0 0 0 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF";
1238 dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = "102 0 0 0 0xFFFFFF 0x01005E";
1239 dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = "103 0 0 0 0xFFFF 0x3333";
1240 dhd->pktfilter[DHD_MDNS_FILTER_NUM] = NULL;
1241 /* Do not enable ARP to pkt filter if dhd_master_mode is false.*/
1242 dhd->pktfilter[DHD_ARP_FILTER_NUM] = NULL;
1243
1244 /* IPv4 broadcast address XXX.XXX.XXX.255 */
1245 dhd->pktfilter[dhd->pktfilter_count] =
1246 "110 0 0 12 0xFFFF00000000000000000000000000000000000000FF 0x080000000000000000000000000000000000000000FF";
1247 dhd->pktfilter_count++;
1248 /* discard IPv4 multicast address 224.0.0.0/4 */
1249 dhd->pktfilter[dhd->pktfilter_count] =
1250 "111 0 0 12 0xFFFF00000000000000000000000000000000F0 0x080000000000000000000000000000000000E0";
1251 dhd->pktfilter_count++;
1252 /* discard IPv6 multicast address FF00::/8 */
1253 dhd->pktfilter[dhd->pktfilter_count] = "112 0 0 12 0xFFFF000000000000000000000000000000000000000000000000FF \
1254 0x86DD000000000000000000000000000000000000000000000000FF";
1255 dhd->pktfilter_count++;
1256 /* discard Netbios pkt */
1257 dhd->pktfilter[dhd->pktfilter_count] = "121 0 0 12 0xFFFF000000000000000000FF000000000000000000000000FFFF \
1258 0x0800000000000000000000110000000000000000000000000089";
1259 dhd->pktfilter_count++;
1260 }
1261 #endif /* PKT_FILTER_SUPPORT */
1262
1263 int
dhd_conf_get_pm(dhd_pub_t * dhd)1264 dhd_conf_get_pm(dhd_pub_t *dhd)
1265 {
1266 if (dhd && dhd->conf) {
1267 return dhd->conf->pm;
1268 }
1269 return -1;
1270 }
1271
1272 uint
dhd_conf_get_insuspend(dhd_pub_t * dhd)1273 dhd_conf_get_insuspend(dhd_pub_t *dhd)
1274 {
1275 uint mode = 0;
1276
1277 if (dhd->op_mode & DHD_FLAG_STA_MODE) {
1278 mode = dhd->conf->insuspend &
1279 (NO_EVENT_IN_SUSPEND | NO_TXDATA_IN_SUSPEND | ROAM_OFFLOAD_IN_SUSPEND);
1280 } else if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
1281 mode = dhd->conf->insuspend &
1282 (NO_EVENT_IN_SUSPEND | NO_TXDATA_IN_SUSPEND | AP_DOWN_IN_SUSPEND);
1283 }
1284
1285 return mode;
1286 }
1287
1288 int
dhd_conf_set_suspend_resume(dhd_pub_t * dhd,int suspend)1289 dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int suspend)
1290 {
1291 uint mode = 0, wl_down = 1;
1292 struct dhd_conf *conf = dhd->conf;
1293
1294 mode = dhd_conf_get_insuspend(dhd);
1295 if (mode)
1296 printf("%s: op_mode %d, suspend %d, mode 0x%x\n", __FUNCTION__,
1297 dhd->op_mode, suspend, mode);
1298
1299 if (suspend) {
1300 if (dhd->op_mode & DHD_FLAG_STA_MODE) {
1301 if (mode & ROAM_OFFLOAD_IN_SUSPEND)
1302 dhd_conf_enable_roam_offload(dhd, 1);
1303 } else if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
1304 if (mode & AP_DOWN_IN_SUSPEND) {
1305 dhd_wl_ioctl_cmd(dhd, WLC_DOWN, (char *)&wl_down,
1306 sizeof(wl_down), TRUE, 0);
1307 }
1308 }
1309 #ifdef SUSPEND_EVENT
1310 if (mode & NO_EVENT_IN_SUSPEND) {
1311 char suspend_eventmask[WL_EVENTING_MASK_LEN];
1312 if (!conf->suspended) {
1313 dhd_conf_get_iovar(dhd, 0, WLC_GET_VAR, "event_msgs",
1314 conf->resume_eventmask, sizeof(conf->resume_eventmask));
1315 }
1316 memset(suspend_eventmask, 0, sizeof(suspend_eventmask));
1317 dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "event_msgs",
1318 suspend_eventmask, sizeof(suspend_eventmask), FALSE);
1319 }
1320 #endif
1321 conf->suspended = TRUE;
1322 } else {
1323 #ifdef SUSPEND_EVENT
1324 if (mode & NO_EVENT_IN_SUSPEND) {
1325 dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "event_msgs",
1326 conf->resume_eventmask, sizeof(conf->resume_eventmask), FALSE);
1327 if (dhd->op_mode & DHD_FLAG_STA_MODE) {
1328 struct ether_addr bssid;
1329 int ret = 0;
1330 ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID, &bssid,
1331 sizeof(struct ether_addr), FALSE, 0);
1332 if (ret != BCME_NOTASSOCIATED && !memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) {
1333 CONFIG_TRACE(("%s: send disassoc\n", __FUNCTION__));
1334 dhd_conf_set_intiovar(dhd, WLC_DISASSOC, "WLC_DISASSOC", 0, 0, FALSE);
1335 }
1336 }
1337 }
1338 #endif
1339 if (dhd->op_mode & DHD_FLAG_STA_MODE) {
1340 if (mode & ROAM_OFFLOAD_IN_SUSPEND)
1341 dhd_conf_enable_roam_offload(dhd, 0);
1342 } else if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
1343 if (mode & AP_DOWN_IN_SUSPEND) {
1344 wl_down = 0;
1345 dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&wl_down,
1346 sizeof(wl_down), TRUE, 0);
1347 }
1348 }
1349 conf->suspended = FALSE;
1350 }
1351
1352 return 0;
1353 }
1354
1355 #ifdef PROP_TXSTATUS
1356 int
dhd_conf_get_disable_proptx(dhd_pub_t * dhd)1357 dhd_conf_get_disable_proptx(dhd_pub_t *dhd)
1358 {
1359 struct dhd_conf *conf = dhd->conf;
1360 int disable_proptx = -1;
1361 int fw_proptx = 0;
1362
1363 /* check fw proptx priority:
1364 * 1st: check fw support by wl cap
1365 * 2nd: 4334/43340/43341/43241 support proptx but not show in wl cap, so enable it by default
1366 * if you would like to disable it, please set disable_proptx=1 in config.txt
1367 * 3th: disable when proptxstatus not support in wl cap
1368 */
1369 if (FW_SUPPORTED(dhd, proptxstatus)) {
1370 fw_proptx = 1;
1371 } else if (conf->chip == BCM4334_CHIP_ID || conf->chip == BCM43340_CHIP_ID ||
1372 dhd->conf->chip == BCM43340_CHIP_ID || conf->chip == BCM4324_CHIP_ID) {
1373 fw_proptx = 1;
1374 } else {
1375 fw_proptx = 0;
1376 }
1377
1378 /* returned disable_proptx value:
1379 * -1: disable in STA and enable in P2P(follow original dhd settings when PROP_TXSTATUS_VSDB enabled)
1380 * 0: depend on fw support
1381 * 1: always disable proptx
1382 */
1383 if (conf->disable_proptx == 0) {
1384 // check fw support as well
1385 if (fw_proptx)
1386 disable_proptx = 0;
1387 else
1388 disable_proptx = 1;
1389 } else if (conf->disable_proptx >= 1) {
1390 disable_proptx = 1;
1391 } else {
1392 // check fw support as well
1393 if (fw_proptx)
1394 disable_proptx = -1;
1395 else
1396 disable_proptx = 1;
1397 }
1398
1399 printf("%s: fw_proptx=%d, disable_proptx=%d\n", __FUNCTION__, fw_proptx, disable_proptx);
1400
1401 return disable_proptx;
1402 }
1403 #endif
1404
1405 uint
pick_config_vars(char * varbuf,uint len,uint start_pos,char * pickbuf)1406 pick_config_vars(char *varbuf, uint len, uint start_pos, char *pickbuf)
1407 {
1408 bool findNewline, changenewline = FALSE, pick = FALSE;
1409 int column;
1410 uint n, pick_column = 0;
1411
1412 findNewline = FALSE;
1413 column = 0;
1414
1415 if (start_pos >= len) {
1416 CONFIG_ERROR(("%s: wrong start pos\n", __FUNCTION__));
1417 return 0;
1418 }
1419
1420 for (n = start_pos; n < len; n++) {
1421 if (varbuf[n] == '\r')
1422 continue;
1423 if ((findNewline || changenewline) && varbuf[n] != '\n')
1424 continue;
1425 findNewline = FALSE;
1426 if (varbuf[n] == '#') {
1427 findNewline = TRUE;
1428 continue;
1429 }
1430 if (varbuf[n] == '\\') {
1431 changenewline = TRUE;
1432 continue;
1433 }
1434 if (!changenewline && varbuf[n] == '\n') {
1435 if (column == 0)
1436 continue;
1437 column = 0;
1438 continue;
1439 }
1440 if (changenewline && varbuf[n] == '\n') {
1441 changenewline = FALSE;
1442 continue;
1443 }
1444
1445 if (column == 0 && !pick) { // start to pick
1446 pick = TRUE;
1447 column++;
1448 pick_column = 0;
1449 } else {
1450 if (pick && column == 0) { // stop to pick
1451 pick = FALSE;
1452 break;
1453 } else
1454 column++;
1455 }
1456 if (pick) {
1457 if (varbuf[n] == 0x9)
1458 continue;
1459 pickbuf[pick_column] = varbuf[n];
1460 pick_column++;
1461 }
1462 }
1463
1464 return n; // return current position
1465 }
1466
1467 bool
dhd_conf_read_log_level(dhd_pub_t * dhd,char * full_param,uint len_param)1468 dhd_conf_read_log_level(dhd_pub_t *dhd, char *full_param, uint len_param)
1469 {
1470 char *data = full_param+len_param;
1471
1472 if (!strncmp("dhd_msg_level=", full_param, len_param)) {
1473 dhd_msg_level = (int)simple_strtol(data, NULL, 0);
1474 printf("%s: dhd_msg_level = 0x%X\n", __FUNCTION__, dhd_msg_level);
1475 }
1476 #ifdef BCMSDIO
1477 else if (!strncmp("sd_msglevel=", full_param, len_param)) {
1478 sd_msglevel = (int)simple_strtol(data, NULL, 0);
1479 printf("%s: sd_msglevel = 0x%X\n", __FUNCTION__, sd_msglevel);
1480 }
1481 #endif
1482 #ifdef BCMDBUS
1483 else if (!strncmp("dbus_msglevel=", full_param, len_param)) {
1484 dbus_msglevel = (int)simple_strtol(data, NULL, 0);
1485 printf("%s: dbus_msglevel = 0x%X\n", __FUNCTION__, dbus_msglevel);
1486 }
1487 #endif
1488 else if (!strncmp("android_msg_level=", full_param, len_param)) {
1489 android_msg_level = (int)simple_strtol(data, NULL, 0);
1490 printf("%s: android_msg_level = 0x%X\n", __FUNCTION__, android_msg_level);
1491 } else if (!strncmp("config_msg_level=", full_param, len_param)) {
1492 config_msg_level = (int)simple_strtol(data, NULL, 0);
1493 printf("%s: config_msg_level = 0x%X\n", __FUNCTION__, config_msg_level);
1494 }
1495 #ifdef WL_CFG80211
1496 else if (!strncmp("wl_dbg_level=", full_param, len_param)) {
1497 wl_dbg_level = (int)simple_strtol(data, NULL, 0);
1498 printf("%s: wl_dbg_level = 0x%X\n", __FUNCTION__, wl_dbg_level);
1499 }
1500 #endif
1501 #if defined(WL_WIRELESS_EXT)
1502 else if (!strncmp("iw_msg_level=", full_param, len_param)) {
1503 iw_msg_level = (int)simple_strtol(data, NULL, 0);
1504 printf("%s: iw_msg_level = 0x%X\n", __FUNCTION__, iw_msg_level);
1505 }
1506 #endif
1507 #if defined(DHD_DEBUG)
1508 else if (!strncmp("dhd_console_ms=", full_param, len_param)) {
1509 dhd_console_ms = (int)simple_strtol(data, NULL, 0);
1510 printf("%s: dhd_console_ms = 0x%X\n", __FUNCTION__, dhd_console_ms);
1511 }
1512 #endif
1513 else
1514 return false;
1515
1516 return true;
1517 }
1518
1519 void
dhd_conf_read_wme_ac_value(wme_param_t * wme,char * pick,int ac_val)1520 dhd_conf_read_wme_ac_value(wme_param_t *wme, char *pick, int ac_val)
1521 {
1522 char *pick_tmp, *pch;
1523
1524 pick_tmp = pick;
1525 pch = bcmstrstr(pick_tmp, "aifsn ");
1526 if (pch) {
1527 wme->aifsn[ac_val] = (int)simple_strtol(pch+strlen("aifsn "), NULL, 0);
1528 printf("%s: ac_val=%d, aifsn=%d\n", __FUNCTION__, ac_val, wme->aifsn[ac_val]);
1529 }
1530 pick_tmp = pick;
1531 pch = bcmstrstr(pick_tmp, "ecwmin ");
1532 if (pch) {
1533 wme->ecwmin[ac_val] = (int)simple_strtol(pch+strlen("ecwmin "), NULL, 0);
1534 printf("%s: ac_val=%d, ecwmin=%d\n", __FUNCTION__, ac_val, wme->ecwmin[ac_val]);
1535 }
1536 pick_tmp = pick;
1537 pch = bcmstrstr(pick_tmp, "ecwmax ");
1538 if (pch) {
1539 wme->ecwmax[ac_val] = (int)simple_strtol(pch+strlen("ecwmax "), NULL, 0);
1540 printf("%s: ac_val=%d, ecwmax=%d\n", __FUNCTION__, ac_val, wme->ecwmax[ac_val]);
1541 }
1542 pick_tmp = pick;
1543 pch = bcmstrstr(pick_tmp, "txop ");
1544 if (pch) {
1545 wme->txop[ac_val] = (int)simple_strtol(pch+strlen("txop "), NULL, 0);
1546 printf("%s: ac_val=%d, txop=0x%x\n", __FUNCTION__, ac_val, wme->txop[ac_val]);
1547 }
1548 }
1549
1550 bool
dhd_conf_read_wme_ac_params(dhd_pub_t * dhd,char * full_param,uint len_param)1551 dhd_conf_read_wme_ac_params(dhd_pub_t *dhd, char *full_param, uint len_param)
1552 {
1553 struct dhd_conf *conf = dhd->conf;
1554 char *data = full_param+len_param;
1555
1556 // wme_ac_sta_be=aifsn 1 ecwmin 2 ecwmax 3 txop 0x5e
1557 // wme_ac_sta_vo=aifsn 1 ecwmin 1 ecwmax 1 txop 0x5e
1558
1559 if (!strncmp("force_wme_ac=", full_param, len_param)) {
1560 conf->force_wme_ac = (int)simple_strtol(data, NULL, 10);
1561 printf("%s: force_wme_ac = %d\n", __FUNCTION__, conf->force_wme_ac);
1562 } else if (!strncmp("wme_ac_sta_be=", full_param, len_param)) {
1563 dhd_conf_read_wme_ac_value(&conf->wme_sta, data, AC_BE);
1564 } else if (!strncmp("wme_ac_sta_bk=", full_param, len_param)) {
1565 dhd_conf_read_wme_ac_value(&conf->wme_sta, data, AC_BK);
1566 } else if (!strncmp("wme_ac_sta_vi=", full_param, len_param)) {
1567 dhd_conf_read_wme_ac_value(&conf->wme_sta, data, AC_VI);
1568 } else if (!strncmp("wme_ac_sta_vo=", full_param, len_param)) {
1569 dhd_conf_read_wme_ac_value(&conf->wme_sta, data, AC_VO);
1570 } else if (!strncmp("wme_ac_ap_be=", full_param, len_param)) {
1571 dhd_conf_read_wme_ac_value(&conf->wme_ap, data, AC_BE);
1572 } else if (!strncmp("wme_ac_ap_bk=", full_param, len_param)) {
1573 dhd_conf_read_wme_ac_value(&conf->wme_ap, data, AC_BK);
1574 } else if (!strncmp("wme_ac_ap_vi=", full_param, len_param)) {
1575 dhd_conf_read_wme_ac_value(&conf->wme_ap, data, AC_VI);
1576 } else if (!strncmp("wme_ac_ap_vo=", full_param, len_param)) {
1577 dhd_conf_read_wme_ac_value(&conf->wme_ap, data, AC_VO);
1578 } else
1579 return false;
1580
1581 return true;
1582 }
1583
1584 #ifdef BCMSDIO
1585 bool
dhd_conf_read_fw_by_mac(dhd_pub_t * dhd,char * full_param,uint len_param)1586 dhd_conf_read_fw_by_mac(dhd_pub_t *dhd, char *full_param, uint len_param)
1587 {
1588 int i, j;
1589 char *pch, *pick_tmp;
1590 wl_mac_list_t *mac_list;
1591 wl_mac_range_t *mac_range;
1592 struct dhd_conf *conf = dhd->conf;
1593 char *data = full_param+len_param;
1594
1595 /* Process fw_by_mac:
1596 * fw_by_mac=[fw_mac_num] \
1597 * [fw_name1] [mac_num1] [oui1-1] [nic_start1-1] [nic_end1-1] \
1598 * [oui1-1] [nic_start1-1] [nic_end1-1]... \
1599 * [oui1-n] [nic_start1-n] [nic_end1-n] \
1600 * [fw_name2] [mac_num2] [oui2-1] [nic_start2-1] [nic_end2-1] \
1601 * [oui2-1] [nic_start2-1] [nic_end2-1]... \
1602 * [oui2-n] [nic_start2-n] [nic_end2-n] \
1603 * Ex: fw_by_mac=2 \
1604 * fw_bcmdhd1.bin 2 0x0022F4 0xE85408 0xE8549D 0x983B16 0x3557A9 0x35582A \
1605 * fw_bcmdhd2.bin 3 0x0022F4 0xE85408 0xE8549D 0x983B16 0x3557A9 0x35582A \
1606 * 0x983B16 0x916157 0x916487
1607 */
1608
1609 if (!strncmp("fw_by_mac=", full_param, len_param)) {
1610 pick_tmp = data;
1611 pch = bcmstrtok(&pick_tmp, " ", 0);
1612 conf->fw_by_mac.count = (uint32)simple_strtol(pch, NULL, 0);
1613 mac_list = kmalloc(sizeof(wl_mac_list_t)*conf->fw_by_mac.count, GFP_KERNEL);
1614 if (!mac_list) {
1615 conf->fw_by_mac.count = 0;
1616 CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
1617 }
1618 printf("%s: fw_count=%d\n", __FUNCTION__, conf->fw_by_mac.count);
1619 conf->fw_by_mac.m_mac_list_head = mac_list;
1620 for (i = 0; i < conf->fw_by_mac.count; i++) {
1621 pch = bcmstrtok(&pick_tmp, " ", 0);
1622 strcpy(mac_list[i].name, pch);
1623 pch = bcmstrtok(&pick_tmp, " ", 0);
1624 mac_list[i].count = (uint32)simple_strtol(pch, NULL, 0);
1625 printf("%s: name=%s, mac_count=%d\n", __FUNCTION__,
1626 mac_list[i].name, mac_list[i].count);
1627 mac_range = kmalloc(sizeof(wl_mac_range_t)*mac_list[i].count, GFP_KERNEL);
1628 if (!mac_range) {
1629 mac_list[i].count = 0;
1630 CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
1631 break;
1632 }
1633 mac_list[i].mac = mac_range;
1634 for (j = 0; j < mac_list[i].count; j++) {
1635 pch = bcmstrtok(&pick_tmp, " ", 0);
1636 mac_range[j].oui = (uint32)simple_strtol(pch, NULL, 0);
1637 pch = bcmstrtok(&pick_tmp, " ", 0);
1638 mac_range[j].nic_start = (uint32)simple_strtol(pch, NULL, 0);
1639 pch = bcmstrtok(&pick_tmp, " ", 0);
1640 mac_range[j].nic_end = (uint32)simple_strtol(pch, NULL, 0);
1641 printf("%s: oui=0x%06X, nic_start=0x%06X, nic_end=0x%06X\n",
1642 __FUNCTION__, mac_range[j].oui,
1643 mac_range[j].nic_start, mac_range[j].nic_end);
1644 }
1645 }
1646 } else
1647 return false;
1648
1649 return true;
1650 }
1651
1652 bool
dhd_conf_read_nv_by_mac(dhd_pub_t * dhd,char * full_param,uint len_param)1653 dhd_conf_read_nv_by_mac(dhd_pub_t *dhd, char *full_param, uint len_param)
1654 {
1655 int i, j;
1656 char *pch, *pick_tmp;
1657 wl_mac_list_t *mac_list;
1658 wl_mac_range_t *mac_range;
1659 struct dhd_conf *conf = dhd->conf;
1660 char *data = full_param+len_param;
1661
1662 /* Process nv_by_mac:
1663 * [nv_by_mac]: The same format as fw_by_mac
1664 */
1665 if (!strncmp("nv_by_mac=", full_param, len_param)) {
1666 pick_tmp = data;
1667 pch = bcmstrtok(&pick_tmp, " ", 0);
1668 conf->nv_by_mac.count = (uint32)simple_strtol(pch, NULL, 0);
1669 mac_list = kmalloc(sizeof(wl_mac_list_t)*conf->nv_by_mac.count, GFP_KERNEL);
1670 if (!mac_list) {
1671 conf->nv_by_mac.count = 0;
1672 CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
1673 }
1674 printf("%s: nv_count=%d\n", __FUNCTION__, conf->nv_by_mac.count);
1675 conf->nv_by_mac.m_mac_list_head = mac_list;
1676 for (i = 0; i < conf->nv_by_mac.count; i++) {
1677 pch = bcmstrtok(&pick_tmp, " ", 0);
1678 strcpy(mac_list[i].name, pch);
1679 pch = bcmstrtok(&pick_tmp, " ", 0);
1680 mac_list[i].count = (uint32)simple_strtol(pch, NULL, 0);
1681 printf("%s: name=%s, mac_count=%d\n", __FUNCTION__,
1682 mac_list[i].name, mac_list[i].count);
1683 mac_range = kmalloc(sizeof(wl_mac_range_t)*mac_list[i].count, GFP_KERNEL);
1684 if (!mac_range) {
1685 mac_list[i].count = 0;
1686 CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
1687 break;
1688 }
1689 mac_list[i].mac = mac_range;
1690 for (j = 0; j < mac_list[i].count; j++) {
1691 pch = bcmstrtok(&pick_tmp, " ", 0);
1692 mac_range[j].oui = (uint32)simple_strtol(pch, NULL, 0);
1693 pch = bcmstrtok(&pick_tmp, " ", 0);
1694 mac_range[j].nic_start = (uint32)simple_strtol(pch, NULL, 0);
1695 pch = bcmstrtok(&pick_tmp, " ", 0);
1696 mac_range[j].nic_end = (uint32)simple_strtol(pch, NULL, 0);
1697 printf("%s: oui=0x%06X, nic_start=0x%06X, nic_end=0x%06X\n",
1698 __FUNCTION__, mac_range[j].oui,
1699 mac_range[j].nic_start, mac_range[j].nic_end);
1700 }
1701 }
1702 } else
1703 return false;
1704
1705 return true;
1706 }
1707 #endif
1708
1709 bool
dhd_conf_read_nv_by_chip(dhd_pub_t * dhd,char * full_param,uint len_param)1710 dhd_conf_read_nv_by_chip(dhd_pub_t *dhd, char *full_param, uint len_param)
1711 {
1712 int i;
1713 char *pch, *pick_tmp;
1714 wl_chip_nv_path_t *chip_nv_path;
1715 struct dhd_conf *conf = dhd->conf;
1716 char *data = full_param+len_param;
1717
1718 /* Process nv_by_chip:
1719 * nv_by_chip=[nv_chip_num] \
1720 * [chip1] [chiprev1] [nv_name1] [chip2] [chiprev2] [nv_name2] \
1721 * Ex: nv_by_chip=2 \
1722 * 43430 0 nvram_ap6212.txt 43430 1 nvram_ap6212a.txt \
1723 */
1724 if (!strncmp("nv_by_chip=", full_param, len_param)) {
1725 pick_tmp = data;
1726 pch = bcmstrtok(&pick_tmp, " ", 0);
1727 conf->nv_by_chip.count = (uint32)simple_strtol(pch, NULL, 0);
1728 chip_nv_path = kmalloc(sizeof(wl_mac_list_t)*conf->nv_by_chip.count, GFP_KERNEL);
1729 if (!chip_nv_path) {
1730 conf->nv_by_chip.count = 0;
1731 CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
1732 }
1733 printf("%s: nv_by_chip_count=%d\n", __FUNCTION__, conf->nv_by_chip.count);
1734 conf->nv_by_chip.m_chip_nv_path_head = chip_nv_path;
1735 for (i = 0; i < conf->nv_by_chip.count; i++) {
1736 pch = bcmstrtok(&pick_tmp, " ", 0);
1737 chip_nv_path[i].chip = (uint32)simple_strtol(pch, NULL, 0);
1738 pch = bcmstrtok(&pick_tmp, " ", 0);
1739 chip_nv_path[i].chiprev = (uint32)simple_strtol(pch, NULL, 0);
1740 pch = bcmstrtok(&pick_tmp, " ", 0);
1741 strcpy(chip_nv_path[i].name, pch);
1742 printf("%s: chip=0x%x, chiprev=%d, name=%s\n", __FUNCTION__,
1743 chip_nv_path[i].chip, chip_nv_path[i].chiprev, chip_nv_path[i].name);
1744 }
1745 } else
1746 return false;
1747
1748 return true;
1749 }
1750
1751 bool
dhd_conf_read_roam_params(dhd_pub_t * dhd,char * full_param,uint len_param)1752 dhd_conf_read_roam_params(dhd_pub_t *dhd, char *full_param, uint len_param)
1753 {
1754 struct dhd_conf *conf = dhd->conf;
1755 char *data = full_param+len_param;
1756
1757 if (!strncmp("roam_off=", full_param, len_param)) {
1758 if (!strncmp(data, "0", 1))
1759 conf->roam_off = 0;
1760 else
1761 conf->roam_off = 1;
1762 printf("%s: roam_off = %d\n", __FUNCTION__, conf->roam_off);
1763 } else if (!strncmp("roam_off_suspend=", full_param, len_param)) {
1764 if (!strncmp(data, "0", 1))
1765 conf->roam_off_suspend = 0;
1766 else
1767 conf->roam_off_suspend = 1;
1768 printf("%s: roam_off_suspend = %d\n", __FUNCTION__, conf->roam_off_suspend);
1769 } else if (!strncmp("roam_trigger=", full_param, len_param)) {
1770 conf->roam_trigger[0] = (int)simple_strtol(data, NULL, 10);
1771 printf("%s: roam_trigger = %d\n", __FUNCTION__,
1772 conf->roam_trigger[0]);
1773 } else if (!strncmp("roam_scan_period=", full_param, len_param)) {
1774 conf->roam_scan_period[0] = (int)simple_strtol(data, NULL, 10);
1775 printf("%s: roam_scan_period = %d\n", __FUNCTION__,
1776 conf->roam_scan_period[0]);
1777 } else if (!strncmp("roam_delta=", full_param, len_param)) {
1778 conf->roam_delta[0] = (int)simple_strtol(data, NULL, 10);
1779 printf("%s: roam_delta = %d\n", __FUNCTION__, conf->roam_delta[0]);
1780 } else if (!strncmp("fullroamperiod=", full_param, len_param)) {
1781 conf->fullroamperiod = (int)simple_strtol(data, NULL, 10);
1782 printf("%s: fullroamperiod = %d\n", __FUNCTION__,
1783 conf->fullroamperiod);
1784 } else
1785 return false;
1786
1787 return true;
1788 }
1789
1790 bool
dhd_conf_read_country_list(dhd_pub_t * dhd,char * full_param,uint len_param)1791 dhd_conf_read_country_list(dhd_pub_t *dhd, char *full_param, uint len_param)
1792 {
1793 int i;
1794 char *pch, *pick_tmp, *pick_tmp2;
1795 struct dhd_conf *conf = dhd->conf;
1796 char *data = full_param+len_param;
1797 wl_country_t *cspec;
1798 conf_country_list_t *country_list = NULL;
1799
1800 /* Process country_list:
1801 * country_list=[country1]:[ccode1]/[regrev1],
1802 * [country2]:[ccode2]/[regrev2] \
1803 * Ex: country_list=US:US/0, TW:TW/1
1804 */
1805 if (!strncmp("country_list=", full_param, len_param)) {
1806 country_list = &dhd->conf->country_list;
1807 }
1808 if (country_list) {
1809 pick_tmp = data;
1810 for (i = 0; i < CONFIG_COUNTRY_LIST_SIZE; i++) {
1811 pick_tmp2 = bcmstrtok(&pick_tmp, ", ", 0);
1812 if (!pick_tmp2)
1813 break;
1814 pch = bcmstrtok(&pick_tmp2, ":", 0);
1815 if (!pch)
1816 break;
1817 cspec = NULL;
1818 cspec = kmalloc(sizeof(wl_country_t), GFP_KERNEL);
1819 if (!cspec) {
1820 CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
1821 break;
1822 }
1823 memset(cspec, 0, sizeof(wl_country_t));
1824
1825 strcpy(cspec->country_abbrev, pch);
1826 pch = bcmstrtok(&pick_tmp2, "/", 0);
1827 if (!pch) {
1828 kfree(cspec);
1829 break;
1830 }
1831 memcpy(cspec->ccode, pch, 2);
1832 pch = bcmstrtok(&pick_tmp2, "/", 0);
1833 if (!pch) {
1834 kfree(cspec);
1835 break;
1836 }
1837 cspec->rev = (int32)simple_strtol(pch, NULL, 10);
1838 country_list->count++;
1839 country_list->cspec[i] = cspec;
1840 CONFIG_TRACE(("%s: country_list abbrev=%s, ccode=%s, regrev=%d\n", __FUNCTION__,
1841 cspec->country_abbrev, cspec->ccode, cspec->rev));
1842 }
1843 if (!strncmp("country_list=", full_param, len_param)) {
1844 printf("%s: %d country in list\n", __FUNCTION__, conf->country_list.count);
1845 }
1846 } else
1847 return false;
1848
1849 return true;
1850 }
1851
1852 bool
dhd_conf_read_mchan_params(dhd_pub_t * dhd,char * full_param,uint len_param)1853 dhd_conf_read_mchan_params(dhd_pub_t *dhd, char *full_param, uint len_param)
1854 {
1855 int i;
1856 char *pch, *pick_tmp, *pick_tmp2;
1857 struct dhd_conf *conf = dhd->conf;
1858 char *data = full_param+len_param;
1859
1860 /* Process mchan_bw:
1861 * mchan_bw=[val]/[any/go/gc]/[any/source/sink]
1862 * Ex: mchan_bw=80/go/source, 30/gc/sink
1863 */
1864 if (!strncmp("mchan_bw=", full_param, len_param)) {
1865 pick_tmp = data;
1866 for (i = 0; i < MCHAN_MAX_NUM; i++) {
1867 pick_tmp2 = bcmstrtok(&pick_tmp, ", ", 0);
1868 if (!pick_tmp2)
1869 break;
1870 pch = bcmstrtok(&pick_tmp2, "/", 0);
1871 if (!pch) {
1872 break;
1873 } else {
1874 conf->mchan[i].bw = (int)simple_strtol(pch, NULL, 0);
1875 if (conf->mchan[i].bw < 0 || conf->mchan[i].bw > 100) {
1876 CONFIG_ERROR(("%s: wrong bw %d\n", __FUNCTION__, conf->mchan[i].bw));
1877 conf->mchan[i].bw = 0;
1878 break;
1879 }
1880 }
1881 pch = bcmstrtok(&pick_tmp2, "/", 0);
1882 if (!pch) {
1883 break;
1884 } else {
1885 if (bcmstrstr(pch, "any")) {
1886 conf->mchan[i].p2p_mode = -1;
1887 } else if (bcmstrstr(pch, "go")) {
1888 conf->mchan[i].p2p_mode = WL_P2P_IF_GO;
1889 } else if (bcmstrstr(pch, "gc")) {
1890 conf->mchan[i].p2p_mode = WL_P2P_IF_CLIENT;
1891 }
1892 }
1893 pch = bcmstrtok(&pick_tmp2, "/", 0);
1894 if (!pch) {
1895 break;
1896 } else {
1897 if (bcmstrstr(pch, "any")) {
1898 conf->mchan[i].miracast_mode = -1;
1899 } else if (bcmstrstr(pch, "source")) {
1900 conf->mchan[i].miracast_mode = MIRACAST_SOURCE;
1901 } else if (bcmstrstr(pch, "sink")) {
1902 conf->mchan[i].miracast_mode = MIRACAST_SINK;
1903 }
1904 }
1905 }
1906 for (i = 0; i < MCHAN_MAX_NUM; i++) {
1907 if (conf->mchan[i].bw >= 0)
1908 printf("%s: mchan_bw=%d/%d/%d\n", __FUNCTION__,
1909 conf->mchan[i].bw, conf->mchan[i].p2p_mode, conf->mchan[i].miracast_mode);
1910 }
1911 } else
1912 return false;
1913
1914 return true;
1915 }
1916
1917 #ifdef PKT_FILTER_SUPPORT
1918 bool
dhd_conf_read_pkt_filter(dhd_pub_t * dhd,char * full_param,uint len_param)1919 dhd_conf_read_pkt_filter(dhd_pub_t *dhd, char *full_param, uint len_param)
1920 {
1921 struct dhd_conf *conf = dhd->conf;
1922 char *data = full_param+len_param;
1923 char *pch, *pick_tmp;
1924 int i;
1925
1926 /* Process pkt filter:
1927 * 1) pkt_filter_add=99 0 0 0 0x000000000000 0x000000000000
1928 * 2) pkt_filter_del=100, 102, 103, 104, 105
1929 * 3) magic_pkt_filter_add=141 0 1 12
1930 */
1931 if (!strncmp("dhd_master_mode=", full_param, len_param)) {
1932 if (!strncmp(data, "0", 1))
1933 dhd_master_mode = FALSE;
1934 else
1935 dhd_master_mode = TRUE;
1936 printf("%s: dhd_master_mode = %d\n", __FUNCTION__, dhd_master_mode);
1937 } else if (!strncmp("pkt_filter_add=", full_param, len_param)) {
1938 pick_tmp = data;
1939 pch = bcmstrtok(&pick_tmp, ",.-", 0);
1940 i = 0;
1941 while (pch != NULL && i < DHD_CONF_FILTER_MAX) {
1942 strcpy(&conf->pkt_filter_add.filter[i][0], pch);
1943 printf("%s: pkt_filter_add[%d][] = %s\n", __FUNCTION__, i, &conf->pkt_filter_add.filter[i][0]);
1944 pch = bcmstrtok(&pick_tmp, ",.-", 0);
1945 i++;
1946 }
1947 conf->pkt_filter_add.count = i;
1948 } else if (!strncmp("pkt_filter_del=", full_param, len_param)) {
1949 pick_tmp = data;
1950 pch = bcmstrtok(&pick_tmp, " ,.-", 0);
1951 i = 0;
1952 while (pch != NULL && i < DHD_CONF_FILTER_MAX) {
1953 conf->pkt_filter_del.id[i] = (uint32)simple_strtol(pch, NULL, 10);
1954 pch = bcmstrtok(&pick_tmp, " ,.-", 0);
1955 i++;
1956 }
1957 conf->pkt_filter_del.count = i;
1958 printf("%s: pkt_filter_del id = ", __FUNCTION__);
1959 for (i = 0; i < conf->pkt_filter_del.count; i++)
1960 printf("%d ", conf->pkt_filter_del.id[i]);
1961 printf("\n");
1962 } else if (!strncmp("magic_pkt_filter_add=", full_param, len_param)) {
1963 conf->magic_pkt_filter_add = kmalloc(MAGIC_PKT_FILTER_LEN, GFP_KERNEL);
1964 if (!conf->magic_pkt_filter_add) {
1965 CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
1966 } else {
1967 memset(conf->magic_pkt_filter_add, 0, MAGIC_PKT_FILTER_LEN);
1968 strcpy(conf->magic_pkt_filter_add, data);
1969 printf("%s: magic_pkt_filter_add = %s\n", __FUNCTION__, conf->magic_pkt_filter_add);
1970 }
1971 } else
1972 return false;
1973
1974 return true;
1975 }
1976 #endif
1977
1978 #ifdef ISAM_PREINIT
1979 /*
1980 * isam_init=mode [sta|ap|apsta|dualap] vifname [wlan1]
1981 * isam_config=ifname [wlan0|wlan1] ssid [xxx] chan [x]
1982 hidden [y|n] maxassoc [x]
1983 amode [open|shared|wpapsk|wpa2psk|wpawpa2psk]
1984 emode [none|wep|tkip|aes|tkipaes]
1985 key [xxxxx]
1986 * isam_enable=ifname [wlan0|wlan1]
1987 */
1988 bool
dhd_conf_read_isam(dhd_pub_t * dhd,char * full_param,uint len_param)1989 dhd_conf_read_isam(dhd_pub_t *dhd, char *full_param, uint len_param)
1990 {
1991 struct dhd_conf *conf = dhd->conf;
1992 char *data = full_param+len_param;
1993
1994 if (!strncmp("isam_init=", full_param, len_param)) {
1995 sprintf(conf->isam_init, "isam_init %s", data);
1996 printf("%s: isam_init=%s\n", __FUNCTION__, conf->isam_init);
1997 } else if (!strncmp("isam_config=", full_param, len_param)) {
1998 sprintf(conf->isam_config, "isam_config %s", data);
1999 printf("%s: isam_config=%s\n", __FUNCTION__, conf->isam_config);
2000 } else if (!strncmp("isam_enable=", full_param, len_param)) {
2001 sprintf(conf->isam_enable, "isam_enable %s", data);
2002 printf("%s: isam_enable=%s\n", __FUNCTION__, conf->isam_enable);
2003 } else
2004 return false;
2005
2006 return true;
2007 }
2008 #endif
2009
2010 #ifdef IDHCP
2011 bool
dhd_conf_read_dhcp_params(dhd_pub_t * dhd,char * full_param,uint len_param)2012 dhd_conf_read_dhcp_params(dhd_pub_t *dhd, char *full_param, uint len_param)
2013 {
2014 struct dhd_conf *conf = dhd->conf;
2015 char *data = full_param+len_param;
2016 struct ipv4_addr ipa_set;
2017
2018 if (!strncmp("dhcpc_enable=", full_param, len_param)) {
2019 conf->dhcpc_enable = (int)simple_strtol(data, NULL, 10);
2020 printf("%s: dhcpc_enable = %d\n", __FUNCTION__, conf->dhcpc_enable);
2021 } else if (!strncmp("dhcpd_enable=", full_param, len_param)) {
2022 conf->dhcpd_enable = (int)simple_strtol(data, NULL, 10);
2023 printf("%s: dhcpd_enable = %d\n", __FUNCTION__, conf->dhcpd_enable);
2024 } else if (!strncmp("dhcpd_ip_addr=", full_param, len_param)) {
2025 if (!bcm_atoipv4(data, &ipa_set))
2026 printf("%s : dhcpd_ip_addr adress setting failed.\n", __FUNCTION__);
2027 conf->dhcpd_ip_addr = ipa_set;
2028 printf("%s: dhcpd_ip_addr = %s\n", __FUNCTION__, data);
2029 } else if (!strncmp("dhcpd_ip_mask=", full_param, len_param)) {
2030 if (!bcm_atoipv4(data, &ipa_set))
2031 printf("%s : dhcpd_ip_mask adress setting failed.\n", __FUNCTION__);
2032 conf->dhcpd_ip_mask = ipa_set;
2033 printf("%s: dhcpd_ip_mask = %s\n", __FUNCTION__, data);
2034 } else if (!strncmp("dhcpd_ip_start=", full_param, len_param)) {
2035 if (!bcm_atoipv4(data, &ipa_set))
2036 printf("%s : dhcpd_ip_start adress setting failed.\n", __FUNCTION__);
2037 conf->dhcpd_ip_start = ipa_set;
2038 printf("%s: dhcpd_ip_start = %s\n", __FUNCTION__, data);
2039 } else if (!strncmp("dhcpd_ip_end=", full_param, len_param)) {
2040 if (!bcm_atoipv4(data, &ipa_set))
2041 printf("%s : dhcpd_ip_end adress setting failed.\n", __FUNCTION__);
2042 conf->dhcpd_ip_end = ipa_set;
2043 printf("%s: dhcpd_ip_end = %s\n", __FUNCTION__, data);
2044 } else
2045 return false;
2046
2047 return true;
2048 }
2049 #endif
2050
2051 #ifdef BCMSDIO
2052 bool
dhd_conf_read_sdio_params(dhd_pub_t * dhd,char * full_param,uint len_param)2053 dhd_conf_read_sdio_params(dhd_pub_t *dhd, char *full_param, uint len_param)
2054 {
2055 struct dhd_conf *conf = dhd->conf;
2056 char *data = full_param+len_param;
2057
2058 if (!strncmp("dhd_doflow=", full_param, len_param)) {
2059 if (!strncmp(data, "0", 1))
2060 dhd_doflow = FALSE;
2061 else
2062 dhd_doflow = TRUE;
2063 printf("%s: dhd_doflow = %d\n", __FUNCTION__, dhd_doflow);
2064 } else if (!strncmp("dhd_slpauto=", full_param, len_param) ||
2065 !strncmp("kso_enable=", full_param, len_param)) {
2066 if (!strncmp(data, "0", 1))
2067 dhd_slpauto = FALSE;
2068 else
2069 dhd_slpauto = TRUE;
2070 printf("%s: dhd_slpauto = %d\n", __FUNCTION__, dhd_slpauto);
2071 } else if (!strncmp("use_rxchain=", full_param, len_param)) {
2072 conf->use_rxchain = (int)simple_strtol(data, NULL, 10);
2073 printf("%s: use_rxchain = %d\n", __FUNCTION__, conf->use_rxchain);
2074 } else if (!strncmp("dhd_txminmax=", full_param, len_param)) {
2075 conf->dhd_txminmax = (uint)simple_strtol(data, NULL, 10);
2076 printf("%s: dhd_txminmax = %d\n", __FUNCTION__, conf->dhd_txminmax);
2077 } else if (!strncmp("txinrx_thres=", full_param, len_param)) {
2078 conf->txinrx_thres = (int)simple_strtol(data, NULL, 10);
2079 printf("%s: txinrx_thres = %d\n", __FUNCTION__, conf->txinrx_thres);
2080 } else if (!strncmp("sd_f2_blocksize=", full_param, len_param)) {
2081 conf->sd_f2_blocksize = (int)simple_strtol(data, NULL, 10);
2082 printf("%s: sd_f2_blocksize = %d\n", __FUNCTION__, conf->sd_f2_blocksize);
2083 }
2084 #if defined(HW_OOB)
2085 else if (!strncmp("oob_enabled_later=", full_param, len_param)) {
2086 if (!strncmp(data, "0", 1))
2087 conf->oob_enabled_later = FALSE;
2088 else
2089 conf->oob_enabled_later = TRUE;
2090 printf("%s: oob_enabled_later = %d\n", __FUNCTION__, conf->oob_enabled_later);
2091 }
2092 #endif
2093 else if (!strncmp("dpc_cpucore=", full_param, len_param)) {
2094 conf->dpc_cpucore = (int)simple_strtol(data, NULL, 10);
2095 printf("%s: dpc_cpucore = %d\n", __FUNCTION__, conf->dpc_cpucore);
2096 } else if (!strncmp("rxf_cpucore=", full_param, len_param)) {
2097 conf->rxf_cpucore = (int)simple_strtol(data, NULL, 10);
2098 printf("%s: rxf_cpucore = %d\n", __FUNCTION__, conf->rxf_cpucore);
2099 } else if (!strncmp("orphan_move=", full_param, len_param)) {
2100 conf->orphan_move = (int)simple_strtol(data, NULL, 10);
2101 printf("%s: orphan_move = %d\n", __FUNCTION__, conf->orphan_move);
2102 }
2103 #if defined(BCMSDIOH_TXGLOM)
2104 else if (!strncmp("txglomsize=", full_param, len_param)) {
2105 conf->txglomsize = (uint)simple_strtol(data, NULL, 10);
2106 if (conf->txglomsize > SDPCM_MAXGLOM_SIZE)
2107 conf->txglomsize = SDPCM_MAXGLOM_SIZE;
2108 printf("%s: txglomsize = %d\n", __FUNCTION__, conf->txglomsize);
2109 } else if (!strncmp("txglom_ext=", full_param, len_param)) {
2110 if (!strncmp(data, "0", 1))
2111 conf->txglom_ext = FALSE;
2112 else
2113 conf->txglom_ext = TRUE;
2114 printf("%s: txglom_ext = %d\n", __FUNCTION__, conf->txglom_ext);
2115 if (conf->txglom_ext) {
2116 if ((conf->chip == BCM43362_CHIP_ID) || (conf->chip == BCM4330_CHIP_ID))
2117 conf->txglom_bucket_size = 1680;
2118 else if (conf->chip == BCM43340_CHIP_ID || conf->chip == BCM43341_CHIP_ID ||
2119 conf->chip == BCM4334_CHIP_ID || conf->chip == BCM4324_CHIP_ID)
2120 conf->txglom_bucket_size = 1684;
2121 }
2122 printf("%s: txglom_bucket_size = %d\n", __FUNCTION__, conf->txglom_bucket_size);
2123 } else if (!strncmp("bus:rxglom=", full_param, len_param)) {
2124 if (!strncmp(data, "0", 1))
2125 conf->bus_rxglom = FALSE;
2126 else
2127 conf->bus_rxglom = TRUE;
2128 printf("%s: bus:rxglom = %d\n", __FUNCTION__, conf->bus_rxglom);
2129 } else if (!strncmp("deferred_tx_len=", full_param, len_param)) {
2130 conf->deferred_tx_len = (int)simple_strtol(data, NULL, 10);
2131 printf("%s: deferred_tx_len = %d\n", __FUNCTION__, conf->deferred_tx_len);
2132 } else if (!strncmp("txctl_tmo_fix=", full_param, len_param)) {
2133 conf->txctl_tmo_fix = (int)simple_strtol(data, NULL, 0);
2134 printf("%s: txctl_tmo_fix = %d\n", __FUNCTION__, conf->txctl_tmo_fix);
2135 } else if (!strncmp("tx_max_offset=", full_param, len_param)) {
2136 conf->tx_max_offset = (int)simple_strtol(data, NULL, 10);
2137 printf("%s: tx_max_offset = %d\n", __FUNCTION__, conf->tx_max_offset);
2138 } else if (!strncmp("txglom_mode=", full_param, len_param)) {
2139 if (!strncmp(data, "0", 1))
2140 conf->txglom_mode = FALSE;
2141 else
2142 conf->txglom_mode = TRUE;
2143 printf("%s: txglom_mode = %d\n", __FUNCTION__, conf->txglom_mode);
2144 }
2145 #endif
2146 else
2147 return false;
2148
2149 return true;
2150 }
2151 #endif
2152
2153 #ifdef BCMPCIE
2154 bool
dhd_conf_read_pcie_params(dhd_pub_t * dhd,char * full_param,uint len_param)2155 dhd_conf_read_pcie_params(dhd_pub_t *dhd, char *full_param, uint len_param)
2156 {
2157 struct dhd_conf *conf = dhd->conf;
2158 char *data = full_param+len_param;
2159
2160 if (!strncmp("bus:deepsleep_disable=", full_param, len_param)) {
2161 if (!strncmp(data, "0", 1))
2162 conf->bus_deepsleep_disable = 0;
2163 else
2164 conf->bus_deepsleep_disable = 1;
2165 printf("%s: bus:deepsleep_disable = %d\n", __FUNCTION__, conf->bus_deepsleep_disable);
2166 } else
2167 return false;
2168
2169 return true;
2170 }
2171 #endif
2172
2173 bool
dhd_conf_read_pm_params(dhd_pub_t * dhd,char * full_param,uint len_param)2174 dhd_conf_read_pm_params(dhd_pub_t *dhd, char *full_param, uint len_param)
2175 {
2176 struct dhd_conf *conf = dhd->conf;
2177 char *data = full_param+len_param;
2178
2179 if (!strncmp("deepsleep=", full_param, len_param)) {
2180 if (!strncmp(data, "1", 1))
2181 conf->deepsleep = TRUE;
2182 else
2183 conf->deepsleep = FALSE;
2184 printf("%s: deepsleep = %d\n", __FUNCTION__, conf->deepsleep);
2185 } else if (!strncmp("PM=", full_param, len_param)) {
2186 conf->pm = (int)simple_strtol(data, NULL, 10);
2187 printf("%s: PM = %d\n", __FUNCTION__, conf->pm);
2188 } else if (!strncmp("pm_in_suspend=", full_param, len_param)) {
2189 conf->pm_in_suspend = (int)simple_strtol(data, NULL, 10);
2190 printf("%s: pm_in_suspend = %d\n", __FUNCTION__, conf->pm_in_suspend);
2191 } else if (!strncmp("suspend_bcn_li_dtim=", full_param, len_param)) {
2192 conf->suspend_bcn_li_dtim = (int)simple_strtol(data, NULL, 10);
2193 printf("%s: suspend_bcn_li_dtim = %d\n", __FUNCTION__, conf->suspend_bcn_li_dtim);
2194 } else if (!strncmp("xmit_in_suspend=", full_param, len_param)) {
2195 if (!strncmp(data, "1", 1))
2196 conf->insuspend &= ~NO_TXDATA_IN_SUSPEND;
2197 else
2198 conf->insuspend |= NO_TXDATA_IN_SUSPEND;
2199 printf("%s: insuspend = 0x%x\n", __FUNCTION__, conf->insuspend);
2200 } else if (!strncmp("insuspend=", full_param, len_param)) {
2201 conf->insuspend = (int)simple_strtol(data, NULL, 0);
2202 printf("%s: insuspend = 0x%x\n", __FUNCTION__, conf->insuspend);
2203 } else
2204 return false;
2205
2206 return true;
2207 }
2208
2209 bool
dhd_conf_read_others(dhd_pub_t * dhd,char * full_param,uint len_param)2210 dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param)
2211 {
2212 struct dhd_conf *conf = dhd->conf;
2213 char *data = full_param+len_param;
2214 uint len_data = strlen(data);
2215 char *pch, *pick_tmp;
2216 int i;
2217
2218 if (!strncmp("dhd_poll=", full_param, len_param)) {
2219 if (!strncmp(data, "0", 1))
2220 conf->dhd_poll = 0;
2221 else
2222 conf->dhd_poll = 1;
2223 printf("%s: dhd_poll = %d\n", __FUNCTION__, conf->dhd_poll);
2224 } else if (!strncmp("dhd_watchdog_ms=", full_param, len_param)) {
2225 dhd_watchdog_ms = (int)simple_strtol(data, NULL, 10);
2226 printf("%s: dhd_watchdog_ms = %d\n", __FUNCTION__, dhd_watchdog_ms);
2227 } else if (!strncmp("band=", full_param, len_param)) {
2228 /* Process band:
2229 * band=a for 5GHz only and band=b for 2.4GHz only
2230 */
2231 if (!strcmp(data, "b"))
2232 conf->band = WLC_BAND_2G;
2233 else if (!strcmp(data, "a"))
2234 conf->band = WLC_BAND_5G;
2235 else
2236 conf->band = WLC_BAND_AUTO;
2237 printf("%s: band = %d\n", __FUNCTION__, conf->band);
2238 } else if (!strncmp("bw_cap_2g=", full_param, len_param)) {
2239 conf->bw_cap[0] = (uint)simple_strtol(data, NULL, 0);
2240 printf("%s: bw_cap_2g = %d\n", __FUNCTION__, conf->bw_cap[0]);
2241 } else if (!strncmp("bw_cap_5g=", full_param, len_param)) {
2242 conf->bw_cap[1] = (uint)simple_strtol(data, NULL, 0);
2243 printf("%s: bw_cap_5g = %d\n", __FUNCTION__, conf->bw_cap[1]);
2244 } else if (!strncmp("bw_cap=", full_param, len_param)) {
2245 pick_tmp = data;
2246 pch = bcmstrtok(&pick_tmp, " ,.-", 0);
2247 if (pch != NULL) {
2248 conf->bw_cap[0] = (uint32)simple_strtol(pch, NULL, 0);
2249 printf("%s: bw_cap 2g = %d\n", __FUNCTION__, conf->bw_cap[0]);
2250 }
2251 pch = bcmstrtok(&pick_tmp, " ,.-", 0);
2252 if (pch != NULL) {
2253 conf->bw_cap[1] = (uint32)simple_strtol(pch, NULL, 0);
2254 printf("%s: bw_cap 5g = %d\n", __FUNCTION__, conf->bw_cap[1]);
2255 }
2256 } else if (!strncmp("ccode=", full_param, len_param)) {
2257 memset(&conf->cspec, 0, sizeof(wl_country_t));
2258 memcpy(conf->cspec.country_abbrev, data, len_data);
2259 memcpy(conf->cspec.ccode, data, len_data);
2260 printf("%s: ccode = %s\n", __FUNCTION__, conf->cspec.ccode);
2261 } else if (!strncmp("regrev=", full_param, len_param)) {
2262 conf->cspec.rev = (int32)simple_strtol(data, NULL, 10);
2263 printf("%s: regrev = %d\n", __FUNCTION__, conf->cspec.rev);
2264 } else if (!strncmp("channels=", full_param, len_param)) {
2265 pick_tmp = data;
2266 pch = bcmstrtok(&pick_tmp, " ,.-", 0);
2267 i = 0;
2268 while (pch != NULL && i<WL_NUMCHANNELS) {
2269 conf->channels.channel[i] = (uint32)simple_strtol(pch, NULL, 10);
2270 pch = bcmstrtok(&pick_tmp, " ,.-", 0);
2271 i++;
2272 }
2273 conf->channels.count = i;
2274 printf("%s: channels = ", __FUNCTION__);
2275 for (i=0; i<conf->channels.count; i++)
2276 printf("%d ", conf->channels.channel[i]);
2277 printf("\n");
2278 } else if (!strncmp("keep_alive_period=", full_param, len_param)) {
2279 conf->keep_alive_period = (uint)simple_strtol(data, NULL, 10);
2280 printf("%s: keep_alive_period = %d\n", __FUNCTION__,
2281 conf->keep_alive_period);
2282 } else if (!strncmp("phy_oclscdenable=", full_param, len_param)) {
2283 conf->phy_oclscdenable = (int)simple_strtol(data, NULL, 10);
2284 printf("%s: phy_oclscdenable = %d\n", __FUNCTION__, conf->phy_oclscdenable);
2285 } else if (!strncmp("srl=", full_param, len_param)) {
2286 conf->srl = (int)simple_strtol(data, NULL, 10);
2287 printf("%s: srl = %d\n", __FUNCTION__, conf->srl);
2288 } else if (!strncmp("lrl=", full_param, len_param)) {
2289 conf->lrl = (int)simple_strtol(data, NULL, 10);
2290 printf("%s: lrl = %d\n", __FUNCTION__, conf->lrl);
2291 } else if (!strncmp("bcn_timeout=", full_param, len_param)) {
2292 conf->bcn_timeout= (uint)simple_strtol(data, NULL, 10);
2293 printf("%s: bcn_timeout = %d\n", __FUNCTION__, conf->bcn_timeout);
2294 } else if (!strncmp("txbf=", full_param, len_param)) {
2295 conf->txbf = (int)simple_strtol(data, NULL, 10);
2296 printf("%s: txbf = %d\n", __FUNCTION__, conf->txbf);
2297 } else if (!strncmp("frameburst=", full_param, len_param)) {
2298 conf->frameburst = (int)simple_strtol(data, NULL, 10);
2299 printf("%s: frameburst = %d\n", __FUNCTION__, conf->frameburst);
2300 } else if (!strncmp("disable_proptx=", full_param, len_param)) {
2301 conf->disable_proptx = (int)simple_strtol(data, NULL, 10);
2302 printf("%s: disable_proptx = %d\n", __FUNCTION__, conf->disable_proptx);
2303 }
2304 #ifdef DHDTCPACK_SUPPRESS
2305 else if (!strncmp("tcpack_sup_mode=", full_param, len_param)) {
2306 conf->tcpack_sup_mode = (uint)simple_strtol(data, NULL, 10);
2307 printf("%s: tcpack_sup_mode = %d\n", __FUNCTION__, conf->tcpack_sup_mode);
2308 }
2309 #endif
2310 else if (!strncmp("pktprio8021x=", full_param, len_param)) {
2311 conf->pktprio8021x = (int)simple_strtol(data, NULL, 10);
2312 printf("%s: pktprio8021x = %d\n", __FUNCTION__, conf->pktprio8021x);
2313 }
2314 #if defined(BCMSDIO) || defined(BCMPCIE)
2315 else if (!strncmp("dhd_txbound=", full_param, len_param)) {
2316 dhd_txbound = (uint)simple_strtol(data, NULL, 10);
2317 printf("%s: dhd_txbound = %d\n", __FUNCTION__, dhd_txbound);
2318 } else if (!strncmp("dhd_rxbound=", full_param, len_param)) {
2319 dhd_rxbound = (uint)simple_strtol(data, NULL, 10);
2320 printf("%s: dhd_rxbound = %d\n", __FUNCTION__, dhd_rxbound);
2321 }
2322 #endif
2323 else if (!strncmp("tsq=", full_param, len_param)) {
2324 conf->tsq = (int)simple_strtol(data, NULL, 10);
2325 printf("%s: tsq = %d\n", __FUNCTION__, conf->tsq);
2326 } else if (!strncmp("ctrl_resched=", full_param, len_param)) {
2327 conf->ctrl_resched = (int)simple_strtol(data, NULL, 10);
2328 printf("%s: ctrl_resched = %d\n", __FUNCTION__, conf->ctrl_resched);
2329 } else if (!strncmp("dhd_ioctl_timeout_msec=", full_param, len_param)) {
2330 conf->dhd_ioctl_timeout_msec = (int)simple_strtol(data, NULL, 10);
2331 printf("%s: dhd_ioctl_timeout_msec = %d\n", __FUNCTION__, conf->dhd_ioctl_timeout_msec);
2332 } else if (!strncmp("in4way=", full_param, len_param)) {
2333 conf->in4way = (int)simple_strtol(data, NULL, 0);
2334 printf("%s: in4way = 0x%x\n", __FUNCTION__, conf->in4way);
2335 } else if (!strncmp("max_wait_gc_time=", full_param, len_param)) {
2336 conf->max_wait_gc_time = (int)simple_strtol(data, NULL, 0);
2337 printf("%s: max_wait_gc_time = %d\n", __FUNCTION__, conf->max_wait_gc_time);
2338 } else if (!strncmp("wl_preinit=", full_param, len_param)) {
2339 conf->wl_preinit = kmalloc(len_param + 1, GFP_KERNEL);
2340 if (!conf->wl_preinit) {
2341 CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
2342 } else {
2343 memset(conf->wl_preinit, 0, len_param+1);
2344 strcpy(conf->wl_preinit, data);
2345 printf("%s: wl_preinit = %s\n", __FUNCTION__, conf->wl_preinit);
2346 }
2347 } else
2348 return false;
2349
2350 return true;
2351 }
2352
2353 int
dhd_conf_read_config(dhd_pub_t * dhd,char * conf_path)2354 dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)
2355 {
2356 int bcmerror = -1;
2357 uint len = 0, start_pos=0;
2358 void *image = NULL;
2359 char *memblock = NULL;
2360 char *bufp, *pick = NULL, *pch;
2361 bool conf_file_exists;
2362 uint len_param;
2363
2364 conf_file_exists = ((conf_path != NULL) && (conf_path[0] != '\0'));
2365 if (!conf_file_exists) {
2366 printf("%s: config path %s\n", __FUNCTION__, conf_path);
2367 return 0;
2368 }
2369
2370 if (conf_file_exists) {
2371 image = dhd_os_open_image(conf_path);
2372 if (image == NULL) {
2373 printf("%s: Ignore config file %s\n", __FUNCTION__, conf_path);
2374 goto err;
2375 }
2376 }
2377
2378 memblock = MALLOC(dhd->osh, MAXSZ_CONFIG);
2379 if (memblock == NULL) {
2380 CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",
2381 __FUNCTION__, MAXSZ_CONFIG));
2382 goto err;
2383 }
2384
2385 pick = MALLOC(dhd->osh, MAXSZ_BUF);
2386 if (!pick) {
2387 CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",
2388 __FUNCTION__, MAXSZ_BUF));
2389 goto err;
2390 }
2391
2392 /* Read variables */
2393 if (conf_file_exists) {
2394 len = dhd_os_get_image_block(memblock, MAXSZ_CONFIG, image);
2395 }
2396 if (len > 0 && len < MAXSZ_CONFIG) {
2397 bufp = (char *)memblock;
2398 bufp[len] = 0;
2399
2400 while (start_pos < len) {
2401 memset(pick, 0, MAXSZ_BUF);
2402 start_pos = pick_config_vars(bufp, len, start_pos, pick);
2403 pch = strchr(pick, '=');
2404 if (pch != NULL) {
2405 len_param = pch-pick+1;
2406 if (len_param == strlen(pick)) {
2407 CONFIG_ERROR(("%s: not a right parameter %s\n", __FUNCTION__, pick));
2408 continue;
2409 }
2410 } else {
2411 CONFIG_ERROR(("%s: not a right parameter %s\n", __FUNCTION__, pick));
2412 continue;
2413 }
2414
2415 if (dhd_conf_read_log_level(dhd, pick, len_param))
2416 continue;
2417 else if (dhd_conf_read_roam_params(dhd, pick, len_param))
2418 continue;
2419 else if (dhd_conf_read_wme_ac_params(dhd, pick, len_param))
2420 continue;
2421 #ifdef BCMSDIO
2422 else if (dhd_conf_read_fw_by_mac(dhd, pick, len_param))
2423 continue;
2424 else if (dhd_conf_read_nv_by_mac(dhd, pick, len_param))
2425 continue;
2426 #endif
2427 else if (dhd_conf_read_nv_by_chip(dhd, pick, len_param))
2428 continue;
2429 else if (dhd_conf_read_country_list(dhd, pick, len_param))
2430 continue;
2431 else if (dhd_conf_read_mchan_params(dhd, pick, len_param))
2432 continue;
2433 #ifdef PKT_FILTER_SUPPORT
2434 else if (dhd_conf_read_pkt_filter(dhd, pick, len_param))
2435 continue;
2436 #endif /* PKT_FILTER_SUPPORT */
2437 #ifdef ISAM_PREINIT
2438 else if (dhd_conf_read_isam(dhd, pick, len_param))
2439 continue;
2440 #endif /* ISAM_PREINIT */
2441 #ifdef IDHCP
2442 else if (dhd_conf_read_dhcp_params(dhd, pick, len_param))
2443 continue;
2444 #endif /* IDHCP */
2445 #ifdef BCMSDIO
2446 else if (dhd_conf_read_sdio_params(dhd, pick, len_param))
2447 continue;
2448 #endif /* BCMSDIO */
2449 #ifdef BCMPCIE
2450 else if (dhd_conf_read_pcie_params(dhd, pick, len_param))
2451 continue;
2452 #endif /* BCMPCIE */
2453 else if (dhd_conf_read_pm_params(dhd, pick, len_param))
2454 continue;
2455 else if (dhd_conf_read_others(dhd, pick, len_param))
2456 continue;
2457 else
2458 continue;
2459 }
2460
2461 bcmerror = 0;
2462 } else {
2463 CONFIG_ERROR(("%s: error reading config file: %d\n", __FUNCTION__, len));
2464 bcmerror = BCME_SDIO_ERROR;
2465 }
2466
2467 err:
2468 if (pick)
2469 MFREE(dhd->osh, pick, MAXSZ_BUF);
2470
2471 if (memblock)
2472 MFREE(dhd->osh, memblock, MAXSZ_CONFIG);
2473
2474 if (image)
2475 dhd_os_close_image(image);
2476
2477 return bcmerror;
2478 }
2479
2480 int
dhd_conf_set_chiprev(dhd_pub_t * dhd,uint chip,uint chiprev)2481 dhd_conf_set_chiprev(dhd_pub_t *dhd, uint chip, uint chiprev)
2482 {
2483 printf("%s: chip=0x%x, chiprev=%d\n", __FUNCTION__, chip, chiprev);
2484 dhd->conf->chip = chip;
2485 dhd->conf->chiprev = chiprev;
2486 return 0;
2487 }
2488
2489 uint
dhd_conf_get_chip(void * context)2490 dhd_conf_get_chip(void *context)
2491 {
2492 dhd_pub_t *dhd = context;
2493
2494 if (dhd && dhd->conf)
2495 return dhd->conf->chip;
2496 return 0;
2497 }
2498
2499 uint
dhd_conf_get_chiprev(void * context)2500 dhd_conf_get_chiprev(void *context)
2501 {
2502 dhd_pub_t *dhd = context;
2503
2504 if (dhd && dhd->conf)
2505 return dhd->conf->chiprev;
2506 return 0;
2507 }
2508
2509 #ifdef BCMSDIO
2510 void
dhd_conf_set_txglom_params(dhd_pub_t * dhd,bool enable)2511 dhd_conf_set_txglom_params(dhd_pub_t *dhd, bool enable)
2512 {
2513 struct dhd_conf *conf = dhd->conf;
2514
2515 if (enable) {
2516 #if defined(BCMSDIOH_TXGLOM_EXT)
2517 if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID ||
2518 conf->chip == BCM43340_CHIP_ID || conf->chip == BCM43341_CHIP_ID ||
2519 conf->chip == BCM4334_CHIP_ID || conf->chip == BCM4324_CHIP_ID) {
2520 conf->txglom_mode = SDPCM_TXGLOM_CPY;
2521 }
2522 #endif
2523 // other parameters set in preinit or config.txt
2524 } else {
2525 // clear txglom parameters
2526 conf->txglom_ext = FALSE;
2527 conf->txglom_bucket_size = 0;
2528 conf->txglomsize = 0;
2529 conf->deferred_tx_len = 0;
2530 }
2531 if (conf->txglom_ext)
2532 printf("%s: txglom_ext=%d, txglom_bucket_size=%d\n", __FUNCTION__,
2533 conf->txglom_ext, conf->txglom_bucket_size);
2534 printf("%s: txglom_mode=%s\n", __FUNCTION__,
2535 conf->txglom_mode == SDPCM_TXGLOM_MDESC ? "multi-desc" : "copy");
2536 printf("%s: txglomsize=%d, deferred_tx_len=%d\n", __FUNCTION__,
2537 conf->txglomsize, conf->deferred_tx_len);
2538 printf("%s: txinrx_thres=%d, dhd_txminmax=%d\n", __FUNCTION__,
2539 conf->txinrx_thres, conf->dhd_txminmax);
2540 printf("%s: tx_max_offset=%d, txctl_tmo_fix=%d\n", __FUNCTION__,
2541 conf->tx_max_offset, conf->txctl_tmo_fix);
2542 }
2543 #endif
2544
2545 static int
dhd_conf_rsdb_mode(dhd_pub_t * dhd,char * buf)2546 dhd_conf_rsdb_mode(dhd_pub_t *dhd, char *buf)
2547 {
2548 char *pch;
2549 wl_config_t rsdb_mode_cfg = {1, 0};
2550
2551 pch = buf;
2552 rsdb_mode_cfg.config = (int)simple_strtol(pch, NULL, 0);
2553
2554 if (pch) {
2555 dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "rsdb_mode", (char *)&rsdb_mode_cfg,
2556 sizeof(rsdb_mode_cfg), TRUE);
2557 printf("%s: rsdb_mode %d\n", __FUNCTION__, rsdb_mode_cfg.config);
2558 }
2559
2560 return 0;
2561 }
2562
2563 typedef int (tpl_parse_t)(dhd_pub_t *dhd, char *buf);
2564
2565 typedef struct iovar_tpl_t {
2566 int cmd;
2567 char *name;
2568 tpl_parse_t *parse;
2569 } iovar_tpl_t;
2570
2571 const iovar_tpl_t iovar_tpl_list[] = {
2572 {WLC_SET_VAR, "rsdb_mode", dhd_conf_rsdb_mode},
2573 };
2574
iovar_tpl_parse(const iovar_tpl_t * tpl,int tpl_count,dhd_pub_t * dhd,int cmd,char * name,char * buf)2575 static int iovar_tpl_parse(const iovar_tpl_t *tpl, int tpl_count,
2576 dhd_pub_t *dhd, int cmd, char *name, char *buf)
2577 {
2578 int i, ret = 0;
2579
2580 /* look for a matching code in the table */
2581 for (i = 0; i < tpl_count; i++, tpl++) {
2582 if (tpl->cmd == cmd && !strcmp(tpl->name, name))
2583 break;
2584 }
2585 if (i < tpl_count && tpl->parse) {
2586 ret = tpl->parse(dhd, buf);
2587 } else {
2588 ret = -1;
2589 }
2590
2591 return ret;
2592 }
2593
2594 bool
dhd_conf_set_wl_preinit(dhd_pub_t * dhd,char * data)2595 dhd_conf_set_wl_preinit(dhd_pub_t *dhd, char *data)
2596 {
2597 int cmd, val, ret = 0;
2598 char name[32], *pch, *pick_tmp, *pick_tmp2;
2599
2600 /* Process wl_preinit:
2601 * wl_preinit=[cmd]=[val], [cmd]=[val]
2602 * Ex: wl_preinit=86=0, mpc=0
2603 */
2604 pick_tmp = data;
2605 while (pick_tmp && (pick_tmp2 = bcmstrtok(&pick_tmp, ",", 0)) != NULL) {
2606 pch = bcmstrtok(&pick_tmp2, "=", 0);
2607 if (!pch)
2608 break;
2609 if (*pch == ' ') {
2610 pch++;
2611 }
2612 memset(name, 0, sizeof (name));
2613 cmd = (int)simple_strtol(pch, NULL, 0);
2614 if (cmd == 0) {
2615 cmd = WLC_SET_VAR;
2616 strcpy(name, pch);
2617 }
2618 pch = bcmstrtok(&pick_tmp2, ",", 0);
2619 if (!pch) {
2620 break;
2621 }
2622 ret = iovar_tpl_parse(iovar_tpl_list, ARRAY_SIZE(iovar_tpl_list),
2623 dhd, cmd, name, pch);
2624 if (ret) {
2625 val = (int)simple_strtol(pch, NULL, 0);
2626 dhd_conf_set_intiovar(dhd, cmd, name, val, -1, TRUE);
2627 }
2628 }
2629
2630 return true;
2631 }
2632
2633 void
dhd_conf_postinit_ioctls(dhd_pub_t * dhd)2634 dhd_conf_postinit_ioctls(dhd_pub_t *dhd)
2635 {
2636 struct dhd_conf *conf = dhd->conf;
2637 char wl_preinit[] = "assoc_retry_max=30";
2638
2639 dhd_conf_set_intiovar(dhd, WLC_UP, "up", 0, 0, FALSE);
2640 dhd_conf_map_country_list(dhd, &conf->cspec);
2641 dhd_conf_set_country(dhd, &conf->cspec);
2642 dhd_conf_fix_country(dhd);
2643 dhd_conf_get_country(dhd, &dhd->dhd_cspec);
2644
2645 dhd_conf_set_intiovar(dhd, WLC_SET_BAND, "WLC_SET_BAND", conf->band, 0, FALSE);
2646 dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "bcn_timeout", conf->bcn_timeout, 0, FALSE);
2647 dhd_conf_set_intiovar(dhd, WLC_SET_PM, "PM", conf->pm, 0, FALSE);
2648 dhd_conf_set_intiovar(dhd, WLC_SET_SRL, "WLC_SET_SRL", conf->srl, 0, FALSE);
2649 dhd_conf_set_intiovar(dhd, WLC_SET_LRL, "WLC_SET_LRL", conf->lrl, 0, FALSE);
2650 dhd_conf_set_bw_cap(dhd);
2651 dhd_conf_set_roam(dhd);
2652
2653 #if defined(BCMPCIE)
2654 dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "bus:deepsleep_disable",
2655 conf->bus_deepsleep_disable, 0, FALSE);
2656 #endif /* defined(BCMPCIE) */
2657
2658 #ifdef IDHCP
2659 dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "dhcpc_enable", conf->dhcpc_enable, 0, FALSE);
2660 if (dhd->conf->dhcpd_enable >= 0) {
2661 dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "dhcpd_ip_addr",
2662 (char *)&conf->dhcpd_ip_addr, sizeof(conf->dhcpd_ip_addr), FALSE);
2663 dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "dhcpd_ip_mask",
2664 (char *)&conf->dhcpd_ip_mask, sizeof(conf->dhcpd_ip_mask), FALSE);
2665 dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "dhcpd_ip_start",
2666 (char *)&conf->dhcpd_ip_start, sizeof(conf->dhcpd_ip_start), FALSE);
2667 dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "dhcpd_ip_end",
2668 (char *)&conf->dhcpd_ip_end, sizeof(conf->dhcpd_ip_end), FALSE);
2669 dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "dhcpd_enable",
2670 conf->dhcpd_enable, 0, FALSE);
2671 }
2672 #endif
2673 dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "txbf", conf->txbf, 0, FALSE);
2674 dhd_conf_set_intiovar(dhd, WLC_SET_FAKEFRAG, "WLC_SET_FAKEFRAG", conf->frameburst, 0, FALSE);
2675
2676 dhd_conf_set_wl_preinit(dhd, wl_preinit);
2677 dhd_conf_set_wl_preinit(dhd, conf->wl_preinit);
2678 #ifndef WL_CFG80211
2679 dhd_conf_set_intiovar(dhd, WLC_UP, "up", 0, 0, FALSE);
2680 #endif
2681
2682 }
2683
2684 int
dhd_conf_preinit(dhd_pub_t * dhd)2685 dhd_conf_preinit(dhd_pub_t *dhd)
2686 {
2687 struct dhd_conf *conf = dhd->conf;
2688 int i;
2689
2690 CONFIG_TRACE(("%s: Enter\n", __FUNCTION__));
2691
2692 #ifdef BCMSDIO
2693 dhd_conf_free_mac_list(&conf->fw_by_mac);
2694 dhd_conf_free_mac_list(&conf->nv_by_mac);
2695 dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);
2696 #endif
2697 dhd_conf_free_country_list(&conf->country_list);
2698 if (conf->magic_pkt_filter_add) {
2699 kfree(conf->magic_pkt_filter_add);
2700 conf->magic_pkt_filter_add = NULL;
2701 }
2702 if (conf->wl_preinit) {
2703 kfree(conf->wl_preinit);
2704 conf->wl_preinit = NULL;
2705 }
2706 memset(&conf->country_list, 0, sizeof(conf_country_list_t));
2707 conf->band = -1;
2708 memset(&conf->bw_cap, -1, sizeof(conf->bw_cap));
2709 if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID) {
2710 strcpy(conf->cspec.country_abbrev, "ALL");
2711 strcpy(conf->cspec.ccode, "ALL");
2712 conf->cspec.rev = 0;
2713 } else if (conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID ||
2714 conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||
2715 conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID ||
2716 conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID ||
2717 conf->chip == BCM4362_CHIP_ID) {
2718 strcpy(conf->cspec.country_abbrev, "CN");
2719 strcpy(conf->cspec.ccode, "CN");
2720 conf->cspec.rev = 38;
2721 } else {
2722 strcpy(conf->cspec.country_abbrev, "CN");
2723 strcpy(conf->cspec.ccode, "CN");
2724 conf->cspec.rev = 0;
2725 }
2726 memset(&conf->channels, 0, sizeof(wl_channel_list_t));
2727 conf->roam_off = 1;
2728 conf->roam_off_suspend = 1;
2729 #ifdef CUSTOM_ROAM_TRIGGER_SETTING
2730 conf->roam_trigger[0] = CUSTOM_ROAM_TRIGGER_SETTING;
2731 #else
2732 conf->roam_trigger[0] = -65;
2733 #endif
2734 conf->roam_trigger[1] = WLC_BAND_ALL;
2735 conf->roam_scan_period[0] = 10;
2736 conf->roam_scan_period[1] = WLC_BAND_ALL;
2737 #ifdef CUSTOM_ROAM_DELTA_SETTING
2738 conf->roam_delta[0] = CUSTOM_ROAM_DELTA_SETTING;
2739 #else
2740 conf->roam_delta[0] = 15;
2741 #endif
2742 conf->roam_delta[1] = WLC_BAND_ALL;
2743 #ifdef FULL_ROAMING_SCAN_PERIOD_60_SEC
2744 conf->fullroamperiod = 60;
2745 #else /* FULL_ROAMING_SCAN_PERIOD_60_SEC */
2746 conf->fullroamperiod = 120;
2747 #endif /* FULL_ROAMING_SCAN_PERIOD_60_SEC */
2748 #ifdef CUSTOM_KEEP_ALIVE_SETTING
2749 conf->keep_alive_period = CUSTOM_KEEP_ALIVE_SETTING;
2750 #else
2751 conf->keep_alive_period = 28000;
2752 #endif
2753 conf->force_wme_ac = 0;
2754 memset(&conf->wme_sta, 0, sizeof(wme_param_t));
2755 memset(&conf->wme_ap, 0, sizeof(wme_param_t));
2756 conf->phy_oclscdenable = -1;
2757 #ifdef PKT_FILTER_SUPPORT
2758 memset(&conf->pkt_filter_add, 0, sizeof(conf_pkt_filter_add_t));
2759 memset(&conf->pkt_filter_del, 0, sizeof(conf_pkt_filter_del_t));
2760 #endif
2761 conf->srl = -1;
2762 conf->lrl = -1;
2763 conf->bcn_timeout = 16;
2764 conf->txbf = -1;
2765 conf->disable_proptx = -1;
2766 conf->dhd_poll = -1;
2767 #ifdef BCMSDIO
2768 conf->use_rxchain = 0;
2769 conf->bus_rxglom = TRUE;
2770 conf->txglom_ext = FALSE;
2771 conf->tx_max_offset = 0;
2772 conf->txglomsize = SDPCM_DEFGLOM_SIZE;
2773 conf->txctl_tmo_fix = 300;
2774 conf->txglom_mode = SDPCM_TXGLOM_MDESC;
2775 conf->deferred_tx_len = 0;
2776 conf->dhd_txminmax = 1;
2777 conf->txinrx_thres = -1;
2778 conf->sd_f2_blocksize = 0;
2779 #if defined(HW_OOB)
2780 conf->oob_enabled_later = FALSE;
2781 #endif
2782 conf->orphan_move = 0;
2783 #endif
2784 #ifdef BCMPCIE
2785 conf->bus_deepsleep_disable = 1;
2786 #endif
2787 conf->dpc_cpucore = -1;
2788 conf->rxf_cpucore = -1;
2789 conf->frameburst = -1;
2790 conf->deepsleep = FALSE;
2791 conf->pm = -1;
2792 conf->pm_in_suspend = -1;
2793 conf->suspend_bcn_li_dtim = -1;
2794 conf->insuspend = 0;
2795 #ifdef SUSPEND_EVENT
2796 memset(&conf->resume_eventmask, 0, sizeof(conf->resume_eventmask));
2797 #endif
2798 #ifdef IDHCP
2799 conf->dhcpc_enable = -1;
2800 conf->dhcpd_enable = -1;
2801 #endif
2802 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
2803 conf->tsq = 10;
2804 #else
2805 conf->tsq = 0;
2806 #endif
2807 #ifdef DHDTCPACK_SUPPRESS
2808 #ifdef BCMPCIE
2809 conf->tcpack_sup_mode = TCPACK_SUP_DEFAULT;
2810 #else
2811 conf->tcpack_sup_mode = TCPACK_SUP_OFF;
2812 #endif
2813 #endif
2814 conf->pktprio8021x = -1;
2815 conf->ctrl_resched = 2;
2816 conf->dhd_ioctl_timeout_msec = 0;
2817 conf->in4way = NO_SCAN_IN4WAY | WAIT_DISCONNECTED;
2818 conf->max_wait_gc_time = 300;
2819 #ifdef ISAM_PREINIT
2820 memset(conf->isam_init, 0, sizeof(conf->isam_init));
2821 memset(conf->isam_config, 0, sizeof(conf->isam_config));
2822 memset(conf->isam_enable, 0, sizeof(conf->isam_enable));
2823 #endif
2824 for (i = 0; i < MCHAN_MAX_NUM; i++) {
2825 memset(&conf->mchan[i], -1, sizeof(mchan_params_t));
2826 }
2827 if (conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID ||
2828 conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||
2829 conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID ||
2830 conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID ||
2831 conf->chip == BCM4362_CHIP_ID) {
2832 #ifdef DHDTCPACK_SUPPRESS
2833 #ifdef BCMSDIO
2834 conf->tcpack_sup_mode = TCPACK_SUP_REPLACE;
2835 #endif
2836 #endif
2837 #if defined(BCMSDIO) || defined(BCMPCIE)
2838 dhd_rxbound = 128;
2839 dhd_txbound = 64;
2840 #endif
2841 conf->txbf = 1;
2842 conf->frameburst = 1;
2843 #ifdef BCMSDIO
2844 conf->dhd_txminmax = -1;
2845 conf->txinrx_thres = 128;
2846 conf->sd_f2_blocksize = CUSTOM_SDIO_F2_BLKSIZE;
2847 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
2848 conf->orphan_move = 1;
2849 #else
2850 conf->orphan_move = 0;
2851 #endif
2852 #endif
2853 }
2854
2855 #ifdef BCMSDIO
2856 #if defined(BCMSDIOH_TXGLOM_EXT)
2857 if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID ||
2858 conf->chip == BCM43340_CHIP_ID || conf->chip == BCM43341_CHIP_ID ||
2859 conf->chip == BCM4334_CHIP_ID || conf->chip == BCM4324_CHIP_ID) {
2860 conf->txglom_ext = TRUE;
2861 } else {
2862 conf->txglom_ext = FALSE;
2863 }
2864 if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID) {
2865 conf->txglom_bucket_size = 1680; // fixed value, don't change
2866 conf->txglomsize = 6;
2867 }
2868 if (conf->chip == BCM4334_CHIP_ID || conf->chip == BCM43340_CHIP_ID ||
2869 conf->chip == BCM43341_CHIP_ID || conf->chip == BCM4324_CHIP_ID) {
2870 conf->txglom_bucket_size = 1684; // fixed value, don't change
2871 conf->txglomsize = 16;
2872 }
2873 #endif
2874 if (conf->txglomsize > SDPCM_MAXGLOM_SIZE)
2875 conf->txglomsize = SDPCM_MAXGLOM_SIZE;
2876 #endif
2877
2878 return 0;
2879 }
2880
2881 int
dhd_conf_reset(dhd_pub_t * dhd)2882 dhd_conf_reset(dhd_pub_t *dhd)
2883 {
2884 #ifdef BCMSDIO
2885 dhd_conf_free_mac_list(&dhd->conf->fw_by_mac);
2886 dhd_conf_free_mac_list(&dhd->conf->nv_by_mac);
2887 dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip);
2888 #endif
2889 dhd_conf_free_country_list(&dhd->conf->country_list);
2890 if (dhd->conf->magic_pkt_filter_add) {
2891 kfree(dhd->conf->magic_pkt_filter_add);
2892 dhd->conf->magic_pkt_filter_add = NULL;
2893 }
2894 if (dhd->conf->wl_preinit) {
2895 kfree(dhd->conf->wl_preinit);
2896 dhd->conf->wl_preinit = NULL;
2897 }
2898 memset(dhd->conf, 0, sizeof(dhd_conf_t));
2899 return 0;
2900 }
2901
2902 int
dhd_conf_attach(dhd_pub_t * dhd)2903 dhd_conf_attach(dhd_pub_t *dhd)
2904 {
2905 dhd_conf_t *conf;
2906
2907 CONFIG_TRACE(("%s: Enter\n", __FUNCTION__));
2908
2909 if (dhd->conf != NULL) {
2910 printf("%s: config is attached before!\n", __FUNCTION__);
2911 return 0;
2912 }
2913 /* Allocate private bus interface state */
2914 conf = MALLOC(dhd->osh, sizeof(dhd_conf_t));
2915 if (!conf) {
2916 CONFIG_ERROR(("%s: MALLOC failed\n", __FUNCTION__));
2917 goto fail;
2918 }
2919 memset(conf, 0, sizeof(dhd_conf_t));
2920
2921 dhd->conf = conf;
2922
2923 return 0;
2924
2925 fail:
2926 if (conf != NULL)
2927 MFREE(dhd->osh, conf, sizeof(dhd_conf_t));
2928 return BCME_NOMEM;
2929 }
2930
2931 void
dhd_conf_detach(dhd_pub_t * dhd)2932 dhd_conf_detach(dhd_pub_t *dhd)
2933 {
2934 CONFIG_TRACE(("%s: Enter\n", __FUNCTION__));
2935
2936 if (dhd->conf) {
2937 #ifdef BCMSDIO
2938 dhd_conf_free_mac_list(&dhd->conf->fw_by_mac);
2939 dhd_conf_free_mac_list(&dhd->conf->nv_by_mac);
2940 dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip);
2941 #endif
2942 dhd_conf_free_country_list(&dhd->conf->country_list);
2943 if (dhd->conf->magic_pkt_filter_add) {
2944 kfree(dhd->conf->magic_pkt_filter_add);
2945 dhd->conf->magic_pkt_filter_add = NULL;
2946 }
2947 if (dhd->conf->wl_preinit) {
2948 kfree(dhd->conf->wl_preinit);
2949 dhd->conf->wl_preinit = NULL;
2950 }
2951 MFREE(dhd->osh, dhd->conf, sizeof(dhd_conf_t));
2952 }
2953 dhd->conf = NULL;
2954 }
2955