• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&param, 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 *)&param, sizeof(param), TRUE);
1007     }
1008 
1009     if (dhd->conf->bw_cap[1] >= 0) {
1010         memset(&param, 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 *)&param, 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(&ether_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