Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f5fe3247 authored by Luis R. Rodriguez's avatar Luis R. Rodriguez Committed by Johannes Berg
Browse files

cfg80211: set driver regulatory updates on its own



This splits up the driver regulatory update on its
own, this helps simplify the reading the case.

Signed-off-by: default avatarLuis R. Rodriguez <mcgrof@do-not-panic.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 84721d44
Loading
Loading
Loading
Loading
+56 −67
Original line number Diff line number Diff line
@@ -2232,38 +2232,19 @@ static int reg_set_rd_user(const struct ieee80211_regdomain *rd,
	return 0;
}

/* Takes ownership of rd only if it doesn't fail */
static int __set_regdom(const struct ieee80211_regdomain *rd,
			struct regulatory_request *lr)
static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
			     struct regulatory_request *driver_request)
{
	const struct ieee80211_regdomain *regd;
	const struct ieee80211_regdomain *intersected_rd = NULL;
	const struct ieee80211_regdomain *tmp;
	struct wiphy *request_wiphy;

	if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) &&
	    !is_unknown_alpha2(rd->alpha2))
	if (is_world_regdom(rd->alpha2))
		return -EINVAL;

	/*
	 * Lets only bother proceeding on the same alpha2 if the current
	 * rd is non static (it means CRDA was present and was used last)
	 * and the pending request came in from a country IE
	 */
	if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
		/*
		 * If someone else asked us to change the rd lets only bother
		 * checking if the alpha2 changes if CRDA was already called
		 */
	if (!regdom_changes(rd->alpha2))
		return -EALREADY;
	}

	/*
	 * Now lets set the regulatory domain, update all driver channels
	 * and finally inform them of what we have done, in case they want
	 * to review or adjust their own settings based on their own
	 * internal EEPROM data
	 */

	if (!is_valid_rd(rd)) {
		pr_err("Invalid regulatory domain detected:\n");
@@ -2271,29 +2252,13 @@ static int __set_regdom(const struct ieee80211_regdomain *rd,
		return -EINVAL;
	}

	request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);
	if (!request_wiphy &&
	    (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
	     lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
	request_wiphy = wiphy_idx_to_wiphy(driver_request->wiphy_idx);
	if (!request_wiphy) {
		schedule_delayed_work(&reg_timeout, 0);
		return -ENODEV;
	}

	if (!lr->intersect) {
		if (lr->initiator != NL80211_REGDOM_SET_BY_DRIVER) {
			reset_regdomains(false, rd);
			return 0;
		}

		/*
		 * For a driver hint, lets copy the regulatory domain the
		 * driver wanted to the wiphy to deal with conflicts
		 */

		/*
		 * Userspace could have sent two replies with only
		 * one kernel request.
		 */
	if (!driver_request->intersect) {
		if (request_wiphy->regd)
			return -EALREADY;

@@ -2306,9 +2271,6 @@ static int __set_regdom(const struct ieee80211_regdomain *rd,
		return 0;
	}

	/* Intersection requires a bit more work */

	if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
	intersected_rd = regdom_intersect(rd, get_cfg80211_regdom());
	if (!intersected_rd)
		return -EINVAL;
@@ -2318,15 +2280,9 @@ static int __set_regdom(const struct ieee80211_regdomain *rd,
	 * However if a driver requested this specific regulatory
	 * domain we keep it for its private use
	 */
		if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER) {
			const struct ieee80211_regdomain *tmp;

	tmp = get_wiphy_regdom(request_wiphy);
	rcu_assign_pointer(request_wiphy->regd, rd);
	rcu_free_regdom(tmp);
		} else {
			kfree(rd);
		}

	rd = NULL;

@@ -2335,9 +2291,40 @@ static int __set_regdom(const struct ieee80211_regdomain *rd,
	return 0;
}

/* Takes ownership of rd only if it doesn't fail */
static int __set_regdom(const struct ieee80211_regdomain *rd,
			struct regulatory_request *lr)
{
	struct wiphy *request_wiphy;

	if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) &&
	    !is_unknown_alpha2(rd->alpha2))
		return -EINVAL;

	/*
	 * Lets only bother proceeding on the same alpha2 if the current
	 * rd is non static (it means CRDA was present and was used last)
	 * and the pending request came in from a country IE
	 */

	if (!is_valid_rd(rd)) {
		pr_err("Invalid regulatory domain detected:\n");
		print_regdomain_info(rd);
		return -EINVAL;
	}

	request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);
	if (!request_wiphy) {
		schedule_delayed_work(&reg_timeout, 0);
		return -ENODEV;
	}

	if (lr->intersect)
		return -EINVAL;

	reset_regdomains(false, rd);
	return 0;
}

/*
 * Use this call to set the current regulatory domain. Conflicts with
@@ -2365,6 +2352,8 @@ int set_regdom(const struct ieee80211_regdomain *rd)
		r = reg_set_rd_user(rd, lr);
		break;
	case NL80211_REGDOM_SET_BY_DRIVER:
		r = reg_set_rd_driver(rd, lr);
		break;
	case NL80211_REGDOM_SET_BY_COUNTRY_IE:
		r = __set_regdom(rd, lr);
		break;