summaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2011-04-05 10:49:04 -0700
committerJohn W. Linville <linville@tuxdriver.com>2011-04-07 15:52:29 -0400
commita90c7a313a1c5b4fc99f987a2ae8f92ab0ae35c7 (patch)
treeb5484abed3ef3f23e17375fbc44657b875b7f418 /net/wireless
parent146095557b01cf5ff5d66554d96cbb8133d94eb9 (diff)
cfg80211: add a timer for invalid user reg hints
We have no other option but to inform userspace that we have queued up their regulatory hint request when we are given one given that nl80211 operates atomically on user requests. The best we can do is accept the request, and add a delayed work item for processing failure and cancel it if we succeeed. Upon failure we restore the regulatory settings and ignore the user input. This fixes this reported bug: https://bugzilla.kernel.org/show_bug.cgi?id=28112 Reported-by: gregoryx.alagnou@intel.com Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/reg.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 7b1a89b20eb..2714379ce2d 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -106,6 +106,9 @@ struct reg_beacon {
static void reg_todo(struct work_struct *work);
static DECLARE_WORK(reg_work, reg_todo);
+static void reg_timeout_work(struct work_struct *work);
+static DECLARE_DELAYED_WORK(reg_timeout, reg_timeout_work);
+
/* We keep a static world regulatory domain in case of the absence of CRDA */
static const struct ieee80211_regdomain world_regdom = {
.n_reg_rules = 5,
@@ -1330,6 +1333,9 @@ static void reg_set_request_processed(void)
need_more_processing = true;
spin_unlock(&reg_requests_lock);
+ if (last_request->initiator == NL80211_REGDOM_SET_BY_USER)
+ cancel_delayed_work_sync(&reg_timeout);
+
if (need_more_processing)
schedule_work(&reg_work);
}
@@ -1440,8 +1446,17 @@ static void reg_process_hint(struct regulatory_request *reg_request)
r = __regulatory_hint(wiphy, reg_request);
/* This is required so that the orig_* parameters are saved */
if (r == -EALREADY && wiphy &&
- wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
+ wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) {
wiphy_update_regulatory(wiphy, initiator);
+ return;
+ }
+
+ /*
+ * We only time out user hints, given that they should be the only
+ * source of bogus requests.
+ */
+ if (reg_request->initiator == NL80211_REGDOM_SET_BY_USER)
+ schedule_delayed_work(&reg_timeout, msecs_to_jiffies(3142));
}
/*
@@ -2169,6 +2184,13 @@ out:
mutex_unlock(&reg_mutex);
}
+static void reg_timeout_work(struct work_struct *work)
+{
+ REG_DBG_PRINT("Timeout while waiting for CRDA to reply, "
+ "restoring regulatory settings");
+ restore_regulatory_settings(true);
+}
+
int __init regulatory_init(void)
{
int err = 0;
@@ -2222,6 +2244,7 @@ void /* __init_or_exit */ regulatory_exit(void)
struct reg_beacon *reg_beacon, *btmp;
cancel_work_sync(&reg_work);
+ cancel_delayed_work_sync(&reg_timeout);
mutex_lock(&cfg80211_mutex);
mutex_lock(&reg_mutex);