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
......@@ -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,
struct regulatory_request *pending_request)
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 @@ new_request:
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);
/* This is required so that the orig_* parameters are saved */
if (r == -EALREADY && wiphy &&
wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) {
wiphy_update_regulatory(wiphy, reg_initiator);
return;
switch (__regulatory_hint(wiphy, reg_request)) {
case REG_REQ_ALREADY_SET:
/* This is required so that the orig_* parameters are saved */
if (wiphy && wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
wiphy_update_regulatory(wiphy, reg_initiator);
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