diff options
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r-- | net/wireless/reg.c | 49 |
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 | ||
60 | static 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 */ |
61 | static struct regulatory_request *last_request; | 70 | static struct regulatory_request *last_request = &core_request_world; |
62 | 71 | ||
63 | /* To trigger userspace events */ | 72 | /* To trigger userspace events */ |
64 | static struct platform_device *reg_pdev; | 73 | static struct platform_device *reg_pdev; |
@@ -150,7 +159,7 @@ static char user_alpha2[2]; | |||
150 | module_param(ieee80211_regdom, charp, 0444); | 159 | module_param(ieee80211_regdom, charp, 0444); |
151 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | 160 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); |
152 | 161 | ||
153 | static void reset_regdomains(void) | 162 | static 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 | ||
1409 | new_request: | 1425 | new_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(®_mutex); | 1792 | mutex_lock(®_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(®_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(®_mutex); | 2282 | mutex_lock(®_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(®_pdev->dev, true); | 2286 | dev_set_uevent_suppress(®_pdev->dev, true); |
2270 | 2287 | ||
2271 | platform_device_unregister(reg_pdev); | 2288 | platform_device_unregister(reg_pdev); |