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

Commit 2f92212b authored by Johannes Berg's avatar Johannes Berg
Browse files

regulatory: use proper enum for return values



Instead of treating special error codes specially,
like -EALREADY, introduce a real enum for all the
needed possibilities and use it.

Acked-by: default avatarLuis R. Rodriguez <mcgrof@do-not-panic.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 9027b149
Loading
Loading
Loading
Loading
+69 −64
Original line number Diff line number Diff line
@@ -65,6 +65,13 @@
#define REG_DBG_PRINT(args...)
#endif

enum reg_request_treatment {
	REG_REQ_OK,
	REG_REQ_IGNORE,
	REG_REQ_INTERSECT,
	REG_REQ_ALREADY_SET,
};

static struct regulatory_request core_request_world = {
	.initiator = NL80211_REGDOM_SET_BY_CORE,
	.alpha2[0] = '0',
@@ -925,16 +932,17 @@ bool reg_last_request_cell_base(void)

#ifdef CONFIG_CFG80211_CERTIFICATION_ONUS
/* Core specific check */
static int reg_ignore_cell_hint(struct regulatory_request *pending_request)
static enum reg_request_treatment
reg_ignore_cell_hint(struct regulatory_request *pending_request)
{
	if (!reg_num_devs_support_basehint)
		return -EOPNOTSUPP;
		return REG_REQ_IGNORE;

	if (reg_request_cell_base(last_request) &&
	    !regdom_changes(pending_request->alpha2))
		return -EALREADY;
		return REG_REQ_ALREADY_SET;

	return 0;
	return REG_REQ_OK;
}

/* Device specific check */
@@ -945,7 +953,7 @@ static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy)
#else
static int reg_ignore_cell_hint(struct regulatory_request *pending_request)
{
	return -EOPNOTSUPP;
	return REG_REQ_IGNORE;
}

static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy)
@@ -1308,15 +1316,10 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
}
EXPORT_SYMBOL(wiphy_apply_custom_regulatory);

/*
 * Return value which can be used by ignore_request() to indicate
 * it has been determined we should intersect two regulatory domains
 */
#define REG_INTERSECT	1

/* This has the logic which determines when a new request
 * should be ignored. */
