]>
Commit | Line | Data |
---|---|---|
a9533e7e HP |
1 | /* |
2 | * Copyright (c) 2010 Broadcom Corporation | |
3 | * | |
4 | * Permission to use, copy, modify, and/or distribute this software for any | |
5 | * purpose with or without fee is hereby granted, provided that the above | |
6 | * copyright notice and this permission notice appear in all copies. | |
7 | * | |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | |
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | |
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 | */ | |
16 | ||
17 | #include <wlc_cfg.h> | |
18 | #include <typedefs.h> | |
19 | #include <bcmdefs.h> | |
20 | #include <osl.h> | |
21 | #include <bcmutils.h> | |
22 | #include <siutils.h> | |
23 | #include <proto/802.11.h> | |
24 | #include <proto/802.11e.h> | |
25 | #include <proto/wpa.h> | |
26 | #include <wlioctl.h> | |
27 | #include <bcmwpa.h> | |
28 | #include <d11.h> | |
29 | #include <wlc_rate.h> | |
30 | #include <wlc_pub.h> | |
31 | #include <wlc_key.h> | |
32 | #include <wlc_bsscfg.h> | |
33 | #include <wlc_mac80211.h> | |
34 | #include <wlc_alloc.h> | |
35 | ||
7cc4a4c0 | 36 | static wlc_pub_t *wlc_pub_malloc(osl_t *osh, uint unit, uint *err, |
a9533e7e | 37 | uint devid); |
7cc4a4c0 JC |
38 | static void wlc_pub_mfree(osl_t *osh, wlc_pub_t *pub); |
39 | static void wlc_tunables_init(wlc_tunables_t *tunables, uint devid); | |
a9533e7e | 40 | |
7cc4a4c0 | 41 | void *wlc_calloc(osl_t *osh, uint unit, uint size) |
a9533e7e HP |
42 | { |
43 | void *item; | |
44 | ||
45 | if ((item = MALLOC(osh, size)) == NULL) | |
46 | WL_ERROR(("wl%d: %s: out of memory, malloced %d bytes\n", | |
47 | unit, __func__, MALLOCED(osh))); | |
48 | else | |
49 | bzero((char *)item, size); | |
50 | return item; | |
51 | } | |
52 | ||
a2627bc0 JC |
53 | void BCMATTACHFN(wlc_tunables_init) (wlc_tunables_t *tunables, uint devid) |
54 | { | |
a9533e7e HP |
55 | tunables->ntxd = NTXD; |
56 | tunables->nrxd = NRXD; | |
57 | tunables->rxbufsz = RXBUFSZ; | |
58 | tunables->nrxbufpost = NRXBUFPOST; | |
59 | tunables->maxscb = MAXSCB; | |
60 | tunables->ampdunummpdu = AMPDU_NUM_MPDU; | |
61 | tunables->maxpktcb = MAXPKTCB; | |
62 | tunables->maxucodebss = WLC_MAX_UCODE_BSS; | |
63 | tunables->maxucodebss4 = WLC_MAX_UCODE_BSS4; | |
64 | tunables->maxbss = MAXBSS; | |
65 | tunables->datahiwat = WLC_DATAHIWAT; | |
66 | tunables->ampdudatahiwat = WLC_AMPDUDATAHIWAT; | |
67 | tunables->rxbnd = RXBND; | |
68 | tunables->txsbnd = TXSBND; | |
69 | #if defined(WLC_HIGH_ONLY) && defined(NTXD_USB_4319) | |
70 | if (devid == BCM4319_CHIP_ID) { | |
71 | tunables->ntxd = NTXD_USB_4319; | |
72 | } | |
73 | #endif /* WLC_HIGH_ONLY */ | |
74 | } | |
75 | ||
7cc4a4c0 JC |
76 | static wlc_pub_t *BCMATTACHFN(wlc_pub_malloc) (osl_t *osh, uint unit, |
77 | uint *err, uint devid) { | |
a9533e7e HP |
78 | wlc_pub_t *pub; |
79 | ||
80 | if ((pub = | |
81 | (wlc_pub_t *) wlc_calloc(osh, unit, sizeof(wlc_pub_t))) == NULL) { | |
82 | *err = 1001; | |
83 | goto fail; | |
84 | } | |
85 | ||
86 | if ((pub->tunables = (wlc_tunables_t *) | |
87 | wlc_calloc(osh, unit, sizeof(wlc_tunables_t))) == NULL) { | |
88 | *err = 1028; | |
89 | goto fail; | |
90 | } | |
91 | ||
92 | /* need to init the tunables now */ | |
93 | wlc_tunables_init(pub->tunables, devid); | |
94 | ||
95 | if ((pub->multicast = (struct ether_addr *) | |
96 | wlc_calloc(osh, unit, | |
97 | (sizeof(struct ether_addr) * MAXMULTILIST))) == NULL) { | |
98 | *err = 1003; | |
99 | goto fail; | |
100 | } | |
101 | ||
102 | return pub; | |
103 | ||
104 | fail: | |
105 | wlc_pub_mfree(osh, pub); | |
106 | return NULL; | |
107 | } | |
108 | ||
a2627bc0 JC |
109 | static void BCMATTACHFN(wlc_pub_mfree) (osl_t *osh, wlc_pub_t *pub) |
110 | { | |
a9533e7e HP |
111 | if (pub == NULL) |
112 | return; | |
113 | ||
114 | if (pub->multicast) | |
115 | MFREE(osh, pub->multicast, | |
116 | (sizeof(struct ether_addr) * MAXMULTILIST)); | |
117 | ||
118 | if (pub->tunables) { | |
119 | MFREE(osh, pub->tunables, sizeof(wlc_tunables_t)); | |
120 | pub->tunables = NULL; | |
121 | } | |
122 | ||
123 | MFREE(osh, pub, sizeof(wlc_pub_t)); | |
124 | } | |
125 | ||
7cc4a4c0 | 126 | wlc_bsscfg_t *wlc_bsscfg_malloc(osl_t *osh, uint unit) |
a9533e7e HP |
127 | { |
128 | wlc_bsscfg_t *cfg; | |
129 | ||
130 | if ((cfg = | |
131 | (wlc_bsscfg_t *) wlc_calloc(osh, unit, | |
132 | sizeof(wlc_bsscfg_t))) == NULL) | |
133 | goto fail; | |
134 | ||
135 | if ((cfg->current_bss = (wlc_bss_info_t *) | |
136 | wlc_calloc(osh, unit, sizeof(wlc_bss_info_t))) == NULL) | |
137 | goto fail; | |
138 | ||
139 | return cfg; | |
140 | ||
141 | fail: | |
142 | wlc_bsscfg_mfree(osh, cfg); | |
143 | return NULL; | |
144 | } | |
145 | ||
7cc4a4c0 | 146 | void wlc_bsscfg_mfree(osl_t *osh, wlc_bsscfg_t *cfg) |
a9533e7e HP |
147 | { |
148 | if (cfg == NULL) | |
149 | return; | |
150 | ||
151 | if (cfg->maclist) { | |
152 | MFREE(osh, cfg->maclist, | |
153 | (int)(OFFSETOF(struct maclist, ea) + | |
154 | cfg->nmac * ETHER_ADDR_LEN)); | |
155 | cfg->maclist = NULL; | |
156 | } | |
157 | ||
158 | if (cfg->current_bss != NULL) { | |
159 | wlc_bss_info_t *current_bss = cfg->current_bss; | |
160 | if (current_bss->bcn_prb != NULL) | |
161 | MFREE(osh, current_bss->bcn_prb, | |
162 | current_bss->bcn_prb_len); | |
163 | MFREE(osh, current_bss, sizeof(wlc_bss_info_t)); | |
164 | cfg->current_bss = NULL; | |
165 | } | |
166 | ||
167 | MFREE(osh, cfg, sizeof(wlc_bsscfg_t)); | |
168 | } | |
169 | ||
7cc4a4c0 | 170 | void wlc_bsscfg_ID_assign(wlc_info_t *wlc, wlc_bsscfg_t *bsscfg) |
a9533e7e HP |
171 | { |
172 | bsscfg->ID = wlc->next_bsscfg_ID; | |
173 | wlc->next_bsscfg_ID++; | |
174 | } | |
175 | ||
176 | /* | |
177 | * The common driver entry routine. Error codes should be unique | |
178 | */ | |
7cc4a4c0 | 179 | wlc_info_t *BCMATTACHFN(wlc_attach_malloc) (osl_t *osh, uint unit, uint *err, |
a9533e7e HP |
180 | uint devid) { |
181 | wlc_info_t *wlc; | |
182 | ||
183 | if ((wlc = | |
184 | (wlc_info_t *) wlc_calloc(osh, unit, | |
185 | sizeof(wlc_info_t))) == NULL) { | |
186 | *err = 1002; | |
187 | goto fail; | |
188 | } | |
189 | ||
190 | wlc->hwrxoff = WL_HWRXOFF; | |
191 | ||
192 | /* allocate wlc_pub_t state structure */ | |
193 | if ((wlc->pub = wlc_pub_malloc(osh, unit, err, devid)) == NULL) { | |
194 | *err = 1003; | |
195 | goto fail; | |
196 | } | |
197 | wlc->pub->wlc = wlc; | |
198 | ||
199 | /* allocate wlc_hw_info_t state structure */ | |
200 | ||
201 | if ((wlc->hw = (wlc_hw_info_t *) | |
202 | wlc_calloc(osh, unit, sizeof(wlc_hw_info_t))) == NULL) { | |
203 | *err = 1005; | |
204 | goto fail; | |
205 | } | |
206 | wlc->hw->wlc = wlc; | |
207 | ||
208 | #ifdef WLC_LOW | |
209 | if ((wlc->hw->bandstate[0] = (wlc_hwband_t *) | |
210 | wlc_calloc(osh, unit, (sizeof(wlc_hwband_t) * MAXBANDS))) == NULL) { | |
211 | *err = 1006; | |
212 | goto fail; | |
213 | } else { | |
214 | int i; | |
215 | ||
216 | for (i = 1; i < MAXBANDS; i++) { | |
217 | wlc->hw->bandstate[i] = (wlc_hwband_t *) | |
218 | ((uintptr) wlc->hw->bandstate[0] + | |
219 | (sizeof(wlc_hwband_t) * i)); | |
220 | } | |
221 | } | |
222 | #endif /* WLC_LOW */ | |
223 | ||
224 | if ((wlc->modulecb = (modulecb_t *) | |
225 | wlc_calloc(osh, unit, | |
226 | sizeof(modulecb_t) * WLC_MAXMODULES)) == NULL) { | |
227 | *err = 1009; | |
228 | goto fail; | |
229 | } | |
230 | ||
231 | if ((wlc->default_bss = (wlc_bss_info_t *) | |
232 | wlc_calloc(osh, unit, sizeof(wlc_bss_info_t))) == NULL) { | |
233 | *err = 1010; | |
234 | goto fail; | |
235 | } | |
236 | ||
237 | if ((wlc->cfg = wlc_bsscfg_malloc(osh, unit)) == NULL) { | |
238 | *err = 1011; | |
239 | goto fail; | |
240 | } | |
241 | wlc_bsscfg_ID_assign(wlc, wlc->cfg); | |
242 | ||
243 | if ((wlc->pkt_callback = (pkt_cb_t *) | |
244 | wlc_calloc(osh, unit, | |
245 | (sizeof(pkt_cb_t) * | |
246 | (wlc->pub->tunables->maxpktcb + 1)))) == NULL) { | |
247 | *err = 1013; | |
248 | goto fail; | |
249 | } | |
250 | ||
251 | if ((wlc->wsec_def_keys[0] = (wsec_key_t *) | |
252 | wlc_calloc(osh, unit, | |
253 | (sizeof(wsec_key_t) * WLC_DEFAULT_KEYS))) == NULL) { | |
254 | *err = 1015; | |
255 | goto fail; | |
256 | } else { | |
257 | int i; | |
258 | for (i = 1; i < WLC_DEFAULT_KEYS; i++) { | |
259 | wlc->wsec_def_keys[i] = (wsec_key_t *) | |
260 | ((uintptr) wlc->wsec_def_keys[0] + | |
261 | (sizeof(wsec_key_t) * i)); | |
262 | } | |
263 | } | |
264 | ||
265 | if ((wlc->protection = (wlc_protection_t *) | |
266 | wlc_calloc(osh, unit, sizeof(wlc_protection_t))) == NULL) { | |
267 | *err = 1016; | |
268 | goto fail; | |
269 | } | |
270 | ||
271 | if ((wlc->stf = (wlc_stf_t *) | |
272 | wlc_calloc(osh, unit, sizeof(wlc_stf_t))) == NULL) { | |
273 | *err = 1017; | |
274 | goto fail; | |
275 | } | |
276 | ||
277 | if ((wlc->bandstate[0] = (wlcband_t *) | |
278 | wlc_calloc(osh, unit, (sizeof(wlcband_t) * MAXBANDS))) == NULL) { | |
279 | *err = 1025; | |
280 | goto fail; | |
281 | } else { | |
282 | int i; | |
283 | ||
284 | for (i = 1; i < MAXBANDS; i++) { | |
285 | wlc->bandstate[i] = | |
286 | (wlcband_t *) ((uintptr) wlc->bandstate[0] + | |
287 | (sizeof(wlcband_t) * i)); | |
288 | } | |
289 | } | |
290 | ||
291 | if ((wlc->corestate = (wlccore_t *) | |
292 | wlc_calloc(osh, unit, sizeof(wlccore_t))) == NULL) { | |
293 | *err = 1026; | |
294 | goto fail; | |
295 | } | |
296 | ||
297 | if ((wlc->corestate->macstat_snapshot = (macstat_t *) | |
298 | wlc_calloc(osh, unit, sizeof(macstat_t))) == NULL) { | |
299 | *err = 1027; | |
300 | goto fail; | |
301 | } | |
302 | ||
303 | return wlc; | |
304 | ||
305 | fail: | |
306 | wlc_detach_mfree(wlc, osh); | |
307 | return NULL; | |
308 | } | |
309 | ||
a2627bc0 JC |
310 | void BCMATTACHFN(wlc_detach_mfree) (wlc_info_t *wlc, osl_t *osh) |
311 | { | |
a9533e7e HP |
312 | if (wlc == NULL) |
313 | return; | |
314 | ||
315 | if (wlc->modulecb) { | |
316 | MFREE(osh, wlc->modulecb, sizeof(modulecb_t) * WLC_MAXMODULES); | |
317 | wlc->modulecb = NULL; | |
318 | } | |
319 | ||
320 | if (wlc->default_bss) { | |
321 | MFREE(osh, wlc->default_bss, sizeof(wlc_bss_info_t)); | |
322 | wlc->default_bss = NULL; | |
323 | } | |
324 | if (wlc->cfg) { | |
325 | wlc_bsscfg_mfree(osh, wlc->cfg); | |
326 | wlc->cfg = NULL; | |
327 | } | |
328 | ||
329 | if (wlc->pkt_callback && wlc->pub && wlc->pub->tunables) { | |
330 | MFREE(osh, | |
331 | wlc->pkt_callback, | |
332 | sizeof(pkt_cb_t) * (wlc->pub->tunables->maxpktcb + 1)); | |
333 | wlc->pkt_callback = NULL; | |
334 | } | |
335 | ||
336 | if (wlc->wsec_def_keys[0]) | |
337 | MFREE(osh, wlc->wsec_def_keys[0], | |
338 | (sizeof(wsec_key_t) * WLC_DEFAULT_KEYS)); | |
339 | ||
340 | if (wlc->protection) { | |
341 | MFREE(osh, wlc->protection, sizeof(wlc_protection_t)); | |
342 | wlc->protection = NULL; | |
343 | } | |
344 | ||
345 | if (wlc->stf) { | |
346 | MFREE(osh, wlc->stf, sizeof(wlc_stf_t)); | |
347 | wlc->stf = NULL; | |
348 | } | |
349 | ||
350 | if (wlc->bandstate[0]) | |
351 | MFREE(osh, wlc->bandstate[0], (sizeof(wlcband_t) * MAXBANDS)); | |
352 | ||
353 | if (wlc->corestate) { | |
354 | if (wlc->corestate->macstat_snapshot) { | |
355 | MFREE(osh, wlc->corestate->macstat_snapshot, | |
356 | sizeof(macstat_t)); | |
357 | wlc->corestate->macstat_snapshot = NULL; | |
358 | } | |
359 | MFREE(osh, wlc->corestate, sizeof(wlccore_t)); | |
360 | wlc->corestate = NULL; | |
361 | } | |
362 | ||
363 | if (wlc->pub) { | |
364 | /* free pub struct */ | |
365 | wlc_pub_mfree(osh, wlc->pub); | |
366 | wlc->pub = NULL; | |
367 | } | |
368 | ||
369 | if (wlc->hw) { | |
370 | #ifdef WLC_LOW | |
371 | if (wlc->hw->bandstate[0]) { | |
372 | MFREE(osh, wlc->hw->bandstate[0], | |
373 | (sizeof(wlc_hwband_t) * MAXBANDS)); | |
374 | wlc->hw->bandstate[0] = NULL; | |
375 | } | |
376 | #endif | |
377 | ||
378 | /* free hw struct */ | |
379 | MFREE(osh, wlc->hw, sizeof(wlc_hw_info_t)); | |
380 | wlc->hw = NULL; | |
381 | } | |
382 | ||
383 | /* free the wlc */ | |
384 | MFREE(osh, wlc, sizeof(wlc_info_t)); | |
385 | wlc = NULL; | |
386 | } |