aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/wireless/core.c144
-rw-r--r--net/wireless/reg.c254
-rw-r--r--net/wireless/reg.h35
3 files changed, 203 insertions, 230 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 59e4d7debf02..88cb73394864 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -29,107 +29,6 @@ MODULE_AUTHOR("Johannes Berg");
29MODULE_LICENSE("GPL"); 29MODULE_LICENSE("GPL");
30MODULE_DESCRIPTION("wireless configuration support"); 30MODULE_DESCRIPTION("wireless configuration support");
31 31
32struct list_head regulatory_requests;
33
34/* Central wireless core regulatory domains, we only need two,
35 * the current one and a world regulatory domain in case we have no
36 * information to give us an alpha2 */
37struct ieee80211_regdomain *cfg80211_regdomain;
38
39/* We keep a static world regulatory domain in case of the absence of CRDA */
40const struct ieee80211_regdomain world_regdom = {
41 .n_reg_rules = 1,
42 .alpha2 = "00",
43 .reg_rules = {
44 REG_RULE(2412-10, 2462+10, 40, 6, 20,
45 NL80211_RRF_PASSIVE_SCAN |
46 NL80211_RRF_NO_IBSS),
47 }
48};
49
50#ifdef CONFIG_WIRELESS_OLD_REGULATORY
51/* All this fucking static junk will be removed soon, so
52 * don't fucking count on it !@#$ */
53
54static char *ieee80211_regdom = "US";
55module_param(ieee80211_regdom, charp, 0444);
56MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
57
58/* We assume 40 MHz bandwidth for the old regulatory work.
59 * We make emphasis we are using the exact same frequencies
60 * as before */
61
62const struct ieee80211_regdomain us_regdom = {
63 .n_reg_rules = 6,
64 .alpha2 = "US",
65 .reg_rules = {
66 /* IEEE 802.11b/g, channels 1..11 */
67 REG_RULE(2412-10, 2462+10, 40, 6, 27, 0),
68 /* IEEE 802.11a, channel 36 */
69 REG_RULE(5180-10, 5180+10, 40, 6, 23, 0),
70 /* IEEE 802.11a, channel 40 */
71 REG_RULE(5200-10, 5200+10, 40, 6, 23, 0),
72 /* IEEE 802.11a, channel 44 */
73 REG_RULE(5220-10, 5220+10, 40, 6, 23, 0),
74 /* IEEE 802.11a, channels 48..64 */
75 REG_RULE(5240-10, 5320+10, 40, 6, 23, 0),
76 /* IEEE 802.11a, channels 149..165, outdoor */
77 REG_RULE(5745-10, 5825+10, 40, 6, 30, 0),
78 }
79};
80
81const struct ieee80211_regdomain jp_regdom = {
82 .n_reg_rules = 3,
83 .alpha2 = "JP",
84 .reg_rules = {
85 /* IEEE 802.11b/g, channels 1..14 */
86 REG_RULE(2412-10, 2484+10, 40, 6, 20, 0),
87 /* IEEE 802.11a, channels 34..48 */
88 REG_RULE(5170-10, 5240+10, 40, 6, 20,
89 NL80211_RRF_PASSIVE_SCAN),
90 /* IEEE 802.11a, channels 52..64 */
91 REG_RULE(5260-10, 5320+10, 40, 6, 20,
92 NL80211_RRF_NO_IBSS |
93 NL80211_RRF_DFS),
94 }
95};
96
97const struct ieee80211_regdomain eu_regdom = {
98 .n_reg_rules = 6,
99 /* This alpha2 is bogus, we leave it here just for stupid
100 * backward compatibility */
101 .alpha2 = "EU",
102 .reg_rules = {
103 /* IEEE 802.11b/g, channels 1..13 */
104 REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
105 /* IEEE 802.11a, channel 36 */
106 REG_RULE(5180-10, 5180+10, 40, 6, 23,
107 NL80211_RRF_PASSIVE_SCAN),
108 /* IEEE 802.11a, channel 40 */
109 REG_RULE(5200-10, 5200+10, 40, 6, 23,
110 NL80211_RRF_PASSIVE_SCAN),
111 /* IEEE 802.11a, channel 44 */
112 REG_RULE(5220-10, 5220+10, 40, 6, 23,
113 NL80211_RRF_PASSIVE_SCAN),
114 /* IEEE 802.11a, channels 48..64 */
115 REG_RULE(5240-10, 5320+10, 40, 6, 20,
116 NL80211_RRF_NO_IBSS |
117 NL80211_RRF_DFS),
118 /* IEEE 802.11a, channels 100..140 */
119 REG_RULE(5500-10, 5700+10, 40, 6, 30,
120 NL80211_RRF_NO_IBSS |
121 NL80211_RRF_DFS),
122 }
123};
124
125#endif
126
127struct ieee80211_regdomain *cfg80211_world_regdom =
128 (struct ieee80211_regdomain *) &world_regdom;
129
130LIST_HEAD(regulatory_requests);
131DEFINE_MUTEX(cfg80211_reg_mutex);
132
133/* RCU might be appropriate here since we usually 32/* RCU might be appropriate here since we usually
134 * only read the list, and that can happen quite 33 * only read the list, and that can happen quite
135 * often because we need to do it for each command */ 34 * often because we need to do it for each command */
@@ -514,34 +413,10 @@ static struct notifier_block cfg80211_netdev_notifier = {
514 .notifier_call = cfg80211_netdev_notifier_call, 413 .notifier_call = cfg80211_netdev_notifier_call,
515}; 414};
516 415
517#ifdef CONFIG_WIRELESS_OLD_REGULATORY
518const struct ieee80211_regdomain *static_regdom(char *alpha2)
519{
520 if (alpha2[0] == 'U' && alpha2[1] == 'S')
521 return &us_regdom;
522 if (alpha2[0] == 'J' && alpha2[1] == 'P')
523 return &jp_regdom;
524 if (alpha2[0] == 'E' && alpha2[1] == 'U')
525 return &eu_regdom;
526 /* Default, as per the old rules */
527 return &us_regdom;
528}
529#endif
530
531static int cfg80211_init(void) 416static int cfg80211_init(void)
532{ 417{
533 int err; 418 int err;
534 419
535#ifdef CONFIG_WIRELESS_OLD_REGULATORY
536 cfg80211_regdomain =
537 (struct ieee80211_regdomain *) static_regdom(ieee80211_regdom);
538 /* Used during reset_regdomains_static() */
539 cfg80211_world_regdom = cfg80211_regdomain;
540#else
541 cfg80211_regdomain =
542 (struct ieee80211_regdomain *) cfg80211_world_regdom;
543#endif
544
545 err = wiphy_sysfs_init(); 420 err = wiphy_sysfs_init();
546 if (err) 421 if (err)
547 goto out_fail_sysfs; 422 goto out_fail_sysfs;
@@ -560,25 +435,6 @@ static int cfg80211_init(void)
560 if (err) 435 if (err)
561 goto out_fail_reg; 436 goto out_fail_reg;
562 437
563#ifdef CONFIG_WIRELESS_OLD_REGULATORY
564 printk(KERN_INFO "cfg80211: Using old static regulatory domain:\n");
565 print_regdomain_info(cfg80211_regdomain);
566 /* The old code still requests for a new regdomain and if
567 * you have CRDA you get it updated, otherwise you get
568 * stuck with the static values. We ignore "EU" code as
569 * that is not a valid ISO / IEC 3166 alpha2 */
570 if (ieee80211_regdom[0] != 'E' &&
571 ieee80211_regdom[1] != 'U')
572 err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE,
573 ieee80211_regdom, NULL);
574#else
575 err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL);
576 if (err)
577 printk(KERN_ERR "cfg80211: calling CRDA failed - "
578 "unable to update world regulatory domain, "
579 "using static definition\n");
580#endif
581
582 return 0; 438 return 0;
583 439
584out_fail_reg: 440out_fail_reg:
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 592b2e391d42..5fbeab50996f 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,6 +63,161 @@ static u32 supported_bandwidths[] = {
51 MHZ_TO_KHZ(20), 63 MHZ_TO_KHZ(20),
52}; 64};
53 65
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 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 struct ieee80211_regdomain *cfg80211_world_regdom =
85 (struct ieee80211_regdomain *) &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(struct ieee80211_regdomain *rd)
172{
173 if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom)
174 return true;
175 return false;
176}
177
178/* The old crap never deals with a world regulatory domain, it only
179 * deals with the static regulatory domain passed and if possible
180 * an updated "US" or "JP" regulatory domain. We do however store the
181 * old static regulatory domain in cfg80211_world_regdom for convenience
182 * of use here */
183static void reset_regdomains_static(void)
184{
185 if (!is_old_static_regdom(cfg80211_regdomain))
186 kfree(cfg80211_regdomain);
187 /* This is setting the regdom to the old static regdom */
188 cfg80211_regdomain =
189 (struct ieee80211_regdomain *) cfg80211_world_regdom;
190}
191#else
192static void reset_regdomains(void)
193{
194 if (cfg80211_world_regdom && cfg80211_world_regdom != &world_regdom) {
195 if (cfg80211_world_regdom == cfg80211_regdomain) {
196 kfree(cfg80211_regdomain);
197 } else {
198 kfree(cfg80211_world_regdom);
199 kfree(cfg80211_regdomain);
200 }
201 } else if (cfg80211_regdomain && cfg80211_regdomain != &world_regdom)
202 kfree(cfg80211_regdomain);
203
204 cfg80211_world_regdom = (struct ieee80211_regdomain *) &world_regdom;
205 cfg80211_regdomain = NULL;
206}
207
208/* Dynamic world regulatory domain requested by the wireless
209 * core upon initialization */
210static void update_world_regdomain(struct ieee80211_regdomain *rd)
211{
212 BUG_ON(list_empty(&regulatory_requests));
213
214 reset_regdomains();
215
216 cfg80211_world_regdom = rd;
217 cfg80211_regdomain = rd;
218}
219#endif
220
54bool is_world_regdom(char *alpha2) 221bool is_world_regdom(char *alpha2)
55{ 222{
56 if (!alpha2) 223 if (!alpha2)
@@ -555,58 +722,6 @@ void print_regdomain_info(struct ieee80211_regdomain *rd)
555 print_rd_rules(rd); 722 print_rd_rules(rd);
556} 723}
557 724
558#ifdef CONFIG_WIRELESS_OLD_REGULATORY
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) 725static int __set_regdom(struct ieee80211_regdomain *rd)
611{ 726{
612 struct regulatory_request *request = NULL; 727 struct regulatory_request *request = NULL;
@@ -615,7 +730,7 @@ static int __set_regdom(struct ieee80211_regdomain *rd)
615 730
616#ifdef CONFIG_WIRELESS_OLD_REGULATORY 731#ifdef CONFIG_WIRELESS_OLD_REGULATORY
617 /* We ignore the world regdom with the old static regdomains setup 732 /* We ignore the world regdom with the old static regdomains setup
618 * as there is no point to it with satic regulatory definitions :( 733 * as there is no point to it with static regulatory definitions :(
619 * Don't worry this shit will be removed soon... */ 734 * Don't worry this shit will be removed soon... */
620 if (is_world_regdom(rd->alpha2)) 735 if (is_world_regdom(rd->alpha2))
621 return -EINVAL; 736 return -EINVAL;
@@ -735,25 +850,58 @@ int set_regdom(struct ieee80211_regdomain *rd)
735 850
736int regulatory_init(void) 851int regulatory_init(void)
737{ 852{
853 int err;
854
738 reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0); 855 reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0);
739 if (IS_ERR(reg_pdev)) 856 if (IS_ERR(reg_pdev))
740 return PTR_ERR(reg_pdev); 857 return PTR_ERR(reg_pdev);
858
859#ifdef CONFIG_WIRELESS_OLD_REGULATORY
860 cfg80211_regdomain =
861 (struct ieee80211_regdomain *) static_regdom(ieee80211_regdom);
862 /* Used during reset_regdomains_static() */
863 cfg80211_world_regdom = cfg80211_regdomain;
864
865 printk(KERN_INFO "cfg80211: Using old static regulatory domain:\n");
866 print_regdomain_info(cfg80211_regdomain);
867 /* The old code still requests for a new regdomain and if
868 * you have CRDA you get it updated, otherwise you get
869 * stuck with the static values. We ignore "EU" code as
870 * that is not a valid ISO / IEC 3166 alpha2 */
871 if (ieee80211_regdom[0] != 'E' && ieee80211_regdom[1] != 'U')
872 err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE,
873 ieee80211_regdom, NULL);
874#else
875 cfg80211_regdomain =
876 (struct ieee80211_regdomain *) cfg80211_world_regdom;
877
878 err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL);
879 if (err)
880 printk(KERN_ERR "cfg80211: calling CRDA failed - "
881 "unable to update world regulatory domain, "
882 "using static definition\n");
883#endif
884
741 return 0; 885 return 0;
742} 886}
743 887
744void regulatory_exit(void) 888void regulatory_exit(void)
745{ 889{
746 struct regulatory_request *req, *req_tmp; 890 struct regulatory_request *req, *req_tmp;
891
747 mutex_lock(&cfg80211_drv_mutex); 892 mutex_lock(&cfg80211_drv_mutex);
893
748#ifdef CONFIG_WIRELESS_OLD_REGULATORY 894#ifdef CONFIG_WIRELESS_OLD_REGULATORY
749 reset_regdomains_static(); 895 reset_regdomains_static();
750#else 896#else
751 reset_regdomains(); 897 reset_regdomains();
752#endif 898#endif
899
753 list_for_each_entry_safe(req, req_tmp, &regulatory_requests, list) { 900 list_for_each_entry_safe(req, req_tmp, &regulatory_requests, list) {
754 list_del(&req->list); 901 list_del(&req->list);
755 kfree(req); 902 kfree(req);
756 } 903 }
757 platform_device_unregister(reg_pdev); 904 platform_device_unregister(reg_pdev);
905
758 mutex_unlock(&cfg80211_drv_mutex); 906 mutex_unlock(&cfg80211_drv_mutex);
759} 907}
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index d75fd0232972..b169815987f4 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -1,44 +1,13 @@
1#ifndef __NET_WIRELESS_REG_H 1#ifndef __NET_WIRELESS_REG_H
2#define __NET_WIRELESS_REG_H 2#define __NET_WIRELESS_REG_H
3 3
4extern const struct ieee80211_regdomain world_regdom; 4extern struct mutex cfg80211_reg_mutex;
5#ifdef CONFIG_WIRELESS_OLD_REGULATORY
6extern const struct ieee80211_regdomain us_regdom;
7extern const struct ieee80211_regdomain jp_regdom;
8extern const struct ieee80211_regdomain eu_regdom;
9#endif
10
11extern struct ieee80211_regdomain *cfg80211_regdomain;
12extern struct ieee80211_regdomain *cfg80211_world_regdom;
13extern struct list_head regulatory_requests;
14
15struct regdom_last_setby {
16 struct wiphy *wiphy;
17 u8 initiator;
18};
19
20/* wiphy is set if this request's initiator is REGDOM_SET_BY_DRIVER */
21struct regulatory_request {
22 struct list_head list;
23 struct wiphy *wiphy;
24 int granted;
25 enum reg_set_by initiator;
26 char alpha2[2];
27};
28
29bool is_world_regdom(char *alpha2); 5bool is_world_regdom(char *alpha2);
30bool reg_is_valid_request(char *alpha2); 6bool reg_is_valid_request(char *alpha2);
31 7
32int set_regdom(struct ieee80211_regdomain *rd);
33int __regulatory_hint_alpha2(struct wiphy *wiphy, enum reg_set_by set_by,
34 const char *alpha2);
35
36int regulatory_init(void); 8int regulatory_init(void);
37void regulatory_exit(void); 9void regulatory_exit(void);
38 10
39void print_regdomain_info(struct ieee80211_regdomain *); 11int set_regdom(struct ieee80211_regdomain *rd);
40
41/* If a char is A-Z */
42#define IS_ALPHA(letter) (letter >= 65 && letter <= 90)
43 12
44#endif /* __NET_WIRELESS_REG_H */ 13#endif /* __NET_WIRELESS_REG_H */