diff options
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/core.c | 13 | ||||
-rw-r--r-- | net/wireless/core.h | 3 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 62 | ||||
-rw-r--r-- | net/wireless/nl80211.h | 5 | ||||
-rw-r--r-- | net/wireless/reg.c | 116 |
5 files changed, 153 insertions, 46 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index dd7f222919fe..17fe39049740 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -350,7 +350,7 @@ int wiphy_register(struct wiphy *wiphy) | |||
350 | mutex_lock(&cfg80211_mutex); | 350 | mutex_lock(&cfg80211_mutex); |
351 | 351 | ||
352 | /* set up regulatory info */ | 352 | /* set up regulatory info */ |
353 | wiphy_update_regulatory(wiphy, REGDOM_SET_BY_CORE); | 353 | wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); |
354 | 354 | ||
355 | res = device_add(&drv->wiphy.dev); | 355 | res = device_add(&drv->wiphy.dev); |
356 | if (res) | 356 | if (res) |
@@ -365,6 +365,17 @@ int wiphy_register(struct wiphy *wiphy) | |||
365 | if (IS_ERR(drv->wiphy.debugfsdir)) | 365 | if (IS_ERR(drv->wiphy.debugfsdir)) |
366 | drv->wiphy.debugfsdir = NULL; | 366 | drv->wiphy.debugfsdir = NULL; |
367 | 367 | ||
368 | if (wiphy->custom_regulatory) { | ||
369 | struct regulatory_request request; | ||
370 | |||
371 | request.wiphy_idx = get_wiphy_idx(wiphy); | ||
372 | request.initiator = NL80211_REGDOM_SET_BY_DRIVER; | ||
373 | request.alpha2[0] = '9'; | ||
374 | request.alpha2[1] = '9'; | ||
375 | |||
376 | nl80211_send_reg_change_event(&request); | ||
377 | } | ||
378 | |||
368 | res = 0; | 379 | res = 0; |
369 | out_unlock: | 380 | out_unlock: |
370 | mutex_unlock(&cfg80211_mutex); | 381 | mutex_unlock(&cfg80211_mutex); |
diff --git a/net/wireless/core.h b/net/wireless/core.h index f6c53f5807f4..6acd483a61f8 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -136,7 +136,8 @@ extern int cfg80211_dev_rename(struct cfg80211_registered_device *drv, | |||
136 | char *newname); | 136 | char *newname); |
137 | 137 | ||
138 | void ieee80211_set_bitrate_flags(struct wiphy *wiphy); | 138 | void ieee80211_set_bitrate_flags(struct wiphy *wiphy); |
139 | void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby); | 139 | void wiphy_update_regulatory(struct wiphy *wiphy, |
140 | enum nl80211_reg_initiator setby); | ||
140 | 141 | ||
141 | void cfg80211_bss_expire(struct cfg80211_registered_device *dev); | 142 | void cfg80211_bss_expire(struct cfg80211_registered_device *dev); |
142 | void cfg80211_bss_age(struct cfg80211_registered_device *dev, | 143 | void cfg80211_bss_age(struct cfg80211_registered_device *dev, |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 531bb67cf502..8ac3d26014a8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2739,6 +2739,9 @@ static struct genl_multicast_group nl80211_config_mcgrp = { | |||
2739 | static struct genl_multicast_group nl80211_scan_mcgrp = { | 2739 | static struct genl_multicast_group nl80211_scan_mcgrp = { |
2740 | .name = "scan", | 2740 | .name = "scan", |
2741 | }; | 2741 | }; |
2742 | static struct genl_multicast_group nl80211_regulatory_mcgrp = { | ||
2743 | .name = "regulatory", | ||
2744 | }; | ||
2742 | 2745 | ||
2743 | /* notification functions */ | 2746 | /* notification functions */ |
2744 | 2747 | ||
@@ -2818,6 +2821,61 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | |||
2818 | genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL); | 2821 | genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL); |
2819 | } | 2822 | } |
2820 | 2823 | ||
2824 | /* | ||
2825 | * This can happen on global regulatory changes or device specific settings | ||
2826 | * based on custom world regulatory domains. | ||
2827 | */ | ||
2828 | void nl80211_send_reg_change_event(struct regulatory_request *request) | ||
2829 | { | ||
2830 | struct sk_buff *msg; | ||
2831 | void *hdr; | ||
2832 | |||
2833 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
2834 | if (!msg) | ||
2835 | return; | ||
2836 | |||
2837 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_CHANGE); | ||
2838 | if (!hdr) { | ||
2839 | nlmsg_free(msg); | ||
2840 | return; | ||
2841 | } | ||
2842 | |||
2843 | /* Userspace can always count this one always being set */ | ||
2844 | NLA_PUT_U8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator); | ||
2845 | |||
2846 | if (request->alpha2[0] == '0' && request->alpha2[1] == '0') | ||
2847 | NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, | ||
2848 | NL80211_REGDOM_TYPE_WORLD); | ||
2849 | else if (request->alpha2[0] == '9' && request->alpha2[1] == '9') | ||
2850 | NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, | ||
2851 | NL80211_REGDOM_TYPE_CUSTOM_WORLD); | ||
2852 | else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') || | ||
2853 | request->intersect) | ||
2854 | NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, | ||
2855 | NL80211_REGDOM_TYPE_INTERSECTION); | ||
2856 | else { | ||
2857 | NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE, | ||
2858 | NL80211_REGDOM_TYPE_COUNTRY); | ||
2859 | NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, request->alpha2); | ||
2860 | } | ||
2861 | |||
2862 | if (wiphy_idx_valid(request->wiphy_idx)) | ||
2863 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx); | ||
2864 | |||
2865 | if (genlmsg_end(msg, hdr) < 0) { | ||
2866 | nlmsg_free(msg); | ||
2867 | return; | ||
2868 | } | ||
2869 | |||
2870 | genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_KERNEL); | ||
2871 | |||
2872 | return; | ||
2873 | |||
2874 | nla_put_failure: | ||
2875 | genlmsg_cancel(msg, hdr); | ||
2876 | nlmsg_free(msg); | ||
2877 | } | ||
2878 | |||
2821 | /* initialisation/exit functions */ | 2879 | /* initialisation/exit functions */ |
2822 | 2880 | ||
2823 | int nl80211_init(void) | 2881 | int nl80211_init(void) |
@@ -2842,6 +2900,10 @@ int nl80211_init(void) | |||
2842 | if (err) | 2900 | if (err) |
2843 | goto err_out; | 2901 | goto err_out; |
2844 | 2902 | ||
2903 | err = genl_register_mc_group(&nl80211_fam, &nl80211_regulatory_mcgrp); | ||
2904 | if (err) | ||
2905 | goto err_out; | ||
2906 | |||
2845 | return 0; | 2907 | return 0; |
2846 | err_out: | 2908 | err_out: |
2847 | genl_unregister_family(&nl80211_fam); | 2909 | genl_unregister_family(&nl80211_fam); |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 69787b621365..e65a3c38c52f 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -11,6 +11,7 @@ extern void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | |||
11 | struct net_device *netdev); | 11 | struct net_device *netdev); |
12 | extern void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | 12 | extern void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, |
13 | struct net_device *netdev); | 13 | struct net_device *netdev); |
14 | extern void nl80211_send_reg_change_event(struct regulatory_request *request); | ||
14 | #else | 15 | #else |
15 | static inline int nl80211_init(void) | 16 | static inline int nl80211_init(void) |
16 | { | 17 | { |
@@ -31,6 +32,10 @@ static inline void nl80211_send_scan_aborted( | |||
31 | struct cfg80211_registered_device *rdev, | 32 | struct cfg80211_registered_device *rdev, |
32 | struct net_device *netdev) | 33 | struct net_device *netdev) |
33 | {} | 34 | {} |
35 | static inline void | ||
36 | nl80211_send_reg_change_event(struct regulatory_request *request) | ||
37 | { | ||
38 | } | ||
34 | #endif /* CONFIG_NL80211 */ | 39 | #endif /* CONFIG_NL80211 */ |
35 | 40 | ||
36 | #endif /* __NET_WIRELESS_NL80211_H */ | 41 | #endif /* __NET_WIRELESS_NL80211_H */ |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 58df98f10990..eb8b8ed16155 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <net/cfg80211.h> | 41 | #include <net/cfg80211.h> |
42 | #include "core.h" | 42 | #include "core.h" |
43 | #include "reg.h" | 43 | #include "reg.h" |
44 | #include "nl80211.h" | ||
44 | 45 | ||
45 | /* Receipt of information from last regulatory request */ | 46 | /* Receipt of information from last regulatory request */ |
46 | static struct regulatory_request *last_request; | 47 | static struct regulatory_request *last_request; |
@@ -86,20 +87,31 @@ struct reg_beacon { | |||
86 | 87 | ||
87 | /* We keep a static world regulatory domain in case of the absence of CRDA */ | 88 | /* We keep a static world regulatory domain in case of the absence of CRDA */ |
88 | static const struct ieee80211_regdomain world_regdom = { | 89 | static const struct ieee80211_regdomain world_regdom = { |
89 | .n_reg_rules = 3, | 90 | .n_reg_rules = 5, |
90 | .alpha2 = "00", | 91 | .alpha2 = "00", |
91 | .reg_rules = { | 92 | .reg_rules = { |
92 | /* IEEE 802.11b/g, channels 1..11 */ | 93 | /* IEEE 802.11b/g, channels 1..11 */ |
93 | REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), | 94 | REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), |
94 | /* IEEE 802.11a, channel 36..48 */ | 95 | /* IEEE 802.11b/g, channels 12..13. No HT40 |
95 | REG_RULE(5180-10, 5240+10, 40, 6, 23, | 96 | * channel fits here. */ |
97 | REG_RULE(2467-10, 2472+10, 20, 6, 20, | ||
96 | NL80211_RRF_PASSIVE_SCAN | | 98 | NL80211_RRF_PASSIVE_SCAN | |
97 | NL80211_RRF_NO_IBSS), | 99 | NL80211_RRF_NO_IBSS), |
100 | /* IEEE 802.11 channel 14 - Only JP enables | ||
101 | * this and for 802.11b only */ | ||
102 | REG_RULE(2484-10, 2484+10, 20, 6, 20, | ||
103 | NL80211_RRF_PASSIVE_SCAN | | ||
104 | NL80211_RRF_NO_IBSS | | ||
105 | NL80211_RRF_NO_OFDM), | ||
106 | /* IEEE 802.11a, channel 36..48 */ | ||
107 | REG_RULE(5180-10, 5240+10, 40, 6, 20, | ||
108 | NL80211_RRF_PASSIVE_SCAN | | ||
109 | NL80211_RRF_NO_IBSS), | ||
98 | 110 | ||
99 | /* NB: 5260 MHz - 5700 MHz requies DFS */ | 111 | /* NB: 5260 MHz - 5700 MHz requies DFS */ |
100 | 112 | ||
101 | /* IEEE 802.11a, channel 149..165 */ | 113 | /* IEEE 802.11a, channel 149..165 */ |
102 | REG_RULE(5745-10, 5825+10, 40, 6, 23, | 114 | REG_RULE(5745-10, 5825+10, 40, 6, 20, |
103 | NL80211_RRF_PASSIVE_SCAN | | 115 | NL80211_RRF_PASSIVE_SCAN | |
104 | NL80211_RRF_NO_IBSS), | 116 | NL80211_RRF_NO_IBSS), |
105 | } | 117 | } |
@@ -846,8 +858,8 @@ static int freq_reg_info_regd(struct wiphy *wiphy, | |||
846 | * Follow the driver's regulatory domain, if present, unless a country | 858 | * Follow the driver's regulatory domain, if present, unless a country |
847 | * IE has been processed or a user wants to help complaince further | 859 | * IE has been processed or a user wants to help complaince further |
848 | */ | 860 | */ |
849 | if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE && | 861 | if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && |
850 | last_request->initiator != REGDOM_SET_BY_USER && | 862 | last_request->initiator != NL80211_REGDOM_SET_BY_USER && |
851 | wiphy->regd) | 863 | wiphy->regd) |
852 | regd = wiphy->regd; | 864 | regd = wiphy->regd; |
853 | 865 | ||
@@ -932,7 +944,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | |||
932 | * http://tinyurl.com/11d-clarification | 944 | * http://tinyurl.com/11d-clarification |
933 | */ | 945 | */ |
934 | if (r == -ERANGE && | 946 | if (r == -ERANGE && |
935 | last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) { | 947 | last_request->initiator == |
948 | NL80211_REGDOM_SET_BY_COUNTRY_IE) { | ||
936 | #ifdef CONFIG_CFG80211_REG_DEBUG | 949 | #ifdef CONFIG_CFG80211_REG_DEBUG |
937 | printk(KERN_DEBUG "cfg80211: Leaving channel %d MHz " | 950 | printk(KERN_DEBUG "cfg80211: Leaving channel %d MHz " |
938 | "intact on %s - no rule found in band on " | 951 | "intact on %s - no rule found in band on " |
@@ -945,7 +958,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | |||
945 | * for the band so we respect its band definitions | 958 | * for the band so we respect its band definitions |
946 | */ | 959 | */ |
947 | #ifdef CONFIG_CFG80211_REG_DEBUG | 960 | #ifdef CONFIG_CFG80211_REG_DEBUG |
948 | if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) | 961 | if (last_request->initiator == |
962 | NL80211_REGDOM_SET_BY_COUNTRY_IE) | ||
949 | printk(KERN_DEBUG "cfg80211: Disabling " | 963 | printk(KERN_DEBUG "cfg80211: Disabling " |
950 | "channel %d MHz on %s due to " | 964 | "channel %d MHz on %s due to " |
951 | "Country IE\n", | 965 | "Country IE\n", |
@@ -959,7 +973,7 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | |||
959 | 973 | ||
960 | power_rule = ®_rule->power_rule; | 974 | power_rule = ®_rule->power_rule; |
961 | 975 | ||
962 | if (last_request->initiator == REGDOM_SET_BY_DRIVER && | 976 | if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && |
963 | request_wiphy && request_wiphy == wiphy && | 977 | request_wiphy && request_wiphy == wiphy && |
964 | request_wiphy->strict_regulatory) { | 978 | request_wiphy->strict_regulatory) { |
965 | /* | 979 | /* |
@@ -1000,11 +1014,12 @@ static void handle_band(struct wiphy *wiphy, enum ieee80211_band band) | |||
1000 | handle_channel(wiphy, band, i); | 1014 | handle_channel(wiphy, band, i); |
1001 | } | 1015 | } |
1002 | 1016 | ||
1003 | static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby) | 1017 | static bool ignore_reg_update(struct wiphy *wiphy, |
1018 | enum nl80211_reg_initiator initiator) | ||
1004 | { | 1019 | { |
1005 | if (!last_request) | 1020 | if (!last_request) |
1006 | return true; | 1021 | return true; |
1007 | if (setby == REGDOM_SET_BY_CORE && | 1022 | if (initiator == NL80211_REGDOM_SET_BY_CORE && |
1008 | wiphy->custom_regulatory) | 1023 | wiphy->custom_regulatory) |
1009 | return true; | 1024 | return true; |
1010 | /* | 1025 | /* |
@@ -1017,12 +1032,12 @@ static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby) | |||
1017 | return false; | 1032 | return false; |
1018 | } | 1033 | } |
1019 | 1034 | ||
1020 | static void update_all_wiphy_regulatory(enum reg_set_by setby) | 1035 | static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) |
1021 | { | 1036 | { |
1022 | struct cfg80211_registered_device *drv; | 1037 | struct cfg80211_registered_device *drv; |
1023 | 1038 | ||
1024 | list_for_each_entry(drv, &cfg80211_drv_list, list) | 1039 | list_for_each_entry(drv, &cfg80211_drv_list, list) |
1025 | wiphy_update_regulatory(&drv->wiphy, setby); | 1040 | wiphy_update_regulatory(&drv->wiphy, initiator); |
1026 | } | 1041 | } |
1027 | 1042 | ||
1028 | static void handle_reg_beacon(struct wiphy *wiphy, | 1043 | static void handle_reg_beacon(struct wiphy *wiphy, |
@@ -1113,7 +1128,7 @@ static bool reg_is_world_roaming(struct wiphy *wiphy) | |||
1113 | if (is_world_regdom(cfg80211_regdomain->alpha2) || | 1128 | if (is_world_regdom(cfg80211_regdomain->alpha2) || |
1114 | (wiphy->regd && is_world_regdom(wiphy->regd->alpha2))) | 1129 | (wiphy->regd && is_world_regdom(wiphy->regd->alpha2))) |
1115 | return true; | 1130 | return true; |
1116 | if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE && | 1131 | if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && |
1117 | wiphy->custom_regulatory) | 1132 | wiphy->custom_regulatory) |
1118 | return true; | 1133 | return true; |
1119 | return false; | 1134 | return false; |
@@ -1127,11 +1142,12 @@ static void reg_process_beacons(struct wiphy *wiphy) | |||
1127 | wiphy_update_beacon_reg(wiphy); | 1142 | wiphy_update_beacon_reg(wiphy); |
1128 | } | 1143 | } |
1129 | 1144 | ||
1130 | void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) | 1145 | void wiphy_update_regulatory(struct wiphy *wiphy, |
1146 | enum nl80211_reg_initiator initiator) | ||
1131 | { | 1147 | { |
1132 | enum ieee80211_band band; | 1148 | enum ieee80211_band band; |
1133 | 1149 | ||
1134 | if (ignore_reg_update(wiphy, setby)) | 1150 | if (ignore_reg_update(wiphy, initiator)) |
1135 | goto out; | 1151 | goto out; |
1136 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 1152 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
1137 | if (wiphy->bands[band]) | 1153 | if (wiphy->bands[band]) |
@@ -1244,17 +1260,16 @@ static int ignore_request(struct wiphy *wiphy, | |||
1244 | return 0; | 1260 | return 0; |
1245 | 1261 | ||
1246 | switch (pending_request->initiator) { | 1262 | switch (pending_request->initiator) { |
1247 | case REGDOM_SET_BY_INIT: | 1263 | case NL80211_REGDOM_SET_BY_CORE: |
1248 | return -EINVAL; | 1264 | return -EINVAL; |
1249 | case REGDOM_SET_BY_CORE: | 1265 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
1250 | return -EINVAL; | ||
1251 | case REGDOM_SET_BY_COUNTRY_IE: | ||
1252 | 1266 | ||
1253 | last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); | 1267 | last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); |
1254 | 1268 | ||
1255 | if (unlikely(!is_an_alpha2(pending_request->alpha2))) | 1269 | if (unlikely(!is_an_alpha2(pending_request->alpha2))) |
1256 | return -EINVAL; | 1270 | return -EINVAL; |
1257 | if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) { | 1271 | if (last_request->initiator == |
1272 | NL80211_REGDOM_SET_BY_COUNTRY_IE) { | ||
1258 | if (last_wiphy != wiphy) { | 1273 | if (last_wiphy != wiphy) { |
1259 | /* | 1274 | /* |
1260 | * Two cards with two APs claiming different | 1275 | * Two cards with two APs claiming different |
@@ -1275,8 +1290,8 @@ static int ignore_request(struct wiphy *wiphy, | |||
1275 | return -EALREADY; | 1290 | return -EALREADY; |
1276 | } | 1291 | } |
1277 | return REG_INTERSECT; | 1292 | return REG_INTERSECT; |
1278 | case REGDOM_SET_BY_DRIVER: | 1293 | case NL80211_REGDOM_SET_BY_DRIVER: |
1279 | if (last_request->initiator == REGDOM_SET_BY_CORE) { | 1294 | if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) { |
1280 | if (is_old_static_regdom(cfg80211_regdomain)) | 1295 | if (is_old_static_regdom(cfg80211_regdomain)) |
1281 | return 0; | 1296 | return 0; |
1282 | if (regdom_changes(pending_request->alpha2)) | 1297 | if (regdom_changes(pending_request->alpha2)) |
@@ -1289,28 +1304,28 @@ static int ignore_request(struct wiphy *wiphy, | |||
1289 | * back in or if you add a new device for which the previously | 1304 | * back in or if you add a new device for which the previously |
1290 | * loaded card also agrees on the regulatory domain. | 1305 | * loaded card also agrees on the regulatory domain. |
1291 | */ | 1306 | */ |
1292 | if (last_request->initiator == REGDOM_SET_BY_DRIVER && | 1307 | if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && |
1293 | !regdom_changes(pending_request->alpha2)) | 1308 | !regdom_changes(pending_request->alpha2)) |
1294 | return -EALREADY; | 1309 | return -EALREADY; |
1295 | 1310 | ||
1296 | return REG_INTERSECT; | 1311 | return REG_INTERSECT; |
1297 | case REGDOM_SET_BY_USER: | 1312 | case NL80211_REGDOM_SET_BY_USER: |
1298 | if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) | 1313 | if (last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) |
1299 | return REG_INTERSECT; | 1314 | return REG_INTERSECT; |
1300 | /* | 1315 | /* |
1301 | * If the user knows better the user should set the regdom | 1316 | * If the user knows better the user should set the regdom |
1302 | * to their country before the IE is picked up | 1317 | * to their country before the IE is picked up |
1303 | */ | 1318 | */ |
1304 | if (last_request->initiator == REGDOM_SET_BY_USER && | 1319 | if (last_request->initiator == NL80211_REGDOM_SET_BY_USER && |
1305 | last_request->intersect) | 1320 | last_request->intersect) |
1306 | return -EOPNOTSUPP; | 1321 | return -EOPNOTSUPP; |
1307 | /* | 1322 | /* |
1308 | * Process user requests only after previous user/driver/core | 1323 | * Process user requests only after previous user/driver/core |
1309 | * requests have been processed | 1324 | * requests have been processed |
1310 | */ | 1325 | */ |
1311 | if (last_request->initiator == REGDOM_SET_BY_CORE || | 1326 | if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE || |
1312 | last_request->initiator == REGDOM_SET_BY_DRIVER || | 1327 | last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER || |
1313 | last_request->initiator == REGDOM_SET_BY_USER) { | 1328 | last_request->initiator == NL80211_REGDOM_SET_BY_USER) { |
1314 | if (regdom_changes(last_request->alpha2)) | 1329 | if (regdom_changes(last_request->alpha2)) |
1315 | return -EAGAIN; | 1330 | return -EAGAIN; |
1316 | } | 1331 | } |
@@ -1350,7 +1365,8 @@ static int __regulatory_hint(struct wiphy *wiphy, | |||
1350 | r = ignore_request(wiphy, pending_request); | 1365 | r = ignore_request(wiphy, pending_request); |
1351 | 1366 | ||
1352 | if (r == REG_INTERSECT) { | 1367 | if (r == REG_INTERSECT) { |
1353 | if (pending_request->initiator == REGDOM_SET_BY_DRIVER) { | 1368 | if (pending_request->initiator == |
1369 | NL80211_REGDOM_SET_BY_DRIVER) { | ||
1354 | r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain); | 1370 | r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain); |
1355 | if (r) { | 1371 | if (r) { |
1356 | kfree(pending_request); | 1372 | kfree(pending_request); |
@@ -1365,7 +1381,8 @@ static int __regulatory_hint(struct wiphy *wiphy, | |||
1365 | * wiphy | 1381 | * wiphy |
1366 | */ | 1382 | */ |
1367 | if (r == -EALREADY && | 1383 | if (r == -EALREADY && |
1368 | pending_request->initiator == REGDOM_SET_BY_DRIVER) { | 1384 | pending_request->initiator == |
1385 | NL80211_REGDOM_SET_BY_DRIVER) { | ||
1369 | r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain); | 1386 | r = reg_copy_regd(&wiphy->regd, cfg80211_regdomain); |
1370 | if (r) { | 1387 | if (r) { |
1371 | kfree(pending_request); | 1388 | kfree(pending_request); |
@@ -1387,8 +1404,16 @@ new_request: | |||
1387 | pending_request = NULL; | 1404 | pending_request = NULL; |
1388 | 1405 | ||
1389 | /* When r == REG_INTERSECT we do need to call CRDA */ | 1406 | /* When r == REG_INTERSECT we do need to call CRDA */ |
1390 | if (r < 0) | 1407 | if (r < 0) { |
1408 | /* | ||
1409 | * Since CRDA will not be called in this case as we already | ||
1410 | * have applied the requested regulatory domain before we just | ||
1411 | * inform userspace we have processed the request | ||
1412 | */ | ||
1413 | if (r == -EALREADY) | ||
1414 | nl80211_send_reg_change_event(last_request); | ||
1391 | return r; | 1415 | return r; |
1416 | } | ||
1392 | 1417 | ||
1393 | /* | 1418 | /* |
1394 | * Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled | 1419 | * Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled |
@@ -1416,7 +1441,7 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
1416 | if (wiphy_idx_valid(reg_request->wiphy_idx)) | 1441 | if (wiphy_idx_valid(reg_request->wiphy_idx)) |
1417 | wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); | 1442 | wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); |
1418 | 1443 | ||
1419 | if (reg_request->initiator == REGDOM_SET_BY_DRIVER && | 1444 | if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && |
1420 | !wiphy) { | 1445 | !wiphy) { |
1421 | kfree(reg_request); | 1446 | kfree(reg_request); |
1422 | goto out; | 1447 | goto out; |
@@ -1430,7 +1455,7 @@ out: | |||
1430 | mutex_unlock(&cfg80211_mutex); | 1455 | mutex_unlock(&cfg80211_mutex); |
1431 | } | 1456 | } |
1432 | 1457 | ||
1433 | /* Processes regulatory hints, this is all the REGDOM_SET_BY_* */ | 1458 | /* Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_* */ |
1434 | static void reg_process_pending_hints(void) | 1459 | static void reg_process_pending_hints(void) |
1435 | { | 1460 | { |
1436 | struct regulatory_request *reg_request; | 1461 | struct regulatory_request *reg_request; |
@@ -1514,7 +1539,7 @@ static int regulatory_hint_core(const char *alpha2) | |||
1514 | 1539 | ||
1515 | request->alpha2[0] = alpha2[0]; | 1540 | request->alpha2[0] = alpha2[0]; |
1516 | request->alpha2[1] = alpha2[1]; | 1541 | request->alpha2[1] = alpha2[1]; |
1517 | request->initiator = REGDOM_SET_BY_CORE; | 1542 | request->initiator = NL80211_REGDOM_SET_BY_CORE; |
1518 | 1543 | ||
1519 | queue_regulatory_request(request); | 1544 | queue_regulatory_request(request); |
1520 | 1545 | ||
@@ -1535,7 +1560,7 @@ int regulatory_hint_user(const char *alpha2) | |||
1535 | request->wiphy_idx = WIPHY_IDX_STALE; | 1560 | request->wiphy_idx = WIPHY_IDX_STALE; |
1536 | request->alpha2[0] = alpha2[0]; | 1561 | request->alpha2[0] = alpha2[0]; |
1537 | request->alpha2[1] = alpha2[1]; | 1562 | request->alpha2[1] = alpha2[1]; |
1538 | request->initiator = REGDOM_SET_BY_USER, | 1563 | request->initiator = NL80211_REGDOM_SET_BY_USER, |
1539 | 1564 | ||
1540 | queue_regulatory_request(request); | 1565 | queue_regulatory_request(request); |
1541 | 1566 | ||
@@ -1561,7 +1586,7 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2) | |||
1561 | 1586 | ||
1562 | request->alpha2[0] = alpha2[0]; | 1587 | request->alpha2[0] = alpha2[0]; |
1563 | request->alpha2[1] = alpha2[1]; | 1588 | request->alpha2[1] = alpha2[1]; |
1564 | request->initiator = REGDOM_SET_BY_DRIVER; | 1589 | request->initiator = NL80211_REGDOM_SET_BY_DRIVER; |
1565 | 1590 | ||
1566 | queue_regulatory_request(request); | 1591 | queue_regulatory_request(request); |
1567 | 1592 | ||
@@ -1710,7 +1735,7 @@ void regulatory_hint_11d(struct wiphy *wiphy, | |||
1710 | request->wiphy_idx = get_wiphy_idx(wiphy); | 1735 | request->wiphy_idx = get_wiphy_idx(wiphy); |
1711 | request->alpha2[0] = rd->alpha2[0]; | 1736 | request->alpha2[0] = rd->alpha2[0]; |
1712 | request->alpha2[1] = rd->alpha2[1]; | 1737 | request->alpha2[1] = rd->alpha2[1]; |
1713 | request->initiator = REGDOM_SET_BY_COUNTRY_IE; | 1738 | request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE; |
1714 | request->country_ie_checksum = checksum; | 1739 | request->country_ie_checksum = checksum; |
1715 | request->country_ie_env = env; | 1740 | request->country_ie_env = env; |
1716 | 1741 | ||
@@ -1818,7 +1843,8 @@ static void print_regdomain(const struct ieee80211_regdomain *rd) | |||
1818 | 1843 | ||
1819 | if (is_intersected_alpha2(rd->alpha2)) { | 1844 | if (is_intersected_alpha2(rd->alpha2)) { |
1820 | 1845 | ||
1821 | if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) { | 1846 | if (last_request->initiator == |
1847 | NL80211_REGDOM_SET_BY_COUNTRY_IE) { | ||
1822 | struct cfg80211_registered_device *drv; | 1848 | struct cfg80211_registered_device *drv; |
1823 | drv = cfg80211_drv_by_wiphy_idx( | 1849 | drv = cfg80211_drv_by_wiphy_idx( |
1824 | last_request->wiphy_idx); | 1850 | last_request->wiphy_idx); |
@@ -1910,7 +1936,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
1910 | * rd is non static (it means CRDA was present and was used last) | 1936 | * rd is non static (it means CRDA was present and was used last) |
1911 | * and the pending request came in from a country IE | 1937 | * and the pending request came in from a country IE |
1912 | */ | 1938 | */ |
1913 | if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE) { | 1939 | if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { |
1914 | /* | 1940 | /* |
1915 | * If someone else asked us to change the rd lets only bother | 1941 | * If someone else asked us to change the rd lets only bother |
1916 | * checking if the alpha2 changes if CRDA was already called | 1942 | * checking if the alpha2 changes if CRDA was already called |
@@ -1942,7 +1968,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
1942 | if (!last_request->intersect) { | 1968 | if (!last_request->intersect) { |
1943 | int r; | 1969 | int r; |
1944 | 1970 | ||
1945 | if (last_request->initiator != REGDOM_SET_BY_DRIVER) { | 1971 | if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) { |
1946 | reset_regdomains(); | 1972 | reset_regdomains(); |
1947 | cfg80211_regdomain = rd; | 1973 | cfg80211_regdomain = rd; |
1948 | return 0; | 1974 | return 0; |
@@ -1966,7 +1992,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
1966 | 1992 | ||
1967 | /* Intersection requires a bit more work */ | 1993 | /* Intersection requires a bit more work */ |
1968 | 1994 | ||
1969 | if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE) { | 1995 | if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { |
1970 | 1996 | ||
1971 | intersected_rd = regdom_intersect(rd, cfg80211_regdomain); | 1997 | intersected_rd = regdom_intersect(rd, cfg80211_regdomain); |
1972 | if (!intersected_rd) | 1998 | if (!intersected_rd) |
@@ -1977,7 +2003,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
1977 | * However if a driver requested this specific regulatory | 2003 | * However if a driver requested this specific regulatory |
1978 | * domain we keep it for its private use | 2004 | * domain we keep it for its private use |
1979 | */ | 2005 | */ |
1980 | if (last_request->initiator == REGDOM_SET_BY_DRIVER) | 2006 | if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER) |
1981 | request_wiphy->regd = rd; | 2007 | request_wiphy->regd = rd; |
1982 | else | 2008 | else |
1983 | kfree(rd); | 2009 | kfree(rd); |
@@ -2067,6 +2093,8 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
2067 | 2093 | ||
2068 | print_regdomain(cfg80211_regdomain); | 2094 | print_regdomain(cfg80211_regdomain); |
2069 | 2095 | ||
2096 | nl80211_send_reg_change_event(last_request); | ||
2097 | |||
2070 | return r; | 2098 | return r; |
2071 | } | 2099 | } |
2072 | 2100 | ||