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

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
...@@ -65,6 +65,13 @@ ...@@ -65,6 +65,13 @@
#define REG_DBG_PRINT(args...) #define REG_DBG_PRINT(args...)
#endif #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 = { static struct regulatory_request core_request_world = {
.initiator = NL80211_REGDOM_SET_BY_CORE, .initiator = NL80211_REGDOM_SET_BY_CORE,
.alpha2[0] = '0', .alpha2[0] = '0',
...@@ -925,16 +932,17 @@ bool reg_last_request_cell_base(void) ...@@ -925,16 +932,17 @@ bool reg_last_request_cell_base(void)
#ifdef CONFIG_CFG80211_CERTIFICATION_ONUS #ifdef CONFIG_CFG80211_CERTIFICATION_ONUS
/* Core specific check */ /* 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) if (!reg_num_devs_support_basehint)
return -EOPNOTSUPP; return REG_REQ_IGNORE;
if (reg_request_cell_base(last_request) && if (reg_request_cell_base(last_request) &&
!regdom_changes(pending_request->alpha2)) !regdom_changes(pending_request->alpha2))
return -EALREADY; return REG_REQ_ALREADY_SET;
return 0; return REG_REQ_OK;
} }
/* Device specific check */ /* Device specific check */
...@@ -945,7 +953,7 @@ static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy) ...@@ -945,7 +953,7 @@ static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy)
#else #else
static int reg_ignore_cell_hint(struct regulatory_request *pending_request) 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) static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy)
...@@ -1308,15 +1316,10 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy, ...@@ -1308,15 +1316,10 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
} }
EXPORT_SYMBOL(wiphy_apply_custom_regulatory); 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 /* This has the logic which determines when a new request
* should be ignored. */ * 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 regulatory_request *pending_request)
{ {
struct wiphy *last_wiphy = NULL; struct wiphy *last_wiphy = NULL;
...@@ -1325,17 +1328,17 @@ static int ignore_request(struct wiphy *wiphy, ...@@ -1325,17 +1328,17 @@ static int ignore_request(struct wiphy *wiphy,
/* All initial requests are respected */ /* All initial requests are respected */
if (!last_request) if (!last_request)
return 0; return REG_REQ_OK;
switch (pending_request->initiator) { switch (pending_request->initiator) {
case NL80211_REGDOM_SET_BY_CORE: case NL80211_REGDOM_SET_BY_CORE:
return 0; return REG_REQ_OK;
case NL80211_REGDOM_SET_BY_COUNTRY_IE: case NL80211_REGDOM_SET_BY_COUNTRY_IE:
if (reg_request_cell_base(last_request)) { if (reg_request_cell_base(last_request)) {
/* Trust a Cell base station over the AP's country IE */ /* Trust a Cell base station over the AP's country IE */
if (regdom_changes(pending_request->alpha2)) if (regdom_changes(pending_request->alpha2))
return -EOPNOTSUPP; return REG_REQ_IGNORE;
return -EALREADY; return REG_REQ_ALREADY_SET;
} }
last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
...@@ -1352,23 +1355,23 @@ static int ignore_request(struct wiphy *wiphy, ...@@ -1352,23 +1355,23 @@ static int ignore_request(struct wiphy *wiphy,
* to be correct. Reject second one for now. * to be correct. Reject second one for now.
*/ */
if (regdom_changes(pending_request->alpha2)) if (regdom_changes(pending_request->alpha2))
return -EOPNOTSUPP; return REG_REQ_IGNORE;
return -EALREADY; return REG_REQ_ALREADY_SET;
} }
/* /*
* Two consecutive Country IE hints on the same wiphy. * Two consecutive Country IE hints on the same wiphy.
* This should be picked up early by the driver/stack * This should be picked up early by the driver/stack
*/ */
if (WARN_ON(regdom_changes(pending_request->alpha2))) if (WARN_ON(regdom_changes(pending_request->alpha2)))
return 0; return REG_REQ_OK;
return -EALREADY; return REG_REQ_ALREADY_SET;
} }
return 0; return 0;
case NL80211_REGDOM_SET_BY_DRIVER: case NL80211_REGDOM_SET_BY_DRIVER:
if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) { if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) {
if (regdom_changes(pending_request->alpha2)) if (regdom_changes(pending_request->alpha2))
return 0; return REG_REQ_OK;
return -EALREADY; return REG_REQ_ALREADY_SET;
} }
/* /*
...@@ -1378,25 +1381,25 @@ static int ignore_request(struct wiphy *wiphy, ...@@ -1378,25 +1381,25 @@ static int ignore_request(struct wiphy *wiphy,
*/ */
if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
!regdom_changes(pending_request->alpha2)) !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: case NL80211_REGDOM_SET_BY_USER:
if (reg_request_cell_base(pending_request)) if (reg_request_cell_base(pending_request))
return reg_ignore_cell_hint(pending_request); return reg_ignore_cell_hint(pending_request);
if (reg_request_cell_base(last_request)) if (reg_request_cell_base(last_request))
return -EOPNOTSUPP; return REG_REQ_IGNORE;
if (last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) 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 * If the user knows better the user should set the regdom
* to their country before the IE is picked up * to their country before the IE is picked up
*/ */
if (last_request->initiator == NL80211_REGDOM_SET_BY_USER && if (last_request->initiator == NL80211_REGDOM_SET_BY_USER &&
last_request->intersect) last_request->intersect)
return -EOPNOTSUPP; return REG_REQ_IGNORE;
/* /*
* Process user requests only after previous user/driver/core * Process user requests only after previous user/driver/core
* requests have been processed * requests have been processed
...@@ -1405,15 +1408,15 @@ static int ignore_request(struct wiphy *wiphy, ...@@ -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_DRIVER ||
last_request->initiator == NL80211_REGDOM_SET_BY_USER) && last_request->initiator == NL80211_REGDOM_SET_BY_USER) &&
regdom_changes(last_request->alpha2)) regdom_changes(last_request->alpha2))
return -EAGAIN; return REG_REQ_IGNORE;
if (!regdom_changes(pending_request->alpha2)) 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) static void reg_set_request_processed(void)
...@@ -1443,23 +1446,24 @@ 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 * The Wireless subsystem can use this function to hint to the wireless core
* what it believes should be the current regulatory domain. * what it believes should be the current regulatory domain.
* *
* Returns zero if all went fine, %-EALREADY if a regulatory domain had * Returns one of the different reg request treatment values.
* already been set or other standard error codes.
* *
* Caller must hold &cfg80211_mutex and &reg_mutex * Caller must hold &cfg80211_mutex and &reg_mutex
*/ */
static int __regulatory_hint(struct wiphy *wiphy, static enum reg_request_treatment
struct regulatory_request *pending_request) __regulatory_hint(struct wiphy *wiphy,
struct regulatory_request *pending_request)
{ {
const struct ieee80211_regdomain *regd; const struct ieee80211_regdomain *regd;
bool intersect = false; bool intersect = false;
int r = 0; enum reg_request_treatment treatment;
assert_cfg80211_lock(); 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 == if (pending_request->initiator ==
NL80211_REGDOM_SET_BY_DRIVER) { NL80211_REGDOM_SET_BY_DRIVER) {
regd = reg_copy_regd(cfg80211_regdomain); regd = reg_copy_regd(cfg80211_regdomain);
...@@ -1470,26 +1474,28 @@ static int __regulatory_hint(struct wiphy *wiphy, ...@@ -1470,26 +1474,28 @@ static int __regulatory_hint(struct wiphy *wiphy,
wiphy->regd = regd; wiphy->regd = regd;
} }
intersect = true; intersect = true;
} else if (r) { break;
case REG_REQ_OK:
break;
default:
/* /*
* If the regulatory domain being requested by the * If the regulatory domain being requested by the
* driver has already been set just copy it to the * driver has already been set just copy it to the
* wiphy * wiphy
*/ */
if (r == -EALREADY && if (treatment == REG_REQ_ALREADY_SET &&
pending_request->initiator == pending_request->initiator == NL80211_REGDOM_SET_BY_DRIVER) {
NL80211_REGDOM_SET_BY_DRIVER) {
regd = reg_copy_regd(cfg80211_regdomain); regd = reg_copy_regd(cfg80211_regdomain);
if (IS_ERR(regd)) { if (IS_ERR(regd)) {
kfree(pending_request); kfree(pending_request);
return PTR_ERR(regd); return REG_REQ_IGNORE;
} }
r = -EALREADY; treatment = REG_REQ_ALREADY_SET;
wiphy->regd = regd; wiphy->regd = regd;
goto new_request; goto new_request;
} }
kfree(pending_request); kfree(pending_request);
return r; return treatment;
} }
new_request: new_request:
...@@ -1506,28 +1512,29 @@ static int __regulatory_hint(struct wiphy *wiphy, ...@@ -1506,28 +1512,29 @@ static int __regulatory_hint(struct wiphy *wiphy,
user_alpha2[1] = last_request->alpha2[1]; user_alpha2[1] = last_request->alpha2[1];
} }
/* When r == REG_INTERSECT we do need to call CRDA */ /* When r == REG_REQ_INTERSECT we do need to call CRDA */
if (r < 0) { if (treatment != REG_REQ_OK && treatment != REG_REQ_INTERSECT) {
/* /*
* Since CRDA will not be called in this case as we already * Since CRDA will not be called in this case as we already
* have applied the requested regulatory domain before we just * have applied the requested regulatory domain before we just
* inform userspace we have processed the request * inform userspace we have processed the request
*/ */
if (r == -EALREADY) { if (treatment == REG_REQ_ALREADY_SET) {
nl80211_send_reg_change_event(last_request); nl80211_send_reg_change_event(last_request);
reg_set_request_processed(); 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 */ /* This processes *all* regulatory hints */
static void reg_process_hint(struct regulatory_request *reg_request, static void reg_process_hint(struct regulatory_request *reg_request,
enum nl80211_reg_initiator reg_initiator) enum nl80211_reg_initiator reg_initiator)
{ {
int r = 0;
struct wiphy *wiphy = NULL; struct wiphy *wiphy = NULL;
BUG_ON(!reg_request->alpha2); BUG_ON(!reg_request->alpha2);
...@@ -1540,20 +1547,18 @@ static void reg_process_hint(struct regulatory_request *reg_request, ...@@ -1540,20 +1547,18 @@ static void reg_process_hint(struct regulatory_request *reg_request,
return; return;
} }
r = __regulatory_hint(wiphy, reg_request); switch (__regulatory_hint(wiphy, reg_request)) {
/* This is required so that the orig_* parameters are saved */ case REG_REQ_ALREADY_SET:
if (r == -EALREADY && wiphy && /* This is required so that the orig_* parameters are saved */
wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { if (wiphy && wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
wiphy_update_regulatory(wiphy, reg_initiator); 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));
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment