diff options
Diffstat (limited to 'drivers/net/wireless/libertas')
35 files changed, 4052 insertions, 4456 deletions
diff --git a/drivers/net/wireless/libertas/11d.c b/drivers/net/wireless/libertas/11d.c deleted file mode 100644 index 5c6968101f0d..000000000000 --- a/drivers/net/wireless/libertas/11d.c +++ /dev/null | |||
@@ -1,696 +0,0 @@ | |||
1 | /** | ||
2 | * This file contains functions for 802.11D. | ||
3 | */ | ||
4 | #include <linux/ctype.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/wireless.h> | ||
7 | |||
8 | #include "host.h" | ||
9 | #include "decl.h" | ||
10 | #include "11d.h" | ||
11 | #include "dev.h" | ||
12 | #include "wext.h" | ||
13 | |||
14 | #define TX_PWR_DEFAULT 10 | ||
15 | |||
16 | static struct region_code_mapping region_code_mapping[] = { | ||
17 | {"US ", 0x10}, /* US FCC */ | ||
18 | {"CA ", 0x10}, /* IC Canada */ | ||
19 | {"SG ", 0x10}, /* Singapore */ | ||
20 | {"EU ", 0x30}, /* ETSI */ | ||
21 | {"AU ", 0x30}, /* Australia */ | ||
22 | {"KR ", 0x30}, /* Republic Of Korea */ | ||
23 | {"ES ", 0x31}, /* Spain */ | ||
24 | {"FR ", 0x32}, /* France */ | ||
25 | {"JP ", 0x40}, /* Japan */ | ||
26 | }; | ||
27 | |||
28 | /* Following 2 structure defines the supported channels */ | ||
29 | static struct chan_freq_power channel_freq_power_UN_BG[] = { | ||
30 | {1, 2412, TX_PWR_DEFAULT}, | ||
31 | {2, 2417, TX_PWR_DEFAULT}, | ||
32 | {3, 2422, TX_PWR_DEFAULT}, | ||
33 | {4, 2427, TX_PWR_DEFAULT}, | ||
34 | {5, 2432, TX_PWR_DEFAULT}, | ||
35 | {6, 2437, TX_PWR_DEFAULT}, | ||
36 | {7, 2442, TX_PWR_DEFAULT}, | ||
37 | {8, 2447, TX_PWR_DEFAULT}, | ||
38 | {9, 2452, TX_PWR_DEFAULT}, | ||
39 | {10, 2457, TX_PWR_DEFAULT}, | ||
40 | {11, 2462, TX_PWR_DEFAULT}, | ||
41 | {12, 2467, TX_PWR_DEFAULT}, | ||
42 | {13, 2472, TX_PWR_DEFAULT}, | ||
43 | {14, 2484, TX_PWR_DEFAULT} | ||
44 | }; | ||
45 | |||
46 | static u8 lbs_region_2_code(u8 *region) | ||
47 | { | ||
48 | u8 i; | ||
49 | |||
50 | for (i = 0; i < COUNTRY_CODE_LEN && region[i]; i++) | ||
51 | region[i] = toupper(region[i]); | ||
52 | |||
53 | for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) { | ||
54 | if (!memcmp(region, region_code_mapping[i].region, | ||
55 | COUNTRY_CODE_LEN)) | ||
56 | return (region_code_mapping[i].code); | ||
57 | } | ||
58 | |||
59 | /* default is US */ | ||
60 | return (region_code_mapping[0].code); | ||
61 | } | ||
62 | |||
63 | static u8 *lbs_code_2_region(u8 code) | ||
64 | { | ||
65 | u8 i; | ||
66 | |||
67 | for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) { | ||
68 | if (region_code_mapping[i].code == code) | ||
69 | return (region_code_mapping[i].region); | ||
70 | } | ||
71 | /* default is US */ | ||
72 | return (region_code_mapping[0].region); | ||
73 | } | ||
74 | |||
75 | /** | ||
76 | * @brief This function finds the nrchan-th chan after the firstchan | ||
77 | * @param band band | ||
78 | * @param firstchan first channel number | ||
79 | * @param nrchan number of channels | ||
80 | * @return the nrchan-th chan number | ||
81 | */ | ||
82 | static u8 lbs_get_chan_11d(u8 firstchan, u8 nrchan, u8 *chan) | ||
83 | /*find the nrchan-th chan after the firstchan*/ | ||
84 | { | ||
85 | u8 i; | ||
86 | struct chan_freq_power *cfp; | ||
87 | u8 cfp_no; | ||
88 | |||
89 | cfp = channel_freq_power_UN_BG; | ||
90 | cfp_no = ARRAY_SIZE(channel_freq_power_UN_BG); | ||
91 | |||
92 | for (i = 0; i < cfp_no; i++) { | ||
93 | if ((cfp + i)->channel == firstchan) { | ||
94 | lbs_deb_11d("firstchan found\n"); | ||
95 | break; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | if (i < cfp_no) { | ||
100 | /*if beyond the boundary */ | ||
101 | if (i + nrchan < cfp_no) { | ||
102 | *chan = (cfp + i + nrchan)->channel; | ||
103 | return 1; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * @brief This function Checks if chan txpwr is learned from AP/IBSS | ||
112 | * @param chan chan number | ||
113 | * @param parsed_region_chan pointer to parsed_region_chan_11d | ||
114 | * @return TRUE; FALSE | ||
115 | */ | ||
116 | static u8 lbs_channel_known_11d(u8 chan, | ||
117 | struct parsed_region_chan_11d * parsed_region_chan) | ||
118 | { | ||
119 | struct chan_power_11d *chanpwr = parsed_region_chan->chanpwr; | ||
120 | u8 nr_chan = parsed_region_chan->nr_chan; | ||
121 | u8 i = 0; | ||
122 | |||
123 | lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (char *)chanpwr, | ||
124 | sizeof(struct chan_power_11d) * nr_chan); | ||
125 | |||
126 | for (i = 0; i < nr_chan; i++) { | ||
127 | if (chan == chanpwr[i].chan) { | ||
128 | lbs_deb_11d("found chan %d\n", chan); | ||
129 | return 1; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | lbs_deb_11d("chan %d not found\n", chan); | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | u32 lbs_chan_2_freq(u8 chan) | ||
138 | { | ||
139 | struct chan_freq_power *cf; | ||
140 | u16 i; | ||
141 | u32 freq = 0; | ||
142 | |||
143 | cf = channel_freq_power_UN_BG; | ||
144 | |||
145 | for (i = 0; i < ARRAY_SIZE(channel_freq_power_UN_BG); i++) { | ||
146 | if (chan == cf[i].channel) | ||
147 | freq = cf[i].freq; | ||
148 | } | ||
149 | |||
150 | return freq; | ||
151 | } | ||
152 | |||
153 | static int generate_domain_info_11d(struct parsed_region_chan_11d | ||
154 | *parsed_region_chan, | ||
155 | struct lbs_802_11d_domain_reg *domaininfo) | ||
156 | { | ||
157 | u8 nr_subband = 0; | ||
158 | |||
159 | u8 nr_chan = parsed_region_chan->nr_chan; | ||
160 | u8 nr_parsedchan = 0; | ||
161 | |||
162 | u8 firstchan = 0, nextchan = 0, maxpwr = 0; | ||
163 | |||
164 | u8 i, flag = 0; | ||
165 | |||
166 | memcpy(domaininfo->countrycode, parsed_region_chan->countrycode, | ||
167 | COUNTRY_CODE_LEN); | ||
168 | |||
169 | lbs_deb_11d("nrchan %d\n", nr_chan); | ||
170 | lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (char *)parsed_region_chan, | ||
171 | sizeof(struct parsed_region_chan_11d)); | ||
172 | |||
173 | for (i = 0; i < nr_chan; i++) { | ||
174 | if (!flag) { | ||
175 | flag = 1; | ||
176 | nextchan = firstchan = | ||
177 | parsed_region_chan->chanpwr[i].chan; | ||
178 | maxpwr = parsed_region_chan->chanpwr[i].pwr; | ||
179 | nr_parsedchan = 1; | ||
180 | continue; | ||
181 | } | ||
182 | |||
183 | if (parsed_region_chan->chanpwr[i].chan == nextchan + 1 && | ||
184 | parsed_region_chan->chanpwr[i].pwr == maxpwr) { | ||
185 | nextchan++; | ||
186 | nr_parsedchan++; | ||
187 | } else { | ||
188 | domaininfo->subband[nr_subband].firstchan = firstchan; | ||
189 | domaininfo->subband[nr_subband].nrchan = | ||
190 | nr_parsedchan; | ||
191 | domaininfo->subband[nr_subband].maxtxpwr = maxpwr; | ||
192 | nr_subband++; | ||
193 | nextchan = firstchan = | ||
194 | parsed_region_chan->chanpwr[i].chan; | ||
195 | maxpwr = parsed_region_chan->chanpwr[i].pwr; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | if (flag) { | ||
200 | domaininfo->subband[nr_subband].firstchan = firstchan; | ||
201 | domaininfo->subband[nr_subband].nrchan = nr_parsedchan; | ||
202 | domaininfo->subband[nr_subband].maxtxpwr = maxpwr; | ||
203 | nr_subband++; | ||
204 | } | ||
205 | domaininfo->nr_subband = nr_subband; | ||
206 | |||
207 | lbs_deb_11d("nr_subband=%x\n", domaininfo->nr_subband); | ||
208 | lbs_deb_hex(LBS_DEB_11D, "domaininfo", (char *)domaininfo, | ||
209 | COUNTRY_CODE_LEN + 1 + | ||
210 | sizeof(struct ieee_subbandset) * nr_subband); | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | /** | ||
215 | * @brief This function generates parsed_region_chan from Domain Info learned from AP/IBSS | ||
216 | * @param region_chan pointer to struct region_channel | ||
217 | * @param *parsed_region_chan pointer to parsed_region_chan_11d | ||
218 | * @return N/A | ||
219 | */ | ||
220 | static void lbs_generate_parsed_region_chan_11d(struct region_channel *region_chan, | ||
221 | struct parsed_region_chan_11d * | ||
222 | parsed_region_chan) | ||
223 | { | ||
224 | u8 i; | ||
225 | struct chan_freq_power *cfp; | ||
226 | |||
227 | if (region_chan == NULL) { | ||
228 | lbs_deb_11d("region_chan is NULL\n"); | ||
229 | return; | ||
230 | } | ||
231 | |||
232 | cfp = region_chan->CFP; | ||
233 | if (cfp == NULL) { | ||
234 | lbs_deb_11d("cfp is NULL \n"); | ||
235 | return; | ||
236 | } | ||
237 | |||
238 | parsed_region_chan->band = region_chan->band; | ||
239 | parsed_region_chan->region = region_chan->region; | ||
240 | memcpy(parsed_region_chan->countrycode, | ||
241 | lbs_code_2_region(region_chan->region), COUNTRY_CODE_LEN); | ||
242 | |||
243 | lbs_deb_11d("region 0x%x, band %d\n", parsed_region_chan->region, | ||
244 | parsed_region_chan->band); | ||
245 | |||
246 | for (i = 0; i < region_chan->nrcfp; i++, cfp++) { | ||
247 | parsed_region_chan->chanpwr[i].chan = cfp->channel; | ||
248 | parsed_region_chan->chanpwr[i].pwr = cfp->maxtxpower; | ||
249 | lbs_deb_11d("chan %d, pwr %d\n", | ||
250 | parsed_region_chan->chanpwr[i].chan, | ||
251 | parsed_region_chan->chanpwr[i].pwr); | ||
252 | } | ||
253 | parsed_region_chan->nr_chan = region_chan->nrcfp; | ||
254 | |||
255 | lbs_deb_11d("nrchan %d\n", parsed_region_chan->nr_chan); | ||
256 | |||
257 | return; | ||
258 | } | ||
259 | |||
260 | /** | ||
261 | * @brief generate parsed_region_chan from Domain Info learned from AP/IBSS | ||
262 | * @param region region ID | ||
263 | * @param band band | ||
264 | * @param chan chan | ||
265 | * @return TRUE;FALSE | ||
266 | */ | ||
267 | static u8 lbs_region_chan_supported_11d(u8 region, u8 chan) | ||
268 | { | ||
269 | struct chan_freq_power *cfp; | ||
270 | int cfp_no; | ||
271 | u8 idx; | ||
272 | int ret = 0; | ||
273 | |||
274 | lbs_deb_enter(LBS_DEB_11D); | ||
275 | |||
276 | cfp = lbs_get_region_cfp_table(region, &cfp_no); | ||
277 | if (cfp == NULL) | ||
278 | return 0; | ||
279 | |||
280 | for (idx = 0; idx < cfp_no; idx++) { | ||
281 | if (chan == (cfp + idx)->channel) { | ||
282 | /* If Mrvl Chip Supported? */ | ||
283 | if ((cfp + idx)->unsupported) { | ||
284 | ret = 0; | ||
285 | } else { | ||
286 | ret = 1; | ||
287 | } | ||
288 | goto done; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | /*chan is not in the region table */ | ||
293 | |||
294 | done: | ||
295 | lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); | ||
296 | return ret; | ||
297 | } | ||
298 | |||
299 | /** | ||
300 | * @brief This function checks if chan txpwr is learned from AP/IBSS | ||
301 | * @param chan chan number | ||
302 | * @param parsed_region_chan pointer to parsed_region_chan_11d | ||
303 | * @return 0 | ||
304 | */ | ||
305 | static int parse_domain_info_11d(struct ieee_ie_country_info_full_set *countryinfo, | ||
306 | u8 band, | ||
307 | struct parsed_region_chan_11d *parsed_region_chan) | ||
308 | { | ||
309 | u8 nr_subband, nrchan; | ||
310 | u8 lastchan, firstchan; | ||
311 | u8 region; | ||
312 | u8 curchan = 0; | ||
313 | |||
314 | u8 idx = 0; /*chan index in parsed_region_chan */ | ||
315 | |||
316 | u8 j, i; | ||
317 | |||
318 | lbs_deb_enter(LBS_DEB_11D); | ||
319 | |||
320 | /*validation Rules: | ||
321 | 1. valid region Code | ||
322 | 2. First Chan increment | ||
323 | 3. channel range no overlap | ||
324 | 4. channel is valid? | ||
325 | 5. channel is supported by region? | ||
326 | 6. Others | ||
327 | */ | ||
328 | |||
329 | lbs_deb_hex(LBS_DEB_11D, "countryinfo", (u8 *) countryinfo, 30); | ||
330 | |||
331 | if ((*(countryinfo->countrycode)) == 0 | ||
332 | || (countryinfo->header.len <= COUNTRY_CODE_LEN)) { | ||
333 | /* No region Info or Wrong region info: treat as No 11D info */ | ||
334 | goto done; | ||
335 | } | ||
336 | |||
337 | /*Step1: check region_code */ | ||
338 | parsed_region_chan->region = region = | ||
339 | lbs_region_2_code(countryinfo->countrycode); | ||
340 | |||
341 | lbs_deb_11d("regioncode=%x\n", (u8) parsed_region_chan->region); | ||
342 | lbs_deb_hex(LBS_DEB_11D, "countrycode", (char *)countryinfo->countrycode, | ||
343 | COUNTRY_CODE_LEN); | ||
344 | |||
345 | parsed_region_chan->band = band; | ||
346 | |||
347 | memcpy(parsed_region_chan->countrycode, countryinfo->countrycode, | ||
348 | COUNTRY_CODE_LEN); | ||
349 | |||
350 | nr_subband = (countryinfo->header.len - COUNTRY_CODE_LEN) / | ||
351 | sizeof(struct ieee_subbandset); | ||
352 | |||
353 | for (j = 0, lastchan = 0; j < nr_subband; j++) { | ||
354 | |||
355 | if (countryinfo->subband[j].firstchan <= lastchan) { | ||
356 | /*Step2&3. Check First Chan Num increment and no overlap */ | ||
357 | lbs_deb_11d("chan %d>%d, overlap\n", | ||
358 | countryinfo->subband[j].firstchan, lastchan); | ||
359 | continue; | ||
360 | } | ||
361 | |||
362 | firstchan = countryinfo->subband[j].firstchan; | ||
363 | nrchan = countryinfo->subband[j].nrchan; | ||
364 | |||
365 | for (i = 0; idx < MAX_NO_OF_CHAN && i < nrchan; i++) { | ||
366 | /*step4: channel is supported? */ | ||
367 | |||
368 | if (!lbs_get_chan_11d(firstchan, i, &curchan)) { | ||
369 | /* Chan is not found in UN table */ | ||
370 | lbs_deb_11d("chan is not supported: %d \n", i); | ||
371 | break; | ||
372 | } | ||
373 | |||
374 | lastchan = curchan; | ||
375 | |||
376 | if (lbs_region_chan_supported_11d(region, curchan)) { | ||
377 | /*step5: Check if curchan is supported by mrvl in region */ | ||
378 | parsed_region_chan->chanpwr[idx].chan = curchan; | ||
379 | parsed_region_chan->chanpwr[idx].pwr = | ||
380 | countryinfo->subband[j].maxtxpwr; | ||
381 | idx++; | ||
382 | } else { | ||
383 | /*not supported and ignore the chan */ | ||
384 | lbs_deb_11d( | ||
385 | "i %d, chan %d unsupported in region %x, band %d\n", | ||
386 | i, curchan, region, band); | ||
387 | } | ||
388 | } | ||
389 | |||
390 | /*Step6: Add other checking if any */ | ||
391 | |||
392 | } | ||
393 | |||
394 | parsed_region_chan->nr_chan = idx; | ||
395 | |||
396 | lbs_deb_11d("nrchan=%x\n", parsed_region_chan->nr_chan); | ||
397 | lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (u8 *) parsed_region_chan, | ||
398 | 2 + COUNTRY_CODE_LEN + sizeof(struct parsed_region_chan_11d) * idx); | ||
399 | |||
400 | done: | ||
401 | lbs_deb_enter(LBS_DEB_11D); | ||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | /** | ||
406 | * @brief This function calculates the scan type for channels | ||
407 | * @param chan chan number | ||
408 | * @param parsed_region_chan pointer to parsed_region_chan_11d | ||
409 | * @return PASSIVE if chan is unknown; ACTIVE if chan is known | ||
410 | */ | ||
411 | u8 lbs_get_scan_type_11d(u8 chan, | ||
412 | struct parsed_region_chan_11d * parsed_region_chan) | ||
413 | { | ||
414 | u8 scan_type = CMD_SCAN_TYPE_PASSIVE; | ||
415 | |||
416 | lbs_deb_enter(LBS_DEB_11D); | ||
417 | |||
418 | if (lbs_channel_known_11d(chan, parsed_region_chan)) { | ||
419 | lbs_deb_11d("found, do active scan\n"); | ||
420 | scan_type = CMD_SCAN_TYPE_ACTIVE; | ||
421 | } else { | ||
422 | lbs_deb_11d("not found, do passive scan\n"); | ||
423 | } | ||
424 | |||
425 | lbs_deb_leave_args(LBS_DEB_11D, "ret scan_type %d", scan_type); | ||
426 | return scan_type; | ||
427 | |||
428 | } | ||
429 | |||
430 | void lbs_init_11d(struct lbs_private *priv) | ||
431 | { | ||
432 | priv->enable11d = 0; | ||
433 | memset(&(priv->parsed_region_chan), 0, | ||
434 | sizeof(struct parsed_region_chan_11d)); | ||
435 | return; | ||
436 | } | ||
437 | |||
438 | /** | ||
439 | * @brief This function sets DOMAIN INFO to FW | ||
440 | * @param priv pointer to struct lbs_private | ||
441 | * @return 0; -1 | ||
442 | */ | ||
443 | static int set_domain_info_11d(struct lbs_private *priv) | ||
444 | { | ||
445 | int ret; | ||
446 | |||
447 | if (!priv->enable11d) { | ||
448 | lbs_deb_11d("dnld domain Info with 11d disabled\n"); | ||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | ret = lbs_prepare_and_send_command(priv, CMD_802_11D_DOMAIN_INFO, | ||
453 | CMD_ACT_SET, | ||
454 | CMD_OPTION_WAITFORRSP, 0, NULL); | ||
455 | if (ret) | ||
456 | lbs_deb_11d("fail to dnld domain info\n"); | ||
457 | |||
458 | return ret; | ||
459 | } | ||
460 | |||
461 | /** | ||
462 | * @brief This function setups scan channels | ||
463 | * @param priv pointer to struct lbs_private | ||
464 | * @param band band | ||
465 | * @return 0 | ||
466 | */ | ||
467 | int lbs_set_universaltable(struct lbs_private *priv, u8 band) | ||
468 | { | ||
469 | u16 size = sizeof(struct chan_freq_power); | ||
470 | u16 i = 0; | ||
471 | |||
472 | memset(priv->universal_channel, 0, | ||
473 | sizeof(priv->universal_channel)); | ||
474 | |||
475 | priv->universal_channel[i].nrcfp = | ||
476 | sizeof(channel_freq_power_UN_BG) / size; | ||
477 | lbs_deb_11d("BG-band nrcfp %d\n", | ||
478 | priv->universal_channel[i].nrcfp); | ||
479 | |||
480 | priv->universal_channel[i].CFP = channel_freq_power_UN_BG; | ||
481 | priv->universal_channel[i].valid = 1; | ||
482 | priv->universal_channel[i].region = UNIVERSAL_REGION_CODE; | ||
483 | priv->universal_channel[i].band = band; | ||
484 | i++; | ||
485 | |||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | /** | ||
490 | * @brief This function implements command CMD_802_11D_DOMAIN_INFO | ||
491 | * @param priv pointer to struct lbs_private | ||
492 | * @param cmd pointer to cmd buffer | ||
493 | * @param cmdno cmd ID | ||
494 | * @param cmdOption cmd action | ||
495 | * @return 0 | ||
496 | */ | ||
497 | int lbs_cmd_802_11d_domain_info(struct lbs_private *priv, | ||
498 | struct cmd_ds_command *cmd, u16 cmdno, | ||
499 | u16 cmdoption) | ||
500 | { | ||
501 | struct cmd_ds_802_11d_domain_info *pdomaininfo = | ||
502 | &cmd->params.domaininfo; | ||
503 | struct mrvl_ie_domain_param_set *domain = &pdomaininfo->domain; | ||
504 | u8 nr_subband = priv->domainreg.nr_subband; | ||
505 | |||
506 | lbs_deb_enter(LBS_DEB_11D); | ||
507 | |||
508 | lbs_deb_11d("nr_subband=%x\n", nr_subband); | ||
509 | |||
510 | cmd->command = cpu_to_le16(cmdno); | ||
511 | pdomaininfo->action = cpu_to_le16(cmdoption); | ||
512 | if (cmdoption == CMD_ACT_GET) { | ||
513 | cmd->size = | ||
514 | cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN); | ||
515 | lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd, | ||
516 | le16_to_cpu(cmd->size)); | ||
517 | goto done; | ||
518 | } | ||
519 | |||
520 | domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN); | ||
521 | memcpy(domain->countrycode, priv->domainreg.countrycode, | ||
522 | sizeof(domain->countrycode)); | ||
523 | |||
524 | domain->header.len = | ||
525 | cpu_to_le16(nr_subband * sizeof(struct ieee_subbandset) + | ||
526 | sizeof(domain->countrycode)); | ||
527 | |||
528 | if (nr_subband) { | ||
529 | memcpy(domain->subband, priv->domainreg.subband, | ||
530 | nr_subband * sizeof(struct ieee_subbandset)); | ||
531 | |||
532 | cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) + | ||
533 | le16_to_cpu(domain->header.len) + | ||
534 | sizeof(struct mrvl_ie_header) + | ||
535 | S_DS_GEN); | ||
536 | } else { | ||
537 | cmd->size = | ||
538 | cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN); | ||
539 | } | ||
540 | |||
541 | lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd, le16_to_cpu(cmd->size)); | ||
542 | |||
543 | done: | ||
544 | lbs_deb_enter(LBS_DEB_11D); | ||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | /** | ||
549 | * @brief This function parses countryinfo from AP and download country info to FW | ||
550 | * @param priv pointer to struct lbs_private | ||
551 | * @param resp pointer to command response buffer | ||
552 | * @return 0; -1 | ||
553 | */ | ||
554 | int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp) | ||
555 | { | ||
556 | struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp; | ||
557 | struct mrvl_ie_domain_param_set *domain = &domaininfo->domain; | ||
558 | u16 action = le16_to_cpu(domaininfo->action); | ||
559 | s16 ret = 0; | ||
560 | u8 nr_subband = 0; | ||
561 | |||
562 | lbs_deb_enter(LBS_DEB_11D); | ||
563 | |||
564 | lbs_deb_hex(LBS_DEB_11D, "domain info resp", (u8 *) resp, | ||
565 | (int)le16_to_cpu(resp->size)); | ||
566 | |||
567 | nr_subband = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) / | ||
568 | sizeof(struct ieee_subbandset); | ||
569 | |||
570 | lbs_deb_11d("domain info resp: nr_subband %d\n", nr_subband); | ||
571 | |||
572 | if (nr_subband > MRVDRV_MAX_SUBBAND_802_11D) { | ||
573 | lbs_deb_11d("Invalid Numrer of Subband returned!!\n"); | ||
574 | return -1; | ||
575 | } | ||
576 | |||
577 | switch (action) { | ||
578 | case CMD_ACT_SET: /*Proc Set action */ | ||
579 | break; | ||
580 | |||
581 | case CMD_ACT_GET: | ||
582 | break; | ||
583 | default: | ||
584 | lbs_deb_11d("Invalid action:%d\n", domaininfo->action); | ||
585 | ret = -1; | ||
586 | break; | ||
587 | } | ||
588 | |||
589 | lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); | ||
590 | return ret; | ||
591 | } | ||
592 | |||
593 | /** | ||
594 | * @brief This function parses countryinfo from AP and download country info to FW | ||
595 | * @param priv pointer to struct lbs_private | ||
596 | * @return 0; -1 | ||
597 | */ | ||
598 | int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv, | ||
599 | struct bss_descriptor * bss) | ||
600 | { | ||
601 | int ret; | ||
602 | |||
603 | lbs_deb_enter(LBS_DEB_11D); | ||
604 | if (priv->enable11d) { | ||
605 | memset(&priv->parsed_region_chan, 0, | ||
606 | sizeof(struct parsed_region_chan_11d)); | ||
607 | ret = parse_domain_info_11d(&bss->countryinfo, 0, | ||
608 | &priv->parsed_region_chan); | ||
609 | |||
610 | if (ret == -1) { | ||
611 | lbs_deb_11d("error parsing domain_info from AP\n"); | ||
612 | goto done; | ||
613 | } | ||
614 | |||
615 | memset(&priv->domainreg, 0, | ||
616 | sizeof(struct lbs_802_11d_domain_reg)); | ||
617 | generate_domain_info_11d(&priv->parsed_region_chan, | ||
618 | &priv->domainreg); | ||
619 | |||
620 | ret = set_domain_info_11d(priv); | ||
621 | |||
622 | if (ret) { | ||
623 | lbs_deb_11d("error setting domain info\n"); | ||
624 | goto done; | ||
625 | } | ||
626 | } | ||
627 | ret = 0; | ||
628 | |||
629 | done: | ||
630 | lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); | ||
631 | return ret; | ||
632 | } | ||
633 | |||
634 | /** | ||
635 | * @brief This function generates 11D info from user specified regioncode and download to FW | ||
636 | * @param priv pointer to struct lbs_private | ||
637 | * @return 0; -1 | ||
638 | */ | ||
639 | int lbs_create_dnld_countryinfo_11d(struct lbs_private *priv) | ||
640 | { | ||
641 | int ret; | ||
642 | struct region_channel *region_chan; | ||
643 | u8 j; | ||
644 | |||
645 | lbs_deb_enter(LBS_DEB_11D); | ||
646 | lbs_deb_11d("curbssparams.band %d\n", priv->curbssparams.band); | ||
647 | |||
648 | if (priv->enable11d) { | ||
649 | /* update parsed_region_chan_11; dnld domaininf to FW */ | ||
650 | |||
651 | for (j = 0; j < ARRAY_SIZE(priv->region_channel); j++) { | ||
652 | region_chan = &priv->region_channel[j]; | ||
653 | |||
654 | lbs_deb_11d("%d region_chan->band %d\n", j, | ||
655 | region_chan->band); | ||
656 | |||
657 | if (!region_chan || !region_chan->valid | ||
658 | || !region_chan->CFP) | ||
659 | continue; | ||
660 | if (region_chan->band != priv->curbssparams.band) | ||
661 | continue; | ||
662 | break; | ||
663 | } | ||
664 | |||
665 | if (j >= ARRAY_SIZE(priv->region_channel)) { | ||
666 | lbs_deb_11d("region_chan not found, band %d\n", | ||
667 | priv->curbssparams.band); | ||
668 | ret = -1; | ||
669 | goto done; | ||
670 | } | ||
671 | |||
672 | memset(&priv->parsed_region_chan, 0, | ||
673 | sizeof(struct parsed_region_chan_11d)); | ||
674 | lbs_generate_parsed_region_chan_11d(region_chan, | ||
675 | &priv-> | ||
676 | parsed_region_chan); | ||
677 | |||
678 | memset(&priv->domainreg, 0, | ||
679 | sizeof(struct lbs_802_11d_domain_reg)); | ||
680 | generate_domain_info_11d(&priv->parsed_region_chan, | ||
681 | &priv->domainreg); | ||
682 | |||
683 | ret = set_domain_info_11d(priv); | ||
684 | |||
685 | if (ret) { | ||
686 | lbs_deb_11d("error setting domain info\n"); | ||
687 | goto done; | ||
688 | } | ||
689 | |||
690 | } | ||
691 | ret = 0; | ||
692 | |||
693 | done: | ||
694 | lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); | ||
695 | return ret; | ||
696 | } | ||
diff --git a/drivers/net/wireless/libertas/11d.h b/drivers/net/wireless/libertas/11d.h deleted file mode 100644 index fb75d3e321a0..000000000000 --- a/drivers/net/wireless/libertas/11d.h +++ /dev/null | |||
@@ -1,105 +0,0 @@ | |||
1 | /** | ||
2 | * This header file contains data structures and | ||
3 | * function declarations of 802.11d | ||
4 | */ | ||
5 | #ifndef _LBS_11D_ | ||
6 | #define _LBS_11D_ | ||
7 | |||
8 | #include "types.h" | ||
9 | #include "defs.h" | ||
10 | |||
11 | #define UNIVERSAL_REGION_CODE 0xff | ||
12 | |||
13 | /** (Beaconsize(256)-5(IEId,len,contrystr(3))/3(FirstChan,NoOfChan,MaxPwr) | ||
14 | */ | ||
15 | #define MRVDRV_MAX_SUBBAND_802_11D 83 | ||
16 | |||
17 | #define COUNTRY_CODE_LEN 3 | ||
18 | #define MAX_NO_OF_CHAN 40 | ||
19 | |||
20 | struct cmd_ds_command; | ||
21 | |||
22 | /** Data structure for Country IE*/ | ||
23 | struct ieee_subbandset { | ||
24 | u8 firstchan; | ||
25 | u8 nrchan; | ||
26 | u8 maxtxpwr; | ||
27 | } __attribute__ ((packed)); | ||
28 | |||
29 | struct ieee_ie_country_info_set { | ||
30 | struct ieee_ie_header header; | ||
31 | |||
32 | u8 countrycode[COUNTRY_CODE_LEN]; | ||
33 | struct ieee_subbandset subband[1]; | ||
34 | }; | ||
35 | |||
36 | struct ieee_ie_country_info_full_set { | ||
37 | struct ieee_ie_header header; | ||
38 | |||
39 | u8 countrycode[COUNTRY_CODE_LEN]; | ||
40 | struct ieee_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D]; | ||
41 | } __attribute__ ((packed)); | ||
42 | |||
43 | struct mrvl_ie_domain_param_set { | ||
44 | struct mrvl_ie_header header; | ||
45 | |||
46 | u8 countrycode[COUNTRY_CODE_LEN]; | ||
47 | struct ieee_subbandset subband[1]; | ||
48 | } __attribute__ ((packed)); | ||
49 | |||
50 | struct cmd_ds_802_11d_domain_info { | ||
51 | __le16 action; | ||
52 | struct mrvl_ie_domain_param_set domain; | ||
53 | } __attribute__ ((packed)); | ||
54 | |||
55 | /** domain regulatory information */ | ||
56 | struct lbs_802_11d_domain_reg { | ||
57 | /** country Code*/ | ||
58 | u8 countrycode[COUNTRY_CODE_LEN]; | ||
59 | /** No. of subband*/ | ||
60 | u8 nr_subband; | ||
61 | struct ieee_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D]; | ||
62 | }; | ||
63 | |||
64 | struct chan_power_11d { | ||
65 | u8 chan; | ||
66 | u8 pwr; | ||
67 | } __attribute__ ((packed)); | ||
68 | |||
69 | struct parsed_region_chan_11d { | ||
70 | u8 band; | ||
71 | u8 region; | ||
72 | s8 countrycode[COUNTRY_CODE_LEN]; | ||
73 | struct chan_power_11d chanpwr[MAX_NO_OF_CHAN]; | ||
74 | u8 nr_chan; | ||
75 | } __attribute__ ((packed)); | ||
76 | |||
77 | struct region_code_mapping { | ||
78 | u8 region[COUNTRY_CODE_LEN]; | ||
79 | u8 code; | ||
80 | }; | ||
81 | |||
82 | struct lbs_private; | ||
83 | |||
84 | u8 lbs_get_scan_type_11d(u8 chan, | ||
85 | struct parsed_region_chan_11d *parsed_region_chan); | ||
86 | |||
87 | u32 lbs_chan_2_freq(u8 chan); | ||
88 | |||
89 | void lbs_init_11d(struct lbs_private *priv); | ||
90 | |||
91 | int lbs_set_universaltable(struct lbs_private *priv, u8 band); | ||
92 | |||
93 | int lbs_cmd_802_11d_domain_info(struct lbs_private *priv, | ||
94 | struct cmd_ds_command *cmd, u16 cmdno, | ||
95 | u16 cmdOption); | ||
96 | |||
97 | int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp); | ||
98 | |||
99 | struct bss_descriptor; | ||
100 | int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv, | ||
101 | struct bss_descriptor * bss); | ||
102 | |||
103 | int lbs_create_dnld_countryinfo_11d(struct lbs_private *priv); | ||
104 | |||
105 | #endif | ||
diff --git a/drivers/net/wireless/libertas/Kconfig b/drivers/net/wireless/libertas/Kconfig new file mode 100644 index 000000000000..0485c9957575 --- /dev/null +++ b/drivers/net/wireless/libertas/Kconfig | |||
@@ -0,0 +1,45 @@ | |||
1 | config LIBERTAS | ||
2 | tristate "Marvell 8xxx Libertas WLAN driver support" | ||
3 | depends on CFG80211 | ||
4 | select WIRELESS_EXT | ||
5 | select WEXT_SPY | ||
6 | select LIB80211 | ||
7 | select FW_LOADER | ||
8 | ---help--- | ||
9 | A library for Marvell Libertas 8xxx devices. | ||
10 | |||
11 | config LIBERTAS_USB | ||
12 | tristate "Marvell Libertas 8388 USB 802.11b/g cards" | ||
13 | depends on LIBERTAS && USB | ||
14 | ---help--- | ||
15 | A driver for Marvell Libertas 8388 USB devices. | ||
16 | |||
17 | config LIBERTAS_CS | ||
18 | tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards" | ||
19 | depends on LIBERTAS && PCMCIA | ||
20 | ---help--- | ||
21 | A driver for Marvell Libertas 8385 CompactFlash devices. | ||
22 | |||
23 | config LIBERTAS_SDIO | ||
24 | tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards" | ||
25 | depends on LIBERTAS && MMC | ||
26 | ---help--- | ||
27 | A driver for Marvell Libertas 8385/8686/8688 SDIO devices. | ||
28 | |||
29 | config LIBERTAS_SPI | ||
30 | tristate "Marvell Libertas 8686 SPI 802.11b/g cards" | ||
31 | depends on LIBERTAS && SPI | ||
32 | ---help--- | ||
33 | A driver for Marvell Libertas 8686 SPI devices. | ||
34 | |||
35 | config LIBERTAS_DEBUG | ||
36 | bool "Enable full debugging output in the Libertas module." | ||
37 | depends on LIBERTAS | ||
38 | ---help--- | ||
39 | Debugging support. | ||
40 | |||
41 | config LIBERTAS_MESH | ||
42 | bool "Enable mesh support" | ||
43 | depends on LIBERTAS | ||
44 | help | ||
45 | This enables Libertas' MESH support, used by e.g. the OLPC people. | ||
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile index 0b6918584503..45e870e33117 100644 --- a/drivers/net/wireless/libertas/Makefile +++ b/drivers/net/wireless/libertas/Makefile | |||
@@ -1,5 +1,15 @@ | |||
1 | libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o \ | 1 | libertas-y += assoc.o |
2 | debugfs.o persistcfg.o ethtool.o assoc.o | 2 | libertas-y += cfg.o |
3 | libertas-y += cmd.o | ||
4 | libertas-y += cmdresp.o | ||
5 | libertas-y += debugfs.o | ||
6 | libertas-y += ethtool.o | ||
7 | libertas-y += main.o | ||
8 | libertas-y += rx.o | ||
9 | libertas-y += scan.o | ||
10 | libertas-y += tx.o | ||
11 | libertas-y += wext.o | ||
12 | libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o | ||
3 | 13 | ||
4 | usb8xxx-objs += if_usb.o | 14 | usb8xxx-objs += if_usb.o |
5 | libertas_cs-objs += if_cs.o | 15 | libertas_cs-objs += if_cs.o |
diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README index ab6a2d518af0..2726c044430f 100644 --- a/drivers/net/wireless/libertas/README +++ b/drivers/net/wireless/libertas/README | |||
@@ -1,5 +1,5 @@ | |||
1 | ================================================================================ | 1 | ================================================================================ |
2 | README for USB8388 | 2 | README for Libertas |
3 | 3 | ||
4 | (c) Copyright © 2003-2006, Marvell International Ltd. | 4 | (c) Copyright © 2003-2006, Marvell International Ltd. |
5 | All Rights Reserved | 5 | All Rights Reserved |
@@ -226,4 +226,28 @@ setuserscan | |||
226 | All entries in the scan table (not just the new scan data when keep=1) | 226 | All entries in the scan table (not just the new scan data when keep=1) |
227 | will be displayed upon completion by use of the getscantable ioctl. | 227 | will be displayed upon completion by use of the getscantable ioctl. |
228 | 228 | ||
229 | ======================== | ||
230 | IWCONFIG COMMANDS | ||
231 | ======================== | ||
232 | power period | ||
233 | |||
234 | This command is used to configure the station in deep sleep mode / | ||
235 | auto deep sleep mode. | ||
236 | |||
237 | The timer is implemented to monitor the activities (command, event, | ||
238 | etc.). When an activity is detected station will exit from deep | ||
239 | sleep mode automatically and restart the timer. At timer expiry | ||
240 | (no activity for defined time period) the deep sleep mode is entered | ||
241 | automatically. | ||
242 | |||
243 | Note: this command is for SDIO interface only. | ||
244 | |||
245 | Usage: | ||
246 | To enable deep sleep mode do: | ||
247 | iwconfig wlan0 power period 0 | ||
248 | To enable auto deep sleep mode with idle time period 5 seconds do: | ||
249 | iwconfig wlan0 power period 5 | ||
250 | To disable deep sleep/auto deep sleep mode do: | ||
251 | iwconfig wlan0 power period -1 | ||
252 | |||
229 | ============================================================================== | 253 | ============================================================================== |
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index dd8732611ba9..12a2ef9dacea 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/etherdevice.h> | 4 | #include <linux/etherdevice.h> |
5 | #include <linux/ieee80211.h> | 5 | #include <linux/ieee80211.h> |
6 | #include <linux/if_arp.h> | 6 | #include <linux/if_arp.h> |
7 | #include <linux/slab.h> | ||
7 | #include <net/lib80211.h> | 8 | #include <net/lib80211.h> |
8 | 9 | ||
9 | #include "assoc.h" | 10 | #include "assoc.h" |
@@ -23,6 +24,13 @@ static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) = | |||
23 | */ | 24 | */ |
24 | #define CAPINFO_MASK (~(0xda00)) | 25 | #define CAPINFO_MASK (~(0xda00)) |
25 | 26 | ||
27 | /** | ||
28 | * 802.11b/g supported bitrates (in 500Kb/s units) | ||
29 | */ | ||
30 | u8 lbs_bg_rates[MAX_RATES] = | ||
31 | { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, | ||
32 | 0x00, 0x00 }; | ||
33 | |||
26 | 34 | ||
27 | /** | 35 | /** |
28 | * @brief This function finds common rates between rates and card rates. | 36 | * @brief This function finds common rates between rates and card rates. |
@@ -147,6 +155,395 @@ static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth | |||
147 | } | 155 | } |
148 | 156 | ||
149 | 157 | ||
158 | int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, | ||
159 | struct assoc_request *assoc) | ||
160 | { | ||
161 | struct cmd_ds_802_11_set_wep cmd; | ||
162 | int ret = 0; | ||
163 | |||
164 | lbs_deb_enter(LBS_DEB_CMD); | ||
165 | |||
166 | memset(&cmd, 0, sizeof(cmd)); | ||
167 | cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP); | ||
168 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
169 | |||
170 | cmd.action = cpu_to_le16(cmd_action); | ||
171 | |||
172 | if (cmd_action == CMD_ACT_ADD) { | ||
173 | int i; | ||
174 | |||
175 | /* default tx key index */ | ||
176 | cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx & | ||
177 | CMD_WEP_KEY_INDEX_MASK); | ||
178 | |||
179 | /* Copy key types and material to host command structure */ | ||
180 | for (i = 0; i < 4; i++) { | ||
181 | struct enc_key *pkey = &assoc->wep_keys[i]; | ||
182 | |||
183 | switch (pkey->len) { | ||
184 | case KEY_LEN_WEP_40: | ||
185 | cmd.keytype[i] = CMD_TYPE_WEP_40_BIT; | ||
186 | memmove(cmd.keymaterial[i], pkey->key, pkey->len); | ||
187 | lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i); | ||
188 | break; | ||
189 | case KEY_LEN_WEP_104: | ||
190 | cmd.keytype[i] = CMD_TYPE_WEP_104_BIT; | ||
191 | memmove(cmd.keymaterial[i], pkey->key, pkey->len); | ||
192 | lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i); | ||
193 | break; | ||
194 | case 0: | ||
195 | break; | ||
196 | default: | ||
197 | lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n", | ||
198 | i, pkey->len); | ||
199 | ret = -1; | ||
200 | goto done; | ||
201 | break; | ||
202 | } | ||
203 | } | ||
204 | } else if (cmd_action == CMD_ACT_REMOVE) { | ||
205 | /* ACT_REMOVE clears _all_ WEP keys */ | ||
206 | |||
207 | /* default tx key index */ | ||
208 | cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx & | ||
209 | CMD_WEP_KEY_INDEX_MASK); | ||
210 | lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx); | ||
211 | } | ||
212 | |||
213 | ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd); | ||
214 | done: | ||
215 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, | ||
220 | uint16_t *enable) | ||
221 | { | ||
222 | struct cmd_ds_802_11_enable_rsn cmd; | ||
223 | int ret; | ||
224 | |||
225 | lbs_deb_enter(LBS_DEB_CMD); | ||
226 | |||
227 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
228 | cmd.action = cpu_to_le16(cmd_action); | ||
229 | |||
230 | if (cmd_action == CMD_ACT_GET) | ||
231 | cmd.enable = 0; | ||
232 | else { | ||
233 | if (*enable) | ||
234 | cmd.enable = cpu_to_le16(CMD_ENABLE_RSN); | ||
235 | else | ||
236 | cmd.enable = cpu_to_le16(CMD_DISABLE_RSN); | ||
237 | lbs_deb_cmd("ENABLE_RSN: %d\n", *enable); | ||
238 | } | ||
239 | |||
240 | ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd); | ||
241 | if (!ret && cmd_action == CMD_ACT_GET) | ||
242 | *enable = le16_to_cpu(cmd.enable); | ||
243 | |||
244 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
245 | return ret; | ||
246 | } | ||
247 | |||
248 | static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam, | ||
249 | struct enc_key *key) | ||
250 | { | ||
251 | lbs_deb_enter(LBS_DEB_CMD); | ||
252 | |||
253 | if (key->flags & KEY_INFO_WPA_ENABLED) | ||
254 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED); | ||
255 | if (key->flags & KEY_INFO_WPA_UNICAST) | ||
256 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST); | ||
257 | if (key->flags & KEY_INFO_WPA_MCAST) | ||
258 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST); | ||
259 | |||
260 | keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL); | ||
261 | keyparam->keytypeid = cpu_to_le16(key->type); | ||
262 | keyparam->keylen = cpu_to_le16(key->len); | ||
263 | memcpy(keyparam->key, key->key, key->len); | ||
264 | |||
265 | /* Length field doesn't include the {type,length} header */ | ||
266 | keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4); | ||
267 | lbs_deb_leave(LBS_DEB_CMD); | ||
268 | } | ||
269 | |||
270 | int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, | ||
271 | struct assoc_request *assoc) | ||
272 | { | ||
273 | struct cmd_ds_802_11_key_material cmd; | ||
274 | int ret = 0; | ||
275 | int index = 0; | ||
276 | |||
277 | lbs_deb_enter(LBS_DEB_CMD); | ||
278 | |||
279 | cmd.action = cpu_to_le16(cmd_action); | ||
280 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
281 | |||
282 | if (cmd_action == CMD_ACT_GET) { | ||
283 | cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_header) + 2); | ||
284 | } else { | ||
285 | memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet)); | ||
286 | |||
287 | if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) { | ||
288 | set_one_wpa_key(&cmd.keyParamSet[index], | ||
289 | &assoc->wpa_unicast_key); | ||
290 | index++; | ||
291 | } | ||
292 | |||
293 | if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) { | ||
294 | set_one_wpa_key(&cmd.keyParamSet[index], | ||
295 | &assoc->wpa_mcast_key); | ||
296 | index++; | ||
297 | } | ||
298 | |||
299 | /* The common header and as many keys as we included */ | ||
300 | cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd), | ||
301 | keyParamSet[index])); | ||
302 | } | ||
303 | ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd); | ||
304 | /* Copy the returned key to driver private data */ | ||
305 | if (!ret && cmd_action == CMD_ACT_GET) { | ||
306 | void *buf_ptr = cmd.keyParamSet; | ||
307 | void *resp_end = &(&cmd)[1]; | ||
308 | |||
309 | while (buf_ptr < resp_end) { | ||
310 | struct MrvlIEtype_keyParamSet *keyparam = buf_ptr; | ||
311 | struct enc_key *key; | ||
312 | uint16_t param_set_len = le16_to_cpu(keyparam->length); | ||
313 | uint16_t key_len = le16_to_cpu(keyparam->keylen); | ||
314 | uint16_t key_flags = le16_to_cpu(keyparam->keyinfo); | ||
315 | uint16_t key_type = le16_to_cpu(keyparam->keytypeid); | ||
316 | void *end; | ||
317 | |||
318 | end = (void *)keyparam + sizeof(keyparam->type) | ||
319 | + sizeof(keyparam->length) + param_set_len; | ||
320 | |||
321 | /* Make sure we don't access past the end of the IEs */ | ||
322 | if (end > resp_end) | ||
323 | break; | ||
324 | |||
325 | if (key_flags & KEY_INFO_WPA_UNICAST) | ||
326 | key = &priv->wpa_unicast_key; | ||
327 | else if (key_flags & KEY_INFO_WPA_MCAST) | ||
328 | key = &priv->wpa_mcast_key; | ||
329 | else | ||
330 | break; | ||
331 | |||
332 | /* Copy returned key into driver */ | ||
333 | memset(key, 0, sizeof(struct enc_key)); | ||
334 | if (key_len > sizeof(key->key)) | ||
335 | break; | ||
336 | key->type = key_type; | ||
337 | key->flags = key_flags; | ||
338 | key->len = key_len; | ||
339 | memcpy(key->key, keyparam->key, key->len); | ||
340 | |||
341 | buf_ptr = end + 1; | ||
342 | } | ||
343 | } | ||
344 | |||
345 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
346 | return ret; | ||
347 | } | ||
348 | |||
349 | static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok) | ||
350 | { | ||
351 | /* Bit Rate | ||
352 | * 15:13 Reserved | ||
353 | * 12 54 Mbps | ||
354 | * 11 48 Mbps | ||
355 | * 10 36 Mbps | ||
356 | * 9 24 Mbps | ||
357 | * 8 18 Mbps | ||
358 | * 7 12 Mbps | ||
359 | * 6 9 Mbps | ||
360 | * 5 6 Mbps | ||
361 | * 4 Reserved | ||
362 | * 3 11 Mbps | ||
363 | * 2 5.5 Mbps | ||
364 | * 1 2 Mbps | ||
365 | * 0 1 Mbps | ||
366 | **/ | ||
367 | |||
368 | uint16_t ratemask; | ||
369 | int i = lbs_data_rate_to_fw_index(rate); | ||
370 | if (lower_rates_ok) | ||
371 | ratemask = (0x1fef >> (12 - i)); | ||
372 | else | ||
373 | ratemask = (1 << i); | ||
374 | return cpu_to_le16(ratemask); | ||
375 | } | ||
376 | |||
377 | int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, | ||
378 | uint16_t cmd_action) | ||
379 | { | ||
380 | struct cmd_ds_802_11_rate_adapt_rateset cmd; | ||
381 | int ret; | ||
382 | |||
383 | lbs_deb_enter(LBS_DEB_CMD); | ||
384 | |||
385 | if (!priv->cur_rate && !priv->enablehwauto) | ||
386 | return -EINVAL; | ||
387 | |||
388 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
389 | |||
390 | cmd.action = cpu_to_le16(cmd_action); | ||
391 | cmd.enablehwauto = cpu_to_le16(priv->enablehwauto); | ||
392 | cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto); | ||
393 | ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd); | ||
394 | if (!ret && cmd_action == CMD_ACT_GET) | ||
395 | priv->enablehwauto = le16_to_cpu(cmd.enablehwauto); | ||
396 | |||
397 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
398 | return ret; | ||
399 | } | ||
400 | |||
401 | /** | ||
402 | * @brief Set the data rate | ||
403 | * | ||
404 | * @param priv A pointer to struct lbs_private structure | ||
405 | * @param rate The desired data rate, or 0 to clear a locked rate | ||
406 | * | ||
407 | * @return 0 on success, error on failure | ||
408 | */ | ||
409 | int lbs_set_data_rate(struct lbs_private *priv, u8 rate) | ||
410 | { | ||
411 | struct cmd_ds_802_11_data_rate cmd; | ||
412 | int ret = 0; | ||
413 | |||
414 | lbs_deb_enter(LBS_DEB_CMD); | ||
415 | |||
416 | memset(&cmd, 0, sizeof(cmd)); | ||
417 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
418 | |||
419 | if (rate > 0) { | ||
420 | cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE); | ||
421 | cmd.rates[0] = lbs_data_rate_to_fw_index(rate); | ||
422 | if (cmd.rates[0] == 0) { | ||
423 | lbs_deb_cmd("DATA_RATE: invalid requested rate of" | ||
424 | " 0x%02X\n", rate); | ||
425 | ret = 0; | ||
426 | goto out; | ||
427 | } | ||
428 | lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]); | ||
429 | } else { | ||
430 | cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO); | ||
431 | lbs_deb_cmd("DATA_RATE: setting auto\n"); | ||
432 | } | ||
433 | |||
434 | ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd); | ||
435 | if (ret) | ||
436 | goto out; | ||
437 | |||
438 | lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof(cmd)); | ||
439 | |||
440 | /* FIXME: get actual rates FW can do if this command actually returns | ||
441 | * all data rates supported. | ||
442 | */ | ||
443 | priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]); | ||
444 | lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate); | ||
445 | |||
446 | out: | ||
447 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
448 | return ret; | ||
449 | } | ||
450 | |||
451 | |||
452 | int lbs_cmd_802_11_rssi(struct lbs_private *priv, | ||
453 | struct cmd_ds_command *cmd) | ||
454 | { | ||
455 | |||
456 | lbs_deb_enter(LBS_DEB_CMD); | ||
457 | cmd->command = cpu_to_le16(CMD_802_11_RSSI); | ||
458 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + | ||
459 | sizeof(struct cmd_header)); | ||
460 | cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR); | ||
461 | |||
462 | /* reset Beacon SNR/NF/RSSI values */ | ||
463 | priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
464 | priv->SNR[TYPE_BEACON][TYPE_AVG] = 0; | ||
465 | priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
466 | priv->NF[TYPE_BEACON][TYPE_AVG] = 0; | ||
467 | priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
468 | priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0; | ||
469 | |||
470 | lbs_deb_leave(LBS_DEB_CMD); | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | int lbs_ret_802_11_rssi(struct lbs_private *priv, | ||
475 | struct cmd_ds_command *resp) | ||
476 | { | ||
477 | struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp; | ||
478 | |||
479 | lbs_deb_enter(LBS_DEB_CMD); | ||
480 | |||
481 | /* store the non average value */ | ||
482 | priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR); | ||
483 | priv->NF[TYPE_BEACON][TYPE_NOAVG] = | ||
484 | get_unaligned_le16(&rssirsp->noisefloor); | ||
485 | |||
486 | priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR); | ||
487 | priv->NF[TYPE_BEACON][TYPE_AVG] = | ||
488 | get_unaligned_le16(&rssirsp->avgnoisefloor); | ||
489 | |||
490 | priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = | ||
491 | CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG], | ||
492 | priv->NF[TYPE_BEACON][TYPE_NOAVG]); | ||
493 | |||
494 | priv->RSSI[TYPE_BEACON][TYPE_AVG] = | ||
495 | CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE, | ||
496 | priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE); | ||
497 | |||
498 | lbs_deb_cmd("RSSI: beacon %d, avg %d\n", | ||
499 | priv->RSSI[TYPE_BEACON][TYPE_NOAVG], | ||
500 | priv->RSSI[TYPE_BEACON][TYPE_AVG]); | ||
501 | |||
502 | lbs_deb_leave(LBS_DEB_CMD); | ||
503 | return 0; | ||
504 | } | ||
505 | |||
506 | |||
507 | int lbs_cmd_bcn_ctrl(struct lbs_private *priv, | ||
508 | struct cmd_ds_command *cmd, | ||
509 | u16 cmd_action) | ||
510 | { | ||
511 | struct cmd_ds_802_11_beacon_control | ||
512 | *bcn_ctrl = &cmd->params.bcn_ctrl; | ||
513 | |||
514 | lbs_deb_enter(LBS_DEB_CMD); | ||
515 | cmd->size = | ||
516 | cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control) | ||
517 | + sizeof(struct cmd_header)); | ||
518 | cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL); | ||
519 | |||
520 | bcn_ctrl->action = cpu_to_le16(cmd_action); | ||
521 | bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable); | ||
522 | bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period); | ||
523 | |||
524 | lbs_deb_leave(LBS_DEB_CMD); | ||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv, | ||
529 | struct cmd_ds_command *resp) | ||
530 | { | ||
531 | struct cmd_ds_802_11_beacon_control *bcn_ctrl = | ||
532 | &resp->params.bcn_ctrl; | ||
533 | |||
534 | lbs_deb_enter(LBS_DEB_CMD); | ||
535 | |||
536 | if (bcn_ctrl->action == CMD_ACT_GET) { | ||
537 | priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable); | ||
538 | priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period); | ||
539 | } | ||
540 | |||
541 | lbs_deb_enter(LBS_DEB_CMD); | ||
542 | return 0; | ||
543 | } | ||
544 | |||
545 | |||
546 | |||
150 | static int lbs_assoc_post(struct lbs_private *priv, | 547 | static int lbs_assoc_post(struct lbs_private *priv, |
151 | struct cmd_ds_802_11_associate_response *resp) | 548 | struct cmd_ds_802_11_associate_response *resp) |
152 | { | 549 | { |
@@ -226,7 +623,7 @@ static int lbs_assoc_post(struct lbs_private *priv, | |||
226 | priv->connect_status = LBS_CONNECTED; | 623 | priv->connect_status = LBS_CONNECTED; |
227 | 624 | ||
228 | /* Update current SSID and BSSID */ | 625 | /* Update current SSID and BSSID */ |
229 | memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); | 626 | memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN); |
230 | priv->curbssparams.ssid_len = bss->ssid_len; | 627 | priv->curbssparams.ssid_len = bss->ssid_len; |
231 | memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); | 628 | memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); |
232 | 629 | ||
@@ -369,12 +766,7 @@ static int lbs_associate(struct lbs_private *priv, | |||
369 | (u16)(pos - (u8 *) &cmd.iebuf)); | 766 | (u16)(pos - (u8 *) &cmd.iebuf)); |
370 | 767 | ||
371 | /* update curbssparams */ | 768 | /* update curbssparams */ |
372 | priv->curbssparams.channel = bss->phy.ds.channel; | 769 | priv->channel = bss->phy.ds.channel; |
373 | |||
374 | if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { | ||
375 | ret = -1; | ||
376 | goto done; | ||
377 | } | ||
378 | 770 | ||
379 | ret = lbs_cmd_with_response(priv, command, &cmd); | 771 | ret = lbs_cmd_with_response(priv, command, &cmd); |
380 | if (ret == 0) { | 772 | if (ret == 0) { |
@@ -414,8 +806,7 @@ static int lbs_try_associate(struct lbs_private *priv, | |||
414 | } | 806 | } |
415 | 807 | ||
416 | /* Use short preamble only when both the BSS and firmware support it */ | 808 | /* Use short preamble only when both the BSS and firmware support it */ |
417 | if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && | 809 | if (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) |
418 | (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) | ||
419 | preamble = RADIO_PREAMBLE_SHORT; | 810 | preamble = RADIO_PREAMBLE_SHORT; |
420 | 811 | ||
421 | ret = lbs_set_radio(priv, preamble, 1); | 812 | ret = lbs_set_radio(priv, preamble, 1); |
@@ -472,7 +863,7 @@ static int lbs_adhoc_post(struct lbs_private *priv, | |||
472 | memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN); | 863 | memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN); |
473 | 864 | ||
474 | /* Set the new SSID to current SSID */ | 865 | /* Set the new SSID to current SSID */ |
475 | memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); | 866 | memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN); |
476 | priv->curbssparams.ssid_len = bss->ssid_len; | 867 | priv->curbssparams.ssid_len = bss->ssid_len; |
477 | 868 | ||
478 | netif_carrier_on(priv->dev); | 869 | netif_carrier_on(priv->dev); |
@@ -487,7 +878,7 @@ static int lbs_adhoc_post(struct lbs_private *priv, | |||
487 | lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n", | 878 | lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n", |
488 | print_ssid(ssid, bss->ssid, bss->ssid_len), | 879 | print_ssid(ssid, bss->ssid, bss->ssid_len), |
489 | priv->curbssparams.bssid, | 880 | priv->curbssparams.bssid, |
490 | priv->curbssparams.channel); | 881 | priv->channel); |
491 | 882 | ||
492 | done: | 883 | done: |
493 | lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); | 884 | lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); |
@@ -546,8 +937,7 @@ static int lbs_adhoc_join(struct lbs_private *priv, | |||
546 | } | 937 | } |
547 | 938 | ||
548 | /* Use short preamble only when both the BSS and firmware support it */ | 939 | /* Use short preamble only when both the BSS and firmware support it */ |
549 | if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && | 940 | if (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { |
550 | (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) { | ||
551 | lbs_deb_join("AdhocJoin: Short preamble\n"); | 941 | lbs_deb_join("AdhocJoin: Short preamble\n"); |
552 | preamble = RADIO_PREAMBLE_SHORT; | 942 | preamble = RADIO_PREAMBLE_SHORT; |
553 | } | 943 | } |
@@ -560,7 +950,7 @@ static int lbs_adhoc_join(struct lbs_private *priv, | |||
560 | lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band); | 950 | lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band); |
561 | 951 | ||
562 | priv->adhoccreate = 0; | 952 | priv->adhoccreate = 0; |
563 | priv->curbssparams.channel = bss->channel; | 953 | priv->channel = bss->channel; |
564 | 954 | ||
565 | /* Build the join command */ | 955 | /* Build the join command */ |
566 | memset(&cmd, 0, sizeof(cmd)); | 956 | memset(&cmd, 0, sizeof(cmd)); |
@@ -633,11 +1023,6 @@ static int lbs_adhoc_join(struct lbs_private *priv, | |||
633 | } | 1023 | } |
634 | } | 1024 | } |
635 | 1025 | ||
636 | if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { | ||
637 | ret = -1; | ||
638 | goto out; | ||
639 | } | ||
640 | |||
641 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd); | 1026 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd); |
642 | if (ret == 0) { | 1027 | if (ret == 0) { |
643 | ret = lbs_adhoc_post(priv, | 1028 | ret = lbs_adhoc_post(priv, |
@@ -661,7 +1046,7 @@ static int lbs_adhoc_start(struct lbs_private *priv, | |||
661 | struct assoc_request *assoc_req) | 1046 | struct assoc_request *assoc_req) |
662 | { | 1047 | { |
663 | struct cmd_ds_802_11_ad_hoc_start cmd; | 1048 | struct cmd_ds_802_11_ad_hoc_start cmd; |
664 | u8 preamble = RADIO_PREAMBLE_LONG; | 1049 | u8 preamble = RADIO_PREAMBLE_SHORT; |
665 | size_t ratesize = 0; | 1050 | size_t ratesize = 0; |
666 | u16 tmpcap = 0; | 1051 | u16 tmpcap = 0; |
667 | int ret = 0; | 1052 | int ret = 0; |
@@ -669,11 +1054,6 @@ static int lbs_adhoc_start(struct lbs_private *priv, | |||
669 | 1054 | ||
670 | lbs_deb_enter(LBS_DEB_ASSOC); | 1055 | lbs_deb_enter(LBS_DEB_ASSOC); |
671 | 1056 | ||
672 | if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { | ||
673 | lbs_deb_join("ADHOC_START: Will use short preamble\n"); | ||
674 | preamble = RADIO_PREAMBLE_SHORT; | ||
675 | } | ||
676 | |||
677 | ret = lbs_set_radio(priv, preamble, 1); | 1057 | ret = lbs_set_radio(priv, preamble, 1); |
678 | if (ret) | 1058 | if (ret) |
679 | goto out; | 1059 | goto out; |
@@ -737,12 +1117,6 @@ static int lbs_adhoc_start(struct lbs_private *priv, | |||
737 | lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n", | 1117 | lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n", |
738 | cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]); | 1118 | cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]); |
739 | 1119 | ||
740 | if (lbs_create_dnld_countryinfo_11d(priv)) { | ||
741 | lbs_deb_join("ADHOC_START: dnld_countryinfo_11d failed\n"); | ||
742 | ret = -1; | ||
743 | goto out; | ||
744 | } | ||
745 | |||
746 | lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n", | 1120 | lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n", |
747 | assoc_req->channel, assoc_req->band); | 1121 | assoc_req->channel, assoc_req->band); |
748 | 1122 | ||
@@ -787,11 +1161,11 @@ int lbs_adhoc_stop(struct lbs_private *priv) | |||
787 | static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, | 1161 | static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, |
788 | struct bss_descriptor *match_bss) | 1162 | struct bss_descriptor *match_bss) |
789 | { | 1163 | { |
790 | if (!secinfo->wep_enabled && !secinfo->WPAenabled | 1164 | if (!secinfo->wep_enabled && |
791 | && !secinfo->WPA2enabled | 1165 | !secinfo->WPAenabled && !secinfo->WPA2enabled && |
792 | && match_bss->wpa_ie[0] != WLAN_EID_GENERIC | 1166 | match_bss->wpa_ie[0] != WLAN_EID_GENERIC && |
793 | && match_bss->rsn_ie[0] != WLAN_EID_RSN | 1167 | match_bss->rsn_ie[0] != WLAN_EID_RSN && |
794 | && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) | 1168 | !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) |
795 | return 1; | 1169 | return 1; |
796 | else | 1170 | else |
797 | return 0; | 1171 | return 0; |
@@ -800,9 +1174,9 @@ static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, | |||
800 | static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, | 1174 | static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, |
801 | struct bss_descriptor *match_bss) | 1175 | struct bss_descriptor *match_bss) |
802 | { | 1176 | { |
803 | if (secinfo->wep_enabled && !secinfo->WPAenabled | 1177 | if (secinfo->wep_enabled && |
804 | && !secinfo->WPA2enabled | 1178 | !secinfo->WPAenabled && !secinfo->WPA2enabled && |
805 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) | 1179 | (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) |
806 | return 1; | 1180 | return 1; |
807 | else | 1181 | else |
808 | return 0; | 1182 | return 0; |
@@ -811,8 +1185,8 @@ static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, | |||
811 | static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, | 1185 | static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, |
812 | struct bss_descriptor *match_bss) | 1186 | struct bss_descriptor *match_bss) |
813 | { | 1187 | { |
814 | if (!secinfo->wep_enabled && secinfo->WPAenabled | 1188 | if (!secinfo->wep_enabled && secinfo->WPAenabled && |
815 | && (match_bss->wpa_ie[0] == WLAN_EID_GENERIC) | 1189 | (match_bss->wpa_ie[0] == WLAN_EID_GENERIC) |
816 | /* privacy bit may NOT be set in some APs like LinkSys WRT54G | 1190 | /* privacy bit may NOT be set in some APs like LinkSys WRT54G |
817 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ | 1191 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ |
818 | ) | 1192 | ) |
@@ -837,11 +1211,11 @@ static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo, | |||
837 | static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, | 1211 | static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, |
838 | struct bss_descriptor *match_bss) | 1212 | struct bss_descriptor *match_bss) |
839 | { | 1213 | { |
840 | if (!secinfo->wep_enabled && !secinfo->WPAenabled | 1214 | if (!secinfo->wep_enabled && |
841 | && !secinfo->WPA2enabled | 1215 | !secinfo->WPAenabled && !secinfo->WPA2enabled && |
842 | && (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) | 1216 | (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) && |
843 | && (match_bss->rsn_ie[0] != WLAN_EID_RSN) | 1217 | (match_bss->rsn_ie[0] != WLAN_EID_RSN) && |
844 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) | 1218 | (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) |
845 | return 1; | 1219 | return 1; |
846 | else | 1220 | else |
847 | return 0; | 1221 | return 0; |
@@ -1099,7 +1473,7 @@ static int assoc_helper_essid(struct lbs_private *priv, | |||
1099 | /* else send START command */ | 1473 | /* else send START command */ |
1100 | lbs_deb_assoc("SSID not found, creating adhoc network\n"); | 1474 | lbs_deb_assoc("SSID not found, creating adhoc network\n"); |
1101 | memcpy(&assoc_req->bss.ssid, &assoc_req->ssid, | 1475 | memcpy(&assoc_req->bss.ssid, &assoc_req->ssid, |
1102 | IW_ESSID_MAX_SIZE); | 1476 | IEEE80211_MAX_SSID_LEN); |
1103 | assoc_req->bss.ssid_len = assoc_req->ssid_len; | 1477 | assoc_req->bss.ssid_len = assoc_req->ssid_len; |
1104 | lbs_adhoc_start(priv, assoc_req); | 1478 | lbs_adhoc_start(priv, assoc_req); |
1105 | } | 1479 | } |
@@ -1152,8 +1526,8 @@ static int assoc_helper_associate(struct lbs_private *priv, | |||
1152 | /* If we're given and 'any' BSSID, try associating based on SSID */ | 1526 | /* If we're given and 'any' BSSID, try associating based on SSID */ |
1153 | 1527 | ||
1154 | if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { | 1528 | if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { |
1155 | if (compare_ether_addr(bssid_any, assoc_req->bssid) | 1529 | if (compare_ether_addr(bssid_any, assoc_req->bssid) && |
1156 | && compare_ether_addr(bssid_off, assoc_req->bssid)) { | 1530 | compare_ether_addr(bssid_off, assoc_req->bssid)) { |
1157 | ret = assoc_helper_bssid(priv, assoc_req); | 1531 | ret = assoc_helper_bssid(priv, assoc_req); |
1158 | done = 1; | 1532 | done = 1; |
1159 | } | 1533 | } |
@@ -1185,7 +1559,8 @@ static int assoc_helper_mode(struct lbs_private *priv, | |||
1185 | } | 1559 | } |
1186 | 1560 | ||
1187 | priv->mode = assoc_req->mode; | 1561 | priv->mode = assoc_req->mode; |
1188 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, assoc_req->mode); | 1562 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, |
1563 | assoc_req->mode == IW_MODE_ADHOC ? 2 : 1); | ||
1189 | 1564 | ||
1190 | done: | 1565 | done: |
1191 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | 1566 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); |
@@ -1205,7 +1580,7 @@ static int assoc_helper_channel(struct lbs_private *priv, | |||
1205 | goto done; | 1580 | goto done; |
1206 | } | 1581 | } |
1207 | 1582 | ||
1208 | if (assoc_req->channel == priv->curbssparams.channel) | 1583 | if (assoc_req->channel == priv->channel) |
1209 | goto done; | 1584 | goto done; |
1210 | 1585 | ||
1211 | if (priv->mesh_dev) { | 1586 | if (priv->mesh_dev) { |
@@ -1217,7 +1592,7 @@ static int assoc_helper_channel(struct lbs_private *priv, | |||
1217 | } | 1592 | } |
1218 | 1593 | ||
1219 | lbs_deb_assoc("ASSOC: channel: %d -> %d\n", | 1594 | lbs_deb_assoc("ASSOC: channel: %d -> %d\n", |
1220 | priv->curbssparams.channel, assoc_req->channel); | 1595 | priv->channel, assoc_req->channel); |
1221 | 1596 | ||
1222 | ret = lbs_set_channel(priv, assoc_req->channel); | 1597 | ret = lbs_set_channel(priv, assoc_req->channel); |
1223 | if (ret < 0) | 1598 | if (ret < 0) |
@@ -1232,17 +1607,15 @@ static int assoc_helper_channel(struct lbs_private *priv, | |||
1232 | goto done; | 1607 | goto done; |
1233 | } | 1608 | } |
1234 | 1609 | ||
1235 | if (assoc_req->channel != priv->curbssparams.channel) { | 1610 | if (assoc_req->channel != priv->channel) { |
1236 | lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n", | 1611 | lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n", |
1237 | assoc_req->channel); | 1612 | assoc_req->channel); |
1238 | goto restore_mesh; | 1613 | goto restore_mesh; |
1239 | } | 1614 | } |
1240 | 1615 | ||
1241 | if ( assoc_req->secinfo.wep_enabled | 1616 | if (assoc_req->secinfo.wep_enabled && |
1242 | && (assoc_req->wep_keys[0].len | 1617 | (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len || |
1243 | || assoc_req->wep_keys[1].len | 1618 | assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)) { |
1244 | || assoc_req->wep_keys[2].len | ||
1245 | || assoc_req->wep_keys[3].len)) { | ||
1246 | /* Make sure WEP keys are re-sent to firmware */ | 1619 | /* Make sure WEP keys are re-sent to firmware */ |
1247 | set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); | 1620 | set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); |
1248 | } | 1621 | } |
@@ -1253,7 +1626,7 @@ static int assoc_helper_channel(struct lbs_private *priv, | |||
1253 | restore_mesh: | 1626 | restore_mesh: |
1254 | if (priv->mesh_dev) | 1627 | if (priv->mesh_dev) |
1255 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, | 1628 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, |
1256 | priv->curbssparams.channel); | 1629 | priv->channel); |
1257 | 1630 | ||
1258 | done: | 1631 | done: |
1259 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | 1632 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); |
@@ -1475,7 +1848,7 @@ static int should_stop_adhoc(struct lbs_private *priv, | |||
1475 | } | 1848 | } |
1476 | 1849 | ||
1477 | if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { | 1850 | if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { |
1478 | if (assoc_req->channel != priv->curbssparams.channel) | 1851 | if (assoc_req->channel != priv->channel) |
1479 | return 1; | 1852 | return 1; |
1480 | } | 1853 | } |
1481 | 1854 | ||
@@ -1557,7 +1930,7 @@ static int lbs_find_best_network_ssid(struct lbs_private *priv, | |||
1557 | 1930 | ||
1558 | found = lbs_find_best_ssid_in_list(priv, preferred_mode); | 1931 | found = lbs_find_best_ssid_in_list(priv, preferred_mode); |
1559 | if (found && (found->ssid_len > 0)) { | 1932 | if (found && (found->ssid_len > 0)) { |
1560 | memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE); | 1933 | memcpy(out_ssid, &found->ssid, IEEE80211_MAX_SSID_LEN); |
1561 | *out_ssid_len = found->ssid_len; | 1934 | *out_ssid_len = found->ssid_len; |
1562 | *out_mode = found->mode; | 1935 | *out_mode = found->mode; |
1563 | ret = 0; | 1936 | ret = 0; |
@@ -1609,14 +1982,14 @@ void lbs_association_worker(struct work_struct *work) | |||
1609 | assoc_req->secinfo.auth_mode); | 1982 | assoc_req->secinfo.auth_mode); |
1610 | 1983 | ||
1611 | /* If 'any' SSID was specified, find an SSID to associate with */ | 1984 | /* If 'any' SSID was specified, find an SSID to associate with */ |
1612 | if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) | 1985 | if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) && |
1613 | && !assoc_req->ssid_len) | 1986 | !assoc_req->ssid_len) |
1614 | find_any_ssid = 1; | 1987 | find_any_ssid = 1; |
1615 | 1988 | ||
1616 | /* But don't use 'any' SSID if there's a valid locked BSSID to use */ | 1989 | /* But don't use 'any' SSID if there's a valid locked BSSID to use */ |
1617 | if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { | 1990 | if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { |
1618 | if (compare_ether_addr(assoc_req->bssid, bssid_any) | 1991 | if (compare_ether_addr(assoc_req->bssid, bssid_any) && |
1619 | && compare_ether_addr(assoc_req->bssid, bssid_off)) | 1992 | compare_ether_addr(assoc_req->bssid, bssid_off)) |
1620 | find_any_ssid = 0; | 1993 | find_any_ssid = 0; |
1621 | } | 1994 | } |
1622 | 1995 | ||
@@ -1678,13 +2051,6 @@ void lbs_association_worker(struct work_struct *work) | |||
1678 | goto out; | 2051 | goto out; |
1679 | } | 2052 | } |
1680 | 2053 | ||
1681 | if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) | ||
1682 | || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) { | ||
1683 | ret = assoc_helper_wep_keys(priv, assoc_req); | ||
1684 | if (ret) | ||
1685 | goto out; | ||
1686 | } | ||
1687 | |||
1688 | if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { | 2054 | if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { |
1689 | ret = assoc_helper_secinfo(priv, assoc_req); | 2055 | ret = assoc_helper_secinfo(priv, assoc_req); |
1690 | if (ret) | 2056 | if (ret) |
@@ -1697,18 +2063,31 @@ void lbs_association_worker(struct work_struct *work) | |||
1697 | goto out; | 2063 | goto out; |
1698 | } | 2064 | } |
1699 | 2065 | ||
1700 | if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) | 2066 | /* |
1701 | || test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { | 2067 | * v10 FW wants WPA keys to be set/cleared before WEP key operations, |
2068 | * otherwise it will fail to correctly associate to WEP networks. | ||
2069 | * Other firmware versions don't appear to care. | ||
2070 | */ | ||
2071 | if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) || | ||
2072 | test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { | ||
1702 | ret = assoc_helper_wpa_keys(priv, assoc_req); | 2073 | ret = assoc_helper_wpa_keys(priv, assoc_req); |
1703 | if (ret) | 2074 | if (ret) |
1704 | goto out; | 2075 | goto out; |
1705 | } | 2076 | } |
1706 | 2077 | ||
2078 | if (test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) || | ||
2079 | test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) { | ||
2080 | ret = assoc_helper_wep_keys(priv, assoc_req); | ||
2081 | if (ret) | ||
2082 | goto out; | ||
2083 | } | ||
2084 | |||
2085 | |||
1707 | /* SSID/BSSID should be the _last_ config option set, because they | 2086 | /* SSID/BSSID should be the _last_ config option set, because they |
1708 | * trigger the association attempt. | 2087 | * trigger the association attempt. |
1709 | */ | 2088 | */ |
1710 | if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) | 2089 | if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) || |
1711 | || test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { | 2090 | test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { |
1712 | int success = 1; | 2091 | int success = 1; |
1713 | 2092 | ||
1714 | ret = assoc_helper_associate(priv, assoc_req); | 2093 | ret = assoc_helper_associate(priv, assoc_req); |
@@ -1775,12 +2154,12 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv) | |||
1775 | assoc_req = priv->pending_assoc_req; | 2154 | assoc_req = priv->pending_assoc_req; |
1776 | if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { | 2155 | if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { |
1777 | memcpy(&assoc_req->ssid, &priv->curbssparams.ssid, | 2156 | memcpy(&assoc_req->ssid, &priv->curbssparams.ssid, |
1778 | IW_ESSID_MAX_SIZE); | 2157 | IEEE80211_MAX_SSID_LEN); |
1779 | assoc_req->ssid_len = priv->curbssparams.ssid_len; | 2158 | assoc_req->ssid_len = priv->curbssparams.ssid_len; |
1780 | } | 2159 | } |
1781 | 2160 | ||
1782 | if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) | 2161 | if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) |
1783 | assoc_req->channel = priv->curbssparams.channel; | 2162 | assoc_req->channel = priv->channel; |
1784 | 2163 | ||
1785 | if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags)) | 2164 | if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags)) |
1786 | assoc_req->band = priv->curbssparams.band; | 2165 | assoc_req->band = priv->curbssparams.band; |
diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h index 6e765e9f91a3..40621b789fc5 100644 --- a/drivers/net/wireless/libertas/assoc.h +++ b/drivers/net/wireless/libertas/assoc.h | |||
@@ -3,7 +3,126 @@ | |||
3 | #ifndef _LBS_ASSOC_H_ | 3 | #ifndef _LBS_ASSOC_H_ |
4 | #define _LBS_ASSOC_H_ | 4 | #define _LBS_ASSOC_H_ |
5 | 5 | ||
6 | #include "dev.h" | 6 | |
7 | #include "defs.h" | ||
8 | #include "host.h" | ||
9 | |||
10 | |||
11 | struct lbs_private; | ||
12 | |||
13 | /* | ||
14 | * In theory, the IE is limited to the IE length, 255, | ||
15 | * but in practice 64 bytes are enough. | ||
16 | */ | ||
17 | #define MAX_WPA_IE_LEN 64 | ||
18 | |||
19 | |||
20 | |||
21 | struct lbs_802_11_security { | ||
22 | u8 WPAenabled; | ||
23 | u8 WPA2enabled; | ||
24 | u8 wep_enabled; | ||
25 | u8 auth_mode; | ||
26 | u32 key_mgmt; | ||
27 | }; | ||
28 | |||
29 | /** Current Basic Service Set State Structure */ | ||
30 | struct current_bss_params { | ||
31 | /** bssid */ | ||
32 | u8 bssid[ETH_ALEN]; | ||
33 | /** ssid */ | ||
34 | u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; | ||
35 | u8 ssid_len; | ||
36 | |||
37 | /** band */ | ||
38 | u8 band; | ||
39 | /** channel is directly in priv->channel */ | ||
40 | /** zero-terminated array of supported data rates */ | ||
41 | u8 rates[MAX_RATES + 1]; | ||
42 | }; | ||
43 | |||
44 | /** | ||
45 | * @brief Structure used to store information for each beacon/probe response | ||
46 | */ | ||
47 | struct bss_descriptor { | ||
48 | u8 bssid[ETH_ALEN]; | ||
49 | |||
50 | u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; | ||
51 | u8 ssid_len; | ||
52 | |||
53 | u16 capability; | ||
54 | u32 rssi; | ||
55 | u32 channel; | ||
56 | u16 beaconperiod; | ||
57 | __le16 atimwindow; | ||
58 | |||
59 | /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */ | ||
60 | u8 mode; | ||
61 | |||
62 | /* zero-terminated array of supported data rates */ | ||
63 | u8 rates[MAX_RATES + 1]; | ||
64 | |||
65 | unsigned long last_scanned; | ||
66 | |||
67 | union ieee_phy_param_set phy; | ||
68 | union ieee_ss_param_set ss; | ||
69 | |||
70 | u8 wpa_ie[MAX_WPA_IE_LEN]; | ||
71 | size_t wpa_ie_len; | ||
72 | u8 rsn_ie[MAX_WPA_IE_LEN]; | ||
73 | size_t rsn_ie_len; | ||
74 | |||
75 | u8 mesh; | ||
76 | |||
77 | struct list_head list; | ||
78 | }; | ||
79 | |||
80 | /** Association request | ||
81 | * | ||
82 | * Encapsulates all the options that describe a specific assocation request | ||
83 | * or configuration of the wireless card's radio, mode, and security settings. | ||
84 | */ | ||
85 | struct assoc_request { | ||
86 | #define ASSOC_FLAG_SSID 1 | ||
87 | #define ASSOC_FLAG_CHANNEL 2 | ||
88 | #define ASSOC_FLAG_BAND 3 | ||
89 | #define ASSOC_FLAG_MODE 4 | ||
90 | #define ASSOC_FLAG_BSSID 5 | ||
91 | #define ASSOC_FLAG_WEP_KEYS 6 | ||
92 | #define ASSOC_FLAG_WEP_TX_KEYIDX 7 | ||
93 | #define ASSOC_FLAG_WPA_MCAST_KEY 8 | ||
94 | #define ASSOC_FLAG_WPA_UCAST_KEY 9 | ||
95 | #define ASSOC_FLAG_SECINFO 10 | ||
96 | #define ASSOC_FLAG_WPA_IE 11 | ||
97 | unsigned long flags; | ||
98 | |||
99 | u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; | ||
100 | u8 ssid_len; | ||
101 | u8 channel; | ||
102 | u8 band; | ||
103 | u8 mode; | ||
104 | u8 bssid[ETH_ALEN] __attribute__ ((aligned (2))); | ||
105 | |||
106 | /** WEP keys */ | ||
107 | struct enc_key wep_keys[4]; | ||
108 | u16 wep_tx_keyidx; | ||
109 | |||
110 | /** WPA keys */ | ||
111 | struct enc_key wpa_mcast_key; | ||
112 | struct enc_key wpa_unicast_key; | ||
113 | |||
114 | struct lbs_802_11_security secinfo; | ||
115 | |||
116 | /** WPA Information Elements*/ | ||
117 | u8 wpa_ie[MAX_WPA_IE_LEN]; | ||
118 | u8 wpa_ie_len; | ||
119 | |||
120 | /* BSS to associate with for infrastructure of Ad-Hoc join */ | ||
121 | struct bss_descriptor bss; | ||
122 | }; | ||
123 | |||
124 | |||
125 | extern u8 lbs_bg_rates[MAX_RATES]; | ||
7 | 126 | ||
8 | void lbs_association_worker(struct work_struct *work); | 127 | void lbs_association_worker(struct work_struct *work); |
9 | struct assoc_request *lbs_get_association_request(struct lbs_private *priv); | 128 | struct assoc_request *lbs_get_association_request(struct lbs_private *priv); |
@@ -13,4 +132,24 @@ int lbs_adhoc_stop(struct lbs_private *priv); | |||
13 | int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, | 132 | int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, |
14 | u8 bssid[ETH_ALEN], u16 reason); | 133 | u8 bssid[ETH_ALEN], u16 reason); |
15 | 134 | ||
135 | int lbs_cmd_802_11_rssi(struct lbs_private *priv, | ||
136 | struct cmd_ds_command *cmd); | ||
137 | int lbs_ret_802_11_rssi(struct lbs_private *priv, | ||
138 | struct cmd_ds_command *resp); | ||
139 | |||
140 | int lbs_cmd_bcn_ctrl(struct lbs_private *priv, | ||
141 | struct cmd_ds_command *cmd, | ||
142 | u16 cmd_action); | ||
143 | int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv, | ||
144 | struct cmd_ds_command *resp); | ||
145 | |||
146 | int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, | ||
147 | struct assoc_request *assoc); | ||
148 | |||
149 | int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, | ||
150 | uint16_t *enable); | ||
151 | |||
152 | int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, | ||
153 | struct assoc_request *assoc); | ||
154 | |||
16 | #endif /* _LBS_ASSOC_H */ | 155 | #endif /* _LBS_ASSOC_H */ |
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c new file mode 100644 index 000000000000..ce7bec402a33 --- /dev/null +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -0,0 +1,203 @@ | |||
1 | /* | ||
2 | * Implement cfg80211 ("iw") support. | ||
3 | * | ||
4 | * Copyright (C) 2009 M&N Solutions GmbH, 61191 Rosbach, Germany | ||
5 | * Holger Schurig <hs4233@mail.mn-solutions.de> | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #include <linux/slab.h> | ||
10 | #include <net/cfg80211.h> | ||
11 | |||
12 | #include "cfg.h" | ||
13 | #include "cmd.h" | ||
14 | |||
15 | |||
16 | #define CHAN2G(_channel, _freq, _flags) { \ | ||
17 | .band = IEEE80211_BAND_2GHZ, \ | ||
18 | .center_freq = (_freq), \ | ||
19 | .hw_value = (_channel), \ | ||
20 | .flags = (_flags), \ | ||
21 | .max_antenna_gain = 0, \ | ||
22 | .max_power = 30, \ | ||
23 | } | ||
24 | |||
25 | static struct ieee80211_channel lbs_2ghz_channels[] = { | ||
26 | CHAN2G(1, 2412, 0), | ||
27 | CHAN2G(2, 2417, 0), | ||
28 | CHAN2G(3, 2422, 0), | ||
29 | CHAN2G(4, 2427, 0), | ||
30 | CHAN2G(5, 2432, 0), | ||
31 | CHAN2G(6, 2437, 0), | ||
32 | CHAN2G(7, 2442, 0), | ||
33 | CHAN2G(8, 2447, 0), | ||
34 | CHAN2G(9, 2452, 0), | ||
35 | CHAN2G(10, 2457, 0), | ||
36 | CHAN2G(11, 2462, 0), | ||
37 | CHAN2G(12, 2467, 0), | ||
38 | CHAN2G(13, 2472, 0), | ||
39 | CHAN2G(14, 2484, 0), | ||
40 | }; | ||
41 | |||
42 | #define RATETAB_ENT(_rate, _rateid, _flags) { \ | ||
43 | .bitrate = (_rate), \ | ||
44 | .hw_value = (_rateid), \ | ||
45 | .flags = (_flags), \ | ||
46 | } | ||
47 | |||
48 | |||
49 | static struct ieee80211_rate lbs_rates[] = { | ||
50 | RATETAB_ENT(10, 0x1, 0), | ||
51 | RATETAB_ENT(20, 0x2, 0), | ||
52 | RATETAB_ENT(55, 0x4, 0), | ||
53 | RATETAB_ENT(110, 0x8, 0), | ||
54 | RATETAB_ENT(60, 0x10, 0), | ||
55 | RATETAB_ENT(90, 0x20, 0), | ||
56 | RATETAB_ENT(120, 0x40, 0), | ||
57 | RATETAB_ENT(180, 0x80, 0), | ||
58 | RATETAB_ENT(240, 0x100, 0), | ||
59 | RATETAB_ENT(360, 0x200, 0), | ||
60 | RATETAB_ENT(480, 0x400, 0), | ||
61 | RATETAB_ENT(540, 0x800, 0), | ||
62 | }; | ||
63 | |||
64 | static struct ieee80211_supported_band lbs_band_2ghz = { | ||
65 | .channels = lbs_2ghz_channels, | ||
66 | .n_channels = ARRAY_SIZE(lbs_2ghz_channels), | ||
67 | .bitrates = lbs_rates, | ||
68 | .n_bitrates = ARRAY_SIZE(lbs_rates), | ||
69 | }; | ||
70 | |||
71 | |||
72 | static const u32 cipher_suites[] = { | ||
73 | WLAN_CIPHER_SUITE_WEP40, | ||
74 | WLAN_CIPHER_SUITE_WEP104, | ||
75 | WLAN_CIPHER_SUITE_TKIP, | ||
76 | WLAN_CIPHER_SUITE_CCMP, | ||
77 | }; | ||
78 | |||
79 | |||
80 | |||
81 | static int lbs_cfg_set_channel(struct wiphy *wiphy, | ||
82 | struct ieee80211_channel *chan, | ||
83 | enum nl80211_channel_type channel_type) | ||
84 | { | ||
85 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
86 | int ret = -ENOTSUPP; | ||
87 | |||
88 | lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", chan->center_freq, channel_type); | ||
89 | |||
90 | if (channel_type != NL80211_CHAN_NO_HT) | ||
91 | goto out; | ||
92 | |||
93 | ret = lbs_set_channel(priv, chan->hw_value); | ||
94 | |||
95 | out: | ||
96 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
97 | return ret; | ||
98 | } | ||
99 | |||
100 | |||
101 | |||
102 | |||
103 | static struct cfg80211_ops lbs_cfg80211_ops = { | ||
104 | .set_channel = lbs_cfg_set_channel, | ||
105 | }; | ||
106 | |||
107 | |||
108 | /* | ||
109 | * At this time lbs_private *priv doesn't even exist, so we just allocate | ||
110 | * memory and don't initialize the wiphy further. This is postponed until we | ||
111 | * can talk to the firmware and happens at registration time in | ||
112 | * lbs_cfg_wiphy_register(). | ||
113 | */ | ||
114 | struct wireless_dev *lbs_cfg_alloc(struct device *dev) | ||
115 | { | ||
116 | int ret = 0; | ||
117 | struct wireless_dev *wdev; | ||
118 | |||
119 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
120 | |||
121 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | ||
122 | if (!wdev) { | ||
123 | dev_err(dev, "cannot allocate wireless device\n"); | ||
124 | return ERR_PTR(-ENOMEM); | ||
125 | } | ||
126 | |||
127 | wdev->wiphy = wiphy_new(&lbs_cfg80211_ops, sizeof(struct lbs_private)); | ||
128 | if (!wdev->wiphy) { | ||
129 | dev_err(dev, "cannot allocate wiphy\n"); | ||
130 | ret = -ENOMEM; | ||
131 | goto err_wiphy_new; | ||
132 | } | ||
133 | |||
134 | lbs_deb_leave(LBS_DEB_CFG80211); | ||
135 | return wdev; | ||
136 | |||
137 | err_wiphy_new: | ||
138 | kfree(wdev); | ||
139 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
140 | return ERR_PTR(ret); | ||
141 | } | ||
142 | |||
143 | |||
144 | /* | ||
145 | * This function get's called after lbs_setup_firmware() determined the | ||
146 | * firmware capabities. So we can setup the wiphy according to our | ||
147 | * hardware/firmware. | ||
148 | */ | ||
149 | int lbs_cfg_register(struct lbs_private *priv) | ||
150 | { | ||
151 | struct wireless_dev *wdev = priv->wdev; | ||
152 | int ret; | ||
153 | |||
154 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
155 | |||
156 | wdev->wiphy->max_scan_ssids = 1; | ||
157 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | ||
158 | |||
159 | /* TODO: BIT(NL80211_IFTYPE_ADHOC); */ | ||
160 | wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | ||
161 | |||
162 | /* TODO: honor priv->regioncode */ | ||
163 | wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz; | ||
164 | |||
165 | /* | ||
166 | * We could check priv->fwcapinfo && FW_CAPINFO_WPA, but I have | ||
167 | * never seen a firmware without WPA | ||
168 | */ | ||
169 | wdev->wiphy->cipher_suites = cipher_suites; | ||
170 | wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | ||
171 | |||
172 | ret = wiphy_register(wdev->wiphy); | ||
173 | if (ret < 0) | ||
174 | lbs_pr_err("cannot register wiphy device\n"); | ||
175 | |||
176 | priv->wiphy_registered = true; | ||
177 | |||
178 | ret = register_netdev(priv->dev); | ||
179 | if (ret) | ||
180 | lbs_pr_err("cannot register network device\n"); | ||
181 | |||
182 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
183 | return ret; | ||
184 | } | ||
185 | |||
186 | |||
187 | void lbs_cfg_free(struct lbs_private *priv) | ||
188 | { | ||
189 | struct wireless_dev *wdev = priv->wdev; | ||
190 | |||
191 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
192 | |||
193 | if (!wdev) | ||
194 | return; | ||
195 | |||
196 | if (priv->wiphy_registered) | ||
197 | wiphy_unregister(wdev->wiphy); | ||
198 | |||
199 | if (wdev->wiphy) | ||
200 | wiphy_free(wdev->wiphy); | ||
201 | |||
202 | kfree(wdev); | ||
203 | } | ||
diff --git a/drivers/net/wireless/libertas/cfg.h b/drivers/net/wireless/libertas/cfg.h new file mode 100644 index 000000000000..e09a193a34d6 --- /dev/null +++ b/drivers/net/wireless/libertas/cfg.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef __LBS_CFG80211_H__ | ||
2 | #define __LBS_CFG80211_H__ | ||
3 | |||
4 | #include "dev.h" | ||
5 | |||
6 | struct wireless_dev *lbs_cfg_alloc(struct device *dev); | ||
7 | int lbs_cfg_register(struct lbs_private *priv); | ||
8 | void lbs_cfg_free(struct lbs_private *priv); | ||
9 | |||
10 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, | ||
11 | u8 ssid_len); | ||
12 | int lbs_scan_networks(struct lbs_private *priv, int full_scan); | ||
13 | void lbs_cfg_scan_worker(struct work_struct *work); | ||
14 | |||
15 | |||
16 | #endif | ||
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 0a324dcd264c..cdb9b9650d73 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -3,21 +3,21 @@ | |||
3 | * It prepares command and sends it to firmware when it is ready. | 3 | * It prepares command and sends it to firmware when it is ready. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <net/iw_handler.h> | ||
7 | #include <net/lib80211.h> | ||
8 | #include <linux/kfifo.h> | 6 | #include <linux/kfifo.h> |
9 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
8 | #include <linux/slab.h> | ||
9 | |||
10 | #include "host.h" | 10 | #include "host.h" |
11 | #include "hostcmd.h" | ||
12 | #include "decl.h" | 11 | #include "decl.h" |
13 | #include "defs.h" | 12 | #include "defs.h" |
14 | #include "dev.h" | 13 | #include "dev.h" |
15 | #include "assoc.h" | 14 | #include "assoc.h" |
16 | #include "wext.h" | 15 | #include "wext.h" |
16 | #include "scan.h" | ||
17 | #include "cmd.h" | 17 | #include "cmd.h" |
18 | 18 | ||
19 | static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); | ||
20 | 19 | ||
20 | static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); | ||
21 | 21 | ||
22 | /** | 22 | /** |
23 | * @brief Simple callback that copies response back into command | 23 | * @brief Simple callback that copies response back into command |
@@ -77,6 +77,30 @@ static u8 is_command_allowed_in_ps(u16 cmd) | |||
77 | } | 77 | } |
78 | 78 | ||
79 | /** | 79 | /** |
80 | * @brief This function checks if the command is allowed. | ||
81 | * | ||
82 | * @param priv A pointer to lbs_private structure | ||
83 | * @return allowed or not allowed. | ||
84 | */ | ||
85 | |||
86 | static int lbs_is_cmd_allowed(struct lbs_private *priv) | ||
87 | { | ||
88 | int ret = 1; | ||
89 | |||
90 | lbs_deb_enter(LBS_DEB_CMD); | ||
91 | |||
92 | if (!priv->is_auto_deep_sleep_enabled) { | ||
93 | if (priv->is_deep_sleep) { | ||
94 | lbs_deb_cmd("command not allowed in deep sleep\n"); | ||
95 | ret = 0; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | lbs_deb_leave(LBS_DEB_CMD); | ||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | /** | ||
80 | * @brief Updates the hardware details like MAC address and regulatory region | 104 | * @brief Updates the hardware details like MAC address and regulatory region |
81 | * | 105 | * |
82 | * @param priv A pointer to struct lbs_private structure | 106 | * @param priv A pointer to struct lbs_private structure |
@@ -120,19 +144,6 @@ int lbs_update_hw_spec(struct lbs_private *priv) | |||
120 | lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", | 144 | lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", |
121 | cmd.hwifversion, cmd.version); | 145 | cmd.hwifversion, cmd.version); |
122 | 146 | ||
123 | /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ | ||
124 | /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ | ||
125 | /* 5.110.22 have mesh command with 0xa3 command id */ | ||
126 | /* 10.0.0.p0 FW brings in mesh config command with different id */ | ||
127 | /* Check FW version MSB and initialize mesh_fw_ver */ | ||
128 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) | ||
129 | priv->mesh_fw_ver = MESH_FW_OLD; | ||
130 | else if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && | ||
131 | (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) | ||
132 | priv->mesh_fw_ver = MESH_FW_NEW; | ||
133 | else | ||
134 | priv->mesh_fw_ver = MESH_NONE; | ||
135 | |||
136 | /* Clamp region code to 8-bit since FW spec indicates that it should | 147 | /* Clamp region code to 8-bit since FW spec indicates that it should |
137 | * only ever be 8-bit, even though the field size is 16-bit. Some firmware | 148 | * only ever be 8-bit, even though the field size is 16-bit. Some firmware |
138 | * returns non-zero high 8 bits here. | 149 | * returns non-zero high 8 bits here. |
@@ -169,11 +180,6 @@ int lbs_update_hw_spec(struct lbs_private *priv) | |||
169 | goto out; | 180 | goto out; |
170 | } | 181 | } |
171 | 182 | ||
172 | if (lbs_set_universaltable(priv, 0)) { | ||
173 | ret = -1; | ||
174 | goto out; | ||
175 | } | ||
176 | |||
177 | out: | 183 | out: |
178 | lbs_deb_leave(LBS_DEB_CMD); | 184 | lbs_deb_leave(LBS_DEB_CMD); |
179 | return ret; | 185 | return ret; |
@@ -222,7 +228,7 @@ static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd, | |||
222 | 228 | ||
223 | cmd->command = cpu_to_le16(CMD_802_11_PS_MODE); | 229 | cmd->command = cpu_to_le16(CMD_802_11_PS_MODE); |
224 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) + | 230 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) + |
225 | S_DS_GEN); | 231 | sizeof(struct cmd_header)); |
226 | psm->action = cpu_to_le16(cmd_action); | 232 | psm->action = cpu_to_le16(cmd_action); |
227 | psm->multipledtim = 0; | 233 | psm->multipledtim = 0; |
228 | switch (cmd_action) { | 234 | switch (cmd_action) { |
@@ -251,33 +257,6 @@ static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd, | |||
251 | return 0; | 257 | return 0; |
252 | } | 258 | } |
253 | 259 | ||
254 | int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv, | ||
255 | uint16_t cmd_action, uint16_t *timeout) | ||
256 | { | ||
257 | struct cmd_ds_802_11_inactivity_timeout cmd; | ||
258 | int ret; | ||
259 | |||
260 | lbs_deb_enter(LBS_DEB_CMD); | ||
261 | |||
262 | cmd.hdr.command = cpu_to_le16(CMD_802_11_INACTIVITY_TIMEOUT); | ||
263 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
264 | |||
265 | cmd.action = cpu_to_le16(cmd_action); | ||
266 | |||
267 | if (cmd_action == CMD_ACT_SET) | ||
268 | cmd.timeout = cpu_to_le16(*timeout); | ||
269 | else | ||
270 | cmd.timeout = 0; | ||
271 | |||
272 | ret = lbs_cmd_with_response(priv, CMD_802_11_INACTIVITY_TIMEOUT, &cmd); | ||
273 | |||
274 | if (!ret) | ||
275 | *timeout = le16_to_cpu(cmd.timeout); | ||
276 | |||
277 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, | 260 | int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, |
282 | struct sleep_params *sp) | 261 | struct sleep_params *sp) |
283 | { | 262 | { |
@@ -320,190 +299,53 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, | |||
320 | return 0; | 299 | return 0; |
321 | } | 300 | } |
322 | 301 | ||
323 | int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, | 302 | static int lbs_wait_for_ds_awake(struct lbs_private *priv) |
324 | struct assoc_request *assoc) | ||
325 | { | 303 | { |
326 | struct cmd_ds_802_11_set_wep cmd; | ||
327 | int ret = 0; | 304 | int ret = 0; |
328 | 305 | ||
329 | lbs_deb_enter(LBS_DEB_CMD); | 306 | lbs_deb_enter(LBS_DEB_CMD); |
330 | 307 | ||
331 | memset(&cmd, 0, sizeof(cmd)); | 308 | if (priv->is_deep_sleep) { |
332 | cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP); | 309 | if (!wait_event_interruptible_timeout(priv->ds_awake_q, |
333 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | 310 | !priv->is_deep_sleep, (10 * HZ))) { |
334 | 311 | lbs_pr_err("ds_awake_q: timer expired\n"); | |
335 | cmd.action = cpu_to_le16(cmd_action); | 312 | ret = -1; |
336 | |||
337 | if (cmd_action == CMD_ACT_ADD) { | ||
338 | int i; | ||
339 | |||
340 | /* default tx key index */ | ||
341 | cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx & | ||
342 | CMD_WEP_KEY_INDEX_MASK); | ||
343 | |||
344 | /* Copy key types and material to host command structure */ | ||
345 | for (i = 0; i < 4; i++) { | ||
346 | struct enc_key *pkey = &assoc->wep_keys[i]; | ||
347 | |||
348 | switch (pkey->len) { | ||
349 | case KEY_LEN_WEP_40: | ||
350 | cmd.keytype[i] = CMD_TYPE_WEP_40_BIT; | ||
351 | memmove(cmd.keymaterial[i], pkey->key, pkey->len); | ||
352 | lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i); | ||
353 | break; | ||
354 | case KEY_LEN_WEP_104: | ||
355 | cmd.keytype[i] = CMD_TYPE_WEP_104_BIT; | ||
356 | memmove(cmd.keymaterial[i], pkey->key, pkey->len); | ||
357 | lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i); | ||
358 | break; | ||
359 | case 0: | ||
360 | break; | ||
361 | default: | ||
362 | lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n", | ||
363 | i, pkey->len); | ||
364 | ret = -1; | ||
365 | goto done; | ||
366 | break; | ||
367 | } | ||
368 | } | 313 | } |
369 | } else if (cmd_action == CMD_ACT_REMOVE) { | ||
370 | /* ACT_REMOVE clears _all_ WEP keys */ | ||
371 | |||
372 | /* default tx key index */ | ||
373 | cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx & | ||
374 | CMD_WEP_KEY_INDEX_MASK); | ||
375 | lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx); | ||
376 | } | ||
377 | |||
378 | ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd); | ||
379 | done: | ||
380 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, | ||
385 | uint16_t *enable) | ||
386 | { | ||
387 | struct cmd_ds_802_11_enable_rsn cmd; | ||
388 | int ret; | ||
389 | |||
390 | lbs_deb_enter(LBS_DEB_CMD); | ||
391 | |||
392 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
393 | cmd.action = cpu_to_le16(cmd_action); | ||
394 | |||
395 | if (cmd_action == CMD_ACT_GET) | ||
396 | cmd.enable = 0; | ||
397 | else { | ||
398 | if (*enable) | ||
399 | cmd.enable = cpu_to_le16(CMD_ENABLE_RSN); | ||
400 | else | ||
401 | cmd.enable = cpu_to_le16(CMD_DISABLE_RSN); | ||
402 | lbs_deb_cmd("ENABLE_RSN: %d\n", *enable); | ||
403 | } | 314 | } |
404 | 315 | ||
405 | ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd); | ||
406 | if (!ret && cmd_action == CMD_ACT_GET) | ||
407 | *enable = le16_to_cpu(cmd.enable); | ||
408 | |||
409 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | 316 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); |
410 | return ret; | 317 | return ret; |
411 | } | 318 | } |
412 | 319 | ||
413 | static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam, | 320 | int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep) |
414 | struct enc_key *key) | ||
415 | { | 321 | { |
416 | lbs_deb_enter(LBS_DEB_CMD); | 322 | int ret = 0; |
417 | |||
418 | if (key->flags & KEY_INFO_WPA_ENABLED) | ||
419 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED); | ||
420 | if (key->flags & KEY_INFO_WPA_UNICAST) | ||
421 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST); | ||
422 | if (key->flags & KEY_INFO_WPA_MCAST) | ||
423 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST); | ||
424 | |||
425 | keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL); | ||
426 | keyparam->keytypeid = cpu_to_le16(key->type); | ||
427 | keyparam->keylen = cpu_to_le16(key->len); | ||
428 | memcpy(keyparam->key, key->key, key->len); | ||
429 | |||
430 | /* Length field doesn't include the {type,length} header */ | ||
431 | keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4); | ||
432 | lbs_deb_leave(LBS_DEB_CMD); | ||
433 | } | ||
434 | |||
435 | int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, | ||
436 | struct assoc_request *assoc) | ||
437 | { | ||
438 | struct cmd_ds_802_11_key_material cmd; | ||
439 | int ret = 0; | ||
440 | int index = 0; | ||
441 | 323 | ||
442 | lbs_deb_enter(LBS_DEB_CMD); | 324 | lbs_deb_enter(LBS_DEB_CMD); |
443 | 325 | ||
444 | cmd.action = cpu_to_le16(cmd_action); | 326 | if (deep_sleep) { |
445 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | 327 | if (priv->is_deep_sleep != 1) { |
446 | 328 | lbs_deb_cmd("deep sleep: sleep\n"); | |
447 | if (cmd_action == CMD_ACT_GET) { | 329 | BUG_ON(!priv->enter_deep_sleep); |
448 | cmd.hdr.size = cpu_to_le16(S_DS_GEN + 2); | 330 | ret = priv->enter_deep_sleep(priv); |
449 | } else { | 331 | if (!ret) { |
450 | memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet)); | 332 | netif_stop_queue(priv->dev); |
451 | 333 | netif_carrier_off(priv->dev); | |
452 | if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) { | 334 | } |
453 | set_one_wpa_key(&cmd.keyParamSet[index], | 335 | } else { |
454 | &assoc->wpa_unicast_key); | 336 | lbs_pr_err("deep sleep: already enabled\n"); |
455 | index++; | ||
456 | } | ||
457 | |||
458 | if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) { | ||
459 | set_one_wpa_key(&cmd.keyParamSet[index], | ||
460 | &assoc->wpa_mcast_key); | ||
461 | index++; | ||
462 | } | 337 | } |
463 | 338 | } else { | |
464 | /* The common header and as many keys as we included */ | 339 | if (priv->is_deep_sleep) { |
465 | cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd), | 340 | lbs_deb_cmd("deep sleep: wakeup\n"); |
466 | keyParamSet[index])); | 341 | BUG_ON(!priv->exit_deep_sleep); |
467 | } | 342 | ret = priv->exit_deep_sleep(priv); |
468 | ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd); | 343 | if (!ret) { |
469 | /* Copy the returned key to driver private data */ | 344 | ret = lbs_wait_for_ds_awake(priv); |
470 | if (!ret && cmd_action == CMD_ACT_GET) { | 345 | if (ret) |
471 | void *buf_ptr = cmd.keyParamSet; | 346 | lbs_pr_err("deep sleep: wakeup" |
472 | void *resp_end = &(&cmd)[1]; | 347 | "failed\n"); |
473 | 348 | } | |
474 | while (buf_ptr < resp_end) { | ||
475 | struct MrvlIEtype_keyParamSet *keyparam = buf_ptr; | ||
476 | struct enc_key *key; | ||
477 | uint16_t param_set_len = le16_to_cpu(keyparam->length); | ||
478 | uint16_t key_len = le16_to_cpu(keyparam->keylen); | ||
479 | uint16_t key_flags = le16_to_cpu(keyparam->keyinfo); | ||
480 | uint16_t key_type = le16_to_cpu(keyparam->keytypeid); | ||
481 | void *end; | ||
482 | |||
483 | end = (void *)keyparam + sizeof(keyparam->type) | ||
484 | + sizeof(keyparam->length) + param_set_len; | ||
485 | |||
486 | /* Make sure we don't access past the end of the IEs */ | ||
487 | if (end > resp_end) | ||
488 | break; | ||
489 | |||
490 | if (key_flags & KEY_INFO_WPA_UNICAST) | ||
491 | key = &priv->wpa_unicast_key; | ||
492 | else if (key_flags & KEY_INFO_WPA_MCAST) | ||
493 | key = &priv->wpa_mcast_key; | ||
494 | else | ||
495 | break; | ||
496 | |||
497 | /* Copy returned key into driver */ | ||
498 | memset(key, 0, sizeof(struct enc_key)); | ||
499 | if (key_len > sizeof(key->key)) | ||
500 | break; | ||
501 | key->type = key_type; | ||
502 | key->flags = key_flags; | ||
503 | key->len = key_len; | ||
504 | memcpy(key->key, keyparam->key, key->len); | ||
505 | |||
506 | buf_ptr = end + 1; | ||
507 | } | 349 | } |
508 | } | 350 | } |
509 | 351 | ||
@@ -535,7 +377,7 @@ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val) | |||
535 | switch (oid) { | 377 | switch (oid) { |
536 | case SNMP_MIB_OID_BSS_TYPE: | 378 | case SNMP_MIB_OID_BSS_TYPE: |
537 | cmd.bufsize = cpu_to_le16(sizeof(u8)); | 379 | cmd.bufsize = cpu_to_le16(sizeof(u8)); |
538 | cmd.value[0] = (val == IW_MODE_ADHOC) ? 2 : 1; | 380 | cmd.value[0] = val; |
539 | break; | 381 | break; |
540 | case SNMP_MIB_OID_11D_ENABLE: | 382 | case SNMP_MIB_OID_11D_ENABLE: |
541 | case SNMP_MIB_OID_FRAG_THRESHOLD: | 383 | case SNMP_MIB_OID_FRAG_THRESHOLD: |
@@ -588,13 +430,7 @@ int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val) | |||
588 | 430 | ||
589 | switch (le16_to_cpu(cmd.bufsize)) { | 431 | switch (le16_to_cpu(cmd.bufsize)) { |
590 | case sizeof(u8): | 432 | case sizeof(u8): |
591 | if (oid == SNMP_MIB_OID_BSS_TYPE) { | 433 | *out_val = cmd.value[0]; |
592 | if (cmd.value[0] == 2) | ||
593 | *out_val = IW_MODE_ADHOC; | ||
594 | else | ||
595 | *out_val = IW_MODE_INFRA; | ||
596 | } else | ||
597 | *out_val = cmd.value[0]; | ||
598 | break; | 434 | break; |
599 | case sizeof(u16): | 435 | case sizeof(u16): |
600 | *out_val = le16_to_cpu(*((__le16 *)(&cmd.value))); | 436 | *out_val = le16_to_cpu(*((__le16 *)(&cmd.value))); |
@@ -681,7 +517,7 @@ static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd, | |||
681 | cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE); | 517 | cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE); |
682 | cmd->size = | 518 | cmd->size = |
683 | cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) + | 519 | cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) + |
684 | S_DS_GEN); | 520 | sizeof(struct cmd_header)); |
685 | 521 | ||
686 | monitor->action = cpu_to_le16(cmd_action); | 522 | monitor->action = cpu_to_le16(cmd_action); |
687 | if (cmd_action == CMD_ACT_SET) { | 523 | if (cmd_action == CMD_ACT_SET) { |
@@ -692,111 +528,6 @@ static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd, | |||
692 | return 0; | 528 | return 0; |
693 | } | 529 | } |
694 | 530 | ||
695 | static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok) | ||
696 | { | ||
697 | /* Bit Rate | ||
698 | * 15:13 Reserved | ||
699 | * 12 54 Mbps | ||
700 | * 11 48 Mbps | ||
701 | * 10 36 Mbps | ||
702 | * 9 24 Mbps | ||
703 | * 8 18 Mbps | ||
704 | * 7 12 Mbps | ||
705 | * 6 9 Mbps | ||
706 | * 5 6 Mbps | ||
707 | * 4 Reserved | ||
708 | * 3 11 Mbps | ||
709 | * 2 5.5 Mbps | ||
710 | * 1 2 Mbps | ||
711 | * 0 1 Mbps | ||
712 | **/ | ||
713 | |||
714 | uint16_t ratemask; | ||
715 | int i = lbs_data_rate_to_fw_index(rate); | ||
716 | if (lower_rates_ok) | ||
717 | ratemask = (0x1fef >> (12 - i)); | ||
718 | else | ||
719 | ratemask = (1 << i); | ||
720 | return cpu_to_le16(ratemask); | ||
721 | } | ||
722 | |||
723 | int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, | ||
724 | uint16_t cmd_action) | ||
725 | { | ||
726 | struct cmd_ds_802_11_rate_adapt_rateset cmd; | ||
727 | int ret; | ||
728 | |||
729 | lbs_deb_enter(LBS_DEB_CMD); | ||
730 | |||
731 | if (!priv->cur_rate && !priv->enablehwauto) | ||
732 | return -EINVAL; | ||
733 | |||
734 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
735 | |||
736 | cmd.action = cpu_to_le16(cmd_action); | ||
737 | cmd.enablehwauto = cpu_to_le16(priv->enablehwauto); | ||
738 | cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto); | ||
739 | ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd); | ||
740 | if (!ret && cmd_action == CMD_ACT_GET) { | ||
741 | priv->ratebitmap = le16_to_cpu(cmd.bitmap); | ||
742 | priv->enablehwauto = le16_to_cpu(cmd.enablehwauto); | ||
743 | } | ||
744 | |||
745 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
746 | return ret; | ||
747 | } | ||
748 | EXPORT_SYMBOL_GPL(lbs_cmd_802_11_rate_adapt_rateset); | ||
749 | |||
750 | /** | ||
751 | * @brief Set the data rate | ||
752 | * | ||
753 | * @param priv A pointer to struct lbs_private structure | ||
754 | * @param rate The desired data rate, or 0 to clear a locked rate | ||
755 | * | ||
756 | * @return 0 on success, error on failure | ||
757 | */ | ||
758 | int lbs_set_data_rate(struct lbs_private *priv, u8 rate) | ||
759 | { | ||
760 | struct cmd_ds_802_11_data_rate cmd; | ||
761 | int ret = 0; | ||
762 | |||
763 | lbs_deb_enter(LBS_DEB_CMD); | ||
764 | |||
765 | memset(&cmd, 0, sizeof(cmd)); | ||
766 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
767 | |||
768 | if (rate > 0) { | ||
769 | cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE); | ||
770 | cmd.rates[0] = lbs_data_rate_to_fw_index(rate); | ||
771 | if (cmd.rates[0] == 0) { | ||
772 | lbs_deb_cmd("DATA_RATE: invalid requested rate of" | ||
773 | " 0x%02X\n", rate); | ||
774 | ret = 0; | ||
775 | goto out; | ||
776 | } | ||
777 | lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]); | ||
778 | } else { | ||
779 | cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO); | ||
780 | lbs_deb_cmd("DATA_RATE: setting auto\n"); | ||
781 | } | ||
782 | |||
783 | ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd); | ||
784 | if (ret) | ||
785 | goto out; | ||
786 | |||
787 | lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof (cmd)); | ||
788 | |||
789 | /* FIXME: get actual rates FW can do if this command actually returns | ||
790 | * all data rates supported. | ||
791 | */ | ||
792 | priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]); | ||
793 | lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate); | ||
794 | |||
795 | out: | ||
796 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
797 | return ret; | ||
798 | } | ||
799 | |||
800 | /** | 531 | /** |
801 | * @brief Get the radio channel | 532 | * @brief Get the radio channel |
802 | * | 533 | * |
@@ -804,7 +535,7 @@ out: | |||
804 | * | 535 | * |
805 | * @return The channel on success, error on failure | 536 | * @return The channel on success, error on failure |
806 | */ | 537 | */ |
807 | int lbs_get_channel(struct lbs_private *priv) | 538 | static int lbs_get_channel(struct lbs_private *priv) |
808 | { | 539 | { |
809 | struct cmd_ds_802_11_rf_channel cmd; | 540 | struct cmd_ds_802_11_rf_channel cmd; |
810 | int ret = 0; | 541 | int ret = 0; |
@@ -836,7 +567,7 @@ int lbs_update_channel(struct lbs_private *priv) | |||
836 | 567 | ||
837 | ret = lbs_get_channel(priv); | 568 | ret = lbs_get_channel(priv); |
838 | if (ret > 0) { | 569 | if (ret > 0) { |
839 | priv->curbssparams.channel = ret; | 570 | priv->channel = ret; |
840 | ret = 0; | 571 | ret = 0; |
841 | } | 572 | } |
842 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | 573 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); |
@@ -855,7 +586,7 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel) | |||
855 | { | 586 | { |
856 | struct cmd_ds_802_11_rf_channel cmd; | 587 | struct cmd_ds_802_11_rf_channel cmd; |
857 | #ifdef DEBUG | 588 | #ifdef DEBUG |
858 | u8 old_channel = priv->curbssparams.channel; | 589 | u8 old_channel = priv->channel; |
859 | #endif | 590 | #endif |
860 | int ret = 0; | 591 | int ret = 0; |
861 | 592 | ||
@@ -870,36 +601,15 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel) | |||
870 | if (ret) | 601 | if (ret) |
871 | goto out; | 602 | goto out; |
872 | 603 | ||
873 | priv->curbssparams.channel = (uint8_t) le16_to_cpu(cmd.channel); | 604 | priv->channel = (uint8_t) le16_to_cpu(cmd.channel); |
874 | lbs_deb_cmd("channel switch from %d to %d\n", old_channel, | 605 | lbs_deb_cmd("channel switch from %d to %d\n", old_channel, |
875 | priv->curbssparams.channel); | 606 | priv->channel); |
876 | 607 | ||
877 | out: | 608 | out: |
878 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | 609 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); |
879 | return ret; | 610 | return ret; |
880 | } | 611 | } |
881 | 612 | ||
882 | static int lbs_cmd_802_11_rssi(struct lbs_private *priv, | ||
883 | struct cmd_ds_command *cmd) | ||
884 | { | ||
885 | |||
886 | lbs_deb_enter(LBS_DEB_CMD); | ||
887 | cmd->command = cpu_to_le16(CMD_802_11_RSSI); | ||
888 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN); | ||
889 | cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR); | ||
890 | |||
891 | /* reset Beacon SNR/NF/RSSI values */ | ||
892 | priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
893 | priv->SNR[TYPE_BEACON][TYPE_AVG] = 0; | ||
894 | priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
895 | priv->NF[TYPE_BEACON][TYPE_AVG] = 0; | ||
896 | priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
897 | priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0; | ||
898 | |||
899 | lbs_deb_leave(LBS_DEB_CMD); | ||
900 | return 0; | ||
901 | } | ||
902 | |||
903 | static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, | 613 | static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, |
904 | u8 cmd_action, void *pdata_buf) | 614 | u8 cmd_action, void *pdata_buf) |
905 | { | 615 | { |
@@ -916,7 +626,7 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, | |||
916 | 626 | ||
917 | cmdptr->size = | 627 | cmdptr->size = |
918 | cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access) | 628 | cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access) |
919 | + S_DS_GEN); | 629 | + sizeof(struct cmd_header)); |
920 | macreg = | 630 | macreg = |
921 | (struct cmd_ds_mac_reg_access *)&cmdptr->params. | 631 | (struct cmd_ds_mac_reg_access *)&cmdptr->params. |
922 | macreg; | 632 | macreg; |
@@ -935,7 +645,7 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, | |||
935 | cmdptr->size = | 645 | cmdptr->size = |
936 | cpu_to_le16(sizeof | 646 | cpu_to_le16(sizeof |
937 | (struct cmd_ds_bbp_reg_access) | 647 | (struct cmd_ds_bbp_reg_access) |
938 | + S_DS_GEN); | 648 | + sizeof(struct cmd_header)); |
939 | bbpreg = | 649 | bbpreg = |
940 | (struct cmd_ds_bbp_reg_access *)&cmdptr->params. | 650 | (struct cmd_ds_bbp_reg_access *)&cmdptr->params. |
941 | bbpreg; | 651 | bbpreg; |
@@ -954,7 +664,7 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, | |||
954 | cmdptr->size = | 664 | cmdptr->size = |
955 | cpu_to_le16(sizeof | 665 | cpu_to_le16(sizeof |
956 | (struct cmd_ds_rf_reg_access) + | 666 | (struct cmd_ds_rf_reg_access) + |
957 | S_DS_GEN); | 667 | sizeof(struct cmd_header)); |
958 | rfreg = | 668 | rfreg = |
959 | (struct cmd_ds_rf_reg_access *)&cmdptr->params. | 669 | (struct cmd_ds_rf_reg_access *)&cmdptr->params. |
960 | rfreg; | 670 | rfreg; |
@@ -974,192 +684,6 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, | |||
974 | return 0; | 684 | return 0; |
975 | } | 685 | } |
976 | 686 | ||
977 | static int lbs_cmd_bt_access(struct cmd_ds_command *cmd, | ||
978 | u16 cmd_action, void *pdata_buf) | ||
979 | { | ||
980 | struct cmd_ds_bt_access *bt_access = &cmd->params.bt; | ||
981 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | ||
982 | |||
983 | cmd->command = cpu_to_le16(CMD_BT_ACCESS); | ||
984 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN); | ||
985 | cmd->result = 0; | ||
986 | bt_access->action = cpu_to_le16(cmd_action); | ||
987 | |||
988 | switch (cmd_action) { | ||
989 | case CMD_ACT_BT_ACCESS_ADD: | ||
990 | memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN); | ||
991 | lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", bt_access->addr1, 6); | ||
992 | break; | ||
993 | case CMD_ACT_BT_ACCESS_DEL: | ||
994 | memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN); | ||
995 | lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", bt_access->addr1, 6); | ||
996 | break; | ||
997 | case CMD_ACT_BT_ACCESS_LIST: | ||
998 | bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); | ||
999 | break; | ||
1000 | case CMD_ACT_BT_ACCESS_RESET: | ||
1001 | break; | ||
1002 | case CMD_ACT_BT_ACCESS_SET_INVERT: | ||
1003 | bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); | ||
1004 | break; | ||
1005 | case CMD_ACT_BT_ACCESS_GET_INVERT: | ||
1006 | break; | ||
1007 | default: | ||
1008 | break; | ||
1009 | } | ||
1010 | lbs_deb_leave(LBS_DEB_CMD); | ||
1011 | return 0; | ||
1012 | } | ||
1013 | |||
1014 | static int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, | ||
1015 | u16 cmd_action, void *pdata_buf) | ||
1016 | { | ||
1017 | struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt; | ||
1018 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | ||
1019 | |||
1020 | cmd->command = cpu_to_le16(CMD_FWT_ACCESS); | ||
1021 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + S_DS_GEN); | ||
1022 | cmd->result = 0; | ||
1023 | |||
1024 | if (pdata_buf) | ||
1025 | memcpy(fwt_access, pdata_buf, sizeof(*fwt_access)); | ||
1026 | else | ||
1027 | memset(fwt_access, 0, sizeof(*fwt_access)); | ||
1028 | |||
1029 | fwt_access->action = cpu_to_le16(cmd_action); | ||
1030 | |||
1031 | lbs_deb_leave(LBS_DEB_CMD); | ||
1032 | return 0; | ||
1033 | } | ||
1034 | |||
1035 | int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, | ||
1036 | struct cmd_ds_mesh_access *cmd) | ||
1037 | { | ||
1038 | int ret; | ||
1039 | |||
1040 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | ||
1041 | |||
1042 | cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS); | ||
1043 | cmd->hdr.size = cpu_to_le16(sizeof(*cmd)); | ||
1044 | cmd->hdr.result = 0; | ||
1045 | |||
1046 | cmd->action = cpu_to_le16(cmd_action); | ||
1047 | |||
1048 | ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd); | ||
1049 | |||
1050 | lbs_deb_leave(LBS_DEB_CMD); | ||
1051 | return ret; | ||
1052 | } | ||
1053 | |||
1054 | static int __lbs_mesh_config_send(struct lbs_private *priv, | ||
1055 | struct cmd_ds_mesh_config *cmd, | ||
1056 | uint16_t action, uint16_t type) | ||
1057 | { | ||
1058 | int ret; | ||
1059 | u16 command = CMD_MESH_CONFIG_OLD; | ||
1060 | |||
1061 | lbs_deb_enter(LBS_DEB_CMD); | ||
1062 | |||
1063 | /* | ||
1064 | * Command id is 0xac for v10 FW along with mesh interface | ||
1065 | * id in bits 14-13-12. | ||
1066 | */ | ||
1067 | if (priv->mesh_fw_ver == MESH_FW_NEW) | ||
1068 | command = CMD_MESH_CONFIG | | ||
1069 | (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET); | ||
1070 | |||
1071 | cmd->hdr.command = cpu_to_le16(command); | ||
1072 | cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config)); | ||
1073 | cmd->hdr.result = 0; | ||
1074 | |||
1075 | cmd->type = cpu_to_le16(type); | ||
1076 | cmd->action = cpu_to_le16(action); | ||
1077 | |||
1078 | ret = lbs_cmd_with_response(priv, command, cmd); | ||
1079 | |||
1080 | lbs_deb_leave(LBS_DEB_CMD); | ||
1081 | return ret; | ||
1082 | } | ||
1083 | |||
1084 | int lbs_mesh_config_send(struct lbs_private *priv, | ||
1085 | struct cmd_ds_mesh_config *cmd, | ||
1086 | uint16_t action, uint16_t type) | ||
1087 | { | ||
1088 | int ret; | ||
1089 | |||
1090 | if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG)) | ||
1091 | return -EOPNOTSUPP; | ||
1092 | |||
1093 | ret = __lbs_mesh_config_send(priv, cmd, action, type); | ||
1094 | return ret; | ||
1095 | } | ||
1096 | |||
1097 | /* This function is the CMD_MESH_CONFIG legacy function. It only handles the | ||
1098 | * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG | ||
1099 | * are all handled by preparing a struct cmd_ds_mesh_config and passing it to | ||
1100 | * lbs_mesh_config_send. | ||
1101 | */ | ||
1102 | int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan) | ||
1103 | { | ||
1104 | struct cmd_ds_mesh_config cmd; | ||
1105 | struct mrvl_meshie *ie; | ||
1106 | DECLARE_SSID_BUF(ssid); | ||
1107 | |||
1108 | memset(&cmd, 0, sizeof(cmd)); | ||
1109 | cmd.channel = cpu_to_le16(chan); | ||
1110 | ie = (struct mrvl_meshie *)cmd.data; | ||
1111 | |||
1112 | switch (action) { | ||
1113 | case CMD_ACT_MESH_CONFIG_START: | ||
1114 | ie->id = WLAN_EID_GENERIC; | ||
1115 | ie->val.oui[0] = 0x00; | ||
1116 | ie->val.oui[1] = 0x50; | ||
1117 | ie->val.oui[2] = 0x43; | ||
1118 | ie->val.type = MARVELL_MESH_IE_TYPE; | ||
1119 | ie->val.subtype = MARVELL_MESH_IE_SUBTYPE; | ||
1120 | ie->val.version = MARVELL_MESH_IE_VERSION; | ||
1121 | ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP; | ||
1122 | ie->val.active_metric_id = MARVELL_MESH_METRIC_ID; | ||
1123 | ie->val.mesh_capability = MARVELL_MESH_CAPABILITY; | ||
1124 | ie->val.mesh_id_len = priv->mesh_ssid_len; | ||
1125 | memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len); | ||
1126 | ie->len = sizeof(struct mrvl_meshie_val) - | ||
1127 | IW_ESSID_MAX_SIZE + priv->mesh_ssid_len; | ||
1128 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val)); | ||
1129 | break; | ||
1130 | case CMD_ACT_MESH_CONFIG_STOP: | ||
1131 | break; | ||
1132 | default: | ||
1133 | return -1; | ||
1134 | } | ||
1135 | lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n", | ||
1136 | action, priv->mesh_tlv, chan, | ||
1137 | print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len)); | ||
1138 | |||
1139 | return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); | ||
1140 | } | ||
1141 | |||
1142 | static int lbs_cmd_bcn_ctrl(struct lbs_private * priv, | ||
1143 | struct cmd_ds_command *cmd, | ||
1144 | u16 cmd_action) | ||
1145 | { | ||
1146 | struct cmd_ds_802_11_beacon_control | ||
1147 | *bcn_ctrl = &cmd->params.bcn_ctrl; | ||
1148 | |||
1149 | lbs_deb_enter(LBS_DEB_CMD); | ||
1150 | cmd->size = | ||
1151 | cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control) | ||
1152 | + S_DS_GEN); | ||
1153 | cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL); | ||
1154 | |||
1155 | bcn_ctrl->action = cpu_to_le16(cmd_action); | ||
1156 | bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable); | ||
1157 | bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period); | ||
1158 | |||
1159 | lbs_deb_leave(LBS_DEB_CMD); | ||
1160 | return 0; | ||
1161 | } | ||
1162 | |||
1163 | static void lbs_queue_cmd(struct lbs_private *priv, | 687 | static void lbs_queue_cmd(struct lbs_private *priv, |
1164 | struct cmd_ctrl_node *cmdnode) | 688 | struct cmd_ctrl_node *cmdnode) |
1165 | { | 689 | { |
@@ -1243,8 +767,17 @@ static void lbs_submit_command(struct lbs_private *priv, | |||
1243 | timeo = HZ/4; | 767 | timeo = HZ/4; |
1244 | } | 768 | } |
1245 | 769 | ||
1246 | /* Setup the timer after transmit command */ | 770 | if (command == CMD_802_11_DEEP_SLEEP) { |
1247 | mod_timer(&priv->command_timer, jiffies + timeo); | 771 | if (priv->is_auto_deep_sleep_enabled) { |
772 | priv->wakeup_dev_required = 1; | ||
773 | priv->dnld_sent = 0; | ||
774 | } | ||
775 | priv->is_deep_sleep = 1; | ||
776 | lbs_complete_command(priv, cmdnode, 0); | ||
777 | } else { | ||
778 | /* Setup the timer after transmit command */ | ||
779 | mod_timer(&priv->command_timer, jiffies + timeo); | ||
780 | } | ||
1248 | 781 | ||
1249 | lbs_deb_leave(LBS_DEB_HOST); | 782 | lbs_deb_leave(LBS_DEB_HOST); |
1250 | } | 783 | } |
@@ -1310,9 +843,6 @@ int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on) | |||
1310 | if (priv->fwrelease < 0x09000000) { | 843 | if (priv->fwrelease < 0x09000000) { |
1311 | switch (preamble) { | 844 | switch (preamble) { |
1312 | case RADIO_PREAMBLE_SHORT: | 845 | case RADIO_PREAMBLE_SHORT: |
1313 | if (!(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) | ||
1314 | goto out; | ||
1315 | /* Fall through */ | ||
1316 | case RADIO_PREAMBLE_AUTO: | 846 | case RADIO_PREAMBLE_AUTO: |
1317 | case RADIO_PREAMBLE_LONG: | 847 | case RADIO_PREAMBLE_LONG: |
1318 | cmd.control = cpu_to_le16(preamble); | 848 | cmd.control = cpu_to_le16(preamble); |
@@ -1391,6 +921,11 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1391 | goto done; | 921 | goto done; |
1392 | } | 922 | } |
1393 | 923 | ||
924 | if (!lbs_is_cmd_allowed(priv)) { | ||
925 | ret = -EBUSY; | ||
926 | goto done; | ||
927 | } | ||
928 | |||
1394 | cmdnode = lbs_get_cmd_ctrl_node(priv); | 929 | cmdnode = lbs_get_cmd_ctrl_node(priv); |
1395 | 930 | ||
1396 | if (cmdnode == NULL) { | 931 | if (cmdnode == NULL) { |
@@ -1441,7 +976,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1441 | 976 | ||
1442 | cmdptr->command = cpu_to_le16(cmd_no); | 977 | cmdptr->command = cpu_to_le16(cmd_no); |
1443 | cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) + | 978 | cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) + |
1444 | S_DS_GEN); | 979 | sizeof(struct cmd_header)); |
1445 | 980 | ||
1446 | memmove(&cmdptr->params.afc, | 981 | memmove(&cmdptr->params.afc, |
1447 | pdata_buf, sizeof(struct cmd_ds_802_11_afc)); | 982 | pdata_buf, sizeof(struct cmd_ds_802_11_afc)); |
@@ -1449,45 +984,19 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1449 | ret = 0; | 984 | ret = 0; |
1450 | goto done; | 985 | goto done; |
1451 | 986 | ||
1452 | case CMD_802_11D_DOMAIN_INFO: | ||
1453 | ret = lbs_cmd_802_11d_domain_info(priv, cmdptr, | ||
1454 | cmd_no, cmd_action); | ||
1455 | break; | ||
1456 | |||
1457 | case CMD_802_11_TPC_CFG: | 987 | case CMD_802_11_TPC_CFG: |
1458 | cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG); | 988 | cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG); |
1459 | cmdptr->size = | 989 | cmdptr->size = |
1460 | cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) + | 990 | cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) + |
1461 | S_DS_GEN); | 991 | sizeof(struct cmd_header)); |
1462 | 992 | ||
1463 | memmove(&cmdptr->params.tpccfg, | 993 | memmove(&cmdptr->params.tpccfg, |
1464 | pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg)); | 994 | pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg)); |
1465 | 995 | ||
1466 | ret = 0; | 996 | ret = 0; |
1467 | break; | 997 | break; |
1468 | case CMD_802_11_LED_GPIO_CTRL: | ||
1469 | { | ||
1470 | struct mrvl_ie_ledgpio *gpio = | ||
1471 | (struct mrvl_ie_ledgpio*) | ||
1472 | cmdptr->params.ledgpio.data; | ||
1473 | |||
1474 | memmove(&cmdptr->params.ledgpio, | ||
1475 | pdata_buf, | ||
1476 | sizeof(struct cmd_ds_802_11_led_ctrl)); | ||
1477 | 998 | ||
1478 | cmdptr->command = | 999 | #ifdef CONFIG_LIBERTAS_MESH |
1479 | cpu_to_le16(CMD_802_11_LED_GPIO_CTRL); | ||
1480 | |||
1481 | #define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8 | ||
1482 | cmdptr->size = | ||
1483 | cpu_to_le16(le16_to_cpu(gpio->header.len) | ||
1484 | + S_DS_GEN | ||
1485 | + ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN); | ||
1486 | gpio->header.len = gpio->header.len; | ||
1487 | |||
1488 | ret = 0; | ||
1489 | break; | ||
1490 | } | ||
1491 | 1000 | ||
1492 | case CMD_BT_ACCESS: | 1001 | case CMD_BT_ACCESS: |
1493 | ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf); | 1002 | ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf); |
@@ -1497,15 +1006,15 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1497 | ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf); | 1006 | ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf); |
1498 | break; | 1007 | break; |
1499 | 1008 | ||
1500 | case CMD_GET_TSF: | 1009 | #endif |
1501 | cmdptr->command = cpu_to_le16(CMD_GET_TSF); | 1010 | |
1502 | cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) + | ||
1503 | S_DS_GEN); | ||
1504 | ret = 0; | ||
1505 | break; | ||
1506 | case CMD_802_11_BEACON_CTRL: | 1011 | case CMD_802_11_BEACON_CTRL: |
1507 | ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); | 1012 | ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); |
1508 | break; | 1013 | break; |
1014 | case CMD_802_11_DEEP_SLEEP: | ||
1015 | cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP); | ||
1016 | cmdptr->size = cpu_to_le16(sizeof(struct cmd_header)); | ||
1017 | break; | ||
1509 | default: | 1018 | default: |
1510 | lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no); | 1019 | lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no); |
1511 | ret = -1; | 1020 | ret = -1; |
@@ -1797,7 +1306,7 @@ int lbs_execute_next_command(struct lbs_private *priv) | |||
1797 | if ((priv->psmode != LBS802_11POWERMODECAM) && | 1306 | if ((priv->psmode != LBS802_11POWERMODECAM) && |
1798 | (priv->psstate == PS_STATE_FULL_POWER) && | 1307 | (priv->psstate == PS_STATE_FULL_POWER) && |
1799 | ((priv->connect_status == LBS_CONNECTED) || | 1308 | ((priv->connect_status == LBS_CONNECTED) || |
1800 | (priv->mesh_connect_status == LBS_CONNECTED))) { | 1309 | lbs_mesh_connected(priv))) { |
1801 | if (priv->secinfo.WPAenabled || | 1310 | if (priv->secinfo.WPAenabled || |
1802 | priv->secinfo.WPA2enabled) { | 1311 | priv->secinfo.WPA2enabled) { |
1803 | /* check for valid WPA group keys */ | 1312 | /* check for valid WPA group keys */ |
@@ -1823,30 +1332,6 @@ done: | |||
1823 | return ret; | 1332 | return ret; |
1824 | } | 1333 | } |
1825 | 1334 | ||
1826 | void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str) | ||
1827 | { | ||
1828 | union iwreq_data iwrq; | ||
1829 | u8 buf[50]; | ||
1830 | |||
1831 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1832 | |||
1833 | memset(&iwrq, 0, sizeof(union iwreq_data)); | ||
1834 | memset(buf, 0, sizeof(buf)); | ||
1835 | |||
1836 | snprintf(buf, sizeof(buf) - 1, "%s", str); | ||
1837 | |||
1838 | iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN; | ||
1839 | |||
1840 | /* Send Event to upper layer */ | ||
1841 | lbs_deb_wext("event indication string %s\n", (char *)buf); | ||
1842 | lbs_deb_wext("event indication length %d\n", iwrq.data.length); | ||
1843 | lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str); | ||
1844 | |||
1845 | wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf); | ||
1846 | |||
1847 | lbs_deb_leave(LBS_DEB_WEXT); | ||
1848 | } | ||
1849 | |||
1850 | static void lbs_send_confirmsleep(struct lbs_private *priv) | 1335 | static void lbs_send_confirmsleep(struct lbs_private *priv) |
1851 | { | 1336 | { |
1852 | unsigned long flags; | 1337 | unsigned long flags; |
@@ -1869,7 +1354,7 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) | |||
1869 | priv->dnld_sent = DNLD_RES_RECEIVED; | 1354 | priv->dnld_sent = DNLD_RES_RECEIVED; |
1870 | 1355 | ||
1871 | /* If nothing to do, go back to sleep (?) */ | 1356 | /* If nothing to do, go back to sleep (?) */ |
1872 | if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx]) | 1357 | if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx]) |
1873 | priv->psstate = PS_STATE_SLEEP; | 1358 | priv->psstate = PS_STATE_SLEEP; |
1874 | 1359 | ||
1875 | spin_unlock_irqrestore(&priv->driver_lock, flags); | 1360 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
@@ -1943,7 +1428,7 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv) | |||
1943 | } | 1428 | } |
1944 | 1429 | ||
1945 | /* Pending events or command responses? */ | 1430 | /* Pending events or command responses? */ |
1946 | if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) { | 1431 | if (kfifo_len(&priv->event_fifo) || priv->resp_len[priv->resp_idx]) { |
1947 | allowed = 0; | 1432 | allowed = 0; |
1948 | lbs_deb_host("pending events or command responses\n"); | 1433 | lbs_deb_host("pending events or command responses\n"); |
1949 | } | 1434 | } |
@@ -2024,7 +1509,7 @@ int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, | |||
2024 | } | 1509 | } |
2025 | 1510 | ||
2026 | 1511 | ||
2027 | static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, | 1512 | struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, |
2028 | uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, | 1513 | uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, |
2029 | int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), | 1514 | int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), |
2030 | unsigned long callback_arg) | 1515 | unsigned long callback_arg) |
@@ -2039,6 +1524,11 @@ static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, | |||
2039 | goto done; | 1524 | goto done; |
2040 | } | 1525 | } |
2041 | 1526 | ||
1527 | if (!lbs_is_cmd_allowed(priv)) { | ||
1528 | cmdnode = ERR_PTR(-EBUSY); | ||
1529 | goto done; | ||
1530 | } | ||
1531 | |||
2042 | cmdnode = lbs_get_cmd_ctrl_node(priv); | 1532 | cmdnode = lbs_get_cmd_ctrl_node(priv); |
2043 | if (cmdnode == NULL) { | 1533 | if (cmdnode == NULL) { |
2044 | lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); | 1534 | lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); |
@@ -2117,5 +1607,3 @@ done: | |||
2117 | return ret; | 1607 | return ret; |
2118 | } | 1608 | } |
2119 | EXPORT_SYMBOL_GPL(__lbs_cmd); | 1609 | EXPORT_SYMBOL_GPL(__lbs_cmd); |
2120 | |||
2121 | |||
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h index 392e578ca095..cb4138a55fdf 100644 --- a/drivers/net/wireless/libertas/cmd.h +++ b/drivers/net/wireless/libertas/cmd.h | |||
@@ -3,11 +3,30 @@ | |||
3 | #ifndef _LBS_CMD_H_ | 3 | #ifndef _LBS_CMD_H_ |
4 | #define _LBS_CMD_H_ | 4 | #define _LBS_CMD_H_ |
5 | 5 | ||
6 | #include "hostcmd.h" | 6 | #include "host.h" |
7 | #include "dev.h" | 7 | #include "dev.h" |
8 | 8 | ||
9 | |||
10 | /* Command & response transfer between host and card */ | ||
11 | |||
12 | struct cmd_ctrl_node { | ||
13 | struct list_head list; | ||
14 | int result; | ||
15 | /* command response */ | ||
16 | int (*callback)(struct lbs_private *, | ||
17 | unsigned long, | ||
18 | struct cmd_header *); | ||
19 | unsigned long callback_arg; | ||
20 | /* command data */ | ||
21 | struct cmd_header *cmdbuf; | ||
22 | /* wait queue */ | ||
23 | u16 cmdwaitqwoken; | ||
24 | wait_queue_head_t cmdwait_q; | ||
25 | }; | ||
26 | |||
27 | |||
9 | /* lbs_cmd() infers the size of the buffer to copy data back into, from | 28 | /* lbs_cmd() infers the size of the buffer to copy data back into, from |
10 | the size of the target of the pointer. Since the command to be sent | 29 | the size of the target of the pointer. Since the command to be sent |
11 | may often be smaller, that size is set in cmd->size by the caller.*/ | 30 | may often be smaller, that size is set in cmd->size by the caller.*/ |
12 | #define lbs_cmd(priv, cmdnr, cmd, cb, cb_arg) ({ \ | 31 | #define lbs_cmd(priv, cmdnr, cmd, cb, cb_arg) ({ \ |
13 | uint16_t __sz = le16_to_cpu((cmd)->hdr.size); \ | 32 | uint16_t __sz = le16_to_cpu((cmd)->hdr.size); \ |
@@ -18,6 +37,11 @@ | |||
18 | #define lbs_cmd_with_response(priv, cmdnr, cmd) \ | 37 | #define lbs_cmd_with_response(priv, cmdnr, cmd) \ |
19 | lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd)) | 38 | lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd)) |
20 | 39 | ||
40 | int lbs_prepare_and_send_command(struct lbs_private *priv, | ||
41 | u16 cmd_no, | ||
42 | u16 cmd_action, | ||
43 | u16 wait_option, u32 cmd_oid, void *pdata_buf); | ||
44 | |||
21 | void lbs_cmd_async(struct lbs_private *priv, uint16_t command, | 45 | void lbs_cmd_async(struct lbs_private *priv, uint16_t command, |
22 | struct cmd_header *in_cmd, int in_cmd_size); | 46 | struct cmd_header *in_cmd, int in_cmd_size); |
23 | 47 | ||
@@ -26,62 +50,81 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command, | |||
26 | int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), | 50 | int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), |
27 | unsigned long callback_arg); | 51 | unsigned long callback_arg); |
28 | 52 | ||
29 | int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, | 53 | struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, |
30 | int8_t p1, int8_t p2); | 54 | uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, |
55 | int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), | ||
56 | unsigned long callback_arg); | ||
31 | 57 | ||
32 | int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, | 58 | int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, |
33 | int8_t p2, int usesnr); | 59 | struct cmd_header *resp); |
34 | 60 | ||
35 | int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, | 61 | int lbs_allocate_cmd_buffer(struct lbs_private *priv); |
36 | int8_t p1, int8_t p2); | 62 | int lbs_free_cmd_buffer(struct lbs_private *priv); |
37 | 63 | ||
38 | int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, | 64 | int lbs_execute_next_command(struct lbs_private *priv); |
39 | int8_t p2, int usesnr); | 65 | void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, |
66 | int result); | ||
67 | int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len); | ||
40 | 68 | ||
41 | int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, | ||
42 | struct cmd_header *resp); | ||
43 | 69 | ||
44 | int lbs_update_hw_spec(struct lbs_private *priv); | 70 | /* From cmdresp.c */ |
45 | 71 | ||
46 | int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, | 72 | void lbs_mac_event_disconnected(struct lbs_private *priv); |
47 | struct cmd_ds_mesh_access *cmd); | ||
48 | 73 | ||
49 | int lbs_set_data_rate(struct lbs_private *priv, u8 rate); | ||
50 | 74 | ||
51 | int lbs_get_channel(struct lbs_private *priv); | 75 | |
76 | /* Events */ | ||
77 | |||
78 | int lbs_process_event(struct lbs_private *priv, u32 event); | ||
79 | |||
80 | |||
81 | /* Actual commands */ | ||
82 | |||
83 | int lbs_update_hw_spec(struct lbs_private *priv); | ||
84 | |||
52 | int lbs_set_channel(struct lbs_private *priv, u8 channel); | 85 | int lbs_set_channel(struct lbs_private *priv, u8 channel); |
53 | 86 | ||
54 | int lbs_mesh_config_send(struct lbs_private *priv, | 87 | int lbs_update_channel(struct lbs_private *priv); |
55 | struct cmd_ds_mesh_config *cmd, | ||
56 | uint16_t action, uint16_t type); | ||
57 | int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); | ||
58 | 88 | ||
59 | int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, | 89 | int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, |
60 | struct wol_config *p_wol_config); | 90 | struct wol_config *p_wol_config); |
61 | int lbs_suspend(struct lbs_private *priv); | ||
62 | void lbs_resume(struct lbs_private *priv); | ||
63 | 91 | ||
64 | int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, | ||
65 | uint16_t cmd_action); | ||
66 | int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv, | ||
67 | uint16_t cmd_action, uint16_t *timeout); | ||
68 | int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, | 92 | int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, |
69 | struct sleep_params *sp); | 93 | struct sleep_params *sp); |
70 | int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, | ||
71 | struct assoc_request *assoc); | ||
72 | int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, | ||
73 | uint16_t *enable); | ||
74 | int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, | ||
75 | struct assoc_request *assoc); | ||
76 | 94 | ||
77 | int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, | 95 | void lbs_ps_sleep(struct lbs_private *priv, int wait_option); |
78 | s16 *maxlevel); | 96 | |
79 | int lbs_set_tx_power(struct lbs_private *priv, s16 dbm); | 97 | void lbs_ps_wakeup(struct lbs_private *priv, int wait_option); |
98 | |||
99 | void lbs_ps_confirm_sleep(struct lbs_private *priv); | ||
80 | 100 | ||
81 | int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on); | 101 | int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on); |
82 | 102 | ||
103 | void lbs_set_mac_control(struct lbs_private *priv); | ||
104 | |||
105 | int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, | ||
106 | s16 *maxlevel); | ||
107 | |||
83 | int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val); | 108 | int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val); |
84 | 109 | ||
85 | int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val); | 110 | int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val); |
86 | 111 | ||
112 | |||
113 | /* Commands only used in wext.c, assoc. and scan.c */ | ||
114 | |||
115 | int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, | ||
116 | int8_t p1, int8_t p2); | ||
117 | |||
118 | int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, | ||
119 | int8_t p2, int usesnr); | ||
120 | |||
121 | int lbs_set_data_rate(struct lbs_private *priv, u8 rate); | ||
122 | |||
123 | int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, | ||
124 | uint16_t cmd_action); | ||
125 | |||
126 | int lbs_set_tx_power(struct lbs_private *priv, s16 dbm); | ||
127 | |||
128 | int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep); | ||
129 | |||
87 | #endif /* _LBS_CMD_H */ | 130 | #endif /* _LBS_CMD_H */ |
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 23f684337fdd..88f7131d66e9 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * This file contains the handling of command | 2 | * This file contains the handling of command |
3 | * responses as well as events generated by firmware. | 3 | * responses as well as events generated by firmware. |
4 | */ | 4 | */ |
5 | #include <linux/slab.h> | ||
5 | #include <linux/delay.h> | 6 | #include <linux/delay.h> |
6 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
7 | #include <linux/if_arp.h> | 8 | #include <linux/if_arp.h> |
@@ -11,6 +12,7 @@ | |||
11 | 12 | ||
12 | #include "host.h" | 13 | #include "host.h" |
13 | #include "decl.h" | 14 | #include "decl.h" |
15 | #include "cmd.h" | ||
14 | #include "defs.h" | 16 | #include "defs.h" |
15 | #include "dev.h" | 17 | #include "dev.h" |
16 | #include "assoc.h" | 18 | #include "assoc.h" |
@@ -26,23 +28,17 @@ | |||
26 | */ | 28 | */ |
27 | void lbs_mac_event_disconnected(struct lbs_private *priv) | 29 | void lbs_mac_event_disconnected(struct lbs_private *priv) |
28 | { | 30 | { |
29 | union iwreq_data wrqu; | ||
30 | |||
31 | if (priv->connect_status != LBS_CONNECTED) | 31 | if (priv->connect_status != LBS_CONNECTED) |
32 | return; | 32 | return; |
33 | 33 | ||
34 | lbs_deb_enter(LBS_DEB_ASSOC); | 34 | lbs_deb_enter(LBS_DEB_ASSOC); |
35 | 35 | ||
36 | memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN); | ||
37 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
38 | |||
39 | /* | 36 | /* |
40 | * Cisco AP sends EAP failure and de-auth in less than 0.5 ms. | 37 | * Cisco AP sends EAP failure and de-auth in less than 0.5 ms. |
41 | * It causes problem in the Supplicant | 38 | * It causes problem in the Supplicant |
42 | */ | 39 | */ |
43 | |||
44 | msleep_interruptible(1000); | 40 | msleep_interruptible(1000); |
45 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | 41 | lbs_send_disconnect_notification(priv); |
46 | 42 | ||
47 | /* report disconnect to upper layer */ | 43 | /* report disconnect to upper layer */ |
48 | netif_stop_queue(priv->dev); | 44 | netif_stop_queue(priv->dev); |
@@ -67,7 +63,7 @@ void lbs_mac_event_disconnected(struct lbs_private *priv) | |||
67 | * no longer valid. | 63 | * no longer valid. |
68 | */ | 64 | */ |
69 | memset(&priv->curbssparams.bssid, 0, ETH_ALEN); | 65 | memset(&priv->curbssparams.bssid, 0, ETH_ALEN); |
70 | memset(&priv->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE); | 66 | memset(&priv->curbssparams.ssid, 0, IEEE80211_MAX_SSID_LEN); |
71 | priv->curbssparams.ssid_len = 0; | 67 | priv->curbssparams.ssid_len = 0; |
72 | 68 | ||
73 | if (priv->psstate != PS_STATE_FULL_POWER) { | 69 | if (priv->psstate != PS_STATE_FULL_POWER) { |
@@ -78,32 +74,6 @@ void lbs_mac_event_disconnected(struct lbs_private *priv) | |||
78 | lbs_deb_leave(LBS_DEB_ASSOC); | 74 | lbs_deb_leave(LBS_DEB_ASSOC); |
79 | } | 75 | } |
80 | 76 | ||
81 | /** | ||
82 | * @brief This function handles MIC failure event. | ||
83 | * | ||
84 | * @param priv A pointer to struct lbs_private structure | ||
85 | * @para event the event id | ||
86 | * @return n/a | ||
87 | */ | ||
88 | static void handle_mic_failureevent(struct lbs_private *priv, u32 event) | ||
89 | { | ||
90 | char buf[50]; | ||
91 | |||
92 | lbs_deb_enter(LBS_DEB_CMD); | ||
93 | memset(buf, 0, sizeof(buf)); | ||
94 | |||
95 | sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication "); | ||
96 | |||
97 | if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) { | ||
98 | strcat(buf, "unicast "); | ||
99 | } else { | ||
100 | strcat(buf, "multicast "); | ||
101 | } | ||
102 | |||
103 | lbs_send_iwevcustom_event(priv, buf); | ||
104 | lbs_deb_leave(LBS_DEB_CMD); | ||
105 | } | ||
106 | |||
107 | static int lbs_ret_reg_access(struct lbs_private *priv, | 77 | static int lbs_ret_reg_access(struct lbs_private *priv, |
108 | u16 type, struct cmd_ds_command *resp) | 78 | u16 type, struct cmd_ds_command *resp) |
109 | { | 79 | { |
@@ -147,53 +117,6 @@ static int lbs_ret_reg_access(struct lbs_private *priv, | |||
147 | return ret; | 117 | return ret; |
148 | } | 118 | } |
149 | 119 | ||
150 | static int lbs_ret_802_11_rssi(struct lbs_private *priv, | ||
151 | struct cmd_ds_command *resp) | ||
152 | { | ||
153 | struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp; | ||
154 | |||
155 | lbs_deb_enter(LBS_DEB_CMD); | ||
156 | |||
157 | /* store the non average value */ | ||
158 | priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR); | ||
159 | priv->NF[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->noisefloor); | ||
160 | |||
161 | priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR); | ||
162 | priv->NF[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgnoisefloor); | ||
163 | |||
164 | priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = | ||
165 | CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG], | ||
166 | priv->NF[TYPE_BEACON][TYPE_NOAVG]); | ||
167 | |||
168 | priv->RSSI[TYPE_BEACON][TYPE_AVG] = | ||
169 | CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE, | ||
170 | priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE); | ||
171 | |||
172 | lbs_deb_cmd("RSSI: beacon %d, avg %d\n", | ||
173 | priv->RSSI[TYPE_BEACON][TYPE_NOAVG], | ||
174 | priv->RSSI[TYPE_BEACON][TYPE_AVG]); | ||
175 | |||
176 | lbs_deb_leave(LBS_DEB_CMD); | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv, | ||
181 | struct cmd_ds_command *resp) | ||
182 | { | ||
183 | struct cmd_ds_802_11_beacon_control *bcn_ctrl = | ||
184 | &resp->params.bcn_ctrl; | ||
185 | |||
186 | lbs_deb_enter(LBS_DEB_CMD); | ||
187 | |||
188 | if (bcn_ctrl->action == CMD_ACT_GET) { | ||
189 | priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable); | ||
190 | priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period); | ||
191 | } | ||
192 | |||
193 | lbs_deb_enter(LBS_DEB_CMD); | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static inline int handle_cmd_response(struct lbs_private *priv, | 120 | static inline int handle_cmd_response(struct lbs_private *priv, |
198 | struct cmd_header *cmd_response) | 121 | struct cmd_header *cmd_response) |
199 | { | 122 | { |
@@ -227,29 +150,13 @@ static inline int handle_cmd_response(struct lbs_private *priv, | |||
227 | ret = lbs_ret_802_11_rssi(priv, resp); | 150 | ret = lbs_ret_802_11_rssi(priv, resp); |
228 | break; | 151 | break; |
229 | 152 | ||
230 | case CMD_RET(CMD_802_11D_DOMAIN_INFO): | ||
231 | ret = lbs_ret_802_11d_domain_info(resp); | ||
232 | break; | ||
233 | |||
234 | case CMD_RET(CMD_802_11_TPC_CFG): | 153 | case CMD_RET(CMD_802_11_TPC_CFG): |
235 | spin_lock_irqsave(&priv->driver_lock, flags); | 154 | spin_lock_irqsave(&priv->driver_lock, flags); |
236 | memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg, | 155 | memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg, |
237 | sizeof(struct cmd_ds_802_11_tpc_cfg)); | 156 | sizeof(struct cmd_ds_802_11_tpc_cfg)); |
238 | spin_unlock_irqrestore(&priv->driver_lock, flags); | 157 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
239 | break; | 158 | break; |
240 | case CMD_RET(CMD_802_11_LED_GPIO_CTRL): | ||
241 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
242 | memmove((void *)priv->cur_cmd->callback_arg, &resp->params.ledgpio, | ||
243 | sizeof(struct cmd_ds_802_11_led_ctrl)); | ||
244 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
245 | break; | ||
246 | 159 | ||
247 | case CMD_RET(CMD_GET_TSF): | ||
248 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
249 | memcpy((void *)priv->cur_cmd->callback_arg, | ||
250 | &resp->params.gettsf.tsfvalue, sizeof(u64)); | ||
251 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
252 | break; | ||
253 | case CMD_RET(CMD_BT_ACCESS): | 160 | case CMD_RET(CMD_BT_ACCESS): |
254 | spin_lock_irqsave(&priv->driver_lock, flags); | 161 | spin_lock_irqsave(&priv->driver_lock, flags); |
255 | if (priv->cur_cmd->callback_arg) | 162 | if (priv->cur_cmd->callback_arg) |
@@ -334,11 +241,6 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) | |||
334 | /* Now we got response from FW, cancel the command timer */ | 241 | /* Now we got response from FW, cancel the command timer */ |
335 | del_timer(&priv->command_timer); | 242 | del_timer(&priv->command_timer); |
336 | priv->cmd_timed_out = 0; | 243 | priv->cmd_timed_out = 0; |
337 | if (priv->nr_retries) { | ||
338 | lbs_pr_info("Received result %x to command %x after %d retries\n", | ||
339 | result, curcmd, priv->nr_retries); | ||
340 | priv->nr_retries = 0; | ||
341 | } | ||
342 | 244 | ||
343 | /* Store the response code to cur_cmd_retcode. */ | 245 | /* Store the response code to cur_cmd_retcode. */ |
344 | priv->cur_cmd_retcode = result; | 246 | priv->cur_cmd_retcode = result; |
@@ -505,9 +407,21 @@ int lbs_process_event(struct lbs_private *priv, u32 event) | |||
505 | 407 | ||
506 | case MACREG_INT_CODE_HOST_AWAKE: | 408 | case MACREG_INT_CODE_HOST_AWAKE: |
507 | lbs_deb_cmd("EVENT: host awake\n"); | 409 | lbs_deb_cmd("EVENT: host awake\n"); |
410 | if (priv->reset_deep_sleep_wakeup) | ||
411 | priv->reset_deep_sleep_wakeup(priv); | ||
412 | priv->is_deep_sleep = 0; | ||
508 | lbs_send_confirmwake(priv); | 413 | lbs_send_confirmwake(priv); |
509 | break; | 414 | break; |
510 | 415 | ||
416 | case MACREG_INT_CODE_DEEP_SLEEP_AWAKE: | ||
417 | if (priv->reset_deep_sleep_wakeup) | ||
418 | priv->reset_deep_sleep_wakeup(priv); | ||
419 | lbs_deb_cmd("EVENT: ds awake\n"); | ||
420 | priv->is_deep_sleep = 0; | ||
421 | priv->wakeup_dev_required = 0; | ||
422 | wake_up_interruptible(&priv->ds_awake_q); | ||
423 | break; | ||
424 | |||
511 | case MACREG_INT_CODE_PS_AWAKE: | 425 | case MACREG_INT_CODE_PS_AWAKE: |
512 | lbs_deb_cmd("EVENT: ps awake\n"); | 426 | lbs_deb_cmd("EVENT: ps awake\n"); |
513 | /* handle unexpected PS AWAKE event */ | 427 | /* handle unexpected PS AWAKE event */ |
@@ -533,12 +447,12 @@ int lbs_process_event(struct lbs_private *priv, u32 event) | |||
533 | 447 | ||
534 | case MACREG_INT_CODE_MIC_ERR_UNICAST: | 448 | case MACREG_INT_CODE_MIC_ERR_UNICAST: |
535 | lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n"); | 449 | lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n"); |
536 | handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST); | 450 | lbs_send_mic_failureevent(priv, event); |
537 | break; | 451 | break; |
538 | 452 | ||
539 | case MACREG_INT_CODE_MIC_ERR_MULTICAST: | 453 | case MACREG_INT_CODE_MIC_ERR_MULTICAST: |
540 | lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n"); | 454 | lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n"); |
541 | handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST); | 455 | lbs_send_mic_failureevent(priv, event); |
542 | break; | 456 | break; |
543 | 457 | ||
544 | case MACREG_INT_CODE_MIB_CHANGED: | 458 | case MACREG_INT_CODE_MIB_CHANGED: |
@@ -567,20 +481,8 @@ int lbs_process_event(struct lbs_private *priv, u32 event) | |||
567 | break; | 481 | break; |
568 | 482 | ||
569 | case MACREG_INT_CODE_MESH_AUTO_STARTED: | 483 | case MACREG_INT_CODE_MESH_AUTO_STARTED: |
570 | /* Ignore spurious autostart events if autostart is disabled */ | 484 | /* Ignore spurious autostart events */ |
571 | if (!priv->mesh_autostart_enabled) { | 485 | lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n"); |
572 | lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n"); | ||
573 | break; | ||
574 | } | ||
575 | lbs_pr_info("EVENT: MESH_AUTO_STARTED\n"); | ||
576 | priv->mesh_connect_status = LBS_CONNECTED; | ||
577 | if (priv->mesh_open) { | ||
578 | netif_carrier_on(priv->mesh_dev); | ||
579 | if (!priv->tx_pending_len) | ||
580 | netif_wake_queue(priv->mesh_dev); | ||
581 | } | ||
582 | priv->mode = IW_MODE_ADHOC; | ||
583 | schedule_work(&priv->sync_channel); | ||
584 | break; | 486 | break; |
585 | 487 | ||
586 | default: | 488 | default: |
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 893a55ca344a..a48ccaffb288 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/delay.h> | 4 | #include <linux/delay.h> |
5 | #include <linux/mm.h> | 5 | #include <linux/mm.h> |
6 | #include <linux/string.h> | 6 | #include <linux/string.h> |
7 | #include <linux/slab.h> | ||
7 | #include <net/iw_handler.h> | 8 | #include <net/iw_handler.h> |
8 | #include <net/lib80211.h> | 9 | #include <net/lib80211.h> |
9 | 10 | ||
@@ -451,10 +452,12 @@ static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf, | |||
451 | CMD_MAC_REG_ACCESS, 0, | 452 | CMD_MAC_REG_ACCESS, 0, |
452 | CMD_OPTION_WAITFORRSP, 0, &offval); | 453 | CMD_OPTION_WAITFORRSP, 0, &offval); |
453 | mdelay(10); | 454 | mdelay(10); |
454 | pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n", | 455 | if (!ret) { |
456 | pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n", | ||
455 | priv->mac_offset, priv->offsetvalue.value); | 457 | priv->mac_offset, priv->offsetvalue.value); |
456 | 458 | ||
457 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | 459 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); |
460 | } | ||
458 | free_page(addr); | 461 | free_page(addr); |
459 | return ret; | 462 | return ret; |
460 | } | 463 | } |
@@ -514,7 +517,8 @@ static ssize_t lbs_wrmac_write(struct file *file, | |||
514 | CMD_OPTION_WAITFORRSP, 0, &offval); | 517 | CMD_OPTION_WAITFORRSP, 0, &offval); |
515 | mdelay(10); | 518 | mdelay(10); |
516 | 519 | ||
517 | res = count; | 520 | if (!res) |
521 | res = count; | ||
518 | out_unlock: | 522 | out_unlock: |
519 | free_page(addr); | 523 | free_page(addr); |
520 | return res; | 524 | return res; |
@@ -539,10 +543,12 @@ static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf, | |||
539 | CMD_BBP_REG_ACCESS, 0, | 543 | CMD_BBP_REG_ACCESS, 0, |
540 | CMD_OPTION_WAITFORRSP, 0, &offval); | 544 | CMD_OPTION_WAITFORRSP, 0, &offval); |
541 | mdelay(10); | 545 | mdelay(10); |
542 | pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n", | 546 | if (!ret) { |
547 | pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n", | ||
543 | priv->bbp_offset, priv->offsetvalue.value); | 548 | priv->bbp_offset, priv->offsetvalue.value); |
544 | 549 | ||
545 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | 550 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); |
551 | } | ||
546 | free_page(addr); | 552 | free_page(addr); |
547 | 553 | ||
548 | return ret; | 554 | return ret; |
@@ -603,7 +609,8 @@ static ssize_t lbs_wrbbp_write(struct file *file, | |||
603 | CMD_OPTION_WAITFORRSP, 0, &offval); | 609 | CMD_OPTION_WAITFORRSP, 0, &offval); |
604 | mdelay(10); | 610 | mdelay(10); |
605 | 611 | ||
606 | res = count; | 612 | if (!res) |
613 | res = count; | ||
607 | out_unlock: | 614 | out_unlock: |
608 | free_page(addr); | 615 | free_page(addr); |
609 | return res; | 616 | return res; |
@@ -628,10 +635,12 @@ static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf, | |||
628 | CMD_RF_REG_ACCESS, 0, | 635 | CMD_RF_REG_ACCESS, 0, |
629 | CMD_OPTION_WAITFORRSP, 0, &offval); | 636 | CMD_OPTION_WAITFORRSP, 0, &offval); |
630 | mdelay(10); | 637 | mdelay(10); |
631 | pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n", | 638 | if (!ret) { |
639 | pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n", | ||
632 | priv->rf_offset, priv->offsetvalue.value); | 640 | priv->rf_offset, priv->offsetvalue.value); |
633 | 641 | ||
634 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | 642 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); |
643 | } | ||
635 | free_page(addr); | 644 | free_page(addr); |
636 | 645 | ||
637 | return ret; | 646 | return ret; |
@@ -692,7 +701,8 @@ static ssize_t lbs_wrrf_write(struct file *file, | |||
692 | CMD_OPTION_WAITFORRSP, 0, &offval); | 701 | CMD_OPTION_WAITFORRSP, 0, &offval); |
693 | mdelay(10); | 702 | mdelay(10); |
694 | 703 | ||
695 | res = count; | 704 | if (!res) |
705 | res = count; | ||
696 | out_unlock: | 706 | out_unlock: |
697 | free_page(addr); | 707 | free_page(addr); |
698 | return res; | 708 | return res; |
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 8b15380ae6e1..709ffcad22ad 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h | |||
@@ -8,71 +8,46 @@ | |||
8 | 8 | ||
9 | #include <linux/netdevice.h> | 9 | #include <linux/netdevice.h> |
10 | 10 | ||
11 | #include "defs.h" | ||
12 | 11 | ||
13 | /** Function Prototype Declaration */ | ||
14 | struct lbs_private; | 12 | struct lbs_private; |
15 | struct sk_buff; | 13 | struct sk_buff; |
16 | struct net_device; | 14 | struct net_device; |
17 | struct cmd_ctrl_node; | ||
18 | struct cmd_ds_command; | ||
19 | 15 | ||
20 | void lbs_set_mac_control(struct lbs_private *priv); | ||
21 | 16 | ||
22 | void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count); | 17 | /* ethtool.c */ |
23 | 18 | extern const struct ethtool_ops lbs_ethtool_ops; | |
24 | int lbs_free_cmd_buffer(struct lbs_private *priv); | ||
25 | |||
26 | int lbs_prepare_and_send_command(struct lbs_private *priv, | ||
27 | u16 cmd_no, | ||
28 | u16 cmd_action, | ||
29 | u16 wait_option, u32 cmd_oid, void *pdata_buf); | ||
30 | 19 | ||
31 | int lbs_allocate_cmd_buffer(struct lbs_private *priv); | ||
32 | int lbs_execute_next_command(struct lbs_private *priv); | ||
33 | int lbs_process_event(struct lbs_private *priv, u32 event); | ||
34 | void lbs_queue_event(struct lbs_private *priv, u32 event); | ||
35 | void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); | ||
36 | 20 | ||
37 | u32 lbs_fw_index_to_data_rate(u8 index); | 21 | /* tx.c */ |
38 | u8 lbs_data_rate_to_fw_index(u32 rate); | 22 | void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count); |
39 | |||
40 | /** The proc fs interface */ | ||
41 | int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len); | ||
42 | void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, | ||
43 | int result); | ||
44 | netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, | 23 | netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, |
45 | struct net_device *dev); | 24 | struct net_device *dev); |
46 | int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band); | ||
47 | 25 | ||
26 | /* rx.c */ | ||
48 | int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *); | 27 | int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *); |
49 | 28 | ||
50 | void lbs_ps_sleep(struct lbs_private *priv, int wait_option); | ||
51 | void lbs_ps_confirm_sleep(struct lbs_private *priv); | ||
52 | void lbs_ps_wakeup(struct lbs_private *priv, int wait_option); | ||
53 | |||
54 | struct chan_freq_power *lbs_find_cfp_by_band_and_channel( | ||
55 | struct lbs_private *priv, | ||
56 | u8 band, | ||
57 | u16 channel); | ||
58 | |||
59 | void lbs_mac_event_disconnected(struct lbs_private *priv); | ||
60 | |||
61 | void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str); | ||
62 | |||
63 | /* persistcfg.c */ | ||
64 | void lbs_persist_config_init(struct net_device *net); | ||
65 | void lbs_persist_config_remove(struct net_device *net); | ||
66 | 29 | ||
67 | /* main.c */ | 30 | /* main.c */ |
68 | struct chan_freq_power *lbs_get_region_cfp_table(u8 region, | ||
69 | int *cfp_no); | ||
70 | struct lbs_private *lbs_add_card(void *card, struct device *dmdev); | 31 | struct lbs_private *lbs_add_card(void *card, struct device *dmdev); |
71 | void lbs_remove_card(struct lbs_private *priv); | 32 | void lbs_remove_card(struct lbs_private *priv); |
72 | int lbs_start_card(struct lbs_private *priv); | 33 | int lbs_start_card(struct lbs_private *priv); |
73 | void lbs_stop_card(struct lbs_private *priv); | 34 | void lbs_stop_card(struct lbs_private *priv); |
74 | void lbs_host_to_card_done(struct lbs_private *priv); | 35 | void lbs_host_to_card_done(struct lbs_private *priv); |
75 | 36 | ||
76 | int lbs_update_channel(struct lbs_private *priv); | 37 | int lbs_set_mac_address(struct net_device *dev, void *addr); |
38 | void lbs_set_multicast_list(struct net_device *dev); | ||
39 | |||
40 | int lbs_suspend(struct lbs_private *priv); | ||
41 | void lbs_resume(struct lbs_private *priv); | ||
42 | |||
43 | void lbs_queue_event(struct lbs_private *priv, u32 event); | ||
44 | void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); | ||
45 | |||
46 | int lbs_enter_auto_deep_sleep(struct lbs_private *priv); | ||
47 | int lbs_exit_auto_deep_sleep(struct lbs_private *priv); | ||
48 | |||
49 | u32 lbs_fw_index_to_data_rate(u8 index); | ||
50 | u8 lbs_data_rate_to_fw_index(u32 rate); | ||
51 | |||
77 | 52 | ||
78 | #endif | 53 | #endif |
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index 72f3479a4d70..ea3f10ef4e00 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h | |||
@@ -42,6 +42,7 @@ | |||
42 | #define LBS_DEB_SDIO 0x00400000 | 42 | #define LBS_DEB_SDIO 0x00400000 |
43 | #define LBS_DEB_SYSFS 0x00800000 | 43 | #define LBS_DEB_SYSFS 0x00800000 |
44 | #define LBS_DEB_SPI 0x01000000 | 44 | #define LBS_DEB_SPI 0x01000000 |
45 | #define LBS_DEB_CFG80211 0x02000000 | ||
45 | 46 | ||
46 | extern unsigned int lbs_debug; | 47 | extern unsigned int lbs_debug; |
47 | 48 | ||
@@ -86,6 +87,7 @@ do { if ((lbs_debug & (grp)) == (grp)) \ | |||
86 | #define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args) | 87 | #define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args) |
87 | #define lbs_deb_sysfs(fmt, args...) LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args) | 88 | #define lbs_deb_sysfs(fmt, args...) LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args) |
88 | #define lbs_deb_spi(fmt, args...) LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args) | 89 | #define lbs_deb_spi(fmt, args...) LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args) |
90 | #define lbs_deb_cfg80211(fmt, args...) LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args) | ||
89 | 91 | ||
90 | #define lbs_pr_info(format, args...) \ | 92 | #define lbs_pr_info(format, args...) \ |
91 | printk(KERN_INFO DRV_NAME": " format, ## args) | 93 | printk(KERN_INFO DRV_NAME": " format, ## args) |
@@ -320,7 +322,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in | |||
320 | extern const char lbs_driver_version[]; | 322 | extern const char lbs_driver_version[]; |
321 | extern u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE]; | 323 | extern u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE]; |
322 | 324 | ||
323 | extern u8 lbs_bg_rates[MAX_RATES]; | ||
324 | 325 | ||
325 | /** ENUM definition*/ | 326 | /** ENUM definition*/ |
326 | /** SNRNF_TYPE */ | 327 | /** SNRNF_TYPE */ |
@@ -396,13 +397,6 @@ enum KEY_INFO_WPA { | |||
396 | KEY_INFO_WPA_ENABLED = 0x04 | 397 | KEY_INFO_WPA_ENABLED = 0x04 |
397 | }; | 398 | }; |
398 | 399 | ||
399 | /** mesh_fw_ver */ | ||
400 | enum _mesh_fw_ver { | ||
401 | MESH_NONE = 0, /* MESH is not supported */ | ||
402 | MESH_FW_OLD, /* MESH is supported in FW V5 */ | ||
403 | MESH_FW_NEW, /* MESH is supported in FW V10 and newer */ | ||
404 | }; | ||
405 | |||
406 | /* Default values for fwt commands. */ | 400 | /* Default values for fwt commands. */ |
407 | #define FWT_DEFAULT_METRIC 0 | 401 | #define FWT_DEFAULT_METRIC 0 |
408 | #define FWT_DEFAULT_DIR 1 | 402 | #define FWT_DEFAULT_DIR 1 |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index d3b69a4b4b5e..6875e1498bd5 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -6,75 +6,11 @@ | |||
6 | #ifndef _LBS_DEV_H_ | 6 | #ifndef _LBS_DEV_H_ |
7 | #define _LBS_DEV_H_ | 7 | #define _LBS_DEV_H_ |
8 | 8 | ||
9 | #include <linux/netdevice.h> | 9 | #include "mesh.h" |
10 | #include <linux/wireless.h> | 10 | #include "scan.h" |
11 | #include <linux/ethtool.h> | 11 | #include "assoc.h" |
12 | #include <linux/debugfs.h> | ||
13 | 12 | ||
14 | #include "defs.h" | 13 | #include <linux/kfifo.h> |
15 | #include "hostcmd.h" | ||
16 | |||
17 | extern const struct ethtool_ops lbs_ethtool_ops; | ||
18 | |||
19 | #define MAX_BSSID_PER_CHANNEL 16 | ||
20 | |||
21 | #define NR_TX_QUEUE 3 | ||
22 | |||
23 | /* For the extended Scan */ | ||
24 | #define MAX_EXTENDED_SCAN_BSSID_LIST MAX_BSSID_PER_CHANNEL * \ | ||
25 | MRVDRV_MAX_CHANNEL_SIZE + 1 | ||
26 | |||
27 | #define MAX_REGION_CHANNEL_NUM 2 | ||
28 | |||
29 | /** Chan-freq-TxPower mapping table*/ | ||
30 | struct chan_freq_power { | ||
31 | /** channel Number */ | ||
32 | u16 channel; | ||
33 | /** frequency of this channel */ | ||
34 | u32 freq; | ||
35 | /** Max allowed Tx power level */ | ||
36 | u16 maxtxpower; | ||
37 | /** TRUE:channel unsupported; FLASE:supported*/ | ||
38 | u8 unsupported; | ||
39 | }; | ||
40 | |||
41 | /** region-band mapping table*/ | ||
42 | struct region_channel { | ||
43 | /** TRUE if this entry is valid */ | ||
44 | u8 valid; | ||
45 | /** region code for US, Japan ... */ | ||
46 | u8 region; | ||
47 | /** band B/G/A, used for BAND_CONFIG cmd */ | ||
48 | u8 band; | ||
49 | /** Actual No. of elements in the array below */ | ||
50 | u8 nrcfp; | ||
51 | /** chan-freq-txpower mapping table*/ | ||
52 | struct chan_freq_power *CFP; | ||
53 | }; | ||
54 | |||
55 | struct lbs_802_11_security { | ||
56 | u8 WPAenabled; | ||
57 | u8 WPA2enabled; | ||
58 | u8 wep_enabled; | ||
59 | u8 auth_mode; | ||
60 | u32 key_mgmt; | ||
61 | }; | ||
62 | |||
63 | /** Current Basic Service Set State Structure */ | ||
64 | struct current_bss_params { | ||
65 | /** bssid */ | ||
66 | u8 bssid[ETH_ALEN]; | ||
67 | /** ssid */ | ||
68 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; | ||
69 | u8 ssid_len; | ||
70 | |||
71 | /** band */ | ||
72 | u8 band; | ||
73 | /** channel */ | ||
74 | u8 channel; | ||
75 | /** zero-terminated array of supported data rates */ | ||
76 | u8 rates[MAX_RATES + 1]; | ||
77 | }; | ||
78 | 14 | ||
79 | /** sleep_params */ | 15 | /** sleep_params */ |
80 | struct sleep_params { | 16 | struct sleep_params { |
@@ -86,205 +22,173 @@ struct sleep_params { | |||
86 | uint16_t sp_reserved; | 22 | uint16_t sp_reserved; |
87 | }; | 23 | }; |
88 | 24 | ||
89 | /* Mesh statistics */ | ||
90 | struct lbs_mesh_stats { | ||
91 | u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */ | ||
92 | u32 fwd_unicast_cnt; /* Fwd: Unicast counter */ | ||
93 | u32 fwd_drop_ttl; /* Fwd: TTL zero */ | ||
94 | u32 fwd_drop_rbt; /* Fwd: Recently Broadcasted */ | ||
95 | u32 fwd_drop_noroute; /* Fwd: No route to Destination */ | ||
96 | u32 fwd_drop_nobuf; /* Fwd: Run out of internal buffers */ | ||
97 | u32 drop_blind; /* Rx: Dropped by blinding table */ | ||
98 | u32 tx_failed_cnt; /* Tx: Failed transmissions */ | ||
99 | }; | ||
100 | 25 | ||
101 | /** Private structure for the MV device */ | 26 | /** Private structure for the MV device */ |
102 | struct lbs_private { | 27 | struct lbs_private { |
103 | int mesh_open; | ||
104 | int mesh_fw_ver; | ||
105 | int infra_open; | ||
106 | int mesh_autostart_enabled; | ||
107 | |||
108 | char name[DEV_NAME_LEN]; | ||
109 | 28 | ||
110 | void *card; | 29 | /* Basic networking */ |
111 | struct net_device *dev; | 30 | struct net_device *dev; |
31 | u32 connect_status; | ||
32 | int infra_open; | ||
33 | struct work_struct mcast_work; | ||
34 | u32 nr_of_multicastmacaddr; | ||
35 | u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; | ||
36 | |||
37 | /* CFG80211 */ | ||
38 | struct wireless_dev *wdev; | ||
39 | bool wiphy_registered; | ||
112 | 40 | ||
41 | /* Mesh */ | ||
113 | struct net_device *mesh_dev; /* Virtual device */ | 42 | struct net_device *mesh_dev; /* Virtual device */ |
43 | #ifdef CONFIG_LIBERTAS_MESH | ||
44 | u32 mesh_connect_status; | ||
45 | struct lbs_mesh_stats mstats; | ||
46 | int mesh_open; | ||
47 | uint16_t mesh_tlv; | ||
48 | u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1]; | ||
49 | u8 mesh_ssid_len; | ||
50 | #endif | ||
51 | |||
52 | /* Monitor mode */ | ||
114 | struct net_device *rtap_net_dev; | 53 | struct net_device *rtap_net_dev; |
54 | u32 monitormode; | ||
115 | 55 | ||
116 | struct iw_statistics wstats; | 56 | /* Debugfs */ |
117 | struct lbs_mesh_stats mstats; | ||
118 | struct dentry *debugfs_dir; | 57 | struct dentry *debugfs_dir; |
119 | struct dentry *debugfs_debug; | 58 | struct dentry *debugfs_debug; |
120 | struct dentry *debugfs_files[6]; | 59 | struct dentry *debugfs_files[6]; |
121 | |||
122 | struct dentry *events_dir; | 60 | struct dentry *events_dir; |
123 | struct dentry *debugfs_events_files[6]; | 61 | struct dentry *debugfs_events_files[6]; |
124 | |||
125 | struct dentry *regs_dir; | 62 | struct dentry *regs_dir; |
126 | struct dentry *debugfs_regs_files[6]; | 63 | struct dentry *debugfs_regs_files[6]; |
127 | 64 | ||
65 | /* Hardware debugging */ | ||
128 | u32 mac_offset; | 66 | u32 mac_offset; |
129 | u32 bbp_offset; | 67 | u32 bbp_offset; |
130 | u32 rf_offset; | 68 | u32 rf_offset; |
69 | struct lbs_offset_value offsetvalue; | ||
131 | 70 | ||
132 | /* Download sent: | 71 | /* Power management */ |
133 | bit0 1/0=data_sent/data_tx_done, | 72 | u16 psmode; |
134 | bit1 1/0=cmd_sent/cmd_tx_done, | 73 | u32 psstate; |
135 | all other bits reserved 0 */ | 74 | u8 needtowakeup; |
136 | u8 dnld_sent; | ||
137 | |||
138 | /** thread to service interrupts */ | ||
139 | struct task_struct *main_thread; | ||
140 | wait_queue_head_t waitq; | ||
141 | struct workqueue_struct *work_thread; | ||
142 | 75 | ||
143 | struct work_struct mcast_work; | 76 | /* Deep sleep */ |
77 | int is_deep_sleep; | ||
78 | int is_auto_deep_sleep_enabled; | ||
79 | int wakeup_dev_required; | ||
80 | int is_activity_detected; | ||
81 | int auto_deep_sleep_timeout; /* in ms */ | ||
82 | wait_queue_head_t ds_awake_q; | ||
83 | struct timer_list auto_deepsleep_timer; | ||
144 | 84 | ||
145 | /** Scanning */ | 85 | /* Hardware access */ |
146 | struct delayed_work scan_work; | 86 | void *card; |
147 | struct delayed_work assoc_work; | 87 | u8 fw_ready; |
148 | struct work_struct sync_channel; | 88 | u8 surpriseremoved; |
149 | /* remember which channel was scanned last, != 0 if currently scanning */ | ||
150 | int scan_channel; | ||
151 | u8 scan_ssid[IW_ESSID_MAX_SIZE + 1]; | ||
152 | u8 scan_ssid_len; | ||
153 | |||
154 | /** Hardware access */ | ||
155 | int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); | 89 | int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); |
156 | void (*reset_card) (struct lbs_private *priv); | 90 | void (*reset_card) (struct lbs_private *priv); |
91 | int (*enter_deep_sleep) (struct lbs_private *priv); | ||
92 | int (*exit_deep_sleep) (struct lbs_private *priv); | ||
93 | int (*reset_deep_sleep_wakeup) (struct lbs_private *priv); | ||
157 | 94 | ||
158 | /* Wake On LAN */ | 95 | /* Adapter info (from EEPROM) */ |
159 | uint32_t wol_criteria; | ||
160 | uint8_t wol_gpio; | ||
161 | uint8_t wol_gap; | ||
162 | |||
163 | /** Wlan adapter data structure*/ | ||
164 | /** STATUS variables */ | ||
165 | u32 fwrelease; | 96 | u32 fwrelease; |
166 | u32 fwcapinfo; | 97 | u32 fwcapinfo; |
98 | u16 regioncode; | ||
99 | u8 current_addr[ETH_ALEN]; | ||
167 | 100 | ||
168 | struct mutex lock; | 101 | /* Command download */ |
169 | 102 | u8 dnld_sent; | |
170 | /* TX packet ready to be sent... */ | 103 | /* bit0 1/0=data_sent/data_tx_done, |
171 | int tx_pending_len; /* -1 while building packet */ | 104 | bit1 1/0=cmd_sent/cmd_tx_done, |
172 | 105 | all other bits reserved 0 */ | |
173 | u8 tx_pending_buf[LBS_UPLD_SIZE]; | ||
174 | /* protected by hard_start_xmit serialization */ | ||
175 | |||
176 | /** command-related variables */ | ||
177 | u16 seqnum; | 106 | u16 seqnum; |
178 | |||
179 | struct cmd_ctrl_node *cmd_array; | 107 | struct cmd_ctrl_node *cmd_array; |
180 | /** Current command */ | ||
181 | struct cmd_ctrl_node *cur_cmd; | 108 | struct cmd_ctrl_node *cur_cmd; |
182 | int cur_cmd_retcode; | 109 | struct list_head cmdfreeq; /* free command buffers */ |
183 | /** command Queues */ | 110 | struct list_head cmdpendingq; /* pending command buffers */ |
184 | /** Free command buffers */ | ||
185 | struct list_head cmdfreeq; | ||
186 | /** Pending command buffers */ | ||
187 | struct list_head cmdpendingq; | ||
188 | |||
189 | wait_queue_head_t cmd_pending; | 111 | wait_queue_head_t cmd_pending; |
112 | struct timer_list command_timer; | ||
113 | int cmd_timed_out; | ||
190 | 114 | ||
191 | /* Command responses sent from the hardware to the driver */ | 115 | /* Command responses sent from the hardware to the driver */ |
116 | int cur_cmd_retcode; | ||
192 | u8 resp_idx; | 117 | u8 resp_idx; |
193 | u8 resp_buf[2][LBS_UPLD_SIZE]; | 118 | u8 resp_buf[2][LBS_UPLD_SIZE]; |
194 | u32 resp_len[2]; | 119 | u32 resp_len[2]; |
195 | 120 | ||
196 | /* Events sent from hardware to driver */ | 121 | /* Events sent from hardware to driver */ |
197 | struct kfifo *event_fifo; | 122 | struct kfifo event_fifo; |
198 | |||
199 | /* nickname */ | ||
200 | u8 nodename[16]; | ||
201 | |||
202 | /** spin locks */ | ||
203 | spinlock_t driver_lock; | ||
204 | |||
205 | /** Timers */ | ||
206 | struct timer_list command_timer; | ||
207 | int nr_retries; | ||
208 | int cmd_timed_out; | ||
209 | |||
210 | /** current ssid/bssid related parameters*/ | ||
211 | struct current_bss_params curbssparams; | ||
212 | 123 | ||
213 | uint16_t mesh_tlv; | 124 | /** thread to service interrupts */ |
214 | u8 mesh_ssid[IW_ESSID_MAX_SIZE + 1]; | 125 | struct task_struct *main_thread; |
215 | u8 mesh_ssid_len; | 126 | wait_queue_head_t waitq; |
216 | 127 | struct workqueue_struct *work_thread; | |
217 | /* IW_MODE_* */ | ||
218 | u8 mode; | ||
219 | |||
220 | /* Scan results list */ | ||
221 | struct list_head network_list; | ||
222 | struct list_head network_free_list; | ||
223 | struct bss_descriptor *networks; | ||
224 | |||
225 | u16 beacon_period; | ||
226 | u8 beacon_enable; | ||
227 | u8 adhoccreate; | ||
228 | |||
229 | /** capability Info used in Association, start, join */ | ||
230 | u16 capability; | ||
231 | |||
232 | /** MAC address information */ | ||
233 | u8 current_addr[ETH_ALEN]; | ||
234 | u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; | ||
235 | u32 nr_of_multicastmacaddr; | ||
236 | 128 | ||
237 | /** 802.11 statistics */ | 129 | /** Encryption stuff */ |
238 | // struct cmd_DS_802_11_GET_STAT wlan802_11Stat; | 130 | struct lbs_802_11_security secinfo; |
131 | struct enc_key wpa_mcast_key; | ||
132 | struct enc_key wpa_unicast_key; | ||
133 | u8 wpa_ie[MAX_WPA_IE_LEN]; | ||
134 | u8 wpa_ie_len; | ||
135 | u16 wep_tx_keyidx; | ||
136 | struct enc_key wep_keys[4]; | ||
239 | 137 | ||
240 | uint16_t enablehwauto; | 138 | /* Wake On LAN */ |
241 | uint16_t ratebitmap; | 139 | uint32_t wol_criteria; |
140 | uint8_t wol_gpio; | ||
141 | uint8_t wol_gap; | ||
242 | 142 | ||
143 | /* Transmitting */ | ||
144 | int tx_pending_len; /* -1 while building packet */ | ||
145 | u8 tx_pending_buf[LBS_UPLD_SIZE]; | ||
146 | /* protected by hard_start_xmit serialization */ | ||
243 | u8 txretrycount; | 147 | u8 txretrycount; |
244 | |||
245 | /** Tx-related variables (for single packet tx) */ | ||
246 | struct sk_buff *currenttxskb; | 148 | struct sk_buff *currenttxskb; |
247 | 149 | ||
248 | /** NIC Operation characteristics */ | 150 | /* Locks */ |
151 | struct mutex lock; | ||
152 | spinlock_t driver_lock; | ||
153 | |||
154 | /* NIC/link operation characteristics */ | ||
249 | u16 mac_control; | 155 | u16 mac_control; |
250 | u32 connect_status; | 156 | u8 radio_on; |
251 | u32 mesh_connect_status; | 157 | u8 channel; |
252 | u16 regioncode; | ||
253 | s16 txpower_cur; | 158 | s16 txpower_cur; |
254 | s16 txpower_min; | 159 | s16 txpower_min; |
255 | s16 txpower_max; | 160 | s16 txpower_max; |
256 | 161 | ||
257 | /** POWER MANAGEMENT AND PnP SUPPORT */ | 162 | /** Scanning */ |
258 | u8 surpriseremoved; | 163 | struct delayed_work scan_work; |
259 | 164 | int scan_channel; | |
260 | u16 psmode; /* Wlan802_11PowermodeCAM=disable | 165 | /* remember which channel was scanned last, != 0 if currently scanning */ |
261 | Wlan802_11PowermodeMAX_PSP=enable */ | 166 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN + 1]; |
262 | u32 psstate; | 167 | u8 scan_ssid_len; |
263 | u8 needtowakeup; | ||
264 | 168 | ||
169 | /* Associating */ | ||
170 | struct delayed_work assoc_work; | ||
171 | struct current_bss_params curbssparams; | ||
172 | u8 mode; | ||
173 | struct list_head network_list; | ||
174 | struct list_head network_free_list; | ||
175 | struct bss_descriptor *networks; | ||
265 | struct assoc_request * pending_assoc_req; | 176 | struct assoc_request * pending_assoc_req; |
266 | struct assoc_request * in_progress_assoc_req; | 177 | struct assoc_request * in_progress_assoc_req; |
178 | uint16_t enablehwauto; | ||
267 | 179 | ||
268 | /** Encryption parameter */ | 180 | /* ADHOC */ |
269 | struct lbs_802_11_security secinfo; | 181 | u16 beacon_period; |
270 | 182 | u8 beacon_enable; | |
271 | /** WEP keys */ | 183 | u8 adhoccreate; |
272 | struct enc_key wep_keys[4]; | ||
273 | u16 wep_tx_keyidx; | ||
274 | |||
275 | /** WPA keys */ | ||
276 | struct enc_key wpa_mcast_key; | ||
277 | struct enc_key wpa_unicast_key; | ||
278 | |||
279 | /* | ||
280 | * In theory, the IE is limited to the IE length, 255, | ||
281 | * but in practice 64 bytes are enough. | ||
282 | */ | ||
283 | #define MAX_WPA_IE_LEN 64 | ||
284 | 184 | ||
285 | /** WPA Information Elements*/ | 185 | /* WEXT */ |
286 | u8 wpa_ie[MAX_WPA_IE_LEN]; | 186 | char name[DEV_NAME_LEN]; |
287 | u8 wpa_ie_len; | 187 | u8 nodename[16]; |
188 | struct iw_statistics wstats; | ||
189 | u8 cur_rate; | ||
190 | #define MAX_REGION_CHANNEL_NUM 2 | ||
191 | struct region_channel region_channel[MAX_REGION_CHANNEL_NUM]; | ||
288 | 192 | ||
289 | /** Requested Signal Strength*/ | 193 | /** Requested Signal Strength*/ |
290 | u16 SNR[MAX_TYPE_B][MAX_TYPE_AVG]; | 194 | u16 SNR[MAX_TYPE_B][MAX_TYPE_AVG]; |
@@ -294,116 +198,8 @@ struct lbs_private { | |||
294 | u8 rawNF[DEFAULT_DATA_AVG_FACTOR]; | 198 | u8 rawNF[DEFAULT_DATA_AVG_FACTOR]; |
295 | u16 nextSNRNF; | 199 | u16 nextSNRNF; |
296 | u16 numSNRNF; | 200 | u16 numSNRNF; |
297 | |||
298 | u8 radio_on; | ||
299 | |||
300 | /** data rate stuff */ | ||
301 | u8 cur_rate; | ||
302 | |||
303 | /** RF calibration data */ | ||
304 | |||
305 | #define MAX_REGION_CHANNEL_NUM 2 | ||
306 | /** region channel data */ | ||
307 | struct region_channel region_channel[MAX_REGION_CHANNEL_NUM]; | ||
308 | |||
309 | struct region_channel universal_channel[MAX_REGION_CHANNEL_NUM]; | ||
310 | |||
311 | /** 11D and Domain Regulatory Data */ | ||
312 | struct lbs_802_11d_domain_reg domainreg; | ||
313 | struct parsed_region_chan_11d parsed_region_chan; | ||
314 | |||
315 | /** FSM variable for 11d support */ | ||
316 | u32 enable11d; | ||
317 | |||
318 | /** MISCELLANEOUS */ | ||
319 | struct lbs_offset_value offsetvalue; | ||
320 | |||
321 | u32 monitormode; | ||
322 | u8 fw_ready; | ||
323 | }; | 201 | }; |
324 | 202 | ||
325 | extern struct cmd_confirm_sleep confirm_sleep; | 203 | extern struct cmd_confirm_sleep confirm_sleep; |
326 | 204 | ||
327 | /** | ||
328 | * @brief Structure used to store information for each beacon/probe response | ||
329 | */ | ||
330 | struct bss_descriptor { | ||
331 | u8 bssid[ETH_ALEN]; | ||
332 | |||
333 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; | ||
334 | u8 ssid_len; | ||
335 | |||
336 | u16 capability; | ||
337 | u32 rssi; | ||
338 | u32 channel; | ||
339 | u16 beaconperiod; | ||
340 | __le16 atimwindow; | ||
341 | |||
342 | /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */ | ||
343 | u8 mode; | ||
344 | |||
345 | /* zero-terminated array of supported data rates */ | ||
346 | u8 rates[MAX_RATES + 1]; | ||
347 | |||
348 | unsigned long last_scanned; | ||
349 | |||
350 | union ieee_phy_param_set phy; | ||
351 | union ieee_ss_param_set ss; | ||
352 | |||
353 | struct ieee_ie_country_info_full_set countryinfo; | ||
354 | |||
355 | u8 wpa_ie[MAX_WPA_IE_LEN]; | ||
356 | size_t wpa_ie_len; | ||
357 | u8 rsn_ie[MAX_WPA_IE_LEN]; | ||
358 | size_t rsn_ie_len; | ||
359 | |||
360 | u8 mesh; | ||
361 | |||
362 | struct list_head list; | ||
363 | }; | ||
364 | |||
365 | /** Association request | ||
366 | * | ||
367 | * Encapsulates all the options that describe a specific assocation request | ||
368 | * or configuration of the wireless card's radio, mode, and security settings. | ||
369 | */ | ||
370 | struct assoc_request { | ||
371 | #define ASSOC_FLAG_SSID 1 | ||
372 | #define ASSOC_FLAG_CHANNEL 2 | ||
373 | #define ASSOC_FLAG_BAND 3 | ||
374 | #define ASSOC_FLAG_MODE 4 | ||
375 | #define ASSOC_FLAG_BSSID 5 | ||
376 | #define ASSOC_FLAG_WEP_KEYS 6 | ||
377 | #define ASSOC_FLAG_WEP_TX_KEYIDX 7 | ||
378 | #define ASSOC_FLAG_WPA_MCAST_KEY 8 | ||
379 | #define ASSOC_FLAG_WPA_UCAST_KEY 9 | ||
380 | #define ASSOC_FLAG_SECINFO 10 | ||
381 | #define ASSOC_FLAG_WPA_IE 11 | ||
382 | unsigned long flags; | ||
383 | |||
384 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; | ||
385 | u8 ssid_len; | ||
386 | u8 channel; | ||
387 | u8 band; | ||
388 | u8 mode; | ||
389 | u8 bssid[ETH_ALEN] __attribute__ ((aligned (2))); | ||
390 | |||
391 | /** WEP keys */ | ||
392 | struct enc_key wep_keys[4]; | ||
393 | u16 wep_tx_keyidx; | ||
394 | |||
395 | /** WPA keys */ | ||
396 | struct enc_key wpa_mcast_key; | ||
397 | struct enc_key wpa_unicast_key; | ||
398 | |||
399 | struct lbs_802_11_security secinfo; | ||
400 | |||
401 | /** WPA Information Elements*/ | ||
402 | u8 wpa_ie[MAX_WPA_IE_LEN]; | ||
403 | u8 wpa_ie_len; | ||
404 | |||
405 | /* BSS to associate with for infrastructure of Ad-Hoc join */ | ||
406 | struct bss_descriptor bss; | ||
407 | }; | ||
408 | |||
409 | #endif | 205 | #endif |
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index 53d56ab83c03..3804a58d7f4e 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c | |||
@@ -8,17 +8,8 @@ | |||
8 | #include "dev.h" | 8 | #include "dev.h" |
9 | #include "wext.h" | 9 | #include "wext.h" |
10 | #include "cmd.h" | 10 | #include "cmd.h" |
11 | #include "mesh.h" | ||
11 | 12 | ||
12 | static const char * mesh_stat_strings[]= { | ||
13 | "drop_duplicate_bcast", | ||
14 | "drop_ttl_zero", | ||
15 | "drop_no_fwd_route", | ||
16 | "drop_no_buffers", | ||
17 | "fwded_unicast_cnt", | ||
18 | "fwded_bcast_cnt", | ||
19 | "drop_blind_table", | ||
20 | "tx_failed_cnt" | ||
21 | }; | ||
22 | 13 | ||
23 | static void lbs_ethtool_get_drvinfo(struct net_device *dev, | 14 | static void lbs_ethtool_get_drvinfo(struct net_device *dev, |
24 | struct ethtool_drvinfo *info) | 15 | struct ethtool_drvinfo *info) |
@@ -73,73 +64,6 @@ out: | |||
73 | return ret; | 64 | return ret; |
74 | } | 65 | } |
75 | 66 | ||
76 | static void lbs_ethtool_get_stats(struct net_device *dev, | ||
77 | struct ethtool_stats *stats, uint64_t *data) | ||
78 | { | ||
79 | struct lbs_private *priv = dev->ml_priv; | ||
80 | struct cmd_ds_mesh_access mesh_access; | ||
81 | int ret; | ||
82 | |||
83 | lbs_deb_enter(LBS_DEB_ETHTOOL); | ||
84 | |||
85 | /* Get Mesh Statistics */ | ||
86 | ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access); | ||
87 | |||
88 | if (ret) { | ||
89 | memset(data, 0, MESH_STATS_NUM*(sizeof(uint64_t))); | ||
90 | return; | ||
91 | } | ||
92 | |||
93 | priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]); | ||
94 | priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]); | ||
95 | priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]); | ||
96 | priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]); | ||
97 | priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]); | ||
98 | priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]); | ||
99 | priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]); | ||
100 | priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]); | ||
101 | |||
102 | data[0] = priv->mstats.fwd_drop_rbt; | ||
103 | data[1] = priv->mstats.fwd_drop_ttl; | ||
104 | data[2] = priv->mstats.fwd_drop_noroute; | ||
105 | data[3] = priv->mstats.fwd_drop_nobuf; | ||
106 | data[4] = priv->mstats.fwd_unicast_cnt; | ||
107 | data[5] = priv->mstats.fwd_bcast_cnt; | ||
108 | data[6] = priv->mstats.drop_blind; | ||
109 | data[7] = priv->mstats.tx_failed_cnt; | ||
110 | |||
111 | lbs_deb_enter(LBS_DEB_ETHTOOL); | ||
112 | } | ||
113 | |||
114 | static int lbs_ethtool_get_sset_count(struct net_device *dev, int sset) | ||
115 | { | ||
116 | struct lbs_private *priv = dev->ml_priv; | ||
117 | |||
118 | if (sset == ETH_SS_STATS && dev == priv->mesh_dev) | ||
119 | return MESH_STATS_NUM; | ||
120 | |||
121 | return -EOPNOTSUPP; | ||
122 | } | ||
123 | |||
124 | static void lbs_ethtool_get_strings(struct net_device *dev, | ||
125 | uint32_t stringset, uint8_t *s) | ||
126 | { | ||
127 | int i; | ||
128 | |||
129 | lbs_deb_enter(LBS_DEB_ETHTOOL); | ||
130 | |||
131 | switch (stringset) { | ||
132 | case ETH_SS_STATS: | ||
133 | for (i=0; i < MESH_STATS_NUM; i++) { | ||
134 | memcpy(s + i * ETH_GSTRING_LEN, | ||
135 | mesh_stat_strings[i], | ||
136 | ETH_GSTRING_LEN); | ||
137 | } | ||
138 | break; | ||
139 | } | ||
140 | lbs_deb_enter(LBS_DEB_ETHTOOL); | ||
141 | } | ||
142 | |||
143 | static void lbs_ethtool_get_wol(struct net_device *dev, | 67 | static void lbs_ethtool_get_wol(struct net_device *dev, |
144 | struct ethtool_wolinfo *wol) | 68 | struct ethtool_wolinfo *wol) |
145 | { | 69 | { |
@@ -190,9 +114,11 @@ const struct ethtool_ops lbs_ethtool_ops = { | |||
190 | .get_drvinfo = lbs_ethtool_get_drvinfo, | 114 | .get_drvinfo = lbs_ethtool_get_drvinfo, |
191 | .get_eeprom = lbs_ethtool_get_eeprom, | 115 | .get_eeprom = lbs_ethtool_get_eeprom, |
192 | .get_eeprom_len = lbs_ethtool_get_eeprom_len, | 116 | .get_eeprom_len = lbs_ethtool_get_eeprom_len, |
193 | .get_sset_count = lbs_ethtool_get_sset_count, | 117 | #ifdef CONFIG_LIBERTAS_MESH |
194 | .get_ethtool_stats = lbs_ethtool_get_stats, | 118 | .get_sset_count = lbs_mesh_ethtool_get_sset_count, |
195 | .get_strings = lbs_ethtool_get_strings, | 119 | .get_ethtool_stats = lbs_mesh_ethtool_get_stats, |
120 | .get_strings = lbs_mesh_ethtool_get_strings, | ||
121 | #endif | ||
196 | .get_wol = lbs_ethtool_get_wol, | 122 | .get_wol = lbs_ethtool_get_wol, |
197 | .set_wol = lbs_ethtool_set_wol, | 123 | .set_wol = lbs_ethtool_set_wol, |
198 | }; | 124 | }; |
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index fe8f0cb737bc..3809c0b49464 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h | |||
@@ -1,201 +1,190 @@ | |||
1 | /** | 1 | /** |
2 | * This file contains definitions of WLAN commands. | 2 | * This file function prototypes, data structure |
3 | * and definitions for all the host/station commands | ||
3 | */ | 4 | */ |
4 | 5 | ||
5 | #ifndef _LBS_HOST_H_ | 6 | #ifndef _LBS_HOST_H_ |
6 | #define _LBS_HOST_H_ | 7 | #define _LBS_HOST_H_ |
7 | 8 | ||
8 | /** PUBLIC DEFINITIONS */ | 9 | #include "types.h" |
9 | #define DEFAULT_AD_HOC_CHANNEL 6 | 10 | #include "defs.h" |
10 | #define DEFAULT_AD_HOC_CHANNEL_A 36 | ||
11 | 11 | ||
12 | #define CMD_OPTION_WAITFORRSP 0x0002 | 12 | #define DEFAULT_AD_HOC_CHANNEL 6 |
13 | |||
14 | #define CMD_OPTION_WAITFORRSP 0x0002 | ||
13 | 15 | ||
14 | /** Host command IDs */ | 16 | /** Host command IDs */ |
15 | 17 | ||
16 | /* Return command are almost always the same as the host command, but with | 18 | /* Return command are almost always the same as the host command, but with |
17 | * bit 15 set high. There are a few exceptions, though... | 19 | * bit 15 set high. There are a few exceptions, though... |
18 | */ | 20 | */ |
19 | #define CMD_RET(cmd) (0x8000 | cmd) | 21 | #define CMD_RET(cmd) (0x8000 | cmd) |
20 | 22 | ||
21 | /* Return command convention exceptions: */ | 23 | /* Return command convention exceptions: */ |
22 | #define CMD_RET_802_11_ASSOCIATE 0x8012 | 24 | #define CMD_RET_802_11_ASSOCIATE 0x8012 |
23 | 25 | ||
24 | /* Command codes */ | 26 | /* Command codes */ |
25 | #define CMD_GET_HW_SPEC 0x0003 | 27 | #define CMD_GET_HW_SPEC 0x0003 |
26 | #define CMD_EEPROM_UPDATE 0x0004 | 28 | #define CMD_EEPROM_UPDATE 0x0004 |
27 | #define CMD_802_11_RESET 0x0005 | 29 | #define CMD_802_11_RESET 0x0005 |
28 | #define CMD_802_11_SCAN 0x0006 | 30 | #define CMD_802_11_SCAN 0x0006 |
29 | #define CMD_802_11_GET_LOG 0x000b | 31 | #define CMD_802_11_GET_LOG 0x000b |
30 | #define CMD_MAC_MULTICAST_ADR 0x0010 | 32 | #define CMD_MAC_MULTICAST_ADR 0x0010 |
31 | #define CMD_802_11_AUTHENTICATE 0x0011 | 33 | #define CMD_802_11_AUTHENTICATE 0x0011 |
32 | #define CMD_802_11_EEPROM_ACCESS 0x0059 | 34 | #define CMD_802_11_EEPROM_ACCESS 0x0059 |
33 | #define CMD_802_11_ASSOCIATE 0x0050 | 35 | #define CMD_802_11_ASSOCIATE 0x0050 |
34 | #define CMD_802_11_SET_WEP 0x0013 | 36 | #define CMD_802_11_SET_WEP 0x0013 |
35 | #define CMD_802_11_GET_STAT 0x0014 | 37 | #define CMD_802_11_GET_STAT 0x0014 |
36 | #define CMD_802_3_GET_STAT 0x0015 | 38 | #define CMD_802_3_GET_STAT 0x0015 |
37 | #define CMD_802_11_SNMP_MIB 0x0016 | 39 | #define CMD_802_11_SNMP_MIB 0x0016 |
38 | #define CMD_MAC_REG_MAP 0x0017 | 40 | #define CMD_MAC_REG_MAP 0x0017 |
39 | #define CMD_BBP_REG_MAP 0x0018 | 41 | #define CMD_BBP_REG_MAP 0x0018 |
40 | #define CMD_MAC_REG_ACCESS 0x0019 | 42 | #define CMD_MAC_REG_ACCESS 0x0019 |
41 | #define CMD_BBP_REG_ACCESS 0x001a | 43 | #define CMD_BBP_REG_ACCESS 0x001a |
42 | #define CMD_RF_REG_ACCESS 0x001b | 44 | #define CMD_RF_REG_ACCESS 0x001b |
43 | #define CMD_802_11_RADIO_CONTROL 0x001c | 45 | #define CMD_802_11_RADIO_CONTROL 0x001c |
44 | #define CMD_802_11_RF_CHANNEL 0x001d | 46 | #define CMD_802_11_RF_CHANNEL 0x001d |
45 | #define CMD_802_11_RF_TX_POWER 0x001e | 47 | #define CMD_802_11_RF_TX_POWER 0x001e |
46 | #define CMD_802_11_RSSI 0x001f | 48 | #define CMD_802_11_RSSI 0x001f |
47 | #define CMD_802_11_RF_ANTENNA 0x0020 | 49 | #define CMD_802_11_RF_ANTENNA 0x0020 |
48 | #define CMD_802_11_PS_MODE 0x0021 | 50 | #define CMD_802_11_PS_MODE 0x0021 |
49 | #define CMD_802_11_DATA_RATE 0x0022 | 51 | #define CMD_802_11_DATA_RATE 0x0022 |
50 | #define CMD_RF_REG_MAP 0x0023 | 52 | #define CMD_RF_REG_MAP 0x0023 |
51 | #define CMD_802_11_DEAUTHENTICATE 0x0024 | 53 | #define CMD_802_11_DEAUTHENTICATE 0x0024 |
52 | #define CMD_802_11_REASSOCIATE 0x0025 | 54 | #define CMD_802_11_REASSOCIATE 0x0025 |
53 | #define CMD_MAC_CONTROL 0x0028 | 55 | #define CMD_MAC_CONTROL 0x0028 |
54 | #define CMD_802_11_AD_HOC_START 0x002b | 56 | #define CMD_802_11_AD_HOC_START 0x002b |
55 | #define CMD_802_11_AD_HOC_JOIN 0x002c | 57 | #define CMD_802_11_AD_HOC_JOIN 0x002c |
56 | #define CMD_802_11_QUERY_TKIP_REPLY_CNTRS 0x002e | 58 | #define CMD_802_11_QUERY_TKIP_REPLY_CNTRS 0x002e |
57 | #define CMD_802_11_ENABLE_RSN 0x002f | 59 | #define CMD_802_11_ENABLE_RSN 0x002f |
58 | #define CMD_802_11_SET_AFC 0x003c | 60 | #define CMD_802_11_SET_AFC 0x003c |
59 | #define CMD_802_11_GET_AFC 0x003d | 61 | #define CMD_802_11_GET_AFC 0x003d |
60 | #define CMD_802_11_AD_HOC_STOP 0x0040 | 62 | #define CMD_802_11_DEEP_SLEEP 0x003e |
61 | #define CMD_802_11_HOST_SLEEP_CFG 0x0043 | 63 | #define CMD_802_11_AD_HOC_STOP 0x0040 |
62 | #define CMD_802_11_WAKEUP_CONFIRM 0x0044 | 64 | #define CMD_802_11_HOST_SLEEP_CFG 0x0043 |
63 | #define CMD_802_11_HOST_SLEEP_ACTIVATE 0x0045 | 65 | #define CMD_802_11_WAKEUP_CONFIRM 0x0044 |
64 | #define CMD_802_11_BEACON_STOP 0x0049 | 66 | #define CMD_802_11_HOST_SLEEP_ACTIVATE 0x0045 |
65 | #define CMD_802_11_MAC_ADDRESS 0x004d | 67 | #define CMD_802_11_BEACON_STOP 0x0049 |
66 | #define CMD_802_11_LED_GPIO_CTRL 0x004e | 68 | #define CMD_802_11_MAC_ADDRESS 0x004d |
67 | #define CMD_802_11_EEPROM_ACCESS 0x0059 | 69 | #define CMD_802_11_LED_GPIO_CTRL 0x004e |
68 | #define CMD_802_11_BAND_CONFIG 0x0058 | 70 | #define CMD_802_11_EEPROM_ACCESS 0x0059 |
69 | #define CMD_GSPI_BUS_CONFIG 0x005a | 71 | #define CMD_802_11_BAND_CONFIG 0x0058 |
70 | #define CMD_802_11D_DOMAIN_INFO 0x005b | 72 | #define CMD_GSPI_BUS_CONFIG 0x005a |
71 | #define CMD_802_11_KEY_MATERIAL 0x005e | 73 | #define CMD_802_11D_DOMAIN_INFO 0x005b |
72 | #define CMD_802_11_SLEEP_PARAMS 0x0066 | 74 | #define CMD_802_11_KEY_MATERIAL 0x005e |
73 | #define CMD_802_11_INACTIVITY_TIMEOUT 0x0067 | 75 | #define CMD_802_11_SLEEP_PARAMS 0x0066 |
74 | #define CMD_802_11_SLEEP_PERIOD 0x0068 | 76 | #define CMD_802_11_INACTIVITY_TIMEOUT 0x0067 |
75 | #define CMD_802_11_TPC_CFG 0x0072 | 77 | #define CMD_802_11_SLEEP_PERIOD 0x0068 |
76 | #define CMD_802_11_PA_CFG 0x0073 | 78 | #define CMD_802_11_TPC_CFG 0x0072 |
77 | #define CMD_802_11_FW_WAKE_METHOD 0x0074 | 79 | #define CMD_802_11_PA_CFG 0x0073 |
78 | #define CMD_802_11_SUBSCRIBE_EVENT 0x0075 | 80 | #define CMD_802_11_FW_WAKE_METHOD 0x0074 |
79 | #define CMD_802_11_RATE_ADAPT_RATESET 0x0076 | 81 | #define CMD_802_11_SUBSCRIBE_EVENT 0x0075 |
80 | #define CMD_802_11_TX_RATE_QUERY 0x007f | 82 | #define CMD_802_11_RATE_ADAPT_RATESET 0x0076 |
81 | #define CMD_GET_TSF 0x0080 | 83 | #define CMD_802_11_TX_RATE_QUERY 0x007f |
82 | #define CMD_BT_ACCESS 0x0087 | 84 | #define CMD_GET_TSF 0x0080 |
83 | #define CMD_FWT_ACCESS 0x0095 | 85 | #define CMD_BT_ACCESS 0x0087 |
84 | #define CMD_802_11_MONITOR_MODE 0x0098 | 86 | #define CMD_FWT_ACCESS 0x0095 |
85 | #define CMD_MESH_ACCESS 0x009b | 87 | #define CMD_802_11_MONITOR_MODE 0x0098 |
86 | #define CMD_MESH_CONFIG_OLD 0x00a3 | 88 | #define CMD_MESH_ACCESS 0x009b |
87 | #define CMD_MESH_CONFIG 0x00ac | 89 | #define CMD_MESH_CONFIG_OLD 0x00a3 |
88 | #define CMD_SET_BOOT2_VER 0x00a5 | 90 | #define CMD_MESH_CONFIG 0x00ac |
89 | #define CMD_FUNC_INIT 0x00a9 | 91 | #define CMD_SET_BOOT2_VER 0x00a5 |
90 | #define CMD_FUNC_SHUTDOWN 0x00aa | 92 | #define CMD_FUNC_INIT 0x00a9 |
91 | #define CMD_802_11_BEACON_CTRL 0x00b0 | 93 | #define CMD_FUNC_SHUTDOWN 0x00aa |
94 | #define CMD_802_11_BEACON_CTRL 0x00b0 | ||
92 | 95 | ||
93 | /* For the IEEE Power Save */ | 96 | /* For the IEEE Power Save */ |
94 | #define CMD_SUBCMD_ENTER_PS 0x0030 | 97 | #define CMD_SUBCMD_ENTER_PS 0x0030 |
95 | #define CMD_SUBCMD_EXIT_PS 0x0031 | 98 | #define CMD_SUBCMD_EXIT_PS 0x0031 |
96 | #define CMD_SUBCMD_SLEEP_CONFIRMED 0x0034 | 99 | #define CMD_SUBCMD_SLEEP_CONFIRMED 0x0034 |
97 | #define CMD_SUBCMD_FULL_POWERDOWN 0x0035 | 100 | #define CMD_SUBCMD_FULL_POWERDOWN 0x0035 |
98 | #define CMD_SUBCMD_FULL_POWERUP 0x0036 | 101 | #define CMD_SUBCMD_FULL_POWERUP 0x0036 |
99 | 102 | ||
100 | #define CMD_ENABLE_RSN 0x0001 | 103 | #define CMD_ENABLE_RSN 0x0001 |
101 | #define CMD_DISABLE_RSN 0x0000 | 104 | #define CMD_DISABLE_RSN 0x0000 |
102 | 105 | ||
103 | #define CMD_ACT_GET 0x0000 | 106 | #define CMD_ACT_GET 0x0000 |
104 | #define CMD_ACT_SET 0x0001 | 107 | #define CMD_ACT_SET 0x0001 |
105 | #define CMD_ACT_GET_AES 0x0002 | ||
106 | #define CMD_ACT_SET_AES 0x0003 | ||
107 | #define CMD_ACT_REMOVE_AES 0x0004 | ||
108 | 108 | ||
109 | /* Define action or option for CMD_802_11_SET_WEP */ | 109 | /* Define action or option for CMD_802_11_SET_WEP */ |
110 | #define CMD_ACT_ADD 0x0002 | 110 | #define CMD_ACT_ADD 0x0002 |
111 | #define CMD_ACT_REMOVE 0x0004 | 111 | #define CMD_ACT_REMOVE 0x0004 |
112 | #define CMD_ACT_USE_DEFAULT 0x0008 | ||
113 | |||
114 | #define CMD_TYPE_WEP_40_BIT 0x01 | ||
115 | #define CMD_TYPE_WEP_104_BIT 0x02 | ||
116 | 112 | ||
117 | #define CMD_NUM_OF_WEP_KEYS 4 | 113 | #define CMD_TYPE_WEP_40_BIT 0x01 |
114 | #define CMD_TYPE_WEP_104_BIT 0x02 | ||
118 | 115 | ||
119 | #define CMD_WEP_KEY_INDEX_MASK 0x3fff | 116 | #define CMD_NUM_OF_WEP_KEYS 4 |
120 | 117 | ||
121 | /* Define action or option for CMD_802_11_RESET */ | 118 | #define CMD_WEP_KEY_INDEX_MASK 0x3fff |
122 | #define CMD_ACT_HALT 0x0003 | ||
123 | 119 | ||
124 | /* Define action or option for CMD_802_11_SCAN */ | 120 | /* Define action or option for CMD_802_11_SCAN */ |
125 | #define CMD_BSS_TYPE_BSS 0x0001 | 121 | #define CMD_BSS_TYPE_BSS 0x0001 |
126 | #define CMD_BSS_TYPE_IBSS 0x0002 | 122 | #define CMD_BSS_TYPE_IBSS 0x0002 |
127 | #define CMD_BSS_TYPE_ANY 0x0003 | 123 | #define CMD_BSS_TYPE_ANY 0x0003 |
128 | 124 | ||
129 | /* Define action or option for CMD_802_11_SCAN */ | 125 | /* Define action or option for CMD_802_11_SCAN */ |
130 | #define CMD_SCAN_TYPE_ACTIVE 0x0000 | 126 | #define CMD_SCAN_TYPE_ACTIVE 0x0000 |
131 | #define CMD_SCAN_TYPE_PASSIVE 0x0001 | 127 | #define CMD_SCAN_TYPE_PASSIVE 0x0001 |
132 | 128 | ||
133 | #define CMD_SCAN_RADIO_TYPE_BG 0 | 129 | #define CMD_SCAN_RADIO_TYPE_BG 0 |
134 | 130 | ||
135 | #define CMD_SCAN_PROBE_DELAY_TIME 0 | 131 | #define CMD_SCAN_PROBE_DELAY_TIME 0 |
136 | 132 | ||
137 | /* Define action or option for CMD_MAC_CONTROL */ | 133 | /* Define action or option for CMD_MAC_CONTROL */ |
138 | #define CMD_ACT_MAC_RX_ON 0x0001 | 134 | #define CMD_ACT_MAC_RX_ON 0x0001 |
139 | #define CMD_ACT_MAC_TX_ON 0x0002 | 135 | #define CMD_ACT_MAC_TX_ON 0x0002 |
140 | #define CMD_ACT_MAC_LOOPBACK_ON 0x0004 | 136 | #define CMD_ACT_MAC_LOOPBACK_ON 0x0004 |
141 | #define CMD_ACT_MAC_WEP_ENABLE 0x0008 | 137 | #define CMD_ACT_MAC_WEP_ENABLE 0x0008 |
142 | #define CMD_ACT_MAC_INT_ENABLE 0x0010 | 138 | #define CMD_ACT_MAC_INT_ENABLE 0x0010 |
143 | #define CMD_ACT_MAC_MULTICAST_ENABLE 0x0020 | 139 | #define CMD_ACT_MAC_MULTICAST_ENABLE 0x0020 |
144 | #define CMD_ACT_MAC_BROADCAST_ENABLE 0x0040 | 140 | #define CMD_ACT_MAC_BROADCAST_ENABLE 0x0040 |
145 | #define CMD_ACT_MAC_PROMISCUOUS_ENABLE 0x0080 | 141 | #define CMD_ACT_MAC_PROMISCUOUS_ENABLE 0x0080 |
146 | #define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100 | 142 | #define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100 |
147 | #define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400 | 143 | #define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400 |
148 | 144 | ||
149 | /* Event flags for CMD_802_11_SUBSCRIBE_EVENT */ | 145 | /* Event flags for CMD_802_11_SUBSCRIBE_EVENT */ |
150 | #define CMD_SUBSCRIBE_RSSI_LOW 0x0001 | 146 | #define CMD_SUBSCRIBE_RSSI_LOW 0x0001 |
151 | #define CMD_SUBSCRIBE_SNR_LOW 0x0002 | 147 | #define CMD_SUBSCRIBE_SNR_LOW 0x0002 |
152 | #define CMD_SUBSCRIBE_FAILCOUNT 0x0004 | 148 | #define CMD_SUBSCRIBE_FAILCOUNT 0x0004 |
153 | #define CMD_SUBSCRIBE_BCNMISS 0x0008 | 149 | #define CMD_SUBSCRIBE_BCNMISS 0x0008 |
154 | #define CMD_SUBSCRIBE_RSSI_HIGH 0x0010 | 150 | #define CMD_SUBSCRIBE_RSSI_HIGH 0x0010 |
155 | #define CMD_SUBSCRIBE_SNR_HIGH 0x0020 | 151 | #define CMD_SUBSCRIBE_SNR_HIGH 0x0020 |
156 | 152 | ||
157 | #define RADIO_PREAMBLE_LONG 0x00 | 153 | #define RADIO_PREAMBLE_LONG 0x00 |
158 | #define RADIO_PREAMBLE_SHORT 0x02 | 154 | #define RADIO_PREAMBLE_SHORT 0x02 |
159 | #define RADIO_PREAMBLE_AUTO 0x04 | 155 | #define RADIO_PREAMBLE_AUTO 0x04 |
160 | 156 | ||
161 | /* Define action or option for CMD_802_11_RF_CHANNEL */ | 157 | /* Define action or option for CMD_802_11_RF_CHANNEL */ |
162 | #define CMD_OPT_802_11_RF_CHANNEL_GET 0x00 | 158 | #define CMD_OPT_802_11_RF_CHANNEL_GET 0x00 |
163 | #define CMD_OPT_802_11_RF_CHANNEL_SET 0x01 | 159 | #define CMD_OPT_802_11_RF_CHANNEL_SET 0x01 |
164 | 160 | ||
165 | /* Define action or option for CMD_802_11_DATA_RATE */ | 161 | /* Define action or option for CMD_802_11_DATA_RATE */ |
166 | #define CMD_ACT_SET_TX_AUTO 0x0000 | 162 | #define CMD_ACT_SET_TX_AUTO 0x0000 |
167 | #define CMD_ACT_SET_TX_FIX_RATE 0x0001 | 163 | #define CMD_ACT_SET_TX_FIX_RATE 0x0001 |
168 | #define CMD_ACT_GET_TX_RATE 0x0002 | 164 | #define CMD_ACT_GET_TX_RATE 0x0002 |
169 | |||
170 | #define CMD_ACT_SET_RX 0x0001 | ||
171 | #define CMD_ACT_SET_TX 0x0002 | ||
172 | #define CMD_ACT_SET_BOTH 0x0003 | ||
173 | #define CMD_ACT_GET_RX 0x0004 | ||
174 | #define CMD_ACT_GET_TX 0x0008 | ||
175 | #define CMD_ACT_GET_BOTH 0x000c | ||
176 | 165 | ||
177 | /* Define action or option for CMD_802_11_PS_MODE */ | 166 | /* Define action or option for CMD_802_11_PS_MODE */ |
178 | #define CMD_TYPE_CAM 0x0000 | 167 | #define CMD_TYPE_CAM 0x0000 |
179 | #define CMD_TYPE_MAX_PSP 0x0001 | 168 | #define CMD_TYPE_MAX_PSP 0x0001 |
180 | #define CMD_TYPE_FAST_PSP 0x0002 | 169 | #define CMD_TYPE_FAST_PSP 0x0002 |
181 | 170 | ||
182 | /* Options for CMD_802_11_FW_WAKE_METHOD */ | 171 | /* Options for CMD_802_11_FW_WAKE_METHOD */ |
183 | #define CMD_WAKE_METHOD_UNCHANGED 0x0000 | 172 | #define CMD_WAKE_METHOD_UNCHANGED 0x0000 |
184 | #define CMD_WAKE_METHOD_COMMAND_INT 0x0001 | 173 | #define CMD_WAKE_METHOD_COMMAND_INT 0x0001 |
185 | #define CMD_WAKE_METHOD_GPIO 0x0002 | 174 | #define CMD_WAKE_METHOD_GPIO 0x0002 |
186 | 175 | ||
187 | /* Object IDs for CMD_802_11_SNMP_MIB */ | 176 | /* Object IDs for CMD_802_11_SNMP_MIB */ |
188 | #define SNMP_MIB_OID_BSS_TYPE 0x0000 | 177 | #define SNMP_MIB_OID_BSS_TYPE 0x0000 |
189 | #define SNMP_MIB_OID_OP_RATE_SET 0x0001 | 178 | #define SNMP_MIB_OID_OP_RATE_SET 0x0001 |
190 | #define SNMP_MIB_OID_BEACON_PERIOD 0x0002 /* Reserved on v9+ */ | 179 | #define SNMP_MIB_OID_BEACON_PERIOD 0x0002 /* Reserved on v9+ */ |
191 | #define SNMP_MIB_OID_DTIM_PERIOD 0x0003 /* Reserved on v9+ */ | 180 | #define SNMP_MIB_OID_DTIM_PERIOD 0x0003 /* Reserved on v9+ */ |
192 | #define SNMP_MIB_OID_ASSOC_TIMEOUT 0x0004 /* Reserved on v9+ */ | 181 | #define SNMP_MIB_OID_ASSOC_TIMEOUT 0x0004 /* Reserved on v9+ */ |
193 | #define SNMP_MIB_OID_RTS_THRESHOLD 0x0005 | 182 | #define SNMP_MIB_OID_RTS_THRESHOLD 0x0005 |
194 | #define SNMP_MIB_OID_SHORT_RETRY_LIMIT 0x0006 | 183 | #define SNMP_MIB_OID_SHORT_RETRY_LIMIT 0x0006 |
195 | #define SNMP_MIB_OID_LONG_RETRY_LIMIT 0x0007 | 184 | #define SNMP_MIB_OID_LONG_RETRY_LIMIT 0x0007 |
196 | #define SNMP_MIB_OID_FRAG_THRESHOLD 0x0008 | 185 | #define SNMP_MIB_OID_FRAG_THRESHOLD 0x0008 |
197 | #define SNMP_MIB_OID_11D_ENABLE 0x0009 | 186 | #define SNMP_MIB_OID_11D_ENABLE 0x0009 |
198 | #define SNMP_MIB_OID_11H_ENABLE 0x000A | 187 | #define SNMP_MIB_OID_11H_ENABLE 0x000A |
199 | 188 | ||
200 | /* Define action or option for CMD_BT_ACCESS */ | 189 | /* Define action or option for CMD_BT_ACCESS */ |
201 | enum cmd_bt_access_opts { | 190 | enum cmd_bt_access_opts { |
@@ -302,4 +291,672 @@ enum cmd_mesh_config_types { | |||
302 | #define MACREG_INT_CODE_MESH_AUTO_STARTED 35 | 291 | #define MACREG_INT_CODE_MESH_AUTO_STARTED 35 |
303 | #define MACREG_INT_CODE_FIRMWARE_READY 48 | 292 | #define MACREG_INT_CODE_FIRMWARE_READY 48 |
304 | 293 | ||
294 | |||
295 | /* 802.11-related definitions */ | ||
296 | |||
297 | /* TxPD descriptor */ | ||
298 | struct txpd { | ||
299 | /* union to cope up with later FW revisions */ | ||
300 | union { | ||
301 | /* Current Tx packet status */ | ||
302 | __le32 tx_status; | ||
303 | struct { | ||
304 | /* BSS type: client, AP, etc. */ | ||
305 | u8 bss_type; | ||
306 | /* BSS number */ | ||
307 | u8 bss_num; | ||
308 | /* Reserved */ | ||
309 | __le16 reserved; | ||
310 | } bss; | ||
311 | } u; | ||
312 | /* Tx control */ | ||
313 | __le32 tx_control; | ||
314 | __le32 tx_packet_location; | ||
315 | /* Tx packet length */ | ||
316 | __le16 tx_packet_length; | ||
317 | /* First 2 byte of destination MAC address */ | ||
318 | u8 tx_dest_addr_high[2]; | ||
319 | /* Last 4 byte of destination MAC address */ | ||
320 | u8 tx_dest_addr_low[4]; | ||
321 | /* Pkt Priority */ | ||
322 | u8 priority; | ||
323 | /* Pkt Trasnit Power control */ | ||
324 | u8 powermgmt; | ||
325 | /* Amount of time the packet has been queued (units = 2ms) */ | ||
326 | u8 pktdelay_2ms; | ||
327 | /* reserved */ | ||
328 | u8 reserved1; | ||
329 | } __attribute__ ((packed)); | ||
330 | |||
331 | /* RxPD Descriptor */ | ||
332 | struct rxpd { | ||
333 | /* union to cope up with later FW revisions */ | ||
334 | union { | ||
335 | /* Current Rx packet status */ | ||
336 | __le16 status; | ||
337 | struct { | ||
338 | /* BSS type: client, AP, etc. */ | ||
339 | u8 bss_type; | ||
340 | /* BSS number */ | ||
341 | u8 bss_num; | ||
342 | } __attribute__ ((packed)) bss; | ||
343 | } __attribute__ ((packed)) u; | ||
344 | |||
345 | /* SNR */ | ||
346 | u8 snr; | ||
347 | |||
348 | /* Tx control */ | ||
349 | u8 rx_control; | ||
350 | |||
351 | /* Pkt length */ | ||
352 | __le16 pkt_len; | ||
353 | |||
354 | /* Noise Floor */ | ||
355 | u8 nf; | ||
356 | |||
357 | /* Rx Packet Rate */ | ||
358 | u8 rx_rate; | ||
359 | |||
360 | /* Pkt addr */ | ||
361 | __le32 pkt_ptr; | ||
362 | |||
363 | /* Next Rx RxPD addr */ | ||
364 | __le32 next_rxpd_ptr; | ||
365 | |||
366 | /* Pkt Priority */ | ||
367 | u8 priority; | ||
368 | u8 reserved[3]; | ||
369 | } __attribute__ ((packed)); | ||
370 | |||
371 | struct cmd_header { | ||
372 | __le16 command; | ||
373 | __le16 size; | ||
374 | __le16 seqnum; | ||
375 | __le16 result; | ||
376 | } __attribute__ ((packed)); | ||
377 | |||
378 | /* Generic structure to hold all key types. */ | ||
379 | struct enc_key { | ||
380 | u16 len; | ||
381 | u16 flags; /* KEY_INFO_* from defs.h */ | ||
382 | u16 type; /* KEY_TYPE_* from defs.h */ | ||
383 | u8 key[32]; | ||
384 | }; | ||
385 | |||
386 | /* lbs_offset_value */ | ||
387 | struct lbs_offset_value { | ||
388 | u32 offset; | ||
389 | u32 value; | ||
390 | } __attribute__ ((packed)); | ||
391 | |||
392 | /* | ||
393 | * Define data structure for CMD_GET_HW_SPEC | ||
394 | * This structure defines the response for the GET_HW_SPEC command | ||
395 | */ | ||
396 | struct cmd_ds_get_hw_spec { | ||
397 | struct cmd_header hdr; | ||
398 | |||
399 | /* HW Interface version number */ | ||
400 | __le16 hwifversion; | ||
401 | /* HW version number */ | ||
402 | __le16 version; | ||
403 | /* Max number of TxPD FW can handle */ | ||
404 | __le16 nr_txpd; | ||
405 | /* Max no of Multicast address */ | ||
406 | __le16 nr_mcast_adr; | ||
407 | /* MAC address */ | ||
408 | u8 permanentaddr[6]; | ||
409 | |||
410 | /* region Code */ | ||
411 | __le16 regioncode; | ||
412 | |||
413 | /* Number of antenna used */ | ||
414 | __le16 nr_antenna; | ||
415 | |||
416 | /* FW release number, example 0x01030304 = 2.3.4p1 */ | ||
417 | __le32 fwrelease; | ||
418 | |||
419 | /* Base Address of TxPD queue */ | ||
420 | __le32 wcb_base; | ||
421 | /* Read Pointer of RxPd queue */ | ||
422 | __le32 rxpd_rdptr; | ||
423 | |||
424 | /* Write Pointer of RxPd queue */ | ||
425 | __le32 rxpd_wrptr; | ||
426 | |||
427 | /*FW/HW capability */ | ||
428 | __le32 fwcapinfo; | ||
429 | } __attribute__ ((packed)); | ||
430 | |||
431 | struct cmd_ds_802_11_subscribe_event { | ||
432 | struct cmd_header hdr; | ||
433 | |||
434 | __le16 action; | ||
435 | __le16 events; | ||
436 | |||
437 | /* A TLV to the CMD_802_11_SUBSCRIBE_EVENT command can contain a | ||
438 | * number of TLVs. From the v5.1 manual, those TLVs would add up to | ||
439 | * 40 bytes. However, future firmware might add additional TLVs, so I | ||
440 | * bump this up a bit. | ||
441 | */ | ||
442 | uint8_t tlv[128]; | ||
443 | } __attribute__ ((packed)); | ||
444 | |||
445 | /* | ||
446 | * This scan handle Country Information IE(802.11d compliant) | ||
447 | * Define data structure for CMD_802_11_SCAN | ||
448 | */ | ||
449 | struct cmd_ds_802_11_scan { | ||
450 | struct cmd_header hdr; | ||
451 | |||
452 | uint8_t bsstype; | ||
453 | uint8_t bssid[ETH_ALEN]; | ||
454 | uint8_t tlvbuffer[0]; | ||
455 | } __attribute__ ((packed)); | ||
456 | |||
457 | struct cmd_ds_802_11_scan_rsp { | ||
458 | struct cmd_header hdr; | ||
459 | |||
460 | __le16 bssdescriptsize; | ||
461 | uint8_t nr_sets; | ||
462 | uint8_t bssdesc_and_tlvbuffer[0]; | ||
463 | } __attribute__ ((packed)); | ||
464 | |||
465 | struct cmd_ds_802_11_get_log { | ||
466 | struct cmd_header hdr; | ||
467 | |||
468 | __le32 mcasttxframe; | ||
469 | __le32 failed; | ||
470 | __le32 retry; | ||
471 | __le32 multiretry; | ||
472 | __le32 framedup; | ||
473 | __le32 rtssuccess; | ||
474 | __le32 rtsfailure; | ||
475 | __le32 ackfailure; | ||
476 | __le32 rxfrag; | ||
477 | __le32 mcastrxframe; | ||
478 | __le32 fcserror; | ||
479 | __le32 txframe; | ||
480 | __le32 wepundecryptable; | ||
481 | } __attribute__ ((packed)); | ||
482 | |||
483 | struct cmd_ds_mac_control { | ||
484 | struct cmd_header hdr; | ||
485 | __le16 action; | ||
486 | u16 reserved; | ||
487 | } __attribute__ ((packed)); | ||
488 | |||
489 | struct cmd_ds_mac_multicast_adr { | ||
490 | struct cmd_header hdr; | ||
491 | __le16 action; | ||
492 | __le16 nr_of_adrs; | ||
493 | u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; | ||
494 | } __attribute__ ((packed)); | ||
495 | |||
496 | struct cmd_ds_802_11_authenticate { | ||
497 | struct cmd_header hdr; | ||
498 | |||
499 | u8 bssid[ETH_ALEN]; | ||
500 | u8 authtype; | ||
501 | u8 reserved[10]; | ||
502 | } __attribute__ ((packed)); | ||
503 | |||
504 | struct cmd_ds_802_11_deauthenticate { | ||
505 | struct cmd_header hdr; | ||
506 | |||
507 | u8 macaddr[ETH_ALEN]; | ||
508 | __le16 reasoncode; | ||
509 | } __attribute__ ((packed)); | ||
510 | |||
511 | struct cmd_ds_802_11_associate { | ||
512 | struct cmd_header hdr; | ||
513 | |||
514 | u8 bssid[6]; | ||
515 | __le16 capability; | ||
516 | __le16 listeninterval; | ||
517 | __le16 bcnperiod; | ||
518 | u8 dtimperiod; | ||
519 | u8 iebuf[512]; /* Enough for required and most optional IEs */ | ||
520 | } __attribute__ ((packed)); | ||
521 | |||
522 | struct cmd_ds_802_11_associate_response { | ||
523 | struct cmd_header hdr; | ||
524 | |||
525 | __le16 capability; | ||
526 | __le16 statuscode; | ||
527 | __le16 aid; | ||
528 | u8 iebuf[512]; | ||
529 | } __attribute__ ((packed)); | ||
530 | |||
531 | struct cmd_ds_802_11_set_wep { | ||
532 | struct cmd_header hdr; | ||
533 | |||
534 | /* ACT_ADD, ACT_REMOVE or ACT_ENABLE */ | ||
535 | __le16 action; | ||
536 | |||
537 | /* key Index selected for Tx */ | ||
538 | __le16 keyindex; | ||
539 | |||
540 | /* 40, 128bit or TXWEP */ | ||
541 | uint8_t keytype[4]; | ||
542 | uint8_t keymaterial[4][16]; | ||
543 | } __attribute__ ((packed)); | ||
544 | |||
545 | struct cmd_ds_802_11_snmp_mib { | ||
546 | struct cmd_header hdr; | ||
547 | |||
548 | __le16 action; | ||
549 | __le16 oid; | ||
550 | __le16 bufsize; | ||
551 | u8 value[128]; | ||
552 | } __attribute__ ((packed)); | ||
553 | |||
554 | struct cmd_ds_mac_reg_access { | ||
555 | __le16 action; | ||
556 | __le16 offset; | ||
557 | __le32 value; | ||
558 | } __attribute__ ((packed)); | ||
559 | |||
560 | struct cmd_ds_bbp_reg_access { | ||
561 | __le16 action; | ||
562 | __le16 offset; | ||
563 | u8 value; | ||
564 | u8 reserved[3]; | ||
565 | } __attribute__ ((packed)); | ||
566 | |||
567 | struct cmd_ds_rf_reg_access { | ||
568 | __le16 action; | ||
569 | __le16 offset; | ||
570 | u8 value; | ||
571 | u8 reserved[3]; | ||
572 | } __attribute__ ((packed)); | ||
573 | |||
574 | struct cmd_ds_802_11_radio_control { | ||
575 | struct cmd_header hdr; | ||
576 | |||
577 | __le16 action; | ||
578 | __le16 control; | ||
579 | } __attribute__ ((packed)); | ||
580 | |||
581 | struct cmd_ds_802_11_beacon_control { | ||
582 | __le16 action; | ||
583 | __le16 beacon_enable; | ||
584 | __le16 beacon_period; | ||
585 | } __attribute__ ((packed)); | ||
586 | |||
587 | struct cmd_ds_802_11_sleep_params { | ||
588 | struct cmd_header hdr; | ||
589 | |||
590 | /* ACT_GET/ACT_SET */ | ||
591 | __le16 action; | ||
592 | |||
593 | /* Sleep clock error in ppm */ | ||
594 | __le16 error; | ||
595 | |||
596 | /* Wakeup offset in usec */ | ||
597 | __le16 offset; | ||
598 | |||
599 | /* Clock stabilization time in usec */ | ||
600 | __le16 stabletime; | ||
601 | |||
602 | /* control periodic calibration */ | ||
603 | uint8_t calcontrol; | ||
604 | |||
605 | /* control the use of external sleep clock */ | ||
606 | uint8_t externalsleepclk; | ||
607 | |||
608 | /* reserved field, should be set to zero */ | ||
609 | __le16 reserved; | ||
610 | } __attribute__ ((packed)); | ||
611 | |||
612 | struct cmd_ds_802_11_rf_channel { | ||
613 | struct cmd_header hdr; | ||
614 | |||
615 | __le16 action; | ||
616 | __le16 channel; | ||
617 | __le16 rftype; /* unused */ | ||
618 | __le16 reserved; /* unused */ | ||
619 | u8 channellist[32]; /* unused */ | ||
620 | } __attribute__ ((packed)); | ||
621 | |||
622 | struct cmd_ds_802_11_rssi { | ||
623 | /* weighting factor */ | ||
624 | __le16 N; | ||
625 | |||
626 | __le16 reserved_0; | ||
627 | __le16 reserved_1; | ||
628 | __le16 reserved_2; | ||
629 | } __attribute__ ((packed)); | ||
630 | |||
631 | struct cmd_ds_802_11_rssi_rsp { | ||
632 | __le16 SNR; | ||
633 | __le16 noisefloor; | ||
634 | __le16 avgSNR; | ||
635 | __le16 avgnoisefloor; | ||
636 | } __attribute__ ((packed)); | ||
637 | |||
638 | struct cmd_ds_802_11_mac_address { | ||
639 | struct cmd_header hdr; | ||
640 | |||
641 | __le16 action; | ||
642 | u8 macadd[ETH_ALEN]; | ||
643 | } __attribute__ ((packed)); | ||
644 | |||
645 | struct cmd_ds_802_11_rf_tx_power { | ||
646 | struct cmd_header hdr; | ||
647 | |||
648 | __le16 action; | ||
649 | __le16 curlevel; | ||
650 | s8 maxlevel; | ||
651 | s8 minlevel; | ||
652 | } __attribute__ ((packed)); | ||
653 | |||
654 | struct cmd_ds_802_11_monitor_mode { | ||
655 | __le16 action; | ||
656 | __le16 mode; | ||
657 | } __attribute__ ((packed)); | ||
658 | |||
659 | struct cmd_ds_set_boot2_ver { | ||
660 | struct cmd_header hdr; | ||
661 | |||
662 | __le16 action; | ||
663 | __le16 version; | ||
664 | } __attribute__ ((packed)); | ||
665 | |||
666 | struct cmd_ds_802_11_fw_wake_method { | ||
667 | struct cmd_header hdr; | ||
668 | |||
669 | __le16 action; | ||
670 | __le16 method; | ||
671 | } __attribute__ ((packed)); | ||
672 | |||
673 | struct cmd_ds_802_11_ps_mode { | ||
674 | __le16 action; | ||
675 | __le16 nullpktinterval; | ||
676 | __le16 multipledtim; | ||
677 | __le16 reserved; | ||
678 | __le16 locallisteninterval; | ||
679 | } __attribute__ ((packed)); | ||
680 | |||
681 | struct cmd_confirm_sleep { | ||
682 | struct cmd_header hdr; | ||
683 | |||
684 | __le16 action; | ||
685 | __le16 nullpktinterval; | ||
686 | __le16 multipledtim; | ||
687 | __le16 reserved; | ||
688 | __le16 locallisteninterval; | ||
689 | } __attribute__ ((packed)); | ||
690 | |||
691 | struct cmd_ds_802_11_data_rate { | ||
692 | struct cmd_header hdr; | ||
693 | |||
694 | __le16 action; | ||
695 | __le16 reserved; | ||
696 | u8 rates[MAX_RATES]; | ||
697 | } __attribute__ ((packed)); | ||
698 | |||
699 | struct cmd_ds_802_11_rate_adapt_rateset { | ||
700 | struct cmd_header hdr; | ||
701 | __le16 action; | ||
702 | __le16 enablehwauto; | ||
703 | __le16 bitmap; | ||
704 | } __attribute__ ((packed)); | ||
705 | |||
706 | struct cmd_ds_802_11_ad_hoc_start { | ||
707 | struct cmd_header hdr; | ||
708 | |||
709 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
710 | u8 bsstype; | ||
711 | __le16 beaconperiod; | ||
712 | u8 dtimperiod; /* Reserved on v9 and later */ | ||
713 | struct ieee_ie_ibss_param_set ibss; | ||
714 | u8 reserved1[4]; | ||
715 | struct ieee_ie_ds_param_set ds; | ||
716 | u8 reserved2[4]; | ||
717 | __le16 probedelay; /* Reserved on v9 and later */ | ||
718 | __le16 capability; | ||
719 | u8 rates[MAX_RATES]; | ||
720 | u8 tlv_memory_size_pad[100]; | ||
721 | } __attribute__ ((packed)); | ||
722 | |||
723 | struct cmd_ds_802_11_ad_hoc_result { | ||
724 | struct cmd_header hdr; | ||
725 | |||
726 | u8 pad[3]; | ||
727 | u8 bssid[ETH_ALEN]; | ||
728 | } __attribute__ ((packed)); | ||
729 | |||
730 | struct adhoc_bssdesc { | ||
731 | u8 bssid[ETH_ALEN]; | ||
732 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
733 | u8 type; | ||
734 | __le16 beaconperiod; | ||
735 | u8 dtimperiod; | ||
736 | __le64 timestamp; | ||
737 | __le64 localtime; | ||
738 | struct ieee_ie_ds_param_set ds; | ||
739 | u8 reserved1[4]; | ||
740 | struct ieee_ie_ibss_param_set ibss; | ||
741 | u8 reserved2[4]; | ||
742 | __le16 capability; | ||
743 | u8 rates[MAX_RATES]; | ||
744 | |||
745 | /* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the | ||
746 | * Adhoc join command and will cause a binary layout mismatch with | ||
747 | * the firmware | ||
748 | */ | ||
749 | } __attribute__ ((packed)); | ||
750 | |||
751 | struct cmd_ds_802_11_ad_hoc_join { | ||
752 | struct cmd_header hdr; | ||
753 | |||
754 | struct adhoc_bssdesc bss; | ||
755 | __le16 failtimeout; /* Reserved on v9 and later */ | ||
756 | __le16 probedelay; /* Reserved on v9 and later */ | ||
757 | } __attribute__ ((packed)); | ||
758 | |||
759 | struct cmd_ds_802_11_ad_hoc_stop { | ||
760 | struct cmd_header hdr; | ||
761 | } __attribute__ ((packed)); | ||
762 | |||
763 | struct cmd_ds_802_11_enable_rsn { | ||
764 | struct cmd_header hdr; | ||
765 | |||
766 | __le16 action; | ||
767 | __le16 enable; | ||
768 | } __attribute__ ((packed)); | ||
769 | |||
770 | struct MrvlIEtype_keyParamSet { | ||
771 | /* type ID */ | ||
772 | __le16 type; | ||
773 | |||
774 | /* length of Payload */ | ||
775 | __le16 length; | ||
776 | |||
777 | /* type of key: WEP=0, TKIP=1, AES=2 */ | ||
778 | __le16 keytypeid; | ||
779 | |||
780 | /* key control Info specific to a keytypeid */ | ||
781 | __le16 keyinfo; | ||
782 | |||
783 | /* length of key */ | ||
784 | __le16 keylen; | ||
785 | |||
786 | /* key material of size keylen */ | ||
787 | u8 key[32]; | ||
788 | } __attribute__ ((packed)); | ||
789 | |||
790 | #define MAX_WOL_RULES 16 | ||
791 | |||
792 | struct host_wol_rule { | ||
793 | uint8_t rule_no; | ||
794 | uint8_t rule_ops; | ||
795 | __le16 sig_offset; | ||
796 | __le16 sig_length; | ||
797 | __le16 reserve; | ||
798 | __be32 sig_mask; | ||
799 | __be32 signature; | ||
800 | } __attribute__ ((packed)); | ||
801 | |||
802 | struct wol_config { | ||
803 | uint8_t action; | ||
804 | uint8_t pattern; | ||
805 | uint8_t no_rules_in_cmd; | ||
806 | uint8_t result; | ||
807 | struct host_wol_rule rule[MAX_WOL_RULES]; | ||
808 | } __attribute__ ((packed)); | ||
809 | |||
810 | struct cmd_ds_host_sleep { | ||
811 | struct cmd_header hdr; | ||
812 | __le32 criteria; | ||
813 | uint8_t gpio; | ||
814 | uint16_t gap; | ||
815 | struct wol_config wol_conf; | ||
816 | } __attribute__ ((packed)); | ||
817 | |||
818 | |||
819 | |||
820 | struct cmd_ds_802_11_key_material { | ||
821 | struct cmd_header hdr; | ||
822 | |||
823 | __le16 action; | ||
824 | struct MrvlIEtype_keyParamSet keyParamSet[2]; | ||
825 | } __attribute__ ((packed)); | ||
826 | |||
827 | struct cmd_ds_802_11_eeprom_access { | ||
828 | struct cmd_header hdr; | ||
829 | __le16 action; | ||
830 | __le16 offset; | ||
831 | __le16 len; | ||
832 | /* firmware says it returns a maximum of 20 bytes */ | ||
833 | #define LBS_EEPROM_READ_LEN 20 | ||
834 | u8 value[LBS_EEPROM_READ_LEN]; | ||
835 | } __attribute__ ((packed)); | ||
836 | |||
837 | struct cmd_ds_802_11_tpc_cfg { | ||
838 | struct cmd_header hdr; | ||
839 | |||
840 | __le16 action; | ||
841 | uint8_t enable; | ||
842 | int8_t P0; | ||
843 | int8_t P1; | ||
844 | int8_t P2; | ||
845 | uint8_t usesnr; | ||
846 | } __attribute__ ((packed)); | ||
847 | |||
848 | |||
849 | struct cmd_ds_802_11_pa_cfg { | ||
850 | struct cmd_header hdr; | ||
851 | |||
852 | __le16 action; | ||
853 | uint8_t enable; | ||
854 | int8_t P0; | ||
855 | int8_t P1; | ||
856 | int8_t P2; | ||
857 | } __attribute__ ((packed)); | ||
858 | |||
859 | |||
860 | struct cmd_ds_802_11_led_ctrl { | ||
861 | __le16 action; | ||
862 | __le16 numled; | ||
863 | u8 data[256]; | ||
864 | } __attribute__ ((packed)); | ||
865 | |||
866 | struct cmd_ds_802_11_afc { | ||
867 | __le16 afc_auto; | ||
868 | union { | ||
869 | struct { | ||
870 | __le16 threshold; | ||
871 | __le16 period; | ||
872 | }; | ||
873 | struct { | ||
874 | __le16 timing_offset; /* signed */ | ||
875 | __le16 carrier_offset; /* signed */ | ||
876 | }; | ||
877 | }; | ||
878 | } __attribute__ ((packed)); | ||
879 | |||
880 | struct cmd_tx_rate_query { | ||
881 | __le16 txrate; | ||
882 | } __attribute__ ((packed)); | ||
883 | |||
884 | struct cmd_ds_get_tsf { | ||
885 | __le64 tsfvalue; | ||
886 | } __attribute__ ((packed)); | ||
887 | |||
888 | struct cmd_ds_bt_access { | ||
889 | __le16 action; | ||
890 | __le32 id; | ||
891 | u8 addr1[ETH_ALEN]; | ||
892 | u8 addr2[ETH_ALEN]; | ||
893 | } __attribute__ ((packed)); | ||
894 | |||
895 | struct cmd_ds_fwt_access { | ||
896 | __le16 action; | ||
897 | __le32 id; | ||
898 | u8 valid; | ||
899 | u8 da[ETH_ALEN]; | ||
900 | u8 dir; | ||
901 | u8 ra[ETH_ALEN]; | ||
902 | __le32 ssn; | ||
903 | __le32 dsn; | ||
904 | __le32 metric; | ||
905 | u8 rate; | ||
906 | u8 hopcount; | ||
907 | u8 ttl; | ||
908 | __le32 expiration; | ||
909 | u8 sleepmode; | ||
910 | __le32 snr; | ||
911 | __le32 references; | ||
912 | u8 prec[ETH_ALEN]; | ||
913 | } __attribute__ ((packed)); | ||
914 | |||
915 | struct cmd_ds_mesh_config { | ||
916 | struct cmd_header hdr; | ||
917 | |||
918 | __le16 action; | ||
919 | __le16 channel; | ||
920 | __le16 type; | ||
921 | __le16 length; | ||
922 | u8 data[128]; /* last position reserved */ | ||
923 | } __attribute__ ((packed)); | ||
924 | |||
925 | struct cmd_ds_mesh_access { | ||
926 | struct cmd_header hdr; | ||
927 | |||
928 | __le16 action; | ||
929 | __le32 data[32]; /* last position reserved */ | ||
930 | } __attribute__ ((packed)); | ||
931 | |||
932 | /* Number of stats counters returned by the firmware */ | ||
933 | #define MESH_STATS_NUM 8 | ||
934 | |||
935 | struct cmd_ds_command { | ||
936 | /* command header */ | ||
937 | __le16 command; | ||
938 | __le16 size; | ||
939 | __le16 seqnum; | ||
940 | __le16 result; | ||
941 | |||
942 | /* command Body */ | ||
943 | union { | ||
944 | struct cmd_ds_802_11_ps_mode psmode; | ||
945 | struct cmd_ds_802_11_monitor_mode monitor; | ||
946 | struct cmd_ds_802_11_rssi rssi; | ||
947 | struct cmd_ds_802_11_rssi_rsp rssirsp; | ||
948 | struct cmd_ds_mac_reg_access macreg; | ||
949 | struct cmd_ds_bbp_reg_access bbpreg; | ||
950 | struct cmd_ds_rf_reg_access rfreg; | ||
951 | |||
952 | struct cmd_ds_802_11_tpc_cfg tpccfg; | ||
953 | struct cmd_ds_802_11_afc afc; | ||
954 | struct cmd_ds_802_11_led_ctrl ledgpio; | ||
955 | |||
956 | struct cmd_ds_bt_access bt; | ||
957 | struct cmd_ds_fwt_access fwt; | ||
958 | struct cmd_ds_802_11_beacon_control bcn_ctrl; | ||
959 | } params; | ||
960 | } __attribute__ ((packed)); | ||
961 | |||
305 | #endif | 962 | #endif |
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h deleted file mode 100644 index c8a1998d4744..000000000000 --- a/drivers/net/wireless/libertas/hostcmd.h +++ /dev/null | |||
@@ -1,800 +0,0 @@ | |||
1 | /* | ||
2 | * This file contains the function prototypes, data structure | ||
3 | * and defines for all the host/station commands | ||
4 | */ | ||
5 | #ifndef _LBS_HOSTCMD_H | ||
6 | #define _LBS_HOSTCMD_H | ||
7 | |||
8 | #include <linux/wireless.h> | ||
9 | #include "11d.h" | ||
10 | #include "types.h" | ||
11 | |||
12 | /* 802.11-related definitions */ | ||
13 | |||
14 | /* TxPD descriptor */ | ||
15 | struct txpd { | ||
16 | /* union to cope up with later FW revisions */ | ||
17 | union { | ||
18 | /* Current Tx packet status */ | ||
19 | __le32 tx_status; | ||
20 | struct { | ||
21 | /* BSS type: client, AP, etc. */ | ||
22 | u8 bss_type; | ||
23 | /* BSS number */ | ||
24 | u8 bss_num; | ||
25 | /* Reserved */ | ||
26 | __le16 reserved; | ||
27 | } bss; | ||
28 | } u; | ||
29 | /* Tx control */ | ||
30 | __le32 tx_control; | ||
31 | __le32 tx_packet_location; | ||
32 | /* Tx packet length */ | ||
33 | __le16 tx_packet_length; | ||
34 | /* First 2 byte of destination MAC address */ | ||
35 | u8 tx_dest_addr_high[2]; | ||
36 | /* Last 4 byte of destination MAC address */ | ||
37 | u8 tx_dest_addr_low[4]; | ||
38 | /* Pkt Priority */ | ||
39 | u8 priority; | ||
40 | /* Pkt Trasnit Power control */ | ||
41 | u8 powermgmt; | ||
42 | /* Amount of time the packet has been queued in the driver (units = 2ms) */ | ||
43 | u8 pktdelay_2ms; | ||
44 | /* reserved */ | ||
45 | u8 reserved1; | ||
46 | } __attribute__ ((packed)); | ||
47 | |||
48 | /* RxPD Descriptor */ | ||
49 | struct rxpd { | ||
50 | /* union to cope up with later FW revisions */ | ||
51 | union { | ||
52 | /* Current Rx packet status */ | ||
53 | __le16 status; | ||
54 | struct { | ||
55 | /* BSS type: client, AP, etc. */ | ||
56 | u8 bss_type; | ||
57 | /* BSS number */ | ||
58 | u8 bss_num; | ||
59 | } __attribute__ ((packed)) bss; | ||
60 | } __attribute__ ((packed)) u; | ||
61 | |||
62 | /* SNR */ | ||
63 | u8 snr; | ||
64 | |||
65 | /* Tx control */ | ||
66 | u8 rx_control; | ||
67 | |||
68 | /* Pkt length */ | ||
69 | __le16 pkt_len; | ||
70 | |||
71 | /* Noise Floor */ | ||
72 | u8 nf; | ||
73 | |||
74 | /* Rx Packet Rate */ | ||
75 | u8 rx_rate; | ||
76 | |||
77 | /* Pkt addr */ | ||
78 | __le32 pkt_ptr; | ||
79 | |||
80 | /* Next Rx RxPD addr */ | ||
81 | __le32 next_rxpd_ptr; | ||
82 | |||
83 | /* Pkt Priority */ | ||
84 | u8 priority; | ||
85 | u8 reserved[3]; | ||
86 | } __attribute__ ((packed)); | ||
87 | |||
88 | struct cmd_header { | ||
89 | __le16 command; | ||
90 | __le16 size; | ||
91 | __le16 seqnum; | ||
92 | __le16 result; | ||
93 | } __attribute__ ((packed)); | ||
94 | |||
95 | struct cmd_ctrl_node { | ||
96 | struct list_head list; | ||
97 | int result; | ||
98 | /* command response */ | ||
99 | int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *); | ||
100 | unsigned long callback_arg; | ||
101 | /* command data */ | ||
102 | struct cmd_header *cmdbuf; | ||
103 | /* wait queue */ | ||
104 | u16 cmdwaitqwoken; | ||
105 | wait_queue_head_t cmdwait_q; | ||
106 | }; | ||
107 | |||
108 | /* Generic structure to hold all key types. */ | ||
109 | struct enc_key { | ||
110 | u16 len; | ||
111 | u16 flags; /* KEY_INFO_* from defs.h */ | ||
112 | u16 type; /* KEY_TYPE_* from defs.h */ | ||
113 | u8 key[32]; | ||
114 | }; | ||
115 | |||
116 | /* lbs_offset_value */ | ||
117 | struct lbs_offset_value { | ||
118 | u32 offset; | ||
119 | u32 value; | ||
120 | } __attribute__ ((packed)); | ||
121 | |||
122 | /* Define general data structure */ | ||
123 | /* cmd_DS_GEN */ | ||
124 | struct cmd_ds_gen { | ||
125 | __le16 command; | ||
126 | __le16 size; | ||
127 | __le16 seqnum; | ||
128 | __le16 result; | ||
129 | void *cmdresp[0]; | ||
130 | } __attribute__ ((packed)); | ||
131 | |||
132 | #define S_DS_GEN sizeof(struct cmd_ds_gen) | ||
133 | |||
134 | |||
135 | /* | ||
136 | * Define data structure for CMD_GET_HW_SPEC | ||
137 | * This structure defines the response for the GET_HW_SPEC command | ||
138 | */ | ||
139 | struct cmd_ds_get_hw_spec { | ||
140 | struct cmd_header hdr; | ||
141 | |||
142 | /* HW Interface version number */ | ||
143 | __le16 hwifversion; | ||
144 | /* HW version number */ | ||
145 | __le16 version; | ||
146 | /* Max number of TxPD FW can handle */ | ||
147 | __le16 nr_txpd; | ||
148 | /* Max no of Multicast address */ | ||
149 | __le16 nr_mcast_adr; | ||
150 | /* MAC address */ | ||
151 | u8 permanentaddr[6]; | ||
152 | |||
153 | /* region Code */ | ||
154 | __le16 regioncode; | ||
155 | |||
156 | /* Number of antenna used */ | ||
157 | __le16 nr_antenna; | ||
158 | |||
159 | /* FW release number, example 0x01030304 = 2.3.4p1 */ | ||
160 | __le32 fwrelease; | ||
161 | |||
162 | /* Base Address of TxPD queue */ | ||
163 | __le32 wcb_base; | ||
164 | /* Read Pointer of RxPd queue */ | ||
165 | __le32 rxpd_rdptr; | ||
166 | |||
167 | /* Write Pointer of RxPd queue */ | ||
168 | __le32 rxpd_wrptr; | ||
169 | |||
170 | /*FW/HW capability */ | ||
171 | __le32 fwcapinfo; | ||
172 | } __attribute__ ((packed)); | ||
173 | |||
174 | struct cmd_ds_802_11_subscribe_event { | ||
175 | struct cmd_header hdr; | ||
176 | |||
177 | __le16 action; | ||
178 | __le16 events; | ||
179 | |||
180 | /* A TLV to the CMD_802_11_SUBSCRIBE_EVENT command can contain a | ||
181 | * number of TLVs. From the v5.1 manual, those TLVs would add up to | ||
182 | * 40 bytes. However, future firmware might add additional TLVs, so I | ||
183 | * bump this up a bit. | ||
184 | */ | ||
185 | uint8_t tlv[128]; | ||
186 | } __attribute__ ((packed)); | ||
187 | |||
188 | /* | ||
189 | * This scan handle Country Information IE(802.11d compliant) | ||
190 | * Define data structure for CMD_802_11_SCAN | ||
191 | */ | ||
192 | struct cmd_ds_802_11_scan { | ||
193 | struct cmd_header hdr; | ||
194 | |||
195 | uint8_t bsstype; | ||
196 | uint8_t bssid[ETH_ALEN]; | ||
197 | uint8_t tlvbuffer[0]; | ||
198 | #if 0 | ||
199 | mrvlietypes_ssidparamset_t ssidParamSet; | ||
200 | mrvlietypes_chanlistparamset_t ChanListParamSet; | ||
201 | mrvlietypes_ratesparamset_t OpRateSet; | ||
202 | #endif | ||
203 | } __attribute__ ((packed)); | ||
204 | |||
205 | struct cmd_ds_802_11_scan_rsp { | ||
206 | struct cmd_header hdr; | ||
207 | |||
208 | __le16 bssdescriptsize; | ||
209 | uint8_t nr_sets; | ||
210 | uint8_t bssdesc_and_tlvbuffer[0]; | ||
211 | } __attribute__ ((packed)); | ||
212 | |||
213 | struct cmd_ds_802_11_get_log { | ||
214 | struct cmd_header hdr; | ||
215 | |||
216 | __le32 mcasttxframe; | ||
217 | __le32 failed; | ||
218 | __le32 retry; | ||
219 | __le32 multiretry; | ||
220 | __le32 framedup; | ||
221 | __le32 rtssuccess; | ||
222 | __le32 rtsfailure; | ||
223 | __le32 ackfailure; | ||
224 | __le32 rxfrag; | ||
225 | __le32 mcastrxframe; | ||
226 | __le32 fcserror; | ||
227 | __le32 txframe; | ||
228 | __le32 wepundecryptable; | ||
229 | } __attribute__ ((packed)); | ||
230 | |||
231 | struct cmd_ds_mac_control { | ||
232 | struct cmd_header hdr; | ||
233 | __le16 action; | ||
234 | u16 reserved; | ||
235 | } __attribute__ ((packed)); | ||
236 | |||
237 | struct cmd_ds_mac_multicast_adr { | ||
238 | struct cmd_header hdr; | ||
239 | __le16 action; | ||
240 | __le16 nr_of_adrs; | ||
241 | u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; | ||
242 | } __attribute__ ((packed)); | ||
243 | |||
244 | struct cmd_ds_gspi_bus_config { | ||
245 | struct cmd_header hdr; | ||
246 | __le16 action; | ||
247 | __le16 bus_delay_mode; | ||
248 | __le16 host_time_delay_to_read_port; | ||
249 | __le16 host_time_delay_to_read_register; | ||
250 | } __attribute__ ((packed)); | ||
251 | |||
252 | struct cmd_ds_802_11_authenticate { | ||
253 | struct cmd_header hdr; | ||
254 | |||
255 | u8 bssid[ETH_ALEN]; | ||
256 | u8 authtype; | ||
257 | u8 reserved[10]; | ||
258 | } __attribute__ ((packed)); | ||
259 | |||
260 | struct cmd_ds_802_11_deauthenticate { | ||
261 | struct cmd_header hdr; | ||
262 | |||
263 | u8 macaddr[ETH_ALEN]; | ||
264 | __le16 reasoncode; | ||
265 | } __attribute__ ((packed)); | ||
266 | |||
267 | struct cmd_ds_802_11_associate { | ||
268 | struct cmd_header hdr; | ||
269 | |||
270 | u8 bssid[6]; | ||
271 | __le16 capability; | ||
272 | __le16 listeninterval; | ||
273 | __le16 bcnperiod; | ||
274 | u8 dtimperiod; | ||
275 | u8 iebuf[512]; /* Enough for required and most optional IEs */ | ||
276 | } __attribute__ ((packed)); | ||
277 | |||
278 | struct cmd_ds_802_11_associate_response { | ||
279 | struct cmd_header hdr; | ||
280 | |||
281 | __le16 capability; | ||
282 | __le16 statuscode; | ||
283 | __le16 aid; | ||
284 | u8 iebuf[512]; | ||
285 | } __attribute__ ((packed)); | ||
286 | |||
287 | struct cmd_ds_802_11_set_wep { | ||
288 | struct cmd_header hdr; | ||
289 | |||
290 | /* ACT_ADD, ACT_REMOVE or ACT_ENABLE */ | ||
291 | __le16 action; | ||
292 | |||
293 | /* key Index selected for Tx */ | ||
294 | __le16 keyindex; | ||
295 | |||
296 | /* 40, 128bit or TXWEP */ | ||
297 | uint8_t keytype[4]; | ||
298 | uint8_t keymaterial[4][16]; | ||
299 | } __attribute__ ((packed)); | ||
300 | |||
301 | struct cmd_ds_802_3_get_stat { | ||
302 | __le32 xmitok; | ||
303 | __le32 rcvok; | ||
304 | __le32 xmiterror; | ||
305 | __le32 rcverror; | ||
306 | __le32 rcvnobuffer; | ||
307 | __le32 rcvcrcerror; | ||
308 | } __attribute__ ((packed)); | ||
309 | |||
310 | struct cmd_ds_802_11_get_stat { | ||
311 | __le32 txfragmentcnt; | ||
312 | __le32 mcasttxframecnt; | ||
313 | __le32 failedcnt; | ||
314 | __le32 retrycnt; | ||
315 | __le32 Multipleretrycnt; | ||
316 | __le32 rtssuccesscnt; | ||
317 | __le32 rtsfailurecnt; | ||
318 | __le32 ackfailurecnt; | ||
319 | __le32 frameduplicatecnt; | ||
320 | __le32 rxfragmentcnt; | ||
321 | __le32 mcastrxframecnt; | ||
322 | __le32 fcserrorcnt; | ||
323 | __le32 bcasttxframecnt; | ||
324 | __le32 bcastrxframecnt; | ||
325 | __le32 txbeacon; | ||
326 | __le32 rxbeacon; | ||
327 | __le32 wepundecryptable; | ||
328 | } __attribute__ ((packed)); | ||
329 | |||
330 | struct cmd_ds_802_11_snmp_mib { | ||
331 | struct cmd_header hdr; | ||
332 | |||
333 | __le16 action; | ||
334 | __le16 oid; | ||
335 | __le16 bufsize; | ||
336 | u8 value[128]; | ||
337 | } __attribute__ ((packed)); | ||
338 | |||
339 | struct cmd_ds_mac_reg_map { | ||
340 | __le16 buffersize; | ||
341 | u8 regmap[128]; | ||
342 | __le16 reserved; | ||
343 | } __attribute__ ((packed)); | ||
344 | |||
345 | struct cmd_ds_bbp_reg_map { | ||
346 | __le16 buffersize; | ||
347 | u8 regmap[128]; | ||
348 | __le16 reserved; | ||
349 | } __attribute__ ((packed)); | ||
350 | |||
351 | struct cmd_ds_rf_reg_map { | ||
352 | __le16 buffersize; | ||
353 | u8 regmap[64]; | ||
354 | __le16 reserved; | ||
355 | } __attribute__ ((packed)); | ||
356 | |||
357 | struct cmd_ds_mac_reg_access { | ||
358 | __le16 action; | ||
359 | __le16 offset; | ||
360 | __le32 value; | ||
361 | } __attribute__ ((packed)); | ||
362 | |||
363 | struct cmd_ds_bbp_reg_access { | ||
364 | __le16 action; | ||
365 | __le16 offset; | ||
366 | u8 value; | ||
367 | u8 reserved[3]; | ||
368 | } __attribute__ ((packed)); | ||
369 | |||
370 | struct cmd_ds_rf_reg_access { | ||
371 | __le16 action; | ||
372 | __le16 offset; | ||
373 | u8 value; | ||
374 | u8 reserved[3]; | ||
375 | } __attribute__ ((packed)); | ||
376 | |||
377 | struct cmd_ds_802_11_radio_control { | ||
378 | struct cmd_header hdr; | ||
379 | |||
380 | __le16 action; | ||
381 | __le16 control; | ||
382 | } __attribute__ ((packed)); | ||
383 | |||
384 | struct cmd_ds_802_11_beacon_control { | ||
385 | __le16 action; | ||
386 | __le16 beacon_enable; | ||
387 | __le16 beacon_period; | ||
388 | } __attribute__ ((packed)); | ||
389 | |||
390 | struct cmd_ds_802_11_sleep_params { | ||
391 | struct cmd_header hdr; | ||
392 | |||
393 | /* ACT_GET/ACT_SET */ | ||
394 | __le16 action; | ||
395 | |||
396 | /* Sleep clock error in ppm */ | ||
397 | __le16 error; | ||
398 | |||
399 | /* Wakeup offset in usec */ | ||
400 | __le16 offset; | ||
401 | |||
402 | /* Clock stabilization time in usec */ | ||
403 | __le16 stabletime; | ||
404 | |||
405 | /* control periodic calibration */ | ||
406 | uint8_t calcontrol; | ||
407 | |||
408 | /* control the use of external sleep clock */ | ||
409 | uint8_t externalsleepclk; | ||
410 | |||
411 | /* reserved field, should be set to zero */ | ||
412 | __le16 reserved; | ||
413 | } __attribute__ ((packed)); | ||
414 | |||
415 | struct cmd_ds_802_11_inactivity_timeout { | ||
416 | struct cmd_header hdr; | ||
417 | |||
418 | /* ACT_GET/ACT_SET */ | ||
419 | __le16 action; | ||
420 | |||
421 | /* Inactivity timeout in msec */ | ||
422 | __le16 timeout; | ||
423 | } __attribute__ ((packed)); | ||
424 | |||
425 | struct cmd_ds_802_11_rf_channel { | ||
426 | struct cmd_header hdr; | ||
427 | |||
428 | __le16 action; | ||
429 | __le16 channel; | ||
430 | __le16 rftype; /* unused */ | ||
431 | __le16 reserved; /* unused */ | ||
432 | u8 channellist[32]; /* unused */ | ||
433 | } __attribute__ ((packed)); | ||
434 | |||
435 | struct cmd_ds_802_11_rssi { | ||
436 | /* weighting factor */ | ||
437 | __le16 N; | ||
438 | |||
439 | __le16 reserved_0; | ||
440 | __le16 reserved_1; | ||
441 | __le16 reserved_2; | ||
442 | } __attribute__ ((packed)); | ||
443 | |||
444 | struct cmd_ds_802_11_rssi_rsp { | ||
445 | __le16 SNR; | ||
446 | __le16 noisefloor; | ||
447 | __le16 avgSNR; | ||
448 | __le16 avgnoisefloor; | ||
449 | } __attribute__ ((packed)); | ||
450 | |||
451 | struct cmd_ds_802_11_mac_address { | ||
452 | struct cmd_header hdr; | ||
453 | |||
454 | __le16 action; | ||
455 | u8 macadd[ETH_ALEN]; | ||
456 | } __attribute__ ((packed)); | ||
457 | |||
458 | struct cmd_ds_802_11_rf_tx_power { | ||
459 | struct cmd_header hdr; | ||
460 | |||
461 | __le16 action; | ||
462 | __le16 curlevel; | ||
463 | s8 maxlevel; | ||
464 | s8 minlevel; | ||
465 | } __attribute__ ((packed)); | ||
466 | |||
467 | struct cmd_ds_802_11_rf_antenna { | ||
468 | __le16 action; | ||
469 | |||
470 | /* Number of antennas or 0xffff(diversity) */ | ||
471 | __le16 antennamode; | ||
472 | |||
473 | } __attribute__ ((packed)); | ||
474 | |||
475 | struct cmd_ds_802_11_monitor_mode { | ||
476 | __le16 action; | ||
477 | __le16 mode; | ||
478 | } __attribute__ ((packed)); | ||
479 | |||
480 | struct cmd_ds_set_boot2_ver { | ||
481 | struct cmd_header hdr; | ||
482 | |||
483 | __le16 action; | ||
484 | __le16 version; | ||
485 | } __attribute__ ((packed)); | ||
486 | |||
487 | struct cmd_ds_802_11_fw_wake_method { | ||
488 | struct cmd_header hdr; | ||
489 | |||
490 | __le16 action; | ||
491 | __le16 method; | ||
492 | } __attribute__ ((packed)); | ||
493 | |||
494 | struct cmd_ds_802_11_sleep_period { | ||
495 | struct cmd_header hdr; | ||
496 | |||
497 | __le16 action; | ||
498 | __le16 period; | ||
499 | } __attribute__ ((packed)); | ||
500 | |||
501 | struct cmd_ds_802_11_ps_mode { | ||
502 | __le16 action; | ||
503 | __le16 nullpktinterval; | ||
504 | __le16 multipledtim; | ||
505 | __le16 reserved; | ||
506 | __le16 locallisteninterval; | ||
507 | } __attribute__ ((packed)); | ||
508 | |||
509 | struct cmd_confirm_sleep { | ||
510 | struct cmd_header hdr; | ||
511 | |||
512 | __le16 action; | ||
513 | __le16 nullpktinterval; | ||
514 | __le16 multipledtim; | ||
515 | __le16 reserved; | ||
516 | __le16 locallisteninterval; | ||
517 | } __attribute__ ((packed)); | ||
518 | |||
519 | struct cmd_ds_802_11_data_rate { | ||
520 | struct cmd_header hdr; | ||
521 | |||
522 | __le16 action; | ||
523 | __le16 reserved; | ||
524 | u8 rates[MAX_RATES]; | ||
525 | } __attribute__ ((packed)); | ||
526 | |||
527 | struct cmd_ds_802_11_rate_adapt_rateset { | ||
528 | struct cmd_header hdr; | ||
529 | __le16 action; | ||
530 | __le16 enablehwauto; | ||
531 | __le16 bitmap; | ||
532 | } __attribute__ ((packed)); | ||
533 | |||
534 | struct cmd_ds_802_11_ad_hoc_start { | ||
535 | struct cmd_header hdr; | ||
536 | |||
537 | u8 ssid[IW_ESSID_MAX_SIZE]; | ||
538 | u8 bsstype; | ||
539 | __le16 beaconperiod; | ||
540 | u8 dtimperiod; /* Reserved on v9 and later */ | ||
541 | struct ieee_ie_ibss_param_set ibss; | ||
542 | u8 reserved1[4]; | ||
543 | struct ieee_ie_ds_param_set ds; | ||
544 | u8 reserved2[4]; | ||
545 | __le16 probedelay; /* Reserved on v9 and later */ | ||
546 | __le16 capability; | ||
547 | u8 rates[MAX_RATES]; | ||
548 | u8 tlv_memory_size_pad[100]; | ||
549 | } __attribute__ ((packed)); | ||
550 | |||
551 | struct cmd_ds_802_11_ad_hoc_result { | ||
552 | struct cmd_header hdr; | ||
553 | |||
554 | u8 pad[3]; | ||
555 | u8 bssid[ETH_ALEN]; | ||
556 | } __attribute__ ((packed)); | ||
557 | |||
558 | struct adhoc_bssdesc { | ||
559 | u8 bssid[ETH_ALEN]; | ||
560 | u8 ssid[IW_ESSID_MAX_SIZE]; | ||
561 | u8 type; | ||
562 | __le16 beaconperiod; | ||
563 | u8 dtimperiod; | ||
564 | __le64 timestamp; | ||
565 | __le64 localtime; | ||
566 | struct ieee_ie_ds_param_set ds; | ||
567 | u8 reserved1[4]; | ||
568 | struct ieee_ie_ibss_param_set ibss; | ||
569 | u8 reserved2[4]; | ||
570 | __le16 capability; | ||
571 | u8 rates[MAX_RATES]; | ||
572 | |||
573 | /* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the | ||
574 | * Adhoc join command and will cause a binary layout mismatch with | ||
575 | * the firmware | ||
576 | */ | ||
577 | } __attribute__ ((packed)); | ||
578 | |||
579 | struct cmd_ds_802_11_ad_hoc_join { | ||
580 | struct cmd_header hdr; | ||
581 | |||
582 | struct adhoc_bssdesc bss; | ||
583 | __le16 failtimeout; /* Reserved on v9 and later */ | ||
584 | __le16 probedelay; /* Reserved on v9 and later */ | ||
585 | } __attribute__ ((packed)); | ||
586 | |||
587 | struct cmd_ds_802_11_ad_hoc_stop { | ||
588 | struct cmd_header hdr; | ||
589 | } __attribute__ ((packed)); | ||
590 | |||
591 | struct cmd_ds_802_11_enable_rsn { | ||
592 | struct cmd_header hdr; | ||
593 | |||
594 | __le16 action; | ||
595 | __le16 enable; | ||
596 | } __attribute__ ((packed)); | ||
597 | |||
598 | struct MrvlIEtype_keyParamSet { | ||
599 | /* type ID */ | ||
600 | __le16 type; | ||
601 | |||
602 | /* length of Payload */ | ||
603 | __le16 length; | ||
604 | |||
605 | /* type of key: WEP=0, TKIP=1, AES=2 */ | ||
606 | __le16 keytypeid; | ||
607 | |||
608 | /* key control Info specific to a keytypeid */ | ||
609 | __le16 keyinfo; | ||
610 | |||
611 | /* length of key */ | ||
612 | __le16 keylen; | ||
613 | |||
614 | /* key material of size keylen */ | ||
615 | u8 key[32]; | ||
616 | } __attribute__ ((packed)); | ||
617 | |||
618 | #define MAX_WOL_RULES 16 | ||
619 | |||
620 | struct host_wol_rule { | ||
621 | uint8_t rule_no; | ||
622 | uint8_t rule_ops; | ||
623 | __le16 sig_offset; | ||
624 | __le16 sig_length; | ||
625 | __le16 reserve; | ||
626 | __be32 sig_mask; | ||
627 | __be32 signature; | ||
628 | } __attribute__ ((packed)); | ||
629 | |||
630 | struct wol_config { | ||
631 | uint8_t action; | ||
632 | uint8_t pattern; | ||
633 | uint8_t no_rules_in_cmd; | ||
634 | uint8_t result; | ||
635 | struct host_wol_rule rule[MAX_WOL_RULES]; | ||
636 | } __attribute__ ((packed)); | ||
637 | |||
638 | struct cmd_ds_host_sleep { | ||
639 | struct cmd_header hdr; | ||
640 | __le32 criteria; | ||
641 | uint8_t gpio; | ||
642 | uint16_t gap; | ||
643 | struct wol_config wol_conf; | ||
644 | } __attribute__ ((packed)); | ||
645 | |||
646 | |||
647 | |||
648 | struct cmd_ds_802_11_key_material { | ||
649 | struct cmd_header hdr; | ||
650 | |||
651 | __le16 action; | ||
652 | struct MrvlIEtype_keyParamSet keyParamSet[2]; | ||
653 | } __attribute__ ((packed)); | ||
654 | |||
655 | struct cmd_ds_802_11_eeprom_access { | ||
656 | struct cmd_header hdr; | ||
657 | __le16 action; | ||
658 | __le16 offset; | ||
659 | __le16 len; | ||
660 | /* firmware says it returns a maximum of 20 bytes */ | ||
661 | #define LBS_EEPROM_READ_LEN 20 | ||
662 | u8 value[LBS_EEPROM_READ_LEN]; | ||
663 | } __attribute__ ((packed)); | ||
664 | |||
665 | struct cmd_ds_802_11_tpc_cfg { | ||
666 | struct cmd_header hdr; | ||
667 | |||
668 | __le16 action; | ||
669 | uint8_t enable; | ||
670 | int8_t P0; | ||
671 | int8_t P1; | ||
672 | int8_t P2; | ||
673 | uint8_t usesnr; | ||
674 | } __attribute__ ((packed)); | ||
675 | |||
676 | |||
677 | struct cmd_ds_802_11_pa_cfg { | ||
678 | struct cmd_header hdr; | ||
679 | |||
680 | __le16 action; | ||
681 | uint8_t enable; | ||
682 | int8_t P0; | ||
683 | int8_t P1; | ||
684 | int8_t P2; | ||
685 | } __attribute__ ((packed)); | ||
686 | |||
687 | |||
688 | struct cmd_ds_802_11_led_ctrl { | ||
689 | __le16 action; | ||
690 | __le16 numled; | ||
691 | u8 data[256]; | ||
692 | } __attribute__ ((packed)); | ||
693 | |||
694 | struct cmd_ds_802_11_afc { | ||
695 | __le16 afc_auto; | ||
696 | union { | ||
697 | struct { | ||
698 | __le16 threshold; | ||
699 | __le16 period; | ||
700 | }; | ||
701 | struct { | ||
702 | __le16 timing_offset; /* signed */ | ||
703 | __le16 carrier_offset; /* signed */ | ||
704 | }; | ||
705 | }; | ||
706 | } __attribute__ ((packed)); | ||
707 | |||
708 | struct cmd_tx_rate_query { | ||
709 | __le16 txrate; | ||
710 | } __attribute__ ((packed)); | ||
711 | |||
712 | struct cmd_ds_get_tsf { | ||
713 | __le64 tsfvalue; | ||
714 | } __attribute__ ((packed)); | ||
715 | |||
716 | struct cmd_ds_bt_access { | ||
717 | __le16 action; | ||
718 | __le32 id; | ||
719 | u8 addr1[ETH_ALEN]; | ||
720 | u8 addr2[ETH_ALEN]; | ||
721 | } __attribute__ ((packed)); | ||
722 | |||
723 | struct cmd_ds_fwt_access { | ||
724 | __le16 action; | ||
725 | __le32 id; | ||
726 | u8 valid; | ||
727 | u8 da[ETH_ALEN]; | ||
728 | u8 dir; | ||
729 | u8 ra[ETH_ALEN]; | ||
730 | __le32 ssn; | ||
731 | __le32 dsn; | ||
732 | __le32 metric; | ||
733 | u8 rate; | ||
734 | u8 hopcount; | ||
735 | u8 ttl; | ||
736 | __le32 expiration; | ||
737 | u8 sleepmode; | ||
738 | __le32 snr; | ||
739 | __le32 references; | ||
740 | u8 prec[ETH_ALEN]; | ||
741 | } __attribute__ ((packed)); | ||
742 | |||
743 | |||
744 | struct cmd_ds_mesh_config { | ||
745 | struct cmd_header hdr; | ||
746 | |||
747 | __le16 action; | ||
748 | __le16 channel; | ||
749 | __le16 type; | ||
750 | __le16 length; | ||
751 | u8 data[128]; /* last position reserved */ | ||
752 | } __attribute__ ((packed)); | ||
753 | |||
754 | |||
755 | struct cmd_ds_mesh_access { | ||
756 | struct cmd_header hdr; | ||
757 | |||
758 | __le16 action; | ||
759 | __le32 data[32]; /* last position reserved */ | ||
760 | } __attribute__ ((packed)); | ||
761 | |||
762 | /* Number of stats counters returned by the firmware */ | ||
763 | #define MESH_STATS_NUM 8 | ||
764 | |||
765 | struct cmd_ds_command { | ||
766 | /* command header */ | ||
767 | __le16 command; | ||
768 | __le16 size; | ||
769 | __le16 seqnum; | ||
770 | __le16 result; | ||
771 | |||
772 | /* command Body */ | ||
773 | union { | ||
774 | struct cmd_ds_802_11_ps_mode psmode; | ||
775 | struct cmd_ds_802_11_get_stat gstat; | ||
776 | struct cmd_ds_802_3_get_stat gstat_8023; | ||
777 | struct cmd_ds_802_11_rf_antenna rant; | ||
778 | struct cmd_ds_802_11_monitor_mode monitor; | ||
779 | struct cmd_ds_802_11_rssi rssi; | ||
780 | struct cmd_ds_802_11_rssi_rsp rssirsp; | ||
781 | struct cmd_ds_mac_reg_access macreg; | ||
782 | struct cmd_ds_bbp_reg_access bbpreg; | ||
783 | struct cmd_ds_rf_reg_access rfreg; | ||
784 | |||
785 | struct cmd_ds_802_11d_domain_info domaininfo; | ||
786 | struct cmd_ds_802_11d_domain_info domaininforesp; | ||
787 | |||
788 | struct cmd_ds_802_11_tpc_cfg tpccfg; | ||
789 | struct cmd_ds_802_11_afc afc; | ||
790 | struct cmd_ds_802_11_led_ctrl ledgpio; | ||
791 | |||
792 | struct cmd_tx_rate_query txrate; | ||
793 | struct cmd_ds_bt_access bt; | ||
794 | struct cmd_ds_fwt_access fwt; | ||
795 | struct cmd_ds_get_tsf gettsf; | ||
796 | struct cmd_ds_802_11_beacon_control bcn_ctrl; | ||
797 | } params; | ||
798 | } __attribute__ ((packed)); | ||
799 | |||
800 | #endif | ||
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 62381768f2d5..6d55439a7b97 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c | |||
@@ -22,6 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/slab.h> | ||
25 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
26 | #include <linux/moduleparam.h> | 27 | #include <linux/moduleparam.h> |
27 | #include <linux/firmware.h> | 28 | #include <linux/firmware.h> |
@@ -48,6 +49,7 @@ | |||
48 | MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>"); | 49 | MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>"); |
49 | MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards"); | 50 | MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards"); |
50 | MODULE_LICENSE("GPL"); | 51 | MODULE_LICENSE("GPL"); |
52 | MODULE_FIRMWARE("libertas_cs_helper.fw"); | ||
51 | 53 | ||
52 | 54 | ||
53 | 55 | ||
@@ -590,7 +592,7 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
590 | 592 | ||
591 | /* TODO: make firmware file configurable */ | 593 | /* TODO: make firmware file configurable */ |
592 | ret = request_firmware(&fw, "libertas_cs_helper.fw", | 594 | ret = request_firmware(&fw, "libertas_cs_helper.fw", |
593 | &handle_to_dev(card->p_dev)); | 595 | &card->p_dev->dev); |
594 | if (ret) { | 596 | if (ret) { |
595 | lbs_pr_err("can't load helper firmware\n"); | 597 | lbs_pr_err("can't load helper firmware\n"); |
596 | ret = -ENODEV; | 598 | ret = -ENODEV; |
@@ -663,7 +665,7 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
663 | 665 | ||
664 | /* TODO: make firmware file configurable */ | 666 | /* TODO: make firmware file configurable */ |
665 | ret = request_firmware(&fw, "libertas_cs.fw", | 667 | ret = request_firmware(&fw, "libertas_cs.fw", |
666 | &handle_to_dev(card->p_dev)); | 668 | &card->p_dev->dev); |
667 | if (ret) { | 669 | if (ret) { |
668 | lbs_pr_err("can't load firmware\n"); | 670 | lbs_pr_err("can't load firmware\n"); |
669 | ret = -ENODEV; | 671 | ret = -ENODEV; |
@@ -793,18 +795,37 @@ static void if_cs_release(struct pcmcia_device *p_dev) | |||
793 | * configure the card at this point -- we wait until we receive a card | 795 | * configure the card at this point -- we wait until we receive a card |
794 | * insertion event. | 796 | * insertion event. |
795 | */ | 797 | */ |
798 | |||
799 | static int if_cs_ioprobe(struct pcmcia_device *p_dev, | ||
800 | cistpl_cftable_entry_t *cfg, | ||
801 | cistpl_cftable_entry_t *dflt, | ||
802 | unsigned int vcc, | ||
803 | void *priv_data) | ||
804 | { | ||
805 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
806 | p_dev->io.BasePort1 = cfg->io.win[0].base; | ||
807 | p_dev->io.NumPorts1 = cfg->io.win[0].len; | ||
808 | |||
809 | /* Do we need to allocate an interrupt? */ | ||
810 | if (cfg->irq.IRQInfo1) | ||
811 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
812 | |||
813 | /* IO window settings */ | ||
814 | if (cfg->io.nwin != 1) { | ||
815 | lbs_pr_err("wrong CIS (check number of IO windows)\n"); | ||
816 | return -ENODEV; | ||
817 | } | ||
818 | |||
819 | /* This reserves IO space but doesn't actually enable it */ | ||
820 | return pcmcia_request_io(p_dev, &p_dev->io); | ||
821 | } | ||
822 | |||
796 | static int if_cs_probe(struct pcmcia_device *p_dev) | 823 | static int if_cs_probe(struct pcmcia_device *p_dev) |
797 | { | 824 | { |
798 | int ret = -ENOMEM; | 825 | int ret = -ENOMEM; |
799 | unsigned int prod_id; | 826 | unsigned int prod_id; |
800 | struct lbs_private *priv; | 827 | struct lbs_private *priv; |
801 | struct if_cs_card *card; | 828 | struct if_cs_card *card; |
802 | /* CIS parsing */ | ||
803 | tuple_t tuple; | ||
804 | cisparse_t parse; | ||
805 | cistpl_cftable_entry_t *cfg = &parse.cftable_entry; | ||
806 | cistpl_io_t *io = &cfg->io; | ||
807 | u_char buf[64]; | ||
808 | 829 | ||
809 | lbs_deb_enter(LBS_DEB_CS); | 830 | lbs_deb_enter(LBS_DEB_CS); |
810 | 831 | ||
@@ -818,48 +839,15 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
818 | 839 | ||
819 | p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; | 840 | p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; |
820 | p_dev->irq.Handler = NULL; | 841 | p_dev->irq.Handler = NULL; |
821 | p_dev->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; | ||
822 | 842 | ||
823 | p_dev->conf.Attributes = 0; | 843 | p_dev->conf.Attributes = 0; |
824 | p_dev->conf.IntType = INT_MEMORY_AND_IO; | 844 | p_dev->conf.IntType = INT_MEMORY_AND_IO; |
825 | 845 | ||
826 | tuple.Attributes = 0; | 846 | if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) { |
827 | tuple.TupleData = buf; | 847 | lbs_pr_err("error in pcmcia_loop_config\n"); |
828 | tuple.TupleDataMax = sizeof(buf); | ||
829 | tuple.TupleOffset = 0; | ||
830 | |||
831 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
832 | if ((ret = pcmcia_get_first_tuple(p_dev, &tuple)) != 0 || | ||
833 | (ret = pcmcia_get_tuple_data(p_dev, &tuple)) != 0 || | ||
834 | (ret = pcmcia_parse_tuple(&tuple, &parse)) != 0) | ||
835 | { | ||
836 | lbs_pr_err("error in pcmcia_get_first_tuple etc\n"); | ||
837 | goto out1; | ||
838 | } | ||
839 | |||
840 | p_dev->conf.ConfigIndex = cfg->index; | ||
841 | |||
842 | /* Do we need to allocate an interrupt? */ | ||
843 | if (cfg->irq.IRQInfo1) { | ||
844 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
845 | } | ||
846 | |||
847 | /* IO window settings */ | ||
848 | if (cfg->io.nwin != 1) { | ||
849 | lbs_pr_err("wrong CIS (check number of IO windows)\n"); | ||
850 | ret = -ENODEV; | ||
851 | goto out1; | 848 | goto out1; |
852 | } | 849 | } |
853 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
854 | p_dev->io.BasePort1 = io->win[0].base; | ||
855 | p_dev->io.NumPorts1 = io->win[0].len; | ||
856 | 850 | ||
857 | /* This reserves IO space but doesn't actually enable it */ | ||
858 | ret = pcmcia_request_io(p_dev, &p_dev->io); | ||
859 | if (ret) { | ||
860 | lbs_pr_err("error in pcmcia_request_io\n"); | ||
861 | goto out1; | ||
862 | } | ||
863 | 851 | ||
864 | /* | 852 | /* |
865 | * Allocate an interrupt line. Note that this does not assign | 853 | * Allocate an interrupt line. Note that this does not assign |
@@ -946,6 +934,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
946 | card->priv = priv; | 934 | card->priv = priv; |
947 | priv->card = card; | 935 | priv->card = card; |
948 | priv->hw_host_to_card = if_cs_host_to_card; | 936 | priv->hw_host_to_card = if_cs_host_to_card; |
937 | priv->enter_deep_sleep = NULL; | ||
938 | priv->exit_deep_sleep = NULL; | ||
939 | priv->reset_deep_sleep_wakeup = NULL; | ||
949 | priv->fw_ready = 1; | 940 | priv->fw_ready = 1; |
950 | 941 | ||
951 | /* Now actually get the IRQ */ | 942 | /* Now actually get the IRQ */ |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 485a8d406525..7d1a3c6b6ce0 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -28,6 +28,7 @@ | |||
28 | 28 | ||
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/moduleparam.h> | 30 | #include <linux/moduleparam.h> |
31 | #include <linux/slab.h> | ||
31 | #include <linux/firmware.h> | 32 | #include <linux/firmware.h> |
32 | #include <linux/netdevice.h> | 33 | #include <linux/netdevice.h> |
33 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
@@ -99,6 +100,12 @@ static struct if_sdio_model if_sdio_models[] = { | |||
99 | .firmware = "sd8688.bin", | 100 | .firmware = "sd8688.bin", |
100 | }, | 101 | }, |
101 | }; | 102 | }; |
103 | MODULE_FIRMWARE("sd8385_helper.bin"); | ||
104 | MODULE_FIRMWARE("sd8385.bin"); | ||
105 | MODULE_FIRMWARE("sd8686_helper.bin"); | ||
106 | MODULE_FIRMWARE("sd8686.bin"); | ||
107 | MODULE_FIRMWARE("sd8688_helper.bin"); | ||
108 | MODULE_FIRMWARE("sd8688.bin"); | ||
102 | 109 | ||
103 | struct if_sdio_packet { | 110 | struct if_sdio_packet { |
104 | struct if_sdio_packet *next; | 111 | struct if_sdio_packet *next; |
@@ -831,6 +838,58 @@ out: | |||
831 | return ret; | 838 | return ret; |
832 | } | 839 | } |
833 | 840 | ||
841 | static int if_sdio_enter_deep_sleep(struct lbs_private *priv) | ||
842 | { | ||
843 | int ret = -1; | ||
844 | struct cmd_header cmd; | ||
845 | |||
846 | memset(&cmd, 0, sizeof(cmd)); | ||
847 | |||
848 | lbs_deb_sdio("send DEEP_SLEEP command\n"); | ||
849 | ret = __lbs_cmd(priv, CMD_802_11_DEEP_SLEEP, &cmd, sizeof(cmd), | ||
850 | lbs_cmd_copyback, (unsigned long) &cmd); | ||
851 | if (ret) | ||
852 | lbs_pr_err("DEEP_SLEEP cmd failed\n"); | ||
853 | |||
854 | mdelay(200); | ||
855 | return ret; | ||
856 | } | ||
857 | |||
858 | static int if_sdio_exit_deep_sleep(struct lbs_private *priv) | ||
859 | { | ||
860 | struct if_sdio_card *card = priv->card; | ||
861 | int ret = -1; | ||
862 | |||
863 | lbs_deb_enter(LBS_DEB_SDIO); | ||
864 | sdio_claim_host(card->func); | ||
865 | |||
866 | sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret); | ||
867 | if (ret) | ||
868 | lbs_pr_err("sdio_writeb failed!\n"); | ||
869 | |||
870 | sdio_release_host(card->func); | ||
871 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | ||
872 | return ret; | ||
873 | } | ||
874 | |||
875 | static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv) | ||
876 | { | ||
877 | struct if_sdio_card *card = priv->card; | ||
878 | int ret = -1; | ||
879 | |||
880 | lbs_deb_enter(LBS_DEB_SDIO); | ||
881 | sdio_claim_host(card->func); | ||
882 | |||
883 | sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret); | ||
884 | if (ret) | ||
885 | lbs_pr_err("sdio_writeb failed!\n"); | ||
886 | |||
887 | sdio_release_host(card->func); | ||
888 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | ||
889 | return ret; | ||
890 | |||
891 | } | ||
892 | |||
834 | /*******************************************************************/ | 893 | /*******************************************************************/ |
835 | /* SDIO callbacks */ | 894 | /* SDIO callbacks */ |
836 | /*******************************************************************/ | 895 | /*******************************************************************/ |
@@ -859,6 +918,7 @@ static void if_sdio_interrupt(struct sdio_func *func) | |||
859 | * Ignore the define name, this really means the card has | 918 | * Ignore the define name, this really means the card has |
860 | * successfully received the command. | 919 | * successfully received the command. |
861 | */ | 920 | */ |
921 | card->priv->is_activity_detected = 1; | ||
862 | if (cause & IF_SDIO_H_INT_DNLD) | 922 | if (cause & IF_SDIO_H_INT_DNLD) |
863 | lbs_host_to_card_done(card->priv); | 923 | lbs_host_to_card_done(card->priv); |
864 | 924 | ||
@@ -934,7 +994,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
934 | } | 994 | } |
935 | 995 | ||
936 | if (i == ARRAY_SIZE(if_sdio_models)) { | 996 | if (i == ARRAY_SIZE(if_sdio_models)) { |
937 | lbs_pr_err("unkown card model 0x%x\n", card->model); | 997 | lbs_pr_err("unknown card model 0x%x\n", card->model); |
938 | ret = -ENODEV; | 998 | ret = -ENODEV; |
939 | goto free; | 999 | goto free; |
940 | } | 1000 | } |
@@ -998,6 +1058,9 @@ static int if_sdio_probe(struct sdio_func *func, | |||
998 | 1058 | ||
999 | priv->card = card; | 1059 | priv->card = card; |
1000 | priv->hw_host_to_card = if_sdio_host_to_card; | 1060 | priv->hw_host_to_card = if_sdio_host_to_card; |
1061 | priv->enter_deep_sleep = if_sdio_enter_deep_sleep; | ||
1062 | priv->exit_deep_sleep = if_sdio_exit_deep_sleep; | ||
1063 | priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup; | ||
1001 | 1064 | ||
1002 | priv->fw_ready = 1; | 1065 | priv->fw_ready = 1; |
1003 | 1066 | ||
diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h index 60c9b2fcef03..12179c1dc9c9 100644 --- a/drivers/net/wireless/libertas/if_sdio.h +++ b/drivers/net/wireless/libertas/if_sdio.h | |||
@@ -51,5 +51,6 @@ | |||
51 | #define IF_SDIO_EVENT 0x80fc | 51 | #define IF_SDIO_EVENT 0x80fc |
52 | 52 | ||
53 | #define IF_SDIO_BLOCK_SIZE 256 | 53 | #define IF_SDIO_BLOCK_SIZE 256 |
54 | 54 | #define CONFIGURATION_REG 0x03 | |
55 | #define HOST_POWER_UP (0x1U << 1) | ||
55 | #endif | 56 | #endif |
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 5b3672c4d0cc..fe3f08028eb3 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/kthread.h> | 23 | #include <linux/kthread.h> |
24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
25 | #include <linux/netdevice.h> | 25 | #include <linux/netdevice.h> |
26 | #include <linux/semaphore.h> | ||
27 | #include <linux/slab.h> | ||
26 | #include <linux/spi/libertas_spi.h> | 28 | #include <linux/spi/libertas_spi.h> |
27 | #include <linux/spi/spi.h> | 29 | #include <linux/spi/spi.h> |
28 | 30 | ||
@@ -32,12 +34,6 @@ | |||
32 | #include "dev.h" | 34 | #include "dev.h" |
33 | #include "if_spi.h" | 35 | #include "if_spi.h" |
34 | 36 | ||
35 | struct if_spi_packet { | ||
36 | struct list_head list; | ||
37 | u16 blen; | ||
38 | u8 buffer[0] __attribute__((aligned(4))); | ||
39 | }; | ||
40 | |||
41 | struct if_spi_card { | 37 | struct if_spi_card { |
42 | struct spi_device *spi; | 38 | struct spi_device *spi; |
43 | struct lbs_private *priv; | 39 | struct lbs_private *priv; |
@@ -66,33 +62,10 @@ struct if_spi_card { | |||
66 | struct semaphore spi_thread_terminated; | 62 | struct semaphore spi_thread_terminated; |
67 | 63 | ||
68 | u8 cmd_buffer[IF_SPI_CMD_BUF_SIZE]; | 64 | u8 cmd_buffer[IF_SPI_CMD_BUF_SIZE]; |
69 | |||
70 | /* A buffer of incoming packets from libertas core. | ||
71 | * Since we can't sleep in hw_host_to_card, we have to buffer | ||
72 | * them. */ | ||
73 | struct list_head cmd_packet_list; | ||
74 | struct list_head data_packet_list; | ||
75 | |||
76 | /* Protects cmd_packet_list and data_packet_list */ | ||
77 | spinlock_t buffer_lock; | ||
78 | }; | 65 | }; |
79 | 66 | ||
80 | static void free_if_spi_card(struct if_spi_card *card) | 67 | static void free_if_spi_card(struct if_spi_card *card) |
81 | { | 68 | { |
82 | struct list_head *cursor, *next; | ||
83 | struct if_spi_packet *packet; | ||
84 | |||
85 | BUG_ON(card->run_thread); | ||
86 | list_for_each_safe(cursor, next, &card->cmd_packet_list) { | ||
87 | packet = container_of(cursor, struct if_spi_packet, list); | ||
88 | list_del(&packet->list); | ||
89 | kfree(packet); | ||
90 | } | ||
91 | list_for_each_safe(cursor, next, &card->data_packet_list) { | ||
92 | packet = container_of(cursor, struct if_spi_packet, list); | ||
93 | list_del(&packet->list); | ||
94 | kfree(packet); | ||
95 | } | ||
96 | spi_set_drvdata(card->spi, NULL); | 69 | spi_set_drvdata(card->spi, NULL); |
97 | kfree(card); | 70 | kfree(card); |
98 | } | 71 | } |
@@ -774,40 +747,6 @@ out: | |||
774 | return err; | 747 | return err; |
775 | } | 748 | } |
776 | 749 | ||
777 | /* Move data or a command from the host to the card. */ | ||
778 | static void if_spi_h2c(struct if_spi_card *card, | ||
779 | struct if_spi_packet *packet, int type) | ||
780 | { | ||
781 | int err = 0; | ||
782 | u16 int_type, port_reg; | ||
783 | |||
784 | switch (type) { | ||
785 | case MVMS_DAT: | ||
786 | int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER; | ||
787 | port_reg = IF_SPI_DATA_RDWRPORT_REG; | ||
788 | break; | ||
789 | case MVMS_CMD: | ||
790 | int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER; | ||
791 | port_reg = IF_SPI_CMD_RDWRPORT_REG; | ||
792 | break; | ||
793 | default: | ||
794 | lbs_pr_err("can't transfer buffer of type %d\n", type); | ||
795 | err = -EINVAL; | ||
796 | goto out; | ||
797 | } | ||
798 | |||
799 | /* Write the data to the card */ | ||
800 | err = spu_write(card, port_reg, packet->buffer, packet->blen); | ||
801 | if (err) | ||
802 | goto out; | ||
803 | |||
804 | out: | ||
805 | kfree(packet); | ||
806 | |||
807 | if (err) | ||
808 | lbs_pr_err("%s: error %d\n", __func__, err); | ||
809 | } | ||
810 | |||
811 | /* Inform the host about a card event */ | 750 | /* Inform the host about a card event */ |
812 | static void if_spi_e2h(struct if_spi_card *card) | 751 | static void if_spi_e2h(struct if_spi_card *card) |
813 | { | 752 | { |
@@ -837,8 +776,6 @@ static int lbs_spi_thread(void *data) | |||
837 | int err; | 776 | int err; |
838 | struct if_spi_card *card = data; | 777 | struct if_spi_card *card = data; |
839 | u16 hiStatus; | 778 | u16 hiStatus; |
840 | unsigned long flags; | ||
841 | struct if_spi_packet *packet; | ||
842 | 779 | ||
843 | while (1) { | 780 | while (1) { |
844 | /* Wait to be woken up by one of two things. First, our ISR | 781 | /* Wait to be woken up by one of two things. First, our ISR |
@@ -877,43 +814,9 @@ static int lbs_spi_thread(void *data) | |||
877 | if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY || | 814 | if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY || |
878 | (card->priv->psstate != PS_STATE_FULL_POWER && | 815 | (card->priv->psstate != PS_STATE_FULL_POWER && |
879 | (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) { | 816 | (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) { |
880 | /* This means two things. First of all, | ||
881 | * if there was a previous command sent, the card has | ||
882 | * successfully received it. | ||
883 | * Secondly, it is now ready to download another | ||
884 | * command. | ||
885 | */ | ||
886 | lbs_host_to_card_done(card->priv); | 817 | lbs_host_to_card_done(card->priv); |
887 | |||
888 | /* Do we have any command packets from the host to | ||
889 | * send? */ | ||
890 | packet = NULL; | ||
891 | spin_lock_irqsave(&card->buffer_lock, flags); | ||
892 | if (!list_empty(&card->cmd_packet_list)) { | ||
893 | packet = (struct if_spi_packet *)(card-> | ||
894 | cmd_packet_list.next); | ||
895 | list_del(&packet->list); | ||
896 | } | ||
897 | spin_unlock_irqrestore(&card->buffer_lock, flags); | ||
898 | |||
899 | if (packet) | ||
900 | if_spi_h2c(card, packet, MVMS_CMD); | ||
901 | } | 818 | } |
902 | if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) { | ||
903 | /* Do we have any data packets from the host to | ||
904 | * send? */ | ||
905 | packet = NULL; | ||
906 | spin_lock_irqsave(&card->buffer_lock, flags); | ||
907 | if (!list_empty(&card->data_packet_list)) { | ||
908 | packet = (struct if_spi_packet *)(card-> | ||
909 | data_packet_list.next); | ||
910 | list_del(&packet->list); | ||
911 | } | ||
912 | spin_unlock_irqrestore(&card->buffer_lock, flags); | ||
913 | 819 | ||
914 | if (packet) | ||
915 | if_spi_h2c(card, packet, MVMS_DAT); | ||
916 | } | ||
917 | if (hiStatus & IF_SPI_HIST_CARD_EVENT) | 820 | if (hiStatus & IF_SPI_HIST_CARD_EVENT) |
918 | if_spi_e2h(card); | 821 | if_spi_e2h(card); |
919 | 822 | ||
@@ -942,40 +845,18 @@ static int if_spi_host_to_card(struct lbs_private *priv, | |||
942 | u8 type, u8 *buf, u16 nb) | 845 | u8 type, u8 *buf, u16 nb) |
943 | { | 846 | { |
944 | int err = 0; | 847 | int err = 0; |
945 | unsigned long flags; | ||
946 | struct if_spi_card *card = priv->card; | 848 | struct if_spi_card *card = priv->card; |
947 | struct if_spi_packet *packet; | ||
948 | u16 blen; | ||
949 | 849 | ||
950 | lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb); | 850 | lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb); |
951 | 851 | ||
952 | if (nb == 0) { | 852 | nb = ALIGN(nb, 4); |
953 | lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb); | ||
954 | err = -EINVAL; | ||
955 | goto out; | ||
956 | } | ||
957 | blen = ALIGN(nb, 4); | ||
958 | packet = kzalloc(sizeof(struct if_spi_packet) + blen, GFP_ATOMIC); | ||
959 | if (!packet) { | ||
960 | err = -ENOMEM; | ||
961 | goto out; | ||
962 | } | ||
963 | packet->blen = blen; | ||
964 | memcpy(packet->buffer, buf, nb); | ||
965 | memset(packet->buffer + nb, 0, blen - nb); | ||
966 | 853 | ||
967 | switch (type) { | 854 | switch (type) { |
968 | case MVMS_CMD: | 855 | case MVMS_CMD: |
969 | priv->dnld_sent = DNLD_CMD_SENT; | 856 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, buf, nb); |
970 | spin_lock_irqsave(&card->buffer_lock, flags); | ||
971 | list_add_tail(&packet->list, &card->cmd_packet_list); | ||
972 | spin_unlock_irqrestore(&card->buffer_lock, flags); | ||
973 | break; | 857 | break; |
974 | case MVMS_DAT: | 858 | case MVMS_DAT: |
975 | priv->dnld_sent = DNLD_DATA_SENT; | 859 | err = spu_write(card, IF_SPI_DATA_RDWRPORT_REG, buf, nb); |
976 | spin_lock_irqsave(&card->buffer_lock, flags); | ||
977 | list_add_tail(&packet->list, &card->data_packet_list); | ||
978 | spin_unlock_irqrestore(&card->buffer_lock, flags); | ||
979 | break; | 860 | break; |
980 | default: | 861 | default: |
981 | lbs_pr_err("can't transfer buffer of type %d", type); | 862 | lbs_pr_err("can't transfer buffer of type %d", type); |
@@ -983,9 +864,6 @@ static int if_spi_host_to_card(struct lbs_private *priv, | |||
983 | break; | 864 | break; |
984 | } | 865 | } |
985 | 866 | ||
986 | /* Wake up the spi thread */ | ||
987 | up(&card->spi_ready); | ||
988 | out: | ||
989 | lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err); | 867 | lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err); |
990 | return err; | 868 | return err; |
991 | } | 869 | } |
@@ -1026,6 +904,10 @@ static int if_spi_calculate_fw_names(u16 card_id, | |||
1026 | chip_id_to_device_name[i].name); | 904 | chip_id_to_device_name[i].name); |
1027 | return 0; | 905 | return 0; |
1028 | } | 906 | } |
907 | MODULE_FIRMWARE("libertas/gspi8385_hlp.bin"); | ||
908 | MODULE_FIRMWARE("libertas/gspi8385.bin"); | ||
909 | MODULE_FIRMWARE("libertas/gspi8686_hlp.bin"); | ||
910 | MODULE_FIRMWARE("libertas/gspi8686.bin"); | ||
1029 | 911 | ||
1030 | static int __devinit if_spi_probe(struct spi_device *spi) | 912 | static int __devinit if_spi_probe(struct spi_device *spi) |
1031 | { | 913 | { |
@@ -1062,9 +944,6 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
1062 | 944 | ||
1063 | sema_init(&card->spi_ready, 0); | 945 | sema_init(&card->spi_ready, 0); |
1064 | sema_init(&card->spi_thread_terminated, 0); | 946 | sema_init(&card->spi_thread_terminated, 0); |
1065 | INIT_LIST_HEAD(&card->cmd_packet_list); | ||
1066 | INIT_LIST_HEAD(&card->data_packet_list); | ||
1067 | spin_lock_init(&card->buffer_lock); | ||
1068 | 947 | ||
1069 | /* Initialize the SPI Interface Unit */ | 948 | /* Initialize the SPI Interface Unit */ |
1070 | err = spu_init(card, pdata->use_dummy_writes); | 949 | err = spu_init(card, pdata->use_dummy_writes); |
@@ -1117,6 +996,9 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
1117 | card->priv = priv; | 996 | card->priv = priv; |
1118 | priv->card = card; | 997 | priv->card = card; |
1119 | priv->hw_host_to_card = if_spi_host_to_card; | 998 | priv->hw_host_to_card = if_spi_host_to_card; |
999 | priv->enter_deep_sleep = NULL; | ||
1000 | priv->exit_deep_sleep = NULL; | ||
1001 | priv->reset_deep_sleep_wakeup = NULL; | ||
1120 | priv->fw_ready = 1; | 1002 | priv->fw_ready = 1; |
1121 | 1003 | ||
1122 | /* Initialize interrupt handling stuff. */ | 1004 | /* Initialize interrupt handling stuff. */ |
@@ -1138,6 +1020,9 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
1138 | goto terminate_thread; | 1020 | goto terminate_thread; |
1139 | } | 1021 | } |
1140 | 1022 | ||
1023 | /* poke the IRQ handler so that we don't miss the first interrupt */ | ||
1024 | up(&card->spi_ready); | ||
1025 | |||
1141 | /* Start the card. | 1026 | /* Start the card. |
1142 | * This will call register_netdev, and we'll start | 1027 | * This will call register_netdev, and we'll start |
1143 | * getting interrupts... */ | 1028 | * getting interrupts... */ |
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 3fac4efa5ac8..fcea5741ba62 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/moduleparam.h> | 5 | #include <linux/moduleparam.h> |
6 | #include <linux/firmware.h> | 6 | #include <linux/firmware.h> |
7 | #include <linux/netdevice.h> | 7 | #include <linux/netdevice.h> |
8 | #include <linux/slab.h> | ||
8 | #include <linux/usb.h> | 9 | #include <linux/usb.h> |
9 | 10 | ||
10 | #ifdef CONFIG_OLPC | 11 | #ifdef CONFIG_OLPC |
@@ -28,6 +29,8 @@ | |||
28 | static char *lbs_fw_name = "usb8388.bin"; | 29 | static char *lbs_fw_name = "usb8388.bin"; |
29 | module_param_named(fw_name, lbs_fw_name, charp, 0644); | 30 | module_param_named(fw_name, lbs_fw_name, charp, 0644); |
30 | 31 | ||
32 | MODULE_FIRMWARE("usb8388.bin"); | ||
33 | |||
31 | static struct usb_device_id if_usb_table[] = { | 34 | static struct usb_device_id if_usb_table[] = { |
32 | /* Enter the device signature inside */ | 35 | /* Enter the device signature inside */ |
33 | { USB_DEVICE(0x1286, 0x2001) }, | 36 | { USB_DEVICE(0x1286, 0x2001) }, |
@@ -300,6 +303,9 @@ static int if_usb_probe(struct usb_interface *intf, | |||
300 | cardp->priv->fw_ready = 1; | 303 | cardp->priv->fw_ready = 1; |
301 | 304 | ||
302 | priv->hw_host_to_card = if_usb_host_to_card; | 305 | priv->hw_host_to_card = if_usb_host_to_card; |
306 | priv->enter_deep_sleep = NULL; | ||
307 | priv->exit_deep_sleep = NULL; | ||
308 | priv->reset_deep_sleep_wakeup = NULL; | ||
303 | #ifdef CONFIG_OLPC | 309 | #ifdef CONFIG_OLPC |
304 | if (machine_is_olpc()) | 310 | if (machine_is_olpc()) |
305 | priv->reset_card = if_usb_reset_olpc_card; | 311 | priv->reset_card = if_usb_reset_olpc_card; |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 87b4e497faa2..598080414b17 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -13,12 +13,15 @@ | |||
13 | #include <linux/kfifo.h> | 13 | #include <linux/kfifo.h> |
14 | #include <linux/stddef.h> | 14 | #include <linux/stddef.h> |
15 | #include <linux/ieee80211.h> | 15 | #include <linux/ieee80211.h> |
16 | #include <linux/slab.h> | ||
16 | #include <net/iw_handler.h> | 17 | #include <net/iw_handler.h> |
18 | #include <net/cfg80211.h> | ||
17 | 19 | ||
18 | #include "host.h" | 20 | #include "host.h" |
19 | #include "decl.h" | 21 | #include "decl.h" |
20 | #include "dev.h" | 22 | #include "dev.h" |
21 | #include "wext.h" | 23 | #include "wext.h" |
24 | #include "cfg.h" | ||
22 | #include "debugfs.h" | 25 | #include "debugfs.h" |
23 | #include "scan.h" | 26 | #include "scan.h" |
24 | #include "assoc.h" | 27 | #include "assoc.h" |
@@ -43,119 +46,6 @@ module_param_named(libertas_debug, lbs_debug, int, 0644); | |||
43 | struct cmd_confirm_sleep confirm_sleep; | 46 | struct cmd_confirm_sleep confirm_sleep; |
44 | 47 | ||
45 | 48 | ||
46 | #define LBS_TX_PWR_DEFAULT 20 /*100mW */ | ||
47 | #define LBS_TX_PWR_US_DEFAULT 20 /*100mW */ | ||
48 | #define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */ | ||
49 | #define LBS_TX_PWR_FR_DEFAULT 20 /*100mW */ | ||
50 | #define LBS_TX_PWR_EMEA_DEFAULT 20 /*100mW */ | ||
51 | |||
52 | /* Format { channel, frequency (MHz), maxtxpower } */ | ||
53 | /* band: 'B/G', region: USA FCC/Canada IC */ | ||
54 | static struct chan_freq_power channel_freq_power_US_BG[] = { | ||
55 | {1, 2412, LBS_TX_PWR_US_DEFAULT}, | ||
56 | {2, 2417, LBS_TX_PWR_US_DEFAULT}, | ||
57 | {3, 2422, LBS_TX_PWR_US_DEFAULT}, | ||
58 | {4, 2427, LBS_TX_PWR_US_DEFAULT}, | ||
59 | {5, 2432, LBS_TX_PWR_US_DEFAULT}, | ||
60 | {6, 2437, LBS_TX_PWR_US_DEFAULT}, | ||
61 | {7, 2442, LBS_TX_PWR_US_DEFAULT}, | ||
62 | {8, 2447, LBS_TX_PWR_US_DEFAULT}, | ||
63 | {9, 2452, LBS_TX_PWR_US_DEFAULT}, | ||
64 | {10, 2457, LBS_TX_PWR_US_DEFAULT}, | ||
65 | {11, 2462, LBS_TX_PWR_US_DEFAULT} | ||
66 | }; | ||
67 | |||
68 | /* band: 'B/G', region: Europe ETSI */ | ||
69 | static struct chan_freq_power channel_freq_power_EU_BG[] = { | ||
70 | {1, 2412, LBS_TX_PWR_EMEA_DEFAULT}, | ||
71 | {2, 2417, LBS_TX_PWR_EMEA_DEFAULT}, | ||
72 | {3, 2422, LBS_TX_PWR_EMEA_DEFAULT}, | ||
73 | {4, 2427, LBS_TX_PWR_EMEA_DEFAULT}, | ||
74 | {5, 2432, LBS_TX_PWR_EMEA_DEFAULT}, | ||
75 | {6, 2437, LBS_TX_PWR_EMEA_DEFAULT}, | ||
76 | {7, 2442, LBS_TX_PWR_EMEA_DEFAULT}, | ||
77 | {8, 2447, LBS_TX_PWR_EMEA_DEFAULT}, | ||
78 | {9, 2452, LBS_TX_PWR_EMEA_DEFAULT}, | ||
79 | {10, 2457, LBS_TX_PWR_EMEA_DEFAULT}, | ||
80 | {11, 2462, LBS_TX_PWR_EMEA_DEFAULT}, | ||
81 | {12, 2467, LBS_TX_PWR_EMEA_DEFAULT}, | ||
82 | {13, 2472, LBS_TX_PWR_EMEA_DEFAULT} | ||
83 | }; | ||
84 | |||
85 | /* band: 'B/G', region: Spain */ | ||
86 | static struct chan_freq_power channel_freq_power_SPN_BG[] = { | ||
87 | {10, 2457, LBS_TX_PWR_DEFAULT}, | ||
88 | {11, 2462, LBS_TX_PWR_DEFAULT} | ||
89 | }; | ||
90 | |||
91 | /* band: 'B/G', region: France */ | ||
92 | static struct chan_freq_power channel_freq_power_FR_BG[] = { | ||
93 | {10, 2457, LBS_TX_PWR_FR_DEFAULT}, | ||
94 | {11, 2462, LBS_TX_PWR_FR_DEFAULT}, | ||
95 | {12, 2467, LBS_TX_PWR_FR_DEFAULT}, | ||
96 | {13, 2472, LBS_TX_PWR_FR_DEFAULT} | ||
97 | }; | ||
98 | |||
99 | /* band: 'B/G', region: Japan */ | ||
100 | static struct chan_freq_power channel_freq_power_JPN_BG[] = { | ||
101 | {1, 2412, LBS_TX_PWR_JP_DEFAULT}, | ||
102 | {2, 2417, LBS_TX_PWR_JP_DEFAULT}, | ||
103 | {3, 2422, LBS_TX_PWR_JP_DEFAULT}, | ||
104 | {4, 2427, LBS_TX_PWR_JP_DEFAULT}, | ||
105 | {5, 2432, LBS_TX_PWR_JP_DEFAULT}, | ||
106 | {6, 2437, LBS_TX_PWR_JP_DEFAULT}, | ||
107 | {7, 2442, LBS_TX_PWR_JP_DEFAULT}, | ||
108 | {8, 2447, LBS_TX_PWR_JP_DEFAULT}, | ||
109 | {9, 2452, LBS_TX_PWR_JP_DEFAULT}, | ||
110 | {10, 2457, LBS_TX_PWR_JP_DEFAULT}, | ||
111 | {11, 2462, LBS_TX_PWR_JP_DEFAULT}, | ||
112 | {12, 2467, LBS_TX_PWR_JP_DEFAULT}, | ||
113 | {13, 2472, LBS_TX_PWR_JP_DEFAULT}, | ||
114 | {14, 2484, LBS_TX_PWR_JP_DEFAULT} | ||
115 | }; | ||
116 | |||
117 | /** | ||
118 | * the structure for channel, frequency and power | ||
119 | */ | ||
120 | struct region_cfp_table { | ||
121 | u8 region; | ||
122 | struct chan_freq_power *cfp_BG; | ||
123 | int cfp_no_BG; | ||
124 | }; | ||
125 | |||
126 | /** | ||
127 | * the structure for the mapping between region and CFP | ||
128 | */ | ||
129 | static struct region_cfp_table region_cfp_table[] = { | ||
130 | {0x10, /*US FCC */ | ||
131 | channel_freq_power_US_BG, | ||
132 | ARRAY_SIZE(channel_freq_power_US_BG), | ||
133 | } | ||
134 | , | ||
135 | {0x20, /*CANADA IC */ | ||
136 | channel_freq_power_US_BG, | ||
137 | ARRAY_SIZE(channel_freq_power_US_BG), | ||
138 | } | ||
139 | , | ||
140 | {0x30, /*EU*/ channel_freq_power_EU_BG, | ||
141 | ARRAY_SIZE(channel_freq_power_EU_BG), | ||
142 | } | ||
143 | , | ||
144 | {0x31, /*SPAIN*/ channel_freq_power_SPN_BG, | ||
145 | ARRAY_SIZE(channel_freq_power_SPN_BG), | ||
146 | } | ||
147 | , | ||
148 | {0x32, /*FRANCE*/ channel_freq_power_FR_BG, | ||
149 | ARRAY_SIZE(channel_freq_power_FR_BG), | ||
150 | } | ||
151 | , | ||
152 | {0x40, /*JAPAN*/ channel_freq_power_JPN_BG, | ||
153 | ARRAY_SIZE(channel_freq_power_JPN_BG), | ||
154 | } | ||
155 | , | ||
156 | /*Add new region here */ | ||
157 | }; | ||
158 | |||
159 | /** | 49 | /** |
160 | * the table to keep region code | 50 | * the table to keep region code |
161 | */ | 51 | */ |
@@ -163,13 +53,6 @@ u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE] = | |||
163 | { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 }; | 53 | { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 }; |
164 | 54 | ||
165 | /** | 55 | /** |
166 | * 802.11b/g supported bitrates (in 500Kb/s units) | ||
167 | */ | ||
168 | u8 lbs_bg_rates[MAX_RATES] = | ||
169 | { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, | ||
170 | 0x00, 0x00 }; | ||
171 | |||
172 | /** | ||
173 | * FW rate table. FW refers to rates by their index in this table, not by the | 56 | * FW rate table. FW refers to rates by their index in this table, not by the |
174 | * rate value itself. Values of 0x00 are | 57 | * rate value itself. Values of 0x00 are |
175 | * reserved positions. | 58 | * reserved positions. |
@@ -212,107 +95,9 @@ u8 lbs_data_rate_to_fw_index(u32 rate) | |||
212 | return 0; | 95 | return 0; |
213 | } | 96 | } |
214 | 97 | ||
215 | /** | ||
216 | * Attributes exported through sysfs | ||
217 | */ | ||
218 | |||
219 | /** | ||
220 | * @brief Get function for sysfs attribute anycast_mask | ||
221 | */ | ||
222 | static ssize_t lbs_anycast_get(struct device *dev, | ||
223 | struct device_attribute *attr, char * buf) | ||
224 | { | ||
225 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
226 | struct cmd_ds_mesh_access mesh_access; | ||
227 | int ret; | ||
228 | |||
229 | memset(&mesh_access, 0, sizeof(mesh_access)); | ||
230 | |||
231 | ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_ANYCAST, &mesh_access); | ||
232 | if (ret) | ||
233 | return ret; | ||
234 | |||
235 | return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0])); | ||
236 | } | ||
237 | |||
238 | /** | ||
239 | * @brief Set function for sysfs attribute anycast_mask | ||
240 | */ | ||
241 | static ssize_t lbs_anycast_set(struct device *dev, | ||
242 | struct device_attribute *attr, const char * buf, size_t count) | ||
243 | { | ||
244 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
245 | struct cmd_ds_mesh_access mesh_access; | ||
246 | uint32_t datum; | ||
247 | int ret; | ||
248 | |||
249 | memset(&mesh_access, 0, sizeof(mesh_access)); | ||
250 | sscanf(buf, "%x", &datum); | ||
251 | mesh_access.data[0] = cpu_to_le32(datum); | ||
252 | |||
253 | ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access); | ||
254 | if (ret) | ||
255 | return ret; | ||
256 | |||
257 | return strlen(buf); | ||
258 | } | ||
259 | |||
260 | /** | ||
261 | * @brief Get function for sysfs attribute prb_rsp_limit | ||
262 | */ | ||
263 | static ssize_t lbs_prb_rsp_limit_get(struct device *dev, | ||
264 | struct device_attribute *attr, char *buf) | ||
265 | { | ||
266 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
267 | struct cmd_ds_mesh_access mesh_access; | ||
268 | int ret; | ||
269 | u32 retry_limit; | ||
270 | |||
271 | memset(&mesh_access, 0, sizeof(mesh_access)); | ||
272 | mesh_access.data[0] = cpu_to_le32(CMD_ACT_GET); | ||
273 | |||
274 | ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT, | ||
275 | &mesh_access); | ||
276 | if (ret) | ||
277 | return ret; | ||
278 | |||
279 | retry_limit = le32_to_cpu(mesh_access.data[1]); | ||
280 | return snprintf(buf, 10, "%d\n", retry_limit); | ||
281 | } | ||
282 | |||
283 | /** | ||
284 | * @brief Set function for sysfs attribute prb_rsp_limit | ||
285 | */ | ||
286 | static ssize_t lbs_prb_rsp_limit_set(struct device *dev, | ||
287 | struct device_attribute *attr, const char *buf, size_t count) | ||
288 | { | ||
289 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
290 | struct cmd_ds_mesh_access mesh_access; | ||
291 | int ret; | ||
292 | unsigned long retry_limit; | ||
293 | |||
294 | memset(&mesh_access, 0, sizeof(mesh_access)); | ||
295 | mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET); | ||
296 | |||
297 | if (!strict_strtoul(buf, 10, &retry_limit)) | ||
298 | return -ENOTSUPP; | ||
299 | if (retry_limit > 15) | ||
300 | return -ENOTSUPP; | ||
301 | |||
302 | mesh_access.data[1] = cpu_to_le32(retry_limit); | ||
303 | |||
304 | ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT, | ||
305 | &mesh_access); | ||
306 | if (ret) | ||
307 | return ret; | ||
308 | |||
309 | return strlen(buf); | ||
310 | } | ||
311 | 98 | ||
312 | static int lbs_add_rtap(struct lbs_private *priv); | 99 | static int lbs_add_rtap(struct lbs_private *priv); |
313 | static void lbs_remove_rtap(struct lbs_private *priv); | 100 | static void lbs_remove_rtap(struct lbs_private *priv); |
314 | static int lbs_add_mesh(struct lbs_private *priv); | ||
315 | static void lbs_remove_mesh(struct lbs_private *priv); | ||
316 | 101 | ||
317 | 102 | ||
318 | /** | 103 | /** |
@@ -339,7 +124,7 @@ static ssize_t lbs_rtap_set(struct device *dev, | |||
339 | if (priv->monitormode == monitor_mode) | 124 | if (priv->monitormode == monitor_mode) |
340 | return strlen(buf); | 125 | return strlen(buf); |
341 | if (!priv->monitormode) { | 126 | if (!priv->monitormode) { |
342 | if (priv->infra_open || priv->mesh_open) | 127 | if (priv->infra_open || lbs_mesh_open(priv)) |
343 | return -EBUSY; | 128 | return -EBUSY; |
344 | if (priv->mode == IW_MODE_INFRA) | 129 | if (priv->mode == IW_MODE_INFRA) |
345 | lbs_cmd_80211_deauthenticate(priv, | 130 | lbs_cmd_80211_deauthenticate(priv, |
@@ -378,74 +163,7 @@ static ssize_t lbs_rtap_set(struct device *dev, | |||
378 | static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set ); | 163 | static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set ); |
379 | 164 | ||
380 | /** | 165 | /** |
381 | * Get function for sysfs attribute mesh | 166 | * @brief This function opens the ethX interface |
382 | */ | ||
383 | static ssize_t lbs_mesh_get(struct device *dev, | ||
384 | struct device_attribute *attr, char * buf) | ||
385 | { | ||
386 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
387 | return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev); | ||
388 | } | ||
389 | |||
390 | /** | ||
391 | * Set function for sysfs attribute mesh | ||
392 | */ | ||
393 | static ssize_t lbs_mesh_set(struct device *dev, | ||
394 | struct device_attribute *attr, const char * buf, size_t count) | ||
395 | { | ||
396 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
397 | int enable; | ||
398 | int ret, action = CMD_ACT_MESH_CONFIG_STOP; | ||
399 | |||
400 | sscanf(buf, "%x", &enable); | ||
401 | enable = !!enable; | ||
402 | if (enable == !!priv->mesh_dev) | ||
403 | return count; | ||
404 | if (enable) | ||
405 | action = CMD_ACT_MESH_CONFIG_START; | ||
406 | ret = lbs_mesh_config(priv, action, priv->curbssparams.channel); | ||
407 | if (ret) | ||
408 | return ret; | ||
409 | |||
410 | if (enable) | ||
411 | lbs_add_mesh(priv); | ||
412 | else | ||
413 | lbs_remove_mesh(priv); | ||
414 | |||
415 | return count; | ||
416 | } | ||
417 | |||
418 | /** | ||
419 | * lbs_mesh attribute to be exported per ethX interface | ||
420 | * through sysfs (/sys/class/net/ethX/lbs_mesh) | ||
421 | */ | ||
422 | static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set); | ||
423 | |||
424 | /** | ||
425 | * anycast_mask attribute to be exported per mshX interface | ||
426 | * through sysfs (/sys/class/net/mshX/anycast_mask) | ||
427 | */ | ||
428 | static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set); | ||
429 | |||
430 | /** | ||
431 | * prb_rsp_limit attribute to be exported per mshX interface | ||
432 | * through sysfs (/sys/class/net/mshX/prb_rsp_limit) | ||
433 | */ | ||
434 | static DEVICE_ATTR(prb_rsp_limit, 0644, lbs_prb_rsp_limit_get, | ||
435 | lbs_prb_rsp_limit_set); | ||
436 | |||
437 | static struct attribute *lbs_mesh_sysfs_entries[] = { | ||
438 | &dev_attr_anycast_mask.attr, | ||
439 | &dev_attr_prb_rsp_limit.attr, | ||
440 | NULL, | ||
441 | }; | ||
442 | |||
443 | static struct attribute_group lbs_mesh_attr_group = { | ||
444 | .attrs = lbs_mesh_sysfs_entries, | ||
445 | }; | ||
446 | |||
447 | /** | ||
448 | * @brief This function opens the ethX or mshX interface | ||
449 | * | 167 | * |
450 | * @param dev A pointer to net_device structure | 168 | * @param dev A pointer to net_device structure |
451 | * @return 0 or -EBUSY if monitor mode active | 169 | * @return 0 or -EBUSY if monitor mode active |
@@ -464,18 +182,12 @@ static int lbs_dev_open(struct net_device *dev) | |||
464 | goto out; | 182 | goto out; |
465 | } | 183 | } |
466 | 184 | ||
467 | if (dev == priv->mesh_dev) { | 185 | priv->infra_open = 1; |
468 | priv->mesh_open = 1; | ||
469 | priv->mesh_connect_status = LBS_CONNECTED; | ||
470 | netif_carrier_on(dev); | ||
471 | } else { | ||
472 | priv->infra_open = 1; | ||
473 | 186 | ||
474 | if (priv->connect_status == LBS_CONNECTED) | 187 | if (priv->connect_status == LBS_CONNECTED) |
475 | netif_carrier_on(dev); | 188 | netif_carrier_on(dev); |
476 | else | 189 | else |
477 | netif_carrier_off(dev); | 190 | netif_carrier_off(dev); |
478 | } | ||
479 | 191 | ||
480 | if (!priv->tx_pending_len) | 192 | if (!priv->tx_pending_len) |
481 | netif_wake_queue(dev); | 193 | netif_wake_queue(dev); |
@@ -487,33 +199,6 @@ static int lbs_dev_open(struct net_device *dev) | |||
487 | } | 199 | } |
488 | 200 | ||
489 | /** | 201 | /** |
490 | * @brief This function closes the mshX interface | ||
491 | * | ||
492 | * @param dev A pointer to net_device structure | ||
493 | * @return 0 | ||
494 | */ | ||
495 | static int lbs_mesh_stop(struct net_device *dev) | ||
496 | { | ||
497 | struct lbs_private *priv = dev->ml_priv; | ||
498 | |||
499 | lbs_deb_enter(LBS_DEB_MESH); | ||
500 | spin_lock_irq(&priv->driver_lock); | ||
501 | |||
502 | priv->mesh_open = 0; | ||
503 | priv->mesh_connect_status = LBS_DISCONNECTED; | ||
504 | |||
505 | netif_stop_queue(dev); | ||
506 | netif_carrier_off(dev); | ||
507 | |||
508 | spin_unlock_irq(&priv->driver_lock); | ||
509 | |||
510 | schedule_work(&priv->mcast_work); | ||
511 | |||
512 | lbs_deb_leave(LBS_DEB_MESH); | ||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | /** | ||
517 | * @brief This function closes the ethX interface | 202 | * @brief This function closes the ethX interface |
518 | * | 203 | * |
519 | * @param dev A pointer to net_device structure | 204 | * @param dev A pointer to net_device structure |
@@ -574,15 +259,17 @@ void lbs_host_to_card_done(struct lbs_private *priv) | |||
574 | priv->dnld_sent = DNLD_RES_RECEIVED; | 259 | priv->dnld_sent = DNLD_RES_RECEIVED; |
575 | 260 | ||
576 | /* Wake main thread if commands are pending */ | 261 | /* Wake main thread if commands are pending */ |
577 | if (!priv->cur_cmd || priv->tx_pending_len > 0) | 262 | if (!priv->cur_cmd || priv->tx_pending_len > 0) { |
578 | wake_up_interruptible(&priv->waitq); | 263 | if (!priv->wakeup_dev_required) |
264 | wake_up_interruptible(&priv->waitq); | ||
265 | } | ||
579 | 266 | ||
580 | spin_unlock_irqrestore(&priv->driver_lock, flags); | 267 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
581 | lbs_deb_leave(LBS_DEB_THREAD); | 268 | lbs_deb_leave(LBS_DEB_THREAD); |
582 | } | 269 | } |
583 | EXPORT_SYMBOL_GPL(lbs_host_to_card_done); | 270 | EXPORT_SYMBOL_GPL(lbs_host_to_card_done); |
584 | 271 | ||
585 | static int lbs_set_mac_address(struct net_device *dev, void *addr) | 272 | int lbs_set_mac_address(struct net_device *dev, void *addr) |
586 | { | 273 | { |
587 | int ret = 0; | 274 | int ret = 0; |
588 | struct lbs_private *priv = dev->ml_priv; | 275 | struct lbs_private *priv = dev->ml_priv; |
@@ -633,15 +320,18 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd, | |||
633 | { | 320 | { |
634 | int i = nr_addrs; | 321 | int i = nr_addrs; |
635 | struct dev_mc_list *mc_list; | 322 | struct dev_mc_list *mc_list; |
323 | int cnt; | ||
636 | 324 | ||
637 | if ((dev->flags & (IFF_UP|IFF_MULTICAST)) != (IFF_UP|IFF_MULTICAST)) | 325 | if ((dev->flags & (IFF_UP|IFF_MULTICAST)) != (IFF_UP|IFF_MULTICAST)) |
638 | return nr_addrs; | 326 | return nr_addrs; |
639 | 327 | ||
640 | netif_addr_lock_bh(dev); | 328 | netif_addr_lock_bh(dev); |
641 | for (mc_list = dev->mc_list; mc_list; mc_list = mc_list->next) { | 329 | cnt = netdev_mc_count(dev); |
330 | netdev_for_each_mc_addr(mc_list, dev) { | ||
642 | if (mac_in_list(cmd->maclist, nr_addrs, mc_list->dmi_addr)) { | 331 | if (mac_in_list(cmd->maclist, nr_addrs, mc_list->dmi_addr)) { |
643 | lbs_deb_net("mcast address %s:%pM skipped\n", dev->name, | 332 | lbs_deb_net("mcast address %s:%pM skipped\n", dev->name, |
644 | mc_list->dmi_addr); | 333 | mc_list->dmi_addr); |
334 | cnt--; | ||
645 | continue; | 335 | continue; |
646 | } | 336 | } |
647 | 337 | ||
@@ -651,9 +341,10 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd, | |||
651 | lbs_deb_net("mcast address %s:%pM added to filter\n", dev->name, | 341 | lbs_deb_net("mcast address %s:%pM added to filter\n", dev->name, |
652 | mc_list->dmi_addr); | 342 | mc_list->dmi_addr); |
653 | i++; | 343 | i++; |
344 | cnt--; | ||
654 | } | 345 | } |
655 | netif_addr_unlock_bh(dev); | 346 | netif_addr_unlock_bh(dev); |
656 | if (mc_list) | 347 | if (cnt) |
657 | return -EOVERFLOW; | 348 | return -EOVERFLOW; |
658 | 349 | ||
659 | return i; | 350 | return i; |
@@ -716,7 +407,7 @@ static void lbs_set_mcast_worker(struct work_struct *work) | |||
716 | lbs_deb_leave(LBS_DEB_NET); | 407 | lbs_deb_leave(LBS_DEB_NET); |
717 | } | 408 | } |
718 | 409 | ||
719 | static void lbs_set_multicast_list(struct net_device *dev) | 410 | void lbs_set_multicast_list(struct net_device *dev) |
720 | { | 411 | { |
721 | struct lbs_private *priv = dev->ml_priv; | 412 | struct lbs_private *priv = dev->ml_priv; |
722 | 413 | ||
@@ -770,9 +461,10 @@ static int lbs_thread(void *data) | |||
770 | shouldsleep = 0; /* We have a command response */ | 461 | shouldsleep = 0; /* We have a command response */ |
771 | else if (priv->cur_cmd) | 462 | else if (priv->cur_cmd) |
772 | shouldsleep = 1; /* Can't send a command; one already running */ | 463 | shouldsleep = 1; /* Can't send a command; one already running */ |
773 | else if (!list_empty(&priv->cmdpendingq)) | 464 | else if (!list_empty(&priv->cmdpendingq) && |
465 | !(priv->wakeup_dev_required)) | ||
774 | shouldsleep = 0; /* We have a command to send */ | 466 | shouldsleep = 0; /* We have a command to send */ |
775 | else if (__kfifo_len(priv->event_fifo)) | 467 | else if (kfifo_len(&priv->event_fifo)) |
776 | shouldsleep = 0; /* We have an event to process */ | 468 | shouldsleep = 0; /* We have an event to process */ |
777 | else | 469 | else |
778 | shouldsleep = 1; /* No command */ | 470 | shouldsleep = 1; /* No command */ |
@@ -822,46 +514,41 @@ static int lbs_thread(void *data) | |||
822 | } | 514 | } |
823 | spin_unlock_irq(&priv->driver_lock); | 515 | spin_unlock_irq(&priv->driver_lock); |
824 | 516 | ||
825 | /* command timeout stuff */ | ||
826 | if (priv->cmd_timed_out && priv->cur_cmd) { | ||
827 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; | ||
828 | |||
829 | if (++priv->nr_retries > 3) { | ||
830 | lbs_pr_info("Excessive timeouts submitting " | ||
831 | "command 0x%04x\n", | ||
832 | le16_to_cpu(cmdnode->cmdbuf->command)); | ||
833 | lbs_complete_command(priv, cmdnode, -ETIMEDOUT); | ||
834 | priv->nr_retries = 0; | ||
835 | if (priv->reset_card) | ||
836 | priv->reset_card(priv); | ||
837 | } else { | ||
838 | priv->cur_cmd = NULL; | ||
839 | priv->dnld_sent = DNLD_RES_RECEIVED; | ||
840 | lbs_pr_info("requeueing command 0x%04x due " | ||
841 | "to timeout (#%d)\n", | ||
842 | le16_to_cpu(cmdnode->cmdbuf->command), | ||
843 | priv->nr_retries); | ||
844 | |||
845 | /* Stick it back at the _top_ of the pending queue | ||
846 | for immediate resubmission */ | ||
847 | list_add(&cmdnode->list, &priv->cmdpendingq); | ||
848 | } | ||
849 | } | ||
850 | priv->cmd_timed_out = 0; | ||
851 | |||
852 | /* Process hardware events, e.g. card removed, link lost */ | 517 | /* Process hardware events, e.g. card removed, link lost */ |
853 | spin_lock_irq(&priv->driver_lock); | 518 | spin_lock_irq(&priv->driver_lock); |
854 | while (__kfifo_len(priv->event_fifo)) { | 519 | while (kfifo_len(&priv->event_fifo)) { |
855 | u32 event; | 520 | u32 event; |
856 | 521 | ||
857 | __kfifo_get(priv->event_fifo, (unsigned char *) &event, | 522 | if (kfifo_out(&priv->event_fifo, |
858 | sizeof(event)); | 523 | (unsigned char *) &event, sizeof(event)) != |
524 | sizeof(event)) | ||
525 | break; | ||
859 | spin_unlock_irq(&priv->driver_lock); | 526 | spin_unlock_irq(&priv->driver_lock); |
860 | lbs_process_event(priv, event); | 527 | lbs_process_event(priv, event); |
861 | spin_lock_irq(&priv->driver_lock); | 528 | spin_lock_irq(&priv->driver_lock); |
862 | } | 529 | } |
863 | spin_unlock_irq(&priv->driver_lock); | 530 | spin_unlock_irq(&priv->driver_lock); |
864 | 531 | ||
532 | if (priv->wakeup_dev_required) { | ||
533 | lbs_deb_thread("Waking up device...\n"); | ||
534 | /* Wake up device */ | ||
535 | if (priv->exit_deep_sleep(priv)) | ||
536 | lbs_deb_thread("Wakeup device failed\n"); | ||
537 | continue; | ||
538 | } | ||
539 | |||
540 | /* command timeout stuff */ | ||
541 | if (priv->cmd_timed_out && priv->cur_cmd) { | ||
542 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; | ||
543 | |||
544 | lbs_pr_info("Timeout submitting command 0x%04x\n", | ||
545 | le16_to_cpu(cmdnode->cmdbuf->command)); | ||
546 | lbs_complete_command(priv, cmdnode, -ETIMEDOUT); | ||
547 | if (priv->reset_card) | ||
548 | priv->reset_card(priv); | ||
549 | } | ||
550 | priv->cmd_timed_out = 0; | ||
551 | |||
865 | if (!priv->fw_ready) | 552 | if (!priv->fw_ready) |
866 | continue; | 553 | continue; |
867 | 554 | ||
@@ -894,6 +581,9 @@ static int lbs_thread(void *data) | |||
894 | (priv->psstate == PS_STATE_PRE_SLEEP)) | 581 | (priv->psstate == PS_STATE_PRE_SLEEP)) |
895 | continue; | 582 | continue; |
896 | 583 | ||
584 | if (priv->is_deep_sleep) | ||
585 | continue; | ||
586 | |||
897 | /* Execute the next command */ | 587 | /* Execute the next command */ |
898 | if (!priv->dnld_sent && !priv->cur_cmd) | 588 | if (!priv->dnld_sent && !priv->cur_cmd) |
899 | lbs_execute_next_command(priv); | 589 | lbs_execute_next_command(priv); |
@@ -920,7 +610,7 @@ static int lbs_thread(void *data) | |||
920 | if (priv->connect_status == LBS_CONNECTED) | 610 | if (priv->connect_status == LBS_CONNECTED) |
921 | netif_wake_queue(priv->dev); | 611 | netif_wake_queue(priv->dev); |
922 | if (priv->mesh_dev && | 612 | if (priv->mesh_dev && |
923 | priv->mesh_connect_status == LBS_CONNECTED) | 613 | lbs_mesh_connected(priv)) |
924 | netif_wake_queue(priv->mesh_dev); | 614 | netif_wake_queue(priv->mesh_dev); |
925 | } | 615 | } |
926 | } | 616 | } |
@@ -928,6 +618,7 @@ static int lbs_thread(void *data) | |||
928 | } | 618 | } |
929 | 619 | ||
930 | del_timer(&priv->command_timer); | 620 | del_timer(&priv->command_timer); |
621 | del_timer(&priv->auto_deepsleep_timer); | ||
931 | wake_up_all(&priv->cmd_pending); | 622 | wake_up_all(&priv->cmd_pending); |
932 | 623 | ||
933 | lbs_deb_leave(LBS_DEB_THREAD); | 624 | lbs_deb_leave(LBS_DEB_THREAD); |
@@ -1029,7 +720,7 @@ done: | |||
1029 | * This function handles the timeout of command sending. | 720 | * This function handles the timeout of command sending. |
1030 | * It will re-send the same command again. | 721 | * It will re-send the same command again. |
1031 | */ | 722 | */ |
1032 | static void command_timer_fn(unsigned long data) | 723 | static void lbs_cmd_timeout_handler(unsigned long data) |
1033 | { | 724 | { |
1034 | struct lbs_private *priv = (struct lbs_private *)data; | 725 | struct lbs_private *priv = (struct lbs_private *)data; |
1035 | unsigned long flags; | 726 | unsigned long flags; |
@@ -1050,17 +741,61 @@ out: | |||
1050 | lbs_deb_leave(LBS_DEB_CMD); | 741 | lbs_deb_leave(LBS_DEB_CMD); |
1051 | } | 742 | } |
1052 | 743 | ||
1053 | static void lbs_sync_channel_worker(struct work_struct *work) | 744 | /** |
745 | * This function put the device back to deep sleep mode when timer expires | ||
746 | * and no activity (command, event, data etc.) is detected. | ||
747 | */ | ||
748 | static void auto_deepsleep_timer_fn(unsigned long data) | ||
1054 | { | 749 | { |
1055 | struct lbs_private *priv = container_of(work, struct lbs_private, | 750 | struct lbs_private *priv = (struct lbs_private *)data; |
1056 | sync_channel); | 751 | int ret; |
1057 | 752 | ||
1058 | lbs_deb_enter(LBS_DEB_MAIN); | 753 | lbs_deb_enter(LBS_DEB_CMD); |
1059 | if (lbs_update_channel(priv)) | 754 | |
1060 | lbs_pr_info("Channel synchronization failed."); | 755 | if (priv->is_activity_detected) { |
1061 | lbs_deb_leave(LBS_DEB_MAIN); | 756 | priv->is_activity_detected = 0; |
757 | } else { | ||
758 | if (priv->is_auto_deep_sleep_enabled && | ||
759 | (!priv->wakeup_dev_required) && | ||
760 | (priv->connect_status != LBS_CONNECTED)) { | ||
761 | lbs_deb_main("Entering auto deep sleep mode...\n"); | ||
762 | ret = lbs_prepare_and_send_command(priv, | ||
763 | CMD_802_11_DEEP_SLEEP, 0, | ||
764 | 0, 0, NULL); | ||
765 | if (ret) | ||
766 | lbs_pr_err("Enter Deep Sleep command failed\n"); | ||
767 | } | ||
768 | } | ||
769 | mod_timer(&priv->auto_deepsleep_timer , jiffies + | ||
770 | (priv->auto_deep_sleep_timeout * HZ)/1000); | ||
771 | lbs_deb_leave(LBS_DEB_CMD); | ||
772 | } | ||
773 | |||
774 | int lbs_enter_auto_deep_sleep(struct lbs_private *priv) | ||
775 | { | ||
776 | lbs_deb_enter(LBS_DEB_SDIO); | ||
777 | |||
778 | priv->is_auto_deep_sleep_enabled = 1; | ||
779 | if (priv->is_deep_sleep) | ||
780 | priv->wakeup_dev_required = 1; | ||
781 | mod_timer(&priv->auto_deepsleep_timer , | ||
782 | jiffies + (priv->auto_deep_sleep_timeout * HZ)/1000); | ||
783 | |||
784 | lbs_deb_leave(LBS_DEB_SDIO); | ||
785 | return 0; | ||
1062 | } | 786 | } |
1063 | 787 | ||
788 | int lbs_exit_auto_deep_sleep(struct lbs_private *priv) | ||
789 | { | ||
790 | lbs_deb_enter(LBS_DEB_SDIO); | ||
791 | |||
792 | priv->is_auto_deep_sleep_enabled = 0; | ||
793 | priv->auto_deep_sleep_timeout = 0; | ||
794 | del_timer(&priv->auto_deepsleep_timer); | ||
795 | |||
796 | lbs_deb_leave(LBS_DEB_SDIO); | ||
797 | return 0; | ||
798 | } | ||
1064 | 799 | ||
1065 | static int lbs_init_adapter(struct lbs_private *priv) | 800 | static int lbs_init_adapter(struct lbs_private *priv) |
1066 | { | 801 | { |
@@ -1089,21 +824,25 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
1089 | memset(priv->current_addr, 0xff, ETH_ALEN); | 824 | memset(priv->current_addr, 0xff, ETH_ALEN); |
1090 | 825 | ||
1091 | priv->connect_status = LBS_DISCONNECTED; | 826 | priv->connect_status = LBS_DISCONNECTED; |
1092 | priv->mesh_connect_status = LBS_DISCONNECTED; | ||
1093 | priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | 827 | priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; |
1094 | priv->mode = IW_MODE_INFRA; | 828 | priv->mode = IW_MODE_INFRA; |
1095 | priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; | 829 | priv->channel = DEFAULT_AD_HOC_CHANNEL; |
1096 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; | 830 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; |
1097 | priv->radio_on = 1; | 831 | priv->radio_on = 1; |
1098 | priv->enablehwauto = 1; | 832 | priv->enablehwauto = 1; |
1099 | priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; | ||
1100 | priv->psmode = LBS802_11POWERMODECAM; | 833 | priv->psmode = LBS802_11POWERMODECAM; |
1101 | priv->psstate = PS_STATE_FULL_POWER; | 834 | priv->psstate = PS_STATE_FULL_POWER; |
835 | priv->is_deep_sleep = 0; | ||
836 | priv->is_auto_deep_sleep_enabled = 0; | ||
837 | priv->wakeup_dev_required = 0; | ||
838 | init_waitqueue_head(&priv->ds_awake_q); | ||
1102 | 839 | ||
1103 | mutex_init(&priv->lock); | 840 | mutex_init(&priv->lock); |
1104 | 841 | ||
1105 | setup_timer(&priv->command_timer, command_timer_fn, | 842 | setup_timer(&priv->command_timer, lbs_cmd_timeout_handler, |
1106 | (unsigned long)priv); | 843 | (unsigned long)priv); |
844 | setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn, | ||
845 | (unsigned long)priv); | ||
1107 | 846 | ||
1108 | INIT_LIST_HEAD(&priv->cmdfreeq); | 847 | INIT_LIST_HEAD(&priv->cmdfreeq); |
1109 | INIT_LIST_HEAD(&priv->cmdpendingq); | 848 | INIT_LIST_HEAD(&priv->cmdpendingq); |
@@ -1121,10 +860,9 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
1121 | priv->resp_len[0] = priv->resp_len[1] = 0; | 860 | priv->resp_len[0] = priv->resp_len[1] = 0; |
1122 | 861 | ||
1123 | /* Create the event FIFO */ | 862 | /* Create the event FIFO */ |
1124 | priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL); | 863 | ret = kfifo_alloc(&priv->event_fifo, sizeof(u32) * 16, GFP_KERNEL); |
1125 | if (IS_ERR(priv->event_fifo)) { | 864 | if (ret) { |
1126 | lbs_pr_err("Out of memory allocating event FIFO buffer\n"); | 865 | lbs_pr_err("Out of memory allocating event FIFO buffer\n"); |
1127 | ret = -ENOMEM; | ||
1128 | goto out; | 866 | goto out; |
1129 | } | 867 | } |
1130 | 868 | ||
@@ -1139,9 +877,9 @@ static void lbs_free_adapter(struct lbs_private *priv) | |||
1139 | lbs_deb_enter(LBS_DEB_MAIN); | 877 | lbs_deb_enter(LBS_DEB_MAIN); |
1140 | 878 | ||
1141 | lbs_free_cmd_buffer(priv); | 879 | lbs_free_cmd_buffer(priv); |
1142 | if (priv->event_fifo) | 880 | kfifo_free(&priv->event_fifo); |
1143 | kfifo_free(priv->event_fifo); | ||
1144 | del_timer(&priv->command_timer); | 881 | del_timer(&priv->command_timer); |
882 | del_timer(&priv->auto_deepsleep_timer); | ||
1145 | kfree(priv->networks); | 883 | kfree(priv->networks); |
1146 | priv->networks = NULL; | 884 | priv->networks = NULL; |
1147 | 885 | ||
@@ -1168,31 +906,41 @@ static const struct net_device_ops lbs_netdev_ops = { | |||
1168 | */ | 906 | */ |
1169 | struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | 907 | struct lbs_private *lbs_add_card(void *card, struct device *dmdev) |
1170 | { | 908 | { |
1171 | struct net_device *dev = NULL; | 909 | struct net_device *dev; |
910 | struct wireless_dev *wdev; | ||
1172 | struct lbs_private *priv = NULL; | 911 | struct lbs_private *priv = NULL; |
1173 | 912 | ||
1174 | lbs_deb_enter(LBS_DEB_MAIN); | 913 | lbs_deb_enter(LBS_DEB_MAIN); |
1175 | 914 | ||
1176 | /* Allocate an Ethernet device and register it */ | 915 | /* Allocate an Ethernet device and register it */ |
1177 | dev = alloc_etherdev(sizeof(struct lbs_private)); | 916 | wdev = lbs_cfg_alloc(dmdev); |
1178 | if (!dev) { | 917 | if (IS_ERR(wdev)) { |
1179 | lbs_pr_err("init wlanX device failed\n"); | 918 | lbs_pr_err("cfg80211 init failed\n"); |
1180 | goto done; | 919 | goto done; |
1181 | } | 920 | } |
1182 | priv = netdev_priv(dev); | 921 | /* TODO? */ |
1183 | dev->ml_priv = priv; | 922 | wdev->iftype = NL80211_IFTYPE_STATION; |
923 | priv = wdev_priv(wdev); | ||
924 | priv->wdev = wdev; | ||
1184 | 925 | ||
1185 | if (lbs_init_adapter(priv)) { | 926 | if (lbs_init_adapter(priv)) { |
1186 | lbs_pr_err("failed to initialize adapter structure.\n"); | 927 | lbs_pr_err("failed to initialize adapter structure.\n"); |
1187 | goto err_init_adapter; | 928 | goto err_wdev; |
1188 | } | 929 | } |
1189 | 930 | ||
931 | //TODO? dev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES); | ||
932 | dev = alloc_netdev(0, "wlan%d", ether_setup); | ||
933 | if (!dev) { | ||
934 | dev_err(dmdev, "no memory for network device instance\n"); | ||
935 | goto err_adapter; | ||
936 | } | ||
937 | |||
938 | dev->ieee80211_ptr = wdev; | ||
939 | dev->ml_priv = priv; | ||
940 | SET_NETDEV_DEV(dev, dmdev); | ||
941 | wdev->netdev = dev; | ||
1190 | priv->dev = dev; | 942 | priv->dev = dev; |
1191 | priv->card = card; | ||
1192 | priv->mesh_open = 0; | ||
1193 | priv->infra_open = 0; | ||
1194 | 943 | ||
1195 | /* Setup the OS Interface to our functions */ | ||
1196 | dev->netdev_ops = &lbs_netdev_ops; | 944 | dev->netdev_ops = &lbs_netdev_ops; |
1197 | dev->watchdog_timeo = 5 * HZ; | 945 | dev->watchdog_timeo = 5 * HZ; |
1198 | dev->ethtool_ops = &lbs_ethtool_ops; | 946 | dev->ethtool_ops = &lbs_ethtool_ops; |
@@ -1201,7 +949,13 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
1201 | #endif | 949 | #endif |
1202 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; | 950 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; |
1203 | 951 | ||
1204 | SET_NETDEV_DEV(dev, dmdev); | 952 | |
953 | // TODO: kzalloc + iwm_init_default_profile(iwm, iwm->umac_profile); ?? | ||
954 | |||
955 | |||
956 | priv->card = card; | ||
957 | priv->infra_open = 0; | ||
958 | |||
1205 | 959 | ||
1206 | priv->rtap_net_dev = NULL; | 960 | priv->rtap_net_dev = NULL; |
1207 | strcpy(dev->name, "wlan%d"); | 961 | strcpy(dev->name, "wlan%d"); |
@@ -1211,26 +965,28 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
1211 | priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main"); | 965 | priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main"); |
1212 | if (IS_ERR(priv->main_thread)) { | 966 | if (IS_ERR(priv->main_thread)) { |
1213 | lbs_deb_thread("Error creating main thread.\n"); | 967 | lbs_deb_thread("Error creating main thread.\n"); |
1214 | goto err_init_adapter; | 968 | goto err_ndev; |
1215 | } | 969 | } |
1216 | 970 | ||
1217 | priv->work_thread = create_singlethread_workqueue("lbs_worker"); | 971 | priv->work_thread = create_singlethread_workqueue("lbs_worker"); |
1218 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); | 972 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); |
1219 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); | 973 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); |
1220 | INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); | 974 | INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); |
1221 | INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker); | ||
1222 | |||
1223 | sprintf(priv->mesh_ssid, "mesh"); | ||
1224 | priv->mesh_ssid_len = 4; | ||
1225 | 975 | ||
1226 | priv->wol_criteria = 0xffffffff; | 976 | priv->wol_criteria = 0xffffffff; |
1227 | priv->wol_gpio = 0xff; | 977 | priv->wol_gpio = 0xff; |
1228 | 978 | ||
1229 | goto done; | 979 | goto done; |
1230 | 980 | ||
1231 | err_init_adapter: | 981 | err_ndev: |
1232 | lbs_free_adapter(priv); | ||
1233 | free_netdev(dev); | 982 | free_netdev(dev); |
983 | |||
984 | err_adapter: | ||
985 | lbs_free_adapter(priv); | ||
986 | |||
987 | err_wdev: | ||
988 | lbs_cfg_free(priv); | ||
989 | |||
1234 | priv = NULL; | 990 | priv = NULL; |
1235 | 991 | ||
1236 | done: | 992 | done: |
@@ -1243,7 +999,6 @@ EXPORT_SYMBOL_GPL(lbs_add_card); | |||
1243 | void lbs_remove_card(struct lbs_private *priv) | 999 | void lbs_remove_card(struct lbs_private *priv) |
1244 | { | 1000 | { |
1245 | struct net_device *dev = priv->dev; | 1001 | struct net_device *dev = priv->dev; |
1246 | union iwreq_data wrqu; | ||
1247 | 1002 | ||
1248 | lbs_deb_enter(LBS_DEB_MAIN); | 1003 | lbs_deb_enter(LBS_DEB_MAIN); |
1249 | 1004 | ||
@@ -1268,15 +1023,19 @@ void lbs_remove_card(struct lbs_private *priv) | |||
1268 | lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); | 1023 | lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); |
1269 | } | 1024 | } |
1270 | 1025 | ||
1271 | memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN); | 1026 | lbs_send_disconnect_notification(priv); |
1272 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | 1027 | |
1273 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | 1028 | if (priv->is_deep_sleep) { |
1029 | priv->is_deep_sleep = 0; | ||
1030 | wake_up_interruptible(&priv->ds_awake_q); | ||
1031 | } | ||
1274 | 1032 | ||
1275 | /* Stop the thread servicing the interrupts */ | 1033 | /* Stop the thread servicing the interrupts */ |
1276 | priv->surpriseremoved = 1; | 1034 | priv->surpriseremoved = 1; |
1277 | kthread_stop(priv->main_thread); | 1035 | kthread_stop(priv->main_thread); |
1278 | 1036 | ||
1279 | lbs_free_adapter(priv); | 1037 | lbs_free_adapter(priv); |
1038 | lbs_cfg_free(priv); | ||
1280 | 1039 | ||
1281 | priv->dev = NULL; | 1040 | priv->dev = NULL; |
1282 | free_netdev(dev); | 1041 | free_netdev(dev); |
@@ -1286,6 +1045,17 @@ void lbs_remove_card(struct lbs_private *priv) | |||
1286 | EXPORT_SYMBOL_GPL(lbs_remove_card); | 1045 | EXPORT_SYMBOL_GPL(lbs_remove_card); |
1287 | 1046 | ||
1288 | 1047 | ||
1048 | static int lbs_rtap_supported(struct lbs_private *priv) | ||
1049 | { | ||
1050 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) | ||
1051 | return 1; | ||
1052 | |||
1053 | /* newer firmware use a capability mask */ | ||
1054 | return ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && | ||
1055 | (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)); | ||
1056 | } | ||
1057 | |||
1058 | |||
1289 | int lbs_start_card(struct lbs_private *priv) | 1059 | int lbs_start_card(struct lbs_private *priv) |
1290 | { | 1060 | { |
1291 | struct net_device *dev = priv->dev; | 1061 | struct net_device *dev = priv->dev; |
@@ -1298,60 +1068,21 @@ int lbs_start_card(struct lbs_private *priv) | |||
1298 | if (ret) | 1068 | if (ret) |
1299 | goto done; | 1069 | goto done; |
1300 | 1070 | ||
1301 | /* init 802.11d */ | 1071 | if (lbs_cfg_register(priv)) { |
1302 | lbs_init_11d(priv); | 1072 | lbs_pr_err("cannot register device\n"); |
1303 | |||
1304 | if (register_netdev(dev)) { | ||
1305 | lbs_pr_err("cannot register ethX device\n"); | ||
1306 | goto done; | 1073 | goto done; |
1307 | } | 1074 | } |
1308 | 1075 | ||
1309 | lbs_update_channel(priv); | 1076 | lbs_update_channel(priv); |
1310 | 1077 | ||
1311 | /* Check mesh FW version and appropriately send the mesh start | 1078 | lbs_init_mesh(priv); |
1312 | * command | ||
1313 | */ | ||
1314 | if (priv->mesh_fw_ver == MESH_FW_OLD) { | ||
1315 | /* Enable mesh, if supported, and work out which TLV it uses. | ||
1316 | 0x100 + 291 is an unofficial value used in 5.110.20.pXX | ||
1317 | 0x100 + 37 is the official value used in 5.110.21.pXX | ||
1318 | but we check them in that order because 20.pXX doesn't | ||
1319 | give an error -- it just silently fails. */ | ||
1320 | |||
1321 | /* 5.110.20.pXX firmware will fail the command if the channel | ||
1322 | doesn't match the existing channel. But only if the TLV | ||
1323 | is correct. If the channel is wrong, _BOTH_ versions will | ||
1324 | give an error to 0x100+291, and allow 0x100+37 to succeed. | ||
1325 | It's just that 5.110.20.pXX will not have done anything | ||
1326 | useful */ | ||
1327 | |||
1328 | priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID; | ||
1329 | if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, | ||
1330 | priv->curbssparams.channel)) { | ||
1331 | priv->mesh_tlv = TLV_TYPE_MESH_ID; | ||
1332 | if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, | ||
1333 | priv->curbssparams.channel)) | ||
1334 | priv->mesh_tlv = 0; | ||
1335 | } | ||
1336 | } else if (priv->mesh_fw_ver == MESH_FW_NEW) { | ||
1337 | /* 10.0.0.pXX new firmwares should succeed with TLV | ||
1338 | * 0x100+37; Do not invoke command with old TLV. | ||
1339 | */ | ||
1340 | priv->mesh_tlv = TLV_TYPE_MESH_ID; | ||
1341 | if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, | ||
1342 | priv->curbssparams.channel)) | ||
1343 | priv->mesh_tlv = 0; | ||
1344 | } | ||
1345 | if (priv->mesh_tlv) { | ||
1346 | lbs_add_mesh(priv); | ||
1347 | |||
1348 | if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) | ||
1349 | lbs_pr_err("cannot register lbs_mesh attribute\n"); | ||
1350 | 1079 | ||
1351 | /* While rtap isn't related to mesh, only mesh-enabled | 1080 | /* |
1352 | * firmware implements the rtap functionality via | 1081 | * While rtap isn't related to mesh, only mesh-enabled |
1353 | * CMD_802_11_MONITOR_MODE. | 1082 | * firmware implements the rtap functionality via |
1354 | */ | 1083 | * CMD_802_11_MONITOR_MODE. |
1084 | */ | ||
1085 | if (lbs_rtap_supported(priv)) { | ||
1355 | if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) | 1086 | if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) |
1356 | lbs_pr_err("cannot register lbs_rtap attribute\n"); | 1087 | lbs_pr_err("cannot register lbs_rtap attribute\n"); |
1357 | } | 1088 | } |
@@ -1385,13 +1116,14 @@ void lbs_stop_card(struct lbs_private *priv) | |||
1385 | netif_carrier_off(dev); | 1116 | netif_carrier_off(dev); |
1386 | 1117 | ||
1387 | lbs_debugfs_remove_one(priv); | 1118 | lbs_debugfs_remove_one(priv); |
1388 | if (priv->mesh_tlv) { | 1119 | lbs_deinit_mesh(priv); |
1389 | device_remove_file(&dev->dev, &dev_attr_lbs_mesh); | 1120 | |
1121 | if (lbs_rtap_supported(priv)) | ||
1390 | device_remove_file(&dev->dev, &dev_attr_lbs_rtap); | 1122 | device_remove_file(&dev->dev, &dev_attr_lbs_rtap); |
1391 | } | ||
1392 | 1123 | ||
1393 | /* Delete the timeout of the currently processing command */ | 1124 | /* Delete the timeout of the currently processing command */ |
1394 | del_timer_sync(&priv->command_timer); | 1125 | del_timer_sync(&priv->command_timer); |
1126 | del_timer_sync(&priv->auto_deepsleep_timer); | ||
1395 | 1127 | ||
1396 | /* Flush pending command nodes */ | 1128 | /* Flush pending command nodes */ |
1397 | spin_lock_irqsave(&priv->driver_lock, flags); | 1129 | spin_lock_irqsave(&priv->driver_lock, flags); |
@@ -1420,157 +1152,6 @@ out: | |||
1420 | EXPORT_SYMBOL_GPL(lbs_stop_card); | 1152 | EXPORT_SYMBOL_GPL(lbs_stop_card); |
1421 | 1153 | ||
1422 | 1154 | ||
1423 | static const struct net_device_ops mesh_netdev_ops = { | ||
1424 | .ndo_open = lbs_dev_open, | ||
1425 | .ndo_stop = lbs_mesh_stop, | ||
1426 | .ndo_start_xmit = lbs_hard_start_xmit, | ||
1427 | .ndo_set_mac_address = lbs_set_mac_address, | ||
1428 | .ndo_set_multicast_list = lbs_set_multicast_list, | ||
1429 | }; | ||
1430 | |||
1431 | /** | ||
1432 | * @brief This function adds mshX interface | ||
1433 | * | ||
1434 | * @param priv A pointer to the struct lbs_private structure | ||
1435 | * @return 0 if successful, -X otherwise | ||
1436 | */ | ||
1437 | static int lbs_add_mesh(struct lbs_private *priv) | ||
1438 | { | ||
1439 | struct net_device *mesh_dev = NULL; | ||
1440 | int ret = 0; | ||
1441 | |||
1442 | lbs_deb_enter(LBS_DEB_MESH); | ||
1443 | |||
1444 | /* Allocate a virtual mesh device */ | ||
1445 | if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) { | ||
1446 | lbs_deb_mesh("init mshX device failed\n"); | ||
1447 | ret = -ENOMEM; | ||
1448 | goto done; | ||
1449 | } | ||
1450 | mesh_dev->ml_priv = priv; | ||
1451 | priv->mesh_dev = mesh_dev; | ||
1452 | |||
1453 | mesh_dev->netdev_ops = &mesh_netdev_ops; | ||
1454 | mesh_dev->ethtool_ops = &lbs_ethtool_ops; | ||
1455 | memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, | ||
1456 | sizeof(priv->dev->dev_addr)); | ||
1457 | |||
1458 | SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent); | ||
1459 | |||
1460 | #ifdef WIRELESS_EXT | ||
1461 | mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def; | ||
1462 | #endif | ||
1463 | mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; | ||
1464 | /* Register virtual mesh interface */ | ||
1465 | ret = register_netdev(mesh_dev); | ||
1466 | if (ret) { | ||
1467 | lbs_pr_err("cannot register mshX virtual interface\n"); | ||
1468 | goto err_free; | ||
1469 | } | ||
1470 | |||
1471 | ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); | ||
1472 | if (ret) | ||
1473 | goto err_unregister; | ||
1474 | |||
1475 | lbs_persist_config_init(mesh_dev); | ||
1476 | |||
1477 | /* Everything successful */ | ||
1478 | ret = 0; | ||
1479 | goto done; | ||
1480 | |||
1481 | err_unregister: | ||
1482 | unregister_netdev(mesh_dev); | ||
1483 | |||
1484 | err_free: | ||
1485 | free_netdev(mesh_dev); | ||
1486 | |||
1487 | done: | ||
1488 | lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); | ||
1489 | return ret; | ||
1490 | } | ||
1491 | |||
1492 | static void lbs_remove_mesh(struct lbs_private *priv) | ||
1493 | { | ||
1494 | struct net_device *mesh_dev; | ||
1495 | |||
1496 | |||
1497 | mesh_dev = priv->mesh_dev; | ||
1498 | if (!mesh_dev) | ||
1499 | return; | ||
1500 | |||
1501 | lbs_deb_enter(LBS_DEB_MESH); | ||
1502 | netif_stop_queue(mesh_dev); | ||
1503 | netif_carrier_off(mesh_dev); | ||
1504 | sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); | ||
1505 | lbs_persist_config_remove(mesh_dev); | ||
1506 | unregister_netdev(mesh_dev); | ||
1507 | priv->mesh_dev = NULL; | ||
1508 | free_netdev(mesh_dev); | ||
1509 | lbs_deb_leave(LBS_DEB_MESH); | ||
1510 | } | ||
1511 | |||
1512 | /** | ||
1513 | * @brief This function finds the CFP in | ||
1514 | * region_cfp_table based on region and band parameter. | ||
1515 | * | ||
1516 | * @param region The region code | ||
1517 | * @param band The band | ||
1518 | * @param cfp_no A pointer to CFP number | ||
1519 | * @return A pointer to CFP | ||
1520 | */ | ||
1521 | struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no) | ||
1522 | { | ||
1523 | int i, end; | ||
1524 | |||
1525 | lbs_deb_enter(LBS_DEB_MAIN); | ||
1526 | |||
1527 | end = ARRAY_SIZE(region_cfp_table); | ||
1528 | |||
1529 | for (i = 0; i < end ; i++) { | ||
1530 | lbs_deb_main("region_cfp_table[i].region=%d\n", | ||
1531 | region_cfp_table[i].region); | ||
1532 | if (region_cfp_table[i].region == region) { | ||
1533 | *cfp_no = region_cfp_table[i].cfp_no_BG; | ||
1534 | lbs_deb_leave(LBS_DEB_MAIN); | ||
1535 | return region_cfp_table[i].cfp_BG; | ||
1536 | } | ||
1537 | } | ||
1538 | |||
1539 | lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL"); | ||
1540 | return NULL; | ||
1541 | } | ||
1542 | |||
1543 | int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band) | ||
1544 | { | ||
1545 | int ret = 0; | ||
1546 | int i = 0; | ||
1547 | |||
1548 | struct chan_freq_power *cfp; | ||
1549 | int cfp_no; | ||
1550 | |||
1551 | lbs_deb_enter(LBS_DEB_MAIN); | ||
1552 | |||
1553 | memset(priv->region_channel, 0, sizeof(priv->region_channel)); | ||
1554 | |||
1555 | cfp = lbs_get_region_cfp_table(region, &cfp_no); | ||
1556 | if (cfp != NULL) { | ||
1557 | priv->region_channel[i].nrcfp = cfp_no; | ||
1558 | priv->region_channel[i].CFP = cfp; | ||
1559 | } else { | ||
1560 | lbs_deb_main("wrong region code %#x in band B/G\n", | ||
1561 | region); | ||
1562 | ret = -1; | ||
1563 | goto out; | ||
1564 | } | ||
1565 | priv->region_channel[i].valid = 1; | ||
1566 | priv->region_channel[i].region = region; | ||
1567 | priv->region_channel[i].band = band; | ||
1568 | i++; | ||
1569 | out: | ||
1570 | lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); | ||
1571 | return ret; | ||
1572 | } | ||
1573 | |||
1574 | void lbs_queue_event(struct lbs_private *priv, u32 event) | 1155 | void lbs_queue_event(struct lbs_private *priv, u32 event) |
1575 | { | 1156 | { |
1576 | unsigned long flags; | 1157 | unsigned long flags; |
@@ -1581,7 +1162,7 @@ void lbs_queue_event(struct lbs_private *priv, u32 event) | |||
1581 | if (priv->psstate == PS_STATE_SLEEP) | 1162 | if (priv->psstate == PS_STATE_SLEEP) |
1582 | priv->psstate = PS_STATE_AWAKE; | 1163 | priv->psstate = PS_STATE_AWAKE; |
1583 | 1164 | ||
1584 | __kfifo_put(priv->event_fifo, (unsigned char *) &event, sizeof(u32)); | 1165 | kfifo_in(&priv->event_fifo, (unsigned char *) &event, sizeof(u32)); |
1585 | 1166 | ||
1586 | wake_up_interruptible(&priv->waitq); | 1167 | wake_up_interruptible(&priv->waitq); |
1587 | 1168 | ||
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c new file mode 100644 index 000000000000..e385af1f4583 --- /dev/null +++ b/drivers/net/wireless/libertas/mesh.c | |||
@@ -0,0 +1,1154 @@ | |||
1 | #include <linux/delay.h> | ||
2 | #include <linux/etherdevice.h> | ||
3 | #include <linux/netdevice.h> | ||
4 | #include <linux/if_ether.h> | ||
5 | #include <linux/if_arp.h> | ||
6 | #include <linux/kthread.h> | ||
7 | #include <linux/kfifo.h> | ||
8 | |||
9 | #include "mesh.h" | ||
10 | #include "decl.h" | ||
11 | #include "cmd.h" | ||
12 | |||
13 | |||
14 | /*************************************************************************** | ||
15 | * Mesh sysfs support | ||
16 | */ | ||
17 | |||
18 | /** | ||
19 | * Attributes exported through sysfs | ||
20 | */ | ||
21 | |||
22 | /** | ||
23 | * @brief Get function for sysfs attribute anycast_mask | ||
24 | */ | ||
25 | static ssize_t lbs_anycast_get(struct device *dev, | ||
26 | struct device_attribute *attr, char * buf) | ||
27 | { | ||
28 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
29 | struct cmd_ds_mesh_access mesh_access; | ||
30 | int ret; | ||
31 | |||
32 | memset(&mesh_access, 0, sizeof(mesh_access)); | ||
33 | |||
34 | ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_ANYCAST, &mesh_access); | ||
35 | if (ret) | ||
36 | return ret; | ||
37 | |||
38 | return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0])); | ||
39 | } | ||
40 | |||
41 | /** | ||
42 | * @brief Set function for sysfs attribute anycast_mask | ||
43 | */ | ||
44 | static ssize_t lbs_anycast_set(struct device *dev, | ||
45 | struct device_attribute *attr, const char * buf, size_t count) | ||
46 | { | ||
47 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
48 | struct cmd_ds_mesh_access mesh_access; | ||
49 | uint32_t datum; | ||
50 | int ret; | ||
51 | |||
52 | memset(&mesh_access, 0, sizeof(mesh_access)); | ||
53 | sscanf(buf, "%x", &datum); | ||
54 | mesh_access.data[0] = cpu_to_le32(datum); | ||
55 | |||
56 | ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access); | ||
57 | if (ret) | ||
58 | return ret; | ||
59 | |||
60 | return strlen(buf); | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * @brief Get function for sysfs attribute prb_rsp_limit | ||
65 | */ | ||
66 | static ssize_t lbs_prb_rsp_limit_get(struct device *dev, | ||
67 | struct device_attribute *attr, char *buf) | ||
68 | { | ||
69 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
70 | struct cmd_ds_mesh_access mesh_access; | ||
71 | int ret; | ||
72 | u32 retry_limit; | ||
73 | |||
74 | memset(&mesh_access, 0, sizeof(mesh_access)); | ||
75 | mesh_access.data[0] = cpu_to_le32(CMD_ACT_GET); | ||
76 | |||
77 | ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT, | ||
78 | &mesh_access); | ||
79 | if (ret) | ||
80 | return ret; | ||
81 | |||
82 | retry_limit = le32_to_cpu(mesh_access.data[1]); | ||
83 | return snprintf(buf, 10, "%d\n", retry_limit); | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * @brief Set function for sysfs attribute prb_rsp_limit | ||
88 | */ | ||
89 | static ssize_t lbs_prb_rsp_limit_set(struct device *dev, | ||
90 | struct device_attribute *attr, const char *buf, size_t count) | ||
91 | { | ||
92 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
93 | struct cmd_ds_mesh_access mesh_access; | ||
94 | int ret; | ||
95 | unsigned long retry_limit; | ||
96 | |||
97 | memset(&mesh_access, 0, sizeof(mesh_access)); | ||
98 | mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET); | ||
99 | |||
100 | if (!strict_strtoul(buf, 10, &retry_limit)) | ||
101 | return -ENOTSUPP; | ||
102 | if (retry_limit > 15) | ||
103 | return -ENOTSUPP; | ||
104 | |||
105 | mesh_access.data[1] = cpu_to_le32(retry_limit); | ||
106 | |||
107 | ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT, | ||
108 | &mesh_access); | ||
109 | if (ret) | ||
110 | return ret; | ||
111 | |||
112 | return strlen(buf); | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * Get function for sysfs attribute mesh | ||
117 | */ | ||
118 | static ssize_t lbs_mesh_get(struct device *dev, | ||
119 | struct device_attribute *attr, char * buf) | ||
120 | { | ||
121 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
122 | return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev); | ||
123 | } | ||
124 | |||
125 | /** | ||
126 | * Set function for sysfs attribute mesh | ||
127 | */ | ||
128 | static ssize_t lbs_mesh_set(struct device *dev, | ||
129 | struct device_attribute *attr, const char * buf, size_t count) | ||
130 | { | ||
131 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
132 | int enable; | ||
133 | int ret, action = CMD_ACT_MESH_CONFIG_STOP; | ||
134 | |||
135 | sscanf(buf, "%x", &enable); | ||
136 | enable = !!enable; | ||
137 | if (enable == !!priv->mesh_dev) | ||
138 | return count; | ||
139 | if (enable) | ||
140 | action = CMD_ACT_MESH_CONFIG_START; | ||
141 | ret = lbs_mesh_config(priv, action, priv->channel); | ||
142 | if (ret) | ||
143 | return ret; | ||
144 | |||
145 | if (enable) | ||
146 | lbs_add_mesh(priv); | ||
147 | else | ||
148 | lbs_remove_mesh(priv); | ||
149 | |||
150 | return count; | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * lbs_mesh attribute to be exported per ethX interface | ||
155 | * through sysfs (/sys/class/net/ethX/lbs_mesh) | ||
156 | */ | ||
157 | static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set); | ||
158 | |||
159 | /** | ||
160 | * anycast_mask attribute to be exported per mshX interface | ||
161 | * through sysfs (/sys/class/net/mshX/anycast_mask) | ||
162 | */ | ||
163 | static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set); | ||
164 | |||
165 | /** | ||
166 | * prb_rsp_limit attribute to be exported per mshX interface | ||
167 | * through sysfs (/sys/class/net/mshX/prb_rsp_limit) | ||
168 | */ | ||
169 | static DEVICE_ATTR(prb_rsp_limit, 0644, lbs_prb_rsp_limit_get, | ||
170 | lbs_prb_rsp_limit_set); | ||
171 | |||
172 | static struct attribute *lbs_mesh_sysfs_entries[] = { | ||
173 | &dev_attr_anycast_mask.attr, | ||
174 | &dev_attr_prb_rsp_limit.attr, | ||
175 | NULL, | ||
176 | }; | ||
177 | |||
178 | static struct attribute_group lbs_mesh_attr_group = { | ||
179 | .attrs = lbs_mesh_sysfs_entries, | ||
180 | }; | ||
181 | |||
182 | |||
183 | |||
184 | /*************************************************************************** | ||
185 | * Initializing and starting, stopping mesh | ||
186 | */ | ||
187 | |||
188 | /* | ||
189 | * Check mesh FW version and appropriately send the mesh start | ||
190 | * command | ||
191 | */ | ||
192 | int lbs_init_mesh(struct lbs_private *priv) | ||
193 | { | ||
194 | struct net_device *dev = priv->dev; | ||
195 | int ret = 0; | ||
196 | |||
197 | lbs_deb_enter(LBS_DEB_MESH); | ||
198 | |||
199 | priv->mesh_connect_status = LBS_DISCONNECTED; | ||
200 | |||
201 | /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ | ||
202 | /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ | ||
203 | /* 5.110.22 have mesh command with 0xa3 command id */ | ||
204 | /* 10.0.0.p0 FW brings in mesh config command with different id */ | ||
205 | /* Check FW version MSB and initialize mesh_fw_ver */ | ||
206 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) { | ||
207 | /* Enable mesh, if supported, and work out which TLV it uses. | ||
208 | 0x100 + 291 is an unofficial value used in 5.110.20.pXX | ||
209 | 0x100 + 37 is the official value used in 5.110.21.pXX | ||
210 | but we check them in that order because 20.pXX doesn't | ||
211 | give an error -- it just silently fails. */ | ||
212 | |||
213 | /* 5.110.20.pXX firmware will fail the command if the channel | ||
214 | doesn't match the existing channel. But only if the TLV | ||
215 | is correct. If the channel is wrong, _BOTH_ versions will | ||
216 | give an error to 0x100+291, and allow 0x100+37 to succeed. | ||
217 | It's just that 5.110.20.pXX will not have done anything | ||
218 | useful */ | ||
219 | |||
220 | priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID; | ||
221 | if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, | ||
222 | priv->channel)) { | ||
223 | priv->mesh_tlv = TLV_TYPE_MESH_ID; | ||
224 | if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, | ||
225 | priv->channel)) | ||
226 | priv->mesh_tlv = 0; | ||
227 | } | ||
228 | } else | ||
229 | if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && | ||
230 | (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) { | ||
231 | /* 10.0.0.pXX new firmwares should succeed with TLV | ||
232 | * 0x100+37; Do not invoke command with old TLV. | ||
233 | */ | ||
234 | priv->mesh_tlv = TLV_TYPE_MESH_ID; | ||
235 | if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, | ||
236 | priv->channel)) | ||
237 | priv->mesh_tlv = 0; | ||
238 | } | ||
239 | |||
240 | |||
241 | if (priv->mesh_tlv) { | ||
242 | sprintf(priv->mesh_ssid, "mesh"); | ||
243 | priv->mesh_ssid_len = 4; | ||
244 | |||
245 | lbs_add_mesh(priv); | ||
246 | |||
247 | if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) | ||
248 | lbs_pr_err("cannot register lbs_mesh attribute\n"); | ||
249 | |||
250 | ret = 1; | ||
251 | } | ||
252 | |||
253 | lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); | ||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | |||
258 | int lbs_deinit_mesh(struct lbs_private *priv) | ||
259 | { | ||
260 | struct net_device *dev = priv->dev; | ||
261 | int ret = 0; | ||
262 | |||
263 | lbs_deb_enter(LBS_DEB_MESH); | ||
264 | |||
265 | if (priv->mesh_tlv) { | ||
266 | device_remove_file(&dev->dev, &dev_attr_lbs_mesh); | ||
267 | ret = 1; | ||
268 | } | ||
269 | |||
270 | lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); | ||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | |||
275 | /** | ||
276 | * @brief This function closes the mshX interface | ||
277 | * | ||
278 | * @param dev A pointer to net_device structure | ||
279 | * @return 0 | ||
280 | */ | ||
281 | static int lbs_mesh_stop(struct net_device *dev) | ||
282 | { | ||
283 | struct lbs_private *priv = dev->ml_priv; | ||
284 | |||
285 | lbs_deb_enter(LBS_DEB_MESH); | ||
286 | spin_lock_irq(&priv->driver_lock); | ||
287 | |||
288 | priv->mesh_open = 0; | ||
289 | priv->mesh_connect_status = LBS_DISCONNECTED; | ||
290 | |||
291 | netif_stop_queue(dev); | ||
292 | netif_carrier_off(dev); | ||
293 | |||
294 | spin_unlock_irq(&priv->driver_lock); | ||
295 | |||
296 | schedule_work(&priv->mcast_work); | ||
297 | |||
298 | lbs_deb_leave(LBS_DEB_MESH); | ||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | /** | ||
303 | * @brief This function opens the mshX interface | ||
304 | * | ||
305 | * @param dev A pointer to net_device structure | ||
306 | * @return 0 or -EBUSY if monitor mode active | ||
307 | */ | ||
308 | static int lbs_mesh_dev_open(struct net_device *dev) | ||
309 | { | ||
310 | struct lbs_private *priv = dev->ml_priv; | ||
311 | int ret = 0; | ||
312 | |||
313 | lbs_deb_enter(LBS_DEB_NET); | ||
314 | |||
315 | spin_lock_irq(&priv->driver_lock); | ||
316 | |||
317 | if (priv->monitormode) { | ||
318 | ret = -EBUSY; | ||
319 | goto out; | ||
320 | } | ||
321 | |||
322 | priv->mesh_open = 1; | ||
323 | priv->mesh_connect_status = LBS_CONNECTED; | ||
324 | netif_carrier_on(dev); | ||
325 | |||
326 | if (!priv->tx_pending_len) | ||
327 | netif_wake_queue(dev); | ||
328 | out: | ||
329 | |||
330 | spin_unlock_irq(&priv->driver_lock); | ||
331 | lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); | ||
332 | return ret; | ||
333 | } | ||
334 | |||
335 | static const struct net_device_ops mesh_netdev_ops = { | ||
336 | .ndo_open = lbs_mesh_dev_open, | ||
337 | .ndo_stop = lbs_mesh_stop, | ||
338 | .ndo_start_xmit = lbs_hard_start_xmit, | ||
339 | .ndo_set_mac_address = lbs_set_mac_address, | ||
340 | .ndo_set_multicast_list = lbs_set_multicast_list, | ||
341 | }; | ||
342 | |||
343 | /** | ||
344 | * @brief This function adds mshX interface | ||
345 | * | ||
346 | * @param priv A pointer to the struct lbs_private structure | ||
347 | * @return 0 if successful, -X otherwise | ||
348 | */ | ||
349 | int lbs_add_mesh(struct lbs_private *priv) | ||
350 | { | ||
351 | struct net_device *mesh_dev = NULL; | ||
352 | int ret = 0; | ||
353 | |||
354 | lbs_deb_enter(LBS_DEB_MESH); | ||
355 | |||
356 | /* Allocate a virtual mesh device */ | ||
357 | mesh_dev = alloc_netdev(0, "msh%d", ether_setup); | ||
358 | if (!mesh_dev) { | ||
359 | lbs_deb_mesh("init mshX device failed\n"); | ||
360 | ret = -ENOMEM; | ||
361 | goto done; | ||
362 | } | ||
363 | mesh_dev->ml_priv = priv; | ||
364 | priv->mesh_dev = mesh_dev; | ||
365 | |||
366 | mesh_dev->netdev_ops = &mesh_netdev_ops; | ||
367 | mesh_dev->ethtool_ops = &lbs_ethtool_ops; | ||
368 | memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, ETH_ALEN); | ||
369 | |||
370 | SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent); | ||
371 | |||
372 | #ifdef WIRELESS_EXT | ||
373 | mesh_dev->wireless_handlers = &mesh_handler_def; | ||
374 | #endif | ||
375 | mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; | ||
376 | /* Register virtual mesh interface */ | ||
377 | ret = register_netdev(mesh_dev); | ||
378 | if (ret) { | ||
379 | lbs_pr_err("cannot register mshX virtual interface\n"); | ||
380 | goto err_free; | ||
381 | } | ||
382 | |||
383 | ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); | ||
384 | if (ret) | ||
385 | goto err_unregister; | ||
386 | |||
387 | lbs_persist_config_init(mesh_dev); | ||
388 | |||
389 | /* Everything successful */ | ||
390 | ret = 0; | ||
391 | goto done; | ||
392 | |||
393 | err_unregister: | ||
394 | unregister_netdev(mesh_dev); | ||
395 | |||
396 | err_free: | ||
397 | free_netdev(mesh_dev); | ||
398 | |||
399 | done: | ||
400 | lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); | ||
401 | return ret; | ||
402 | } | ||
403 | |||
404 | void lbs_remove_mesh(struct lbs_private *priv) | ||
405 | { | ||
406 | struct net_device *mesh_dev; | ||
407 | |||
408 | mesh_dev = priv->mesh_dev; | ||
409 | if (!mesh_dev) | ||
410 | return; | ||
411 | |||
412 | lbs_deb_enter(LBS_DEB_MESH); | ||
413 | netif_stop_queue(mesh_dev); | ||
414 | netif_carrier_off(mesh_dev); | ||
415 | sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); | ||
416 | lbs_persist_config_remove(mesh_dev); | ||
417 | unregister_netdev(mesh_dev); | ||
418 | priv->mesh_dev = NULL; | ||
419 | free_netdev(mesh_dev); | ||
420 | lbs_deb_leave(LBS_DEB_MESH); | ||
421 | } | ||
422 | |||
423 | |||
424 | |||
425 | /*************************************************************************** | ||
426 | * Sending and receiving | ||
427 | */ | ||
428 | struct net_device *lbs_mesh_set_dev(struct lbs_private *priv, | ||
429 | struct net_device *dev, struct rxpd *rxpd) | ||
430 | { | ||
431 | if (priv->mesh_dev) { | ||
432 | if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) { | ||
433 | if (rxpd->rx_control & RxPD_MESH_FRAME) | ||
434 | dev = priv->mesh_dev; | ||
435 | } else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) { | ||
436 | if (rxpd->u.bss.bss_num == MESH_IFACE_ID) | ||
437 | dev = priv->mesh_dev; | ||
438 | } | ||
439 | } | ||
440 | return dev; | ||
441 | } | ||
442 | |||
443 | |||
444 | void lbs_mesh_set_txpd(struct lbs_private *priv, | ||
445 | struct net_device *dev, struct txpd *txpd) | ||
446 | { | ||
447 | if (dev == priv->mesh_dev) { | ||
448 | if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) | ||
449 | txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); | ||
450 | else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) | ||
451 | txpd->u.bss.bss_num = MESH_IFACE_ID; | ||
452 | } | ||
453 | } | ||
454 | |||
455 | |||
456 | /*************************************************************************** | ||
457 | * Mesh command handling | ||
458 | */ | ||
459 | |||
460 | int lbs_cmd_bt_access(struct cmd_ds_command *cmd, | ||
461 | u16 cmd_action, void *pdata_buf) | ||
462 | { | ||
463 | struct cmd_ds_bt_access *bt_access = &cmd->params.bt; | ||
464 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | ||
465 | |||
466 | cmd->command = cpu_to_le16(CMD_BT_ACCESS); | ||
467 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + | ||
468 | sizeof(struct cmd_header)); | ||
469 | cmd->result = 0; | ||
470 | bt_access->action = cpu_to_le16(cmd_action); | ||
471 | |||
472 | switch (cmd_action) { | ||
473 | case CMD_ACT_BT_ACCESS_ADD: | ||
474 | memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN); | ||
475 | lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", | ||
476 | bt_access->addr1, 6); | ||
477 | break; | ||
478 | case CMD_ACT_BT_ACCESS_DEL: | ||
479 | memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN); | ||
480 | lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", | ||
481 | bt_access->addr1, 6); | ||
482 | break; | ||
483 | case CMD_ACT_BT_ACCESS_LIST: | ||
484 | bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); | ||
485 | break; | ||
486 | case CMD_ACT_BT_ACCESS_RESET: | ||
487 | break; | ||
488 | case CMD_ACT_BT_ACCESS_SET_INVERT: | ||
489 | bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); | ||
490 | break; | ||
491 | case CMD_ACT_BT_ACCESS_GET_INVERT: | ||
492 | break; | ||
493 | default: | ||
494 | break; | ||
495 | } | ||
496 | lbs_deb_leave(LBS_DEB_CMD); | ||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, | ||
501 | u16 cmd_action, void *pdata_buf) | ||
502 | { | ||
503 | struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt; | ||
504 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | ||
505 | |||
506 | cmd->command = cpu_to_le16(CMD_FWT_ACCESS); | ||
507 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + | ||
508 | sizeof(struct cmd_header)); | ||
509 | cmd->result = 0; | ||
510 | |||
511 | if (pdata_buf) | ||
512 | memcpy(fwt_access, pdata_buf, sizeof(*fwt_access)); | ||
513 | else | ||
514 | memset(fwt_access, 0, sizeof(*fwt_access)); | ||
515 | |||
516 | fwt_access->action = cpu_to_le16(cmd_action); | ||
517 | |||
518 | lbs_deb_leave(LBS_DEB_CMD); | ||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, | ||
523 | struct cmd_ds_mesh_access *cmd) | ||
524 | { | ||
525 | int ret; | ||
526 | |||
527 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | ||
528 | |||
529 | cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS); | ||
530 | cmd->hdr.size = cpu_to_le16(sizeof(*cmd)); | ||
531 | cmd->hdr.result = 0; | ||
532 | |||
533 | cmd->action = cpu_to_le16(cmd_action); | ||
534 | |||
535 | ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd); | ||
536 | |||
537 | lbs_deb_leave(LBS_DEB_CMD); | ||
538 | return ret; | ||
539 | } | ||
540 | |||
541 | static int __lbs_mesh_config_send(struct lbs_private *priv, | ||
542 | struct cmd_ds_mesh_config *cmd, | ||
543 | uint16_t action, uint16_t type) | ||
544 | { | ||
545 | int ret; | ||
546 | u16 command = CMD_MESH_CONFIG_OLD; | ||
547 | |||
548 | lbs_deb_enter(LBS_DEB_CMD); | ||
549 | |||
550 | /* | ||
551 | * Command id is 0xac for v10 FW along with mesh interface | ||
552 | * id in bits 14-13-12. | ||
553 | */ | ||
554 | if (priv->mesh_tlv == TLV_TYPE_MESH_ID) | ||
555 | command = CMD_MESH_CONFIG | | ||
556 | (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET); | ||
557 | |||
558 | cmd->hdr.command = cpu_to_le16(command); | ||
559 | cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config)); | ||
560 | cmd->hdr.result = 0; | ||
561 | |||
562 | cmd->type = cpu_to_le16(type); | ||
563 | cmd->action = cpu_to_le16(action); | ||
564 | |||
565 | ret = lbs_cmd_with_response(priv, command, cmd); | ||
566 | |||
567 | lbs_deb_leave(LBS_DEB_CMD); | ||
568 | return ret; | ||
569 | } | ||
570 | |||
571 | int lbs_mesh_config_send(struct lbs_private *priv, | ||
572 | struct cmd_ds_mesh_config *cmd, | ||
573 | uint16_t action, uint16_t type) | ||
574 | { | ||
575 | int ret; | ||
576 | |||
577 | if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG)) | ||
578 | return -EOPNOTSUPP; | ||
579 | |||
580 | ret = __lbs_mesh_config_send(priv, cmd, action, type); | ||
581 | return ret; | ||
582 | } | ||
583 | |||
584 | /* This function is the CMD_MESH_CONFIG legacy function. It only handles the | ||
585 | * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG | ||
586 | * are all handled by preparing a struct cmd_ds_mesh_config and passing it to | ||
587 | * lbs_mesh_config_send. | ||
588 | */ | ||
589 | int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan) | ||
590 | { | ||
591 | struct cmd_ds_mesh_config cmd; | ||
592 | struct mrvl_meshie *ie; | ||
593 | DECLARE_SSID_BUF(ssid); | ||
594 | |||
595 | memset(&cmd, 0, sizeof(cmd)); | ||
596 | cmd.channel = cpu_to_le16(chan); | ||
597 | ie = (struct mrvl_meshie *)cmd.data; | ||
598 | |||
599 | switch (action) { | ||
600 | case CMD_ACT_MESH_CONFIG_START: | ||
601 | ie->id = WLAN_EID_GENERIC; | ||
602 | ie->val.oui[0] = 0x00; | ||
603 | ie->val.oui[1] = 0x50; | ||
604 | ie->val.oui[2] = 0x43; | ||
605 | ie->val.type = MARVELL_MESH_IE_TYPE; | ||
606 | ie->val.subtype = MARVELL_MESH_IE_SUBTYPE; | ||
607 | ie->val.version = MARVELL_MESH_IE_VERSION; | ||
608 | ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP; | ||
609 | ie->val.active_metric_id = MARVELL_MESH_METRIC_ID; | ||
610 | ie->val.mesh_capability = MARVELL_MESH_CAPABILITY; | ||
611 | ie->val.mesh_id_len = priv->mesh_ssid_len; | ||
612 | memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len); | ||
613 | ie->len = sizeof(struct mrvl_meshie_val) - | ||
614 | IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len; | ||
615 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val)); | ||
616 | break; | ||
617 | case CMD_ACT_MESH_CONFIG_STOP: | ||
618 | break; | ||
619 | default: | ||
620 | return -1; | ||
621 | } | ||
622 | lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n", | ||
623 | action, priv->mesh_tlv, chan, | ||
624 | print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len)); | ||
625 | |||
626 | return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); | ||
627 | } | ||
628 | |||
629 | |||
630 | |||
631 | /*************************************************************************** | ||
632 | * Persistent configuration support | ||
633 | */ | ||
634 | |||
635 | static int mesh_get_default_parameters(struct device *dev, | ||
636 | struct mrvl_mesh_defaults *defs) | ||
637 | { | ||
638 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
639 | struct cmd_ds_mesh_config cmd; | ||
640 | int ret; | ||
641 | |||
642 | memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config)); | ||
643 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_GET, | ||
644 | CMD_TYPE_MESH_GET_DEFAULTS); | ||
645 | |||
646 | if (ret) | ||
647 | return -EOPNOTSUPP; | ||
648 | |||
649 | memcpy(defs, &cmd.data[0], sizeof(struct mrvl_mesh_defaults)); | ||
650 | |||
651 | return 0; | ||
652 | } | ||
653 | |||
654 | /** | ||
655 | * @brief Get function for sysfs attribute bootflag | ||
656 | */ | ||
657 | static ssize_t bootflag_get(struct device *dev, | ||
658 | struct device_attribute *attr, char *buf) | ||
659 | { | ||
660 | struct mrvl_mesh_defaults defs; | ||
661 | int ret; | ||
662 | |||
663 | ret = mesh_get_default_parameters(dev, &defs); | ||
664 | |||
665 | if (ret) | ||
666 | return ret; | ||
667 | |||
668 | return snprintf(buf, 12, "%d\n", le32_to_cpu(defs.bootflag)); | ||
669 | } | ||
670 | |||
671 | /** | ||
672 | * @brief Set function for sysfs attribute bootflag | ||
673 | */ | ||
674 | static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr, | ||
675 | const char *buf, size_t count) | ||
676 | { | ||
677 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
678 | struct cmd_ds_mesh_config cmd; | ||
679 | uint32_t datum; | ||
680 | int ret; | ||
681 | |||
682 | memset(&cmd, 0, sizeof(cmd)); | ||
683 | ret = sscanf(buf, "%d", &datum); | ||
684 | if ((ret != 1) || (datum > 1)) | ||
685 | return -EINVAL; | ||
686 | |||
687 | *((__le32 *)&cmd.data[0]) = cpu_to_le32(!!datum); | ||
688 | cmd.length = cpu_to_le16(sizeof(uint32_t)); | ||
689 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
690 | CMD_TYPE_MESH_SET_BOOTFLAG); | ||
691 | if (ret) | ||
692 | return ret; | ||
693 | |||
694 | return strlen(buf); | ||
695 | } | ||
696 | |||
697 | /** | ||
698 | * @brief Get function for sysfs attribute boottime | ||
699 | */ | ||
700 | static ssize_t boottime_get(struct device *dev, | ||
701 | struct device_attribute *attr, char *buf) | ||
702 | { | ||
703 | struct mrvl_mesh_defaults defs; | ||
704 | int ret; | ||
705 | |||
706 | ret = mesh_get_default_parameters(dev, &defs); | ||
707 | |||
708 | if (ret) | ||
709 | return ret; | ||
710 | |||
711 | return snprintf(buf, 12, "%d\n", defs.boottime); | ||
712 | } | ||
713 | |||
714 | /** | ||
715 | * @brief Set function for sysfs attribute boottime | ||
716 | */ | ||
717 | static ssize_t boottime_set(struct device *dev, | ||
718 | struct device_attribute *attr, const char *buf, size_t count) | ||
719 | { | ||
720 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
721 | struct cmd_ds_mesh_config cmd; | ||
722 | uint32_t datum; | ||
723 | int ret; | ||
724 | |||
725 | memset(&cmd, 0, sizeof(cmd)); | ||
726 | ret = sscanf(buf, "%d", &datum); | ||
727 | if ((ret != 1) || (datum > 255)) | ||
728 | return -EINVAL; | ||
729 | |||
730 | /* A too small boot time will result in the device booting into | ||
731 | * standalone (no-host) mode before the host can take control of it, | ||
732 | * so the change will be hard to revert. This may be a desired | ||
733 | * feature (e.g to configure a very fast boot time for devices that | ||
734 | * will not be attached to a host), but dangerous. So I'm enforcing a | ||
735 | * lower limit of 20 seconds: remove and recompile the driver if this | ||
736 | * does not work for you. | ||
737 | */ | ||
738 | datum = (datum < 20) ? 20 : datum; | ||
739 | cmd.data[0] = datum; | ||
740 | cmd.length = cpu_to_le16(sizeof(uint8_t)); | ||
741 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
742 | CMD_TYPE_MESH_SET_BOOTTIME); | ||
743 | if (ret) | ||
744 | return ret; | ||
745 | |||
746 | return strlen(buf); | ||
747 | } | ||
748 | |||
749 | /** | ||
750 | * @brief Get function for sysfs attribute channel | ||
751 | */ | ||
752 | static ssize_t channel_get(struct device *dev, | ||
753 | struct device_attribute *attr, char *buf) | ||
754 | { | ||
755 | struct mrvl_mesh_defaults defs; | ||
756 | int ret; | ||
757 | |||
758 | ret = mesh_get_default_parameters(dev, &defs); | ||
759 | |||
760 | if (ret) | ||
761 | return ret; | ||
762 | |||
763 | return snprintf(buf, 12, "%d\n", le16_to_cpu(defs.channel)); | ||
764 | } | ||
765 | |||
766 | /** | ||
767 | * @brief Set function for sysfs attribute channel | ||
768 | */ | ||
769 | static ssize_t channel_set(struct device *dev, struct device_attribute *attr, | ||
770 | const char *buf, size_t count) | ||
771 | { | ||
772 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
773 | struct cmd_ds_mesh_config cmd; | ||
774 | uint32_t datum; | ||
775 | int ret; | ||
776 | |||
777 | memset(&cmd, 0, sizeof(cmd)); | ||
778 | ret = sscanf(buf, "%d", &datum); | ||
779 | if (ret != 1 || datum < 1 || datum > 11) | ||
780 | return -EINVAL; | ||
781 | |||
782 | *((__le16 *)&cmd.data[0]) = cpu_to_le16(datum); | ||
783 | cmd.length = cpu_to_le16(sizeof(uint16_t)); | ||
784 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
785 | CMD_TYPE_MESH_SET_DEF_CHANNEL); | ||
786 | if (ret) | ||
787 | return ret; | ||
788 | |||
789 | return strlen(buf); | ||
790 | } | ||
791 | |||
792 | /** | ||
793 | * @brief Get function for sysfs attribute mesh_id | ||
794 | */ | ||
795 | static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr, | ||
796 | char *buf) | ||
797 | { | ||
798 | struct mrvl_mesh_defaults defs; | ||
799 | int maxlen; | ||
800 | int ret; | ||
801 | |||
802 | ret = mesh_get_default_parameters(dev, &defs); | ||
803 | |||
804 | if (ret) | ||
805 | return ret; | ||
806 | |||
807 | if (defs.meshie.val.mesh_id_len > IEEE80211_MAX_SSID_LEN) { | ||
808 | lbs_pr_err("inconsistent mesh ID length"); | ||
809 | defs.meshie.val.mesh_id_len = IEEE80211_MAX_SSID_LEN; | ||
810 | } | ||
811 | |||
812 | /* SSID not null terminated: reserve room for \0 + \n */ | ||
813 | maxlen = defs.meshie.val.mesh_id_len + 2; | ||
814 | maxlen = (PAGE_SIZE > maxlen) ? maxlen : PAGE_SIZE; | ||
815 | |||
816 | defs.meshie.val.mesh_id[defs.meshie.val.mesh_id_len] = '\0'; | ||
817 | |||
818 | return snprintf(buf, maxlen, "%s\n", defs.meshie.val.mesh_id); | ||
819 | } | ||
820 | |||
821 | /** | ||
822 | * @brief Set function for sysfs attribute mesh_id | ||
823 | */ | ||
824 | static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr, | ||
825 | const char *buf, size_t count) | ||
826 | { | ||
827 | struct cmd_ds_mesh_config cmd; | ||
828 | struct mrvl_mesh_defaults defs; | ||
829 | struct mrvl_meshie *ie; | ||
830 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
831 | int len; | ||
832 | int ret; | ||
833 | |||
834 | if (count < 2 || count > IEEE80211_MAX_SSID_LEN + 1) | ||
835 | return -EINVAL; | ||
836 | |||
837 | memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config)); | ||
838 | ie = (struct mrvl_meshie *) &cmd.data[0]; | ||
839 | |||
840 | /* fetch all other Information Element parameters */ | ||
841 | ret = mesh_get_default_parameters(dev, &defs); | ||
842 | |||
843 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); | ||
844 | |||
845 | /* transfer IE elements */ | ||
846 | memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); | ||
847 | |||
848 | len = count - 1; | ||
849 | memcpy(ie->val.mesh_id, buf, len); | ||
850 | /* SSID len */ | ||
851 | ie->val.mesh_id_len = len; | ||
852 | /* IE len */ | ||
853 | ie->len = sizeof(struct mrvl_meshie_val) - IEEE80211_MAX_SSID_LEN + len; | ||
854 | |||
855 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
856 | CMD_TYPE_MESH_SET_MESH_IE); | ||
857 | if (ret) | ||
858 | return ret; | ||
859 | |||
860 | return strlen(buf); | ||
861 | } | ||
862 | |||
863 | /** | ||
864 | * @brief Get function for sysfs attribute protocol_id | ||
865 | */ | ||
866 | static ssize_t protocol_id_get(struct device *dev, | ||
867 | struct device_attribute *attr, char *buf) | ||
868 | { | ||
869 | struct mrvl_mesh_defaults defs; | ||
870 | int ret; | ||
871 | |||
872 | ret = mesh_get_default_parameters(dev, &defs); | ||
873 | |||
874 | if (ret) | ||
875 | return ret; | ||
876 | |||
877 | return snprintf(buf, 5, "%d\n", defs.meshie.val.active_protocol_id); | ||
878 | } | ||
879 | |||
880 | /** | ||
881 | * @brief Set function for sysfs attribute protocol_id | ||
882 | */ | ||
883 | static ssize_t protocol_id_set(struct device *dev, | ||
884 | struct device_attribute *attr, const char *buf, size_t count) | ||
885 | { | ||
886 | struct cmd_ds_mesh_config cmd; | ||
887 | struct mrvl_mesh_defaults defs; | ||
888 | struct mrvl_meshie *ie; | ||
889 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
890 | uint32_t datum; | ||
891 | int ret; | ||
892 | |||
893 | memset(&cmd, 0, sizeof(cmd)); | ||
894 | ret = sscanf(buf, "%d", &datum); | ||
895 | if ((ret != 1) || (datum > 255)) | ||
896 | return -EINVAL; | ||
897 | |||
898 | /* fetch all other Information Element parameters */ | ||
899 | ret = mesh_get_default_parameters(dev, &defs); | ||
900 | |||
901 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); | ||
902 | |||
903 | /* transfer IE elements */ | ||
904 | ie = (struct mrvl_meshie *) &cmd.data[0]; | ||
905 | memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); | ||
906 | /* update protocol id */ | ||
907 | ie->val.active_protocol_id = datum; | ||
908 | |||
909 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
910 | CMD_TYPE_MESH_SET_MESH_IE); | ||
911 | if (ret) | ||
912 | return ret; | ||
913 | |||
914 | return strlen(buf); | ||
915 | } | ||
916 | |||
917 | /** | ||
918 | * @brief Get function for sysfs attribute metric_id | ||
919 | */ | ||
920 | static ssize_t metric_id_get(struct device *dev, | ||
921 | struct device_attribute *attr, char *buf) | ||
922 | { | ||
923 | struct mrvl_mesh_defaults defs; | ||
924 | int ret; | ||
925 | |||
926 | ret = mesh_get_default_parameters(dev, &defs); | ||
927 | |||
928 | if (ret) | ||
929 | return ret; | ||
930 | |||
931 | return snprintf(buf, 5, "%d\n", defs.meshie.val.active_metric_id); | ||
932 | } | ||
933 | |||
934 | /** | ||
935 | * @brief Set function for sysfs attribute metric_id | ||
936 | */ | ||
937 | static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr, | ||
938 | const char *buf, size_t count) | ||
939 | { | ||
940 | struct cmd_ds_mesh_config cmd; | ||
941 | struct mrvl_mesh_defaults defs; | ||
942 | struct mrvl_meshie *ie; | ||
943 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
944 | uint32_t datum; | ||
945 | int ret; | ||
946 | |||
947 | memset(&cmd, 0, sizeof(cmd)); | ||
948 | ret = sscanf(buf, "%d", &datum); | ||
949 | if ((ret != 1) || (datum > 255)) | ||
950 | return -EINVAL; | ||
951 | |||
952 | /* fetch all other Information Element parameters */ | ||
953 | ret = mesh_get_default_parameters(dev, &defs); | ||
954 | |||
955 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); | ||
956 | |||
957 | /* transfer IE elements */ | ||
958 | ie = (struct mrvl_meshie *) &cmd.data[0]; | ||
959 | memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); | ||
960 | /* update metric id */ | ||
961 | ie->val.active_metric_id = datum; | ||
962 | |||
963 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
964 | CMD_TYPE_MESH_SET_MESH_IE); | ||
965 | if (ret) | ||
966 | return ret; | ||
967 | |||
968 | return strlen(buf); | ||
969 | } | ||
970 | |||
971 | /** | ||
972 | * @brief Get function for sysfs attribute capability | ||
973 | */ | ||
974 | static ssize_t capability_get(struct device *dev, | ||
975 | struct device_attribute *attr, char *buf) | ||
976 | { | ||
977 | struct mrvl_mesh_defaults defs; | ||
978 | int ret; | ||
979 | |||
980 | ret = mesh_get_default_parameters(dev, &defs); | ||
981 | |||
982 | if (ret) | ||
983 | return ret; | ||
984 | |||
985 | return snprintf(buf, 5, "%d\n", defs.meshie.val.mesh_capability); | ||
986 | } | ||
987 | |||
988 | /** | ||
989 | * @brief Set function for sysfs attribute capability | ||
990 | */ | ||
991 | static ssize_t capability_set(struct device *dev, struct device_attribute *attr, | ||
992 | const char *buf, size_t count) | ||
993 | { | ||
994 | struct cmd_ds_mesh_config cmd; | ||
995 | struct mrvl_mesh_defaults defs; | ||
996 | struct mrvl_meshie *ie; | ||
997 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
998 | uint32_t datum; | ||
999 | int ret; | ||
1000 | |||
1001 | memset(&cmd, 0, sizeof(cmd)); | ||
1002 | ret = sscanf(buf, "%d", &datum); | ||
1003 | if ((ret != 1) || (datum > 255)) | ||
1004 | return -EINVAL; | ||
1005 | |||
1006 | /* fetch all other Information Element parameters */ | ||
1007 | ret = mesh_get_default_parameters(dev, &defs); | ||
1008 | |||
1009 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); | ||
1010 | |||
1011 | /* transfer IE elements */ | ||
1012 | ie = (struct mrvl_meshie *) &cmd.data[0]; | ||
1013 | memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); | ||
1014 | /* update value */ | ||
1015 | ie->val.mesh_capability = datum; | ||
1016 | |||
1017 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
1018 | CMD_TYPE_MESH_SET_MESH_IE); | ||
1019 | if (ret) | ||
1020 | return ret; | ||
1021 | |||
1022 | return strlen(buf); | ||
1023 | } | ||
1024 | |||
1025 | |||
1026 | static DEVICE_ATTR(bootflag, 0644, bootflag_get, bootflag_set); | ||
1027 | static DEVICE_ATTR(boottime, 0644, boottime_get, boottime_set); | ||
1028 | static DEVICE_ATTR(channel, 0644, channel_get, channel_set); | ||
1029 | static DEVICE_ATTR(mesh_id, 0644, mesh_id_get, mesh_id_set); | ||
1030 | static DEVICE_ATTR(protocol_id, 0644, protocol_id_get, protocol_id_set); | ||
1031 | static DEVICE_ATTR(metric_id, 0644, metric_id_get, metric_id_set); | ||
1032 | static DEVICE_ATTR(capability, 0644, capability_get, capability_set); | ||
1033 | |||
1034 | static struct attribute *boot_opts_attrs[] = { | ||
1035 | &dev_attr_bootflag.attr, | ||
1036 | &dev_attr_boottime.attr, | ||
1037 | &dev_attr_channel.attr, | ||
1038 | NULL | ||
1039 | }; | ||
1040 | |||
1041 | static struct attribute_group boot_opts_group = { | ||
1042 | .name = "boot_options", | ||
1043 | .attrs = boot_opts_attrs, | ||
1044 | }; | ||
1045 | |||
1046 | static struct attribute *mesh_ie_attrs[] = { | ||
1047 | &dev_attr_mesh_id.attr, | ||
1048 | &dev_attr_protocol_id.attr, | ||
1049 | &dev_attr_metric_id.attr, | ||
1050 | &dev_attr_capability.attr, | ||
1051 | NULL | ||
1052 | }; | ||
1053 | |||
1054 | static struct attribute_group mesh_ie_group = { | ||
1055 | .name = "mesh_ie", | ||
1056 | .attrs = mesh_ie_attrs, | ||
1057 | }; | ||
1058 | |||
1059 | void lbs_persist_config_init(struct net_device *dev) | ||
1060 | { | ||
1061 | int ret; | ||
1062 | ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group); | ||
1063 | ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group); | ||
1064 | } | ||
1065 | |||
1066 | void lbs_persist_config_remove(struct net_device *dev) | ||
1067 | { | ||
1068 | sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group); | ||
1069 | sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group); | ||
1070 | } | ||
1071 | |||
1072 | |||
1073 | |||
1074 | /*************************************************************************** | ||
1075 | * Ethtool related | ||
1076 | */ | ||
1077 | |||
1078 | static const char *mesh_stat_strings[] = { | ||
1079 | "drop_duplicate_bcast", | ||
1080 | "drop_ttl_zero", | ||
1081 | "drop_no_fwd_route", | ||
1082 | "drop_no_buffers", | ||
1083 | "fwded_unicast_cnt", | ||
1084 | "fwded_bcast_cnt", | ||
1085 | "drop_blind_table", | ||
1086 | "tx_failed_cnt" | ||
1087 | }; | ||
1088 | |||
1089 | void lbs_mesh_ethtool_get_stats(struct net_device *dev, | ||
1090 | struct ethtool_stats *stats, uint64_t *data) | ||
1091 | { | ||
1092 | struct lbs_private *priv = dev->ml_priv; | ||
1093 | struct cmd_ds_mesh_access mesh_access; | ||
1094 | int ret; | ||
1095 | |||
1096 | lbs_deb_enter(LBS_DEB_ETHTOOL); | ||
1097 | |||
1098 | /* Get Mesh Statistics */ | ||
1099 | ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access); | ||
1100 | |||
1101 | if (ret) { | ||
1102 | memset(data, 0, MESH_STATS_NUM*(sizeof(uint64_t))); | ||
1103 | return; | ||
1104 | } | ||
1105 | |||
1106 | priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]); | ||
1107 | priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]); | ||
1108 | priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]); | ||
1109 | priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]); | ||
1110 | priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]); | ||
1111 | priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]); | ||
1112 | priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]); | ||
1113 | priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]); | ||
1114 | |||
1115 | data[0] = priv->mstats.fwd_drop_rbt; | ||
1116 | data[1] = priv->mstats.fwd_drop_ttl; | ||
1117 | data[2] = priv->mstats.fwd_drop_noroute; | ||
1118 | data[3] = priv->mstats.fwd_drop_nobuf; | ||
1119 | data[4] = priv->mstats.fwd_unicast_cnt; | ||
1120 | data[5] = priv->mstats.fwd_bcast_cnt; | ||
1121 | data[6] = priv->mstats.drop_blind; | ||
1122 | data[7] = priv->mstats.tx_failed_cnt; | ||
1123 | |||
1124 | lbs_deb_enter(LBS_DEB_ETHTOOL); | ||
1125 | } | ||
1126 | |||
1127 | int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset) | ||
1128 | { | ||
1129 | struct lbs_private *priv = dev->ml_priv; | ||
1130 | |||
1131 | if (sset == ETH_SS_STATS && dev == priv->mesh_dev) | ||
1132 | return MESH_STATS_NUM; | ||
1133 | |||
1134 | return -EOPNOTSUPP; | ||
1135 | } | ||
1136 | |||
1137 | void lbs_mesh_ethtool_get_strings(struct net_device *dev, | ||
1138 | uint32_t stringset, uint8_t *s) | ||
1139 | { | ||
1140 | int i; | ||
1141 | |||
1142 | lbs_deb_enter(LBS_DEB_ETHTOOL); | ||
1143 | |||
1144 | switch (stringset) { | ||
1145 | case ETH_SS_STATS: | ||
1146 | for (i = 0; i < MESH_STATS_NUM; i++) { | ||
1147 | memcpy(s + i * ETH_GSTRING_LEN, | ||
1148 | mesh_stat_strings[i], | ||
1149 | ETH_GSTRING_LEN); | ||
1150 | } | ||
1151 | break; | ||
1152 | } | ||
1153 | lbs_deb_enter(LBS_DEB_ETHTOOL); | ||
1154 | } | ||
diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h new file mode 100644 index 000000000000..e2573303a328 --- /dev/null +++ b/drivers/net/wireless/libertas/mesh.h | |||
@@ -0,0 +1,110 @@ | |||
1 | /** | ||
2 | * Contains all definitions needed for the Libertas' MESH implementation. | ||
3 | */ | ||
4 | #ifndef _LBS_MESH_H_ | ||
5 | #define _LBS_MESH_H_ | ||
6 | |||
7 | |||
8 | #include <net/iw_handler.h> | ||
9 | #include <net/lib80211.h> | ||
10 | |||
11 | |||
12 | #ifdef CONFIG_LIBERTAS_MESH | ||
13 | |||
14 | /* Mesh statistics */ | ||
15 | struct lbs_mesh_stats { | ||
16 | u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */ | ||
17 | u32 fwd_unicast_cnt; /* Fwd: Unicast counter */ | ||
18 | u32 fwd_drop_ttl; /* Fwd: TTL zero */ | ||
19 | u32 fwd_drop_rbt; /* Fwd: Recently Broadcasted */ | ||
20 | u32 fwd_drop_noroute; /* Fwd: No route to Destination */ | ||
21 | u32 fwd_drop_nobuf; /* Fwd: Run out of internal buffers */ | ||
22 | u32 drop_blind; /* Rx: Dropped by blinding table */ | ||
23 | u32 tx_failed_cnt; /* Tx: Failed transmissions */ | ||
24 | }; | ||
25 | |||
26 | |||
27 | struct net_device; | ||
28 | struct lbs_private; | ||
29 | |||
30 | int lbs_init_mesh(struct lbs_private *priv); | ||
31 | int lbs_deinit_mesh(struct lbs_private *priv); | ||
32 | |||
33 | int lbs_add_mesh(struct lbs_private *priv); | ||
34 | void lbs_remove_mesh(struct lbs_private *priv); | ||
35 | |||
36 | |||
37 | /* Sending / Receiving */ | ||
38 | |||
39 | struct rxpd; | ||
40 | struct txpd; | ||
41 | |||
42 | struct net_device *lbs_mesh_set_dev(struct lbs_private *priv, | ||
43 | struct net_device *dev, struct rxpd *rxpd); | ||
44 | void lbs_mesh_set_txpd(struct lbs_private *priv, | ||
45 | struct net_device *dev, struct txpd *txpd); | ||
46 | |||
47 | |||
48 | /* Command handling */ | ||
49 | |||
50 | struct cmd_ds_command; | ||
51 | struct cmd_ds_mesh_access; | ||
52 | struct cmd_ds_mesh_config; | ||
53 | |||
54 | int lbs_cmd_bt_access(struct cmd_ds_command *cmd, | ||
55 | u16 cmd_action, void *pdata_buf); | ||
56 | int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, | ||
57 | u16 cmd_action, void *pdata_buf); | ||
58 | int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, | ||
59 | struct cmd_ds_mesh_access *cmd); | ||
60 | int lbs_mesh_config_send(struct lbs_private *priv, | ||
61 | struct cmd_ds_mesh_config *cmd, | ||
62 | uint16_t action, uint16_t type); | ||
63 | int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); | ||
64 | |||
65 | |||
66 | |||
67 | /* Persistent configuration */ | ||
68 | |||
69 | void lbs_persist_config_init(struct net_device *net); | ||
70 | void lbs_persist_config_remove(struct net_device *net); | ||
71 | |||
72 | |||
73 | /* WEXT handler */ | ||
74 | |||
75 | extern struct iw_handler_def mesh_handler_def; | ||
76 | |||
77 | |||
78 | /* Ethtool statistics */ | ||
79 | |||
80 | struct ethtool_stats; | ||
81 | |||
82 | void lbs_mesh_ethtool_get_stats(struct net_device *dev, | ||
83 | struct ethtool_stats *stats, uint64_t *data); | ||
84 | int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset); | ||
85 | void lbs_mesh_ethtool_get_strings(struct net_device *dev, | ||
86 | uint32_t stringset, uint8_t *s); | ||
87 | |||
88 | |||
89 | /* Accessors */ | ||
90 | |||
91 | #define lbs_mesh_open(priv) (priv->mesh_open) | ||
92 | #define lbs_mesh_connected(priv) (priv->mesh_connect_status == LBS_CONNECTED) | ||
93 | |||
94 | #else | ||
95 | |||
96 | #define lbs_init_mesh(priv) | ||
97 | #define lbs_deinit_mesh(priv) | ||
98 | #define lbs_add_mesh(priv) | ||
99 | #define lbs_remove_mesh(priv) | ||
100 | #define lbs_mesh_set_dev(priv, dev, rxpd) (dev) | ||
101 | #define lbs_mesh_set_txpd(priv, dev, txpd) | ||
102 | #define lbs_mesh_config(priv, enable, chan) | ||
103 | #define lbs_mesh_open(priv) (0) | ||
104 | #define lbs_mesh_connected(priv) (0) | ||
105 | |||
106 | #endif | ||
107 | |||
108 | |||
109 | |||
110 | #endif | ||
diff --git a/drivers/net/wireless/libertas/persistcfg.c b/drivers/net/wireless/libertas/persistcfg.c deleted file mode 100644 index 18fe29faf99b..000000000000 --- a/drivers/net/wireless/libertas/persistcfg.c +++ /dev/null | |||
@@ -1,453 +0,0 @@ | |||
1 | #include <linux/moduleparam.h> | ||
2 | #include <linux/delay.h> | ||
3 | #include <linux/etherdevice.h> | ||
4 | #include <linux/netdevice.h> | ||
5 | #include <linux/if_arp.h> | ||
6 | #include <linux/kthread.h> | ||
7 | #include <linux/kfifo.h> | ||
8 | |||
9 | #include "host.h" | ||
10 | #include "decl.h" | ||
11 | #include "dev.h" | ||
12 | #include "wext.h" | ||
13 | #include "debugfs.h" | ||
14 | #include "scan.h" | ||
15 | #include "assoc.h" | ||
16 | #include "cmd.h" | ||
17 | |||
18 | static int mesh_get_default_parameters(struct device *dev, | ||
19 | struct mrvl_mesh_defaults *defs) | ||
20 | { | ||
21 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
22 | struct cmd_ds_mesh_config cmd; | ||
23 | int ret; | ||
24 | |||
25 | memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config)); | ||
26 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_GET, | ||
27 | CMD_TYPE_MESH_GET_DEFAULTS); | ||
28 | |||
29 | if (ret) | ||
30 | return -EOPNOTSUPP; | ||
31 | |||
32 | memcpy(defs, &cmd.data[0], sizeof(struct mrvl_mesh_defaults)); | ||
33 | |||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | /** | ||
38 | * @brief Get function for sysfs attribute bootflag | ||
39 | */ | ||
40 | static ssize_t bootflag_get(struct device *dev, | ||
41 | struct device_attribute *attr, char *buf) | ||
42 | { | ||
43 | struct mrvl_mesh_defaults defs; | ||
44 | int ret; | ||
45 | |||
46 | ret = mesh_get_default_parameters(dev, &defs); | ||
47 | |||
48 | if (ret) | ||
49 | return ret; | ||
50 | |||
51 | return snprintf(buf, 12, "%d\n", le32_to_cpu(defs.bootflag)); | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * @brief Set function for sysfs attribute bootflag | ||
56 | */ | ||
57 | static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr, | ||
58 | const char *buf, size_t count) | ||
59 | { | ||
60 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
61 | struct cmd_ds_mesh_config cmd; | ||
62 | uint32_t datum; | ||
63 | int ret; | ||
64 | |||
65 | memset(&cmd, 0, sizeof(cmd)); | ||
66 | ret = sscanf(buf, "%d", &datum); | ||
67 | if ((ret != 1) || (datum > 1)) | ||
68 | return -EINVAL; | ||
69 | |||
70 | *((__le32 *)&cmd.data[0]) = cpu_to_le32(!!datum); | ||
71 | cmd.length = cpu_to_le16(sizeof(uint32_t)); | ||
72 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
73 | CMD_TYPE_MESH_SET_BOOTFLAG); | ||
74 | if (ret) | ||
75 | return ret; | ||
76 | |||
77 | return strlen(buf); | ||
78 | } | ||
79 | |||
80 | /** | ||
81 | * @brief Get function for sysfs attribute boottime | ||
82 | */ | ||
83 | static ssize_t boottime_get(struct device *dev, | ||
84 | struct device_attribute *attr, char *buf) | ||
85 | { | ||
86 | struct mrvl_mesh_defaults defs; | ||
87 | int ret; | ||
88 | |||
89 | ret = mesh_get_default_parameters(dev, &defs); | ||
90 | |||
91 | if (ret) | ||
92 | return ret; | ||
93 | |||
94 | return snprintf(buf, 12, "%d\n", defs.boottime); | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * @brief Set function for sysfs attribute boottime | ||
99 | */ | ||
100 | static ssize_t boottime_set(struct device *dev, | ||
101 | struct device_attribute *attr, const char *buf, size_t count) | ||
102 | { | ||
103 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
104 | struct cmd_ds_mesh_config cmd; | ||
105 | uint32_t datum; | ||
106 | int ret; | ||
107 | |||
108 | memset(&cmd, 0, sizeof(cmd)); | ||
109 | ret = sscanf(buf, "%d", &datum); | ||
110 | if ((ret != 1) || (datum > 255)) | ||
111 | return -EINVAL; | ||
112 | |||
113 | /* A too small boot time will result in the device booting into | ||
114 | * standalone (no-host) mode before the host can take control of it, | ||
115 | * so the change will be hard to revert. This may be a desired | ||
116 | * feature (e.g to configure a very fast boot time for devices that | ||
117 | * will not be attached to a host), but dangerous. So I'm enforcing a | ||
118 | * lower limit of 20 seconds: remove and recompile the driver if this | ||
119 | * does not work for you. | ||
120 | */ | ||
121 | datum = (datum < 20) ? 20 : datum; | ||
122 | cmd.data[0] = datum; | ||
123 | cmd.length = cpu_to_le16(sizeof(uint8_t)); | ||
124 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
125 | CMD_TYPE_MESH_SET_BOOTTIME); | ||
126 | if (ret) | ||
127 | return ret; | ||
128 | |||
129 | return strlen(buf); | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * @brief Get function for sysfs attribute channel | ||
134 | */ | ||
135 | static ssize_t channel_get(struct device *dev, | ||
136 | struct device_attribute *attr, char *buf) | ||
137 | { | ||
138 | struct mrvl_mesh_defaults defs; | ||
139 | int ret; | ||
140 | |||
141 | ret = mesh_get_default_parameters(dev, &defs); | ||
142 | |||
143 | if (ret) | ||
144 | return ret; | ||
145 | |||
146 | return snprintf(buf, 12, "%d\n", le16_to_cpu(defs.channel)); | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * @brief Set function for sysfs attribute channel | ||
151 | */ | ||
152 | static ssize_t channel_set(struct device *dev, struct device_attribute *attr, | ||
153 | const char *buf, size_t count) | ||
154 | { | ||
155 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
156 | struct cmd_ds_mesh_config cmd; | ||
157 | uint32_t datum; | ||
158 | int ret; | ||
159 | |||
160 | memset(&cmd, 0, sizeof(cmd)); | ||
161 | ret = sscanf(buf, "%d", &datum); | ||
162 | if (ret != 1 || datum < 1 || datum > 11) | ||
163 | return -EINVAL; | ||
164 | |||
165 | *((__le16 *)&cmd.data[0]) = cpu_to_le16(datum); | ||
166 | cmd.length = cpu_to_le16(sizeof(uint16_t)); | ||
167 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
168 | CMD_TYPE_MESH_SET_DEF_CHANNEL); | ||
169 | if (ret) | ||
170 | return ret; | ||
171 | |||
172 | return strlen(buf); | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * @brief Get function for sysfs attribute mesh_id | ||
177 | */ | ||
178 | static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr, | ||
179 | char *buf) | ||
180 | { | ||
181 | struct mrvl_mesh_defaults defs; | ||
182 | int maxlen; | ||
183 | int ret; | ||
184 | |||
185 | ret = mesh_get_default_parameters(dev, &defs); | ||
186 | |||
187 | if (ret) | ||
188 | return ret; | ||
189 | |||
190 | if (defs.meshie.val.mesh_id_len > IW_ESSID_MAX_SIZE) { | ||
191 | lbs_pr_err("inconsistent mesh ID length"); | ||
192 | defs.meshie.val.mesh_id_len = IW_ESSID_MAX_SIZE; | ||
193 | } | ||
194 | |||
195 | /* SSID not null terminated: reserve room for \0 + \n */ | ||
196 | maxlen = defs.meshie.val.mesh_id_len + 2; | ||
197 | maxlen = (PAGE_SIZE > maxlen) ? maxlen : PAGE_SIZE; | ||
198 | |||
199 | defs.meshie.val.mesh_id[defs.meshie.val.mesh_id_len] = '\0'; | ||
200 | |||
201 | return snprintf(buf, maxlen, "%s\n", defs.meshie.val.mesh_id); | ||
202 | } | ||
203 | |||
204 | /** | ||
205 | * @brief Set function for sysfs attribute mesh_id | ||
206 | */ | ||
207 | static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr, | ||
208 | const char *buf, size_t count) | ||
209 | { | ||
210 | struct cmd_ds_mesh_config cmd; | ||
211 | struct mrvl_mesh_defaults defs; | ||
212 | struct mrvl_meshie *ie; | ||
213 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
214 | int len; | ||
215 | int ret; | ||
216 | |||
217 | if (count < 2 || count > IW_ESSID_MAX_SIZE + 1) | ||
218 | return -EINVAL; | ||
219 | |||
220 | memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config)); | ||
221 | ie = (struct mrvl_meshie *) &cmd.data[0]; | ||
222 | |||
223 | /* fetch all other Information Element parameters */ | ||
224 | ret = mesh_get_default_parameters(dev, &defs); | ||
225 | |||
226 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); | ||
227 | |||
228 | /* transfer IE elements */ | ||
229 | memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); | ||
230 | |||
231 | len = count - 1; | ||
232 | memcpy(ie->val.mesh_id, buf, len); | ||
233 | /* SSID len */ | ||
234 | ie->val.mesh_id_len = len; | ||
235 | /* IE len */ | ||
236 | ie->len = sizeof(struct mrvl_meshie_val) - IW_ESSID_MAX_SIZE + len; | ||
237 | |||
238 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
239 | CMD_TYPE_MESH_SET_MESH_IE); | ||
240 | if (ret) | ||
241 | return ret; | ||
242 | |||
243 | return strlen(buf); | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * @brief Get function for sysfs attribute protocol_id | ||
248 | */ | ||
249 | static ssize_t protocol_id_get(struct device *dev, | ||
250 | struct device_attribute *attr, char *buf) | ||
251 | { | ||
252 | struct mrvl_mesh_defaults defs; | ||
253 | int ret; | ||
254 | |||
255 | ret = mesh_get_default_parameters(dev, &defs); | ||
256 | |||
257 | if (ret) | ||
258 | return ret; | ||
259 | |||
260 | return snprintf(buf, 5, "%d\n", defs.meshie.val.active_protocol_id); | ||
261 | } | ||
262 | |||
263 | /** | ||
264 | * @brief Set function for sysfs attribute protocol_id | ||
265 | */ | ||
266 | static ssize_t protocol_id_set(struct device *dev, | ||
267 | struct device_attribute *attr, const char *buf, size_t count) | ||
268 | { | ||
269 | struct cmd_ds_mesh_config cmd; | ||
270 | struct mrvl_mesh_defaults defs; | ||
271 | struct mrvl_meshie *ie; | ||
272 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
273 | uint32_t datum; | ||
274 | int ret; | ||
275 | |||
276 | memset(&cmd, 0, sizeof(cmd)); | ||
277 | ret = sscanf(buf, "%d", &datum); | ||
278 | if ((ret != 1) || (datum > 255)) | ||
279 | return -EINVAL; | ||
280 | |||
281 | /* fetch all other Information Element parameters */ | ||
282 | ret = mesh_get_default_parameters(dev, &defs); | ||
283 | |||
284 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); | ||
285 | |||
286 | /* transfer IE elements */ | ||
287 | ie = (struct mrvl_meshie *) &cmd.data[0]; | ||
288 | memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); | ||
289 | /* update protocol id */ | ||
290 | ie->val.active_protocol_id = datum; | ||
291 | |||
292 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
293 | CMD_TYPE_MESH_SET_MESH_IE); | ||
294 | if (ret) | ||
295 | return ret; | ||
296 | |||
297 | return strlen(buf); | ||
298 | } | ||
299 | |||
300 | /** | ||
301 | * @brief Get function for sysfs attribute metric_id | ||
302 | */ | ||
303 | static ssize_t metric_id_get(struct device *dev, | ||
304 | struct device_attribute *attr, char *buf) | ||
305 | { | ||
306 | struct mrvl_mesh_defaults defs; | ||
307 | int ret; | ||
308 | |||
309 | ret = mesh_get_default_parameters(dev, &defs); | ||
310 | |||
311 | if (ret) | ||
312 | return ret; | ||
313 | |||
314 | return snprintf(buf, 5, "%d\n", defs.meshie.val.active_metric_id); | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * @brief Set function for sysfs attribute metric_id | ||
319 | */ | ||
320 | static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr, | ||
321 | const char *buf, size_t count) | ||
322 | { | ||
323 | struct cmd_ds_mesh_config cmd; | ||
324 | struct mrvl_mesh_defaults defs; | ||
325 | struct mrvl_meshie *ie; | ||
326 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
327 | uint32_t datum; | ||
328 | int ret; | ||
329 | |||
330 | memset(&cmd, 0, sizeof(cmd)); | ||
331 | ret = sscanf(buf, "%d", &datum); | ||
332 | if ((ret != 1) || (datum > 255)) | ||
333 | return -EINVAL; | ||
334 | |||
335 | /* fetch all other Information Element parameters */ | ||
336 | ret = mesh_get_default_parameters(dev, &defs); | ||
337 | |||
338 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); | ||
339 | |||
340 | /* transfer IE elements */ | ||
341 | ie = (struct mrvl_meshie *) &cmd.data[0]; | ||
342 | memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); | ||
343 | /* update metric id */ | ||
344 | ie->val.active_metric_id = datum; | ||
345 | |||
346 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
347 | CMD_TYPE_MESH_SET_MESH_IE); | ||
348 | if (ret) | ||
349 | return ret; | ||
350 | |||
351 | return strlen(buf); | ||
352 | } | ||
353 | |||
354 | /** | ||
355 | * @brief Get function for sysfs attribute capability | ||
356 | */ | ||
357 | static ssize_t capability_get(struct device *dev, | ||
358 | struct device_attribute *attr, char *buf) | ||
359 | { | ||
360 | struct mrvl_mesh_defaults defs; | ||
361 | int ret; | ||
362 | |||
363 | ret = mesh_get_default_parameters(dev, &defs); | ||
364 | |||
365 | if (ret) | ||
366 | return ret; | ||
367 | |||
368 | return snprintf(buf, 5, "%d\n", defs.meshie.val.mesh_capability); | ||
369 | } | ||
370 | |||
371 | /** | ||
372 | * @brief Set function for sysfs attribute capability | ||
373 | */ | ||
374 | static ssize_t capability_set(struct device *dev, struct device_attribute *attr, | ||
375 | const char *buf, size_t count) | ||
376 | { | ||
377 | struct cmd_ds_mesh_config cmd; | ||
378 | struct mrvl_mesh_defaults defs; | ||
379 | struct mrvl_meshie *ie; | ||
380 | struct lbs_private *priv = to_net_dev(dev)->ml_priv; | ||
381 | uint32_t datum; | ||
382 | int ret; | ||
383 | |||
384 | memset(&cmd, 0, sizeof(cmd)); | ||
385 | ret = sscanf(buf, "%d", &datum); | ||
386 | if ((ret != 1) || (datum > 255)) | ||
387 | return -EINVAL; | ||
388 | |||
389 | /* fetch all other Information Element parameters */ | ||
390 | ret = mesh_get_default_parameters(dev, &defs); | ||
391 | |||
392 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); | ||
393 | |||
394 | /* transfer IE elements */ | ||
395 | ie = (struct mrvl_meshie *) &cmd.data[0]; | ||
396 | memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); | ||
397 | /* update value */ | ||
398 | ie->val.mesh_capability = datum; | ||
399 | |||
400 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | ||
401 | CMD_TYPE_MESH_SET_MESH_IE); | ||
402 | if (ret) | ||
403 | return ret; | ||
404 | |||
405 | return strlen(buf); | ||
406 | } | ||
407 | |||
408 | |||
409 | static DEVICE_ATTR(bootflag, 0644, bootflag_get, bootflag_set); | ||
410 | static DEVICE_ATTR(boottime, 0644, boottime_get, boottime_set); | ||
411 | static DEVICE_ATTR(channel, 0644, channel_get, channel_set); | ||
412 | static DEVICE_ATTR(mesh_id, 0644, mesh_id_get, mesh_id_set); | ||
413 | static DEVICE_ATTR(protocol_id, 0644, protocol_id_get, protocol_id_set); | ||
414 | static DEVICE_ATTR(metric_id, 0644, metric_id_get, metric_id_set); | ||
415 | static DEVICE_ATTR(capability, 0644, capability_get, capability_set); | ||
416 | |||
417 | static struct attribute *boot_opts_attrs[] = { | ||
418 | &dev_attr_bootflag.attr, | ||
419 | &dev_attr_boottime.attr, | ||
420 | &dev_attr_channel.attr, | ||
421 | NULL | ||
422 | }; | ||
423 | |||
424 | static struct attribute_group boot_opts_group = { | ||
425 | .name = "boot_options", | ||
426 | .attrs = boot_opts_attrs, | ||
427 | }; | ||
428 | |||
429 | static struct attribute *mesh_ie_attrs[] = { | ||
430 | &dev_attr_mesh_id.attr, | ||
431 | &dev_attr_protocol_id.attr, | ||
432 | &dev_attr_metric_id.attr, | ||
433 | &dev_attr_capability.attr, | ||
434 | NULL | ||
435 | }; | ||
436 | |||
437 | static struct attribute_group mesh_ie_group = { | ||
438 | .name = "mesh_ie", | ||
439 | .attrs = mesh_ie_attrs, | ||
440 | }; | ||
441 | |||
442 | void lbs_persist_config_init(struct net_device *dev) | ||
443 | { | ||
444 | int ret; | ||
445 | ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group); | ||
446 | ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group); | ||
447 | } | ||
448 | |||
449 | void lbs_persist_config_remove(struct net_device *dev) | ||
450 | { | ||
451 | sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group); | ||
452 | sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group); | ||
453 | } | ||
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 65f02cc6752f..784dae714705 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c | |||
@@ -2,9 +2,10 @@ | |||
2 | * This file contains the handling of RX in wlan driver. | 2 | * This file contains the handling of RX in wlan driver. |
3 | */ | 3 | */ |
4 | #include <linux/etherdevice.h> | 4 | #include <linux/etherdevice.h> |
5 | #include <linux/slab.h> | ||
5 | #include <linux/types.h> | 6 | #include <linux/types.h> |
6 | 7 | ||
7 | #include "hostcmd.h" | 8 | #include "host.h" |
8 | #include "radiotap.h" | 9 | #include "radiotap.h" |
9 | #include "decl.h" | 10 | #include "decl.h" |
10 | #include "dev.h" | 11 | #include "dev.h" |
@@ -160,15 +161,8 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) | |||
160 | p_rx_pd = (struct rxpd *) skb->data; | 161 | p_rx_pd = (struct rxpd *) skb->data; |
161 | p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd + | 162 | p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd + |
162 | le32_to_cpu(p_rx_pd->pkt_ptr)); | 163 | le32_to_cpu(p_rx_pd->pkt_ptr)); |
163 | if (priv->mesh_dev) { | 164 | |
164 | if (priv->mesh_fw_ver == MESH_FW_OLD) { | 165 | dev = lbs_mesh_set_dev(priv, dev, p_rx_pd); |
165 | if (p_rx_pd->rx_control & RxPD_MESH_FRAME) | ||
166 | dev = priv->mesh_dev; | ||
167 | } else if (priv->mesh_fw_ver == MESH_FW_NEW) { | ||
168 | if (p_rx_pd->u.bss.bss_num == MESH_IFACE_ID) | ||
169 | dev = priv->mesh_dev; | ||
170 | } | ||
171 | } | ||
172 | 166 | ||
173 | lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, | 167 | lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, |
174 | min_t(unsigned int, skb->len, 100)); | 168 | min_t(unsigned int, skb->len, 100)); |
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 6c95af3023cc..24cd54b3a806 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * IOCTL handlers as well as command preperation and response routines | 4 | * IOCTL handlers as well as command preperation and response routines |
5 | * for sending scan commands to the firmware. | 5 | * for sending scan commands to the firmware. |
6 | */ | 6 | */ |
7 | #include <linux/slab.h> | ||
7 | #include <linux/types.h> | 8 | #include <linux/types.h> |
8 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
9 | #include <linux/etherdevice.h> | 10 | #include <linux/etherdevice.h> |
@@ -12,18 +13,19 @@ | |||
12 | #include <net/lib80211.h> | 13 | #include <net/lib80211.h> |
13 | 14 | ||
14 | #include "host.h" | 15 | #include "host.h" |
15 | #include "decl.h" | ||
16 | #include "dev.h" | 16 | #include "dev.h" |
17 | #include "scan.h" | 17 | #include "scan.h" |
18 | #include "assoc.h" | ||
19 | #include "wext.h" | ||
18 | #include "cmd.h" | 20 | #include "cmd.h" |
19 | 21 | ||
20 | //! Approximate amount of data needed to pass a scan result back to iwlist | 22 | //! Approximate amount of data needed to pass a scan result back to iwlist |
21 | #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \ | 23 | #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \ |
22 | + IW_ESSID_MAX_SIZE \ | 24 | + IEEE80211_MAX_SSID_LEN \ |
23 | + IW_EV_UINT_LEN \ | 25 | + IW_EV_UINT_LEN \ |
24 | + IW_EV_FREQ_LEN \ | 26 | + IW_EV_FREQ_LEN \ |
25 | + IW_EV_QUAL_LEN \ | 27 | + IW_EV_QUAL_LEN \ |
26 | + IW_ESSID_MAX_SIZE \ | 28 | + IEEE80211_MAX_SSID_LEN \ |
27 | + IW_EV_PARAM_LEN \ | 29 | + IW_EV_PARAM_LEN \ |
28 | + 40) /* 40 for WPAIE */ | 30 | + 40) /* 40 for WPAIE */ |
29 | 31 | ||
@@ -121,6 +123,189 @@ static inline int is_same_network(struct bss_descriptor *src, | |||
121 | 123 | ||
122 | 124 | ||
123 | 125 | ||
126 | /*********************************************************************/ | ||
127 | /* */ | ||
128 | /* Region channel support */ | ||
129 | /* */ | ||
130 | /*********************************************************************/ | ||
131 | |||
132 | #define LBS_TX_PWR_DEFAULT 20 /*100mW */ | ||
133 | #define LBS_TX_PWR_US_DEFAULT 20 /*100mW */ | ||
134 | #define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */ | ||
135 | #define LBS_TX_PWR_FR_DEFAULT 20 /*100mW */ | ||
136 | #define LBS_TX_PWR_EMEA_DEFAULT 20 /*100mW */ | ||
137 | |||
138 | /* Format { channel, frequency (MHz), maxtxpower } */ | ||
139 | /* band: 'B/G', region: USA FCC/Canada IC */ | ||
140 | static struct chan_freq_power channel_freq_power_US_BG[] = { | ||
141 | {1, 2412, LBS_TX_PWR_US_DEFAULT}, | ||
142 | {2, 2417, LBS_TX_PWR_US_DEFAULT}, | ||
143 | {3, 2422, LBS_TX_PWR_US_DEFAULT}, | ||
144 | {4, 2427, LBS_TX_PWR_US_DEFAULT}, | ||
145 | {5, 2432, LBS_TX_PWR_US_DEFAULT}, | ||
146 | {6, 2437, LBS_TX_PWR_US_DEFAULT}, | ||
147 | {7, 2442, LBS_TX_PWR_US_DEFAULT}, | ||
148 | {8, 2447, LBS_TX_PWR_US_DEFAULT}, | ||
149 | {9, 2452, LBS_TX_PWR_US_DEFAULT}, | ||
150 | {10, 2457, LBS_TX_PWR_US_DEFAULT}, | ||
151 | {11, 2462, LBS_TX_PWR_US_DEFAULT} | ||
152 | }; | ||
153 | |||
154 | /* band: 'B/G', region: Europe ETSI */ | ||
155 | static struct chan_freq_power channel_freq_power_EU_BG[] = { | ||
156 | {1, 2412, LBS_TX_PWR_EMEA_DEFAULT}, | ||
157 | {2, 2417, LBS_TX_PWR_EMEA_DEFAULT}, | ||
158 | {3, 2422, LBS_TX_PWR_EMEA_DEFAULT}, | ||
159 | {4, 2427, LBS_TX_PWR_EMEA_DEFAULT}, | ||
160 | {5, 2432, LBS_TX_PWR_EMEA_DEFAULT}, | ||
161 | {6, 2437, LBS_TX_PWR_EMEA_DEFAULT}, | ||
162 | {7, 2442, LBS_TX_PWR_EMEA_DEFAULT}, | ||
163 | {8, 2447, LBS_TX_PWR_EMEA_DEFAULT}, | ||
164 | {9, 2452, LBS_TX_PWR_EMEA_DEFAULT}, | ||
165 | {10, 2457, LBS_TX_PWR_EMEA_DEFAULT}, | ||
166 | {11, 2462, LBS_TX_PWR_EMEA_DEFAULT}, | ||
167 | {12, 2467, LBS_TX_PWR_EMEA_DEFAULT}, | ||
168 | {13, 2472, LBS_TX_PWR_EMEA_DEFAULT} | ||
169 | }; | ||
170 | |||
171 | /* band: 'B/G', region: Spain */ | ||
172 | static struct chan_freq_power channel_freq_power_SPN_BG[] = { | ||
173 | {10, 2457, LBS_TX_PWR_DEFAULT}, | ||
174 | {11, 2462, LBS_TX_PWR_DEFAULT} | ||
175 | }; | ||
176 | |||
177 | /* band: 'B/G', region: France */ | ||
178 | static struct chan_freq_power channel_freq_power_FR_BG[] = { | ||
179 | {10, 2457, LBS_TX_PWR_FR_DEFAULT}, | ||
180 | {11, 2462, LBS_TX_PWR_FR_DEFAULT}, | ||
181 | {12, 2467, LBS_TX_PWR_FR_DEFAULT}, | ||
182 | {13, 2472, LBS_TX_PWR_FR_DEFAULT} | ||
183 | }; | ||
184 | |||
185 | /* band: 'B/G', region: Japan */ | ||
186 | static struct chan_freq_power channel_freq_power_JPN_BG[] = { | ||
187 | {1, 2412, LBS_TX_PWR_JP_DEFAULT}, | ||
188 | {2, 2417, LBS_TX_PWR_JP_DEFAULT}, | ||
189 | {3, 2422, LBS_TX_PWR_JP_DEFAULT}, | ||
190 | {4, 2427, LBS_TX_PWR_JP_DEFAULT}, | ||
191 | {5, 2432, LBS_TX_PWR_JP_DEFAULT}, | ||
192 | {6, 2437, LBS_TX_PWR_JP_DEFAULT}, | ||
193 | {7, 2442, LBS_TX_PWR_JP_DEFAULT}, | ||
194 | {8, 2447, LBS_TX_PWR_JP_DEFAULT}, | ||
195 | {9, 2452, LBS_TX_PWR_JP_DEFAULT}, | ||
196 | {10, 2457, LBS_TX_PWR_JP_DEFAULT}, | ||
197 | {11, 2462, LBS_TX_PWR_JP_DEFAULT}, | ||
198 | {12, 2467, LBS_TX_PWR_JP_DEFAULT}, | ||
199 | {13, 2472, LBS_TX_PWR_JP_DEFAULT}, | ||
200 | {14, 2484, LBS_TX_PWR_JP_DEFAULT} | ||
201 | }; | ||
202 | |||
203 | /** | ||
204 | * the structure for channel, frequency and power | ||
205 | */ | ||
206 | struct region_cfp_table { | ||
207 | u8 region; | ||
208 | struct chan_freq_power *cfp_BG; | ||
209 | int cfp_no_BG; | ||
210 | }; | ||
211 | |||
212 | /** | ||
213 | * the structure for the mapping between region and CFP | ||
214 | */ | ||
215 | static struct region_cfp_table region_cfp_table[] = { | ||
216 | {0x10, /*US FCC */ | ||
217 | channel_freq_power_US_BG, | ||
218 | ARRAY_SIZE(channel_freq_power_US_BG), | ||
219 | } | ||
220 | , | ||
221 | {0x20, /*CANADA IC */ | ||
222 | channel_freq_power_US_BG, | ||
223 | ARRAY_SIZE(channel_freq_power_US_BG), | ||
224 | } | ||
225 | , | ||
226 | {0x30, /*EU*/ channel_freq_power_EU_BG, | ||
227 | ARRAY_SIZE(channel_freq_power_EU_BG), | ||
228 | } | ||
229 | , | ||
230 | {0x31, /*SPAIN*/ channel_freq_power_SPN_BG, | ||
231 | ARRAY_SIZE(channel_freq_power_SPN_BG), | ||
232 | } | ||
233 | , | ||
234 | {0x32, /*FRANCE*/ channel_freq_power_FR_BG, | ||
235 | ARRAY_SIZE(channel_freq_power_FR_BG), | ||
236 | } | ||
237 | , | ||
238 | {0x40, /*JAPAN*/ channel_freq_power_JPN_BG, | ||
239 | ARRAY_SIZE(channel_freq_power_JPN_BG), | ||
240 | } | ||
241 | , | ||
242 | /*Add new region here */ | ||
243 | }; | ||
244 | |||
245 | /** | ||
246 | * @brief This function finds the CFP in | ||
247 | * region_cfp_table based on region and band parameter. | ||
248 | * | ||
249 | * @param region The region code | ||
250 | * @param band The band | ||
251 | * @param cfp_no A pointer to CFP number | ||
252 | * @return A pointer to CFP | ||
253 | */ | ||
254 | static struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no) | ||
255 | { | ||
256 | int i, end; | ||
257 | |||
258 | lbs_deb_enter(LBS_DEB_MAIN); | ||
259 | |||
260 | end = ARRAY_SIZE(region_cfp_table); | ||
261 | |||
262 | for (i = 0; i < end ; i++) { | ||
263 | lbs_deb_main("region_cfp_table[i].region=%d\n", | ||
264 | region_cfp_table[i].region); | ||
265 | if (region_cfp_table[i].region == region) { | ||
266 | *cfp_no = region_cfp_table[i].cfp_no_BG; | ||
267 | lbs_deb_leave(LBS_DEB_MAIN); | ||
268 | return region_cfp_table[i].cfp_BG; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL"); | ||
273 | return NULL; | ||
274 | } | ||
275 | |||
276 | int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band) | ||
277 | { | ||
278 | int ret = 0; | ||
279 | int i = 0; | ||
280 | |||
281 | struct chan_freq_power *cfp; | ||
282 | int cfp_no; | ||
283 | |||
284 | lbs_deb_enter(LBS_DEB_MAIN); | ||
285 | |||
286 | memset(priv->region_channel, 0, sizeof(priv->region_channel)); | ||
287 | |||
288 | cfp = lbs_get_region_cfp_table(region, &cfp_no); | ||
289 | if (cfp != NULL) { | ||
290 | priv->region_channel[i].nrcfp = cfp_no; | ||
291 | priv->region_channel[i].CFP = cfp; | ||
292 | } else { | ||
293 | lbs_deb_main("wrong region code %#x in band B/G\n", | ||
294 | region); | ||
295 | ret = -1; | ||
296 | goto out; | ||
297 | } | ||
298 | priv->region_channel[i].valid = 1; | ||
299 | priv->region_channel[i].region = region; | ||
300 | priv->region_channel[i].band = band; | ||
301 | i++; | ||
302 | out: | ||
303 | lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); | ||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | |||
308 | |||
124 | 309 | ||
125 | /*********************************************************************/ | 310 | /*********************************************************************/ |
126 | /* */ | 311 | /* */ |
@@ -161,31 +346,15 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, | |||
161 | scantype = CMD_SCAN_TYPE_ACTIVE; | 346 | scantype = CMD_SCAN_TYPE_ACTIVE; |
162 | 347 | ||
163 | for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) { | 348 | for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) { |
164 | if (priv->enable11d && (priv->connect_status != LBS_CONNECTED) | 349 | if (!priv->region_channel[rgnidx].valid) |
165 | && (priv->mesh_connect_status != LBS_CONNECTED)) { | 350 | continue; |
166 | /* Scan all the supported chan for the first scan */ | 351 | scanregion = &priv->region_channel[rgnidx]; |
167 | if (!priv->universal_channel[rgnidx].valid) | ||
168 | continue; | ||
169 | scanregion = &priv->universal_channel[rgnidx]; | ||
170 | |||
171 | /* clear the parsed_region_chan for the first scan */ | ||
172 | memset(&priv->parsed_region_chan, 0x00, | ||
173 | sizeof(priv->parsed_region_chan)); | ||
174 | } else { | ||
175 | if (!priv->region_channel[rgnidx].valid) | ||
176 | continue; | ||
177 | scanregion = &priv->region_channel[rgnidx]; | ||
178 | } | ||
179 | 352 | ||
180 | for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) { | 353 | for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) { |
181 | struct chanscanparamset *chan = &scanchanlist[chanidx]; | 354 | struct chanscanparamset *chan = &scanchanlist[chanidx]; |
182 | 355 | ||
183 | cfp = scanregion->CFP + nextchan; | 356 | cfp = scanregion->CFP + nextchan; |
184 | 357 | ||
185 | if (priv->enable11d) | ||
186 | scantype = lbs_get_scan_type_11d(cfp->channel, | ||
187 | &priv->parsed_region_chan); | ||
188 | |||
189 | if (scanregion->band == BAND_B || scanregion->band == BAND_G) | 358 | if (scanregion->band == BAND_B || scanregion->band == BAND_G) |
190 | chan->radiotype = CMD_SCAN_RADIO_TYPE_BG; | 359 | chan->radiotype = CMD_SCAN_RADIO_TYPE_BG; |
191 | 360 | ||
@@ -399,11 +568,8 @@ int lbs_scan_networks(struct lbs_private *priv, int full_scan) | |||
399 | chan_count = lbs_scan_create_channel_list(priv, chan_list); | 568 | chan_count = lbs_scan_create_channel_list(priv, chan_list); |
400 | 569 | ||
401 | netif_stop_queue(priv->dev); | 570 | netif_stop_queue(priv->dev); |
402 | netif_carrier_off(priv->dev); | 571 | if (priv->mesh_dev) |
403 | if (priv->mesh_dev) { | ||
404 | netif_stop_queue(priv->mesh_dev); | 572 | netif_stop_queue(priv->mesh_dev); |
405 | netif_carrier_off(priv->mesh_dev); | ||
406 | } | ||
407 | 573 | ||
408 | /* Prepare to continue an interrupted scan */ | 574 | /* Prepare to continue an interrupted scan */ |
409 | lbs_deb_scan("chan_count %d, scan_channel %d\n", | 575 | lbs_deb_scan("chan_count %d, scan_channel %d\n", |
@@ -467,16 +633,13 @@ out2: | |||
467 | priv->scan_channel = 0; | 633 | priv->scan_channel = 0; |
468 | 634 | ||
469 | out: | 635 | out: |
470 | if (priv->connect_status == LBS_CONNECTED) { | 636 | if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len) |
471 | netif_carrier_on(priv->dev); | 637 | netif_wake_queue(priv->dev); |
472 | if (!priv->tx_pending_len) | 638 | |
473 | netif_wake_queue(priv->dev); | 639 | if (priv->mesh_dev && lbs_mesh_connected(priv) && |
474 | } | 640 | !priv->tx_pending_len) |
475 | if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) { | 641 | netif_wake_queue(priv->mesh_dev); |
476 | netif_carrier_on(priv->mesh_dev); | 642 | |
477 | if (!priv->tx_pending_len) | ||
478 | netif_wake_queue(priv->mesh_dev); | ||
479 | } | ||
480 | kfree(chan_list); | 643 | kfree(chan_list); |
481 | 644 | ||
482 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | 645 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); |
@@ -519,7 +682,6 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
519 | struct ieee_ie_cf_param_set *cf; | 682 | struct ieee_ie_cf_param_set *cf; |
520 | struct ieee_ie_ibss_param_set *ibss; | 683 | struct ieee_ie_ibss_param_set *ibss; |
521 | DECLARE_SSID_BUF(ssid); | 684 | DECLARE_SSID_BUF(ssid); |
522 | struct ieee_ie_country_info_set *pcountryinfo; | ||
523 | uint8_t *pos, *end, *p; | 685 | uint8_t *pos, *end, *p; |
524 | uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; | 686 | uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; |
525 | uint16_t beaconsize = 0; | 687 | uint16_t beaconsize = 0; |
@@ -642,26 +804,6 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
642 | lbs_deb_scan("got IBSS IE\n"); | 804 | lbs_deb_scan("got IBSS IE\n"); |
643 | break; | 805 | break; |
644 | 806 | ||
645 | case WLAN_EID_COUNTRY: | ||
646 | pcountryinfo = (struct ieee_ie_country_info_set *) pos; | ||
647 | lbs_deb_scan("got COUNTRY IE\n"); | ||
648 | if (pcountryinfo->header.len < sizeof(pcountryinfo->countrycode) | ||
649 | || pcountryinfo->header.len > 254) { | ||
650 | lbs_deb_scan("%s: 11D- Err CountryInfo len %d, min %zd, max 254\n", | ||
651 | __func__, | ||
652 | pcountryinfo->header.len, | ||
653 | sizeof(pcountryinfo->countrycode)); | ||
654 | ret = -1; | ||
655 | goto done; | ||
656 | } | ||
657 | |||
658 | memcpy(&bss->countryinfo, pcountryinfo, | ||
659 | pcountryinfo->header.len + 2); | ||
660 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo", | ||
661 | (uint8_t *) pcountryinfo, | ||
662 | (int) (pcountryinfo->header.len + 2)); | ||
663 | break; | ||
664 | |||
665 | case WLAN_EID_EXT_SUPP_RATES: | 807 | case WLAN_EID_EXT_SUPP_RATES: |
666 | /* only process extended supported rate if data rate is | 808 | /* only process extended supported rate if data rate is |
667 | * already found. Data rate IE should come before | 809 | * already found. Data rate IE should come before |
@@ -812,7 +954,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
812 | /* SSID */ | 954 | /* SSID */ |
813 | iwe.cmd = SIOCGIWESSID; | 955 | iwe.cmd = SIOCGIWESSID; |
814 | iwe.u.data.flags = 1; | 956 | iwe.u.data.flags = 1; |
815 | iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE); | 957 | iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IEEE80211_MAX_SSID_LEN); |
816 | start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid); | 958 | start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid); |
817 | 959 | ||
818 | /* Mode */ | 960 | /* Mode */ |
@@ -1022,9 +1164,12 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1022 | return -EAGAIN; | 1164 | return -EAGAIN; |
1023 | 1165 | ||
1024 | /* Update RSSI if current BSS is a locally created ad-hoc BSS */ | 1166 | /* Update RSSI if current BSS is a locally created ad-hoc BSS */ |
1025 | if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) | 1167 | if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) { |
1026 | lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, | 1168 | err = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, |
1027 | CMD_OPTION_WAITFORRSP, 0, NULL); | 1169 | CMD_OPTION_WAITFORRSP, 0, NULL); |
1170 | if (err) | ||
1171 | goto out; | ||
1172 | } | ||
1028 | 1173 | ||
1029 | mutex_lock(&priv->lock); | 1174 | mutex_lock(&priv->lock); |
1030 | list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { | 1175 | list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { |
@@ -1058,7 +1203,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1058 | 1203 | ||
1059 | dwrq->length = (ev - extra); | 1204 | dwrq->length = (ev - extra); |
1060 | dwrq->flags = 0; | 1205 | dwrq->flags = 0; |
1061 | 1206 | out: | |
1062 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err); | 1207 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err); |
1063 | return err; | 1208 | return err; |
1064 | } | 1209 | } |
@@ -1141,11 +1286,11 @@ static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, | |||
1141 | /* The size of the TLV buffer is equal to the entire command response | 1286 | /* The size of the TLV buffer is equal to the entire command response |
1142 | * size (scanrespsize) minus the fixed fields (sizeof()'s), the | 1287 | * size (scanrespsize) minus the fixed fields (sizeof()'s), the |
1143 | * BSS Descriptions (bssdescriptsize as bytesLef) and the command | 1288 | * BSS Descriptions (bssdescriptsize as bytesLef) and the command |
1144 | * response header (S_DS_GEN) | 1289 | * response header (sizeof(struct cmd_header)) |
1145 | */ | 1290 | */ |
1146 | tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize) | 1291 | tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize) |
1147 | + sizeof(scanresp->nr_sets) | 1292 | + sizeof(scanresp->nr_sets) |
1148 | + S_DS_GEN); | 1293 | + sizeof(struct cmd_header)); |
1149 | 1294 | ||
1150 | /* | 1295 | /* |
1151 | * Process each scan response returned (scanresp->nr_sets). Save | 1296 | * Process each scan response returned (scanresp->nr_sets). Save |
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h index fab7d5d097fc..8fb1706d7526 100644 --- a/drivers/net/wireless/libertas/scan.h +++ b/drivers/net/wireless/libertas/scan.h | |||
@@ -9,8 +9,36 @@ | |||
9 | 9 | ||
10 | #include <net/iw_handler.h> | 10 | #include <net/iw_handler.h> |
11 | 11 | ||
12 | struct lbs_private; | ||
13 | |||
12 | #define MAX_NETWORK_COUNT 128 | 14 | #define MAX_NETWORK_COUNT 128 |
13 | 15 | ||
16 | /** Chan-freq-TxPower mapping table*/ | ||
17 | struct chan_freq_power { | ||
18 | /** channel Number */ | ||
19 | u16 channel; | ||
20 | /** frequency of this channel */ | ||
21 | u32 freq; | ||
22 | /** Max allowed Tx power level */ | ||
23 | u16 maxtxpower; | ||
24 | /** TRUE:channel unsupported; FLASE:supported*/ | ||
25 | u8 unsupported; | ||
26 | }; | ||
27 | |||
28 | /** region-band mapping table*/ | ||
29 | struct region_channel { | ||
30 | /** TRUE if this entry is valid */ | ||
31 | u8 valid; | ||
32 | /** region code for US, Japan ... */ | ||
33 | u8 region; | ||
34 | /** band B/G/A, used for BAND_CONFIG cmd */ | ||
35 | u8 band; | ||
36 | /** Actual No. of elements in the array below */ | ||
37 | u8 nrcfp; | ||
38 | /** chan-freq-txpower mapping table*/ | ||
39 | struct chan_freq_power *CFP; | ||
40 | }; | ||
41 | |||
14 | /** | 42 | /** |
15 | * @brief Maximum number of channels that can be sent in a setuserscan ioctl | 43 | * @brief Maximum number of channels that can be sent in a setuserscan ioctl |
16 | */ | 44 | */ |
@@ -18,6 +46,8 @@ | |||
18 | 46 | ||
19 | int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len); | 47 | int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len); |
20 | 48 | ||
49 | int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band); | ||
50 | |||
21 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, | 51 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, |
22 | u8 ssid_len); | 52 | u8 ssid_len); |
23 | 53 | ||
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index 8c3766a6e8e7..52d244ea3d97 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c | |||
@@ -5,7 +5,7 @@ | |||
5 | #include <linux/etherdevice.h> | 5 | #include <linux/etherdevice.h> |
6 | #include <linux/sched.h> | 6 | #include <linux/sched.h> |
7 | 7 | ||
8 | #include "hostcmd.h" | 8 | #include "host.h" |
9 | #include "radiotap.h" | 9 | #include "radiotap.h" |
10 | #include "decl.h" | 10 | #include "decl.h" |
11 | #include "defs.h" | 11 | #include "defs.h" |
@@ -131,12 +131,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
131 | txpd->tx_packet_length = cpu_to_le16(pkt_len); | 131 | txpd->tx_packet_length = cpu_to_le16(pkt_len); |
132 | txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd)); | 132 | txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd)); |
133 | 133 | ||
134 | if (dev == priv->mesh_dev) { | 134 | lbs_mesh_set_txpd(priv, dev, txpd); |
135 | if (priv->mesh_fw_ver == MESH_FW_OLD) | ||
136 | txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); | ||
137 | else if (priv->mesh_fw_ver == MESH_FW_NEW) | ||
138 | txpd->u.bss.bss_num = MESH_IFACE_ID; | ||
139 | } | ||
140 | 135 | ||
141 | lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd)); | 136 | lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd)); |
142 | 137 | ||
@@ -203,7 +198,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) | |||
203 | if (priv->connect_status == LBS_CONNECTED) | 198 | if (priv->connect_status == LBS_CONNECTED) |
204 | netif_wake_queue(priv->dev); | 199 | netif_wake_queue(priv->dev); |
205 | 200 | ||
206 | if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) | 201 | if (priv->mesh_dev && lbs_mesh_connected(priv)) |
207 | netif_wake_queue(priv->mesh_dev); | 202 | netif_wake_queue(priv->mesh_dev); |
208 | } | 203 | } |
209 | EXPORT_SYMBOL_GPL(lbs_send_tx_feedback); | 204 | EXPORT_SYMBOL_GPL(lbs_send_tx_feedback); |
diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h index 99905df65b25..3e72c86ceca8 100644 --- a/drivers/net/wireless/libertas/types.h +++ b/drivers/net/wireless/libertas/types.h | |||
@@ -5,8 +5,8 @@ | |||
5 | #define _LBS_TYPES_H_ | 5 | #define _LBS_TYPES_H_ |
6 | 6 | ||
7 | #include <linux/if_ether.h> | 7 | #include <linux/if_ether.h> |
8 | #include <linux/ieee80211.h> | ||
8 | #include <asm/byteorder.h> | 9 | #include <asm/byteorder.h> |
9 | #include <linux/wireless.h> | ||
10 | 10 | ||
11 | struct ieee_ie_header { | 11 | struct ieee_ie_header { |
12 | u8 id; | 12 | u8 id; |
@@ -247,7 +247,7 @@ struct mrvl_meshie_val { | |||
247 | uint8_t active_metric_id; | 247 | uint8_t active_metric_id; |
248 | uint8_t mesh_capability; | 248 | uint8_t mesh_capability; |
249 | uint8_t mesh_id_len; | 249 | uint8_t mesh_id_len; |
250 | uint8_t mesh_id[IW_ESSID_MAX_SIZE]; | 250 | uint8_t mesh_id[IEEE80211_MAX_SSID_LEN]; |
251 | } __attribute__ ((packed)); | 251 | } __attribute__ ((packed)); |
252 | 252 | ||
253 | struct mrvl_meshie { | 253 | struct mrvl_meshie { |
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index be837a0d2517..9b555884b08a 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * This file contains ioctl functions | 2 | * This file contains ioctl functions |
3 | */ | 3 | */ |
4 | #include <linux/ctype.h> | 4 | #include <linux/ctype.h> |
5 | #include <linux/slab.h> | ||
5 | #include <linux/delay.h> | 6 | #include <linux/delay.h> |
6 | #include <linux/if.h> | 7 | #include <linux/if.h> |
7 | #include <linux/if_arp.h> | 8 | #include <linux/if_arp.h> |
@@ -45,6 +46,63 @@ static inline void lbs_cancel_association_work(struct lbs_private *priv) | |||
45 | priv->pending_assoc_req = NULL; | 46 | priv->pending_assoc_req = NULL; |
46 | } | 47 | } |
47 | 48 | ||
49 | void lbs_send_disconnect_notification(struct lbs_private *priv) | ||
50 | { | ||
51 | union iwreq_data wrqu; | ||
52 | |||
53 | memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN); | ||
54 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
55 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | ||
56 | } | ||
57 | |||
58 | static void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str) | ||
59 | { | ||
60 | union iwreq_data iwrq; | ||
61 | u8 buf[50]; | ||
62 | |||
63 | lbs_deb_enter(LBS_DEB_WEXT); | ||
64 | |||
65 | memset(&iwrq, 0, sizeof(union iwreq_data)); | ||
66 | memset(buf, 0, sizeof(buf)); | ||
67 | |||
68 | snprintf(buf, sizeof(buf) - 1, "%s", str); | ||
69 | |||
70 | iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN; | ||
71 | |||
72 | /* Send Event to upper layer */ | ||
73 | lbs_deb_wext("event indication string %s\n", (char *)buf); | ||
74 | lbs_deb_wext("event indication length %d\n", iwrq.data.length); | ||
75 | lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str); | ||
76 | |||
77 | wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf); | ||
78 | |||
79 | lbs_deb_leave(LBS_DEB_WEXT); | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * @brief This function handles MIC failure event. | ||
84 | * | ||
85 | * @param priv A pointer to struct lbs_private structure | ||
86 | * @para event the event id | ||
87 | * @return n/a | ||
88 | */ | ||
89 | void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event) | ||
90 | { | ||
91 | char buf[50]; | ||
92 | |||
93 | lbs_deb_enter(LBS_DEB_CMD); | ||
94 | memset(buf, 0, sizeof(buf)); | ||
95 | |||
96 | sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication "); | ||
97 | |||
98 | if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) | ||
99 | strcat(buf, "unicast "); | ||
100 | else | ||
101 | strcat(buf, "multicast "); | ||
102 | |||
103 | lbs_send_iwevcustom_event(priv, buf); | ||
104 | lbs_deb_leave(LBS_DEB_CMD); | ||
105 | } | ||
48 | 106 | ||
49 | /** | 107 | /** |
50 | * @brief Find the channel frequency power info with specific channel | 108 | * @brief Find the channel frequency power info with specific channel |
@@ -66,8 +124,6 @@ struct chan_freq_power *lbs_find_cfp_by_band_and_channel( | |||
66 | for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) { | 124 | for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) { |
67 | rc = &priv->region_channel[j]; | 125 | rc = &priv->region_channel[j]; |
68 | 126 | ||
69 | if (priv->enable11d) | ||
70 | rc = &priv->universal_channel[j]; | ||
71 | if (!rc->valid || !rc->CFP) | 127 | if (!rc->valid || !rc->CFP) |
72 | continue; | 128 | continue; |
73 | if (rc->band != band) | 129 | if (rc->band != band) |
@@ -107,8 +163,6 @@ static struct chan_freq_power *find_cfp_by_band_and_freq( | |||
107 | for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) { | 163 | for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) { |
108 | rc = &priv->region_channel[j]; | 164 | rc = &priv->region_channel[j]; |
109 | 165 | ||
110 | if (priv->enable11d) | ||
111 | rc = &priv->universal_channel[j]; | ||
112 | if (!rc->valid || !rc->CFP) | 166 | if (!rc->valid || !rc->CFP) |
113 | continue; | 167 | continue; |
114 | if (rc->band != band) | 168 | if (rc->band != band) |
@@ -139,7 +193,7 @@ static void copy_active_data_rates(struct lbs_private *priv, u8 *rates) | |||
139 | lbs_deb_enter(LBS_DEB_WEXT); | 193 | lbs_deb_enter(LBS_DEB_WEXT); |
140 | 194 | ||
141 | if ((priv->connect_status != LBS_CONNECTED) && | 195 | if ((priv->connect_status != LBS_CONNECTED) && |
142 | (priv->mesh_connect_status != LBS_CONNECTED)) | 196 | !lbs_mesh_connected(priv)) |
143 | memcpy(rates, lbs_bg_rates, MAX_RATES); | 197 | memcpy(rates, lbs_bg_rates, MAX_RATES); |
144 | else | 198 | else |
145 | memcpy(rates, priv->curbssparams.rates, MAX_RATES); | 199 | memcpy(rates, priv->curbssparams.rates, MAX_RATES); |
@@ -169,12 +223,12 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, | |||
169 | lbs_deb_enter(LBS_DEB_WEXT); | 223 | lbs_deb_enter(LBS_DEB_WEXT); |
170 | 224 | ||
171 | cfp = lbs_find_cfp_by_band_and_channel(priv, 0, | 225 | cfp = lbs_find_cfp_by_band_and_channel(priv, 0, |
172 | priv->curbssparams.channel); | 226 | priv->channel); |
173 | 227 | ||
174 | if (!cfp) { | 228 | if (!cfp) { |
175 | if (priv->curbssparams.channel) | 229 | if (priv->channel) |
176 | lbs_deb_wext("invalid channel %d\n", | 230 | lbs_deb_wext("invalid channel %d\n", |
177 | priv->curbssparams.channel); | 231 | priv->channel); |
178 | return -EINVAL; | 232 | return -EINVAL; |
179 | } | 233 | } |
180 | 234 | ||
@@ -245,6 +299,7 @@ static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info, | |||
245 | return 0; | 299 | return 0; |
246 | } | 300 | } |
247 | 301 | ||
302 | #ifdef CONFIG_LIBERTAS_MESH | ||
248 | static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, | 303 | static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, |
249 | struct iw_point *dwrq, char *extra) | 304 | struct iw_point *dwrq, char *extra) |
250 | { | 305 | { |
@@ -254,7 +309,7 @@ static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, | |||
254 | 309 | ||
255 | /* Use nickname to indicate that mesh is on */ | 310 | /* Use nickname to indicate that mesh is on */ |
256 | 311 | ||
257 | if (priv->mesh_connect_status == LBS_CONNECTED) { | 312 | if (lbs_mesh_connected(priv)) { |
258 | strncpy(extra, "Mesh", 12); | 313 | strncpy(extra, "Mesh", 12); |
259 | extra[12] = '\0'; | 314 | extra[12] = '\0'; |
260 | dwrq->length = strlen(extra); | 315 | dwrq->length = strlen(extra); |
@@ -268,6 +323,7 @@ static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, | |||
268 | lbs_deb_leave(LBS_DEB_WEXT); | 323 | lbs_deb_leave(LBS_DEB_WEXT); |
269 | return 0; | 324 | return 0; |
270 | } | 325 | } |
326 | #endif | ||
271 | 327 | ||
272 | static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, | 328 | static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, |
273 | struct iw_param *vwrq, char *extra) | 329 | struct iw_param *vwrq, char *extra) |
@@ -369,6 +425,7 @@ static int lbs_get_mode(struct net_device *dev, | |||
369 | return 0; | 425 | return 0; |
370 | } | 426 | } |
371 | 427 | ||
428 | #ifdef CONFIG_LIBERTAS_MESH | ||
372 | static int mesh_wlan_get_mode(struct net_device *dev, | 429 | static int mesh_wlan_get_mode(struct net_device *dev, |
373 | struct iw_request_info *info, u32 * uwrq, | 430 | struct iw_request_info *info, u32 * uwrq, |
374 | char *extra) | 431 | char *extra) |
@@ -380,6 +437,7 @@ static int mesh_wlan_get_mode(struct net_device *dev, | |||
380 | lbs_deb_leave(LBS_DEB_WEXT); | 437 | lbs_deb_leave(LBS_DEB_WEXT); |
381 | return 0; | 438 | return 0; |
382 | } | 439 | } |
440 | #endif | ||
383 | 441 | ||
384 | static int lbs_get_txpow(struct net_device *dev, | 442 | static int lbs_get_txpow(struct net_device *dev, |
385 | struct iw_request_info *info, | 443 | struct iw_request_info *info, |
@@ -547,8 +605,6 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info, | |||
547 | struct chan_freq_power *cfp; | 605 | struct chan_freq_power *cfp; |
548 | u8 rates[MAX_RATES + 1]; | 606 | u8 rates[MAX_RATES + 1]; |
549 | 607 | ||
550 | u8 flag = 0; | ||
551 | |||
552 | lbs_deb_enter(LBS_DEB_WEXT); | 608 | lbs_deb_enter(LBS_DEB_WEXT); |
553 | 609 | ||
554 | dwrq->length = sizeof(struct iw_range); | 610 | dwrq->length = sizeof(struct iw_range); |
@@ -570,52 +626,21 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info, | |||
570 | 626 | ||
571 | range->scan_capa = IW_SCAN_CAPA_ESSID; | 627 | range->scan_capa = IW_SCAN_CAPA_ESSID; |
572 | 628 | ||
573 | if (priv->enable11d && | 629 | for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES) |
574 | (priv->connect_status == LBS_CONNECTED || | 630 | && (j < ARRAY_SIZE(priv->region_channel)); j++) { |
575 | priv->mesh_connect_status == LBS_CONNECTED)) { | 631 | cfp = priv->region_channel[j].CFP; |
576 | u8 chan_no; | ||
577 | u8 band; | ||
578 | |||
579 | struct parsed_region_chan_11d *parsed_region_chan = | ||
580 | &priv->parsed_region_chan; | ||
581 | |||
582 | if (parsed_region_chan == NULL) { | ||
583 | lbs_deb_wext("11d: parsed_region_chan is NULL\n"); | ||
584 | goto out; | ||
585 | } | ||
586 | band = parsed_region_chan->band; | ||
587 | lbs_deb_wext("band %d, nr_char %d\n", band, | ||
588 | parsed_region_chan->nr_chan); | ||
589 | |||
590 | for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES) | 632 | for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES) |
591 | && (i < parsed_region_chan->nr_chan); i++) { | 633 | && priv->region_channel[j].valid |
592 | chan_no = parsed_region_chan->chanpwr[i].chan; | 634 | && cfp |
593 | lbs_deb_wext("chan_no %d\n", chan_no); | 635 | && (i < priv->region_channel[j].nrcfp); i++) { |
594 | range->freq[range->num_frequency].i = (long)chan_no; | 636 | range->freq[range->num_frequency].i = |
637 | (long)cfp->channel; | ||
595 | range->freq[range->num_frequency].m = | 638 | range->freq[range->num_frequency].m = |
596 | (long)lbs_chan_2_freq(chan_no) * 100000; | 639 | (long)cfp->freq * 100000; |
597 | range->freq[range->num_frequency].e = 1; | 640 | range->freq[range->num_frequency].e = 1; |
641 | cfp++; | ||
598 | range->num_frequency++; | 642 | range->num_frequency++; |
599 | } | 643 | } |
600 | flag = 1; | ||
601 | } | ||
602 | if (!flag) { | ||
603 | for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES) | ||
604 | && (j < ARRAY_SIZE(priv->region_channel)); j++) { | ||
605 | cfp = priv->region_channel[j].CFP; | ||
606 | for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES) | ||
607 | && priv->region_channel[j].valid | ||
608 | && cfp | ||
609 | && (i < priv->region_channel[j].nrcfp); i++) { | ||
610 | range->freq[range->num_frequency].i = | ||
611 | (long)cfp->channel; | ||
612 | range->freq[range->num_frequency].m = | ||
613 | (long)cfp->freq * 100000; | ||
614 | range->freq[range->num_frequency].e = 1; | ||
615 | cfp++; | ||
616 | range->num_frequency++; | ||
617 | } | ||
618 | } | ||
619 | } | 644 | } |
620 | 645 | ||
621 | lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n", | 646 | lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n", |
@@ -700,7 +725,6 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info, | |||
700 | | IW_ENC_CAPA_CIPHER_CCMP; | 725 | | IW_ENC_CAPA_CIPHER_CCMP; |
701 | } | 726 | } |
702 | 727 | ||
703 | out: | ||
704 | lbs_deb_leave(LBS_DEB_WEXT); | 728 | lbs_deb_leave(LBS_DEB_WEXT); |
705 | return 0; | 729 | return 0; |
706 | } | 730 | } |
@@ -709,6 +733,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, | |||
709 | struct iw_param *vwrq, char *extra) | 733 | struct iw_param *vwrq, char *extra) |
710 | { | 734 | { |
711 | struct lbs_private *priv = dev->ml_priv; | 735 | struct lbs_private *priv = dev->ml_priv; |
736 | int ret = 0; | ||
712 | 737 | ||
713 | lbs_deb_enter(LBS_DEB_WEXT); | 738 | lbs_deb_enter(LBS_DEB_WEXT); |
714 | 739 | ||
@@ -737,8 +762,54 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, | |||
737 | "setting power timeout is not supported\n"); | 762 | "setting power timeout is not supported\n"); |
738 | return -EINVAL; | 763 | return -EINVAL; |
739 | } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { | 764 | } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { |
740 | lbs_deb_wext("setting power period not supported\n"); | 765 | vwrq->value = vwrq->value / 1000; |
741 | return -EINVAL; | 766 | if (!priv->enter_deep_sleep) { |
767 | lbs_pr_err("deep sleep feature is not implemented " | ||
768 | "for this interface driver\n"); | ||
769 | return -EINVAL; | ||
770 | } | ||
771 | |||
772 | if (priv->connect_status == LBS_CONNECTED) { | ||
773 | if ((priv->is_auto_deep_sleep_enabled) && | ||
774 | (vwrq->value == -1000)) { | ||
775 | lbs_exit_auto_deep_sleep(priv); | ||
776 | return 0; | ||
777 | } else { | ||
778 | lbs_pr_err("can't use deep sleep cmd in " | ||
779 | "connected state\n"); | ||
780 | return -EINVAL; | ||
781 | } | ||
782 | } | ||
783 | |||
784 | if ((vwrq->value < 0) && (vwrq->value != -1000)) { | ||
785 | lbs_pr_err("unknown option\n"); | ||
786 | return -EINVAL; | ||
787 | } | ||
788 | |||
789 | if (vwrq->value > 0) { | ||
790 | if (!priv->is_auto_deep_sleep_enabled) { | ||
791 | priv->is_activity_detected = 0; | ||
792 | priv->auto_deep_sleep_timeout = vwrq->value; | ||
793 | lbs_enter_auto_deep_sleep(priv); | ||
794 | } else { | ||
795 | priv->auto_deep_sleep_timeout = vwrq->value; | ||
796 | lbs_deb_debugfs("auto deep sleep: " | ||
797 | "already enabled\n"); | ||
798 | } | ||
799 | return 0; | ||
800 | } else { | ||
801 | if (priv->is_auto_deep_sleep_enabled) { | ||
802 | lbs_exit_auto_deep_sleep(priv); | ||
803 | /* Try to exit deep sleep if auto */ | ||
804 | /*deep sleep disabled */ | ||
805 | ret = lbs_set_deep_sleep(priv, 0); | ||
806 | } | ||
807 | if (vwrq->value == 0) | ||
808 | ret = lbs_set_deep_sleep(priv, 1); | ||
809 | else if (vwrq->value == -1000) | ||
810 | ret = lbs_set_deep_sleep(priv, 0); | ||
811 | return ret; | ||
812 | } | ||
742 | } | 813 | } |
743 | 814 | ||
744 | if (priv->psmode != LBS802_11POWERMODECAM) { | 815 | if (priv->psmode != LBS802_11POWERMODECAM) { |
@@ -752,6 +823,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, | |||
752 | } | 823 | } |
753 | 824 | ||
754 | lbs_deb_leave(LBS_DEB_WEXT); | 825 | lbs_deb_leave(LBS_DEB_WEXT); |
826 | |||
755 | return 0; | 827 | return 0; |
756 | } | 828 | } |
757 | 829 | ||
@@ -785,7 +857,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) | |||
785 | u32 rssi_qual; | 857 | u32 rssi_qual; |
786 | u32 tx_qual; | 858 | u32 tx_qual; |
787 | u32 quality = 0; | 859 | u32 quality = 0; |
788 | int stats_valid = 0; | 860 | int ret, stats_valid = 0; |
789 | u8 rssi; | 861 | u8 rssi; |
790 | u32 tx_retries; | 862 | u32 tx_retries; |
791 | struct cmd_ds_802_11_get_log log; | 863 | struct cmd_ds_802_11_get_log log; |
@@ -796,7 +868,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) | |||
796 | 868 | ||
797 | /* If we're not associated, all quality values are meaningless */ | 869 | /* If we're not associated, all quality values are meaningless */ |
798 | if ((priv->connect_status != LBS_CONNECTED) && | 870 | if ((priv->connect_status != LBS_CONNECTED) && |
799 | (priv->mesh_connect_status != LBS_CONNECTED)) | 871 | !lbs_mesh_connected(priv)) |
800 | goto out; | 872 | goto out; |
801 | 873 | ||
802 | /* Quality by RSSI */ | 874 | /* Quality by RSSI */ |
@@ -834,7 +906,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) | |||
834 | 906 | ||
835 | memset(&log, 0, sizeof(log)); | 907 | memset(&log, 0, sizeof(log)); |
836 | log.hdr.size = cpu_to_le16(sizeof(log)); | 908 | log.hdr.size = cpu_to_le16(sizeof(log)); |
837 | lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log); | 909 | ret = lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log); |
910 | if (ret) | ||
911 | goto out; | ||
838 | 912 | ||
839 | tx_retries = le32_to_cpu(log.retry); | 913 | tx_retries = le32_to_cpu(log.retry); |
840 | 914 | ||
@@ -862,8 +936,10 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) | |||
862 | stats_valid = 1; | 936 | stats_valid = 1; |
863 | 937 | ||
864 | /* update stats asynchronously for future calls */ | 938 | /* update stats asynchronously for future calls */ |
865 | lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, | 939 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, |
866 | 0, 0, NULL); | 940 | 0, 0, NULL); |
941 | if (ret) | ||
942 | lbs_pr_err("RSSI command failed\n"); | ||
867 | out: | 943 | out: |
868 | if (!stats_valid) { | 944 | if (!stats_valid) { |
869 | priv->wstats.miss.beacon = 0; | 945 | priv->wstats.miss.beacon = 0; |
@@ -939,6 +1015,7 @@ out: | |||
939 | return ret; | 1015 | return ret; |
940 | } | 1016 | } |
941 | 1017 | ||
1018 | #ifdef CONFIG_LIBERTAS_MESH | ||
942 | static int lbs_mesh_set_freq(struct net_device *dev, | 1019 | static int lbs_mesh_set_freq(struct net_device *dev, |
943 | struct iw_request_info *info, | 1020 | struct iw_request_info *info, |
944 | struct iw_freq *fwrq, char *extra) | 1021 | struct iw_freq *fwrq, char *extra) |
@@ -973,7 +1050,7 @@ static int lbs_mesh_set_freq(struct net_device *dev, | |||
973 | goto out; | 1050 | goto out; |
974 | } | 1051 | } |
975 | 1052 | ||
976 | if (fwrq->m != priv->curbssparams.channel) { | 1053 | if (fwrq->m != priv->channel) { |
977 | lbs_deb_wext("mesh channel change forces eth disconnect\n"); | 1054 | lbs_deb_wext("mesh channel change forces eth disconnect\n"); |
978 | if (priv->mode == IW_MODE_INFRA) | 1055 | if (priv->mode == IW_MODE_INFRA) |
979 | lbs_cmd_80211_deauthenticate(priv, | 1056 | lbs_cmd_80211_deauthenticate(priv, |
@@ -990,6 +1067,7 @@ out: | |||
990 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | 1067 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); |
991 | return ret; | 1068 | return ret; |
992 | } | 1069 | } |
1070 | #endif | ||
993 | 1071 | ||
994 | static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, | 1072 | static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, |
995 | struct iw_param *vwrq, char *extra) | 1073 | struct iw_param *vwrq, char *extra) |
@@ -1000,6 +1078,7 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, | |||
1000 | u8 rates[MAX_RATES + 1]; | 1078 | u8 rates[MAX_RATES + 1]; |
1001 | 1079 | ||
1002 | lbs_deb_enter(LBS_DEB_WEXT); | 1080 | lbs_deb_enter(LBS_DEB_WEXT); |
1081 | |||
1003 | lbs_deb_wext("vwrq->value %d\n", vwrq->value); | 1082 | lbs_deb_wext("vwrq->value %d\n", vwrq->value); |
1004 | lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed); | 1083 | lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed); |
1005 | 1084 | ||
@@ -1953,10 +2032,8 @@ static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info, | |||
1953 | if (priv->connect_status == LBS_CONNECTED) { | 2032 | if (priv->connect_status == LBS_CONNECTED) { |
1954 | memcpy(extra, priv->curbssparams.ssid, | 2033 | memcpy(extra, priv->curbssparams.ssid, |
1955 | priv->curbssparams.ssid_len); | 2034 | priv->curbssparams.ssid_len); |
1956 | extra[priv->curbssparams.ssid_len] = '\0'; | ||
1957 | } else { | 2035 | } else { |
1958 | memset(extra, 0, 32); | 2036 | memset(extra, 0, 32); |
1959 | extra[priv->curbssparams.ssid_len] = '\0'; | ||
1960 | } | 2037 | } |
1961 | /* | 2038 | /* |
1962 | * If none, we may want to get the one that was set | 2039 | * If none, we may want to get the one that was set |
@@ -1975,7 +2052,7 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info, | |||
1975 | { | 2052 | { |
1976 | struct lbs_private *priv = dev->ml_priv; | 2053 | struct lbs_private *priv = dev->ml_priv; |
1977 | int ret = 0; | 2054 | int ret = 0; |
1978 | u8 ssid[IW_ESSID_MAX_SIZE]; | 2055 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
1979 | u8 ssid_len = 0; | 2056 | u8 ssid_len = 0; |
1980 | struct assoc_request * assoc_req; | 2057 | struct assoc_request * assoc_req; |
1981 | int in_ssid_len = dwrq->length; | 2058 | int in_ssid_len = dwrq->length; |
@@ -1989,7 +2066,7 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info, | |||
1989 | } | 2066 | } |
1990 | 2067 | ||
1991 | /* Check the size of the string */ | 2068 | /* Check the size of the string */ |
1992 | if (in_ssid_len > IW_ESSID_MAX_SIZE) { | 2069 | if (in_ssid_len > IEEE80211_MAX_SSID_LEN) { |
1993 | ret = -E2BIG; | 2070 | ret = -E2BIG; |
1994 | goto out; | 2071 | goto out; |
1995 | } | 2072 | } |
@@ -2020,7 +2097,7 @@ out: | |||
2020 | ret = -ENOMEM; | 2097 | ret = -ENOMEM; |
2021 | } else { | 2098 | } else { |
2022 | /* Copy the SSID to the association request */ | 2099 | /* Copy the SSID to the association request */ |
2023 | memcpy(&assoc_req->ssid, &ssid, IW_ESSID_MAX_SIZE); | 2100 | memcpy(&assoc_req->ssid, &ssid, IEEE80211_MAX_SSID_LEN); |
2024 | assoc_req->ssid_len = ssid_len; | 2101 | assoc_req->ssid_len = ssid_len; |
2025 | set_bit(ASSOC_FLAG_SSID, &assoc_req->flags); | 2102 | set_bit(ASSOC_FLAG_SSID, &assoc_req->flags); |
2026 | lbs_postpone_association_work(priv); | 2103 | lbs_postpone_association_work(priv); |
@@ -2038,6 +2115,7 @@ out: | |||
2038 | return ret; | 2115 | return ret; |
2039 | } | 2116 | } |
2040 | 2117 | ||
2118 | #ifdef CONFIG_LIBERTAS_MESH | ||
2041 | static int lbs_mesh_get_essid(struct net_device *dev, | 2119 | static int lbs_mesh_get_essid(struct net_device *dev, |
2042 | struct iw_request_info *info, | 2120 | struct iw_request_info *info, |
2043 | struct iw_point *dwrq, char *extra) | 2121 | struct iw_point *dwrq, char *extra) |
@@ -2071,7 +2149,7 @@ static int lbs_mesh_set_essid(struct net_device *dev, | |||
2071 | } | 2149 | } |
2072 | 2150 | ||
2073 | /* Check the size of the string */ | 2151 | /* Check the size of the string */ |
2074 | if (dwrq->length > IW_ESSID_MAX_SIZE) { | 2152 | if (dwrq->length > IEEE80211_MAX_SSID_LEN) { |
2075 | ret = -E2BIG; | 2153 | ret = -E2BIG; |
2076 | goto out; | 2154 | goto out; |
2077 | } | 2155 | } |
@@ -2086,11 +2164,12 @@ static int lbs_mesh_set_essid(struct net_device *dev, | |||
2086 | } | 2164 | } |
2087 | 2165 | ||
2088 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, | 2166 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, |
2089 | priv->curbssparams.channel); | 2167 | priv->channel); |
2090 | out: | 2168 | out: |
2091 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | 2169 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); |
2092 | return ret; | 2170 | return ret; |
2093 | } | 2171 | } |
2172 | #endif | ||
2094 | 2173 | ||
2095 | /** | 2174 | /** |
2096 | * @brief Connect to the AP or Ad-hoc Network with specific bssid | 2175 | * @brief Connect to the AP or Ad-hoc Network with specific bssid |
@@ -2197,7 +2276,13 @@ static const iw_handler lbs_handler[] = { | |||
2197 | (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ | 2276 | (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ |
2198 | (iw_handler) NULL, /* SIOCSIWPMKSA */ | 2277 | (iw_handler) NULL, /* SIOCSIWPMKSA */ |
2199 | }; | 2278 | }; |
2279 | struct iw_handler_def lbs_handler_def = { | ||
2280 | .num_standard = ARRAY_SIZE(lbs_handler), | ||
2281 | .standard = (iw_handler *) lbs_handler, | ||
2282 | .get_wireless_stats = lbs_get_wireless_stats, | ||
2283 | }; | ||
2200 | 2284 | ||
2285 | #ifdef CONFIG_LIBERTAS_MESH | ||
2201 | static const iw_handler mesh_wlan_handler[] = { | 2286 | static const iw_handler mesh_wlan_handler[] = { |
2202 | (iw_handler) NULL, /* SIOCSIWCOMMIT */ | 2287 | (iw_handler) NULL, /* SIOCSIWCOMMIT */ |
2203 | (iw_handler) lbs_get_name, /* SIOCGIWNAME */ | 2288 | (iw_handler) lbs_get_name, /* SIOCGIWNAME */ |
@@ -2255,14 +2340,10 @@ static const iw_handler mesh_wlan_handler[] = { | |||
2255 | (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ | 2340 | (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ |
2256 | (iw_handler) NULL, /* SIOCSIWPMKSA */ | 2341 | (iw_handler) NULL, /* SIOCSIWPMKSA */ |
2257 | }; | 2342 | }; |
2258 | struct iw_handler_def lbs_handler_def = { | ||
2259 | .num_standard = ARRAY_SIZE(lbs_handler), | ||
2260 | .standard = (iw_handler *) lbs_handler, | ||
2261 | .get_wireless_stats = lbs_get_wireless_stats, | ||
2262 | }; | ||
2263 | 2343 | ||
2264 | struct iw_handler_def mesh_handler_def = { | 2344 | struct iw_handler_def mesh_handler_def = { |
2265 | .num_standard = ARRAY_SIZE(mesh_wlan_handler), | 2345 | .num_standard = ARRAY_SIZE(mesh_wlan_handler), |
2266 | .standard = (iw_handler *) mesh_wlan_handler, | 2346 | .standard = (iw_handler *) mesh_wlan_handler, |
2267 | .get_wireless_stats = lbs_get_wireless_stats, | 2347 | .get_wireless_stats = lbs_get_wireless_stats, |
2268 | }; | 2348 | }; |
2349 | #endif | ||
diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h index 4c08db497606..f3f19fe8c6c6 100644 --- a/drivers/net/wireless/libertas/wext.h +++ b/drivers/net/wireless/libertas/wext.h | |||
@@ -4,7 +4,14 @@ | |||
4 | #ifndef _LBS_WEXT_H_ | 4 | #ifndef _LBS_WEXT_H_ |
5 | #define _LBS_WEXT_H_ | 5 | #define _LBS_WEXT_H_ |
6 | 6 | ||
7 | void lbs_send_disconnect_notification(struct lbs_private *priv); | ||
8 | void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event); | ||
9 | |||
10 | struct chan_freq_power *lbs_find_cfp_by_band_and_channel( | ||
11 | struct lbs_private *priv, | ||
12 | u8 band, | ||
13 | u16 channel); | ||
14 | |||
7 | extern struct iw_handler_def lbs_handler_def; | 15 | extern struct iw_handler_def lbs_handler_def; |
8 | extern struct iw_handler_def mesh_handler_def; | ||
9 | 16 | ||
10 | #endif | 17 | #endif |