diff options
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r-- | net/wireless/reg.c | 262 |
1 files changed, 192 insertions, 70 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 4b9f8912526c..37693b6ef23a 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 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); |
@@ -656,7 +661,8 @@ static int freq_reg_info_regd(struct wiphy *wiphy, | |||
656 | * Follow the driver's regulatory domain, if present, unless a country | 661 | * Follow the driver's regulatory domain, if present, unless a country |
657 | * IE has been processed or a user wants to help complaince further | 662 | * IE has been processed or a user wants to help complaince further |
658 | */ | 663 | */ |
659 | if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | 664 | if (!custom_regd && |
665 | last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | ||
660 | last_request->initiator != NL80211_REGDOM_SET_BY_USER && | 666 | last_request->initiator != NL80211_REGDOM_SET_BY_USER && |
661 | wiphy->regd) | 667 | wiphy->regd) |
662 | regd = wiphy->regd; | 668 | regd = wiphy->regd; |
@@ -711,6 +717,60 @@ int freq_reg_info(struct wiphy *wiphy, | |||
711 | } | 717 | } |
712 | EXPORT_SYMBOL(freq_reg_info); | 718 | EXPORT_SYMBOL(freq_reg_info); |
713 | 719 | ||
720 | #ifdef CONFIG_CFG80211_REG_DEBUG | ||
721 | static const char *reg_initiator_name(enum nl80211_reg_initiator initiator) | ||
722 | { | ||
723 | switch (initiator) { | ||
724 | case NL80211_REGDOM_SET_BY_CORE: | ||
725 | return "Set by core"; | ||
726 | case NL80211_REGDOM_SET_BY_USER: | ||
727 | return "Set by user"; | ||
728 | case NL80211_REGDOM_SET_BY_DRIVER: | ||
729 | return "Set by driver"; | ||
730 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | ||
731 | return "Set by country IE"; | ||
732 | default: | ||
733 | WARN_ON(1); | ||
734 | return "Set by bug"; | ||
735 | } | ||
736 | } | ||
737 | |||
738 | static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan, | ||
739 | u32 desired_bw_khz, | ||
740 | const struct ieee80211_reg_rule *reg_rule) | ||
741 | { | ||
742 | const struct ieee80211_power_rule *power_rule; | ||
743 | const struct ieee80211_freq_range *freq_range; | ||
744 | char max_antenna_gain[32]; | ||
745 | |||
746 | power_rule = ®_rule->power_rule; | ||
747 | freq_range = ®_rule->freq_range; | ||
748 | |||
749 | if (!power_rule->max_antenna_gain) | ||
750 | snprintf(max_antenna_gain, 32, "N/A"); | ||
751 | else | ||
752 | snprintf(max_antenna_gain, 32, "%d", power_rule->max_antenna_gain); | ||
753 | |||
754 | REG_DBG_PRINT("Updating information on frequency %d MHz " | ||
755 | "for a %d MHz width channel with regulatory rule:\n", | ||
756 | chan->center_freq, | ||
757 | KHZ_TO_MHZ(desired_bw_khz)); | ||
758 | |||
759 | REG_DBG_PRINT("%d KHz - %d KHz @ KHz), (%s mBi, %d mBm)\n", | ||
760 | freq_range->start_freq_khz, | ||
761 | freq_range->end_freq_khz, | ||
762 | max_antenna_gain, | ||
763 | power_rule->max_eirp); | ||
764 | } | ||
765 | #else | ||
766 | static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan, | ||
767 | u32 desired_bw_khz, | ||
768 | const struct ieee80211_reg_rule *reg_rule) | ||
769 | { | ||
770 | return; | ||
771 | } | ||
772 | #endif | ||
773 | |||
714 | /* | 774 | /* |
715 | * Note that right now we assume the desired channel bandwidth | 775 | * Note that right now we assume the desired channel bandwidth |
716 | * is always 20 MHz for each individual channel (HT40 uses 20 MHz | 776 | * is always 20 MHz for each individual channel (HT40 uses 20 MHz |
@@ -720,7 +780,9 @@ EXPORT_SYMBOL(freq_reg_info); | |||
720 | * on the wiphy with the target_bw specified. Then we can simply use | 780 | * on the wiphy with the target_bw specified. Then we can simply use |
721 | * that below for the desired_bw_khz below. | 781 | * that below for the desired_bw_khz below. |
722 | */ | 782 | */ |
723 | static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | 783 | static void handle_channel(struct wiphy *wiphy, |
784 | enum nl80211_reg_initiator initiator, | ||
785 | enum ieee80211_band band, | ||
724 | unsigned int chan_idx) | 786 | unsigned int chan_idx) |
725 | { | 787 | { |
726 | int r; | 788 | int r; |
@@ -748,8 +810,27 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | |||
748 | desired_bw_khz, | 810 | desired_bw_khz, |
749 | ®_rule); | 811 | ®_rule); |
750 | 812 | ||
751 | if (r) | 813 | if (r) { |
814 | /* | ||
815 | * We will disable all channels that do not match our | ||
816 | * recieved regulatory rule unless the hint is coming | ||
817 | * from a Country IE and the Country IE had no information | ||
818 | * about a band. The IEEE 802.11 spec allows for an AP | ||
819 | * to send only a subset of the regulatory rules allowed, | ||
820 | * so an AP in the US that only supports 2.4 GHz may only send | ||
821 | * a country IE with information for the 2.4 GHz band | ||
822 | * while 5 GHz is still supported. | ||
823 | */ | ||
824 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && | ||
825 | r == -ERANGE) | ||
826 | return; | ||
827 | |||
828 | REG_DBG_PRINT("Disabling freq %d MHz\n", chan->center_freq); | ||
829 | chan->flags = IEEE80211_CHAN_DISABLED; | ||
752 | return; | 830 | return; |
831 | } | ||
832 | |||
833 | chan_reg_rule_print_dbg(chan, desired_bw_khz, reg_rule); | ||
753 | 834 | ||
754 | power_rule = ®_rule->power_rule; | 835 | power_rule = ®_rule->power_rule; |
755 | freq_range = ®_rule->freq_range; | 836 | freq_range = ®_rule->freq_range; |
@@ -784,7 +865,9 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | |||
784 | chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); | 865 | chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); |
785 | } | 866 | } |
786 | 867 | ||
787 | static void handle_band(struct wiphy *wiphy, enum ieee80211_band band) | 868 | static void handle_band(struct wiphy *wiphy, |
869 | enum ieee80211_band band, | ||
870 | enum nl80211_reg_initiator initiator) | ||
788 | { | 871 | { |
789 | unsigned int i; | 872 | unsigned int i; |
790 | struct ieee80211_supported_band *sband; | 873 | struct ieee80211_supported_band *sband; |
@@ -793,24 +876,42 @@ static void handle_band(struct wiphy *wiphy, enum ieee80211_band band) | |||
793 | sband = wiphy->bands[band]; | 876 | sband = wiphy->bands[band]; |
794 | 877 | ||
795 | for (i = 0; i < sband->n_channels; i++) | 878 | for (i = 0; i < sband->n_channels; i++) |
796 | handle_channel(wiphy, band, i); | 879 | handle_channel(wiphy, initiator, band, i); |
797 | } | 880 | } |
798 | 881 | ||
799 | static bool ignore_reg_update(struct wiphy *wiphy, | 882 | static bool ignore_reg_update(struct wiphy *wiphy, |
800 | enum nl80211_reg_initiator initiator) | 883 | enum nl80211_reg_initiator initiator) |
801 | { | 884 | { |
802 | if (!last_request) | 885 | if (!last_request) { |
886 | REG_DBG_PRINT("Ignoring regulatory request %s since " | ||
887 | "last_request is not set\n", | ||
888 | reg_initiator_name(initiator)); | ||
803 | return true; | 889 | return true; |
890 | } | ||
891 | |||
804 | if (initiator == NL80211_REGDOM_SET_BY_CORE && | 892 | if (initiator == NL80211_REGDOM_SET_BY_CORE && |
805 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) | 893 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) { |
894 | REG_DBG_PRINT("Ignoring regulatory request %s " | ||
895 | "since the driver uses its own custom " | ||
896 | "regulatory domain ", | ||
897 | reg_initiator_name(initiator)); | ||
806 | return true; | 898 | return true; |
899 | } | ||
900 | |||
807 | /* | 901 | /* |
808 | * wiphy->regd will be set once the device has its own | 902 | * wiphy->regd will be set once the device has its own |
809 | * desired regulatory domain set | 903 | * desired regulatory domain set |
810 | */ | 904 | */ |
811 | if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && !wiphy->regd && | 905 | if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && !wiphy->regd && |
812 | !is_world_regdom(last_request->alpha2)) | 906 | initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && |
907 | !is_world_regdom(last_request->alpha2)) { | ||
908 | REG_DBG_PRINT("Ignoring regulatory request %s " | ||
909 | "since the driver requires its own regulaotry " | ||
910 | "domain to be set first", | ||
911 | reg_initiator_name(initiator)); | ||
813 | return true; | 912 | return true; |
913 | } | ||
914 | |||
814 | return false; | 915 | return false; |
815 | } | 916 | } |
816 | 917 | ||
@@ -1030,7 +1131,7 @@ void wiphy_update_regulatory(struct wiphy *wiphy, | |||
1030 | goto out; | 1131 | goto out; |
1031 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 1132 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
1032 | if (wiphy->bands[band]) | 1133 | if (wiphy->bands[band]) |
1033 | handle_band(wiphy, band); | 1134 | handle_band(wiphy, band, initiator); |
1034 | } | 1135 | } |
1035 | out: | 1136 | out: |
1036 | reg_process_beacons(wiphy); | 1137 | reg_process_beacons(wiphy); |
@@ -1066,10 +1167,17 @@ static void handle_channel_custom(struct wiphy *wiphy, | |||
1066 | regd); | 1167 | regd); |
1067 | 1168 | ||
1068 | if (r) { | 1169 | if (r) { |
1170 | REG_DBG_PRINT("Disabling freq %d MHz as custom " | ||
1171 | "regd has no rule that fits a %d MHz " | ||
1172 | "wide channel\n", | ||
1173 | chan->center_freq, | ||
1174 | KHZ_TO_MHZ(desired_bw_khz)); | ||
1069 | chan->flags = IEEE80211_CHAN_DISABLED; | 1175 | chan->flags = IEEE80211_CHAN_DISABLED; |
1070 | return; | 1176 | return; |
1071 | } | 1177 | } |
1072 | 1178 | ||
1179 | chan_reg_rule_print_dbg(chan, desired_bw_khz, reg_rule); | ||
1180 | |||
1073 | power_rule = ®_rule->power_rule; | 1181 | power_rule = ®_rule->power_rule; |
1074 | freq_range = ®_rule->freq_range; | 1182 | freq_range = ®_rule->freq_range; |
1075 | 1183 | ||
@@ -1215,6 +1323,21 @@ static int ignore_request(struct wiphy *wiphy, | |||
1215 | return -EINVAL; | 1323 | return -EINVAL; |
1216 | } | 1324 | } |
1217 | 1325 | ||
1326 | static void reg_set_request_processed(void) | ||
1327 | { | ||
1328 | bool need_more_processing = false; | ||
1329 | |||
1330 | last_request->processed = true; | ||
1331 | |||
1332 | spin_lock(®_requests_lock); | ||
1333 | if (!list_empty(®_requests_list)) | ||
1334 | need_more_processing = true; | ||
1335 | spin_unlock(®_requests_lock); | ||
1336 | |||
1337 | if (need_more_processing) | ||
1338 | schedule_work(®_work); | ||
1339 | } | ||
1340 | |||
1218 | /** | 1341 | /** |
1219 | * __regulatory_hint - hint to the wireless core a regulatory domain | 1342 | * __regulatory_hint - hint to the wireless core a regulatory domain |
1220 | * @wiphy: if the hint comes from country information from an AP, this | 1343 | * @wiphy: if the hint comes from country information from an AP, this |
@@ -1290,8 +1413,10 @@ new_request: | |||
1290 | * have applied the requested regulatory domain before we just | 1413 | * have applied the requested regulatory domain before we just |
1291 | * inform userspace we have processed the request | 1414 | * inform userspace we have processed the request |
1292 | */ | 1415 | */ |
1293 | if (r == -EALREADY) | 1416 | if (r == -EALREADY) { |
1294 | nl80211_send_reg_change_event(last_request); | 1417 | nl80211_send_reg_change_event(last_request); |
1418 | reg_set_request_processed(); | ||
1419 | } | ||
1295 | return r; | 1420 | return r; |
1296 | } | 1421 | } |
1297 | 1422 | ||
@@ -1307,16 +1432,13 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
1307 | 1432 | ||
1308 | BUG_ON(!reg_request->alpha2); | 1433 | BUG_ON(!reg_request->alpha2); |
1309 | 1434 | ||
1310 | mutex_lock(&cfg80211_mutex); | ||
1311 | mutex_lock(®_mutex); | ||
1312 | |||
1313 | if (wiphy_idx_valid(reg_request->wiphy_idx)) | 1435 | if (wiphy_idx_valid(reg_request->wiphy_idx)) |
1314 | wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); | 1436 | wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); |
1315 | 1437 | ||
1316 | if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && | 1438 | if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && |
1317 | !wiphy) { | 1439 | !wiphy) { |
1318 | kfree(reg_request); | 1440 | kfree(reg_request); |
1319 | goto out; | 1441 | return; |
1320 | } | 1442 | } |
1321 | 1443 | ||
1322 | r = __regulatory_hint(wiphy, reg_request); | 1444 | r = __regulatory_hint(wiphy, reg_request); |
@@ -1324,28 +1446,46 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
1324 | if (r == -EALREADY && wiphy && | 1446 | if (r == -EALREADY && wiphy && |
1325 | wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) | 1447 | wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) |
1326 | wiphy_update_regulatory(wiphy, initiator); | 1448 | wiphy_update_regulatory(wiphy, initiator); |
1327 | out: | ||
1328 | mutex_unlock(®_mutex); | ||
1329 | mutex_unlock(&cfg80211_mutex); | ||
1330 | } | 1449 | } |
1331 | 1450 | ||
1332 | /* Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_* */ | 1451 | /* |
1452 | * Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_* | ||
1453 | * Regulatory hints come on a first come first serve basis and we | ||
1454 | * must process each one atomically. | ||
1455 | */ | ||
1333 | static void reg_process_pending_hints(void) | 1456 | static void reg_process_pending_hints(void) |
1334 | { | 1457 | { |
1335 | struct regulatory_request *reg_request; | 1458 | struct regulatory_request *reg_request; |
1336 | 1459 | ||
1460 | mutex_lock(&cfg80211_mutex); | ||
1461 | mutex_lock(®_mutex); | ||
1462 | |||
1463 | /* When last_request->processed becomes true this will be rescheduled */ | ||
1464 | if (last_request && !last_request->processed) { | ||
1465 | REG_DBG_PRINT("Pending regulatory request, waiting " | ||
1466 | "for it to be processed..."); | ||
1467 | goto out; | ||
1468 | } | ||
1469 | |||
1337 | spin_lock(®_requests_lock); | 1470 | spin_lock(®_requests_lock); |
1338 | while (!list_empty(®_requests_list)) { | ||
1339 | reg_request = list_first_entry(®_requests_list, | ||
1340 | struct regulatory_request, | ||
1341 | list); | ||
1342 | list_del_init(®_request->list); | ||
1343 | 1471 | ||
1472 | if (list_empty(®_requests_list)) { | ||
1344 | spin_unlock(®_requests_lock); | 1473 | spin_unlock(®_requests_lock); |
1345 | reg_process_hint(reg_request); | 1474 | goto out; |
1346 | spin_lock(®_requests_lock); | ||
1347 | } | 1475 | } |
1476 | |||
1477 | reg_request = list_first_entry(®_requests_list, | ||
1478 | struct regulatory_request, | ||
1479 | list); | ||
1480 | list_del_init(®_request->list); | ||
1481 | |||
1348 | spin_unlock(®_requests_lock); | 1482 | spin_unlock(®_requests_lock); |
1483 | |||
1484 | reg_process_hint(reg_request); | ||
1485 | |||
1486 | out: | ||
1487 | mutex_unlock(®_mutex); | ||
1488 | mutex_unlock(&cfg80211_mutex); | ||
1349 | } | 1489 | } |
1350 | 1490 | ||
1351 | /* Processes beacon hints -- this has nothing to do with country IEs */ | 1491 | /* Processes beacon hints -- this has nothing to do with country IEs */ |
@@ -1392,8 +1532,6 @@ static void reg_todo(struct work_struct *work) | |||
1392 | reg_process_pending_beacon_hints(); | 1532 | reg_process_pending_beacon_hints(); |
1393 | } | 1533 | } |
1394 | 1534 | ||
1395 | static DECLARE_WORK(reg_work, reg_todo); | ||
1396 | |||
1397 | static void queue_regulatory_request(struct regulatory_request *request) | 1535 | static void queue_regulatory_request(struct regulatory_request *request) |
1398 | { | 1536 | { |
1399 | if (isalpha(request->alpha2[0])) | 1537 | if (isalpha(request->alpha2[0])) |
@@ -1428,12 +1566,7 @@ static int regulatory_hint_core(const char *alpha2) | |||
1428 | request->alpha2[1] = alpha2[1]; | 1566 | request->alpha2[1] = alpha2[1]; |
1429 | request->initiator = NL80211_REGDOM_SET_BY_CORE; | 1567 | request->initiator = NL80211_REGDOM_SET_BY_CORE; |
1430 | 1568 | ||
1431 | /* | 1569 | queue_regulatory_request(request); |
1432 | * This ensures last_request is populated once modules | ||
1433 | * come swinging in and calling regulatory hints and | ||
1434 | * wiphy_apply_custom_regulatory(). | ||
1435 | */ | ||
1436 | reg_process_hint(request); | ||
1437 | 1570 | ||
1438 | return 0; | 1571 | return 0; |
1439 | } | 1572 | } |
@@ -1559,7 +1692,7 @@ static void restore_alpha2(char *alpha2, bool reset_user) | |||
1559 | if (is_user_regdom_saved()) { | 1692 | if (is_user_regdom_saved()) { |
1560 | /* Unless we're asked to ignore it and reset it */ | 1693 | /* Unless we're asked to ignore it and reset it */ |
1561 | if (reset_user) { | 1694 | if (reset_user) { |
1562 | REG_DBG_PRINT("cfg80211: Restoring regulatory settings " | 1695 | REG_DBG_PRINT("Restoring regulatory settings " |
1563 | "including user preference\n"); | 1696 | "including user preference\n"); |
1564 | user_alpha2[0] = '9'; | 1697 | user_alpha2[0] = '9'; |
1565 | user_alpha2[1] = '7'; | 1698 | user_alpha2[1] = '7'; |
@@ -1570,7 +1703,7 @@ static void restore_alpha2(char *alpha2, bool reset_user) | |||
1570 | * back as they were for a full restore. | 1703 | * back as they were for a full restore. |
1571 | */ | 1704 | */ |
1572 | if (!is_world_regdom(ieee80211_regdom)) { | 1705 | if (!is_world_regdom(ieee80211_regdom)) { |
1573 | REG_DBG_PRINT("cfg80211: Keeping preference on " | 1706 | REG_DBG_PRINT("Keeping preference on " |
1574 | "module parameter ieee80211_regdom: %c%c\n", | 1707 | "module parameter ieee80211_regdom: %c%c\n", |
1575 | ieee80211_regdom[0], | 1708 | ieee80211_regdom[0], |
1576 | ieee80211_regdom[1]); | 1709 | ieee80211_regdom[1]); |
@@ -1578,7 +1711,7 @@ static void restore_alpha2(char *alpha2, bool reset_user) | |||
1578 | alpha2[1] = ieee80211_regdom[1]; | 1711 | alpha2[1] = ieee80211_regdom[1]; |
1579 | } | 1712 | } |
1580 | } else { | 1713 | } else { |
1581 | REG_DBG_PRINT("cfg80211: Restoring regulatory settings " | 1714 | REG_DBG_PRINT("Restoring regulatory settings " |
1582 | "while preserving user preference for: %c%c\n", | 1715 | "while preserving user preference for: %c%c\n", |
1583 | user_alpha2[0], | 1716 | user_alpha2[0], |
1584 | user_alpha2[1]); | 1717 | user_alpha2[1]); |
@@ -1586,14 +1719,14 @@ static void restore_alpha2(char *alpha2, bool reset_user) | |||
1586 | alpha2[1] = user_alpha2[1]; | 1719 | alpha2[1] = user_alpha2[1]; |
1587 | } | 1720 | } |
1588 | } else if (!is_world_regdom(ieee80211_regdom)) { | 1721 | } else if (!is_world_regdom(ieee80211_regdom)) { |
1589 | REG_DBG_PRINT("cfg80211: Keeping preference on " | 1722 | REG_DBG_PRINT("Keeping preference on " |
1590 | "module parameter ieee80211_regdom: %c%c\n", | 1723 | "module parameter ieee80211_regdom: %c%c\n", |
1591 | ieee80211_regdom[0], | 1724 | ieee80211_regdom[0], |
1592 | ieee80211_regdom[1]); | 1725 | ieee80211_regdom[1]); |
1593 | alpha2[0] = ieee80211_regdom[0]; | 1726 | alpha2[0] = ieee80211_regdom[0]; |
1594 | alpha2[1] = ieee80211_regdom[1]; | 1727 | alpha2[1] = ieee80211_regdom[1]; |
1595 | } else | 1728 | } else |
1596 | REG_DBG_PRINT("cfg80211: Restoring regulatory settings\n"); | 1729 | REG_DBG_PRINT("Restoring regulatory settings\n"); |
1597 | } | 1730 | } |
1598 | 1731 | ||
1599 | /* | 1732 | /* |
@@ -1661,7 +1794,7 @@ static void restore_regulatory_settings(bool reset_user) | |||
1661 | 1794 | ||
1662 | void regulatory_hint_disconnect(void) | 1795 | void regulatory_hint_disconnect(void) |
1663 | { | 1796 | { |
1664 | REG_DBG_PRINT("cfg80211: All devices are disconnected, going to " | 1797 | REG_DBG_PRINT("All devices are disconnected, going to " |
1665 | "restore regulatory settings\n"); | 1798 | "restore regulatory settings\n"); |
1666 | restore_regulatory_settings(false); | 1799 | restore_regulatory_settings(false); |
1667 | } | 1800 | } |
@@ -1691,7 +1824,7 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy, | |||
1691 | if (!reg_beacon) | 1824 | if (!reg_beacon) |
1692 | return -ENOMEM; | 1825 | return -ENOMEM; |
1693 | 1826 | ||
1694 | REG_DBG_PRINT("cfg80211: Found new beacon on " | 1827 | REG_DBG_PRINT("Found new beacon on " |
1695 | "frequency: %d MHz (Ch %d) on %s\n", | 1828 | "frequency: %d MHz (Ch %d) on %s\n", |
1696 | beacon_chan->center_freq, | 1829 | beacon_chan->center_freq, |
1697 | ieee80211_frequency_to_channel(beacon_chan->center_freq), | 1830 | ieee80211_frequency_to_channel(beacon_chan->center_freq), |
@@ -1721,8 +1854,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) | |||
1721 | const struct ieee80211_freq_range *freq_range = NULL; | 1854 | const struct ieee80211_freq_range *freq_range = NULL; |
1722 | const struct ieee80211_power_rule *power_rule = NULL; | 1855 | const struct ieee80211_power_rule *power_rule = NULL; |
1723 | 1856 | ||
1724 | printk(KERN_INFO " (start_freq - end_freq @ bandwidth), " | 1857 | pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)\n"); |
1725 | "(max_antenna_gain, max_eirp)\n"); | ||
1726 | 1858 | ||
1727 | for (i = 0; i < rd->n_reg_rules; i++) { | 1859 | for (i = 0; i < rd->n_reg_rules; i++) { |
1728 | reg_rule = &rd->reg_rules[i]; | 1860 | reg_rule = &rd->reg_rules[i]; |
@@ -1734,16 +1866,14 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) | |||
1734 | * in certain regions | 1866 | * in certain regions |
1735 | */ | 1867 | */ |
1736 | if (power_rule->max_antenna_gain) | 1868 | if (power_rule->max_antenna_gain) |
1737 | printk(KERN_INFO " (%d KHz - %d KHz @ %d KHz), " | 1869 | pr_info(" (%d KHz - %d KHz @ %d KHz), (%d mBi, %d mBm)\n", |
1738 | "(%d mBi, %d mBm)\n", | ||
1739 | freq_range->start_freq_khz, | 1870 | freq_range->start_freq_khz, |
1740 | freq_range->end_freq_khz, | 1871 | freq_range->end_freq_khz, |
1741 | freq_range->max_bandwidth_khz, | 1872 | freq_range->max_bandwidth_khz, |
1742 | power_rule->max_antenna_gain, | 1873 | power_rule->max_antenna_gain, |
1743 | power_rule->max_eirp); | 1874 | power_rule->max_eirp); |
1744 | else | 1875 | else |
1745 | printk(KERN_INFO " (%d KHz - %d KHz @ %d KHz), " | 1876 | pr_info(" (%d KHz - %d KHz @ %d KHz), (N/A, %d mBm)\n", |
1746 | "(N/A, %d mBm)\n", | ||
1747 | freq_range->start_freq_khz, | 1877 | freq_range->start_freq_khz, |
1748 | freq_range->end_freq_khz, | 1878 | freq_range->end_freq_khz, |
1749 | freq_range->max_bandwidth_khz, | 1879 | freq_range->max_bandwidth_khz, |
@@ -1762,27 +1892,20 @@ static void print_regdomain(const struct ieee80211_regdomain *rd) | |||
1762 | rdev = cfg80211_rdev_by_wiphy_idx( | 1892 | rdev = cfg80211_rdev_by_wiphy_idx( |
1763 | last_request->wiphy_idx); | 1893 | last_request->wiphy_idx); |
1764 | if (rdev) { | 1894 | if (rdev) { |
1765 | printk(KERN_INFO "cfg80211: Current regulatory " | 1895 | pr_info("Current regulatory domain updated by AP to: %c%c\n", |
1766 | "domain updated by AP to: %c%c\n", | ||
1767 | rdev->country_ie_alpha2[0], | 1896 | rdev->country_ie_alpha2[0], |
1768 | rdev->country_ie_alpha2[1]); | 1897 | rdev->country_ie_alpha2[1]); |
1769 | } else | 1898 | } else |
1770 | printk(KERN_INFO "cfg80211: Current regulatory " | 1899 | pr_info("Current regulatory domain intersected:\n"); |
1771 | "domain intersected:\n"); | ||
1772 | } else | 1900 | } else |
1773 | printk(KERN_INFO "cfg80211: Current regulatory " | 1901 | pr_info("Current regulatory domain intersected:\n"); |
1774 | "domain intersected:\n"); | ||
1775 | } else if (is_world_regdom(rd->alpha2)) | 1902 | } else if (is_world_regdom(rd->alpha2)) |
1776 | printk(KERN_INFO "cfg80211: World regulatory " | 1903 | pr_info("World regulatory domain updated:\n"); |
1777 | "domain updated:\n"); | ||
1778 | else { | 1904 | else { |
1779 | if (is_unknown_alpha2(rd->alpha2)) | 1905 | if (is_unknown_alpha2(rd->alpha2)) |
1780 | printk(KERN_INFO "cfg80211: Regulatory domain " | 1906 | pr_info("Regulatory domain changed to driver built-in settings (unknown country)\n"); |
1781 | "changed to driver built-in settings " | ||
1782 | "(unknown country)\n"); | ||
1783 | else | 1907 | else |
1784 | printk(KERN_INFO "cfg80211: Regulatory domain " | 1908 | pr_info("Regulatory domain changed to country: %c%c\n", |
1785 | "changed to country: %c%c\n", | ||
1786 | rd->alpha2[0], rd->alpha2[1]); | 1909 | rd->alpha2[0], rd->alpha2[1]); |
1787 | } | 1910 | } |
1788 | print_rd_rules(rd); | 1911 | print_rd_rules(rd); |
@@ -1790,8 +1913,7 @@ static void print_regdomain(const struct ieee80211_regdomain *rd) | |||
1790 | 1913 | ||
1791 | static void print_regdomain_info(const struct ieee80211_regdomain *rd) | 1914 | static void print_regdomain_info(const struct ieee80211_regdomain *rd) |
1792 | { | 1915 | { |
1793 | printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n", | 1916 | pr_info("Regulatory domain: %c%c\n", rd->alpha2[0], rd->alpha2[1]); |
1794 | rd->alpha2[0], rd->alpha2[1]); | ||
1795 | print_rd_rules(rd); | 1917 | print_rd_rules(rd); |
1796 | } | 1918 | } |
1797 | 1919 | ||
@@ -1842,8 +1964,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
1842 | return -EINVAL; | 1964 | return -EINVAL; |
1843 | 1965 | ||
1844 | if (!is_valid_rd(rd)) { | 1966 | if (!is_valid_rd(rd)) { |
1845 | printk(KERN_ERR "cfg80211: Invalid " | 1967 | pr_err("Invalid regulatory domain detected:\n"); |
1846 | "regulatory domain detected:\n"); | ||
1847 | print_regdomain_info(rd); | 1968 | print_regdomain_info(rd); |
1848 | return -EINVAL; | 1969 | return -EINVAL; |
1849 | } | 1970 | } |
@@ -1959,6 +2080,8 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
1959 | 2080 | ||
1960 | nl80211_send_reg_change_event(last_request); | 2081 | nl80211_send_reg_change_event(last_request); |
1961 | 2082 | ||
2083 | reg_set_request_processed(); | ||
2084 | |||
1962 | mutex_unlock(®_mutex); | 2085 | mutex_unlock(®_mutex); |
1963 | 2086 | ||
1964 | return r; | 2087 | return r; |
@@ -2015,8 +2138,7 @@ int __init regulatory_init(void) | |||
2015 | * early boot for call_usermodehelper(). For now treat these | 2138 | * early boot for call_usermodehelper(). For now treat these |
2016 | * errors as non-fatal. | 2139 | * errors as non-fatal. |
2017 | */ | 2140 | */ |
2018 | printk(KERN_ERR "cfg80211: kobject_uevent_env() was unable " | 2141 | pr_err("kobject_uevent_env() was unable to call CRDA during init\n"); |
2019 | "to call CRDA during init"); | ||
2020 | #ifdef CONFIG_CFG80211_REG_DEBUG | 2142 | #ifdef CONFIG_CFG80211_REG_DEBUG |
2021 | /* We want to find out exactly why when debugging */ | 2143 | /* We want to find out exactly why when debugging */ |
2022 | WARN_ON(err); | 2144 | WARN_ON(err); |