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.c311
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 */
46struct 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
54static LIST_HEAD(regulatory_requests);
55DEFINE_MUTEX(cfg80211_reg_mutex);
56
45/* To trigger userspace events */ 57/* To trigger userspace events */
46static struct platform_device *reg_pdev; 58static 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
54bool is_world_regdom(char *alpha2) 66static 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 */
71static const struct ieee80211_regdomain *cfg80211_regdomain;
72
73/* We keep a static world regulatory domain in case of the absence of CRDA */
74static 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
84static const struct ieee80211_regdomain *cfg80211_world_regdom =
85 &world_regdom;
86
87#ifdef CONFIG_WIRELESS_OLD_REGULATORY
88static char *ieee80211_regdom = "US";
89module_param(ieee80211_regdom, charp, 0444);
90MODULE_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
96static 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
115static 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
131static 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
159static 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
171static 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
178static inline bool is_old_static_regdom(const struct ieee80211_regdomain *rd)
179{
180 return false;
181}
182#endif
183
184static 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 */
205static void update_world_regdomain(const struct ieee80211_regdomain *rd)
206{
207 BUG_ON(list_empty(&regulatory_requests));
208
209 reset_regdomains();
210
211 cfg80211_world_regdom = rd;
212 cfg80211_regdomain = rd;
213}
214
215bool 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
63static bool is_alpha2_set(char *alpha2) 224static 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
80static bool is_unknown_alpha2(char *alpha2) 241static 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
91static bool is_an_alpha2(char *alpha2) 252static 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
100static bool alpha2_equal(char *alpha2_x, char *alpha2_y) 261static 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
110static bool regdom_changed(char *alpha2) 271static 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
241static bool __reg_is_valid_request(char *alpha2, 398static 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 */
257bool reg_is_valid_request(char *alpha2) 414bool 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 */
264static bool is_valid_reg_rule(struct ieee80211_reg_rule *rule) 421static 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
283static bool is_valid_rd(struct ieee80211_regdomain *rd) 440static 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:
494EXPORT_SYMBOL(regulatory_hint); 651EXPORT_SYMBOL(regulatory_hint);
495 652
496 653
497static void print_rd_rules(struct ieee80211_regdomain *rd) 654static 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
532static void print_regdomain(struct ieee80211_regdomain *rd) 689static 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
551void print_regdomain_info(struct ieee80211_regdomain *rd) 708void 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 715static int __set_regdom(const struct ieee80211_regdomain *rd)
559
560static 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 */
572static 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
581static 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 */
599static void update_world_regdomain(struct ieee80211_regdomain *rd)
600{
601 BUG_ON(list_empty(&regulatory_requests));
602
603 reset_regdomains();
604
605 cfg80211_world_regdom = rd;
606 cfg80211_regdomain = rd;
607}
608#endif
609
610static 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(&regulatory_requests)) 732 if (list_empty(&regulatory_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 */
692int set_regdom(struct ieee80211_regdomain *rd) 780int 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
736int regulatory_init(void) 824int 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
744void regulatory_exit(void) 857void 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, &regulatory_requests, list) { 865 list_for_each_entry_safe(req, req_tmp, &regulatory_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}