2013-02-13 23:48:00

by Johannes Berg

[permalink] [raw]
Subject: [PATCH v2 0/3] VHT regulatory

Now with a patch to advertise this in nl80211, so
wpa_s can stop parsing the regulatory information
(if the new capability is present.)

johannes



2013-02-13 23:48:01

by Johannes Berg

[permalink] [raw]
Subject: [PATCH v2 2/3] cfg80211: allow drivers to selectively disable 80/160 MHz

From: Johannes Berg <[email protected]>

Some drivers might support 80 or 160 MHz only on some
channels for whatever reason, so allow them to disable
these channel widths. Also maintain the new flags when
regulatory bandwidth limitations would disable these
wide channels.

Reviewed-by: Luis R. Rodriguez <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
---
include/net/cfg80211.h | 12 ++++++++++++
net/wireless/chan.c | 13 ++++++++++++-
net/wireless/reg.c | 8 ++++++++
3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 767599c..80cf5af 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -100,6 +100,16 @@ enum ieee80211_band {
* @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel
* is not permitted.
* @IEEE80211_CHAN_NO_OFDM: OFDM is not allowed on this channel.
+ * @IEEE80211_CHAN_NO_80MHZ: If the driver supports 80 MHz on the band,
+ * this flag indicates that an 80 MHz channel cannot use this
+ * 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_NO_160MHZ: If the driver supports 160 MHz on the band,
+ * this flag indicates that an 160 MHz channel cannot use this
+ * channel as the control or any of the secondary channels.
+ * This may be due to the driver or due to regulatory bandwidth
+ * restrictions.
*/
enum ieee80211_channel_flags {
IEEE80211_CHAN_DISABLED = 1<<0,
@@ -109,6 +119,8 @@ enum ieee80211_channel_flags {
IEEE80211_CHAN_NO_HT40PLUS = 1<<4,
IEEE80211_CHAN_NO_HT40MINUS = 1<<5,
IEEE80211_CHAN_NO_OFDM = 1<<6,
+ IEEE80211_CHAN_NO_80MHZ = 1<<7,
+ IEEE80211_CHAN_NO_160MHZ = 1<<8,
};

#define IEEE80211_CHAN_NO_HT40 \
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 810c23c..fd556ac 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -375,6 +375,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
case NL80211_CHAN_WIDTH_80:
if (!vht_cap->vht_supported)
return false;
+ prohibited_flags |= IEEE80211_CHAN_NO_80MHZ;
width = 80;
break;
case NL80211_CHAN_WIDTH_160:
@@ -382,6 +383,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
return false;
if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ))
return false;
+ prohibited_flags |= IEEE80211_CHAN_NO_160MHZ;
width = 160;
break;
default:
@@ -389,7 +391,16 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
return false;
}

- /* TODO: missing regulatory check on 80/160 bandwidth */
+ /*
+ * TODO: What if there are only certain 80/160/80+80 MHz channels
+ * allowed by the driver, or only certain combinations?
+ * For 40 MHz the driver can set the NO_HT40 flags, but for
+ * 80/160 MHz and in particular 80+80 MHz this isn't really
+ * feasible and we only have NO_80MHZ/NO_160MHZ so far but
+ * no way to cover 80+80 MHz or more complex restrictions.
+ * Note that such restrictions also need to be advertised to
+ * userspace, for example for P2P channel selection.
+ */

if (width > 20)
prohibited_flags |= IEEE80211_CHAN_NO_OFDM;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index bf35e1f..dee9ab4 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -866,6 +866,10 @@ static void handle_channel(struct wiphy *wiphy,

if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
bw_flags = IEEE80211_CHAN_NO_HT40;
+ if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80))
+ bw_flags |= IEEE80211_CHAN_NO_80MHZ;
+ if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160))
+ bw_flags |= IEEE80211_CHAN_NO_160MHZ;

if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
request_wiphy && request_wiphy == wiphy &&
@@ -1264,6 +1268,10 @@ static void handle_channel_custom(struct wiphy *wiphy,

if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
bw_flags = IEEE80211_CHAN_NO_HT40;
+ if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80))
+ bw_flags |= IEEE80211_CHAN_NO_80MHZ;
+ if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160))
+ bw_flags |= IEEE80211_CHAN_NO_160MHZ;

chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
--
1.8.0


2013-02-14 17:52:46

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 1/3] regulatory: allow VHT channels in world roaming

On Thu, 2013-02-14 at 00:47 +0100, Johannes Berg wrote:
> From: Johannes Berg <[email protected]>
>
> For VHT, the wider bandwidths (up to 160 MHz) need
> to be allowed. Since world roaming only covers the
> case of connecting to an AP, it can be opened up
> there, we will rely on the AP to know the local
> regulations.

Since I don't particularly care about the regulatory stuff right now (we
have custom world roaming) I'm just going to drop this until somebody
else figures out VHT ...

johannes


2013-02-13 23:48:00

by Johannes Berg

