diff options
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r-- | net/wireless/reg.c | 311 |
1 files changed, 212 insertions, 99 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 592b2e391d42..626dbb688499 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -42,6 +42,18 @@ | |||
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 */ | ||
46 | struct regulatory_request { | ||
47 | struct list_head list; | ||
48 | struct wiphy *wiphy; | ||
49 | int granted; | ||
50 | enum reg_set_by initiator; | ||
51 | char alpha2[2]; | ||
52 | }; | ||
53 | |||
54 | static LIST_HEAD(regulatory_requests); | ||
55 | DEFINE_MUTEX(cfg80211_reg_mutex); | ||
56 | |||
45 | /* To trigger userspace events */ | 57 | /* To trigger userspace events */ |
46 | static struct platform_device *reg_pdev; | 58 | static struct platform_device *reg_pdev; |
47 | 59 | ||
@@ -51,7 +63,156 @@ static u32 supported_bandwidths[] = { | |||
51 | MHZ_TO_KHZ(20), | 63 | MHZ_TO_KHZ(20), |
52 | }; | 64 | }; |
53 | 65 | ||
54 | bool is_world_regdom(char *alpha2) | 66 | static struct list_head regulatory_requests; |
67 | |||
68 | /* Central wireless core regulatory domains, we only need two, | ||
69 | * the current one and a world regulatory domain in case we have no | ||
70 | * information to give us an alpha2 */ | ||
71 | static const struct ieee80211_regdomain *cfg80211_regdomain; | ||
72 | |||
73 | /* We keep a static world regulatory domain in case of the absence of CRDA */ | ||
74 | static const struct ieee80211_regdomain world_regdom = { | ||
75 | .n_reg_rules = 1, | ||
76 | .alpha2 = "00", | ||
77 | .reg_rules = { | ||
78 | REG_RULE(2412-10, 2462+10, 40, 6, 20, | ||
79 | NL80211_RRF_PASSIVE_SCAN | | ||
80 | NL80211_RRF_NO_IBSS), | ||
81 | } | ||
82 | }; | ||
83 | |||
84 | static const struct ieee80211_regdomain *cfg80211_world_regdom = | ||
85 | &world_regdom; | ||
86 | |||
87 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
88 | static char *ieee80211_regdom = "US"; | ||
89 | module_param(ieee80211_regdom, charp, 0444); | ||
90 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | ||
91 | |||
92 | /* We assume 40 MHz bandwidth for the old regulatory work. | ||
93 | * We make emphasis we are using the exact same frequencies | ||
94 | * as before */ | ||
95 | |||
96 | static const struct ieee80211_regdomain us_regdom = { | ||
97 | .n_reg_rules = 6, | ||
98 | .alpha2 = "US", | ||
99 | .reg_rules = { | ||
100 | /* IEEE 802.11b/g, channels 1..11 */ | ||
101 | REG_RULE(2412-10, 2462+10, 40, 6, 27, 0), | ||
102 | /* IEEE 802.11a, channel 36 */ | ||
103 | REG_RULE(5180-10, 5180+10, 40, 6, 23, 0), | ||
104 | /* IEEE 802.11a, channel 40 */ | ||
105 | REG_RULE(5200-10, 5200+10, 40, 6, 23, 0), | ||
106 | /* IEEE 802.11a, channel 44 */ | ||
107 | REG_RULE(5220-10, 5220+10, 40, 6, 23, 0), | ||
108 | /* IEEE 802.11a, channels 48..64 */ | ||
109 | REG_RULE(5240-10, 5320+10, 40, 6, 23, 0), | ||
110 | /* IEEE 802.11a, channels 149..165, outdoor */ | ||
111 | REG_RULE(5745-10, 5825+10, 40, 6, 30, 0), | ||
112 | } | ||
113 | }; | ||
114 | |||
115 | static const struct ieee80211_regdomain jp_regdom = { | ||
116 | .n_reg_rules = 3, | ||
117 | .alpha2 = "JP", | ||
118 | .reg_rules = { | ||
119 | /* IEEE 802.11b/g, channels 1..14 */ | ||
120 | REG_RULE(2412-10, 2484+10, 40, 6, 20, 0), | ||
121 | /* IEEE 802.11a, channels 34..48 */ | ||
122 | REG_RULE(5170-10, 5240+10, 40, 6, 20, | ||
123 | NL80211_RRF_PASSIVE_SCAN), | ||
124 | /* IEEE 802.11a, channels 52..64 */ | ||
125 | REG_RULE(5260-10, 5320+10, 40, 6, 20, | ||
126 | NL80211_RRF_NO_IBSS | | ||
127 | NL80211_RRF_DFS), | ||
128 | } | ||
129 | }; | ||
130 | |||
131 | static const struct ieee80211_regdomain eu_regdom = { | ||
132 | .n_reg_rules = 6, | ||
133 | /* This alpha2 is bogus, we leave it here just for stupid | ||
134 | * backward compatibility */ | ||
135 | .alpha2 = "EU", | ||
136 | .reg_rules = { | ||
137 | /* IEEE 802.11b/g, channels 1..13 */ | ||
138 | REG_RULE(2412-10, 2472+10, 40, 6, 20, 0), | ||
139 | /* IEEE 802.11a, channel 36 */ | ||
140 | REG_RULE(5180-10, 5180+10, 40, 6, 23, | ||
141 | NL80211_RRF_PASSIVE_SCAN), | ||
142 | /* IEEE 802.11a, channel 40 */ | ||
143 | REG_RULE(5200-10, 5200+10, 40, 6, 23, | ||
144 | NL80211_RRF_PASSIVE_SCAN), | ||
145 | /* IEEE 802.11a, channel 44 */ | ||
146 | REG_RULE(5220-10, 5220+10, 40, 6, 23, | ||
147 | NL80211_RRF_PASSIVE_SCAN), | ||
148 | /* IEEE 802.11a, channels 48..64 */ | ||
149 | REG_RULE(5240-10, 5320+10, 40, 6, 20, | ||
150 | NL80211_RRF_NO_IBSS | | ||
151 | NL80211_RRF_DFS), | ||
152 | /* IEEE 802.11a, channels 100..140 */ | ||
153 | REG_RULE(5500-10, 5700+10, 40, 6, 30, | ||
154 | NL80211_RRF_NO_IBSS | | ||
155 | NL80211_RRF_DFS), | ||
156 | } | ||
157 | }; | ||
158 | |||
159 | static const struct ieee80211_regdomain *static_regdom(char *alpha2) | ||
160 | { | ||
161 | if (alpha2[0] == 'U' && alpha2[1] == 'S') | ||
162 | return &us_regdom; | ||
163 | if (alpha2[0] == 'J' && alpha2[1] == 'P') | ||
164 | return &jp_regdom; | ||
165 | if (alpha2[0] == 'E' && alpha2[1] == 'U') | ||
166 | return &eu_regdom; | ||
167 | /* Default, as per the old rules */ | ||
168 | return &us_regdom; | ||
169 | } | ||
170 | |||
171 | static bool is_old_static_regdom(const struct ieee80211_regdomain *rd) | ||
172 | { | ||
173 | if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom) | ||
174 | return true; | ||
175 | return false; | ||
176 | } | ||
177 | #else | ||
178 | static inline bool is_old_static_regdom(const struct ieee80211_regdomain *rd) | ||
179 | { | ||
180 | return false; | ||
181 | } | ||
182 | #endif | ||
183 | |||
184 | static void reset_regdomains(void) | ||
185 | { | ||
186 | /* avoid freeing static information or freeing something twice */ | ||
187 | if (cfg80211_regdomain == cfg80211_world_regdom) | ||
188 | cfg80211_regdomain = NULL; | ||
189 | if (cfg80211_world_regdom == &world_regdom) | ||
190 | cfg80211_world_regdom = NULL; | ||
191 | if (cfg80211_regdomain == &world_regdom) | ||
192 | cfg80211_regdomain = NULL; | ||
193 | if (is_old_static_regdom(cfg80211_regdomain)) | ||
194 | cfg80211_regdomain = NULL; | ||
195 | |||
196 | kfree(cfg80211_regdomain); | ||
197 | kfree(cfg80211_world_regdom); | ||
198 | |||
199 | cfg80211_world_regdom = &world_regdom; | ||
200 | cfg80211_regdomain = NULL; | ||
201 | } | ||
202 | |||
203 | /* Dynamic world regulatory domain requested by the wireless | ||
204 | * core upon initialization */ | ||
205 | static void update_world_regdomain(const struct ieee80211_regdomain *rd) | ||
206 | { | ||
207 | BUG_ON(list_empty(®ulatory_requests)); | ||
208 | |||
209 | reset_regdomains(); | ||
210 | |||
211 | cfg80211_world_regdom = rd; | ||
212 | cfg80211_regdomain = rd; | ||
213 | } | ||
214 | |||
215 | bool is_world_regdom(const char *alpha2) | ||
55 | { | 216 | { |
56 | if (!alpha2) | 217 | if (!alpha2) |
57 | return false; | 218 | return false; |
@@ -60,7 +221,7 @@ bool is_world_regdom(char *alpha2) | |||
60 | return false; | 221 | return false; |
61 | } | 222 | } |
62 | 223 | ||
63 | static bool is_alpha2_set(char *alpha2) | 224 | static bool is_alpha2_set(const char *alpha2) |
64 | { | 225 | { |
65 | if (!alpha2) | 226 | if (!alpha2) |
66 | return false; | 227 | return false; |
@@ -77,7 +238,7 @@ static bool is_alpha_upper(char letter) | |||
77 | return false; | 238 | return false; |
78 | } | 239 | } |
79 | 240 | ||
80 | static bool is_unknown_alpha2(char *alpha2) | 241 | static bool is_unknown_alpha2(const char *alpha2) |
81 | { | 242 | { |
82 | if (!alpha2) | 243 | if (!alpha2) |
83 | return false; | 244 | return false; |
@@ -88,7 +249,7 @@ static bool is_unknown_alpha2(char *alpha2) | |||
88 | return false; | 249 | return false; |
89 | } | 250 | } |
90 | 251 | ||
91 | static bool is_an_alpha2(char *alpha2) | 252 | static bool is_an_alpha2(const char *alpha2) |
92 | { | 253 | { |
93 | if (!alpha2) | 254 | if (!alpha2) |
94 | return false; | 255 | return false; |
@@ -97,7 +258,7 @@ static bool is_an_alpha2(char *alpha2) | |||
97 | return false; | 258 | return false; |
98 | } | 259 | } |
99 | 260 | ||
100 | static bool alpha2_equal(char *alpha2_x, char *alpha2_y) | 261 | static bool alpha2_equal(const char *alpha2_x, const char *alpha2_y) |
101 | { | 262 | { |
102 | if (!alpha2_x || !alpha2_y) | 263 | if (!alpha2_x || !alpha2_y) |
103 | return false; | 264 | return false; |
@@ -107,7 +268,7 @@ static bool alpha2_equal(char *alpha2_x, char *alpha2_y) | |||
107 | return false; | 268 | return false; |
108 | } | 269 | } |
109 | 270 | ||
110 | static bool regdom_changed(char *alpha2) | 271 | static bool regdom_changed(const char *alpha2) |
111 | { | 272 | { |
112 | if (!cfg80211_regdomain) | 273 | if (!cfg80211_regdomain) |
113 | return true; | 274 | return true; |
@@ -130,12 +291,8 @@ static int call_crda(const char *alpha2) | |||
130 | printk(KERN_INFO "cfg80211: Calling CRDA for country: %c%c\n", | 291 | printk(KERN_INFO "cfg80211: Calling CRDA for country: %c%c\n", |
131 | alpha2[0], alpha2[1]); | 292 | alpha2[0], alpha2[1]); |
132 | else | 293 | else |
133 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
134 | return -EINVAL; | ||
135 | #else | ||
136 | printk(KERN_INFO "cfg80211: Calling CRDA to update world " | 294 | printk(KERN_INFO "cfg80211: Calling CRDA to update world " |
137 | "regulatory domain\n"); | 295 | "regulatory domain\n"); |
138 | #endif | ||
139 | 296 | ||
140 | country_env[8] = alpha2[0]; | 297 | country_env[8] = alpha2[0]; |
141 | country_env[9] = alpha2[1]; | 298 | country_env[9] = alpha2[1]; |
@@ -238,7 +395,7 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, | |||
238 | } | 395 | } |
239 | } | 396 | } |
240 | 397 | ||
241 | static bool __reg_is_valid_request(char *alpha2, | 398 | static bool __reg_is_valid_request(const char *alpha2, |
242 | struct regulatory_request **request) | 399 | struct regulatory_request **request) |
243 | { | 400 | { |
244 | struct regulatory_request *req; | 401 | struct regulatory_request *req; |
@@ -254,16 +411,16 @@ static bool __reg_is_valid_request(char *alpha2, | |||
254 | } | 411 | } |
255 | 412 | ||
256 | /* Used by nl80211 before kmalloc'ing our regulatory domain */ | 413 | /* Used by nl80211 before kmalloc'ing our regulatory domain */ |
257 | bool reg_is_valid_request(char *alpha2) | 414 | bool reg_is_valid_request(const char *alpha2) |
258 | { | 415 | { |
259 | struct regulatory_request *request = NULL; | 416 | struct regulatory_request *request = NULL; |
260 | return __reg_is_valid_request(alpha2, &request); | 417 | return __reg_is_valid_request(alpha2, &request); |
261 | } | 418 | } |
262 | 419 | ||
263 | /* Sanity check on a regulatory rule */ | 420 | /* Sanity check on a regulatory rule */ |
264 | static bool is_valid_reg_rule(struct ieee80211_reg_rule *rule) | 421 | static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule) |
265 | { | 422 | { |
266 | struct ieee80211_freq_range *freq_range = &rule->freq_range; | 423 | const struct ieee80211_freq_range *freq_range = &rule->freq_range; |
267 | u32 freq_diff; | 424 | u32 freq_diff; |
268 | 425 | ||
269 | if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0) | 426 | if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0) |
@@ -280,9 +437,9 @@ static bool is_valid_reg_rule(struct ieee80211_reg_rule *rule) | |||
280 | return true; | 437 | return true; |
281 | } | 438 | } |
282 | 439 | ||
283 | static bool is_valid_rd(struct ieee80211_regdomain *rd) | 440 | static bool is_valid_rd(const struct ieee80211_regdomain *rd) |
284 | { | 441 | { |
285 | struct ieee80211_reg_rule *reg_rule = NULL; | 442 | const struct ieee80211_reg_rule *reg_rule = NULL; |
286 | unsigned int i; | 443 | unsigned int i; |
287 | 444 | ||
288 | if (!rd->n_reg_rules) | 445 | if (!rd->n_reg_rules) |
@@ -494,12 +651,12 @@ unlock_and_exit: | |||
494 | EXPORT_SYMBOL(regulatory_hint); | 651 | EXPORT_SYMBOL(regulatory_hint); |
495 | 652 | ||
496 | 653 | ||
497 | static void print_rd_rules(struct ieee80211_regdomain *rd) | 654 | static void print_rd_rules(const struct ieee80211_regdomain *rd) |
498 | { | 655 | { |
499 | unsigned int i; | 656 | unsigned int i; |
500 | struct ieee80211_reg_rule *reg_rule = NULL; | 657 | const struct ieee80211_reg_rule *reg_rule = NULL; |
501 | struct ieee80211_freq_range *freq_range = NULL; | 658 | const struct ieee80211_freq_range *freq_range = NULL; |
502 | struct ieee80211_power_rule *power_rule = NULL; | 659 | const struct ieee80211_power_rule *power_rule = NULL; |
503 | 660 | ||
504 | printk(KERN_INFO "\t(start_freq - end_freq @ bandwidth), " | 661 | printk(KERN_INFO "\t(start_freq - end_freq @ bandwidth), " |
505 | "(max_antenna_gain, max_eirp)\n"); | 662 | "(max_antenna_gain, max_eirp)\n"); |
@@ -529,7 +686,7 @@ static void print_rd_rules(struct ieee80211_regdomain *rd) | |||
529 | } | 686 | } |
530 | } | 687 | } |
531 | 688 | ||
532 | static void print_regdomain(struct ieee80211_regdomain *rd) | 689 | static void print_regdomain(const struct ieee80211_regdomain *rd) |
533 | { | 690 | { |
534 | 691 | ||
535 | if (is_world_regdom(rd->alpha2)) | 692 | if (is_world_regdom(rd->alpha2)) |
@@ -548,85 +705,25 @@ static void print_regdomain(struct ieee80211_regdomain *rd) | |||
548 | print_rd_rules(rd); | 705 | print_rd_rules(rd); |
549 | } | 706 | } |
550 | 707 | ||
551 | void print_regdomain_info(struct ieee80211_regdomain *rd) | 708 | void print_regdomain_info(const struct ieee80211_regdomain *rd) |
552 | { | 709 | { |
553 | printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n", | 710 | printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n", |
554 | rd->alpha2[0], rd->alpha2[1]); | 711 | rd->alpha2[0], rd->alpha2[1]); |
555 | print_rd_rules(rd); | 712 | print_rd_rules(rd); |
556 | } | 713 | } |
557 | 714 | ||
558 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | 715 | static int __set_regdom(const struct ieee80211_regdomain *rd) |
559 | |||
560 | static bool is_old_static_regdom(struct ieee80211_regdomain *rd) | ||
561 | { | ||
562 | if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom) | ||
563 | return true; | ||
564 | return false; | ||
565 | } | ||
566 | |||
567 | /* The old crap never deals with a world regulatory domain, it only | ||
568 | * deals with the static regulatory domain passed and if possible | ||
569 | * an updated "US" or "JP" regulatory domain. We do however store the | ||
570 | * old static regulatory domain in cfg80211_world_regdom for convenience | ||
571 | * of use here */ | ||
572 | static void reset_regdomains_static(void) | ||
573 | { | ||
574 | if (!is_old_static_regdom(cfg80211_regdomain)) | ||
575 | kfree(cfg80211_regdomain); | ||
576 | /* This is setting the regdom to the old static regdom */ | ||
577 | cfg80211_regdomain = | ||
578 | (struct ieee80211_regdomain *) cfg80211_world_regdom; | ||
579 | } | ||
580 | #else | ||
581 | static void reset_regdomains(void) | ||
582 | { | ||
583 | if (cfg80211_world_regdom && cfg80211_world_regdom != &world_regdom) { | ||
584 | if (cfg80211_world_regdom == cfg80211_regdomain) { | ||
585 | kfree(cfg80211_regdomain); | ||
586 | } else { | ||
587 | kfree(cfg80211_world_regdom); | ||
588 | kfree(cfg80211_regdomain); | ||
589 | } | ||
590 | } else if (cfg80211_regdomain && cfg80211_regdomain != &world_regdom) | ||
591 | kfree(cfg80211_regdomain); | ||
592 | |||
593 | cfg80211_world_regdom = (struct ieee80211_regdomain *) &world_regdom; | ||
594 | cfg80211_regdomain = NULL; | ||
595 | } | ||
596 | |||
597 | /* Dynamic world regulatory domain requested by the wireless | ||
598 | * core upon initialization */ | ||
599 | static void update_world_regdomain(struct ieee80211_regdomain *rd) | ||
600 | { | ||
601 | BUG_ON(list_empty(®ulatory_requests)); | ||
602 | |||
603 | reset_regdomains(); | ||
604 | |||
605 | cfg80211_world_regdom = rd; | ||
606 | cfg80211_regdomain = rd; | ||
607 | } | ||
608 | #endif | ||
609 | |||
610 | static int __set_regdom(struct ieee80211_regdomain *rd) | ||
611 | { | 716 | { |
612 | struct regulatory_request *request = NULL; | 717 | struct regulatory_request *request = NULL; |
613 | 718 | ||
614 | /* Some basic sanity checks first */ | 719 | /* Some basic sanity checks first */ |
615 | 720 | ||
616 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
617 | /* We ignore the world regdom with the old static regdomains setup | ||
618 | * as there is no point to it with satic regulatory definitions :( | ||
619 | * Don't worry this shit will be removed soon... */ | ||
620 | if (is_world_regdom(rd->alpha2)) | ||
621 | return -EINVAL; | ||
622 | #else | ||
623 | if (is_world_regdom(rd->alpha2)) { | 721 | if (is_world_regdom(rd->alpha2)) { |
624 | if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) | 722 | if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) |
625 | return -EINVAL; | 723 | return -EINVAL; |
626 | update_world_regdomain(rd); | 724 | update_world_regdomain(rd); |
627 | return 0; | 725 | return 0; |
628 | } | 726 | } |
629 | #endif | ||
630 | 727 | ||
631 | if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) && | 728 | if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) && |
632 | !is_unknown_alpha2(rd->alpha2)) | 729 | !is_unknown_alpha2(rd->alpha2)) |
@@ -635,15 +732,10 @@ static int __set_regdom(struct ieee80211_regdomain *rd) | |||
635 | if (list_empty(®ulatory_requests)) | 732 | if (list_empty(®ulatory_requests)) |
636 | return -EINVAL; | 733 | return -EINVAL; |
637 | 734 | ||
638 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | 735 | /* allow overriding the static definitions if CRDA is present */ |
639 | /* Static "US" and "JP" will be overridden, but just once */ | ||
640 | if (!is_old_static_regdom(cfg80211_regdomain) && | 736 | if (!is_old_static_regdom(cfg80211_regdomain) && |
641 | !regdom_changed(rd->alpha2)) | 737 | !regdom_changed(rd->alpha2)) |
642 | return -EINVAL; | ||
643 | #else | ||
644 | if (!regdom_changed(rd->alpha2)) | ||
645 | return -EINVAL; | 738 | return -EINVAL; |
646 | #endif | ||
647 | 739 | ||
648 | /* Now lets set the regulatory domain, update all driver channels | 740 | /* Now lets set the regulatory domain, update all driver channels |
649 | * and finally inform them of what we have done, in case they want | 741 | * and finally inform them of what we have done, in case they want |
@@ -653,11 +745,7 @@ static int __set_regdom(struct ieee80211_regdomain *rd) | |||
653 | if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) | 745 | if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) |
654 | return -EINVAL; | 746 | return -EINVAL; |
655 | 747 | ||
656 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
657 | reset_regdomains_static(); | ||
658 | #else | ||
659 | reset_regdomains(); | 748 | reset_regdomains(); |
660 | #endif | ||
661 | 749 | ||
662 | /* Country IE parsing coming soon */ | 750 | /* Country IE parsing coming soon */ |
663 | switch (request->initiator) { | 751 | switch (request->initiator) { |
@@ -689,7 +777,7 @@ static int __set_regdom(struct ieee80211_regdomain *rd) | |||
689 | * multiple drivers can be ironed out later. Caller must've already | 777 | * multiple drivers can be ironed out later. Caller must've already |
690 | * kmalloc'd the rd structure. If this calls fails you should kfree() | 778 | * kmalloc'd the rd structure. If this calls fails you should kfree() |
691 | * the passed rd. Caller must hold cfg80211_drv_mutex */ | 779 | * the passed rd. Caller must hold cfg80211_drv_mutex */ |
692 | int set_regdom(struct ieee80211_regdomain *rd) | 780 | int set_regdom(const struct ieee80211_regdomain *rd) |
693 | { | 781 | { |
694 | struct regulatory_request *this_request = NULL, *prev_request = NULL; | 782 | struct regulatory_request *this_request = NULL, *prev_request = NULL; |
695 | int r; | 783 | int r; |
@@ -735,25 +823,50 @@ int set_regdom(struct ieee80211_regdomain *rd) | |||
735 | 823 | ||
736 | int regulatory_init(void) | 824 | int regulatory_init(void) |
737 | { | 825 | { |
826 | int err; | ||
827 | |||
738 | reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0); | 828 | reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0); |
739 | if (IS_ERR(reg_pdev)) | 829 | if (IS_ERR(reg_pdev)) |
740 | return PTR_ERR(reg_pdev); | 830 | return PTR_ERR(reg_pdev); |
831 | |||
832 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
833 | cfg80211_regdomain = static_regdom(ieee80211_regdom); | ||
834 | |||
835 | printk(KERN_INFO "cfg80211: Using static regulatory domain info\n"); | ||
836 | print_regdomain_info(cfg80211_regdomain); | ||
837 | /* The old code still requests for a new regdomain and if | ||
838 | * you have CRDA you get it updated, otherwise you get | ||
839 | * stuck with the static values. We ignore "EU" code as | ||
840 | * that is not a valid ISO / IEC 3166 alpha2 */ | ||
841 | if (ieee80211_regdom[0] != 'E' && ieee80211_regdom[1] != 'U') | ||
842 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, | ||
843 | ieee80211_regdom, NULL); | ||
844 | #else | ||
845 | cfg80211_regdomain = cfg80211_world_regdom; | ||
846 | |||
847 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL); | ||
848 | if (err) | ||
849 | printk(KERN_ERR "cfg80211: calling CRDA failed - " | ||
850 | "unable to update world regulatory domain, " | ||
851 | "using static definition\n"); | ||
852 | #endif | ||
853 | |||
741 | return 0; | 854 | return 0; |
742 | } | 855 | } |
743 | 856 | ||
744 | void regulatory_exit(void) | 857 | void regulatory_exit(void) |
745 | { | 858 | { |
746 | struct regulatory_request *req, *req_tmp; | 859 | struct regulatory_request *req, *req_tmp; |
860 | |||
747 | mutex_lock(&cfg80211_drv_mutex); | 861 | mutex_lock(&cfg80211_drv_mutex); |
748 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | 862 | |
749 | reset_regdomains_static(); | ||
750 | #else | ||
751 | reset_regdomains(); | 863 | reset_regdomains(); |
752 | #endif | 864 | |
753 | list_for_each_entry_safe(req, req_tmp, ®ulatory_requests, list) { | 865 | list_for_each_entry_safe(req, req_tmp, ®ulatory_requests, list) { |
754 | list_del(&req->list); | 866 | list_del(&req->list); |
755 | kfree(req); | 867 | kfree(req); |
756 | } | 868 | } |
757 | platform_device_unregister(reg_pdev); | 869 | platform_device_unregister(reg_pdev); |
870 | |||
758 | mutex_unlock(&cfg80211_drv_mutex); | 871 | mutex_unlock(&cfg80211_drv_mutex); |
759 | } | 872 | } |