* [PATCH v3 1/3] mac80211: Support forcing station to disable HT (802.11n).
@ 2011-11-03 5:55 greearb
2011-11-03 5:55 ` [PATCH v3 2/3] mac80211: Support disabling ht40 greearb
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: greearb @ 2011-11-03 5:55 UTC (permalink / raw)
To: linux-wireless; +Cc: Ben Greear
From: Ben Greear <greearb@candelatech.com>
This allows a user to configure a wifi station interface
to disable the HT features, even if the AP and NIC supports it.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 8049bf7... 499a5a4... M include/linux/nl80211.h
:100644 100644 92cf1c2... d2168c0... M include/net/cfg80211.h
:100644 100644 57fb58f... d4092e8... M net/mac80211/mlme.c
:100644 100644 b9ec306... 72e19e4... M net/wireless/core.h
:100644 100644 21fc970... 5c41411... M net/wireless/mlme.c
:100644 100644 48260c2... 3c4dab1... M net/wireless/nl80211.c
:100644 100644 6e86d5a... 449a19f... M net/wireless/sme.c
include/linux/nl80211.h | 4 ++++
include/net/cfg80211.h | 6 ++++++
net/mac80211/mlme.c | 3 +++
net/wireless/core.h | 6 ++++--
net/wireless/mlme.c | 10 +++++++---
net/wireless/nl80211.c | 10 +++++++++-
net/wireless/sme.c | 3 ++-
7 files changed, 35 insertions(+), 7 deletions(-)
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 8049bf7..499a5a4 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1109,6 +1109,9 @@ enum nl80211_commands {
* %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
* used for asking the driver to perform a TDLS operation.
*
+ * @NL80211_ATTR_DISABLE_HT: Force HT capable interfaces to disable
+ * this feature.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1337,6 +1340,7 @@ enum nl80211_attrs {
NL80211_ATTR_TDLS_SUPPORT,
NL80211_ATTR_TDLS_EXTERNAL_SETUP,
+ NL80211_ATTR_DISABLE_HT,
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 92cf1c2..d2168c0 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1035,6 +1035,8 @@ struct cfg80211_auth_request {
bool local_state_change;
};
+#define ASSOC_REQ_DISABLE_HT (1<<0) /* Disable HT (802.11n) */
+
/**
* struct cfg80211_assoc_request - (Re)Association request data
*
@@ -1046,6 +1048,7 @@ struct cfg80211_auth_request {
* @use_mfp: Use management frame protection (IEEE 802.11w) in this association
* @crypto: crypto settings
* @prev_bssid: previous BSSID, if not %NULL use reassociate frame
+ * @flags: See ASSOC_REQ_* flags above.
*/
struct cfg80211_assoc_request {
struct cfg80211_bss *bss;
@@ -1053,6 +1056,7 @@ struct cfg80211_assoc_request {
size_t ie_len;
struct cfg80211_crypto_settings crypto;
bool use_mfp;
+ u32 flags;
};
/**
@@ -1147,6 +1151,7 @@ struct cfg80211_ibss_params {
* @ie: IEs for association request
* @ie_len: Length of assoc_ie in octets
* @privacy: indicates whether privacy-enabled APs should be used
+ * @flags: See ASSOC_REQ_* #defines above.
* @crypto: crypto settings
* @key_len: length of WEP key for shared key authentication
* @key_idx: index of WEP key for shared key authentication
@@ -1164,6 +1169,7 @@ struct cfg80211_connect_params {
struct cfg80211_crypto_settings crypto;
const u8 *key;
u8 key_len, key_idx;
+ u32 flags;
};
/**
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 57fb58f..d4092e8 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2611,6 +2611,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
+ if (req->flags & ASSOC_REQ_DISABLE_HT)
+ ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
+
if (req->ie && req->ie_len) {
memcpy(wk->ie, req->ie, req->ie_len);
wk->ie_len = req->ie_len;
diff --git a/net/wireless/core.h b/net/wireless/core.h
index b9ec306..72e19e4 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -339,13 +339,15 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
const u8 *bssid, const u8 *prev_bssid,
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len, bool use_mfp,
- struct cfg80211_crypto_settings *crypt);
+ struct cfg80211_crypto_settings *crypt,
+ u32 assoc_flags);
int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct ieee80211_channel *chan,
const u8 *bssid, const u8 *prev_bssid,
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len, bool use_mfp,
- struct cfg80211_crypto_settings *crypt);
+ struct cfg80211_crypto_settings *crypt,
+ u32 assoc_flags);
int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
struct net_device *dev, const u8 *bssid,
const u8 *ie, int ie_len, u16 reason,
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 21fc970..5c41411 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -507,7 +507,8 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
const u8 *bssid, const u8 *prev_bssid,
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len, bool use_mfp,
- struct cfg80211_crypto_settings *crypt)
+ struct cfg80211_crypto_settings *crypt,
+ u32 assoc_flags)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_assoc_request req;
@@ -537,6 +538,7 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
memcpy(&req.crypto, crypt, sizeof(req.crypto));
req.use_mfp = use_mfp;
req.prev_bssid = prev_bssid;
+ req.flags = assoc_flags;
req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
if (!req.bss) {
@@ -574,14 +576,16 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
const u8 *bssid, const u8 *prev_bssid,
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len, bool use_mfp,
- struct cfg80211_crypto_settings *crypt)
+ struct cfg80211_crypto_settings *crypt,
+ u32 assoc_flags)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
wdev_lock(wdev);
err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
- ssid, ssid_len, ie, ie_len, use_mfp, crypt);
+ ssid, ssid_len, ie, ie_len, use_mfp, crypt,
+ assoc_flags);
wdev_unlock(wdev);
return err;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 48260c2..3c4dab1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -197,6 +197,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
[NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
[NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
+ [NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
};
/* policy for the key attributes */
@@ -4354,6 +4355,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
int err, ssid_len, ie_len = 0;
bool use_mfp = false;
+ u32 flags = 0;
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
return -EINVAL;
@@ -4397,11 +4399,14 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_PREV_BSSID])
prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
+ if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
+ flags |= ASSOC_REQ_DISABLE_HT;
+
err = nl80211_crypto_settings(rdev, info, &crypto, 1);
if (!err)
err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
ssid, ssid_len, ie, ie_len, use_mfp,
- &crypto);
+ &crypto, flags);
return err;
}
@@ -4891,6 +4896,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
return PTR_ERR(connkeys);
}
+ if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
+ connect.flags |= ASSOC_REQ_DISABLE_HT;
+
err = cfg80211_connect(rdev, dev, &connect, connkeys);
if (err)
kfree(connkeys);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 6e86d5a..449a19f 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -189,7 +189,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
prev_bssid,
params->ssid, params->ssid_len,
params->ie, params->ie_len,
- false, ¶ms->crypto);
+ false, ¶ms->crypto,
+ params->flags);
if (err)
__cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
NULL, 0,
--
1.7.3.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 2/3] mac80211: Support disabling ht40.
2011-11-03 5:55 [PATCH v3 1/3] mac80211: Support forcing station to disable HT (802.11n) greearb
@ 2011-11-03 5:55 ` greearb
2011-11-03 5:55 ` [PATCH v3 3/3] mac80211: Allow overriding some HT information greearb
2011-11-03 8:37 ` [PATCH v3 1/3] mac80211: Support forcing station to disable HT (802.11n) Johannes Berg
2 siblings, 0 replies; 13+ messages in thread
From: greearb @ 2011-11-03 5:55 UTC (permalink / raw)
To: linux-wireless; +Cc: Ben Greear
From: Ben Greear <greearb@candelatech.com>
Allows users to forceably disable HT40 support in station
interfaces.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 499a5a4... 61b45aa... M include/linux/nl80211.h
:100644 100644 d2168c0... eeeef41... M include/net/cfg80211.h
:100644 100644 ea10a51... e4cfeda... M net/mac80211/ieee80211_i.h
:100644 100644 d4092e8... 149fb1d... M net/mac80211/mlme.c
:100644 100644 3c4dab1... 7924e28... M net/wireless/nl80211.c
include/linux/nl80211.h | 4 ++++
include/net/cfg80211.h | 1 +
net/mac80211/ieee80211_i.h | 1 +
net/mac80211/mlme.c | 5 +++++
net/wireless/nl80211.c | 7 +++++++
5 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 499a5a4..61b45aa 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1111,6 +1111,8 @@ enum nl80211_commands {
*
* @NL80211_ATTR_DISABLE_HT: Force HT capable interfaces to disable
* this feature.
+ * @NL80211_ATTR_DISABLE_HT40: Disable HT-40 even if AP and hardware
+ * support it.
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -1341,6 +1343,8 @@ enum nl80211_attrs {
NL80211_ATTR_TDLS_EXTERNAL_SETUP,
NL80211_ATTR_DISABLE_HT,
+ NL80211_ATTR_DISABLE_HT40,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d2168c0..eeeef41 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1036,6 +1036,7 @@ struct cfg80211_auth_request {
};
#define ASSOC_REQ_DISABLE_HT (1<<0) /* Disable HT (802.11n) */
+#define ASSOC_REQ_DISABLE_HT40 (1<<1) /* Disable HT40 (802.11n) */
/**
* struct cfg80211_assoc_request - (Re)Association request data
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ea10a51..e4cfeda 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -364,6 +364,7 @@ enum ieee80211_sta_flags {
IEEE80211_STA_UAPSD_ENABLED = BIT(7),
IEEE80211_STA_NULLFUNC_ACKED = BIT(8),
IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9),
+ IEEE80211_STA_DISABLE_HT40 = BIT(10),
};
struct ieee80211_if_managed {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index d4092e8..149fb1d 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -207,6 +207,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
channel_type = NL80211_CHAN_HT20;
if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
+ !(sdata->u.mgd.flags & IEEE80211_STA_DISABLE_HT40) &&
(sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
(hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
@@ -2601,6 +2602,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N;
ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
+ ifmgd->flags &= ~IEEE80211_STA_DISABLE_HT40;
ifmgd->beacon_crc_valid = false;
@@ -2614,6 +2616,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
if (req->flags & ASSOC_REQ_DISABLE_HT)
ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
+ if (req->flags & ASSOC_REQ_DISABLE_HT40)
+ ifmgd->flags |= IEEE80211_STA_DISABLE_HT40;
+
if (req->ie && req->ie_len) {
memcpy(wk->ie, req->ie, req->ie_len);
wk->ie_len = req->ie_len;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 3c4dab1..7924e28 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -198,6 +198,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
[NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
[NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
+ [NL80211_ATTR_DISABLE_HT40] = { .type = NLA_FLAG },
};
/* policy for the key attributes */
@@ -4402,6 +4403,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
flags |= ASSOC_REQ_DISABLE_HT;
+ if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT40]))
+ flags |= ASSOC_REQ_DISABLE_HT40;
+
err = nl80211_crypto_settings(rdev, info, &crypto, 1);
if (!err)
err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
@@ -4899,6 +4903,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
connect.flags |= ASSOC_REQ_DISABLE_HT;
+ if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT40]))
+ connect.flags |= ASSOC_REQ_DISABLE_HT40;
+
err = cfg80211_connect(rdev, dev, &connect, connkeys);
if (err)
kfree(connkeys);
--
1.7.3.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 3/3] mac80211: Allow overriding some HT information.
2011-11-03 5:55 [PATCH v3 1/3] mac80211: Support forcing station to disable HT (802.11n) greearb
2011-11-03 5:55 ` [PATCH v3 2/3] mac80211: Support disabling ht40 greearb
@ 2011-11-03 5:55 ` greearb
2011-11-03 8:47 ` Johannes Berg
2011-11-03 8:37 ` [PATCH v3 1/3] mac80211: Support forcing station to disable HT (802.11n) Johannes Berg
2 siblings, 1 reply; 13+ messages in thread
From: greearb @ 2011-11-03 5:55 UTC (permalink / raw)
To: linux-wireless; +Cc: Ben Greear
From: Ben Greear <greearb@candelatech.com>
* Allow configuring the MCS (/n) rates available.
* Allow configuration of MAX-A-MSDU
* Allow configuration of A-MPDU factor & density.
Users can only remove existing rates. The MPDU factor
can only be decreased. The MPDU density can be set to
any value, but at least ath9k will not honor settings below
1us. The MAX-AMSDU can only be disabled.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 48363c3... 25ea406... M include/linux/ieee80211.h
:100644 100644 61b45aa... 9e9ed9d... M include/linux/nl80211.h
:100644 100644 eeeef41... da5a7f9... M include/net/cfg80211.h
:100644 100644 a9ded52... 7f4389e... M net/mac80211/cfg.c
:100644 100644 f80a35c... 39c10a1... M net/mac80211/ht.c
:100644 100644 e4cfeda... aa61189... M net/mac80211/ieee80211_i.h
:100644 100644 149fb1d... dc2e124... M net/mac80211/mlme.c
:100644 100644 6c53b6d... 3f318df... M net/mac80211/work.c
:100644 100644 72e19e4... dd6feda... M net/wireless/core.h
:100644 100644 5c41411... a37e4bc... M net/wireless/mlme.c
:100644 100644 7924e28... 1c544db... M net/wireless/nl80211.c
:100644 100644 449a19f... d144e2d... M net/wireless/sme.c
include/linux/ieee80211.h | 6 ++++
include/linux/nl80211.h | 3 ++
include/net/cfg80211.h | 12 +++++++
net/mac80211/cfg.c | 2 +-
net/mac80211/ht.c | 70 +++++++++++++++++++++++++++++++++++++++++++-
net/mac80211/ieee80211_i.h | 9 +++++-
net/mac80211/mlme.c | 8 ++++-
net/mac80211/work.c | 35 +++++++++++++++------
net/wireless/core.h | 6 ++-
net/wireless/mlme.c | 13 ++++++--
net/wireless/nl80211.c | 32 +++++++++++++++++++-
net/wireless/sme.c | 3 +-
12 files changed, 177 insertions(+), 22 deletions(-)
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 48363c3..25ea406 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -906,6 +906,12 @@ struct ieee80211_mcs_info {
#define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2
#define IEEE80211_HT_MCS_TX_MAX_STREAMS 4
#define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10
+/*
+ * Stations supporting 802.11n are required to support
+ * at least the first 8 MCS rates. See section 7.3.2.56.4
+ * and 20.1.1 of the 802.11n spec.
+ */
+#define IEEE80211_HT_MCS_REQ_RATES_STA 8
/*
* 802.11n D5.0 20.3.5 / 20.6 says:
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 61b45aa..9e9ed9d 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1113,6 +1113,8 @@ enum nl80211_commands {
* this feature.
* @NL80211_ATTR_DISABLE_HT40: Disable HT-40 even if AP and hardware
* support it.
+ * @NL80211_ATTR_HT_CAPABILITY_MASK: Specify which bits of the HT_CAPs
+ * to pay attention to.
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -1344,6 +1346,7 @@ enum nl80211_attrs {
NL80211_ATTR_DISABLE_HT,
NL80211_ATTR_DISABLE_HT40,
+ NL80211_ATTR_HT_CAPABILITY_MASK,
/* add attributes here, update the policy in nl80211.c */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index eeeef41..da5a7f9 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1050,6 +1050,10 @@ struct cfg80211_auth_request {
* @crypto: crypto settings
* @prev_bssid: previous BSSID, if not %NULL use reassociate frame
* @flags: See ASSOC_REQ_* flags above.
+ * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask
+ * will be used in ht_capa. Only the MCS rates, MPDU and MSDU
+ * are currently supported.
+ * @ht_capa_mask: The bits of ht_capa which are to be used.
*/
struct cfg80211_assoc_request {
struct cfg80211_bss *bss;
@@ -1058,6 +1062,8 @@ struct cfg80211_assoc_request {
struct cfg80211_crypto_settings crypto;
bool use_mfp;
u32 flags;
+ struct ieee80211_ht_cap ht_capa;
+ struct ieee80211_ht_cap ht_capa_mask;
};
/**
@@ -1157,6 +1163,10 @@ struct cfg80211_ibss_params {
* @key_len: length of WEP key for shared key authentication
* @key_idx: index of WEP key for shared key authentication
* @key: WEP key for shared key authentication
+ * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask
+ * will be used in ht_capa. Only the MCS rates, MPDU and MSDU
+ * are currently supported.
+ * @ht_capa_mask: The bits of ht_capa which are to be used.
*/
struct cfg80211_connect_params {
struct ieee80211_channel *channel;
@@ -1171,6 +1181,8 @@ struct cfg80211_connect_params {
const u8 *key;
u8 key_len, key_idx;
u32 flags;
+ struct ieee80211_ht_cap ht_capa;
+ struct ieee80211_ht_cap ht_capa_mask;
};
/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a9ded52..7f4389e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -778,7 +778,7 @@ static void sta_apply_parameters(struct ieee80211_local *local,
}
if (params->ht_capa)
- ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
+ ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
params->ht_capa,
&sta->sta.ht_cap);
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index f80a35c..39c10a1 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -18,7 +18,69 @@
#include "ieee80211_i.h"
#include "rate.h"
-void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
+void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta_ht_cap *ht_cap,
+ int min_rates)
+{
+ u8 *scaps = (u8 *)(&sdata->u.mgd.ht_capa.mcs.rx_mask);
+ u8 *smask = (u8 *)(&sdata->u.mgd.ht_capa_mask.mcs.rx_mask);
+ int i;
+
+ /* check for HT over-rides, MCS rates first. */
+ for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
+ int q;
+ for (q = 0; q < 8; q++) {
+ /*
+ * We always need to advert at least MCS0-7, to
+ * be a compliant HT station, for instance
+ */
+ if (((i * 8 + q) >= min_rates) &&
+ (smask[i] & (1<<q))) {
+ if (!(scaps[i] & (1<<q))) {
+ /*
+ * Can only disable rates, not force
+ * new ones
+ */
+ ht_cap->mcs.rx_mask[i] &= ~(1<<q);
+ }
+ }
+ }
+ }
+
+ /* Force removal of HT-40 capabilities? */
+ if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_HT40) {
+ ht_cap->cap &= ~(IEEE80211_HT_CAP_SUP_WIDTH_20_40
+ | IEEE80211_HT_CAP_SGI_40);
+ }
+
+ /* Allow user to disable the max-AMSDU bit. */
+ if (sdata->u.mgd.ht_capa_mask.cap_info & IEEE80211_HT_CAP_MAX_AMSDU) {
+ if (!(sdata->u.mgd.ht_capa.cap_info
+ & IEEE80211_HT_CAP_MAX_AMSDU))
+ ht_cap->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU;
+ }
+
+ /* Allow user to decrease AMPDU factor */
+ if (sdata->u.mgd.ht_capa_mask.ampdu_params_info &
+ IEEE80211_HT_AMPDU_PARM_FACTOR) {
+ u16 n = sdata->u.mgd.ht_capa.ampdu_params_info
+ & IEEE80211_HT_AMPDU_PARM_FACTOR;
+ if (n < ht_cap->ampdu_factor)
+ ht_cap->ampdu_factor = n;
+ }
+
+ /* Set the AMPDU density. */
+ if (sdata->u.mgd.ht_capa_mask.ampdu_params_info &
+ IEEE80211_HT_AMPDU_PARM_DENSITY)
+ ht_cap->ampdu_density =
+ (sdata->u.mgd.ht_capa.ampdu_params_info &
+ IEEE80211_HT_AMPDU_PARM_DENSITY)
+ >> IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT;
+}
+
+
+void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_supported_band *sband,
struct ieee80211_ht_cap *ht_cap_ie,
struct ieee80211_sta_ht_cap *ht_cap)
{
@@ -102,6 +164,12 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
/* handle MCS rate 32 too */
if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1)
ht_cap->mcs.rx_mask[32/8] |= 1;
+
+ /*
+ * If user has specified capability over-rides, take care
+ * of that here.
+ */
+ ieee80211_apply_htcap_overrides(sdata, ht_cap, 0);
}
void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e4cfeda..aa61189 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -444,6 +444,9 @@ struct ieee80211_if_managed {
*/
int rssi_min_thold, rssi_max_thold;
int last_ave_beacon_signal;
+ struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */
+ struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */
+
};
struct ieee80211_if_ibss {
@@ -1180,7 +1183,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
struct net_device *dev);
/* HT */
-void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
+void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta_ht_cap *ht_cap,
+ int min_rates);
+void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_supported_band *sband,
struct ieee80211_ht_cap *ht_cap_ie,
struct ieee80211_sta_ht_cap *ht_cap);
void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 149fb1d..dc2e124 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1585,7 +1585,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
- ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
+ ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
elems.ht_cap_elem, &sta->sta.ht_cap);
ap_ht_cap_flags = sta->sta.ht_cap.cap;
@@ -1954,7 +1954,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
- ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
+ ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
elems.ht_cap_elem, &sta->sta.ht_cap);
ap_ht_cap_flags = sta->sta.ht_cap.cap;
@@ -2619,6 +2619,10 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
if (req->flags & ASSOC_REQ_DISABLE_HT40)
ifmgd->flags |= IEEE80211_STA_DISABLE_HT40;
+ memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa));
+ memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask,
+ sizeof(ifmgd->ht_capa_mask));
+
if (req->ie && req->ie_len) {
memcpy(wk->ie, req->ie, req->ie_len);
wk->ie_len = req->ie_len;
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index 6c53b6d..3f318df 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -94,7 +94,8 @@ static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
/* frame sending functions */
-static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
+static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, const u8 *ht_info_ie,
struct ieee80211_supported_band *sband,
struct ieee80211_channel *channel,
enum ieee80211_smps_mode smps)
@@ -102,11 +103,11 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
struct ieee80211_ht_info *ht_info;
u8 *pos;
u32 flags = channel->flags;
- u16 cap = sband->ht_cap.cap;
+ u16 cap;
__le16 tmp;
+ struct ieee80211_sta_ht_cap ht_cap;
- if (!sband->ht_cap.ht_supported)
- return;
+ BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap));
if (!ht_info_ie)
return;
@@ -114,6 +115,20 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info))
return;
+ memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
+ /*
+ * This is for an association attempt, and stations must
+ * support at least the first 8 MCS rates. See section 20.1.1
+ * of the 802.11n spec for details.
+ */
+ ieee80211_apply_htcap_overrides(sdata, &ht_cap,
+ IEEE80211_HT_MCS_REQ_RATES_STA);
+
+ cap = ht_cap.cap;
+
+ if (!ht_cap.ht_supported)
+ return;
+
ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2);
/* determine capability flags */
@@ -166,13 +181,13 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
pos += sizeof(u16);
/* AMPDU parameters */
- *pos++ = sband->ht_cap.ampdu_factor |
- (sband->ht_cap.ampdu_density <<
- IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
+ *pos++ = ht_cap.ampdu_factor |
+ (ht_cap.ampdu_density <<
+ IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
/* MCS set */
- memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
- pos += sizeof(sband->ht_cap.mcs);
+ memcpy(pos, &ht_cap.mcs, sizeof(ht_cap.mcs));
+ pos += sizeof(ht_cap.mcs);
/* extended capabilities */
pos += sizeof(__le16);
@@ -356,7 +371,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
if (wk->assoc.use_11n && wk->assoc.wmm_used &&
local->hw.queues >= 4)
- ieee80211_add_ht_ie(skb, wk->assoc.ht_information_ie,
+ ieee80211_add_ht_ie(sdata, skb, wk->assoc.ht_information_ie,
sband, wk->chan, wk->assoc.smps);
/* if present, add any custom non-vendor IEs that go after HT */
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 72e19e4..dd6feda 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -340,14 +340,16 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len, bool use_mfp,
struct cfg80211_crypto_settings *crypt,
- u32 assoc_flags);
+ u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
+ struct ieee80211_ht_cap *ht_capa_mask);
int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct ieee80211_channel *chan,
const u8 *bssid, const u8 *prev_bssid,
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len, bool use_mfp,
struct cfg80211_crypto_settings *crypt,
- u32 assoc_flags);
+ u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
+ struct ieee80211_ht_cap *ht_capa_mask);
int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
struct net_device *dev, const u8 *bssid,
const u8 *ie, int ie_len, u16 reason,
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 5c41411..a37e4bc 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -508,7 +508,8 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len, bool use_mfp,
struct cfg80211_crypto_settings *crypt,
- u32 assoc_flags)
+ u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
+ struct ieee80211_ht_cap *ht_capa_mask)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_assoc_request req;
@@ -539,6 +540,11 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
req.use_mfp = use_mfp;
req.prev_bssid = prev_bssid;
req.flags = assoc_flags;
+ if (ht_capa)
+ memcpy(&req.ht_capa, ht_capa, sizeof(req.ht_capa));
+ if (ht_capa_mask)
+ memcpy(&req.ht_capa_mask, ht_capa_mask,
+ sizeof(req.ht_capa_mask));
req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
if (!req.bss) {
@@ -577,7 +583,8 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len, bool use_mfp,
struct cfg80211_crypto_settings *crypt,
- u32 assoc_flags)
+ u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
+ struct ieee80211_ht_cap *ht_capa_mask)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
@@ -585,7 +592,7 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
wdev_lock(wdev);
err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
ssid, ssid_len, ie, ie_len, use_mfp, crypt,
- assoc_flags);
+ assoc_flags, ht_capa, ht_capa_mask);
wdev_unlock(wdev);
return err;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 7924e28..1c544db 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -199,6 +199,10 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
[NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
[NL80211_ATTR_DISABLE_HT40] = { .type = NLA_FLAG },
+ [NL80211_ATTR_HT_CAPABILITY_MASK] = {
+ .type = NLA_BINARY,
+ .len = NL80211_HT_CAPABILITY_LEN
+ },
};
/* policy for the key attributes */
@@ -4357,6 +4361,8 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
int err, ssid_len, ie_len = 0;
bool use_mfp = false;
u32 flags = 0;
+ struct ieee80211_ht_cap *ht_capa = NULL;
+ struct ieee80211_ht_cap *ht_capa_mask = NULL;
if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
return -EINVAL;
@@ -4406,11 +4412,22 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT40]))
flags |= ASSOC_REQ_DISABLE_HT40;
+ if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
+ ht_capa_mask =
+ nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]);
+
+ if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
+ if (!ht_capa_mask)
+ return -EINVAL;
+ ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
+ }
+
err = nl80211_crypto_settings(rdev, info, &crypto, 1);
if (!err)
err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
ssid, ssid_len, ie, ie_len, use_mfp,
- &crypto, flags);
+ &crypto, flags, ht_capa,
+ ht_capa_mask);
return err;
}
@@ -4906,6 +4923,19 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT40]))
connect.flags |= ASSOC_REQ_DISABLE_HT40;
+ if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
+ memcpy(&connect.ht_capa_mask,
+ nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
+ sizeof(connect.ht_capa_mask));
+
+ if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
+ if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
+ return -EINVAL;
+ memcpy(&connect.ht_capa,
+ nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
+ sizeof(connect.ht_capa));
+ }
+
err = cfg80211_connect(rdev, dev, &connect, connkeys);
if (err)
kfree(connkeys);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 449a19f..d144e2d 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -190,7 +190,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
params->ssid, params->ssid_len,
params->ie, params->ie_len,
false, ¶ms->crypto,
- params->flags);
+ params->flags, ¶ms->ht_capa,
+ ¶ms->ht_capa_mask);
if (err)
__cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
NULL, 0,
--
1.7.3.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v3 1/3] mac80211: Support forcing station to disable HT (802.11n).
2011-11-03 5:55 [PATCH v3 1/3] mac80211: Support forcing station to disable HT (802.11n) greearb
2011-11-03 5:55 ` [PATCH v3 2/3] mac80211: Support disabling ht40 greearb
2011-11-03 5:55 ` [PATCH v3 3/3] mac80211: Allow overriding some HT information greearb
@ 2011-11-03 8:37 ` Johannes Berg
2011-11-03 17:18 ` Ben Greear
2 siblings, 1 reply; 13+ messages in thread
From: Johannes Berg @ 2011-11-03 8:37 UTC (permalink / raw)
To: greearb; +Cc: linux-wireless
On Wed, 2011-11-02 at 22:55 -0700, greearb@candelatech.com wrote:
> From: Ben Greear <greearb@candelatech.com>
>
> This allows a user to configure a wifi station interface
> to disable the HT features, even if the AP and NIC supports it.
I like this version much better. Some nitpicks:
> +#define ASSOC_REQ_DISABLE_HT (1<<0) /* Disable HT (802.11n) */
You could use an enum to use kernel-doc notation here.
> @@ -1046,6 +1048,7 @@ struct cfg80211_auth_request {
> * @use_mfp: Use management frame protection (IEEE 802.11w) in this association
> * @crypto: crypto settings
> * @prev_bssid: previous BSSID, if not %NULL use reassociate frame
> + * @flags: See ASSOC_REQ_* flags above.
and then say "See &enum cfg80211_assoc_req_flags" or so should even
create the correct link in kernel-doc output.
> @@ -1053,6 +1056,7 @@ struct cfg80211_assoc_request {
> size_t ie_len;
> struct cfg80211_crypto_settings crypto;
> bool use_mfp;
> + u32 flags;
Seems like it might be good for use_mfp to become a flag? Anyway,
internal APIs are easy to change.
> --- a/net/mac80211/mlme.c
> +++ b/net/mac80211/mlme.c
I'd rather split this up into cfg80211/mac80211. In fact, maybe
splitting it into one cfg80211 and one mac80211 patch, instead of three
different patches that span both might be worthwhile?
johannes
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 3/3] mac80211: Allow overriding some HT information.
2011-11-03 5:55 ` [PATCH v3 3/3] mac80211: Allow overriding some HT information greearb
@ 2011-11-03 8:47 ` Johannes Berg
2011-11-03 17:13 ` Ben Greear
0 siblings, 1 reply; 13+ messages in thread
From: Johannes Berg @ 2011-11-03 8:47 UTC (permalink / raw)
To: greearb; +Cc: linux-wireless
On Wed, 2011-11-02 at 22:55 -0700, greearb@candelatech.com wrote:
> -void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
> +void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
> + struct ieee80211_sta_ht_cap *ht_cap,
> + int min_rates)
> +{
> + u8 *scaps = (u8 *)(&sdata->u.mgd.ht_capa.mcs.rx_mask);
> + u8 *smask = (u8 *)(&sdata->u.mgd.ht_capa_mask.mcs.rx_mask);
> + int i;
> +
> + /* check for HT over-rides, MCS rates first. */
> + for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
> + int q;
> + for (q = 0; q < 8; q++) {
> + /*
> + * We always need to advert at least MCS0-7, to
> + * be a compliant HT station, for instance
> + */
> + if (((i * 8 + q) >= min_rates) &&
> + (smask[i] & (1<<q))) {
> + if (!(scaps[i] & (1<<q))) {
> + /*
> + * Can only disable rates, not force
> + * new ones
> + */
> + ht_cap->mcs.rx_mask[i] &= ~(1<<q);
> + }
> + }
> + }
> + }
> +
> + /* Force removal of HT-40 capabilities? */
> + if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_HT40) {
> + ht_cap->cap &= ~(IEEE80211_HT_CAP_SUP_WIDTH_20_40
> + | IEEE80211_HT_CAP_SGI_40);
> + }
Here's another argument for splitting the patches differently -- this
ought to be part of the disable HT40 patch.
> + /* Allow user to decrease AMPDU factor */
> + if (sdata->u.mgd.ht_capa_mask.ampdu_params_info &
> + IEEE80211_HT_AMPDU_PARM_FACTOR) {
> + u16 n = sdata->u.mgd.ht_capa.ampdu_params_info
> + & IEEE80211_HT_AMPDU_PARM_FACTOR;
> + if (n < ht_cap->ampdu_factor)
> + ht_cap->ampdu_factor = n;
> + }
> +
> + /* Set the AMPDU density. */
> + if (sdata->u.mgd.ht_capa_mask.ampdu_params_info &
> + IEEE80211_HT_AMPDU_PARM_DENSITY)
> + ht_cap->ampdu_density =
> + (sdata->u.mgd.ht_capa.ampdu_params_info &
> + IEEE80211_HT_AMPDU_PARM_DENSITY)
> + >> IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT;
> +}
The AMPDU density should only allow increasing.
I think a lot of this validation should live in cfg80211 so if another
driver wants to implement it, this kind of thing is already covered.
> + memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
> + /*
> + * This is for an association attempt, and stations must
> + * support at least the first 8 MCS rates. See section 20.1.1
> + * of the 802.11n spec for details.
> + */
I think cfg80211 should probably just reject other configuration
attempts.
> + [NL80211_ATTR_HT_CAPABILITY_MASK] = {
> + .type = NLA_BINARY,
> + .len = NL80211_HT_CAPABILITY_LEN
> + },
My mistake -- remove the type, it should be just the length for proper
checking.
I think there's a lot of data in the ht_cap struct that you don't use,
is that right? If so you should reject it being configured. I'm also not
quite sure why you support both disable-HT40, and then this setting here
that has SUP_WIDTH_20_40 too.
I'm more and more coming to the conclusion that it would be clearer to
make separate configuration items for the various things. Most
capabilities you could only disable (greenfield, ...) except for maybe
40mhz-intol, so maybe that would be easier as a separate u16 attribute
"disable these HT capabilities"?
johannes
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 3/3] mac80211: Allow overriding some HT information.
2011-11-03 8:47 ` Johannes Berg
@ 2011-11-03 17:13 ` Ben Greear
2011-11-04 14:41 ` Johannes Berg
0 siblings, 1 reply; 13+ messages in thread
From: Ben Greear @ 2011-11-03 17:13 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 11/03/2011 01:47 AM, Johannes Berg wrote:
> On Wed, 2011-11-02 at 22:55 -0700, greearb@candelatech.com wrote:
>
>> -void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
>> +void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
>> + struct ieee80211_sta_ht_cap *ht_cap,
>> + int min_rates)
>> +{
>> + u8 *scaps = (u8 *)(&sdata->u.mgd.ht_capa.mcs.rx_mask);
>> + u8 *smask = (u8 *)(&sdata->u.mgd.ht_capa_mask.mcs.rx_mask);
>> + int i;
>> +
>> + /* check for HT over-rides, MCS rates first. */
>> + for (i = 0; i< IEEE80211_HT_MCS_MASK_LEN; i++) {
>> + int q;
>> + for (q = 0; q< 8; q++) {
>> + /*
>> + * We always need to advert at least MCS0-7, to
>> + * be a compliant HT station, for instance
>> + */
>> + if (((i * 8 + q)>= min_rates)&&
>> + (smask[i]& (1<<q))) {
>> + if (!(scaps[i]& (1<<q))) {
>> + /*
>> + * Can only disable rates, not force
>> + * new ones
>> + */
>> + ht_cap->mcs.rx_mask[i]&= ~(1<<q);
>> + }
>> + }
>> + }
>> + }
>> +
>> + /* Force removal of HT-40 capabilities? */
>> + if (sdata->u.mgd.flags& IEEE80211_STA_DISABLE_HT40) {
>> + ht_cap->cap&= ~(IEEE80211_HT_CAP_SUP_WIDTH_20_40
>> + | IEEE80211_HT_CAP_SGI_40);
>> + }
>
> Here's another argument for splitting the patches differently -- this
> ought to be part of the disable HT40 patch.
One thing I could do is move patch 3 to be the first patch. That gives this method
reason to exist, but I can leave out the disable-HT40 parts and (re)add that in
the disable-ht40 patch.
>> + /* Allow user to decrease AMPDU factor */
>> + if (sdata->u.mgd.ht_capa_mask.ampdu_params_info&
>> + IEEE80211_HT_AMPDU_PARM_FACTOR) {
>> + u16 n = sdata->u.mgd.ht_capa.ampdu_params_info
>> + & IEEE80211_HT_AMPDU_PARM_FACTOR;
>> + if (n< ht_cap->ampdu_factor)
>> + ht_cap->ampdu_factor = n;
>> + }
>> +
>> + /* Set the AMPDU density. */
>> + if (sdata->u.mgd.ht_capa_mask.ampdu_params_info&
>> + IEEE80211_HT_AMPDU_PARM_DENSITY)
>> + ht_cap->ampdu_density =
>> + (sdata->u.mgd.ht_capa.ampdu_params_info&
>> + IEEE80211_HT_AMPDU_PARM_DENSITY)
>> + >> IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT;
>> +}
>
> The AMPDU density should only allow increasing.
>
> I think a lot of this validation should live in cfg80211 so if another
> driver wants to implement it, this kind of thing is already covered.
The ath9k driver supports 0, and then every value that corresponds to 1us or higher.
If you set it to 1/2us, for instance, it just quietly rounds up to 1us. It defaults
to 8, so it appears valid to decrease or increase this value.
So, we'd either need to have cfg80211 somehow query the driver for valid
settings to do precise checks on what is valid or not.
I think at some point, for esoteric settings such as this, the user is
just going to have to be somewhat aware of what their hardware is capable
of.
>> + memcpy(&ht_cap,&sband->ht_cap, sizeof(ht_cap));
>> + /*
>> + * This is for an association attempt, and stations must
>> + * support at least the first 8 MCS rates. See section 20.1.1
>> + * of the 802.11n spec for details.
>> + */
>
> I think cfg80211 should probably just reject other configuration
> attempts.
It's valid to force a lower rate (mcs-1, for instance), but we just need to
advertise that we support mcs0-7. We *could* allow individually setting
advertise-mcs-rates v/s allow-mcs-rates, but that may be useful to exactly
no one :)
>
>> + [NL80211_ATTR_HT_CAPABILITY_MASK] = {
>> + .type = NLA_BINARY,
>> + .len = NL80211_HT_CAPABILITY_LEN
>> + },
>
> My mistake -- remove the type, it should be just the length for proper
> checking.
>
>
> I think there's a lot of data in the ht_cap struct that you don't use,
> is that right? If so you should reject it being configured. I'm also not
> quite sure why you support both disable-HT40, and then this setting here
> that has SUP_WIDTH_20_40 too.
If I add rejection like this, it will make writing backwards compat user
space very difficult. It would be similar to rejecting unknown netlink
attributes, for instance.
I was thinking that if ht-40 is disabled, then I should clear both the
IEEE80211_HT_CAP_SUP_WIDTH_20_40 and the IEEE80211_HT_CAP_SGI_40 from
the capabilities. Perhaps there are other flags I should clear as well?
> I'm more and more coming to the conclusion that it would be clearer to
> make separate configuration items for the various things. Most
> capabilities you could only disable (greenfield, ...) except for maybe
> 40mhz-intol, so maybe that would be easier as a separate u16 attribute
> "disable these HT capabilities"?
It seemed like more work for not much gain to me, but I don't mind splitting
it out into separate netlink configurables if you want.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 1/3] mac80211: Support forcing station to disable HT (802.11n).
2011-11-03 8:37 ` [PATCH v3 1/3] mac80211: Support forcing station to disable HT (802.11n) Johannes Berg
@ 2011-11-03 17:18 ` Ben Greear
2011-11-04 14:38 ` Johannes Berg
0 siblings, 1 reply; 13+ messages in thread
From: Ben Greear @ 2011-11-03 17:18 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 11/03/2011 01:37 AM, Johannes Berg wrote:
> On Wed, 2011-11-02 at 22:55 -0700, greearb@candelatech.com wrote:
>> From: Ben Greear<greearb@candelatech.com>
>>
>> This allows a user to configure a wifi station interface
>> to disable the HT features, even if the AP and NIC supports it.
>
> I like this version much better. Some nitpicks:
>
>
>> +#define ASSOC_REQ_DISABLE_HT (1<<0) /* Disable HT (802.11n) */
>
> You could use an enum to use kernel-doc notation here.
Sure, will do.
>> @@ -1053,6 +1056,7 @@ struct cfg80211_assoc_request {
>> size_t ie_len;
>> struct cfg80211_crypto_settings crypto;
>> bool use_mfp;
>> + u32 flags;
>
> Seems like it might be good for use_mfp to become a flag? Anyway,
> internal APIs are easy to change.
Yes, but I've been beat over the head enough to know not to mix
this kind of cleanup into my patches :)
Will do a follow-on patch after I get my changes in.
>> --- a/net/mac80211/mlme.c
>> +++ b/net/mac80211/mlme.c
>
> I'd rather split this up into cfg80211/mac80211. In fact, maybe
> splitting it into one cfg80211 and one mac80211 patch, instead of three
> different patches that span both might be worthwhile?
I really don't care either way. Just let me know how you want it
and I'll split it up thus. Just please do not change your mind later,
splitting patches is nothing but work :P
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 1/3] mac80211: Support forcing station to disable HT (802.11n).
2011-11-03 17:18 ` Ben Greear
@ 2011-11-04 14:38 ` Johannes Berg
0 siblings, 0 replies; 13+ messages in thread
From: Johannes Berg @ 2011-11-04 14:38 UTC (permalink / raw)
To: Ben Greear; +Cc: linux-wireless
On Thu, 2011-11-03 at 10:18 -0700, Ben Greear wrote:
> >> --- a/net/mac80211/mlme.c
> >> +++ b/net/mac80211/mlme.c
> >
> > I'd rather split this up into cfg80211/mac80211. In fact, maybe
> > splitting it into one cfg80211 and one mac80211 patch, instead of three
> > different patches that span both might be worthwhile?
>
> I really don't care either way. Just let me know how you want it
> and I'll split it up thus. Just please do not change your mind later,
> splitting patches is nothing but work :P
:-)
Shouldn't be a lot of work to split along subsystems, though of course
API updates would have to be done right away.
johannes
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 3/3] mac80211: Allow overriding some HT information.
2011-11-03 17:13 ` Ben Greear
@ 2011-11-04 14:41 ` Johannes Berg
2011-11-04 16:17 ` Ben Greear
0 siblings, 1 reply; 13+ messages in thread
From: Johannes Berg @ 2011-11-04 14:41 UTC (permalink / raw)
To: Ben Greear; +Cc: linux-wireless
On Thu, 2011-11-03 at 10:13 -0700, Ben Greear wrote:
> > Here's another argument for splitting the patches differently -- this
> > ought to be part of the disable HT40 patch.
>
> One thing I could do is move patch 3 to be the first patch. That gives this method
> reason to exist, but I can leave out the disable-HT40 parts and (re)add that in
> the disable-ht40 patch.
I think the whole thing could just be one cfg80211 and one mac80211
patch, wouldn't that make it simpler?
> >> + /* Set the AMPDU density. */
> >> + if (sdata->u.mgd.ht_capa_mask.ampdu_params_info&
> >> + IEEE80211_HT_AMPDU_PARM_DENSITY)
> >> + ht_cap->ampdu_density =
> >> + (sdata->u.mgd.ht_capa.ampdu_params_info&
> >> + IEEE80211_HT_AMPDU_PARM_DENSITY)
> >> + >> IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT;
> >> +}
> >
> > The AMPDU density should only allow increasing.
> >
> > I think a lot of this validation should live in cfg80211 so if another
> > driver wants to implement it, this kind of thing is already covered.
>
> The ath9k driver supports 0, and then every value that corresponds to 1us or higher.
> If you set it to 1/2us, for instance, it just quietly rounds up to 1us. It defaults
> to 8, so it appears valid to decrease or increase this value.
What quietly rounds up?
If it defaults to 8 then I'm sure there's a reason for it, such as the
crypto engine not being fast enough and needing 8us buffer between
frames. As such, I really don't think decreasing it is valid.
> > I think there's a lot of data in the ht_cap struct that you don't use,
> > is that right? If so you should reject it being configured. I'm also not
> > quite sure why you support both disable-HT40, and then this setting here
> > that has SUP_WIDTH_20_40 too.
>
> If I add rejection like this, it will make writing backwards compat user
> space very difficult. It would be similar to rejecting unknown netlink
> attributes, for instance.
Good point.
> I was thinking that if ht-40 is disabled, then I should clear both the
> IEEE80211_HT_CAP_SUP_WIDTH_20_40 and the IEEE80211_HT_CAP_SGI_40 from
> the capabilities. Perhaps there are other flags I should clear as well?
I don't know?
> > I'm more and more coming to the conclusion that it would be clearer to
> > make separate configuration items for the various things. Most
> > capabilities you could only disable (greenfield, ...) except for maybe
> > 40mhz-intol, so maybe that would be easier as a separate u16 attribute
> > "disable these HT capabilities"?
>
> It seemed like more work for not much gain to me, but I don't mind splitting
> it out into separate netlink configurables if you want.
It just seems to me it would clarify the semantics. Not really sure I
care all that much though.
johannes
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 3/3] mac80211: Allow overriding some HT information.
2011-11-04 14:41 ` Johannes Berg
@ 2011-11-04 16:17 ` Ben Greear
2011-11-04 16:24 ` Johannes Berg
0 siblings, 1 reply; 13+ messages in thread
From: Ben Greear @ 2011-11-04 16:17 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 11/04/2011 07:41 AM, Johannes Berg wrote:
> On Thu, 2011-11-03 at 10:13 -0700, Ben Greear wrote:
>
>>> Here's another argument for splitting the patches differently -- this
>>> ought to be part of the disable HT40 patch.
>>
>> One thing I could do is move patch 3 to be the first patch. That gives this method
>> reason to exist, but I can leave out the disable-HT40 parts and (re)add that in
>> the disable-ht40 patch.
>
> I think the whole thing could just be one cfg80211 and one mac80211
> patch, wouldn't that make it simpler?
Ok, I will do that.
>>> The AMPDU density should only allow increasing.
>>>
>>> I think a lot of this validation should live in cfg80211 so if another
>>> driver wants to implement it, this kind of thing is already covered.
>>
>> The ath9k driver supports 0, and then every value that corresponds to 1us or higher.
>> If you set it to 1/2us, for instance, it just quietly rounds up to 1us. It defaults
>> to 8, so it appears valid to decrease or increase this value.
>
> What quietly rounds up?
>
> If it defaults to 8 then I'm sure there's a reason for it, such as the
> crypto engine not being fast enough and needing 8us buffer between
> frames. As such, I really don't think decreasing it is valid.
See this code in ath9k, top of main.c. It appears to support more
than the default of 8. I tested it out, and it appears to work
when set to lower values. I am disabling hw-crypt since I need
multiple VIFS, but not sure that matters or not.
static u8 parse_mpdudensity(u8 mpdudensity)
{
/*
* 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
* 0 for no restriction
* 1 for 1/4 us
* 2 for 1/2 us
* 3 for 1 us
* 4 for 2 us
* 5 for 4 us
* 6 for 8 us
* 7 for 16 us
*/
switch (mpdudensity) {
case 0:
return 0;
case 1:
case 2:
case 3:
/* Our lower layer calculations limit our precision to
1 microsecond */
return 1;
case 4:
return 2;
case 5:
return 4;
case 6:
return 8;
case 7:
return 16;
default:
return 0;
}
}
>> I was thinking that if ht-40 is disabled, then I should clear both the
>> IEEE80211_HT_CAP_SUP_WIDTH_20_40 and the IEEE80211_HT_CAP_SGI_40 from
>> the capabilities. Perhaps there are other flags I should clear as well?
>
> I don't know?
Well, it can always be changed later if I missed something. This code
should have no affect unless the users specifically enable the feature
anyway...and we'll be doing lots of testing on our systems at various
settings...
>>> I'm more and more coming to the conclusion that it would be clearer to
>>> make separate configuration items for the various things. Most
>>> capabilities you could only disable (greenfield, ...) except for maybe
>>> 40mhz-intol, so maybe that would be easier as a separate u16 attribute
>>> "disable these HT capabilities"?
>>
>> It seemed like more work for not much gain to me, but I don't mind splitting
>> it out into separate netlink configurables if you want.
>
> It just seems to me it would clarify the semantics. Not really sure I
> care all that much though.
If it's OK with you, I'll skip this for now. If anyone ever cares,
it would be easy enough to add.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 3/3] mac80211: Allow overriding some HT information.
2011-11-04 16:17 ` Ben Greear
@ 2011-11-04 16:24 ` Johannes Berg
2011-11-04 16:27 ` Ben Greear
0 siblings, 1 reply; 13+ messages in thread
From: Johannes Berg @ 2011-11-04 16:24 UTC (permalink / raw)
To: Ben Greear; +Cc: linux-wireless
On Fri, 2011-11-04 at 09:17 -0700, Ben Greear wrote:
> >>> The AMPDU density should only allow increasing.
> >>>
> >>> I think a lot of this validation should live in cfg80211 so if another
> >>> driver wants to implement it, this kind of thing is already covered.
> >>
> >> The ath9k driver supports 0, and then every value that corresponds to 1us or higher.
> >> If you set it to 1/2us, for instance, it just quietly rounds up to 1us. It defaults
> >> to 8, so it appears valid to decrease or increase this value.
> >
> > What quietly rounds up?
> >
> > If it defaults to 8 then I'm sure there's a reason for it, such as the
> > crypto engine not being fast enough and needing 8us buffer between
> > frames. As such, I really don't think decreasing it is valid.
>
> See this code in ath9k, top of main.c. It appears to support more
> than the default of 8. I tested it out, and it appears to work
> when set to lower values. I am disabling hw-crypt since I need
> multiple VIFS, but not sure that matters or not.
>
> static u8 parse_mpdudensity(u8 mpdudensity)
Well, this is used for TX. You're advertising the value for RX.
Advertising a smaller value may work for you -- but only if the AP uses
something larger anyway. It's free to do this. The code you quoted
implements this -- it looks at what the min spacing is the peer wants,
and then uses something bigger.
So I still stand by what I said earlier -- you should not allow
advertising a smaller value than the hardware wanted to use initially.
If the AP doesn't use that smaller value, all is well, but if it
actually uses a smaller value then the hardware might fall over.
johannes
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 3/3] mac80211: Allow overriding some HT information.
2011-11-04 16:24 ` Johannes Berg
@ 2011-11-04 16:27 ` Ben Greear
2011-11-04 16:30 ` Johannes Berg
0 siblings, 1 reply; 13+ messages in thread
From: Ben Greear @ 2011-11-04 16:27 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 11/04/2011 09:24 AM, Johannes Berg wrote:
> On Fri, 2011-11-04 at 09:17 -0700, Ben Greear wrote:
>
>>>>> The AMPDU density should only allow increasing.
>>>>>
>>>>> I think a lot of this validation should live in cfg80211 so if another
>>>>> driver wants to implement it, this kind of thing is already covered.
>>>>
>>>> The ath9k driver supports 0, and then every value that corresponds to 1us or higher.
>>>> If you set it to 1/2us, for instance, it just quietly rounds up to 1us. It defaults
>>>> to 8, so it appears valid to decrease or increase this value.
>>>
>>> What quietly rounds up?
>>>
>>> If it defaults to 8 then I'm sure there's a reason for it, such as the
>>> crypto engine not being fast enough and needing 8us buffer between
>>> frames. As such, I really don't think decreasing it is valid.
>>
>> See this code in ath9k, top of main.c. It appears to support more
>> than the default of 8. I tested it out, and it appears to work
>> when set to lower values. I am disabling hw-crypt since I need
>> multiple VIFS, but not sure that matters or not.
>>
>> static u8 parse_mpdudensity(u8 mpdudensity)
>
> Well, this is used for TX. You're advertising the value for RX.
> Advertising a smaller value may work for you -- but only if the AP uses
> something larger anyway. It's free to do this. The code you quoted
> implements this -- it looks at what the min spacing is the peer wants,
> and then uses something bigger.
>
> So I still stand by what I said earlier -- you should not allow
> advertising a smaller value than the hardware wanted to use initially.
> If the AP doesn't use that smaller value, all is well, but if it
> actually uses a smaller value then the hardware might fall over.
Ok, I'll add that restriction. When this all settles, maybe I
can get some info from the ath9k folks about what their hardware
can actually support.
Thanks,
Ben
>
> johannes
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 3/3] mac80211: Allow overriding some HT information.
2011-11-04 16:27 ` Ben Greear
@ 2011-11-04 16:30 ` Johannes Berg
0 siblings, 0 replies; 13+ messages in thread
From: Johannes Berg @ 2011-11-04 16:30 UTC (permalink / raw)
To: Ben Greear; +Cc: linux-wireless
On Fri, 2011-11-04 at 09:27 -0700, Ben Greear wrote:
> > So I still stand by what I said earlier -- you should not allow
> > advertising a smaller value than the hardware wanted to use initially.
> > If the AP doesn't use that smaller value, all is well, but if it
> > actually uses a smaller value then the hardware might fall over.
>
> Ok, I'll add that restriction. When this all settles, maybe I
> can get some info from the ath9k folks about what their hardware
> can actually support.
There's little point in advertising something bigger than the HW
supports, so I'd say that's the smallest :-)
(ok, so this might be for hw crypto, etc., but ath9k could advertise a
smaller value when hw crypto is disabled for example)
johannes
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2011-11-04 16:30 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-03 5:55 [PATCH v3 1/3] mac80211: Support forcing station to disable HT (802.11n) greearb
2011-11-03 5:55 ` [PATCH v3 2/3] mac80211: Support disabling ht40 greearb
2011-11-03 5:55 ` [PATCH v3 3/3] mac80211: Allow overriding some HT information greearb
2011-11-03 8:47 ` Johannes Berg
2011-11-03 17:13 ` Ben Greear
2011-11-04 14:41 ` Johannes Berg
2011-11-04 16:17 ` Ben Greear
2011-11-04 16:24 ` Johannes Berg
2011-11-04 16:27 ` Ben Greear
2011-11-04 16:30 ` Johannes Berg
2011-11-03 8:37 ` [PATCH v3 1/3] mac80211: Support forcing station to disable HT (802.11n) Johannes Berg
2011-11-03 17:18 ` Ben Greear
2011-11-04 14:38 ` Johannes Berg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).