aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/regulatory.txt11
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c2
-rw-r--r--include/net/wireless.h23
-rw-r--r--net/wireless/nl80211.c2
-rw-r--r--net/wireless/reg.c63
-rw-r--r--net/wireless/reg.h23
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
136Example code - drivers providing a built in regulatory domain: 136Example 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
139If you have regulatory information you can obtain from your 141If you have regulatory information you can obtain from your
140driver and you *need* to use this we let you build a regulatory domain 142driver and you *need* to use this we let you build a regulatory domain
141structure and pass it to the wireless core. To do this you should 143structure 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;
177disable_int: 177disable_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 */
373extern int regulatory_hint(struct wiphy *wiphy, 359extern 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 */
46struct regulatory_request { 49struct 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. */
300static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, 303static 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 */
559int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, 548int __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
608int regulatory_hint(struct wiphy *wiphy, const char *alpha2, 589void 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
624unlock_and_exit:
625 mutex_unlock(&cfg80211_drv_mutex); 595 mutex_unlock(&cfg80211_drv_mutex);
626 return r;
627} 596}
628EXPORT_SYMBOL(regulatory_hint); 597EXPORT_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 */
37extern int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, 28extern 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 */