]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/net/wireless/libertas/11d.c
[PATCH] libertas: make debug configurable
[mirror_ubuntu-artful-kernel.git] / drivers / net / wireless / libertas / 11d.c
CommitLineData
876c9d3a
MT
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 wlan_region_2_code(u8 * region)
47{
48 u8 i;
49 u8 size = sizeof(region_code_mapping)/
50 sizeof(struct region_code_mapping);
51
52 for (i = 0; region[i] && i < COUNTRY_CODE_LEN; i++)
53 region[i] = toupper(region[i]);
54
55 for (i = 0; i < size; i++) {
56 if (!memcmp(region, region_code_mapping[i].region,
57 COUNTRY_CODE_LEN))
58 return (region_code_mapping[i].code);
59 }
60
61 /* default is US */
62 return (region_code_mapping[0].code);
63}
64
65static u8 *wlan_code_2_region(u8 code)
66{
67 u8 i;
68 u8 size = sizeof(region_code_mapping)
69 / sizeof(struct region_code_mapping);
70 for (i = 0; i < size; i++) {
71 if (region_code_mapping[i].code == code)
72 return (region_code_mapping[i].region);
73 }
74 /* default is US */
75 return (region_code_mapping[0].region);
76}
77
78/**
79 * @brief This function finds the nrchan-th chan after the firstchan
80 * @param band band
81 * @param firstchan first channel number
82 * @param nrchan number of channels
83 * @return the nrchan-th chan number
84*/
85static u8 wlan_get_chan_11d(u8 band, u8 firstchan, u8 nrchan, u8 * chan)
86/*find the nrchan-th chan after the firstchan*/
87{
88 u8 i;
89 struct chan_freq_power *cfp;
90 u8 cfp_no;
91
92 cfp = channel_freq_power_UN_BG;
93 cfp_no = sizeof(channel_freq_power_UN_BG) /
94 sizeof(struct chan_freq_power);
95
96 for (i = 0; i < cfp_no; i++) {
97 if ((cfp + i)->channel == firstchan) {
9012b28a 98 lbs_deb_11d("firstchan found\n");
876c9d3a
MT
99 break;
100 }
101 }
102
103 if (i < cfp_no) {
104 /*if beyond the boundary */
105 if (i + nrchan < cfp_no) {
106 *chan = (cfp + i + nrchan)->channel;
107 return 1;
108 }
109 }
110
111 return 0;
112}
113
114/**
115 * @brief This function Checks if chan txpwr is learned from AP/IBSS
116 * @param chan chan number
117 * @param parsed_region_chan pointer to parsed_region_chan_11d
118 * @return TRUE; FALSE
119*/
120static u8 wlan_channel_known_11d(u8 chan,
121 struct parsed_region_chan_11d * parsed_region_chan)
122{
123 struct chan_power_11d *chanpwr = parsed_region_chan->chanpwr;
124 u8 nr_chan = parsed_region_chan->nr_chan;
125 u8 i = 0;
126
127 lbs_dbg_hex("11D:parsed_region_chan:", (char *)chanpwr,
128 sizeof(struct chan_power_11d) * nr_chan);
129
130 for (i = 0; i < nr_chan; i++) {
131 if (chan == chanpwr[i].chan) {
9012b28a 132 lbs_deb_11d("11D: Found Chan:%d\n", chan);
876c9d3a
MT
133 return 1;
134 }
135 }
136
9012b28a 137 lbs_deb_11d("11D: Not Find Chan:%d\n", chan);
876c9d3a
MT
138 return 0;
139}
140
141u32 libertas_chan_2_freq(u8 chan, u8 band)
142{
143 struct chan_freq_power *cf;
144 u16 cnt;
145 u16 i;
146 u32 freq = 0;
147
148 cf = channel_freq_power_UN_BG;
149 cnt =
150 sizeof(channel_freq_power_UN_BG) /
151 sizeof(struct chan_freq_power);
152
153 for (i = 0; i < cnt; i++) {
154 if (chan == cf[i].channel)
155 freq = cf[i].freq;
156 }
157
158 return freq;
159}
160
161static int generate_domain_info_11d(struct parsed_region_chan_11d
162 *parsed_region_chan,
163 struct wlan_802_11d_domain_reg * domaininfo)
164{
165 u8 nr_subband = 0;
166
167 u8 nr_chan = parsed_region_chan->nr_chan;
168 u8 nr_parsedchan = 0;
169
170 u8 firstchan = 0, nextchan = 0, maxpwr = 0;
171
172 u8 i, flag = 0;
173
174 memcpy(domaininfo->countrycode, parsed_region_chan->countrycode,
175 COUNTRY_CODE_LEN);
176
9012b28a 177 lbs_deb_11d("11D:nrchan=%d\n", nr_chan);
876c9d3a
MT
178 lbs_dbg_hex("11D:parsed_region_chan:", (char *)parsed_region_chan,
179 sizeof(struct parsed_region_chan_11d));
180
181 for (i = 0; i < nr_chan; i++) {
182 if (!flag) {
183 flag = 1;
184 nextchan = firstchan =
185 parsed_region_chan->chanpwr[i].chan;
186 maxpwr = parsed_region_chan->chanpwr[i].pwr;
187 nr_parsedchan = 1;
188 continue;
189 }
190
191 if (parsed_region_chan->chanpwr[i].chan == nextchan + 1 &&
192 parsed_region_chan->chanpwr[i].pwr == maxpwr) {
193 nextchan++;
194 nr_parsedchan++;
195 } else {
196 domaininfo->subband[nr_subband].firstchan = firstchan;
197 domaininfo->subband[nr_subband].nrchan =
198 nr_parsedchan;
199 domaininfo->subband[nr_subband].maxtxpwr = maxpwr;
200 nr_subband++;
201 nextchan = firstchan =
202 parsed_region_chan->chanpwr[i].chan;
203 maxpwr = parsed_region_chan->chanpwr[i].pwr;
204 }
205 }
206
207 if (flag) {
208 domaininfo->subband[nr_subband].firstchan = firstchan;
209 domaininfo->subband[nr_subband].nrchan = nr_parsedchan;
210 domaininfo->subband[nr_subband].maxtxpwr = maxpwr;
211 nr_subband++;
212 }
213 domaininfo->nr_subband = nr_subband;
214
9012b28a 215 lbs_deb_11d("nr_subband=%x\n", domaininfo->nr_subband);
876c9d3a
MT
216 lbs_dbg_hex("11D:domaininfo:", (char *)domaininfo,
217 COUNTRY_CODE_LEN + 1 +
218 sizeof(struct ieeetypes_subbandset) * nr_subband);
219 return 0;
220}
221
222/**
223 * @brief This function generates parsed_region_chan from Domain Info learned from AP/IBSS
224 * @param region_chan pointer to struct region_channel
225 * @param *parsed_region_chan pointer to parsed_region_chan_11d
226 * @return N/A
227*/
228static void wlan_generate_parsed_region_chan_11d(struct region_channel * region_chan,
229 struct parsed_region_chan_11d *
230 parsed_region_chan)
231{
232 u8 i;
233 struct chan_freq_power *cfp;
234
235 if (region_chan == NULL) {
9012b28a 236 lbs_deb_11d("11D: region_chan is NULL\n");
876c9d3a
MT
237 return;
238 }
239
240 cfp = region_chan->CFP;
241 if (cfp == NULL) {
9012b28a 242 lbs_deb_11d("11D: cfp equal NULL \n");
876c9d3a
MT
243 return;
244 }
245
246 parsed_region_chan->band = region_chan->band;
247 parsed_region_chan->region = region_chan->region;
248 memcpy(parsed_region_chan->countrycode,
249 wlan_code_2_region(region_chan->region), COUNTRY_CODE_LEN);
250
9012b28a 251 lbs_deb_11d("11D: region[0x%x] band[%d]\n", parsed_region_chan->region,
876c9d3a
MT
252 parsed_region_chan->band);
253
254 for (i = 0; i < region_chan->nrcfp; i++, cfp++) {
255 parsed_region_chan->chanpwr[i].chan = cfp->channel;
256 parsed_region_chan->chanpwr[i].pwr = cfp->maxtxpower;
9012b28a 257 lbs_deb_11d("11D: Chan[%d] Pwr[%d]\n",
876c9d3a
MT
258 parsed_region_chan->chanpwr[i].chan,
259 parsed_region_chan->chanpwr[i].pwr);
260 }
261 parsed_region_chan->nr_chan = region_chan->nrcfp;
262
9012b28a 263 lbs_deb_11d("11D: nrchan[%d]\n", parsed_region_chan->nr_chan);
876c9d3a
MT
264
265 return;
266}
267
268/**
269 * @brief generate parsed_region_chan from Domain Info learned from AP/IBSS
270 * @param region region ID
271 * @param band band
272 * @param chan chan
273 * @return TRUE;FALSE
274*/
275static u8 wlan_region_chan_supported_11d(u8 region, u8 band, u8 chan)
276{
277 struct chan_freq_power *cfp;
278 int cfp_no;
279 u8 idx;
9012b28a 280 int ret = 0;
876c9d3a 281
9012b28a 282 lbs_deb_enter(LBS_DEB_11D);
876c9d3a
MT
283
284 cfp = libertas_get_region_cfp_table(region, band, &cfp_no);
285 if (cfp == NULL)
286 return 0;
287
288 for (idx = 0; idx < cfp_no; idx++) {
289 if (chan == (cfp + idx)->channel) {
290 /* If Mrvl Chip Supported? */
291 if ((cfp + idx)->unsupported) {
9012b28a 292 ret = 0;
876c9d3a 293 } else {
9012b28a 294 ret = 1;
876c9d3a 295 }
9012b28a 296 goto done;
876c9d3a
MT
297 }
298 }
299
300 /*chan is not in the region table */
9012b28a
HS
301
302done:
303 lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
304 return ret;
876c9d3a
MT
305}
306
307/**
308 * @brief This function checks if chan txpwr is learned from AP/IBSS
309 * @param chan chan number
310 * @param parsed_region_chan pointer to parsed_region_chan_11d
311 * @return 0
312*/
313static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
314 countryinfo,
315 u8 band,
316 struct parsed_region_chan_11d *
317 parsed_region_chan)
318{
319 u8 nr_subband, nrchan;
320 u8 lastchan, firstchan;
321 u8 region;
322 u8 curchan = 0;
323
324 u8 idx = 0; /*chan index in parsed_region_chan */
325
326 u8 j, i;
327
9012b28a 328 lbs_deb_enter(LBS_DEB_11D);
876c9d3a
MT
329
330 /*validation Rules:
331 1. valid region Code
332 2. First Chan increment
333 3. channel range no overlap
334 4. channel is valid?
335 5. channel is supported by region?
336 6. Others
337 */
338
339 lbs_dbg_hex("CountryInfo:", (u8 *) countryinfo, 30);
340
341 if ((*(countryinfo->countrycode)) == 0
342 || (countryinfo->len <= COUNTRY_CODE_LEN)) {
343 /* No region Info or Wrong region info: treat as No 11D info */
9012b28a 344 goto done;
876c9d3a
MT
345 }
346
347 /*Step1: check region_code */
348 parsed_region_chan->region = region =
349 wlan_region_2_code(countryinfo->countrycode);
350
9012b28a 351 lbs_deb_11d("regioncode=%x\n", (u8) parsed_region_chan->region);
876c9d3a
MT
352 lbs_dbg_hex("CountryCode:", (char *)countryinfo->countrycode,
353 COUNTRY_CODE_LEN);
354
355 parsed_region_chan->band = band;
356
357 memcpy(parsed_region_chan->countrycode, countryinfo->countrycode,
358 COUNTRY_CODE_LEN);
359
360 nr_subband = (countryinfo->len - COUNTRY_CODE_LEN) /
361 sizeof(struct ieeetypes_subbandset);
362
363 for (j = 0, lastchan = 0; j < nr_subband; j++) {
364
365 if (countryinfo->subband[j].firstchan <= lastchan) {
366 /*Step2&3. Check First Chan Num increment and no overlap */
9012b28a 367 lbs_deb_11d("11D: Chan[%d>%d] Overlap\n",
876c9d3a
MT
368 countryinfo->subband[j].firstchan, lastchan);
369 continue;
370 }
371
372 firstchan = countryinfo->subband[j].firstchan;
373 nrchan = countryinfo->subband[j].nrchan;
374
375 for (i = 0; idx < MAX_NO_OF_CHAN && i < nrchan; i++) {
376 /*step4: channel is supported? */
377
378 if (!wlan_get_chan_11d(band, firstchan, i, &curchan)) {
379 /* Chan is not found in UN table */
9012b28a 380 lbs_deb_11d("chan is not supported: %d \n", i);
876c9d3a
MT
381 break;
382 }
383
384 lastchan = curchan;
385
386 if (wlan_region_chan_supported_11d
387 (region, band, curchan)) {
388 /*step5: Check if curchan is supported by mrvl in region */
389 parsed_region_chan->chanpwr[idx].chan = curchan;
390 parsed_region_chan->chanpwr[idx].pwr =
391 countryinfo->subband[j].maxtxpwr;
392 idx++;
393 } else {
394 /*not supported and ignore the chan */
9012b28a 395 lbs_deb_11d(
876c9d3a
MT
396 "11D:i[%d] chan[%d] unsupported in region[%x] band[%d]\n",
397 i, curchan, region, band);
398 }
399 }
400
401 /*Step6: Add other checking if any */
402
403 }
404
405 parsed_region_chan->nr_chan = idx;
406
9012b28a 407 lbs_deb_11d("nrchan=%x\n", parsed_region_chan->nr_chan);
876c9d3a
MT
408 lbs_dbg_hex("11D:parsed_region_chan:", (u8 *) parsed_region_chan,
409 2 + COUNTRY_CODE_LEN + sizeof(struct parsed_region_chan_11d) * idx);
410
9012b28a
HS
411done:
412 lbs_deb_enter(LBS_DEB_11D);
876c9d3a
MT
413 return 0;
414}
415
416/**
417 * @brief This function calculates the scan type for channels
418 * @param chan chan number
419 * @param parsed_region_chan pointer to parsed_region_chan_11d
420 * @return PASSIVE if chan is unknown; ACTIVE if chan is known
421*/
422u8 libertas_get_scan_type_11d(u8 chan,
423 struct parsed_region_chan_11d * parsed_region_chan)
424{
425 u8 scan_type = cmd_scan_type_passive;
426
9012b28a 427 lbs_deb_enter(LBS_DEB_11D);
876c9d3a
MT
428
429 if (wlan_channel_known_11d(chan, parsed_region_chan)) {
9012b28a 430 lbs_deb_11d("11D: Found and do Active Scan\n");
876c9d3a
MT
431 scan_type = cmd_scan_type_active;
432 } else {
9012b28a 433 lbs_deb_11d("11D: Not Find and do Passive Scan\n");
876c9d3a
MT
434 }
435
9012b28a 436 lbs_deb_leave_args(LBS_DEB_11D, "ret scan_type %d", scan_type);
876c9d3a
MT
437 return scan_type;
438
439}
440
441void libertas_init_11d(wlan_private * priv)
442{
443 priv->adapter->enable11d = 0;
444 memset(&(priv->adapter->parsed_region_chan), 0,
445 sizeof(struct parsed_region_chan_11d));
446 return;
447}
448
449static int wlan_enable_11d(wlan_private * priv, u8 flag)
450{
451 int ret;
452
453 priv->adapter->enable11d = flag;
454
455 /* send cmd to FW to enable/disable 11D function in FW */
456 ret = libertas_prepare_and_send_command(priv,
457 cmd_802_11_snmp_mib,
458 cmd_act_set,
459 cmd_option_waitforrsp,
460 OID_802_11D_ENABLE,
461 &priv->adapter->enable11d);
462 if (ret)
9012b28a 463 lbs_deb_11d("11D: Fail to enable 11D \n");
876c9d3a
MT
464
465 return 0;
466}
467
468/**
469 * @brief This function sets DOMAIN INFO to FW
470 * @param priv pointer to wlan_private
471 * @return 0; -1
472*/
473static int set_domain_info_11d(wlan_private * priv)
474{
475 int ret;
476
477 if (!priv->adapter->enable11d) {
9012b28a 478 lbs_deb_11d("11D: dnld domain Info with 11d disabled\n");
876c9d3a
MT
479 return 0;
480 }
481
482 ret = libertas_prepare_and_send_command(priv, cmd_802_11d_domain_info,
483 cmd_act_set,
484 cmd_option_waitforrsp, 0, NULL);
485 if (ret)
9012b28a 486 lbs_deb_11d("11D: Fail to dnld domain Info\n");
876c9d3a
MT
487
488 return ret;
489}
490
491/**
492 * @brief This function setups scan channels
493 * @param priv pointer to wlan_private
494 * @param band band
495 * @return 0
496*/
497int libertas_set_universaltable(wlan_private * priv, u8 band)
498{
499 wlan_adapter *adapter = priv->adapter;
500 u16 size = sizeof(struct chan_freq_power);
501 u16 i = 0;
502
503 memset(adapter->universal_channel, 0,
504 sizeof(adapter->universal_channel));
505
506 adapter->universal_channel[i].nrcfp =
507 sizeof(channel_freq_power_UN_BG) / size;
9012b28a 508 lbs_deb_11d("11D: BG-band nrcfp=%d\n",
876c9d3a
MT
509 adapter->universal_channel[i].nrcfp);
510
511 adapter->universal_channel[i].CFP = channel_freq_power_UN_BG;
512 adapter->universal_channel[i].valid = 1;
513 adapter->universal_channel[i].region = UNIVERSAL_REGION_CODE;
514 adapter->universal_channel[i].band = band;
515 i++;
516
517 return 0;
518}
519
520/**
521 * @brief This function implements command CMD_802_11D_DOMAIN_INFO
522 * @param priv pointer to wlan_private
523 * @param cmd pointer to cmd buffer
524 * @param cmdno cmd ID
525 * @param cmdOption cmd action
526 * @return 0
527*/
528int libertas_cmd_802_11d_domain_info(wlan_private * priv,
529 struct cmd_ds_command *cmd, u16 cmdno,
530 u16 cmdoption)
531{
532 struct cmd_ds_802_11d_domain_info *pdomaininfo =
533 &cmd->params.domaininfo;
534 struct mrvlietypes_domainparamset *domain = &pdomaininfo->domain;
535 wlan_adapter *adapter = priv->adapter;
536 u8 nr_subband = adapter->domainreg.nr_subband;
537
9012b28a 538 lbs_deb_enter(LBS_DEB_11D);
876c9d3a 539
9012b28a 540 lbs_deb_11d("nr_subband=%x\n", nr_subband);
876c9d3a
MT
541
542 cmd->command = cpu_to_le16(cmdno);
543 pdomaininfo->action = cpu_to_le16(cmdoption);
544 if (cmdoption == cmd_act_get) {
545 cmd->size =
546 cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
547 lbs_dbg_hex("11D: 802_11D_DOMAIN_INFO:", (u8 *) cmd,
548 (int)(cmd->size));
9012b28a 549 goto done;
876c9d3a
MT
550 }
551
552 domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
553 memcpy(domain->countrycode, adapter->domainreg.countrycode,
554 sizeof(domain->countrycode));
555
556 domain->header.len =
557 cpu_to_le16(nr_subband * sizeof(struct ieeetypes_subbandset) +
558 sizeof(domain->countrycode));
559
560 if (nr_subband) {
561 memcpy(domain->subband, adapter->domainreg.subband,
562 nr_subband * sizeof(struct ieeetypes_subbandset));
563
564 cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
565 domain->header.len +
566 sizeof(struct mrvlietypesheader) +
567 S_DS_GEN);
568 } else {
569 cmd->size =
570 cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
571 }
572
573 lbs_dbg_hex("11D:802_11D_DOMAIN_INFO:", (u8 *) cmd, (int)(cmd->size));
574
9012b28a
HS
575done:
576 lbs_deb_enter(LBS_DEB_11D);
876c9d3a
MT
577 return 0;
578}
579
580/**
581 * @brief This function implements private cmd: enable/disable 11D
582 * @param priv pointer to wlan_private
583 * @param wrq pointer to user data
584 * @return 0 or -1
585 */
586int libertas_cmd_enable_11d(wlan_private * priv, struct iwreq *wrq)
587{
588 int data = 0;
589 int *val;
590
9012b28a 591 lbs_deb_enter(LBS_DEB_11D);
876c9d3a
MT
592 data = SUBCMD_DATA(wrq);
593
9012b28a 594 lbs_deb_11d("enable 11D: %s\n",
876c9d3a
MT
595 (data == 1) ? "enable" : "Disable");
596
597 wlan_enable_11d(priv, data);
598 val = (int *)wrq->u.name;
599 *val = priv->adapter->enable11d;
600
9012b28a 601 lbs_deb_enter(LBS_DEB_11D);
876c9d3a
MT
602 return 0;
603}
604
605/**
606 * @brief This function parses countryinfo from AP and download country info to FW
607 * @param priv pointer to wlan_private
608 * @param resp pointer to command response buffer
609 * @return 0; -1
610 */
611int libertas_ret_802_11d_domain_info(wlan_private * priv,
612 struct cmd_ds_command *resp)
613{
614 struct cmd_ds_802_11d_domain_info
615 *domaininfo = &resp->params.domaininforesp;
616 struct mrvlietypes_domainparamset *domain = &domaininfo->domain;
617 u16 action = le16_to_cpu(domaininfo->action);
618 s16 ret = 0;
619 u8 nr_subband = 0;
620
9012b28a 621 lbs_deb_enter(LBS_DEB_11D);
876c9d3a
MT
622
623 lbs_dbg_hex("11D DOMAIN Info Rsp Data:", (u8 *) resp,
624 (int)le16_to_cpu(resp->size));
625
626 nr_subband = (domain->header.len - 3) / sizeof(struct ieeetypes_subbandset);
627 /* countrycode 3 bytes */
628
9012b28a 629 lbs_deb_11d("11D Domain Info Resp: nr_subband=%d\n", nr_subband);
876c9d3a
MT
630
631 if (nr_subband > MRVDRV_MAX_SUBBAND_802_11D) {
9012b28a 632 lbs_deb_11d("Invalid Numrer of Subband returned!!\n");
876c9d3a
MT
633 return -1;
634 }
635
636 switch (action) {
637 case cmd_act_set: /*Proc Set action */
638 break;
639
640 case cmd_act_get:
641 break;
642 default:
9012b28a 643 lbs_deb_11d("Invalid action:%d\n", domaininfo->action);
876c9d3a
MT
644 ret = -1;
645 break;
646 }
647
9012b28a 648 lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
876c9d3a
MT
649 return ret;
650}
651
652/**
653 * @brief This function parses countryinfo from AP and download country info to FW
654 * @param priv pointer to wlan_private
655 * @return 0; -1
656 */
657int libertas_parse_dnld_countryinfo_11d(wlan_private * priv)
658{
659 int ret;
660 wlan_adapter *adapter = priv->adapter;
661
9012b28a 662 lbs_deb_enter(LBS_DEB_11D);
876c9d3a
MT
663 if (priv->adapter->enable11d) {
664 memset(&adapter->parsed_region_chan, 0,
665 sizeof(struct parsed_region_chan_11d));
666 ret = parse_domain_info_11d(&adapter->pattemptedbssdesc->
667 countryinfo, 0,
668 &adapter->parsed_region_chan);
669
670 if (ret == -1) {
9012b28a
HS
671 lbs_deb_11d("11D: Err Parse domain_info from AP..\n");
672 goto done;
876c9d3a
MT
673 }
674
675 memset(&adapter->domainreg, 0,
676 sizeof(struct wlan_802_11d_domain_reg));
677 generate_domain_info_11d(&adapter->parsed_region_chan,
678 &adapter->domainreg);
679
680 ret = set_domain_info_11d(priv);
681
682 if (ret) {
9012b28a
HS
683 lbs_deb_11d("11D: Err set domainInfo to FW\n");
684 goto done;
876c9d3a
MT
685 }
686 }
9012b28a
HS
687 ret = 0;
688
689done:
690 lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
691 return ret;
876c9d3a
MT
692}
693
694/**
695 * @brief This function generates 11D info from user specified regioncode and download to FW
696 * @param priv pointer to wlan_private
697 * @return 0; -1
698 */
699int libertas_create_dnld_countryinfo_11d(wlan_private * priv)
700{
701 int ret;
702 wlan_adapter *adapter = priv->adapter;
703 struct region_channel *region_chan;
704 u8 j;
705
9012b28a
HS
706 lbs_deb_enter(LBS_DEB_11D);
707 lbs_deb_11d("11D:curbssparams.band[%d]\n", adapter->curbssparams.band);
876c9d3a
MT
708
709 if (priv->adapter->enable11d) {
710 /* update parsed_region_chan_11; dnld domaininf to FW */
711
712 for (j = 0; j < sizeof(adapter->region_channel) /
713 sizeof(adapter->region_channel[0]); j++) {
714 region_chan = &adapter->region_channel[j];
715
9012b28a 716 lbs_deb_11d("11D:[%d] region_chan->band[%d]\n", j,
876c9d3a
MT
717 region_chan->band);
718
719 if (!region_chan || !region_chan->valid
720 || !region_chan->CFP)
721 continue;
722 if (region_chan->band != adapter->curbssparams.band)
723 continue;
724 break;
725 }
726
727 if (j >= sizeof(adapter->region_channel) /
728 sizeof(adapter->region_channel[0])) {
9012b28a 729 lbs_deb_11d("11D:region_chan not found. band[%d]\n",
876c9d3a 730 adapter->curbssparams.band);
9012b28a
HS
731 ret = -1;
732 goto done;
876c9d3a
MT
733 }
734
735 memset(&adapter->parsed_region_chan, 0,
736 sizeof(struct parsed_region_chan_11d));
737 wlan_generate_parsed_region_chan_11d(region_chan,
738 &adapter->
739 parsed_region_chan);
740
741 memset(&adapter->domainreg, 0,
742 sizeof(struct wlan_802_11d_domain_reg));
743 generate_domain_info_11d(&adapter->parsed_region_chan,
744 &adapter->domainreg);
745
746 ret = set_domain_info_11d(priv);
747
748 if (ret) {
9012b28a
HS
749 lbs_deb_11d("11D: Err set domainInfo to FW\n");
750 goto done;
876c9d3a
MT
751 }
752
753 }
9012b28a 754 ret = 0;
876c9d3a 755
9012b28a
HS
756done:
757 lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
758 return ret;
876c9d3a 759}