aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas')
-rw-r--r--drivers/net/wireless/libertas/11d.c696
-rw-r--r--drivers/net/wireless/libertas/11d.h105
-rw-r--r--drivers/net/wireless/libertas/Kconfig45
-rw-r--r--drivers/net/wireless/libertas/Makefile14
-rw-r--r--drivers/net/wireless/libertas/README26
-rw-r--r--drivers/net/wireless/libertas/assoc.c535
-rw-r--r--drivers/net/wireless/libertas/assoc.h141
-rw-r--r--drivers/net/wireless/libertas/cfg.c203
-rw-r--r--drivers/net/wireless/libertas/cfg.h16
-rw-r--r--drivers/net/wireless/libertas/cmd.c720
-rw-r--r--drivers/net/wireless/libertas/cmd.h115
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c138
-rw-r--r--drivers/net/wireless/libertas/debugfs.c28
-rw-r--r--drivers/net/wireless/libertas/decl.h65
-rw-r--r--drivers/net/wireless/libertas/defs.h10
-rw-r--r--drivers/net/wireless/libertas/dev.h432
-rw-r--r--drivers/net/wireless/libertas/ethtool.c86
-rw-r--r--drivers/net/wireless/libertas/host.h959
-rw-r--r--drivers/net/wireless/libertas/hostcmd.h800
-rw-r--r--drivers/net/wireless/libertas/if_cs.c77
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c65
-rw-r--r--drivers/net/wireless/libertas/if_sdio.h3
-rw-r--r--drivers/net/wireless/libertas/if_spi.c145
-rw-r--r--drivers/net/wireless/libertas/if_usb.c6
-rw-r--r--drivers/net/wireless/libertas/main.c795
-rw-r--r--drivers/net/wireless/libertas/mesh.c1154
-rw-r--r--drivers/net/wireless/libertas/mesh.h110
-rw-r--r--drivers/net/wireless/libertas/persistcfg.c453
-rw-r--r--drivers/net/wireless/libertas/rx.c14
-rw-r--r--drivers/net/wireless/libertas/scan.c273
-rw-r--r--drivers/net/wireless/libertas/scan.h30
-rw-r--r--drivers/net/wireless/libertas/tx.c11
-rw-r--r--drivers/net/wireless/libertas/types.h4
-rw-r--r--drivers/net/wireless/libertas/wext.c225
-rw-r--r--drivers/net/wireless/libertas/wext.h9
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
16static 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 */
29static 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
46static 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
63static 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*/
82static 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*/
116static 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
137u32 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
153static 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*/
220static 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*/
267static 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
294done:
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*/
305static 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
400done:
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*/
411u8 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
430void 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*/
443static 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*/
467int 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*/
497int 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
543done:
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 */
554int 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 */
598int 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
629done:
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 */
639int 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
693done:
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
20struct cmd_ds_command;
21
22/** Data structure for Country IE*/
23struct ieee_subbandset {
24 u8 firstchan;
25 u8 nrchan;
26 u8 maxtxpwr;
27} __attribute__ ((packed));
28
29struct 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
36struct 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
43struct 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
50struct 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 */
56struct 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
64struct chan_power_11d {
65 u8 chan;
66 u8 pwr;
67} __attribute__ ((packed));
68
69struct 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
77struct region_code_mapping {
78 u8 region[COUNTRY_CODE_LEN];
79 u8 code;
80};
81
82struct lbs_private;
83
84u8 lbs_get_scan_type_11d(u8 chan,
85 struct parsed_region_chan_11d *parsed_region_chan);
86
87u32 lbs_chan_2_freq(u8 chan);
88
89void lbs_init_11d(struct lbs_private *priv);
90
91int lbs_set_universaltable(struct lbs_private *priv, u8 band);
92
93int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
94 struct cmd_ds_command *cmd, u16 cmdno,
95 u16 cmdOption);
96
97int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp);
98
99struct bss_descriptor;
100int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv,
101 struct bss_descriptor * bss);
102
103int 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 @@
1config 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
11config 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
17config 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
23config 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
29config 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
35config LIBERTAS_DEBUG
36 bool "Enable full debugging output in the Libertas module."
37 depends on LIBERTAS
38 ---help---
39 Debugging support.
40
41config 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 @@
1libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o \ 1libertas-y += assoc.o
2 debugfs.o persistcfg.o ethtool.o assoc.o 2libertas-y += cfg.o
3libertas-y += cmd.o
4libertas-y += cmdresp.o
5libertas-y += debugfs.o
6libertas-y += ethtool.o
7libertas-y += main.o
8libertas-y += rx.o
9libertas-y += scan.o
10libertas-y += tx.o
11libertas-y += wext.o
12libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o
3 13
4usb8xxx-objs += if_usb.o 14usb8xxx-objs += if_usb.o
5libertas_cs-objs += if_cs.o 15libertas_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========================
230IWCONFIG COMMANDS
231========================
232power 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 */
30u8 lbs_bg_rates[MAX_RATES] =
31 { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
320x00, 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
158int 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);
214done:
215 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
216 return ret;
217}
218
219int 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
248static 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
270int 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
349static __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
377int 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 */
409int 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
446out:
447 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
448 return ret;
449}
450
451
452int 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
474int 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
507int 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
528int 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
150static int lbs_assoc_post(struct lbs_private *priv, 547static 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
492done: 883done:
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)
787static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, 1161static 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,
800static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, 1174static 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,
811static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, 1185static 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,
837static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, 1211static 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
1190done: 1565done:
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
11struct 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
21struct 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 */
30struct 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 */
47struct 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 */
85struct 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
125extern u8 lbs_bg_rates[MAX_RATES];
7 126
8void lbs_association_worker(struct work_struct *work); 127void lbs_association_worker(struct work_struct *work);
9struct assoc_request *lbs_get_association_request(struct lbs_private *priv); 128struct assoc_request *lbs_get_association_request(struct lbs_private *priv);
@@ -13,4 +132,24 @@ int lbs_adhoc_stop(struct lbs_private *priv);
13int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, 132int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
14 u8 bssid[ETH_ALEN], u16 reason); 133 u8 bssid[ETH_ALEN], u16 reason);
15 134
135int lbs_cmd_802_11_rssi(struct lbs_private *priv,
136 struct cmd_ds_command *cmd);
137int lbs_ret_802_11_rssi(struct lbs_private *priv,
138 struct cmd_ds_command *resp);
139
140int lbs_cmd_bcn_ctrl(struct lbs_private *priv,
141 struct cmd_ds_command *cmd,
142 u16 cmd_action);
143int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv,
144 struct cmd_ds_command *resp);
145
146int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
147 struct assoc_request *assoc);
148
149int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
150 uint16_t *enable);
151
152int 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
25static 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
49static 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
64static 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
72static 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
81static 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
103static 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 */
114struct 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 */
149int 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
187void 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
6struct wireless_dev *lbs_cfg_alloc(struct device *dev);
7int lbs_cfg_register(struct lbs_private *priv);
8void lbs_cfg_free(struct lbs_private *priv);
9
10int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
11 u8 ssid_len);
12int lbs_scan_networks(struct lbs_private *priv, int full_scan);
13void 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
19static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
20 19
20static 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
86static 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
177out: 183out:
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
254int 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
281int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, 260int 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
323int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, 302static 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);
379done:
380 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
381 return ret;
382}
383
384int 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
413static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam, 320int 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
435int 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
695static __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
723int 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}
748EXPORT_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 */
758int 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
795out:
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 */
807int lbs_get_channel(struct lbs_private *priv) 538static 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
877out: 608out:
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
882static 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
903static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, 613static 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
977static 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
1014static 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
1035int 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
1054static 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
1084int 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 */
1102int 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
1142static 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
1163static void lbs_queue_cmd(struct lbs_private *priv, 687static 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
1826void 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
1850static void lbs_send_confirmsleep(struct lbs_private *priv) 1335static 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
2027static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, 1512struct 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}
2119EXPORT_SYMBOL_GPL(__lbs_cmd); 1609EXPORT_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
12struct 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
40int 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
21void lbs_cmd_async(struct lbs_private *priv, uint16_t command, 45void 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
29int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, 53struct 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
32int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, 58int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
33 int8_t p2, int usesnr); 59 struct cmd_header *resp);
34 60
35int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, 61int lbs_allocate_cmd_buffer(struct lbs_private *priv);
36 int8_t p1, int8_t p2); 62int lbs_free_cmd_buffer(struct lbs_private *priv);
37 63
38int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, 64int lbs_execute_next_command(struct lbs_private *priv);
39 int8_t p2, int usesnr); 65void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
66 int result);
67int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
40 68
41int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
42 struct cmd_header *resp);
43 69
44int lbs_update_hw_spec(struct lbs_private *priv); 70/* From cmdresp.c */
45 71
46int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, 72void lbs_mac_event_disconnected(struct lbs_private *priv);
47 struct cmd_ds_mesh_access *cmd);
48 73
49int lbs_set_data_rate(struct lbs_private *priv, u8 rate);
50 74
51int lbs_get_channel(struct lbs_private *priv); 75
76/* Events */
77
78int lbs_process_event(struct lbs_private *priv, u32 event);
79
80
81/* Actual commands */
82
83int lbs_update_hw_spec(struct lbs_private *priv);
84
52int lbs_set_channel(struct lbs_private *priv, u8 channel); 85int lbs_set_channel(struct lbs_private *priv, u8 channel);
53 86
54int lbs_mesh_config_send(struct lbs_private *priv, 87int lbs_update_channel(struct lbs_private *priv);
55 struct cmd_ds_mesh_config *cmd,
56 uint16_t action, uint16_t type);
57int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
58 88
59int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, 89int 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);
61int lbs_suspend(struct lbs_private *priv);
62void lbs_resume(struct lbs_private *priv);
63 91
64int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
65 uint16_t cmd_action);
66int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv,
67 uint16_t cmd_action, uint16_t *timeout);
68int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, 92int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
69 struct sleep_params *sp); 93 struct sleep_params *sp);
70int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
71 struct assoc_request *assoc);
72int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
73 uint16_t *enable);
74int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
75 struct assoc_request *assoc);
76 94
77int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, 95void lbs_ps_sleep(struct lbs_private *priv, int wait_option);
78 s16 *maxlevel); 96
79int lbs_set_tx_power(struct lbs_private *priv, s16 dbm); 97void lbs_ps_wakeup(struct lbs_private *priv, int wait_option);
98
99void lbs_ps_confirm_sleep(struct lbs_private *priv);
80 100
81int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on); 101int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on);
82 102
103void lbs_set_mac_control(struct lbs_private *priv);
104
105int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
106 s16 *maxlevel);
107
83int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val); 108int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val);
84 109
85int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val); 110int 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
115int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
116 int8_t p1, int8_t p2);
117
118int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
119 int8_t p2, int usesnr);
120
121int lbs_set_data_rate(struct lbs_private *priv, u8 rate);
122
123int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
124 uint16_t cmd_action);
125
126int lbs_set_tx_power(struct lbs_private *priv, s16 dbm);
127
128int 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 */
27void lbs_mac_event_disconnected(struct lbs_private *priv) 29void 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 */
88static 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
107static int lbs_ret_reg_access(struct lbs_private *priv, 77static 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
150static 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
180static 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
197static inline int handle_cmd_response(struct lbs_private *priv, 120static 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;
518out_unlock: 522out_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;
607out_unlock: 614out_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;
696out_unlock: 706out_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 */
14struct lbs_private; 12struct lbs_private;
15struct sk_buff; 13struct sk_buff;
16struct net_device; 14struct net_device;
17struct cmd_ctrl_node;
18struct cmd_ds_command;
19 15
20void lbs_set_mac_control(struct lbs_private *priv);
21 16
22void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count); 17/* ethtool.c */
23 18extern const struct ethtool_ops lbs_ethtool_ops;
24int lbs_free_cmd_buffer(struct lbs_private *priv);
25
26int 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
31int lbs_allocate_cmd_buffer(struct lbs_private *priv);
32int lbs_execute_next_command(struct lbs_private *priv);
33int lbs_process_event(struct lbs_private *priv, u32 event);
34void lbs_queue_event(struct lbs_private *priv, u32 event);
35void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
36 20
37u32 lbs_fw_index_to_data_rate(u8 index); 21/* tx.c */
38u8 lbs_data_rate_to_fw_index(u32 rate); 22void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count);
39
40/** The proc fs interface */
41int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
42void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
43 int result);
44netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, 23netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb,
45 struct net_device *dev); 24 struct net_device *dev);
46int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
47 25
26/* rx.c */
48int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *); 27int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *);
49 28
50void lbs_ps_sleep(struct lbs_private *priv, int wait_option);
51void lbs_ps_confirm_sleep(struct lbs_private *priv);
52void lbs_ps_wakeup(struct lbs_private *priv, int wait_option);
53
54struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
55 struct lbs_private *priv,
56 u8 band,
57 u16 channel);
58
59void lbs_mac_event_disconnected(struct lbs_private *priv);
60
61void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str);
62
63/* persistcfg.c */
64void lbs_persist_config_init(struct net_device *net);
65void lbs_persist_config_remove(struct net_device *net);
66 29
67/* main.c */ 30/* main.c */
68struct chan_freq_power *lbs_get_region_cfp_table(u8 region,
69 int *cfp_no);
70struct lbs_private *lbs_add_card(void *card, struct device *dmdev); 31struct lbs_private *lbs_add_card(void *card, struct device *dmdev);
71void lbs_remove_card(struct lbs_private *priv); 32void lbs_remove_card(struct lbs_private *priv);
72int lbs_start_card(struct lbs_private *priv); 33int lbs_start_card(struct lbs_private *priv);
73void lbs_stop_card(struct lbs_private *priv); 34void lbs_stop_card(struct lbs_private *priv);
74void lbs_host_to_card_done(struct lbs_private *priv); 35void lbs_host_to_card_done(struct lbs_private *priv);
75 36
76int lbs_update_channel(struct lbs_private *priv); 37int lbs_set_mac_address(struct net_device *dev, void *addr);
38void lbs_set_multicast_list(struct net_device *dev);
39
40int lbs_suspend(struct lbs_private *priv);
41void lbs_resume(struct lbs_private *priv);
42
43void lbs_queue_event(struct lbs_private *priv, u32 event);
44void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
45
46int lbs_enter_auto_deep_sleep(struct lbs_private *priv);
47int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
48
49u32 lbs_fw_index_to_data_rate(u8 index);
50u8 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
46extern unsigned int lbs_debug; 47extern 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
320extern const char lbs_driver_version[]; 322extern const char lbs_driver_version[];
321extern u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE]; 323extern u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE];
322 324
323extern 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 */
400enum _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
17extern 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*/
30struct 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*/
42struct 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
55struct 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 */
64struct 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 */
80struct sleep_params { 16struct 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 */
90struct 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 */
102struct lbs_private { 27struct 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
325extern struct cmd_confirm_sleep confirm_sleep; 203extern struct cmd_confirm_sleep confirm_sleep;
326 204
327/**
328 * @brief Structure used to store information for each beacon/probe response
329 */
330struct 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 */
370struct 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
12static 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
23static void lbs_ethtool_get_drvinfo(struct net_device *dev, 14static 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
76static 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
114static 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
124static 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
143static void lbs_ethtool_get_wol(struct net_device *dev, 67static 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 */
201enum cmd_bt_access_opts { 190enum 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 */
298struct 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 */
332struct 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
371struct 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. */
379struct 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 */
387struct 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 */
396struct 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
431struct 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 */
449struct 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
457struct 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
465struct 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
483struct cmd_ds_mac_control {
484 struct cmd_header hdr;
485 __le16 action;
486 u16 reserved;
487} __attribute__ ((packed));
488
489struct 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
496struct 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
504struct cmd_ds_802_11_deauthenticate {
505 struct cmd_header hdr;
506
507 u8 macaddr[ETH_ALEN];
508 __le16 reasoncode;
509} __attribute__ ((packed));
510
511struct 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
522struct 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
531struct 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
545struct 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
554struct cmd_ds_mac_reg_access {
555 __le16 action;
556 __le16 offset;
557 __le32 value;
558} __attribute__ ((packed));
559
560struct cmd_ds_bbp_reg_access {
561 __le16 action;
562 __le16 offset;
563 u8 value;
564 u8 reserved[3];
565} __attribute__ ((packed));
566
567struct cmd_ds_rf_reg_access {
568 __le16 action;
569 __le16 offset;
570 u8 value;
571 u8 reserved[3];
572} __attribute__ ((packed));
573
574struct cmd_ds_802_11_radio_control {
575 struct cmd_header hdr;
576
577 __le16 action;
578 __le16 control;
579} __attribute__ ((packed));
580
581struct cmd_ds_802_11_beacon_control {
582 __le16 action;
583 __le16 beacon_enable;
584 __le16 beacon_period;
585} __attribute__ ((packed));
586
587struct 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
612struct 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
622struct 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
631struct cmd_ds_802_11_rssi_rsp {
632 __le16 SNR;
633 __le16 noisefloor;
634 __le16 avgSNR;
635 __le16 avgnoisefloor;
636} __attribute__ ((packed));
637
638struct cmd_ds_802_11_mac_address {
639 struct cmd_header hdr;
640
641 __le16 action;
642 u8 macadd[ETH_ALEN];
643} __attribute__ ((packed));
644
645struct 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
654struct cmd_ds_802_11_monitor_mode {
655 __le16 action;
656 __le16 mode;
657} __attribute__ ((packed));
658
659struct cmd_ds_set_boot2_ver {
660 struct cmd_header hdr;
661
662 __le16 action;
663 __le16 version;
664} __attribute__ ((packed));
665
666struct cmd_ds_802_11_fw_wake_method {
667 struct cmd_header hdr;
668
669 __le16 action;
670 __le16 method;
671} __attribute__ ((packed));
672
673struct 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
681struct 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
691struct 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
699struct 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
706struct 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
723struct 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
730struct 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
751struct 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
759struct cmd_ds_802_11_ad_hoc_stop {
760 struct cmd_header hdr;
761} __attribute__ ((packed));
762
763struct cmd_ds_802_11_enable_rsn {
764 struct cmd_header hdr;
765
766 __le16 action;
767 __le16 enable;
768} __attribute__ ((packed));
769
770struct 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
792struct 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
802struct 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
810struct 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
820struct 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
827struct 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
837struct 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
849struct 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
860struct cmd_ds_802_11_led_ctrl {
861 __le16 action;
862 __le16 numled;
863 u8 data[256];
864} __attribute__ ((packed));
865
866struct 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
880struct cmd_tx_rate_query {
881 __le16 txrate;
882} __attribute__ ((packed));
883
884struct cmd_ds_get_tsf {
885 __le64 tsfvalue;
886} __attribute__ ((packed));
887
888struct cmd_ds_bt_access {
889 __le16 action;
890 __le32 id;
891 u8 addr1[ETH_ALEN];
892 u8 addr2[ETH_ALEN];
893} __attribute__ ((packed));
894
895struct 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
915struct 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
925struct 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
935struct 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 */
15struct 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 */
49struct 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
88struct cmd_header {
89 __le16 command;
90 __le16 size;
91 __le16 seqnum;
92 __le16 result;
93} __attribute__ ((packed));
94
95struct 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. */
109struct 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 */
117struct lbs_offset_value {
118 u32 offset;
119 u32 value;
120} __attribute__ ((packed));
121
122/* Define general data structure */
123/* cmd_DS_GEN */
124struct 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 */
139struct 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
174struct 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 */
192struct 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
205struct 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
213struct 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
231struct cmd_ds_mac_control {
232 struct cmd_header hdr;
233 __le16 action;
234 u16 reserved;
235} __attribute__ ((packed));
236
237struct 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
244struct 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
252struct 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
260struct cmd_ds_802_11_deauthenticate {
261 struct cmd_header hdr;
262
263 u8 macaddr[ETH_ALEN];
264 __le16 reasoncode;
265} __attribute__ ((packed));
266
267struct 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
278struct 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
287struct 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
301struct 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
310struct 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
330struct 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
339struct cmd_ds_mac_reg_map {
340 __le16 buffersize;
341 u8 regmap[128];
342 __le16 reserved;
343} __attribute__ ((packed));
344
345struct cmd_ds_bbp_reg_map {
346 __le16 buffersize;
347 u8 regmap[128];
348 __le16 reserved;
349} __attribute__ ((packed));
350
351struct cmd_ds_rf_reg_map {
352 __le16 buffersize;
353 u8 regmap[64];
354 __le16 reserved;
355} __attribute__ ((packed));
356
357struct cmd_ds_mac_reg_access {
358 __le16 action;
359 __le16 offset;
360 __le32 value;
361} __attribute__ ((packed));
362
363struct cmd_ds_bbp_reg_access {
364 __le16 action;
365 __le16 offset;
366 u8 value;
367 u8 reserved[3];
368} __attribute__ ((packed));
369
370struct cmd_ds_rf_reg_access {
371 __le16 action;
372 __le16 offset;
373 u8 value;
374 u8 reserved[3];
375} __attribute__ ((packed));
376
377struct cmd_ds_802_11_radio_control {
378 struct cmd_header hdr;
379
380 __le16 action;
381 __le16 control;
382} __attribute__ ((packed));
383
384struct cmd_ds_802_11_beacon_control {
385 __le16 action;
386 __le16 beacon_enable;
387 __le16 beacon_period;
388} __attribute__ ((packed));
389
390struct 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
415struct 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
425struct 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
435struct 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
444struct cmd_ds_802_11_rssi_rsp {
445 __le16 SNR;
446 __le16 noisefloor;
447 __le16 avgSNR;
448 __le16 avgnoisefloor;
449} __attribute__ ((packed));
450
451struct cmd_ds_802_11_mac_address {
452 struct cmd_header hdr;
453
454 __le16 action;
455 u8 macadd[ETH_ALEN];
456} __attribute__ ((packed));
457
458struct 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
467struct 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
475struct cmd_ds_802_11_monitor_mode {
476 __le16 action;
477 __le16 mode;
478} __attribute__ ((packed));
479
480struct cmd_ds_set_boot2_ver {
481 struct cmd_header hdr;
482
483 __le16 action;
484 __le16 version;
485} __attribute__ ((packed));
486
487struct cmd_ds_802_11_fw_wake_method {
488 struct cmd_header hdr;
489
490 __le16 action;
491 __le16 method;
492} __attribute__ ((packed));
493
494struct cmd_ds_802_11_sleep_period {
495 struct cmd_header hdr;
496
497 __le16 action;
498 __le16 period;
499} __attribute__ ((packed));
500
501struct 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
509struct 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
519struct 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
527struct 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
534struct 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
551struct 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
558struct 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
579struct 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
587struct cmd_ds_802_11_ad_hoc_stop {
588 struct cmd_header hdr;
589} __attribute__ ((packed));
590
591struct cmd_ds_802_11_enable_rsn {
592 struct cmd_header hdr;
593
594 __le16 action;
595 __le16 enable;
596} __attribute__ ((packed));
597
598struct 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
620struct 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
630struct 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
638struct 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
648struct 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
655struct 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
665struct 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
677struct 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
688struct cmd_ds_802_11_led_ctrl {
689 __le16 action;
690 __le16 numled;
691 u8 data[256];
692} __attribute__ ((packed));
693
694struct 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
708struct cmd_tx_rate_query {
709 __le16 txrate;
710} __attribute__ ((packed));
711
712struct cmd_ds_get_tsf {
713 __le64 tsfvalue;
714} __attribute__ ((packed));
715
716struct cmd_ds_bt_access {
717 __le16 action;
718 __le32 id;
719 u8 addr1[ETH_ALEN];
720 u8 addr2[ETH_ALEN];
721} __attribute__ ((packed));
722
723struct 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
744struct 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
755struct 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
765struct 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 @@
48MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>"); 49MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>");
49MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards"); 50MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards");
50MODULE_LICENSE("GPL"); 51MODULE_LICENSE("GPL");
52MODULE_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
799static 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
796static int if_cs_probe(struct pcmcia_device *p_dev) 823static 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};
103MODULE_FIRMWARE("sd8385_helper.bin");
104MODULE_FIRMWARE("sd8385.bin");
105MODULE_FIRMWARE("sd8686_helper.bin");
106MODULE_FIRMWARE("sd8686.bin");
107MODULE_FIRMWARE("sd8688_helper.bin");
108MODULE_FIRMWARE("sd8688.bin");
102 109
103struct if_sdio_packet { 110struct 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
841static 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
858static 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
875static 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
35struct if_spi_packet {
36 struct list_head list;
37 u16 blen;
38 u8 buffer[0] __attribute__((aligned(4)));
39};
40
41struct if_spi_card { 37struct 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
80static void free_if_spi_card(struct if_spi_card *card) 67static 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. */
778static 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
804out:
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 */
812static void if_spi_e2h(struct if_spi_card *card) 751static 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);
988out:
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}
907MODULE_FIRMWARE("libertas/gspi8385_hlp.bin");
908MODULE_FIRMWARE("libertas/gspi8385.bin");
909MODULE_FIRMWARE("libertas/gspi8686_hlp.bin");
910MODULE_FIRMWARE("libertas/gspi8686.bin");
1029 911
1030static int __devinit if_spi_probe(struct spi_device *spi) 912static 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 @@
28static char *lbs_fw_name = "usb8388.bin"; 29static char *lbs_fw_name = "usb8388.bin";
29module_param_named(fw_name, lbs_fw_name, charp, 0644); 30module_param_named(fw_name, lbs_fw_name, charp, 0644);
30 31
32MODULE_FIRMWARE("usb8388.bin");
33
31static struct usb_device_id if_usb_table[] = { 34static 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);
43struct cmd_confirm_sleep confirm_sleep; 46struct 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 */
54static 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 */
69static 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 */
86static 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 */
92static 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 */
100static 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 */
120struct 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 */
129static 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 */
168u8 lbs_bg_rates[MAX_RATES] =
169 { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
1700x00, 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 */
222static 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 */
241static 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 */
263static 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 */
286static 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
312static int lbs_add_rtap(struct lbs_private *priv); 99static int lbs_add_rtap(struct lbs_private *priv);
313static void lbs_remove_rtap(struct lbs_private *priv); 100static void lbs_remove_rtap(struct lbs_private *priv);
314static int lbs_add_mesh(struct lbs_private *priv);
315static 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,
378static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set ); 163static 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 */
383static 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 */
393static 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 */
422static 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 */
428static 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 */
434static DEVICE_ATTR(prb_rsp_limit, 0644, lbs_prb_rsp_limit_get,
435 lbs_prb_rsp_limit_set);
436
437static struct attribute *lbs_mesh_sysfs_entries[] = {
438 &dev_attr_anycast_mask.attr,
439 &dev_attr_prb_rsp_limit.attr,
440 NULL,
441};
442
443static 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 */
495static 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}
583EXPORT_SYMBOL_GPL(lbs_host_to_card_done); 270EXPORT_SYMBOL_GPL(lbs_host_to_card_done);
584 271
585static int lbs_set_mac_address(struct net_device *dev, void *addr) 272int 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
719static void lbs_set_multicast_list(struct net_device *dev) 410void 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 */
1032static void command_timer_fn(unsigned long data) 723static 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
1053static 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 */
748static 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
774int 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
788int 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
1065static int lbs_init_adapter(struct lbs_private *priv) 800static 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 */
1169struct lbs_private *lbs_add_card(void *card, struct device *dmdev) 907struct 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
1231err_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
1236done: 992done:
@@ -1243,7 +999,6 @@ EXPORT_SYMBOL_GPL(lbs_add_card);
1243void lbs_remove_card(struct lbs_private *priv) 999void 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)
1286EXPORT_SYMBOL_GPL(lbs_remove_card); 1045EXPORT_SYMBOL_GPL(lbs_remove_card);
1287 1046
1288 1047
1048static 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
1289int lbs_start_card(struct lbs_private *priv) 1059int 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:
1420EXPORT_SYMBOL_GPL(lbs_stop_card); 1152EXPORT_SYMBOL_GPL(lbs_stop_card);
1421 1153
1422 1154
1423static 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 */
1437static 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
1481err_unregister:
1482 unregister_netdev(mesh_dev);
1483
1484err_free:
1485 free_netdev(mesh_dev);
1486
1487done:
1488 lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
1489 return ret;
1490}
1491
1492static 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 */
1521struct 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
1543int 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++;
1569out:
1570 lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
1571 return ret;
1572}
1573
1574void lbs_queue_event(struct lbs_private *priv, u32 event) 1155void 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 */
25static 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 */
44static 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 */
66static 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 */
89static 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 */
118static 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 */
128static 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 */
157static 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 */
163static 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 */
169static DEVICE_ATTR(prb_rsp_limit, 0644, lbs_prb_rsp_limit_get,
170 lbs_prb_rsp_limit_set);
171
172static struct attribute *lbs_mesh_sysfs_entries[] = {
173 &dev_attr_anycast_mask.attr,
174 &dev_attr_prb_rsp_limit.attr,
175 NULL,
176};
177
178static 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 */
192int 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
258int 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 */
281static 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 */
308static 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
335static 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 */
349int 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
393err_unregister:
394 unregister_netdev(mesh_dev);
395
396err_free:
397 free_netdev(mesh_dev);
398
399done:
400 lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
401 return ret;
402}
403
404void 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 */
428struct 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
444void 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
460int 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
500int 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
522int 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
541static 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
571int 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 */
589int 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
635static 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 */
657static 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 */
674static 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 */
700static 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 */
717static 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 */
752static 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 */
769static 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 */
795static 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 */
824static 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 */
866static 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 */
883static 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 */
920static 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 */
937static 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 */
974static 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 */
991static 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
1026static DEVICE_ATTR(bootflag, 0644, bootflag_get, bootflag_set);
1027static DEVICE_ATTR(boottime, 0644, boottime_get, boottime_set);
1028static DEVICE_ATTR(channel, 0644, channel_get, channel_set);
1029static DEVICE_ATTR(mesh_id, 0644, mesh_id_get, mesh_id_set);
1030static DEVICE_ATTR(protocol_id, 0644, protocol_id_get, protocol_id_set);
1031static DEVICE_ATTR(metric_id, 0644, metric_id_get, metric_id_set);
1032static DEVICE_ATTR(capability, 0644, capability_get, capability_set);
1033
1034static struct attribute *boot_opts_attrs[] = {
1035 &dev_attr_bootflag.attr,
1036 &dev_attr_boottime.attr,
1037 &dev_attr_channel.attr,
1038 NULL
1039};
1040
1041static struct attribute_group boot_opts_group = {
1042 .name = "boot_options",
1043 .attrs = boot_opts_attrs,
1044};
1045
1046static 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
1054static struct attribute_group mesh_ie_group = {
1055 .name = "mesh_ie",
1056 .attrs = mesh_ie_attrs,
1057};
1058
1059void 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
1066void 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
1078static 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
1089void 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
1127int 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
1137void 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 */
15struct 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
27struct net_device;
28struct lbs_private;
29
30int lbs_init_mesh(struct lbs_private *priv);
31int lbs_deinit_mesh(struct lbs_private *priv);
32
33int lbs_add_mesh(struct lbs_private *priv);
34void lbs_remove_mesh(struct lbs_private *priv);
35
36
37/* Sending / Receiving */
38
39struct rxpd;
40struct txpd;
41
42struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
43 struct net_device *dev, struct rxpd *rxpd);
44void lbs_mesh_set_txpd(struct lbs_private *priv,
45 struct net_device *dev, struct txpd *txpd);
46
47
48/* Command handling */
49
50struct cmd_ds_command;
51struct cmd_ds_mesh_access;
52struct cmd_ds_mesh_config;
53
54int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
55 u16 cmd_action, void *pdata_buf);
56int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
57 u16 cmd_action, void *pdata_buf);
58int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
59 struct cmd_ds_mesh_access *cmd);
60int lbs_mesh_config_send(struct lbs_private *priv,
61 struct cmd_ds_mesh_config *cmd,
62 uint16_t action, uint16_t type);
63int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
64
65
66
67/* Persistent configuration */
68
69void lbs_persist_config_init(struct net_device *net);
70void lbs_persist_config_remove(struct net_device *net);
71
72
73/* WEXT handler */
74
75extern struct iw_handler_def mesh_handler_def;
76
77
78/* Ethtool statistics */
79
80struct ethtool_stats;
81
82void lbs_mesh_ethtool_get_stats(struct net_device *dev,
83 struct ethtool_stats *stats, uint64_t *data);
84int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset);
85void 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
18static 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 */
40static 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 */
57static 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 */
83static 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 */
100static 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 */
135static 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 */
152static 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 */
178static 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 */
207static 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 */
249static 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 */
266static 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 */
303static 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 */
320static 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 */
357static 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 */
374static 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
409static DEVICE_ATTR(bootflag, 0644, bootflag_get, bootflag_set);
410static DEVICE_ATTR(boottime, 0644, boottime_get, boottime_set);
411static DEVICE_ATTR(channel, 0644, channel_get, channel_set);
412static DEVICE_ATTR(mesh_id, 0644, mesh_id_get, mesh_id_set);
413static DEVICE_ATTR(protocol_id, 0644, protocol_id_get, protocol_id_set);
414static DEVICE_ATTR(metric_id, 0644, metric_id_get, metric_id_set);
415static DEVICE_ATTR(capability, 0644, capability_get, capability_set);
416
417static struct attribute *boot_opts_attrs[] = {
418 &dev_attr_bootflag.attr,
419 &dev_attr_boottime.attr,
420 &dev_attr_channel.attr,
421 NULL
422};
423
424static struct attribute_group boot_opts_group = {
425 .name = "boot_options",
426 .attrs = boot_opts_attrs,
427};
428
429static 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
437static struct attribute_group mesh_ie_group = {
438 .name = "mesh_ie",
439 .attrs = mesh_ie_attrs,
440};
441
442void 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
449void 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 */
140static 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 */
155static 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 */
172static 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 */
178static 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 */
186static 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 */
206struct 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 */
215static 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 */
254static 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
276int 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++;
302out:
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
469out: 635out:
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 1206out:
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
12struct lbs_private;
13
12#define MAX_NETWORK_COUNT 128 14#define MAX_NETWORK_COUNT 128
13 15
16/** Chan-freq-TxPower mapping table*/
17struct 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*/
29struct 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
19int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len); 47int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
20 48
49int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
50
21int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, 51int 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}
209EXPORT_SYMBOL_GPL(lbs_send_tx_feedback); 204EXPORT_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
11struct ieee_ie_header { 11struct 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
253struct mrvl_meshie { 253struct 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
49void 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
58static 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 */
89void 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
248static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, 303static 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
272static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, 328static 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
372static int mesh_wlan_get_mode(struct net_device *dev, 429static 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
384static int lbs_get_txpow(struct net_device *dev, 442static 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
703out:
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");
867out: 943out:
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
942static int lbs_mesh_set_freq(struct net_device *dev, 1019static 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
994static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, 1072static 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
2041static int lbs_mesh_get_essid(struct net_device *dev, 2119static 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};
2279struct 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
2201static const iw_handler mesh_wlan_handler[] = { 2286static 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};
2258struct 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
2264struct iw_handler_def mesh_handler_def = { 2344struct 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
7void lbs_send_disconnect_notification(struct lbs_private *priv);
8void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
9
10struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
11 struct lbs_private *priv,
12 u8 band,
13 u16 channel);
14
7extern struct iw_handler_def lbs_handler_def; 15extern struct iw_handler_def lbs_handler_def;
8extern struct iw_handler_def mesh_handler_def;
9 16
10#endif 17#endif