@@ -42,6 +42,7 @@
#include <linux/ctype.h>
#include <linux/nl80211.h>
#include <linux/platform_device.h>
+#include <linux/timer.h>
#include <net/cfg80211.h>
#include "core.h"
#include "reg.h"
@@ -106,6 +107,10 @@ struct reg_beacon {
static void reg_todo(struct work_struct *work);
static DECLARE_WORK(reg_work, reg_todo);
+static struct timer_list reg_timer;
+static void reg_timeout_work(struct work_struct *work);
+static DECLARE_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 +1335,9 @@ static void reg_set_request_processed(void)
need_more_processing = true;
spin_unlock(®_requests_lock);
+ if (last_request->initiator == NL80211_REGDOM_SET_BY_USER)
+ del_timer_sync(®_timer);
+
if (need_more_processing)
schedule_work(®_work);
}
@@ -1584,6 +1592,7 @@ int regulatory_hint_user(const char *alpha2)
request->initiator = NL80211_REGDOM_SET_BY_USER;
queue_regulatory_request(request);
+ mod_timer(®_timer, jiffies + msecs_to_jiffies(3142));
return 0;
}
@@ -1787,7 +1796,6 @@ static void restore_regulatory_settings(bool reset_user)
regulatory_hint_user(user_alpha2);
}
-
void regulatory_hint_disconnect(void)
{
REG_DBG_PRINT("All devices are disconnected, going to "
@@ -2125,6 +2133,18 @@ out:
mutex_unlock(®_mutex);
}
+static void reg_timeout_work(struct work_struct *work)
+{
+ restore_regulatory_settings(true);
+}
+
+static void reg_set_failed_timer(unsigned long data)
+{
+ REG_DBG_PRINT("Timeout while waiting for CRDA to reply,"
+ "restoring regulatory settings");
+ schedule_work(®_timeout);
+}
+
int __init regulatory_init(void)
{
int err = 0;
@@ -2137,6 +2157,7 @@ int __init regulatory_init(void)
spin_lock_init(®_requests_lock);
spin_lock_init(®_pending_beacons_lock);
+ setup_timer(®_timer, reg_set_failed_timer, (unsigned long) NULL);
cfg80211_regdomain = cfg80211_world_regdom;
@@ -2178,6 +2199,8 @@ void /* __init_or_exit */ regulatory_exit(void)
struct reg_beacon *reg_beacon, *btmp;
cancel_work_sync(®_work);
+ cancel_work_sync(®_timeout);
+ del_timer_sync(®_timer);
mutex_lock(&cfg80211_mutex);
mutex_lock(®_mutex);