wireless: remove cfg80211_reg_mutex
[linux-2.6-block.git] / net / wireless / reg.c
CommitLineData
8318d78a
JB
1/*
2 * Copyright 2002-2005, Instant802 Networks, Inc.
3 * Copyright 2005-2006, Devicescape Software, Inc.
4 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
b2e1b302 5 * Copyright 2008 Luis R. Rodriguez <lrodriguz@atheros.com>
8318d78a
JB
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
b2e1b302
LR
12/**
13 * DOC: Wireless regulatory infrastructure
8318d78a
JB
14 *
15 * The usual implementation is for a driver to read a device EEPROM to
16 * determine which regulatory domain it should be operating under, then
17 * looking up the allowable channels in a driver-local table and finally
18 * registering those channels in the wiphy structure.
19 *
b2e1b302
LR
20 * Another set of compliance enforcement is for drivers to use their
21 * own compliance limits which can be stored on the EEPROM. The host
22 * driver or firmware may ensure these are used.
23 *
24 * In addition to all this we provide an extra layer of regulatory
25 * conformance. For drivers which do not have any regulatory
26 * information CRDA provides the complete regulatory solution.
27 * For others it provides a community effort on further restrictions
28 * to enhance compliance.
29 *
30 * Note: When number of rules --> infinity we will not be able to
31 * index on alpha2 any more, instead we'll probably have to
32 * rely on some SHA1 checksum of the regdomain for example.
33 *
8318d78a
JB
34 */
35#include <linux/kernel.h>
b2e1b302
LR
36#include <linux/list.h>
37#include <linux/random.h>
38#include <linux/nl80211.h>
39#include <linux/platform_device.h>
8318d78a 40#include <net/wireless.h>
b2e1b302 41#include <net/cfg80211.h>
8318d78a 42#include "core.h"
b2e1b302 43#include "reg.h"
8318d78a 44
734366de
JB
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);
734366de 55
b2e1b302
LR
56/* To trigger userspace events */
57static struct platform_device *reg_pdev;
8318d78a 58
b2e1b302
LR
59/* Keep the ordering from large to small */
60static u32 supported_bandwidths[] = {
61 MHZ_TO_KHZ(40),
62 MHZ_TO_KHZ(20),
8318d78a
JB
63};
64
734366de
JB
65/* Central wireless core regulatory domains, we only need two,
66 * the current one and a world regulatory domain in case we have no
67 * information to give us an alpha2 */
a3d2eaf0 68static const struct ieee80211_regdomain *cfg80211_regdomain;
734366de
JB
69
70/* We keep a static world regulatory domain in case of the absence of CRDA */
71static const struct ieee80211_regdomain world_regdom = {
72 .n_reg_rules = 1,
73 .alpha2 = "00",
74 .reg_rules = {
75 REG_RULE(2412-10, 2462+10, 40, 6, 20,
76 NL80211_RRF_PASSIVE_SCAN |
77 NL80211_RRF_NO_IBSS),
78 }
79};
80
a3d2eaf0
JB
81static const struct ieee80211_regdomain *cfg80211_world_regdom =
82 &world_regdom;
734366de
JB
83
84#ifdef CONFIG_WIRELESS_OLD_REGULATORY
85static char *ieee80211_regdom = "US";
86module_param(ieee80211_regdom, charp, 0444);
87MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
88
89/* We assume 40 MHz bandwidth for the old regulatory work.
90 * We make emphasis we are using the exact same frequencies
91 * as before */
92
93static const struct ieee80211_regdomain us_regdom = {
94 .n_reg_rules = 6,
95 .alpha2 = "US",
96 .reg_rules = {
97 /* IEEE 802.11b/g, channels 1..11 */
98 REG_RULE(2412-10, 2462+10, 40, 6, 27, 0),
99 /* IEEE 802.11a, channel 36 */
100 REG_RULE(5180-10, 5180+10, 40, 6, 23, 0),
101 /* IEEE 802.11a, channel 40 */
102 REG_RULE(5200-10, 5200+10, 40, 6, 23, 0),
103 /* IEEE 802.11a, channel 44 */
104 REG_RULE(5220-10, 5220+10, 40, 6, 23, 0),
105 /* IEEE 802.11a, channels 48..64 */
106 REG_RULE(5240-10, 5320+10, 40, 6, 23, 0),
107 /* IEEE 802.11a, channels 149..165, outdoor */
108 REG_RULE(5745-10, 5825+10, 40, 6, 30, 0),
109 }
110};
111
112static const struct ieee80211_regdomain jp_regdom = {
113 .n_reg_rules = 3,
114 .alpha2 = "JP",
115 .reg_rules = {
116 /* IEEE 802.11b/g, channels 1..14 */
117 REG_RULE(2412-10, 2484+10, 40, 6, 20, 0),
118 /* IEEE 802.11a, channels 34..48 */
119 REG_RULE(5170-10, 5240+10, 40, 6, 20,
120 NL80211_RRF_PASSIVE_SCAN),
121 /* IEEE 802.11a, channels 52..64 */
122 REG_RULE(5260-10, 5320+10, 40, 6, 20,
123 NL80211_RRF_NO_IBSS |
124 NL80211_RRF_DFS),
125 }
126};
127
128static const struct ieee80211_regdomain eu_regdom = {
129 .n_reg_rules = 6,
130 /* This alpha2 is bogus, we leave it here just for stupid
131 * backward compatibility */
132 .alpha2 = "EU",
133 .reg_rules = {
134 /* IEEE 802.11b/g, channels 1..13 */
135 REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
136 /* IEEE 802.11a, channel 36 */
137 REG_RULE(5180-10, 5180+10, 40, 6, 23,
138 NL80211_RRF_PASSIVE_SCAN),
139 /* IEEE 802.11a, channel 40 */
140 REG_RULE(5200-10, 5200+10, 40, 6, 23,
141 NL80211_RRF_PASSIVE_SCAN),
142 /* IEEE 802.11a, channel 44 */
143 REG_RULE(5220-10, 5220+10, 40, 6, 23,
144 NL80211_RRF_PASSIVE_SCAN),
145 /* IEEE 802.11a, channels 48..64 */
146 REG_RULE(5240-10, 5320+10, 40, 6, 20,
147 NL80211_RRF_NO_IBSS |
148 NL80211_RRF_DFS),
149 /* IEEE 802.11a, channels 100..140 */
150 REG_RULE(5500-10, 5700+10, 40, 6, 30,
151 NL80211_RRF_NO_IBSS |
152 NL80211_RRF_DFS),
153 }
154};
155
156static const struct ieee80211_regdomain *static_regdom(char *alpha2)
157{
158 if (alpha2[0] == 'U' && alpha2[1] == 'S')
159 return &us_regdom;
160 if (alpha2[0] == 'J' && alpha2[1] == 'P')
161 return &jp_regdom;
162 if (alpha2[0] == 'E' && alpha2[1] == 'U')
163 return &eu_regdom;
164 /* Default, as per the old rules */
165 return &us_regdom;
166}
167
a3d2eaf0 168static bool is_old_static_regdom(const struct ieee80211_regdomain *rd)
734366de
JB
169{
170 if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom)
171 return true;
172 return false;
173}
942b25cf
JB
174#else
175static inline bool is_old_static_regdom(const struct ieee80211_regdomain *rd)
734366de 176{
942b25cf 177 return false;
734366de 178}
942b25cf
JB
179#endif
180
734366de
JB
181static void reset_regdomains(void)
182{
942b25cf
JB
183 /* avoid freeing static information or freeing something twice */
184 if (cfg80211_regdomain == cfg80211_world_regdom)
185 cfg80211_regdomain = NULL;
186 if (cfg80211_world_regdom == &world_regdom)
187 cfg80211_world_regdom = NULL;
188 if (cfg80211_regdomain == &world_regdom)
189 cfg80211_regdomain = NULL;
190 if (is_old_static_regdom(cfg80211_regdomain))
191 cfg80211_regdomain = NULL;
192
193 kfree(cfg80211_regdomain);
194 kfree(cfg80211_world_regdom);
734366de 195
a3d2eaf0 196 cfg80211_world_regdom = &world_regdom;
734366de
JB
197 cfg80211_regdomain = NULL;
198}
199
200/* Dynamic world regulatory domain requested by the wireless
201 * core upon initialization */
a3d2eaf0 202static void update_world_regdomain(const struct ieee80211_regdomain *rd)
734366de
JB
203{
204 BUG_ON(list_empty(&regulatory_requests));
205
206 reset_regdomains();
207
208 cfg80211_world_regdom = rd;
209 cfg80211_regdomain = rd;
210}
734366de 211
a3d2eaf0 212bool is_world_regdom(const char *alpha2)
b2e1b302
LR
213{
214 if (!alpha2)
215 return false;
216 if (alpha2[0] == '0' && alpha2[1] == '0')
217 return true;
218 return false;
219}
8318d78a 220
a3d2eaf0 221static bool is_alpha2_set(const char *alpha2)
b2e1b302
LR
222{
223 if (!alpha2)
224 return false;
225 if (alpha2[0] != 0 && alpha2[1] != 0)
226 return true;
227 return false;
228}
8318d78a 229
b2e1b302
LR
230static bool is_alpha_upper(char letter)
231{
232 /* ASCII A - Z */
233 if (letter >= 65 && letter <= 90)
234 return true;
235 return false;
236}
8318d78a 237
a3d2eaf0 238static bool is_unknown_alpha2(const char *alpha2)
b2e1b302
LR
239{
240 if (!alpha2)
241 return false;
242 /* Special case where regulatory domain was built by driver
243 * but a specific alpha2 cannot be determined */
244 if (alpha2[0] == '9' && alpha2[1] == '9')
245 return true;
246 return false;
247}
8318d78a 248
a3d2eaf0 249static bool is_an_alpha2(const char *alpha2)
b2e1b302
LR
250{
251 if (!alpha2)
252 return false;
253 if (is_alpha_upper(alpha2[0]) && is_alpha_upper(alpha2[1]))
254 return true;
255 return false;
256}
8318d78a 257
a3d2eaf0 258static bool alpha2_equal(const char *alpha2_x, const char *alpha2_y)
b2e1b302
LR
259{
260 if (!alpha2_x || !alpha2_y)
261 return false;
262 if (alpha2_x[0] == alpha2_y[0] &&
263 alpha2_x[1] == alpha2_y[1])
264 return true;
265 return false;
266}
267
a3d2eaf0 268static bool regdom_changed(const char *alpha2)
b2e1b302
LR
269{
270 if (!cfg80211_regdomain)
271 return true;
272 if (alpha2_equal(cfg80211_regdomain->alpha2, alpha2))
273 return false;
274 return true;
275}
276
277/* This lets us keep regulatory code which is updated on a regulatory
278 * basis in userspace. */
279static int call_crda(const char *alpha2)
280{
281 char country_env[9 + 2] = "COUNTRY=";
282 char *envp[] = {
283 country_env,
284 NULL
285 };
286
287 if (!is_world_regdom((char *) alpha2))
288 printk(KERN_INFO "cfg80211: Calling CRDA for country: %c%c\n",
289 alpha2[0], alpha2[1]);
290 else
b2e1b302
LR
291 printk(KERN_INFO "cfg80211: Calling CRDA to update world "
292 "regulatory domain\n");
b2e1b302
LR
293
294 country_env[8] = alpha2[0];
295 country_env[9] = alpha2[1];
296
297 return kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, envp);
298}
299
300/* This has the logic which determines when a new request
301 * should be ignored. */
302static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by,
303 char *alpha2, struct ieee80211_regdomain *rd)
304{
305 struct regulatory_request *last_request = NULL;
59d393ad 306
b2e1b302
LR
307 /* All initial requests are respected */
308 if (list_empty(&regulatory_requests))
309 return 0;
310
311 last_request = list_first_entry(&regulatory_requests,
312 struct regulatory_request, list);
313
314 switch (set_by) {
315 case REGDOM_SET_BY_INIT:
316 return -EINVAL;
317 case REGDOM_SET_BY_CORE:
318 /* Always respect new wireless core hints, should only
319 * come in for updating the world regulatory domain at init
320 * anyway */
321 return 0;
322 case REGDOM_SET_BY_COUNTRY_IE:
323 if (last_request->initiator == set_by) {
324 if (last_request->wiphy != wiphy) {
325 /* Two cards with two APs claiming different
326 * different Country IE alpha2s!
327 * You're special!! */
328 if (!alpha2_equal(last_request->alpha2,
329 cfg80211_regdomain->alpha2)) {
330 /* XXX: Deal with conflict, consider
331 * building a new one out of the
332 * intersection */
333 WARN_ON(1);
334 return -EOPNOTSUPP;
335 }
336 return -EALREADY;
337 }
338 /* Two consecutive Country IE hints on the same wiphy */
339 if (!alpha2_equal(cfg80211_regdomain->alpha2, alpha2))
340 return 0;
341 return -EALREADY;
342 }
343 if (WARN_ON(!is_alpha2_set(alpha2) || !is_an_alpha2(alpha2)),
344 "Invalid Country IE regulatory hint passed "
345 "to the wireless core\n")
346 return -EINVAL;
347 /* We ignore Country IE hints for now, as we haven't yet
348 * added the dot11MultiDomainCapabilityEnabled flag
349 * for wiphys */
350 return 1;
351 case REGDOM_SET_BY_DRIVER:
352 BUG_ON(!wiphy);
353 if (last_request->initiator == set_by) {
354 /* Two separate drivers hinting different things,
355 * this is possible if you have two devices present
356 * on a system with different EEPROM regulatory
357 * readings. XXX: Do intersection, we support only
358 * the first regulatory hint for now */
359 if (last_request->wiphy != wiphy)
360 return -EALREADY;
361 if (rd)
362 return -EALREADY;
363 /* Driver should not be trying to hint different
364 * regulatory domains! */
365 BUG_ON(!alpha2_equal(alpha2,
366 cfg80211_regdomain->alpha2));
367 return -EALREADY;
368 }
369 if (last_request->initiator == REGDOM_SET_BY_CORE)
370 return 0;
371 /* XXX: Handle intersection, and add the
372 * dot11MultiDomainCapabilityEnabled flag to wiphy. For now
373 * we assume the driver has this set to false, following the
374 * 802.11d dot11MultiDomainCapabilityEnabled documentation */
375 if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE)
376 return 0;
377 return 0;
378 case REGDOM_SET_BY_USER:
379 if (last_request->initiator == set_by ||
380 last_request->initiator == REGDOM_SET_BY_CORE)
381 return 0;
382 /* Drivers can use their wiphy's reg_notifier()
383 * to override any information */
384 if (last_request->initiator == REGDOM_SET_BY_DRIVER)
385 return 0;
386 /* XXX: Handle intersection */
387 if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE)
388 return -EOPNOTSUPP;
389 return 0;
390 default:
391 return -EINVAL;
8318d78a 392 }
b2e1b302 393}
8318d78a 394
a3d2eaf0 395static bool __reg_is_valid_request(const char *alpha2,
b2e1b302
LR
396 struct regulatory_request **request)
397{
398 struct regulatory_request *req;
399 if (list_empty(&regulatory_requests))
400 return false;
401 list_for_each_entry(req, &regulatory_requests, list) {
402 if (alpha2_equal(req->alpha2, alpha2)) {
403 *request = req;
404 return true;
405 }
406 }
407 return false;
408}
8318d78a 409
b2e1b302 410/* Used by nl80211 before kmalloc'ing our regulatory domain */
a3d2eaf0 411bool reg_is_valid_request(const char *alpha2)
b2e1b302
LR
412{
413 struct regulatory_request *request = NULL;
414 return __reg_is_valid_request(alpha2, &request);
415}
8318d78a 416
b2e1b302 417/* Sanity check on a regulatory rule */
a3d2eaf0 418static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
8318d78a 419{
a3d2eaf0 420 const struct ieee80211_freq_range *freq_range = &rule->freq_range;
b2e1b302
LR
421 u32 freq_diff;
422
423 if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0)
424 return false;
425
426 if (freq_range->start_freq_khz > freq_range->end_freq_khz)
427 return false;
428
429 freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
430
431 if (freq_range->max_bandwidth_khz > freq_diff)
432 return false;
433
434 return true;
435}
436
a3d2eaf0 437static bool is_valid_rd(const struct ieee80211_regdomain *rd)
b2e1b302 438{
a3d2eaf0 439 const struct ieee80211_reg_rule *reg_rule = NULL;
b2e1b302 440 unsigned int i;
8318d78a 441
b2e1b302
LR
442 if (!rd->n_reg_rules)
443 return false;
8318d78a 444
b2e1b302
LR
445 for (i = 0; i < rd->n_reg_rules; i++) {
446 reg_rule = &rd->reg_rules[i];
447 if (!is_valid_reg_rule(reg_rule))
448 return false;
449 }
450
451 return true;
8318d78a
JB
452}
453
b2e1b302
LR
454/* Returns value in KHz */
455static u32 freq_max_bandwidth(const struct ieee80211_freq_range *freq_range,
456 u32 freq)
457{
458 unsigned int i;
459 for (i = 0; i < ARRAY_SIZE(supported_bandwidths); i++) {
460 u32 start_freq_khz = freq - supported_bandwidths[i]/2;
461 u32 end_freq_khz = freq + supported_bandwidths[i]/2;
462 if (start_freq_khz >= freq_range->start_freq_khz &&
463 end_freq_khz <= freq_range->end_freq_khz)
464 return supported_bandwidths[i];
465 }
466 return 0;
467}
8318d78a 468
b2e1b302
LR
469/* XXX: add support for the rest of enum nl80211_reg_rule_flags, we may
470 * want to just have the channel structure use these */
471static u32 map_regdom_flags(u32 rd_flags)
472{
473 u32 channel_flags = 0;
474 if (rd_flags & NL80211_RRF_PASSIVE_SCAN)
475 channel_flags |= IEEE80211_CHAN_PASSIVE_SCAN;
476 if (rd_flags & NL80211_RRF_NO_IBSS)
477 channel_flags |= IEEE80211_CHAN_NO_IBSS;
478 if (rd_flags & NL80211_RRF_DFS)
479 channel_flags |= IEEE80211_CHAN_RADAR;
480 return channel_flags;
481}
482
483/**
484 * freq_reg_info - get regulatory information for the given frequency
485 * @center_freq: Frequency in KHz for which we want regulatory information for
486 * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one
487 * you can set this to 0. If this frequency is allowed we then set
488 * this value to the maximum allowed bandwidth.
489 * @reg_rule: the regulatory rule which we have for this frequency
490 *
491 * Use this function to get the regulatory rule for a specific frequency.
492 */
493static int freq_reg_info(u32 center_freq, u32 *bandwidth,
494 const struct ieee80211_reg_rule **reg_rule)
8318d78a
JB
495{
496 int i;
b2e1b302 497 u32 max_bandwidth = 0;
8318d78a 498
b2e1b302
LR
499 if (!cfg80211_regdomain)
500 return -EINVAL;
501
502 for (i = 0; i < cfg80211_regdomain->n_reg_rules; i++) {
503 const struct ieee80211_reg_rule *rr;
504 const struct ieee80211_freq_range *fr = NULL;
505 const struct ieee80211_power_rule *pr = NULL;
506
507 rr = &cfg80211_regdomain->reg_rules[i];
508 fr = &rr->freq_range;
509 pr = &rr->power_rule;
510 max_bandwidth = freq_max_bandwidth(fr, center_freq);
511 if (max_bandwidth && *bandwidth <= max_bandwidth) {
512 *reg_rule = rr;
513 *bandwidth = max_bandwidth;
8318d78a
JB
514 break;
515 }
516 }
517
b2e1b302
LR
518 return !max_bandwidth;
519}
520
521static void handle_channel(struct ieee80211_channel *chan)
522{
523 int r;
524 u32 flags = chan->orig_flags;
525 u32 max_bandwidth = 0;
526 const struct ieee80211_reg_rule *reg_rule = NULL;
527 const struct ieee80211_power_rule *power_rule = NULL;
528
529 r = freq_reg_info(MHZ_TO_KHZ(chan->center_freq),
530 &max_bandwidth, &reg_rule);
531
532 if (r) {
8318d78a
JB
533 flags |= IEEE80211_CHAN_DISABLED;
534 chan->flags = flags;
535 return;
536 }
537
b2e1b302
LR
538 power_rule = &reg_rule->power_rule;
539
540 chan->flags = flags | map_regdom_flags(reg_rule->flags);
8318d78a 541 chan->max_antenna_gain = min(chan->orig_mag,
b2e1b302
LR
542 (int) MBI_TO_DBI(power_rule->max_antenna_gain));
543 chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth);
253898c4 544 if (chan->orig_mpwr)
b2e1b302
LR
545 chan->max_power = min(chan->orig_mpwr,
546 (int) MBM_TO_DBM(power_rule->max_eirp));
253898c4 547 else
b2e1b302 548 chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
8318d78a
JB
549}
550
b2e1b302 551static void handle_band(struct ieee80211_supported_band *sband)
8318d78a
JB
552{
553 int i;
554
555 for (i = 0; i < sband->n_channels; i++)
b2e1b302 556 handle_channel(&sband->channels[i]);
8318d78a
JB
557}
558
b2e1b302 559static void update_all_wiphy_regulatory(enum reg_set_by setby)
8318d78a 560{
b2e1b302 561 struct cfg80211_registered_device *drv;
8318d78a 562
b2e1b302
LR
563 list_for_each_entry(drv, &cfg80211_drv_list, list)
564 wiphy_update_regulatory(&drv->wiphy, setby);
565}
566
567void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby)
568{
569 enum ieee80211_band band;
570 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
8318d78a 571 if (wiphy->bands[band])
b2e1b302
LR
572 handle_band(wiphy->bands[band]);
573 if (wiphy->reg_notifier)
574 wiphy->reg_notifier(wiphy, setby);
575 }
576}
577
578/* Caller must hold &cfg80211_drv_mutex */
579int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by,
580 const char *alpha2, struct ieee80211_regdomain *rd)
581{
582 struct regulatory_request *request;
583 char *rd_alpha2;
584 int r = 0;
585
586 r = ignore_request(wiphy, set_by, (char *) alpha2, rd);
587 if (r)
588 return r;
589
590 if (rd)
591 rd_alpha2 = rd->alpha2;
592 else
593 rd_alpha2 = (char *) alpha2;
594
595 switch (set_by) {
596 case REGDOM_SET_BY_CORE:
597 case REGDOM_SET_BY_COUNTRY_IE:
598 case REGDOM_SET_BY_DRIVER:
599 case REGDOM_SET_BY_USER:
600 request = kzalloc(sizeof(struct regulatory_request),
601 GFP_KERNEL);
602 if (!request)
603 return -ENOMEM;
604
605 request->alpha2[0] = rd_alpha2[0];
606 request->alpha2[1] = rd_alpha2[1];
607 request->initiator = set_by;
608 request->wiphy = wiphy;
609
610 list_add_tail(&request->list, &regulatory_requests);
611 if (rd)
612 break;
613 r = call_crda(alpha2);
614#ifndef CONFIG_WIRELESS_OLD_REGULATORY
615 if (r)
616 printk(KERN_ERR "cfg80211: Failed calling CRDA\n");
617#endif
618 break;
619 default:
620 r = -ENOTSUPP;
621 break;
622 }
623
624 return r;
625}
626
627/* If rd is not NULL and if this call fails the caller must free it */
628int regulatory_hint(struct wiphy *wiphy, const char *alpha2,
629 struct ieee80211_regdomain *rd)
630{
631 int r;
632 BUG_ON(!rd && !alpha2);
633
634 mutex_lock(&cfg80211_drv_mutex);
635
636 r = __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2, rd);
637 if (r || !rd)
638 goto unlock_and_exit;
639
640 /* If the driver passed a regulatory domain we skipped asking
641 * userspace for one so we can now go ahead and set it */
642 r = set_regdom(rd);
643
644unlock_and_exit:
645 mutex_unlock(&cfg80211_drv_mutex);
646 return r;
647}
648EXPORT_SYMBOL(regulatory_hint);
649
650
a3d2eaf0 651static void print_rd_rules(const struct ieee80211_regdomain *rd)
b2e1b302
LR
652{
653 unsigned int i;
a3d2eaf0
JB
654 const struct ieee80211_reg_rule *reg_rule = NULL;
655 const struct ieee80211_freq_range *freq_range = NULL;
656 const struct ieee80211_power_rule *power_rule = NULL;
b2e1b302
LR
657
658 printk(KERN_INFO "\t(start_freq - end_freq @ bandwidth), "
659 "(max_antenna_gain, max_eirp)\n");
660
661 for (i = 0; i < rd->n_reg_rules; i++) {
662 reg_rule = &rd->reg_rules[i];
663 freq_range = &reg_rule->freq_range;
664 power_rule = &reg_rule->power_rule;
665
666 /* There may not be documentation for max antenna gain
667 * in certain regions */
668 if (power_rule->max_antenna_gain)
669 printk(KERN_INFO "\t(%d KHz - %d KHz @ %d KHz), "
670 "(%d mBi, %d mBm)\n",
671 freq_range->start_freq_khz,
672 freq_range->end_freq_khz,
673 freq_range->max_bandwidth_khz,
674 power_rule->max_antenna_gain,
675 power_rule->max_eirp);
676 else
677 printk(KERN_INFO "\t(%d KHz - %d KHz @ %d KHz), "
678 "(N/A, %d mBm)\n",
679 freq_range->start_freq_khz,
680 freq_range->end_freq_khz,
681 freq_range->max_bandwidth_khz,
682 power_rule->max_eirp);
683 }
684}
685
a3d2eaf0 686static void print_regdomain(const struct ieee80211_regdomain *rd)
b2e1b302
LR
687{
688
689 if (is_world_regdom(rd->alpha2))
690 printk(KERN_INFO "cfg80211: World regulatory "
691 "domain updated:\n");
692 else {
693 if (is_unknown_alpha2(rd->alpha2))
694 printk(KERN_INFO "cfg80211: Regulatory domain "
695 "changed to driver built-in settings "
696 "(unknown country)\n");
697 else
698 printk(KERN_INFO "cfg80211: Regulatory domain "
699 "changed to country: %c%c\n",
700 rd->alpha2[0], rd->alpha2[1]);
701 }
702 print_rd_rules(rd);
703}
704
a3d2eaf0 705void print_regdomain_info(const struct ieee80211_regdomain *rd)
b2e1b302
LR
706{
707 printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n",
708 rd->alpha2[0], rd->alpha2[1]);
709 print_rd_rules(rd);
710}
711
a3d2eaf0 712static int __set_regdom(const struct ieee80211_regdomain *rd)
b2e1b302
LR
713{
714 struct regulatory_request *request = NULL;
715
716 /* Some basic sanity checks first */
717
b2e1b302
LR
718 if (is_world_regdom(rd->alpha2)) {
719 if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request)))
720 return -EINVAL;
721 update_world_regdomain(rd);
722 return 0;
723 }
b2e1b302
LR
724
725 if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) &&
726 !is_unknown_alpha2(rd->alpha2))
727 return -EINVAL;
728
729 if (list_empty(&regulatory_requests))
730 return -EINVAL;
731
942b25cf 732 /* allow overriding the static definitions if CRDA is present */
b2e1b302 733 if (!is_old_static_regdom(cfg80211_regdomain) &&
942b25cf 734 !regdom_changed(rd->alpha2))
b2e1b302 735 return -EINVAL;
b2e1b302
LR
736
737 /* Now lets set the regulatory domain, update all driver channels
738 * and finally inform them of what we have done, in case they want
739 * to review or adjust their own settings based on their own
740 * internal EEPROM data */
741
742 if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request)))
743 return -EINVAL;
744
b2e1b302 745 reset_regdomains();
b2e1b302
LR
746
747 /* Country IE parsing coming soon */
748 switch (request->initiator) {
749 case REGDOM_SET_BY_CORE:
750 case REGDOM_SET_BY_DRIVER:
751 case REGDOM_SET_BY_USER:
752 if (!is_valid_rd(rd)) {
753 printk(KERN_ERR "cfg80211: Invalid "
754 "regulatory domain detected:\n");
755 print_regdomain_info(rd);
756 return -EINVAL;
757 }
758 break;
759 case REGDOM_SET_BY_COUNTRY_IE: /* Not yet */
760 WARN_ON(1);
761 default:
762 return -EOPNOTSUPP;
763 }
764
765 /* Tada! */
766 cfg80211_regdomain = rd;
767 request->granted = 1;
768
769 return 0;
770}
771
772
773/* Use this call to set the current regulatory domain. Conflicts with
774 * multiple drivers can be ironed out later. Caller must've already
775 * kmalloc'd the rd structure. If this calls fails you should kfree()
776 * the passed rd. Caller must hold cfg80211_drv_mutex */
a3d2eaf0 777int set_regdom(const struct ieee80211_regdomain *rd)
b2e1b302
LR
778{
779 struct regulatory_request *this_request = NULL, *prev_request = NULL;
780 int r;
781
782 if (!list_empty(&regulatory_requests))
783 prev_request = list_first_entry(&regulatory_requests,
784 struct regulatory_request, list);
785
786 /* Note that this doesn't update the wiphys, this is done below */
787 r = __set_regdom(rd);
788 if (r)
789 return r;
790
791 BUG_ON((!__reg_is_valid_request(rd->alpha2, &this_request)));
792
793 /* The initial standard core update of the world regulatory domain, no
794 * need to keep that request info around if it didn't fail. */
795 if (is_world_regdom(rd->alpha2) &&
796 this_request->initiator == REGDOM_SET_BY_CORE &&
797 this_request->granted) {
798 list_del(&this_request->list);
799 kfree(this_request);
800 this_request = NULL;
801 }
802
803 /* Remove old requests, we only leave behind the last one */
804 if (prev_request) {
805 list_del(&prev_request->list);
806 kfree(prev_request);
807 prev_request = NULL;
808 }
809
810 /* This would make this whole thing pointless */
811 BUG_ON(rd != cfg80211_regdomain);
812
813 /* update all wiphys now with the new established regulatory domain */
814 update_all_wiphy_regulatory(this_request->initiator);
815
816 print_regdomain(rd);
817
818 return r;
819}
820
821int regulatory_init(void)
822{
734366de
JB
823 int err;
824
b2e1b302
LR
825 reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0);
826 if (IS_ERR(reg_pdev))
827 return PTR_ERR(reg_pdev);
734366de
JB
828
829#ifdef CONFIG_WIRELESS_OLD_REGULATORY
a3d2eaf0 830 cfg80211_regdomain = static_regdom(ieee80211_regdom);
734366de 831
942b25cf 832 printk(KERN_INFO "cfg80211: Using static regulatory domain info\n");
734366de
JB
833 print_regdomain_info(cfg80211_regdomain);
834 /* The old code still requests for a new regdomain and if
835 * you have CRDA you get it updated, otherwise you get
836 * stuck with the static values. We ignore "EU" code as
837 * that is not a valid ISO / IEC 3166 alpha2 */
838 if (ieee80211_regdom[0] != 'E' && ieee80211_regdom[1] != 'U')
839 err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE,
840 ieee80211_regdom, NULL);
841#else
a3d2eaf0 842 cfg80211_regdomain = cfg80211_world_regdom;
734366de
JB
843
844 err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL);
845 if (err)
846 printk(KERN_ERR "cfg80211: calling CRDA failed - "
847 "unable to update world regulatory domain, "
848 "using static definition\n");
849#endif
850
b2e1b302
LR
851 return 0;
852}
853
854void regulatory_exit(void)
855{
856 struct regulatory_request *req, *req_tmp;
734366de 857
b2e1b302 858 mutex_lock(&cfg80211_drv_mutex);
734366de 859
b2e1b302 860 reset_regdomains();
734366de 861
b2e1b302
LR
862 list_for_each_entry_safe(req, req_tmp, &regulatory_requests, list) {
863 list_del(&req->list);
864 kfree(req);
865 }
866 platform_device_unregister(reg_pdev);
734366de 867
b2e1b302 868 mutex_unlock(&cfg80211_drv_mutex);
8318d78a 869}