[permalink] [raw]
Subject: [PATCH v2 1/3] regulatory: allow VHT channels in world roaming

From: Johannes Berg <[email protected]>

For VHT, the wider bandwidths (up to 160 MHz) need
to be allowed. Since world roaming only covers the
case of connecting to an AP, it can be opened up
there, we will rely on the AP to know the local
regulations.

Signed-off-by: Johannes Berg <[email protected]>
---
net/wireless/reg.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index e97d5b0..bf35e1f 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -184,14 +184,14 @@ static const struct ieee80211_regdomain world_regdom = {
NL80211_RRF_NO_IBSS |
NL80211_RRF_NO_OFDM),
/* IEEE 802.11a, channel 36..48 */
- REG_RULE(5180-10, 5240+10, 40, 6, 20,
+ REG_RULE(5180-10, 5240+10, 80, 6, 20,
NL80211_RRF_PASSIVE_SCAN |
NL80211_RRF_NO_IBSS),

- /* NB: 5260 MHz - 5700 MHz requies DFS */
+ /* NB: 5260 MHz - 5700 MHz requires DFS */

/* IEEE 802.11a, channel 149..165 */
- REG_RULE(5745-10, 5825+10, 40, 6, 20,
+ REG_RULE(5745-10, 5825+10, 80, 6, 20,
NL80211_RRF_PASSIVE_SCAN |
NL80211_RRF_NO_IBSS),

--
1.8.0


2013-02-13 23:48:02

by Johannes Berg

[permalink] [raw]
Subject: [PATCH v2 3/3] nl80211: advertise HT/VHT channel limitations

From: Johannes Berg <[email protected]>

When drivers or regulatory have limitations on
40, 80 or 160 MHz channels, advertise these to
userspace via nl80211. Also add a new feature
flag to let userspace know this is supported.

Signed-off-by: Johannes Berg <[email protected]>
---
include/uapi/linux/nl80211.h | 17 +++++++++++++++++
net/wireless/core.c | 3 ++-
net/wireless/nl80211.c | 12 ++++++++++++
3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 90b7af8..3880f6a 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2041,6 +2041,16 @@ enum nl80211_band_attr {
* (enum nl80211_dfs_state)
* @NL80211_FREQUENCY_ATTR_DFS_TIME: time in miliseconds for how long
* this channel is in this DFS state.
+ * @NL80211_FREQUENCY_ATTR_NO_HT40_MINUS: HT40- isn't possible with this
+ * channel as the control channel
+ * @NL80211_FREQUENCY_ATTR_NO_HT40_PLUS: HT40+ isn't possible with this
+ * channel as the control channel
+ * @NL80211_FREQUENCY_ATTR_NO_80MHZ: any 80 MHz channel using this channel
+ * as the primary or any of the secondary channels isn't possible,
+ * this includes 80+80 channels
+ * @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_MAX: highest frequency attribute number
* currently defined
* @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
@@ -2055,6 +2065,10 @@ enum nl80211_frequency_attr {
NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
NL80211_FREQUENCY_ATTR_DFS_STATE,
NL80211_FREQUENCY_ATTR_DFS_TIME,
+ NL80211_FREQUENCY_ATTR_NO_HT40_MINUS,
+ NL80211_FREQUENCY_ATTR_NO_HT40_PLUS,
+ NL80211_FREQUENCY_ATTR_NO_80MHZ,
+ NL80211_FREQUENCY_ATTR_NO_160MHZ,

/* keep last */
__NL80211_FREQUENCY_ATTR_AFTER_LAST,
@@ -3421,6 +3435,8 @@ enum nl80211_ap_sme_features {
* Note that even for drivers that support this, the default is to add
* stations in authenticated/associated state, so to add unauthenticated
* stations the authenticated/associated bits have to be set in the mask.
+ * @NL80211_FEATURE_ADVERTISE_CHAN_LIMITS: cfg80211 advertises channel limits
+ * (HT40, VHT 80/160 MHz) if this flag is set
*/
enum nl80211_feature_flags {
NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
@@ -3437,6 +3453,7 @@ enum nl80211_feature_flags {
NL80211_FEATURE_P2P_GO_CTWIN = 1 << 11,
NL80211_FEATURE_P2P_GO_OPPPS = 1 << 12,
NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 13,
+ NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 1 << 14,
};

/**
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 9220021..33b75b9 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -367,7 +367,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
rdev->wiphy.rts_threshold = (u32) -1;
rdev->wiphy.coverage_class = 0;

- rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH;
+ rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH |
+ NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;

return &rdev->wiphy;
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c1e18cc..7e40b9e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -562,6 +562,18 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, time))
goto nla_put_failure;
}
+ if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) &&
+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS))
+ goto nla_put_failure;
+ if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) &&
+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS))
+ goto nla_put_failure;
+ if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) &&
+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ))
+ goto nla_put_failure;
+ if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) &&
+ nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ))
+ goto nla_put_failure;

if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
DBM_TO_MBM(chan->max_power)))
--
1.8.0