Includes some documentation fixes.
------
As before, this series addresses the option of enabling additional channels for
use based on the following relaxations:
1. Indoor operation, where a device can use channels requiring indoor
operation, subject to that it can guarantee indoor operation.
2. Concurrent GO operation, where devices may instantiate a P2P GO
while they are under the guidance of an authorized master.
The series includes:
* Some clarification (mainly in documentation) about the intended usage of
channels marked as INDOOR_ONLY and CONCURRENT GO.
* Mapping of NL80211_RFF_NO_OUTDOOR to NL80211_CHAN_INDOOR_ONLY
* Support for a user hint that the platform is operating in an indoor
environment, i.e., channel marked as INDOOR_ONLY can be used.
* Allow initiating radiation on channel marked with INDOOR_ONLY also
for scanning an frame injection in monitor mode.
* Some additional fixes for comments I got.
Following is an example of a possible channel map that can be used to allow
the INDOOR_ONLY and CONCURRENT_GO relaxations. Note that:
* Channels 12,13 are marked as Concurrent GO, so even in the lack of exact
information about the current regulatory domain, these channels can be used
for GO instantiation based on the concurrent GO relaxation.
* The above is also true for channels 149-165 (a.k.a U-NII 3).
* Channels 36-48 (a.k.a thee U-NII 1), are marked both with Concurrent GO and
indoor only. While the Concurrent GO can be used as described above, the
indoor only setting allows to use these channels given the platform is
identified as an indoor one, i.e., media server.
2412 MHz [1] (16.0 dBm)
2417 MHz [2] (16.0 dBm)
2422 MHz [3] (16.0 dBm)
2427 MHz [4] (16.0 dBm)
2432 MHz [5] (16.0 dBm)
2437 MHz [6] (16.0 dBm)
2442 MHz [7] (16.0 dBm)
2447 MHz [8] (16.0 dBm)
2452 MHz [9] (16.0 dBm)
2457 MHz [10] (16.0 dBm)
2462 MHz [11] (16.0 dBm)
2467 MHz [12] (16.0 dBm) (no IR, Concurrent GO)
2472 MHz [13] (16.0 dBm) (no IR, Concurrent GO)
5180 MHz [36] (16.0 dBm) (no IR, Indoor Only, Concurrent GO)
5200 MHz [40] (16.0 dBm) (no IR, Indoor Only, Concurrent GO)
5220 MHz [44] (16.0 dBm) (no IR, Indoor Only, Concurrent GO)
5240 MHz [48] (16.0 dBm) (no IR, Indoor Only, Concurrent GO)
5260 MHz [52] (16.0 dBm) (no IR, radar detection)
5280 MHz [56] (16.0 dBm) (no IR, radar detection)
5300 MHz [60] (16.0 dBm) (no IR, radar detection)
5320 MHz [64] (16.0 dBm) (no IR, radar detection)
5500 MHz [100] (16.0 dBm) (no IR, radar detection)
5520 MHz [104] (16.0 dBm) (no IR, radar detection)
5540 MHz [108] (16.0 dBm) (no IR, radar detection)
5560 MHz [112] (16.0 dBm) (no IR, radar detection)
5580 MHz [116] (16.0 dBm) (no IR, radar detection)
5600 MHz [120] (16.0 dBm) (no IR, radar detection)
5620 MHz [124] (16.0 dBm) (no IR, radar detection)
5640 MHz [128] (16.0 dBm) (no IR, radar detection)
5660 MHz [132] (16.0 dBm) (no IR, radar detection)
5680 MHz [136] (16.0 dBm) (no IR, radar detection)
5700 MHz [140] (16.0 dBm) (no IR, radar detection)
5720 MHz [144] (16.0 dBm) (no IR, radar detection)
5745 MHz [149] (16.0 dBm) (no IR, Concurrent GO)
5765 MHz [153] (16.0 dBm) (no IR, Concurrent GO)
5785 MHz [157] (16.0 dBm) (no IR, Concurrent GO)
5805 MHz [161] (16.0 dBm) (no IR, Concurrent GO)
5825 MHz [165] (16.0 dBm) (no IR, Concurrent GO)
Thanks in advance,
Ilan.
David Spinadel (1):
cfg80211: Add indoor only and GO concurrent channel attributes
Ilan Peer (4):
cfg80211: Add Kconfig option for cellular BS hints
cfg80211: Enable GO operation on additional channels
cfg80211: Add an option to hint indoor operation
cfg80211: Enable GO operation on indoor channels
include/net/cfg80211.h | 14 +++++-
include/net/regulatory.h | 6 +++
include/uapi/linux/nl80211.h | 26 +++++++++++
net/mac80211/ibss.c | 9 ++--
net/wireless/Kconfig | 37 ++++++++++++++++
net/wireless/chan.c | 77 +++++++++++++++++++++++++++++++--
net/wireless/mesh.c | 3 +-
net/wireless/nl80211.c | 35 ++++++++-------
net/wireless/reg.c | 97 +++++++++++++++++++++++++++++++++++++++++-
net/wireless/reg.h | 13 ++++++
net/wireless/trace.h | 11 +++--
11 files changed, 299 insertions(+), 29 deletions(-)
--
1.7.10.4
PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBsaW51eC13aXJlbGVzcy1vd25l
ckB2Z2VyLmtlcm5lbC5vcmcgW21haWx0bzpsaW51eC13aXJlbGVzcy0NCj4gb3duZXJAdmdlci5r
ZXJuZWwub3JnXSBPbiBCZWhhbGYgT2YgSm9oYW5uZXMgQmVyZw0KPiBTZW50OiBGcmlkYXksIEZl
YnJ1YXJ5IDIxLCAyMDE0IDExOjAzDQo+IFRvOiBQZWVyLCBJbGFuDQo+IENjOiBsaW51eC13aXJl
bGVzc0B2Z2VyLmtlcm5lbC5vcmc7IG1jZ3JvZkBkby1ub3QtcGFuaWMuY29tDQo+IFN1YmplY3Q6
IFJlOiBbUEFUQ0ggdjUgNC81XSBjZmc4MDIxMTogQWRkIGFuIG9wdGlvbiB0byBoaW50IGluZG9v
ciBvcGVyYXRpb24NCj4gDQo+IE9uIFRodSwgMjAxNC0wMi0yMCBhdCAxNDoyMSArMDIwMCwgSWxh
biBQZWVyIHdyb3RlOg0KPiANCj4gPiArYm9vbCByZWd1bGF0b3J5X2luZG9vcl9hbGxvd2VkKHZv
aWQpDQo+ID4gK3sNCj4gPiArCXJldHVybiByZWdfaXNfaW5kb29yOw0KPiA+ICt9DQo+ID4gK0VY
UE9SVF9TWU1CT0xfR1BMKHJlZ3VsYXRvcnlfaW5kb29yX2FsbG93ZWQpOw0KPiANCj4gSSBkb24n
dCBzZWUgYW55IHVzZXIgb2YgdGhpcyAoaW4gcGFydGljdWxhciBub25lIHRoYXQgd291bGQgbmVl
ZCBpdCBleHBvcnRlZCk/DQo+IA0KDQpMZWZ0b3ZlcnMgZnJvbSB0aGUgcHJldmlvdXMgc2V0IDop
IC4uLiBmaXhpbmcuDQoNClRoYW5rcywNCg0KSWxhbi4NCg==
Add the option to hint the wireless core that it is operating in an indoor
environment.
Change-Id: Ie082a09b41292c6e12d4b2ffb01117c14b6a94f6
Signed-off-by: Ilan Peer <[email protected]>
---
include/net/cfg80211.h | 5 ++++
include/uapi/linux/nl80211.h | 3 ++
net/wireless/nl80211.c | 18 +++++-------
net/wireless/reg.c | 64 +++++++++++++++++++++++++++++++++++++++++-
net/wireless/reg.h | 1 +
5 files changed, 79 insertions(+), 12 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index e872c9c..5c6053c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3626,6 +3626,11 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
*/
const char *reg_initiator_name(enum nl80211_reg_initiator initiator);
+/**
+ * regulatory_indoor_allowed - is indoor operation allowed
+ */
+bool regulatory_indoor_allowed(void);
+
/*
* callbacks for asynchronous cfg80211 methods, notification
* functions and BSS handling helpers
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 061f8d4..42710e5 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2583,10 +2583,13 @@ enum nl80211_dfs_regions {
* present has been registered with the wireless core that
* has listed NL80211_FEATURE_CELL_BASE_REG_HINTS as a
* supported feature.
+ * @NL80211_USER_REG_HINT_INDOOR: a user sent an hint indicating that the
+ * platform is operating in an indoor environment.
*/
enum nl80211_user_reg_hint_type {
NL80211_USER_REG_HINT_USER = 0,
NL80211_USER_REG_HINT_CELL_BASE = 1,
+ NL80211_USER_REG_HINT_INDOOR = 2,
};
/**
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 2270d9b..50826a9 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4659,7 +4659,6 @@ static int parse_reg_rule(struct nlattr *tb[],
static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
{
- int r;
char *data = NULL;
enum nl80211_user_reg_hint_type user_reg_hint_type;
@@ -4672,11 +4671,6 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
if (unlikely(!rcu_access_pointer(cfg80211_regdomain)))
return -EINPROGRESS;
- if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
- return -EINVAL;
-
- data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
-
if (info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE])
user_reg_hint_type =
nla_get_u32(info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE]);
@@ -4686,14 +4680,16 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
switch (user_reg_hint_type) {
case NL80211_USER_REG_HINT_USER:
case NL80211_USER_REG_HINT_CELL_BASE:
- break;
+ if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
+ return -EINVAL;
+
+ data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
+ return regulatory_hint_user(data, user_reg_hint_type);
+ case NL80211_USER_REG_HINT_INDOOR:
+ return regulatory_hint_indoor_user();
default:
return -EINVAL;
}
-
- r = regulatory_hint_user(data, user_reg_hint_type);
-
- return r;
}
static int nl80211_get_mesh_config(struct sk_buff *skb,
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 8f5b460..50e41a5 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -65,11 +65,26 @@
#define REG_DBG_PRINT(args...)
#endif
+/**
+ * enum reg_request_treatment - regulatory request treatment
+ *
+ * @REG_REQ_OK: continue processing the regulatory request
+ * @REG_REQ_IGNORE: ignore the regulatory request
+ * @REG_REQ_INTERSECT: the regulatory domain resulting from this request should
+ * be intersected with the current one.
+ * @REG_REQ_ALREADY_SET: the regulatory request will not change the current
+ * regulatory settings, and no further processing is required.
+ * @REG_REQ_USER_HINT_HANDLED: a non alpha2 user hint was handled and no
+ * further processing is required, i.e., not need to update last_request
+ * etc. This should be used for user hints that do not provide an alpha2
+ * but some other type of regulatory hint, i.e., indoor operation.
+ */
enum reg_request_treatment {
REG_REQ_OK,
REG_REQ_IGNORE,
REG_REQ_INTERSECT,
REG_REQ_ALREADY_SET,
+ REG_REQ_USER_HINT_HANDLED,
};
static struct regulatory_request core_request_world = {
@@ -110,6 +125,14 @@ const struct ieee80211_regdomain __rcu *cfg80211_regdomain;
*/
static int reg_num_devs_support_basehint;
+/*
+ * State variable indicating if the platform on which the devices
+ * are attached is operating in an indoor environment. The state variable
+ * is relevant for all registered devices.
+ * Note: currently not protected by any synchronization primitive.
+ */
+static bool reg_is_indoor;
+
static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
{
return rtnl_dereference(cfg80211_regdomain);
@@ -1104,6 +1127,13 @@ static bool reg_request_cell_base(struct regulatory_request *request)
return request->user_reg_hint_type == NL80211_USER_REG_HINT_CELL_BASE;
}
+static bool reg_request_indoor(struct regulatory_request *request)
+{
+ if (request->initiator != NL80211_REGDOM_SET_BY_USER)
+ return false;
+ return request->user_reg_hint_type == NL80211_USER_REG_HINT_INDOOR;
+}
+
bool reg_last_request_cell_base(void)
{
return reg_request_cell_base(get_last_request());
@@ -1546,6 +1576,11 @@ __reg_process_hint_user(struct regulatory_request *user_request)
{
struct regulatory_request *lr = get_last_request();
+ if (reg_request_indoor(user_request)) {
+ reg_is_indoor = true;
+ return REG_REQ_USER_HINT_HANDLED;
+ }
+
if (reg_request_cell_base(user_request))
return reg_ignore_cell_hint(user_request);
@@ -1593,7 +1628,8 @@ reg_process_hint_user(struct regulatory_request *user_request)
treatment = __reg_process_hint_user(user_request);
if (treatment == REG_REQ_IGNORE ||
- treatment == REG_REQ_ALREADY_SET) {
+ treatment == REG_REQ_ALREADY_SET ||
+ treatment == REG_REQ_USER_HINT_HANDLED) {
kfree(user_request);
return treatment;
}
@@ -1654,6 +1690,7 @@ reg_process_hint_driver(struct wiphy *wiphy,
case REG_REQ_OK:
break;
case REG_REQ_IGNORE:
+ case REG_REQ_USER_HINT_HANDLED:
kfree(driver_request);
return treatment;
case REG_REQ_INTERSECT:
@@ -1753,6 +1790,7 @@ reg_process_hint_country_ie(struct wiphy *wiphy,
case REG_REQ_OK:
break;
case REG_REQ_IGNORE:
+ case REG_REQ_USER_HINT_HANDLED:
/* fall through */
case REG_REQ_ALREADY_SET:
kfree(country_ie_request);
@@ -1945,6 +1983,22 @@ int regulatory_hint_user(const char *alpha2,
return 0;
}
+int regulatory_hint_indoor_user(void)
+{
+ struct regulatory_request *request;
+
+ request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
+ if (!request)
+ return -ENOMEM;
+
+ request->wiphy_idx = WIPHY_IDX_INVALID;
+ request->initiator = NL80211_REGDOM_SET_BY_USER;
+ request->user_reg_hint_type = NL80211_USER_REG_HINT_INDOOR;
+ queue_regulatory_request(request);
+
+ return 0;
+}
+
/* Driver hints */
int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
{
@@ -2112,6 +2166,8 @@ static void restore_regulatory_settings(bool reset_user)
ASSERT_RTNL();
+ reg_is_indoor = false;
+
reset_regdomains(true, &world_regdom);
restore_alpha2(alpha2, reset_user);
@@ -2626,6 +2682,12 @@ int cfg80211_get_unii(int freq)
return -EINVAL;
}
+bool regulatory_indoor_allowed(void)
+{
+ return reg_is_indoor;
+}
+EXPORT_SYMBOL_GPL(regulatory_indoor_allowed);
+
int __init regulatory_init(void)
{
int err = 0;
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 9c11e72..b350a30 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -25,6 +25,7 @@ enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy);
int regulatory_hint_user(const char *alpha2,
enum nl80211_user_reg_hint_type user_reg_hint_type);
+int regulatory_hint_indoor_user(void);
int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env);
void wiphy_regulatory_register(struct wiphy *wiphy);
--
1.7.10.4
On Thu, Feb 20, 2014 at 3:44 AM, Ilan Peer <[email protected]> wrote:
> Move the regulatory cellular base station hints support under
> a specific configuration option and make the option depend
> on CFG80211_CERTIFICATION_ONUS.
>
> Signed-off-by: Ilan Peer <[email protected]>
Reviewed-by: Luis R. Rodriguez <[email protected]>
Luis
On Thu, 2014-02-20 at 14:21 +0200, Ilan Peer wrote:
> +bool regulatory_indoor_allowed(void)
> +{
> + return reg_is_indoor;
> +}
> +EXPORT_SYMBOL_GPL(regulatory_indoor_allowed);
I don't see any user of this (in particular none that would need it
exported)?
johannes
From: David Spinadel <[email protected]>
The FCC are clarifying some soft configuration requirements,
which among other include the following:
1. Indoor operation, where a device can use channels requiring indoor
operation, subject to that it can guarantee indoor operation,
i.e., the device is connected to AC Power or the device is under
the control of a local master that is acting as an AP and is
connected to AC Power.
2. Concurrent GO operation, where devices may instantiate a P2P GO
while they are under the guidance of an authorized master. For example,
on a channel on which a BSS is connected to an authorized master, i.e.,
with DFS and radar detection capability in the UNII band.
See https://apps.fcc.gov/eas/comments/GetPublishedDocument.html?id=327&tn=528122
Add support for advertising Indoor-only and GO-Concurrent channel
properties.
Signed-off-by: David Spinadel <[email protected]>
Signed-off-by: Ilan Peer <[email protected]>
---
include/net/cfg80211.h | 5 +++++
include/uapi/linux/nl80211.h | 23 +++++++++++++++++++++++
net/wireless/nl80211.c | 6 ++++++
net/wireless/reg.c | 2 ++
4 files changed, 36 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9f90554..2ba017c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -109,6 +109,9 @@ enum ieee80211_band {
* channel as the control or any of the secondary channels.
* This may be due to the driver or due to regulatory bandwidth
* restrictions.
+ * @IEEE80211_CHAN_INDOOR_ONLY: see %NL80211_FREQUENCY_ATTR_INDOOR_ONLY
+ * @IEEE80211_CHAN_GO_CONCURRENT: see %NL80211_FREQUENCY_ATTR_GO_CONCURRENT
+ *
*/
enum ieee80211_channel_flags {
IEEE80211_CHAN_DISABLED = 1<<0,
@@ -120,6 +123,8 @@ enum ieee80211_channel_flags {
IEEE80211_CHAN_NO_OFDM = 1<<6,
IEEE80211_CHAN_NO_80MHZ = 1<<7,
IEEE80211_CHAN_NO_160MHZ = 1<<8,
+ IEEE80211_CHAN_INDOOR_ONLY = 1<<9,
+ IEEE80211_CHAN_GO_CONCURRENT = 1<<10,
};
#define IEEE80211_CHAN_NO_HT40 \
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index a12e6ca..061f8d4 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2329,9 +2329,30 @@ enum nl80211_band_attr {
* @NL80211_FREQUENCY_ATTR_NO_160MHZ: any 160 MHz (but not 80+80) channel
* using this channel as the primary or any of the secondary channels
* isn't possible
+ * @NL80211_FREQUENCY_ATTR_INDOOR_ONLY: Only indoor use is permitted on this
+ * channel. A channel that has the INDOOR_ONLY attribute can only be
+ * used when there is a clear assessment that the device is operating in
+ * an indoor surroundings, i.e., it is connected to AC power (and not
+ * through portable DC inverters) or is under the control of a master
+ * that is acting as an AP and is connected to AC power.
+ * @NL80211_FREQUENCY_ATTR_GO_CONCURRENT: GO operation is allowed on this
+ * channel if it's connected concurrently to a BSS on the same channel on
+ * the 2 GHz band or to a channel in the same UNII band (on the 5 GHz
+ * band), and IEEE80211_CHAN_RADAR is not set. Instantiating a GO on a
+ * channel that has the GO_CONCURRENT attribute set can be done when there
+ * is a clear assessment that the device is operating under the guidance of
+ * an authorized master, i.e., setting up a GO while the device is also
+ * connected to an AP with DFS and radar detection on the UNII band (it is
+ * up to user-space, i.e., wpa_supplicant to perform the required
+ * verifications)
* @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
* currently defined
* @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
+ *
+ * See https://apps.fcc.gov/eas/comments/GetPublishedDocument.html?id=327&tn=528122
+ * for more information on the FCC description of the relaxations allowed
+ * by NL80211_FREQUENCY_ATTR_INDOOR_ONLY and
+ * NL80211_FREQUENCY_ATTR_GO_CONCURRENT.
*/
enum nl80211_frequency_attr {
__NL80211_FREQUENCY_ATTR_INVALID,
@@ -2347,6 +2368,8 @@ enum nl80211_frequency_attr {
NL80211_FREQUENCY_ATTR_NO_HT40_PLUS,
NL80211_FREQUENCY_ATTR_NO_80MHZ,
NL80211_FREQUENCY_ATTR_NO_160MHZ,
+ NL80211_FREQUENCY_ATTR_INDOOR_ONLY,
+ NL80211_FREQUENCY_ATTR_GO_CONCURRENT,
/* keep last */
__NL80211_FREQUENCY_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 8e6b6a2..95a8c72 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -608,6 +608,12 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) &&
nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ))
goto nla_put_failure;
+ if ((chan->flags & IEEE80211_CHAN_INDOOR_ONLY) &&
+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_INDOOR_ONLY))
+ goto nla_put_failure;
+ if ((chan->flags & IEEE80211_CHAN_GO_CONCURRENT) &&
+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_GO_CONCURRENT))
+ goto nla_put_failure;
}
if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 27c5253..eeccce3 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -867,6 +867,8 @@ static u32 map_regdom_flags(u32 rd_flags)
channel_flags |= IEEE80211_CHAN_RADAR;
if (rd_flags & NL80211_RRF_NO_OFDM)
channel_flags |= IEEE80211_CHAN_NO_OFDM;
+ if (rd_flags & NL80211_RRF_NO_OUTDOOR)
+ channel_flags |= IEEE80211_CHAN_INDOOR_ONLY;
return channel_flags;
}
--
1.7.10.4
Move the regulatory cellular base station hints support under
a specific configuration option and make the option depend
on CFG80211_CERTIFICATION_ONUS.
Signed-off-by: Ilan Peer <[email protected]>
---
net/wireless/Kconfig | 13 +++++++++++++
net/wireless/reg.c | 2 +-
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 16d08b3..2a891bc 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -95,6 +95,19 @@ config CFG80211_CERTIFICATION_ONUS
you are a wireless researcher and are working in a controlled
and approved environment by your local regulatory agency.
+config CFG80211_REG_CELLULAR_HINTS
+ bool "cfg80211 regulatory support for cellular base station hints"
+ depends on CFG80211_CERTIFICATION_ONUS
+ ---help---
+ This option enables support for parsing regulatory hints
+ from cellular base stations. If enabled and at least one driver
+ claims support for parsing cellular base station hints the
+ regulatory core will allow and parse these regulatory hints.
+ The regulatory core will only apply these regulatory hints on
+ drivers that support this feature. You should only enable this
+ feature if you have tested and validated this feature on your
+ systems.
+
config CFG80211_DEFAULT_PS
bool "enable powersave by default"
depends on CFG80211
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index eeccce3..096268f 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1109,7 +1109,7 @@ bool reg_last_request_cell_base(void)
return reg_request_cell_base(get_last_request());
}
-#ifdef CONFIG_CFG80211_CERTIFICATION_ONUS
+#ifdef CONFIG_CFG80211_REG_CELLULAR_HINTS
/* Core specific check */
static enum reg_request_treatment
reg_ignore_cell_hint(struct regulatory_request *pending_request)
--
1.7.10.4
On Thu, Feb 20, 2014 at 3:44 AM, Ilan Peer <[email protected]> wrote:
> + list_for_each_entry(wdev_iter, &rdev->wdev_list, list) {
This is still my only remaining concern. The Kconfig and documentation
don't point this out and it should if its limited to only trusting
concurrency based on the interfaces from the same driver. If we stick
with this that should be prevalent on the documentation. With that
added you get my:
Reviewed-by: Luis R. Rodriguez <[email protected]>
Luis
Add the option to hint the wireless core that it is operating in an indoor
environment.
Change-Id: Ie082a09b41292c6e12d4b2ffb01117c14b6a94f6
Signed-off-by: Ilan Peer <[email protected]>
---
include/net/cfg80211.h | 5 ++++
include/uapi/linux/nl80211.h | 3 ++
net/wireless/nl80211.c | 18 +++++-------
net/wireless/reg.c | 64 +++++++++++++++++++++++++++++++++++++++++-
net/wireless/reg.h | 1 +
5 files changed, 79 insertions(+), 12 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index e872c9c..5c6053c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3626,6 +3626,11 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
*/
const char *reg_initiator_name(enum nl80211_reg_initiator initiator);
+/**
+ * regulatory_indoor_allowed - is indoor operation allowed
+ */
+bool regulatory_indoor_allowed(void);
+
/*
* callbacks for asynchronous cfg80211 methods, notification
* functions and BSS handling helpers
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 061f8d4..42710e5 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2583,10 +2583,13 @@ enum nl80211_dfs_regions {
* present has been registered with the wireless core that
* has listed NL80211_FEATURE_CELL_BASE_REG_HINTS as a
* supported feature.
+ * @NL80211_USER_REG_HINT_INDOOR: a user sent an hint indicating that the
+ * platform is operating in an indoor environment.
*/
enum nl80211_user_reg_hint_type {
NL80211_USER_REG_HINT_USER = 0,
NL80211_USER_REG_HINT_CELL_BASE = 1,
+ NL80211_USER_REG_HINT_INDOOR = 2,
};
/**
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 2270d9b..50826a9 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4659,7 +4659,6 @@ static int parse_reg_rule(struct nlattr *tb[],
static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
{
- int r;
char *data = NULL;
enum nl80211_user_reg_hint_type user_reg_hint_type;
@@ -4672,11 +4671,6 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
if (unlikely(!rcu_access_pointer(cfg80211_regdomain)))
return -EINPROGRESS;
- if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
- return -EINVAL;
-
- data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
-
if (info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE])
user_reg_hint_type =
nla_get_u32(info->attrs[NL80211_ATTR_USER_REG_HINT_TYPE]);
@@ -4686,14 +4680,16 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
switch (user_reg_hint_type) {
case NL80211_USER_REG_HINT_USER:
case NL80211_USER_REG_HINT_CELL_BASE:
- break;
+ if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
+ return -EINVAL;
+
+ data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
+ return regulatory_hint_user(data, user_reg_hint_type);
+ case NL80211_USER_REG_HINT_INDOOR:
+ return regulatory_hint_indoor_user();
default:
return -EINVAL;
}
-
- r = regulatory_hint_user(data, user_reg_hint_type);
-
- return r;
}
static int nl80211_get_mesh_config(struct sk_buff *skb,
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 8f5b460..50e41a5 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -65,11 +65,26 @@
#define REG_DBG_PRINT(args...)
#endif
+/**
+ * enum reg_request_treatment - regulatory request treatment
+ *
+ * @REG_REQ_OK: continue processing the regulatory request
+ * @REG_REQ_IGNORE: ignore the regulatory request
+ * @REG_REQ_INTERSECT: the regulatory domain resulting from this request should
+ * be intersected with the current one.
+ * @REG_REQ_ALREADY_SET: the regulatory request will not change the current
+ * regulatory settings, and no further processing is required.
+ * @REG_REQ_USER_HINT_HANDLED: a non alpha2 user hint was handled and no
+ * further processing is required, i.e., not need to update last_request
+ * etc. This should be used for user hints that do not provide an alpha2
+ * but some other type of regulatory hint, i.e., indoor operation.
+ */
enum reg_request_treatment {
REG_REQ_OK,
REG_REQ_IGNORE,
REG_REQ_INTERSECT,
REG_REQ_ALREADY_SET,
+ REG_REQ_USER_HINT_HANDLED,
};
static struct regulatory_request core_request_world = {
@@ -110,6 +125,14 @@ const struct ieee80211_regdomain __rcu *cfg80211_regdomain;
*/
static int reg_num_devs_support_basehint;
+/*
+ * State variable indicating if the platform on which the devices
+ * are attached is operating in an indoor environment. The state variable
+ * is relevant for all registered devices.
+ * Note: currently not protected by any synchronization primitive.
+ */
+static bool reg_is_indoor;
+
static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
{
return rtnl_dereference(cfg80211_regdomain);
@@ -1104,6 +1127,13 @@ static bool reg_request_cell_base(struct regulatory_request *request)
return request->user_reg_hint_type == NL80211_USER_REG_HINT_CELL_BASE;
}
+static bool reg_request_indoor(struct regulatory_request *request)
+{
+ if (request->initiator != NL80211_REGDOM_SET_BY_USER)
+ return false;
+ return request->user_reg_hint_type == NL80211_USER_REG_HINT_INDOOR;
+}
+
bool reg_last_request_cell_base(void)
{
return reg_request_cell_base(get_last_request());
@@ -1546,6 +1576,11 @@ __reg_process_hint_user(struct regulatory_request *user_request)
{
struct regulatory_request *lr = get_last_request();
+ if (reg_request_indoor(user_request)) {
+ reg_is_indoor = true;
+ return REG_REQ_USER_HINT_HANDLED;
+ }
+
if (reg_request_cell_base(user_request))
return reg_ignore_cell_hint(user_request);
@@ -1593,7 +1628,8 @@ reg_process_hint_user(struct regulatory_request *user_request)
treatment = __reg_process_hint_user(user_request);
if (treatment == REG_REQ_IGNORE ||
- treatment == REG_REQ_ALREADY_SET) {
+ treatment == REG_REQ_ALREADY_SET ||
+ treatment == REG_REQ_USER_HINT_HANDLED) {
kfree(user_request);
return treatment;
}
@@ -1654,6 +1690,7 @@ reg_process_hint_driver(struct wiphy *wiphy,
case REG_REQ_OK:
break;
case REG_REQ_IGNORE:
+ case REG_REQ_USER_HINT_HANDLED:
kfree(driver_request);
return treatment;
case REG_REQ_INTERSECT:
@@ -1753,6 +1790,7 @@ reg_process_hint_country_ie(struct wiphy *wiphy,
case REG_REQ_OK:
break;
case REG_REQ_IGNORE:
+ case REG_REQ_USER_HINT_HANDLED:
/* fall through */
case REG_REQ_ALREADY_SET:
kfree(country_ie_request);
@@ -1945,6 +1983,22 @@ int regulatory_hint_user(const char *alpha2,
return 0;
}
+int regulatory_hint_indoor_user(void)
+{
+ struct regulatory_request *request;
+
+ request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
+ if (!request)
+ return -ENOMEM;
+
+ request->wiphy_idx = WIPHY_IDX_INVALID;
+ request->initiator = NL80211_REGDOM_SET_BY_USER;
+ request->user_reg_hint_type = NL80211_USER_REG_HINT_INDOOR;
+ queue_regulatory_request(request);
+
+ return 0;
+}
+
/* Driver hints */
int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
{
@@ -2112,6 +2166,8 @@ static void restore_regulatory_settings(bool reset_user)
ASSERT_RTNL();
+ reg_is_indoor = false;
+
reset_regdomains(true, &world_regdom);
restore_alpha2(alpha2, reset_user);
@@ -2626,6 +2682,12 @@ int cfg80211_get_unii(int freq)
return -EINVAL;
}
+bool regulatory_indoor_allowed(void)
+{
+ return reg_is_indoor;
+}
+EXPORT_SYMBOL_GPL(regulatory_indoor_allowed);
+
int __init regulatory_init(void)
{
int err = 0;
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 9c11e72..b350a30 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -25,6 +25,7 @@ enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy);
int regulatory_hint_user(const char *alpha2,
enum nl80211_user_reg_hint_type user_reg_hint_type);
+int regulatory_hint_indoor_user(void);
int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env);
void wiphy_regulatory_register(struct wiphy *wiphy);
--
1.7.10.4
PiA+ICBzdGF0aWMgYm9vbCBjZmc4MDIxMV9nb19wZXJtaXNzaXZlX2NoYW4oc3RydWN0DQo+IGNm
ZzgwMjExX3JlZ2lzdGVyZWRfZGV2aWNlICpyZGV2LA0KPiA+ICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICBzdHJ1Y3QgaWVlZTgwMjExX2NoYW5uZWwNCj4gPiAqY2hhbikg
QEAgLTYyMSw4ICs2MjMsMTQgQEAgc3RhdGljIGJvb2wNCj4gY2ZnODAyMTFfZ29fcGVybWlzc2l2
ZV9jaGFuKHN0cnVjdCBjZmc4MDIxMV9yZWdpc3RlcmVkX2RldmljZSAqcmRldiwNCj4gPiAgICAg
ICAgIEFTU0VSVF9SVE5MKCk7DQo+ID4NCj4gPiAgICAgICAgIGlmICghY29uZmlnX2VuYWJsZWQo
Q09ORklHX0NGRzgwMjExX1JFR19SRUxBWF9OT19JUikgfHwNCj4gPiAtICAgICAgICAgICAhKHdp
cGh5LT5yZWd1bGF0b3J5X2ZsYWdzICYgUkVHVUxBVE9SWV9FTkFCTEVfUkVMQVhfTk9fSVIpDQo+
IHx8DQo+ID4gLSAgICAgICAgICAgIShjaGFuLT5mbGFncyAmIElFRUU4MDIxMV9DSEFOX0dPX0NP
TkNVUlJFTlQpKQ0KPiA+ICsgICAgICAgICAgICEod2lwaHktPnJlZ3VsYXRvcnlfZmxhZ3MgJiBS
RUdVTEFUT1JZX0VOQUJMRV9SRUxBWF9OT19JUikpDQo+ID4gKyAgICAgICAgICAgICAgIHJldHVy
biBmYWxzZTsNCj4gPiArDQo+ID4gKyAgICAgICBpZiAocmVndWxhdG9yeV9pbmRvb3JfYWxsb3dl
ZCgpICYmDQo+ID4gKyAgICAgICAgICAgKGNoYW4tPmZsYWdzICYgSUVFRTgwMjExX0NIQU5fSU5E
T09SX09OTFkpKQ0KPiA+ICsgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsNCj4gPiArDQo+ID4g
KyAgICAgICBpZiAoIShjaGFuLT5mbGFncyAmIElFRUU4MDIxMV9DSEFOX0dPX0NPTkNVUlJFTlQp
KQ0KPiA+ICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7DQo+IA0KPiBTaG91bGRuJ3QgdGhp
cyBjaGVjayBnbyBiZWZvcmUgdGhlIGluZG9vciBvbmU/DQo+IA0KDQpJIGRvIG5vdCB0aGluayBz
bywgYXMgdGhpcyByZWxheGF0aW9ucyBpcyBvcnRob2dvbmFsIHRvIHRoZSBHTyBjb25jdXJyZW50
IG9uZS4gSXQgbWVhbnMgdGhhdCBJZiBhIGNoYW5uZWwgaXMgZW5hYmxlZCBidXQgb25seSB1bmRl
ciBpbmRvb3IgYW5kIGluZG9vciBvcGVyYXRpb24gaXMgaGludGVkIHRoZSByZWxheGF0aW9uIHJl
bW92ZXMgdGhlIE5PX0lSIHJlc3RyaWN0aW9uIGlmIHN1Y2ggZXhpc3RzICh3aXRob3V0IHRoZSBy
ZWxheGF0aW9uIGluZG9vciBvcGVyYXRpb24gd291bGQgYmUgIGFsbG93ZWQgYnV0IG5vdCAgZm9y
IEdPKS4NCg0KUmVnYXJkcywNCg0KSWxhbi4NCg==
On Thu, Feb 20, 2014 at 3:44 AM, Ilan Peer <[email protected]> wrote:
> + * Note: currently not protected by any synchronization primitive.
You should verify this is protected by RTNL as the other stuff.
Luis
On Thu, Feb 20, 2014 at 3:44 AM, Ilan Peer <[email protected]> wrote:
> From: David Spinadel <[email protected]>
>
> The FCC are clarifying some soft configuration requirements,
> which among other include the following:
>
> 1. Indoor operation, where a device can use channels requiring indoor
> operation, subject to that it can guarantee indoor operation,
> i.e., the device is connected to AC Power or the device is under
> the control of a local master that is acting as an AP and is
> connected to AC Power.
> 2. Concurrent GO operation, where devices may instantiate a P2P GO
> while they are under the guidance of an authorized master. For example,
> on a channel on which a BSS is connected to an authorized master, i.e.,
> with DFS and radar detection capability in the UNII band.
>
> See https://apps.fcc.gov/eas/comments/GetPublishedDocument.html?id=327&tn=528122
>
> Add support for advertising Indoor-only and GO-Concurrent channel
> properties.
>
> Signed-off-by: David Spinadel <[email protected]>
> Signed-off-by: Ilan Peer <[email protected]>
Reviewed-by: Luis R. Rodriguez <[email protected]>
Luis
On Sat, Feb 22, 2014 at 11:54 AM, Peer, Ilan <[email protected]> wrote:
>> > static bool cfg80211_go_permissive_chan(struct
>> cfg80211_registered_device *rdev,
>> > struct ieee80211_channel
>> > *chan) @@ -621,8 +623,14 @@ static bool
>> cfg80211_go_permissive_chan(struct cfg80211_registered_device *rdev,
>> > ASSERT_RTNL();
>> >
>> > if (!config_enabled(CONFIG_CFG80211_REG_RELAX_NO_IR) ||
>> > - !(wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR)
>> ||
>> > - !(chan->flags & IEEE80211_CHAN_GO_CONCURRENT))
>> > + !(wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR))
>> > + return false;
>> > +
>> > + if (regulatory_indoor_allowed() &&
>> > + (chan->flags & IEEE80211_CHAN_INDOOR_ONLY))
>> > + return true;
>> > +
>> > + if (!(chan->flags & IEEE80211_CHAN_GO_CONCURRENT))
>> > return false;
>>
>> Shouldn't this check go before the indoor one?
>>
>
> I do not think so, as this relaxations is orthogonal to the GO concurrent one. It means that If a channel is enabled but only under indoor and indoor operation is hinted the relaxation removes the NO_IR restriction if such exists (without the relaxation indoor operation would be allowed but not for GO).
Ah yes, the first check remains as this then though:
if (!config_enabled(CONFIG_CFG80211_REG_RELAX_NO_IR) ||
!(wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR))
return false;
That seems wrong for the general case.
Luis
On Thu, Feb 20, 2014 at 3:44 AM, Ilan Peer <[email protected]> wrote:
> Allow GO operation on a channel marked with IEEE80211_CHAN_INDOOR_ONLY
> iff there is a user hint indicating that the platform is operating in
> an indoor environment, i.e., the platform is a printer or media center
> device.
>
> Signed-off-by: Ilan Peer <[email protected]>
> ---
> net/wireless/chan.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/net/wireless/chan.c b/net/wireless/chan.c
> index 1d8c990..b18367d 100644
> --- a/net/wireless/chan.c
> +++ b/net/wireless/chan.c
> @@ -611,6 +611,8 @@ EXPORT_SYMBOL(cfg80211_chandef_usable);
> * IEEE80211_CHAN_GO_CONCURRENT and there is an additional station interface
> * associated to an AP on the same channel or on the same UNII band
> * (assuming that the AP is an authorized master).
> + * In addition allow the GO to operate on a channel on which indoor operation is
> + * allowed, iff we are currently operating in an indoor environment.
> */
> static bool cfg80211_go_permissive_chan(struct cfg80211_registered_device *rdev,
> struct ieee80211_channel *chan)
> @@ -621,8 +623,14 @@ static bool cfg80211_go_permissive_chan(struct cfg80211_registered_device *rdev,
> ASSERT_RTNL();
>
> if (!config_enabled(CONFIG_CFG80211_REG_RELAX_NO_IR) ||
> - !(wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR) ||
> - !(chan->flags & IEEE80211_CHAN_GO_CONCURRENT))
> + !(wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR))
> + return false;
> +
> + if (regulatory_indoor_allowed() &&
> + (chan->flags & IEEE80211_CHAN_INDOOR_ONLY))
> + return true;
> +
> + if (!(chan->flags & IEEE80211_CHAN_GO_CONCURRENT))
> return false;
Shouldn't this check go before the indoor one?
Luis
On Sat, Feb 22, 2014 at 12:00 PM, Peer, Ilan <[email protected]> wrote:
>> -----Original Message-----
>> From: [email protected] [mailto:[email protected]] On Behalf Of Luis R.
>> Rodriguez
>> Sent: Saturday, February 22, 2014 02:28
>> To: Peer, Ilan
>> Cc: linux-wireless
>> Subject: Re: [PATCH 4/5] cfg80211: Add an option to hint indoor operation
>>
>> On Thu, Feb 20, 2014 at 3:44 AM, Ilan Peer <[email protected]> wrote:
>> > + * Note: currently not protected by any synchronization primitive.
>>
>> You should verify this is protected by RTNL as the other stuff.
>>
>
> It is protect in all cases by RTNL ... I just did not think that it is needed. Do you a problematic scenario that requires RTNL?
It will depend on where the hints are consumed and readers, and also
resets of regulatory, so yes, its needed, just extend the
documentation as with the others to indicate its under RTNL.
Luis
Allow GO operation on a channel marked with IEEE80211_CHAN_GO_CONCURRENT
iff there is an active station interface that is associated to
an AP operating on the same channel in the 2 GHz band or the same UNII band
(in the 5 GHz band). This relaxation is not allowed if the channel is
marked with IEEE80211_CHAN_RADAR.
Note that this is a permissive approach to the FCC definitions,
that require a clear assessment that the device operating the AP is
an authorized master, i.e., with radar detection and DFS capabilities.
It is assumed that such restrictions are enforced by user space.
Furthermore, it is assumed, that if the conditions that allowed for
the operation of the GO on such a channel change, i.e., the station
interface disconnected from the AP, it is the responsibility of user
space to evacuate the GO from the channel.
Signed-off-by: Ilan Peer <[email protected]>
---
include/net/cfg80211.h | 4 ++-
include/net/regulatory.h | 6 ++++
net/mac80211/ibss.c | 9 ++++--
net/wireless/Kconfig | 24 ++++++++++++++++
net/wireless/chan.c | 69 ++++++++++++++++++++++++++++++++++++++++++++--
net/wireless/mesh.c | 3 +-
net/wireless/nl80211.c | 11 +++++---
net/wireless/reg.c | 29 +++++++++++++++++++
net/wireless/reg.h | 12 ++++++++
net/wireless/trace.h | 11 +++++---
10 files changed, 162 insertions(+), 16 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 2ba017c..e872c9c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4521,12 +4521,14 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy,
* cfg80211_reg_can_beacon - check if beaconing is allowed
* @wiphy: the wiphy
* @chandef: the channel definition
+ * @iftype: interface type
*
* Return: %true if there is no secondary channel or the secondary channel(s)
* can be used for beaconing (i.e. is not a radar channel etc.)
*/
bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
- struct cfg80211_chan_def *chandef);
+ struct cfg80211_chan_def *chandef,
+ enum nl80211_iftype iftype);
/*
* cfg80211_ch_switch_notify - update wdev channel and notify userspace
diff --git a/include/net/regulatory.h b/include/net/regulatory.h
index b07cdc9..0d96cd0 100644
--- a/include/net/regulatory.h
+++ b/include/net/regulatory.h
@@ -131,6 +131,11 @@ struct regulatory_request {
* all country IE information processed by the regulatory core. This will
* override %REGULATORY_COUNTRY_IE_FOLLOW_POWER as all country IEs will
* be ignored.
+ * @REGULATORY_ENABLE_RELAX_NO_IR: for devices that wish to allow the
+ * NO_IR relaxation, which enables transmissions on channels on which
+ * otherwise initiating radiation is not allowed. This will enable the
+ * relaxations enabled under the CFG80211_REG_RELAX_NO_IR configuration
+ * option
*/
enum ieee80211_regulatory_flags {
REGULATORY_CUSTOM_REG = BIT(0),
@@ -138,6 +143,7 @@ enum ieee80211_regulatory_flags {
REGULATORY_DISABLE_BEACON_HINTS = BIT(2),
REGULATORY_COUNTRY_IE_FOLLOW_POWER = BIT(3),
REGULATORY_COUNTRY_IE_IGNORE = BIT(4),
+ REGULATORY_ENABLE_RELAX_NO_IR = BIT(5),
};
struct ieee80211_freq_range {
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 4453e27..a3b9561 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -262,7 +262,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
/* make a copy of the chandef, it could be modified below. */
chandef = *req_chandef;
chan = chandef.chan;
- if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
+ if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef,
+ NL80211_IFTYPE_ADHOC)) {
if (chandef.width == NL80211_CHAN_WIDTH_5 ||
chandef.width == NL80211_CHAN_WIDTH_10 ||
chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
@@ -274,7 +275,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
chandef.width = NL80211_CHAN_WIDTH_20;
chandef.center_freq1 = chan->center_freq;
/* check again for downgraded chandef */
- if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
+ if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef,
+ NL80211_IFTYPE_ADHOC)) {
sdata_info(sdata,
"Failed to join IBSS, beacons forbidden\n");
return;
@@ -856,7 +858,8 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
goto disconnect;
}
- if (!cfg80211_reg_can_beacon(sdata->local->hw.wiphy, ¶ms.chandef)) {
+ if (!cfg80211_reg_can_beacon(sdata->local->hw.wiphy, ¶ms.chandef,
+ NL80211_IFTYPE_ADHOC)) {
sdata_info(sdata,
"IBSS %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
ifibss->bssid,
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 2a891bc..405f3c4 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -108,6 +108,30 @@ config CFG80211_REG_CELLULAR_HINTS
feature if you have tested and validated this feature on your
systems.
+config CFG80211_REG_RELAX_NO_IR
+ bool "cfg80211 support for NO_IR relaxation"
+ depends on CFG80211_CERTIFICATION_ONUS
+ ---help---
+ This option enables support for relaxation of the NO_IR flag for
+ situations that certain regulatory bodies have provided clarifications
+ on how relaxation can occur. This feature has an inherent dependency on
+ userspace features which must have been properly tested and as such is
+ not enabled by default.
+
+ A relaxation feature example is allowing the operation of a P2P group
+ owner (GO) on channels marked with NO_IR if there is an additional BSS
+ interface which associated to an AP which userspace assumes or confirms
+ to be an authorized master, i.e., with radar detection support and DFS
+ capabilities. However, note that in order to not create daisy chain
+ scenarios, this relaxation is not allowed in cases that the BSS client
+ is associated to P2P GO and in addition the P2P GO instantiated on
+ a channel due to this relaxation should not allow connection from
+ non P2P clients.
+
+ The regulatory core will apply these relaxations only for drivers that
+ support this feature by declaring the appropriate channel flags and
+ capabilities in their registration flow.
+
config CFG80211_DEFAULT_PS
bool "enable powersave by default"
depends on CFG80211
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index f8ab7df..1d8c990 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -605,15 +605,78 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
}
EXPORT_SYMBOL(cfg80211_chandef_usable);
+/*
+ * For GO only, check if the channel can be used under permissive conditions
+ * mandated by the some regulatory bodies, i.e., the channel is marked with
+ * IEEE80211_CHAN_GO_CONCURRENT and there is an additional station interface
+ * associated to an AP on the same channel or on the same UNII band
+ * (assuming that the AP is an authorized master).
+ */
+static bool cfg80211_go_permissive_chan(struct cfg80211_registered_device *rdev,
+ struct ieee80211_channel *chan)
+{
+ struct wireless_dev *wdev_iter;
+ struct wiphy *wiphy = wiphy_idx_to_wiphy(rdev->wiphy_idx);
+
+ ASSERT_RTNL();
+
+ if (!config_enabled(CONFIG_CFG80211_REG_RELAX_NO_IR) ||
+ !(wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR) ||
+ !(chan->flags & IEEE80211_CHAN_GO_CONCURRENT))
+ return false;
+
+ list_for_each_entry(wdev_iter, &rdev->wdev_list, list) {
+ struct ieee80211_channel *other_chan = NULL;
+ int r1, r2;
+
+ if (wdev_iter->iftype != NL80211_IFTYPE_STATION ||
+ !netif_running(wdev_iter->netdev))
+ continue;
+
+ wdev_lock(wdev_iter);
+ if (wdev_iter->current_bss)
+ other_chan = wdev_iter->current_bss->pub.channel;
+ wdev_unlock(wdev_iter);
+
+ if (!other_chan)
+ continue;
+
+ if (chan == other_chan)
+ return true;
+
+ if (chan->band != IEEE80211_BAND_5GHZ)
+ continue;
+
+ r1 = cfg80211_get_unii(chan->center_freq);
+ r2 = cfg80211_get_unii(other_chan->center_freq);
+
+ if (r1 != -EINVAL && r1 == r2)
+ return true;
+ }
+
+ return false;
+}
+
bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
- struct cfg80211_chan_def *chandef)
+ struct cfg80211_chan_def *chandef,
+ enum nl80211_iftype iftype)
{
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
bool res;
u32 prohibited_flags = IEEE80211_CHAN_DISABLED |
- IEEE80211_CHAN_NO_IR |
IEEE80211_CHAN_RADAR;
- trace_cfg80211_reg_can_beacon(wiphy, chandef);
+ trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype);
+
+ /*
+ * Under certain conditions suggested by the some regulatory bodies
+ * a GO can operate on channels marked with IEEE80211_NO_IR
+ * so set this flag only if such relaxations are not enabled and
+ * the conditions are not met.
+ */
+ if (iftype != NL80211_IFTYPE_P2P_GO ||
+ !cfg80211_go_permissive_chan(rdev, chandef->chan))
+ prohibited_flags |= IEEE80211_CHAN_NO_IR;
if (cfg80211_chandef_dfs_required(wiphy, chandef) > 0 &&
cfg80211_chandef_dfs_available(wiphy, chandef)) {
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index d42a3fc..45c2c85 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -175,7 +175,8 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
scan_width);
}
- if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef))
+ if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef,
+ NL80211_IFTYPE_MESH_POINT))
return -EINVAL;
err = cfg80211_chandef_dfs_required(wdev->wiphy, &setup->chandef);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 95a8c72..2270d9b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1933,7 +1933,7 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
result = -EBUSY;
break;
}
- if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef)) {
+ if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef, iftype)) {
result = -EINVAL;
break;
}
@@ -3259,7 +3259,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
} else if (!nl80211_get_ap_channel(rdev, ¶ms))
return -EINVAL;
- if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef))
+ if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef,
+ wdev->iftype))
return -EINVAL;
err = cfg80211_chandef_dfs_required(wdev->wiphy, ¶ms.chandef);
@@ -5914,7 +5915,8 @@ skip_beacons:
if (err)
return err;
- if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef))
+ if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef,
+ wdev->iftype))
return -EINVAL;
if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP ||
@@ -6685,7 +6687,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
if (err)
return err;
- if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef))
+ if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef,
+ NL80211_IFTYPE_ADHOC))
return -EINVAL;
switch (ibss.chandef.width) {
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 096268f..8f5b460 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -2597,6 +2597,35 @@ static void reg_timeout_work(struct work_struct *work)
rtnl_unlock();
}
+/*
+ * See http://www.fcc.gov/document/5-ghz-unlicensed-spectrum-unii, for
+ * UNII band definitions
+ */
+int cfg80211_get_unii(int freq)
+{
+ /* UNII-1 */
+ if (freq >= 5150 && freq <= 5250)
+ return 0;
+
+ /* UNII-2A */
+ if (freq > 5250 && freq <= 5350)
+ return 1;
+
+ /* UNII-2B */
+ if (freq > 5350 && freq <= 5470)
+ return 2;
+
+ /* UNII-2C */
+ if (freq > 5470 && freq <= 5725)
+ return 3;
+
+ /* UNII-3 */
+ if (freq > 5725 && freq <= 5825)
+ return 4;
+
+ return -EINVAL;
+}
+
int __init regulatory_init(void)
{
int err = 0;
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 1852461..9c11e72 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -105,4 +105,16 @@ void regulatory_hint_country_ie(struct wiphy *wiphy,
*/
void regulatory_hint_disconnect(void);
+/**
+ * cfg80211_get_unii - get the U-NII band for the frequency
+ * @freq: the frequency for which we want to get the UNII band.
+
+ * Get a value specifying the U-NII band frequency belongs to.
+ * U-NII bands are defined by the FCC in C.F.R 47 part 15.
+ *
+ * Returns -EINVAL if freq is invalid, 0 for UNII-1, 1 for UNII-2A,
+ * 2 for UNII-2B, 3 for UNII-2C and 4 for UNII-3.
+ */
+int cfg80211_get_unii(int freq);
+
#endif /* __NET_WIRELESS_REG_H */
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 5eaeed5..6293e8d 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2189,18 +2189,21 @@ TRACE_EVENT(cfg80211_cqm_rssi_notify,
);
TRACE_EVENT(cfg80211_reg_can_beacon,
- TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
- TP_ARGS(wiphy, chandef),
+ TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef,
+ enum nl80211_iftype iftype),
+ TP_ARGS(wiphy, chandef, iftype),
TP_STRUCT__entry(
WIPHY_ENTRY
CHAN_DEF_ENTRY
+ __field(enum nl80211_iftype, iftype)
),
TP_fast_assign(
WIPHY_ASSIGN;
CHAN_DEF_ASSIGN(chandef);
+ __entry->iftype = iftype;
),
- TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
- WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
+ TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", iftype=%d",
+ WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->iftype)
);
TRACE_EVENT(cfg80211_chandef_dfs_required,
--
1.7.10.4
PiBPbiBTYXQsIEZlYiAyMiwgMjAxNCBhdCAxMTo1NCBBTSwgUGVlciwgSWxhbiA8aWxhbi5wZWVy
QGludGVsLmNvbT4gd3JvdGU6DQo+ID4+ID4gIHN0YXRpYyBib29sIGNmZzgwMjExX2dvX3Blcm1p
c3NpdmVfY2hhbihzdHJ1Y3QNCj4gPj4gY2ZnODAyMTFfcmVnaXN0ZXJlZF9kZXZpY2UgKnJkZXYs
DQo+ID4+ID4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBp
ZWVlODAyMTFfY2hhbm5lbA0KPiA+PiA+ICpjaGFuKSBAQCAtNjIxLDggKzYyMywxNCBAQCBzdGF0
aWMgYm9vbA0KPiA+PiBjZmc4MDIxMV9nb19wZXJtaXNzaXZlX2NoYW4oc3RydWN0IGNmZzgwMjEx
X3JlZ2lzdGVyZWRfZGV2aWNlICpyZGV2LA0KPiA+PiA+ICAgICAgICAgQVNTRVJUX1JUTkwoKTsN
Cj4gPj4gPg0KPiA+PiA+ICAgICAgICAgaWYgKCFjb25maWdfZW5hYmxlZChDT05GSUdfQ0ZHODAy
MTFfUkVHX1JFTEFYX05PX0lSKSB8fA0KPiA+PiA+IC0gICAgICAgICAgICEod2lwaHktPnJlZ3Vs
YXRvcnlfZmxhZ3MgJg0KPiBSRUdVTEFUT1JZX0VOQUJMRV9SRUxBWF9OT19JUikNCj4gPj4gfHwN
Cj4gPj4gPiAtICAgICAgICAgICAhKGNoYW4tPmZsYWdzICYgSUVFRTgwMjExX0NIQU5fR09fQ09O
Q1VSUkVOVCkpDQo+ID4+ID4gKyAgICAgICAgICAgISh3aXBoeS0+cmVndWxhdG9yeV9mbGFncyAm
DQo+IFJFR1VMQVRPUllfRU5BQkxFX1JFTEFYX05PX0lSKSkNCj4gPj4gPiArICAgICAgICAgICAg
ICAgcmV0dXJuIGZhbHNlOw0KPiA+PiA+ICsNCj4gPj4gPiArICAgICAgIGlmIChyZWd1bGF0b3J5
X2luZG9vcl9hbGxvd2VkKCkgJiYNCj4gPj4gPiArICAgICAgICAgICAoY2hhbi0+ZmxhZ3MgJiBJ
RUVFODAyMTFfQ0hBTl9JTkRPT1JfT05MWSkpDQo+ID4+ID4gKyAgICAgICAgICAgICAgIHJldHVy
biB0cnVlOw0KPiA+PiA+ICsNCj4gPj4gPiArICAgICAgIGlmICghKGNoYW4tPmZsYWdzICYgSUVF
RTgwMjExX0NIQU5fR09fQ09OQ1VSUkVOVCkpDQo+ID4+ID4gICAgICAgICAgICAgICAgIHJldHVy
biBmYWxzZTsNCj4gPj4NCj4gPj4gU2hvdWxkbid0IHRoaXMgY2hlY2sgZ28gYmVmb3JlIHRoZSBp
bmRvb3Igb25lPw0KPiA+Pg0KPiA+DQo+ID4gSSBkbyBub3QgdGhpbmsgc28sIGFzIHRoaXMgcmVs
YXhhdGlvbnMgaXMgb3J0aG9nb25hbCB0byB0aGUgR08gY29uY3VycmVudCBvbmUuDQo+IEl0IG1l
YW5zIHRoYXQgSWYgYSBjaGFubmVsIGlzIGVuYWJsZWQgYnV0IG9ubHkgdW5kZXIgaW5kb29yIGFu
ZCBpbmRvb3INCj4gb3BlcmF0aW9uIGlzIGhpbnRlZCB0aGUgcmVsYXhhdGlvbiByZW1vdmVzIHRo
ZSBOT19JUiByZXN0cmljdGlvbiBpZiBzdWNoDQo+IGV4aXN0cyAod2l0aG91dCB0aGUgcmVsYXhh
dGlvbiBpbmRvb3Igb3BlcmF0aW9uIHdvdWxkIGJlICBhbGxvd2VkIGJ1dCBub3QNCj4gZm9yIEdP
KS4NCj4gDQo+IEFoIHllcywgdGhlIGZpcnN0IGNoZWNrIHJlbWFpbnMgYXMgdGhpcyB0aGVuIHRo
b3VnaDoNCj4gDQo+IGlmICghY29uZmlnX2VuYWJsZWQoQ09ORklHX0NGRzgwMjExX1JFR19SRUxB
WF9OT19JUikgfHwNCj4gICAgISh3aXBoeS0+cmVndWxhdG9yeV9mbGFncyAmIFJFR1VMQVRPUllf
RU5BQkxFX1JFTEFYX05PX0lSKSkNCj4gICAgICAgICAgICAgIHJldHVybiBmYWxzZTsNCj4gDQo+
IFRoYXQgc2VlbXMgd3JvbmcgZm9yIHRoZSBnZW5lcmFsIGNhc2UuDQo+IA0KDQpTb3JyeSBidXQg
SSBkbyBub3QgZm9sbG93IC4uLiB3aGF0J3MgdGhlIGJ1Zz8NCg0KVGhhbmtzLA0KDQpJbGFuLg0K
PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBtY2dyb2ZAZ21haWwuY29tIFtt
YWlsdG86bWNncm9mQGdtYWlsLmNvbV0gT24gQmVoYWxmIE9mIEx1aXMgUi4NCj4gUm9kcmlndWV6
DQo+IFNlbnQ6IFNhdHVyZGF5LCBGZWJydWFyeSAyMiwgMjAxNCAwMjoyOA0KPiBUbzogUGVlciwg
SWxhbg0KPiBDYzogbGludXgtd2lyZWxlc3MNCj4gU3ViamVjdDogUmU6IFtQQVRDSCA0LzVdIGNm
ZzgwMjExOiBBZGQgYW4gb3B0aW9uIHRvIGhpbnQgaW5kb29yIG9wZXJhdGlvbg0KPiANCj4gT24g
VGh1LCBGZWIgMjAsIDIwMTQgYXQgMzo0NCBBTSwgSWxhbiBQZWVyIDxpbGFuLnBlZXJAaW50ZWwu
Y29tPiB3cm90ZToNCj4gPiArICogTm90ZTogY3VycmVudGx5IG5vdCBwcm90ZWN0ZWQgYnkgYW55
IHN5bmNocm9uaXphdGlvbiBwcmltaXRpdmUuDQo+IA0KPiBZb3Ugc2hvdWxkIHZlcmlmeSB0aGlz
IGlzIHByb3RlY3RlZCBieSBSVE5MIGFzIHRoZSBvdGhlciBzdHVmZi4NCj4gDQoNCkl0IGlzIHBy
b3RlY3QgaW4gYWxsIGNhc2VzIGJ5IFJUTkwgLi4uIEkganVzdCBkaWQgbm90IHRoaW5rIHRoYXQg
aXQgaXMgbmVlZGVkLiBEbyB5b3UgYSBwcm9ibGVtYXRpYyBzY2VuYXJpbyB0aGF0IHJlcXVpcmVz
IFJUTkw/DQoNClRoYW5rcywNCg0KSWxhbi4NCg==
Allow GO operation on a channel marked with IEEE80211_CHAN_INDOOR_ONLY
iff there is a user hint indicating that the platform is operating in
an indoor environment, i.e., the platform is a printer or media center
device.
Signed-off-by: Ilan Peer <[email protected]>
---
net/wireless/chan.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 1d8c990..b18367d 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -611,6 +611,8 @@ EXPORT_SYMBOL(cfg80211_chandef_usable);
* IEEE80211_CHAN_GO_CONCURRENT and there is an additional station interface
* associated to an AP on the same channel or on the same UNII band
* (assuming that the AP is an authorized master).
+ * In addition allow the GO to operate on a channel on which indoor operation is
+ * allowed, iff we are currently operating in an indoor environment.
*/
static bool cfg80211_go_permissive_chan(struct cfg80211_registered_device *rdev,
struct ieee80211_channel *chan)
@@ -621,8 +623,14 @@ static bool cfg80211_go_permissive_chan(struct cfg80211_registered_device *rdev,
ASSERT_RTNL();
if (!config_enabled(CONFIG_CFG80211_REG_RELAX_NO_IR) ||
- !(wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR) ||
- !(chan->flags & IEEE80211_CHAN_GO_CONCURRENT))
+ !(wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR))
+ return false;
+
+ if (regulatory_indoor_allowed() &&
+ (chan->flags & IEEE80211_CHAN_INDOOR_ONLY))
+ return true;
+
+ if (!(chan->flags & IEEE80211_CHAN_GO_CONCURRENT))
return false;
list_for_each_entry(wdev_iter, &rdev->wdev_list, list) {
--
1.7.10.4