diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-12-03 23:00:08 +0100 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-01-03 13:01:27 +0100 |
commit | e8da2bb4fe9ecb888f44714e2624c7d4268ac09d (patch) | |
tree | c776f0786e9d72c34888a25cec998f348ef64d70 /net/wireless/reg.c | |
parent | 5d885b999c68283c493cf00cc020260d38951ae6 (diff) | |
download | linux-stable-e8da2bb4fe9ecb888f44714e2624c7d4268ac09d.tar.gz linux-stable-e8da2bb4fe9ecb888f44714e2624c7d4268ac09d.tar.bz2 linux-stable-e8da2bb4fe9ecb888f44714e2624c7d4268ac09d.zip |
regulatory: clarify locking rules and assertions
Many places that currently check that cfg80211_mutex
is held don't actually use any data protected by it.
The functions that need to hold the cfg80211_mutex
are the ones using the cfg80211_regdomain variable,
so add the lock assertion to those and clarify this
in the comments.
The reason for this is that nl80211 uses the regdom
without being able to hold reg_mutex.
Acked-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r-- | net/wireless/reg.c | 31 |
1 files changed, 11 insertions, 20 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 75239789213a..603a01911a50 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -94,14 +94,14 @@ static struct device_type reg_device_type = { /* * Central wireless core regulatory domains, we only need two, * the current one and a world regulatory domain in case we have no - * information to give us an alpha2 + * information to give us an alpha2. + * Protected by the cfg80211_mutex. */ const struct ieee80211_regdomain *cfg80211_regdomain; /* * Protects static reg.c components: * - cfg80211_world_regdom - * - cfg80211_regdom * - last_request * - reg_num_devs_support_basehint */ @@ -185,6 +185,9 @@ MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); static void reset_regdomains(bool full_reset) { + assert_cfg80211_lock(); + assert_reg_lock(); + /* avoid freeing static information or freeing something twice */ if (cfg80211_regdomain == cfg80211_world_regdom) cfg80211_regdomain = NULL; @@ -215,6 +218,9 @@ static void update_world_regdomain(const struct ieee80211_regdomain *rd) { WARN_ON(!last_request); + assert_cfg80211_lock(); + assert_reg_lock(); + reset_regdomains(false); cfg80211_world_regdom = rd; @@ -422,8 +428,6 @@ static int call_crda(const char *alpha2) /* Used by nl80211 before kmalloc'ing our regulatory domain */ bool reg_is_valid_request(const char *alpha2) { - assert_cfg80211_lock(); - if (!last_request) return false; @@ -915,8 +919,6 @@ bool reg_last_request_cell_base(void) { bool val; - assert_cfg80211_lock(); - mutex_lock(®_mutex); val = reg_request_cell_base(last_request); mutex_unlock(®_mutex); @@ -999,8 +1001,6 @@ static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx, bool channel_changed = false; struct ieee80211_channel chan_before; - assert_cfg80211_lock(); - sband = wiphy->bands[reg_beacon->chan.band]; chan = &sband->channels[chan_idx]; @@ -1042,8 +1042,6 @@ static void wiphy_update_new_beacon(struct wiphy *wiphy, unsigned int i; struct ieee80211_supported_band *sband; - assert_cfg80211_lock(); - if (!wiphy->bands[reg_beacon->chan.band]) return; @@ -1062,8 +1060,6 @@ static void wiphy_update_beacon_reg(struct wiphy *wiphy) struct ieee80211_supported_band *sband; struct reg_beacon *reg_beacon; - assert_cfg80211_lock(); - list_for_each_entry(reg_beacon, ®_beacon_list, list) { if (!wiphy->bands[reg_beacon->chan.band]) continue; @@ -1075,6 +1071,8 @@ static void wiphy_update_beacon_reg(struct wiphy *wiphy) static bool reg_is_world_roaming(struct wiphy *wiphy) { + assert_cfg80211_lock(); + if (is_world_regdom(cfg80211_regdomain->alpha2) || (wiphy->regd && is_world_regdom(wiphy->regd->alpha2))) return true; @@ -1116,8 +1114,6 @@ static void reg_process_ht_flags_channel(struct wiphy *wiphy, struct ieee80211_channel *channel_before = NULL, *channel_after = NULL; unsigned int i; - assert_cfg80211_lock(); - if (!is_ht40_allowed(channel)) { channel->flags |= IEEE80211_CHAN_NO_HT40; return; @@ -1180,6 +1176,7 @@ static void wiphy_update_regulatory(struct wiphy *wiphy, { enum ieee80211_band band; + assert_cfg80211_lock(); assert_reg_lock(); if (ignore_reg_update(wiphy, initiator)) @@ -1299,8 +1296,6 @@ get_reg_request_treatment(struct wiphy *wiphy, { struct wiphy *last_wiphy = NULL; - assert_cfg80211_lock(); - /* All initial requests are respected */ if (!last_request) return REG_REQ_OK; @@ -2246,8 +2241,6 @@ int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env) void wiphy_regulatory_register(struct wiphy *wiphy) { - assert_cfg80211_lock(); - mutex_lock(®_mutex); if (!reg_dev_ignore_cell_hint(wiphy)) @@ -2263,8 +2256,6 @@ void wiphy_regulatory_deregister(struct wiphy *wiphy) { struct wiphy *request_wiphy = NULL; - assert_cfg80211_lock(); - mutex_lock(®_mutex); if (!reg_dev_ignore_cell_hint(wiphy)) |