From: greearb@candelatech.com
To: linux-wireless@vger.kernel.org
Cc: Ben Greear <greearb@candelatech.com>
Subject: [wireless-next PATCH 3/5] wifi: Allow overriding some HT information.
Date: Thu, 27 Oct 2011 22:11:18 -0700 [thread overview]
Message-ID: <1319778680-11405-3-git-send-email-greearb@candelatech.com> (raw)
In-Reply-To: <1319778680-11405-1-git-send-email-greearb@candelatech.com>
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 MSDU and MPDU
values can be set to any value allowed by the 802.11n
specification.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 ae50ade... 7f269cd... M include/linux/nl80211.h
:100644 100644 9d7a5e0... 802ff5f... M include/net/cfg80211.h
:100644 100644 c63d7f0... dde541f... M net/mac80211/cfg.c
:100644 100644 f80a35c... 0753c96... M net/mac80211/ht.c
:100644 100644 f4a7618... f279ee9... M net/mac80211/ieee80211_i.h
:100644 100644 164cdb1... 681ba4e... M net/mac80211/mlme.c
:100644 100644 94472eb... 2f546be... M net/mac80211/work.c
:100644 100644 5696621... 2cbb7c6... M net/wireless/nl80211.c
include/linux/nl80211.h | 3 ++
include/net/cfg80211.h | 4 ++
net/mac80211/cfg.c | 28 +++++++++++++++++-
net/mac80211/ht.c | 70 +++++++++++++++++++++++++++++++++++++++++++-
net/mac80211/ieee80211_i.h | 9 +++++-
net/mac80211/mlme.c | 4 +-
net/mac80211/work.c | 34 +++++++++++++++------
net/wireless/nl80211.c | 14 +++++++++
8 files changed, 151 insertions(+), 15 deletions(-)
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index ae50ade..7f269cd 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1113,6 +1113,8 @@ enum nl80211_commands {
* function as /a/b/g stations.
* @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_11N,
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 9d7a5e0..802ff5f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -256,11 +256,15 @@ struct ieee80211_supported_band {
* @use_4addr: use 4-address frames
* @disable_11n: Don't use 11n features (HT, etc)
* @disable_ht40: Don't use HT40, even if hardware & AP support it.
+ * @ht_capa: HT Capabilities for this interface.
+ * @ht_capa_mask: Bits of ht_capa that are to be used.
*/
struct vif_params {
int use_4addr;
int disable_11n;
int disable_ht40;
+ 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 c63d7f0..dde541f 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -105,6 +105,32 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
}
}
+ if (params->ht_capa) {
+ u8 *caps = (u8 *)(params->ht_capa);
+ u8 *mask = (u8 *)(params->ht_capa_mask);
+ u8 *scaps = (u8 *)(&sdata->ht_capa);
+ u8 *smask = (u8 *)(&sdata->ht_capa_mask);
+ int i;
+
+ for (i = 0; i < sizeof(sdata->ht_capa); i++) {
+ if (mask[i]) {
+ int q;
+ smask[i] |= mask[i];
+ for (q = 0; q < 8; q++) {
+ if (mask[i] & (1<<q)) {
+ if (caps[i] & (1<<q))
+ scaps[i] |= (1<<q);
+ else
+ scaps[i] &= ~(1<<q);
+ }
+ }
+ }
+ }
+ } else if (params->ht_capa_mask) {
+ memcpy(&sdata->ht_capa_mask, params->ht_capa_mask,
+ sizeof(sdata->ht_capa_mask));
+ }
+
return 0;
}
@@ -784,7 +810,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..0753c96 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -18,7 +18,70 @@
#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->ht_capa.mcs.rx_mask);
+ u8 *smask = (u8 *)(&sdata->ht_capa_mask.mcs.rx_mask);
+ int i;
+
+ /* check for HT over-rides, mcs rates only at this time,
+ * and can only disable them, not force new ones to be
+ * made available.
+ */
+ 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->cfg_disable_ht40) {
+ ht_cap->cap &= ~(IEEE80211_HT_CAP_SUP_WIDTH_20_40
+ | IEEE80211_HT_CAP_SGI_40);
+ }
+
+ /* Allow user to set max AMDSU bit. */
+ if (sdata->ht_capa_mask.cap_info & IEEE80211_HT_CAP_MAX_AMSDU) {
+ if (sdata->ht_capa.cap_info & IEEE80211_HT_CAP_MAX_AMSDU)
+ ht_cap->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
+ else
+ ht_cap->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU;
+ }
+
+ /* Set the AMPDU factor */
+ if (sdata->ht_capa_mask.ampdu_params_info &
+ IEEE80211_HT_AMPDU_PARM_FACTOR)
+ ht_cap->ampdu_factor = sdata->ht_capa.ampdu_params_info &
+ IEEE80211_HT_AMPDU_PARM_FACTOR;
+
+ /* Set the AMPDU density */
+ if (sdata->ht_capa_mask.ampdu_params_info &
+ IEEE80211_HT_AMPDU_PARM_DENSITY)
+ ht_cap->ampdu_density =
+ (sdata->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 +165,11 @@ 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 f4a7618..f279ee9 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -598,6 +598,9 @@ struct ieee80211_sub_if_data {
bool cfg_disable_11n; /* configured to disable 11n? */
bool cfg_disable_ht40; /* configured to not use HT-40 */
+ struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */
+ struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */
+
/* Fragment table for host-based reassembly */
struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
unsigned int fragment_next;
@@ -1181,7 +1184,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 164cdb1..681ba4e 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1571,7 +1571,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;
@@ -1940,7 +1940,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;
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index 94472eb..2f546be 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,19 @@ 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 we must
+ * advert at least the first 8 rates, even if we
+ * will later force the rate control to a lower rate.
+ */
+ ieee80211_apply_htcap_overrides(sdata, &ht_cap, 8);
+
+ 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 +180,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 +370,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/nl80211.c b/net/wireless/nl80211.c
index 5696621..2cbb7c6 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1655,6 +1655,20 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
params.disable_ht40 = -1;
}
+ if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) {
+ params.ht_capa_mask =
+ nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]);
+ change = true;
+ }
+
+ if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
+ if (!params.ht_capa_mask)
+ return -EINVAL;
+ params.ht_capa =
+ nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
+ change = true;
+ }
+
if (change)
err = cfg80211_change_iface(rdev, dev, ntype, flags, ¶ms);
else
--
1.7.3.4
next prev parent reply other threads:[~2011-10-28 5:11 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-10-28 5:11 [wireless-next PATCH 1/5] mac80211: Support forcing station to disable 11n greearb
2011-10-28 5:11 ` [wireless-next PATCH 2/5] wifi: Support disabling ht40 greearb
2011-10-28 8:09 ` Johannes Berg
2011-10-28 16:25 ` Ben Greear
2011-10-28 5:11 ` greearb [this message]
2011-10-28 8:12 ` [wireless-next PATCH 3/5] wifi: Allow overriding some HT information Johannes Berg
2011-10-28 16:33 ` Ben Greear
2011-11-02 8:13 ` Johannes Berg
2011-11-02 16:59 ` Ben Greear
2011-11-02 17:49 ` Johannes Berg
2011-11-02 18:03 ` Ben Greear
2011-11-03 8:32 ` Johannes Berg
2011-10-28 5:11 ` [wireless-next PATCH 4/5] wifi: Warn if cannot add station debugfs entries greearb
2011-10-28 8:13 ` Johannes Berg
2011-10-28 16:13 ` Ben Greear
2011-10-28 5:11 ` [wireless-next PATCH 5/5] wifi-debugfs: Fix AMSDU rate printout greearb
2011-10-28 8:13 ` Johannes Berg
2011-11-17 17:49 ` Ben Greear
2011-11-17 18:03 ` John W. Linville
2011-10-28 5:15 ` [wireless-next PATCH 1/5] mac80211: Support forcing station to disable 11n Ben Greear
2011-10-28 8:08 ` Johannes Berg
2011-10-28 16:24 ` Ben Greear
2011-11-02 7:56 ` Johannes Berg
2011-11-02 16:37 ` Ben Greear
2011-10-28 18:55 ` Ben Greear
2011-11-02 7:53 ` Johannes Berg
2011-11-02 16:34 ` Ben Greear
2011-11-02 17:51 ` Johannes Berg
2011-11-03 6:04 ` Ben Greear
2011-11-03 8:30 ` Johannes Berg
2011-11-03 18:17 ` Ben Greear
2011-11-04 14:42 ` Johannes Berg
2011-11-04 16:11 ` Ben Greear
2011-11-04 16:17 ` Johannes Berg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1319778680-11405-3-git-send-email-greearb@candelatech.com \
--to=greearb@candelatech.com \
--cc=linux-wireless@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).