|
@@ -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;
|
|
|
}
|
|
|
}
|