fix hostapd race condition which breaks wpa with madwifi
[openwrt.git] / package / libertas / src / 11d.c
1 /**
2 * This file contains functions for 802.11D.
3 */
4 #include <linux/ctype.h>
5 #include <linux/kernel.h>
6 #include <linux/wireless.h>
7
8 #include "host.h"
9 #include "decl.h"
10 #include "11d.h"
11 #include "dev.h"
12 #include "wext.h"
13
14 #define TX_PWR_DEFAULT 10
15
16 static struct region_code_mapping region_code_mapping[] = {
17 {"US ", 0x10}, /* US FCC */
18 {"CA ", 0x10}, /* IC Canada */
19 {"SG ", 0x10}, /* Singapore */
20 {"EU ", 0x30}, /* ETSI */
21 {"AU ", 0x30}, /* Australia */
22 {"KR ", 0x30}, /* Republic Of Korea */
23 {"ES ", 0x31}, /* Spain */
24 {"FR ", 0x32}, /* France */
25 {"JP ", 0x40}, /* Japan */
26 };
27
28 /* Following 2 structure defines the supported channels */
29 static struct chan_freq_power channel_freq_power_UN_BG[] = {
30 {1, 2412, TX_PWR_DEFAULT},
31 {2, 2417, TX_PWR_DEFAULT},
32 {3, 2422, TX_PWR_DEFAULT},
33 {4, 2427, TX_PWR_DEFAULT},
34 {5, 2432, TX_PWR_DEFAULT},
35 {6, 2437, TX_PWR_DEFAULT},
36 {7, 2442, TX_PWR_DEFAULT},
37 {8, 2447, TX_PWR_DEFAULT},
38 {9, 2452, TX_PWR_DEFAULT},
39 {10, 2457, TX_PWR_DEFAULT},
40 {11, 2462, TX_PWR_DEFAULT},
41 {12, 2467, TX_PWR_DEFAULT},
42 {13, 2472, TX_PWR_DEFAULT},
43 {14, 2484, TX_PWR_DEFAULT}
44 };
45
46 static u8 lbs_region_2_code(u8 *region)
47 {
48 u8 i;
49 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
65 static u8 *lbs_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 */
85 static u8 lbs_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) {
98 lbs_deb_11d("firstchan found\n");
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 */
120 static u8 lbs_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_deb_hex(LBS_DEB_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) {
132 lbs_deb_11d("found chan %d\n", chan);
133 return 1;
134 }
135 }
136
137 lbs_deb_11d("chan %d not found\n", chan);
138 return 0;
139 }
140
141 u32 lbs_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
161 static int generate_domain_info_11d(struct parsed_region_chan_11d
162 *parsed_region_chan,
163 struct lbs_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
177 lbs_deb_11d("nrchan %d\n", nr_chan);
178 lbs_deb_hex(LBS_DEB_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
215 lbs_deb_11d("nr_subband=%x\n", domaininfo->nr_subband);
216 lbs_deb_hex(LBS_DEB_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 */
228 static void lbs_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) {
236 lbs_deb_11d("region_chan is NULL\n");
237 return;
238 }
239
240 cfp = region_chan->CFP;
241 if (cfp == NULL) {
242 lbs_deb_11d("cfp is NULL \n");
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 lbs_code_2_region(region_chan->region), COUNTRY_CODE_LEN);
250
251 lbs_deb_11d("region 0x%x, band %d\n", parsed_region_chan->region,
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;
257 lbs_deb_11d("chan %d, pwr %d\n",
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
263 lbs_deb_11d("nrchan %d\n", parsed_region_chan->nr_chan);
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 */
275 static u8 lbs_region_chan_supported_11d(u8 region, u8 band, u8 chan)
276 {
277 struct chan_freq_power *cfp;
278 int cfp_no;
279 u8 idx;
280 int ret = 0;
281
282 lbs_deb_enter(LBS_DEB_11D);
283
284 cfp = lbs_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) {
292 ret = 0;
293 } else {
294 ret = 1;
295 }
296 goto done;
297 }
298 }
299
300 /*chan is not in the region table */
301
302 done:
303 lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
304 return ret;
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 */
313 static 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
328 lbs_deb_enter(LBS_DEB_11D);
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_deb_hex(LBS_DEB_11D, "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 */
344 goto done;
345 }
346
347 /*Step1: check region_code */
348 parsed_region_chan->region = region =
349 lbs_region_2_code(countryinfo->countrycode);
350
351 lbs_deb_11d("regioncode=%x\n", (u8) parsed_region_chan->region);
352 lbs_deb_hex(LBS_DEB_11D, "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 */
367 lbs_deb_11d("chan %d>%d, overlap\n",
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 (!lbs_get_chan_11d(band, firstchan, i, &curchan)) {
379 /* Chan is not found in UN table */
380 lbs_deb_11d("chan is not supported: %d \n", i);
381 break;
382 }
383
384 lastchan = curchan;
385
386 if (lbs_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 */
395 lbs_deb_11d(
396 "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
407 lbs_deb_11d("nrchan=%x\n", parsed_region_chan->nr_chan);
408 lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (u8 *) parsed_region_chan,
409 2 + COUNTRY_CODE_LEN + sizeof(struct parsed_region_chan_11d) * idx);
410
411 done:
412 lbs_deb_enter(LBS_DEB_11D);
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 */
422 u8 lbs_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
427 lbs_deb_enter(LBS_DEB_11D);
428
429 if (lbs_channel_known_11d(chan, parsed_region_chan)) {
430 lbs_deb_11d("found, do active scan\n");
431 scan_type = CMD_SCAN_TYPE_ACTIVE;
432 } else {
433 lbs_deb_11d("not found, do passive scan\n");
434 }
435
436 lbs_deb_leave_args(LBS_DEB_11D, "ret scan_type %d", scan_type);
437 return scan_type;
438
439 }
440
441 void lbs_init_11d(struct lbs_private *priv)
442 {
443 priv->enable11d = 0;
444 memset(&(priv->parsed_region_chan), 0,
445 sizeof(struct parsed_region_chan_11d));
446 return;
447 }
448
449 /**
450 * @brief This function sets DOMAIN INFO to FW
451 * @param priv pointer to struct lbs_private
452 * @return 0; -1
453 */
454 static int set_domain_info_11d(struct lbs_private *priv)
455 {
456 int ret;
457
458 if (!priv->enable11d) {
459 lbs_deb_11d("dnld domain Info with 11d disabled\n");
460 return 0;
461 }
462
463 ret = lbs_prepare_and_send_command(priv, CMD_802_11D_DOMAIN_INFO,
464 CMD_ACT_SET,
465 CMD_OPTION_WAITFORRSP, 0, NULL);
466 if (ret)
467 lbs_deb_11d("fail to dnld domain info\n");
468
469 return ret;
470 }
471
472 /**
473 * @brief This function setups scan channels
474 * @param priv pointer to struct lbs_private
475 * @param band band
476 * @return 0
477 */
478 int lbs_set_universaltable(struct lbs_private *priv, u8 band)
479 {
480 u16 size = sizeof(struct chan_freq_power);
481 u16 i = 0;
482
483 memset(priv->universal_channel, 0,
484 sizeof(priv->universal_channel));
485
486 priv->universal_channel[i].nrcfp =
487 sizeof(channel_freq_power_UN_BG) / size;
488 lbs_deb_11d("BG-band nrcfp %d\n",
489 priv->universal_channel[i].nrcfp);
490
491 priv->universal_channel[i].CFP = channel_freq_power_UN_BG;
492 priv->universal_channel[i].valid = 1;
493 priv->universal_channel[i].region = UNIVERSAL_REGION_CODE;
494 priv->universal_channel[i].band = band;
495 i++;
496
497 return 0;
498 }
499
500 /**
501 * @brief This function implements command CMD_802_11D_DOMAIN_INFO
502 * @param priv pointer to struct lbs_private
503 * @param cmd pointer to cmd buffer
504 * @param cmdno cmd ID
505 * @param cmdOption cmd action
506 * @return 0
507 */
508 int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
509 struct cmd_ds_command *cmd, u16 cmdno,
510 u16 cmdoption)
511 {
512 struct cmd_ds_802_11d_domain_info *pdomaininfo =
513 &cmd->params.domaininfo;
514 struct mrvlietypes_domainparamset *domain = &pdomaininfo->domain;
515 u8 nr_subband = priv->domainreg.nr_subband;
516
517 lbs_deb_enter(LBS_DEB_11D);
518
519 lbs_deb_11d("nr_subband=%x\n", nr_subband);
520
521 cmd->command = cpu_to_le16(cmdno);
522 pdomaininfo->action = cpu_to_le16(cmdoption);
523 if (cmdoption == CMD_ACT_GET) {
524 cmd->size =
525 cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
526 lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd,
527 le16_to_cpu(cmd->size));
528 goto done;
529 }
530
531 domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
532 memcpy(domain->countrycode, priv->domainreg.countrycode,
533 sizeof(domain->countrycode));
534
535 domain->header.len =
536 cpu_to_le16(nr_subband * sizeof(struct ieeetypes_subbandset) +
537 sizeof(domain->countrycode));
538
539 if (nr_subband) {
540 memcpy(domain->subband, priv->domainreg.subband,
541 nr_subband * sizeof(struct ieeetypes_subbandset));
542
543 cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
544 le16_to_cpu(domain->header.len) +
545 sizeof(struct mrvlietypesheader) +
546 S_DS_GEN);
547 } else {
548 cmd->size =
549 cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
550 }
551
552 lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd, le16_to_cpu(cmd->size));
553
554 done:
555 lbs_deb_enter(LBS_DEB_11D);
556 return 0;
557 }
558
559 /**
560 * @brief This function parses countryinfo from AP and download country info to FW
561 * @param priv pointer to struct lbs_private
562 * @param resp pointer to command response buffer
563 * @return 0; -1
564 */
565 int lbs_ret_802_11d_domain_info(struct lbs_private *priv,
566 struct cmd_ds_command *resp)
567 {
568 struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp;
569 struct mrvlietypes_domainparamset *domain = &domaininfo->domain;
570 u16 action = le16_to_cpu(domaininfo->action);
571 s16 ret = 0;
572 u8 nr_subband = 0;
573
574 lbs_deb_enter(LBS_DEB_11D);
575
576 lbs_deb_hex(LBS_DEB_11D, "domain info resp", (u8 *) resp,
577 (int)le16_to_cpu(resp->size));
578
579 nr_subband = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) /
580 sizeof(struct ieeetypes_subbandset);
581
582 lbs_deb_11d("domain info resp: nr_subband %d\n", nr_subband);
583
584 if (nr_subband > MRVDRV_MAX_SUBBAND_802_11D) {
585 lbs_deb_11d("Invalid Numrer of Subband returned!!\n");
586 return -1;
587 }
588
589 switch (action) {
590 case CMD_ACT_SET: /*Proc Set action */
591 break;
592
593 case CMD_ACT_GET:
594 break;
595 default:
596 lbs_deb_11d("Invalid action:%d\n", domaininfo->action);
597 ret = -1;
598 break;
599 }
600
601 lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
602 return ret;
603 }
604
605 /**
606 * @brief This function parses countryinfo from AP and download country info to FW
607 * @param priv pointer to struct lbs_private
608 * @return 0; -1
609 */
610 int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv,
611 struct bss_descriptor * bss)
612 {
613 int ret;
614
615 lbs_deb_enter(LBS_DEB_11D);
616 if (priv->enable11d) {
617 memset(&priv->parsed_region_chan, 0,
618 sizeof(struct parsed_region_chan_11d));
619 ret = parse_domain_info_11d(&bss->countryinfo, 0,
620 &priv->parsed_region_chan);
621
622 if (ret == -1) {
623 lbs_deb_11d("error parsing domain_info from AP\n");
624 goto done;
625 }
626
627 memset(&priv->domainreg, 0,
628 sizeof(struct lbs_802_11d_domain_reg));
629 generate_domain_info_11d(&priv->parsed_region_chan,
630 &priv->domainreg);
631
632 ret = set_domain_info_11d(priv);
633
634 if (ret) {
635 lbs_deb_11d("error setting domain info\n");
636 goto done;
637 }
638 }
639 ret = 0;
640
641 done:
642 lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
643 return ret;
644 }
645
646 /**
647 * @brief This function generates 11D info from user specified regioncode and download to FW
648 * @param priv pointer to struct lbs_private
649 * @return 0; -1
650 */
651 int lbs_create_dnld_countryinfo_11d(struct lbs_private *priv)
652 {
653 int ret;
654 struct region_channel *region_chan;
655 u8 j;
656
657 lbs_deb_enter(LBS_DEB_11D);
658 lbs_deb_11d("curbssparams.band %d\n", priv->curbssparams.band);
659
660 if (priv->enable11d) {
661 /* update parsed_region_chan_11; dnld domaininf to FW */
662
663 for (j = 0; j < ARRAY_SIZE(priv->region_channel); j++) {
664 region_chan = &priv->region_channel[j];
665
666 lbs_deb_11d("%d region_chan->band %d\n", j,
667 region_chan->band);
668
669 if (!region_chan || !region_chan->valid
670 || !region_chan->CFP)
671 continue;
672 if (region_chan->band != priv->curbssparams.band)
673 continue;
674 break;
675 }
676
677 if (j >= ARRAY_SIZE(priv->region_channel)) {
678 lbs_deb_11d("region_chan not found, band %d\n",
679 priv->curbssparams.band);
680 ret = -1;
681 goto done;
682 }
683
684 memset(&priv->parsed_region_chan, 0,
685 sizeof(struct parsed_region_chan_11d));
686 lbs_generate_parsed_region_chan_11d(region_chan,
687 &priv->
688 parsed_region_chan);
689
690 memset(&priv->domainreg, 0,
691 sizeof(struct lbs_802_11d_domain_reg));
692 generate_domain_info_11d(&priv->parsed_region_chan,
693 &priv->domainreg);
694
695 ret = set_domain_info_11d(priv);
696
697 if (ret) {
698 lbs_deb_11d("error setting domain info\n");
699 goto done;
700 }
701
702 }
703 ret = 0;
704
705 done:
706 lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
707 return ret;
708 }
This page took 0.087464 seconds and 5 git commands to generate.