aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/reg.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2010-11-24 16:49:20 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-11-24 16:49:20 -0500
commit51cce8a590c4696d62bfacc63378d1036084cef7 (patch)
treedc24485bdff37ca6a83c69e93ffdbe5c5807b59d /net/wireless/reg.c
parent2fe66ec242d3f76e3b0101f36419e7e5405bcff3 (diff)
parent4f8559383c41262b50dc758e2e310f257ce6a14d (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r--net/wireless/reg.c127
1 files changed, 73 insertions, 54 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 3be18d9a944..5ed615f94e0 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -32,6 +32,9 @@
32 * rely on some SHA1 checksum of the regdomain for example. 32 * rely on some SHA1 checksum of the regdomain for example.
33 * 33 *
34 */ 34 */
35
36#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
37
35#include <linux/kernel.h> 38#include <linux/kernel.h>
36#include <linux/slab.h> 39#include <linux/slab.h>
37#include <linux/list.h> 40#include <linux/list.h>
@@ -48,7 +51,7 @@
48#ifdef CONFIG_CFG80211_REG_DEBUG 51#ifdef CONFIG_CFG80211_REG_DEBUG
49#define REG_DBG_PRINT(format, args...) \ 52#define REG_DBG_PRINT(format, args...) \
50 do { \ 53 do { \
51 printk(KERN_DEBUG "cfg80211: " format , ## args); \ 54 printk(KERN_DEBUG pr_fmt(format), ##args); \
52 } while (0) 55 } while (0)
53#else 56#else
54#define REG_DBG_PRINT(args...) 57#define REG_DBG_PRINT(args...)
@@ -96,6 +99,9 @@ struct reg_beacon {
96 struct ieee80211_channel chan; 99 struct ieee80211_channel chan;
97}; 100};
98 101
102static void reg_todo(struct work_struct *work);
103static DECLARE_WORK(reg_work, reg_todo);
104
99/* We keep a static world regulatory domain in case of the absence of CRDA */ 105/* We keep a static world regulatory domain in case of the absence of CRDA */
100static const struct ieee80211_regdomain world_regdom = { 106static const struct ieee80211_regdomain world_regdom = {
101 .n_reg_rules = 5, 107 .n_reg_rules = 5,
@@ -367,11 +373,10 @@ static int call_crda(const char *alpha2)
367 }; 373 };
368 374
369 if (!is_world_regdom((char *) alpha2)) 375 if (!is_world_regdom((char *) alpha2))
370 printk(KERN_INFO "cfg80211: Calling CRDA for country: %c%c\n", 376 pr_info("Calling CRDA for country: %c%c\n",
371 alpha2[0], alpha2[1]); 377 alpha2[0], alpha2[1]);
372 else 378 else
373 printk(KERN_INFO "cfg80211: Calling CRDA to update world " 379 pr_info("Calling CRDA to update world regulatory domain\n");
374 "regulatory domain\n");
375 380
376 /* query internal regulatory database (if it exists) */ 381 /* query internal regulatory database (if it exists) */
377 reg_regdb_query(alpha2); 382 reg_regdb_query(alpha2);
@@ -1317,6 +1322,21 @@ static int ignore_request(struct wiphy *wiphy,
1317 return -EINVAL; 1322 return -EINVAL;
1318} 1323}
1319 1324
1325static void reg_set_request_processed(void)
1326{
1327 bool need_more_processing = false;
1328
1329 last_request->processed = true;
1330
1331 spin_lock(&reg_requests_lock);
1332 if (!list_empty(&reg_requests_list))
1333 need_more_processing = true;
1334 spin_unlock(&reg_requests_lock);
1335
1336 if (need_more_processing)
1337 schedule_work(&reg_work);
1338}
1339
1320/** 1340/**
1321 * __regulatory_hint - hint to the wireless core a regulatory domain 1341 * __regulatory_hint - hint to the wireless core a regulatory domain
1322 * @wiphy: if the hint comes from country information from an AP, this 1342 * @wiphy: if the hint comes from country information from an AP, this
@@ -1392,8 +1412,10 @@ new_request:
1392 * have applied the requested regulatory domain before we just 1412 * have applied the requested regulatory domain before we just
1393 * inform userspace we have processed the request 1413 * inform userspace we have processed the request
1394 */ 1414 */
1395 if (r == -EALREADY) 1415 if (r == -EALREADY) {
1396 nl80211_send_reg_change_event(last_request); 1416 nl80211_send_reg_change_event(last_request);
1417 reg_set_request_processed();
1418 }
1397 return r; 1419 return r;
1398 } 1420 }
1399 1421
@@ -1409,16 +1431,13 @@ static void reg_process_hint(struct regulatory_request *reg_request)
1409 1431
1410 BUG_ON(!reg_request->alpha2); 1432 BUG_ON(!reg_request->alpha2);
1411 1433
1412 mutex_lock(&cfg80211_mutex);
1413 mutex_lock(&reg_mutex);
1414
1415 if (wiphy_idx_valid(reg_request->wiphy_idx)) 1434 if (wiphy_idx_valid(reg_request->wiphy_idx))
1416 wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); 1435 wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
1417 1436
1418 if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && 1437 if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
1419 !wiphy) { 1438 !wiphy) {
1420 kfree(reg_request); 1439 kfree(reg_request);
1421 goto out; 1440 return;
1422 } 1441 }
1423 1442
1424 r = __regulatory_hint(wiphy, reg_request); 1443 r = __regulatory_hint(wiphy, reg_request);
@@ -1426,28 +1445,46 @@ static void reg_process_hint(struct regulatory_request *reg_request)
1426 if (r == -EALREADY && wiphy && 1445 if (r == -EALREADY && wiphy &&
1427 wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) 1446 wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
1428 wiphy_update_regulatory(wiphy, initiator); 1447 wiphy_update_regulatory(wiphy, initiator);
1429out:
1430 mutex_unlock(&reg_mutex);
1431 mutex_unlock(&cfg80211_mutex);
1432} 1448}
1433 1449
1434/* Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_* */ 1450/*
1451 * Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_*
1452 * Regulatory hints come on a first come first serve basis and we
1453 * must process each one atomically.
1454 */
1435static void reg_process_pending_hints(void) 1455static void reg_process_pending_hints(void)
1436 { 1456{
1437 struct regulatory_request *reg_request; 1457 struct regulatory_request *reg_request;
1438 1458
1459 mutex_lock(&cfg80211_mutex);
1460 mutex_lock(&reg_mutex);
1461
1462 /* When last_request->processed becomes true this will be rescheduled */
1463 if (last_request && !last_request->processed) {
1464 REG_DBG_PRINT("Pending regulatory request, waiting "
1465 "for it to be processed...");
1466 goto out;
1467 }
1468
1439 spin_lock(&reg_requests_lock); 1469 spin_lock(&reg_requests_lock);
1440 while (!list_empty(&reg_requests_list)) {
1441 reg_request = list_first_entry(&reg_requests_list,
1442 struct regulatory_request,
1443 list);
1444 list_del_init(&reg_request->list);
1445 1470
1471 if (list_empty(&reg_requests_list)) {
1446 spin_unlock(&reg_requests_lock); 1472 spin_unlock(&reg_requests_lock);
1447 reg_process_hint(reg_request); 1473 goto out;
1448 spin_lock(&reg_requests_lock);
1449 } 1474 }
1475
1476 reg_request = list_first_entry(&reg_requests_list,
1477 struct regulatory_request,
1478 list);
1479 list_del_init(&reg_request->list);
1480
1450 spin_unlock(&reg_requests_lock); 1481 spin_unlock(&reg_requests_lock);
1482
1483 reg_process_hint(reg_request);
1484
1485out:
1486 mutex_unlock(&reg_mutex);
1487 mutex_unlock(&cfg80211_mutex);
1451} 1488}
1452 1489
1453/* Processes beacon hints -- this has nothing to do with country IEs */ 1490/* Processes beacon hints -- this has nothing to do with country IEs */
@@ -1494,8 +1531,6 @@ static void reg_todo(struct work_struct *work)
1494 reg_process_pending_beacon_hints(); 1531 reg_process_pending_beacon_hints();
1495} 1532}
1496 1533
1497static DECLARE_WORK(reg_work, reg_todo);
1498
1499static void queue_regulatory_request(struct regulatory_request *request) 1534static void queue_regulatory_request(struct regulatory_request *request)
1500{ 1535{
1501 if (isalpha(request->alpha2[0])) 1536 if (isalpha(request->alpha2[0]))
@@ -1530,12 +1565,7 @@ static int regulatory_hint_core(const char *alpha2)
1530 request->alpha2[1] = alpha2[1]; 1565 request->alpha2[1] = alpha2[1];
1531 request->initiator = NL80211_REGDOM_SET_BY_CORE; 1566 request->initiator = NL80211_REGDOM_SET_BY_CORE;
1532 1567
1533 /* 1568 queue_regulatory_request(request);
1534 * This ensures last_request is populated once modules
1535 * come swinging in and calling regulatory hints and
1536 * wiphy_apply_custom_regulatory().
1537 */
1538 reg_process_hint(request);
1539 1569
1540 return 0; 1570 return 0;
1541} 1571}
@@ -1823,8 +1853,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
1823 const struct ieee80211_freq_range *freq_range = NULL; 1853 const struct ieee80211_freq_range *freq_range = NULL;
1824 const struct ieee80211_power_rule *power_rule = NULL; 1854 const struct ieee80211_power_rule *power_rule = NULL;
1825 1855
1826 printk(KERN_INFO " (start_freq - end_freq @ bandwidth), " 1856 pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)\n");
1827 "(max_antenna_gain, max_eirp)\n");
1828 1857
1829 for (i = 0; i < rd->n_reg_rules; i++) { 1858 for (i = 0; i < rd->n_reg_rules; i++) {
1830 reg_rule = &rd->reg_rules[i]; 1859 reg_rule = &rd->reg_rules[i];
@@ -1836,16 +1865,14 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
1836 * in certain regions 1865 * in certain regions
1837 */ 1866 */
1838 if (power_rule->max_antenna_gain) 1867 if (power_rule->max_antenna_gain)
1839 printk(KERN_INFO " (%d KHz - %d KHz @ %d KHz), " 1868 pr_info(" (%d KHz - %d KHz @ %d KHz), (%d mBi, %d mBm)\n",
1840 "(%d mBi, %d mBm)\n",
1841 freq_range->start_freq_khz, 1869 freq_range->start_freq_khz,
1842 freq_range->end_freq_khz, 1870 freq_range->end_freq_khz,
1843 freq_range->max_bandwidth_khz, 1871 freq_range->max_bandwidth_khz,
1844 power_rule->max_antenna_gain, 1872 power_rule->max_antenna_gain,
1845 power_rule->max_eirp); 1873 power_rule->max_eirp);
1846 else 1874 else
1847 printk(KERN_INFO " (%d KHz - %d KHz @ %d KHz), " 1875 pr_info(" (%d KHz - %d KHz @ %d KHz), (N/A, %d mBm)\n",
1848 "(N/A, %d mBm)\n",
1849 freq_range->start_freq_khz, 1876 freq_range->start_freq_khz,
1850 freq_range->end_freq_khz, 1877 freq_range->end_freq_khz,
1851 freq_range->max_bandwidth_khz, 1878 freq_range->max_bandwidth_khz,
@@ -1864,27 +1891,20 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
1864 rdev = cfg80211_rdev_by_wiphy_idx( 1891 rdev = cfg80211_rdev_by_wiphy_idx(
1865 last_request->wiphy_idx); 1892 last_request->wiphy_idx);
1866 if (rdev) { 1893 if (rdev) {
1867 printk(KERN_INFO "cfg80211: Current regulatory " 1894 pr_info("Current regulatory domain updated by AP to: %c%c\n",
1868 "domain updated by AP to: %c%c\n",
1869 rdev->country_ie_alpha2[0], 1895 rdev->country_ie_alpha2[0],
1870 rdev->country_ie_alpha2[1]); 1896 rdev->country_ie_alpha2[1]);
1871 } else 1897 } else
1872 printk(KERN_INFO "cfg80211: Current regulatory " 1898 pr_info("Current regulatory domain intersected:\n");
1873 "domain intersected:\n");
1874 } else 1899 } else
1875 printk(KERN_INFO "cfg80211: Current regulatory " 1900 pr_info("Current regulatory domain intersected:\n");
1876 "domain intersected:\n");
1877 } else if (is_world_regdom(rd->alpha2)) 1901 } else if (is_world_regdom(rd->alpha2))
1878 printk(KERN_INFO "cfg80211: World regulatory " 1902 pr_info("World regulatory domain updated:\n");
1879 "domain updated:\n");
1880 else { 1903 else {
1881 if (is_unknown_alpha2(rd->alpha2)) 1904 if (is_unknown_alpha2(rd->alpha2))
1882 printk(KERN_INFO "cfg80211: Regulatory domain " 1905 pr_info("Regulatory domain changed to driver built-in settings (unknown country)\n");
1883 "changed to driver built-in settings "
1884 "(unknown country)\n");
1885 else 1906 else
1886 printk(KERN_INFO "cfg80211: Regulatory domain " 1907 pr_info("Regulatory domain changed to country: %c%c\n",
1887 "changed to country: %c%c\n",
1888 rd->alpha2[0], rd->alpha2[1]); 1908 rd->alpha2[0], rd->alpha2[1]);
1889 } 1909 }
1890 print_rd_rules(rd); 1910 print_rd_rules(rd);
@@ -1892,8 +1912,7 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
1892 1912
1893static void print_regdomain_info(const struct ieee80211_regdomain *rd) 1913static void print_regdomain_info(const struct ieee80211_regdomain *rd)
1894{ 1914{
1895 printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n", 1915 pr_info("Regulatory domain: %c%c\n", rd->alpha2[0], rd->alpha2[1]);
1896 rd->alpha2[0], rd->alpha2[1]);
1897 print_rd_rules(rd); 1916 print_rd_rules(rd);
1898} 1917}
1899 1918
@@ -1944,8 +1963,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
1944 return -EINVAL; 1963 return -EINVAL;
1945 1964
1946 if (!is_valid_rd(rd)) { 1965 if (!is_valid_rd(rd)) {
1947 printk(KERN_ERR "cfg80211: Invalid " 1966 pr_err("Invalid regulatory domain detected:\n");
1948 "regulatory domain detected:\n");
1949 print_regdomain_info(rd); 1967 print_regdomain_info(rd);
1950 return -EINVAL; 1968 return -EINVAL;
1951 } 1969 }
@@ -2061,6 +2079,8 @@ int set_regdom(const struct ieee80211_regdomain *rd)
2061 2079
2062 nl80211_send_reg_change_event(last_request); 2080 nl80211_send_reg_change_event(last_request);
2063 2081
2082 reg_set_request_processed();
2083
2064 mutex_unlock(&reg_mutex); 2084 mutex_unlock(&reg_mutex);
2065 2085
2066 return r; 2086 return r;
@@ -2117,8 +2137,7 @@ int __init regulatory_init(void)
2117 * early boot for call_usermodehelper(). For now treat these 2137 * early boot for call_usermodehelper(). For now treat these
2118 * errors as non-fatal. 2138 * errors as non-fatal.
2119 */ 2139 */
2120 printk(KERN_ERR "cfg80211: kobject_uevent_env() was unable " 2140 pr_err("kobject_uevent_env() was unable to call CRDA during init\n");
2121 "to call CRDA during init");
2122#ifdef CONFIG_CFG80211_REG_DEBUG 2141#ifdef CONFIG_CFG80211_REG_DEBUG
2123 /* We want to find out exactly why when debugging */ 2142 /* We want to find out exactly why when debugging */
2124 WARN_ON(err); 2143 WARN_ON(err);