* Re: [PATCH v4 2/2] mac80211: Support ht-cap over-rides.
From: Johannes Berg @ 2011-11-07 17:06 UTC (permalink / raw)
To: Ben Greear; +Cc: linux-wireless
In-Reply-To: <4EB8051D.5010704@candelatech.com>
On Mon, 2011-11-07 at 08:19 -0800, Ben Greear wrote:
> > Why is this not just a static const that you fill manually? There's
> > nothing that's not constant here. So e.g.
> >
> > static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = {
> > .ampdu_params_info = IEEE80211_HT_AMPDU_PARM_FACTOR |
> > IEEE80211_HT_AMPDU_PARM_DENSITY,
> > .mcs = {
> > .rx_mask = { 0xff, 0xff, 0xff, 0xff, 0xff,
> > 0xff, 0xff, 0xff, 0xff, 0xff, },
> > },
> > /* etc */
> > };
>
> Well, you suggested a pointer in the wiphy struct that was null
> for non mac80211 interfaces. I'm not sure how to distinguish between
> mac80211 and other wiphys when reporting the capabilities if I use
> this global static. I also like that the non-static logic lets
> us tweak this for individual drivers if that becomes an issue.
Right. So if you assign this pointer in alloc_hw() then the driver can
still override it before register_hw(). I don't see at all why it needs
to be dynamically allocated.
johannes
^ permalink raw reply
* Re: [PATCH v4 1/2] wireless: Support ht-capabilities over-rides.
From: Ben Greear @ 2011-11-07 17:40 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1320656776.3993.21.camel@jlt3.sipsolutions.net>
On 11/07/2011 01:06 AM, Johannes Berg wrote:
>> @@ -537,6 +539,12 @@ 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));
>
> I think somewhere here you should mask this mask with the
> ht_capa_mod_mask. That way, you force drivers to advertise a correct
> ht_capa_mod_mask, if you don't do that we will certainly see drivers use
> more of ht_capa than contained in ht_capa_mod_mask. Probably should be a
> helper function since I think you might need it in more places.
This goes back to how hard we want to be on user-space. If we are lax,
and just ignore settings that are not (yet?) supported by the kernel,
then user-space becomes much easier to make backwards/forwards
compat. That is my preferred approach.
In order for drivers (I assume you mean mac80211 as a driver)
to support more stuff, then we will have to explicitly add
more code there. At that point, the ht-capa-mod-mask
will need to be updated to stay in sync. The mod-mask is going
to live in mac80211 as far as I can tell, it seems valid
to just keep them up to date in that manner and let user-space
be oblivious to the mask *if it prefers*.
If you feel strongly that we need to be very strict with
user-space in this case, then please say so, and I'll quite arguing
and code it up. It is going to make the hostapd code
more complex, however.
Thanks,
Ben
>
> johannes
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: [PATCH v4 1/2] wireless: Support ht-capabilities over-rides.
From: Johannes Berg @ 2011-11-07 17:42 UTC (permalink / raw)
To: Ben Greear; +Cc: linux-wireless
In-Reply-To: <4EB81817.9060300@candelatech.com>
On Mon, 2011-11-07 at 09:40 -0800, Ben Greear wrote:
> On 11/07/2011 01:06 AM, Johannes Berg wrote:
>
> >> @@ -537,6 +539,12 @@ 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));
> >
> > I think somewhere here you should mask this mask with the
> > ht_capa_mod_mask. That way, you force drivers to advertise a correct
> > ht_capa_mod_mask, if you don't do that we will certainly see drivers use
> > more of ht_capa than contained in ht_capa_mod_mask. Probably should be a
> > helper function since I think you might need it in more places.
>
> This goes back to how hard we want to be on user-space. If we are lax,
> and just ignore settings that are not (yet?) supported by the kernel,
> then user-space becomes much easier to make backwards/forwards
> compat. That is my preferred approach.
No, not really -- I'm not saying reject it, I'm just saying don't let
userspace configure more than the driver said it could configure. if you
just do essentially "configured_masked &= advertised_mask" you still
keep this property you want, but you force drivers to advertise
everything users will be able to change otherwise it just doesn't take
effect.
johannes
^ permalink raw reply
* Re: [PATCH v4 1/2] wireless: Support ht-capabilities over-rides.
From: Ben Greear @ 2011-11-07 17:45 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1320687773.3993.53.camel@jlt3.sipsolutions.net>
On 11/07/2011 09:42 AM, Johannes Berg wrote:
> On Mon, 2011-11-07 at 09:40 -0800, Ben Greear wrote:
>> On 11/07/2011 01:06 AM, Johannes Berg wrote:
>>
>>>> @@ -537,6 +539,12 @@ 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));
>>>
>>> I think somewhere here you should mask this mask with the
>>> ht_capa_mod_mask. That way, you force drivers to advertise a correct
>>> ht_capa_mod_mask, if you don't do that we will certainly see drivers use
>>> more of ht_capa than contained in ht_capa_mod_mask. Probably should be a
>>> helper function since I think you might need it in more places.
>>
>> This goes back to how hard we want to be on user-space. If we are lax,
>> and just ignore settings that are not (yet?) supported by the kernel,
>> then user-space becomes much easier to make backwards/forwards
>> compat. That is my preferred approach.
>
> No, not really -- I'm not saying reject it, I'm just saying don't let
> userspace configure more than the driver said it could configure. if you
> just do essentially "configured_masked&= advertised_mask" you still
> keep this property you want, but you force drivers to advertise
> everything users will be able to change otherwise it just doesn't take
> effect.
Ok, I think I understand, and that sounds fine to me.
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
* [PATCH] iw: fix regression in tx power validation
From: Felix Fietkau @ 2011-11-07 17:49 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes
Only bail out if the last character is *not* \0
---
phy.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/phy.c b/phy.c
index 91042b4..d9090fd 100644
--- a/phy.c
+++ b/phy.c
@@ -293,7 +293,7 @@ static int handle_txpower(struct nl80211_state *state,
}
mbm = strtol(argv[1], &endptr, 10);
- if (!*endptr)
+ if (*endptr)
return 2;
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, mbm);
} else if (argc != 1)
--
1.7.3.2
^ permalink raw reply related
* Re: [PATCH] iw: fix regression in tx power validation
From: Johannes Berg @ 2011-11-07 17:58 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-wireless
In-Reply-To: <1320688191-24689-1-git-send-email-nbd@openwrt.org>
On Mon, 2011-11-07 at 18:49 +0100, Felix Fietkau wrote:
> Only bail out if the last character is *not* \0
Oops, thanks.
> ---
> phy.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/phy.c b/phy.c
> index 91042b4..d9090fd 100644
> --- a/phy.c
> +++ b/phy.c
> @@ -293,7 +293,7 @@ static int handle_txpower(struct nl80211_state *state,
> }
>
> mbm = strtol(argv[1], &endptr, 10);
> - if (!*endptr)
> + if (*endptr)
> return 2;
> NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, mbm);
> } else if (argc != 1)
^ permalink raw reply
* Re: [PATCH] mac80211: init rate-control for TDLS sta when supp-rates are known
From: John W. Linville @ 2011-11-07 18:11 UTC (permalink / raw)
To: Jouni Malinen; +Cc: Arik Nemtsov, linux-wireless, Johannes Berg
In-Reply-To: <20111027142248.GA3972@jm.kir.nu>
On Thu, Oct 27, 2011 at 05:22:48PM +0300, Jouni Malinen wrote:
> On Wed, Oct 26, 2011 at 03:47:46PM +0200, Arik Nemtsov wrote:
> > Initialize rate control algorithms only when supported rates are known
> > for a TDLS peer sta. Direct Tx between peers is not allowed before the
> > link is enabled. In turn, this only occurs after a change_station()
> > call that sets supported rates.
>
> Thanks - this seems to fix the issues I saw previously. I tested ath9k
> with this instead of my earlier patch and was able to run successfully
> through my TDLS test scripts against another implementation.
I merged this patch from Jouni:
commit e3a4cc2f073739c9c9c2e97efc774703061f034a
Author: Jouni Malinen <j@w1.fi>
Date: Sun Oct 23 22:36:04 2011 +0300
mac80211: Fix TDLS support validation in add_station handler
We need to verify whether the command is successful before allocating
the station entry to avoid extra processing. This also fixes a memory
leak on the error path.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
I'm not sure what to do with this patch now. I think I will just drop
it, and you can send me a new patch that applies on top of Jouni's
(perhaps even reverting it) as appropriate?
Thanks,
John
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply
* RE: [PATCH] net, wireless, mwifiex: Fix mem leak in mwifiex_update_curr_bss_params()
From: Bing Zhao @ 2011-11-07 19:27 UTC (permalink / raw)
To: Srivatsa S. Bhat, Jesper Juhl
Cc: linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, John W. Linville
In-Reply-To: <4EB70920.80905@linux.vnet.ibm.com>
> On 11/07/2011 03:28 AM, Jesper Juhl wrote:
> > If kmemdup() fails we leak the memory allocated to bss_desc.
> > This patch fixes the leak.
> > I also removed the pointless default assignment of 'NULL' to 'bss_desc'
> > while I was there anyway.
> >
> > Signed-off-by: Jesper Juhl <jj@chaosbits.net>
Hi Jesper,
Thanks for the patch.
>
> Looks good to me.
> Reviewed-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Hi Srivatsa,
Thanks for your review.
Acked-by: Bing Zhao <bzhao@marvell.com>
Thanks,
Bing
>
> Thanks,
> Srivatsa S. Bhat
>
> > ---
> > drivers/net/wireless/mwifiex/scan.c | 3 ++-
> > 1 files changed, 2 insertions(+), 1 deletions(-)
> >
> > note: patch is compile tested only since I don't have the hardware.
> >
> > diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
> > index dae8dbb..8a3f959 100644
> > --- a/drivers/net/wireless/mwifiex/scan.c
> > +++ b/drivers/net/wireless/mwifiex/scan.c
> > @@ -1469,7 +1469,7 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid,
> > s32 rssi, const u8 *ie_buf, size_t ie_len,
> > u16 beacon_period, u16 cap_info_bitmap, u8 band)
> > {
> > - struct mwifiex_bssdescriptor *bss_desc = NULL;
> > + struct mwifiex_bssdescriptor *bss_desc;
> > int ret;
> > unsigned long flags;
> > u8 *beacon_ie;
> > @@ -1484,6 +1484,7 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid,
> >
> > beacon_ie = kmemdup(ie_buf, ie_len, GFP_KERNEL);
> > if (!beacon_ie) {
> > + kfree(bss_desc);
> > dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
> > return -ENOMEM;
> > }
^ permalink raw reply
* Compat-wireless release for 2011-11-07 is baked
From: Compat-wireless cronjob account @ 2011-11-07 20:02 UTC (permalink / raw)
To: linux-wireless
compat-wireless code metrics
814862 - Total upstream lines of code being pulled
2431 - backport code changes
2113 - backport code additions
318 - backport code deletions
8588 - backport from compat module
11019 - total backport code
1.3523 - % of code consists of backport work
^ permalink raw reply
* Re: [PATCH v2 00/11] ath6kl: Add WOW support
From: Kalle Valo @ 2011-11-07 21:02 UTC (permalink / raw)
To: Raja Mani; +Cc: linux-wireless
In-Reply-To: <1320643547-3578-1-git-send-email-rmani@qca.qualcomm.com>
On 11/07/2011 07:25 AM, Raja Mani wrote:
> Version 2 patch set is tested on Qualcomm MSM board and
> takes care most of the review comments given by Kalle.
>
> V2 changes:
> * WOW mode selection logic is moved to HIF layer, earlier it was implemented in CFG i/f layer.
> * Individual parameters are used in the functions instead of struct as a parameter.
> * Unused one extra byte is removed in struct wmi_add_wow_pattern_cmd.
> * Used ar->state for WOW state handling and separate WOW state handling is removed.
> * host sdio irq wake up capability is checked before entering into WOW suspend mode.
> * Empty commit logs are avoided. :-)
> * No error is reported from Sparse.
> * Rebased to multi vif implementation.
>
> and other minor corrections.
>
> Using these patch set, WOW patterns can be controlled and configured via iw command.
> Please refer iw help menu for more details.
>
> Limitations:
> * Optional bytes can't be specified while configuring WOW patterns from iw command.
> This is due to the limitation in the firmware.
>
> * Pattern byte matching will always happen from the first byte of received packet.
> This is the limitation in the recent "iw" command (It doesn't take the pattern
> offset where to start pattern matching in the received packets as of now).
Thanks, patchset looks really good now. There were two things I didn't
like, the check_wow() call in RX path and locking for
ath6kl_wmi_relinquish_implicit_pstream_credits(). But we can fix those
later.
All 11 patches applied. I did a couple of minor changes, I'll send a
separate email describing those.
Kalle
^ permalink raw reply
* Re: [PATCH v2 07/11] ath6kl: Invoke WOW suspend/resume calls during PM operation
From: Kalle Valo @ 2011-11-07 21:03 UTC (permalink / raw)
To: Raja Mani; +Cc: linux-wireless
In-Reply-To: <1320643547-3578-8-git-send-email-rmani@qca.qualcomm.com>
On 11/07/2011 07:25 AM, Raja Mani wrote:
> Link ath6kl's wow suspend/resume functions with the actual suspend/resume path.
>
> WOW mode is selected when the host sdio controller supports both
> MMC_PM_KEEP_POWER and MMC_PM_WAKE_SDIO_IRQ capabilities.
>
[...]
> @@ -1833,6 +1860,7 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar)
> ath6kl_warn("Failed to boot hw in resume: %d\n", ret);
> return ret;
> }
> + break;
>
> default:
> break;
Good catch, I had missed that break. But when you make small fixes like
this, please also mention that in the commit log.
Kalle
^ permalink raw reply
* Re: [PATCH v2 10/11] ath6kl: Remove WARN_ON msg in Suspend path
From: Kalle Valo @ 2011-11-07 21:05 UTC (permalink / raw)
To: Raja Mani; +Cc: linux-wireless
In-Reply-To: <1320643547-3578-11-git-send-email-rmani@qca.qualcomm.com>
On 11/07/2011 07:25 AM, Raja Mani wrote:
> In the current code, WOW resume is executed first from RX path
> and ar->state is moved to ATH6KL_STATE_ON. When platform calls
> ath6kl_sdio_resume() in CFG resume context, that time ar->state
> could have moved to ON state. Printing WARN_ON(1) is void in
> this context. Hence removing this.
>
> Once WOW resume is removed from RX path, This WARN_ON msg can be
> reverted.
I changed places with this and patch 9. This is to avoid useless
warnings during bisect.
Kalle
^ permalink raw reply
* Re: [PATCH] ath6kl: Fix tx packet drop in AP mode with bridge
From: Kalle Valo @ 2011-11-07 21:14 UTC (permalink / raw)
To: Vasanthakumar Thiagarajan; +Cc: linux-wireless
In-Reply-To: <1320401931-3493-1-git-send-email-vthiagar@qca.qualcomm.com>
On 11/04/2011 12:18 PM, Vasanthakumar Thiagarajan wrote:
> skb is dropped in ath6kl_data_tx() when the headroom in skb
> is insufficient. We hit this condition for every skb in AP mode
> which is used with bridge, so all tx packets are getting dropped
> when tried to send traffic to wireless client from bridge. Fix
> this by reallocating the headroom instead of dropping the skb
> when it has lesser headroom than needed.
Thanks, applied.
Kalle
^ permalink raw reply
* Re: [PATCH] ath6kl: Fix error in writing create_qos debugfs
From: Kalle Valo @ 2011-11-07 21:18 UTC (permalink / raw)
To: Vasanthakumar Thiagarajan; +Cc: linux-wireless
In-Reply-To: <1320411895-4828-1-git-send-email-vthiagar@qca.qualcomm.com>
On 11/04/2011 03:04 PM, Vasanthakumar Thiagarajan wrote:
> 100 bytes are allocated to store the parameters which are needed
> to create a priority stream. These 100 bytes are not sufficiant and
> throws error when running the following command.
>
> echo "6 2 3 1 1 9999999 9999999 9999999 7777777 0 6 45000 200 56789000
> 56789000 5678900 0 0 9999999 20000 0" > create_qos
>
> 179 bytes are needed when the following vlaues are given so that
> a maximum possible value in that data type can be given in decimal.
>
> echo "255 255 255 255 255 4294967295 4294967295 4294967295 4294967295
> 4294967295 255 65535 65535 4294967295 4294967295 4294967295 4294967295
> 4294967295 4294967295 4294967295 4294967295" > create_qos
>
> Following takes 187 bytes when given in hex
>
> echo "0xff 0xff 0xff 0xff 0xff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff
> 0xff 0xffff 0xffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff 0xffffffff
> 0xffffffff 0xffffffff" > create_qos
>
> Increase the size to 200 bytes so that it can hold upto the maximum
> value possible for that data type.
Thanks, applied.
Kalle
^ permalink raw reply
* Re: [PATCH] mac80211: init rate-control for TDLS sta when supp-rates are known
From: Arik Nemtsov @ 2011-11-07 21:22 UTC (permalink / raw)
To: John W. Linville; +Cc: Jouni Malinen, linux-wireless, Johannes Berg
In-Reply-To: <20111107181135.GD2798@tuxdriver.com>
On Mon, Nov 7, 2011 at 20:11, John W. Linville <linville@tuxdriver.com> wrote:
> I merged this patch from Jouni:
>
> commit e3a4cc2f073739c9c9c2e97efc774703061f034a
> Author: Jouni Malinen <j@w1.fi>
> Date: Sun Oct 23 22:36:04 2011 +0300
>
> mac80211: Fix TDLS support validation in add_station handler
>
> We need to verify whether the command is successful before allocating
> the station entry to avoid extra processing. This also fixes a memory
> leak on the error path.
>
> Signed-off-by: Jouni Malinen <j@w1.fi>
> Signed-off-by: John W. Linville <linville@tuxdriver.com>
>
> I'm not sure what to do with this patch now. I think I will just drop
> it, and you can send me a new patch that applies on top of Jouni's
> (perhaps even reverting it) as appropriate?
Actually the merged patch from Jouni is unrelated to this fix (and
should have been merged). There's a different patch from Jouni that
should not be applied - "mac80211: Fix STA supported rate
configuration with dummy entry".
I'll resend this one after rebasing to the latest wireless-testing
(there was a conflict).
Arik
^ permalink raw reply
* [PATCH v2] mac80211: init rate-control for TDLS sta when supp-rates are known
From: Arik Nemtsov @ 2011-11-07 21:24 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg, John W. Linville, Arik Nemtsov
Initialize rate control algorithms only when supported rates are known
for a TDLS peer sta. Direct Tx between peers is not allowed before the
link is enabled. In turn, this only occurs after a change_station()
call that sets supported rates.
Signed-off-by: Arik Nemtsov <arik@wizery.com>
---
v1->2: rebase on top of wireless-testing
net/mac80211/cfg.c | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a9ded52..8f774cb 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -847,7 +847,12 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
sta_apply_parameters(local, sta, params);
- rate_control_rate_init(sta);
+ /*
+ * for TDLS, rate control should be initialized only when supported
+ * rates are known.
+ */
+ if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER))
+ rate_control_rate_init(sta);
layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
sdata->vif.type == NL80211_IFTYPE_AP;
@@ -931,6 +936,9 @@ static int ieee80211_change_station(struct wiphy *wiphy,
sta_apply_parameters(local, sta, params);
+ if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && params->supported_rates)
+ rate_control_rate_init(sta);
+
rcu_read_unlock();
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
--
1.7.5.4
^ permalink raw reply related
* [PATCH v5 1/2] wireless: Support ht-capabilities over-rides.
From: greearb @ 2011-11-07 21:35 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>
---
* Removed DISABLE_HT40 variable..instead just modify ht-cap
flags to disable ht-40.
* Mask out un-supported values. Will not return error, but will
force driver to keep the mod-mask up to date if someone wants to
override additional features.
:100644 100644 8049bf7... 5b86a3b... M include/linux/nl80211.h
:100644 100644 92cf1c2... cc7e995... M include/net/cfg80211.h
:100644 100644 b9ec306... dd6feda... M net/wireless/core.h
:100644 100644 21fc970... e0d3a50... 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..cc7e995 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_msk: 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;
+ 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..e0d3a50 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,
+ 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
* [PATCH v5 2/2] mac80211: Support ht-cap over-rides.
From: greearb @ 2011-11-07 21:35 UTC (permalink / raw)
To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <1320701702-13968-1-git-send-email-greearb@candelatech.com>
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>
---
* Remove disable-ht40 option...just modify the ht-cap flags instead.
* Use static for ht-cap-mod-mask struct.
: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
* [PATCH] iw: Support ht-capability overrides mask.
From: greearb @ 2011-11-07 21:56 UTC (permalink / raw)
To: linux-wireless; +Cc: Ben Greear
From: Ben Greear <greearb@candelatech.com>
Let user know which capabilities are supported.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
NOTE: This should not be applied until the kernel portions
are accepted.
:100644 100644 b55b282... fdb523d... M info.c
:100644 100644 8049bf7... 20710b1... M nl80211.h
info.c | 32 ++++++++++++++++++++++++++++++++
nl80211.h | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 85 insertions(+), 0 deletions(-)
diff --git a/info.c b/info.c
index b55b282..fdb523d 100644
--- a/info.c
+++ b/info.c
@@ -400,6 +400,38 @@ broken_combination:
if (tb_msg[NL80211_ATTR_SUPPORT_AP_UAPSD])
printf("\tDevice supports AP-side u-APSD.\n");
+ if (tb_msg[NL80211_ATTR_HT_CAPABILITY_MASK]) {
+ struct ieee80211_ht_cap *cm;
+ printf("\tHT Capabilities over-rides:\n");
+ if (nla_len(tb_msg[NL80211_ATTR_HT_CAPABILITY_MASK]) >=
+ sizeof(*cm)) {
+ cm = nla_data(tb_msg[NL80211_ATTR_HT_CAPABILITY_MASK]);
+ printf("\t\t* MCS: %02hx %02hx %02hx %02hx %02hx %02hx"
+ " %02hx %02hx %02hx %02hx\n",
+ cm->mcs.rx_mask[0], cm->mcs.rx_mask[1],
+ cm->mcs.rx_mask[2], cm->mcs.rx_mask[3],
+ cm->mcs.rx_mask[4], cm->mcs.rx_mask[5],
+ cm->mcs.rx_mask[6], cm->mcs.rx_mask[7],
+ cm->mcs.rx_mask[8], cm->mcs.rx_mask[9]);
+ printf("\t\t* MAX-AMSDU: %s\n"
+ "\t\t* WIDTH-20-40: %s\n"
+ "\t\t* SGI-40: %s\n"
+ "\t\t* AMPDU-Factor: %s\n"
+ "\t\t* AMPDU-Density: %s\n",
+ cm->cap_info & IEEE80211_HT_CAP_MAX_AMSDU ? "Yes" : "No",
+ cm->cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ? "Yes" : "No",
+ cm->cap_info & IEEE80211_HT_CAP_SGI_40 ? "Yes" : "No",
+ cm->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_FACTOR ? "Yes" : "No",
+ cm->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_DENSITY ? "Yes" : "No");
+ } else {
+ printf("\tERROR: capabilities mask is too short, expected: %d"
+ ", received: %d\n",
+ sizeof(*cm), nla_len(tb_msg[NL80211_ATTR_HT_CAPABILITY_MASK]));
+ }
+ } else {
+ printf("\tHT Capabilities over-rides are NOT supported.\n");
+ }
+
return NL_SKIP;
}
diff --git a/nl80211.h b/nl80211.h
index 8049bf7..20710b1 100644
--- a/nl80211.h
+++ b/nl80211.h
@@ -1109,6 +1109,10 @@ 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 +1341,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,
@@ -1421,6 +1428,52 @@ enum nl80211_iftype {
NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1
};
+/* 802.11n HT capability AMPDU settings (for ampdu_params_info) */
+#define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03
+#define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C
+
+#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002
+#define IEEE80211_HT_CAP_SGI_40 0x0040
+#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800
+
+#define IEEE80211_HT_MCS_MASK_LEN 10
+
+/**
+ * struct ieee80211_mcs_info - MCS information
+ * @rx_mask: RX mask
+ * @rx_highest: highest supported RX rate. If set represents
+ * the highest supported RX data rate in units of 1 Mbps.
+ * If this field is 0 this value should not be used to
+ * consider the highest RX data rate supported.
+ * @tx_params: TX parameters
+ */
+struct ieee80211_mcs_info {
+ __u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN];
+ __u16 rx_highest;
+ __u8 tx_params;
+ __u8 reserved[3];
+} __attribute__ ((packed));
+
+
+/**
+ * struct ieee80211_ht_cap - HT capabilities
+ *
+ * This structure is the "HT capabilities element" as
+ * described in 802.11n D5.0 7.3.2.57
+ */
+struct ieee80211_ht_cap {
+ __u16 cap_info;
+ __u8 ampdu_params_info;
+
+ /* 16 bytes MCS information */
+ struct ieee80211_mcs_info mcs;
+
+ __u16 extended_ht_cap_info;
+ __u32 tx_BF_cap_info;
+ __u8 antenna_selection_info;
+} __attribute__ ((packed));
+
+
/**
* enum nl80211_sta_flags - station flags
*
--
1.7.3.4
^ permalink raw reply related
* Re: [PATCH v5 1/2] wireless: Support ht-capabilities over-rides.
From: Ben Greear @ 2011-11-07 22:52 UTC (permalink / raw)
To: greearb; +Cc: linux-wireless
In-Reply-To: <1320701702-13968-1-git-send-email-greearb@candelatech.com>
On 11/07/2011 01:35 PM, greearb@candelatech.com wrote:
> 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>
> ---
>
> * Removed DISABLE_HT40 variable..instead just modify ht-cap
> flags to disable ht-40.
>
> * Mask out un-supported values. Will not return error, but will
> force driver to keep the mod-mask up to date if someone wants to
> override additional features.
>
> :100644 100644 8049bf7... 5b86a3b... M include/linux/nl80211.h
> :100644 100644 92cf1c2... cc7e995... M include/net/cfg80211.h
> :100644 100644 b9ec306... dd6feda... M net/wireless/core.h
> :100644 100644 21fc970... e0d3a50... 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..cc7e995 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_msk: 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;
>
> + struct ieee80211_ht_cap *ht_capa_mod_mask;
Gah, this needs to be const.. I'll send a new patch with
this change shortly.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* [PATCH v6 1/2] wireless: Support ht-capabilities over-rides.
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
* [PATCH v6 2/2] mac80211: Support ht-cap over-rides.
From: greearb @ 2011-11-07 23:14 UTC (permalink / raw)
To: linux-wireless; +Cc: Ben Greear
In-Reply-To: <1320707676-17255-1-git-send-email-greearb@candelatech.com>
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
* Re: iwlagn is getting very shaky
From: Guy, Wey-Yi @ 2011-11-07 23:37 UTC (permalink / raw)
To: Norbert Preining
Cc: David Rientjes, linux-kernel@vger.kernel.org,
ipw3945-devel@lists.sourceforge.net, ilw@linux.intel.com,
linux-wireless@vger.kernel.org, Pekka Enberg
In-Reply-To: <20111107123812.GB23508@gamma.logic.tuwien.ac.at>
[-- Attachment #1: Type: text/plain, Size: 5024 bytes --]
Hi Norbert,
Could you please try with this patch?
Thanks
Wey
On Mon, 2011-11-07 at 04:38 -0800, Norbert Preining wrote:
> Hi Wey, hi all,
>
> On Fr, 04 Nov 2011, Norbert Preining wrote:
> > > after the firmware reloaded, is the traffic resume? or it is continuous
> > > without traffic?
> >
> > Ok, I compiled a new kernel from todays git, and I see that there
> > are kernel bugs, but after the hardware restart traffic gets through.
>
> Well, not always actually. I just had *at*home*, were it used to work
> without any flaws till 3.1, I saw that after resume it worked for a
> short time, then the queue got stuck, then not even forcing a reset via
> the /ss/kernel/debug/..../iwlwifi/debug/force_reset did work. Only
> an unload and reload of the module, followed by a few more hickups,
> restarted the wlan card:
>
> [ 6564.905884] PM: Finishing wakeup.
> [ 6564.905889] Restarting tasks ... done.
> [ 6564.924087] video LNXVIDEO:00: Restoring backlight state
> [ 6566.045358] e1000e 0000:00:19.0: irq 45 for MSI/MSI-X
> [ 6566.100108] e1000e 0000:00:19.0: irq 45 for MSI/MSI-X
> [ 6566.101277] iwlwifi 0000:06:00.0: L1 Enabled; Disabling L0S
> [ 6566.105210] iwlwifi 0000:06:00.0: Radio type=0x1-0x2-0x0
> [ 6573.822081] wlan0: authenticate with 00:0a:79:eb:56:10 (try 1)
> [ 6573.829824] wlan0: authenticated
> [ 6573.835543] wlan0: associate with 00:0a:79:eb:56:10 (try 1)
> [ 6573.841527] wlan0: RX AssocResp from 00:0a:79:eb:56:10 (capab=0x411 status=0 aid=2)
> [ 6573.841537] wlan0: associated
>
> Here it worked for a bit, 20secs
>
> [ 6593.731625] iwlwifi 0000:06:00.0: Tx aggregation enabled on ra = 00:0a:79:eb:56:10 tid = 0
> [ 6603.704072] iwlwifi 0000:06:00.0: Queue 11 stuck for 10000 ms.
> [ 6603.704084] iwlwifi 0000:06:00.0: Current read_ptr 249 write_ptr 14
> [ 6603.704092] iwlwifi 0000:06:00.0: On demand firmware reload
> [ 6603.704566] ieee80211 phy0: Hardware restart was requested
> [ 6603.704680] iwlwifi 0000:06:00.0: L1 Enabled; Disabling L0S
> [ 6603.707700] iwlwifi 0000:06:00.0: Radio type=0x1-0x2-0x0
>
> Here I forced the reset
>
> [ 6774.772656] iwlwifi 0000:06:00.0: On demand firmware reload
> [ 6774.773868] ieee80211 phy0: Hardware restart was requested
> [ 6774.773958] iwlwifi 0000:06:00.0: L1 Enabled; Disabling L0S
> [ 6774.777053] iwlwifi 0000:06:00.0: Radio type=0x1-0x2-0x0
>
> unloading and reloading
>
> [ 6823.909282] wlan0: deauthenticating from 00:0a:79:eb:56:10 by local choice (reason=3)
> [ 6823.976417] cfg80211: Calling CRDA for country: JP
> [ 6824.037466] iwlwifi 0000:06:00.0: PCI INT A disabled
> [ 6830.344831] Intel(R) Wireless WiFi Link AGN driver for Linux, in-tree:d
> [ 6830.344835] Copyright(c) 2003-2011 Intel Corporation
> [ 6830.344941] iwlwifi 0000:06:00.0: PCI INT A -> GSI 17 (level, low) -> IRQ 17
> [ 6830.344974] iwlwifi 0000:06:00.0: setting latency timer to 64
> [ 6830.345174] iwlwifi 0000:06:00.0: pci_resource_len = 0x00002000
> [ 6830.345176] iwlwifi 0000:06:00.0: pci_resource_base = ffffc90000048000
> [ 6830.345179] iwlwifi 0000:06:00.0: HW Revision ID = 0x0
> [ 6830.345292] iwlwifi 0000:06:00.0: irq 46 for MSI/MSI-X
> [ 6830.345369] iwlwifi 0000:06:00.0: Detected Intel(R) WiFi Link 5100 AGN, REV=0x54
> [ 6830.345467] iwlwifi 0000:06:00.0: L1 Enabled; Disabling L0S
> [ 6830.367544] iwlwifi 0000:06:00.0: device EEPROM VER=0x11e, CALIB=0x4
> [ 6830.367547] iwlwifi 0000:06:00.0: Device SKU: 0Xf0
> [ 6830.367557] iwlwifi 0000:06:00.0: Tunable channels: 13 802.11bg, 24 802.11a channels
> [ 6830.425994] iwlwifi 0000:06:00.0: loaded firmware version 8.83.5.1 build 33692 (EXP)
> [ 6830.426214] Registered led device: phy1-led
> [ 6830.426519] ieee80211 phy1: Selected rate control algorithm 'iwl-agn-rs'
>
> more hickups
>
> [ 6830.518627] iwlwifi 0000:06:00.0: L1 Enabled; Disabling L0S
> [ 6830.522336] iwlwifi 0000:06:00.0: Radio type=0x1-0x2-0x0
> [ 6830.636966] iwlwifi 0000:06:00.0: L1 Enabled; Disabling L0S
> [ 6830.640324] iwlwifi 0000:06:00.0: Radio type=0x1-0x2-0x0
> [ 6838.327066] wlan0: authenticate with 00:0a:79:eb:56:10 (try 1)
> [ 6838.330447] wlan0: authenticated
> [ 6838.335890] wlan0: associate with 00:0a:79:eb:56:10 (try 1)
> [ 6838.341503] wlan0: RX AssocResp from 00:0a:79:eb:56:10 (capab=0x411 status=0 aid=2)
> [ 6838.341507] wlan0: associated
>
> finally got it working, one more final hickup
>
> [ 6860.602423] iwlwifi 0000:06:00.0: Tx aggregation enabled on ra = 00:0a:79:eb:56:10 tid = 0
>
> from now on working
>
> Would be great to fix that for 3.2
>
> Herzliche Grüße
>
> Norbert
> ------------------------------------------------------------------------
> Norbert Preining preining@{jaist.ac.jp, logic.at, debian.org}
> JAIST, Japan TeX Live & Debian Developer
> DSA: 0x09C5B094 fp: 14DF 2E6C 0307 BE6D AD76 A9C0 D2BF 4AA3 09C5 B094
> ------------------------------------------------------------------------
> PEEBLES (pl.n.)
> Small, carefully rolled pellets of skegness (q.v.)
> --- Douglas Adams, The Meaning of Liff
[-- Attachment #2: [Internal-wifi-devel]_[PATCH]_iwlwifi:_check_the_HW_when_a_queue_is_stuck --]
[-- Type: application/mbox, Size: 4362 bytes --]
^ permalink raw reply
* [PATCH RESEND 0/4] mwifiex: resending missed patches
From: Bing Zhao @ 2011-11-08 3:31 UTC (permalink / raw)
To: linux-wireless
Cc: John W. Linville, Dan Carpenter, Amitkumar Karwar, Kiran Divekar,
Yogesh Powar, Frank Huang, Bing Zhao
Hi John,
These patches have been sent before. I'm resending them with my
Acked-by or Signed-off-by.
Could you please merge them to wireless-testing.git?
Thanks,
Bing
---
Amitkumar Karwar (1):
mwifiex: enable SDIO multiport aggregation
Dan Carpenter (3):
mwifiex: remove unneeded kfree(NULL);
mwifiex: remove an unneeded NULL check
mwifiex: prevent corruption instead of just warning
drivers/net/wireless/mwifiex/pcie.c | 11 ++++++-----
drivers/net/wireless/mwifiex/sdio.c | 4 ++--
2 files changed, 8 insertions(+), 7 deletions(-)
^ permalink raw reply
* [PATCH RESEND 2/4] mwifiex: remove an unneeded NULL check
From: Bing Zhao @ 2011-11-08 3:31 UTC (permalink / raw)
To: linux-wireless
Cc: John W. Linville, Dan Carpenter, Amitkumar Karwar, Kiran Divekar,
Yogesh Powar, Frank Huang, Bing Zhao
In-Reply-To: <1320723107-24202-1-git-send-email-bzhao@marvell.com>
From: Dan Carpenter <dan.carpenter@oracle.com>
We dereference adapter in the error handling code so this needed to
be fixed. This function is always called like:
adapter->if_ops.host_to_card(adapter, ...);
so adapter can never be NULL and I've removed the NULL check.
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Acked-by: Bing Zhao <bzhao@marvell.com>
---
drivers/net/wireless/mwifiex/pcie.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 4466976..d12d440 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -1671,9 +1671,8 @@ static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type,
struct sk_buff *skb,
struct mwifiex_tx_param *tx_param)
{
- if (!adapter || !skb) {
- dev_err(adapter->dev, "Invalid parameter in %s <%p, %p>\n",
- __func__, adapter, skb);
+ if (!skb) {
+ dev_err(adapter->dev, "Passed NULL skb to %s\n", __func__);
return -1;
}
--
1.7.0.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox