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>
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 7523978..603a019 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -94,14 +94,14 @@
/*
* 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 @@
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 @@
{
WARN_ON(!last_request);
+ assert_cfg80211_lock();
+ assert_reg_lock();
+
reset_regdomains(false);
cfg80211_world_regdom = rd;
@@ -422,8 +428,6 @@
/* 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 val;
- assert_cfg80211_lock();
-
mutex_lock(®_mutex);
val = reg_request_cell_base(last_request);
mutex_unlock(®_mutex);
@@ -999,8 +1001,6 @@
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 @@
unsigned int i;
struct ieee80211_supported_band *sband;
- assert_cfg80211_lock();
-
if (!wiphy->bands[reg_beacon->chan.band])
return;
@@ -1062,8 +1060,6 @@
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 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 @@
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 @@
{
enum ieee80211_band band;
+ assert_cfg80211_lock();
assert_reg_lock();
if (ignore_reg_update(wiphy, initiator))
@@ -1299,8 +1296,6 @@
{
struct wiphy *last_wiphy = NULL;
- assert_cfg80211_lock();
-
/* All initial requests are respected */
if (!last_request)
return REG_REQ_OK;
@@ -2246,8 +2241,6 @@
void wiphy_regulatory_register(struct wiphy *wiphy)
{
- assert_cfg80211_lock();
-
mutex_lock(®_mutex);
if (!reg_dev_ignore_cell_hint(wiphy))
@@ -2263,8 +2256,6 @@
{
struct wiphy *request_wiphy = NULL;
- assert_cfg80211_lock();
-
mutex_lock(®_mutex);
if (!reg_dev_ignore_cell_hint(wiphy))