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