aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/reg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r--net/wireless/reg.c462
1 files changed, 266 insertions, 196 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 626dbb688499..4c7e39d466c4 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -42,17 +42,34 @@
42#include "core.h" 42#include "core.h"
43#include "reg.h" 43#include "reg.h"
44 44
45/* wiphy is set if this request's initiator is REGDOM_SET_BY_DRIVER */ 45/**
46 * struct regulatory_request - receipt of last regulatory request
47 *
48 * @wiphy: this is set if this request's initiator is
49 * %REGDOM_SET_BY_COUNTRY_IE or %REGDOM_SET_BY_DRIVER. This
50 * can be used by the wireless core to deal with conflicts
51 * and potentially inform users of which devices specifically
52 * cased the conflicts.
53 * @initiator: indicates who sent this request, could be any of
54 * of those set in reg_set_by, %REGDOM_SET_BY_*
55 * @alpha2: the ISO / IEC 3166 alpha2 country code of the requested
56 * regulatory domain. We have a few special codes:
57 * 00 - World regulatory domain
58 * 99 - built by driver but a specific alpha2 cannot be determined
59 * 98 - result of an intersection between two regulatory domains
60 * @intersect: indicates whether the wireless core should intersect
61 * the requested regulatory domain with the presently set regulatory
62 * domain.
63 */
46struct regulatory_request { 64struct regulatory_request {
47 struct list_head list;
48 struct wiphy *wiphy; 65 struct wiphy *wiphy;
49 int granted;
50 enum reg_set_by initiator; 66 enum reg_set_by initiator;
51 char alpha2[2]; 67 char alpha2[2];
68 bool intersect;
52}; 69};
53 70
54static LIST_HEAD(regulatory_requests); 71/* Receipt of information from last regulatory request */
55DEFINE_MUTEX(cfg80211_reg_mutex); 72static struct regulatory_request *last_request;
56 73
57/* To trigger userspace events */ 74/* To trigger userspace events */
58static struct platform_device *reg_pdev; 75static struct platform_device *reg_pdev;
@@ -63,8 +80,6 @@ static u32 supported_bandwidths[] = {
63 MHZ_TO_KHZ(20), 80 MHZ_TO_KHZ(20),
64}; 81};
65 82
66static struct list_head regulatory_requests;
67
68/* Central wireless core regulatory domains, we only need two, 83/* Central wireless core regulatory domains, we only need two,
69 * the current one and a world regulatory domain in case we have no 84 * the current one and a world regulatory domain in case we have no
70 * information to give us an alpha2 */ 85 * information to give us an alpha2 */
@@ -204,7 +219,7 @@ static void reset_regdomains(void)
204 * core upon initialization */ 219 * core upon initialization */
205static void update_world_regdomain(const struct ieee80211_regdomain *rd) 220static void update_world_regdomain(const struct ieee80211_regdomain *rd)
206{ 221{
207 BUG_ON(list_empty(&regulatory_requests)); 222 BUG_ON(!last_request);
208 223
209 reset_regdomains(); 224 reset_regdomains();
210 225
@@ -300,121 +315,13 @@ static int call_crda(const char *alpha2)
300 return kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, envp); 315 return kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, envp);
301} 316}
302 317
303/* This has the logic which determines when a new request
304 * should be ignored. */
305static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by,
306 char *alpha2, struct ieee80211_regdomain *rd)
307{
308 struct regulatory_request *last_request = NULL;
309
310 /* All initial requests are respected */
311 if (list_empty(&regulatory_requests))
312 return 0;
313
314 last_request = list_first_entry(&regulatory_requests,
315 struct regulatory_request, list);
316
317 switch (set_by) {
318 case REGDOM_SET_BY_INIT:
319 return -EINVAL;
320 case REGDOM_SET_BY_CORE:
321 /* Always respect new wireless core hints, should only
322 * come in for updating the world regulatory domain at init
323 * anyway */
324 return 0;
325 case REGDOM_SET_BY_COUNTRY_IE:
326 if (last_request->initiator == set_by) {
327 if (last_request->wiphy != wiphy) {
328 /* Two cards with two APs claiming different
329 * different Country IE alpha2s!
330 * You're special!! */
331 if (!alpha2_equal(last_request->alpha2,
332 cfg80211_regdomain->alpha2)) {
333 /* XXX: Deal with conflict, consider
334 * building a new one out of the
335 * intersection */
336 WARN_ON(1);
337 return -EOPNOTSUPP;
338 }
339 return -EALREADY;
340 }
341 /* Two consecutive Country IE hints on the same wiphy */
342 if (!alpha2_equal(cfg80211_regdomain->alpha2, alpha2))
343 return 0;
344 return -EALREADY;
345 }
346 if (WARN_ON(!is_alpha2_set(alpha2) || !is_an_alpha2(alpha2)),
347 "Invalid Country IE regulatory hint passed "
348 "to the wireless core\n")
349 return -EINVAL;
350 /* We ignore Country IE hints for now, as we haven't yet
351 * added the dot11MultiDomainCapabilityEnabled flag
352 * for wiphys */
353 return 1;
354 case REGDOM_SET_BY_DRIVER:
355 BUG_ON(!wiphy);
356 if (last_request->initiator == set_by) {
357 /* Two separate drivers hinting different things,
358 * this is possible if you have two devices present
359 * on a system with different EEPROM regulatory
360 * readings. XXX: Do intersection, we support only
361 * the first regulatory hint for now */
362 if (last_request->wiphy != wiphy)
363 return -EALREADY;
364 if (rd)
365 return -EALREADY;
366 /* Driver should not be trying to hint different
367 * regulatory domains! */
368 BUG_ON(!alpha2_equal(alpha2,
369 cfg80211_regdomain->alpha2));
370 return -EALREADY;
371 }
372 if (last_request->initiator == REGDOM_SET_BY_CORE)
373 return 0;
374 /* XXX: Handle intersection, and add the
375 * dot11MultiDomainCapabilityEnabled flag to wiphy. For now
376 * we assume the driver has this set to false, following the
377 * 802.11d dot11MultiDomainCapabilityEnabled documentation */
378 if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE)
379 return 0;
380 return 0;
381 case REGDOM_SET_BY_USER:
382 if (last_request->initiator == set_by ||
383 last_request->initiator == REGDOM_SET_BY_CORE)
384 return 0;
385 /* Drivers can use their wiphy's reg_notifier()
386 * to override any information */
387 if (last_request->initiator == REGDOM_SET_BY_DRIVER)
388 return 0;
389 /* XXX: Handle intersection */
390 if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE)
391 return -EOPNOTSUPP;
392 return 0;
393 default:
394 return -EINVAL;
395 }
396}
397
398static bool __reg_is_valid_request(const char *alpha2,
399 struct regulatory_request **request)
400{
401 struct regulatory_request *req;
402 if (list_empty(&regulatory_requests))
403 return false;
404 list_for_each_entry(req, &regulatory_requests, list) {
405 if (alpha2_equal(req->alpha2, alpha2)) {
406 *request = req;
407 return true;
408 }
409 }
410 return false;
411}
412
413/* Used by nl80211 before kmalloc'ing our regulatory domain */ 318/* Used by nl80211 before kmalloc'ing our regulatory domain */
414bool reg_is_valid_request(const char *alpha2) 319bool reg_is_valid_request(const char *alpha2)
415{ 320{
416 struct regulatory_request *request = NULL; 321 if (!last_request)
417 return __reg_is_valid_request(alpha2, &request); 322 return false;
323
324 return alpha2_equal(last_request->alpha2, alpha2);
418} 325}
419 326
420/* Sanity check on a regulatory rule */ 327/* Sanity check on a regulatory rule */
@@ -431,7 +338,7 @@ static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
431 338
432 freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz; 339 freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
433 340
434 if (freq_range->max_bandwidth_khz > freq_diff) 341 if (freq_diff <= 0 || freq_range->max_bandwidth_khz > freq_diff)
435 return false; 342 return false;
436 343
437 return true; 344 return true;
@@ -469,6 +376,143 @@ static u32 freq_max_bandwidth(const struct ieee80211_freq_range *freq_range,
469 return 0; 376 return 0;
470} 377}
471 378
379/* Helper for regdom_intersect(), this does the real
380 * mathematical intersection fun */
381static int reg_rules_intersect(
382 const struct ieee80211_reg_rule *rule1,
383 const struct ieee80211_reg_rule *rule2,
384 struct ieee80211_reg_rule *intersected_rule)
385{
386 const struct ieee80211_freq_range *freq_range1, *freq_range2;
387 struct ieee80211_freq_range *freq_range;
388 const struct ieee80211_power_rule *power_rule1, *power_rule2;
389 struct ieee80211_power_rule *power_rule;
390 u32 freq_diff;
391
392 freq_range1 = &rule1->freq_range;
393 freq_range2 = &rule2->freq_range;
394 freq_range = &intersected_rule->freq_range;
395
396 power_rule1 = &rule1->power_rule;
397 power_rule2 = &rule2->power_rule;
398 power_rule = &intersected_rule->power_rule;
399
400 freq_range->start_freq_khz = max(freq_range1->start_freq_khz,
401 freq_range2->start_freq_khz);
402 freq_range->end_freq_khz = min(freq_range1->end_freq_khz,
403 freq_range2->end_freq_khz);
404 freq_range->max_bandwidth_khz = min(freq_range1->max_bandwidth_khz,
405 freq_range2->max_bandwidth_khz);
406
407 freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
408 if (freq_range->max_bandwidth_khz > freq_diff)
409 freq_range->max_bandwidth_khz = freq_diff;
410
411 power_rule->max_eirp = min(power_rule1->max_eirp,
412 power_rule2->max_eirp);
413 power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain,
414 power_rule2->max_antenna_gain);
415
416 intersected_rule->flags = (rule1->flags | rule2->flags);
417
418 if (!is_valid_reg_rule(intersected_rule))
419 return -EINVAL;
420
421 return 0;
422}
423
424/**
425 * regdom_intersect - do the intersection between two regulatory domains
426 * @rd1: first regulatory domain
427 * @rd2: second regulatory domain
428 *
429 * Use this function to get the intersection between two regulatory domains.
430 * Once completed we will mark the alpha2 for the rd as intersected, "98",
431 * as no one single alpha2 can represent this regulatory domain.
432 *
433 * Returns a pointer to the regulatory domain structure which will hold the
434 * resulting intersection of rules between rd1 and rd2. We will
435 * kzalloc() this structure for you.
436 */
437static struct ieee80211_regdomain *regdom_intersect(
438 const struct ieee80211_regdomain *rd1,
439 const struct ieee80211_regdomain *rd2)
440{
441 int r, size_of_regd;
442 unsigned int x, y;
443 unsigned int num_rules = 0, rule_idx = 0;
444 const struct ieee80211_reg_rule *rule1, *rule2;
445 struct ieee80211_reg_rule *intersected_rule;
446 struct ieee80211_regdomain *rd;
447 /* This is just a dummy holder to help us count */
448 struct ieee80211_reg_rule irule;
449
450 /* Uses the stack temporarily for counter arithmetic */
451 intersected_rule = &irule;
452
453 memset(intersected_rule, 0, sizeof(struct ieee80211_reg_rule));
454
455 if (!rd1 || !rd2)
456 return NULL;
457
458 /* First we get a count of the rules we'll need, then we actually
459 * build them. This is to so we can malloc() and free() a
460 * regdomain once. The reason we use reg_rules_intersect() here
461 * is it will return -EINVAL if the rule computed makes no sense.
462 * All rules that do check out OK are valid. */
463
464 for (x = 0; x < rd1->n_reg_rules; x++) {
465 rule1 = &rd1->reg_rules[x];
466 for (y = 0; y < rd2->n_reg_rules; y++) {
467 rule2 = &rd2->reg_rules[y];
468 if (!reg_rules_intersect(rule1, rule2,
469 intersected_rule))
470 num_rules++;
471 memset(intersected_rule, 0,
472 sizeof(struct ieee80211_reg_rule));
473 }
474 }
475
476 if (!num_rules)
477 return NULL;
478
479 size_of_regd = sizeof(struct ieee80211_regdomain) +
480 ((num_rules + 1) * sizeof(struct ieee80211_reg_rule));
481
482 rd = kzalloc(size_of_regd, GFP_KERNEL);
483 if (!rd)
484 return NULL;
485
486 for (x = 0; x < rd1->n_reg_rules; x++) {
487 rule1 = &rd1->reg_rules[x];
488 for (y = 0; y < rd2->n_reg_rules; y++) {
489 rule2 = &rd2->reg_rules[y];
490 /* This time around instead of using the stack lets
491 * write to the target rule directly saving ourselves
492 * a memcpy() */
493 intersected_rule = &rd->reg_rules[rule_idx];
494 r = reg_rules_intersect(rule1, rule2,
495 intersected_rule);
496 /* No need to memset here the intersected rule here as
497 * we're not using the stack anymore */
498 if (r)
499 continue;
500 rule_idx++;
501 }
502 }
503
504 if (rule_idx != num_rules) {
505 kfree(rd);
506 return NULL;
507 }
508
509 rd->n_reg_rules = num_rules;
510 rd->alpha2[0] = '9';
511 rd->alpha2[1] = '8';
512
513 return rd;
514}
515
472/* XXX: add support for the rest of enum nl80211_reg_rule_flags, we may 516/* XXX: add support for the rest of enum nl80211_reg_rule_flags, we may
473 * want to just have the channel structure use these */ 517 * want to just have the channel structure use these */
474static u32 map_regdom_flags(u32 rd_flags) 518static u32 map_regdom_flags(u32 rd_flags)
@@ -578,22 +622,81 @@ void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby)
578 } 622 }
579} 623}
580 624
625/* Return value which can be used by ignore_request() to indicate
626 * it has been determined we should intersect two regulatory domains */
627#define REG_INTERSECT 1
628
629/* This has the logic which determines when a new request
630 * should be ignored. */
631static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by,
632 const char *alpha2)
633{
634 /* All initial requests are respected */
635 if (!last_request)
636 return 0;
637
638 switch (set_by) {
639 case REGDOM_SET_BY_INIT:
640 return -EINVAL;
641 case REGDOM_SET_BY_CORE:
642 /*
643 * Always respect new wireless core hints, should only happen
644 * when updating the world regulatory domain at init.
645 */
646 return 0;
647 case REGDOM_SET_BY_COUNTRY_IE:
648 if (unlikely(!is_an_alpha2(alpha2)))
649 return -EINVAL;
650 if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) {
651 if (last_request->wiphy != wiphy) {
652 /*
653 * Two cards with two APs claiming different
654 * different Country IE alpha2s. We could
655 * intersect them, but that seems unlikely
656 * to be correct. Reject second one for now.
657 */
658 if (!alpha2_equal(alpha2,
659 cfg80211_regdomain->alpha2))
660 return -EOPNOTSUPP;
661 return -EALREADY;
662 }
663 /* Two consecutive Country IE hints on the same wiphy */
664 if (!alpha2_equal(cfg80211_regdomain->alpha2, alpha2))
665 return 0;
666 return -EALREADY;
667 }
668 /*
669 * Ignore Country IE hints for now, need to think about
670 * what we need to do to support multi-domain operation.
671 */
672 return -EOPNOTSUPP;
673 case REGDOM_SET_BY_DRIVER:
674 if (last_request->initiator == REGDOM_SET_BY_DRIVER)
675 return -EALREADY;
676 return 0;
677 case REGDOM_SET_BY_USER:
678 if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE)
679 return REG_INTERSECT;
680 return 0;
681 }
682
683 return -EINVAL;
684}
685
581/* Caller must hold &cfg80211_drv_mutex */ 686/* Caller must hold &cfg80211_drv_mutex */
582int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, 687int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
583 const char *alpha2, struct ieee80211_regdomain *rd) 688 const char *alpha2)
584{ 689{
585 struct regulatory_request *request; 690 struct regulatory_request *request;
586 char *rd_alpha2; 691 bool intersect = false;
587 int r = 0; 692 int r = 0;
588 693
589 r = ignore_request(wiphy, set_by, (char *) alpha2, rd); 694 r = ignore_request(wiphy, set_by, alpha2);
590 if (r)
591 return r;
592 695
593 if (rd) 696 if (r == REG_INTERSECT)
594 rd_alpha2 = rd->alpha2; 697 intersect = true;
595 else 698 else if (r)
596 rd_alpha2 = (char *) alpha2; 699 return r;
597 700
598 switch (set_by) { 701 switch (set_by) {
599 case REGDOM_SET_BY_CORE: 702 case REGDOM_SET_BY_CORE:
@@ -601,18 +704,18 @@ int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
601 case REGDOM_SET_BY_DRIVER: 704 case REGDOM_SET_BY_DRIVER:
602 case REGDOM_SET_BY_USER: 705 case REGDOM_SET_BY_USER:
603 request = kzalloc(sizeof(struct regulatory_request), 706 request = kzalloc(sizeof(struct regulatory_request),
604 GFP_KERNEL); 707 GFP_KERNEL);
605 if (!request) 708 if (!request)
606 return -ENOMEM; 709 return -ENOMEM;
607 710
608 request->alpha2[0] = rd_alpha2[0]; 711 request->alpha2[0] = alpha2[0];
609 request->alpha2[1] = rd_alpha2[1]; 712 request->alpha2[1] = alpha2[1];
610 request->initiator = set_by; 713 request->initiator = set_by;
611 request->wiphy = wiphy; 714 request->wiphy = wiphy;
715 request->intersect = intersect;
612 716
613 list_add_tail(&request->list, &regulatory_requests); 717 kfree(last_request);
614 if (rd) 718 last_request = request;
615 break;
616 r = call_crda(alpha2); 719 r = call_crda(alpha2);
617#ifndef CONFIG_WIRELESS_OLD_REGULATORY 720#ifndef CONFIG_WIRELESS_OLD_REGULATORY
618 if (r) 721 if (r)
@@ -627,26 +730,13 @@ int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
627 return r; 730 return r;
628} 731}
629 732
630/* If rd is not NULL and if this call fails the caller must free it */ 733void regulatory_hint(struct wiphy *wiphy, const char *alpha2)
631int regulatory_hint(struct wiphy *wiphy, const char *alpha2,
632 struct ieee80211_regdomain *rd)
633{ 734{
634 int r; 735 BUG_ON(!alpha2);
635 BUG_ON(!rd && !alpha2);
636 736
637 mutex_lock(&cfg80211_drv_mutex); 737 mutex_lock(&cfg80211_drv_mutex);
638 738 __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2);
639 r = __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2, rd);
640 if (r || !rd)
641 goto unlock_and_exit;
642
643 /* If the driver passed a regulatory domain we skipped asking
644 * userspace for one so we can now go ahead and set it */
645 r = set_regdom(rd);
646
647unlock_and_exit:
648 mutex_unlock(&cfg80211_drv_mutex); 739 mutex_unlock(&cfg80211_drv_mutex);
649 return r;
650} 740}
651EXPORT_SYMBOL(regulatory_hint); 741EXPORT_SYMBOL(regulatory_hint);
652 742
@@ -705,21 +795,21 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
705 print_rd_rules(rd); 795 print_rd_rules(rd);
706} 796}
707 797
708void print_regdomain_info(const struct ieee80211_regdomain *rd) 798static void print_regdomain_info(const struct ieee80211_regdomain *rd)
709{ 799{
710 printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n", 800 printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n",
711 rd->alpha2[0], rd->alpha2[1]); 801 rd->alpha2[0], rd->alpha2[1]);
712 print_rd_rules(rd); 802 print_rd_rules(rd);
713} 803}
714 804
805/* Takes ownership of rd only if it doesn't fail */
715static int __set_regdom(const struct ieee80211_regdomain *rd) 806static int __set_regdom(const struct ieee80211_regdomain *rd)
716{ 807{
717 struct regulatory_request *request = NULL; 808 const struct ieee80211_regdomain *intersected_rd = NULL;
718
719 /* Some basic sanity checks first */ 809 /* Some basic sanity checks first */
720 810
721 if (is_world_regdom(rd->alpha2)) { 811 if (is_world_regdom(rd->alpha2)) {
722 if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) 812 if (WARN_ON(!reg_is_valid_request(rd->alpha2)))
723 return -EINVAL; 813 return -EINVAL;
724 update_world_regdomain(rd); 814 update_world_regdomain(rd);
725 return 0; 815 return 0;
@@ -729,7 +819,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
729 !is_unknown_alpha2(rd->alpha2)) 819 !is_unknown_alpha2(rd->alpha2))
730 return -EINVAL; 820 return -EINVAL;
731 821
732 if (list_empty(&regulatory_requests)) 822 if (!last_request)
733 return -EINVAL; 823 return -EINVAL;
734 824
735 /* allow overriding the static definitions if CRDA is present */ 825 /* allow overriding the static definitions if CRDA is present */
@@ -742,13 +832,13 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
742 * to review or adjust their own settings based on their own 832 * to review or adjust their own settings based on their own
743 * internal EEPROM data */ 833 * internal EEPROM data */
744 834
745 if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) 835 if (WARN_ON(!reg_is_valid_request(rd->alpha2)))
746 return -EINVAL; 836 return -EINVAL;
747 837
748 reset_regdomains(); 838 reset_regdomains();
749 839
750 /* Country IE parsing coming soon */ 840 /* Country IE parsing coming soon */
751 switch (request->initiator) { 841 switch (last_request->initiator) {
752 case REGDOM_SET_BY_CORE: 842 case REGDOM_SET_BY_CORE:
753 case REGDOM_SET_BY_DRIVER: 843 case REGDOM_SET_BY_DRIVER:
754 case REGDOM_SET_BY_USER: 844 case REGDOM_SET_BY_USER:
@@ -765,9 +855,16 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
765 return -EOPNOTSUPP; 855 return -EOPNOTSUPP;
766 } 856 }
767 857
858 if (unlikely(last_request->intersect)) {
859 intersected_rd = regdom_intersect(rd, cfg80211_regdomain);
860 if (!intersected_rd)
861 return -EINVAL;
862 kfree(rd);
863 rd = intersected_rd;
864 }
865
768 /* Tada! */ 866 /* Tada! */
769 cfg80211_regdomain = rd; 867 cfg80211_regdomain = rd;
770 request->granted = 1;
771 868
772 return 0; 869 return 0;
773} 870}
@@ -775,46 +872,23 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
775 872
776/* Use this call to set the current regulatory domain. Conflicts with 873/* Use this call to set the current regulatory domain. Conflicts with
777 * multiple drivers can be ironed out later. Caller must've already 874 * multiple drivers can be ironed out later. Caller must've already
778 * kmalloc'd the rd structure. If this calls fails you should kfree() 875 * kmalloc'd the rd structure. Caller must hold cfg80211_drv_mutex */
779 * the passed rd. Caller must hold cfg80211_drv_mutex */
780int set_regdom(const struct ieee80211_regdomain *rd) 876int set_regdom(const struct ieee80211_regdomain *rd)
781{ 877{
782 struct regulatory_request *this_request = NULL, *prev_request = NULL;
783 int r; 878 int r;
784 879
785 if (!list_empty(&regulatory_requests))
786 prev_request = list_first_entry(&regulatory_requests,
787 struct regulatory_request, list);
788
789 /* Note that this doesn't update the wiphys, this is done below */ 880 /* Note that this doesn't update the wiphys, this is done below */
790 r = __set_regdom(rd); 881 r = __set_regdom(rd);
791 if (r) 882 if (r) {
883 kfree(rd);
792 return r; 884 return r;
793
794 BUG_ON((!__reg_is_valid_request(rd->alpha2, &this_request)));
795
796 /* The initial standard core update of the world regulatory domain, no
797 * need to keep that request info around if it didn't fail. */
798 if (is_world_regdom(rd->alpha2) &&
799 this_request->initiator == REGDOM_SET_BY_CORE &&
800 this_request->granted) {
801 list_del(&this_request->list);
802 kfree(this_request);
803 this_request = NULL;
804 }
805
806 /* Remove old requests, we only leave behind the last one */
807 if (prev_request) {
808 list_del(&prev_request->list);
809 kfree(prev_request);
810 prev_request = NULL;
811 } 885 }
812 886
813 /* This would make this whole thing pointless */ 887 /* This would make this whole thing pointless */
814 BUG_ON(rd != cfg80211_regdomain); 888 BUG_ON(rd != cfg80211_regdomain);
815 889
816 /* update all wiphys now with the new established regulatory domain */ 890 /* update all wiphys now with the new established regulatory domain */
817 update_all_wiphy_regulatory(this_request->initiator); 891 update_all_wiphy_regulatory(last_request->initiator);
818 892
819 print_regdomain(rd); 893 print_regdomain(rd);
820 894
@@ -838,13 +912,13 @@ int regulatory_init(void)
838 * you have CRDA you get it updated, otherwise you get 912 * you have CRDA you get it updated, otherwise you get
839 * stuck with the static values. We ignore "EU" code as 913 * stuck with the static values. We ignore "EU" code as
840 * that is not a valid ISO / IEC 3166 alpha2 */ 914 * that is not a valid ISO / IEC 3166 alpha2 */
841 if (ieee80211_regdom[0] != 'E' && ieee80211_regdom[1] != 'U') 915 if (ieee80211_regdom[0] != 'E' || ieee80211_regdom[1] != 'U')
842 err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, 916 err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE,
843 ieee80211_regdom, NULL); 917 ieee80211_regdom);
844#else 918#else
845 cfg80211_regdomain = cfg80211_world_regdom; 919 cfg80211_regdomain = cfg80211_world_regdom;
846 920
847 err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL); 921 err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00");
848 if (err) 922 if (err)
849 printk(KERN_ERR "cfg80211: calling CRDA failed - " 923 printk(KERN_ERR "cfg80211: calling CRDA failed - "
850 "unable to update world regulatory domain, " 924 "unable to update world regulatory domain, "
@@ -856,16 +930,12 @@ int regulatory_init(void)
856 930
857void regulatory_exit(void) 931void regulatory_exit(void)
858{ 932{
859 struct regulatory_request *req, *req_tmp;
860
861 mutex_lock(&cfg80211_drv_mutex); 933 mutex_lock(&cfg80211_drv_mutex);
862 934
863 reset_regdomains(); 935 reset_regdomains();
864 936
865 list_for_each_entry_safe(req, req_tmp, &regulatory_requests, list) { 937 kfree(last_request);
866 list_del(&req->list); 938
867 kfree(req);
868 }
869 platform_device_unregister(reg_pdev); 939 platform_device_unregister(reg_pdev);
870 940
871 mutex_unlock(&cfg80211_drv_mutex); 941 mutex_unlock(&cfg80211_drv_mutex);