diff options
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r-- | net/wireless/reg.c | 127 |
1 files changed, 73 insertions, 54 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 3be18d9a944f..5ed615f94e0c 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 | ||
102 | static void reg_todo(struct work_struct *work); | ||
103 | static 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 */ |
100 | static const struct ieee80211_regdomain world_regdom = { | 106 | static 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 | ||
1325 | static void reg_set_request_processed(void) | ||
1326 | { | ||
1327 | bool need_more_processing = false; | ||
1328 | |||
1329 | last_request->processed = true; | ||
1330 | |||
1331 | spin_lock(®_requests_lock); | ||
1332 | if (!list_empty(®_requests_list)) | ||
1333 | need_more_processing = true; | ||
1334 | spin_unlock(®_requests_lock); | ||
1335 | |||
1336 | if (need_more_processing) | ||
1337 | schedule_work(®_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(®_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); |
1429 | out: | ||
1430 | mutex_unlock(®_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 | */ | ||
1435 | static void reg_process_pending_hints(void) | 1455 | static 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(®_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(®_requests_lock); | 1469 | spin_lock(®_requests_lock); |
1440 | while (!list_empty(®_requests_list)) { | ||
1441 | reg_request = list_first_entry(®_requests_list, | ||
1442 | struct regulatory_request, | ||
1443 | list); | ||
1444 | list_del_init(®_request->list); | ||
1445 | 1470 | ||
1471 | if (list_empty(®_requests_list)) { | ||
1446 | spin_unlock(®_requests_lock); | 1472 | spin_unlock(®_requests_lock); |
1447 | reg_process_hint(reg_request); | 1473 | goto out; |
1448 | spin_lock(®_requests_lock); | ||
1449 | } | 1474 | } |
1475 | |||
1476 | reg_request = list_first_entry(®_requests_list, | ||
1477 | struct regulatory_request, | ||
1478 | list); | ||
1479 | list_del_init(®_request->list); | ||
1480 | |||
1450 | spin_unlock(®_requests_lock); | 1481 | spin_unlock(®_requests_lock); |
1482 | |||
1483 | reg_process_hint(reg_request); | ||
1484 | |||
1485 | out: | ||
1486 | mutex_unlock(®_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 | ||
1497 | static DECLARE_WORK(reg_work, reg_todo); | ||
1498 | |||
1499 | static void queue_regulatory_request(struct regulatory_request *request) | 1534 | static 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 | ||
1893 | static void print_regdomain_info(const struct ieee80211_regdomain *rd) | 1913 | static 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(®_mutex); | 2084 | mutex_unlock(®_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); |