From 0d97a61917d8c00adb9e445ec23ee09150d720a4 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 5 Nov 2013 09:18:04 -0800 Subject: [PATCH] cfg80211: process user regulatory requests on its own This makes the code path easier to read and lets us split out some functionality that is only user specific, that makes it easier to read the other types of requests. Signed-off-by: Luis R. Rodriguez Signed-off-by: Johannes Berg --- net/wireless/reg.c | 114 ++++++++++++++++++++++++++++++++------------- 1 file changed, 81 insertions(+), 33 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 2b7ab01b2616..1bd590c2ed7f 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1337,6 +1337,7 @@ get_reg_request_treatment(struct wiphy *wiphy, switch (pending_request->initiator) { case NL80211_REGDOM_SET_BY_CORE: + case NL80211_REGDOM_SET_BY_USER: return REG_REQ_IGNORE; case NL80211_REGDOM_SET_BY_COUNTRY_IE: if (reg_request_cell_base(lr)) { @@ -1388,36 +1389,6 @@ get_reg_request_treatment(struct wiphy *wiphy, return REG_REQ_ALREADY_SET; return REG_REQ_INTERSECT; - case NL80211_REGDOM_SET_BY_USER: - if (reg_request_cell_base(pending_request)) - return reg_ignore_cell_hint(pending_request); - - if (reg_request_cell_base(lr)) - return REG_REQ_IGNORE; - - if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) - return REG_REQ_INTERSECT; - /* - * If the user knows better the user should set the regdom - * to their country before the IE is picked up - */ - if (lr->initiator == NL80211_REGDOM_SET_BY_USER && - lr->intersect) - return REG_REQ_IGNORE; - /* - * Process user requests only after previous user/driver/core - * requests have been processed - */ - if ((lr->initiator == NL80211_REGDOM_SET_BY_CORE || - lr->initiator == NL80211_REGDOM_SET_BY_DRIVER || - lr->initiator == NL80211_REGDOM_SET_BY_USER) && - regdom_changes(lr->alpha2)) - return REG_REQ_IGNORE; - - if (!regdom_changes(pending_request->alpha2)) - return REG_REQ_ALREADY_SET; - - return REG_REQ_OK; } return REG_REQ_IGNORE; @@ -1469,6 +1440,80 @@ reg_process_hint_core(struct regulatory_request *core_request) return REG_REQ_OK; } +static enum reg_request_treatment +__reg_process_hint_user(struct regulatory_request *user_request) +{ + struct regulatory_request *lr = get_last_request(); + + if (reg_request_cell_base(user_request)) + return reg_ignore_cell_hint(user_request); + + if (reg_request_cell_base(lr)) + return REG_REQ_IGNORE; + + if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) + return REG_REQ_INTERSECT; + /* + * If the user knows better the user should set the regdom + * to their country before the IE is picked up + */ + if (lr->initiator == NL80211_REGDOM_SET_BY_USER && + lr->intersect) + return REG_REQ_IGNORE; + /* + * Process user requests only after previous user/driver/core + * requests have been processed + */ + if ((lr->initiator == NL80211_REGDOM_SET_BY_CORE || + lr->initiator == NL80211_REGDOM_SET_BY_DRIVER || + lr->initiator == NL80211_REGDOM_SET_BY_USER) && + regdom_changes(lr->alpha2)) + return REG_REQ_IGNORE; + + if (!regdom_changes(user_request->alpha2)) + return REG_REQ_ALREADY_SET; + + return REG_REQ_OK; +} + +/** + * reg_process_hint_user - process user regulatory requests + * @user_request: a pending user regulatory request + * + * The wireless subsystem can use this function to process + * a regulatory request initiated by userspace. + * + * Returns one of the different reg request treatment values. + */ +static enum reg_request_treatment +reg_process_hint_user(struct regulatory_request *user_request) +{ + enum reg_request_treatment treatment; + struct regulatory_request *lr; + + treatment = __reg_process_hint_user(user_request); + if (treatment == REG_REQ_IGNORE || + treatment == REG_REQ_ALREADY_SET) { + kfree(user_request); + return treatment; + } + + lr = get_last_request(); + if (lr != &core_request_world && lr) + kfree_rcu(lr, rcu_head); + + user_request->intersect = treatment == REG_REQ_INTERSECT; + user_request->processed = false; + rcu_assign_pointer(last_request, user_request); + + user_alpha2[0] = user_request->alpha2[0]; + user_alpha2[1] = user_request->alpha2[1]; + + if (call_crda(user_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 @@ -1585,6 +1630,12 @@ static void reg_process_hint(struct regulatory_request *reg_request) reg_process_hint_core(reg_request); return; case NL80211_REGDOM_SET_BY_USER: + treatment = reg_process_hint_user(reg_request); + if (treatment == REG_REQ_OK || + treatment == REG_REQ_ALREADY_SET) + return; + schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); + return; case NL80211_REGDOM_SET_BY_DRIVER: case NL80211_REGDOM_SET_BY_COUNTRY_IE: treatment = __regulatory_hint(wiphy, reg_request); @@ -1601,9 +1652,6 @@ static void reg_process_hint(struct regulatory_request *reg_request) wiphy_update_regulatory(wiphy, reg_request->initiator); break; default: - if (reg_request->initiator == NL80211_REGDOM_SET_BY_USER) - schedule_delayed_work(®_timeout, - msecs_to_jiffies(3142)); break; } }