* [PATCH v6 1/2] wireless: Support ht-capabilities over-rides.
@ 2011-11-07 23:14 greearb
2011-11-07 23:14 ` [PATCH v6 2/2] mac80211: Support ht-cap over-rides greearb
2011-11-08 8:14 ` [PATCH v6 1/2] wireless: Support ht-capabilities over-rides Johannes Berg
0 siblings, 2 replies; 7+ messages in thread
From: greearb @ 2011-11-07 23:14 UTC (permalink / raw)
To: linux-wireless; +Cc: Ben Greear
From: Ben Greear <greearb@candelatech.com>
This allows users to disable features such as HT, HT40,
and to modify the MCS, AMPDU, and AMSDU settings for
drivers that support it.
The MCS, AMPDU, and AMSDU features that may be disabled are
are reported in the phy-info netlink message as a mask.
Attemping to disable features that are not supported will
take no affect, but will not return errors. This is to aid
backwards compatibility in user-space apps that may not be
clever enough to deal with parsing the the capabilities mask.
This patch only enables the infrastructure. An additional
patch will enable the feature in mac80211.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
v6: Fix const issue, fix typo in comment.
:100644 100644 8049bf7... 5b86a3b... M include/linux/nl80211.h
:100644 100644 92cf1c2... 5598b91... M include/net/cfg80211.h
:100644 100644 b9ec306... dd6feda... M net/wireless/core.h
:100644 100644 21fc970... 54d9071... M net/wireless/mlme.c
:100644 100644 48260c2... 80e5144... M net/wireless/nl80211.c
:100644 100644 6e86d5a... d144e2d... M net/wireless/sme.c
include/linux/nl80211.h | 8 ++++++++
include/net/cfg80211.h | 28 ++++++++++++++++++++++++++++
net/wireless/core.h | 8 ++++++--
net/wireless/mlme.c | 37 ++++++++++++++++++++++++++++++++++---
net/wireless/nl80211.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
net/wireless/sme.c | 4 +++-
6 files changed, 122 insertions(+), 7 deletions(-)
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 8049bf7..5b86a3b 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1109,6 +1109,11 @@ 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_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
*/
@@ -1337,6 +1342,9 @@ enum nl80211_attrs {
NL80211_ATTR_TDLS_SUPPORT,
NL80211_ATTR_TDLS_EXTERNAL_SETUP,
+ NL80211_ATTR_DISABLE_HT,
+ NL80211_ATTR_HT_CAPABILITY_MASK,
+
/* 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..5598b91 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1036,6 +1036,15 @@ struct cfg80211_auth_request {
};
/**
+ * enum cfg80211_assoc_req_flags - Over-ride default behaviour in association.
+ *
+ * @ASSOC_REQ_DISABLE_HT: Disable HT (802.11n)
+ */
+enum cfg80211_assoc_req_flags {
+ ASSOC_REQ_DISABLE_HT = BIT(0),
+};
+
+/**
* struct cfg80211_assoc_request - (Re)Association request data
*
* This structure provides information needed to complete IEEE 802.11
@@ -1046,6 +1055,10 @@ 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 &enum cfg80211_assoc_req_flags
+ * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask
+ * will be used in ht_capa. Un-supported values will be ignored.
+ * @ht_capa_mask: The bits of ht_capa which are to be used.
*/
struct cfg80211_assoc_request {
struct cfg80211_bss *bss;
@@ -1053,6 +1066,9 @@ struct cfg80211_assoc_request {
size_t ie_len;
struct cfg80211_crypto_settings crypto;
bool use_mfp;
+ u32 flags;
+ struct ieee80211_ht_cap ht_capa;
+ struct ieee80211_ht_cap ht_capa_mask;
};
/**
@@ -1151,6 +1167,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
+ * @flags: See &enum cfg80211_assoc_req_flags
+ * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask
+ * will be used in ht_capa. Un-supported values will be ignored.
+ * @ht_capa_mask: The bits of ht_capa which are to be used.
*/
struct cfg80211_connect_params {
struct ieee80211_channel *channel;
@@ -1164,6 +1184,9 @@ struct cfg80211_connect_params {
struct cfg80211_crypto_settings crypto;
const u8 *key;
u8 key_len, key_idx;
+ u32 flags;
+ struct ieee80211_ht_cap ht_capa;
+ struct ieee80211_ht_cap ht_capa_mask;
};
/**
@@ -1903,6 +1926,9 @@ struct wiphy_wowlan_support {
* may request, if implemented.
*
* @wowlan: WoWLAN support information
+ *
+ * @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden.
+ * If null, then none can be over-ridden.
*/
struct wiphy {
/* assign these fields before you register the wiphy */
@@ -1983,6 +2009,8 @@ struct wiphy {
/* dir in debugfs: ieee80211/<wiphyname> */
struct dentry *debugfsdir;
+ const struct ieee80211_ht_cap *ht_capa_mod_mask;
+
#ifdef CONFIG_NET_NS
/* the network namespace this phy lives in currently */
struct net *_net;
diff --git a/net/wireless/core.h b/net/wireless/core.h
index b9ec306..dd6feda 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -339,13 +339,17 @@ 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 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);
+ struct cfg80211_crypto_settings *crypt,
+ 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 21fc970..54d9071 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -501,13 +501,32 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
return err;
}
+/* Do a logical ht_capa &= ht_capa_mask. */
+static void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
+ const struct ieee80211_ht_cap *ht_capa_mask)
+{
+ int i;
+ u8 *p1, *p2;
+ if (!ht_capa_mask) {
+ memset(ht_capa, 0, sizeof(*ht_capa));
+ return;
+ }
+
+ p1 = (u8*)(ht_capa);
+ p2 = (u8*)(ht_capa_mask);
+ for (i = 0; i<sizeof(*ht_capa); i++)
+ p1[i] &= p2[i];
+}
+
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, 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;
@@ -537,6 +556,15 @@ 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;
+ 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));
+ cfg80211_oper_and_ht_capa(&req.ht_capa_mask,
+ rdev->wiphy.ht_capa_mod_mask);
+
req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
if (!req.bss) {
@@ -574,14 +602,17 @@ 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 ieee80211_ht_cap *ht_capa,
+ struct ieee80211_ht_cap *ht_capa_mask)
{
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, ht_capa, ht_capa_mask);
wdev_unlock(wdev);
return err;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 48260c2..80e5144 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -197,6 +197,10 @@ 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 },
+ [NL80211_ATTR_HT_CAPABILITY_MASK] = {
+ .len = NL80211_HT_CAPABILITY_LEN
+ },
};
/* policy for the key attributes */
@@ -1008,6 +1012,11 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
if (nl80211_put_iface_combinations(&dev->wiphy, msg))
goto nla_put_failure;
+ if (dev->wiphy.ht_capa_mod_mask)
+ NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
+ sizeof(*dev->wiphy.ht_capa_mod_mask),
+ dev->wiphy.ht_capa_mod_mask);
+
return genlmsg_end(msg, hdr);
nla_put_failure:
@@ -4354,6 +4363,9 @@ 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;
+ 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;
@@ -4397,11 +4409,25 @@ 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;
+
+ 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);
+ &crypto, flags, ht_capa,
+ ht_capa_mask);
return err;
}
@@ -4891,6 +4917,22 @@ 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;
+
+ 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 6e86d5a..d144e2d 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -189,7 +189,9 @@ 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, ¶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] 7+ messages in thread
* [PATCH v6 2/2] mac80211: Support ht-cap over-rides.
2011-11-07 23:14 [PATCH v6 1/2] wireless: Support ht-capabilities over-rides greearb
@ 2011-11-07 23:14 ` greearb
2011-11-08 8:14 ` [PATCH v6 1/2] wireless: Support ht-capabilities over-rides Johannes Berg
1 sibling, 0 replies; 7+ messages in thread
From: greearb @ 2011-11-07 23:14 UTC (permalink / raw)
To: linux-wireless; +Cc: Ben Greear
From: Ben Greear <greearb@candelatech.com>
This implements ht-cap over-rides for mac80211 drivers.
HT may be disabled, making an /a/b/g/n station act like an
a/b/g station. HT40 may be disabled forcing the station to
be HT20 even if the AP and local hardware support HT40.
MAX-AMSDU may be disabled.
AMPDU-Density may be increased.
AMPDU-Factor may be decreased.
This has been successfully tested with ath9k using patched
wpa_supplicant and iw.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 48363c3... 25ea406... M include/linux/ieee80211.h
:100644 100644 a9ded52... 7f4389e... M net/mac80211/cfg.c
:100644 100644 f80a35c... 47b89bb... M net/mac80211/ht.c
:100644 100644 ea10a51... 6afa409... M net/mac80211/ieee80211_i.h
:100644 100644 d4ee6d2... 7be5ad8... M net/mac80211/main.c
:100644 100644 57fb58f... 7c71db0... M net/mac80211/mlme.c
:100644 100644 6c53b6d... 3f318df... M net/mac80211/work.c
include/linux/ieee80211.h | 6 +++
net/mac80211/cfg.c | 2 +-
net/mac80211/ht.c | 90 +++++++++++++++++++++++++++++++++++++++++++-
net/mac80211/ieee80211_i.h | 10 ++++-
net/mac80211/main.c | 14 +++++++
net/mac80211/mlme.c | 12 +++++-
net/mac80211/work.c | 35 ++++++++++++-----
7 files changed, 154 insertions(+), 15 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/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..47b89bb 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -18,7 +18,89 @@
#include "ieee80211_i.h"
#include "rate.h"
-void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
+bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata)
+{
+ if ((sdata->u.mgd.ht_capa_mask.cap_info &
+ IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
+ !(sdata->u.mgd.ht_capa.cap_info &
+ IEEE80211_HT_CAP_SUP_WIDTH_20_40))
+ return true;
+ return false;
+}
+
+void __check_htcap_disable(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta_ht_cap *ht_cap,
+ u16 flag)
+{
+ if (sdata->u.mgd.ht_capa_mask.cap_info & flag) {
+ if (!(sdata->u.mgd.ht_capa.cap_info & flag))
+ ht_cap->cap &= ~flag;
+ }
+}
+
+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;
+
+ /* NOTE: If you add more over-rides here, update register_hw
+ * ht_capa_mod_msk logic in main.c as well.
+ */
+
+ /* 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? */
+ __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SUP_WIDTH_20_40);
+ __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SGI_40);
+
+ /* Allow user to disable the max-AMSDU bit. */
+ __check_htcap_disable(sdata, ht_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;
+ }
+
+ /* Allow the user to increase AMPDU density. */
+ if (sdata->u.mgd.ht_capa_mask.ampdu_params_info &
+ IEEE80211_HT_AMPDU_PARM_DENSITY) {
+ u16 n = (sdata->u.mgd.ht_capa.ampdu_params_info &
+ IEEE80211_HT_AMPDU_PARM_DENSITY)
+ >> IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT;
+ if (n > ht_cap->ampdu_density)
+ ht_cap->ampdu_density = n;
+ }
+}
+
+
+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 +184,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 ea10a51..6afa409 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -443,6 +443,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 {
@@ -1179,7 +1182,12 @@ 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,
+bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata);
+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/main.c b/net/mac80211/main.c
index d4ee6d2..7be5ad8 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -560,6 +560,19 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
},
};
+static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = {
+ .ampdu_params_info = IEEE80211_HT_AMPDU_PARM_FACTOR |
+ IEEE80211_HT_AMPDU_PARM_DENSITY,
+
+ .cap_info = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+ IEEE80211_HT_CAP_MAX_AMSDU |
+ IEEE80211_HT_CAP_SGI_40,
+ .mcs = {
+ .rx_mask = { 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, },
+ },
+};
+
struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
const struct ieee80211_ops *ops)
{
@@ -628,6 +641,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
local->user_power_level = -1;
local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
+ wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
INIT_LIST_HEAD(&local->interfaces);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 57fb58f..7c71db0 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) &&
+ !ieee80111_cfg_override_disables_ht40(sdata) &&
(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) {
@@ -1584,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;
@@ -1953,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;
@@ -2611,6 +2612,13 @@ 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;
+
+ 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 */
--
1.7.3.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v6 1/2] wireless: Support ht-capabilities over-rides.
2011-11-07 23:14 [PATCH v6 1/2] wireless: Support ht-capabilities over-rides greearb
2011-11-07 23:14 ` [PATCH v6 2/2] mac80211: Support ht-cap over-rides greearb
@ 2011-11-08 8:14 ` Johannes Berg
2011-11-08 17:43 ` Ben Greear
1 sibling, 1 reply; 7+ messages in thread
From: Johannes Berg @ 2011-11-08 8:14 UTC (permalink / raw)
To: greearb; +Cc: linux-wireless
On Mon, 2011-11-07 at 15:14 -0800, greearb@candelatech.com wrote:
> +++ b/net/wireless/mlme.c
> @@ -501,13 +501,32 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
> return err;
> }
>
> +/* Do a logical ht_capa &= ht_capa_mask. */
> +static void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
> + const struct ieee80211_ht_cap *ht_capa_mask)
> +{
> + int i;
> + u8 *p1, *p2;
> + if (!ht_capa_mask) {
> + memset(ht_capa, 0, sizeof(*ht_capa));
> + return;
> + }
> +
> + p1 = (u8*)(ht_capa);
> + p2 = (u8*)(ht_capa_mask);
> + for (i = 0; i<sizeof(*ht_capa); i++)
> + p1[i] &= p2[i];
> +}
I think you also need to call this in the cfg80211_connect() path.
Also, maybe we should reject this configuration if the device didn't
support it at all, ie. ht_capa_mask was NULL? It also seems a bit odd to
allow this on a device that doesn't even support HT.
Also how would you feel about rejecting, instead of silently ignoring,
things that we do look at but don't support, e.g. a wrong A-MSDU
setting? Alternatively, cfg80211 could modify the settings in a way that
drivers don't have to worry about the "downgrade only" part.
Finally, I think we need a tad more documentation about how this is
supposed to work in case somebody wants to implement it on non-mac80211.
The way it's done right now it seems fairly error prone, with all
restrictions that the driver needs to implement like not allowing the
a-MSDU size to be increased.
johannes
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v6 1/2] wireless: Support ht-capabilities over-rides.
2011-11-08 8:14 ` [PATCH v6 1/2] wireless: Support ht-capabilities over-rides Johannes Berg
@ 2011-11-08 17:43 ` Ben Greear
2011-11-08 18:00 ` Johannes Berg
0 siblings, 1 reply; 7+ messages in thread
From: Ben Greear @ 2011-11-08 17:43 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 11/08/2011 12:14 AM, Johannes Berg wrote:
> On Mon, 2011-11-07 at 15:14 -0800, greearb@candelatech.com wrote:
>
>> +++ b/net/wireless/mlme.c
>> @@ -501,13 +501,32 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
>> return err;
>> }
>>
>> +/* Do a logical ht_capa&= ht_capa_mask. */
>> +static void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
>> + const struct ieee80211_ht_cap *ht_capa_mask)
>> +{
>> + int i;
>> + u8 *p1, *p2;
>> + if (!ht_capa_mask) {
>> + memset(ht_capa, 0, sizeof(*ht_capa));
>> + return;
>> + }
>> +
>> + p1 = (u8*)(ht_capa);
>> + p2 = (u8*)(ht_capa_mask);
>> + for (i = 0; i<sizeof(*ht_capa); i++)
>> + p1[i]&= p2[i];
>> +}
>
> I think you also need to call this in the cfg80211_connect() path.
I'll double check that...for some reason I thought everything
eventually went through this code path.
>
> Also, maybe we should reject this configuration if the device didn't
> support it at all, ie. ht_capa_mask was NULL? It also seems a bit odd to
> allow this on a device that doesn't even support HT.
I really don't like that. It would mean that supplicant will
have to selectively not add certain netlink attributes based on the
driver and/or kernel version. That means either probing
to determine what the phy supports (and returning errors on
up to user if they configure it for something not supported?)
or just forcing the user to make all the decisions when writing
the supplicant config file.
The truth is, my app auto-generates the supplicant config files,
and I know what wifi driver I'm using etc, so it would be easy enough
for me to live with this. But, it seems like it will make life
painful for anyone with less knowledge of the system.
> Also how would you feel about rejecting, instead of silently ignoring,
> things that we do look at but don't support, e.g. a wrong A-MSDU
> setting? Alternatively, cfg80211 could modify the settings in a way that
> drivers don't have to worry about the "downgrade only" part.
I dislike that as well, for similar reasons. Getting an -EINVAL back
from a netlink call gives very little info to the user anyway...who
knows what exactly was invalid? Perhaps a printk warning coming out
of mac80211 when it checks for the restrictions against what the
driver supports would be more useful?
> Finally, I think we need a tad more documentation about how this is
> supposed to work in case somebody wants to implement it on non-mac80211.
> The way it's done right now it seems fairly error prone, with all
> restrictions that the driver needs to implement like not allowing the
> a-MSDU size to be increased.
Well, who knows...in their driver maybe the restrictions are not
the same. I think that adding more info about what fields are
currently supported for mac80211 might be useful, but trying to
generalize restrictions for drivers that have not even implemented
any of this seems like useless overhead.
Thanks,
Ben
>
> johannes
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v6 1/2] wireless: Support ht-capabilities over-rides.
2011-11-08 17:43 ` Ben Greear
@ 2011-11-08 18:00 ` Johannes Berg
2011-11-08 18:16 ` Ben Greear
0 siblings, 1 reply; 7+ messages in thread
From: Johannes Berg @ 2011-11-08 18:00 UTC (permalink / raw)
To: Ben Greear; +Cc: linux-wireless
On Tue, 2011-11-08 at 09:43 -0800, Ben Greear wrote:
> >> +/* Do a logical ht_capa&= ht_capa_mask. */
> >> +static void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
> >> + const struct ieee80211_ht_cap *ht_capa_mask)
> > I think you also need to call this in the cfg80211_connect() path.
>
> I'll double check that...for some reason I thought everything
> eventually went through this code path.
Not for full-mac drivers, e.g. iwm.
> > Also, maybe we should reject this configuration if the device didn't
> > support it at all, ie. ht_capa_mask was NULL? It also seems a bit odd to
> > allow this on a device that doesn't even support HT.
>
> I really don't like that. It would mean that supplicant will
> have to selectively not add certain netlink attributes based on the
> driver and/or kernel version. That means either probing
> to determine what the phy supports (and returning errors on
> up to user if they configure it for something not supported?)
> or just forcing the user to make all the decisions when writing
> the supplicant config file.
>
> The truth is, my app auto-generates the supplicant config files,
> and I know what wifi driver I'm using etc, so it would be easy enough
> for me to live with this. But, it seems like it will make life
> painful for anyone with less knowledge of the system.
>
> > Also how would you feel about rejecting, instead of silently ignoring,
> > things that we do look at but don't support, e.g. a wrong A-MSDU
> > setting? Alternatively, cfg80211 could modify the settings in a way that
> > drivers don't have to worry about the "downgrade only" part.
>
> I dislike that as well, for similar reasons. Getting an -EINVAL back
> from a netlink call gives very little info to the user anyway...who
> knows what exactly was invalid? Perhaps a printk warning coming out
> of mac80211 when it checks for the restrictions against what the
> driver supports would be more useful?
Fair enough. I think what I'm really after is having a way to know wtf
we're using when you requested something. That would probably be more
useful overall.
FWIW, I did talk to some people at the kernel summit about the -EINVAL
thing and maybe there's an idea to send back the invalid attribute at
least, but doesn't really matter here. I'm OK with just allowing it all
since it's not going to be used a lot anyway.
> > Finally, I think we need a tad more documentation about how this is
> > supposed to work in case somebody wants to implement it on non-mac80211.
> > The way it's done right now it seems fairly error prone, with all
> > restrictions that the driver needs to implement like not allowing the
> > a-MSDU size to be increased.
>
> Well, who knows...in their driver maybe the restrictions are not
> the same. I think that adding more info about what fields are
> currently supported for mac80211 might be useful, but trying to
> generalize restrictions for drivers that have not even implemented
> any of this seems like useless overhead.
Well, it goes both ways though, having more validation up front will
make it a lot easier for new drivers to implement it because they don't
have to bother with the validation, and I really don't see any way that
a driver might allow making the a-MPDU spacing *smaller*, if it could
deal with smaller it'd advertise that to start with.
OTOH, if you request a connect(), you don't even know the band and
technically a driver could have different capabilities on different
bands.
johannes
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v6 1/2] wireless: Support ht-capabilities over-rides.
2011-11-08 18:00 ` Johannes Berg
@ 2011-11-08 18:16 ` Ben Greear
2011-11-08 18:21 ` Johannes Berg
0 siblings, 1 reply; 7+ messages in thread
From: Ben Greear @ 2011-11-08 18:16 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
On 11/08/2011 10:00 AM, Johannes Berg wrote:
> On Tue, 2011-11-08 at 09:43 -0800, Ben Greear wrote:
>>> Also how would you feel about rejecting, instead of silently ignoring,
>>> things that we do look at but don't support, e.g. a wrong A-MSDU
>>> setting? Alternatively, cfg80211 could modify the settings in a way that
>>> drivers don't have to worry about the "downgrade only" part.
>>
>> I dislike that as well, for similar reasons. Getting an -EINVAL back
>> from a netlink call gives very little info to the user anyway...who
>> knows what exactly was invalid? Perhaps a printk warning coming out
>> of mac80211 when it checks for the restrictions against what the
>> driver supports would be more useful?
>
> Fair enough. I think what I'm really after is having a way to know wtf
> we're using when you requested something. That would probably be more
> useful overall.
The current ht_cap settings for each station are in debugfs, so hopefully it
would not be that difficult to add it to a netlink response. Perhaps
it's already there..I haven't looked yet.
> FWIW, I did talk to some people at the kernel summit about the -EINVAL
> thing and maybe there's an idea to send back the invalid attribute at
> least, but doesn't really matter here. I'm OK with just allowing it all
> since it's not going to be used a lot anyway.
Ok, I'll add some printks.
>>> Finally, I think we need a tad more documentation about how this is
>>> supposed to work in case somebody wants to implement it on non-mac80211.
>>> The way it's done right now it seems fairly error prone, with all
>>> restrictions that the driver needs to implement like not allowing the
>>> a-MSDU size to be increased.
>>
>> Well, who knows...in their driver maybe the restrictions are not
>> the same. I think that adding more info about what fields are
>> currently supported for mac80211 might be useful, but trying to
>> generalize restrictions for drivers that have not even implemented
>> any of this seems like useless overhead.
>
> Well, it goes both ways though, having more validation up front will
> make it a lot easier for new drivers to implement it because they don't
> have to bother with the validation, and I really don't see any way that
> a driver might allow making the a-MPDU spacing *smaller*, if it could
> deal with smaller it'd advertise that to start with.
>
> OTOH, if you request a connect(), you don't even know the band and
> technically a driver could have different capabilities on different
> bands.
Lets see if any other drivers try to support these features. Anyone
doing that work will likely see some ways to make use of common code
and things can be shuffled then. As written, the patches are not overly
invasive, so I think we can move stuff around later without too much
trouble.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v6 1/2] wireless: Support ht-capabilities over-rides.
2011-11-08 18:16 ` Ben Greear
@ 2011-11-08 18:21 ` Johannes Berg
0 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2011-11-08 18:21 UTC (permalink / raw)
To: Ben Greear; +Cc: linux-wireless
On Tue, 2011-11-08 at 10:16 -0800, Ben Greear wrote:
> > Fair enough. I think what I'm really after is having a way to know wtf
> > we're using when you requested something. That would probably be more
> > useful overall.
ok.
> The current ht_cap settings for each station are in debugfs, so hopefully it
> would not be that difficult to add it to a netlink response. Perhaps
> it's already there..I haven't looked yet.
>
> > FWIW, I did talk to some people at the kernel summit about the -EINVAL
> > thing and maybe there's an idea to send back the invalid attribute at
> > least, but doesn't really matter here. I'm OK with just allowing it all
> > since it's not going to be used a lot anyway.
>
> Ok, I'll add some printks.
I really don't think you should add printks here for this.
> > OTOH, if you request a connect(), you don't even know the band and
> > technically a driver could have different capabilities on different
> > bands.
>
> Lets see if any other drivers try to support these features. Anyone
> doing that work will likely see some ways to make use of common code
> and things can be shuffled then. As written, the patches are not overly
> invasive, so I think we can move stuff around later without too much
> trouble.
Ok, fair enough.
johannes
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2011-11-08 18:21 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-07 23:14 [PATCH v6 1/2] wireless: Support ht-capabilities over-rides greearb
2011-11-07 23:14 ` [PATCH v6 2/2] mac80211: Support ht-cap over-rides greearb
2011-11-08 8:14 ` [PATCH v6 1/2] wireless: Support ht-capabilities over-rides Johannes Berg
2011-11-08 17:43 ` Ben Greear
2011-11-08 18:00 ` Johannes Berg
2011-11-08 18:16 ` Ben Greear
2011-11-08 18:21 ` Johannes Berg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox