diff options
-rw-r--r-- | Documentation/networking/regulatory.txt | 11 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_mac.c | 2 | ||||
-rw-r--r-- | include/net/wireless.h | 23 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 2 | ||||
-rw-r--r-- | net/wireless/reg.c | 63 | ||||
-rw-r--r-- | net/wireless/reg.h | 23 |
6 files changed, 36 insertions, 88 deletions
diff --git a/Documentation/networking/regulatory.txt b/Documentation/networking/regulatory.txt index 357d4ba4f135..dcf31648414a 100644 --- a/Documentation/networking/regulatory.txt +++ b/Documentation/networking/regulatory.txt | |||
@@ -131,11 +131,13 @@ are expected to do this during initialization. | |||
131 | 131 | ||
132 | r = zd_reg2alpha2(mac->regdomain, alpha2); | 132 | r = zd_reg2alpha2(mac->regdomain, alpha2); |
133 | if (!r) | 133 | if (!r) |
134 | regulatory_hint(hw->wiphy, alpha2, NULL); | 134 | regulatory_hint(hw->wiphy, alpha2); |
135 | 135 | ||
136 | Example code - drivers providing a built in regulatory domain: | 136 | Example code - drivers providing a built in regulatory domain: |
137 | -------------------------------------------------------------- | 137 | -------------------------------------------------------------- |
138 | 138 | ||
139 | [NOTE: This API is not currently available, it can be added when required] | ||
140 | |||
139 | If you have regulatory information you can obtain from your | 141 | If you have regulatory information you can obtain from your |
140 | driver and you *need* to use this we let you build a regulatory domain | 142 | driver and you *need* to use this we let you build a regulatory domain |
141 | structure and pass it to the wireless core. To do this you should | 143 | structure and pass it to the wireless core. To do this you should |
@@ -182,6 +184,7 @@ Then in some part of your code after your wiphy has been registered: | |||
182 | memcpy(rd, &mydriver_jp_regdom, sizeof(struct ieee80211_regdomain)); | 184 | memcpy(rd, &mydriver_jp_regdom, sizeof(struct ieee80211_regdomain)); |
183 | 185 | ||
184 | for (i=0; i < num_rules; i++) | 186 | for (i=0; i < num_rules; i++) |
185 | memcpy(&rd->reg_rules[i], &mydriver_jp_regdom.reg_rules[i], | 187 | memcpy(&rd->reg_rules[i], |
186 | sizeof(struct ieee80211_reg_rule)); | 188 | &mydriver_jp_regdom.reg_rules[i], |
187 | return regulatory_hint(hw->wiphy, NULL, rd); | 189 | sizeof(struct ieee80211_reg_rule)); |
190 | regulatory_struct_hint(rd); | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 2f0802b29c4b..07513e48b8f2 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -171,7 +171,7 @@ int zd_mac_init_hw(struct ieee80211_hw *hw) | |||
171 | 171 | ||
172 | r = zd_reg2alpha2(mac->regdomain, alpha2); | 172 | r = zd_reg2alpha2(mac->regdomain, alpha2); |
173 | if (!r) | 173 | if (!r) |
174 | regulatory_hint(hw->wiphy, alpha2, NULL); | 174 | regulatory_hint(hw->wiphy, alpha2); |
175 | 175 | ||
176 | r = 0; | 176 | r = 0; |
177 | disable_int: | 177 | disable_int: |
diff --git a/include/net/wireless.h b/include/net/wireless.h index 6e3ea0159045..41294c5f6f8f 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h | |||
@@ -342,34 +342,19 @@ ieee80211_get_channel(struct wiphy *wiphy, int freq) | |||
342 | 342 | ||
343 | /** | 343 | /** |
344 | * regulatory_hint - driver hint to the wireless core a regulatory domain | 344 | * regulatory_hint - driver hint to the wireless core a regulatory domain |
345 | * @wiphy: the driver's very own &struct wiphy | 345 | * @wiphy: the wireless device giving the hint (used only for reporting |
346 | * conflicts) | ||
346 | * @alpha2: the ISO/IEC 3166 alpha2 the driver claims its regulatory domain | 347 | * @alpha2: the ISO/IEC 3166 alpha2 the driver claims its regulatory domain |
347 | * should be in. If @rd is set this should be NULL. Note that if you | 348 | * should be in. If @rd is set this should be NULL. Note that if you |
348 | * set this to NULL you should still set rd->alpha2 to some accepted | 349 | * set this to NULL you should still set rd->alpha2 to some accepted |
349 | * alpha2. | 350 | * alpha2. |
350 | * @rd: a complete regulatory domain provided by the driver. If passed | ||
351 | * the driver does not need to worry about freeing it. | ||
352 | * | 351 | * |
353 | * Wireless drivers can use this function to hint to the wireless core | 352 | * Wireless drivers can use this function to hint to the wireless core |
354 | * what it believes should be the current regulatory domain by | 353 | * what it believes should be the current regulatory domain by |
355 | * giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory | 354 | * giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory |
356 | * domain should be in or by providing a completely build regulatory domain. | 355 | * domain should be in or by providing a completely build regulatory domain. |
357 | * If the driver provides an ISO/IEC 3166 alpha2 userspace will be queried | 356 | * If the driver provides an ISO/IEC 3166 alpha2 userspace will be queried |
358 | * for a regulatory domain structure for the respective country. If | 357 | * for a regulatory domain structure for the respective country. |
359 | * a regulatory domain is build and passed you should set the alpha2 | ||
360 | * if possible, otherwise set it to the special value of "99" which tells | ||
361 | * the wireless core it is unknown. | ||
362 | * | ||
363 | * Returns -EALREADY if *a regulatory domain* has already been set. Note that | ||
364 | * this could be by another driver. It is safe for drivers to continue if | ||
365 | * -EALREADY is returned, if drivers are not capable of world roaming they | ||
366 | * should not register more channels than they support. Right now we only | ||
367 | * support listening to the first driver hint. If the driver is capable | ||
368 | * of world roaming but wants to respect its own EEPROM mappings for | ||
369 | * specific regulatory domains it should register the @reg_notifier callback | ||
370 | * on the &struct wiphy. Returns 0 if the hint went through fine or through an | ||
371 | * intersection operation. Otherwise a standard error code is returned. | ||
372 | */ | 358 | */ |
373 | extern int regulatory_hint(struct wiphy *wiphy, | 359 | extern void regulatory_hint(struct wiphy *wiphy, const char *alpha2); |
374 | const char *alpha2, struct ieee80211_regdomain *rd); | ||
375 | #endif /* __NET_WIRELESS_H */ | 360 | #endif /* __NET_WIRELESS_H */ |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f82cc9aa6908..5e1d658a8b5a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -1695,7 +1695,7 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
1695 | return -EINVAL; | 1695 | return -EINVAL; |
1696 | #endif | 1696 | #endif |
1697 | mutex_lock(&cfg80211_drv_mutex); | 1697 | mutex_lock(&cfg80211_drv_mutex); |
1698 | r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, NULL); | 1698 | r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data); |
1699 | mutex_unlock(&cfg80211_drv_mutex); | 1699 | mutex_unlock(&cfg80211_drv_mutex); |
1700 | return r; | 1700 | return r; |
1701 | } | 1701 | } |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 038f8f133c54..dc10071deaaa 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -42,7 +42,10 @@ | |||
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 */ | 45 | /* |
46 | * wiphy is set if this request's initiator is | ||
47 | * REGDOM_SET_BY_COUNTRY_IE or _DRIVER | ||
48 | */ | ||
46 | struct regulatory_request { | 49 | struct regulatory_request { |
47 | struct wiphy *wiphy; | 50 | struct wiphy *wiphy; |
48 | enum reg_set_by initiator; | 51 | enum reg_set_by initiator; |
@@ -298,7 +301,7 @@ static int call_crda(const char *alpha2) | |||
298 | /* This has the logic which determines when a new request | 301 | /* This has the logic which determines when a new request |
299 | * should be ignored. */ | 302 | * should be ignored. */ |
300 | static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, | 303 | static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, |
301 | char *alpha2, struct ieee80211_regdomain *rd) | 304 | const char *alpha2) |
302 | { | 305 | { |
303 | /* All initial requests are respected */ | 306 | /* All initial requests are respected */ |
304 | if (!last_request) | 307 | if (!last_request) |
@@ -343,22 +346,8 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, | |||
343 | return 1; | 346 | return 1; |
344 | case REGDOM_SET_BY_DRIVER: | 347 | case REGDOM_SET_BY_DRIVER: |
345 | BUG_ON(!wiphy); | 348 | BUG_ON(!wiphy); |
346 | if (last_request->initiator == REGDOM_SET_BY_DRIVER) { | 349 | if (last_request->initiator == REGDOM_SET_BY_DRIVER) |
347 | /* Two separate drivers hinting different things, | ||
348 | * this is possible if you have two devices present | ||
349 | * on a system with different EEPROM regulatory | ||
350 | * readings. XXX: Do intersection, we support only | ||
351 | * the first regulatory hint for now */ | ||
352 | if (last_request->wiphy != wiphy) | ||
353 | return -EALREADY; | ||
354 | if (rd) | ||
355 | return -EALREADY; | ||
356 | /* Driver should not be trying to hint different | ||
357 | * regulatory domains! */ | ||
358 | BUG_ON(!alpha2_equal(alpha2, | ||
359 | cfg80211_regdomain->alpha2)); | ||
360 | return -EALREADY; | 350 | return -EALREADY; |
361 | } | ||
362 | if (last_request->initiator == REGDOM_SET_BY_CORE) | 351 | if (last_request->initiator == REGDOM_SET_BY_CORE) |
363 | return 0; | 352 | return 0; |
364 | /* XXX: Handle intersection, and add the | 353 | /* XXX: Handle intersection, and add the |
@@ -557,40 +546,32 @@ void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) | |||
557 | 546 | ||
558 | /* Caller must hold &cfg80211_drv_mutex */ | 547 | /* Caller must hold &cfg80211_drv_mutex */ |
559 | int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, | 548 | int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, |
560 | const char *alpha2, struct ieee80211_regdomain *rd) | 549 | const char *alpha2) |
561 | { | 550 | { |
562 | struct regulatory_request *request; | 551 | struct regulatory_request *request; |
563 | char *rd_alpha2; | ||
564 | int r = 0; | 552 | int r = 0; |
565 | 553 | ||
566 | r = ignore_request(wiphy, set_by, (char *) alpha2, rd); | 554 | r = ignore_request(wiphy, set_by, alpha2); |
567 | if (r) | 555 | if (r) |
568 | return r; | 556 | return r; |
569 | 557 | ||
570 | if (rd) | ||
571 | rd_alpha2 = rd->alpha2; | ||
572 | else | ||
573 | rd_alpha2 = (char *) alpha2; | ||
574 | |||
575 | switch (set_by) { | 558 | switch (set_by) { |
576 | case REGDOM_SET_BY_CORE: | 559 | case REGDOM_SET_BY_CORE: |
577 | case REGDOM_SET_BY_COUNTRY_IE: | 560 | case REGDOM_SET_BY_COUNTRY_IE: |
578 | case REGDOM_SET_BY_DRIVER: | 561 | case REGDOM_SET_BY_DRIVER: |
579 | case REGDOM_SET_BY_USER: | 562 | case REGDOM_SET_BY_USER: |
580 | request = kzalloc(sizeof(struct regulatory_request), | 563 | request = kzalloc(sizeof(struct regulatory_request), |
581 | GFP_KERNEL); | 564 | GFP_KERNEL); |
582 | if (!request) | 565 | if (!request) |
583 | return -ENOMEM; | 566 | return -ENOMEM; |
584 | 567 | ||
585 | request->alpha2[0] = rd_alpha2[0]; | 568 | request->alpha2[0] = alpha2[0]; |
586 | request->alpha2[1] = rd_alpha2[1]; | 569 | request->alpha2[1] = alpha2[1]; |
587 | request->initiator = set_by; | 570 | request->initiator = set_by; |
588 | request->wiphy = wiphy; | 571 | request->wiphy = wiphy; |
589 | 572 | ||
590 | kfree(last_request); | 573 | kfree(last_request); |
591 | last_request = request; | 574 | last_request = request; |
592 | if (rd) | ||
593 | break; | ||
594 | r = call_crda(alpha2); | 575 | r = call_crda(alpha2); |
595 | #ifndef CONFIG_WIRELESS_OLD_REGULATORY | 576 | #ifndef CONFIG_WIRELESS_OLD_REGULATORY |
596 | if (r) | 577 | if (r) |
@@ -605,25 +586,13 @@ int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, | |||
605 | return r; | 586 | return r; |
606 | } | 587 | } |
607 | 588 | ||
608 | int regulatory_hint(struct wiphy *wiphy, const char *alpha2, | 589 | void regulatory_hint(struct wiphy *wiphy, const char *alpha2) |
609 | struct ieee80211_regdomain *rd) | ||
610 | { | 590 | { |
611 | int r; | 591 | BUG_ON(!alpha2); |
612 | BUG_ON(!rd && !alpha2); | ||
613 | 592 | ||
614 | mutex_lock(&cfg80211_drv_mutex); | 593 | mutex_lock(&cfg80211_drv_mutex); |
615 | 594 | __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2); | |
616 | r = __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2, rd); | ||
617 | if (r || !rd) | ||
618 | goto unlock_and_exit; | ||
619 | |||
620 | /* If the driver passed a regulatory domain we skipped asking | ||
621 | * userspace for one so we can now go ahead and set it */ | ||
622 | r = set_regdom(rd); | ||
623 | |||
624 | unlock_and_exit: | ||
625 | mutex_unlock(&cfg80211_drv_mutex); | 595 | mutex_unlock(&cfg80211_drv_mutex); |
626 | return r; | ||
627 | } | 596 | } |
628 | EXPORT_SYMBOL(regulatory_hint); | 597 | EXPORT_SYMBOL(regulatory_hint); |
629 | 598 | ||
@@ -792,11 +761,11 @@ int regulatory_init(void) | |||
792 | * that is not a valid ISO / IEC 3166 alpha2 */ | 761 | * that is not a valid ISO / IEC 3166 alpha2 */ |
793 | if (ieee80211_regdom[0] != 'E' || ieee80211_regdom[1] != 'U') | 762 | if (ieee80211_regdom[0] != 'E' || ieee80211_regdom[1] != 'U') |
794 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, | 763 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, |
795 | ieee80211_regdom, NULL); | 764 | ieee80211_regdom); |
796 | #else | 765 | #else |
797 | cfg80211_regdomain = cfg80211_world_regdom; | 766 | cfg80211_regdomain = cfg80211_world_regdom; |
798 | 767 | ||
799 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL); | 768 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00"); |
800 | if (err) | 769 | if (err) |
801 | printk(KERN_ERR "cfg80211: calling CRDA failed - " | 770 | printk(KERN_ERR "cfg80211: calling CRDA failed - " |
802 | "unable to update world regulatory domain, " | 771 | "unable to update world regulatory domain, " |
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index 0c1572b92fef..c9b6b6358bbe 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -11,30 +11,21 @@ int set_regdom(const struct ieee80211_regdomain *rd); | |||
11 | 11 | ||
12 | /** | 12 | /** |
13 | * __regulatory_hint - hint to the wireless core a regulatory domain | 13 | * __regulatory_hint - hint to the wireless core a regulatory domain |
14 | * @wiphy: if a driver is providing the hint this is the driver's very | 14 | * @wiphy: if the hint comes from country information from an AP, this |
15 | * own &struct wiphy | 15 | * is required to be set to the wiphy that received the information |
16 | * @alpha2: the ISO/IEC 3166 alpha2 being claimed the regulatory domain | 16 | * @alpha2: the ISO/IEC 3166 alpha2 being claimed the regulatory domain |
17 | * should be in. If @rd is set this should be NULL | 17 | * should be in. |
18 | * @rd: a complete regulatory domain, if passed the caller need not worry | ||
19 | * about freeing it | ||
20 | * | 18 | * |
21 | * The Wireless subsystem can use this function to hint to the wireless core | 19 | * The Wireless subsystem can use this function to hint to the wireless core |
22 | * what it believes should be the current regulatory domain by | 20 | * what it believes should be the current regulatory domain by |
23 | * giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory | 21 | * giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory |
24 | * domain should be in or by providing a completely build regulatory domain. | 22 | * domain should be in. |
25 | * | 23 | * |
26 | * Returns -EALREADY if *a regulatory domain* has already been set. Note that | 24 | * Returns zero if all went fine, %-EALREADY if a regulatory domain had |
27 | * this could be by another driver. It is safe for drivers to continue if | 25 | * already been set or other standard error codes. |
28 | * -EALREADY is returned, if drivers are not capable of world roaming they | ||
29 | * should not register more channels than they support. Right now we only | ||
30 | * support listening to the first driver hint. If the driver is capable | ||
31 | * of world roaming but wants to respect its own EEPROM mappings for | ||
32 | * specific regulatory domains it should register the @reg_notifier callback | ||
33 | * on the &struct wiphy. Returns 0 if the hint went through fine or through an | ||
34 | * intersection operation. Otherwise a standard error code is returned. | ||
35 | * | 26 | * |
36 | */ | 27 | */ |
37 | extern int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, | 28 | extern int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, |
38 | const char *alpha2, struct ieee80211_regdomain *rd); | 29 | const char *alpha2); |
39 | 30 | ||
40 | #endif /* __NET_WIRELESS_REG_H */ | 31 | #endif /* __NET_WIRELESS_REG_H */ |