1*4882a593Smuzhiyun
2*4882a593Smuzhiyun #include <typedefs.h>
3*4882a593Smuzhiyun #include <osl.h>
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun #include <bcmendian.h>
6*4882a593Smuzhiyun #include <bcmutils.h>
7*4882a593Smuzhiyun #include <hndsoc.h>
8*4882a593Smuzhiyun #include <bcmsdbus.h>
9*4882a593Smuzhiyun #if defined(HW_OOB) || defined(FORCE_WOWLAN)
10*4882a593Smuzhiyun #include <bcmdefs.h>
11*4882a593Smuzhiyun #include <bcmsdh.h>
12*4882a593Smuzhiyun #include <sdio.h>
13*4882a593Smuzhiyun #include <sbchipc.h>
14*4882a593Smuzhiyun #endif
15*4882a593Smuzhiyun #ifdef DHDTCPACK_SUPPRESS
16*4882a593Smuzhiyun #include <dhd_ip.h>
17*4882a593Smuzhiyun #endif /* DHDTCPACK_SUPPRESS */
18*4882a593Smuzhiyun #ifdef WL_CFG80211
19*4882a593Smuzhiyun #include <wl_cfg80211.h>
20*4882a593Smuzhiyun #endif
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #include <dhd_config.h>
23*4882a593Smuzhiyun #include <dhd_dbg.h>
24*4882a593Smuzhiyun #include <wl_android.h>
25*4882a593Smuzhiyun #ifdef BCMPCIE
26*4882a593Smuzhiyun #include <dhd_flowring.h>
27*4882a593Smuzhiyun #endif
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #if defined(BCMSDIO) || defined(BCMPCIE)
30*4882a593Smuzhiyun #include <dhd_linux.h>
31*4882a593Smuzhiyun #include <dhd_bus.h>
32*4882a593Smuzhiyun #ifdef BCMSDIO
33*4882a593Smuzhiyun #include <linux/mmc/core.h>
34*4882a593Smuzhiyun #include <linux/mmc/card.h>
35*4882a593Smuzhiyun #include <linux/mmc/host.h>
36*4882a593Smuzhiyun #include <linux/mmc/sdio_func.h>
37*4882a593Smuzhiyun #endif /* defined(BCMSDIO) */
38*4882a593Smuzhiyun #endif
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun /* message levels */
41*4882a593Smuzhiyun #define CONFIG_ERROR_LEVEL (1 << 0)
42*4882a593Smuzhiyun #define CONFIG_TRACE_LEVEL (1 << 1)
43*4882a593Smuzhiyun #define CONFIG_MSG_LEVEL (1 << 0)
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun uint config_msg_level = CONFIG_ERROR_LEVEL | CONFIG_MSG_LEVEL;
46*4882a593Smuzhiyun uint dump_msg_level = 0;
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #define CONFIG_MSG(x, args...) \
49*4882a593Smuzhiyun do { \
50*4882a593Smuzhiyun if (config_msg_level & CONFIG_MSG_LEVEL) { \
51*4882a593Smuzhiyun printf("%s : " x, __func__, ## args); \
52*4882a593Smuzhiyun } \
53*4882a593Smuzhiyun } while (0)
54*4882a593Smuzhiyun #define CONFIG_ERROR(x, args...) \
55*4882a593Smuzhiyun do { \
56*4882a593Smuzhiyun if (config_msg_level & CONFIG_ERROR_LEVEL) { \
57*4882a593Smuzhiyun printf("CONFIG-ERROR) %s : " x, __func__, ## args); \
58*4882a593Smuzhiyun } \
59*4882a593Smuzhiyun } while (0)
60*4882a593Smuzhiyun #define CONFIG_TRACE(x, args...) \
61*4882a593Smuzhiyun do { \
62*4882a593Smuzhiyun if (config_msg_level & CONFIG_TRACE_LEVEL) { \
63*4882a593Smuzhiyun printf("CONFIG-TRACE) %s : " x, __func__, ## args); \
64*4882a593Smuzhiyun } \
65*4882a593Smuzhiyun } while (0)
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun #define MAXSZ_BUF 4096
68*4882a593Smuzhiyun #define MAXSZ_CONFIG 8192
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun extern uint wl_reassoc_support;
71*4882a593Smuzhiyun #ifdef BTC_WAR
72*4882a593Smuzhiyun extern int btc_war;
73*4882a593Smuzhiyun #endif /* BTC_WAR */
74*4882a593Smuzhiyun #if defined(BCMSDIO) && defined(DYNAMIC_MAX_HDR_READ)
75*4882a593Smuzhiyun extern uint firstread;
76*4882a593Smuzhiyun #endif
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun #if defined(PROP_TXSTATUS)
79*4882a593Smuzhiyun #include <dhd_wlfc.h>
80*4882a593Smuzhiyun #endif /* PROP_TXSTATUS */
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun #define MAX_EVENT_BUF_NUM 16
83*4882a593Smuzhiyun typedef struct eventmsg_buf {
84*4882a593Smuzhiyun u16 num;
85*4882a593Smuzhiyun struct {
86*4882a593Smuzhiyun u16 type;
87*4882a593Smuzhiyun bool set;
88*4882a593Smuzhiyun } event [MAX_EVENT_BUF_NUM];
89*4882a593Smuzhiyun } eventmsg_buf_t;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun typedef struct chip_name_map_t {
92*4882a593Smuzhiyun uint chip;
93*4882a593Smuzhiyun uint chiprev;
94*4882a593Smuzhiyun uint ag_type;
95*4882a593Smuzhiyun char *chip_name;
96*4882a593Smuzhiyun char *module_name;
97*4882a593Smuzhiyun } chip_name_map_t;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun /* Map of WLC_E events to connection failure strings */
100*4882a593Smuzhiyun #define DONT_CARE 9999
101*4882a593Smuzhiyun const chip_name_map_t chip_name_map[] = {
102*4882a593Smuzhiyun /* ChipID Chiprev AG ChipName ModuleName */
103*4882a593Smuzhiyun #ifdef BCMSDIO
104*4882a593Smuzhiyun {BCM43362_CHIP_ID, 0, DONT_CARE, "bcm40181a0", ""},
105*4882a593Smuzhiyun {BCM43362_CHIP_ID, 1, DONT_CARE, "bcm40181a2", "ap6181"},
106*4882a593Smuzhiyun {BCM4330_CHIP_ID, 4, FW_TYPE_G, "RK903b2", ""},
107*4882a593Smuzhiyun {BCM4330_CHIP_ID, 4, FW_TYPE_AG, "RK903_ag", "AP6330"},
108*4882a593Smuzhiyun {BCM43430_CHIP_ID, 0, DONT_CARE, "bcm43438a0", "ap6212"},
109*4882a593Smuzhiyun {BCM43430_CHIP_ID, 1, DONT_CARE, "bcm43438a1", "ap6212a"},
110*4882a593Smuzhiyun {BCM43430_CHIP_ID, 2, DONT_CARE, "bcm43436b0", "ap6236"},
111*4882a593Smuzhiyun {BCM43012_CHIP_ID, 1, FW_TYPE_G, "bcm43013b0", ""},
112*4882a593Smuzhiyun {BCM43012_CHIP_ID, 1, FW_TYPE_AG, "bcm43013c0_ag", ""},
113*4882a593Smuzhiyun {BCM43012_CHIP_ID, 2, DONT_CARE, "bcm43013c1_ag", ""},
114*4882a593Smuzhiyun {BCM4334_CHIP_ID, 3, DONT_CARE, "bcm4334b1_ag", ""},
115*4882a593Smuzhiyun {BCM43340_CHIP_ID, 2, DONT_CARE, "bcm43341b0_ag", ""},
116*4882a593Smuzhiyun {BCM43341_CHIP_ID, 2, DONT_CARE, "bcm43341b0_ag", ""},
117*4882a593Smuzhiyun {BCM4324_CHIP_ID, 5, DONT_CARE, "bcm43241b4_ag", "ap62x2"},
118*4882a593Smuzhiyun {BCM4335_CHIP_ID, 2, DONT_CARE, "bcm4339a0_ag", "AP6335"},
119*4882a593Smuzhiyun {BCM4339_CHIP_ID, 1, DONT_CARE, "bcm4339a0_ag", "AP6335"},
120*4882a593Smuzhiyun {BCM4345_CHIP_ID, 6, DONT_CARE, "bcm43455c0_ag", "ap6255"},
121*4882a593Smuzhiyun {BCM43454_CHIP_ID, 6, DONT_CARE, "bcm43455c0_ag", ""},
122*4882a593Smuzhiyun {BCM4345_CHIP_ID, 9, DONT_CARE, "bcm43456c5_ag", "ap6256"},
123*4882a593Smuzhiyun {BCM43454_CHIP_ID, 9, DONT_CARE, "bcm43456c5_ag", ""},
124*4882a593Smuzhiyun {BCM4354_CHIP_ID, 1, DONT_CARE, "bcm4354a1_ag", "ap6354"},
125*4882a593Smuzhiyun {BCM4354_CHIP_ID, 2, DONT_CARE, "bcm4356a2_ag", "ap6356"},
126*4882a593Smuzhiyun {BCM4356_CHIP_ID, 2, DONT_CARE, "bcm4356a2_ag", "ap6356"},
127*4882a593Smuzhiyun {BCM4371_CHIP_ID, 2, DONT_CARE, "bcm4356a2_ag", ""},
128*4882a593Smuzhiyun {BCM43569_CHIP_ID, 3, DONT_CARE, "bcm4358a3_ag", ""},
129*4882a593Smuzhiyun {BCM4359_CHIP_ID, 5, DONT_CARE, "bcm4359b1_ag", ""},
130*4882a593Smuzhiyun {BCM4359_CHIP_ID, 9, DONT_CARE, "bcm4359c0_ag", "ap6398s"},
131*4882a593Smuzhiyun {BCM43751_CHIP_ID, 1, DONT_CARE, "bcm43751a1_ag", ""},
132*4882a593Smuzhiyun {BCM43751_CHIP_ID, 2, DONT_CARE, "bcm43751a2_ag", ""},
133*4882a593Smuzhiyun {BCM43752_CHIP_ID, 1, DONT_CARE, "bcm43752a1_ag", ""},
134*4882a593Smuzhiyun {BCM43752_CHIP_ID, 2, DONT_CARE, "bcm43752a2_ag", "ap6275s"},
135*4882a593Smuzhiyun #endif
136*4882a593Smuzhiyun #ifdef BCMPCIE
137*4882a593Smuzhiyun {BCM4354_CHIP_ID, 2, DONT_CARE, "bcm4356a2_pcie_ag", ""},
138*4882a593Smuzhiyun {BCM4356_CHIP_ID, 2, DONT_CARE, "bcm4356a2_pcie_ag", ""},
139*4882a593Smuzhiyun {BCM4359_CHIP_ID, 9, DONT_CARE, "bcm4359c0_pcie_ag", ""},
140*4882a593Smuzhiyun {BCM43751_CHIP_ID, 1, DONT_CARE, "bcm43751a1_pcie_ag", ""},
141*4882a593Smuzhiyun {BCM43751_CHIP_ID, 2, DONT_CARE, "bcm43751a2_pcie_ag", ""},
142*4882a593Smuzhiyun {BCM43752_CHIP_ID, 1, DONT_CARE, "bcm43752a1_pcie_ag", ""},
143*4882a593Smuzhiyun {BCM43752_CHIP_ID, 2, DONT_CARE, "bcm43752a2_pcie_ag", "AP6275P"},
144*4882a593Smuzhiyun {BCM4375_CHIP_ID, 5, DONT_CARE, "bcm4375b4_pcie_ag", ""},
145*4882a593Smuzhiyun #endif
146*4882a593Smuzhiyun #ifdef BCMDBUS
147*4882a593Smuzhiyun {BCM43143_CHIP_ID, 2, DONT_CARE, "bcm43143b0", ""},
148*4882a593Smuzhiyun {BCM43242_CHIP_ID, 1, DONT_CARE, "bcm43242a1_ag", ""},
149*4882a593Smuzhiyun {BCM43569_CHIP_ID, 2, DONT_CARE, "bcm4358u_ag", ""},
150*4882a593Smuzhiyun #endif
151*4882a593Smuzhiyun };
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun #ifdef UPDATE_MODULE_NAME
154*4882a593Smuzhiyun typedef void (compat_func_t)(dhd_pub_t *dhd);
155*4882a593Smuzhiyun typedef struct module_name_map_t {
156*4882a593Smuzhiyun uint devid;
157*4882a593Smuzhiyun uint chip;
158*4882a593Smuzhiyun uint chiprev;
159*4882a593Smuzhiyun uint svid;
160*4882a593Smuzhiyun uint ssid;
161*4882a593Smuzhiyun char *module_name;
162*4882a593Smuzhiyun char *chip_name;
163*4882a593Smuzhiyun compat_func_t *compat_func;
164*4882a593Smuzhiyun } module_name_map_t;
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun #if defined(BCMSDIO) || defined(BCMPCIE)
167*4882a593Smuzhiyun static void dhd_conf_compat_vht(dhd_pub_t *dhd);
168*4882a593Smuzhiyun #endif
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun const module_name_map_t module_name_map[] = {
171*4882a593Smuzhiyun /* Devce ID Chip ID Chiprev SVID SSID
172*4882a593Smuzhiyun * ModuleName ChipName Compat function
173*4882a593Smuzhiyun */
174*4882a593Smuzhiyun #ifdef BCMSDIO
175*4882a593Smuzhiyun {BCM43751_CHIP_ID, BCM43752_CHIP_ID, 2, 0, 0,
176*4882a593Smuzhiyun "ap6398s2", "bcm4359c51a2_ag", dhd_conf_compat_vht},
177*4882a593Smuzhiyun {BCM43751_CHIP_ID, BCM43752_CHIP_ID, 2, 0, 0,
178*4882a593Smuzhiyun "ap6398sr32", "bcm4359c51a2_ag", dhd_conf_compat_vht},
179*4882a593Smuzhiyun {BCM43751_CHIP_ID, BCM43752_CHIP_ID, 2, 0, 0,
180*4882a593Smuzhiyun "ap6398sv", "bcm4359c51a2_ag", dhd_conf_compat_vht},
181*4882a593Smuzhiyun {BCM43751_CHIP_ID, BCM43752_CHIP_ID, 2, 0, 0,
182*4882a593Smuzhiyun "ap6398sv3", "bcm4359c51a2_ag", dhd_conf_compat_vht},
183*4882a593Smuzhiyun #endif
184*4882a593Smuzhiyun #ifdef BCMPCIE
185*4882a593Smuzhiyun {BCM43751_D11AX_ID, BCM43752_CHIP_ID, 2, 0x179F, 0x003C,
186*4882a593Smuzhiyun "ap6398p2", "bcm4359c51a2_pcie_ag", dhd_conf_compat_vht},
187*4882a593Smuzhiyun {BCM43751_D11AX_ID, BCM43752_CHIP_ID, 2, 0x17F9, 0x003C,
188*4882a593Smuzhiyun "ap6398p2", "bcm4359c51a2_pcie_ag", dhd_conf_compat_vht},
189*4882a593Smuzhiyun {BCM43751_D11AX_ID, BCM43752_CHIP_ID, 2, 0x17F9, 0x003D,
190*4882a593Smuzhiyun "ap6398pr32", "bcm4359c51a2_pcie_ag", dhd_conf_compat_vht},
191*4882a593Smuzhiyun {BCM43751_D11AX_ID, BCM43752_CHIP_ID, 2, 0x17F9, 0x003E,
192*4882a593Smuzhiyun "ap6398pv", "bcm4359c51a2_pcie_ag", dhd_conf_compat_vht},
193*4882a593Smuzhiyun {BCM43751_D11AX_ID, BCM43752_CHIP_ID, 2, 0x17F9, 0x003F,
194*4882a593Smuzhiyun "ap6398pv3", "bcm4359c51a2_pcie_ag", dhd_conf_compat_vht},
195*4882a593Smuzhiyun #endif
196*4882a593Smuzhiyun };
197*4882a593Smuzhiyun #endif
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun #ifdef BCMPCIE
200*4882a593Smuzhiyun typedef struct chip_cisaddr_map_t {
201*4882a593Smuzhiyun uint chip;
202*4882a593Smuzhiyun uint chiprev;
203*4882a593Smuzhiyun uint start_addr;
204*4882a593Smuzhiyun uint end_addr;
205*4882a593Smuzhiyun } chip_cisaddr_map_t;
206*4882a593Smuzhiyun const chip_cisaddr_map_t chip_cisaddr_map[] = {
207*4882a593Smuzhiyun /* ChipID Chiprev Start End */
208*4882a593Smuzhiyun {BCM4354_CHIP_ID, 2, 0x0, 0x0},
209*4882a593Smuzhiyun {BCM4356_CHIP_ID, 2, 0x0, 0x0},
210*4882a593Smuzhiyun {BCM4359_CHIP_ID, 9, 0x0, 0x0},
211*4882a593Smuzhiyun // {BCM43752_CHIP_ID, 2, 0x18011120, 0x18011177},
212*4882a593Smuzhiyun // {BCM4375_CHIP_ID, 5, 0x18011120, 0x18011177},
213*4882a593Smuzhiyun };
214*4882a593Smuzhiyun #endif
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun #ifdef DHD_TPUT_PATCH
217*4882a593Smuzhiyun extern int dhd_change_mtu(dhd_pub_t *dhd, int new_mtu, int ifidx);
218*4882a593Smuzhiyun #endif
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun #ifdef WL_CFG80211
221*4882a593Smuzhiyun bool
dhd_conf_legacy_chip_check(dhd_pub_t * dhd)222*4882a593Smuzhiyun dhd_conf_legacy_chip_check(dhd_pub_t *dhd)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun uint chip = dhd->conf->chip;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID ||
227*4882a593Smuzhiyun chip == BCM4334_CHIP_ID || chip == BCM43340_CHIP_ID ||
228*4882a593Smuzhiyun chip == BCM43341_CHIP_ID || chip == BCM4324_CHIP_ID ||
229*4882a593Smuzhiyun chip == BCM4335_CHIP_ID || chip == BCM4339_CHIP_ID ||
230*4882a593Smuzhiyun chip == BCM4354_CHIP_ID || chip == BCM4356_CHIP_ID ||
231*4882a593Smuzhiyun chip == BCM4371_CHIP_ID ||
232*4882a593Smuzhiyun chip == BCM43430_CHIP_ID ||
233*4882a593Smuzhiyun chip == BCM4345_CHIP_ID || chip == BCM43454_CHIP_ID ||
234*4882a593Smuzhiyun chip == BCM4359_CHIP_ID ||
235*4882a593Smuzhiyun chip == BCM43143_CHIP_ID || chip == BCM43242_CHIP_ID ||
236*4882a593Smuzhiyun chip == BCM43569_CHIP_ID) {
237*4882a593Smuzhiyun return true;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun return false;
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun bool
dhd_conf_new_chip_check(dhd_pub_t * dhd)244*4882a593Smuzhiyun dhd_conf_new_chip_check(dhd_pub_t *dhd)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun uint chip = dhd->conf->chip;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID ||
249*4882a593Smuzhiyun chip == BCM4334_CHIP_ID || chip == BCM43340_CHIP_ID ||
250*4882a593Smuzhiyun chip == BCM43341_CHIP_ID || chip == BCM4324_CHIP_ID ||
251*4882a593Smuzhiyun chip == BCM4335_CHIP_ID || chip == BCM4339_CHIP_ID ||
252*4882a593Smuzhiyun chip == BCM4354_CHIP_ID || chip == BCM4356_CHIP_ID ||
253*4882a593Smuzhiyun chip == BCM4371_CHIP_ID ||
254*4882a593Smuzhiyun chip == BCM43430_CHIP_ID ||
255*4882a593Smuzhiyun chip == BCM4345_CHIP_ID || chip == BCM43454_CHIP_ID ||
256*4882a593Smuzhiyun chip == BCM43143_CHIP_ID || chip == BCM43242_CHIP_ID ||
257*4882a593Smuzhiyun chip == BCM43569_CHIP_ID) {
258*4882a593Smuzhiyun return false;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun return true;
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun bool
dhd_conf_extsae_chip(dhd_pub_t * dhd)265*4882a593Smuzhiyun dhd_conf_extsae_chip(dhd_pub_t *dhd)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun uint chip = dhd->conf->chip;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID ||
270*4882a593Smuzhiyun chip == BCM4334_CHIP_ID || chip == BCM43340_CHIP_ID ||
271*4882a593Smuzhiyun chip == BCM43341_CHIP_ID || chip == BCM4324_CHIP_ID ||
272*4882a593Smuzhiyun chip == BCM4335_CHIP_ID || chip == BCM4339_CHIP_ID ||
273*4882a593Smuzhiyun chip == BCM4354_CHIP_ID || chip == BCM4356_CHIP_ID ||
274*4882a593Smuzhiyun chip == BCM43143_CHIP_ID || chip == BCM43242_CHIP_ID ||
275*4882a593Smuzhiyun chip == BCM43569_CHIP_ID) {
276*4882a593Smuzhiyun return false;
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun return true;
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun #endif
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun #ifdef BCMSDIO
284*4882a593Smuzhiyun static void
dhd_conf_disable_slpauto(dhd_pub_t * dhd)285*4882a593Smuzhiyun dhd_conf_disable_slpauto(dhd_pub_t *dhd)
286*4882a593Smuzhiyun {
287*4882a593Smuzhiyun uint chip = dhd->conf->chip;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID ||
290*4882a593Smuzhiyun chip == BCM4334_CHIP_ID || chip == BCM43340_CHIP_ID ||
291*4882a593Smuzhiyun chip == BCM43341_CHIP_ID || chip == BCM4324_CHIP_ID ||
292*4882a593Smuzhiyun chip == BCM4335_CHIP_ID || chip == BCM4339_CHIP_ID ||
293*4882a593Smuzhiyun chip == BCM4354_CHIP_ID || chip == BCM4356_CHIP_ID ||
294*4882a593Smuzhiyun chip == BCM4371_CHIP_ID ||
295*4882a593Smuzhiyun chip == BCM43430_CHIP_ID ||
296*4882a593Smuzhiyun chip == BCM4345_CHIP_ID || chip == BCM43454_CHIP_ID ||
297*4882a593Smuzhiyun chip == BCM4359_CHIP_ID) {
298*4882a593Smuzhiyun dhd_slpauto = FALSE;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun CONFIG_MSG("dhd_slpauto = %d\n", dhd_slpauto);
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun #endif
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun void
dhd_conf_free_chip_nv_path_list(wl_chip_nv_path_list_ctrl_t * chip_nv_list)305*4882a593Smuzhiyun dhd_conf_free_chip_nv_path_list(wl_chip_nv_path_list_ctrl_t *chip_nv_list)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun CONFIG_TRACE("called\n");
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun if (chip_nv_list->m_chip_nv_path_head) {
310*4882a593Smuzhiyun CONFIG_TRACE("Free %p\n", chip_nv_list->m_chip_nv_path_head);
311*4882a593Smuzhiyun kfree(chip_nv_list->m_chip_nv_path_head);
312*4882a593Smuzhiyun chip_nv_list->m_chip_nv_path_head = NULL;
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun chip_nv_list->count = 0;
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun #if defined(BCMSDIO) || defined(BCMPCIE)
318*4882a593Smuzhiyun typedef struct cis_tuple_format {
319*4882a593Smuzhiyun uint8 id;
320*4882a593Smuzhiyun uint8 len; /* total length of tag and data */
321*4882a593Smuzhiyun uint8 tag;
322*4882a593Smuzhiyun uint8 data[1];
323*4882a593Smuzhiyun } cis_tuple_format_t;
324*4882a593Smuzhiyun #define SBSDIO_CIS_SIZE_LIMIT 0x200
325*4882a593Smuzhiyun #define SBSDIO_TUPLE_SIZE_LIMIT 0xff
326*4882a593Smuzhiyun #define CIS_TUPLE_ID_BRCM 0x80
327*4882a593Smuzhiyun #define CIS_TUPLE_TAG_MACADDR 0x19
328*4882a593Smuzhiyun #define CIS_TUPLE_ID_AMPAK 0x8e
329*4882a593Smuzhiyun #define CIS_TUPLE_TAG_MODULE 0x41
330*4882a593Smuzhiyun #define CIS_TUPLE_LENGTH 1
331*4882a593Smuzhiyun #define CIS_TUPLE_HDR_LEN 2
332*4882a593Smuzhiyun #endif
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun #ifdef BCMSDIO
335*4882a593Smuzhiyun #if defined(HW_OOB) || defined(FORCE_WOWLAN)
336*4882a593Smuzhiyun void
dhd_conf_set_hw_oob_intr(bcmsdh_info_t * sdh,struct si_pub * sih)337*4882a593Smuzhiyun dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, struct si_pub *sih)
338*4882a593Smuzhiyun {
339*4882a593Smuzhiyun uint32 gpiocontrol, addr;
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun if (CHIPID(sih->chip) == BCM43362_CHIP_ID) {
342*4882a593Smuzhiyun CONFIG_MSG("Enable HW OOB for 43362\n");
343*4882a593Smuzhiyun addr = SI_ENUM_BASE(sih) + OFFSETOF(chipcregs_t, gpiocontrol);
344*4882a593Smuzhiyun gpiocontrol = bcmsdh_reg_read(sdh, addr, 4);
345*4882a593Smuzhiyun gpiocontrol |= 0x2;
346*4882a593Smuzhiyun bcmsdh_reg_write(sdh, addr, 4, gpiocontrol);
347*4882a593Smuzhiyun bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10005, 0xf, NULL);
348*4882a593Smuzhiyun bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10006, 0x0, NULL);
349*4882a593Smuzhiyun bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10007, 0x2, NULL);
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun #endif
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun void
dhd_conf_get_otp(dhd_pub_t * dhd,bcmsdh_info_t * sdh,si_t * sih)355*4882a593Smuzhiyun dhd_conf_get_otp(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih)
356*4882a593Smuzhiyun {
357*4882a593Smuzhiyun int i, err = -1;
358*4882a593Smuzhiyun uint8 *cis, *ptr = 0;
359*4882a593Smuzhiyun uint8 mac_header[3] = {0x80, 0x07, 0x19};
360*4882a593Smuzhiyun cis_tuple_format_t *tuple;
361*4882a593Smuzhiyun int totlen, len;
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun if (!(cis = MALLOC(dhd->osh, SBSDIO_CIS_SIZE_LIMIT))) {
364*4882a593Smuzhiyun CONFIG_ERROR("cis malloc failed\n");
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun bzero(cis, SBSDIO_CIS_SIZE_LIMIT);
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun if ((err = bcmsdh_cis_read(sdh, 0, cis, SBSDIO_CIS_SIZE_LIMIT))) {
369*4882a593Smuzhiyun CONFIG_ERROR("cis read err %d\n", err);
370*4882a593Smuzhiyun MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT);
371*4882a593Smuzhiyun return;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun tuple = (cis_tuple_format_t *)cis;
374*4882a593Smuzhiyun totlen = SBSDIO_CIS_SIZE_LIMIT;
375*4882a593Smuzhiyun if (config_msg_level & CONFIG_TRACE_LEVEL) {
376*4882a593Smuzhiyun prhex("CIS", &tuple->id, totlen);
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun while (totlen >= (tuple->len + CIS_TUPLE_HDR_LEN)) {
379*4882a593Smuzhiyun len = tuple->len;
380*4882a593Smuzhiyun if ((config_msg_level & CONFIG_TRACE_LEVEL) && tuple->id) {
381*4882a593Smuzhiyun prhex("TPL", &tuple->id, tuple->len + CIS_TUPLE_HDR_LEN);
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun if (tuple->id == 0xff || tuple->len == 0xff)
384*4882a593Smuzhiyun break;
385*4882a593Smuzhiyun if ((tuple->id == CIS_TUPLE_ID_BRCM) &&
386*4882a593Smuzhiyun (tuple->tag == CIS_TUPLE_TAG_MACADDR) &&
387*4882a593Smuzhiyun (totlen >= (int)(len + CIS_TUPLE_HDR_LEN))) {
388*4882a593Smuzhiyun memcpy(&dhd->conf->otp_mac, tuple->data, ETHER_ADDR_LEN);
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun #ifdef GET_OTP_MODULE_NAME
391*4882a593Smuzhiyun else if (tuple->id == CIS_TUPLE_ID_AMPAK && (tuple->len) &&
392*4882a593Smuzhiyun tuple->tag == CIS_TUPLE_TAG_MODULE) {
393*4882a593Smuzhiyun int len = tuple->len - 1;
394*4882a593Smuzhiyun if (len <= sizeof(dhd->conf->module_name) - 1) {
395*4882a593Smuzhiyun strncpy(dhd->conf->module_name, tuple->data, len);
396*4882a593Smuzhiyun CONFIG_MSG("module_name=%s\n", dhd->conf->module_name);
397*4882a593Smuzhiyun } else {
398*4882a593Smuzhiyun CONFIG_ERROR("len is too long %d >= %d\n",
399*4882a593Smuzhiyun len, (int)sizeof(dhd->conf->module_name) - 1);
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun #endif
403*4882a593Smuzhiyun tuple = (cis_tuple_format_t*)((uint8*)tuple + (len + CIS_TUPLE_HDR_LEN));
404*4882a593Smuzhiyun totlen -= (len + CIS_TUPLE_HDR_LEN);
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun if (!memcmp(ðer_null, &dhd->conf->otp_mac, ETHER_ADDR_LEN)) {
408*4882a593Smuzhiyun ptr = cis;
409*4882a593Smuzhiyun /* Special OTP */
410*4882a593Smuzhiyun if (bcmsdh_reg_read(sdh, SI_ENUM_BASE(sih), 4) == 0x16044330) {
411*4882a593Smuzhiyun for (i=0; i<SBSDIO_CIS_SIZE_LIMIT; i++) {
412*4882a593Smuzhiyun if (!memcmp(mac_header, ptr, 3)) {
413*4882a593Smuzhiyun memcpy(&dhd->conf->otp_mac, ptr+3, ETHER_ADDR_LEN);
414*4882a593Smuzhiyun break;
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun ptr++;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun ASSERT(cis);
422*4882a593Smuzhiyun MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT);
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun #ifdef SET_FWNV_BY_MAC
426*4882a593Smuzhiyun void
dhd_conf_free_mac_list(wl_mac_list_ctrl_t * mac_list)427*4882a593Smuzhiyun dhd_conf_free_mac_list(wl_mac_list_ctrl_t *mac_list)
428*4882a593Smuzhiyun {
429*4882a593Smuzhiyun int i;
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun CONFIG_TRACE("called\n");
432*4882a593Smuzhiyun if (mac_list->m_mac_list_head) {
433*4882a593Smuzhiyun for (i=0; i<mac_list->count; i++) {
434*4882a593Smuzhiyun if (mac_list->m_mac_list_head[i].mac) {
435*4882a593Smuzhiyun CONFIG_TRACE("Free mac %p\n", mac_list->m_mac_list_head[i].mac);
436*4882a593Smuzhiyun kfree(mac_list->m_mac_list_head[i].mac);
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun CONFIG_TRACE("Free m_mac_list_head %p\n", mac_list->m_mac_list_head);
440*4882a593Smuzhiyun kfree(mac_list->m_mac_list_head);
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun mac_list->count = 0;
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun void
dhd_conf_set_fw_name_by_mac(dhd_pub_t * dhd,char * fw_path)446*4882a593Smuzhiyun dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, char *fw_path)
447*4882a593Smuzhiyun {
448*4882a593Smuzhiyun int i, j;
449*4882a593Smuzhiyun uint8 *mac = (uint8 *)&dhd->conf->otp_mac;
450*4882a593Smuzhiyun int fw_num=0, mac_num=0;
451*4882a593Smuzhiyun uint32 oui, nic;
452*4882a593Smuzhiyun wl_mac_list_t *mac_list;
453*4882a593Smuzhiyun wl_mac_range_t *mac_range;
454*4882a593Smuzhiyun int fw_type, fw_type_new;
455*4882a593Smuzhiyun char *name_ptr;
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun mac_list = dhd->conf->fw_by_mac.m_mac_list_head;
458*4882a593Smuzhiyun fw_num = dhd->conf->fw_by_mac.count;
459*4882a593Smuzhiyun if (!mac_list || !fw_num)
460*4882a593Smuzhiyun return;
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun oui = (mac[0] << 16) | (mac[1] << 8) | (mac[2]);
463*4882a593Smuzhiyun nic = (mac[3] << 16) | (mac[4] << 8) | (mac[5]);
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun /* find out the last '/' */
466*4882a593Smuzhiyun i = strlen(fw_path);
467*4882a593Smuzhiyun while (i > 0) {
468*4882a593Smuzhiyun if (fw_path[i] == '/') {
469*4882a593Smuzhiyun i++;
470*4882a593Smuzhiyun break;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun i--;
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun name_ptr = &fw_path[i];
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun if (strstr(name_ptr, "_apsta"))
477*4882a593Smuzhiyun fw_type = FW_TYPE_APSTA;
478*4882a593Smuzhiyun else if (strstr(name_ptr, "_p2p"))
479*4882a593Smuzhiyun fw_type = FW_TYPE_P2P;
480*4882a593Smuzhiyun else if (strstr(name_ptr, "_mesh"))
481*4882a593Smuzhiyun fw_type = FW_TYPE_MESH;
482*4882a593Smuzhiyun else if (strstr(name_ptr, "_ezmesh"))
483*4882a593Smuzhiyun fw_type = FW_TYPE_EZMESH;
484*4882a593Smuzhiyun else if (strstr(name_ptr, "_es"))
485*4882a593Smuzhiyun fw_type = FW_TYPE_ES;
486*4882a593Smuzhiyun else if (strstr(name_ptr, "_mfg"))
487*4882a593Smuzhiyun fw_type = FW_TYPE_MFG;
488*4882a593Smuzhiyun else
489*4882a593Smuzhiyun fw_type = FW_TYPE_STA;
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun for (i=0; i<fw_num; i++) {
492*4882a593Smuzhiyun mac_num = mac_list[i].count;
493*4882a593Smuzhiyun mac_range = mac_list[i].mac;
494*4882a593Smuzhiyun if (strstr(mac_list[i].name, "_apsta"))
495*4882a593Smuzhiyun fw_type_new = FW_TYPE_APSTA;
496*4882a593Smuzhiyun else if (strstr(mac_list[i].name, "_p2p"))
497*4882a593Smuzhiyun fw_type_new = FW_TYPE_P2P;
498*4882a593Smuzhiyun else if (strstr(mac_list[i].name, "_mesh"))
499*4882a593Smuzhiyun fw_type_new = FW_TYPE_MESH;
500*4882a593Smuzhiyun else if (strstr(mac_list[i].name, "_ezmesh"))
501*4882a593Smuzhiyun fw_type_new = FW_TYPE_EZMESH;
502*4882a593Smuzhiyun else if (strstr(mac_list[i].name, "_es"))
503*4882a593Smuzhiyun fw_type_new = FW_TYPE_ES;
504*4882a593Smuzhiyun else if (strstr(mac_list[i].name, "_mfg"))
505*4882a593Smuzhiyun fw_type_new = FW_TYPE_MFG;
506*4882a593Smuzhiyun else
507*4882a593Smuzhiyun fw_type_new = FW_TYPE_STA;
508*4882a593Smuzhiyun if (fw_type != fw_type_new) {
509*4882a593Smuzhiyun CONFIG_MSG("fw_typ=%d != fw_type_new=%d\n", fw_type, fw_type_new);
510*4882a593Smuzhiyun continue;
511*4882a593Smuzhiyun }
512*4882a593Smuzhiyun for (j=0; j<mac_num; j++) {
513*4882a593Smuzhiyun if (oui == mac_range[j].oui) {
514*4882a593Smuzhiyun if (nic >= mac_range[j].nic_start && nic <= mac_range[j].nic_end) {
515*4882a593Smuzhiyun strcpy(name_ptr, mac_list[i].name);
516*4882a593Smuzhiyun CONFIG_MSG("matched oui=0x%06X, nic=0x%06X\n", oui, nic);
517*4882a593Smuzhiyun CONFIG_MSG("fw_path=%s\n", fw_path);
518*4882a593Smuzhiyun return;
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun void
dhd_conf_set_nv_name_by_mac(dhd_pub_t * dhd,char * nv_path)526*4882a593Smuzhiyun dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, char *nv_path)
527*4882a593Smuzhiyun {
528*4882a593Smuzhiyun int i, j;
529*4882a593Smuzhiyun uint8 *mac = (uint8 *)&dhd->conf->otp_mac;
530*4882a593Smuzhiyun int nv_num=0, mac_num=0;
531*4882a593Smuzhiyun uint32 oui, nic;
532*4882a593Smuzhiyun wl_mac_list_t *mac_list;
533*4882a593Smuzhiyun wl_mac_range_t *mac_range;
534*4882a593Smuzhiyun char *pnv_name;
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun mac_list = dhd->conf->nv_by_mac.m_mac_list_head;
537*4882a593Smuzhiyun nv_num = dhd->conf->nv_by_mac.count;
538*4882a593Smuzhiyun if (!mac_list || !nv_num)
539*4882a593Smuzhiyun return;
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun oui = (mac[0] << 16) | (mac[1] << 8) | (mac[2]);
542*4882a593Smuzhiyun nic = (mac[3] << 16) | (mac[4] << 8) | (mac[5]);
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun /* find out the last '/' */
545*4882a593Smuzhiyun i = strlen(nv_path);
546*4882a593Smuzhiyun while (i > 0) {
547*4882a593Smuzhiyun if (nv_path[i] == '/') break;
548*4882a593Smuzhiyun i--;
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun pnv_name = &nv_path[i+1];
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun for (i=0; i<nv_num; i++) {
553*4882a593Smuzhiyun mac_num = mac_list[i].count;
554*4882a593Smuzhiyun mac_range = mac_list[i].mac;
555*4882a593Smuzhiyun for (j=0; j<mac_num; j++) {
556*4882a593Smuzhiyun if (oui == mac_range[j].oui) {
557*4882a593Smuzhiyun if (nic >= mac_range[j].nic_start && nic <= mac_range[j].nic_end) {
558*4882a593Smuzhiyun strcpy(pnv_name, mac_list[i].name);
559*4882a593Smuzhiyun CONFIG_MSG("matched oui=0x%06X, nic=0x%06X\n", oui, nic);
560*4882a593Smuzhiyun CONFIG_MSG("nv_path=%s\n", nv_path);
561*4882a593Smuzhiyun return;
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun #endif
568*4882a593Smuzhiyun #endif
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun #ifdef BCMPCIE
571*4882a593Smuzhiyun static int
dhd_conf_read_otp_from_bp(si_t * sih,uint32 * data_buf,uint32 cis_start_addr,uint32 cis_max_cnt)572*4882a593Smuzhiyun dhd_conf_read_otp_from_bp(si_t *sih, uint32 *data_buf,
573*4882a593Smuzhiyun uint32 cis_start_addr, uint32 cis_max_cnt)
574*4882a593Smuzhiyun {
575*4882a593Smuzhiyun int int_val = 0, i = 0, bp_idx = 0;
576*4882a593Smuzhiyun int boardtype_backplane_addr[] = {
577*4882a593Smuzhiyun 0x18010324, /* OTP Control 1 */
578*4882a593Smuzhiyun 0x18012618, /* PMU min resource mask */
579*4882a593Smuzhiyun };
580*4882a593Smuzhiyun int boardtype_backplane_data[] = {
581*4882a593Smuzhiyun 0x00fa0000,
582*4882a593Smuzhiyun 0x0e4fffff /* Keep on ARMHTAVAIL */
583*4882a593Smuzhiyun };
584*4882a593Smuzhiyun uint32 org_boardtype_backplane_data[] = {
585*4882a593Smuzhiyun 0,
586*4882a593Smuzhiyun 0
587*4882a593Smuzhiyun };
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun for (bp_idx=0; bp_idx<ARRAYSIZE(boardtype_backplane_addr); bp_idx++) {
590*4882a593Smuzhiyun /* Read OTP Control 1 and PMU min_rsrc_mask before writing */
591*4882a593Smuzhiyun if (si_backplane_access(sih, boardtype_backplane_addr[bp_idx], sizeof(int),
592*4882a593Smuzhiyun &org_boardtype_backplane_data[bp_idx], TRUE) != BCME_OK) {
593*4882a593Smuzhiyun CONFIG_ERROR("invalid size/addr combination\n");
594*4882a593Smuzhiyun return BCME_ERROR;
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun /* Write new OTP and PMU configuration */
598*4882a593Smuzhiyun if (si_backplane_access(sih, boardtype_backplane_addr[bp_idx], sizeof(int),
599*4882a593Smuzhiyun &boardtype_backplane_data[bp_idx], FALSE) != BCME_OK) {
600*4882a593Smuzhiyun CONFIG_ERROR("invalid size/addr combination\n");
601*4882a593Smuzhiyun return BCME_ERROR;
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun if (si_backplane_access(sih, boardtype_backplane_addr[bp_idx], sizeof(int),
605*4882a593Smuzhiyun &int_val, TRUE) != BCME_OK) {
606*4882a593Smuzhiyun CONFIG_ERROR("invalid size/addr combination\n");
607*4882a593Smuzhiyun return BCME_ERROR;
608*4882a593Smuzhiyun }
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun CONFIG_TRACE("boardtype_backplane_addr 0x%08x rdata 0x%04x\n",
611*4882a593Smuzhiyun boardtype_backplane_addr[bp_idx], int_val);
612*4882a593Smuzhiyun }
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun /* read tuple raw data */
615*4882a593Smuzhiyun for (i=0; i<cis_max_cnt; i++) {
616*4882a593Smuzhiyun if (si_backplane_access(sih, cis_start_addr + i * sizeof(uint32),
617*4882a593Smuzhiyun sizeof(uint32), &data_buf[i], TRUE) != BCME_OK) {
618*4882a593Smuzhiyun break;
619*4882a593Smuzhiyun }
620*4882a593Smuzhiyun CONFIG_TRACE("tuple index %d, raw data 0x%08x\n", i, data_buf[i]);
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun for (bp_idx=0; bp_idx<ARRAYSIZE(boardtype_backplane_addr); bp_idx++) {
624*4882a593Smuzhiyun /* Write original OTP and PMU configuration */
625*4882a593Smuzhiyun if (si_backplane_access(sih, boardtype_backplane_addr[bp_idx], sizeof(int),
626*4882a593Smuzhiyun &org_boardtype_backplane_data[bp_idx], FALSE) != BCME_OK) {
627*4882a593Smuzhiyun CONFIG_ERROR("invalid size/addr combination\n");
628*4882a593Smuzhiyun return BCME_ERROR;
629*4882a593Smuzhiyun }
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun if (si_backplane_access(sih, boardtype_backplane_addr[bp_idx], sizeof(int),
632*4882a593Smuzhiyun &int_val, TRUE) != BCME_OK) {
633*4882a593Smuzhiyun CONFIG_ERROR("invalid size/addr combination\n");
634*4882a593Smuzhiyun return BCME_ERROR;
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun CONFIG_TRACE("boardtype_backplane_addr 0x%08x rdata 0x%04x\n",
638*4882a593Smuzhiyun boardtype_backplane_addr[bp_idx], int_val);
639*4882a593Smuzhiyun }
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun return i * sizeof(uint32);
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun int
dhd_conf_get_otp(dhd_pub_t * dhd,si_t * sih)645*4882a593Smuzhiyun dhd_conf_get_otp(dhd_pub_t *dhd, si_t *sih)
646*4882a593Smuzhiyun {
647*4882a593Smuzhiyun int totlen, len;
648*4882a593Smuzhiyun uint32 *raw_data = NULL;
649*4882a593Smuzhiyun cis_tuple_format_t *tuple;
650*4882a593Smuzhiyun uint32 cis_start_addr = 0, cis_end_addr = 0, cis_max_cnt;
651*4882a593Smuzhiyun uint chip, chiprev;
652*4882a593Smuzhiyun int i, ret = BCME_OK;
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun chip = dhd->conf->chip;
655*4882a593Smuzhiyun chiprev = dhd->conf->chiprev;
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun for (i=0; i<sizeof(chip_cisaddr_map)/sizeof(chip_cisaddr_map[0]); i++) {
658*4882a593Smuzhiyun const chip_cisaddr_map_t* row = &chip_cisaddr_map[i];
659*4882a593Smuzhiyun if (row->chip == chip && row->chiprev == chiprev) {
660*4882a593Smuzhiyun cis_start_addr = row->start_addr;
661*4882a593Smuzhiyun cis_end_addr = row->end_addr;
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun
665*4882a593Smuzhiyun if (!cis_start_addr || !cis_end_addr) {
666*4882a593Smuzhiyun CONFIG_TRACE("no matched chip\n");
667*4882a593Smuzhiyun goto exit;
668*4882a593Smuzhiyun }
669*4882a593Smuzhiyun cis_max_cnt = (cis_end_addr - cis_start_addr + 1) / sizeof(uint32);
670*4882a593Smuzhiyun
671*4882a593Smuzhiyun raw_data = kmalloc(cis_max_cnt, GFP_KERNEL);
672*4882a593Smuzhiyun if (raw_data == NULL) {
673*4882a593Smuzhiyun CONFIG_ERROR("Failed to allocate buffer of %d bytes\n", cis_max_cnt);
674*4882a593Smuzhiyun goto exit;
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun totlen = dhd_conf_read_otp_from_bp(sih, raw_data, cis_start_addr, cis_max_cnt);
678*4882a593Smuzhiyun if (totlen == BCME_ERROR || totlen == 0) {
679*4882a593Smuzhiyun CONFIG_ERROR("Can't read the OTP\n");
680*4882a593Smuzhiyun ret = BCME_ERROR;
681*4882a593Smuzhiyun goto exit;
682*4882a593Smuzhiyun }
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun tuple = (cis_tuple_format_t *)raw_data;
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun if (config_msg_level & CONFIG_TRACE_LEVEL) {
687*4882a593Smuzhiyun CONFIG_TRACE("start: 0x%x, end: 0x%x, totlen: %d\n",
688*4882a593Smuzhiyun cis_start_addr, cis_end_addr, totlen);
689*4882a593Smuzhiyun prhex("CIS", &tuple->id, totlen);
690*4882a593Smuzhiyun }
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun /* check the first tuple has tag 'start' */
693*4882a593Smuzhiyun if (tuple->id != CIS_TUPLE_ID_BRCM) {
694*4882a593Smuzhiyun CONFIG_ERROR("Can not find the TAG\n");
695*4882a593Smuzhiyun ret = BCME_ERROR;
696*4882a593Smuzhiyun goto exit;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun /* find tagged parameter */
700*4882a593Smuzhiyun while (totlen >= (tuple->len + CIS_TUPLE_HDR_LEN)) {
701*4882a593Smuzhiyun len = tuple->len;
702*4882a593Smuzhiyun if ((config_msg_level & CONFIG_TRACE_LEVEL) && tuple->id) {
703*4882a593Smuzhiyun prhex("TPL", &tuple->id, tuple->len+CIS_TUPLE_HDR_LEN);
704*4882a593Smuzhiyun }
705*4882a593Smuzhiyun if ((tuple->id == CIS_TUPLE_ID_BRCM) &&
706*4882a593Smuzhiyun (tuple->tag == CIS_TUPLE_TAG_MACADDR) &&
707*4882a593Smuzhiyun (totlen >= (int)(len + CIS_TUPLE_HDR_LEN))) {
708*4882a593Smuzhiyun memcpy(&dhd->conf->otp_mac, tuple->data, ETHER_ADDR_LEN);
709*4882a593Smuzhiyun }
710*4882a593Smuzhiyun tuple = (cis_tuple_format_t*)((uint8*)tuple + (len + CIS_TUPLE_HDR_LEN));
711*4882a593Smuzhiyun totlen -= (len + CIS_TUPLE_HDR_LEN);
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun exit:
715*4882a593Smuzhiyun if(raw_data)
716*4882a593Smuzhiyun kfree(raw_data);
717*4882a593Smuzhiyun return ret;
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun bool
dhd_conf_legacy_msi_chip(dhd_pub_t * dhd)721*4882a593Smuzhiyun dhd_conf_legacy_msi_chip(dhd_pub_t *dhd)
722*4882a593Smuzhiyun {
723*4882a593Smuzhiyun uint chip;
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun chip = dhd->conf->chip;
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun if (chip == BCM4354_CHIP_ID || chip == BCM4356_CHIP_ID ||
728*4882a593Smuzhiyun chip == BCM4371_CHIP_ID ||
729*4882a593Smuzhiyun chip == BCM4359_CHIP_ID) {
730*4882a593Smuzhiyun return true;
731*4882a593Smuzhiyun }
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun return false;
734*4882a593Smuzhiyun }
735*4882a593Smuzhiyun #endif
736*4882a593Smuzhiyun
737*4882a593Smuzhiyun void
dhd_conf_free_country_list(struct dhd_conf * conf)738*4882a593Smuzhiyun dhd_conf_free_country_list(struct dhd_conf *conf)
739*4882a593Smuzhiyun {
740*4882a593Smuzhiyun country_list_t *country = conf->country_head;
741*4882a593Smuzhiyun int count = 0;
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun CONFIG_TRACE("called\n");
744*4882a593Smuzhiyun while (country) {
745*4882a593Smuzhiyun CONFIG_TRACE("Free cspec %s\n", country->cspec.country_abbrev);
746*4882a593Smuzhiyun conf->country_head = country->next;
747*4882a593Smuzhiyun kfree(country);
748*4882a593Smuzhiyun country = conf->country_head;
749*4882a593Smuzhiyun count++;
750*4882a593Smuzhiyun }
751*4882a593Smuzhiyun CONFIG_TRACE("%d country released\n", count);
752*4882a593Smuzhiyun }
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun void
dhd_conf_free_mchan_list(struct dhd_conf * conf)755*4882a593Smuzhiyun dhd_conf_free_mchan_list(struct dhd_conf *conf)
756*4882a593Smuzhiyun {
757*4882a593Smuzhiyun mchan_params_t *mchan = conf->mchan;
758*4882a593Smuzhiyun int count = 0;
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun CONFIG_TRACE("called\n");
761*4882a593Smuzhiyun while (mchan) {
762*4882a593Smuzhiyun CONFIG_TRACE("Free cspec %p\n", mchan);
763*4882a593Smuzhiyun conf->mchan = mchan->next;
764*4882a593Smuzhiyun kfree(mchan);
765*4882a593Smuzhiyun mchan = conf->mchan;
766*4882a593Smuzhiyun count++;
767*4882a593Smuzhiyun }
768*4882a593Smuzhiyun CONFIG_TRACE("%d mchan released\n", count);
769*4882a593Smuzhiyun }
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun const chip_name_map_t*
dhd_conf_match_chip(dhd_pub_t * dhd,uint ag_type)772*4882a593Smuzhiyun dhd_conf_match_chip(dhd_pub_t *dhd, uint ag_type)
773*4882a593Smuzhiyun {
774*4882a593Smuzhiyun uint chip, chiprev;
775*4882a593Smuzhiyun int i;
776*4882a593Smuzhiyun
777*4882a593Smuzhiyun chip = dhd->conf->chip;
778*4882a593Smuzhiyun chiprev = dhd->conf->chiprev;
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun for (i=0; i<sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) {
781*4882a593Smuzhiyun const chip_name_map_t *row = &chip_name_map[i];
782*4882a593Smuzhiyun if (row->chip == chip && row->chiprev == chiprev &&
783*4882a593Smuzhiyun (row->ag_type == ag_type ||
784*4882a593Smuzhiyun ag_type == DONT_CARE || row->ag_type == DONT_CARE)) {
785*4882a593Smuzhiyun return row;
786*4882a593Smuzhiyun }
787*4882a593Smuzhiyun }
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun return NULL;
790*4882a593Smuzhiyun }
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun #ifdef UPDATE_MODULE_NAME
793*4882a593Smuzhiyun const module_name_map_t*
dhd_conf_match_module(dhd_pub_t * dhd)794*4882a593Smuzhiyun dhd_conf_match_module(dhd_pub_t *dhd)
795*4882a593Smuzhiyun {
796*4882a593Smuzhiyun uint devid, chip, chiprev;
797*4882a593Smuzhiyun #ifdef BCMPCIE
798*4882a593Smuzhiyun uint svid, ssid;
799*4882a593Smuzhiyun #endif
800*4882a593Smuzhiyun #if defined(BCMSDIO) || defined(BCMPCIE)
801*4882a593Smuzhiyun int i;
802*4882a593Smuzhiyun #endif
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun devid = dhd->conf->devid;
805*4882a593Smuzhiyun chip = dhd->conf->chip;
806*4882a593Smuzhiyun chiprev = dhd->conf->chiprev;
807*4882a593Smuzhiyun #ifdef BCMPCIE
808*4882a593Smuzhiyun svid = dhd->conf->svid;
809*4882a593Smuzhiyun ssid = dhd->conf->ssid;
810*4882a593Smuzhiyun #endif
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun #ifdef BCMSDIO
813*4882a593Smuzhiyun for (i=0; i<sizeof(module_name_map)/sizeof(module_name_map[0]); i++) {
814*4882a593Smuzhiyun const module_name_map_t *row = &module_name_map[i];
815*4882a593Smuzhiyun if (row->devid == devid && row->chip == chip && row->chiprev == chiprev &&
816*4882a593Smuzhiyun !strcmp(row->module_name, dhd->conf->module_name)) {
817*4882a593Smuzhiyun return row;
818*4882a593Smuzhiyun }
819*4882a593Smuzhiyun }
820*4882a593Smuzhiyun #endif
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun #ifdef BCMPCIE
823*4882a593Smuzhiyun for (i=0; i<sizeof(module_name_map)/sizeof(module_name_map[0]); i++) {
824*4882a593Smuzhiyun const module_name_map_t *row = &module_name_map[i];
825*4882a593Smuzhiyun if (row->devid == devid && row->chip == chip && row->chiprev == chiprev &&
826*4882a593Smuzhiyun row->svid == svid && row->ssid == ssid) {
827*4882a593Smuzhiyun return row;
828*4882a593Smuzhiyun }
829*4882a593Smuzhiyun }
830*4882a593Smuzhiyun #endif
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun return NULL;
833*4882a593Smuzhiyun }
834*4882a593Smuzhiyun #endif
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun char *
dhd_conf_get_chip_name(dhd_pub_t * dhd,int ag_type,bool * chip_map_v2)837*4882a593Smuzhiyun dhd_conf_get_chip_name(dhd_pub_t *dhd, int ag_type, bool *chip_map_v2)
838*4882a593Smuzhiyun {
839*4882a593Smuzhiyun #ifdef UPDATE_MODULE_NAME
840*4882a593Smuzhiyun const module_name_map_t *row_module = NULL;
841*4882a593Smuzhiyun #endif
842*4882a593Smuzhiyun const chip_name_map_t *row_chip = NULL;
843*4882a593Smuzhiyun char *name = NULL;
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun *chip_map_v2 = FALSE;
846*4882a593Smuzhiyun #ifdef UPDATE_MODULE_NAME
847*4882a593Smuzhiyun row_module = dhd_conf_match_module(dhd);
848*4882a593Smuzhiyun if (row_module && strlen(row_module->chip_name)) {
849*4882a593Smuzhiyun name = row_module->chip_name;
850*4882a593Smuzhiyun } else
851*4882a593Smuzhiyun #endif
852*4882a593Smuzhiyun {
853*4882a593Smuzhiyun row_chip = dhd_conf_match_chip(dhd, ag_type);
854*4882a593Smuzhiyun if (row_chip && strlen(row_chip->chip_name)) {
855*4882a593Smuzhiyun name = row_chip->chip_name;
856*4882a593Smuzhiyun }
857*4882a593Smuzhiyun }
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun return name;
860*4882a593Smuzhiyun }
861*4882a593Smuzhiyun
862*4882a593Smuzhiyun char *
dhd_conf_get_module_name(dhd_pub_t * dhd,int ag_type)863*4882a593Smuzhiyun dhd_conf_get_module_name(dhd_pub_t *dhd, int ag_type)
864*4882a593Smuzhiyun {
865*4882a593Smuzhiyun #if defined(BCMPCIE) && defined(UPDATE_MODULE_NAME)
866*4882a593Smuzhiyun const module_name_map_t *row_module = NULL;
867*4882a593Smuzhiyun #endif
868*4882a593Smuzhiyun const chip_name_map_t *row_chip = NULL;
869*4882a593Smuzhiyun char *name = NULL;
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun #if defined(BCMPCIE) && defined(UPDATE_MODULE_NAME)
872*4882a593Smuzhiyun row_module = dhd_conf_match_module(dhd);
873*4882a593Smuzhiyun if (row_module && strlen(row_module->module_name)) {
874*4882a593Smuzhiyun name = row_module->module_name;
875*4882a593Smuzhiyun } else
876*4882a593Smuzhiyun #endif
877*4882a593Smuzhiyun {
878*4882a593Smuzhiyun row_chip = dhd_conf_match_chip(dhd, ag_type);
879*4882a593Smuzhiyun if (row_chip && strlen(row_chip->module_name)) {
880*4882a593Smuzhiyun name = row_chip->module_name;
881*4882a593Smuzhiyun }
882*4882a593Smuzhiyun }
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun return name;
885*4882a593Smuzhiyun }
886*4882a593Smuzhiyun
887*4882a593Smuzhiyun int
dhd_conf_set_fw_name_by_chip(dhd_pub_t * dhd,char * fw_path)888*4882a593Smuzhiyun dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path)
889*4882a593Smuzhiyun {
890*4882a593Smuzhiyun int fw_type, ag_type;
891*4882a593Smuzhiyun char *name_ptr, *chip_name = NULL;
892*4882a593Smuzhiyun bool chip_map_v2;
893*4882a593Smuzhiyun int i;
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun if (fw_path[0] == '\0') {
896*4882a593Smuzhiyun #ifdef CONFIG_BCMDHD_FW_PATH
897*4882a593Smuzhiyun bcm_strncpy_s(fw_path, MOD_PARAM_PATHLEN-1, CONFIG_BCMDHD_FW_PATH, MOD_PARAM_PATHLEN-1);
898*4882a593Smuzhiyun if (fw_path[0] == '\0')
899*4882a593Smuzhiyun #endif
900*4882a593Smuzhiyun {
901*4882a593Smuzhiyun CONFIG_MSG("firmware path is null\n");
902*4882a593Smuzhiyun return 0;
903*4882a593Smuzhiyun }
904*4882a593Smuzhiyun }
905*4882a593Smuzhiyun #ifndef FW_PATH_AUTO_SELECT
906*4882a593Smuzhiyun return DONT_CARE;
907*4882a593Smuzhiyun #endif
908*4882a593Smuzhiyun
909*4882a593Smuzhiyun /* find out the last '/' */
910*4882a593Smuzhiyun i = strlen(fw_path);
911*4882a593Smuzhiyun while (i > 0) {
912*4882a593Smuzhiyun if (fw_path[i] == '/') {
913*4882a593Smuzhiyun i++;
914*4882a593Smuzhiyun break;
915*4882a593Smuzhiyun }
916*4882a593Smuzhiyun i--;
917*4882a593Smuzhiyun }
918*4882a593Smuzhiyun name_ptr = &fw_path[i];
919*4882a593Smuzhiyun #ifdef BAND_AG
920*4882a593Smuzhiyun ag_type = FW_TYPE_AG;
921*4882a593Smuzhiyun #else
922*4882a593Smuzhiyun ag_type = strstr(name_ptr, "_ag") ? FW_TYPE_AG : FW_TYPE_G;
923*4882a593Smuzhiyun #endif
924*4882a593Smuzhiyun if (strstr(name_ptr, "_apsta"))
925*4882a593Smuzhiyun fw_type = FW_TYPE_APSTA;
926*4882a593Smuzhiyun else if (strstr(name_ptr, "_p2p"))
927*4882a593Smuzhiyun fw_type = FW_TYPE_P2P;
928*4882a593Smuzhiyun else if (strstr(name_ptr, "_mesh"))
929*4882a593Smuzhiyun fw_type = FW_TYPE_MESH;
930*4882a593Smuzhiyun else if (strstr(name_ptr, "_ezmesh"))
931*4882a593Smuzhiyun fw_type = FW_TYPE_EZMESH;
932*4882a593Smuzhiyun else if (strstr(name_ptr, "_es"))
933*4882a593Smuzhiyun fw_type = FW_TYPE_ES;
934*4882a593Smuzhiyun else if (strstr(name_ptr, "_mfg"))
935*4882a593Smuzhiyun fw_type = FW_TYPE_MFG;
936*4882a593Smuzhiyun else if (strstr(name_ptr, "_minime"))
937*4882a593Smuzhiyun fw_type = FW_TYPE_MINIME;
938*4882a593Smuzhiyun else
939*4882a593Smuzhiyun fw_type = FW_TYPE_STA;
940*4882a593Smuzhiyun #ifdef WLEASYMESH
941*4882a593Smuzhiyun if (dhd->conf->fw_type == FW_TYPE_EZMESH)
942*4882a593Smuzhiyun fw_type = FW_TYPE_EZMESH;
943*4882a593Smuzhiyun #endif /* WLEASYMESH */
944*4882a593Smuzhiyun
945*4882a593Smuzhiyun chip_name = dhd_conf_get_chip_name(dhd, ag_type, &chip_map_v2);
946*4882a593Smuzhiyun if (chip_name) {
947*4882a593Smuzhiyun strcpy(name_ptr, "fw_");
948*4882a593Smuzhiyun strcat(name_ptr, chip_name);
949*4882a593Smuzhiyun #ifdef BCMUSBDEV_COMPOSITE
950*4882a593Smuzhiyun strcat(name_ptr, "_cusb");
951*4882a593Smuzhiyun #endif
952*4882a593Smuzhiyun if (fw_type == FW_TYPE_APSTA)
953*4882a593Smuzhiyun strcat(name_ptr, "_apsta.bin");
954*4882a593Smuzhiyun else if (fw_type == FW_TYPE_P2P)
955*4882a593Smuzhiyun strcat(name_ptr, "_p2p.bin");
956*4882a593Smuzhiyun else if (fw_type == FW_TYPE_MESH)
957*4882a593Smuzhiyun strcat(name_ptr, "_mesh.bin");
958*4882a593Smuzhiyun else if (fw_type == FW_TYPE_EZMESH)
959*4882a593Smuzhiyun strcat(name_ptr, "_ezmesh.bin");
960*4882a593Smuzhiyun else if (fw_type == FW_TYPE_ES)
961*4882a593Smuzhiyun strcat(name_ptr, "_es.bin");
962*4882a593Smuzhiyun else if (fw_type == FW_TYPE_MFG)
963*4882a593Smuzhiyun strcat(name_ptr, "_mfg.bin");
964*4882a593Smuzhiyun else if (fw_type == FW_TYPE_MINIME)
965*4882a593Smuzhiyun strcat(name_ptr, "_minime.bin");
966*4882a593Smuzhiyun else
967*4882a593Smuzhiyun strcat(name_ptr, ".bin");
968*4882a593Smuzhiyun }
969*4882a593Smuzhiyun
970*4882a593Smuzhiyun dhd->conf->fw_type = fw_type;
971*4882a593Smuzhiyun
972*4882a593Smuzhiyun #ifndef MINIME
973*4882a593Smuzhiyun if (fw_type == FW_TYPE_MINIME)
974*4882a593Smuzhiyun CONFIG_ERROR("***** Please enable MINIME in Makefile *****\n");
975*4882a593Smuzhiyun #endif
976*4882a593Smuzhiyun
977*4882a593Smuzhiyun CONFIG_TRACE("firmware_path=%s\n", fw_path);
978*4882a593Smuzhiyun return ag_type;
979*4882a593Smuzhiyun }
980*4882a593Smuzhiyun
981*4882a593Smuzhiyun void
dhd_conf_set_clm_name_by_chip(dhd_pub_t * dhd,char * clm_path,int ag_type)982*4882a593Smuzhiyun dhd_conf_set_clm_name_by_chip(dhd_pub_t *dhd, char *clm_path, int ag_type)
983*4882a593Smuzhiyun {
984*4882a593Smuzhiyun char *name_ptr, *chip_name = NULL;
985*4882a593Smuzhiyun bool chip_map_v2;
986*4882a593Smuzhiyun int i;
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun if (clm_path[0] == '\0') {
989*4882a593Smuzhiyun CONFIG_MSG("clm path is null\n");
990*4882a593Smuzhiyun return;
991*4882a593Smuzhiyun }
992*4882a593Smuzhiyun
993*4882a593Smuzhiyun /* find out the last '/' */
994*4882a593Smuzhiyun i = strlen(clm_path);
995*4882a593Smuzhiyun while (i > 0) {
996*4882a593Smuzhiyun if (clm_path[i] == '/') {
997*4882a593Smuzhiyun i++;
998*4882a593Smuzhiyun break;
999*4882a593Smuzhiyun }
1000*4882a593Smuzhiyun i--;
1001*4882a593Smuzhiyun }
1002*4882a593Smuzhiyun name_ptr = &clm_path[i];
1003*4882a593Smuzhiyun
1004*4882a593Smuzhiyun chip_name = dhd_conf_get_chip_name(dhd, ag_type, &chip_map_v2);
1005*4882a593Smuzhiyun if (chip_name) {
1006*4882a593Smuzhiyun strcpy(name_ptr, "clm_");
1007*4882a593Smuzhiyun strcat(name_ptr, chip_name);
1008*4882a593Smuzhiyun strcat(name_ptr, ".blob");
1009*4882a593Smuzhiyun }
1010*4882a593Smuzhiyun
1011*4882a593Smuzhiyun CONFIG_TRACE("clm_path=%s\n", clm_path);
1012*4882a593Smuzhiyun }
1013*4882a593Smuzhiyun
1014*4882a593Smuzhiyun void
dhd_conf_set_nv_name_by_chip(dhd_pub_t * dhd,char * nv_path,int ag_type)1015*4882a593Smuzhiyun dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path, int ag_type)
1016*4882a593Smuzhiyun {
1017*4882a593Smuzhiyun uint chip, chiprev;
1018*4882a593Smuzhiyun char *name_ptr, *module_name = NULL, nv_name[32];
1019*4882a593Smuzhiyun int i;
1020*4882a593Smuzhiyun
1021*4882a593Smuzhiyun chip = dhd->conf->chip;
1022*4882a593Smuzhiyun chiprev = dhd->conf->chiprev;
1023*4882a593Smuzhiyun
1024*4882a593Smuzhiyun if (nv_path[0] == '\0') {
1025*4882a593Smuzhiyun #ifdef CONFIG_BCMDHD_NVRAM_PATH
1026*4882a593Smuzhiyun bcm_strncpy_s(nv_path, MOD_PARAM_PATHLEN-1, CONFIG_BCMDHD_NVRAM_PATH, MOD_PARAM_PATHLEN-1);
1027*4882a593Smuzhiyun if (nv_path[0] == '\0')
1028*4882a593Smuzhiyun #endif
1029*4882a593Smuzhiyun {
1030*4882a593Smuzhiyun CONFIG_MSG("nvram path is null\n");
1031*4882a593Smuzhiyun return;
1032*4882a593Smuzhiyun }
1033*4882a593Smuzhiyun }
1034*4882a593Smuzhiyun
1035*4882a593Smuzhiyun /* find out the last '/' */
1036*4882a593Smuzhiyun i = strlen(nv_path);
1037*4882a593Smuzhiyun while (i > 0) {
1038*4882a593Smuzhiyun if (nv_path[i] == '/') {
1039*4882a593Smuzhiyun i++;
1040*4882a593Smuzhiyun break;
1041*4882a593Smuzhiyun }
1042*4882a593Smuzhiyun i--;
1043*4882a593Smuzhiyun }
1044*4882a593Smuzhiyun name_ptr = &nv_path[i];
1045*4882a593Smuzhiyun
1046*4882a593Smuzhiyun module_name = dhd_conf_get_module_name(dhd, ag_type);
1047*4882a593Smuzhiyun if (module_name) {
1048*4882a593Smuzhiyun strcpy(name_ptr, "nvram_");
1049*4882a593Smuzhiyun strcat(name_ptr, module_name);
1050*4882a593Smuzhiyun #ifdef BCMUSBDEV_COMPOSITE
1051*4882a593Smuzhiyun strcat(name_ptr, "_cusb");
1052*4882a593Smuzhiyun #endif
1053*4882a593Smuzhiyun strcat(name_ptr, ".txt");
1054*4882a593Smuzhiyun }
1055*4882a593Smuzhiyun strcpy(nv_name, name_ptr);
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun #if defined(BCMSDIO) && defined(GET_OTP_MODULE_NAME)
1058*4882a593Smuzhiyun if (strlen(dhd->conf->module_name)) {
1059*4882a593Smuzhiyun strcpy(name_ptr, "nvram_");
1060*4882a593Smuzhiyun strcat(name_ptr, dhd->conf->module_name);
1061*4882a593Smuzhiyun strcat(name_ptr, ".txt");
1062*4882a593Smuzhiyun #ifdef COMPAT_OLD_MODULE
1063*4882a593Smuzhiyun if (dhd->conf->chip == BCM4359_CHIP_ID) {
1064*4882a593Smuzhiyun struct file *fp;
1065*4882a593Smuzhiyun // compatible for AP6398S and AP6398SA
1066*4882a593Smuzhiyun fp = dhd_filp_open(nv_path, O_RDONLY, 0);
1067*4882a593Smuzhiyun if (IS_ERR(fp) || (fp == NULL)) {
1068*4882a593Smuzhiyun strcpy(name_ptr, nv_name);
1069*4882a593Smuzhiyun } else {
1070*4882a593Smuzhiyun dhd_filp_close((struct file *)fp, NULL);
1071*4882a593Smuzhiyun }
1072*4882a593Smuzhiyun }
1073*4882a593Smuzhiyun #endif
1074*4882a593Smuzhiyun }
1075*4882a593Smuzhiyun #endif
1076*4882a593Smuzhiyun
1077*4882a593Smuzhiyun for (i=0; i<dhd->conf->nv_by_chip.count; i++) {
1078*4882a593Smuzhiyun if (chip==dhd->conf->nv_by_chip.m_chip_nv_path_head[i].chip &&
1079*4882a593Smuzhiyun chiprev==dhd->conf->nv_by_chip.m_chip_nv_path_head[i].chiprev) {
1080*4882a593Smuzhiyun strcpy(name_ptr, dhd->conf->nv_by_chip.m_chip_nv_path_head[i].name);
1081*4882a593Smuzhiyun break;
1082*4882a593Smuzhiyun }
1083*4882a593Smuzhiyun }
1084*4882a593Smuzhiyun
1085*4882a593Smuzhiyun CONFIG_TRACE("nvram_path=%s\n", nv_path);
1086*4882a593Smuzhiyun }
1087*4882a593Smuzhiyun
1088*4882a593Smuzhiyun void
dhd_conf_copy_path(dhd_pub_t * dhd,char * dst_name,char * dst_path,char * src_path)1089*4882a593Smuzhiyun dhd_conf_copy_path(dhd_pub_t *dhd, char *dst_name, char *dst_path, char *src_path)
1090*4882a593Smuzhiyun {
1091*4882a593Smuzhiyun int i;
1092*4882a593Smuzhiyun
1093*4882a593Smuzhiyun if (src_path[0] == '\0') {
1094*4882a593Smuzhiyun CONFIG_MSG("src_path is null\n");
1095*4882a593Smuzhiyun return;
1096*4882a593Smuzhiyun } else
1097*4882a593Smuzhiyun strcpy(dst_path, src_path);
1098*4882a593Smuzhiyun
1099*4882a593Smuzhiyun /* find out the last '/' */
1100*4882a593Smuzhiyun i = strlen(dst_path);
1101*4882a593Smuzhiyun while (i > 0) {
1102*4882a593Smuzhiyun if (dst_path[i] == '/') {
1103*4882a593Smuzhiyun i++;
1104*4882a593Smuzhiyun break;
1105*4882a593Smuzhiyun }
1106*4882a593Smuzhiyun i--;
1107*4882a593Smuzhiyun }
1108*4882a593Smuzhiyun strcpy(&dst_path[i], dst_name);
1109*4882a593Smuzhiyun
1110*4882a593Smuzhiyun CONFIG_TRACE("dst_path=%s\n", dst_path);
1111*4882a593Smuzhiyun }
1112*4882a593Smuzhiyun
1113*4882a593Smuzhiyun #ifdef CONFIG_PATH_AUTO_SELECT
1114*4882a593Smuzhiyun void
dhd_conf_set_conf_name_by_chip(dhd_pub_t * dhd,char * conf_path)1115*4882a593Smuzhiyun dhd_conf_set_conf_name_by_chip(dhd_pub_t *dhd, char *conf_path)
1116*4882a593Smuzhiyun {
1117*4882a593Smuzhiyun char *name_ptr, *chip_name = NULL;
1118*4882a593Smuzhiyun bool chip_map_v2;
1119*4882a593Smuzhiyun int i;
1120*4882a593Smuzhiyun
1121*4882a593Smuzhiyun if (conf_path[0] == '\0') {
1122*4882a593Smuzhiyun CONFIG_MSG("config path is null\n");
1123*4882a593Smuzhiyun return;
1124*4882a593Smuzhiyun }
1125*4882a593Smuzhiyun
1126*4882a593Smuzhiyun /* find out the last '/' */
1127*4882a593Smuzhiyun i = strlen(conf_path);
1128*4882a593Smuzhiyun while (i > 0) {
1129*4882a593Smuzhiyun if (conf_path[i] == '/') {
1130*4882a593Smuzhiyun i++;
1131*4882a593Smuzhiyun break;
1132*4882a593Smuzhiyun }
1133*4882a593Smuzhiyun i--;
1134*4882a593Smuzhiyun }
1135*4882a593Smuzhiyun name_ptr = &conf_path[i];
1136*4882a593Smuzhiyun
1137*4882a593Smuzhiyun chip_name = dhd_conf_get_chip_name(dhd, DONT_CARE, &chip_map_v2);
1138*4882a593Smuzhiyun if (chip_name) {
1139*4882a593Smuzhiyun strcpy(name_ptr, "config_");
1140*4882a593Smuzhiyun strcat(name_ptr, chip_name);
1141*4882a593Smuzhiyun strcat(name_ptr, ".txt");
1142*4882a593Smuzhiyun }
1143*4882a593Smuzhiyun
1144*4882a593Smuzhiyun CONFIG_TRACE("config_path=%s\n", conf_path);
1145*4882a593Smuzhiyun }
1146*4882a593Smuzhiyun #endif
1147*4882a593Smuzhiyun
1148*4882a593Smuzhiyun #ifdef TPUT_MONITOR
1149*4882a593Smuzhiyun void
dhd_conf_tput_monitor(dhd_pub_t * dhd)1150*4882a593Smuzhiyun dhd_conf_tput_monitor(dhd_pub_t *dhd)
1151*4882a593Smuzhiyun {
1152*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
1153*4882a593Smuzhiyun
1154*4882a593Smuzhiyun if (conf->tput_monitor_ms && conf->data_drop_mode >= FW_DROP) {
1155*4882a593Smuzhiyun if (conf->tput_ts.tv_sec == 0 && conf->tput_ts.tv_nsec == 0) {
1156*4882a593Smuzhiyun osl_do_gettimeofday(&conf->tput_ts);
1157*4882a593Smuzhiyun } else {
1158*4882a593Smuzhiyun struct osl_timespec cur_ts;
1159*4882a593Smuzhiyun int32 tput_tx = 0, tput_rx = 0, tput_tx_kb = 0,
1160*4882a593Smuzhiyun tput_rx_kb = 0, tput_net = 0, tput_net_kb = 0;
1161*4882a593Smuzhiyun uint32 diff_ms;
1162*4882a593Smuzhiyun unsigned long diff_bytes;
1163*4882a593Smuzhiyun osl_do_gettimeofday(&cur_ts);
1164*4882a593Smuzhiyun diff_ms = osl_do_gettimediff(&cur_ts, &conf->tput_ts)/1000;
1165*4882a593Smuzhiyun if (diff_ms >= conf->tput_monitor_ms) {
1166*4882a593Smuzhiyun diff_bytes = dhd->dstats.tx_bytes - conf->last_tx;
1167*4882a593Smuzhiyun tput_tx = (int32)((diff_bytes/1024/1024)*8)*1000/diff_ms;
1168*4882a593Smuzhiyun if (tput_tx == 0) {
1169*4882a593Smuzhiyun tput_tx = (int32)(diff_bytes*8/1024/1024)*1000/diff_ms;
1170*4882a593Smuzhiyun tput_tx_kb = (int32)(diff_bytes*8*1000/1024)/diff_ms;
1171*4882a593Smuzhiyun tput_tx_kb = tput_tx_kb % 1000;
1172*4882a593Smuzhiyun }
1173*4882a593Smuzhiyun diff_bytes = dhd->dstats.rx_bytes - conf->last_rx;
1174*4882a593Smuzhiyun tput_rx = (int32)((diff_bytes/1024/1024)*8)*1000/diff_ms;
1175*4882a593Smuzhiyun if (tput_rx == 0) {
1176*4882a593Smuzhiyun tput_rx = (int32)(diff_bytes*8/1024/1024)*1000/diff_ms;
1177*4882a593Smuzhiyun tput_rx_kb = (int32)(diff_bytes*8*1000/1024)/diff_ms;
1178*4882a593Smuzhiyun tput_rx_kb = tput_tx_kb % 1000;
1179*4882a593Smuzhiyun }
1180*4882a593Smuzhiyun diff_bytes = conf->net_len - conf->last_net_tx;
1181*4882a593Smuzhiyun tput_net = (int32)((diff_bytes/1024/1024)*8)*1000/diff_ms;
1182*4882a593Smuzhiyun if (tput_net == 0) {
1183*4882a593Smuzhiyun tput_net = (int32)(diff_bytes*8/1024/1024)*1000/diff_ms;
1184*4882a593Smuzhiyun tput_net_kb = (int32)(diff_bytes*8*1000/1024)/diff_ms;
1185*4882a593Smuzhiyun tput_net_kb = tput_net_kb % 1000;
1186*4882a593Smuzhiyun }
1187*4882a593Smuzhiyun conf->last_tx = dhd->dstats.tx_bytes;
1188*4882a593Smuzhiyun conf->last_rx = dhd->dstats.rx_bytes;
1189*4882a593Smuzhiyun conf->last_net_tx = conf->net_len;
1190*4882a593Smuzhiyun memcpy(&conf->tput_ts, &cur_ts, sizeof(struct osl_timespec));
1191*4882a593Smuzhiyun CONFIG_TRACE("xmit=%3d.%d%d%d Mbps, tx=%3d.%d%d%d Mbps, rx=%3d.%d%d%d Mbps\n",
1192*4882a593Smuzhiyun tput_net, (tput_net_kb/100)%10, (tput_net_kb/10)%10, (tput_net_kb)%10,
1193*4882a593Smuzhiyun tput_tx, (tput_tx_kb/100)%10, (tput_tx_kb/10)%10, (tput_tx_kb)%10,
1194*4882a593Smuzhiyun tput_rx, (tput_rx_kb/100)%10, (tput_rx_kb/10)%10, (tput_rx_kb)%10);
1195*4882a593Smuzhiyun }
1196*4882a593Smuzhiyun }
1197*4882a593Smuzhiyun }
1198*4882a593Smuzhiyun }
1199*4882a593Smuzhiyun #endif
1200*4882a593Smuzhiyun
1201*4882a593Smuzhiyun #ifdef DHD_TPUT_PATCH
1202*4882a593Smuzhiyun void
dhd_conf_set_tput_patch(dhd_pub_t * dhd)1203*4882a593Smuzhiyun dhd_conf_set_tput_patch(dhd_pub_t *dhd)
1204*4882a593Smuzhiyun {
1205*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
1206*4882a593Smuzhiyun
1207*4882a593Smuzhiyun if (conf->tput_patch) {
1208*4882a593Smuzhiyun conf->mtu = 1500;
1209*4882a593Smuzhiyun /* set pktsetsum false by default since this will cause to
1210*4882a593Smuzhiyun * the checksum is wrong of downloaded file
1211*4882a593Smuzhiyun */
1212*4882a593Smuzhiyun conf->pktsetsum = FALSE;
1213*4882a593Smuzhiyun #ifdef BCMSDIO
1214*4882a593Smuzhiyun conf->dhd_dpc_prio = 98;
1215*4882a593Smuzhiyun /* need to check if CPU can support multi-core first,
1216*4882a593Smuzhiyun * so don't enable it by default.
1217*4882a593Smuzhiyun */
1218*4882a593Smuzhiyun // conf->dpc_cpucore = 2;
1219*4882a593Smuzhiyun // conf->rxf_cpucore = 3;
1220*4882a593Smuzhiyun // conf->disable_proptx = 1;
1221*4882a593Smuzhiyun conf->frameburst = 1;
1222*4882a593Smuzhiyun #ifdef DYNAMIC_MAX_HDR_READ
1223*4882a593Smuzhiyun conf->max_hdr_read = 256;
1224*4882a593Smuzhiyun firstread = 256;
1225*4882a593Smuzhiyun #endif /* DYNAMIC_MAX_HDR_READ */
1226*4882a593Smuzhiyun dhd_rxbound = 512;
1227*4882a593Smuzhiyun #endif /* BCMSDIO */
1228*4882a593Smuzhiyun #ifdef BCMPCIE
1229*4882a593Smuzhiyun #if defined(SET_XPS_CPUS)
1230*4882a593Smuzhiyun conf->xps_cpus = TRUE;
1231*4882a593Smuzhiyun #endif /* SET_XPS_CPUS */
1232*4882a593Smuzhiyun #if defined(SET_RPS_CPUS)
1233*4882a593Smuzhiyun conf->rps_cpus = TRUE;
1234*4882a593Smuzhiyun #endif /* SET_RPS_CPUS */
1235*4882a593Smuzhiyun conf->orphan_move = 3;
1236*4882a593Smuzhiyun conf->flow_ring_queue_threshold = 2048;
1237*4882a593Smuzhiyun #endif /* BCMPCIE */
1238*4882a593Smuzhiyun #ifdef DHDTCPACK_SUPPRESS
1239*4882a593Smuzhiyun conf->tcpack_sup_ratio = 15;
1240*4882a593Smuzhiyun conf->tcpack_sup_delay = 10;
1241*4882a593Smuzhiyun #endif /* DHDTCPACK_SUPPRESS */
1242*4882a593Smuzhiyun }
1243*4882a593Smuzhiyun else {
1244*4882a593Smuzhiyun conf->mtu = 0;
1245*4882a593Smuzhiyun conf->pktsetsum = FALSE;
1246*4882a593Smuzhiyun #ifdef BCMSDIO
1247*4882a593Smuzhiyun conf->dhd_dpc_prio = -1;
1248*4882a593Smuzhiyun conf->disable_proptx = -1;
1249*4882a593Smuzhiyun conf->frameburst = 1;
1250*4882a593Smuzhiyun #ifdef DYNAMIC_MAX_HDR_READ
1251*4882a593Smuzhiyun conf->max_hdr_read = 0;
1252*4882a593Smuzhiyun firstread = 32;
1253*4882a593Smuzhiyun #endif /* DYNAMIC_MAX_HDR_READ */
1254*4882a593Smuzhiyun dhd_rxbound = 128;
1255*4882a593Smuzhiyun #endif /* BCMSDIO */
1256*4882a593Smuzhiyun #ifdef BCMPCIE
1257*4882a593Smuzhiyun #if defined(SET_XPS_CPUS)
1258*4882a593Smuzhiyun conf->xps_cpus = FALSE;
1259*4882a593Smuzhiyun #endif /* SET_XPS_CPUS */
1260*4882a593Smuzhiyun #if defined(SET_RPS_CPUS)
1261*4882a593Smuzhiyun conf->rps_cpus = FALSE;
1262*4882a593Smuzhiyun #endif /* SET_RPS_CPUS */
1263*4882a593Smuzhiyun #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
1264*4882a593Smuzhiyun conf->orphan_move = 1;
1265*4882a593Smuzhiyun #else
1266*4882a593Smuzhiyun conf->orphan_move = 0;
1267*4882a593Smuzhiyun #endif
1268*4882a593Smuzhiyun conf->flow_ring_queue_threshold = 2048;
1269*4882a593Smuzhiyun #endif /* BCMPCIE */
1270*4882a593Smuzhiyun #ifdef DHDTCPACK_SUPPRESS
1271*4882a593Smuzhiyun conf->tcpack_sup_ratio = CUSTOM_TCPACK_SUPP_RATIO;
1272*4882a593Smuzhiyun conf->tcpack_sup_delay = CUSTOM_TCPACK_DELAY_TIME;
1273*4882a593Smuzhiyun #endif /* DHDTCPACK_SUPPRESS */
1274*4882a593Smuzhiyun }
1275*4882a593Smuzhiyun }
1276*4882a593Smuzhiyun
1277*4882a593Smuzhiyun void
dhd_conf_dump_tput_patch(dhd_pub_t * dhd)1278*4882a593Smuzhiyun dhd_conf_dump_tput_patch(dhd_pub_t *dhd)
1279*4882a593Smuzhiyun {
1280*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
1281*4882a593Smuzhiyun
1282*4882a593Smuzhiyun CONFIG_TRACE("tput_patch=%d\n", conf->tput_patch);
1283*4882a593Smuzhiyun CONFIG_TRACE("mtu=%d\n", conf->mtu);
1284*4882a593Smuzhiyun CONFIG_TRACE("pktsetsum=%d\n", conf->pktsetsum);
1285*4882a593Smuzhiyun CONFIG_TRACE("orphan_move=%d\n", conf->orphan_move);
1286*4882a593Smuzhiyun #ifdef DHDTCPACK_SUPPRESS
1287*4882a593Smuzhiyun CONFIG_TRACE("tcpack_sup_ratio=%d\n", conf->tcpack_sup_ratio);
1288*4882a593Smuzhiyun CONFIG_TRACE("tcpack_sup_delay=%d\n", conf->tcpack_sup_delay);
1289*4882a593Smuzhiyun #endif
1290*4882a593Smuzhiyun
1291*4882a593Smuzhiyun #ifdef BCMSDIO
1292*4882a593Smuzhiyun CONFIG_TRACE("dhd_dpc_prio=%d\n", conf->dhd_dpc_prio);
1293*4882a593Smuzhiyun CONFIG_TRACE("dhd_poll=%d\n", conf->dhd_poll);
1294*4882a593Smuzhiyun CONFIG_TRACE("disable_proptx=%d\n", conf->disable_proptx);
1295*4882a593Smuzhiyun CONFIG_TRACE("frameburst=%d\n", conf->frameburst);
1296*4882a593Smuzhiyun #ifdef DYNAMIC_MAX_HDR_READ
1297*4882a593Smuzhiyun CONFIG_TRACE("max_hdr_read=%d\n", conf->max_hdr_read);
1298*4882a593Smuzhiyun CONFIG_TRACE("firstread=%d\n", firstread);
1299*4882a593Smuzhiyun #endif
1300*4882a593Smuzhiyun CONFIG_TRACE("dhd_rxbound=%d\n", dhd_rxbound);
1301*4882a593Smuzhiyun #endif
1302*4882a593Smuzhiyun
1303*4882a593Smuzhiyun #ifdef BCMPCIE
1304*4882a593Smuzhiyun CONFIG_TRACE("flow_ring_queue_threshold=%d\n", conf->flow_ring_queue_threshold);
1305*4882a593Smuzhiyun #endif
1306*4882a593Smuzhiyun
1307*4882a593Smuzhiyun #if defined(SET_XPS_CPUS)
1308*4882a593Smuzhiyun CONFIG_TRACE("xps_cpus=%d\n", conf->xps_cpus);
1309*4882a593Smuzhiyun #endif
1310*4882a593Smuzhiyun #if defined(SET_RPS_CPUS)
1311*4882a593Smuzhiyun CONFIG_TRACE("rps_cpus=%d\n", conf->rps_cpus);
1312*4882a593Smuzhiyun #endif
1313*4882a593Smuzhiyun
1314*4882a593Smuzhiyun }
1315*4882a593Smuzhiyun #endif /* DHD_TPUT_PATCH */
1316*4882a593Smuzhiyun
1317*4882a593Smuzhiyun #ifdef DHD_LINUX_STD_FW_API
1318*4882a593Smuzhiyun #define FIRMWARE_CLASS_PATH "/sys/module/firmware_class/parameters/path"
1319*4882a593Smuzhiyun static void
dhd_conf_get_filename(char * pFilename)1320*4882a593Smuzhiyun dhd_conf_get_filename(char *pFilename)
1321*4882a593Smuzhiyun {
1322*4882a593Smuzhiyun const char *pName = NULL;
1323*4882a593Smuzhiyun
1324*4882a593Smuzhiyun if ((pFilename) && (*pFilename)) {
1325*4882a593Smuzhiyun // back/reverse search the '/'
1326*4882a593Smuzhiyun pName = strrchr(pFilename, '/');
1327*4882a593Smuzhiyun if (NULL == pName) {
1328*4882a593Smuzhiyun pName = pFilename;
1329*4882a593Smuzhiyun } else {
1330*4882a593Smuzhiyun if (pName[1]) {
1331*4882a593Smuzhiyun pName++;
1332*4882a593Smuzhiyun } else {
1333*4882a593Smuzhiyun pName = NULL;
1334*4882a593Smuzhiyun }
1335*4882a593Smuzhiyun }
1336*4882a593Smuzhiyun }
1337*4882a593Smuzhiyun
1338*4882a593Smuzhiyun if (pName)
1339*4882a593Smuzhiyun strcpy(pFilename, pName);
1340*4882a593Smuzhiyun
1341*4882a593Smuzhiyun return;
1342*4882a593Smuzhiyun }
1343*4882a593Smuzhiyun
1344*4882a593Smuzhiyun static void
dhd_conf_add_filepath(dhd_pub_t * dhd,char * pFilename)1345*4882a593Smuzhiyun dhd_conf_add_filepath(dhd_pub_t *dhd, char *pFilename)
1346*4882a593Smuzhiyun {
1347*4882a593Smuzhiyun char path[WLC_IOCTL_SMLEN];
1348*4882a593Smuzhiyun char *name_ptr, *module_name = NULL;
1349*4882a593Smuzhiyun
1350*4882a593Smuzhiyun if (strlen(pFilename)) {
1351*4882a593Smuzhiyun name_ptr = path;
1352*4882a593Smuzhiyun strcpy(name_ptr, "");
1353*4882a593Smuzhiyun #ifdef FW_AMPAK_PATH
1354*4882a593Smuzhiyun strcat(name_ptr, "/");
1355*4882a593Smuzhiyun strcat(name_ptr, FW_AMPAK_PATH);
1356*4882a593Smuzhiyun #endif
1357*4882a593Smuzhiyun #ifdef MODULE_PATH
1358*4882a593Smuzhiyun #if defined(BCMSDIO) && defined(GET_OTP_MODULE_NAME)
1359*4882a593Smuzhiyun if (strlen(dhd->conf->module_name))
1360*4882a593Smuzhiyun module_name = dhd->conf->module_name;
1361*4882a593Smuzhiyun else
1362*4882a593Smuzhiyun #endif
1363*4882a593Smuzhiyun {
1364*4882a593Smuzhiyun module_name = dhd_conf_get_module_name(dhd, DONT_CARE);
1365*4882a593Smuzhiyun }
1366*4882a593Smuzhiyun #endif
1367*4882a593Smuzhiyun if (module_name) {
1368*4882a593Smuzhiyun strcat(name_ptr, "/");
1369*4882a593Smuzhiyun strcat(name_ptr, module_name);
1370*4882a593Smuzhiyun }
1371*4882a593Smuzhiyun strcat(name_ptr, "/");
1372*4882a593Smuzhiyun strcat(name_ptr, pFilename);
1373*4882a593Smuzhiyun strcpy(pFilename, path);
1374*4882a593Smuzhiyun }
1375*4882a593Smuzhiyun
1376*4882a593Smuzhiyun return;
1377*4882a593Smuzhiyun }
1378*4882a593Smuzhiyun #endif /* DHD_LINUX_STD_FW_API */
1379*4882a593Smuzhiyun
1380*4882a593Smuzhiyun void
dhd_conf_set_path_params(dhd_pub_t * dhd,char * fw_path,char * nv_path)1381*4882a593Smuzhiyun dhd_conf_set_path_params(dhd_pub_t *dhd, char *fw_path, char *nv_path)
1382*4882a593Smuzhiyun {
1383*4882a593Smuzhiyun int ag_type;
1384*4882a593Smuzhiyun
1385*4882a593Smuzhiyun /* External conf takes precedence if specified */
1386*4882a593Smuzhiyun dhd_conf_preinit(dhd);
1387*4882a593Smuzhiyun
1388*4882a593Smuzhiyun #ifdef DHD_LINUX_STD_FW_API
1389*4882a593Smuzhiyun // preprocess the filename to only left 'name'
1390*4882a593Smuzhiyun dhd_conf_get_filename(fw_path);
1391*4882a593Smuzhiyun dhd_conf_get_filename(nv_path);
1392*4882a593Smuzhiyun dhd_conf_get_filename(dhd->clm_path);
1393*4882a593Smuzhiyun dhd_conf_get_filename(dhd->conf_path);
1394*4882a593Smuzhiyun #endif
1395*4882a593Smuzhiyun
1396*4882a593Smuzhiyun if (dhd->conf_path[0] == '\0') {
1397*4882a593Smuzhiyun dhd_conf_copy_path(dhd, "config.txt", dhd->conf_path, nv_path);
1398*4882a593Smuzhiyun }
1399*4882a593Smuzhiyun if (dhd->clm_path[0] == '\0') {
1400*4882a593Smuzhiyun dhd_conf_copy_path(dhd, "clm.blob", dhd->clm_path, fw_path);
1401*4882a593Smuzhiyun }
1402*4882a593Smuzhiyun #ifdef CONFIG_PATH_AUTO_SELECT
1403*4882a593Smuzhiyun dhd_conf_set_conf_name_by_chip(dhd, dhd->conf_path);
1404*4882a593Smuzhiyun #endif
1405*4882a593Smuzhiyun
1406*4882a593Smuzhiyun ag_type = dhd_conf_set_fw_name_by_chip(dhd, fw_path);
1407*4882a593Smuzhiyun dhd_conf_set_nv_name_by_chip(dhd, nv_path, ag_type);
1408*4882a593Smuzhiyun dhd_conf_set_clm_name_by_chip(dhd, dhd->clm_path, ag_type);
1409*4882a593Smuzhiyun #ifdef SET_FWNV_BY_MAC
1410*4882a593Smuzhiyun dhd_conf_set_fw_name_by_mac(dhd, fw_path);
1411*4882a593Smuzhiyun dhd_conf_set_nv_name_by_mac(dhd, nv_path);
1412*4882a593Smuzhiyun #endif
1413*4882a593Smuzhiyun
1414*4882a593Smuzhiyun #ifdef DHD_LINUX_STD_FW_API
1415*4882a593Smuzhiyun dhd_conf_add_filepath(dhd, fw_path);
1416*4882a593Smuzhiyun dhd_conf_add_filepath(dhd, nv_path);
1417*4882a593Smuzhiyun dhd_conf_add_filepath(dhd, dhd->clm_path);
1418*4882a593Smuzhiyun dhd_conf_add_filepath(dhd, dhd->conf_path);
1419*4882a593Smuzhiyun #endif
1420*4882a593Smuzhiyun
1421*4882a593Smuzhiyun CONFIG_MSG("Final fw_path=%s\n", fw_path);
1422*4882a593Smuzhiyun CONFIG_MSG("Final nv_path=%s\n", nv_path);
1423*4882a593Smuzhiyun CONFIG_MSG("Final clm_path=%s\n", dhd->clm_path);
1424*4882a593Smuzhiyun CONFIG_MSG("Final conf_path=%s\n", dhd->conf_path);
1425*4882a593Smuzhiyun
1426*4882a593Smuzhiyun dhd_conf_read_config(dhd, dhd->conf_path);
1427*4882a593Smuzhiyun #ifdef DHD_TPUT_PATCH
1428*4882a593Smuzhiyun dhd_conf_dump_tput_patch(dhd);
1429*4882a593Smuzhiyun #endif
1430*4882a593Smuzhiyun }
1431*4882a593Smuzhiyun
1432*4882a593Smuzhiyun int
dhd_conf_set_intiovar(dhd_pub_t * dhd,int ifidx,uint cmd,char * name,int val,int def,bool down)1433*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd_pub_t *dhd, int ifidx, uint cmd, char *name, int val,
1434*4882a593Smuzhiyun int def, bool down)
1435*4882a593Smuzhiyun {
1436*4882a593Smuzhiyun int ret = -1;
1437*4882a593Smuzhiyun char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */
1438*4882a593Smuzhiyun
1439*4882a593Smuzhiyun if (val >= def) {
1440*4882a593Smuzhiyun if (down) {
1441*4882a593Smuzhiyun if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, ifidx)) < 0)
1442*4882a593Smuzhiyun CONFIG_ERROR("WLC_DOWN setting failed %d\n", ret);
1443*4882a593Smuzhiyun }
1444*4882a593Smuzhiyun if (cmd == WLC_SET_VAR) {
1445*4882a593Smuzhiyun CONFIG_TRACE("set %s %d\n", name, val);
1446*4882a593Smuzhiyun bcm_mkiovar(name, (char *)&val, sizeof(val), iovbuf, sizeof(iovbuf));
1447*4882a593Smuzhiyun if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, ifidx)) < 0)
1448*4882a593Smuzhiyun CONFIG_ERROR("%s setting failed %d\n", name, ret);
1449*4882a593Smuzhiyun } else {
1450*4882a593Smuzhiyun CONFIG_TRACE("set %s %d %d\n", name, cmd, val);
1451*4882a593Smuzhiyun if ((ret = dhd_wl_ioctl_cmd(dhd, cmd, &val, sizeof(val), TRUE, ifidx)) < 0)
1452*4882a593Smuzhiyun CONFIG_ERROR("%s setting failed %d\n", name, ret);
1453*4882a593Smuzhiyun }
1454*4882a593Smuzhiyun }
1455*4882a593Smuzhiyun
1456*4882a593Smuzhiyun return ret;
1457*4882a593Smuzhiyun }
1458*4882a593Smuzhiyun
1459*4882a593Smuzhiyun static int
dhd_conf_set_bufiovar(dhd_pub_t * dhd,int ifidx,uint cmd,char * name,char * buf,int len,bool down)1460*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd_pub_t *dhd, int ifidx, uint cmd, char *name,
1461*4882a593Smuzhiyun char *buf, int len, bool down)
1462*4882a593Smuzhiyun {
1463*4882a593Smuzhiyun char iovbuf[WLC_IOCTL_SMLEN];
1464*4882a593Smuzhiyun s32 iovar_len;
1465*4882a593Smuzhiyun int ret = -1;
1466*4882a593Smuzhiyun
1467*4882a593Smuzhiyun if (down) {
1468*4882a593Smuzhiyun if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, ifidx)) < 0)
1469*4882a593Smuzhiyun CONFIG_ERROR("WLC_DOWN setting failed %d\n", ret);
1470*4882a593Smuzhiyun }
1471*4882a593Smuzhiyun
1472*4882a593Smuzhiyun if (cmd == WLC_SET_VAR) {
1473*4882a593Smuzhiyun iovar_len = bcm_mkiovar(name, buf, len, iovbuf, sizeof(iovbuf));
1474*4882a593Smuzhiyun if (iovar_len > 0)
1475*4882a593Smuzhiyun ret = dhd_wl_ioctl_cmd(dhd, cmd, iovbuf, iovar_len, TRUE, ifidx);
1476*4882a593Smuzhiyun else
1477*4882a593Smuzhiyun ret = BCME_BUFTOOSHORT;
1478*4882a593Smuzhiyun if (ret < 0)
1479*4882a593Smuzhiyun CONFIG_ERROR("%s setting failed %d, len=%d\n", name, ret, len);
1480*4882a593Smuzhiyun } else {
1481*4882a593Smuzhiyun if ((ret = dhd_wl_ioctl_cmd(dhd, cmd, buf, len, TRUE, ifidx)) < 0)
1482*4882a593Smuzhiyun CONFIG_ERROR("%s setting failed %d\n", name, ret);
1483*4882a593Smuzhiyun }
1484*4882a593Smuzhiyun
1485*4882a593Smuzhiyun return ret;
1486*4882a593Smuzhiyun }
1487*4882a593Smuzhiyun
1488*4882a593Smuzhiyun static int
dhd_conf_iovar_buf(dhd_pub_t * dhd,int ifidx,int cmd,char * name,char * buf,int len)1489*4882a593Smuzhiyun dhd_conf_iovar_buf(dhd_pub_t *dhd, int ifidx, int cmd, char *name,
1490*4882a593Smuzhiyun char *buf, int len)
1491*4882a593Smuzhiyun {
1492*4882a593Smuzhiyun char *iovbuf = NULL;
1493*4882a593Smuzhiyun int ret = -1, iovbuf_len = WLC_IOCTL_MEDLEN;
1494*4882a593Smuzhiyun s32 iovar_len;
1495*4882a593Smuzhiyun
1496*4882a593Smuzhiyun iovbuf = kmalloc(iovbuf_len, GFP_KERNEL);
1497*4882a593Smuzhiyun if (iovbuf == NULL) {
1498*4882a593Smuzhiyun CONFIG_ERROR("Failed to allocate buffer of %d bytes\n", iovbuf_len);
1499*4882a593Smuzhiyun goto exit;
1500*4882a593Smuzhiyun }
1501*4882a593Smuzhiyun
1502*4882a593Smuzhiyun if (cmd == WLC_GET_VAR) {
1503*4882a593Smuzhiyun if (bcm_mkiovar(name, buf, len, iovbuf, iovbuf_len)) {
1504*4882a593Smuzhiyun ret = dhd_wl_ioctl_cmd(dhd, cmd, iovbuf, iovbuf_len, FALSE, ifidx);
1505*4882a593Smuzhiyun if (!ret) {
1506*4882a593Smuzhiyun memcpy(buf, iovbuf, len);
1507*4882a593Smuzhiyun } else {
1508*4882a593Smuzhiyun CONFIG_ERROR("get iovar %s failed %d\n", name, ret);
1509*4882a593Smuzhiyun }
1510*4882a593Smuzhiyun } else {
1511*4882a593Smuzhiyun CONFIG_ERROR("mkiovar %s failed\n", name);
1512*4882a593Smuzhiyun }
1513*4882a593Smuzhiyun } else if (cmd == WLC_SET_VAR) {
1514*4882a593Smuzhiyun iovar_len = bcm_mkiovar(name, buf, len, iovbuf, iovbuf_len);
1515*4882a593Smuzhiyun if (iovar_len > 0)
1516*4882a593Smuzhiyun ret = dhd_wl_ioctl_cmd(dhd, cmd, iovbuf, iovar_len, TRUE, ifidx);
1517*4882a593Smuzhiyun else
1518*4882a593Smuzhiyun ret = BCME_BUFTOOSHORT;
1519*4882a593Smuzhiyun if (ret < 0)
1520*4882a593Smuzhiyun CONFIG_ERROR("%s setting failed %d, len=%d\n", name, ret, len);
1521*4882a593Smuzhiyun }
1522*4882a593Smuzhiyun
1523*4882a593Smuzhiyun exit:
1524*4882a593Smuzhiyun if (iovbuf)
1525*4882a593Smuzhiyun kfree(iovbuf);
1526*4882a593Smuzhiyun return ret;
1527*4882a593Smuzhiyun }
1528*4882a593Smuzhiyun
1529*4882a593Smuzhiyun static int
dhd_conf_get_iovar(dhd_pub_t * dhd,int ifidx,int cmd,char * name,char * buf,int len)1530*4882a593Smuzhiyun dhd_conf_get_iovar(dhd_pub_t *dhd, int ifidx, int cmd, char *name,
1531*4882a593Smuzhiyun char *buf, int len)
1532*4882a593Smuzhiyun {
1533*4882a593Smuzhiyun char iovbuf[WLC_IOCTL_SMLEN];
1534*4882a593Smuzhiyun int ret = -1;
1535*4882a593Smuzhiyun
1536*4882a593Smuzhiyun if (cmd == WLC_GET_VAR) {
1537*4882a593Smuzhiyun if (bcm_mkiovar(name, NULL, 0, iovbuf, sizeof(iovbuf))) {
1538*4882a593Smuzhiyun ret = dhd_wl_ioctl_cmd(dhd, cmd, iovbuf, sizeof(iovbuf), FALSE, ifidx);
1539*4882a593Smuzhiyun if (!ret) {
1540*4882a593Smuzhiyun memcpy(buf, iovbuf, len);
1541*4882a593Smuzhiyun } else {
1542*4882a593Smuzhiyun CONFIG_ERROR("get iovar %s failed %d\n", name, ret);
1543*4882a593Smuzhiyun }
1544*4882a593Smuzhiyun } else {
1545*4882a593Smuzhiyun CONFIG_ERROR("mkiovar %s failed\n", name);
1546*4882a593Smuzhiyun }
1547*4882a593Smuzhiyun } else {
1548*4882a593Smuzhiyun ret = dhd_wl_ioctl_cmd(dhd, cmd, buf, len, FALSE, 0);
1549*4882a593Smuzhiyun if (ret < 0)
1550*4882a593Smuzhiyun CONFIG_ERROR("get iovar %s failed %d\n", name, ret);
1551*4882a593Smuzhiyun }
1552*4882a593Smuzhiyun
1553*4882a593Smuzhiyun return ret;
1554*4882a593Smuzhiyun }
1555*4882a593Smuzhiyun
1556*4882a593Smuzhiyun static int
dhd_conf_get_ioctl_ver(dhd_pub_t * dhd)1557*4882a593Smuzhiyun dhd_conf_get_ioctl_ver(dhd_pub_t *dhd)
1558*4882a593Smuzhiyun {
1559*4882a593Smuzhiyun int ret = 0;
1560*4882a593Smuzhiyun s32 val = 0;
1561*4882a593Smuzhiyun
1562*4882a593Smuzhiyun dhd->conf->ioctl_ver = WLC_IOCTL_VERSION;
1563*4882a593Smuzhiyun ret = dhd_conf_get_iovar(dhd, 0, WLC_GET_VERSION, "WLC_GET_VERSION",
1564*4882a593Smuzhiyun (char *)&val, sizeof(val));
1565*4882a593Smuzhiyun if (ret) {
1566*4882a593Smuzhiyun return ret;
1567*4882a593Smuzhiyun }
1568*4882a593Smuzhiyun val = dtoh32(val);
1569*4882a593Smuzhiyun if (val != WLC_IOCTL_VERSION && val != 1) {
1570*4882a593Smuzhiyun CONFIG_ERROR("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
1571*4882a593Smuzhiyun val, WLC_IOCTL_VERSION);
1572*4882a593Smuzhiyun return BCME_VERSION;
1573*4882a593Smuzhiyun }
1574*4882a593Smuzhiyun dhd->conf->ioctl_ver = val;
1575*4882a593Smuzhiyun CONFIG_TRACE("ioctl_ver=%d\n", dhd->conf->ioctl_ver);
1576*4882a593Smuzhiyun
1577*4882a593Smuzhiyun return ret;
1578*4882a593Smuzhiyun }
1579*4882a593Smuzhiyun
1580*4882a593Smuzhiyun int
dhd_conf_get_country(dhd_pub_t * dhd,wl_country_t * cspec)1581*4882a593Smuzhiyun dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec)
1582*4882a593Smuzhiyun {
1583*4882a593Smuzhiyun int bcmerror = -1;
1584*4882a593Smuzhiyun
1585*4882a593Smuzhiyun memset(cspec, 0, sizeof(wl_country_t));
1586*4882a593Smuzhiyun bcm_mkiovar("country", NULL, 0, (char*)cspec, sizeof(wl_country_t));
1587*4882a593Smuzhiyun if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cspec, sizeof(wl_country_t),
1588*4882a593Smuzhiyun FALSE, 0)) < 0)
1589*4882a593Smuzhiyun CONFIG_ERROR("country code getting failed %d\n", bcmerror);
1590*4882a593Smuzhiyun
1591*4882a593Smuzhiyun return bcmerror;
1592*4882a593Smuzhiyun }
1593*4882a593Smuzhiyun
1594*4882a593Smuzhiyun int
dhd_conf_map_country_list(dhd_pub_t * dhd,wl_country_t * cspec)1595*4882a593Smuzhiyun dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec)
1596*4882a593Smuzhiyun {
1597*4882a593Smuzhiyun int bcmerror = -1;
1598*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
1599*4882a593Smuzhiyun country_list_t *country = conf->country_head;
1600*4882a593Smuzhiyun
1601*4882a593Smuzhiyun #ifdef CCODE_LIST
1602*4882a593Smuzhiyun bcmerror = dhd_ccode_map_country_list(dhd, cspec);
1603*4882a593Smuzhiyun #endif
1604*4882a593Smuzhiyun // **:XZ/11 => return XZ/11 if not found
1605*4882a593Smuzhiyun // **:**/0 => return user specified ccode if not found, but set regrev 0
1606*4882a593Smuzhiyun while (country != NULL) {
1607*4882a593Smuzhiyun if (!strncmp("**", country->cspec.country_abbrev, 2)) {
1608*4882a593Smuzhiyun if (!strncmp("**", country->cspec.ccode, 2)) {
1609*4882a593Smuzhiyun cspec->rev = 0;
1610*4882a593Smuzhiyun bcmerror = 0;
1611*4882a593Smuzhiyun break;
1612*4882a593Smuzhiyun }
1613*4882a593Smuzhiyun memcpy(cspec->ccode, country->cspec.ccode, WLC_CNTRY_BUF_SZ);
1614*4882a593Smuzhiyun cspec->rev = country->cspec.rev;
1615*4882a593Smuzhiyun bcmerror = 0;
1616*4882a593Smuzhiyun break;
1617*4882a593Smuzhiyun } else if (!strncmp(cspec->country_abbrev,
1618*4882a593Smuzhiyun country->cspec.country_abbrev, 2)) {
1619*4882a593Smuzhiyun memcpy(cspec->ccode, country->cspec.ccode, WLC_CNTRY_BUF_SZ);
1620*4882a593Smuzhiyun cspec->rev = country->cspec.rev;
1621*4882a593Smuzhiyun bcmerror = 0;
1622*4882a593Smuzhiyun break;
1623*4882a593Smuzhiyun }
1624*4882a593Smuzhiyun country = country->next;
1625*4882a593Smuzhiyun }
1626*4882a593Smuzhiyun
1627*4882a593Smuzhiyun if (!bcmerror)
1628*4882a593Smuzhiyun CONFIG_MSG("%s/%d\n", cspec->ccode, cspec->rev);
1629*4882a593Smuzhiyun
1630*4882a593Smuzhiyun return bcmerror;
1631*4882a593Smuzhiyun }
1632*4882a593Smuzhiyun
1633*4882a593Smuzhiyun int
dhd_conf_set_country(dhd_pub_t * dhd,wl_country_t * cspec)1634*4882a593Smuzhiyun dhd_conf_set_country(dhd_pub_t *dhd, wl_country_t *cspec)
1635*4882a593Smuzhiyun {
1636*4882a593Smuzhiyun int bcmerror = -1;
1637*4882a593Smuzhiyun
1638*4882a593Smuzhiyun memset(&dhd->dhd_cspec, 0, sizeof(wl_country_t));
1639*4882a593Smuzhiyun
1640*4882a593Smuzhiyun CONFIG_MSG("set country %s, revision %d\n", cspec->ccode, cspec->rev);
1641*4882a593Smuzhiyun bcmerror = dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "country", (char *)cspec,
1642*4882a593Smuzhiyun sizeof(wl_country_t), FALSE);
1643*4882a593Smuzhiyun dhd_conf_get_country(dhd, cspec);
1644*4882a593Smuzhiyun CONFIG_MSG("Country code: %s (%s/%d)\n",
1645*4882a593Smuzhiyun cspec->country_abbrev, cspec->ccode, cspec->rev);
1646*4882a593Smuzhiyun
1647*4882a593Smuzhiyun return bcmerror;
1648*4882a593Smuzhiyun }
1649*4882a593Smuzhiyun
1650*4882a593Smuzhiyun int
dhd_conf_fix_country(dhd_pub_t * dhd)1651*4882a593Smuzhiyun dhd_conf_fix_country(dhd_pub_t *dhd)
1652*4882a593Smuzhiyun {
1653*4882a593Smuzhiyun int bcmerror = -1;
1654*4882a593Smuzhiyun int band;
1655*4882a593Smuzhiyun wl_uint32_list_t *list;
1656*4882a593Smuzhiyun u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)];
1657*4882a593Smuzhiyun wl_country_t cspec;
1658*4882a593Smuzhiyun
1659*4882a593Smuzhiyun if (!(dhd && dhd->conf)) {
1660*4882a593Smuzhiyun return bcmerror;
1661*4882a593Smuzhiyun }
1662*4882a593Smuzhiyun
1663*4882a593Smuzhiyun memset(valid_chan_list, 0, sizeof(valid_chan_list));
1664*4882a593Smuzhiyun list = (wl_uint32_list_t *)(void *) valid_chan_list;
1665*4882a593Smuzhiyun list->count = htod32(WL_NUMCHANNELS);
1666*4882a593Smuzhiyun if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VALID_CHANNELS, valid_chan_list,
1667*4882a593Smuzhiyun sizeof(valid_chan_list), FALSE, 0)) < 0) {
1668*4882a593Smuzhiyun CONFIG_ERROR("get channels failed with %d\n", bcmerror);
1669*4882a593Smuzhiyun }
1670*4882a593Smuzhiyun
1671*4882a593Smuzhiyun band = dhd_conf_get_band(dhd);
1672*4882a593Smuzhiyun
1673*4882a593Smuzhiyun if (bcmerror || ((band==WLC_BAND_AUTO || band==WLC_BAND_2G || band==-1) &&
1674*4882a593Smuzhiyun dtoh32(list->count)<11)) {
1675*4882a593Smuzhiyun CONFIG_ERROR("bcmerror=%d, # of channels %d\n",
1676*4882a593Smuzhiyun bcmerror, dtoh32(list->count));
1677*4882a593Smuzhiyun dhd_conf_map_country_list(dhd, &dhd->conf->cspec);
1678*4882a593Smuzhiyun if ((bcmerror = dhd_conf_set_country(dhd, &dhd->conf->cspec)) < 0) {
1679*4882a593Smuzhiyun strcpy(cspec.country_abbrev, "US");
1680*4882a593Smuzhiyun cspec.rev = 0;
1681*4882a593Smuzhiyun strcpy(cspec.ccode, "US");
1682*4882a593Smuzhiyun dhd_conf_map_country_list(dhd, &cspec);
1683*4882a593Smuzhiyun dhd_conf_set_country(dhd, &cspec);
1684*4882a593Smuzhiyun }
1685*4882a593Smuzhiyun }
1686*4882a593Smuzhiyun
1687*4882a593Smuzhiyun return bcmerror;
1688*4882a593Smuzhiyun }
1689*4882a593Smuzhiyun
1690*4882a593Smuzhiyun static int
dhd_conf_rsdb_mode(dhd_pub_t * dhd,char * cmd,char * buf)1691*4882a593Smuzhiyun dhd_conf_rsdb_mode(dhd_pub_t *dhd, char *cmd, char *buf)
1692*4882a593Smuzhiyun {
1693*4882a593Smuzhiyun wl_config_t rsdb_mode_cfg = {1, 0};
1694*4882a593Smuzhiyun
1695*4882a593Smuzhiyun if (buf) {
1696*4882a593Smuzhiyun rsdb_mode_cfg.config = (int)simple_strtol(buf, NULL, 0);
1697*4882a593Smuzhiyun CONFIG_MSG("rsdb_mode %d\n", rsdb_mode_cfg.config);
1698*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, cmd, (char *)&rsdb_mode_cfg,
1699*4882a593Smuzhiyun sizeof(rsdb_mode_cfg), TRUE);
1700*4882a593Smuzhiyun }
1701*4882a593Smuzhiyun
1702*4882a593Smuzhiyun return 0;
1703*4882a593Smuzhiyun }
1704*4882a593Smuzhiyun
1705*4882a593Smuzhiyun int
dhd_conf_reg2args(dhd_pub_t * dhd,char * cmd,bool set,uint32 index,uint32 * val)1706*4882a593Smuzhiyun dhd_conf_reg2args(dhd_pub_t *dhd, char *cmd, bool set, uint32 index, uint32 *val)
1707*4882a593Smuzhiyun {
1708*4882a593Smuzhiyun char var[WLC_IOCTL_SMLEN];
1709*4882a593Smuzhiyun uint32 int_val, len;
1710*4882a593Smuzhiyun void *ptr = NULL;
1711*4882a593Smuzhiyun int ret = 0;
1712*4882a593Smuzhiyun
1713*4882a593Smuzhiyun len = sizeof(int_val);
1714*4882a593Smuzhiyun int_val = htod32(index);
1715*4882a593Smuzhiyun memset(var, 0, sizeof(var));
1716*4882a593Smuzhiyun memcpy(var, (char *)&int_val, sizeof(int_val));
1717*4882a593Smuzhiyun
1718*4882a593Smuzhiyun if (set) {
1719*4882a593Smuzhiyun int_val = htod32(*val);
1720*4882a593Smuzhiyun memcpy(&var[len], (char *)&int_val, sizeof(int_val));
1721*4882a593Smuzhiyun len += sizeof(int_val);
1722*4882a593Smuzhiyun dhd_conf_iovar_buf(dhd, 0, WLC_SET_VAR, cmd, var, sizeof(var));
1723*4882a593Smuzhiyun } else {
1724*4882a593Smuzhiyun ret = dhd_conf_iovar_buf(dhd, 0, WLC_GET_VAR, cmd, var, sizeof(var));
1725*4882a593Smuzhiyun if (ret < 0)
1726*4882a593Smuzhiyun return ret;
1727*4882a593Smuzhiyun ptr = var;
1728*4882a593Smuzhiyun *val = dtoh32(*(int *)ptr);
1729*4882a593Smuzhiyun }
1730*4882a593Smuzhiyun
1731*4882a593Smuzhiyun return ret;
1732*4882a593Smuzhiyun }
1733*4882a593Smuzhiyun
1734*4882a593Smuzhiyun static int
dhd_conf_btc_params(dhd_pub_t * dhd,char * cmd,char * buf)1735*4882a593Smuzhiyun dhd_conf_btc_params(dhd_pub_t *dhd, char *cmd, char *buf)
1736*4882a593Smuzhiyun {
1737*4882a593Smuzhiyun int ret = BCME_OK;
1738*4882a593Smuzhiyun uint32 cur_val;
1739*4882a593Smuzhiyun int index = 0, mask = 0, value = 0;
1740*4882a593Smuzhiyun // btc_params=[index] [mask] [value]
1741*4882a593Smuzhiyun // Ex: btc_params=82 0x0021 0x0001
1742*4882a593Smuzhiyun
1743*4882a593Smuzhiyun if (buf) {
1744*4882a593Smuzhiyun sscanf(buf, "%d %x %x", &index, &mask, &value);
1745*4882a593Smuzhiyun }
1746*4882a593Smuzhiyun
1747*4882a593Smuzhiyun CONFIG_TRACE("%s%d mask=0x%04x value=0x%04x\n", cmd, index, mask, value);
1748*4882a593Smuzhiyun
1749*4882a593Smuzhiyun ret = dhd_conf_reg2args(dhd, cmd, FALSE, index, &cur_val);
1750*4882a593Smuzhiyun CONFIG_TRACE("%s%d = 0x%04x\n", cmd, index, cur_val);
1751*4882a593Smuzhiyun cur_val &= (~mask);
1752*4882a593Smuzhiyun cur_val |= value;
1753*4882a593Smuzhiyun
1754*4882a593Smuzhiyun // need to WLC_UP before btc_params
1755*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, 0, WLC_UP, "WLC_UP", 0, 0, FALSE);
1756*4882a593Smuzhiyun
1757*4882a593Smuzhiyun CONFIG_TRACE("wl %s%d 0x%04x\n", cmd, index, cur_val);
1758*4882a593Smuzhiyun ret = dhd_conf_reg2args(dhd, cmd, TRUE, index, &cur_val);
1759*4882a593Smuzhiyun
1760*4882a593Smuzhiyun ret = dhd_conf_reg2args(dhd, cmd, FALSE, index, &cur_val);
1761*4882a593Smuzhiyun CONFIG_MSG("%s%d = 0x%04x\n", cmd, index, cur_val);
1762*4882a593Smuzhiyun
1763*4882a593Smuzhiyun return ret;
1764*4882a593Smuzhiyun }
1765*4882a593Smuzhiyun
1766*4882a593Smuzhiyun typedef struct sub_cmd_t {
1767*4882a593Smuzhiyun char *name;
1768*4882a593Smuzhiyun uint16 id; /* id for the dongle f/w switch/case */
1769*4882a593Smuzhiyun uint16 type; /* base type of argument IOVT_XXXX */
1770*4882a593Smuzhiyun } sub_cmd_t;
1771*4882a593Smuzhiyun
1772*4882a593Smuzhiyun /* wl he sub cmd list */
1773*4882a593Smuzhiyun static const sub_cmd_t he_cmd_list[] = {
1774*4882a593Smuzhiyun {"enab", WL_HE_CMD_ENAB, IOVT_UINT8},
1775*4882a593Smuzhiyun {"features", WL_HE_CMD_FEATURES, IOVT_UINT32},
1776*4882a593Smuzhiyun {"bsscolor", WL_HE_CMD_BSSCOLOR, IOVT_UINT8},
1777*4882a593Smuzhiyun {"partialbsscolor", WL_HE_CMD_PARTIAL_BSSCOLOR, IOVT_UINT8},
1778*4882a593Smuzhiyun {"cap", WL_HE_CMD_CAP, IOVT_UINT8},
1779*4882a593Smuzhiyun {"staid", WL_HE_CMD_STAID, IOVT_UINT16},
1780*4882a593Smuzhiyun {"rtsdurthresh", WL_HE_CMD_RTSDURTHRESH, IOVT_UINT16},
1781*4882a593Smuzhiyun {"peduration", WL_HE_CMD_PEDURATION, IOVT_UINT8},
1782*4882a593Smuzhiyun {"testbed_mode", WL_HE_CMD_TESTBED_MODE, IOVT_UINT32},
1783*4882a593Smuzhiyun {"omi_ulmu_throttle", WL_HE_CMD_OMI_ULMU_THROTTLE, IOVT_UINT16},
1784*4882a593Smuzhiyun {"omi_dlmu_rr_mpf_map", WL_HE_CMD_OMI_DLMU_RSD_RCM_MPF_MAP, IOVT_UINT32},
1785*4882a593Smuzhiyun {"ulmu_disable_policy", WL_HE_CMD_ULMU_DISABLE_POLICY, IOVT_UINT8},
1786*4882a593Smuzhiyun {"sr_prohibit", WL_HE_CMD_SR_PROHIBIT, IOVT_UINT8},
1787*4882a593Smuzhiyun };
1788*4882a593Smuzhiyun
1789*4882a593Smuzhiyun static uint
wl_he_iovt2len(uint iovt)1790*4882a593Smuzhiyun wl_he_iovt2len(uint iovt)
1791*4882a593Smuzhiyun {
1792*4882a593Smuzhiyun switch (iovt) {
1793*4882a593Smuzhiyun case IOVT_BOOL:
1794*4882a593Smuzhiyun case IOVT_INT8:
1795*4882a593Smuzhiyun case IOVT_UINT8:
1796*4882a593Smuzhiyun return sizeof(uint8);
1797*4882a593Smuzhiyun case IOVT_INT16:
1798*4882a593Smuzhiyun case IOVT_UINT16:
1799*4882a593Smuzhiyun return sizeof(uint16);
1800*4882a593Smuzhiyun case IOVT_INT32:
1801*4882a593Smuzhiyun case IOVT_UINT32:
1802*4882a593Smuzhiyun return sizeof(uint32);
1803*4882a593Smuzhiyun default:
1804*4882a593Smuzhiyun /* ASSERT(0); */
1805*4882a593Smuzhiyun return 0;
1806*4882a593Smuzhiyun }
1807*4882a593Smuzhiyun }
1808*4882a593Smuzhiyun
1809*4882a593Smuzhiyun static int
dhd_conf_he_cmd(dhd_pub_t * dhd,char * cmd,char * buf)1810*4882a593Smuzhiyun dhd_conf_he_cmd(dhd_pub_t * dhd, char *cmd, char *buf)
1811*4882a593Smuzhiyun {
1812*4882a593Smuzhiyun int ret = BCME_OK, i;
1813*4882a593Smuzhiyun bcm_xtlv_t *pxtlv = NULL;
1814*4882a593Smuzhiyun uint8 mybuf[128];
1815*4882a593Smuzhiyun uint16 he_id = -1, he_len = 0, mybuf_len = sizeof(mybuf);
1816*4882a593Smuzhiyun uint32 he_val;
1817*4882a593Smuzhiyun const sub_cmd_t *tpl = he_cmd_list;
1818*4882a593Smuzhiyun char sub_cmd[32], he_val_str[10];
1819*4882a593Smuzhiyun
1820*4882a593Smuzhiyun if (buf) {
1821*4882a593Smuzhiyun sscanf(buf, "%s %s", sub_cmd, he_val_str);
1822*4882a593Smuzhiyun }
1823*4882a593Smuzhiyun
1824*4882a593Smuzhiyun for (i=0; i<ARRAY_SIZE(he_cmd_list); i++, tpl++) {
1825*4882a593Smuzhiyun if (!strcmp(tpl->name, sub_cmd)) {
1826*4882a593Smuzhiyun he_id = tpl->id;
1827*4882a593Smuzhiyun he_len = wl_he_iovt2len(tpl->type);
1828*4882a593Smuzhiyun break;
1829*4882a593Smuzhiyun }
1830*4882a593Smuzhiyun }
1831*4882a593Smuzhiyun if (he_id < 0) {
1832*4882a593Smuzhiyun CONFIG_ERROR("No he id found for %s\n", sub_cmd);
1833*4882a593Smuzhiyun return 0;
1834*4882a593Smuzhiyun }
1835*4882a593Smuzhiyun
1836*4882a593Smuzhiyun pxtlv = (bcm_xtlv_t *)mybuf;
1837*4882a593Smuzhiyun
1838*4882a593Smuzhiyun if (strlen(he_val_str)) {
1839*4882a593Smuzhiyun he_val = simple_strtol(he_val_str, NULL, 0);
1840*4882a593Smuzhiyun ret = bcm_pack_xtlv_entry((uint8**)&pxtlv, &mybuf_len, he_id,
1841*4882a593Smuzhiyun he_len, (uint8 *)&he_val, BCM_XTLV_OPTION_ALIGN32);
1842*4882a593Smuzhiyun if (ret != BCME_OK) {
1843*4882a593Smuzhiyun CONFIG_ERROR("failed to pack he enab, err: %s\n", bcmerrorstr(ret));
1844*4882a593Smuzhiyun return 0;
1845*4882a593Smuzhiyun }
1846*4882a593Smuzhiyun CONFIG_TRACE("he %s 0x%x\n", sub_cmd, he_val);
1847*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, cmd, (char *)&mybuf,
1848*4882a593Smuzhiyun sizeof(mybuf), TRUE);
1849*4882a593Smuzhiyun }
1850*4882a593Smuzhiyun
1851*4882a593Smuzhiyun return 0;
1852*4882a593Smuzhiyun }
1853*4882a593Smuzhiyun
1854*4882a593Smuzhiyun #ifndef SUPPORT_RANDOM_MAC_SCAN
1855*4882a593Smuzhiyun int
dhd_conf_scan_mac(dhd_pub_t * dhd,char * cmd,char * buf)1856*4882a593Smuzhiyun dhd_conf_scan_mac(dhd_pub_t * dhd, char *cmd, char *buf)
1857*4882a593Smuzhiyun {
1858*4882a593Smuzhiyun uint8 buffer[WLC_IOCTL_SMLEN] = {0, };
1859*4882a593Smuzhiyun wl_scanmac_t *sm = NULL;
1860*4882a593Smuzhiyun wl_scanmac_enable_t *sm_enable = NULL;
1861*4882a593Smuzhiyun int enable = 0, len = 0, ret = -1;
1862*4882a593Smuzhiyun char sub_cmd[32], iovbuf[WLC_IOCTL_SMLEN];
1863*4882a593Smuzhiyun s32 iovar_len;
1864*4882a593Smuzhiyun
1865*4882a593Smuzhiyun memset(sub_cmd, 0, sizeof(sub_cmd));
1866*4882a593Smuzhiyun if (buf) {
1867*4882a593Smuzhiyun sscanf(buf, "%s %d", sub_cmd, &enable);
1868*4882a593Smuzhiyun }
1869*4882a593Smuzhiyun
1870*4882a593Smuzhiyun if (!strcmp(sub_cmd, "enable")) {
1871*4882a593Smuzhiyun sm = (wl_scanmac_t *)buffer;
1872*4882a593Smuzhiyun sm_enable = (wl_scanmac_enable_t *)sm->data;
1873*4882a593Smuzhiyun sm->len = sizeof(*sm_enable);
1874*4882a593Smuzhiyun sm_enable->enable = enable;
1875*4882a593Smuzhiyun len = OFFSETOF(wl_scanmac_t, data) + sm->len;
1876*4882a593Smuzhiyun sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
1877*4882a593Smuzhiyun CONFIG_TRACE("scanmac enable %d\n", sm_enable->enable);
1878*4882a593Smuzhiyun
1879*4882a593Smuzhiyun iovar_len = bcm_mkiovar("scanmac", buffer, len, iovbuf, sizeof(iovbuf));
1880*4882a593Smuzhiyun if (iovar_len > 0)
1881*4882a593Smuzhiyun ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iovar_len, TRUE, 0);
1882*4882a593Smuzhiyun else
1883*4882a593Smuzhiyun ret = BCME_BUFTOOSHORT;
1884*4882a593Smuzhiyun if (ret == BCME_UNSUPPORTED)
1885*4882a593Smuzhiyun CONFIG_TRACE("scanmac, UNSUPPORTED\n");
1886*4882a593Smuzhiyun else if (ret != BCME_OK)
1887*4882a593Smuzhiyun CONFIG_ERROR("%s setting failed %d, len=%d\n", "scanmac", ret, len);
1888*4882a593Smuzhiyun }
1889*4882a593Smuzhiyun else {
1890*4882a593Smuzhiyun CONFIG_ERROR("wrong cmd \"%s %d\"\n", sub_cmd, enable);
1891*4882a593Smuzhiyun }
1892*4882a593Smuzhiyun
1893*4882a593Smuzhiyun return 0;
1894*4882a593Smuzhiyun }
1895*4882a593Smuzhiyun #endif
1896*4882a593Smuzhiyun
1897*4882a593Smuzhiyun int
dhd_conf_country(dhd_pub_t * dhd,char * cmd,char * buf)1898*4882a593Smuzhiyun dhd_conf_country(dhd_pub_t *dhd, char *cmd, char *buf)
1899*4882a593Smuzhiyun {
1900*4882a593Smuzhiyun wl_country_t cspec = {{0}, 0, {0}};
1901*4882a593Smuzhiyun wl_country_t cur_cspec = {{0}, 0, {0}};
1902*4882a593Smuzhiyun int err = 0;
1903*4882a593Smuzhiyun
1904*4882a593Smuzhiyun if (buf) {
1905*4882a593Smuzhiyun dhd_conf_get_country(dhd, &cur_cspec);
1906*4882a593Smuzhiyun strlcpy(cspec.country_abbrev, buf, WL_CCODE_LEN + 1);
1907*4882a593Smuzhiyun strlcpy(cspec.ccode, buf, WL_CCODE_LEN + 1);
1908*4882a593Smuzhiyun dhd_conf_map_country_list(dhd, &cspec);
1909*4882a593Smuzhiyun if (!memcmp(&cspec.ccode, &cur_cspec.ccode, WL_CCODE_LEN + 1) &&
1910*4882a593Smuzhiyun (cspec.rev == cur_cspec.rev)) {
1911*4882a593Smuzhiyun CONFIG_MSG("country code = %s/%d is already configured\n",
1912*4882a593Smuzhiyun cspec.ccode, cspec.rev);
1913*4882a593Smuzhiyun return 0;
1914*4882a593Smuzhiyun }
1915*4882a593Smuzhiyun err = dhd_conf_set_country(dhd, &cspec);
1916*4882a593Smuzhiyun if (!err) {
1917*4882a593Smuzhiyun dhd_conf_fix_country(dhd);
1918*4882a593Smuzhiyun }
1919*4882a593Smuzhiyun dhd_conf_get_country(dhd, &dhd->dhd_cspec);
1920*4882a593Smuzhiyun }
1921*4882a593Smuzhiyun
1922*4882a593Smuzhiyun return err;
1923*4882a593Smuzhiyun }
1924*4882a593Smuzhiyun
1925*4882a593Smuzhiyun typedef int (tpl_parse_t)(dhd_pub_t *dhd, char *name, char *buf);
1926*4882a593Smuzhiyun
1927*4882a593Smuzhiyun typedef struct iovar_tpl_t {
1928*4882a593Smuzhiyun int cmd;
1929*4882a593Smuzhiyun char *name;
1930*4882a593Smuzhiyun tpl_parse_t *parse;
1931*4882a593Smuzhiyun } iovar_tpl_t;
1932*4882a593Smuzhiyun
1933*4882a593Smuzhiyun const iovar_tpl_t iovar_tpl_list[] = {
1934*4882a593Smuzhiyun {WLC_SET_VAR, "rsdb_mode", dhd_conf_rsdb_mode},
1935*4882a593Smuzhiyun {WLC_SET_VAR, "he", dhd_conf_he_cmd},
1936*4882a593Smuzhiyun {WLC_SET_VAR, "btc_params", dhd_conf_btc_params},
1937*4882a593Smuzhiyun #ifndef SUPPORT_RANDOM_MAC_SCAN
1938*4882a593Smuzhiyun {WLC_SET_VAR, "scanmac", dhd_conf_scan_mac},
1939*4882a593Smuzhiyun #endif
1940*4882a593Smuzhiyun {WLC_SET_VAR, "country", dhd_conf_country},
1941*4882a593Smuzhiyun };
1942*4882a593Smuzhiyun
iovar_tpl_parse(const iovar_tpl_t * tpl,int tpl_count,dhd_pub_t * dhd,int cmd,char * name,char * buf)1943*4882a593Smuzhiyun static int iovar_tpl_parse(const iovar_tpl_t *tpl, int tpl_count,
1944*4882a593Smuzhiyun dhd_pub_t *dhd, int cmd, char *name, char *buf)
1945*4882a593Smuzhiyun {
1946*4882a593Smuzhiyun int i, ret = 0;
1947*4882a593Smuzhiyun
1948*4882a593Smuzhiyun /* look for a matching code in the table */
1949*4882a593Smuzhiyun for (i = 0; i < tpl_count; i++, tpl++) {
1950*4882a593Smuzhiyun if (tpl->cmd == cmd && !strcmp(tpl->name, name))
1951*4882a593Smuzhiyun break;
1952*4882a593Smuzhiyun }
1953*4882a593Smuzhiyun if (i < tpl_count && tpl->parse) {
1954*4882a593Smuzhiyun ret = tpl->parse(dhd, name, buf);
1955*4882a593Smuzhiyun } else {
1956*4882a593Smuzhiyun ret = -1;
1957*4882a593Smuzhiyun }
1958*4882a593Smuzhiyun
1959*4882a593Smuzhiyun return ret;
1960*4882a593Smuzhiyun }
1961*4882a593Smuzhiyun
1962*4882a593Smuzhiyun static bool
dhd_conf_set_wl_cmd(dhd_pub_t * dhd,char * data,bool down)1963*4882a593Smuzhiyun dhd_conf_set_wl_cmd(dhd_pub_t *dhd, char *data, bool down)
1964*4882a593Smuzhiyun {
1965*4882a593Smuzhiyun int cmd, val, ret = 0, len;
1966*4882a593Smuzhiyun char name[32], *pch, *pick_tmp, *pick_tmp2, *pdata = NULL;
1967*4882a593Smuzhiyun
1968*4882a593Smuzhiyun /* Process wl_preinit:
1969*4882a593Smuzhiyun * wl_preinit=[cmd]=[val], [cmd]=[val]
1970*4882a593Smuzhiyun * Ex: wl_preinit=86=0, mpc=0
1971*4882a593Smuzhiyun */
1972*4882a593Smuzhiyun
1973*4882a593Smuzhiyun if (data == NULL)
1974*4882a593Smuzhiyun return FALSE;
1975*4882a593Smuzhiyun
1976*4882a593Smuzhiyun len = strlen(data);
1977*4882a593Smuzhiyun pdata = kmalloc(len+1, GFP_KERNEL);
1978*4882a593Smuzhiyun if (pdata == NULL) {
1979*4882a593Smuzhiyun CONFIG_ERROR("Failed to allocate buffer of %d bytes\n", len+1);
1980*4882a593Smuzhiyun goto exit;
1981*4882a593Smuzhiyun }
1982*4882a593Smuzhiyun memset(pdata, 0, len+1);
1983*4882a593Smuzhiyun strcpy(pdata, data);
1984*4882a593Smuzhiyun
1985*4882a593Smuzhiyun pick_tmp = pdata;
1986*4882a593Smuzhiyun while (pick_tmp && (pick_tmp2 = bcmstrtok(&pick_tmp, ",", 0)) != NULL) {
1987*4882a593Smuzhiyun char *pEnd;
1988*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp2, "=", 0);
1989*4882a593Smuzhiyun if (!pch)
1990*4882a593Smuzhiyun break;
1991*4882a593Smuzhiyun if (*pch == ' ') {
1992*4882a593Smuzhiyun pch++;
1993*4882a593Smuzhiyun }
1994*4882a593Smuzhiyun memset(name, 0 , sizeof (name));
1995*4882a593Smuzhiyun cmd = bcm_strtoul(pch, &pEnd, 0);
1996*4882a593Smuzhiyun if (cmd == 0 || strlen(pEnd)) {
1997*4882a593Smuzhiyun cmd = WLC_SET_VAR;
1998*4882a593Smuzhiyun strcpy(name, pch);
1999*4882a593Smuzhiyun }
2000*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp2, ",", 0);
2001*4882a593Smuzhiyun if (!pch) {
2002*4882a593Smuzhiyun break;
2003*4882a593Smuzhiyun }
2004*4882a593Smuzhiyun ret = iovar_tpl_parse(iovar_tpl_list, ARRAY_SIZE(iovar_tpl_list),
2005*4882a593Smuzhiyun dhd, cmd, name, pch);
2006*4882a593Smuzhiyun if (ret) {
2007*4882a593Smuzhiyun val = (int)simple_strtol(pch, NULL, 0);
2008*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, 0, cmd, name, val, -1, down);
2009*4882a593Smuzhiyun }
2010*4882a593Smuzhiyun }
2011*4882a593Smuzhiyun
2012*4882a593Smuzhiyun exit:
2013*4882a593Smuzhiyun if (pdata)
2014*4882a593Smuzhiyun kfree(pdata);
2015*4882a593Smuzhiyun return true;
2016*4882a593Smuzhiyun }
2017*4882a593Smuzhiyun
2018*4882a593Smuzhiyun int
dhd_conf_get_band(dhd_pub_t * dhd)2019*4882a593Smuzhiyun dhd_conf_get_band(dhd_pub_t *dhd)
2020*4882a593Smuzhiyun {
2021*4882a593Smuzhiyun int band = -1;
2022*4882a593Smuzhiyun
2023*4882a593Smuzhiyun if (dhd && dhd->conf)
2024*4882a593Smuzhiyun band = dhd->conf->band;
2025*4882a593Smuzhiyun else
2026*4882a593Smuzhiyun CONFIG_ERROR("dhd or conf is NULL\n");
2027*4882a593Smuzhiyun
2028*4882a593Smuzhiyun return band;
2029*4882a593Smuzhiyun }
2030*4882a593Smuzhiyun
2031*4882a593Smuzhiyun bool
dhd_conf_match_channel(dhd_pub_t * dhd,uint32 channel)2032*4882a593Smuzhiyun dhd_conf_match_channel(dhd_pub_t *dhd, uint32 channel)
2033*4882a593Smuzhiyun {
2034*4882a593Smuzhiyun int i;
2035*4882a593Smuzhiyun bool match = false;
2036*4882a593Smuzhiyun
2037*4882a593Smuzhiyun if (dhd && dhd->conf) {
2038*4882a593Smuzhiyun if (dhd->conf->channels.count == 0)
2039*4882a593Smuzhiyun return true;
2040*4882a593Smuzhiyun for (i=0; i<dhd->conf->channels.count; i++) {
2041*4882a593Smuzhiyun if (channel == dhd->conf->channels.channel[i])
2042*4882a593Smuzhiyun match = true;
2043*4882a593Smuzhiyun }
2044*4882a593Smuzhiyun } else {
2045*4882a593Smuzhiyun match = true;
2046*4882a593Smuzhiyun CONFIG_ERROR("dhd or conf is NULL\n");
2047*4882a593Smuzhiyun }
2048*4882a593Smuzhiyun
2049*4882a593Smuzhiyun return match;
2050*4882a593Smuzhiyun }
2051*4882a593Smuzhiyun
2052*4882a593Smuzhiyun int
dhd_conf_set_roam(dhd_pub_t * dhd,int ifidx)2053*4882a593Smuzhiyun dhd_conf_set_roam(dhd_pub_t *dhd, int ifidx)
2054*4882a593Smuzhiyun {
2055*4882a593Smuzhiyun int bcmerror = -1;
2056*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
2057*4882a593Smuzhiyun uint wnm_bsstrans_resp = 0;
2058*4882a593Smuzhiyun
2059*4882a593Smuzhiyun if (dhd->conf->chip == BCM4359_CHIP_ID) {
2060*4882a593Smuzhiyun dhd_conf_get_iovar(dhd, ifidx, WLC_GET_VAR, "wnm_bsstrans_resp",
2061*4882a593Smuzhiyun (char *)&wnm_bsstrans_resp, sizeof(wnm_bsstrans_resp));
2062*4882a593Smuzhiyun if (wnm_bsstrans_resp == WL_BSSTRANS_POLICY_PRODUCT) {
2063*4882a593Smuzhiyun dhd->wbtext_policy = WL_BSSTRANS_POLICY_ROAM_ALWAYS;
2064*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "wnm_bsstrans_resp",
2065*4882a593Smuzhiyun WL_BSSTRANS_POLICY_ROAM_ALWAYS, 0, FALSE);
2066*4882a593Smuzhiyun }
2067*4882a593Smuzhiyun }
2068*4882a593Smuzhiyun
2069*4882a593Smuzhiyun dhd_roam_disable = conf->roam_off;
2070*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "roam_off", dhd->conf->roam_off, 0, FALSE);
2071*4882a593Smuzhiyun
2072*4882a593Smuzhiyun if (!conf->roam_off || !conf->roam_off_suspend) {
2073*4882a593Smuzhiyun CONFIG_MSG("set roam_trigger %d\n", conf->roam_trigger[0]);
2074*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_ROAM_TRIGGER, "WLC_SET_ROAM_TRIGGER",
2075*4882a593Smuzhiyun (char *)conf->roam_trigger, sizeof(conf->roam_trigger), FALSE);
2076*4882a593Smuzhiyun
2077*4882a593Smuzhiyun CONFIG_MSG("set roam_scan_period %d\n", conf->roam_scan_period[0]);
2078*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_ROAM_SCAN_PERIOD, "WLC_SET_ROAM_SCAN_PERIOD",
2079*4882a593Smuzhiyun (char *)conf->roam_scan_period, sizeof(conf->roam_scan_period), FALSE);
2080*4882a593Smuzhiyun
2081*4882a593Smuzhiyun CONFIG_MSG("set roam_delta %d\n", conf->roam_delta[0]);
2082*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_ROAM_DELTA, "WLC_SET_ROAM_DELTA",
2083*4882a593Smuzhiyun (char *)conf->roam_delta, sizeof(conf->roam_delta), FALSE);
2084*4882a593Smuzhiyun
2085*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "fullroamperiod",
2086*4882a593Smuzhiyun dhd->conf->fullroamperiod, 1, FALSE);
2087*4882a593Smuzhiyun }
2088*4882a593Smuzhiyun
2089*4882a593Smuzhiyun return bcmerror;
2090*4882a593Smuzhiyun }
2091*4882a593Smuzhiyun
2092*4882a593Smuzhiyun void
dhd_conf_add_to_eventbuffer(struct eventmsg_buf * ev,u16 event,bool set)2093*4882a593Smuzhiyun dhd_conf_add_to_eventbuffer(struct eventmsg_buf *ev, u16 event, bool set)
2094*4882a593Smuzhiyun {
2095*4882a593Smuzhiyun if (!ev || (event > WLC_E_LAST))
2096*4882a593Smuzhiyun return;
2097*4882a593Smuzhiyun
2098*4882a593Smuzhiyun if (ev->num < MAX_EVENT_BUF_NUM) {
2099*4882a593Smuzhiyun ev->event[ev->num].type = event;
2100*4882a593Smuzhiyun ev->event[ev->num].set = set;
2101*4882a593Smuzhiyun ev->num++;
2102*4882a593Smuzhiyun } else {
2103*4882a593Smuzhiyun CONFIG_ERROR("evenbuffer doesn't support > %u events. Update"
2104*4882a593Smuzhiyun " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM);
2105*4882a593Smuzhiyun ASSERT(0);
2106*4882a593Smuzhiyun }
2107*4882a593Smuzhiyun }
2108*4882a593Smuzhiyun
2109*4882a593Smuzhiyun s32
dhd_conf_apply_eventbuffer(dhd_pub_t * dhd,eventmsg_buf_t * ev)2110*4882a593Smuzhiyun dhd_conf_apply_eventbuffer(dhd_pub_t *dhd, eventmsg_buf_t *ev)
2111*4882a593Smuzhiyun {
2112*4882a593Smuzhiyun char eventmask[WL_EVENTING_MASK_LEN];
2113*4882a593Smuzhiyun int i, ret = 0;
2114*4882a593Smuzhiyun
2115*4882a593Smuzhiyun if (!ev || (!ev->num))
2116*4882a593Smuzhiyun return -EINVAL;
2117*4882a593Smuzhiyun
2118*4882a593Smuzhiyun /* Read event_msgs mask */
2119*4882a593Smuzhiyun ret = dhd_conf_get_iovar(dhd, 0, WLC_GET_VAR, "event_msgs", eventmask,
2120*4882a593Smuzhiyun sizeof(eventmask));
2121*4882a593Smuzhiyun if (unlikely(ret)) {
2122*4882a593Smuzhiyun CONFIG_ERROR("Get event_msgs error (%d)\n", ret);
2123*4882a593Smuzhiyun goto exit;
2124*4882a593Smuzhiyun }
2125*4882a593Smuzhiyun
2126*4882a593Smuzhiyun /* apply the set bits */
2127*4882a593Smuzhiyun for (i = 0; i < ev->num; i++) {
2128*4882a593Smuzhiyun if (ev->event[i].set)
2129*4882a593Smuzhiyun setbit(eventmask, ev->event[i].type);
2130*4882a593Smuzhiyun else
2131*4882a593Smuzhiyun clrbit(eventmask, ev->event[i].type);
2132*4882a593Smuzhiyun }
2133*4882a593Smuzhiyun
2134*4882a593Smuzhiyun /* Write updated Event mask */
2135*4882a593Smuzhiyun ret = dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "event_msgs", eventmask,
2136*4882a593Smuzhiyun sizeof(eventmask), FALSE);
2137*4882a593Smuzhiyun if (unlikely(ret)) {
2138*4882a593Smuzhiyun CONFIG_ERROR("Set event_msgs error (%d)\n", ret);
2139*4882a593Smuzhiyun }
2140*4882a593Smuzhiyun
2141*4882a593Smuzhiyun exit:
2142*4882a593Smuzhiyun return ret;
2143*4882a593Smuzhiyun }
2144*4882a593Smuzhiyun
2145*4882a593Smuzhiyun static int
dhd_conf_enable_roam_offload(dhd_pub_t * dhd,int enable)2146*4882a593Smuzhiyun dhd_conf_enable_roam_offload(dhd_pub_t *dhd, int enable)
2147*4882a593Smuzhiyun {
2148*4882a593Smuzhiyun int err;
2149*4882a593Smuzhiyun eventmsg_buf_t ev_buf;
2150*4882a593Smuzhiyun
2151*4882a593Smuzhiyun if (dhd->conf->roam_off_suspend)
2152*4882a593Smuzhiyun return 0;
2153*4882a593Smuzhiyun
2154*4882a593Smuzhiyun err = dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "roam_offload", enable, 0, FALSE);
2155*4882a593Smuzhiyun if (err)
2156*4882a593Smuzhiyun return err;
2157*4882a593Smuzhiyun
2158*4882a593Smuzhiyun bzero(&ev_buf, sizeof(eventmsg_buf_t));
2159*4882a593Smuzhiyun dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_PSK_SUP, !enable);
2160*4882a593Smuzhiyun dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_REQ_IE, !enable);
2161*4882a593Smuzhiyun dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_RESP_IE, !enable);
2162*4882a593Smuzhiyun dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_REASSOC, !enable);
2163*4882a593Smuzhiyun dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_JOIN, !enable);
2164*4882a593Smuzhiyun dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_ROAM, !enable);
2165*4882a593Smuzhiyun err = dhd_conf_apply_eventbuffer(dhd, &ev_buf);
2166*4882a593Smuzhiyun
2167*4882a593Smuzhiyun CONFIG_TRACE("roam_offload %d\n", enable);
2168*4882a593Smuzhiyun
2169*4882a593Smuzhiyun return err;
2170*4882a593Smuzhiyun }
2171*4882a593Smuzhiyun
2172*4882a593Smuzhiyun void
dhd_conf_set_bw_cap(dhd_pub_t * dhd)2173*4882a593Smuzhiyun dhd_conf_set_bw_cap(dhd_pub_t *dhd)
2174*4882a593Smuzhiyun {
2175*4882a593Smuzhiyun struct {
2176*4882a593Smuzhiyun u32 band;
2177*4882a593Smuzhiyun u32 bw_cap;
2178*4882a593Smuzhiyun } param = {0, 0};
2179*4882a593Smuzhiyun
2180*4882a593Smuzhiyun if (dhd->conf->bw_cap[0] >= 0) {
2181*4882a593Smuzhiyun memset(¶m, 0, sizeof(param));
2182*4882a593Smuzhiyun param.band = WLC_BAND_2G;
2183*4882a593Smuzhiyun param.bw_cap = (uint)dhd->conf->bw_cap[0];
2184*4882a593Smuzhiyun CONFIG_MSG("set bw_cap 2g 0x%x\n", param.bw_cap);
2185*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "bw_cap", (char *)¶m,
2186*4882a593Smuzhiyun sizeof(param), TRUE);
2187*4882a593Smuzhiyun }
2188*4882a593Smuzhiyun
2189*4882a593Smuzhiyun if (dhd->conf->bw_cap[1] >= 0) {
2190*4882a593Smuzhiyun memset(¶m, 0, sizeof(param));
2191*4882a593Smuzhiyun param.band = WLC_BAND_5G;
2192*4882a593Smuzhiyun param.bw_cap = (uint)dhd->conf->bw_cap[1];
2193*4882a593Smuzhiyun CONFIG_MSG("set bw_cap 5g 0x%x\n", param.bw_cap);
2194*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "bw_cap", (char *)¶m,
2195*4882a593Smuzhiyun sizeof(param), TRUE);
2196*4882a593Smuzhiyun }
2197*4882a593Smuzhiyun }
2198*4882a593Smuzhiyun
2199*4882a593Smuzhiyun void
dhd_conf_get_wme(dhd_pub_t * dhd,int ifidx,int mode,edcf_acparam_t * acp)2200*4882a593Smuzhiyun dhd_conf_get_wme(dhd_pub_t *dhd, int ifidx, int mode, edcf_acparam_t *acp)
2201*4882a593Smuzhiyun {
2202*4882a593Smuzhiyun int bcmerror = -1;
2203*4882a593Smuzhiyun char iovbuf[WLC_IOCTL_SMLEN];
2204*4882a593Smuzhiyun edcf_acparam_t *acparam;
2205*4882a593Smuzhiyun
2206*4882a593Smuzhiyun bzero(iovbuf, sizeof(iovbuf));
2207*4882a593Smuzhiyun
2208*4882a593Smuzhiyun /*
2209*4882a593Smuzhiyun * Get current acparams, using buf as an input buffer.
2210*4882a593Smuzhiyun * Return data is array of 4 ACs of wme params.
2211*4882a593Smuzhiyun */
2212*4882a593Smuzhiyun if (mode == 0)
2213*4882a593Smuzhiyun bcm_mkiovar("wme_ac_sta", NULL, 0, iovbuf, sizeof(iovbuf));
2214*4882a593Smuzhiyun else
2215*4882a593Smuzhiyun bcm_mkiovar("wme_ac_ap", NULL, 0, iovbuf, sizeof(iovbuf));
2216*4882a593Smuzhiyun if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf),
2217*4882a593Smuzhiyun FALSE, ifidx)) < 0) {
2218*4882a593Smuzhiyun CONFIG_ERROR("wme_ac_sta getting failed %d\n", bcmerror);
2219*4882a593Smuzhiyun return;
2220*4882a593Smuzhiyun }
2221*4882a593Smuzhiyun memcpy((char*)acp, iovbuf, sizeof(edcf_acparam_t)*AC_COUNT);
2222*4882a593Smuzhiyun
2223*4882a593Smuzhiyun acparam = &acp[AC_BK];
2224*4882a593Smuzhiyun CONFIG_TRACE("BK: aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n",
2225*4882a593Smuzhiyun acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,
2226*4882a593Smuzhiyun acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,
2227*4882a593Smuzhiyun acparam->TXOP);
2228*4882a593Smuzhiyun acparam = &acp[AC_BE];
2229*4882a593Smuzhiyun CONFIG_TRACE("BE: aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n",
2230*4882a593Smuzhiyun acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,
2231*4882a593Smuzhiyun acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,
2232*4882a593Smuzhiyun acparam->TXOP);
2233*4882a593Smuzhiyun acparam = &acp[AC_VI];
2234*4882a593Smuzhiyun CONFIG_TRACE("VI: aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n",
2235*4882a593Smuzhiyun acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,
2236*4882a593Smuzhiyun acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,
2237*4882a593Smuzhiyun acparam->TXOP);
2238*4882a593Smuzhiyun acparam = &acp[AC_VO];
2239*4882a593Smuzhiyun CONFIG_TRACE("VO: aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n",
2240*4882a593Smuzhiyun acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,
2241*4882a593Smuzhiyun acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,
2242*4882a593Smuzhiyun acparam->TXOP);
2243*4882a593Smuzhiyun
2244*4882a593Smuzhiyun return;
2245*4882a593Smuzhiyun }
2246*4882a593Smuzhiyun
2247*4882a593Smuzhiyun void
dhd_conf_update_wme(dhd_pub_t * dhd,int ifidx,int mode,edcf_acparam_t * acparam_cur,int aci)2248*4882a593Smuzhiyun dhd_conf_update_wme(dhd_pub_t *dhd, int ifidx, int mode,
2249*4882a593Smuzhiyun edcf_acparam_t *acparam_cur, int aci)
2250*4882a593Smuzhiyun {
2251*4882a593Smuzhiyun int aifsn, ecwmin, ecwmax, txop;
2252*4882a593Smuzhiyun edcf_acparam_t *acp;
2253*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
2254*4882a593Smuzhiyun wme_param_t *wme;
2255*4882a593Smuzhiyun
2256*4882a593Smuzhiyun if (mode == 0)
2257*4882a593Smuzhiyun wme = &conf->wme_sta;
2258*4882a593Smuzhiyun else
2259*4882a593Smuzhiyun wme = &conf->wme_ap;
2260*4882a593Smuzhiyun
2261*4882a593Smuzhiyun /* Default value */
2262*4882a593Smuzhiyun aifsn = acparam_cur->ACI&EDCF_AIFSN_MASK;
2263*4882a593Smuzhiyun ecwmin = acparam_cur->ECW&EDCF_ECWMIN_MASK;
2264*4882a593Smuzhiyun ecwmax = (acparam_cur->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT;
2265*4882a593Smuzhiyun txop = acparam_cur->TXOP;
2266*4882a593Smuzhiyun
2267*4882a593Smuzhiyun /* Modified value */
2268*4882a593Smuzhiyun if (wme->aifsn[aci] > 0)
2269*4882a593Smuzhiyun aifsn = wme->aifsn[aci];
2270*4882a593Smuzhiyun if (wme->ecwmin[aci] > 0)
2271*4882a593Smuzhiyun ecwmin = wme->ecwmin[aci];
2272*4882a593Smuzhiyun if (wme->ecwmax[aci] > 0)
2273*4882a593Smuzhiyun ecwmax = wme->ecwmax[aci];
2274*4882a593Smuzhiyun if (wme->txop[aci] > 0)
2275*4882a593Smuzhiyun txop = wme->txop[aci];
2276*4882a593Smuzhiyun
2277*4882a593Smuzhiyun if (!(wme->aifsn[aci] || wme->ecwmin[aci] ||
2278*4882a593Smuzhiyun wme->ecwmax[aci] || wme->txop[aci]))
2279*4882a593Smuzhiyun return;
2280*4882a593Smuzhiyun
2281*4882a593Smuzhiyun /* Update */
2282*4882a593Smuzhiyun acp = acparam_cur;
2283*4882a593Smuzhiyun acp->ACI = (acp->ACI & ~EDCF_AIFSN_MASK) | (aifsn & EDCF_AIFSN_MASK);
2284*4882a593Smuzhiyun acp->ECW = ((ecwmax << EDCF_ECWMAX_SHIFT) & EDCF_ECWMAX_MASK) | (acp->ECW & EDCF_ECWMIN_MASK);
2285*4882a593Smuzhiyun acp->ECW = ((acp->ECW & EDCF_ECWMAX_MASK) | (ecwmin & EDCF_ECWMIN_MASK));
2286*4882a593Smuzhiyun acp->TXOP = txop;
2287*4882a593Smuzhiyun
2288*4882a593Smuzhiyun CONFIG_MSG("wme_ac %s aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n",
2289*4882a593Smuzhiyun mode?"ap":"sta", acp->ACI, acp->ACI&EDCF_AIFSN_MASK,
2290*4882a593Smuzhiyun acp->ECW&EDCF_ECWMIN_MASK, (acp->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,
2291*4882a593Smuzhiyun acp->TXOP);
2292*4882a593Smuzhiyun
2293*4882a593Smuzhiyun /*
2294*4882a593Smuzhiyun * Now use buf as an output buffer.
2295*4882a593Smuzhiyun * Put WME acparams after "wme_ac\0" in buf.
2296*4882a593Smuzhiyun * NOTE: only one of the four ACs can be set at a time.
2297*4882a593Smuzhiyun */
2298*4882a593Smuzhiyun if (mode == 0)
2299*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_VAR, "wme_ac_sta", (char *)acp,
2300*4882a593Smuzhiyun sizeof(edcf_acparam_t), FALSE);
2301*4882a593Smuzhiyun else
2302*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_VAR, "wme_ac_ap", (char *)acp,
2303*4882a593Smuzhiyun sizeof(edcf_acparam_t), FALSE);
2304*4882a593Smuzhiyun
2305*4882a593Smuzhiyun }
2306*4882a593Smuzhiyun
2307*4882a593Smuzhiyun void
dhd_conf_set_wme(dhd_pub_t * dhd,int ifidx,int mode)2308*4882a593Smuzhiyun dhd_conf_set_wme(dhd_pub_t *dhd, int ifidx, int mode)
2309*4882a593Smuzhiyun {
2310*4882a593Smuzhiyun edcf_acparam_t acparam_cur[AC_COUNT];
2311*4882a593Smuzhiyun
2312*4882a593Smuzhiyun if (dhd && dhd->conf) {
2313*4882a593Smuzhiyun if (!dhd->conf->force_wme_ac) {
2314*4882a593Smuzhiyun CONFIG_TRACE("force_wme_ac is not enabled %d\n",
2315*4882a593Smuzhiyun dhd->conf->force_wme_ac);
2316*4882a593Smuzhiyun return;
2317*4882a593Smuzhiyun }
2318*4882a593Smuzhiyun
2319*4882a593Smuzhiyun CONFIG_TRACE("Before change:\n");
2320*4882a593Smuzhiyun dhd_conf_get_wme(dhd, ifidx, mode, acparam_cur);
2321*4882a593Smuzhiyun
2322*4882a593Smuzhiyun dhd_conf_update_wme(dhd, ifidx, mode, &acparam_cur[AC_BK], AC_BK);
2323*4882a593Smuzhiyun dhd_conf_update_wme(dhd, ifidx, mode, &acparam_cur[AC_BE], AC_BE);
2324*4882a593Smuzhiyun dhd_conf_update_wme(dhd, ifidx, mode, &acparam_cur[AC_VI], AC_VI);
2325*4882a593Smuzhiyun dhd_conf_update_wme(dhd, ifidx, mode, &acparam_cur[AC_VO], AC_VO);
2326*4882a593Smuzhiyun
2327*4882a593Smuzhiyun CONFIG_TRACE("After change:\n");
2328*4882a593Smuzhiyun dhd_conf_get_wme(dhd, ifidx, mode, acparam_cur);
2329*4882a593Smuzhiyun } else {
2330*4882a593Smuzhiyun CONFIG_ERROR("dhd or conf is NULL\n");
2331*4882a593Smuzhiyun }
2332*4882a593Smuzhiyun
2333*4882a593Smuzhiyun return;
2334*4882a593Smuzhiyun }
2335*4882a593Smuzhiyun
2336*4882a593Smuzhiyun void
dhd_conf_set_mchan_bw(dhd_pub_t * dhd,int p2p_mode,int miracast_mode)2337*4882a593Smuzhiyun dhd_conf_set_mchan_bw(dhd_pub_t *dhd, int p2p_mode, int miracast_mode)
2338*4882a593Smuzhiyun {
2339*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
2340*4882a593Smuzhiyun mchan_params_t *mchan = conf->mchan;
2341*4882a593Smuzhiyun bool set = true;
2342*4882a593Smuzhiyun
2343*4882a593Smuzhiyun while (mchan != NULL) {
2344*4882a593Smuzhiyun set = true;
2345*4882a593Smuzhiyun set &= (mchan->bw >= 0);
2346*4882a593Smuzhiyun set &= ((mchan->p2p_mode == -1) | (mchan->p2p_mode == p2p_mode));
2347*4882a593Smuzhiyun set &= ((mchan->miracast_mode == -1) | (mchan->miracast_mode == miracast_mode));
2348*4882a593Smuzhiyun if (set) {
2349*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "mchan_bw", mchan->bw, 0, FALSE);
2350*4882a593Smuzhiyun }
2351*4882a593Smuzhiyun mchan = mchan->next;
2352*4882a593Smuzhiyun }
2353*4882a593Smuzhiyun
2354*4882a593Smuzhiyun return;
2355*4882a593Smuzhiyun }
2356*4882a593Smuzhiyun
2357*4882a593Smuzhiyun #ifdef PKT_FILTER_SUPPORT
2358*4882a593Smuzhiyun void
dhd_conf_add_pkt_filter(dhd_pub_t * dhd)2359*4882a593Smuzhiyun dhd_conf_add_pkt_filter(dhd_pub_t *dhd)
2360*4882a593Smuzhiyun {
2361*4882a593Smuzhiyun int i, j;
2362*4882a593Smuzhiyun char str[16];
2363*4882a593Smuzhiyun #define MACS "%02x%02x%02x%02x%02x%02x"
2364*4882a593Smuzhiyun
2365*4882a593Smuzhiyun /* 0) suspend_mode=1
2366*4882a593Smuzhiyun * Case 0: default is unicast pkt and event wake up
2367*4882a593Smuzhiyun * Case 1: no connection in suspend
2368*4882a593Smuzhiyun * 1) wl_suspend=3=0
2369*4882a593Smuzhiyun * 2) wl_resume=2=0
2370*4882a593Smuzhiyun * 3) insuspend=0x7
2371*4882a593Smuzhiyun * Case 2: keep connection in suspend, but no pkt and event wake up
2372*4882a593Smuzhiyun * 1) dhd_master_mode=1
2373*4882a593Smuzhiyun * 2) pkt_filter_delete=100, 102, 103, 104, 105, 106, 107
2374*4882a593Smuzhiyun * 3) pkt_filter_add=141 0 0 0 0xFFFFFFFFFFFF 0x000000000000
2375*4882a593Smuzhiyun * 4) insuspend=0x7
2376*4882a593Smuzhiyun * 5) rekey_offload=1
2377*4882a593Smuzhiyun * Case 3: magic pkt and event wake up
2378*4882a593Smuzhiyun * 1) dhd_master_mode=1
2379*4882a593Smuzhiyun * 2) pkt_filter_delete=100, 102, 103, 104, 105, 106, 107
2380*4882a593Smuzhiyun * 3) magic_pkt_filter_add=141 0 1 12
2381*4882a593Smuzhiyun * 4) rekey_offload=1
2382*4882a593Smuzhiyun */
2383*4882a593Smuzhiyun for(i=0; i<dhd->conf->pkt_filter_add.count; i++) {
2384*4882a593Smuzhiyun dhd->pktfilter[i+dhd->pktfilter_count] = dhd->conf->pkt_filter_add.filter[i];
2385*4882a593Smuzhiyun CONFIG_MSG("%s\n", dhd->pktfilter[i+dhd->pktfilter_count]);
2386*4882a593Smuzhiyun }
2387*4882a593Smuzhiyun dhd->pktfilter_count += i;
2388*4882a593Smuzhiyun
2389*4882a593Smuzhiyun if (dhd->conf->magic_pkt_filter_add) {
2390*4882a593Smuzhiyun strcat(dhd->conf->magic_pkt_filter_add, " 0x");
2391*4882a593Smuzhiyun strcat(dhd->conf->magic_pkt_filter_add, "FFFFFFFFFFFF");
2392*4882a593Smuzhiyun for (j=0; j<16; j++)
2393*4882a593Smuzhiyun strcat(dhd->conf->magic_pkt_filter_add, "FFFFFFFFFFFF");
2394*4882a593Smuzhiyun strcat(dhd->conf->magic_pkt_filter_add, " 0x");
2395*4882a593Smuzhiyun strcat(dhd->conf->magic_pkt_filter_add, "FFFFFFFFFFFF");
2396*4882a593Smuzhiyun sprintf(str, MACS, MAC2STRDBG(dhd->mac.octet));
2397*4882a593Smuzhiyun for (j=0; j<16; j++)
2398*4882a593Smuzhiyun strncat(dhd->conf->magic_pkt_filter_add, str, 12);
2399*4882a593Smuzhiyun dhd->pktfilter[dhd->pktfilter_count] = dhd->conf->magic_pkt_filter_add;
2400*4882a593Smuzhiyun dhd->pktfilter_count += 1;
2401*4882a593Smuzhiyun }
2402*4882a593Smuzhiyun }
2403*4882a593Smuzhiyun
2404*4882a593Smuzhiyun bool
dhd_conf_del_pkt_filter(dhd_pub_t * dhd,uint32 id)2405*4882a593Smuzhiyun dhd_conf_del_pkt_filter(dhd_pub_t *dhd, uint32 id)
2406*4882a593Smuzhiyun {
2407*4882a593Smuzhiyun int i;
2408*4882a593Smuzhiyun
2409*4882a593Smuzhiyun if (dhd && dhd->conf) {
2410*4882a593Smuzhiyun for (i=0; i<dhd->conf->pkt_filter_del.count; i++) {
2411*4882a593Smuzhiyun if (id == dhd->conf->pkt_filter_del.id[i]) {
2412*4882a593Smuzhiyun CONFIG_MSG("%d\n", dhd->conf->pkt_filter_del.id[i]);
2413*4882a593Smuzhiyun return true;
2414*4882a593Smuzhiyun }
2415*4882a593Smuzhiyun }
2416*4882a593Smuzhiyun return false;
2417*4882a593Smuzhiyun }
2418*4882a593Smuzhiyun return false;
2419*4882a593Smuzhiyun }
2420*4882a593Smuzhiyun
2421*4882a593Smuzhiyun void
dhd_conf_discard_pkt_filter(dhd_pub_t * dhd)2422*4882a593Smuzhiyun dhd_conf_discard_pkt_filter(dhd_pub_t *dhd)
2423*4882a593Smuzhiyun {
2424*4882a593Smuzhiyun dhd->pktfilter_count = 6;
2425*4882a593Smuzhiyun dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = NULL;
2426*4882a593Smuzhiyun dhd->pktfilter[DHD_BROADCAST_FILTER_NUM] = "101 0 0 0 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF";
2427*4882a593Smuzhiyun dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = "102 0 0 0 0xFFFFFF 0x01005E";
2428*4882a593Smuzhiyun dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = "103 0 0 0 0xFFFF 0x3333";
2429*4882a593Smuzhiyun dhd->pktfilter[DHD_MDNS_FILTER_NUM] = NULL;
2430*4882a593Smuzhiyun /* Do not enable ARP to pkt filter if dhd_master_mode is false.*/
2431*4882a593Smuzhiyun dhd->pktfilter[DHD_ARP_FILTER_NUM] = NULL;
2432*4882a593Smuzhiyun
2433*4882a593Smuzhiyun /* IPv4 broadcast address XXX.XXX.XXX.255 */
2434*4882a593Smuzhiyun dhd->pktfilter[dhd->pktfilter_count] = "110 0 0 12 0xFFFF00000000000000000000000000000000000000FF 0x080000000000000000000000000000000000000000FF";
2435*4882a593Smuzhiyun dhd->pktfilter_count++;
2436*4882a593Smuzhiyun /* discard IPv4 multicast address 224.0.0.0/4 */
2437*4882a593Smuzhiyun dhd->pktfilter[dhd->pktfilter_count] = "111 0 0 12 0xFFFF00000000000000000000000000000000F0 0x080000000000000000000000000000000000E0";
2438*4882a593Smuzhiyun dhd->pktfilter_count++;
2439*4882a593Smuzhiyun /* discard IPv6 multicast address FF00::/8 */
2440*4882a593Smuzhiyun dhd->pktfilter[dhd->pktfilter_count] = "112 0 0 12 0xFFFF000000000000000000000000000000000000000000000000FF 0x86DD000000000000000000000000000000000000000000000000FF";
2441*4882a593Smuzhiyun dhd->pktfilter_count++;
2442*4882a593Smuzhiyun /* discard Netbios pkt */
2443*4882a593Smuzhiyun dhd->pktfilter[dhd->pktfilter_count] = "121 0 0 12 0xFFFF000000000000000000FF000000000000000000000000FFFF 0x0800000000000000000000110000000000000000000000000089";
2444*4882a593Smuzhiyun dhd->pktfilter_count++;
2445*4882a593Smuzhiyun
2446*4882a593Smuzhiyun }
2447*4882a593Smuzhiyun #endif /* PKT_FILTER_SUPPORT */
2448*4882a593Smuzhiyun
2449*4882a593Smuzhiyun int
dhd_conf_get_pm(dhd_pub_t * dhd)2450*4882a593Smuzhiyun dhd_conf_get_pm(dhd_pub_t *dhd)
2451*4882a593Smuzhiyun {
2452*4882a593Smuzhiyun if (dhd && dhd->conf) {
2453*4882a593Smuzhiyun return dhd->conf->pm;
2454*4882a593Smuzhiyun }
2455*4882a593Smuzhiyun return -1;
2456*4882a593Smuzhiyun }
2457*4882a593Smuzhiyun
2458*4882a593Smuzhiyun int
dhd_conf_check_hostsleep(dhd_pub_t * dhd,int cmd,void * buf,int len,int * hostsleep_set,int * hostsleep_val,int * ret)2459*4882a593Smuzhiyun dhd_conf_check_hostsleep(dhd_pub_t *dhd, int cmd, void *buf, int len,
2460*4882a593Smuzhiyun int *hostsleep_set, int *hostsleep_val, int *ret)
2461*4882a593Smuzhiyun {
2462*4882a593Smuzhiyun if (dhd->conf->insuspend & (NO_TXCTL_IN_SUSPEND | WOWL_IN_SUSPEND)) {
2463*4882a593Smuzhiyun if (cmd == WLC_SET_VAR) {
2464*4882a593Smuzhiyun char *psleep = NULL;
2465*4882a593Smuzhiyun psleep = strstr(buf, "hostsleep");
2466*4882a593Smuzhiyun if (psleep) {
2467*4882a593Smuzhiyun *hostsleep_set = 1;
2468*4882a593Smuzhiyun memcpy(hostsleep_val, psleep+strlen("hostsleep")+1, sizeof(int));
2469*4882a593Smuzhiyun }
2470*4882a593Smuzhiyun }
2471*4882a593Smuzhiyun if (dhd->hostsleep && (!*hostsleep_set || *hostsleep_val)) {
2472*4882a593Smuzhiyun CONFIG_TRACE("block all none hostsleep clr cmd\n");
2473*4882a593Smuzhiyun *ret = BCME_EPERM;
2474*4882a593Smuzhiyun goto exit;
2475*4882a593Smuzhiyun } else if (*hostsleep_set && *hostsleep_val) {
2476*4882a593Smuzhiyun CONFIG_TRACE("hostsleep %d => %d\n", dhd->hostsleep, *hostsleep_val);
2477*4882a593Smuzhiyun dhd->hostsleep = *hostsleep_val;
2478*4882a593Smuzhiyun if (dhd->conf->insuspend & NO_TXDATA_IN_SUSPEND) {
2479*4882a593Smuzhiyun dhd_txflowcontrol(dhd, ALL_INTERFACES, ON);
2480*4882a593Smuzhiyun }
2481*4882a593Smuzhiyun if (dhd->hostsleep == 2) {
2482*4882a593Smuzhiyun *ret = 0;
2483*4882a593Smuzhiyun goto exit;
2484*4882a593Smuzhiyun }
2485*4882a593Smuzhiyun } else if (dhd->hostsleep == 2 && !*hostsleep_val) {
2486*4882a593Smuzhiyun CONFIG_TRACE("hostsleep %d => %d\n", dhd->hostsleep, *hostsleep_val);
2487*4882a593Smuzhiyun dhd->hostsleep = *hostsleep_val;
2488*4882a593Smuzhiyun if (dhd->conf->insuspend & NO_TXDATA_IN_SUSPEND) {
2489*4882a593Smuzhiyun dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF);
2490*4882a593Smuzhiyun }
2491*4882a593Smuzhiyun *ret = 0;
2492*4882a593Smuzhiyun goto exit;
2493*4882a593Smuzhiyun }
2494*4882a593Smuzhiyun }
2495*4882a593Smuzhiyun #ifdef NO_POWER_SAVE
2496*4882a593Smuzhiyun if (cmd == WLC_SET_PM) {
2497*4882a593Smuzhiyun if (*(const u32*)buf != 0) {
2498*4882a593Smuzhiyun CONFIG_TRACE("skip PM\n");
2499*4882a593Smuzhiyun *ret = BCME_OK;
2500*4882a593Smuzhiyun goto exit;
2501*4882a593Smuzhiyun }
2502*4882a593Smuzhiyun } else if (cmd == WLC_SET_VAR) {
2503*4882a593Smuzhiyun int cmd_len = strlen("mpc");
2504*4882a593Smuzhiyun if (!strncmp(buf, "mpc", cmd_len)) {
2505*4882a593Smuzhiyun if (*((u32 *)((u8*)buf+cmd_len+1)) != 0) {
2506*4882a593Smuzhiyun CONFIG_TRACE("skip mpc\n");
2507*4882a593Smuzhiyun *ret = BCME_OK;
2508*4882a593Smuzhiyun goto exit;
2509*4882a593Smuzhiyun }
2510*4882a593Smuzhiyun }
2511*4882a593Smuzhiyun }
2512*4882a593Smuzhiyun #endif
2513*4882a593Smuzhiyun
2514*4882a593Smuzhiyun return 0;
2515*4882a593Smuzhiyun exit:
2516*4882a593Smuzhiyun return -1;
2517*4882a593Smuzhiyun }
2518*4882a593Smuzhiyun
2519*4882a593Smuzhiyun void
dhd_conf_get_hostsleep(dhd_pub_t * dhd,int hostsleep_set,int hostsleep_val,int ret)2520*4882a593Smuzhiyun dhd_conf_get_hostsleep(dhd_pub_t *dhd,
2521*4882a593Smuzhiyun int hostsleep_set, int hostsleep_val, int ret)
2522*4882a593Smuzhiyun {
2523*4882a593Smuzhiyun if (dhd->conf->insuspend & (NO_TXCTL_IN_SUSPEND | WOWL_IN_SUSPEND)) {
2524*4882a593Smuzhiyun if (hostsleep_set) {
2525*4882a593Smuzhiyun if (hostsleep_val && ret) {
2526*4882a593Smuzhiyun CONFIG_TRACE("reset hostsleep %d => 0\n", dhd->hostsleep);
2527*4882a593Smuzhiyun dhd->hostsleep = 0;
2528*4882a593Smuzhiyun if (dhd->conf->insuspend & NO_TXDATA_IN_SUSPEND) {
2529*4882a593Smuzhiyun dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF);
2530*4882a593Smuzhiyun }
2531*4882a593Smuzhiyun } else if (!hostsleep_val && !ret) {
2532*4882a593Smuzhiyun CONFIG_TRACE("set hostsleep %d => 0\n", dhd->hostsleep);
2533*4882a593Smuzhiyun dhd->hostsleep = 0;
2534*4882a593Smuzhiyun if (dhd->conf->insuspend & NO_TXDATA_IN_SUSPEND) {
2535*4882a593Smuzhiyun dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF);
2536*4882a593Smuzhiyun }
2537*4882a593Smuzhiyun }
2538*4882a593Smuzhiyun }
2539*4882a593Smuzhiyun }
2540*4882a593Smuzhiyun }
2541*4882a593Smuzhiyun
2542*4882a593Smuzhiyun #ifdef WL_EXT_WOWL
2543*4882a593Smuzhiyun #define WL_WOWL_TCPFIN (1 << 26)
2544*4882a593Smuzhiyun typedef struct wl_wowl_pattern2 {
2545*4882a593Smuzhiyun char cmd[4];
2546*4882a593Smuzhiyun wl_wowl_pattern_t wowl_pattern;
2547*4882a593Smuzhiyun } wl_wowl_pattern2_t;
2548*4882a593Smuzhiyun static int
dhd_conf_wowl_pattern(dhd_pub_t * dhd,int ifidx,bool add,char * data)2549*4882a593Smuzhiyun dhd_conf_wowl_pattern(dhd_pub_t *dhd, int ifidx, bool add, char *data)
2550*4882a593Smuzhiyun {
2551*4882a593Smuzhiyun uint buf_len = 0;
2552*4882a593Smuzhiyun int id, type, polarity, offset;
2553*4882a593Smuzhiyun char cmd[4]="\0", mask[128]="\0", pattern[128]="\0", mask_tmp[128]="\0", *pmask_tmp;
2554*4882a593Smuzhiyun uint32 masksize, patternsize, pad_len = 0;
2555*4882a593Smuzhiyun wl_wowl_pattern2_t *wowl_pattern2 = NULL;
2556*4882a593Smuzhiyun char *mask_and_pattern;
2557*4882a593Smuzhiyun int ret = 0, i, j, v;
2558*4882a593Smuzhiyun
2559*4882a593Smuzhiyun if (data) {
2560*4882a593Smuzhiyun if (add)
2561*4882a593Smuzhiyun strcpy(cmd, "add");
2562*4882a593Smuzhiyun else
2563*4882a593Smuzhiyun strcpy(cmd, "clr");
2564*4882a593Smuzhiyun if (!strcmp(cmd, "clr")) {
2565*4882a593Smuzhiyun CONFIG_TRACE("wowl_pattern clr\n");
2566*4882a593Smuzhiyun ret = dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_VAR, "wowl_pattern", cmd,
2567*4882a593Smuzhiyun sizeof(cmd), FALSE);
2568*4882a593Smuzhiyun goto exit;
2569*4882a593Smuzhiyun }
2570*4882a593Smuzhiyun sscanf(data, "%d %d %d %d %s %s", &id, &type, &polarity, &offset,
2571*4882a593Smuzhiyun mask_tmp, pattern);
2572*4882a593Smuzhiyun masksize = strlen(mask_tmp) -2;
2573*4882a593Smuzhiyun CONFIG_TRACE("0 mask_tmp=%s, masksize=%d\n", mask_tmp, masksize);
2574*4882a593Smuzhiyun
2575*4882a593Smuzhiyun // add pading
2576*4882a593Smuzhiyun if (masksize % 16)
2577*4882a593Smuzhiyun pad_len = (16 - masksize % 16);
2578*4882a593Smuzhiyun for (i=0; i<pad_len; i++)
2579*4882a593Smuzhiyun strcat(mask_tmp, "0");
2580*4882a593Smuzhiyun masksize += pad_len;
2581*4882a593Smuzhiyun CONFIG_TRACE("1 mask_tmp=%s, masksize=%d\n", mask_tmp, masksize);
2582*4882a593Smuzhiyun
2583*4882a593Smuzhiyun // translate 0x00 to 0, others to 1
2584*4882a593Smuzhiyun j = 0;
2585*4882a593Smuzhiyun pmask_tmp = &mask_tmp[2];
2586*4882a593Smuzhiyun for (i=0; i<masksize/2; i++) {
2587*4882a593Smuzhiyun if(strncmp(&pmask_tmp[i*2], "00", 2))
2588*4882a593Smuzhiyun pmask_tmp[j] = '1';
2589*4882a593Smuzhiyun else
2590*4882a593Smuzhiyun pmask_tmp[j] = '0';
2591*4882a593Smuzhiyun j++;
2592*4882a593Smuzhiyun }
2593*4882a593Smuzhiyun pmask_tmp[j] = '\0';
2594*4882a593Smuzhiyun masksize = masksize / 2;
2595*4882a593Smuzhiyun CONFIG_TRACE("2 mask_tmp=%s, masksize=%d\n", mask_tmp, masksize);
2596*4882a593Smuzhiyun
2597*4882a593Smuzhiyun // reorder per 8bits
2598*4882a593Smuzhiyun pmask_tmp = &mask_tmp[2];
2599*4882a593Smuzhiyun for (i=0; i<masksize/8; i++) {
2600*4882a593Smuzhiyun char c;
2601*4882a593Smuzhiyun for (j=0; j<4; j++) {
2602*4882a593Smuzhiyun c = pmask_tmp[i*8+j];
2603*4882a593Smuzhiyun pmask_tmp[i*8+j] = pmask_tmp[(i+1)*8-j-1];
2604*4882a593Smuzhiyun pmask_tmp[(i+1)*8-j-1] = c;
2605*4882a593Smuzhiyun }
2606*4882a593Smuzhiyun }
2607*4882a593Smuzhiyun CONFIG_TRACE("3 mask_tmp=%s, masksize=%d\n", mask_tmp, masksize);
2608*4882a593Smuzhiyun
2609*4882a593Smuzhiyun // translate 8bits to 1byte
2610*4882a593Smuzhiyun j = 0; v = 0;
2611*4882a593Smuzhiyun pmask_tmp = &mask_tmp[2];
2612*4882a593Smuzhiyun strcpy(mask, "0x");
2613*4882a593Smuzhiyun for (i=0; i<masksize; i++) {
2614*4882a593Smuzhiyun v = (v<<1) | (pmask_tmp[i]=='1');
2615*4882a593Smuzhiyun if (((i+1)%4) == 0) {
2616*4882a593Smuzhiyun if (v < 10)
2617*4882a593Smuzhiyun mask[j+2] = v + '0';
2618*4882a593Smuzhiyun else
2619*4882a593Smuzhiyun mask[j+2] = (v-10) + 'a';
2620*4882a593Smuzhiyun j++;
2621*4882a593Smuzhiyun v = 0;
2622*4882a593Smuzhiyun }
2623*4882a593Smuzhiyun }
2624*4882a593Smuzhiyun mask[j+2] = '\0';
2625*4882a593Smuzhiyun masksize = j/2;
2626*4882a593Smuzhiyun CONFIG_TRACE("4 mask=%s, masksize=%d\n", mask, masksize);
2627*4882a593Smuzhiyun
2628*4882a593Smuzhiyun patternsize = (strlen(pattern)-2)/2;
2629*4882a593Smuzhiyun buf_len = sizeof(wl_wowl_pattern2_t) + patternsize + masksize;
2630*4882a593Smuzhiyun wowl_pattern2 = kmalloc(buf_len, GFP_KERNEL);
2631*4882a593Smuzhiyun if (wowl_pattern2 == NULL) {
2632*4882a593Smuzhiyun CONFIG_ERROR("Failed to allocate buffer of %d bytes\n", buf_len);
2633*4882a593Smuzhiyun goto exit;
2634*4882a593Smuzhiyun }
2635*4882a593Smuzhiyun memset(wowl_pattern2, 0, sizeof(wl_wowl_pattern2_t));
2636*4882a593Smuzhiyun
2637*4882a593Smuzhiyun strncpy(wowl_pattern2->cmd, cmd, sizeof(cmd));
2638*4882a593Smuzhiyun wowl_pattern2->wowl_pattern.id = id;
2639*4882a593Smuzhiyun wowl_pattern2->wowl_pattern.type = 0;
2640*4882a593Smuzhiyun wowl_pattern2->wowl_pattern.offset = offset;
2641*4882a593Smuzhiyun mask_and_pattern = (char*)wowl_pattern2 + sizeof(wl_wowl_pattern2_t);
2642*4882a593Smuzhiyun
2643*4882a593Smuzhiyun wowl_pattern2->wowl_pattern.masksize = masksize;
2644*4882a593Smuzhiyun ret = wl_pattern_atoh(mask, mask_and_pattern);
2645*4882a593Smuzhiyun if (ret == -1) {
2646*4882a593Smuzhiyun CONFIG_ERROR("rejecting mask=%s\n", mask);
2647*4882a593Smuzhiyun goto exit;
2648*4882a593Smuzhiyun }
2649*4882a593Smuzhiyun
2650*4882a593Smuzhiyun mask_and_pattern += wowl_pattern2->wowl_pattern.masksize;
2651*4882a593Smuzhiyun wowl_pattern2->wowl_pattern.patternoffset = sizeof(wl_wowl_pattern_t) +
2652*4882a593Smuzhiyun wowl_pattern2->wowl_pattern.masksize;
2653*4882a593Smuzhiyun
2654*4882a593Smuzhiyun wowl_pattern2->wowl_pattern.patternsize = patternsize;
2655*4882a593Smuzhiyun ret = wl_pattern_atoh(pattern, mask_and_pattern);
2656*4882a593Smuzhiyun if (ret == -1) {
2657*4882a593Smuzhiyun CONFIG_ERROR("rejecting pattern=%s\n", pattern);
2658*4882a593Smuzhiyun goto exit;
2659*4882a593Smuzhiyun }
2660*4882a593Smuzhiyun
2661*4882a593Smuzhiyun CONFIG_TRACE("%s %d %s %s\n", cmd, offset, mask, pattern);
2662*4882a593Smuzhiyun
2663*4882a593Smuzhiyun ret = dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_VAR, "wowl_pattern",
2664*4882a593Smuzhiyun (char *)wowl_pattern2, buf_len, FALSE);
2665*4882a593Smuzhiyun }
2666*4882a593Smuzhiyun
2667*4882a593Smuzhiyun exit:
2668*4882a593Smuzhiyun if (wowl_pattern2)
2669*4882a593Smuzhiyun kfree(wowl_pattern2);
2670*4882a593Smuzhiyun return ret;
2671*4882a593Smuzhiyun }
2672*4882a593Smuzhiyun
2673*4882a593Smuzhiyun static int
dhd_conf_wowl_wakeind(dhd_pub_t * dhd,int ifidx,bool clear)2674*4882a593Smuzhiyun dhd_conf_wowl_wakeind(dhd_pub_t *dhd, int ifidx, bool clear)
2675*4882a593Smuzhiyun {
2676*4882a593Smuzhiyun s8 iovar_buf[WLC_IOCTL_SMLEN];
2677*4882a593Smuzhiyun wl_wowl_wakeind_t *wake = NULL;
2678*4882a593Smuzhiyun int ret = -1;
2679*4882a593Smuzhiyun char clr[6]="clear", wakeind_str[32]="\0";
2680*4882a593Smuzhiyun
2681*4882a593Smuzhiyun if (clear) {
2682*4882a593Smuzhiyun CONFIG_TRACE("wowl_wakeind clear\n");
2683*4882a593Smuzhiyun ret = dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_VAR, "wowl_wakeind",
2684*4882a593Smuzhiyun clr, sizeof(clr), 0);
2685*4882a593Smuzhiyun } else {
2686*4882a593Smuzhiyun ret = dhd_conf_get_iovar(dhd, ifidx, WLC_GET_VAR, "wowl_wakeind",
2687*4882a593Smuzhiyun iovar_buf, sizeof(iovar_buf));
2688*4882a593Smuzhiyun if (!ret) {
2689*4882a593Smuzhiyun wake = (wl_wowl_wakeind_t *) iovar_buf;
2690*4882a593Smuzhiyun if (wake->ucode_wakeind & WL_WOWL_MAGIC)
2691*4882a593Smuzhiyun strcpy(wakeind_str, "(MAGIC packet)");
2692*4882a593Smuzhiyun if (wake->ucode_wakeind & WL_WOWL_NET)
2693*4882a593Smuzhiyun strcpy(wakeind_str, "(Netpattern)");
2694*4882a593Smuzhiyun if (wake->ucode_wakeind & WL_WOWL_DIS)
2695*4882a593Smuzhiyun strcpy(wakeind_str, "(Disassoc/Deauth)");
2696*4882a593Smuzhiyun if (wake->ucode_wakeind & WL_WOWL_BCN)
2697*4882a593Smuzhiyun strcpy(wakeind_str, "(Loss of beacon)");
2698*4882a593Smuzhiyun if (wake->ucode_wakeind & WL_WOWL_TCPKEEP_TIME)
2699*4882a593Smuzhiyun strcpy(wakeind_str, "(TCPKA timeout)");
2700*4882a593Smuzhiyun if (wake->ucode_wakeind & WL_WOWL_TCPKEEP_DATA)
2701*4882a593Smuzhiyun strcpy(wakeind_str, "(TCPKA data)");
2702*4882a593Smuzhiyun if (wake->ucode_wakeind & WL_WOWL_TCPFIN)
2703*4882a593Smuzhiyun strcpy(wakeind_str, "(TCP FIN)");
2704*4882a593Smuzhiyun CONFIG_MSG("wakeind=0x%x %s\n", wake->ucode_wakeind, wakeind_str);
2705*4882a593Smuzhiyun }
2706*4882a593Smuzhiyun }
2707*4882a593Smuzhiyun
2708*4882a593Smuzhiyun return ret;
2709*4882a593Smuzhiyun }
2710*4882a593Smuzhiyun #endif
2711*4882a593Smuzhiyun
2712*4882a593Smuzhiyun int
dhd_conf_mkeep_alive(dhd_pub_t * dhd,int ifidx,int id,int period,char * packet,bool bcast)2713*4882a593Smuzhiyun dhd_conf_mkeep_alive(dhd_pub_t *dhd, int ifidx, int id, int period,
2714*4882a593Smuzhiyun char *packet, bool bcast)
2715*4882a593Smuzhiyun {
2716*4882a593Smuzhiyun wl_mkeep_alive_pkt_v1_t *mkeep_alive_pktp;
2717*4882a593Smuzhiyun int ret = 0, len_bytes=0, buf_len=0;
2718*4882a593Smuzhiyun char *buf = NULL, *iovar_buf = NULL;
2719*4882a593Smuzhiyun uint8 *pdata;
2720*4882a593Smuzhiyun
2721*4882a593Smuzhiyun CONFIG_TRACE("id=%d, period=%d, packet=%s\n", id, period, packet);
2722*4882a593Smuzhiyun if (period >= 0) {
2723*4882a593Smuzhiyun buf = kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL);
2724*4882a593Smuzhiyun if (buf == NULL) {
2725*4882a593Smuzhiyun CONFIG_ERROR("Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN);
2726*4882a593Smuzhiyun goto exit;
2727*4882a593Smuzhiyun }
2728*4882a593Smuzhiyun iovar_buf = kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL);
2729*4882a593Smuzhiyun if (iovar_buf == NULL) {
2730*4882a593Smuzhiyun CONFIG_ERROR("Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN);
2731*4882a593Smuzhiyun goto exit;
2732*4882a593Smuzhiyun }
2733*4882a593Smuzhiyun mkeep_alive_pktp = (wl_mkeep_alive_pkt_v1_t *)buf;
2734*4882a593Smuzhiyun mkeep_alive_pktp->version = htod16(WL_MKEEP_ALIVE_VERSION_1);
2735*4882a593Smuzhiyun mkeep_alive_pktp->length = htod16(WL_MKEEP_ALIVE_FIXED_LEN);
2736*4882a593Smuzhiyun mkeep_alive_pktp->keep_alive_id = id;
2737*4882a593Smuzhiyun buf_len += WL_MKEEP_ALIVE_FIXED_LEN;
2738*4882a593Smuzhiyun mkeep_alive_pktp->period_msec = period;
2739*4882a593Smuzhiyun if (packet && strlen(packet)) {
2740*4882a593Smuzhiyun len_bytes = wl_pattern_atoh(packet, (char *)mkeep_alive_pktp->data);
2741*4882a593Smuzhiyun buf_len += len_bytes;
2742*4882a593Smuzhiyun if (bcast) {
2743*4882a593Smuzhiyun memcpy(mkeep_alive_pktp->data, ðer_bcast, ETHER_ADDR_LEN);
2744*4882a593Smuzhiyun }
2745*4882a593Smuzhiyun ret = dhd_conf_get_iovar(dhd, ifidx, WLC_GET_VAR, "cur_etheraddr",
2746*4882a593Smuzhiyun iovar_buf, WLC_IOCTL_SMLEN);
2747*4882a593Smuzhiyun if (!ret) {
2748*4882a593Smuzhiyun pdata = mkeep_alive_pktp->data;
2749*4882a593Smuzhiyun memcpy(pdata+6, iovar_buf, ETHER_ADDR_LEN);
2750*4882a593Smuzhiyun }
2751*4882a593Smuzhiyun }
2752*4882a593Smuzhiyun mkeep_alive_pktp->len_bytes = htod16(len_bytes);
2753*4882a593Smuzhiyun ret = dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_VAR, "mkeep_alive",
2754*4882a593Smuzhiyun buf, buf_len, FALSE);
2755*4882a593Smuzhiyun }
2756*4882a593Smuzhiyun
2757*4882a593Smuzhiyun exit:
2758*4882a593Smuzhiyun if (buf)
2759*4882a593Smuzhiyun kfree(buf);
2760*4882a593Smuzhiyun if (iovar_buf)
2761*4882a593Smuzhiyun kfree(iovar_buf);
2762*4882a593Smuzhiyun return ret;
2763*4882a593Smuzhiyun }
2764*4882a593Smuzhiyun
2765*4882a593Smuzhiyun #ifdef ARP_OFFLOAD_SUPPORT
2766*4882a593Smuzhiyun void
dhd_conf_set_garp(dhd_pub_t * dhd,int ifidx,uint32 ipa,bool enable)2767*4882a593Smuzhiyun dhd_conf_set_garp(dhd_pub_t *dhd, int ifidx, uint32 ipa, bool enable)
2768*4882a593Smuzhiyun {
2769*4882a593Smuzhiyun int i, len = 0, total_len = WLC_IOCTL_SMLEN;
2770*4882a593Smuzhiyun char *iovar_buf = NULL, *packet = NULL;
2771*4882a593Smuzhiyun
2772*4882a593Smuzhiyun if (!dhd->conf->garp || ifidx != 0 || !(dhd->op_mode & DHD_FLAG_STA_MODE))
2773*4882a593Smuzhiyun return;
2774*4882a593Smuzhiyun
2775*4882a593Smuzhiyun CONFIG_TRACE("enable=%d\n", enable);
2776*4882a593Smuzhiyun
2777*4882a593Smuzhiyun if (enable) {
2778*4882a593Smuzhiyun iovar_buf = kmalloc(total_len, GFP_KERNEL);
2779*4882a593Smuzhiyun if (iovar_buf == NULL) {
2780*4882a593Smuzhiyun CONFIG_ERROR("Failed to allocate buffer of %d bytes\n", total_len);
2781*4882a593Smuzhiyun goto exit;
2782*4882a593Smuzhiyun }
2783*4882a593Smuzhiyun packet = kmalloc(total_len, GFP_KERNEL);
2784*4882a593Smuzhiyun if (packet == NULL) {
2785*4882a593Smuzhiyun CONFIG_ERROR("Failed to allocate buffer of %d bytes\n", total_len);
2786*4882a593Smuzhiyun goto exit;
2787*4882a593Smuzhiyun }
2788*4882a593Smuzhiyun dhd_conf_get_iovar(dhd, ifidx, WLC_GET_VAR, "cur_etheraddr", iovar_buf, total_len);
2789*4882a593Smuzhiyun
2790*4882a593Smuzhiyun len += snprintf(packet+len, total_len, "0xffffffffffff");
2791*4882a593Smuzhiyun for (i=0; i<ETHER_ADDR_LEN; i++)
2792*4882a593Smuzhiyun len += snprintf(packet+len, total_len, "%02x", iovar_buf[i]);
2793*4882a593Smuzhiyun len += snprintf(packet+len, total_len, "08060001080006040001");
2794*4882a593Smuzhiyun // Sender Hardware Addr.
2795*4882a593Smuzhiyun for (i=0; i<ETHER_ADDR_LEN; i++)
2796*4882a593Smuzhiyun len += snprintf(packet+len, total_len, "%02x", iovar_buf[i]);
2797*4882a593Smuzhiyun // Sender IP Addr.
2798*4882a593Smuzhiyun len += snprintf(packet+len, total_len, "%02x%02x%02x%02x",
2799*4882a593Smuzhiyun ipa&0xff, (ipa>>8)&0xff, (ipa>>16)&0xff, (ipa>>24)&0xff);
2800*4882a593Smuzhiyun // Target Hardware Addr.
2801*4882a593Smuzhiyun len += snprintf(packet+len, total_len, "ffffffffffff");
2802*4882a593Smuzhiyun // Target IP Addr.
2803*4882a593Smuzhiyun len += snprintf(packet+len, total_len, "%02x%02x%02x%02x",
2804*4882a593Smuzhiyun ipa&0xff, (ipa>>8)&0xff, (ipa>>16)&0xff, (ipa>>24)&0xff);
2805*4882a593Smuzhiyun len += snprintf(packet+len, total_len, "000000000000000000000000000000000000");
2806*4882a593Smuzhiyun }
2807*4882a593Smuzhiyun
2808*4882a593Smuzhiyun dhd_conf_mkeep_alive(dhd, ifidx, 0, dhd->conf->keep_alive_period, packet, TRUE);
2809*4882a593Smuzhiyun
2810*4882a593Smuzhiyun exit:
2811*4882a593Smuzhiyun if (iovar_buf)
2812*4882a593Smuzhiyun kfree(iovar_buf);
2813*4882a593Smuzhiyun if (packet)
2814*4882a593Smuzhiyun kfree(packet);
2815*4882a593Smuzhiyun return;
2816*4882a593Smuzhiyun }
2817*4882a593Smuzhiyun #endif
2818*4882a593Smuzhiyun
2819*4882a593Smuzhiyun uint
dhd_conf_get_insuspend(dhd_pub_t * dhd,uint mask)2820*4882a593Smuzhiyun dhd_conf_get_insuspend(dhd_pub_t *dhd, uint mask)
2821*4882a593Smuzhiyun {
2822*4882a593Smuzhiyun uint insuspend = 0;
2823*4882a593Smuzhiyun
2824*4882a593Smuzhiyun if (dhd->op_mode & DHD_FLAG_STA_MODE) {
2825*4882a593Smuzhiyun insuspend = dhd->conf->insuspend &
2826*4882a593Smuzhiyun (NO_EVENT_IN_SUSPEND | NO_TXDATA_IN_SUSPEND | NO_TXCTL_IN_SUSPEND |
2827*4882a593Smuzhiyun ROAM_OFFLOAD_IN_SUSPEND | WOWL_IN_SUSPEND);
2828*4882a593Smuzhiyun } else if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
2829*4882a593Smuzhiyun insuspend = dhd->conf->insuspend &
2830*4882a593Smuzhiyun (NO_EVENT_IN_SUSPEND | NO_TXDATA_IN_SUSPEND | NO_TXCTL_IN_SUSPEND |
2831*4882a593Smuzhiyun AP_DOWN_IN_SUSPEND | AP_FILTER_IN_SUSPEND);
2832*4882a593Smuzhiyun }
2833*4882a593Smuzhiyun
2834*4882a593Smuzhiyun return (insuspend & mask);
2835*4882a593Smuzhiyun }
2836*4882a593Smuzhiyun
2837*4882a593Smuzhiyun static void
dhd_conf_check_connection(dhd_pub_t * dhd,int ifidx,int suspend)2838*4882a593Smuzhiyun dhd_conf_check_connection(dhd_pub_t *dhd, int ifidx, int suspend)
2839*4882a593Smuzhiyun {
2840*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
2841*4882a593Smuzhiyun struct ether_addr bssid;
2842*4882a593Smuzhiyun wl_event_msg_t msg;
2843*4882a593Smuzhiyun int pm;
2844*4882a593Smuzhiyun #ifdef WL_CFG80211
2845*4882a593Smuzhiyun struct net_device *net;
2846*4882a593Smuzhiyun unsigned long flags = 0;
2847*4882a593Smuzhiyun #endif /* defined(WL_CFG80211) */
2848*4882a593Smuzhiyun
2849*4882a593Smuzhiyun if (suspend) {
2850*4882a593Smuzhiyun memset(&bssid, 0, ETHER_ADDR_LEN);
2851*4882a593Smuzhiyun dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, FALSE, ifidx);
2852*4882a593Smuzhiyun if (memcmp(ðer_null, &bssid, ETHER_ADDR_LEN))
2853*4882a593Smuzhiyun memcpy(&conf->bssid_insuspend, &bssid, ETHER_ADDR_LEN);
2854*4882a593Smuzhiyun else
2855*4882a593Smuzhiyun memset(&conf->bssid_insuspend, 0, ETHER_ADDR_LEN);
2856*4882a593Smuzhiyun }
2857*4882a593Smuzhiyun else {
2858*4882a593Smuzhiyun if (memcmp(ðer_null, &conf->bssid_insuspend, ETHER_ADDR_LEN)) {
2859*4882a593Smuzhiyun memset(&bssid, 0, ETHER_ADDR_LEN);
2860*4882a593Smuzhiyun dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, FALSE, ifidx);
2861*4882a593Smuzhiyun if (memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) {
2862*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_PM, "WLC_SET_PM", 0, 0, FALSE);
2863*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_VAR, "send_nulldata",
2864*4882a593Smuzhiyun (char *)&bssid, ETHER_ADDR_LEN, FALSE);
2865*4882a593Smuzhiyun OSL_SLEEP(100);
2866*4882a593Smuzhiyun if (conf->pm >= 0)
2867*4882a593Smuzhiyun pm = conf->pm;
2868*4882a593Smuzhiyun else
2869*4882a593Smuzhiyun pm = PM_FAST;
2870*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_PM, "WLC_SET_PM", pm, 0, FALSE);
2871*4882a593Smuzhiyun } else {
2872*4882a593Smuzhiyun CONFIG_TRACE("send WLC_E_DEAUTH_IND event\n");
2873*4882a593Smuzhiyun bzero(&msg, sizeof(wl_event_msg_t));
2874*4882a593Smuzhiyun msg.ifidx = ifidx;
2875*4882a593Smuzhiyun memcpy(&msg.addr, &conf->bssid_insuspend, ETHER_ADDR_LEN);
2876*4882a593Smuzhiyun msg.event_type = hton32(WLC_E_DEAUTH_IND);
2877*4882a593Smuzhiyun msg.status = 0;
2878*4882a593Smuzhiyun msg.reason = hton32(DOT11_RC_DEAUTH_LEAVING);
2879*4882a593Smuzhiyun #ifdef WL_EVENT
2880*4882a593Smuzhiyun wl_ext_event_send(dhd->event_params, &msg, NULL);
2881*4882a593Smuzhiyun #endif
2882*4882a593Smuzhiyun #ifdef WL_CFG80211
2883*4882a593Smuzhiyun spin_lock_irqsave(&dhd->up_lock, flags);
2884*4882a593Smuzhiyun net = dhd_idx2net(dhd, ifidx);
2885*4882a593Smuzhiyun if (net && dhd->up) {
2886*4882a593Smuzhiyun wl_cfg80211_event(net, &msg, NULL);
2887*4882a593Smuzhiyun }
2888*4882a593Smuzhiyun spin_unlock_irqrestore(&dhd->up_lock, flags);
2889*4882a593Smuzhiyun #endif /* defined(WL_CFG80211) */
2890*4882a593Smuzhiyun }
2891*4882a593Smuzhiyun }
2892*4882a593Smuzhiyun }
2893*4882a593Smuzhiyun }
2894*4882a593Smuzhiyun
2895*4882a593Smuzhiyun #ifdef SUSPEND_EVENT
2896*4882a593Smuzhiyun static void
dhd_conf_set_suspend_event(dhd_pub_t * dhd,int suspend)2897*4882a593Smuzhiyun dhd_conf_set_suspend_event(dhd_pub_t *dhd, int suspend)
2898*4882a593Smuzhiyun {
2899*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
2900*4882a593Smuzhiyun char suspend_eventmask[WL_EVENTING_MASK_LEN];
2901*4882a593Smuzhiyun
2902*4882a593Smuzhiyun CONFIG_TRACE("Enter\n");
2903*4882a593Smuzhiyun if (suspend) {
2904*4882a593Smuzhiyun #ifdef PROP_TXSTATUS
2905*4882a593Smuzhiyun #if defined(BCMSDIO) || defined(BCMDBUS)
2906*4882a593Smuzhiyun if (dhd->wlfc_enabled) {
2907*4882a593Smuzhiyun dhd_wlfc_deinit(dhd);
2908*4882a593Smuzhiyun conf->wlfc = TRUE;
2909*4882a593Smuzhiyun } else {
2910*4882a593Smuzhiyun conf->wlfc = FALSE;
2911*4882a593Smuzhiyun }
2912*4882a593Smuzhiyun #endif /* BCMSDIO || BCMDBUS */
2913*4882a593Smuzhiyun #endif /* PROP_TXSTATUS */
2914*4882a593Smuzhiyun dhd_conf_get_iovar(dhd, 0, WLC_GET_VAR, "event_msgs",
2915*4882a593Smuzhiyun conf->resume_eventmask, sizeof(conf->resume_eventmask));
2916*4882a593Smuzhiyun memset(suspend_eventmask, 0, sizeof(suspend_eventmask));
2917*4882a593Smuzhiyun setbit(suspend_eventmask, WLC_E_ESCAN_RESULT);
2918*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "event_msgs",
2919*4882a593Smuzhiyun suspend_eventmask, sizeof(suspend_eventmask), FALSE);
2920*4882a593Smuzhiyun }
2921*4882a593Smuzhiyun else {
2922*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "event_msgs",
2923*4882a593Smuzhiyun conf->resume_eventmask, sizeof(conf->resume_eventmask), FALSE);
2924*4882a593Smuzhiyun #ifdef PROP_TXSTATUS
2925*4882a593Smuzhiyun #if defined(BCMSDIO) || defined(BCMDBUS)
2926*4882a593Smuzhiyun if (conf->wlfc) {
2927*4882a593Smuzhiyun dhd_wlfc_init(dhd);
2928*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, 0, WLC_UP, "WLC_UP", 0, 0, FALSE);
2929*4882a593Smuzhiyun }
2930*4882a593Smuzhiyun #endif
2931*4882a593Smuzhiyun #endif /* PROP_TXSTATUS */
2932*4882a593Smuzhiyun }
2933*4882a593Smuzhiyun
2934*4882a593Smuzhiyun }
2935*4882a593Smuzhiyun #endif
2936*4882a593Smuzhiyun
2937*4882a593Smuzhiyun int
dhd_conf_suspend_resume_sta(dhd_pub_t * dhd,int ifidx,int suspend)2938*4882a593Smuzhiyun dhd_conf_suspend_resume_sta(dhd_pub_t *dhd, int ifidx, int suspend)
2939*4882a593Smuzhiyun {
2940*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
2941*4882a593Smuzhiyun uint insuspend = 0;
2942*4882a593Smuzhiyun int pm;
2943*4882a593Smuzhiyun #ifdef WL_EXT_WOWL
2944*4882a593Smuzhiyun int i;
2945*4882a593Smuzhiyun #endif
2946*4882a593Smuzhiyun
2947*4882a593Smuzhiyun insuspend = dhd_conf_get_insuspend(dhd, ALL_IN_SUSPEND);
2948*4882a593Smuzhiyun if (insuspend)
2949*4882a593Smuzhiyun WL_MSG(dhd_ifname(dhd, ifidx), "suspend %d\n", suspend);
2950*4882a593Smuzhiyun
2951*4882a593Smuzhiyun if (suspend) {
2952*4882a593Smuzhiyun dhd_conf_check_connection(dhd, ifidx, suspend);
2953*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "roam_off",
2954*4882a593Smuzhiyun conf->roam_off_suspend, 0, FALSE);
2955*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "bcn_li_dtim",
2956*4882a593Smuzhiyun conf->suspend_bcn_li_dtim, 0, FALSE);
2957*4882a593Smuzhiyun if (conf->pm_in_suspend >= 0)
2958*4882a593Smuzhiyun pm = conf->pm_in_suspend;
2959*4882a593Smuzhiyun else if (conf->pm >= 0)
2960*4882a593Smuzhiyun pm = conf->pm;
2961*4882a593Smuzhiyun else
2962*4882a593Smuzhiyun pm = PM_FAST;
2963*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_PM, "WLC_SET_PM", pm, 0, FALSE);
2964*4882a593Smuzhiyun #ifdef WL_EXT_WOWL
2965*4882a593Smuzhiyun if ((insuspend & WOWL_IN_SUSPEND) && dhd_master_mode) {
2966*4882a593Smuzhiyun dhd_conf_wowl_pattern(dhd, ifidx, FALSE, "clr");
2967*4882a593Smuzhiyun for(i=0; i<conf->pkt_filter_add.count; i++) {
2968*4882a593Smuzhiyun dhd_conf_wowl_pattern(dhd, ifidx, TRUE, conf->pkt_filter_add.filter[i]);
2969*4882a593Smuzhiyun }
2970*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "wowl", conf->wowl, 0, FALSE);
2971*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "wowl_activate", 1, 0, FALSE);
2972*4882a593Smuzhiyun dhd_conf_wowl_wakeind(dhd, ifidx, TRUE);
2973*4882a593Smuzhiyun }
2974*4882a593Smuzhiyun #endif
2975*4882a593Smuzhiyun }
2976*4882a593Smuzhiyun else {
2977*4882a593Smuzhiyun dhd_conf_get_iovar(dhd, ifidx, WLC_GET_PM, "WLC_GET_PM", (char *)&pm, sizeof(pm));
2978*4882a593Smuzhiyun CONFIG_TRACE("PM in suspend = %d\n", pm);
2979*4882a593Smuzhiyun if (conf->pm >= 0)
2980*4882a593Smuzhiyun pm = conf->pm;
2981*4882a593Smuzhiyun else
2982*4882a593Smuzhiyun pm = PM_FAST;
2983*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_PM, "WLC_SET_PM", pm, 0, FALSE);
2984*4882a593Smuzhiyun #ifdef WL_EXT_WOWL
2985*4882a593Smuzhiyun if (insuspend & WOWL_IN_SUSPEND) {
2986*4882a593Smuzhiyun dhd_conf_wowl_wakeind(dhd, ifidx, FALSE);
2987*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "wowl_activate", 0, 0, FALSE);
2988*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "wowl", 0, 0, FALSE);
2989*4882a593Smuzhiyun dhd_conf_wowl_pattern(dhd, ifidx, FALSE, "clr");
2990*4882a593Smuzhiyun }
2991*4882a593Smuzhiyun #endif
2992*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "bcn_li_dtim", 0, 0, FALSE);
2993*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "roam_off",
2994*4882a593Smuzhiyun conf->roam_off, 0, FALSE);
2995*4882a593Smuzhiyun dhd_conf_check_connection(dhd, ifidx, suspend);
2996*4882a593Smuzhiyun }
2997*4882a593Smuzhiyun
2998*4882a593Smuzhiyun return 0;
2999*4882a593Smuzhiyun }
3000*4882a593Smuzhiyun
3001*4882a593Smuzhiyun #ifndef WL_EXT_IAPSTA
3002*4882a593Smuzhiyun static int
dhd_conf_suspend_resume_ap(dhd_pub_t * dhd,int ifidx,int suspend)3003*4882a593Smuzhiyun dhd_conf_suspend_resume_ap(dhd_pub_t *dhd, int ifidx, int suspend)
3004*4882a593Smuzhiyun {
3005*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
3006*4882a593Smuzhiyun uint insuspend = 0;
3007*4882a593Smuzhiyun
3008*4882a593Smuzhiyun insuspend = dhd_conf_get_insuspend(dhd, ALL_IN_SUSPEND);
3009*4882a593Smuzhiyun if (insuspend)
3010*4882a593Smuzhiyun WL_MSG(dhd_ifname(dhd, ifidx), "suspend %d\n", suspend);
3011*4882a593Smuzhiyun
3012*4882a593Smuzhiyun if (suspend) {
3013*4882a593Smuzhiyun if (insuspend & AP_DOWN_IN_SUSPEND) {
3014*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_DOWN, "WLC_DOWN", 1, 0, FALSE);
3015*4882a593Smuzhiyun }
3016*4882a593Smuzhiyun } else {
3017*4882a593Smuzhiyun if (insuspend & AP_DOWN_IN_SUSPEND) {
3018*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_UP, "WLC_UP", 0, 0, FALSE);
3019*4882a593Smuzhiyun }
3020*4882a593Smuzhiyun }
3021*4882a593Smuzhiyun
3022*4882a593Smuzhiyun return 0;
3023*4882a593Smuzhiyun }
3024*4882a593Smuzhiyun #endif /* !WL_EXT_IAPSTA */
3025*4882a593Smuzhiyun
3026*4882a593Smuzhiyun static int
dhd_conf_suspend_resume_bus(dhd_pub_t * dhd,int suspend)3027*4882a593Smuzhiyun dhd_conf_suspend_resume_bus(dhd_pub_t *dhd, int suspend)
3028*4882a593Smuzhiyun {
3029*4882a593Smuzhiyun uint insuspend = 0;
3030*4882a593Smuzhiyun
3031*4882a593Smuzhiyun insuspend = dhd_conf_get_insuspend(dhd, ALL_IN_SUSPEND);
3032*4882a593Smuzhiyun if (insuspend)
3033*4882a593Smuzhiyun CONFIG_MSG("suspend %d\n", suspend);
3034*4882a593Smuzhiyun
3035*4882a593Smuzhiyun if (suspend) {
3036*4882a593Smuzhiyun if (insuspend & (WOWL_IN_SUSPEND | NO_TXCTL_IN_SUSPEND)) {
3037*4882a593Smuzhiyun #ifdef BCMSDIO
3038*4882a593Smuzhiyun uint32 intstatus = 0;
3039*4882a593Smuzhiyun int ret = 0;
3040*4882a593Smuzhiyun #endif
3041*4882a593Smuzhiyun int hostsleep = 2;
3042*4882a593Smuzhiyun #ifdef WL_EXT_WOWL
3043*4882a593Smuzhiyun hostsleep = 1;
3044*4882a593Smuzhiyun #endif
3045*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "hostsleep", hostsleep, 0, FALSE);
3046*4882a593Smuzhiyun #ifdef BCMSDIO
3047*4882a593Smuzhiyun ret = dhd_bus_sleep(dhd, TRUE, &intstatus);
3048*4882a593Smuzhiyun CONFIG_TRACE("ret = %d, intstatus = 0x%x\n", ret, intstatus);
3049*4882a593Smuzhiyun #endif
3050*4882a593Smuzhiyun }
3051*4882a593Smuzhiyun } else {
3052*4882a593Smuzhiyun if (insuspend & (WOWL_IN_SUSPEND | NO_TXCTL_IN_SUSPEND)) {
3053*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "hostsleep", 0, 0, FALSE);
3054*4882a593Smuzhiyun }
3055*4882a593Smuzhiyun }
3056*4882a593Smuzhiyun
3057*4882a593Smuzhiyun return 0;
3058*4882a593Smuzhiyun }
3059*4882a593Smuzhiyun
3060*4882a593Smuzhiyun int
dhd_conf_set_suspend_resume(dhd_pub_t * dhd,int suspend)3061*4882a593Smuzhiyun dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int suspend)
3062*4882a593Smuzhiyun {
3063*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
3064*4882a593Smuzhiyun uint insuspend = 0;
3065*4882a593Smuzhiyun
3066*4882a593Smuzhiyun insuspend = dhd_conf_get_insuspend(dhd, ALL_IN_SUSPEND);
3067*4882a593Smuzhiyun if (insuspend)
3068*4882a593Smuzhiyun CONFIG_MSG("op_mode %d, suspend %d, suspended %d, insuspend 0x%x, suspend_mode=%d\n",
3069*4882a593Smuzhiyun dhd->op_mode, suspend, conf->suspended, insuspend, conf->suspend_mode);
3070*4882a593Smuzhiyun
3071*4882a593Smuzhiyun if (conf->suspended == suspend || !dhd->up) {
3072*4882a593Smuzhiyun return 0;
3073*4882a593Smuzhiyun }
3074*4882a593Smuzhiyun
3075*4882a593Smuzhiyun if (suspend) {
3076*4882a593Smuzhiyun if (insuspend & (NO_EVENT_IN_SUSPEND|NO_TXCTL_IN_SUSPEND|WOWL_IN_SUSPEND)) {
3077*4882a593Smuzhiyun if (conf->suspend_mode == PM_NOTIFIER)
3078*4882a593Smuzhiyun #ifdef WL_EXT_IAPSTA
3079*4882a593Smuzhiyun wl_iapsta_wait_event_complete(dhd);
3080*4882a593Smuzhiyun #else
3081*4882a593Smuzhiyun wl_ext_wait_event_complete(dhd, 0);
3082*4882a593Smuzhiyun #endif /* WL_EXT_IAPSTA */
3083*4882a593Smuzhiyun }
3084*4882a593Smuzhiyun if (insuspend & NO_TXDATA_IN_SUSPEND) {
3085*4882a593Smuzhiyun dhd_txflowcontrol(dhd, ALL_INTERFACES, ON);
3086*4882a593Smuzhiyun }
3087*4882a593Smuzhiyun #if defined(WL_CFG80211) || defined(WL_ESCAN)
3088*4882a593Smuzhiyun if (insuspend & (NO_EVENT_IN_SUSPEND|NO_TXCTL_IN_SUSPEND|WOWL_IN_SUSPEND)) {
3089*4882a593Smuzhiyun if (conf->suspend_mode == PM_NOTIFIER)
3090*4882a593Smuzhiyun wl_ext_user_sync(dhd, 0, TRUE);
3091*4882a593Smuzhiyun }
3092*4882a593Smuzhiyun #endif
3093*4882a593Smuzhiyun if (insuspend & ROAM_OFFLOAD_IN_SUSPEND)
3094*4882a593Smuzhiyun dhd_conf_enable_roam_offload(dhd, 2);
3095*4882a593Smuzhiyun #ifdef SUSPEND_EVENT
3096*4882a593Smuzhiyun if (insuspend & NO_EVENT_IN_SUSPEND) {
3097*4882a593Smuzhiyun dhd_conf_set_suspend_event(dhd, suspend);
3098*4882a593Smuzhiyun }
3099*4882a593Smuzhiyun #endif
3100*4882a593Smuzhiyun #ifdef WL_EXT_IAPSTA
3101*4882a593Smuzhiyun wl_iapsta_suspend_resume(dhd, suspend);
3102*4882a593Smuzhiyun #else
3103*4882a593Smuzhiyun if (dhd->op_mode & DHD_FLAG_STA_MODE) {
3104*4882a593Smuzhiyun dhd_conf_suspend_resume_sta(dhd, 0, suspend);
3105*4882a593Smuzhiyun } else if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
3106*4882a593Smuzhiyun dhd_conf_suspend_resume_ap(dhd, 0, suspend);
3107*4882a593Smuzhiyun }
3108*4882a593Smuzhiyun #endif /* WL_EXT_IAPSTA */
3109*4882a593Smuzhiyun dhd_conf_set_wl_cmd(dhd, conf->wl_suspend, FALSE);
3110*4882a593Smuzhiyun dhd_conf_suspend_resume_bus(dhd, suspend);
3111*4882a593Smuzhiyun conf->suspended = TRUE;
3112*4882a593Smuzhiyun }
3113*4882a593Smuzhiyun else {
3114*4882a593Smuzhiyun dhd_conf_suspend_resume_bus(dhd, suspend);
3115*4882a593Smuzhiyun #ifdef SUSPEND_EVENT
3116*4882a593Smuzhiyun if (insuspend & NO_EVENT_IN_SUSPEND) {
3117*4882a593Smuzhiyun dhd_conf_set_suspend_event(dhd, suspend);
3118*4882a593Smuzhiyun }
3119*4882a593Smuzhiyun #endif
3120*4882a593Smuzhiyun if (insuspend & ROAM_OFFLOAD_IN_SUSPEND)
3121*4882a593Smuzhiyun dhd_conf_enable_roam_offload(dhd, 0);
3122*4882a593Smuzhiyun dhd_conf_set_wl_cmd(dhd, conf->wl_resume, FALSE);
3123*4882a593Smuzhiyun #ifdef WL_EXT_IAPSTA
3124*4882a593Smuzhiyun wl_iapsta_suspend_resume(dhd, suspend);
3125*4882a593Smuzhiyun #else
3126*4882a593Smuzhiyun if (dhd->op_mode & DHD_FLAG_STA_MODE) {
3127*4882a593Smuzhiyun dhd_conf_suspend_resume_sta(dhd, 0, suspend);
3128*4882a593Smuzhiyun } else if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
3129*4882a593Smuzhiyun dhd_conf_suspend_resume_ap(dhd, 0, suspend);
3130*4882a593Smuzhiyun }
3131*4882a593Smuzhiyun #endif /* WL_EXT_IAPSTA */
3132*4882a593Smuzhiyun #if defined(WL_CFG80211) || defined(WL_ESCAN)
3133*4882a593Smuzhiyun if (insuspend & (NO_EVENT_IN_SUSPEND|NO_TXCTL_IN_SUSPEND|WOWL_IN_SUSPEND)) {
3134*4882a593Smuzhiyun if (conf->suspend_mode == PM_NOTIFIER)
3135*4882a593Smuzhiyun wl_ext_user_sync(dhd, 0, FALSE);
3136*4882a593Smuzhiyun }
3137*4882a593Smuzhiyun #endif
3138*4882a593Smuzhiyun if (insuspend & NO_TXDATA_IN_SUSPEND) {
3139*4882a593Smuzhiyun dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF);
3140*4882a593Smuzhiyun }
3141*4882a593Smuzhiyun conf->suspended = FALSE;
3142*4882a593Smuzhiyun }
3143*4882a593Smuzhiyun
3144*4882a593Smuzhiyun return 0;
3145*4882a593Smuzhiyun }
3146*4882a593Smuzhiyun
3147*4882a593Smuzhiyun #ifdef PROP_TXSTATUS
3148*4882a593Smuzhiyun int
dhd_conf_get_disable_proptx(dhd_pub_t * dhd)3149*4882a593Smuzhiyun dhd_conf_get_disable_proptx(dhd_pub_t *dhd)
3150*4882a593Smuzhiyun {
3151*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
3152*4882a593Smuzhiyun int disable_proptx = -1;
3153*4882a593Smuzhiyun int fw_proptx = 0;
3154*4882a593Smuzhiyun
3155*4882a593Smuzhiyun /* check fw proptx priority:
3156*4882a593Smuzhiyun * 1st: check fw support by wl cap
3157*4882a593Smuzhiyun * 2nd: 4334/43340/43341/43241 support proptx but not show in wl cap, so enable it by default
3158*4882a593Smuzhiyun * if you would like to disable it, please set disable_proptx=1 in config.txt
3159*4882a593Smuzhiyun * 3th: disable when proptxstatus not support in wl cap
3160*4882a593Smuzhiyun */
3161*4882a593Smuzhiyun if (FW_SUPPORTED(dhd, proptxstatus)) {
3162*4882a593Smuzhiyun fw_proptx = 1;
3163*4882a593Smuzhiyun } else if (conf->chip == BCM4334_CHIP_ID || conf->chip == BCM43340_CHIP_ID ||
3164*4882a593Smuzhiyun dhd->conf->chip == BCM43340_CHIP_ID || conf->chip == BCM4324_CHIP_ID) {
3165*4882a593Smuzhiyun fw_proptx = 1;
3166*4882a593Smuzhiyun } else {
3167*4882a593Smuzhiyun fw_proptx = 0;
3168*4882a593Smuzhiyun }
3169*4882a593Smuzhiyun
3170*4882a593Smuzhiyun /* returned disable_proptx value:
3171*4882a593Smuzhiyun * -1: disable in STA and enable in P2P(follow original dhd settings when PROP_TXSTATUS_VSDB enabled)
3172*4882a593Smuzhiyun * 0: depend on fw support
3173*4882a593Smuzhiyun * 1: always disable proptx
3174*4882a593Smuzhiyun */
3175*4882a593Smuzhiyun if (conf->disable_proptx == 0) {
3176*4882a593Smuzhiyun // check fw support as well
3177*4882a593Smuzhiyun if (fw_proptx)
3178*4882a593Smuzhiyun disable_proptx = 0;
3179*4882a593Smuzhiyun else
3180*4882a593Smuzhiyun disable_proptx = 1;
3181*4882a593Smuzhiyun } else if (conf->disable_proptx >= 1) {
3182*4882a593Smuzhiyun disable_proptx = 1;
3183*4882a593Smuzhiyun } else {
3184*4882a593Smuzhiyun // check fw support as well
3185*4882a593Smuzhiyun if (fw_proptx)
3186*4882a593Smuzhiyun disable_proptx = -1;
3187*4882a593Smuzhiyun else
3188*4882a593Smuzhiyun disable_proptx = 1;
3189*4882a593Smuzhiyun }
3190*4882a593Smuzhiyun
3191*4882a593Smuzhiyun CONFIG_MSG("fw_proptx=%d, disable_proptx=%d\n", fw_proptx, disable_proptx);
3192*4882a593Smuzhiyun
3193*4882a593Smuzhiyun return disable_proptx;
3194*4882a593Smuzhiyun }
3195*4882a593Smuzhiyun #endif
3196*4882a593Smuzhiyun
3197*4882a593Smuzhiyun uint
pick_config_vars(char * varbuf,uint len,uint start_pos,char * pickbuf,int picklen)3198*4882a593Smuzhiyun pick_config_vars(char *varbuf, uint len, uint start_pos, char *pickbuf, int picklen)
3199*4882a593Smuzhiyun {
3200*4882a593Smuzhiyun bool findNewline, changenewline=FALSE, pick=FALSE;
3201*4882a593Smuzhiyun int column;
3202*4882a593Smuzhiyun uint n, pick_column=0;
3203*4882a593Smuzhiyun
3204*4882a593Smuzhiyun findNewline = FALSE;
3205*4882a593Smuzhiyun column = 0;
3206*4882a593Smuzhiyun
3207*4882a593Smuzhiyun if (start_pos >= len) {
3208*4882a593Smuzhiyun CONFIG_ERROR("wrong start pos\n");
3209*4882a593Smuzhiyun return 0;
3210*4882a593Smuzhiyun }
3211*4882a593Smuzhiyun
3212*4882a593Smuzhiyun for (n = start_pos; n < len; n++) {
3213*4882a593Smuzhiyun if (varbuf[n] == '\r')
3214*4882a593Smuzhiyun continue;
3215*4882a593Smuzhiyun if ((findNewline || changenewline) && varbuf[n] != '\n')
3216*4882a593Smuzhiyun continue;
3217*4882a593Smuzhiyun findNewline = FALSE;
3218*4882a593Smuzhiyun if (varbuf[n] == '#') {
3219*4882a593Smuzhiyun findNewline = TRUE;
3220*4882a593Smuzhiyun continue;
3221*4882a593Smuzhiyun }
3222*4882a593Smuzhiyun if (varbuf[n] == '\\') {
3223*4882a593Smuzhiyun changenewline = TRUE;
3224*4882a593Smuzhiyun continue;
3225*4882a593Smuzhiyun }
3226*4882a593Smuzhiyun if (!changenewline && varbuf[n] == '\n') {
3227*4882a593Smuzhiyun if (column == 0)
3228*4882a593Smuzhiyun continue;
3229*4882a593Smuzhiyun column = 0;
3230*4882a593Smuzhiyun continue;
3231*4882a593Smuzhiyun }
3232*4882a593Smuzhiyun if (changenewline && varbuf[n] == '\n') {
3233*4882a593Smuzhiyun changenewline = FALSE;
3234*4882a593Smuzhiyun continue;
3235*4882a593Smuzhiyun }
3236*4882a593Smuzhiyun
3237*4882a593Smuzhiyun if (column==0 && !pick) { // start to pick
3238*4882a593Smuzhiyun pick = TRUE;
3239*4882a593Smuzhiyun column++;
3240*4882a593Smuzhiyun pick_column = 0;
3241*4882a593Smuzhiyun } else {
3242*4882a593Smuzhiyun if (pick && column==0) { // stop to pick
3243*4882a593Smuzhiyun pick = FALSE;
3244*4882a593Smuzhiyun break;
3245*4882a593Smuzhiyun } else
3246*4882a593Smuzhiyun column++;
3247*4882a593Smuzhiyun }
3248*4882a593Smuzhiyun if (pick) {
3249*4882a593Smuzhiyun if (varbuf[n] == 0x9)
3250*4882a593Smuzhiyun continue;
3251*4882a593Smuzhiyun if (pick_column >= picklen)
3252*4882a593Smuzhiyun break;
3253*4882a593Smuzhiyun pickbuf[pick_column] = varbuf[n];
3254*4882a593Smuzhiyun pick_column++;
3255*4882a593Smuzhiyun }
3256*4882a593Smuzhiyun }
3257*4882a593Smuzhiyun
3258*4882a593Smuzhiyun return n; // return current position
3259*4882a593Smuzhiyun }
3260*4882a593Smuzhiyun
3261*4882a593Smuzhiyun bool
dhd_conf_read_chiprev(dhd_pub_t * dhd,int * chip_match,char * full_param,uint len_param)3262*4882a593Smuzhiyun dhd_conf_read_chiprev(dhd_pub_t *dhd, int *chip_match,
3263*4882a593Smuzhiyun char *full_param, uint len_param)
3264*4882a593Smuzhiyun {
3265*4882a593Smuzhiyun char *data = full_param+len_param, *pick_tmp, *pch;
3266*4882a593Smuzhiyun uint chip = 0, rev = 0;
3267*4882a593Smuzhiyun
3268*4882a593Smuzhiyun /* Process chip, regrev:
3269*4882a593Smuzhiyun * chip=[chipid], rev==[rev]
3270*4882a593Smuzhiyun * Ex: chip=0x4359, rev=9
3271*4882a593Smuzhiyun */
3272*4882a593Smuzhiyun if (!strncmp("chip=", full_param, len_param)) {
3273*4882a593Smuzhiyun chip = (int)simple_strtol(data, NULL, 0);
3274*4882a593Smuzhiyun pick_tmp = data;
3275*4882a593Smuzhiyun pch = bcmstrstr(pick_tmp, "rev=");
3276*4882a593Smuzhiyun if (pch) {
3277*4882a593Smuzhiyun rev = (int)simple_strtol(pch+strlen("rev="), NULL, 0);
3278*4882a593Smuzhiyun }
3279*4882a593Smuzhiyun if (chip == dhd->conf->chip && rev == dhd->conf->chiprev)
3280*4882a593Smuzhiyun *chip_match = 1;
3281*4882a593Smuzhiyun else
3282*4882a593Smuzhiyun *chip_match = 0;
3283*4882a593Smuzhiyun CONFIG_MSG("chip=0x%x, rev=%d, chip_match=%d\n", chip, rev, *chip_match);
3284*4882a593Smuzhiyun }
3285*4882a593Smuzhiyun
3286*4882a593Smuzhiyun return TRUE;
3287*4882a593Smuzhiyun }
3288*4882a593Smuzhiyun
3289*4882a593Smuzhiyun bool
dhd_conf_read_log_level(dhd_pub_t * dhd,char * full_param,uint len_param)3290*4882a593Smuzhiyun dhd_conf_read_log_level(dhd_pub_t *dhd, char *full_param, uint len_param)
3291*4882a593Smuzhiyun {
3292*4882a593Smuzhiyun char *data = full_param+len_param;
3293*4882a593Smuzhiyun
3294*4882a593Smuzhiyun if (!strncmp("dhd_msg_level=", full_param, len_param)) {
3295*4882a593Smuzhiyun dhd_msg_level = (int)simple_strtol(data, NULL, 0);
3296*4882a593Smuzhiyun CONFIG_MSG("dhd_msg_level = 0x%X\n", dhd_msg_level);
3297*4882a593Smuzhiyun }
3298*4882a593Smuzhiyun else if (!strncmp("dump_msg_level=", full_param, len_param)) {
3299*4882a593Smuzhiyun dump_msg_level = (int)simple_strtol(data, NULL, 0);
3300*4882a593Smuzhiyun CONFIG_MSG("dump_msg_level = 0x%X\n", dump_msg_level);
3301*4882a593Smuzhiyun }
3302*4882a593Smuzhiyun #ifdef BCMSDIO
3303*4882a593Smuzhiyun else if (!strncmp("sd_msglevel=", full_param, len_param)) {
3304*4882a593Smuzhiyun sd_msglevel = (int)simple_strtol(data, NULL, 0);
3305*4882a593Smuzhiyun CONFIG_MSG("sd_msglevel = 0x%X\n", sd_msglevel);
3306*4882a593Smuzhiyun }
3307*4882a593Smuzhiyun #endif
3308*4882a593Smuzhiyun #ifdef BCMDBUS
3309*4882a593Smuzhiyun else if (!strncmp("dbus_msglevel=", full_param, len_param)) {
3310*4882a593Smuzhiyun dbus_msglevel = (int)simple_strtol(data, NULL, 0);
3311*4882a593Smuzhiyun CONFIG_MSG("dbus_msglevel = 0x%X\n", dbus_msglevel);
3312*4882a593Smuzhiyun }
3313*4882a593Smuzhiyun #endif
3314*4882a593Smuzhiyun else if (!strncmp("android_msg_level=", full_param, len_param)) {
3315*4882a593Smuzhiyun android_msg_level = (int)simple_strtol(data, NULL, 0);
3316*4882a593Smuzhiyun CONFIG_MSG("android_msg_level = 0x%X\n", android_msg_level);
3317*4882a593Smuzhiyun }
3318*4882a593Smuzhiyun else if (!strncmp("config_msg_level=", full_param, len_param)) {
3319*4882a593Smuzhiyun config_msg_level = (int)simple_strtol(data, NULL, 0);
3320*4882a593Smuzhiyun CONFIG_MSG("config_msg_level = 0x%X\n", config_msg_level);
3321*4882a593Smuzhiyun }
3322*4882a593Smuzhiyun #ifdef WL_CFG80211
3323*4882a593Smuzhiyun else if (!strncmp("wl_dbg_level=", full_param, len_param)) {
3324*4882a593Smuzhiyun wl_dbg_level = (int)simple_strtol(data, NULL, 0);
3325*4882a593Smuzhiyun CONFIG_MSG("wl_dbg_level = 0x%X\n", wl_dbg_level);
3326*4882a593Smuzhiyun }
3327*4882a593Smuzhiyun #endif
3328*4882a593Smuzhiyun #if defined(WL_WIRELESS_EXT)
3329*4882a593Smuzhiyun else if (!strncmp("iw_msg_level=", full_param, len_param)) {
3330*4882a593Smuzhiyun iw_msg_level = (int)simple_strtol(data, NULL, 0);
3331*4882a593Smuzhiyun CONFIG_MSG("iw_msg_level = 0x%X\n", iw_msg_level);
3332*4882a593Smuzhiyun }
3333*4882a593Smuzhiyun #endif
3334*4882a593Smuzhiyun #if defined(DHD_DEBUG)
3335*4882a593Smuzhiyun else if (!strncmp("dhd_console_ms=", full_param, len_param)) {
3336*4882a593Smuzhiyun dhd->dhd_console_ms = (int)simple_strtol(data, NULL, 0);
3337*4882a593Smuzhiyun CONFIG_MSG("dhd_console_ms = %d\n", dhd->dhd_console_ms);
3338*4882a593Smuzhiyun }
3339*4882a593Smuzhiyun #endif
3340*4882a593Smuzhiyun else
3341*4882a593Smuzhiyun return false;
3342*4882a593Smuzhiyun
3343*4882a593Smuzhiyun return true;
3344*4882a593Smuzhiyun }
3345*4882a593Smuzhiyun
3346*4882a593Smuzhiyun void
dhd_conf_read_wme_ac_value(wme_param_t * wme,char * pick,int ac_val)3347*4882a593Smuzhiyun dhd_conf_read_wme_ac_value(wme_param_t *wme, char *pick, int ac_val)
3348*4882a593Smuzhiyun {
3349*4882a593Smuzhiyun char *pick_tmp, *pch;
3350*4882a593Smuzhiyun
3351*4882a593Smuzhiyun pick_tmp = pick;
3352*4882a593Smuzhiyun pch = bcmstrstr(pick_tmp, "aifsn ");
3353*4882a593Smuzhiyun if (pch) {
3354*4882a593Smuzhiyun wme->aifsn[ac_val] = (int)simple_strtol(pch+strlen("aifsn "), NULL, 0);
3355*4882a593Smuzhiyun CONFIG_MSG("ac_val=%d, aifsn=%d\n", ac_val, wme->aifsn[ac_val]);
3356*4882a593Smuzhiyun }
3357*4882a593Smuzhiyun pick_tmp = pick;
3358*4882a593Smuzhiyun pch = bcmstrstr(pick_tmp, "ecwmin ");
3359*4882a593Smuzhiyun if (pch) {
3360*4882a593Smuzhiyun wme->ecwmin[ac_val] = (int)simple_strtol(pch+strlen("ecwmin "), NULL, 0);
3361*4882a593Smuzhiyun CONFIG_MSG("ac_val=%d, ecwmin=%d\n", ac_val, wme->ecwmin[ac_val]);
3362*4882a593Smuzhiyun }
3363*4882a593Smuzhiyun pick_tmp = pick;
3364*4882a593Smuzhiyun pch = bcmstrstr(pick_tmp, "ecwmax ");
3365*4882a593Smuzhiyun if (pch) {
3366*4882a593Smuzhiyun wme->ecwmax[ac_val] = (int)simple_strtol(pch+strlen("ecwmax "), NULL, 0);
3367*4882a593Smuzhiyun CONFIG_MSG("ac_val=%d, ecwmax=%d\n", ac_val, wme->ecwmax[ac_val]);
3368*4882a593Smuzhiyun }
3369*4882a593Smuzhiyun pick_tmp = pick;
3370*4882a593Smuzhiyun pch = bcmstrstr(pick_tmp, "txop ");
3371*4882a593Smuzhiyun if (pch) {
3372*4882a593Smuzhiyun wme->txop[ac_val] = (int)simple_strtol(pch+strlen("txop "), NULL, 0);
3373*4882a593Smuzhiyun CONFIG_MSG("ac_val=%d, txop=0x%x\n", ac_val, wme->txop[ac_val]);
3374*4882a593Smuzhiyun }
3375*4882a593Smuzhiyun
3376*4882a593Smuzhiyun }
3377*4882a593Smuzhiyun
3378*4882a593Smuzhiyun bool
dhd_conf_read_wme_ac_params(dhd_pub_t * dhd,char * full_param,uint len_param)3379*4882a593Smuzhiyun dhd_conf_read_wme_ac_params(dhd_pub_t *dhd, char *full_param, uint len_param)
3380*4882a593Smuzhiyun {
3381*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
3382*4882a593Smuzhiyun char *data = full_param+len_param;
3383*4882a593Smuzhiyun
3384*4882a593Smuzhiyun // wme_ac_sta_be=aifsn 1 ecwmin 2 ecwmax 3 txop 0x5e
3385*4882a593Smuzhiyun // wme_ac_sta_vo=aifsn 1 ecwmin 1 ecwmax 1 txop 0x5e
3386*4882a593Smuzhiyun
3387*4882a593Smuzhiyun if (!strncmp("force_wme_ac=", full_param, len_param)) {
3388*4882a593Smuzhiyun conf->force_wme_ac = (int)simple_strtol(data, NULL, 10);
3389*4882a593Smuzhiyun CONFIG_MSG("force_wme_ac = %d\n", conf->force_wme_ac);
3390*4882a593Smuzhiyun }
3391*4882a593Smuzhiyun else if (!strncmp("wme_ac_sta_be=", full_param, len_param)) {
3392*4882a593Smuzhiyun dhd_conf_read_wme_ac_value(&conf->wme_sta, data, AC_BE);
3393*4882a593Smuzhiyun }
3394*4882a593Smuzhiyun else if (!strncmp("wme_ac_sta_bk=", full_param, len_param)) {
3395*4882a593Smuzhiyun dhd_conf_read_wme_ac_value(&conf->wme_sta, data, AC_BK);
3396*4882a593Smuzhiyun }
3397*4882a593Smuzhiyun else if (!strncmp("wme_ac_sta_vi=", full_param, len_param)) {
3398*4882a593Smuzhiyun dhd_conf_read_wme_ac_value(&conf->wme_sta, data, AC_VI);
3399*4882a593Smuzhiyun }
3400*4882a593Smuzhiyun else if (!strncmp("wme_ac_sta_vo=", full_param, len_param)) {
3401*4882a593Smuzhiyun dhd_conf_read_wme_ac_value(&conf->wme_sta, data, AC_VO);
3402*4882a593Smuzhiyun }
3403*4882a593Smuzhiyun else if (!strncmp("wme_ac_ap_be=", full_param, len_param)) {
3404*4882a593Smuzhiyun dhd_conf_read_wme_ac_value(&conf->wme_ap, data, AC_BE);
3405*4882a593Smuzhiyun }
3406*4882a593Smuzhiyun else if (!strncmp("wme_ac_ap_bk=", full_param, len_param)) {
3407*4882a593Smuzhiyun dhd_conf_read_wme_ac_value(&conf->wme_ap, data, AC_BK);
3408*4882a593Smuzhiyun }
3409*4882a593Smuzhiyun else if (!strncmp("wme_ac_ap_vi=", full_param, len_param)) {
3410*4882a593Smuzhiyun dhd_conf_read_wme_ac_value(&conf->wme_ap, data, AC_VI);
3411*4882a593Smuzhiyun }
3412*4882a593Smuzhiyun else if (!strncmp("wme_ac_ap_vo=", full_param, len_param)) {
3413*4882a593Smuzhiyun dhd_conf_read_wme_ac_value(&conf->wme_ap, data, AC_VO);
3414*4882a593Smuzhiyun }
3415*4882a593Smuzhiyun else
3416*4882a593Smuzhiyun return false;
3417*4882a593Smuzhiyun
3418*4882a593Smuzhiyun return true;
3419*4882a593Smuzhiyun }
3420*4882a593Smuzhiyun
3421*4882a593Smuzhiyun #ifdef SET_FWNV_BY_MAC
3422*4882a593Smuzhiyun bool
dhd_conf_read_fw_by_mac(dhd_pub_t * dhd,char * full_param,uint len_param)3423*4882a593Smuzhiyun dhd_conf_read_fw_by_mac(dhd_pub_t *dhd, char *full_param, uint len_param)
3424*4882a593Smuzhiyun {
3425*4882a593Smuzhiyun int i, j;
3426*4882a593Smuzhiyun char *pch, *pick_tmp;
3427*4882a593Smuzhiyun wl_mac_list_t *mac_list;
3428*4882a593Smuzhiyun wl_mac_range_t *mac_range;
3429*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
3430*4882a593Smuzhiyun char *data = full_param+len_param;
3431*4882a593Smuzhiyun
3432*4882a593Smuzhiyun /* Process fw_by_mac:
3433*4882a593Smuzhiyun * fw_by_mac=[fw_mac_num] \
3434*4882a593Smuzhiyun * [fw_name1] [mac_num1] [oui1-1] [nic_start1-1] [nic_end1-1] \
3435*4882a593Smuzhiyun * [oui1-1] [nic_start1-1] [nic_end1-1]... \
3436*4882a593Smuzhiyun * [oui1-n] [nic_start1-n] [nic_end1-n] \
3437*4882a593Smuzhiyun * [fw_name2] [mac_num2] [oui2-1] [nic_start2-1] [nic_end2-1] \
3438*4882a593Smuzhiyun * [oui2-1] [nic_start2-1] [nic_end2-1]... \
3439*4882a593Smuzhiyun * [oui2-n] [nic_start2-n] [nic_end2-n] \
3440*4882a593Smuzhiyun * Ex: fw_by_mac=2 \
3441*4882a593Smuzhiyun * fw_bcmdhd1.bin 2 0x0022F4 0xE85408 0xE8549D 0x983B16 0x3557A9 0x35582A \
3442*4882a593Smuzhiyun * fw_bcmdhd2.bin 3 0x0022F4 0xE85408 0xE8549D 0x983B16 0x3557A9 0x35582A \
3443*4882a593Smuzhiyun * 0x983B16 0x916157 0x916487
3444*4882a593Smuzhiyun */
3445*4882a593Smuzhiyun
3446*4882a593Smuzhiyun if (!strncmp("fw_by_mac=", full_param, len_param)) {
3447*4882a593Smuzhiyun dhd_conf_free_mac_list(&conf->fw_by_mac);
3448*4882a593Smuzhiyun pick_tmp = data;
3449*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ", 0);
3450*4882a593Smuzhiyun conf->fw_by_mac.count = (uint32)simple_strtol(pch, NULL, 0);
3451*4882a593Smuzhiyun if (!(mac_list = kmalloc(sizeof(wl_mac_list_t)*conf->fw_by_mac.count,
3452*4882a593Smuzhiyun GFP_KERNEL))) {
3453*4882a593Smuzhiyun conf->fw_by_mac.count = 0;
3454*4882a593Smuzhiyun CONFIG_ERROR("kmalloc failed\n");
3455*4882a593Smuzhiyun }
3456*4882a593Smuzhiyun CONFIG_MSG("fw_count=%d\n", conf->fw_by_mac.count);
3457*4882a593Smuzhiyun conf->fw_by_mac.m_mac_list_head = mac_list;
3458*4882a593Smuzhiyun for (i=0; i<conf->fw_by_mac.count; i++) {
3459*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ", 0);
3460*4882a593Smuzhiyun strcpy(mac_list[i].name, pch);
3461*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ", 0);
3462*4882a593Smuzhiyun mac_list[i].count = (uint32)simple_strtol(pch, NULL, 0);
3463*4882a593Smuzhiyun CONFIG_MSG("name=%s, mac_count=%d\n",
3464*4882a593Smuzhiyun mac_list[i].name, mac_list[i].count);
3465*4882a593Smuzhiyun if (!(mac_range = kmalloc(sizeof(wl_mac_range_t)*mac_list[i].count,
3466*4882a593Smuzhiyun GFP_KERNEL))) {
3467*4882a593Smuzhiyun mac_list[i].count = 0;
3468*4882a593Smuzhiyun CONFIG_ERROR("kmalloc failed\n");
3469*4882a593Smuzhiyun break;
3470*4882a593Smuzhiyun }
3471*4882a593Smuzhiyun mac_list[i].mac = mac_range;
3472*4882a593Smuzhiyun for (j=0; j<mac_list[i].count; j++) {
3473*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ", 0);
3474*4882a593Smuzhiyun mac_range[j].oui = (uint32)simple_strtol(pch, NULL, 0);
3475*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ", 0);
3476*4882a593Smuzhiyun mac_range[j].nic_start = (uint32)simple_strtol(pch, NULL, 0);
3477*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ", 0);
3478*4882a593Smuzhiyun mac_range[j].nic_end = (uint32)simple_strtol(pch, NULL, 0);
3479*4882a593Smuzhiyun CONFIG_MSG("oui=0x%06X, nic_start=0x%06X, nic_end=0x%06X\n",
3480*4882a593Smuzhiyun mac_range[j].oui, mac_range[j].nic_start, mac_range[j].nic_end);
3481*4882a593Smuzhiyun }
3482*4882a593Smuzhiyun }
3483*4882a593Smuzhiyun }
3484*4882a593Smuzhiyun else
3485*4882a593Smuzhiyun return false;
3486*4882a593Smuzhiyun
3487*4882a593Smuzhiyun return true;
3488*4882a593Smuzhiyun }
3489*4882a593Smuzhiyun
3490*4882a593Smuzhiyun bool
dhd_conf_read_nv_by_mac(dhd_pub_t * dhd,char * full_param,uint len_param)3491*4882a593Smuzhiyun dhd_conf_read_nv_by_mac(dhd_pub_t *dhd, char *full_param, uint len_param)
3492*4882a593Smuzhiyun {
3493*4882a593Smuzhiyun int i, j;
3494*4882a593Smuzhiyun char *pch, *pick_tmp;
3495*4882a593Smuzhiyun wl_mac_list_t *mac_list;
3496*4882a593Smuzhiyun wl_mac_range_t *mac_range;
3497*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
3498*4882a593Smuzhiyun char *data = full_param+len_param;
3499*4882a593Smuzhiyun
3500*4882a593Smuzhiyun /* Process nv_by_mac:
3501*4882a593Smuzhiyun * [nv_by_mac]: The same format as fw_by_mac
3502*4882a593Smuzhiyun */
3503*4882a593Smuzhiyun if (!strncmp("nv_by_mac=", full_param, len_param)) {
3504*4882a593Smuzhiyun dhd_conf_free_mac_list(&conf->nv_by_mac);
3505*4882a593Smuzhiyun pick_tmp = data;
3506*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ", 0);
3507*4882a593Smuzhiyun conf->nv_by_mac.count = (uint32)simple_strtol(pch, NULL, 0);
3508*4882a593Smuzhiyun if (!(mac_list = kmalloc(sizeof(wl_mac_list_t)*conf->nv_by_mac.count,
3509*4882a593Smuzhiyun GFP_KERNEL))) {
3510*4882a593Smuzhiyun conf->nv_by_mac.count = 0;
3511*4882a593Smuzhiyun CONFIG_ERROR("kmalloc failed\n");
3512*4882a593Smuzhiyun }
3513*4882a593Smuzhiyun CONFIG_MSG("nv_count=%d\n", conf->nv_by_mac.count);
3514*4882a593Smuzhiyun conf->nv_by_mac.m_mac_list_head = mac_list;
3515*4882a593Smuzhiyun for (i=0; i<conf->nv_by_mac.count; i++) {
3516*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ", 0);
3517*4882a593Smuzhiyun strcpy(mac_list[i].name, pch);
3518*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ", 0);
3519*4882a593Smuzhiyun mac_list[i].count = (uint32)simple_strtol(pch, NULL, 0);
3520*4882a593Smuzhiyun CONFIG_MSG("name=%s, mac_count=%d\n",
3521*4882a593Smuzhiyun mac_list[i].name, mac_list[i].count);
3522*4882a593Smuzhiyun if (!(mac_range = kmalloc(sizeof(wl_mac_range_t)*mac_list[i].count,
3523*4882a593Smuzhiyun GFP_KERNEL))) {
3524*4882a593Smuzhiyun mac_list[i].count = 0;
3525*4882a593Smuzhiyun CONFIG_ERROR("kmalloc failed\n");
3526*4882a593Smuzhiyun break;
3527*4882a593Smuzhiyun }
3528*4882a593Smuzhiyun mac_list[i].mac = mac_range;
3529*4882a593Smuzhiyun for (j=0; j<mac_list[i].count; j++) {
3530*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ", 0);
3531*4882a593Smuzhiyun mac_range[j].oui = (uint32)simple_strtol(pch, NULL, 0);
3532*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ", 0);
3533*4882a593Smuzhiyun mac_range[j].nic_start = (uint32)simple_strtol(pch, NULL, 0);
3534*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ", 0);
3535*4882a593Smuzhiyun mac_range[j].nic_end = (uint32)simple_strtol(pch, NULL, 0);
3536*4882a593Smuzhiyun CONFIG_MSG("oui=0x%06X, nic_start=0x%06X, nic_end=0x%06X\n",
3537*4882a593Smuzhiyun mac_range[j].oui, mac_range[j].nic_start, mac_range[j].nic_end);
3538*4882a593Smuzhiyun }
3539*4882a593Smuzhiyun }
3540*4882a593Smuzhiyun }
3541*4882a593Smuzhiyun else
3542*4882a593Smuzhiyun return false;
3543*4882a593Smuzhiyun
3544*4882a593Smuzhiyun return true;
3545*4882a593Smuzhiyun }
3546*4882a593Smuzhiyun #endif
3547*4882a593Smuzhiyun
3548*4882a593Smuzhiyun bool
dhd_conf_read_nv_by_chip(dhd_pub_t * dhd,char * full_param,uint len_param)3549*4882a593Smuzhiyun dhd_conf_read_nv_by_chip(dhd_pub_t *dhd, char *full_param, uint len_param)
3550*4882a593Smuzhiyun {
3551*4882a593Smuzhiyun int i;
3552*4882a593Smuzhiyun char *pch, *pick_tmp;
3553*4882a593Smuzhiyun wl_chip_nv_path_t *chip_nv_path;
3554*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
3555*4882a593Smuzhiyun char *data = full_param+len_param;
3556*4882a593Smuzhiyun
3557*4882a593Smuzhiyun /* Process nv_by_chip:
3558*4882a593Smuzhiyun * nv_by_chip=[nv_chip_num] \
3559*4882a593Smuzhiyun * [chip1] [chiprev1] [nv_name1] [chip2] [chiprev2] [nv_name2] \
3560*4882a593Smuzhiyun * Ex: nv_by_chip=2 \
3561*4882a593Smuzhiyun * 43430 0 nvram_ap6212.txt 43430 1 nvram_ap6212a.txt \
3562*4882a593Smuzhiyun */
3563*4882a593Smuzhiyun if (!strncmp("nv_by_chip=", full_param, len_param)) {
3564*4882a593Smuzhiyun dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);
3565*4882a593Smuzhiyun pick_tmp = data;
3566*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ", 0);
3567*4882a593Smuzhiyun conf->nv_by_chip.count = (uint32)simple_strtol(pch, NULL, 0);
3568*4882a593Smuzhiyun if (!(chip_nv_path = kmalloc(sizeof(wl_chip_nv_path_t)*conf->nv_by_chip.count,
3569*4882a593Smuzhiyun GFP_KERNEL))) {
3570*4882a593Smuzhiyun conf->nv_by_chip.count = 0;
3571*4882a593Smuzhiyun CONFIG_ERROR("kmalloc failed\n");
3572*4882a593Smuzhiyun }
3573*4882a593Smuzhiyun CONFIG_MSG("nv_by_chip_count=%d\n", conf->nv_by_chip.count);
3574*4882a593Smuzhiyun conf->nv_by_chip.m_chip_nv_path_head = chip_nv_path;
3575*4882a593Smuzhiyun for (i=0; i<conf->nv_by_chip.count; i++) {
3576*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ", 0);
3577*4882a593Smuzhiyun chip_nv_path[i].chip = (uint32)simple_strtol(pch, NULL, 0);
3578*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ", 0);
3579*4882a593Smuzhiyun chip_nv_path[i].chiprev = (uint32)simple_strtol(pch, NULL, 0);
3580*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ", 0);
3581*4882a593Smuzhiyun strcpy(chip_nv_path[i].name, pch);
3582*4882a593Smuzhiyun CONFIG_MSG("chip=0x%x, chiprev=%d, name=%s\n",
3583*4882a593Smuzhiyun chip_nv_path[i].chip, chip_nv_path[i].chiprev, chip_nv_path[i].name);
3584*4882a593Smuzhiyun }
3585*4882a593Smuzhiyun }
3586*4882a593Smuzhiyun else
3587*4882a593Smuzhiyun return false;
3588*4882a593Smuzhiyun
3589*4882a593Smuzhiyun return true;
3590*4882a593Smuzhiyun }
3591*4882a593Smuzhiyun
3592*4882a593Smuzhiyun bool
dhd_conf_read_roam_params(dhd_pub_t * dhd,char * full_param,uint len_param)3593*4882a593Smuzhiyun dhd_conf_read_roam_params(dhd_pub_t *dhd, char *full_param, uint len_param)
3594*4882a593Smuzhiyun {
3595*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
3596*4882a593Smuzhiyun char *data = full_param+len_param;
3597*4882a593Smuzhiyun
3598*4882a593Smuzhiyun if (!strncmp("roam_off=", full_param, len_param)) {
3599*4882a593Smuzhiyun if (!strncmp(data, "0", 1))
3600*4882a593Smuzhiyun conf->roam_off = 0;
3601*4882a593Smuzhiyun else
3602*4882a593Smuzhiyun conf->roam_off = 1;
3603*4882a593Smuzhiyun CONFIG_MSG("roam_off = %d\n", conf->roam_off);
3604*4882a593Smuzhiyun }
3605*4882a593Smuzhiyun else if (!strncmp("roam_off_suspend=", full_param, len_param)) {
3606*4882a593Smuzhiyun if (!strncmp(data, "0", 1))
3607*4882a593Smuzhiyun conf->roam_off_suspend = 0;
3608*4882a593Smuzhiyun else
3609*4882a593Smuzhiyun conf->roam_off_suspend = 1;
3610*4882a593Smuzhiyun CONFIG_MSG("roam_off_suspend = %d\n", conf->roam_off_suspend);
3611*4882a593Smuzhiyun }
3612*4882a593Smuzhiyun else if (!strncmp("roam_trigger=", full_param, len_param)) {
3613*4882a593Smuzhiyun conf->roam_trigger[0] = (int)simple_strtol(data, NULL, 10);
3614*4882a593Smuzhiyun CONFIG_MSG("roam_trigger = %d\n", conf->roam_trigger[0]);
3615*4882a593Smuzhiyun }
3616*4882a593Smuzhiyun else if (!strncmp("roam_scan_period=", full_param, len_param)) {
3617*4882a593Smuzhiyun conf->roam_scan_period[0] = (int)simple_strtol(data, NULL, 10);
3618*4882a593Smuzhiyun CONFIG_MSG("roam_scan_period = %d\n", conf->roam_scan_period[0]);
3619*4882a593Smuzhiyun }
3620*4882a593Smuzhiyun else if (!strncmp("roam_delta=", full_param, len_param)) {
3621*4882a593Smuzhiyun conf->roam_delta[0] = (int)simple_strtol(data, NULL, 10);
3622*4882a593Smuzhiyun CONFIG_MSG("roam_delta = %d\n", conf->roam_delta[0]);
3623*4882a593Smuzhiyun }
3624*4882a593Smuzhiyun else if (!strncmp("fullroamperiod=", full_param, len_param)) {
3625*4882a593Smuzhiyun conf->fullroamperiod = (int)simple_strtol(data, NULL, 10);
3626*4882a593Smuzhiyun CONFIG_MSG("fullroamperiod = %d\n", conf->fullroamperiod);
3627*4882a593Smuzhiyun }
3628*4882a593Smuzhiyun else if (!strncmp("wl_reassoc_support=", full_param, len_param)) {
3629*4882a593Smuzhiyun if (!strncmp(data, "0", 1))
3630*4882a593Smuzhiyun wl_reassoc_support = FALSE;
3631*4882a593Smuzhiyun else
3632*4882a593Smuzhiyun wl_reassoc_support = TRUE;
3633*4882a593Smuzhiyun CONFIG_MSG("wl_reassoc_support = %d\n", wl_reassoc_support);
3634*4882a593Smuzhiyun }
3635*4882a593Smuzhiyun else
3636*4882a593Smuzhiyun return false;
3637*4882a593Smuzhiyun
3638*4882a593Smuzhiyun return true;
3639*4882a593Smuzhiyun }
3640*4882a593Smuzhiyun
3641*4882a593Smuzhiyun bool
dhd_conf_read_country(dhd_pub_t * dhd,char * full_param,uint len_param)3642*4882a593Smuzhiyun dhd_conf_read_country(dhd_pub_t *dhd, char *full_param, uint len_param)
3643*4882a593Smuzhiyun {
3644*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
3645*4882a593Smuzhiyun country_list_t *country_next = NULL, *country;
3646*4882a593Smuzhiyun int i, count = 0;
3647*4882a593Smuzhiyun char *pch, *pick_tmp, *pick_tmp2;
3648*4882a593Smuzhiyun char *data = full_param+len_param;
3649*4882a593Smuzhiyun uint len_data = strlen(data);
3650*4882a593Smuzhiyun
3651*4882a593Smuzhiyun /* Process country_list:
3652*4882a593Smuzhiyun * country_list=[country1]:[ccode1]/[regrev1],
3653*4882a593Smuzhiyun * [country2]:[ccode2]/[regrev2] \
3654*4882a593Smuzhiyun * Ex: country_list=US:US/0, TW:TW/1
3655*4882a593Smuzhiyun */
3656*4882a593Smuzhiyun if (!strncmp("ccode=", full_param, len_param)) {
3657*4882a593Smuzhiyun len_data = min((uint)WLC_CNTRY_BUF_SZ, len_data);
3658*4882a593Smuzhiyun memset(&conf->cspec, 0, sizeof(wl_country_t));
3659*4882a593Smuzhiyun memcpy(conf->cspec.country_abbrev, data, len_data);
3660*4882a593Smuzhiyun memcpy(conf->cspec.ccode, data, len_data);
3661*4882a593Smuzhiyun CONFIG_MSG("ccode = %s\n", conf->cspec.ccode);
3662*4882a593Smuzhiyun }
3663*4882a593Smuzhiyun else if (!strncmp("regrev=", full_param, len_param)) {
3664*4882a593Smuzhiyun conf->cspec.rev = (int32)simple_strtol(data, NULL, 10);
3665*4882a593Smuzhiyun CONFIG_MSG("regrev = %d\n", conf->cspec.rev);
3666*4882a593Smuzhiyun }
3667*4882a593Smuzhiyun else if (!strncmp("country_list=", full_param, len_param)) {
3668*4882a593Smuzhiyun dhd_conf_free_country_list(conf);
3669*4882a593Smuzhiyun pick_tmp = data;
3670*4882a593Smuzhiyun for (i=0; i<CONFIG_COUNTRY_LIST_SIZE; i++) {
3671*4882a593Smuzhiyun pick_tmp2 = bcmstrtok(&pick_tmp, ", ", 0);
3672*4882a593Smuzhiyun if (!pick_tmp2)
3673*4882a593Smuzhiyun break;
3674*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp2, ":", 0);
3675*4882a593Smuzhiyun if (!pch)
3676*4882a593Smuzhiyun break;
3677*4882a593Smuzhiyun country = NULL;
3678*4882a593Smuzhiyun if (!(country = kmalloc(sizeof(country_list_t), GFP_KERNEL))) {
3679*4882a593Smuzhiyun CONFIG_ERROR("kmalloc failed\n");
3680*4882a593Smuzhiyun break;
3681*4882a593Smuzhiyun }
3682*4882a593Smuzhiyun memset(country, 0, sizeof(country_list_t));
3683*4882a593Smuzhiyun
3684*4882a593Smuzhiyun memcpy(country->cspec.country_abbrev, pch, 2);
3685*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp2, "/", 0);
3686*4882a593Smuzhiyun if (!pch) {
3687*4882a593Smuzhiyun kfree(country);
3688*4882a593Smuzhiyun break;
3689*4882a593Smuzhiyun }
3690*4882a593Smuzhiyun memcpy(country->cspec.ccode, pch, 2);
3691*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp2, "/", 0);
3692*4882a593Smuzhiyun if (!pch) {
3693*4882a593Smuzhiyun kfree(country);
3694*4882a593Smuzhiyun break;
3695*4882a593Smuzhiyun }
3696*4882a593Smuzhiyun country->cspec.rev = (int32)simple_strtol(pch, NULL, 10);
3697*4882a593Smuzhiyun count++;
3698*4882a593Smuzhiyun if (!conf->country_head) {
3699*4882a593Smuzhiyun conf->country_head = country;
3700*4882a593Smuzhiyun country_next = country;
3701*4882a593Smuzhiyun } else {
3702*4882a593Smuzhiyun country_next->next = country;
3703*4882a593Smuzhiyun country_next = country;
3704*4882a593Smuzhiyun }
3705*4882a593Smuzhiyun CONFIG_TRACE("abbrev=%s, ccode=%s, regrev=%d\n",
3706*4882a593Smuzhiyun country->cspec.country_abbrev, country->cspec.ccode, country->cspec.rev);
3707*4882a593Smuzhiyun }
3708*4882a593Smuzhiyun CONFIG_MSG("%d country in list\n", count);
3709*4882a593Smuzhiyun }
3710*4882a593Smuzhiyun else
3711*4882a593Smuzhiyun return false;
3712*4882a593Smuzhiyun
3713*4882a593Smuzhiyun return true;
3714*4882a593Smuzhiyun }
3715*4882a593Smuzhiyun
3716*4882a593Smuzhiyun bool
dhd_conf_read_mchan_params(dhd_pub_t * dhd,char * full_param,uint len_param)3717*4882a593Smuzhiyun dhd_conf_read_mchan_params(dhd_pub_t *dhd, char *full_param, uint len_param)
3718*4882a593Smuzhiyun {
3719*4882a593Smuzhiyun int i;
3720*4882a593Smuzhiyun char *pch, *pick_tmp, *pick_tmp2;
3721*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
3722*4882a593Smuzhiyun mchan_params_t *mchan_next = NULL, *mchan;
3723*4882a593Smuzhiyun char *data = full_param+len_param;
3724*4882a593Smuzhiyun
3725*4882a593Smuzhiyun /* Process mchan_bw:
3726*4882a593Smuzhiyun * mchan_bw=[val]/[any/go/gc]/[any/source/sink]
3727*4882a593Smuzhiyun * Ex: mchan_bw=80/go/source, 30/gc/sink
3728*4882a593Smuzhiyun */
3729*4882a593Smuzhiyun if (!strncmp("mchan_bw=", full_param, len_param)) {
3730*4882a593Smuzhiyun dhd_conf_free_mchan_list(conf);
3731*4882a593Smuzhiyun pick_tmp = data;
3732*4882a593Smuzhiyun for (i=0; i<MCHAN_MAX_NUM; i++) {
3733*4882a593Smuzhiyun pick_tmp2 = bcmstrtok(&pick_tmp, ", ", 0);
3734*4882a593Smuzhiyun if (!pick_tmp2)
3735*4882a593Smuzhiyun break;
3736*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp2, "/", 0);
3737*4882a593Smuzhiyun if (!pch)
3738*4882a593Smuzhiyun break;
3739*4882a593Smuzhiyun
3740*4882a593Smuzhiyun mchan = NULL;
3741*4882a593Smuzhiyun if (!(mchan = kmalloc(sizeof(mchan_params_t), GFP_KERNEL))) {
3742*4882a593Smuzhiyun CONFIG_ERROR("kmalloc failed\n");
3743*4882a593Smuzhiyun break;
3744*4882a593Smuzhiyun }
3745*4882a593Smuzhiyun memset(mchan, 0, sizeof(mchan_params_t));
3746*4882a593Smuzhiyun
3747*4882a593Smuzhiyun mchan->bw = (int)simple_strtol(pch, NULL, 0);
3748*4882a593Smuzhiyun if (mchan->bw < 0 || mchan->bw > 100) {
3749*4882a593Smuzhiyun CONFIG_ERROR("wrong bw %d\n", mchan->bw);
3750*4882a593Smuzhiyun kfree(mchan);
3751*4882a593Smuzhiyun break;
3752*4882a593Smuzhiyun }
3753*4882a593Smuzhiyun
3754*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp2, "/", 0);
3755*4882a593Smuzhiyun if (!pch) {
3756*4882a593Smuzhiyun kfree(mchan);
3757*4882a593Smuzhiyun break;
3758*4882a593Smuzhiyun } else {
3759*4882a593Smuzhiyun if (bcmstrstr(pch, "any")) {
3760*4882a593Smuzhiyun mchan->p2p_mode = -1;
3761*4882a593Smuzhiyun } else if (bcmstrstr(pch, "go")) {
3762*4882a593Smuzhiyun mchan->p2p_mode = WL_P2P_IF_GO;
3763*4882a593Smuzhiyun } else if (bcmstrstr(pch, "gc")) {
3764*4882a593Smuzhiyun mchan->p2p_mode = WL_P2P_IF_CLIENT;
3765*4882a593Smuzhiyun }
3766*4882a593Smuzhiyun }
3767*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp2, "/", 0);
3768*4882a593Smuzhiyun if (!pch) {
3769*4882a593Smuzhiyun kfree(mchan);
3770*4882a593Smuzhiyun break;
3771*4882a593Smuzhiyun } else {
3772*4882a593Smuzhiyun if (bcmstrstr(pch, "any")) {
3773*4882a593Smuzhiyun mchan->miracast_mode = -1;
3774*4882a593Smuzhiyun } else if (bcmstrstr(pch, "source")) {
3775*4882a593Smuzhiyun mchan->miracast_mode = MIRACAST_SOURCE;
3776*4882a593Smuzhiyun } else if (bcmstrstr(pch, "sink")) {
3777*4882a593Smuzhiyun mchan->miracast_mode = MIRACAST_SINK;
3778*4882a593Smuzhiyun }
3779*4882a593Smuzhiyun }
3780*4882a593Smuzhiyun if (!conf->mchan) {
3781*4882a593Smuzhiyun conf->mchan = mchan;
3782*4882a593Smuzhiyun mchan_next = mchan;
3783*4882a593Smuzhiyun } else {
3784*4882a593Smuzhiyun mchan_next->next = mchan;
3785*4882a593Smuzhiyun mchan_next = mchan;
3786*4882a593Smuzhiyun }
3787*4882a593Smuzhiyun CONFIG_TRACE("mchan_bw=%d/%d/%d\n", mchan->bw,mchan->p2p_mode,
3788*4882a593Smuzhiyun mchan->miracast_mode);
3789*4882a593Smuzhiyun }
3790*4882a593Smuzhiyun }
3791*4882a593Smuzhiyun else
3792*4882a593Smuzhiyun return false;
3793*4882a593Smuzhiyun
3794*4882a593Smuzhiyun return true;
3795*4882a593Smuzhiyun }
3796*4882a593Smuzhiyun
3797*4882a593Smuzhiyun #ifdef PKT_FILTER_SUPPORT
3798*4882a593Smuzhiyun bool
dhd_conf_read_pkt_filter(dhd_pub_t * dhd,char * full_param,uint len_param)3799*4882a593Smuzhiyun dhd_conf_read_pkt_filter(dhd_pub_t *dhd, char *full_param, uint len_param)
3800*4882a593Smuzhiyun {
3801*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
3802*4882a593Smuzhiyun char *data = full_param+len_param;
3803*4882a593Smuzhiyun char *pch, *pick_tmp;
3804*4882a593Smuzhiyun int i;
3805*4882a593Smuzhiyun
3806*4882a593Smuzhiyun /* Process pkt filter:
3807*4882a593Smuzhiyun * 1) pkt_filter_add=99 0 0 0 0x000000000000 0x000000000000
3808*4882a593Smuzhiyun * 2) pkt_filter_delete=100, 102, 103, 104, 105
3809*4882a593Smuzhiyun * 3) magic_pkt_filter_add=141 0 1 12
3810*4882a593Smuzhiyun */
3811*4882a593Smuzhiyun if (!strncmp("dhd_master_mode=", full_param, len_param)) {
3812*4882a593Smuzhiyun if (!strncmp(data, "0", 1))
3813*4882a593Smuzhiyun dhd_master_mode = FALSE;
3814*4882a593Smuzhiyun else
3815*4882a593Smuzhiyun dhd_master_mode = TRUE;
3816*4882a593Smuzhiyun CONFIG_MSG("dhd_master_mode = %d\n", dhd_master_mode);
3817*4882a593Smuzhiyun }
3818*4882a593Smuzhiyun else if (!strncmp("pkt_filter_add=", full_param, len_param)) {
3819*4882a593Smuzhiyun pick_tmp = data;
3820*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, ",.-", 0);
3821*4882a593Smuzhiyun i=0;
3822*4882a593Smuzhiyun while (pch != NULL && i<DHD_CONF_FILTER_MAX) {
3823*4882a593Smuzhiyun strcpy(&conf->pkt_filter_add.filter[i][0], pch);
3824*4882a593Smuzhiyun CONFIG_MSG("pkt_filter_add[%d][] = %s\n",
3825*4882a593Smuzhiyun i, &conf->pkt_filter_add.filter[i][0]);
3826*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, ",.-", 0);
3827*4882a593Smuzhiyun i++;
3828*4882a593Smuzhiyun }
3829*4882a593Smuzhiyun conf->pkt_filter_add.count = i;
3830*4882a593Smuzhiyun }
3831*4882a593Smuzhiyun else if (!strncmp("pkt_filter_delete=", full_param, len_param) ||
3832*4882a593Smuzhiyun !strncmp("pkt_filter_del=", full_param, len_param)) {
3833*4882a593Smuzhiyun pick_tmp = data;
3834*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ,.-", 0);
3835*4882a593Smuzhiyun i=0;
3836*4882a593Smuzhiyun while (pch != NULL && i<DHD_CONF_FILTER_MAX) {
3837*4882a593Smuzhiyun conf->pkt_filter_del.id[i] = (uint32)simple_strtol(pch, NULL, 10);
3838*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ,.-", 0);
3839*4882a593Smuzhiyun i++;
3840*4882a593Smuzhiyun }
3841*4882a593Smuzhiyun conf->pkt_filter_del.count = i;
3842*4882a593Smuzhiyun CONFIG_MSG("pkt_filter_del id = ");
3843*4882a593Smuzhiyun for (i=0; i<conf->pkt_filter_del.count; i++)
3844*4882a593Smuzhiyun printk(KERN_CONT "%d ", conf->pkt_filter_del.id[i]);
3845*4882a593Smuzhiyun printk(KERN_CONT "\n");
3846*4882a593Smuzhiyun }
3847*4882a593Smuzhiyun else if (!strncmp("magic_pkt_filter_add=", full_param, len_param)) {
3848*4882a593Smuzhiyun if (conf->magic_pkt_filter_add) {
3849*4882a593Smuzhiyun kfree(conf->magic_pkt_filter_add);
3850*4882a593Smuzhiyun conf->magic_pkt_filter_add = NULL;
3851*4882a593Smuzhiyun }
3852*4882a593Smuzhiyun if (!(conf->magic_pkt_filter_add = kmalloc(MAGIC_PKT_FILTER_LEN, GFP_KERNEL))) {
3853*4882a593Smuzhiyun CONFIG_ERROR("kmalloc failed\n");
3854*4882a593Smuzhiyun } else {
3855*4882a593Smuzhiyun memset(conf->magic_pkt_filter_add, 0, MAGIC_PKT_FILTER_LEN);
3856*4882a593Smuzhiyun strcpy(conf->magic_pkt_filter_add, data);
3857*4882a593Smuzhiyun CONFIG_MSG("magic_pkt_filter_add = %s\n", conf->magic_pkt_filter_add);
3858*4882a593Smuzhiyun }
3859*4882a593Smuzhiyun }
3860*4882a593Smuzhiyun else
3861*4882a593Smuzhiyun return false;
3862*4882a593Smuzhiyun
3863*4882a593Smuzhiyun return true;
3864*4882a593Smuzhiyun }
3865*4882a593Smuzhiyun #endif
3866*4882a593Smuzhiyun
3867*4882a593Smuzhiyun #ifdef ISAM_PREINIT
3868*4882a593Smuzhiyun #if !defined(WL_EXT_IAPSTA)
3869*4882a593Smuzhiyun #error "WL_EXT_IAPSTA should be defined to enable ISAM_PREINIT"
3870*4882a593Smuzhiyun #endif /* !WL_EXT_IAPSTA */
3871*4882a593Smuzhiyun /*
3872*4882a593Smuzhiyun * isam_init=mode [sta|ap|apsta|dualap] vifname [wlan1]
3873*4882a593Smuzhiyun * isam_config=ifname [wlan0|wlan1] ssid [xxx] chan [x]
3874*4882a593Smuzhiyun hidden [y|n] maxassoc [x]
3875*4882a593Smuzhiyun amode [open|shared|wpapsk|wpa2psk|wpawpa2psk]
3876*4882a593Smuzhiyun emode [none|wep|tkip|aes|tkipaes]
3877*4882a593Smuzhiyun key [xxxxx]
3878*4882a593Smuzhiyun * isam_enable=ifname [wlan0|wlan1]
3879*4882a593Smuzhiyun */
3880*4882a593Smuzhiyun bool
dhd_conf_read_isam(dhd_pub_t * dhd,char * full_param,uint len_param)3881*4882a593Smuzhiyun dhd_conf_read_isam(dhd_pub_t *dhd, char *full_param, uint len_param)
3882*4882a593Smuzhiyun {
3883*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
3884*4882a593Smuzhiyun char *data = full_param+len_param;
3885*4882a593Smuzhiyun
3886*4882a593Smuzhiyun if (!strncmp("isam_init=", full_param, len_param)) {
3887*4882a593Smuzhiyun sprintf(conf->isam_init, "isam_init %s", data);
3888*4882a593Smuzhiyun CONFIG_MSG("isam_init=%s\n", conf->isam_init);
3889*4882a593Smuzhiyun }
3890*4882a593Smuzhiyun else if (!strncmp("isam_config=", full_param, len_param)) {
3891*4882a593Smuzhiyun sprintf(conf->isam_config, "isam_config %s", data);
3892*4882a593Smuzhiyun CONFIG_MSG("isam_config=%s\n", conf->isam_config);
3893*4882a593Smuzhiyun }
3894*4882a593Smuzhiyun else if (!strncmp("isam_enable=", full_param, len_param)) {
3895*4882a593Smuzhiyun sprintf(conf->isam_enable, "isam_enable %s", data);
3896*4882a593Smuzhiyun CONFIG_MSG("isam_enable=%s\n", conf->isam_enable);
3897*4882a593Smuzhiyun }
3898*4882a593Smuzhiyun else
3899*4882a593Smuzhiyun return false;
3900*4882a593Smuzhiyun
3901*4882a593Smuzhiyun return true;
3902*4882a593Smuzhiyun }
3903*4882a593Smuzhiyun #endif
3904*4882a593Smuzhiyun
3905*4882a593Smuzhiyun #ifdef IDHCP
3906*4882a593Smuzhiyun bool
dhd_conf_read_dhcp_params(dhd_pub_t * dhd,char * full_param,uint len_param)3907*4882a593Smuzhiyun dhd_conf_read_dhcp_params(dhd_pub_t *dhd, char *full_param, uint len_param)
3908*4882a593Smuzhiyun {
3909*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
3910*4882a593Smuzhiyun char *data = full_param+len_param;
3911*4882a593Smuzhiyun struct ipv4_addr ipa_set;
3912*4882a593Smuzhiyun
3913*4882a593Smuzhiyun if (!strncmp("dhcpc_enable=", full_param, len_param)) {
3914*4882a593Smuzhiyun conf->dhcpc_enable = (int)simple_strtol(data, NULL, 10);
3915*4882a593Smuzhiyun CONFIG_MSG("dhcpc_enable = %d\n", conf->dhcpc_enable);
3916*4882a593Smuzhiyun }
3917*4882a593Smuzhiyun else if (!strncmp("dhcpd_enable=", full_param, len_param)) {
3918*4882a593Smuzhiyun conf->dhcpd_enable = (int)simple_strtol(data, NULL, 10);
3919*4882a593Smuzhiyun CONFIG_MSG("dhcpd_enable = %d\n", conf->dhcpd_enable);
3920*4882a593Smuzhiyun }
3921*4882a593Smuzhiyun else if (!strncmp("dhcpd_ip_addr=", full_param, len_param)) {
3922*4882a593Smuzhiyun if (!bcm_atoipv4(data, &ipa_set)) {
3923*4882a593Smuzhiyun CONFIG_ERROR("dhcpd_ip_addr adress setting failed.n");
3924*4882a593Smuzhiyun return false;
3925*4882a593Smuzhiyun }
3926*4882a593Smuzhiyun memcpy(&conf->dhcpd_ip_addr, &ipa_set, sizeof(struct ipv4_addr));
3927*4882a593Smuzhiyun CONFIG_MSG("dhcpd_ip_addr = %s\n", data);
3928*4882a593Smuzhiyun }
3929*4882a593Smuzhiyun else if (!strncmp("dhcpd_ip_mask=", full_param, len_param)) {
3930*4882a593Smuzhiyun if (!bcm_atoipv4(data, &ipa_set)) {
3931*4882a593Smuzhiyun CONFIG_ERROR("dhcpd_ip_mask adress setting failed\n");
3932*4882a593Smuzhiyun return false;
3933*4882a593Smuzhiyun }
3934*4882a593Smuzhiyun memcpy(&conf->dhcpd_ip_mask, &ipa_set, sizeof(struct ipv4_addr));
3935*4882a593Smuzhiyun CONFIG_MSG("dhcpd_ip_mask = %s\n", data);
3936*4882a593Smuzhiyun }
3937*4882a593Smuzhiyun else if (!strncmp("dhcpd_ip_start=", full_param, len_param)) {
3938*4882a593Smuzhiyun if (!bcm_atoipv4(data, &ipa_set)) {
3939*4882a593Smuzhiyun CONFIG_ERROR("dhcpd_ip_start adress setting failed\n");
3940*4882a593Smuzhiyun return false;
3941*4882a593Smuzhiyun }
3942*4882a593Smuzhiyun memcpy(&conf->dhcpd_ip_start, &ipa_set, sizeof(struct ipv4_addr));
3943*4882a593Smuzhiyun CONFIG_MSG("dhcpd_ip_start = %s\n", data);
3944*4882a593Smuzhiyun }
3945*4882a593Smuzhiyun else if (!strncmp("dhcpd_ip_end=", full_param, len_param)) {
3946*4882a593Smuzhiyun if (!bcm_atoipv4(data, &ipa_set)) {
3947*4882a593Smuzhiyun CONFIG_ERROR("dhcpd_ip_end adress setting failed\n");
3948*4882a593Smuzhiyun return false;
3949*4882a593Smuzhiyun }
3950*4882a593Smuzhiyun memcpy(&conf->dhcpd_ip_end, &ipa_set, sizeof(struct ipv4_addr));
3951*4882a593Smuzhiyun CONFIG_MSG("dhcpd_ip_end = %s\n", data);
3952*4882a593Smuzhiyun }
3953*4882a593Smuzhiyun else
3954*4882a593Smuzhiyun return false;
3955*4882a593Smuzhiyun
3956*4882a593Smuzhiyun return true;
3957*4882a593Smuzhiyun }
3958*4882a593Smuzhiyun #endif
3959*4882a593Smuzhiyun
3960*4882a593Smuzhiyun #ifdef BCMSDIO
3961*4882a593Smuzhiyun bool
dhd_conf_read_sdio_params(dhd_pub_t * dhd,char * full_param,uint len_param)3962*4882a593Smuzhiyun dhd_conf_read_sdio_params(dhd_pub_t *dhd, char *full_param, uint len_param)
3963*4882a593Smuzhiyun {
3964*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
3965*4882a593Smuzhiyun char *data = full_param+len_param;
3966*4882a593Smuzhiyun
3967*4882a593Smuzhiyun if (!strncmp("dhd_doflow=", full_param, len_param)) {
3968*4882a593Smuzhiyun if (!strncmp(data, "0", 1))
3969*4882a593Smuzhiyun dhd_doflow = FALSE;
3970*4882a593Smuzhiyun else
3971*4882a593Smuzhiyun dhd_doflow = TRUE;
3972*4882a593Smuzhiyun CONFIG_MSG("dhd_doflow = %d\n", dhd_doflow);
3973*4882a593Smuzhiyun }
3974*4882a593Smuzhiyun else if (!strncmp("dhd_slpauto=", full_param, len_param)) {
3975*4882a593Smuzhiyun if (!strncmp(data, "0", 1)) {
3976*4882a593Smuzhiyun dhd_conf_disable_slpauto(dhd);
3977*4882a593Smuzhiyun } else
3978*4882a593Smuzhiyun dhd_slpauto = TRUE;
3979*4882a593Smuzhiyun CONFIG_MSG("dhd_slpauto = %d\n", dhd_slpauto);
3980*4882a593Smuzhiyun }
3981*4882a593Smuzhiyun else if (!strncmp("use_rxchain=", full_param, len_param)) {
3982*4882a593Smuzhiyun conf->use_rxchain = (int)simple_strtol(data, NULL, 10);
3983*4882a593Smuzhiyun CONFIG_MSG("use_rxchain = %d\n", conf->use_rxchain);
3984*4882a593Smuzhiyun }
3985*4882a593Smuzhiyun else if (!strncmp("dhd_txminmax=", full_param, len_param)) {
3986*4882a593Smuzhiyun conf->dhd_txminmax = (uint)simple_strtol(data, NULL, 10);
3987*4882a593Smuzhiyun CONFIG_MSG("dhd_txminmax = %d\n", conf->dhd_txminmax);
3988*4882a593Smuzhiyun }
3989*4882a593Smuzhiyun else if (!strncmp("txinrx_thres=", full_param, len_param)) {
3990*4882a593Smuzhiyun conf->txinrx_thres = (int)simple_strtol(data, NULL, 10);
3991*4882a593Smuzhiyun CONFIG_MSG("txinrx_thres = %d\n", conf->txinrx_thres);
3992*4882a593Smuzhiyun }
3993*4882a593Smuzhiyun #ifdef DYNAMIC_MAX_HDR_READ
3994*4882a593Smuzhiyun else if (!strncmp("max_hdr_read=", full_param, len_param)) {
3995*4882a593Smuzhiyun conf->max_hdr_read = (int)simple_strtol(data, NULL, 10);
3996*4882a593Smuzhiyun CONFIG_MSG("max_hdr_read = %d\n", conf->max_hdr_read);
3997*4882a593Smuzhiyun }
3998*4882a593Smuzhiyun else if (!strncmp("dhd_firstread=", full_param, len_param)) {
3999*4882a593Smuzhiyun firstread = (int)simple_strtol(data, NULL, 10);
4000*4882a593Smuzhiyun CONFIG_MSG("dhd_firstread = %d\n", firstread);
4001*4882a593Smuzhiyun }
4002*4882a593Smuzhiyun #endif
4003*4882a593Smuzhiyun #if defined(HW_OOB)
4004*4882a593Smuzhiyun else if (!strncmp("oob_enabled_later=", full_param, len_param)) {
4005*4882a593Smuzhiyun if (!strncmp(data, "0", 1))
4006*4882a593Smuzhiyun conf->oob_enabled_later = FALSE;
4007*4882a593Smuzhiyun else
4008*4882a593Smuzhiyun conf->oob_enabled_later = TRUE;
4009*4882a593Smuzhiyun CONFIG_MSG("oob_enabled_later = %d\n", conf->oob_enabled_later);
4010*4882a593Smuzhiyun }
4011*4882a593Smuzhiyun #endif
4012*4882a593Smuzhiyun else if (!strncmp("dpc_cpucore=", full_param, len_param)) {
4013*4882a593Smuzhiyun conf->dpc_cpucore = (int)simple_strtol(data, NULL, 10);
4014*4882a593Smuzhiyun CONFIG_MSG("dpc_cpucore = %d\n", conf->dpc_cpucore);
4015*4882a593Smuzhiyun }
4016*4882a593Smuzhiyun else if (!strncmp("rxf_cpucore=", full_param, len_param)) {
4017*4882a593Smuzhiyun conf->rxf_cpucore = (int)simple_strtol(data, NULL, 10);
4018*4882a593Smuzhiyun CONFIG_MSG("rxf_cpucore = %d\n", conf->rxf_cpucore);
4019*4882a593Smuzhiyun }
4020*4882a593Smuzhiyun else if (!strncmp("dhd_dpc_prio=", full_param, len_param)) {
4021*4882a593Smuzhiyun conf->dhd_dpc_prio = (int)simple_strtol(data, NULL, 10);
4022*4882a593Smuzhiyun CONFIG_MSG("dhd_dpc_prio = %d\n", conf->dhd_dpc_prio);
4023*4882a593Smuzhiyun }
4024*4882a593Smuzhiyun #if defined(BCMSDIOH_TXGLOM)
4025*4882a593Smuzhiyun else if (!strncmp("txglomsize=", full_param, len_param)) {
4026*4882a593Smuzhiyun conf->txglomsize = (uint)simple_strtol(data, NULL, 10);
4027*4882a593Smuzhiyun if (conf->txglomsize > SDPCM_MAXGLOM_SIZE)
4028*4882a593Smuzhiyun conf->txglomsize = SDPCM_MAXGLOM_SIZE;
4029*4882a593Smuzhiyun CONFIG_MSG("txglomsize = %d\n", conf->txglomsize);
4030*4882a593Smuzhiyun }
4031*4882a593Smuzhiyun else if (!strncmp("txglom_ext=", full_param, len_param)) {
4032*4882a593Smuzhiyun if (!strncmp(data, "0", 1))
4033*4882a593Smuzhiyun conf->txglom_ext = FALSE;
4034*4882a593Smuzhiyun else
4035*4882a593Smuzhiyun conf->txglom_ext = TRUE;
4036*4882a593Smuzhiyun CONFIG_MSG("txglom_ext = %d\n", conf->txglom_ext);
4037*4882a593Smuzhiyun if (conf->txglom_ext) {
4038*4882a593Smuzhiyun if ((conf->chip == BCM43362_CHIP_ID) || (conf->chip == BCM4330_CHIP_ID))
4039*4882a593Smuzhiyun conf->txglom_bucket_size = 1680;
4040*4882a593Smuzhiyun else if (conf->chip == BCM43340_CHIP_ID || conf->chip == BCM43341_CHIP_ID ||
4041*4882a593Smuzhiyun conf->chip == BCM4334_CHIP_ID || conf->chip == BCM4324_CHIP_ID)
4042*4882a593Smuzhiyun conf->txglom_bucket_size = 1684;
4043*4882a593Smuzhiyun }
4044*4882a593Smuzhiyun CONFIG_MSG("txglom_bucket_size = %d\n", conf->txglom_bucket_size);
4045*4882a593Smuzhiyun }
4046*4882a593Smuzhiyun else if (!strncmp("bus:rxglom=", full_param, len_param)) {
4047*4882a593Smuzhiyun if (!strncmp(data, "0", 1))
4048*4882a593Smuzhiyun conf->bus_rxglom = FALSE;
4049*4882a593Smuzhiyun else
4050*4882a593Smuzhiyun conf->bus_rxglom = TRUE;
4051*4882a593Smuzhiyun CONFIG_MSG("bus:rxglom = %d\n", conf->bus_rxglom);
4052*4882a593Smuzhiyun }
4053*4882a593Smuzhiyun else if (!strncmp("deferred_tx_len=", full_param, len_param)) {
4054*4882a593Smuzhiyun conf->deferred_tx_len = (int)simple_strtol(data, NULL, 10);
4055*4882a593Smuzhiyun CONFIG_MSG("deferred_tx_len = %d\n", conf->deferred_tx_len);
4056*4882a593Smuzhiyun }
4057*4882a593Smuzhiyun else if (!strncmp("txctl_tmo_fix=", full_param, len_param)) {
4058*4882a593Smuzhiyun conf->txctl_tmo_fix = (int)simple_strtol(data, NULL, 0);
4059*4882a593Smuzhiyun CONFIG_MSG("txctl_tmo_fix = %d\n", conf->txctl_tmo_fix);
4060*4882a593Smuzhiyun }
4061*4882a593Smuzhiyun else if (!strncmp("tx_max_offset=", full_param, len_param)) {
4062*4882a593Smuzhiyun conf->tx_max_offset = (int)simple_strtol(data, NULL, 10);
4063*4882a593Smuzhiyun CONFIG_MSG("tx_max_offset = %d\n", conf->tx_max_offset);
4064*4882a593Smuzhiyun }
4065*4882a593Smuzhiyun else if (!strncmp("txglom_mode=", full_param, len_param)) {
4066*4882a593Smuzhiyun if (!strncmp(data, "0", 1))
4067*4882a593Smuzhiyun conf->txglom_mode = FALSE;
4068*4882a593Smuzhiyun else
4069*4882a593Smuzhiyun conf->txglom_mode = TRUE;
4070*4882a593Smuzhiyun CONFIG_MSG("txglom_mode = %d\n", conf->txglom_mode);
4071*4882a593Smuzhiyun }
4072*4882a593Smuzhiyun #if defined(SDIO_ISR_THREAD)
4073*4882a593Smuzhiyun else if (!strncmp("intr_extn=", full_param, len_param)) {
4074*4882a593Smuzhiyun if (!strncmp(data, "0", 1))
4075*4882a593Smuzhiyun conf->intr_extn = FALSE;
4076*4882a593Smuzhiyun else
4077*4882a593Smuzhiyun conf->intr_extn = TRUE;
4078*4882a593Smuzhiyun CONFIG_MSG("intr_extn = %d\n", conf->intr_extn);
4079*4882a593Smuzhiyun }
4080*4882a593Smuzhiyun #endif
4081*4882a593Smuzhiyun #ifdef BCMSDIO_RXLIM_POST
4082*4882a593Smuzhiyun else if (!strncmp("rxlim_en=", full_param, len_param)) {
4083*4882a593Smuzhiyun if (!strncmp(data, "0", 1))
4084*4882a593Smuzhiyun conf->rxlim_en = FALSE;
4085*4882a593Smuzhiyun else
4086*4882a593Smuzhiyun conf->rxlim_en = TRUE;
4087*4882a593Smuzhiyun CONFIG_MSG("rxlim_en = %d\n", conf->rxlim_en);
4088*4882a593Smuzhiyun }
4089*4882a593Smuzhiyun #endif
4090*4882a593Smuzhiyun #ifdef BCMSDIO_TXSEQ_SYNC
4091*4882a593Smuzhiyun else if (!strncmp("txseq_sync=", full_param, len_param)) {
4092*4882a593Smuzhiyun if (!strncmp(data, "0", 1))
4093*4882a593Smuzhiyun conf->txseq_sync = FALSE;
4094*4882a593Smuzhiyun else
4095*4882a593Smuzhiyun conf->txseq_sync = TRUE;
4096*4882a593Smuzhiyun CONFIG_MSG("txseq_sync = %d\n", conf->txseq_sync);
4097*4882a593Smuzhiyun }
4098*4882a593Smuzhiyun #endif
4099*4882a593Smuzhiyun #endif
4100*4882a593Smuzhiyun #ifdef MINIME
4101*4882a593Smuzhiyun else if (!strncmp("ramsize=", full_param, len_param)) {
4102*4882a593Smuzhiyun conf->ramsize = (uint32)simple_strtol(data, NULL, 0);
4103*4882a593Smuzhiyun CONFIG_MSG("ramsize = %d\n", conf->ramsize);
4104*4882a593Smuzhiyun }
4105*4882a593Smuzhiyun #endif
4106*4882a593Smuzhiyun #ifdef BCMSDIO_INTSTATUS_WAR
4107*4882a593Smuzhiyun else if (!strncmp("read_intr_mode=", full_param, len_param)) {
4108*4882a593Smuzhiyun conf->read_intr_mode = (int)simple_strtol(data, NULL, 0);
4109*4882a593Smuzhiyun CONFIG_MSG("read_intr_mode = %d\n", conf->read_intr_mode);
4110*4882a593Smuzhiyun }
4111*4882a593Smuzhiyun #endif
4112*4882a593Smuzhiyun else if (!strncmp("kso_try_max=", full_param, len_param)) {
4113*4882a593Smuzhiyun conf->kso_try_max = (int)simple_strtol(data, NULL, 0);
4114*4882a593Smuzhiyun CONFIG_MSG("kso_try_max = %d\n", conf->kso_try_max);
4115*4882a593Smuzhiyun }
4116*4882a593Smuzhiyun else
4117*4882a593Smuzhiyun return false;
4118*4882a593Smuzhiyun
4119*4882a593Smuzhiyun return true;
4120*4882a593Smuzhiyun }
4121*4882a593Smuzhiyun #endif
4122*4882a593Smuzhiyun
4123*4882a593Smuzhiyun #ifdef BCMPCIE
4124*4882a593Smuzhiyun bool
dhd_conf_read_pcie_params(dhd_pub_t * dhd,char * full_param,uint len_param)4125*4882a593Smuzhiyun dhd_conf_read_pcie_params(dhd_pub_t *dhd, char *full_param, uint len_param)
4126*4882a593Smuzhiyun {
4127*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
4128*4882a593Smuzhiyun char *data = full_param+len_param;
4129*4882a593Smuzhiyun
4130*4882a593Smuzhiyun if (!strncmp("bus:deepsleep_disable=", full_param, len_param)) {
4131*4882a593Smuzhiyun if (!strncmp(data, "0", 1))
4132*4882a593Smuzhiyun conf->bus_deepsleep_disable = 0;
4133*4882a593Smuzhiyun else
4134*4882a593Smuzhiyun conf->bus_deepsleep_disable = 1;
4135*4882a593Smuzhiyun CONFIG_MSG("bus:deepsleep_disable = %d\n", conf->bus_deepsleep_disable);
4136*4882a593Smuzhiyun }
4137*4882a593Smuzhiyun else if (!strncmp("flow_ring_queue_threshold=", full_param, len_param)) {
4138*4882a593Smuzhiyun conf->flow_ring_queue_threshold = (int)simple_strtol(data, NULL, 10);
4139*4882a593Smuzhiyun CONFIG_MSG("flow_ring_queue_threshold = %d\n", conf->flow_ring_queue_threshold);
4140*4882a593Smuzhiyun }
4141*4882a593Smuzhiyun else if (!strncmp("d2h_intr_control=", full_param, len_param)) {
4142*4882a593Smuzhiyun conf->d2h_intr_control = (int)simple_strtol(data, NULL, 10);
4143*4882a593Smuzhiyun CONFIG_MSG("d2h_intr_control = %d\n", conf->d2h_intr_control);
4144*4882a593Smuzhiyun }
4145*4882a593Smuzhiyun else if (!strncmp("enq_hdr_pkt=", full_param, len_param)) {
4146*4882a593Smuzhiyun conf->enq_hdr_pkt = (int)simple_strtol(data, NULL, 0);
4147*4882a593Smuzhiyun CONFIG_MSG("enq_hdr_pkt = 0x%x\n", conf->enq_hdr_pkt);
4148*4882a593Smuzhiyun }
4149*4882a593Smuzhiyun else if (!strncmp("aspm=", full_param, len_param)) {
4150*4882a593Smuzhiyun conf->aspm = (int)simple_strtol(data, NULL, 0);
4151*4882a593Smuzhiyun CONFIG_MSG("aspm = %d\n", conf->aspm);
4152*4882a593Smuzhiyun }
4153*4882a593Smuzhiyun else if (!strncmp("l1ss=", full_param, len_param)) {
4154*4882a593Smuzhiyun conf->l1ss = (int)simple_strtol(data, NULL, 0);
4155*4882a593Smuzhiyun CONFIG_MSG("l1ss = %d\n", conf->l1ss);
4156*4882a593Smuzhiyun }
4157*4882a593Smuzhiyun else
4158*4882a593Smuzhiyun return false;
4159*4882a593Smuzhiyun
4160*4882a593Smuzhiyun return true;
4161*4882a593Smuzhiyun }
4162*4882a593Smuzhiyun #endif
4163*4882a593Smuzhiyun
4164*4882a593Smuzhiyun bool
dhd_conf_read_pm_params(dhd_pub_t * dhd,char * full_param,uint len_param)4165*4882a593Smuzhiyun dhd_conf_read_pm_params(dhd_pub_t *dhd, char *full_param, uint len_param)
4166*4882a593Smuzhiyun {
4167*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
4168*4882a593Smuzhiyun char *data = full_param+len_param;
4169*4882a593Smuzhiyun
4170*4882a593Smuzhiyun if (!strncmp("deepsleep=", full_param, len_param)) {
4171*4882a593Smuzhiyun if (!strncmp(data, "1", 1))
4172*4882a593Smuzhiyun conf->deepsleep = TRUE;
4173*4882a593Smuzhiyun else
4174*4882a593Smuzhiyun conf->deepsleep = FALSE;
4175*4882a593Smuzhiyun CONFIG_MSG("deepsleep = %d\n", conf->deepsleep);
4176*4882a593Smuzhiyun }
4177*4882a593Smuzhiyun else if (!strncmp("PM=", full_param, len_param)) {
4178*4882a593Smuzhiyun conf->pm = (int)simple_strtol(data, NULL, 10);
4179*4882a593Smuzhiyun CONFIG_MSG("PM = %d\n", conf->pm);
4180*4882a593Smuzhiyun }
4181*4882a593Smuzhiyun else if (!strncmp("pm_in_suspend=", full_param, len_param)) {
4182*4882a593Smuzhiyun conf->pm_in_suspend = (int)simple_strtol(data, NULL, 10);
4183*4882a593Smuzhiyun CONFIG_MSG("pm_in_suspend = %d\n", conf->pm_in_suspend);
4184*4882a593Smuzhiyun }
4185*4882a593Smuzhiyun else if (!strncmp("suspend_mode=", full_param, len_param)) {
4186*4882a593Smuzhiyun conf->suspend_mode = (int)simple_strtol(data, NULL, 0);
4187*4882a593Smuzhiyun CONFIG_MSG("suspend_mode = %d\n", conf->suspend_mode);
4188*4882a593Smuzhiyun if (conf->suspend_mode == EARLY_SUSPEND)
4189*4882a593Smuzhiyun conf->insuspend &= ~(NO_TXDATA_IN_SUSPEND | NO_TXCTL_IN_SUSPEND);
4190*4882a593Smuzhiyun else if (conf->suspend_mode == PM_NOTIFIER ||
4191*4882a593Smuzhiyun conf->suspend_mode == SUSPEND_MODE_2)
4192*4882a593Smuzhiyun conf->insuspend |= (NO_TXDATA_IN_SUSPEND | NO_TXCTL_IN_SUSPEND);
4193*4882a593Smuzhiyun CONFIG_MSG("insuspend = 0x%x\n", conf->insuspend);
4194*4882a593Smuzhiyun }
4195*4882a593Smuzhiyun else if (!strncmp("suspend_bcn_li_dtim=", full_param, len_param)) {
4196*4882a593Smuzhiyun conf->suspend_bcn_li_dtim = (int)simple_strtol(data, NULL, 10);
4197*4882a593Smuzhiyun CONFIG_MSG("suspend_bcn_li_dtim = %d\n", conf->suspend_bcn_li_dtim);
4198*4882a593Smuzhiyun }
4199*4882a593Smuzhiyun else if (!strncmp("xmit_in_suspend=", full_param, len_param)) {
4200*4882a593Smuzhiyun if (!strncmp(data, "1", 1))
4201*4882a593Smuzhiyun conf->insuspend &= ~NO_TXDATA_IN_SUSPEND;
4202*4882a593Smuzhiyun else
4203*4882a593Smuzhiyun conf->insuspend |= NO_TXDATA_IN_SUSPEND;
4204*4882a593Smuzhiyun CONFIG_MSG("insuspend = 0x%x\n", conf->insuspend);
4205*4882a593Smuzhiyun }
4206*4882a593Smuzhiyun else if (!strncmp("insuspend=", full_param, len_param)) {
4207*4882a593Smuzhiyun conf->insuspend = (int)simple_strtol(data, NULL, 0);
4208*4882a593Smuzhiyun CONFIG_MSG("insuspend = 0x%x\n", conf->insuspend);
4209*4882a593Smuzhiyun }
4210*4882a593Smuzhiyun #ifdef WL_EXT_WOWL
4211*4882a593Smuzhiyun else if (!strncmp("wowl=", full_param, len_param)) {
4212*4882a593Smuzhiyun conf->wowl = (int)simple_strtol(data, NULL, 0);
4213*4882a593Smuzhiyun CONFIG_MSG("wowl = 0x%x\n", conf->wowl);
4214*4882a593Smuzhiyun }
4215*4882a593Smuzhiyun #endif
4216*4882a593Smuzhiyun else if (!strncmp("rekey_offload=", full_param, len_param)) {
4217*4882a593Smuzhiyun if (!strncmp(data, "1", 1))
4218*4882a593Smuzhiyun conf->rekey_offload = TRUE;
4219*4882a593Smuzhiyun else
4220*4882a593Smuzhiyun conf->rekey_offload = FALSE;
4221*4882a593Smuzhiyun CONFIG_MSG("rekey_offload = %d\n", conf->rekey_offload);
4222*4882a593Smuzhiyun }
4223*4882a593Smuzhiyun else
4224*4882a593Smuzhiyun return false;
4225*4882a593Smuzhiyun
4226*4882a593Smuzhiyun return true;
4227*4882a593Smuzhiyun }
4228*4882a593Smuzhiyun
4229*4882a593Smuzhiyun #ifdef GET_CUSTOM_MAC_FROM_CONFIG
4230*4882a593Smuzhiyun int
bcm_str2hex(const char * p,char * ea,int size)4231*4882a593Smuzhiyun bcm_str2hex(const char *p, char *ea, int size)
4232*4882a593Smuzhiyun {
4233*4882a593Smuzhiyun int i = 0;
4234*4882a593Smuzhiyun char *ep;
4235*4882a593Smuzhiyun
4236*4882a593Smuzhiyun for (;;) {
4237*4882a593Smuzhiyun ea[i++] = (char) bcm_strtoul(p, &ep, 16);
4238*4882a593Smuzhiyun p = ep;
4239*4882a593Smuzhiyun if (!*p++ || i == size)
4240*4882a593Smuzhiyun break;
4241*4882a593Smuzhiyun }
4242*4882a593Smuzhiyun
4243*4882a593Smuzhiyun return (i == size);
4244*4882a593Smuzhiyun }
4245*4882a593Smuzhiyun #endif
4246*4882a593Smuzhiyun
4247*4882a593Smuzhiyun bool
dhd_conf_read_others(dhd_pub_t * dhd,char * full_param,uint len_param)4248*4882a593Smuzhiyun dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param)
4249*4882a593Smuzhiyun {
4250*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
4251*4882a593Smuzhiyun char *data = full_param+len_param;
4252*4882a593Smuzhiyun char *pch, *pick_tmp;
4253*4882a593Smuzhiyun int i;
4254*4882a593Smuzhiyun #ifdef GET_CUSTOM_MAC_FROM_CONFIG
4255*4882a593Smuzhiyun struct ether_addr ea_addr;
4256*4882a593Smuzhiyun char macpad[56];
4257*4882a593Smuzhiyun #endif
4258*4882a593Smuzhiyun
4259*4882a593Smuzhiyun if (!strncmp("dhd_poll=", full_param, len_param)) {
4260*4882a593Smuzhiyun if (!strncmp(data, "0", 1))
4261*4882a593Smuzhiyun conf->dhd_poll = 0;
4262*4882a593Smuzhiyun else
4263*4882a593Smuzhiyun conf->dhd_poll = 1;
4264*4882a593Smuzhiyun CONFIG_MSG("dhd_poll = %d\n", conf->dhd_poll);
4265*4882a593Smuzhiyun }
4266*4882a593Smuzhiyun else if (!strncmp("dhd_watchdog_ms=", full_param, len_param)) {
4267*4882a593Smuzhiyun dhd_watchdog_ms = (int)simple_strtol(data, NULL, 10);
4268*4882a593Smuzhiyun CONFIG_MSG("dhd_watchdog_ms = %d\n", dhd_watchdog_ms);
4269*4882a593Smuzhiyun }
4270*4882a593Smuzhiyun else if (!strncmp("band=", full_param, len_param)) {
4271*4882a593Smuzhiyun /* Process band:
4272*4882a593Smuzhiyun * band=a for 5GHz only and band=b for 2.4GHz only
4273*4882a593Smuzhiyun */
4274*4882a593Smuzhiyun if (!strcmp(data, "b"))
4275*4882a593Smuzhiyun conf->band = WLC_BAND_2G;
4276*4882a593Smuzhiyun else if (!strcmp(data, "a"))
4277*4882a593Smuzhiyun conf->band = WLC_BAND_5G;
4278*4882a593Smuzhiyun else
4279*4882a593Smuzhiyun conf->band = WLC_BAND_AUTO;
4280*4882a593Smuzhiyun CONFIG_MSG("band = %d\n", conf->band);
4281*4882a593Smuzhiyun }
4282*4882a593Smuzhiyun else if (!strncmp("bw_cap_2g=", full_param, len_param)) {
4283*4882a593Smuzhiyun conf->bw_cap[0] = (uint)simple_strtol(data, NULL, 0);
4284*4882a593Smuzhiyun CONFIG_MSG("bw_cap_2g = %d\n", conf->bw_cap[0]);
4285*4882a593Smuzhiyun }
4286*4882a593Smuzhiyun else if (!strncmp("bw_cap_5g=", full_param, len_param)) {
4287*4882a593Smuzhiyun conf->bw_cap[1] = (uint)simple_strtol(data, NULL, 0);
4288*4882a593Smuzhiyun CONFIG_MSG("bw_cap_5g = %d\n", conf->bw_cap[1]);
4289*4882a593Smuzhiyun }
4290*4882a593Smuzhiyun else if (!strncmp("bw_cap=", full_param, len_param)) {
4291*4882a593Smuzhiyun pick_tmp = data;
4292*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ,.-", 0);
4293*4882a593Smuzhiyun if (pch != NULL) {
4294*4882a593Smuzhiyun conf->bw_cap[0] = (uint32)simple_strtol(pch, NULL, 0);
4295*4882a593Smuzhiyun CONFIG_MSG("bw_cap 2g = %d\n", conf->bw_cap[0]);
4296*4882a593Smuzhiyun }
4297*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ,.-", 0);
4298*4882a593Smuzhiyun if (pch != NULL) {
4299*4882a593Smuzhiyun conf->bw_cap[1] = (uint32)simple_strtol(pch, NULL, 0);
4300*4882a593Smuzhiyun CONFIG_MSG("bw_cap 5g = %d\n", conf->bw_cap[1]);
4301*4882a593Smuzhiyun }
4302*4882a593Smuzhiyun }
4303*4882a593Smuzhiyun else if (!strncmp("channels=", full_param, len_param)) {
4304*4882a593Smuzhiyun pick_tmp = data;
4305*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ,.-", 0);
4306*4882a593Smuzhiyun i=0;
4307*4882a593Smuzhiyun while (pch != NULL && i<WL_NUMCHANNELS) {
4308*4882a593Smuzhiyun conf->channels.channel[i] = (uint32)simple_strtol(pch, NULL, 10);
4309*4882a593Smuzhiyun pch = bcmstrtok(&pick_tmp, " ,.-", 0);
4310*4882a593Smuzhiyun i++;
4311*4882a593Smuzhiyun }
4312*4882a593Smuzhiyun conf->channels.count = i;
4313*4882a593Smuzhiyun CONFIG_MSG("channels = ");
4314*4882a593Smuzhiyun for (i=0; i<conf->channels.count; i++)
4315*4882a593Smuzhiyun printk(KERN_CONT "%d ", conf->channels.channel[i]);
4316*4882a593Smuzhiyun printk(KERN_CONT "\n");
4317*4882a593Smuzhiyun }
4318*4882a593Smuzhiyun else if (!strncmp("keep_alive_period=", full_param, len_param)) {
4319*4882a593Smuzhiyun conf->keep_alive_period = (uint)simple_strtol(data, NULL, 10);
4320*4882a593Smuzhiyun CONFIG_MSG("keep_alive_period = %d\n", conf->keep_alive_period);
4321*4882a593Smuzhiyun }
4322*4882a593Smuzhiyun #ifdef ARP_OFFLOAD_SUPPORT
4323*4882a593Smuzhiyun else if (!strncmp("garp=", full_param, len_param)) {
4324*4882a593Smuzhiyun if (!strncmp(data, "0", 1))
4325*4882a593Smuzhiyun conf->garp = FALSE;
4326*4882a593Smuzhiyun else
4327*4882a593Smuzhiyun conf->garp = TRUE;
4328*4882a593Smuzhiyun CONFIG_MSG("garp = %d\n", conf->garp);
4329*4882a593Smuzhiyun }
4330*4882a593Smuzhiyun #endif
4331*4882a593Smuzhiyun else if (!strncmp("srl=", full_param, len_param)) {
4332*4882a593Smuzhiyun conf->srl = (int)simple_strtol(data, NULL, 10);
4333*4882a593Smuzhiyun CONFIG_MSG("srl = %d\n", conf->srl);
4334*4882a593Smuzhiyun }
4335*4882a593Smuzhiyun else if (!strncmp("lrl=", full_param, len_param)) {
4336*4882a593Smuzhiyun conf->lrl = (int)simple_strtol(data, NULL, 10);
4337*4882a593Smuzhiyun CONFIG_MSG("lrl = %d\n", conf->lrl);
4338*4882a593Smuzhiyun }
4339*4882a593Smuzhiyun else if (!strncmp("bcn_timeout=", full_param, len_param)) {
4340*4882a593Smuzhiyun conf->bcn_timeout= (uint)simple_strtol(data, NULL, 10);
4341*4882a593Smuzhiyun CONFIG_MSG("bcn_timeout = %d\n", conf->bcn_timeout);
4342*4882a593Smuzhiyun }
4343*4882a593Smuzhiyun else if (!strncmp("frameburst=", full_param, len_param)) {
4344*4882a593Smuzhiyun conf->frameburst = (int)simple_strtol(data, NULL, 10);
4345*4882a593Smuzhiyun CONFIG_MSG("frameburst = %d\n", conf->frameburst);
4346*4882a593Smuzhiyun }
4347*4882a593Smuzhiyun else if (!strncmp("disable_proptx=", full_param, len_param)) {
4348*4882a593Smuzhiyun conf->disable_proptx = (int)simple_strtol(data, NULL, 10);
4349*4882a593Smuzhiyun CONFIG_MSG("disable_proptx = %d\n", conf->disable_proptx);
4350*4882a593Smuzhiyun }
4351*4882a593Smuzhiyun #ifdef DHDTCPACK_SUPPRESS
4352*4882a593Smuzhiyun else if (!strncmp("tcpack_sup_mode=", full_param, len_param)) {
4353*4882a593Smuzhiyun conf->tcpack_sup_mode = (uint)simple_strtol(data, NULL, 10);
4354*4882a593Smuzhiyun CONFIG_MSG("tcpack_sup_mode = %d\n", conf->tcpack_sup_mode);
4355*4882a593Smuzhiyun }
4356*4882a593Smuzhiyun else if (!strncmp("tcpack_sup_ratio=", full_param, len_param)) {
4357*4882a593Smuzhiyun conf->tcpack_sup_ratio = (uint)simple_strtol(data, NULL, 10);
4358*4882a593Smuzhiyun CONFIG_MSG("tcpack_sup_ratio = %d\n", conf->tcpack_sup_ratio);
4359*4882a593Smuzhiyun }
4360*4882a593Smuzhiyun else if (!strncmp("tcpack_sup_delay=", full_param, len_param)) {
4361*4882a593Smuzhiyun conf->tcpack_sup_delay = (uint)simple_strtol(data, NULL, 10);
4362*4882a593Smuzhiyun CONFIG_MSG("tcpack_sup_delay = %d\n", conf->tcpack_sup_delay);
4363*4882a593Smuzhiyun }
4364*4882a593Smuzhiyun #endif
4365*4882a593Smuzhiyun else if (!strncmp("pktprio8021x=", full_param, len_param)) {
4366*4882a593Smuzhiyun conf->pktprio8021x = (int)simple_strtol(data, NULL, 10);
4367*4882a593Smuzhiyun CONFIG_MSG("pktprio8021x = %d\n", conf->pktprio8021x);
4368*4882a593Smuzhiyun }
4369*4882a593Smuzhiyun #if defined(BCMSDIO) || defined(BCMPCIE)
4370*4882a593Smuzhiyun else if (!strncmp("dhd_txbound=", full_param, len_param)) {
4371*4882a593Smuzhiyun dhd_txbound = (uint)simple_strtol(data, NULL, 10);
4372*4882a593Smuzhiyun CONFIG_MSG("dhd_txbound = %d\n", dhd_txbound);
4373*4882a593Smuzhiyun }
4374*4882a593Smuzhiyun else if (!strncmp("dhd_rxbound=", full_param, len_param)) {
4375*4882a593Smuzhiyun dhd_rxbound = (uint)simple_strtol(data, NULL, 10);
4376*4882a593Smuzhiyun CONFIG_MSG("dhd_rxbound = %d\n", dhd_rxbound);
4377*4882a593Smuzhiyun }
4378*4882a593Smuzhiyun #endif
4379*4882a593Smuzhiyun else if (!strncmp("orphan_move=", full_param, len_param)) {
4380*4882a593Smuzhiyun conf->orphan_move = (int)simple_strtol(data, NULL, 10);
4381*4882a593Smuzhiyun CONFIG_MSG("orphan_move = %d\n", conf->orphan_move);
4382*4882a593Smuzhiyun }
4383*4882a593Smuzhiyun else if (!strncmp("tsq=", full_param, len_param)) {
4384*4882a593Smuzhiyun conf->tsq = (int)simple_strtol(data, NULL, 10);
4385*4882a593Smuzhiyun CONFIG_MSG("tsq = %d\n", conf->tsq);
4386*4882a593Smuzhiyun }
4387*4882a593Smuzhiyun else if (!strncmp("ctrl_resched=", full_param, len_param)) {
4388*4882a593Smuzhiyun conf->ctrl_resched = (int)simple_strtol(data, NULL, 10);
4389*4882a593Smuzhiyun CONFIG_MSG("ctrl_resched = %d\n", conf->ctrl_resched);
4390*4882a593Smuzhiyun }
4391*4882a593Smuzhiyun else if (!strncmp("rxcnt_timeout=", full_param, len_param)) {
4392*4882a593Smuzhiyun conf->rxcnt_timeout = (int)simple_strtol(data, NULL, 10);
4393*4882a593Smuzhiyun CONFIG_MSG("rxcnt_timeout = %d\n", conf->rxcnt_timeout);
4394*4882a593Smuzhiyun }
4395*4882a593Smuzhiyun else if (!strncmp("in4way=", full_param, len_param)) {
4396*4882a593Smuzhiyun conf->in4way = (int)simple_strtol(data, NULL, 0);
4397*4882a593Smuzhiyun CONFIG_MSG("in4way = 0x%x\n", conf->in4way);
4398*4882a593Smuzhiyun }
4399*4882a593Smuzhiyun #ifdef BTC_WAR
4400*4882a593Smuzhiyun else if (!strncmp("btc_war=", full_param, len_param)) {
4401*4882a593Smuzhiyun btc_war = (int)simple_strtol(data, NULL, 0);
4402*4882a593Smuzhiyun CONFIG_MSG("btc_war = 0x%x\n", btc_war);
4403*4882a593Smuzhiyun }
4404*4882a593Smuzhiyun #endif /* BTC_WAR */
4405*4882a593Smuzhiyun else if (!strncmp("war=", full_param, len_param)) {
4406*4882a593Smuzhiyun conf->war = (int)simple_strtol(data, NULL, 0);
4407*4882a593Smuzhiyun CONFIG_MSG("war = 0x%x\n", conf->war);
4408*4882a593Smuzhiyun }
4409*4882a593Smuzhiyun else if (!strncmp("wl_preinit=", full_param, len_param)) {
4410*4882a593Smuzhiyun if (conf->wl_preinit) {
4411*4882a593Smuzhiyun kfree(conf->wl_preinit);
4412*4882a593Smuzhiyun conf->wl_preinit = NULL;
4413*4882a593Smuzhiyun }
4414*4882a593Smuzhiyun if (!(conf->wl_preinit = kmalloc(strlen(data)+1, GFP_KERNEL))) {
4415*4882a593Smuzhiyun CONFIG_ERROR("kmalloc failed\n");
4416*4882a593Smuzhiyun } else {
4417*4882a593Smuzhiyun memset(conf->wl_preinit, 0, strlen(data)+1);
4418*4882a593Smuzhiyun strcpy(conf->wl_preinit, data);
4419*4882a593Smuzhiyun CONFIG_MSG("wl_preinit = %s\n", conf->wl_preinit);
4420*4882a593Smuzhiyun }
4421*4882a593Smuzhiyun }
4422*4882a593Smuzhiyun else if (!strncmp("wl_suspend=", full_param, len_param)) {
4423*4882a593Smuzhiyun if (conf->wl_suspend) {
4424*4882a593Smuzhiyun kfree(conf->wl_suspend);
4425*4882a593Smuzhiyun conf->wl_suspend = NULL;
4426*4882a593Smuzhiyun }
4427*4882a593Smuzhiyun if (!(conf->wl_suspend = kmalloc(strlen(data)+1, GFP_KERNEL))) {
4428*4882a593Smuzhiyun CONFIG_ERROR("kmalloc failed\n");
4429*4882a593Smuzhiyun } else {
4430*4882a593Smuzhiyun memset(conf->wl_suspend, 0, strlen(data)+1);
4431*4882a593Smuzhiyun strcpy(conf->wl_suspend, data);
4432*4882a593Smuzhiyun CONFIG_MSG("wl_suspend = %s\n", conf->wl_suspend);
4433*4882a593Smuzhiyun }
4434*4882a593Smuzhiyun }
4435*4882a593Smuzhiyun else if (!strncmp("wl_resume=", full_param, len_param)) {
4436*4882a593Smuzhiyun if (conf->wl_resume) {
4437*4882a593Smuzhiyun kfree(conf->wl_resume);
4438*4882a593Smuzhiyun conf->wl_resume = NULL;
4439*4882a593Smuzhiyun }
4440*4882a593Smuzhiyun if (!(conf->wl_resume = kmalloc(strlen(data)+1, GFP_KERNEL))) {
4441*4882a593Smuzhiyun CONFIG_ERROR("kmalloc failed\n");
4442*4882a593Smuzhiyun } else {
4443*4882a593Smuzhiyun memset(conf->wl_resume, 0, strlen(data)+1);
4444*4882a593Smuzhiyun strcpy(conf->wl_resume, data);
4445*4882a593Smuzhiyun CONFIG_MSG("wl_resume = %s\n", conf->wl_resume);
4446*4882a593Smuzhiyun }
4447*4882a593Smuzhiyun }
4448*4882a593Smuzhiyun #ifdef GET_CUSTOM_MAC_FROM_CONFIG
4449*4882a593Smuzhiyun else if (!strncmp("mac=", full_param, len_param)) {
4450*4882a593Smuzhiyun if (!bcm_ether_atoe(data, &ea_addr)) {
4451*4882a593Smuzhiyun CONFIG_ERROR("mac adress read error");
4452*4882a593Smuzhiyun return false;
4453*4882a593Smuzhiyun }
4454*4882a593Smuzhiyun memcpy(&conf->hw_ether, &ea_addr, ETHER_ADDR_LEN);
4455*4882a593Smuzhiyun CONFIG_MSG("mac = %s\n", data);
4456*4882a593Smuzhiyun }
4457*4882a593Smuzhiyun else if (!strncmp("macpad=", full_param, len_param)) {
4458*4882a593Smuzhiyun if (!bcm_str2hex(data, macpad, sizeof(macpad))) {
4459*4882a593Smuzhiyun CONFIG_ERROR("macpad adress read error");
4460*4882a593Smuzhiyun return false;
4461*4882a593Smuzhiyun }
4462*4882a593Smuzhiyun memcpy(&conf->hw_ether[ETHER_ADDR_LEN], macpad, sizeof(macpad));
4463*4882a593Smuzhiyun if (config_msg_level & CONFIG_TRACE_LEVEL) {
4464*4882a593Smuzhiyun CONFIG_MSG("macpad =\n");
4465*4882a593Smuzhiyun for (i=0; i<sizeof(macpad); i++) {
4466*4882a593Smuzhiyun printk(KERN_CONT "0x%02x, ", conf->hw_ether[ETHER_ADDR_LEN+i]);
4467*4882a593Smuzhiyun if ((i+1)%8 == 0)
4468*4882a593Smuzhiyun printk(KERN_CONT "\n");
4469*4882a593Smuzhiyun }
4470*4882a593Smuzhiyun }
4471*4882a593Smuzhiyun }
4472*4882a593Smuzhiyun #endif
4473*4882a593Smuzhiyun #ifdef PROPTX_MAXCOUNT
4474*4882a593Smuzhiyun else if (!strncmp("proptx_maxcnt_2g=", full_param, len_param)) {
4475*4882a593Smuzhiyun conf->proptx_maxcnt_2g = (int)simple_strtol(data, NULL, 0);
4476*4882a593Smuzhiyun CONFIG_MSG("proptx_maxcnt_2g = %d\n", conf->proptx_maxcnt_2g);
4477*4882a593Smuzhiyun }
4478*4882a593Smuzhiyun else if (!strncmp("proptx_maxcnt_5g=", full_param, len_param)) {
4479*4882a593Smuzhiyun conf->proptx_maxcnt_5g = (int)simple_strtol(data, NULL, 0);
4480*4882a593Smuzhiyun CONFIG_MSG("proptx_maxcnt_5g = %d\n", conf->proptx_maxcnt_5g);
4481*4882a593Smuzhiyun }
4482*4882a593Smuzhiyun #endif
4483*4882a593Smuzhiyun #ifdef TPUT_MONITOR
4484*4882a593Smuzhiyun else if (!strncmp("data_drop_mode=", full_param, len_param)) {
4485*4882a593Smuzhiyun conf->data_drop_mode = (int)simple_strtol(data, NULL, 0);
4486*4882a593Smuzhiyun CONFIG_MSG("data_drop_mode = %d\n", conf->data_drop_mode);
4487*4882a593Smuzhiyun }
4488*4882a593Smuzhiyun else if (!strncmp("tput_monitor_ms=", full_param, len_param)) {
4489*4882a593Smuzhiyun conf->tput_monitor_ms = (int)simple_strtol(data, NULL, 0);
4490*4882a593Smuzhiyun CONFIG_MSG("tput_monitor_ms = %d\n", conf->tput_monitor_ms);
4491*4882a593Smuzhiyun }
4492*4882a593Smuzhiyun #ifdef BCMSDIO
4493*4882a593Smuzhiyun else if (!strncmp("doflow_tput_thresh=", full_param, len_param)) {
4494*4882a593Smuzhiyun conf->doflow_tput_thresh = (int)simple_strtol(data, NULL, 0);
4495*4882a593Smuzhiyun CONFIG_MSG("doflow_tput_thresh = %d\n", conf->doflow_tput_thresh);
4496*4882a593Smuzhiyun if (conf->doflow_tput_thresh > 0)
4497*4882a593Smuzhiyun conf->tput_monitor_ms = 1000;
4498*4882a593Smuzhiyun }
4499*4882a593Smuzhiyun #endif
4500*4882a593Smuzhiyun #endif
4501*4882a593Smuzhiyun #ifdef SCAN_SUPPRESS
4502*4882a593Smuzhiyun else if (!strncmp("scan_intput=", full_param, len_param)) {
4503*4882a593Smuzhiyun conf->scan_intput = (int)simple_strtol(data, NULL, 0);
4504*4882a593Smuzhiyun CONFIG_MSG("scan_intput = 0x%x\n", conf->scan_intput);
4505*4882a593Smuzhiyun }
4506*4882a593Smuzhiyun else if (!strncmp("scan_tput_thresh=", full_param, len_param)) {
4507*4882a593Smuzhiyun conf->scan_tput_thresh = (int)simple_strtol(data, NULL, 0);
4508*4882a593Smuzhiyun CONFIG_MSG("scan_tput_thresh = %d\n", conf->scan_tput_thresh);
4509*4882a593Smuzhiyun if (conf->scan_tput_thresh > 0)
4510*4882a593Smuzhiyun conf->tput_monitor_ms = 1000;
4511*4882a593Smuzhiyun }
4512*4882a593Smuzhiyun else if (!strncmp("scan_busy_tmo=", full_param, len_param)) {
4513*4882a593Smuzhiyun conf->scan_busy_tmo = (int)simple_strtol(data, NULL, 0);
4514*4882a593Smuzhiyun CONFIG_MSG("scan_busy_tmo = %d\n", conf->scan_busy_tmo);
4515*4882a593Smuzhiyun }
4516*4882a593Smuzhiyun else if (!strncmp("scan_busy_thresh=", full_param, len_param)) {
4517*4882a593Smuzhiyun conf->scan_busy_thresh = (int)simple_strtol(data, NULL, 0);
4518*4882a593Smuzhiyun CONFIG_MSG("scan_busy_thresh = %d\n", conf->scan_busy_thresh);
4519*4882a593Smuzhiyun }
4520*4882a593Smuzhiyun #endif
4521*4882a593Smuzhiyun #ifdef DHD_TPUT_PATCH
4522*4882a593Smuzhiyun else if (!strncmp("tput_patch=", full_param, len_param)) {
4523*4882a593Smuzhiyun if (!strncmp(data, "1", 1))
4524*4882a593Smuzhiyun conf->tput_patch = TRUE;
4525*4882a593Smuzhiyun else
4526*4882a593Smuzhiyun conf->tput_patch = FALSE;
4527*4882a593Smuzhiyun CONFIG_MSG("tput_patch = %d\n", conf->tput_patch);
4528*4882a593Smuzhiyun dhd_conf_set_tput_patch(dhd);
4529*4882a593Smuzhiyun }
4530*4882a593Smuzhiyun else if (!strncmp("mtu=", full_param, len_param)) {
4531*4882a593Smuzhiyun conf->mtu = (int)simple_strtol(data, NULL, 0);
4532*4882a593Smuzhiyun CONFIG_MSG("mtu = %d\n", conf->mtu);
4533*4882a593Smuzhiyun }
4534*4882a593Smuzhiyun else if (!strncmp("pktsetsum=", full_param, len_param)) {
4535*4882a593Smuzhiyun if (!strncmp(data, "1", 1))
4536*4882a593Smuzhiyun conf->pktsetsum = TRUE;
4537*4882a593Smuzhiyun else
4538*4882a593Smuzhiyun conf->pktsetsum = FALSE;
4539*4882a593Smuzhiyun CONFIG_MSG("pktsetsum = %d\n", conf->pktsetsum);
4540*4882a593Smuzhiyun }
4541*4882a593Smuzhiyun #endif
4542*4882a593Smuzhiyun #ifdef SET_XPS_CPUS
4543*4882a593Smuzhiyun else if (!strncmp("xps_cpus=", full_param, len_param)) {
4544*4882a593Smuzhiyun if (!strncmp(data, "1", 1))
4545*4882a593Smuzhiyun conf->xps_cpus = TRUE;
4546*4882a593Smuzhiyun else
4547*4882a593Smuzhiyun conf->xps_cpus = FALSE;
4548*4882a593Smuzhiyun CONFIG_MSG("xps_cpus = %d\n", conf->xps_cpus);
4549*4882a593Smuzhiyun }
4550*4882a593Smuzhiyun #endif
4551*4882a593Smuzhiyun #ifdef SET_RPS_CPUS
4552*4882a593Smuzhiyun else if (!strncmp("rps_cpus=", full_param, len_param)) {
4553*4882a593Smuzhiyun if (!strncmp(data, "1", 1))
4554*4882a593Smuzhiyun conf->rps_cpus = TRUE;
4555*4882a593Smuzhiyun else
4556*4882a593Smuzhiyun conf->rps_cpus = FALSE;
4557*4882a593Smuzhiyun CONFIG_MSG("rps_cpus = %d\n", conf->rps_cpus);
4558*4882a593Smuzhiyun }
4559*4882a593Smuzhiyun #endif
4560*4882a593Smuzhiyun #ifdef CHECK_DOWNLOAD_FW
4561*4882a593Smuzhiyun else if (!strncmp("fwchk=", full_param, len_param)) {
4562*4882a593Smuzhiyun if (!strncmp(data, "1", 1))
4563*4882a593Smuzhiyun conf->fwchk = TRUE;
4564*4882a593Smuzhiyun else
4565*4882a593Smuzhiyun conf->fwchk = FALSE;
4566*4882a593Smuzhiyun CONFIG_MSG("fwchk = %d\n", conf->fwchk);
4567*4882a593Smuzhiyun }
4568*4882a593Smuzhiyun #endif
4569*4882a593Smuzhiyun else if (!strncmp("vndr_ie_assocreq=", full_param, len_param)) {
4570*4882a593Smuzhiyun if (conf->vndr_ie_assocreq) {
4571*4882a593Smuzhiyun kfree(conf->vndr_ie_assocreq);
4572*4882a593Smuzhiyun conf->vndr_ie_assocreq = NULL;
4573*4882a593Smuzhiyun }
4574*4882a593Smuzhiyun if (!(conf->vndr_ie_assocreq = kmalloc(strlen(data)+1, GFP_KERNEL))) {
4575*4882a593Smuzhiyun CONFIG_ERROR("kmalloc failed\n");
4576*4882a593Smuzhiyun } else {
4577*4882a593Smuzhiyun memset(conf->vndr_ie_assocreq, 0, strlen(data)+1);
4578*4882a593Smuzhiyun strcpy(conf->vndr_ie_assocreq, data);
4579*4882a593Smuzhiyun CONFIG_MSG("vndr_ie_assocreq = %s\n", conf->vndr_ie_assocreq);
4580*4882a593Smuzhiyun }
4581*4882a593Smuzhiyun }
4582*4882a593Smuzhiyun else
4583*4882a593Smuzhiyun return false;
4584*4882a593Smuzhiyun
4585*4882a593Smuzhiyun return true;
4586*4882a593Smuzhiyun }
4587*4882a593Smuzhiyun
4588*4882a593Smuzhiyun int
dhd_conf_read_config(dhd_pub_t * dhd,char * conf_path)4589*4882a593Smuzhiyun dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)
4590*4882a593Smuzhiyun {
4591*4882a593Smuzhiyun int bcmerror = -1, chip_match = -1;
4592*4882a593Smuzhiyun uint len = 0, memblock_len = 0, start_pos=0, end_pos=0;
4593*4882a593Smuzhiyun char *memblock = NULL;
4594*4882a593Smuzhiyun char *bufp, *pick = NULL, *pch;
4595*4882a593Smuzhiyun bool conf_file_exists;
4596*4882a593Smuzhiyun uint len_param;
4597*4882a593Smuzhiyun
4598*4882a593Smuzhiyun len = MAXSZ_CONFIG;
4599*4882a593Smuzhiyun
4600*4882a593Smuzhiyun conf_file_exists = ((conf_path != NULL) && (conf_path[0] != '\0'));
4601*4882a593Smuzhiyun if (!conf_file_exists) {
4602*4882a593Smuzhiyun CONFIG_MSG("config path %s\n", conf_path);
4603*4882a593Smuzhiyun return (0);
4604*4882a593Smuzhiyun }
4605*4882a593Smuzhiyun
4606*4882a593Smuzhiyun if (conf_file_exists)
4607*4882a593Smuzhiyun bcmerror = dhd_get_download_buffer(dhd, conf_path, NVRAM, &memblock,
4608*4882a593Smuzhiyun (int *)&len);
4609*4882a593Smuzhiyun else
4610*4882a593Smuzhiyun bcmerror = dhd_get_download_buffer(dhd, NULL, NVRAM, &memblock, (int *)&len);
4611*4882a593Smuzhiyun
4612*4882a593Smuzhiyun if (bcmerror != BCME_OK) {
4613*4882a593Smuzhiyun CONFIG_MSG("Ignore config file %s\n", conf_path);
4614*4882a593Smuzhiyun goto err;
4615*4882a593Smuzhiyun }
4616*4882a593Smuzhiyun
4617*4882a593Smuzhiyun #ifdef DHD_LINUX_STD_FW_API
4618*4882a593Smuzhiyun memblock_len = len;
4619*4882a593Smuzhiyun #else
4620*4882a593Smuzhiyun memblock_len = MAXSZ_CONFIG;
4621*4882a593Smuzhiyun #endif /* DHD_LINUX_STD_FW_API */
4622*4882a593Smuzhiyun
4623*4882a593Smuzhiyun pick = MALLOC(dhd->osh, MAXSZ_BUF);
4624*4882a593Smuzhiyun if (!pick) {
4625*4882a593Smuzhiyun CONFIG_ERROR("Failed to allocate memory %d bytes\n", MAXSZ_BUF);
4626*4882a593Smuzhiyun goto err;
4627*4882a593Smuzhiyun }
4628*4882a593Smuzhiyun
4629*4882a593Smuzhiyun /* Read variables */
4630*4882a593Smuzhiyun if (len > 0 && len < MAXSZ_CONFIG) {
4631*4882a593Smuzhiyun bufp = (char *)memblock;
4632*4882a593Smuzhiyun bufp[len] = 0;
4633*4882a593Smuzhiyun
4634*4882a593Smuzhiyun while (start_pos < len) {
4635*4882a593Smuzhiyun memset(pick, 0, MAXSZ_BUF);
4636*4882a593Smuzhiyun end_pos = pick_config_vars(bufp, len, start_pos, pick, MAXSZ_BUF);
4637*4882a593Smuzhiyun if (end_pos - start_pos >= MAXSZ_BUF)
4638*4882a593Smuzhiyun CONFIG_ERROR("out of buf to read MAXSIZ_BUF=%d\n", MAXSZ_BUF);
4639*4882a593Smuzhiyun start_pos = end_pos;
4640*4882a593Smuzhiyun pch = strchr(pick, '=');
4641*4882a593Smuzhiyun if (pch != NULL) {
4642*4882a593Smuzhiyun len_param = pch-pick+1;
4643*4882a593Smuzhiyun if (len_param == strlen(pick)) {
4644*4882a593Smuzhiyun CONFIG_ERROR("not a right parameter %s\n", pick);
4645*4882a593Smuzhiyun continue;
4646*4882a593Smuzhiyun }
4647*4882a593Smuzhiyun } else {
4648*4882a593Smuzhiyun CONFIG_ERROR("not a right parameter %s\n", pick);
4649*4882a593Smuzhiyun continue;
4650*4882a593Smuzhiyun }
4651*4882a593Smuzhiyun
4652*4882a593Smuzhiyun dhd_conf_read_chiprev(dhd, &chip_match, pick, len_param);
4653*4882a593Smuzhiyun if (!chip_match)
4654*4882a593Smuzhiyun continue;
4655*4882a593Smuzhiyun
4656*4882a593Smuzhiyun if (dhd_conf_read_log_level(dhd, pick, len_param))
4657*4882a593Smuzhiyun continue;
4658*4882a593Smuzhiyun else if (dhd_conf_read_roam_params(dhd, pick, len_param))
4659*4882a593Smuzhiyun continue;
4660*4882a593Smuzhiyun else if (dhd_conf_read_wme_ac_params(dhd, pick, len_param))
4661*4882a593Smuzhiyun continue;
4662*4882a593Smuzhiyun #ifdef SET_FWNV_BY_MAC
4663*4882a593Smuzhiyun else if (dhd_conf_read_fw_by_mac(dhd, pick, len_param))
4664*4882a593Smuzhiyun continue;
4665*4882a593Smuzhiyun else if (dhd_conf_read_nv_by_mac(dhd, pick, len_param))
4666*4882a593Smuzhiyun continue;
4667*4882a593Smuzhiyun #endif
4668*4882a593Smuzhiyun else if (dhd_conf_read_nv_by_chip(dhd, pick, len_param))
4669*4882a593Smuzhiyun continue;
4670*4882a593Smuzhiyun else if (dhd_conf_read_country(dhd, pick, len_param))
4671*4882a593Smuzhiyun continue;
4672*4882a593Smuzhiyun else if (dhd_conf_read_mchan_params(dhd, pick, len_param))
4673*4882a593Smuzhiyun continue;
4674*4882a593Smuzhiyun #ifdef PKT_FILTER_SUPPORT
4675*4882a593Smuzhiyun else if (dhd_conf_read_pkt_filter(dhd, pick, len_param))
4676*4882a593Smuzhiyun continue;
4677*4882a593Smuzhiyun #endif /* PKT_FILTER_SUPPORT */
4678*4882a593Smuzhiyun #ifdef ISAM_PREINIT
4679*4882a593Smuzhiyun else if (dhd_conf_read_isam(dhd, pick, len_param))
4680*4882a593Smuzhiyun continue;
4681*4882a593Smuzhiyun #endif /* ISAM_PREINIT */
4682*4882a593Smuzhiyun #ifdef IDHCP
4683*4882a593Smuzhiyun else if (dhd_conf_read_dhcp_params(dhd, pick, len_param))
4684*4882a593Smuzhiyun continue;
4685*4882a593Smuzhiyun #endif /* IDHCP */
4686*4882a593Smuzhiyun #ifdef BCMSDIO
4687*4882a593Smuzhiyun else if (dhd_conf_read_sdio_params(dhd, pick, len_param))
4688*4882a593Smuzhiyun continue;
4689*4882a593Smuzhiyun #endif /* BCMSDIO */
4690*4882a593Smuzhiyun #ifdef BCMPCIE
4691*4882a593Smuzhiyun else if (dhd_conf_read_pcie_params(dhd, pick, len_param))
4692*4882a593Smuzhiyun continue;
4693*4882a593Smuzhiyun #endif /* BCMPCIE */
4694*4882a593Smuzhiyun else if (dhd_conf_read_pm_params(dhd, pick, len_param))
4695*4882a593Smuzhiyun continue;
4696*4882a593Smuzhiyun else if (dhd_conf_read_others(dhd, pick, len_param))
4697*4882a593Smuzhiyun continue;
4698*4882a593Smuzhiyun else
4699*4882a593Smuzhiyun continue;
4700*4882a593Smuzhiyun }
4701*4882a593Smuzhiyun
4702*4882a593Smuzhiyun bcmerror = 0;
4703*4882a593Smuzhiyun } else {
4704*4882a593Smuzhiyun CONFIG_ERROR("error reading config file: %d\n", len);
4705*4882a593Smuzhiyun bcmerror = BCME_SDIO_ERROR;
4706*4882a593Smuzhiyun }
4707*4882a593Smuzhiyun
4708*4882a593Smuzhiyun err:
4709*4882a593Smuzhiyun if (pick)
4710*4882a593Smuzhiyun MFREE(dhd->osh, pick, MAXSZ_BUF);
4711*4882a593Smuzhiyun
4712*4882a593Smuzhiyun if (memblock)
4713*4882a593Smuzhiyun dhd_free_download_buffer(dhd, memblock, memblock_len);
4714*4882a593Smuzhiyun
4715*4882a593Smuzhiyun return bcmerror;
4716*4882a593Smuzhiyun }
4717*4882a593Smuzhiyun
4718*4882a593Smuzhiyun #if defined(BCMSDIO) || defined(BCMPCIE)
4719*4882a593Smuzhiyun void
dhd_conf_set_devid(dhd_pub_t * dhd)4720*4882a593Smuzhiyun dhd_conf_set_devid(dhd_pub_t *dhd)
4721*4882a593Smuzhiyun {
4722*4882a593Smuzhiyun wifi_adapter_info_t *adapter = NULL;
4723*4882a593Smuzhiyun uint32 bus_type = -1;
4724*4882a593Smuzhiyun uint32 bus_num = -1;
4725*4882a593Smuzhiyun uint32 slot_num = -1;
4726*4882a593Smuzhiyun
4727*4882a593Smuzhiyun dhd_bus_get_ids(dhd->bus, &bus_type, &bus_num, &slot_num);
4728*4882a593Smuzhiyun adapter = dhd_wifi_platform_get_adapter(bus_type, bus_num, slot_num);
4729*4882a593Smuzhiyun if (adapter) {
4730*4882a593Smuzhiyun #if defined(BCMSDIO)
4731*4882a593Smuzhiyun dhd->conf->devid = adapter->sdio_func->device;
4732*4882a593Smuzhiyun #endif
4733*4882a593Smuzhiyun #if defined(BCMPCIE)
4734*4882a593Smuzhiyun dhd->conf->devid = adapter->pci_dev->device;
4735*4882a593Smuzhiyun dhd->conf->svid = adapter->pci_dev->subsystem_vendor;
4736*4882a593Smuzhiyun dhd->conf->ssid = adapter->pci_dev->subsystem_device;
4737*4882a593Smuzhiyun #endif
4738*4882a593Smuzhiyun } else {
4739*4882a593Smuzhiyun CONFIG_ERROR("can't find adapter\n");
4740*4882a593Smuzhiyun }
4741*4882a593Smuzhiyun
4742*4882a593Smuzhiyun return;
4743*4882a593Smuzhiyun }
4744*4882a593Smuzhiyun #endif
4745*4882a593Smuzhiyun
4746*4882a593Smuzhiyun int
dhd_conf_set_chiprev(dhd_pub_t * dhd,uint chip,uint chiprev)4747*4882a593Smuzhiyun dhd_conf_set_chiprev(dhd_pub_t *dhd, uint chip, uint chiprev)
4748*4882a593Smuzhiyun {
4749*4882a593Smuzhiyun #if defined(BCMSDIO) || defined(BCMPCIE)
4750*4882a593Smuzhiyun dhd_conf_set_devid(dhd);
4751*4882a593Smuzhiyun #endif
4752*4882a593Smuzhiyun dhd->conf->chip = chip;
4753*4882a593Smuzhiyun dhd->conf->chiprev = chiprev;
4754*4882a593Smuzhiyun
4755*4882a593Smuzhiyun #if defined(BCMSDIO)
4756*4882a593Smuzhiyun CONFIG_MSG("devid=0x%x, chip=0x%x, chiprev=%d\n",
4757*4882a593Smuzhiyun dhd->conf->devid, dhd->conf->chip, dhd->conf->chiprev);
4758*4882a593Smuzhiyun #endif
4759*4882a593Smuzhiyun #if defined(BCMPCIE)
4760*4882a593Smuzhiyun CONFIG_MSG("devid=0x%x, chip=0x%x, chiprev=%d, svid=0x%04x, ssid=0x%04x\n",
4761*4882a593Smuzhiyun dhd->conf->devid, dhd->conf->chip, dhd->conf->chiprev,
4762*4882a593Smuzhiyun dhd->conf->svid, dhd->conf->ssid);
4763*4882a593Smuzhiyun #endif
4764*4882a593Smuzhiyun #if defined(BCMDBUS)
4765*4882a593Smuzhiyun CONFIG_MSG("chip=0x%x, chiprev=%d\n", dhd->conf->chip, dhd->conf->chiprev);
4766*4882a593Smuzhiyun #endif
4767*4882a593Smuzhiyun
4768*4882a593Smuzhiyun return 0;
4769*4882a593Smuzhiyun }
4770*4882a593Smuzhiyun
4771*4882a593Smuzhiyun uint
dhd_conf_get_chip(void * context)4772*4882a593Smuzhiyun dhd_conf_get_chip(void *context)
4773*4882a593Smuzhiyun {
4774*4882a593Smuzhiyun dhd_pub_t *dhd = context;
4775*4882a593Smuzhiyun
4776*4882a593Smuzhiyun if (dhd && dhd->conf)
4777*4882a593Smuzhiyun return dhd->conf->chip;
4778*4882a593Smuzhiyun return 0;
4779*4882a593Smuzhiyun }
4780*4882a593Smuzhiyun
4781*4882a593Smuzhiyun uint
dhd_conf_get_chiprev(void * context)4782*4882a593Smuzhiyun dhd_conf_get_chiprev(void *context)
4783*4882a593Smuzhiyun {
4784*4882a593Smuzhiyun dhd_pub_t *dhd = context;
4785*4882a593Smuzhiyun
4786*4882a593Smuzhiyun if (dhd && dhd->conf)
4787*4882a593Smuzhiyun return dhd->conf->chiprev;
4788*4882a593Smuzhiyun return 0;
4789*4882a593Smuzhiyun }
4790*4882a593Smuzhiyun
4791*4882a593Smuzhiyun #ifdef BCMSDIO
4792*4882a593Smuzhiyun void
dhd_conf_set_txglom_params(dhd_pub_t * dhd,bool enable)4793*4882a593Smuzhiyun dhd_conf_set_txglom_params(dhd_pub_t *dhd, bool enable)
4794*4882a593Smuzhiyun {
4795*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
4796*4882a593Smuzhiyun
4797*4882a593Smuzhiyun if (enable) {
4798*4882a593Smuzhiyun #if defined(BCMSDIOH_TXGLOM_EXT)
4799*4882a593Smuzhiyun if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID ||
4800*4882a593Smuzhiyun conf->chip == BCM43340_CHIP_ID || conf->chip == BCM43341_CHIP_ID ||
4801*4882a593Smuzhiyun conf->chip == BCM4334_CHIP_ID || conf->chip == BCM4324_CHIP_ID) {
4802*4882a593Smuzhiyun conf->txglom_mode = SDPCM_TXGLOM_CPY;
4803*4882a593Smuzhiyun }
4804*4882a593Smuzhiyun #endif
4805*4882a593Smuzhiyun // other parameters set in preinit or config.txt
4806*4882a593Smuzhiyun if (conf->txglom_ext)
4807*4882a593Smuzhiyun CONFIG_MSG("txglom_ext=%d, txglom_bucket_size=%d\n",
4808*4882a593Smuzhiyun conf->txglom_ext, conf->txglom_bucket_size);
4809*4882a593Smuzhiyun CONFIG_MSG("txglom_mode=%s\n",
4810*4882a593Smuzhiyun conf->txglom_mode==SDPCM_TXGLOM_MDESC?"multi-desc":"copy");
4811*4882a593Smuzhiyun CONFIG_MSG("txglomsize=%d, deferred_tx_len=%d\n",
4812*4882a593Smuzhiyun conf->txglomsize, conf->deferred_tx_len);
4813*4882a593Smuzhiyun CONFIG_MSG("txinrx_thres=%d, dhd_txminmax=%d\n",
4814*4882a593Smuzhiyun conf->txinrx_thres, conf->dhd_txminmax);
4815*4882a593Smuzhiyun CONFIG_MSG("tx_max_offset=%d, txctl_tmo_fix=%d\n",
4816*4882a593Smuzhiyun conf->tx_max_offset, conf->txctl_tmo_fix);
4817*4882a593Smuzhiyun } else {
4818*4882a593Smuzhiyun // clear txglom parameters
4819*4882a593Smuzhiyun conf->txglom_ext = FALSE;
4820*4882a593Smuzhiyun conf->txglom_bucket_size = 0;
4821*4882a593Smuzhiyun conf->txglomsize = 0;
4822*4882a593Smuzhiyun conf->deferred_tx_len = 0;
4823*4882a593Smuzhiyun }
4824*4882a593Smuzhiyun
4825*4882a593Smuzhiyun }
4826*4882a593Smuzhiyun
4827*4882a593Smuzhiyun static void
dhd_conf_set_ampdu_mpdu(dhd_pub_t * dhd)4828*4882a593Smuzhiyun dhd_conf_set_ampdu_mpdu(dhd_pub_t *dhd)
4829*4882a593Smuzhiyun {
4830*4882a593Smuzhiyun uint chip = dhd->conf->chip;
4831*4882a593Smuzhiyun char ampdu_mpdu[32] = "ampdu_mpdu=";
4832*4882a593Smuzhiyun int val = -1;
4833*4882a593Smuzhiyun
4834*4882a593Smuzhiyun if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID ||
4835*4882a593Smuzhiyun chip == BCM4334_CHIP_ID || chip == BCM43340_CHIP_ID ||
4836*4882a593Smuzhiyun chip == BCM43341_CHIP_ID || chip == BCM4324_CHIP_ID ||
4837*4882a593Smuzhiyun chip == BCM4335_CHIP_ID || chip == BCM4339_CHIP_ID ||
4838*4882a593Smuzhiyun chip == BCM4354_CHIP_ID || chip == BCM4356_CHIP_ID ||
4839*4882a593Smuzhiyun chip == BCM4371_CHIP_ID ||
4840*4882a593Smuzhiyun chip == BCM43430_CHIP_ID ||
4841*4882a593Smuzhiyun chip == BCM4345_CHIP_ID || chip == BCM43454_CHIP_ID ||
4842*4882a593Smuzhiyun chip == BCM4359_CHIP_ID || chip == BCM43012_CHIP_ID) {
4843*4882a593Smuzhiyun val = 16;
4844*4882a593Smuzhiyun } else if (chip == BCM43751_CHIP_ID || chip == BCM43752_CHIP_ID) {
4845*4882a593Smuzhiyun val = 32;
4846*4882a593Smuzhiyun }
4847*4882a593Smuzhiyun
4848*4882a593Smuzhiyun if (val > 0) {
4849*4882a593Smuzhiyun snprintf(ampdu_mpdu+strlen(ampdu_mpdu), sizeof(ampdu_mpdu), "%d", val);
4850*4882a593Smuzhiyun dhd_conf_set_wl_cmd(dhd, ampdu_mpdu, TRUE);
4851*4882a593Smuzhiyun }
4852*4882a593Smuzhiyun }
4853*4882a593Smuzhiyun #endif
4854*4882a593Smuzhiyun
4855*4882a593Smuzhiyun #ifdef UPDATE_MODULE_NAME
4856*4882a593Smuzhiyun #if defined(BCMSDIO) || defined(BCMPCIE)
4857*4882a593Smuzhiyun static void
dhd_conf_compat_vht(dhd_pub_t * dhd)4858*4882a593Smuzhiyun dhd_conf_compat_vht(dhd_pub_t *dhd)
4859*4882a593Smuzhiyun {
4860*4882a593Smuzhiyun char vht_features[] = "vht_features=0";
4861*4882a593Smuzhiyun
4862*4882a593Smuzhiyun CONFIG_TRACE("Enter\n");
4863*4882a593Smuzhiyun
4864*4882a593Smuzhiyun dhd_conf_set_wl_cmd(dhd, vht_features, TRUE);
4865*4882a593Smuzhiyun }
4866*4882a593Smuzhiyun #endif
4867*4882a593Smuzhiyun
4868*4882a593Smuzhiyun int
dhd_conf_compat_func(dhd_pub_t * dhd)4869*4882a593Smuzhiyun dhd_conf_compat_func(dhd_pub_t *dhd)
4870*4882a593Smuzhiyun {
4871*4882a593Smuzhiyun const module_name_map_t *row = NULL;
4872*4882a593Smuzhiyun
4873*4882a593Smuzhiyun row = dhd_conf_match_module(dhd);
4874*4882a593Smuzhiyun if (row && row->compat_func) {
4875*4882a593Smuzhiyun row->compat_func(dhd);
4876*4882a593Smuzhiyun }
4877*4882a593Smuzhiyun
4878*4882a593Smuzhiyun return 0;
4879*4882a593Smuzhiyun }
4880*4882a593Smuzhiyun #endif
4881*4882a593Smuzhiyun
4882*4882a593Smuzhiyun void
dhd_conf_preinit_ioctls_sta(dhd_pub_t * dhd,int ifidx)4883*4882a593Smuzhiyun dhd_conf_preinit_ioctls_sta(dhd_pub_t *dhd, int ifidx)
4884*4882a593Smuzhiyun {
4885*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
4886*4882a593Smuzhiyun int pm;
4887*4882a593Smuzhiyun
4888*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "bcn_timeout", conf->bcn_timeout, 0, FALSE);
4889*4882a593Smuzhiyun #ifdef NO_POWER_SAVE
4890*4882a593Smuzhiyun pm = PM_OFF;
4891*4882a593Smuzhiyun #else
4892*4882a593Smuzhiyun if (conf->pm >= 0)
4893*4882a593Smuzhiyun pm = conf->pm;
4894*4882a593Smuzhiyun else
4895*4882a593Smuzhiyun pm = PM_FAST;
4896*4882a593Smuzhiyun #endif
4897*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_PM, "WLC_SET_PM", pm, 0, FALSE);
4898*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, ifidx, WLC_SET_VAR, "assoc_retry_max", 10, 0, FALSE);
4899*4882a593Smuzhiyun dhd_conf_set_roam(dhd, ifidx);
4900*4882a593Smuzhiyun }
4901*4882a593Smuzhiyun
4902*4882a593Smuzhiyun void
dhd_conf_postinit_ioctls(dhd_pub_t * dhd)4903*4882a593Smuzhiyun dhd_conf_postinit_ioctls(dhd_pub_t *dhd)
4904*4882a593Smuzhiyun {
4905*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
4906*4882a593Smuzhiyun char wl_preinit[] = "";
4907*4882a593Smuzhiyun #ifdef NO_POWER_SAVE
4908*4882a593Smuzhiyun char wl_no_power_save[] = "mpc=0, 86=0";
4909*4882a593Smuzhiyun dhd_conf_set_wl_cmd(dhd, wl_no_power_save, FALSE);
4910*4882a593Smuzhiyun #endif
4911*4882a593Smuzhiyun
4912*4882a593Smuzhiyun dhd_conf_get_ioctl_ver(dhd);
4913*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, 0, WLC_UP, "WLC_UP", 0, 0, FALSE);
4914*4882a593Smuzhiyun dhd_conf_country(dhd, "country", conf->cspec.country_abbrev);
4915*4882a593Smuzhiyun
4916*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, 0, WLC_SET_BAND, "WLC_SET_BAND", conf->band, 0, FALSE);
4917*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, 0, WLC_SET_SRL, "WLC_SET_SRL", conf->srl, 0, FALSE);
4918*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, 0, WLC_SET_LRL, "WLC_SET_LRL", conf->lrl, 0, FALSE);
4919*4882a593Smuzhiyun dhd_conf_set_bw_cap(dhd);
4920*4882a593Smuzhiyun dhd_conf_set_roam(dhd, 0);
4921*4882a593Smuzhiyun
4922*4882a593Smuzhiyun #if defined(BCMPCIE)
4923*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "bus:deepsleep_disable",
4924*4882a593Smuzhiyun conf->bus_deepsleep_disable, 0, FALSE);
4925*4882a593Smuzhiyun #endif /* defined(BCMPCIE) */
4926*4882a593Smuzhiyun
4927*4882a593Smuzhiyun #ifdef IDHCP
4928*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "dhcpc_enable", conf->dhcpc_enable,
4929*4882a593Smuzhiyun 0, FALSE);
4930*4882a593Smuzhiyun if (conf->dhcpd_enable >= 0) {
4931*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "dhcpd_ip_addr",
4932*4882a593Smuzhiyun (char *)&conf->dhcpd_ip_addr, sizeof(conf->dhcpd_ip_addr), FALSE);
4933*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "dhcpd_ip_mask",
4934*4882a593Smuzhiyun (char *)&conf->dhcpd_ip_mask, sizeof(conf->dhcpd_ip_mask), FALSE);
4935*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "dhcpd_ip_start",
4936*4882a593Smuzhiyun (char *)&conf->dhcpd_ip_start, sizeof(conf->dhcpd_ip_start), FALSE);
4937*4882a593Smuzhiyun dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "dhcpd_ip_end",
4938*4882a593Smuzhiyun (char *)&conf->dhcpd_ip_end, sizeof(conf->dhcpd_ip_end), FALSE);
4939*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "dhcpd_enable",
4940*4882a593Smuzhiyun conf->dhcpd_enable, 0, FALSE);
4941*4882a593Smuzhiyun }
4942*4882a593Smuzhiyun #endif
4943*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, 0, WLC_SET_FAKEFRAG, "WLC_SET_FAKEFRAG",
4944*4882a593Smuzhiyun conf->frameburst, 0, FALSE);
4945*4882a593Smuzhiyun
4946*4882a593Smuzhiyun dhd_conf_preinit_ioctls_sta(dhd, 0);
4947*4882a593Smuzhiyun dhd_conf_set_wl_cmd(dhd, wl_preinit, TRUE);
4948*4882a593Smuzhiyun #if defined(BCMSDIO)
4949*4882a593Smuzhiyun dhd_conf_set_ampdu_mpdu(dhd);
4950*4882a593Smuzhiyun #endif
4951*4882a593Smuzhiyun
4952*4882a593Smuzhiyun #ifdef DHD_TPUT_PATCH
4953*4882a593Smuzhiyun if (dhd->conf->mtu)
4954*4882a593Smuzhiyun dhd_change_mtu(dhd, dhd->conf->mtu, 0);
4955*4882a593Smuzhiyun #endif
4956*4882a593Smuzhiyun if (conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||
4957*4882a593Smuzhiyun conf->chip == BCM4371_CHIP_ID || conf->chip == BCM4359_CHIP_ID ||
4958*4882a593Smuzhiyun conf->chip == BCM43569_CHIP_ID ||
4959*4882a593Smuzhiyun conf->chip == BCM43751_CHIP_ID || conf->chip == BCM43752_CHIP_ID ||
4960*4882a593Smuzhiyun conf->chip == BCM4375_CHIP_ID) {
4961*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "txbf", 1, 0, FALSE);
4962*4882a593Smuzhiyun }
4963*4882a593Smuzhiyun if (conf->chip == BCM4375_CHIP_ID) {
4964*4882a593Smuzhiyun char he_cmd[] = "110=1, nmode=1, vhtmode=1, he=enab 1";
4965*4882a593Smuzhiyun dhd_conf_set_wl_cmd(dhd, he_cmd, TRUE);
4966*4882a593Smuzhiyun }
4967*4882a593Smuzhiyun if (conf->chip == BCM43752_CHIP_ID || conf->chip == BCM4359_CHIP_ID) {
4968*4882a593Smuzhiyun char txack_alive[] = "txack_alive=0";
4969*4882a593Smuzhiyun dhd_conf_set_wl_cmd(dhd, txack_alive, TRUE);
4970*4882a593Smuzhiyun }
4971*4882a593Smuzhiyun #ifdef WLDWDS
4972*4882a593Smuzhiyun {
4973*4882a593Smuzhiyun char dwds[] = "dwds=1";
4974*4882a593Smuzhiyun dhd_conf_set_wl_cmd(dhd, dwds, TRUE);
4975*4882a593Smuzhiyun }
4976*4882a593Smuzhiyun #endif /* WLDWDS */
4977*4882a593Smuzhiyun #if defined(WLEASYMESH)
4978*4882a593Smuzhiyun if (conf->fw_type == FW_TYPE_EZMESH) {
4979*4882a593Smuzhiyun if (conf->chip == BCM4359_CHIP_ID) {
4980*4882a593Smuzhiyun char ezmesh[] = "mbss=1, rsdb_mode=0";
4981*4882a593Smuzhiyun dhd_conf_set_wl_cmd(dhd, ezmesh, TRUE);
4982*4882a593Smuzhiyun } else {
4983*4882a593Smuzhiyun char ezmesh[] = "mbss=1";
4984*4882a593Smuzhiyun dhd_conf_set_wl_cmd(dhd, ezmesh, TRUE);
4985*4882a593Smuzhiyun }
4986*4882a593Smuzhiyun }
4987*4882a593Smuzhiyun #endif /* WLEASYMESH */
4988*4882a593Smuzhiyun #if defined(BCMSDIO)
4989*4882a593Smuzhiyun if (conf->devid == BCM43751_CHIP_ID)
4990*4882a593Smuzhiyun #elif defined(BCMPCIE)
4991*4882a593Smuzhiyun if (conf->devid == BCM43751_D11AX_ID)
4992*4882a593Smuzhiyun #endif
4993*4882a593Smuzhiyun {
4994*4882a593Smuzhiyun if (FW_SUPPORTED(dhd, mbo)) {
4995*4882a593Smuzhiyun char he_features[] = "he=enab 0,he=features 0";
4996*4882a593Smuzhiyun dhd_conf_set_wl_cmd(dhd, he_features, TRUE);
4997*4882a593Smuzhiyun }
4998*4882a593Smuzhiyun }
4999*4882a593Smuzhiyun #ifdef UPDATE_MODULE_NAME
5000*4882a593Smuzhiyun dhd_conf_compat_func(dhd);
5001*4882a593Smuzhiyun #endif
5002*4882a593Smuzhiyun #ifndef SUPPORT_RANDOM_MAC_SCAN
5003*4882a593Smuzhiyun {
5004*4882a593Smuzhiyun char scanmac[] = "scanmac=enable 0";
5005*4882a593Smuzhiyun dhd_conf_set_wl_cmd(dhd, scanmac, TRUE);
5006*4882a593Smuzhiyun }
5007*4882a593Smuzhiyun #endif
5008*4882a593Smuzhiyun dhd_conf_set_wl_cmd(dhd, conf->wl_preinit, TRUE);
5009*4882a593Smuzhiyun
5010*4882a593Smuzhiyun #ifndef WL_CFG80211
5011*4882a593Smuzhiyun dhd_conf_set_intiovar(dhd, 0, WLC_UP, "WLC_UP", 0, 0, FALSE);
5012*4882a593Smuzhiyun #endif
5013*4882a593Smuzhiyun
5014*4882a593Smuzhiyun }
5015*4882a593Smuzhiyun
5016*4882a593Smuzhiyun void
dhd_conf_free_preinit(dhd_pub_t * dhd)5017*4882a593Smuzhiyun dhd_conf_free_preinit(dhd_pub_t *dhd)
5018*4882a593Smuzhiyun {
5019*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
5020*4882a593Smuzhiyun
5021*4882a593Smuzhiyun #ifdef SET_FWNV_BY_MAC
5022*4882a593Smuzhiyun dhd_conf_free_mac_list(&conf->fw_by_mac);
5023*4882a593Smuzhiyun dhd_conf_free_mac_list(&conf->nv_by_mac);
5024*4882a593Smuzhiyun #endif
5025*4882a593Smuzhiyun dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);
5026*4882a593Smuzhiyun dhd_conf_free_country_list(conf);
5027*4882a593Smuzhiyun dhd_conf_free_mchan_list(conf);
5028*4882a593Smuzhiyun #ifdef PKT_FILTER_SUPPORT
5029*4882a593Smuzhiyun if (conf->magic_pkt_filter_add) {
5030*4882a593Smuzhiyun kfree(conf->magic_pkt_filter_add);
5031*4882a593Smuzhiyun conf->magic_pkt_filter_add = NULL;
5032*4882a593Smuzhiyun }
5033*4882a593Smuzhiyun #endif
5034*4882a593Smuzhiyun if (conf->wl_preinit) {
5035*4882a593Smuzhiyun kfree(conf->wl_preinit);
5036*4882a593Smuzhiyun conf->wl_preinit = NULL;
5037*4882a593Smuzhiyun }
5038*4882a593Smuzhiyun if (conf->wl_suspend) {
5039*4882a593Smuzhiyun kfree(conf->wl_suspend);
5040*4882a593Smuzhiyun conf->wl_suspend = NULL;
5041*4882a593Smuzhiyun }
5042*4882a593Smuzhiyun if (conf->wl_resume) {
5043*4882a593Smuzhiyun kfree(conf->wl_resume);
5044*4882a593Smuzhiyun conf->wl_resume = NULL;
5045*4882a593Smuzhiyun }
5046*4882a593Smuzhiyun if (conf->vndr_ie_assocreq) {
5047*4882a593Smuzhiyun kfree(conf->vndr_ie_assocreq);
5048*4882a593Smuzhiyun conf->vndr_ie_assocreq = NULL;
5049*4882a593Smuzhiyun }
5050*4882a593Smuzhiyun }
5051*4882a593Smuzhiyun
5052*4882a593Smuzhiyun int
dhd_conf_preinit(dhd_pub_t * dhd)5053*4882a593Smuzhiyun dhd_conf_preinit(dhd_pub_t *dhd)
5054*4882a593Smuzhiyun {
5055*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
5056*4882a593Smuzhiyun
5057*4882a593Smuzhiyun CONFIG_TRACE("Enter\n");
5058*4882a593Smuzhiyun
5059*4882a593Smuzhiyun dhd_conf_free_preinit(dhd);
5060*4882a593Smuzhiyun conf->band = -1;
5061*4882a593Smuzhiyun memset(&conf->bw_cap, -1, sizeof(conf->bw_cap));
5062*4882a593Smuzhiyun if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID) {
5063*4882a593Smuzhiyun strcpy(conf->cspec.country_abbrev, "ALL");
5064*4882a593Smuzhiyun strcpy(conf->cspec.ccode, "ALL");
5065*4882a593Smuzhiyun conf->cspec.rev = 0;
5066*4882a593Smuzhiyun }
5067*4882a593Smuzhiyun else if (conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID ||
5068*4882a593Smuzhiyun conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||
5069*4882a593Smuzhiyun conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID ||
5070*4882a593Smuzhiyun conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID ||
5071*4882a593Smuzhiyun conf->chip == BCM4375_CHIP_ID) {
5072*4882a593Smuzhiyun strcpy(conf->cspec.country_abbrev, "CN");
5073*4882a593Smuzhiyun strcpy(conf->cspec.ccode, "CN");
5074*4882a593Smuzhiyun conf->cspec.rev = 38;
5075*4882a593Smuzhiyun }
5076*4882a593Smuzhiyun else {
5077*4882a593Smuzhiyun strcpy(conf->cspec.country_abbrev, "CN");
5078*4882a593Smuzhiyun strcpy(conf->cspec.ccode, "CN");
5079*4882a593Smuzhiyun conf->cspec.rev = 0;
5080*4882a593Smuzhiyun }
5081*4882a593Smuzhiyun memset(&conf->channels, 0, sizeof(wl_channel_list_t));
5082*4882a593Smuzhiyun conf->ioctl_ver = WLC_IOCTL_VERSION;
5083*4882a593Smuzhiyun conf->roam_off = 1;
5084*4882a593Smuzhiyun conf->roam_off_suspend = 1;
5085*4882a593Smuzhiyun conf->roam_trigger[0] = -65;
5086*4882a593Smuzhiyun conf->roam_trigger[1] = WLC_BAND_ALL;
5087*4882a593Smuzhiyun conf->roam_scan_period[0] = 10;
5088*4882a593Smuzhiyun conf->roam_scan_period[1] = WLC_BAND_ALL;
5089*4882a593Smuzhiyun conf->roam_delta[0] = 10;
5090*4882a593Smuzhiyun conf->roam_delta[1] = WLC_BAND_ALL;
5091*4882a593Smuzhiyun conf->fullroamperiod = 20;
5092*4882a593Smuzhiyun conf->keep_alive_period = 30000;
5093*4882a593Smuzhiyun #ifdef ARP_OFFLOAD_SUPPORT
5094*4882a593Smuzhiyun conf->garp = FALSE;
5095*4882a593Smuzhiyun #endif
5096*4882a593Smuzhiyun conf->force_wme_ac = 0;
5097*4882a593Smuzhiyun memset(&conf->wme_sta, 0, sizeof(wme_param_t));
5098*4882a593Smuzhiyun memset(&conf->wme_ap, 0, sizeof(wme_param_t));
5099*4882a593Smuzhiyun #ifdef PKT_FILTER_SUPPORT
5100*4882a593Smuzhiyun memset(&conf->pkt_filter_add, 0, sizeof(conf_pkt_filter_add_t));
5101*4882a593Smuzhiyun memset(&conf->pkt_filter_del, 0, sizeof(conf_pkt_filter_del_t));
5102*4882a593Smuzhiyun #endif
5103*4882a593Smuzhiyun conf->srl = -1;
5104*4882a593Smuzhiyun conf->lrl = -1;
5105*4882a593Smuzhiyun conf->bcn_timeout = 16;
5106*4882a593Smuzhiyun conf->disable_proptx = -1;
5107*4882a593Smuzhiyun conf->dhd_poll = -1;
5108*4882a593Smuzhiyun #ifdef BCMSDIO
5109*4882a593Smuzhiyun conf->use_rxchain = 0;
5110*4882a593Smuzhiyun conf->bus_rxglom = TRUE;
5111*4882a593Smuzhiyun conf->txglom_ext = FALSE;
5112*4882a593Smuzhiyun conf->tx_max_offset = 0;
5113*4882a593Smuzhiyun conf->txglomsize = SDPCM_DEFGLOM_SIZE;
5114*4882a593Smuzhiyun conf->txctl_tmo_fix = 300;
5115*4882a593Smuzhiyun conf->txglom_mode = SDPCM_TXGLOM_CPY;
5116*4882a593Smuzhiyun conf->deferred_tx_len = 0;
5117*4882a593Smuzhiyun conf->dhd_txminmax = 1;
5118*4882a593Smuzhiyun conf->txinrx_thres = -1;
5119*4882a593Smuzhiyun #ifdef MINIME
5120*4882a593Smuzhiyun conf->ramsize = 0x80000;
5121*4882a593Smuzhiyun #endif
5122*4882a593Smuzhiyun #if defined(SDIO_ISR_THREAD)
5123*4882a593Smuzhiyun conf->intr_extn = FALSE;
5124*4882a593Smuzhiyun #endif
5125*4882a593Smuzhiyun #ifdef BCMSDIO_RXLIM_POST
5126*4882a593Smuzhiyun conf->rxlim_en = FALSE;
5127*4882a593Smuzhiyun #endif
5128*4882a593Smuzhiyun #ifdef BCMSDIO_TXSEQ_SYNC
5129*4882a593Smuzhiyun conf->txseq_sync = FALSE;
5130*4882a593Smuzhiyun #endif
5131*4882a593Smuzhiyun #if defined(HW_OOB)
5132*4882a593Smuzhiyun conf->oob_enabled_later = FALSE;
5133*4882a593Smuzhiyun #endif
5134*4882a593Smuzhiyun #ifdef BCMSDIO_INTSTATUS_WAR
5135*4882a593Smuzhiyun conf->read_intr_mode = 0;
5136*4882a593Smuzhiyun #endif
5137*4882a593Smuzhiyun conf->kso_try_max = 0;
5138*4882a593Smuzhiyun #ifdef KSO_DEBUG
5139*4882a593Smuzhiyun memset(&conf->kso_try_array, 0, sizeof(conf->kso_try_array));
5140*4882a593Smuzhiyun #endif
5141*4882a593Smuzhiyun #endif
5142*4882a593Smuzhiyun #ifdef BCMPCIE
5143*4882a593Smuzhiyun conf->bus_deepsleep_disable = 1;
5144*4882a593Smuzhiyun conf->flow_ring_queue_threshold = FLOW_RING_QUEUE_THRESHOLD;
5145*4882a593Smuzhiyun conf->d2h_intr_method = -1;
5146*4882a593Smuzhiyun conf->d2h_intr_control = -1;
5147*4882a593Smuzhiyun conf->aspm = -1;
5148*4882a593Smuzhiyun conf->l1ss = -1;
5149*4882a593Smuzhiyun conf->enq_hdr_pkt = 0;
5150*4882a593Smuzhiyun #endif
5151*4882a593Smuzhiyun conf->dpc_cpucore = -1;
5152*4882a593Smuzhiyun conf->rxf_cpucore = -1;
5153*4882a593Smuzhiyun conf->dhd_dpc_prio = -1;
5154*4882a593Smuzhiyun conf->frameburst = -1;
5155*4882a593Smuzhiyun conf->deepsleep = FALSE;
5156*4882a593Smuzhiyun conf->pm = -1;
5157*4882a593Smuzhiyun conf->pm_in_suspend = -1;
5158*4882a593Smuzhiyun conf->insuspend = 0;
5159*4882a593Smuzhiyun conf->suspend_mode = PM_NOTIFIER;
5160*4882a593Smuzhiyun conf->suspend_bcn_li_dtim = -1;
5161*4882a593Smuzhiyun conf->rekey_offload = FALSE;
5162*4882a593Smuzhiyun #ifdef WL_EXT_WOWL
5163*4882a593Smuzhiyun dhd_master_mode = TRUE;
5164*4882a593Smuzhiyun conf->wowl = WL_WOWL_NET|WL_WOWL_DIS|WL_WOWL_BCN;
5165*4882a593Smuzhiyun conf->insuspend |= (WOWL_IN_SUSPEND | NO_TXDATA_IN_SUSPEND);
5166*4882a593Smuzhiyun #endif
5167*4882a593Smuzhiyun if (conf->suspend_mode == PM_NOTIFIER || conf->suspend_mode == SUSPEND_MODE_2)
5168*4882a593Smuzhiyun conf->insuspend |= (NO_TXDATA_IN_SUSPEND | NO_TXCTL_IN_SUSPEND);
5169*4882a593Smuzhiyun conf->suspended = FALSE;
5170*4882a593Smuzhiyun memset(&conf->bssid_insuspend, 0, ETHER_ADDR_LEN);
5171*4882a593Smuzhiyun #ifdef SUSPEND_EVENT
5172*4882a593Smuzhiyun memset(&conf->resume_eventmask, 0, sizeof(conf->resume_eventmask));
5173*4882a593Smuzhiyun conf->wlfc = FALSE;
5174*4882a593Smuzhiyun #endif
5175*4882a593Smuzhiyun #ifdef GET_CUSTOM_MAC_FROM_CONFIG
5176*4882a593Smuzhiyun memset(&conf->hw_ether, 0, sizeof(conf->hw_ether));
5177*4882a593Smuzhiyun #endif
5178*4882a593Smuzhiyun #ifdef IDHCP
5179*4882a593Smuzhiyun conf->dhcpc_enable = -1;
5180*4882a593Smuzhiyun conf->dhcpd_enable = -1;
5181*4882a593Smuzhiyun #endif
5182*4882a593Smuzhiyun conf->orphan_move = 0;
5183*4882a593Smuzhiyun #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
5184*4882a593Smuzhiyun conf->tsq = 10;
5185*4882a593Smuzhiyun #else
5186*4882a593Smuzhiyun conf->tsq = 0;
5187*4882a593Smuzhiyun #endif
5188*4882a593Smuzhiyun #ifdef DHDTCPACK_SUPPRESS
5189*4882a593Smuzhiyun #ifdef BCMPCIE
5190*4882a593Smuzhiyun conf->tcpack_sup_mode = TCPACK_SUP_HOLD;
5191*4882a593Smuzhiyun #else
5192*4882a593Smuzhiyun conf->tcpack_sup_mode = TCPACK_SUP_OFF;
5193*4882a593Smuzhiyun #endif
5194*4882a593Smuzhiyun conf->tcpack_sup_ratio = CUSTOM_TCPACK_SUPP_RATIO;
5195*4882a593Smuzhiyun conf->tcpack_sup_delay = CUSTOM_TCPACK_DELAY_TIME;
5196*4882a593Smuzhiyun #endif
5197*4882a593Smuzhiyun conf->pktprio8021x = -1;
5198*4882a593Smuzhiyun conf->ctrl_resched = 2;
5199*4882a593Smuzhiyun conf->rxcnt_timeout = 3;
5200*4882a593Smuzhiyun conf->in4way = STA_NO_SCAN_IN4WAY | STA_WAIT_DISCONNECTED |
5201*4882a593Smuzhiyun AP_WAIT_STA_RECONNECT;
5202*4882a593Smuzhiyun if (conf->chip == BCM43752_CHIP_ID)
5203*4882a593Smuzhiyun conf->war = SET_CHAN_INCONN | FW_REINIT_INCSA | FW_REINIT_EMPTY_SCAN;
5204*4882a593Smuzhiyun else
5205*4882a593Smuzhiyun conf->war = 0;
5206*4882a593Smuzhiyun #ifdef P2P_AP_CONCURRENT
5207*4882a593Smuzhiyun conf->war |= P2P_AP_MAC_CONFLICT;
5208*4882a593Smuzhiyun #endif
5209*4882a593Smuzhiyun #ifdef PROPTX_MAXCOUNT
5210*4882a593Smuzhiyun conf->proptx_maxcnt_2g = 46;
5211*4882a593Smuzhiyun conf->proptx_maxcnt_5g = WL_TXSTATUS_FREERUNCTR_MASK;
5212*4882a593Smuzhiyun #endif /* DYNAMIC_PROPTX_MAXCOUNT */
5213*4882a593Smuzhiyun #ifdef TPUT_MONITOR
5214*4882a593Smuzhiyun conf->data_drop_mode = NO_DATA_DROP;
5215*4882a593Smuzhiyun conf->tput_monitor_ms = 0;
5216*4882a593Smuzhiyun #ifdef BCMSDIO
5217*4882a593Smuzhiyun if (conf->chip == BCM43752_CHIP_ID || conf->chip == BCM4375_CHIP_ID)
5218*4882a593Smuzhiyun conf->doflow_tput_thresh = 200;
5219*4882a593Smuzhiyun else
5220*4882a593Smuzhiyun conf->doflow_tput_thresh = 9999;
5221*4882a593Smuzhiyun if (conf->doflow_tput_thresh > 0 && conf->doflow_tput_thresh < 9999)
5222*4882a593Smuzhiyun conf->tput_monitor_ms = 1000;
5223*4882a593Smuzhiyun #endif
5224*4882a593Smuzhiyun #endif
5225*4882a593Smuzhiyun #ifdef SCAN_SUPPRESS
5226*4882a593Smuzhiyun conf->scan_intput = SCAN_CURCHAN_INTPUT;
5227*4882a593Smuzhiyun conf->scan_busy_thresh = 10;
5228*4882a593Smuzhiyun conf->scan_busy_tmo = 120;
5229*4882a593Smuzhiyun if (conf->chip == BCM43752_CHIP_ID || conf->chip == BCM4375_CHIP_ID)
5230*4882a593Smuzhiyun conf->scan_tput_thresh = 100;
5231*4882a593Smuzhiyun else
5232*4882a593Smuzhiyun conf->scan_tput_thresh = 9999;
5233*4882a593Smuzhiyun if (conf->scan_tput_thresh > 0 && conf->scan_tput_thresh < 9999)
5234*4882a593Smuzhiyun conf->tput_monitor_ms = 1000;
5235*4882a593Smuzhiyun #endif
5236*4882a593Smuzhiyun #ifdef DHD_TPUT_PATCH
5237*4882a593Smuzhiyun conf->tput_patch = FALSE;
5238*4882a593Smuzhiyun conf->mtu = 0;
5239*4882a593Smuzhiyun conf->pktsetsum = FALSE;
5240*4882a593Smuzhiyun #endif
5241*4882a593Smuzhiyun #ifdef SET_XPS_CPUS
5242*4882a593Smuzhiyun conf->xps_cpus = FALSE;
5243*4882a593Smuzhiyun #endif
5244*4882a593Smuzhiyun #ifdef SET_RPS_CPUS
5245*4882a593Smuzhiyun conf->rps_cpus = FALSE;
5246*4882a593Smuzhiyun #endif
5247*4882a593Smuzhiyun #ifdef CHECK_DOWNLOAD_FW
5248*4882a593Smuzhiyun conf->fwchk = FALSE;
5249*4882a593Smuzhiyun #endif
5250*4882a593Smuzhiyun #ifdef ISAM_PREINIT
5251*4882a593Smuzhiyun memset(conf->isam_init, 0, sizeof(conf->isam_init));
5252*4882a593Smuzhiyun memset(conf->isam_config, 0, sizeof(conf->isam_config));
5253*4882a593Smuzhiyun memset(conf->isam_enable, 0, sizeof(conf->isam_enable));
5254*4882a593Smuzhiyun #endif
5255*4882a593Smuzhiyun #if defined(SDIO_ISR_THREAD)
5256*4882a593Smuzhiyun if (conf->chip == BCM43012_CHIP_ID ||
5257*4882a593Smuzhiyun conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID ||
5258*4882a593Smuzhiyun conf->chip == BCM43454_CHIP_ID || conf->chip == BCM4345_CHIP_ID ||
5259*4882a593Smuzhiyun conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||
5260*4882a593Smuzhiyun conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID ||
5261*4882a593Smuzhiyun conf->chip == BCM4359_CHIP_ID ||
5262*4882a593Smuzhiyun conf->chip == BCM43751_CHIP_ID || conf->chip == BCM43752_CHIP_ID ||
5263*4882a593Smuzhiyun conf->chip == BCM4375_CHIP_ID) {
5264*4882a593Smuzhiyun conf->intr_extn = TRUE;
5265*4882a593Smuzhiyun }
5266*4882a593Smuzhiyun #endif
5267*4882a593Smuzhiyun if ((conf->chip == BCM43430_CHIP_ID && conf->chiprev == 2) ||
5268*4882a593Smuzhiyun conf->chip == BCM43012_CHIP_ID ||
5269*4882a593Smuzhiyun conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID ||
5270*4882a593Smuzhiyun conf->chip == BCM43454_CHIP_ID || conf->chip == BCM4345_CHIP_ID ||
5271*4882a593Smuzhiyun conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||
5272*4882a593Smuzhiyun conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID ||
5273*4882a593Smuzhiyun conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID ||
5274*4882a593Smuzhiyun conf->chip == BCM43751_CHIP_ID || conf->chip == BCM43752_CHIP_ID ||
5275*4882a593Smuzhiyun conf->chip == BCM4375_CHIP_ID) {
5276*4882a593Smuzhiyun #ifdef DHDTCPACK_SUPPRESS
5277*4882a593Smuzhiyun #ifdef BCMSDIO
5278*4882a593Smuzhiyun conf->tcpack_sup_mode = TCPACK_SUP_REPLACE;
5279*4882a593Smuzhiyun #endif
5280*4882a593Smuzhiyun #endif
5281*4882a593Smuzhiyun #if defined(BCMSDIO) || defined(BCMPCIE)
5282*4882a593Smuzhiyun dhd_rxbound = 128;
5283*4882a593Smuzhiyun dhd_txbound = 64;
5284*4882a593Smuzhiyun #endif
5285*4882a593Smuzhiyun conf->frameburst = 1;
5286*4882a593Smuzhiyun #ifdef BCMSDIO
5287*4882a593Smuzhiyun conf->dhd_txminmax = -1;
5288*4882a593Smuzhiyun conf->txinrx_thres = 128;
5289*4882a593Smuzhiyun #endif
5290*4882a593Smuzhiyun #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
5291*4882a593Smuzhiyun conf->orphan_move = 1;
5292*4882a593Smuzhiyun #else
5293*4882a593Smuzhiyun conf->orphan_move = 0;
5294*4882a593Smuzhiyun #endif
5295*4882a593Smuzhiyun }
5296*4882a593Smuzhiyun #ifdef DHD_TPUT_PATCH
5297*4882a593Smuzhiyun if (conf->chip == BCM43751_CHIP_ID || conf->chip == BCM43752_CHIP_ID ||
5298*4882a593Smuzhiyun conf->chip == BCM4375_CHIP_ID) {
5299*4882a593Smuzhiyun conf->tput_patch = TRUE;
5300*4882a593Smuzhiyun dhd_conf_set_tput_patch(dhd);
5301*4882a593Smuzhiyun }
5302*4882a593Smuzhiyun #endif
5303*4882a593Smuzhiyun
5304*4882a593Smuzhiyun #ifdef BCMSDIO
5305*4882a593Smuzhiyun #if defined(BCMSDIOH_TXGLOM_EXT)
5306*4882a593Smuzhiyun if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID ||
5307*4882a593Smuzhiyun conf->chip == BCM43340_CHIP_ID || conf->chip == BCM43341_CHIP_ID ||
5308*4882a593Smuzhiyun conf->chip == BCM4334_CHIP_ID || conf->chip == BCM4324_CHIP_ID) {
5309*4882a593Smuzhiyun conf->txglom_ext = TRUE;
5310*4882a593Smuzhiyun } else {
5311*4882a593Smuzhiyun conf->txglom_ext = FALSE;
5312*4882a593Smuzhiyun }
5313*4882a593Smuzhiyun if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID) {
5314*4882a593Smuzhiyun conf->txglom_bucket_size = 1680; // fixed value, don't change
5315*4882a593Smuzhiyun conf->txglomsize = 6;
5316*4882a593Smuzhiyun }
5317*4882a593Smuzhiyun if (conf->chip == BCM4334_CHIP_ID || conf->chip == BCM43340_CHIP_ID ||
5318*4882a593Smuzhiyun conf->chip == BCM43341_CHIP_ID || conf->chip == BCM4324_CHIP_ID) {
5319*4882a593Smuzhiyun conf->txglom_bucket_size = 1684; // fixed value, don't change
5320*4882a593Smuzhiyun conf->txglomsize = 16;
5321*4882a593Smuzhiyun }
5322*4882a593Smuzhiyun #endif
5323*4882a593Smuzhiyun if (conf->txglomsize > SDPCM_MAXGLOM_SIZE)
5324*4882a593Smuzhiyun conf->txglomsize = SDPCM_MAXGLOM_SIZE;
5325*4882a593Smuzhiyun #endif
5326*4882a593Smuzhiyun init_waitqueue_head(&conf->event_complete);
5327*4882a593Smuzhiyun #ifdef CUSTOMER_HW_ROCKCHIP
5328*4882a593Smuzhiyun #ifdef BCMPCIE
5329*4882a593Smuzhiyun conf->d2h_intr_control = 0;
5330*4882a593Smuzhiyun #endif
5331*4882a593Smuzhiyun #endif
5332*4882a593Smuzhiyun
5333*4882a593Smuzhiyun return 0;
5334*4882a593Smuzhiyun }
5335*4882a593Smuzhiyun
5336*4882a593Smuzhiyun int
dhd_conf_reset(dhd_pub_t * dhd)5337*4882a593Smuzhiyun dhd_conf_reset(dhd_pub_t *dhd)
5338*4882a593Smuzhiyun {
5339*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
5340*4882a593Smuzhiyun
5341*4882a593Smuzhiyun dhd_conf_free_preinit(dhd);
5342*4882a593Smuzhiyun memset(conf, 0, sizeof(dhd_conf_t));
5343*4882a593Smuzhiyun return 0;
5344*4882a593Smuzhiyun }
5345*4882a593Smuzhiyun
5346*4882a593Smuzhiyun int
dhd_conf_attach(dhd_pub_t * dhd)5347*4882a593Smuzhiyun dhd_conf_attach(dhd_pub_t *dhd)
5348*4882a593Smuzhiyun {
5349*4882a593Smuzhiyun dhd_conf_t *conf;
5350*4882a593Smuzhiyun
5351*4882a593Smuzhiyun CONFIG_TRACE("Enter\n");
5352*4882a593Smuzhiyun
5353*4882a593Smuzhiyun if (dhd->conf != NULL) {
5354*4882a593Smuzhiyun CONFIG_MSG("config is attached before!\n");
5355*4882a593Smuzhiyun return 0;
5356*4882a593Smuzhiyun }
5357*4882a593Smuzhiyun /* Allocate private bus interface state */
5358*4882a593Smuzhiyun if (!(conf = MALLOC(dhd->osh, sizeof(dhd_conf_t)))) {
5359*4882a593Smuzhiyun CONFIG_ERROR("MALLOC failed\n");
5360*4882a593Smuzhiyun goto fail;
5361*4882a593Smuzhiyun }
5362*4882a593Smuzhiyun memset(conf, 0, sizeof(dhd_conf_t));
5363*4882a593Smuzhiyun
5364*4882a593Smuzhiyun dhd->conf = conf;
5365*4882a593Smuzhiyun
5366*4882a593Smuzhiyun return 0;
5367*4882a593Smuzhiyun
5368*4882a593Smuzhiyun fail:
5369*4882a593Smuzhiyun if (conf != NULL)
5370*4882a593Smuzhiyun MFREE(dhd->osh, conf, sizeof(dhd_conf_t));
5371*4882a593Smuzhiyun return BCME_NOMEM;
5372*4882a593Smuzhiyun }
5373*4882a593Smuzhiyun
5374*4882a593Smuzhiyun void
dhd_conf_detach(dhd_pub_t * dhd)5375*4882a593Smuzhiyun dhd_conf_detach(dhd_pub_t *dhd)
5376*4882a593Smuzhiyun {
5377*4882a593Smuzhiyun struct dhd_conf *conf = dhd->conf;
5378*4882a593Smuzhiyun
5379*4882a593Smuzhiyun CONFIG_TRACE("Enter\n");
5380*4882a593Smuzhiyun if (dhd->conf) {
5381*4882a593Smuzhiyun dhd_conf_free_preinit(dhd);
5382*4882a593Smuzhiyun MFREE(dhd->osh, conf, sizeof(dhd_conf_t));
5383*4882a593Smuzhiyun }
5384*4882a593Smuzhiyun dhd->conf = NULL;
5385*4882a593Smuzhiyun }
5386