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 | */ | |
45575664 | 16 | |
f97e956a | 17 | #include <brcmu_utils.h> |
cc3cea5a | 18 | #include "types.h" |
cc3cea5a | 19 | #include "pub.h" |
cc3cea5a | 20 | #include "main.h" |
3bec7bb9 | 21 | #include "alloc.h" |
a9533e7e | 22 | |
1c4c54ba RV |
23 | static struct brcms_c_bsscfg *brcms_c_bsscfg_malloc(uint unit); |
24 | static void brcms_c_bsscfg_mfree(struct brcms_c_bsscfg *cfg); | |
25 | static struct wlc_pub *brcms_c_pub_malloc(uint unit, | |
08db27dc | 26 | uint *err, uint devid); |
1c4c54ba RV |
27 | static void brcms_c_pub_mfree(struct wlc_pub *pub); |
28 | static void brcms_c_tunables_init(wlc_tunables_t *tunables, uint devid); | |
a9533e7e | 29 | |
1c4c54ba | 30 | static void brcms_c_tunables_init(wlc_tunables_t *tunables, uint devid) |
a2627bc0 | 31 | { |
a9533e7e HP |
32 | tunables->ntxd = NTXD; |
33 | tunables->nrxd = NRXD; | |
34 | tunables->rxbufsz = RXBUFSZ; | |
35 | tunables->nrxbufpost = NRXBUFPOST; | |
36 | tunables->maxscb = MAXSCB; | |
37 | tunables->ampdunummpdu = AMPDU_NUM_MPDU; | |
38 | tunables->maxpktcb = MAXPKTCB; | |
39 | tunables->maxucodebss = WLC_MAX_UCODE_BSS; | |
40 | tunables->maxucodebss4 = WLC_MAX_UCODE_BSS4; | |
41 | tunables->maxbss = MAXBSS; | |
42 | tunables->datahiwat = WLC_DATAHIWAT; | |
43 | tunables->ampdudatahiwat = WLC_AMPDUDATAHIWAT; | |
44 | tunables->rxbnd = RXBND; | |
45 | tunables->txsbnd = TXSBND; | |
a9533e7e HP |
46 | } |
47 | ||
1c4c54ba | 48 | static struct wlc_pub *brcms_c_pub_malloc(uint unit, uint *err, uint devid) |
0d2f0724 | 49 | { |
08db27dc | 50 | struct wlc_pub *pub; |
a9533e7e | 51 | |
56aec662 | 52 | pub = kzalloc(sizeof(struct wlc_pub), GFP_ATOMIC); |
ca8c1e59 | 53 | if (pub == NULL) { |
a9533e7e HP |
54 | *err = 1001; |
55 | goto fail; | |
56 | } | |
57 | ||
56aec662 | 58 | pub->tunables = kzalloc(sizeof(wlc_tunables_t), GFP_ATOMIC); |
ca8c1e59 | 59 | if (pub->tunables == NULL) { |
a9533e7e HP |
60 | *err = 1028; |
61 | goto fail; | |
62 | } | |
63 | ||
64 | /* need to init the tunables now */ | |
1c4c54ba | 65 | brcms_c_tunables_init(pub->tunables, devid); |
a9533e7e | 66 | |
56aec662 | 67 | pub->multicast = kzalloc(ETH_ALEN * MAXMULTILIST, GFP_ATOMIC); |
ca8c1e59 | 68 | if (pub->multicast == NULL) { |
a9533e7e HP |
69 | *err = 1003; |
70 | goto fail; | |
71 | } | |
72 | ||
73 | return pub; | |
74 | ||
75 | fail: | |
1c4c54ba | 76 | brcms_c_pub_mfree(pub); |
a9533e7e HP |
77 | return NULL; |
78 | } | |
79 | ||
1c4c54ba | 80 | static void brcms_c_pub_mfree(struct wlc_pub *pub) |
a2627bc0 | 81 | { |
a9533e7e HP |
82 | if (pub == NULL) |
83 | return; | |
84 | ||
e4cf544e | 85 | kfree(pub->multicast); |
e4cf544e | 86 | kfree(pub->tunables); |
182acb3c | 87 | kfree(pub); |
a9533e7e HP |
88 | } |
89 | ||
1c4c54ba | 90 | static struct brcms_c_bsscfg *brcms_c_bsscfg_malloc(uint unit) |
a9533e7e | 91 | { |
fe741e5e | 92 | struct brcms_c_bsscfg *cfg; |
a9533e7e | 93 | |
fe741e5e | 94 | cfg = kzalloc(sizeof(struct brcms_c_bsscfg), GFP_ATOMIC); |
ca8c1e59 | 95 | if (cfg == NULL) |
a9533e7e HP |
96 | goto fail; |
97 | ||
56aec662 | 98 | cfg->current_bss = kzalloc(sizeof(wlc_bss_info_t), GFP_ATOMIC); |
ca8c1e59 | 99 | if (cfg->current_bss == NULL) |
a9533e7e HP |
100 | goto fail; |
101 | ||
102 | return cfg; | |
103 | ||
104 | fail: | |
1c4c54ba | 105 | brcms_c_bsscfg_mfree(cfg); |
a9533e7e HP |
106 | return NULL; |
107 | } | |
108 | ||
1c4c54ba | 109 | static void brcms_c_bsscfg_mfree(struct brcms_c_bsscfg *cfg) |
a9533e7e HP |
110 | { |
111 | if (cfg == NULL) | |
112 | return; | |
113 | ||
7c0e45d7 AS |
114 | kfree(cfg->maclist); |
115 | kfree(cfg->current_bss); | |
182acb3c | 116 | kfree(cfg); |
a9533e7e HP |
117 | } |
118 | ||
1c4c54ba | 119 | static void brcms_c_bsscfg_ID_assign(struct brcms_c_info *wlc, |
fe741e5e | 120 | struct brcms_c_bsscfg *bsscfg) |
a9533e7e HP |
121 | { |
122 | bsscfg->ID = wlc->next_bsscfg_ID; | |
123 | wlc->next_bsscfg_ID++; | |
124 | } | |
125 | ||
126 | /* | |
127 | * The common driver entry routine. Error codes should be unique | |
128 | */ | |
f52a0ad0 | 129 | struct brcms_c_info *brcms_c_attach_malloc(uint unit, uint *err, uint devid) |
0d2f0724 | 130 | { |
fe741e5e | 131 | struct brcms_c_info *wlc; |
a9533e7e | 132 | |
fe741e5e | 133 | wlc = kzalloc(sizeof(struct brcms_c_info), GFP_ATOMIC); |
ca8c1e59 | 134 | if (wlc == NULL) { |
a9533e7e HP |
135 | *err = 1002; |
136 | goto fail; | |
137 | } | |
138 | ||
fe741e5e | 139 | /* allocate struct brcms_c_pub state structure */ |
1c4c54ba | 140 | wlc->pub = brcms_c_pub_malloc(unit, err, devid); |
ca8c1e59 | 141 | if (wlc->pub == NULL) { |
a9533e7e HP |
142 | *err = 1003; |
143 | goto fail; | |
144 | } | |
145 | wlc->pub->wlc = wlc; | |
146 | ||
fe741e5e | 147 | /* allocate struct brcms_c_hw_info state structure */ |
a9533e7e | 148 | |
fe741e5e | 149 | wlc->hw = kzalloc(sizeof(struct brcms_c_hw_info), GFP_ATOMIC); |
ca8c1e59 | 150 | if (wlc->hw == NULL) { |
a9533e7e HP |
151 | *err = 1005; |
152 | goto fail; | |
153 | } | |
154 | wlc->hw->wlc = wlc; | |
155 | ||
56aec662 | 156 | wlc->hw->bandstate[0] = |
fe741e5e | 157 | kzalloc(sizeof(struct brcms_c_hwband) * MAXBANDS, GFP_ATOMIC); |
ca8c1e59 | 158 | if (wlc->hw->bandstate[0] == NULL) { |
a9533e7e HP |
159 | *err = 1006; |
160 | goto fail; | |
161 | } else { | |
162 | int i; | |
163 | ||
164 | for (i = 1; i < MAXBANDS; i++) { | |
fe741e5e | 165 | wlc->hw->bandstate[i] = (struct brcms_c_hwband *) |
f024c48a | 166 | ((unsigned long)wlc->hw->bandstate[0] + |
fe741e5e | 167 | (sizeof(struct brcms_c_hwband) * i)); |
a9533e7e HP |
168 | } |
169 | } | |
a9533e7e | 170 | |
56aec662 RV |
171 | wlc->modulecb = |
172 | kzalloc(sizeof(struct modulecb) * WLC_MAXMODULES, GFP_ATOMIC); | |
ca8c1e59 | 173 | if (wlc->modulecb == NULL) { |
a9533e7e HP |
174 | *err = 1009; |
175 | goto fail; | |
176 | } | |
177 | ||
56aec662 | 178 | wlc->default_bss = kzalloc(sizeof(wlc_bss_info_t), GFP_ATOMIC); |
ca8c1e59 | 179 | if (wlc->default_bss == NULL) { |
a9533e7e HP |
180 | *err = 1010; |
181 | goto fail; | |
182 | } | |
183 | ||
1c4c54ba | 184 | wlc->cfg = brcms_c_bsscfg_malloc(unit); |
ca8c1e59 | 185 | if (wlc->cfg == NULL) { |
a9533e7e HP |
186 | *err = 1011; |
187 | goto fail; | |
188 | } | |
1c4c54ba | 189 | brcms_c_bsscfg_ID_assign(wlc, wlc->cfg); |
a9533e7e | 190 | |
56aec662 RV |
191 | wlc->wsec_def_keys[0] = |
192 | kzalloc(sizeof(wsec_key_t) * WLC_DEFAULT_KEYS, GFP_ATOMIC); | |
ca8c1e59 | 193 | if (wlc->wsec_def_keys[0] == NULL) { |
a9533e7e HP |
194 | *err = 1015; |
195 | goto fail; | |
196 | } else { | |
197 | int i; | |
198 | for (i = 1; i < WLC_DEFAULT_KEYS; i++) { | |
199 | wlc->wsec_def_keys[i] = (wsec_key_t *) | |
f024c48a | 200 | ((unsigned long)wlc->wsec_def_keys[0] + |
a9533e7e HP |
201 | (sizeof(wsec_key_t) * i)); |
202 | } | |
203 | } | |
204 | ||
fe741e5e RV |
205 | wlc->protection = kzalloc(sizeof(struct brcms_c_protection), |
206 | GFP_ATOMIC); | |
ca8c1e59 | 207 | if (wlc->protection == NULL) { |
a9533e7e HP |
208 | *err = 1016; |
209 | goto fail; | |
210 | } | |
211 | ||
fe741e5e | 212 | wlc->stf = kzalloc(sizeof(struct brcms_c_stf), GFP_ATOMIC); |
ca8c1e59 | 213 | if (wlc->stf == NULL) { |
a9533e7e HP |
214 | *err = 1017; |
215 | goto fail; | |
216 | } | |
217 | ||
56aec662 | 218 | wlc->bandstate[0] = |
fe741e5e | 219 | kzalloc(sizeof(struct brcms_c_band)*MAXBANDS, GFP_ATOMIC); |
ca8c1e59 | 220 | if (wlc->bandstate[0] == NULL) { |
a9533e7e HP |
221 | *err = 1025; |
222 | goto fail; | |
223 | } else { | |
224 | int i; | |
225 | ||
226 | for (i = 1; i < MAXBANDS; i++) { | |
fe741e5e RV |
227 | wlc->bandstate[i] = (struct brcms_c_band *) |
228 | ((unsigned long)wlc->bandstate[0] | |
229 | + (sizeof(struct brcms_c_band)*i)); | |
a9533e7e HP |
230 | } |
231 | } | |
232 | ||
fe741e5e | 233 | wlc->corestate = kzalloc(sizeof(struct brcms_c_core), GFP_ATOMIC); |
ca8c1e59 | 234 | if (wlc->corestate == NULL) { |
a9533e7e HP |
235 | *err = 1026; |
236 | goto fail; | |
237 | } | |
238 | ||
ca8c1e59 | 239 | wlc->corestate->macstat_snapshot = |
56aec662 | 240 | kzalloc(sizeof(macstat_t), GFP_ATOMIC); |
ca8c1e59 | 241 | if (wlc->corestate->macstat_snapshot == NULL) { |
a9533e7e HP |
242 | *err = 1027; |
243 | goto fail; | |
244 | } | |
245 | ||
246 | return wlc; | |
247 | ||
248 | fail: | |
f52a0ad0 | 249 | brcms_c_detach_mfree(wlc); |
a9533e7e HP |
250 | return NULL; |
251 | } | |
252 | ||
f52a0ad0 | 253 | void brcms_c_detach_mfree(struct brcms_c_info *wlc) |
a2627bc0 | 254 | { |
a9533e7e HP |
255 | if (wlc == NULL) |
256 | return; | |
257 | ||
1c4c54ba RV |
258 | brcms_c_bsscfg_mfree(wlc->cfg); |
259 | brcms_c_pub_mfree(wlc->pub); | |
7c0e45d7 AS |
260 | kfree(wlc->modulecb); |
261 | kfree(wlc->default_bss); | |
7c0e45d7 AS |
262 | kfree(wlc->wsec_def_keys[0]); |
263 | kfree(wlc->protection); | |
264 | kfree(wlc->stf); | |
265 | kfree(wlc->bandstate[0]); | |
266 | kfree(wlc->corestate->macstat_snapshot); | |
267 | kfree(wlc->corestate); | |
268 | kfree(wlc->hw->bandstate[0]); | |
269 | kfree(wlc->hw); | |
a9533e7e HP |
270 | |
271 | /* free the wlc */ | |
182acb3c | 272 | kfree(wlc); |
a9533e7e HP |
273 | wlc = NULL; |
274 | } |