diff options
author | Luis R. Rodriguez <mcgrof@do-not-panic.com> | 2013-11-05 09:18:05 -0800 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-11-25 20:51:10 +0100 |
commit | 21636c7faae0a980e73f366e164ffaa77a424786 (patch) | |
tree | 090765286c7187cace67aa5436cc763ec7312782 /net/wireless/reg.c | |
parent | 0d97a61917d8c00adb9e445ec23ee09150d720a4 (diff) | |
download | lwn-21636c7faae0a980e73f366e164ffaa77a424786.tar.gz lwn-21636c7faae0a980e73f366e164ffaa77a424786.zip |
cfg80211: process driver regulatory requests on its own
This makes the code easier to read and follow.
Signed-off-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 | 103 |
1 files changed, 86 insertions, 17 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 1bd590c2ed7f..7188ef9f07b6 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1338,6 +1338,7 @@ get_reg_request_treatment(struct wiphy *wiphy, switch (pending_request->initiator) { case NL80211_REGDOM_SET_BY_CORE: case NL80211_REGDOM_SET_BY_USER: + case NL80211_REGDOM_SET_BY_DRIVER: return REG_REQ_IGNORE; case NL80211_REGDOM_SET_BY_COUNTRY_IE: if (reg_request_cell_base(lr)) { @@ -1372,23 +1373,6 @@ get_reg_request_treatment(struct wiphy *wiphy, return REG_REQ_ALREADY_SET; } return REG_REQ_OK; - case NL80211_REGDOM_SET_BY_DRIVER: - if (lr->initiator == NL80211_REGDOM_SET_BY_CORE) { - if (regdom_changes(pending_request->alpha2)) - return REG_REQ_OK; - return REG_REQ_ALREADY_SET; - } - - /* - * This would happen if you unplug and plug your card - * back in or if you add a new device for which the previously - * loaded card also agrees on the regulatory domain. - */ - if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && - !regdom_changes(pending_request->alpha2)) - return REG_REQ_ALREADY_SET; - - return REG_REQ_INTERSECT; } return REG_REQ_IGNORE; @@ -1514,6 +1498,89 @@ reg_process_hint_user(struct regulatory_request *user_request) return REG_REQ_OK; } +static enum reg_request_treatment +__reg_process_hint_driver(struct regulatory_request *driver_request) +{ + struct regulatory_request *lr = get_last_request(); + + if (lr->initiator == NL80211_REGDOM_SET_BY_CORE) { + if (regdom_changes(driver_request->alpha2)) + return REG_REQ_OK; + return REG_REQ_ALREADY_SET; + } + + /* + * This would happen if you unplug and plug your card + * back in or if you add a new device for which the previously + * loaded card also agrees on the regulatory domain. + */ + if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && + !regdom_changes(driver_request->alpha2)) + return REG_REQ_ALREADY_SET; + + return REG_REQ_INTERSECT; +} + +/** + * reg_process_hint_driver - process driver regulatory requests + * @driver_request: a pending driver regulatory request + * + * The wireless subsystem can use this function to process + * a regulatory request issued by an 802.11 driver. + * + * Returns one of the different reg request treatment values. + */ +static enum reg_request_treatment +reg_process_hint_driver(struct wiphy *wiphy, + struct regulatory_request *driver_request) +{ + const struct ieee80211_regdomain *regd; + enum reg_request_treatment treatment; + struct regulatory_request *lr; + + treatment = __reg_process_hint_driver(driver_request); + + switch (treatment) { + case REG_REQ_OK: + break; + case REG_REQ_IGNORE: + kfree(driver_request); + return treatment; + case REG_REQ_INTERSECT: + /* fall through */ + case REG_REQ_ALREADY_SET: + regd = reg_copy_regd(get_cfg80211_regdom()); + if (IS_ERR(regd)) { + kfree(driver_request); + return REG_REQ_IGNORE; + } + rcu_assign_pointer(wiphy->regd, regd); + } + + lr = get_last_request(); + if (lr != &core_request_world && lr) + kfree_rcu(lr, rcu_head); + + driver_request->intersect = treatment == REG_REQ_INTERSECT; + driver_request->processed = false; + rcu_assign_pointer(last_request, driver_request); + + /* + * Since CRDA will not be called in this case as we already + * have applied the requested regulatory domain before we just + * inform userspace we have processed the request + */ + if (treatment == REG_REQ_ALREADY_SET) { + nl80211_send_reg_change_event(driver_request); + reg_set_request_processed(); + return treatment; + } + + if (call_crda(driver_request->alpha2)) + return REG_REQ_IGNORE; + return REG_REQ_OK; +} + /** * __regulatory_hint - hint to the wireless core a regulatory domain * @wiphy: if the hint comes from country information from an AP, this @@ -1637,6 +1704,8 @@ static void reg_process_hint(struct regulatory_request *reg_request) schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); return; case NL80211_REGDOM_SET_BY_DRIVER: + treatment = reg_process_hint_driver(wiphy, reg_request); + break; case NL80211_REGDOM_SET_BY_COUNTRY_IE: treatment = __regulatory_hint(wiphy, reg_request); break; |