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: Luis R. Rodriguez <mcgrof@do-not-panic.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
@@ -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)
|
|||||||
|
|
||||||
#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)
|
|||||||
#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,
|
|||||||
}
|
}
|
||||||
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,
|
|||||||
|
|
||||||
/* 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,
|
|||||||
* 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,
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
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)
|
|||||||
* 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 ®_mutex
|
* Caller must hold &cfg80211_mutex and ®_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,
|
|||||||
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 @@ new_request:
|
|||||||
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,
|
|||||||
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(®_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(®_timeout, msecs_to_jiffies(3142));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user