summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis R. Rodriguez <mcgrof@do-not-panic.com>2013-11-05 09:18:04 -0800
committerJohannes Berg <johannes.berg@intel.com>2013-11-25 20:51:07 +0100
commit0d97a61917d8c00adb9e445ec23ee09150d720a4 (patch)
treed3bfc62b435a4747752c73f973147f56cb8ba8d2
parentb3eb7f3f592c0a5ae96c0cf53037f1a1d7eb4a85 (diff)
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 <mcgrof@do-not-panic.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/wireless/reg.c114
1 files changed, 81 insertions, 33 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 2b7ab01b261..1bd590c2ed7 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(&reg_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(&reg_timeout,
- msecs_to_jiffies(3142));
break;
}
}