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:
Родитель
9027b1493b
Коммит
2f92212b71
|
@ -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 ®_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(®_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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче