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.c169
1 files changed, 74 insertions, 95 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 75a406d33619..f256dfffbf46 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -62,6 +62,16 @@ const struct ieee80211_regdomain *cfg80211_regdomain;
62 */ 62 */
63static const struct ieee80211_regdomain *country_ie_regdomain; 63static const struct ieee80211_regdomain *country_ie_regdomain;
64 64
65/*
66 * Protects static reg.c components:
67 * - cfg80211_world_regdom
68 * - cfg80211_regdom
69 * - country_ie_regdomain
70 * - last_request
71 */
72DEFINE_MUTEX(reg_mutex);
73#define assert_reg_lock() WARN_ON(!mutex_is_locked(&reg_mutex))
74
65/* Used to queue up regulatory hints */ 75/* Used to queue up regulatory hints */
66static LIST_HEAD(reg_requests_list); 76static LIST_HEAD(reg_requests_list);
67static spinlock_t reg_requests_lock; 77static spinlock_t reg_requests_lock;
@@ -113,11 +123,7 @@ static const struct ieee80211_regdomain world_regdom = {
113static const struct ieee80211_regdomain *cfg80211_world_regdom = 123static const struct ieee80211_regdomain *cfg80211_world_regdom =
114 &world_regdom; 124 &world_regdom;
115 125
116#ifdef CONFIG_WIRELESS_OLD_REGULATORY
117static char *ieee80211_regdom = "US";
118#else
119static char *ieee80211_regdom = "00"; 126static char *ieee80211_regdom = "00";
120#endif
121 127
122module_param(ieee80211_regdom, charp, 0444); 128module_param(ieee80211_regdom, charp, 0444);
123MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); 129MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
@@ -1012,7 +1018,6 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
1012 map_regdom_flags(reg_rule->flags) | bw_flags; 1018 map_regdom_flags(reg_rule->flags) | bw_flags;
1013 chan->max_antenna_gain = chan->orig_mag = 1019 chan->max_antenna_gain = chan->orig_mag =
1014 (int) MBI_TO_DBI(power_rule->max_antenna_gain); 1020 (int) MBI_TO_DBI(power_rule->max_antenna_gain);
1015 chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
1016 chan->max_power = chan->orig_mpwr = 1021 chan->max_power = chan->orig_mpwr =
1017 (int) MBM_TO_DBM(power_rule->max_eirp); 1022 (int) MBM_TO_DBM(power_rule->max_eirp);
1018 return; 1023 return;
@@ -1021,7 +1026,6 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
1021 chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags); 1026 chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags);
1022 chan->max_antenna_gain = min(chan->orig_mag, 1027 chan->max_antenna_gain = min(chan->orig_mag,
1023 (int) MBI_TO_DBI(power_rule->max_antenna_gain)); 1028 (int) MBI_TO_DBI(power_rule->max_antenna_gain));
1024 chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
1025 if (chan->orig_mpwr) 1029 if (chan->orig_mpwr)
1026 chan->max_power = min(chan->orig_mpwr, 1030 chan->max_power = min(chan->orig_mpwr,
1027 (int) MBM_TO_DBM(power_rule->max_eirp)); 1031 (int) MBM_TO_DBM(power_rule->max_eirp));
@@ -1061,10 +1065,10 @@ static bool ignore_reg_update(struct wiphy *wiphy,
1061 1065
1062static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) 1066static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
1063{ 1067{
1064 struct cfg80211_registered_device *drv; 1068 struct cfg80211_registered_device *rdev;
1065 1069
1066 list_for_each_entry(drv, &cfg80211_drv_list, list) 1070 list_for_each_entry(rdev, &cfg80211_rdev_list, list)
1067 wiphy_update_regulatory(&drv->wiphy, initiator); 1071 wiphy_update_regulatory(&rdev->wiphy, initiator);
1068} 1072}
1069 1073
1070static void handle_reg_beacon(struct wiphy *wiphy, 1074static void handle_reg_beacon(struct wiphy *wiphy,
@@ -1298,7 +1302,7 @@ static void handle_channel_custom(struct wiphy *wiphy,
1298 struct ieee80211_supported_band *sband; 1302 struct ieee80211_supported_band *sband;
1299 struct ieee80211_channel *chan; 1303 struct ieee80211_channel *chan;
1300 1304
1301 assert_cfg80211_lock(); 1305 assert_reg_lock();
1302 1306
1303 sband = wiphy->bands[band]; 1307 sband = wiphy->bands[band];
1304 BUG_ON(chan_idx >= sband->n_channels); 1308 BUG_ON(chan_idx >= sband->n_channels);
@@ -1323,7 +1327,6 @@ static void handle_channel_custom(struct wiphy *wiphy,
1323 1327
1324 chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; 1328 chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
1325 chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); 1329 chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
1326 chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
1327 chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); 1330 chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
1328} 1331}
1329 1332
@@ -1347,14 +1350,14 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
1347 enum ieee80211_band band; 1350 enum ieee80211_band band;
1348 unsigned int bands_set = 0; 1351 unsigned int bands_set = 0;
1349 1352
1350 mutex_lock(&cfg80211_mutex); 1353 mutex_lock(&reg_mutex);
1351 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 1354 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1352 if (!wiphy->bands[band]) 1355 if (!wiphy->bands[band])
1353 continue; 1356 continue;
1354 handle_band_custom(wiphy, band, regd); 1357 handle_band_custom(wiphy, band, regd);
1355 bands_set++; 1358 bands_set++;
1356 } 1359 }
1357 mutex_unlock(&cfg80211_mutex); 1360 mutex_unlock(&reg_mutex);
1358 1361
1359 /* 1362 /*
1360 * no point in calling this if it won't have any effect 1363 * no point in calling this if it won't have any effect
@@ -1421,7 +1424,7 @@ static int ignore_request(struct wiphy *wiphy,
1421 if (last_wiphy != wiphy) { 1424 if (last_wiphy != wiphy) {
1422 /* 1425 /*
1423 * Two cards with two APs claiming different 1426 * Two cards with two APs claiming different
1424 * different Country IE alpha2s. We could 1427 * Country IE alpha2s. We could
1425 * intersect them, but that seems unlikely 1428 * intersect them, but that seems unlikely
1426 * to be correct. Reject second one for now. 1429 * to be correct. Reject second one for now.
1427 */ 1430 */
@@ -1500,7 +1503,7 @@ static int ignore_request(struct wiphy *wiphy,
1500 * Returns zero if all went fine, %-EALREADY if a regulatory domain had 1503 * Returns zero if all went fine, %-EALREADY if a regulatory domain had
1501 * already been set or other standard error codes. 1504 * already been set or other standard error codes.
1502 * 1505 *
1503 * Caller must hold &cfg80211_mutex 1506 * Caller must hold &cfg80211_mutex and &reg_mutex
1504 */ 1507 */
1505static int __regulatory_hint(struct wiphy *wiphy, 1508static int __regulatory_hint(struct wiphy *wiphy,
1506 struct regulatory_request *pending_request) 1509 struct regulatory_request *pending_request)
@@ -1575,6 +1578,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
1575 BUG_ON(!reg_request->alpha2); 1578 BUG_ON(!reg_request->alpha2);
1576 1579
1577 mutex_lock(&cfg80211_mutex); 1580 mutex_lock(&cfg80211_mutex);
1581 mutex_lock(&reg_mutex);
1578 1582
1579 if (wiphy_idx_valid(reg_request->wiphy_idx)) 1583 if (wiphy_idx_valid(reg_request->wiphy_idx))
1580 wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); 1584 wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
@@ -1590,6 +1594,7 @@ static void reg_process_hint(struct regulatory_request *reg_request)
1590 if (r == -EALREADY && wiphy && wiphy->strict_regulatory) 1594 if (r == -EALREADY && wiphy && wiphy->strict_regulatory)
1591 wiphy_update_regulatory(wiphy, reg_request->initiator); 1595 wiphy_update_regulatory(wiphy, reg_request->initiator);
1592out: 1596out:
1597 mutex_unlock(&reg_mutex);
1593 mutex_unlock(&cfg80211_mutex); 1598 mutex_unlock(&cfg80211_mutex);
1594} 1599}
1595 1600
@@ -1615,9 +1620,13 @@ static void reg_process_pending_hints(void)
1615/* Processes beacon hints -- this has nothing to do with country IEs */ 1620/* Processes beacon hints -- this has nothing to do with country IEs */
1616static void reg_process_pending_beacon_hints(void) 1621static void reg_process_pending_beacon_hints(void)
1617{ 1622{
1618 struct cfg80211_registered_device *drv; 1623 struct cfg80211_registered_device *rdev;
1619 struct reg_beacon *pending_beacon, *tmp; 1624 struct reg_beacon *pending_beacon, *tmp;
1620 1625
1626 /*
1627 * No need to hold the reg_mutex here as we just touch wiphys
1628 * and do not read or access regulatory variables.
1629 */
1621 mutex_lock(&cfg80211_mutex); 1630 mutex_lock(&cfg80211_mutex);
1622 1631
1623 /* This goes through the _pending_ beacon list */ 1632 /* This goes through the _pending_ beacon list */
@@ -1634,8 +1643,8 @@ static void reg_process_pending_beacon_hints(void)
1634 list_del_init(&pending_beacon->list); 1643 list_del_init(&pending_beacon->list);
1635 1644
1636 /* Applies the beacon hint to current wiphys */ 1645 /* Applies the beacon hint to current wiphys */
1637 list_for_each_entry(drv, &cfg80211_drv_list, list) 1646 list_for_each_entry(rdev, &cfg80211_rdev_list, list)
1638 wiphy_update_new_beacon(&drv->wiphy, pending_beacon); 1647 wiphy_update_new_beacon(&rdev->wiphy, pending_beacon);
1639 1648
1640 /* Remembers the beacon hint for new wiphys or reg changes */ 1649 /* Remembers the beacon hint for new wiphys or reg changes */
1641 list_add_tail(&pending_beacon->list, &reg_beacon_list); 1650 list_add_tail(&pending_beacon->list, &reg_beacon_list);
@@ -1739,12 +1748,13 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
1739} 1748}
1740EXPORT_SYMBOL(regulatory_hint); 1749EXPORT_SYMBOL(regulatory_hint);
1741 1750
1751/* Caller must hold reg_mutex */
1742static bool reg_same_country_ie_hint(struct wiphy *wiphy, 1752static bool reg_same_country_ie_hint(struct wiphy *wiphy,
1743 u32 country_ie_checksum) 1753 u32 country_ie_checksum)
1744{ 1754{
1745 struct wiphy *request_wiphy; 1755 struct wiphy *request_wiphy;
1746 1756
1747 assert_cfg80211_lock(); 1757 assert_reg_lock();
1748 1758
1749 if (unlikely(last_request->initiator != 1759 if (unlikely(last_request->initiator !=
1750 NL80211_REGDOM_SET_BY_COUNTRY_IE)) 1760 NL80211_REGDOM_SET_BY_COUNTRY_IE))
@@ -1767,6 +1777,10 @@ static bool reg_same_country_ie_hint(struct wiphy *wiphy,
1767 return false; 1777 return false;
1768} 1778}
1769 1779
1780/*
1781 * We hold wdev_lock() here so we cannot hold cfg80211_mutex() and
1782 * therefore cannot iterate over the rdev list here.
1783 */
1770void regulatory_hint_11d(struct wiphy *wiphy, 1784void regulatory_hint_11d(struct wiphy *wiphy,
1771 u8 *country_ie, 1785 u8 *country_ie,
1772 u8 country_ie_len) 1786 u8 country_ie_len)
@@ -1777,12 +1791,10 @@ void regulatory_hint_11d(struct wiphy *wiphy,
1777 enum environment_cap env = ENVIRON_ANY; 1791 enum environment_cap env = ENVIRON_ANY;
1778 struct regulatory_request *request; 1792 struct regulatory_request *request;
1779 1793
1780 mutex_lock(&cfg80211_mutex); 1794 mutex_lock(&reg_mutex);
1781 1795
1782 if (unlikely(!last_request)) { 1796 if (unlikely(!last_request))
1783 mutex_unlock(&cfg80211_mutex); 1797 goto out;
1784 return;
1785 }
1786 1798
1787 /* IE len must be evenly divisible by 2 */ 1799 /* IE len must be evenly divisible by 2 */
1788 if (country_ie_len & 0x01) 1800 if (country_ie_len & 0x01)
@@ -1808,54 +1820,14 @@ void regulatory_hint_11d(struct wiphy *wiphy,
1808 env = ENVIRON_OUTDOOR; 1820 env = ENVIRON_OUTDOOR;
1809 1821
1810 /* 1822 /*
1811 * We will run this for *every* beacon processed for the BSSID, so 1823 * We will run this only upon a successful connection on cfg80211.
1812 * we optimize an early check to exit out early if we don't have to 1824 * We leave conflict resolution to the workqueue, where can hold
1813 * do anything 1825 * cfg80211_mutex.
1814 */ 1826 */
1815 if (likely(last_request->initiator == 1827 if (likely(last_request->initiator ==
1816 NL80211_REGDOM_SET_BY_COUNTRY_IE && 1828 NL80211_REGDOM_SET_BY_COUNTRY_IE &&
1817 wiphy_idx_valid(last_request->wiphy_idx))) { 1829 wiphy_idx_valid(last_request->wiphy_idx)))
1818 struct cfg80211_registered_device *drv_last_ie; 1830 goto out;
1819
1820 drv_last_ie =
1821 cfg80211_drv_by_wiphy_idx(last_request->wiphy_idx);
1822
1823 /*
1824 * Lets keep this simple -- we trust the first AP
1825 * after we intersect with CRDA
1826 */
1827 if (likely(&drv_last_ie->wiphy == wiphy)) {
1828 /*
1829 * Ignore IEs coming in on this wiphy with
1830 * the same alpha2 and environment cap
1831 */
1832 if (likely(alpha2_equal(drv_last_ie->country_ie_alpha2,
1833 alpha2) &&
1834 env == drv_last_ie->env)) {
1835 goto out;
1836 }
1837 /*
1838 * the wiphy moved on to another BSSID or the AP
1839 * was reconfigured. XXX: We need to deal with the
1840 * case where the user suspends and goes to goes
1841 * to another country, and then gets IEs from an
1842 * AP with different settings
1843 */
1844 goto out;
1845 } else {
1846 /*
1847 * Ignore IEs coming in on two separate wiphys with
1848 * the same alpha2 and environment cap
1849 */
1850 if (likely(alpha2_equal(drv_last_ie->country_ie_alpha2,
1851 alpha2) &&
1852 env == drv_last_ie->env)) {
1853 goto out;
1854 }
1855 /* We could potentially intersect though */
1856 goto out;
1857 }
1858 }
1859 1831
1860 rd = country_ie_2_rd(country_ie, country_ie_len, &checksum); 1832 rd = country_ie_2_rd(country_ie, country_ie_len, &checksum);
1861 if (!rd) 1833 if (!rd)
@@ -1890,7 +1862,7 @@ void regulatory_hint_11d(struct wiphy *wiphy,
1890 request->country_ie_checksum = checksum; 1862 request->country_ie_checksum = checksum;
1891 request->country_ie_env = env; 1863 request->country_ie_env = env;
1892 1864
1893 mutex_unlock(&cfg80211_mutex); 1865 mutex_unlock(&reg_mutex);
1894 1866
1895 queue_regulatory_request(request); 1867 queue_regulatory_request(request);
1896 1868
@@ -1899,9 +1871,8 @@ void regulatory_hint_11d(struct wiphy *wiphy,
1899free_rd_out: 1871free_rd_out:
1900 kfree(rd); 1872 kfree(rd);
1901out: 1873out:
1902 mutex_unlock(&cfg80211_mutex); 1874 mutex_unlock(&reg_mutex);
1903} 1875}
1904EXPORT_SYMBOL(regulatory_hint_11d);
1905 1876
1906static bool freq_is_chan_12_13_14(u16 freq) 1877static bool freq_is_chan_12_13_14(u16 freq)
1907{ 1878{
@@ -1996,14 +1967,14 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
1996 1967
1997 if (last_request->initiator == 1968 if (last_request->initiator ==
1998 NL80211_REGDOM_SET_BY_COUNTRY_IE) { 1969 NL80211_REGDOM_SET_BY_COUNTRY_IE) {
1999 struct cfg80211_registered_device *drv; 1970 struct cfg80211_registered_device *rdev;
2000 drv = cfg80211_drv_by_wiphy_idx( 1971 rdev = cfg80211_rdev_by_wiphy_idx(
2001 last_request->wiphy_idx); 1972 last_request->wiphy_idx);
2002 if (drv) { 1973 if (rdev) {
2003 printk(KERN_INFO "cfg80211: Current regulatory " 1974 printk(KERN_INFO "cfg80211: Current regulatory "
2004 "domain updated by AP to: %c%c\n", 1975 "domain updated by AP to: %c%c\n",
2005 drv->country_ie_alpha2[0], 1976 rdev->country_ie_alpha2[0],
2006 drv->country_ie_alpha2[1]); 1977 rdev->country_ie_alpha2[1]);
2007 } else 1978 } else
2008 printk(KERN_INFO "cfg80211: Current regulatory " 1979 printk(KERN_INFO "cfg80211: Current regulatory "
2009 "domain intersected: \n"); 1980 "domain intersected: \n");
@@ -2064,7 +2035,7 @@ static inline void reg_country_ie_process_debug(
2064static int __set_regdom(const struct ieee80211_regdomain *rd) 2035static int __set_regdom(const struct ieee80211_regdomain *rd)
2065{ 2036{
2066 const struct ieee80211_regdomain *intersected_rd = NULL; 2037 const struct ieee80211_regdomain *intersected_rd = NULL;
2067 struct cfg80211_registered_device *drv = NULL; 2038 struct cfg80211_registered_device *rdev = NULL;
2068 struct wiphy *request_wiphy; 2039 struct wiphy *request_wiphy;
2069 /* Some basic sanity checks first */ 2040 /* Some basic sanity checks first */
2070 2041
@@ -2203,11 +2174,11 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
2203 if (!intersected_rd) 2174 if (!intersected_rd)
2204 return -EINVAL; 2175 return -EINVAL;
2205 2176
2206 drv = wiphy_to_dev(request_wiphy); 2177 rdev = wiphy_to_dev(request_wiphy);
2207 2178
2208 drv->country_ie_alpha2[0] = rd->alpha2[0]; 2179 rdev->country_ie_alpha2[0] = rd->alpha2[0];
2209 drv->country_ie_alpha2[1] = rd->alpha2[1]; 2180 rdev->country_ie_alpha2[1] = rd->alpha2[1];
2210 drv->env = last_request->country_ie_env; 2181 rdev->env = last_request->country_ie_env;
2211 2182
2212 BUG_ON(intersected_rd == rd); 2183 BUG_ON(intersected_rd == rd);
2213 2184
@@ -2232,10 +2203,13 @@ int set_regdom(const struct ieee80211_regdomain *rd)
2232 2203
2233 assert_cfg80211_lock(); 2204 assert_cfg80211_lock();
2234 2205
2206 mutex_lock(&reg_mutex);
2207
2235 /* Note that this doesn't update the wiphys, this is done below */ 2208 /* Note that this doesn't update the wiphys, this is done below */
2236 r = __set_regdom(rd); 2209 r = __set_regdom(rd);
2237 if (r) { 2210 if (r) {
2238 kfree(rd); 2211 kfree(rd);
2212 mutex_unlock(&reg_mutex);
2239 return r; 2213 return r;
2240 } 2214 }
2241 2215
@@ -2250,6 +2224,8 @@ int set_regdom(const struct ieee80211_regdomain *rd)
2250 2224
2251 nl80211_send_reg_change_event(last_request); 2225 nl80211_send_reg_change_event(last_request);
2252 2226
2227 mutex_unlock(&reg_mutex);
2228
2253 return r; 2229 return r;
2254} 2230}
2255 2231
@@ -2260,16 +2236,20 @@ void reg_device_remove(struct wiphy *wiphy)
2260 2236
2261 assert_cfg80211_lock(); 2237 assert_cfg80211_lock();
2262 2238
2239 mutex_lock(&reg_mutex);
2240
2263 kfree(wiphy->regd); 2241 kfree(wiphy->regd);
2264 2242
2265 if (last_request) 2243 if (last_request)
2266 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); 2244 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
2267 2245
2268 if (!request_wiphy || request_wiphy != wiphy) 2246 if (!request_wiphy || request_wiphy != wiphy)
2269 return; 2247 goto out;
2270 2248
2271 last_request->wiphy_idx = WIPHY_IDX_STALE; 2249 last_request->wiphy_idx = WIPHY_IDX_STALE;
2272 last_request->country_ie_env = ENVIRON_ANY; 2250 last_request->country_ie_env = ENVIRON_ANY;
2251out:
2252 mutex_unlock(&reg_mutex);
2273} 2253}
2274 2254
2275int regulatory_init(void) 2255int regulatory_init(void)
@@ -2288,22 +2268,12 @@ int regulatory_init(void)
2288 2268
2289 printk(KERN_INFO "cfg80211: Using static regulatory domain info\n"); 2269 printk(KERN_INFO "cfg80211: Using static regulatory domain info\n");
2290 print_regdomain_info(cfg80211_regdomain); 2270 print_regdomain_info(cfg80211_regdomain);
2291 /*
2292 * The old code still requests for a new regdomain and if
2293 * you have CRDA you get it updated, otherwise you get
2294 * stuck with the static values. Since "EU" is not a valid
2295 * ISO / IEC 3166 alpha2 code we can't expect userpace to
2296 * give us a regulatory domain for it. We need last_request
2297 * iniitalized though so lets just send a request which we
2298 * know will be ignored... this crap will be removed once
2299 * OLD_REG dies.
2300 */
2301 err = regulatory_hint_core(ieee80211_regdom);
2302#else 2271#else
2303 cfg80211_regdomain = cfg80211_world_regdom; 2272 cfg80211_regdomain = cfg80211_world_regdom;
2304 2273
2305 err = regulatory_hint_core(ieee80211_regdom);
2306#endif 2274#endif
2275 /* We always try to get an update for the static regdomain */
2276 err = regulatory_hint_core(cfg80211_regdomain->alpha2);
2307 if (err) { 2277 if (err) {
2308 if (err == -ENOMEM) 2278 if (err == -ENOMEM)
2309 return err; 2279 return err;
@@ -2322,6 +2292,13 @@ int regulatory_init(void)
2322#endif 2292#endif
2323 } 2293 }
2324 2294
2295 /*
2296 * Finally, if the user set the module parameter treat it
2297 * as a user hint.
2298 */
2299 if (!is_world_regdom(ieee80211_regdom))
2300 regulatory_hint_user(ieee80211_regdom);
2301
2325 return 0; 2302 return 0;
2326} 2303}
2327 2304
@@ -2333,6 +2310,7 @@ void regulatory_exit(void)
2333 cancel_work_sync(&reg_work); 2310 cancel_work_sync(&reg_work);
2334 2311
2335 mutex_lock(&cfg80211_mutex); 2312 mutex_lock(&cfg80211_mutex);
2313 mutex_lock(&reg_mutex);
2336 2314
2337 reset_regdomains(); 2315 reset_regdomains();
2338 2316
@@ -2371,5 +2349,6 @@ void regulatory_exit(void)
2371 } 2349 }
2372 spin_unlock(&reg_requests_lock); 2350 spin_unlock(&reg_requests_lock);
2373 2351
2352 mutex_unlock(&reg_mutex);
2374 mutex_unlock(&cfg80211_mutex); 2353 mutex_unlock(&cfg80211_mutex);
2375} 2354}