diff options
author | Janusz Dziedzic <janusz.dziedzic@tieto.com> | 2014-02-14 11:54:00 +0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-02-25 19:27:04 +0400 |
commit | 092008abeed1e4168c08826262695ea67657e1aa (patch) | |
tree | 68705af45715df5cbc38b77bba2f6a23f9eeb874 /net | |
parent | 963a1852fbac4f75a2d938fa2e734ef1e6d4c044 (diff) | |
download | linux-092008abeed1e4168c08826262695ea67657e1aa.tar.xz |
cfg80211: regulatory: reset regdomain in case of error
Reset regdomain to world regdomain in case
of errors in set_regdom() function.
This will fix a problem with such scenario:
- iw reg set US
- iw reg set 00
- iw reg set US
The last step always fail and we get deadlock
in kernel regulatory code. Next setting new
regulatory wasn't possible due to:
Pending regulatory request, waiting for it to be processed...
Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
Acked-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/wireless/reg.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 4c50c21d6f52..f0541370e68e 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2373,6 +2373,7 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd, int set_regdom(const struct ieee80211_regdomain *rd) { struct regulatory_request *lr; + bool user_reset = false; int r; if (!reg_is_valid_request(rd->alpha2)) { @@ -2389,6 +2390,7 @@ int set_regdom(const struct ieee80211_regdomain *rd) break; case NL80211_REGDOM_SET_BY_USER: r = reg_set_rd_user(rd, lr); + user_reset = true; break; case NL80211_REGDOM_SET_BY_DRIVER: r = reg_set_rd_driver(rd, lr); @@ -2402,8 +2404,14 @@ int set_regdom(const struct ieee80211_regdomain *rd) } if (r) { - if (r == -EALREADY) + switch (r) { + case -EALREADY: reg_set_request_processed(); + break; + default: + /* Back to world regulatory in case of errors */ + restore_regulatory_settings(user_reset); + } kfree(rd); return r; |