cfg80211: process user regulatory requests on its own
authorLuis R. Rodriguez <mcgrof@do-not-panic.com>
Tue, 5 Nov 2013 17:18:04 +0000 (09:18 -0800)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 25 Nov 2013 19:51:07 +0000 (20:51 +0100)
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>
net/wireless/reg.c

index 2b7ab01b26160c4b7c693f3887c7d35f3be7495e..1bd590c2ed7fd083ce37199704d411b61557c422 100644 (file)
@@ -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;
        }
 }