2 * Copyright (c) 2010 Broadcom Corporation
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.
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.
16 #include <linux/kernel.h>
17 #include <linux/string.h>
20 #include <linux/module.h>
21 #include <linux/pci.h>
30 #include <wlc_event.h>
31 #include <wlc_mac80211.h>
32 #include <wlc_alloc.h>
35 static struct wlc_pub
*wlc_pub_malloc(struct osl_info
*osh
, uint unit
,
36 uint
*err
, uint devid
);
37 static void wlc_pub_mfree(struct osl_info
*osh
, struct wlc_pub
*pub
);
38 static void wlc_tunables_init(wlc_tunables_t
*tunables
, uint devid
);
40 void *wlc_calloc(struct osl_info
*osh
, uint unit
, uint size
)
44 item
= kzalloc(size
, GFP_ATOMIC
);
46 WL_ERROR("wl%d: %s: out of memory\n", unit
, __func__
);
50 void wlc_tunables_init(wlc_tunables_t
*tunables
, uint devid
)
52 tunables
->ntxd
= NTXD
;
53 tunables
->nrxd
= NRXD
;
54 tunables
->rxbufsz
= RXBUFSZ
;
55 tunables
->nrxbufpost
= NRXBUFPOST
;
56 tunables
->maxscb
= MAXSCB
;
57 tunables
->ampdunummpdu
= AMPDU_NUM_MPDU
;
58 tunables
->maxpktcb
= MAXPKTCB
;
59 tunables
->maxucodebss
= WLC_MAX_UCODE_BSS
;
60 tunables
->maxucodebss4
= WLC_MAX_UCODE_BSS4
;
61 tunables
->maxbss
= MAXBSS
;
62 tunables
->datahiwat
= WLC_DATAHIWAT
;
63 tunables
->ampdudatahiwat
= WLC_AMPDUDATAHIWAT
;
64 tunables
->rxbnd
= RXBND
;
65 tunables
->txsbnd
= TXSBND
;
68 static struct wlc_pub
*wlc_pub_malloc(struct osl_info
*osh
, uint unit
,
69 uint
*err
, uint devid
)
73 pub
= (struct wlc_pub
*) wlc_calloc(osh
, unit
, sizeof(struct wlc_pub
));
79 pub
->tunables
= (wlc_tunables_t
*)wlc_calloc(osh
, unit
,
80 sizeof(wlc_tunables_t
));
81 if (pub
->tunables
== NULL
) {
86 /* need to init the tunables now */
87 wlc_tunables_init(pub
->tunables
, devid
);
89 pub
->multicast
= (u8
*)wlc_calloc(osh
, unit
,
90 (ETH_ALEN
* MAXMULTILIST
));
91 if (pub
->multicast
== NULL
) {
99 wlc_pub_mfree(osh
, pub
);
103 static void wlc_pub_mfree(struct osl_info
*osh
, struct wlc_pub
*pub
)
109 kfree(pub
->multicast
);
111 kfree(pub
->tunables
);
112 pub
->tunables
= NULL
;
118 wlc_bsscfg_t
*wlc_bsscfg_malloc(struct osl_info
*osh
, uint unit
)
122 cfg
= (wlc_bsscfg_t
*) wlc_calloc(osh
, unit
, sizeof(wlc_bsscfg_t
));
126 cfg
->current_bss
= (wlc_bss_info_t
*)wlc_calloc(osh
, unit
,
127 sizeof(wlc_bss_info_t
));
128 if (cfg
->current_bss
== NULL
)
134 wlc_bsscfg_mfree(osh
, cfg
);
138 void wlc_bsscfg_mfree(struct osl_info
*osh
, wlc_bsscfg_t
*cfg
)
148 if (cfg
->current_bss
!= NULL
) {
149 wlc_bss_info_t
*current_bss
= cfg
->current_bss
;
151 cfg
->current_bss
= NULL
;
157 void wlc_bsscfg_ID_assign(struct wlc_info
*wlc
, wlc_bsscfg_t
*bsscfg
)
159 bsscfg
->ID
= wlc
->next_bsscfg_ID
;
160 wlc
->next_bsscfg_ID
++;
164 * The common driver entry routine. Error codes should be unique
166 struct wlc_info
*wlc_attach_malloc(struct osl_info
*osh
, uint unit
, uint
*err
,
169 struct wlc_info
*wlc
;
171 wlc
= (struct wlc_info
*) wlc_calloc(osh
, unit
,
172 sizeof(struct wlc_info
));
178 wlc
->hwrxoff
= WL_HWRXOFF
;
180 /* allocate struct wlc_pub state structure */
181 wlc
->pub
= wlc_pub_malloc(osh
, unit
, err
, devid
);
182 if (wlc
->pub
== NULL
) {
188 /* allocate struct wlc_hw_info state structure */
190 wlc
->hw
= (struct wlc_hw_info
*)wlc_calloc(osh
, unit
,
191 sizeof(struct wlc_hw_info
));
192 if (wlc
->hw
== NULL
) {
198 wlc
->hw
->bandstate
[0] = (wlc_hwband_t
*)wlc_calloc(osh
, unit
,
199 (sizeof(wlc_hwband_t
) * MAXBANDS
));
200 if (wlc
->hw
->bandstate
[0] == NULL
) {
206 for (i
= 1; i
< MAXBANDS
; i
++) {
207 wlc
->hw
->bandstate
[i
] = (wlc_hwband_t
*)
208 ((unsigned long)wlc
->hw
->bandstate
[0] +
209 (sizeof(wlc_hwband_t
) * i
));
213 wlc
->modulecb
= (modulecb_t
*)wlc_calloc(osh
, unit
,
214 sizeof(modulecb_t
) * WLC_MAXMODULES
);
215 if (wlc
->modulecb
== NULL
) {
220 wlc
->default_bss
= (wlc_bss_info_t
*)wlc_calloc(osh
, unit
,
221 sizeof(wlc_bss_info_t
));
222 if (wlc
->default_bss
== NULL
) {
227 wlc
->cfg
= wlc_bsscfg_malloc(osh
, unit
);
228 if (wlc
->cfg
== NULL
) {
232 wlc_bsscfg_ID_assign(wlc
, wlc
->cfg
);
234 wlc
->pkt_callback
= (pkt_cb_t
*)wlc_calloc(osh
, unit
,
235 (sizeof(pkt_cb_t
) * (wlc
->pub
->tunables
->maxpktcb
+ 1)));
236 if (wlc
->pkt_callback
== NULL
) {
241 wlc
->wsec_def_keys
[0] = (wsec_key_t
*)wlc_calloc(osh
, unit
,
242 (sizeof(wsec_key_t
) * WLC_DEFAULT_KEYS
));
243 if (wlc
->wsec_def_keys
[0] == NULL
) {
248 for (i
= 1; i
< WLC_DEFAULT_KEYS
; i
++) {
249 wlc
->wsec_def_keys
[i
] = (wsec_key_t
*)
250 ((unsigned long)wlc
->wsec_def_keys
[0] +
251 (sizeof(wsec_key_t
) * i
));
255 wlc
->protection
= (wlc_protection_t
*)wlc_calloc(osh
, unit
,
256 sizeof(wlc_protection_t
));
257 if (wlc
->protection
== NULL
) {
262 wlc
->stf
= (wlc_stf_t
*)wlc_calloc(osh
, unit
, sizeof(wlc_stf_t
));
263 if (wlc
->stf
== NULL
) {
268 wlc
->bandstate
[0] = (struct wlcband
*)wlc_calloc(osh
, unit
,
269 (sizeof(struct wlcband
)*MAXBANDS
));
270 if (wlc
->bandstate
[0] == NULL
) {
276 for (i
= 1; i
< MAXBANDS
; i
++) {
278 (struct wlcband
*) ((unsigned long)wlc
->bandstate
[0]
279 + (sizeof(struct wlcband
)*i
));
283 wlc
->corestate
= (struct wlccore
*)wlc_calloc(osh
, unit
,
284 sizeof(struct wlccore
));
285 if (wlc
->corestate
== NULL
) {
290 wlc
->corestate
->macstat_snapshot
=
291 (macstat_t
*)wlc_calloc(osh
, unit
, sizeof(macstat_t
));
292 if (wlc
->corestate
->macstat_snapshot
== NULL
) {
300 wlc_detach_mfree(wlc
, osh
);
304 void wlc_detach_mfree(struct wlc_info
*wlc
, struct osl_info
*osh
)
310 kfree(wlc
->modulecb
);
311 wlc
->modulecb
= NULL
;
314 if (wlc
->default_bss
) {
315 kfree(wlc
->default_bss
);
316 wlc
->default_bss
= NULL
;
319 wlc_bsscfg_mfree(osh
, wlc
->cfg
);
323 if (wlc
->pkt_callback
&& wlc
->pub
&& wlc
->pub
->tunables
) {
324 kfree(wlc
->pkt_callback
);
325 wlc
->pkt_callback
= NULL
;
328 if (wlc
->wsec_def_keys
[0])
329 kfree(wlc
->wsec_def_keys
[0]);
330 if (wlc
->protection
) {
331 kfree(wlc
->protection
);
332 wlc
->protection
= NULL
;
340 if (wlc
->bandstate
[0])
341 kfree(wlc
->bandstate
[0]);
343 if (wlc
->corestate
) {
344 if (wlc
->corestate
->macstat_snapshot
) {
345 kfree(wlc
->corestate
->macstat_snapshot
); wlc
->corestate
->macstat_snapshot
= NULL
;
347 kfree(wlc
->corestate
);
348 wlc
->corestate
= NULL
;
352 /* free pub struct */
353 wlc_pub_mfree(osh
, wlc
->pub
);
358 if (wlc
->hw
->bandstate
[0]) {
359 kfree(wlc
->hw
->bandstate
[0]);
360 wlc
->hw
->bandstate
[0] = NULL
;