static int ignore_request(struct wiphy *wiphy,
static enum reg_request_treatment
get_reg_request_treatment(struct wiphy *wiphy,
			  struct regulatory_request *pending_request)
{
	struct wiphy *last_wiphy = NULL;
@@ -1325,17 +1328,17 @@ static int ignore_request(struct wiphy *wiphy,

	/* All initial requests are respected */
	if (!last_request)
		return 0;
		return REG_REQ_OK;

	switch (pending_request->initiator) {
	case NL80211_REGDOM_SET_BY_CORE:
		return 0;
		return REG_REQ_OK;
	case NL80211_REGDOM_SET_BY_COUNTRY_IE:
		if (reg_request_cell_base(last_request)) {
			/* Trust a Cell base station over the AP's country IE */
			if (regdom_changes(pending_request->alpha2))
				return -EOPNOTSUPP;
			return -EALREADY;
				return REG_REQ_IGNORE;
			return REG_REQ_ALREADY_SET;
		}

		last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
@@ -1352,23 +1355,23 @@ static int ignore_request(struct wiphy *wiphy,
				 * to be correct. Reject second one for now.
				 */
				if (regdom_changes(pending_request->alpha2))
					return -EOPNOTSUPP;
				return -EALREADY;
					return REG_REQ_IGNORE;
				return REG_REQ_ALREADY_SET;
			}
			/*
			 * Two consecutive Country IE hints on the same wiphy.
			 * This should be picked up early by the driver/stack
			 */
			if (WARN_ON(regdom_changes(pending_request->alpha2)))
				return 0;
			return -EALREADY;
				return REG_REQ_OK;
			return REG_REQ_ALREADY_SET;
		}
		return 0;
	case NL80211_REGDOM_SET_BY_DRIVER:
		if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) {
			if (regdom_changes(pending_request->alpha2))
				return 0;
			return -EALREADY;
				return REG_REQ_OK;
			return REG_REQ_ALREADY_SET;
		}

		/*
@@ -1378,25 +1381,25 @@ static int ignore_request(struct wiphy *wiphy,
		 */
		if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
		    !regdom_changes(pending_request->alpha2))
			return -EALREADY;
			return REG_REQ_ALREADY_SET;

		return REG_INTERSECT;
		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(last_request))
			return -EOPNOTSUPP;
			return REG_REQ_IGNORE;

		if (last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
			return REG_INTERSECT;
			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 (last_request->initiator == NL80211_REGDOM_SET_BY_USER &&
		    last_request->intersect)
			return -EOPNOTSUPP;
			return REG_REQ_IGNORE;
		/*
		 * Process user requests only after previous user/driver/core
		 * requests have been processed
@@ -1405,15 +1408,15 @@ static int ignore_request(struct wiphy *wiphy,
		     last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
		     last_request->initiator == NL80211_REGDOM_SET_BY_USER) &&
		    regdom_changes(last_request->alpha2))
			return -EAGAIN;
			return REG_REQ_IGNORE;

		if (!regdom_changes(pending_request->alpha2))
			return -EALREADY;
			return REG_REQ_ALREADY_SET;

		return 0;
		return REG_REQ_OK;
	}

	return -EINVAL;
	return REG_REQ_IGNORE;
}

static void reg_set_request_processed(void)
@@ -1443,23 +1446,24 @@ static void reg_set_request_processed(void)
 * The Wireless subsystem can use this function to hint to the wireless core
 * what it believes should be the current regulatory domain.
 *
 * Returns zero if all went fine, %-EALREADY if a regulatory domain had
 * already been set or other standard error codes.
 * Returns one of the different reg request treatment values.
 *
 * Caller must hold &cfg80211_mutex and &reg_mutex
 */
static int __regulatory_hint(struct wiphy *wiphy,
static enum reg_request_treatment
__regulatory_hint(struct wiphy *wiphy,
		  struct regulatory_request *pending_request)
{
	const struct ieee80211_regdomain *regd;
	bool intersect = false;
	int r = 0;
	enum reg_request_treatment treatment;

	assert_cfg80211_lock();

	r = ignore_request(wiphy, pending_request);
	treatment = get_reg_request_treatment(wiphy, pending_request);

	if (r == REG_INTERSECT) {
	switch (treatment) {
	case REG_REQ_INTERSECT:
		if (pending_request->initiator ==
		    NL80211_REGDOM_SET_BY_DRIVER) {
			regd = reg_copy_regd(cfg80211_regdomain);
@@ -1470,26 +1474,28 @@ static int __regulatory_hint(struct wiphy *wiphy,
			wiphy->regd = regd;
		}
		intersect = true;
	} else if (r) {
		break;
	case REG_REQ_OK:
		break;
	default:
		/*
		 * If the regulatory domain being requested by the
		 * driver has already been set just copy it to the
		 * wiphy
		 */
		if (r == -EALREADY &&
		    pending_request->initiator ==
		    NL80211_REGDOM_SET_BY_DRIVER) {
		if (treatment == REG_REQ_ALREADY_SET &&
		    pending_request->initiator == NL80211_REGDOM_SET_BY_DRIVER) {
			regd = reg_copy_regd(cfg80211_regdomain);
			if (IS_ERR(regd)) {
				kfree(pending_request);
				return PTR_ERR(regd);
				return REG_REQ_IGNORE;
			}
			r = -EALREADY;
			treatment = REG_REQ_ALREADY_SET;
			wiphy->regd = regd;
			goto new_request;
		}
		kfree(pending_request);
		return r;
		return treatment;
	}

new_request:
@@ -1506,28 +1512,29 @@ static int __regulatory_hint(struct wiphy *wiphy,
		user_alpha2[1] = last_request->alpha2[1];
	}

	/* When r == REG_INTERSECT we do need to call CRDA */
	if (r < 0) {
	/* When r == REG_REQ_INTERSECT we do need to call CRDA */
	if (treatment != REG_REQ_OK && treatment != REG_REQ_INTERSECT) {
		/*
		 * Since CRDA will not be called in this case as we already
		 * have applied the requested regulatory domain before we just
		 * inform userspace we have processed the request
		 */
		if (r == -EALREADY) {
		if (treatment == REG_REQ_ALREADY_SET) {
			nl80211_send_reg_change_event(last_request);
			reg_set_request_processed();
		}
		return r;
		return treatment;
	}

	return call_crda(last_request->alpha2);
	if (call_crda(last_request->alpha2))
		return REG_REQ_IGNORE;
	return REG_REQ_OK;
}

/* This processes *all* regulatory hints */
static void reg_process_hint(struct regulatory_request *reg_request,
			     enum nl80211_reg_initiator reg_initiator)
{
	int r = 0;
	struct wiphy *wiphy = NULL;

	BUG_ON(!reg_request->alpha2);
@@ -1540,20 +1547,18 @@ static void reg_process_hint(struct regulatory_request *reg_request,
		return;
	}

	r = __regulatory_hint(wiphy, reg_request);
	switch (__regulatory_hint(wiphy, reg_request)) {
	case REG_REQ_ALREADY_SET:
		/* This is required so that the orig_* parameters are saved */
	if (r == -EALREADY && wiphy &&
	    wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) {
		if (wiphy && wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
			wiphy_update_regulatory(wiphy, reg_initiator);
		return;
		break;
	default:
		if (reg_initiator == NL80211_REGDOM_SET_BY_USER)
			schedule_delayed_work(&reg_timeout,
					      msecs_to_jiffies(3142));
		break;
	}

	/*
	 * We only time out user hints, given that they should be the only
	 * source of bogus requests.
	 */
	if (r != -EALREADY && reg_initiator == NL80211_REGDOM_SET_BY_USER)
		schedule_delayed_work(&reg_timeout, msecs_to_jiffies(3142));
}

/*