aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/reg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r--net/wireless/reg.c49
1 files changed, 33 insertions, 16 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index e71f5a66574e..3302c56f60d1 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -57,8 +57,17 @@
57#define REG_DBG_PRINT(args...) 57#define REG_DBG_PRINT(args...)
58#endif 58#endif
59 59
60static struct regulatory_request core_request_world = {
61 .initiator = NL80211_REGDOM_SET_BY_CORE,
62 .alpha2[0] = '0',
63 .alpha2[1] = '0',
64 .intersect = false,
65 .processed = true,
66 .country_ie_env = ENVIRON_ANY,
67};
68
60/* Receipt of information from last regulatory request */ 69/* Receipt of information from last regulatory request */
61static struct regulatory_request *last_request; 70static struct regulatory_request *last_request = &core_request_world;
62 71
63/* To trigger userspace events */ 72/* To trigger userspace events */
64static struct platform_device *reg_pdev; 73static struct platform_device *reg_pdev;
@@ -150,7 +159,7 @@ static char user_alpha2[2];
150module_param(ieee80211_regdom, charp, 0444); 159module_param(ieee80211_regdom, charp, 0444);
151MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); 160MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
152 161
153static void reset_regdomains(void) 162static void reset_regdomains(bool full_reset)
154{ 163{
155 /* avoid freeing static information or freeing something twice */ 164 /* avoid freeing static information or freeing something twice */
156 if (cfg80211_regdomain == cfg80211_world_regdom) 165 if (cfg80211_regdomain == cfg80211_world_regdom)
@@ -165,6 +174,13 @@ static void reset_regdomains(void)
165 174
166 cfg80211_world_regdom = &world_regdom; 175 cfg80211_world_regdom = &world_regdom;
167 cfg80211_regdomain = NULL; 176 cfg80211_regdomain = NULL;
177
178 if (!full_reset)
179 return;
180
181 if (last_request != &core_request_world)
182 kfree(last_request);
183 last_request = &core_request_world;
168} 184}
169 185
170/* 186/*
@@ -175,7 +191,7 @@ static void update_world_regdomain(const struct ieee80211_regdomain *rd)
175{ 191{
176 BUG_ON(!last_request); 192 BUG_ON(!last_request);
177 193
178 reset_regdomains(); 194 reset_regdomains(false);
179 195
180 cfg80211_world_regdom = rd; 196 cfg80211_world_regdom = rd;
181 cfg80211_regdomain = rd; 197 cfg80211_regdomain = rd;
@@ -1407,7 +1423,8 @@ static int __regulatory_hint(struct wiphy *wiphy,
1407 } 1423 }
1408 1424
1409new_request: 1425new_request:
1410 kfree(last_request); 1426 if (last_request != &core_request_world)
1427 kfree(last_request);
1411 1428
1412 last_request = pending_request; 1429 last_request = pending_request;
1413 last_request->intersect = intersect; 1430 last_request->intersect = intersect;
@@ -1577,9 +1594,6 @@ static int regulatory_hint_core(const char *alpha2)
1577{ 1594{
1578 struct regulatory_request *request; 1595 struct regulatory_request *request;
1579 1596
1580 kfree(last_request);
1581 last_request = NULL;
1582
1583 request = kzalloc(sizeof(struct regulatory_request), 1597 request = kzalloc(sizeof(struct regulatory_request),
1584 GFP_KERNEL); 1598 GFP_KERNEL);
1585 if (!request) 1599 if (!request)
@@ -1777,7 +1791,7 @@ static void restore_regulatory_settings(bool reset_user)
1777 mutex_lock(&cfg80211_mutex); 1791 mutex_lock(&cfg80211_mutex);
1778 mutex_lock(&reg_mutex); 1792 mutex_lock(&reg_mutex);
1779 1793
1780 reset_regdomains(); 1794 reset_regdomains(true);
1781 restore_alpha2(alpha2, reset_user); 1795 restore_alpha2(alpha2, reset_user);
1782 1796
1783 /* 1797 /*
@@ -2037,12 +2051,18 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
2037 } 2051 }
2038 2052
2039 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); 2053 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
2054 if (!request_wiphy &&
2055 (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
2056 last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
2057 schedule_delayed_work(&reg_timeout, 0);
2058 return -ENODEV;
2059 }
2040 2060
2041 if (!last_request->intersect) { 2061 if (!last_request->intersect) {
2042 int r; 2062 int r;
2043 2063
2044 if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) { 2064 if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) {
2045 reset_regdomains(); 2065 reset_regdomains(false);
2046 cfg80211_regdomain = rd; 2066 cfg80211_regdomain = rd;
2047 return 0; 2067 return 0;
2048 } 2068 }
@@ -2063,7 +2083,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
2063 if (r) 2083 if (r)
2064 return r; 2084 return r;
2065 2085
2066 reset_regdomains(); 2086 reset_regdomains(false);
2067 cfg80211_regdomain = rd; 2087 cfg80211_regdomain = rd;
2068 return 0; 2088 return 0;
2069 } 2089 }
@@ -2088,7 +2108,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
2088 2108
2089 rd = NULL; 2109 rd = NULL;
2090 2110
2091 reset_regdomains(); 2111 reset_regdomains(false);
2092 cfg80211_regdomain = intersected_rd; 2112 cfg80211_regdomain = intersected_rd;
2093 2113
2094 return 0; 2114 return 0;
@@ -2108,7 +2128,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
2108 kfree(rd); 2128 kfree(rd);
2109 rd = NULL; 2129 rd = NULL;
2110 2130
2111 reset_regdomains(); 2131 reset_regdomains(false);
2112 cfg80211_regdomain = intersected_rd; 2132 cfg80211_regdomain = intersected_rd;
2113 2133
2114 return 0; 2134 return 0;
@@ -2261,11 +2281,8 @@ void /* __init_or_exit */ regulatory_exit(void)
2261 mutex_lock(&cfg80211_mutex); 2281 mutex_lock(&cfg80211_mutex);
2262 mutex_lock(&reg_mutex); 2282 mutex_lock(&reg_mutex);
2263 2283
2264 reset_regdomains(); 2284 reset_regdomains(true);
2265
2266 kfree(last_request);
2267 2285
2268 last_request = NULL;
2269 dev_set_uevent_suppress(&reg_pdev->dev, true); 2286 dev_set_uevent_suppress(&reg_pdev->dev, true);
2270 2287
2271 platform_device_unregister(reg_pdev); 2288 platform_device_unregister(reg_pdev);