* Re: [PATCH] compat: backport eth_change_mtu and eth_validate_addr
From: Luis R. Rodriguez @ 2010-05-06 0:41 UTC (permalink / raw)
To: Hauke Mehrtens; +Cc: linux-wireless, mcgrof
In-Reply-To: <1273098457-21658-1-git-send-email-hauke@hauke-m.de>
On Wed, May 5, 2010 at 3:27 PM, Hauke Mehrtens <hauke@hauke-m.de> wrote:
>
> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Awesome, thanks.
Luis
^ permalink raw reply
* Re: [PATCH] compat-wireless: rt2x00 added to driver-select
From: Luis R. Rodriguez @ 2010-05-06 0:39 UTC (permalink / raw)
To: Walter Goldens; +Cc: linux-wireless, users
In-Reply-To: <946956.98853.qm@web56807.mail.re3.yahoo.com>
On Wed, May 5, 2010 at 2:44 AM, Walter Goldens <goldenstranger@yahoo.com> wrote:
> Signed-off-by: Walter Goldens <goldenstranger@yahoo.com>
Thanks! Applied.
Luis
^ permalink raw reply
* Re: carl9170 1.0.5.1
From: Luis R. Rodriguez @ 2010-05-06 0:11 UTC (permalink / raw)
To: dhlii; +Cc: Christian Lamparter, linux-wireless
In-Reply-To: <4BE1BBD6.3030505@dlasys.net>
On Wed, May 5, 2010 at 11:41 AM, David H. Lynch Jr. <dhlii@dlasys.net> wrote:
> I am trying to build a kernel using the carl9170 driver/firmware.
> I am not particular about what kernel or how so long as I can get it
> running.
>
> When I build out of the wireless-testing git tree (puled today)
> 2.6.34-rc6
> using my current systems .config I get a very quick error on boot about
> PCI bridge windows.
> googling the error indicates this is a know 2.6.34 problem and that there
> are fixes in other 2.6.34 trees.
> I have been unable to find the actual patches or I would just apply them
> to wireless-testing.
>
> Alternately, I tried to build out of the ubuntu-lucid git tree. 2.6.32
> again with my existing .config.
> I the carl9170 driver does not build. While I found patches at OpenWRT
> that are supposed to allow building carl9170 with 2.6.33 or less,
> the errors are unrelated to what is changed by those patches.
>
> I have also tried using linux-source-2.6.32 pulled from cannonical via
> apt for my install rather than the ubuntu-lucid git tree
> with similar results.
You can build the driver with compat-wireless so that way you can keep
your existing functional kernel and only backport the driver. We did
this way back when we first started doing development on ath9k and it
worked well.
Luis
^ permalink raw reply
* Re: pull request: wireless-next-2.6 2010-05-05
From: David Miller @ 2010-05-05 22:40 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, netdev
In-Reply-To: <20100505203528.GB2603@tuxdriver.com>
From: "John W. Linville" <linville@tuxdriver.com>
Date: Wed, 5 May 2010 16:35:29 -0400
> Dave,
>
> Another enormous batch intended for 2.6.35... This is mostly the 'usual
> suspects' -- driver updates from Intel, Atheros, Nokia, and the rt2x00
> guys, mac80211 stuff from Johannes, and a variety of other bits. One
> noteworth bit is the addition of the orinoco_usb driver.
Pulled, thanks John.
^ permalink raw reply
* [PATCH v2] mac80211: Add HT IE to IBSS beacons and probe responses.
From: Benoit Papillault @ 2010-05-05 22:36 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Benoit Papillault
In-Reply-To: <1273098986-19330-1-git-send-email-benoit.papillault@free.fr>
When an HT IBSS is configured, we add HT Information and HT Capabilities
IE to beacons & probe responses. This is done according to channel_type
transmitted by iw/cfg80211.
v2: Added helpers to build HT Capability & HT Information IE
Signed-off-by: Benoit Papillault <benoit.papillault@free.fr>
---
net/mac80211/ibss.c | 64 +++++++++++++++++++++++++---
net/mac80211/ieee80211_i.h | 10 ++++
net/mac80211/util.c | 98 ++++++++++++++++++++++++++++++++++---------
3 files changed, 144 insertions(+), 28 deletions(-)
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index b72ee64..2371d69 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -64,6 +64,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
const u8 *bssid, const int beacon_int,
struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type,
const u32 basic_rates,
const u16 capability, u64 tsf)
{
@@ -103,7 +104,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
local->oper_channel = chan;
- local->oper_channel_type = NL80211_CHAN_NO_HT;
+ local->oper_channel_type = channel_type;
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
sband = local->hw.wiphy->bands[chan->band];
@@ -118,7 +119,10 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
*pos++ = basic | (u8) (rate / 5);
}
- /* Build IBSS probe response */
+ /*
+ * Build IBSS probe response template (this template is also used
+ * when sending beacon, see ieee80211_beacon_get_tim())
+ */
mgmt = (void *) skb_put(skb, 24 + sizeof(mgmt->u.beacon));
memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
@@ -165,6 +169,14 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
memcpy(pos, &supp_rates[8], rates);
}
+ if (channel_type != NL80211_CHAN_NO_HT &&
+ sband->ht_cap.ht_supported) {
+ pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_cap));
+ ieee80211_add_ht_cap(&pos, sband);
+ pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_info));
+ ieee80211_add_ht_info(&pos, sband, chan, channel_type);
+ }
+
if (ifibss->ie_len)
memcpy(skb_put(skb, ifibss->ie_len),
ifibss->ie, ifibss->ie_len);
@@ -202,6 +214,9 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
u32 basic_rates;
int i, j;
u16 beacon_int = cbss->beacon_interval;
+ const u8 * ht_info_ie;
+ const struct ieee80211_ht_info *ht_info;
+ enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
if (beacon_int < 10)
beacon_int = 10;
@@ -223,9 +238,28 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
}
}
+ /* parse HT Information IE, if present */
+ ht_info_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_INFORMATION);
+ if (ht_info_ie) {
+ ht_info = (const struct ieee80211_ht_info *)(ht_info_ie + 2);
+ switch (ht_info->ht_param
+ & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
+ case IEEE80211_HT_PARAM_CHA_SEC_NONE:
+ channel_type = NL80211_CHAN_HT20;
+ break;
+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+ channel_type = NL80211_CHAN_HT40PLUS;
+ break;
+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+ channel_type = NL80211_CHAN_HT40MINUS;
+ break;
+ }
+ }
+
__ieee80211_sta_join_ibss(sdata, cbss->bssid,
beacon_int,
cbss->channel,
+ channel_type,
basic_rates,
cbss->capability,
cbss->tsf);
@@ -529,7 +563,8 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
sdata->drop_unencrypted = 0;
__ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
- ifibss->channel, 3, /* first two are basic */
+ ifibss->channel, ifibss->channel_type,
+ 3, /* first two are basic */
capability, 0);
}
@@ -906,6 +941,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
sdata->vif.bss_conf.beacon_int = params->beacon_interval;
sdata->u.ibss.channel = params->channel;
+ sdata->u.ibss.channel_type = params->channel_type;
sdata->u.ibss.fixed_channel = params->channel_fixed;
/* fix ourselves to that channel now already */
@@ -921,11 +957,25 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
sdata->u.ibss.ie_len = params->ie_len;
}
+ /*
+ * Allocate IBSS probe response template (see
+ * __ieee80211_sta_join_ibss for the needed size). According to IEEE
+ * 802.11-2007 10.4.4.2, there is only 20 possibles values. We
+ * support up IEEE80211_MAX_SUPP_RATES (currently 32) : so 8 for
+ * Supported Rates and IEEE80211_MAX_SUPP_RATES-8 for Extended
+ * Supported Rates
+ */
+
skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
- 36 /* bitrates */ +
- 34 /* SSID */ +
- 3 /* DS params */ +
- 4 /* IBSS params */ +
+ sizeof(struct ieee80211_hdr_3addr) +
+ 12 /* struct ieee80211_mgmt.u.beacon */ +
+ 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ +
+ 2 + 8 /* max Supported Rates */ +
+ 3 /* max DS params */ +
+ 4 /* IBSS params */ +
+ 2 + (IEEE80211_MAX_SUPP_RATES-8) /* max Ext Rates */ +
+ 2 + sizeof(struct ieee80211_ht_cap) +
+ 2 + sizeof(struct ieee80211_ht_info) +
params->ie_len);
if (!skb)
return -ENOMEM;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index c8077a3..b3a5d3c 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -404,6 +404,7 @@ struct ieee80211_if_ibss {
u8 ssid_len, ie_len;
u8 *ie;
struct ieee80211_channel *channel;
+ enum nl80211_channel_type channel_type;
unsigned long ibss_join_req;
/* probe response/beacon for IBSS */
@@ -1193,6 +1194,15 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
u16 transaction, u16 auth_alg,
u8 *extra, size_t extra_len, const u8 *bssid,
const u8 *key, u8 key_len, u8 key_idx);
+
+int ieee80211_add_ht_cap(u8 **ppos,
+ struct ieee80211_supported_band *sband);
+
+int ieee80211_add_ht_info(u8 **ppos,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_channel *channel,
+ enum nl80211_channel_type channel_type);
+
int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
const u8 *ie, size_t ie_len,
enum ieee80211_band band);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 2b75b4f..cc08411 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -898,6 +898,82 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
ieee80211_tx_skb(sdata, skb);
}
+int ieee80211_add_ht_cap(u8 **ppos,
+ struct ieee80211_supported_band *sband)
+{
+ u16 cap = sband->ht_cap.cap;
+ struct ieee80211_ht_cap ht_cap;
+ u8 *pos = *ppos;
+
+ if (ieee80211_disable_40mhz_24ghz &&
+ sband->band == IEEE80211_BAND_2GHZ) {
+ cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ cap &= ~IEEE80211_HT_CAP_SGI_40;
+ }
+
+ ht_cap.cap_info = cpu_to_le16(cap);
+ ht_cap.ampdu_params_info = sband->ht_cap.ampdu_factor |
+ (sband->ht_cap.ampdu_density <<
+ IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
+ ht_cap.mcs = sband->ht_cap.mcs;
+ ht_cap.extended_ht_cap_info = cpu_to_le16(0);
+ ht_cap.tx_BF_cap_info = cpu_to_le32(0);
+ ht_cap.antenna_selection_info = 0;
+
+ /* HT Capabilities element */
+ *pos++ = WLAN_EID_HT_CAPABILITY;
+ *pos++ = sizeof(struct ieee80211_ht_cap);
+ memcpy(pos, &ht_cap, sizeof(struct ieee80211_ht_cap));
+ pos += sizeof(struct ieee80211_ht_cap);
+
+ *ppos = pos;
+
+ return 1;
+}
+
+int ieee80211_add_ht_info(u8 **ppos,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_channel *channel,
+ enum nl80211_channel_type channel_type)
+{
+ struct ieee80211_ht_info ht_info;
+ u8 *pos = *ppos;
+
+ ht_info.control_chan =
+ ieee80211_frequency_to_channel(channel->center_freq);
+ ht_info.ht_param = 0;
+ switch (channel_type) {
+ case NL80211_CHAN_NO_HT: /* to make compiler happy */
+ case NL80211_CHAN_HT20:
+ ht_info.ht_param |= IEEE80211_HT_PARAM_CHA_SEC_NONE;
+ break;
+ case NL80211_CHAN_HT40MINUS:
+ ht_info.ht_param |= IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ break;
+ case NL80211_CHAN_HT40PLUS:
+ ht_info.ht_param |= IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ break;
+ }
+ if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
+ ht_info.ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
+ ht_info.operation_mode = cpu_to_le16(0);
+ ht_info.stbc_param = cpu_to_le16(0);
+ /* It seems that Basic MCS set and Supported MCS set are identical
+ * for the first 10 bytes */
+ memset(&ht_info.basic_set, 0, 16);
+ memcpy(&ht_info.basic_set, &sband->ht_cap.mcs, 10);
+
+ /* HT Information element */
+ *pos++ = WLAN_EID_HT_INFORMATION;
+ *pos++ = sizeof(struct ieee80211_ht_info);
+ memcpy(pos, &ht_info, sizeof(struct ieee80211_ht_info));
+ pos += sizeof(struct ieee80211_ht_info);
+
+ *ppos = pos;
+
+ return 1;
+}
+
int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
const u8 *ie, size_t ie_len,
enum ieee80211_band band)
@@ -966,27 +1042,7 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
}
if (sband->ht_cap.ht_supported) {
- u16 cap = sband->ht_cap.cap;
- __le16 tmp;
-
- if (ieee80211_disable_40mhz_24ghz &&
- sband->band == IEEE80211_BAND_2GHZ) {
- cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- cap &= ~IEEE80211_HT_CAP_SGI_40;
- }
-
- *pos++ = WLAN_EID_HT_CAPABILITY;
- *pos++ = sizeof(struct ieee80211_ht_cap);
- memset(pos, 0, sizeof(struct ieee80211_ht_cap));
- tmp = cpu_to_le16(cap);
- memcpy(pos, &tmp, sizeof(u16));
- pos += sizeof(u16);
- *pos++ = sband->ht_cap.ampdu_factor |
- (sband->ht_cap.ampdu_density <<
- IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
- memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
- pos += sizeof(sband->ht_cap.mcs);
- pos += 2 + 4 + 1; /* ext info, BF cap, antsel */
+ ieee80211_add_ht_cap(&pos, sband);
}
/*
--
1.5.6.5
^ permalink raw reply related
* [PATCH v2] cfg80211: Parse channel_type in NL80211_CMD_JOIN_IBSS
From: Benoit Papillault @ 2010-05-05 22:36 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Benoit Papillault
The channel_type field is filled by iw and parse by cfg80211 before
being sent to mac80211 for instance (we also check if the specified
channel is capable of ht40+, ht40- or ht20). This information is needed
to properly configure an HT IBSS.
It requires a patch to iw to fill this field.
Signed-off-by: Benoit Papillault <benoit.papillault@free.fr>
---
include/net/cfg80211.h | 1 +
net/wireless/nl80211.c | 20 ++++++++++++++++----
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7d10c01..93e5558 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -806,6 +806,7 @@ struct cfg80211_ibss_params {
u8 *ssid;
u8 *bssid;
struct ieee80211_channel *channel;
+ enum nl80211_channel_type channel_type;
u8 *ie;
u8 ssid_len, ie_len;
u16 beacon_interval;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 01da83d..0a82623 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3792,6 +3792,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
struct cfg80211_ibss_params ibss;
struct wiphy *wiphy;
struct cfg80211_cached_keys *connkeys = NULL;
+ enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
int err;
memset(&ibss, 0, sizeof(ibss));
@@ -3813,6 +3814,17 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}
+ if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
+ channel_type = nla_get_u32(
+ info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
+ if (channel_type != NL80211_CHAN_NO_HT &&
+ channel_type != NL80211_CHAN_HT20 &&
+ channel_type != NL80211_CHAN_HT40PLUS &&
+ channel_type != NL80211_CHAN_HT40MINUS)
+ return -EINVAL;
+ }
+ ibss.channel_type = channel_type;
+
rtnl_lock();
err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
@@ -3846,11 +3858,11 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
}
- ibss.channel = ieee80211_get_channel(wiphy,
- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
+ ibss.channel = rdev_freq_to_chan(rdev,
+ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
+ channel_type);
if (!ibss.channel ||
- ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
- ibss.channel->flags & IEEE80211_CHAN_DISABLED) {
+ ibss.channel->flags & IEEE80211_CHAN_NO_IBSS) {
err = -EINVAL;
goto out;
}
--
1.5.6.5
^ permalink raw reply related
* [PATCH] compat: backport eth_change_mtu and eth_validate_addr
From: Hauke Mehrtens @ 2010-05-05 22:27 UTC (permalink / raw)
To: lrodriguez; +Cc: linux-wireless, mcgrof, Hauke Mehrtens
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
compat/compat-2.6.29.c | 26 ++++++++++++++++++++++++++
include/linux/compat-2.6.29.h | 2 ++
2 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/compat/compat-2.6.29.c b/compat/compat-2.6.29.c
index 5ee1e44..8c725ee 100644
--- a/compat/compat-2.6.29.c
+++ b/compat/compat-2.6.29.c
@@ -98,6 +98,32 @@ int eth_mac_addr(struct net_device *dev, void *p)
return 0;
}
EXPORT_SYMBOL(eth_mac_addr);
+
+/**
+ * eth_change_mtu - set new MTU size
+ * @dev: network device
+ * @new_mtu: new Maximum Transfer Unit
+ *
+ * Allow changing MTU size. Needs to be overridden for devices
+ * supporting jumbo frames.
+ */
+int eth_change_mtu(struct net_device *dev, int new_mtu)
+{
+ if (new_mtu < 68 || new_mtu > ETH_DATA_LEN)
+ return -EINVAL;
+ dev->mtu = new_mtu;
+ return 0;
+}
+EXPORT_SYMBOL(eth_change_mtu);
+
+int eth_validate_addr(struct net_device *dev)
+{
+ if (!is_valid_ether_addr(dev->dev_addr))
+ return -EADDRNOTAVAIL;
+
+ return 0;
+}
+EXPORT_SYMBOL(eth_validate_addr);
/* Source: net/ethernet/eth.c */
diff --git a/include/linux/compat-2.6.29.h b/include/linux/compat-2.6.29.h
index 165b78c..f063e24 100644
--- a/include/linux/compat-2.6.29.h
+++ b/include/linux/compat-2.6.29.h
@@ -246,6 +246,8 @@ extern void usb_unpoison_anchored_urbs(struct usb_anchor *anchor);
)
extern int eth_mac_addr(struct net_device *dev, void *p);
+extern int eth_change_mtu(struct net_device *dev, int new_mtu);
+extern int eth_validate_addr(struct net_device *dev);
#else
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH] compat-wireless: updates for orinoco
From: Luis R. Rodriguez @ 2010-05-05 22:23 UTC (permalink / raw)
To: Johannes Berg
Cc: Luis Rodriguez, Hauke Mehrtens, linux-wireless@vger.kernel.org
In-Reply-To: <1273041903.3728.0.camel@jlt3.sipsolutions.net>
On Tue, May 04, 2010 at 11:45:03PM -0700, Johannes Berg wrote:
> On Tue, 2010-05-04 at 16:26 -0700, Luis R. Rodriguez wrote:
>
> > void netdev_attach_ops(struct net_device *dev,
> > const struct net_device_ops *ops)
> > {
> > #define SET_NETDEVOP(_op) (_op ? _op : NULL)
>
> isn't that like the dumbest macro ever?
That's subjective, I am lazy.
Luis
^ permalink raw reply
* Re: [PATCH] mac80211: Add HT IE to IBSS beacons and probe responses.
From: Benoit Papillault @ 2010-05-05 21:37 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1273060014.3728.15.camel@jlt3.sipsolutions.net>
Le 05/05/2010 13:46, Johannes Berg a écrit :
> On Tue, 2010-05-04 at 08:47 +0200, Benoit Papillault wrote:
>> When an HT IBSS is configured, we add HT Information and HT Capabilities
>> IE to beacon& probe responses. This is done according to channel_type
>> transmitted by iw/cfg80211.
>
> Just noticed something else -- this allows creating an HT40 IBSS on an
> invalid channel pair -- do we want to catch that?
>
> johannse
>
Do you mean creating an ht40+ over channel 112, where only ht40- is
allowed by 802.11 ? Since it's the same for AP & IBSS, maybe it could be
done in the regulatory code?
Anyway, since this latter issue was already there for a while, it could
be fixed in a follow up patch.
Regards,
Benoit
^ permalink raw reply
* Re: [PATCH v2] cfg80211/mac80211: better channel handling
From: Benoit Papillault @ 2010-05-05 20:58 UTC (permalink / raw)
To: Johannes Berg; +Cc: John Linville, linux-wireless
In-Reply-To: <1273065902.3728.17.camel@jlt3.sipsolutions.net>
Le 05/05/2010 15:25, Johannes Berg a écrit :
> Currently (all tested with hwsim) you can do stupid
> things like setting up an AP on a certain channel,
> then adding another virtual interface and making
> that associate on another channel -- this will make
> the beaconing to move channel but obviously without
> the necessary IEs data update.
>
> In order to improve this situation, first make the
> configuration APIs (cfg80211 and nl80211) aware of
> multi-channel operation -- we'll eventually need
> that in the future anyway. There's one userland API
> change and one API addition. The API change is that
> now SET_WIPHY must be called with virtual interface
> index rather than only wiphy index in order to take
> effect for that interface -- luckily all current
> users (hostapd) do that. For monitor interfaces, the
> old setting is preserved, but monitors are always
> slaved to other devices anyway so no guarantees.
Real hardware are not capable of listening on multiple channels (except
2 ht20 channels in ht40 mode, maybe?). So I don't understand why we
should have a per-interface channel.
I think we should either have two strategies :
- "first one is the winner" : once a channel has been set, it cannot be
changed. For instance, if you create an AP interface (with hostapd) and
latter a STA interface, the STA interface can only scan on the channel
the AP is.
- "last one is the winner" : in this case, the last call to set the
channel is always successful. Of course, this will change channel on
existing interfaces which might change their IE accordingly, through an
appropriate API.
I might be wrong, but I don't see this multi-channel usage...
Regards,
Benoit
^ permalink raw reply
* pull request: wireless-next-2.6 2010-05-05
From: John W. Linville @ 2010-05-05 20:35 UTC (permalink / raw)
To: davem; +Cc: linux-wireless, netdev
Dave,
Another enormous batch intended for 2.6.35... This is mostly the 'usual
suspects' -- driver updates from Intel, Atheros, Nokia, and the rt2x00
guys, mac80211 stuff from Johannes, and a variety of other bits. One
noteworth bit is the addition of the orinoco_usb driver.
Please let me know if there are problems!
¡Olé!
Thanks,
John
---
The following changes since commit 0a12761bcd5646691c5d16dd93df84d1b8849285:
David S. Miller (1):
forcedeth: Kill NAPI config options.
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 for-davem
Abhijeet Kolekar (2):
iwlwifi: reset pci retry timeout
iwl3945: add ucode statistics
Benoit Papillault (1):
ath9k: Added get_survey callback in order to get channel noise
Dan Carpenter (1):
iwl: cleanup: remove unneeded error handling
Dan Williams (1):
libertas: fix 8686 firmware loading regression
Daniel Halperin (1):
iwlwifi: set AMPDU status variables correctly
David Kilroy (6):
orinoco: add hermes_ops
orinoco: allow driver to specify netdev_ops
orinoco: encapsulate driver locking
orinoco: add orinoco_usb driver
orinoco_usb: avoid in_atomic
orinoco_usb: implement fw download
Felix Fietkau (13):
mac80211: fix handling of 4-address-mode in ieee80211_change_iface
ath9k_hw: update initvals for AR9003
ath9k_hw: fix pll clock setting for 5ghz on AR9003
ath9k_hw: fix typo in the AR9003 EEPROM data structure definition
ath9k_hw: update EEPROM data structure for AR9280
ath9k_hw: fix fast clock handling for 5GHz channels
ath9k: wake queue after processing edma rx frames
ath9k_hw: use the configured power limit for AR9003
ath9k_hw: Fix typos in tx rate power level parsing for AR9003
ath9k_hw: Fix endian bug in an AR9003 EEPROM field
ath9k_hw: fix noisefloor timeout handling on AR9003
cfg80211: add ap isolation support
mac80211: implement ap isolation support
Gertjan van Wingerde (4):
rt2x00: Remove rt2x00pci.h include from rt2800lib.
rt2x00: Enable RT30xx by default.
rt2x00: Fix HT40+/HT40- setting in rt2800.
rt2x00: Register frame length in TX entry descriptor instead of L2PAD.
Hans de Goede (1):
p54pci: fix regression from prevent stuck rx-ring on slow system
Helmut Schaa (6):
rt2x00: rt2800lib: disable HT40 for now as it causes reception problems
rt2x00: rt2800: use tx_power2 in rt2800_config_channel_rf3xxx
rt2x00: fix typo in rt2800.h
rt2x00: rt2800lib: Fix rx path on SoC devices
rt2x00: rt2800lib: Remove redundant check for RT2872
rt2x00: rt2800lib: update rfcsr & bbp init code for SoC devices
Johannes Berg (9):
mac80211: give virtual interface to hw_scan
mac80211: notify driver about IBSS status
mac80211: tell driver about IBSS merge
iwlwifi: work around passive scan issue
mac80211: fix ieee80211_find_sta[_by_hw]
mac80211: allow controlling aggregation manually
mac80211: improve IBSS scanning
mac80211_hwsim: fix double-scan detection
mac80211: use fixed channel in ibss join when appropriate
John W. Linville (25):
ssb: do not read SPROM if it does not exist
MAINTAINERS: add entry for include/linux/iw_handler.h
mwl8k: remove usage of deprecated noise value
ar9170: remove usage of deprecated noise value
ath5k: remove usage of deprecated noise value
ath9k: remove usage of deprecated noise value
b43: remove usage of deprecated noise value
b43legacy: remove usage of deprecated noise value
libertas_tf: remove usage of deprecated noise value
p54: remove usage of deprecated noise value
rt2x00: remove usage of deprecated noise value
wl1251: remove usage of deprecated noise value
rtl8180: use cached queue mapping for skb in rtl8180_tx
rtl8180: fix tx status reporting
libertas_tf: avoid warning about pr_fmt redefinition
mac80211: remove deprecated noise field from ieee80211_rx_status
iwmc3200wifi: cleanup unneeded debugfs error handling
rt2x00: remove now unused noise field from struct rxdone_entry_desc
b43: Added get_survey callback in order to get channel noise
b43legacy: Added get_survey callback in order to get channel noise
Merge branch 'wireless-next-2.6' of git://git.kernel.org/.../iwlwifi/iwlwifi-2.6
iwmc3200wifi: fix busted iwm_debugfs_init definition
rtl8180: use SET_IEEE80211_PERM_ADDR
rtl8187: use SET_IEEE80211_PERM_ADDR
Merge branch 'master' of git://git.kernel.org/.../linville/wireless-next-2.6 into for-davem
Juuso Oikarinen (5):
mac80211: Fix sta->last_tx_rate setting with no-op rate control devices
mac80211: Determine dynamic PS timeout based on ps-qos network latency
cfg80211: Remove default dynamic PS timeout value
wl1271: Improve command polling
wl1271: Rewrite hardware keep-alive handling
Larry Finger (1):
ssb: Make bus registration failure not be silent
Luciano Coelho (1):
wl1271: fix a bunch of sparse warnings
Luis R. Rodriguez (2):
ath9k_hw: disable TX IQ calibration for AR9003
ath9k_hw: Fix TX interrupt mitigation settings
Rafał Miłecki (3):
ssb: Look for SPROM at different offset on higher rev CC
ssb: Use relative offsets for SPROM
ssb: Fix order of definitions and some text space indents
Reinette Chatre (2):
Merge branch 'wireless-2.6' into wireless-next-2.6
iwlwifi: recalculate average tpt if not current
Saravanan Dhanabal (1):
wl1271: Configure QOS nullfunc template for U-APSD
Shanyu Zhao (2):
mac80211: fix rts threshold check
iwlwifi: set correct AC to swq_id for aggregation
Stanislaw Gruszka (2):
mac80211: do not wip out old supported rates
mac80211: fix supported rates IE if AP doesn't give us it's rates
Steve deRosier (1):
libertastf: add configurable debug messages
Sujith (14):
ath9k_htc: Simplify TX URB management
ath9k_htc: Handle device unplug properly
ath9k_htc: Use multiple register writes
ath9k_htc: Cancel running timers before disabling HW
ath9k_hw: Remove pointless ANI deinit
ath9k_htc: Pass correct private pointer
ath9k_htc: Use USB reboot
ath9k_htc: Process command data properly
ath9k_htc: Increase WMI timeout value
ath9k_htc: Fix WMI command race
ath9k_htc: Really fix device hotunplug
ath9k_htc: Remove unnecessary powersave restore
ath9k_htc: Validate TX Endpoint ID
ath9k_htc: Simplify RX IRQ handler
Vasanthakumar Thiagarajan (1):
ath9k_hw: Fix usec to hw clock conversion in 5Ghz for ar9003
Vivek Natarajan (2):
ath9k_htc: Handle CONF_IDLE during unassociated state to save power.
ath9k: Avoid corrupt frames being forwarded to mac80211.
Wey-Yi Guy (4):
iwlwifi: remove get_stats callback function
iwlwifi: remove outdated comments
iwlwifi: set hw parameters based on device type
iwlwifi: greenfield support only true for 11n devices
Xose Vazquez Perez (1):
wireless: rt2x00: rt2800usb: be in sync with latest windows drivers.
MAINTAINERS | 1 +
drivers/net/wireless/Kconfig | 6 +
drivers/net/wireless/at76c50x-usb.c | 1 +
drivers/net/wireless/ath/ar9170/main.c | 4 +-
drivers/net/wireless/ath/ath5k/base.c | 6 +-
drivers/net/wireless/ath/ath9k/ani.c | 9 -
drivers/net/wireless/ath/ath9k/ani.h | 1 -
drivers/net/wireless/ath/ath9k/ar5008_initvals.h | 2 +-
drivers/net/wireless/ath/ath9k/ar5008_phy.c | 5 +-
drivers/net/wireless/ath/ath9k/ar9002_hw.c | 5 +
drivers/net/wireless/ath/ath9k/ar9002_initvals.h | 8 +-
drivers/net/wireless/ath/ath9k/ar9002_phy.c | 16 +-
drivers/net/wireless/ath/ath9k/ar9003_calib.c | 3 +-
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 8 +-
drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 2 +-
drivers/net/wireless/ath/ath9k/ar9003_initvals.h | 265 ++--
drivers/net/wireless/ath/ath9k/ar9003_mac.c | 3 +
drivers/net/wireless/ath/ath9k/ar9003_phy.c | 16 +-
drivers/net/wireless/ath/ath9k/common.c | 1 -
drivers/net/wireless/ath/ath9k/eeprom.h | 3 +-
drivers/net/wireless/ath/ath9k/eeprom_def.c | 2 +
drivers/net/wireless/ath/ath9k/hif_usb.c | 149 +-
drivers/net/wireless/ath/ath9k/hif_usb.h | 1 -
drivers/net/wireless/ath/ath9k/htc.h | 2 +
drivers/net/wireless/ath/ath9k/htc_drv_init.c | 8 +
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 84 +-
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 59 +-
drivers/net/wireless/ath/ath9k/htc_hst.c | 5 +-
drivers/net/wireless/ath/ath9k/hw.c | 27 +-
drivers/net/wireless/ath/ath9k/hw.h | 8 +-
drivers/net/wireless/ath/ath9k/mac.c | 10 +-
drivers/net/wireless/ath/ath9k/main.c | 20 +
drivers/net/wireless/ath/ath9k/wmi.c | 11 +-
drivers/net/wireless/ath/ath9k/wmi.h | 4 +-
drivers/net/wireless/ath/ath9k/xmit.c | 2 +
drivers/net/wireless/b43/main.c | 21 +-
drivers/net/wireless/b43/xmit.c | 1 -
drivers/net/wireless/b43legacy/main.c | 21 +-
drivers/net/wireless/b43legacy/xmit.c | 1 -
drivers/net/wireless/iwlwifi/Makefile | 1 +
drivers/net/wireless/iwlwifi/iwl-1000.c | 1 -
drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c | 500 ++++++
drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h | 60 +
drivers/net/wireless/iwlwifi/iwl-3945.c | 72 +-
drivers/net/wireless/iwlwifi/iwl-3945.h | 2 +
drivers/net/wireless/iwlwifi/iwl-5000.c | 73 +-
drivers/net/wireless/iwlwifi/iwl-6000.c | 73 +-
drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 23 +-
drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 20 +-
drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 16 +-
drivers/net/wireless/iwlwifi/iwl-agn.c | 14 -
drivers/net/wireless/iwlwifi/iwl-commands.h | 4 +-
drivers/net/wireless/iwlwifi/iwl-core.c | 10 +-
drivers/net/wireless/iwlwifi/iwl-core.h | 4 +-
drivers/net/wireless/iwlwifi/iwl-debugfs.c | 18 +-
drivers/net/wireless/iwlwifi/iwl-dev.h | 5 +
drivers/net/wireless/iwlwifi/iwl-scan.c | 3 +-
drivers/net/wireless/iwlwifi/iwl3945-base.c | 6 +-
drivers/net/wireless/iwmc3200wifi/bus.h | 2 +-
drivers/net/wireless/iwmc3200wifi/debug.h | 7 +-
drivers/net/wireless/iwmc3200wifi/debugfs.c | 110 +--
drivers/net/wireless/iwmc3200wifi/sdio.c | 17 +-
drivers/net/wireless/libertas/if_sdio.c | 4 +-
drivers/net/wireless/libertas_tf/cmd.c | 203 ++-
drivers/net/wireless/libertas_tf/deb_defs.h | 104 ++
drivers/net/wireless/libertas_tf/if_usb.c | 251 +++-
drivers/net/wireless/libertas_tf/libertas_tf.h | 2 +
drivers/net/wireless/libertas_tf/main.c | 91 +-
drivers/net/wireless/mac80211_hwsim.c | 6 +-
drivers/net/wireless/mwl8k.c | 6 +-
drivers/net/wireless/orinoco/Kconfig | 7 +
drivers/net/wireless/orinoco/Makefile | 1 +
drivers/net/wireless/orinoco/airport.c | 8 +-
drivers/net/wireless/orinoco/cfg.c | 2 +-
drivers/net/wireless/orinoco/fw.c | 10 +-
drivers/net/wireless/orinoco/hermes.c | 286 ++++-
drivers/net/wireless/orinoco/hermes.h | 62 +-
drivers/net/wireless/orinoco/hermes_dld.c | 243 +---
drivers/net/wireless/orinoco/hw.c | 63 +-
drivers/net/wireless/orinoco/main.c | 137 +-
drivers/net/wireless/orinoco/orinoco.h | 30 +-
drivers/net/wireless/orinoco/orinoco_cs.c | 6 +-
drivers/net/wireless/orinoco/orinoco_nortel.c | 2 +-
drivers/net/wireless/orinoco/orinoco_pci.c | 2 +-
drivers/net/wireless/orinoco/orinoco_plx.c | 2 +-
drivers/net/wireless/orinoco/orinoco_tmd.c | 2 +-
drivers/net/wireless/orinoco/orinoco_usb.c | 1800 ++++++++++++++++++++++
drivers/net/wireless/orinoco/spectrum_cs.c | 7 +-
drivers/net/wireless/orinoco/wext.c | 6 +-
drivers/net/wireless/p54/main.c | 3 +-
drivers/net/wireless/p54/p54pci.c | 16 +-
drivers/net/wireless/p54/txrx.c | 1 -
drivers/net/wireless/rt2x00/Kconfig | 4 +-
drivers/net/wireless/rt2x00/rt2400pci.c | 4 +-
drivers/net/wireless/rt2x00/rt2500pci.c | 2 +-
drivers/net/wireless/rt2x00/rt2500usb.c | 2 +-
drivers/net/wireless/rt2x00/rt2800.h | 11 +-
drivers/net/wireless/rt2x00/rt2800lib.c | 91 +-
drivers/net/wireless/rt2x00/rt2800pci.c | 6 +-
drivers/net/wireless/rt2x00/rt2800usb.c | 13 +-
drivers/net/wireless/rt2x00/rt2x00dev.c | 1 -
drivers/net/wireless/rt2x00/rt2x00queue.c | 6 +-
drivers/net/wireless/rt2x00/rt2x00queue.h | 6 +-
drivers/net/wireless/rt2x00/rt61pci.c | 5 +-
drivers/net/wireless/rt2x00/rt73usb.c | 2 +-
drivers/net/wireless/rtl818x/rtl8180_dev.c | 13 +-
drivers/net/wireless/rtl818x/rtl8187_dev.c | 10 +-
drivers/net/wireless/wl12xx/wl1251_main.c | 2 +-
drivers/net/wireless/wl12xx/wl1251_rx.c | 6 -
drivers/net/wireless/wl12xx/wl1271_acx.c | 2 +-
drivers/net/wireless/wl12xx/wl1271_boot.c | 8 +-
drivers/net/wireless/wl12xx/wl1271_cmd.c | 14 +-
drivers/net/wireless/wl12xx/wl1271_conf.h | 2 +-
drivers/net/wireless/wl12xx/wl1271_main.c | 97 +-
drivers/ssb/driver_chipcommon.c | 2 +
drivers/ssb/main.c | 3 +
drivers/ssb/pci.c | 14 +-
drivers/ssb/sprom.c | 14 +
include/linux/nl80211.h | 5 +
include/linux/ssb/ssb.h | 4 +
include/linux/ssb/ssb_driver_chipcommon.h | 15 +
include/linux/ssb/ssb_regs.h | 239 ++--
include/net/cfg80211.h | 4 +
include/net/mac80211.h | 21 +-
net/mac80211/cfg.c | 18 +-
net/mac80211/debugfs_sta.c | 65 +-
net/mac80211/driver-ops.h | 5 +-
net/mac80211/driver-trace.h | 9 +-
net/mac80211/ibss.c | 27 +-
net/mac80211/ieee80211_i.h | 3 +-
net/mac80211/main.c | 19 +-
net/mac80211/mlme.c | 21 +
net/mac80211/rx.c | 2 -
net/mac80211/scan.c | 53 +-
net/mac80211/sta_info.c | 17 +-
net/mac80211/status.c | 7 +
net/mac80211/tx.c | 5 +-
net/mac80211/work.c | 28 +-
net/wireless/core.c | 3 +-
net/wireless/nl80211.c | 4 +
140 files changed, 4751 insertions(+), 1368 deletions(-)
create mode 100644 drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c
create mode 100644 drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h
create mode 100644 drivers/net/wireless/libertas_tf/deb_defs.h
create mode 100644 drivers/net/wireless/orinoco/orinoco_usb.c
Omnibus patch is available here:
http://www.kernel.org/pub/linux/kernel/people/linville/wireless-next-2.6-2010-04-23.patch.bz2
--
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: 2.6.34-rc6 pci bridge problems
From: Christian Lamparter @ 2010-05-05 19:59 UTC (permalink / raw)
To: dhlii; +Cc: linux-wireless, linux-kernel, linux-pci
In-Reply-To: <4BE1BBD6.3030505@dlasys.net>
On Wednesday 05 May 2010 20:41:26 David H. Lynch Jr. wrote:
> When I build out of the wireless-testing git tree (puled today)
> 2.6.34-rc6 using my current systems .config I get a very quick error
> on boot about PCI bridge windows.
> googling the error indicates this is a know 2.6.34 problem and that
> there are fixes in other 2.6.34 trees.
> I have been unable to find the actual patches or I would just apply
> them to wireless-testing.
so? If there is already a patch available, then the linux-pci people
have to know something about it. I'm sure they can help you out there.
Just describe your problem in detail (a extensive checklist is located in
your kernel's root directory "REPORTING-BUGS" file) as a reply to this mail.
I simply can't give you any support for problems I know nothing about.
So please, concentrate your questions around this particular device and
interaction with firmware and driver. But as I said in my previous mail,
you don't need a special kernel driver. *carlu* really is a userspace-only
application that can communicate with the device (through the use of
libusb) at the "lowest level". It may be even possible to port the code to
other platforms (FreeBSD & Mac OS X, Windows) with little effort.
Regards,
Chr
^ permalink raw reply
* Re: First results with netbook from John
From: Gábor Stefanik @ 2010-05-05 18:58 UTC (permalink / raw)
To: Larry Finger
Cc: Michael Buesch, Rafał Miłecki, John Linville, wireless,
b43-dev
In-Reply-To: <4BE1B2DF.8070506@lwfinger.net>
One thing to try: swap the cards between the laptop and the netbook,
to check if the differences depend on the card or the system.
On Wed, May 5, 2010 at 8:03 PM, Larry Finger <Larry.Finger@lwfinger.net> wrote:
> I received the netbook from John last Saturday. It took a while to get
> it integrated into my network as this is my first Fedora system, but I
> now have some results to report.
>
> I loaded wl logging both MMIO and PCI configuration register reads and
> writes. The two types are now interleaved. The latter are logged with
> trace_printk() calls. Note: There is a bug in current kernel code that
> keeps these calls from being logged. Thanks to Stephen Rostedt for
> sorting out this problem.
>
> Both systems have the same core sequence and the same revisions. The
> cores in order are ChipCommon rev 0x16, IEEE 802.11 rev 0x0F, PCMCIA rev
> 0x0A, and PCI-E rev 0x09.
>
> I now know for certain that the netbook has an SPROM at offset 0x800.
> Trying to read at offset 0x1000, which is the SPROM location in the
> laptop, locks the machine, thus we need to determine the SPROM location
> without reading 0x1000.
>
> Fortunately, the wl driver reads and writes PCI configuration space from
> the Linux shim code, not from the binary blob, thus these operations can
> be traced.
>
> The _only_ differences between the laptop and netbook operations between
> startup and the reading of the SPROM are as follows:
>
> Register Laptop Netbook Explanation
>
> PCI 0x0C 0x10 0x08 Cache Line Size
> PCI 0x04 0x00100106 0x001000006 Command Features [1]
> Core 0 0x2C 0x10 0x12 Chip Status Reg [2]
> Core 3 0x800 0x2801 0x3801 On laptop 0x3801 written
> Core 3 0x280a 0x6dbe 0xedbe On laptop 0xedbe written
>
> The code then switches to Core 1 (802.11) and begins reading SPROM. On
> the laptop, it reads from 0x1000 and does a try at the smaller size
> SPROM, then switches to the larger size, just as ssb does. On the
> netbook, it immediately reads the larger size at offset 0x800.
>
> I have not yet looked closely at the differences between wl and ssb, but
> I did note one difference. In wl, bits 0xFF00 are cleared in PCI
> register 0x40. The only thing I could find is this code fragment from
> ipw2100 and ipw2200:
>
> /* We disable the RETRY_TIMEOUT register (0x41) to keep
> * PCI Tx retries from interfering with C3 CPU state */
> pci_read_config_dword(pdev, 0x40, &val);
> if ((val & 0x0000ff00) != 0)
> pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
>
> Larry
>
> [1] The Wikipedia article on PCI configuration space says that this is a
> bitmask of features that can be enabled/disabled. I have no explanation
> of the details.
>
> [2] This extra bit looks most promising of all the differences. It is
> the bit involved in the is_sprom_available() routine for the 4315 device
> in the Broadcom driver that has been reverse engineered; however, the
> definition must have changed as that code would say there is no SPROM,
> which is clearly untrue.
>
--
Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-)
^ permalink raw reply
* carl9170 1.0.5.1
From: David H. Lynch Jr. @ 2010-05-05 18:41 UTC (permalink / raw)
To: Christian Lamparter; +Cc: linux-wireless
In-Reply-To: <201005021452.01101.chunkeey@googlemail.com>
I am trying to build a kernel using the carl9170 driver/firmware.
I am not particular about what kernel or how so long as I can get
it running.
When I build out of the wireless-testing git tree (puled today)
2.6.34-rc6
using my current systems .config I get a very quick error on boot
about PCI bridge windows.
googling the error indicates this is a know 2.6.34 problem and that
there are fixes in other 2.6.34 trees.
I have been unable to find the actual patches or I would just apply
them to wireless-testing.
Alternately, I tried to build out of the ubuntu-lucid git tree.
2.6.32 again with my existing .config.
I the carl9170 driver does not build. While I found patches at
OpenWRT that are supposed to allow building carl9170 with 2.6.33 or less,
the errors are unrelated to what is changed by those patches.
I have also tried using linux-source-2.6.32 pulled from cannonical
via apt for my install rather than the ubuntu-lucid git tree
with similar results.
On 05/02/2010 08:52 AM, Christian Lamparter wrote:
> On Sunday 02 May 2010 13:14:59 David H. Lynch Jr. wrote:
>
>> On 05/02/2010 03:47 AM, Benoit Papillault wrote:
>>
>>> Le 01/05/2010 22:45, Christian Lamparter a écrit :
>>>
>>>> On Saturday 01 May 2010 20:23:26 David H. Lynch Jr. wrote:
>>>>
>>>>> I think I can tell you what I am supposed add - I need to be able
>>>>> to provide userspace apps with precise timing information for each
>>>>> packet.
>>>>> Since i am working on GPL'd code and the results are going to be
>>>>> provided to third parties whatever I do is GPL'd too.
>>>>>
>>>> if by precise timing you mean "exact mac time in TU/usecs when frame
>>>> was received at the radio", then you might have a _problem_.
>>>> You see, the firmware already receives fully packed frames from
>>>> the MAC processor and only _forwards_ them all [as is] in
>>>> one big DMA to the USB subsystem.
>>>> (this is done in src/wlan.c handle_rx())
>>>>
>>>> So, unless the HW has a _magic_ flag to enable this capability...
>>>> you are sort of screwed :-/.
>>>>
>>> I would love this feature as well. I have a device to test if that can
>>> help. I share the feeling of Christian however... but maybe your
>>> documentation says something about a special flag.
>>>
>> I am interested in round trip time as measured from some fixed point
>> in the sending process to some fixed point in the packet acknowledgement.
>> The more accurate the better. Preferably measured by events at the
>> radio rather than on the linux side.
>>
>
>> I am interested in tx packets rather than rx packets.
>>
> ahh, well... there goes' benoit interest ;).
>
>
>> If necessary I can measure the times myself as delta's from one
>> event to another withing the SH2.
>>
>> I have not digested the docs I have thoroughly yet but a cursory
>> review suggests a less than trivial project.
>> I have not yet found a good high resolution clock inside the ar9170
>> there are alot of clocks but they all seem to be 16bit. Probably that
>> will make things harder.
>>
> TSF timer could be used for this. (see 802.11-2007, Section 11 et seq.)
> It's a 2^64 bit timer with a 1us resolution and a accuracy _better_
> or equal to +/- 0.01%.
>
> The register address are at:
> - 0x1c3514 (low, AR9170_MAC_REG_TSF_L, read only)
> - 0x1c3518 (high, AR9170_MAC_REG_TSF_H, read only)
>
> But it comes at a small price: this timer is sometimes
> update& synchronized (802.11 11.1.3.4 and 11.1.4) in
> station or ad-hoc mode. The exact details are hidden
> inside MAC chip, but it should be possible to disable
> both by selecting the monitor mode.
>
>
>> I was expecting to have to make changes to the ar9170 firmware. I
>> was expecting to have to devise some means of passing that information
>> to the Linux driver and to the userspace application.
>>
> Well, then you have two more good reasons why to use carl9170:
>
> * the ar9170usb driver and ar9170 firmware don't track tx frames.
> carl9170 on the other hand does (every frame has a 8 bit "cookie").
> This feature was necessary to generate an accurate tx transmission
> feedback report for every individual frame for the driver.
>
> * carl9170 has the ability to store additional per-frame data.
> In fact, if you don't need to have a different retry rates
> you could realloc the 3 * 32 bit "rr" (as in retry rate)
> array in the carl9170_tx_superdesc and _carl9170_tx_superdesc
> struct (see wlan.h) for your purposes (storage for your time values).
>
> And if you fetched all the data, everything will be sent
> with an ordinary tx status feedback report to the application
> (add the timer fields into carl9170_tx_status and _carl9170_tx_status
> struct - see fwcmd.h)
>
> (* talked about this earlier, but you never know...
>
> carlu _tool_ already provides a low-level HW driver for userspace.
> This has the obvious advantage that you won't need to mess with
> the kernel driver and network stacks.
>
> The only work you'll have to do is: get the kernel code for
> the MAC& PHY initialization and put it into carlu.
> But the framework is already there so it's mostly copy + paste )
>
>
>> I would be happy to do that in some fashion that conformed to an existing
>> or future standard, but I was not anticipating a broad desire for what I am
>> doing. Variable latencies are highly undesirable in this application,
>> but the userspace application will be aggregating large amounts of
>> information, if latencies in what is measured are constrained and the
>> unit of time measurement is small enough everything will work.
>> If it comes to that we switch to different hardware, but my project
>> is bringing a concept that was demonstrated with an expensive SDR to an
>> ar9170.
>>
> It's always nice to have some "added value" for cheap and generic devices.
> e.g.: Atheros AR92xx chips can be used as among other stuff as a
> full range spectrum analyzer.
>
> Regards,
> Chr
> --
> 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
>
--
Dave Lynch DLA Systems
Software Development: Embedded Linux
717.587.7774 dhlii@dlasys.net http://www.dlasys.net
Over 25 years' experience in platforms, languages, and technologies too numerous to list.
"Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction."
Albert Einstein
^ permalink raw reply
* First results with netbook from John
From: Larry Finger @ 2010-05-05 18:03 UTC (permalink / raw)
To: Michael Buesch, Gábor Stefanik, Rafał Miłecki,
John Linville
Cc: wireless, b43-dev
I received the netbook from John last Saturday. It took a while to get
it integrated into my network as this is my first Fedora system, but I
now have some results to report.
I loaded wl logging both MMIO and PCI configuration register reads and
writes. The two types are now interleaved. The latter are logged with
trace_printk() calls. Note: There is a bug in current kernel code that
keeps these calls from being logged. Thanks to Stephen Rostedt for
sorting out this problem.
Both systems have the same core sequence and the same revisions. The
cores in order are ChipCommon rev 0x16, IEEE 802.11 rev 0x0F, PCMCIA rev
0x0A, and PCI-E rev 0x09.
I now know for certain that the netbook has an SPROM at offset 0x800.
Trying to read at offset 0x1000, which is the SPROM location in the
laptop, locks the machine, thus we need to determine the SPROM location
without reading 0x1000.
Fortunately, the wl driver reads and writes PCI configuration space from
the Linux shim code, not from the binary blob, thus these operations can
be traced.
The _only_ differences between the laptop and netbook operations between
startup and the reading of the SPROM are as follows:
Register Laptop Netbook Explanation
PCI 0x0C 0x10 0x08 Cache Line Size
PCI 0x04 0x00100106 0x001000006 Command Features [1]
Core 0 0x2C 0x10 0x12 Chip Status Reg [2]
Core 3 0x800 0x2801 0x3801 On laptop 0x3801 written
Core 3 0x280a 0x6dbe 0xedbe On laptop 0xedbe written
The code then switches to Core 1 (802.11) and begins reading SPROM. On
the laptop, it reads from 0x1000 and does a try at the smaller size
SPROM, then switches to the larger size, just as ssb does. On the
netbook, it immediately reads the larger size at offset 0x800.
I have not yet looked closely at the differences between wl and ssb, but
I did note one difference. In wl, bits 0xFF00 are cleared in PCI
register 0x40. The only thing I could find is this code fragment from
ipw2100 and ipw2200:
/* We disable the RETRY_TIMEOUT register (0x41) to keep
* PCI Tx retries from interfering with C3 CPU state */
pci_read_config_dword(pdev, 0x40, &val);
if ((val & 0x0000ff00) != 0)
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
Larry
[1] The Wikipedia article on PCI configuration space says that this is a
bitmask of features that can be enabled/disabled. I have no explanation
of the details.
[2] This extra bit looks most promising of all the differences. It is
the bit involved in the is_sprom_available() routine for the 4315 device
in the Broadcom driver that has been reverse engineered; however, the
definition must have changed as that code would say there is no SPROM,
which is clearly untrue.
^ permalink raw reply
* The case of the bogus SSID
From: pigiron @ 2010-05-05 17:01 UTC (permalink / raw)
To: linux-wireless
The kind folks at linux-wireless IRC suggested that I should probably bring this ugly topic over here.
I've been digging into this problem for the last few days, and am now in need of some guidance from you wireless guru's. I hope the you folks can follow my twisted path. Here's the scenario:
SYMPTOMS:
=========
Linux clients (and apparently *only* Linux clients) cannot associate with an AP running a brand new "flavor" of DD-WRT firmware. Myself and others have reported the same problem. The response from the chief DD-WRT person was basically, "tested and works on Windows and OSX, so it must be a Linux problem".
The Wicd network manager displays strange UTF-8 type characters for the SSID. This causes it to create an incorrect WPA PSK.
Also, two ESSIDs are returned for that MAC when running the "iwlist wlan0 scan" command using many different wireless devices. So far, I've found that ipw2200 and rta2870sta seem to be the only devices that don't report an "extra" ESSID with iwlist.
Not surprisingly, I can connect to the router by manually running wpa_supplicant.
The problem still exists when running compat-wireless-2010-04-26.
Here's an example of the "iwlist wlan0 scan" output with the router in it's "default" configuration:
Cell 02 - Address: 00:25:9C:XX:XX:XX
Channel:6
Frequency:2.437 GHz (Channel 6)
Quality=70/70 Signal level=-33 dBm
Encryption key:off
---> ESSID:"dd-wrt"
Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 6 Mb/s
9 Mb/s; 12 Mb/s; 18 Mb/s
Bit Rates:24 Mb/s; 36 Mb/s; 48 Mb/s; 54 Mb/s
---> ESSID:""
Mode:Unknown/bug
Extra:tsf=00000064b6ade4fb
Extra: Last beacon: 4120ms ago
IE: Unknown: 000664642D777274
IE: Unknown: 010882848B960C121824
IE: Unknown: 030106
IE: Unknown: 2A0100
IE: Unknown: 32043048606C
IE: Unknown: DD180050F2020101020003A4000027A4000042435E00623
IE: Unknown: 331A4C101BFFFF000000000000000000000000000000000
IE: Unknown: 2D1A4C101BFFFF000000000000000000000000000000000
>>>> IE: Unknown: 34160600190000000000000000000000000000000000000
IE: Unknown: 3D160600190000000000000000000000000000000000000
IE: Unknown: 4A0E14000A002C01C800140005001900
IE: Unknown: 7F0101
IE: Unknown: DD0900037F01010000FF7F
IE: Unknown: DD0A00037F04010000000000
PROBLEM:
========
I tried to narrow the problem by firing up the debugger against iwlist. After iwlist performs a SIOGIWSCAN, it then retreives the AP response, and this contains a second, bogus SSID (specifically a SIOCGIWESSID), with data matching one of the Information Elements above... actually two. But here's the data that I think causes the problem:
IE: Unknown: 34160600190000000000000000000000000000000000000
Both the Wireshark scan capture and my digging into the 802.11k-2008 specification show that line as being a "Neighbor Report" Information Element (0x34 = 52 decimal = Neighbor Report).
I noticed that decimal 52 is assigned to WLAN_EID_MESH_ID in the ieee80211.h file, and recently the same 52 was also assigned to WLAN_EID_NEIGHBOR_REPORT in the same enumerated ieee80211_eid{} structure.
BUT... before I go kernel diving, I have a question. I guess I'm trying to first determine if the problem may be in the router. From my reading of the 802.11k-2008 specification, I'm thinking that a Neighbor Report should not even be inside a scan response from the AP. Every reference to "Neighbor Report" that I can find in the specification *seems* to state that a Neighbor Report response should only arrive at the STA after the AP receives a "Neighbor Report Request" frame. And it should then be contained inside a "Neighbor Report Response" frame. Is my thinking correct??? Or am I off base (yet again ;)???
FYI: The router is configured as a simple AP acting as a gateway to a cable modem. No vlans, no hotspot, etc... i.e. nothing "exotic". In fact, no one has yet found a configuration setting that will make this problem disappear.
OBTW: All beacon frames coming from the router also contain this Neighbor Report.
Also, here is a snippet from a scan report using iw (notice that it's not confused by the Neighbor Report):
-------------------------- BEGIN NETLINK MESSAGE ---------------------------
[HEADER] 16 octets
.nlmsg_len = 312
.nlmsg_type = 24 <0x18>
.nlmsg_flags = 2 <MULTI>
.nlmsg_seq = 1273073208
.nlmsg_pid = 6127
[PAYLOAD] 296 octets
22 01 00 00 08 00 2e 00 c5 00 00 00 08 00 03 00 03 00 ".................
00 00 14 01 2f 00 0a 00 01 00 00 25 9c XX XX XX 00 00 ..../......%......
ce 00 06 00 00 06 64 64 2d 77 72 74 01 08 82 84 8b 96 ......dd-wrt......
0c 12 18 24 03 01 06 2a 01 00 32 04 30 48 60 6c dd 18 ...$...*..2.0H`l..
00 50 f2 02 01 01 02 00 03 a4 00 00 27 a4 00 00 42 43 .P..........'...BC
5e 00 62 32 2f 00 33 1a 4c 10 1b ff ff 00 00 00 00 00 ^.b2/.3.L.........
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2d 1a ................-.
4c 10 1b ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 L.................
00 00 00 00 00 00 00 00 34 16 06 00 19 00 00 00 00 00 ........4.........
00 00 00 00 00 00 00 00 00 00 00 00 00 00 3d 16 06 00 ..............=...
19 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..................
00 00 4a 0e 14 00 0a 00 2c 01 c8 00 14 00 05 00 19 00 ..J.....,.........
7f 01 01 dd 09 00 03 7f 01 01 00 00 ff 7f dd 0a 00 03 ..................
7f 04 01 00 00 00 00 00 00 00 0c 00 03 00 10 69 af ac ...............i..
77 00 00 00 06 00 04 00 64 00 00 00 06 00 05 00 21 04 w.......d.......!.
00 00 08 00 02 00 85 09 00 00 08 00 0a 00 e7 11 00 00 ..................
08 00 07 00 54 f2 ff ff ....T...
--------------------------- END NETLINK MESSAGE ---------------------------
BSS 00:25:9c:XX:XX:XX (on wlan0)
TSF: 513998285072 usec (5d, 22:46:38)
freq: 2437
beacon interval: 100
capability: ESS ShortPreamble ShortSlotTime (0x0421)
signal: -35.00 dBm
last seen: 4583 ms ago
SSID: dd-wrt
Supported rates: 1.0* 2.0* 5.5* 11.0* 6.0 9.0 12.0 18.0
DS Parameter set: channel 6
ERP: <no flags>
Extended supported rates: 24.0 36.0 48.0 54.0
WMM: * Parameter version 1
* BE: CW 15-1023, AIFSN 3
* BK: CW 15-1023, AIFSN 7
* VI: CW 7-15, AIFSN 2, TXOP 3008 usec
* VO: acm CW 3-7, AIFSN 2, TXOP 1504 usec
Unknown IE (51): 4c 10 1b ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
HT capabilities:
Capabilities: 0x104c
HT20
SM Power Save disabled
RX HT40 SGI
No RX STBC
Max AMSDU length: 7935 bytes
DSSS/CCK HT40
Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
Minimum RX AMPDU time spacing: 1/2 usec (0x02)
HT RX MCS rate indexes supported: 0-15
HT TX MCS rate indexes are undefined
Unknown IE (52): 06 00 19 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Unknown IE (61): 06 00 19 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Unknown IE (74): 14 00 0a 00 2c 01 c8 00 14 00 05 00 19 00
Extended capabilities: HT Information Exchange Supported
Vendor specific: OUI 00:03:7f, data: 01 01 00 00 ff 7f
Vendor specific: OUI 00:03:7f, data: 04 01 00 00 00 00 00
^ permalink raw reply
* [PATCH v2] mac80211: improve IBSS scanning
From: Johannes Berg @ 2010-05-05 13:33 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1272869388.3614.0.camel@jlt3.sipsolutions.net>
When IBSS is fixed to a frequency, it can still
scan to try to find the right BSSID. This makes
sense if the BSSID isn't also fixed, but it need
not scan all channels -- just one is sufficient.
Make it do that by moving the scan setup code to
ieee80211_request_internal_scan() and include
a channel variable setting.
Note that this can be further improved to start
the IBSS right away if both frequency and BSSID
are fixed.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
Argh, forgot a quilt refresh :(
net/mac80211/ibss.c | 15 ++++++++++++---
net/mac80211/ieee80211_i.h | 3 ++-
net/mac80211/main.c | 17 +----------------
net/mac80211/scan.c | 28 +++++++++++++++++++++++++++-
4 files changed, 42 insertions(+), 21 deletions(-)
--- wireless-testing.orig/net/mac80211/main.c 2010-05-02 17:47:28.000000000 +0200
+++ wireless-testing/net/mac80211/main.c 2010-05-05 15:32:16.000000000 +0200
@@ -439,7 +439,7 @@ int ieee80211_register_hw(struct ieee802
struct ieee80211_local *local = hw_to_local(hw);
int result;
enum ieee80211_band band;
- int channels, i, j, max_bitrates;
+ int channels, max_bitrates;
bool supp_ht;
static const u32 cipher_suites[] = {
WLAN_CIPHER_SUITE_WEP40,
@@ -605,21 +605,6 @@ int ieee80211_register_hw(struct ieee802
ieee80211_led_init(local);
- /* alloc internal scan request */
- i = 0;
- local->int_scan_req->ssids = &local->scan_ssid;
- local->int_scan_req->n_ssids = 1;
- for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
- if (!hw->wiphy->bands[band])
- continue;
- for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) {
- local->int_scan_req->channels[i] =
- &hw->wiphy->bands[band]->channels[j];
- i++;
- }
- }
- local->int_scan_req->n_channels = i;
-
local->network_latency_notifier.notifier_call =
ieee80211_max_network_latency;
result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,
--- wireless-testing.orig/net/mac80211/scan.c 2010-05-02 17:47:28.000000000 +0200
+++ wireless-testing/net/mac80211/scan.c 2010-05-02 17:47:50.000000000 +0200
@@ -729,10 +729,12 @@ int ieee80211_request_scan(struct ieee80
}
int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
- const u8 *ssid, u8 ssid_len)
+ const u8 *ssid, u8 ssid_len,
+ struct ieee80211_channel *chan)
{
struct ieee80211_local *local = sdata->local;
int ret = -EBUSY;
+ enum nl80211_band band;
mutex_lock(&local->scan_mtx);
@@ -740,6 +742,30 @@ int ieee80211_request_internal_scan(stru
if (local->scan_req)
goto unlock;
+ /* fill internal scan request */
+ if (!chan) {
+ int i, nchan = 0;
+
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+ if (!local->hw.wiphy->bands[band])
+ continue;
+ for (i = 0;
+ i < local->hw.wiphy->bands[band]->n_channels;
+ i++) {
+ local->int_scan_req->channels[nchan] =
+ &local->hw.wiphy->bands[band]->channels[i];
+ nchan++;
+ }
+ }
+
+ local->int_scan_req->n_channels = nchan;
+ } else {
+ local->int_scan_req->channels[0] = chan;
+ local->int_scan_req->n_channels = 1;
+ }
+
+ local->int_scan_req->ssids = &local->scan_ssid;
+ local->int_scan_req->n_ssids = 1;
memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
local->int_scan_req->ssids[0].ssid_len = ssid_len;
--- wireless-testing.orig/net/mac80211/ibss.c 2010-05-02 17:47:28.000000000 +0200
+++ wireless-testing/net/mac80211/ibss.c 2010-05-05 15:32:16.000000000 +0200
@@ -489,7 +489,9 @@ static void ieee80211_sta_merge_ibss(str
printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
"IBSS networks with same SSID (merge)\n", sdata->name);
- ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len);
+ ieee80211_request_internal_scan(sdata,
+ ifibss->ssid, ifibss->ssid_len,
+ ifibss->fixed_channel ? ifibss->channel : NULL);
}
static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
@@ -596,8 +598,9 @@ static void ieee80211_sta_find_ibss(stru
printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
"join\n", sdata->name);
- ieee80211_request_internal_scan(sdata, ifibss->ssid,
- ifibss->ssid_len);
+ ieee80211_request_internal_scan(sdata,
+ ifibss->ssid, ifibss->ssid_len,
+ ifibss->fixed_channel ? ifibss->channel : NULL);
} else {
int interval = IEEE80211_SCAN_INTERVAL;
@@ -905,6 +908,12 @@ int ieee80211_ibss_join(struct ieee80211
sdata->u.ibss.channel = params->channel;
sdata->u.ibss.fixed_channel = params->channel_fixed;
+ /* fix ourselves to that channel now already */
+ if (params->channel_fixed) {
+ sdata->local->oper_channel = params->channel;
+ sdata->local->oper_channel_type = NL80211_CHAN_NO_HT;
+ }
+
if (params->ie) {
sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len,
GFP_KERNEL);
--- wireless-testing.orig/net/mac80211/ieee80211_i.h 2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h 2010-05-05 15:32:18.000000000 +0200
@@ -1020,7 +1020,8 @@ void ieee80211_ibss_restart(struct ieee8
/* scan/BSS handling */
void ieee80211_scan_work(struct work_struct *work);
int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
- const u8 *ssid, u8 ssid_len);
+ const u8 *ssid, u8 ssid_len,
+ struct ieee80211_channel *chan);
int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
struct cfg80211_scan_request *req);
void ieee80211_scan_cancel(struct ieee80211_local *local);
^ permalink raw reply
* [PATCH] mac80211: improve HT channel handling
From: Johannes Berg @ 2010-05-05 13:28 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
Currently, when one interface switches HT mode,
all others will follow along. This is clearly
undesirable, since the new one might switch to
no-HT while another one is operating in HT.
Address this issue by keeping track of the HT
mode per interface, and allowing only changes
that are compatible, i.e. switching into HT40+
is not possible when another interface is in
HT40-, in that case the second one needs to
fall back to HT20.
Also, to allow drivers to know what's going on,
store the per-interface HT mode (channel type)
in the virtual interface's bss_conf.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
drivers/net/wireless/mac80211_hwsim.c | 19 ++++-----
include/net/mac80211.h | 4 +
net/mac80211/cfg.c | 23 ++++++++---
net/mac80211/chan.c | 70 ++++++++++++++++++++++++++++++++++
net/mac80211/ibss.c | 5 +-
net/mac80211/ieee80211_i.h | 5 +-
net/mac80211/main.c | 2
net/mac80211/mlme.c | 44 +++++++++++----------
8 files changed, 132 insertions(+), 40 deletions(-)
--- wireless-testing.orig/include/net/mac80211.h 2010-05-05 15:21:53.000000000 +0200
+++ wireless-testing/include/net/mac80211.h 2010-05-05 15:23:27.000000000 +0200
@@ -191,6 +191,9 @@ enum ieee80211_bss_change {
* the current band.
* @bssid: The BSSID for this BSS
* @enable_beacon: whether beaconing should be enabled or not
+ * @channel_type: Channel type for this BSS -- the hardware might be
+ * configured for HT40+ while this BSS only uses no-HT, for
+ * example.
* @ht_operation_mode: HT operation mode (like in &struct ieee80211_ht_info).
* This field is only valid when the channel type is one of the HT types.
* @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value
@@ -215,6 +218,7 @@ struct ieee80211_bss_conf {
u16 ht_operation_mode;
s32 cqm_rssi_thold;
u32 cqm_rssi_hyst;
+ enum nl80211_channel_type channel_type;
};
/**
--- wireless-testing.orig/net/mac80211/cfg.c 2010-05-05 15:21:53.000000000 +0200
+++ wireless-testing/net/mac80211/cfg.c 2010-05-05 15:23:27.000000000 +0200
@@ -1167,23 +1167,34 @@ static int ieee80211_set_channel(struct
enum nl80211_channel_type channel_type)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
+ struct ieee80211_sub_if_data *sdata = NULL;
+
+ if (netdev)
+ sdata = IEEE80211_DEV_TO_SUB_IF(netdev);
switch (ieee80211_get_channel_mode(local, NULL)) {
case CHAN_MODE_HOPPING:
return -EBUSY;
case CHAN_MODE_FIXED:
- if (local->oper_channel == chan &&
- local->oper_channel_type == channel_type)
+ if (local->oper_channel != chan)
+ return -EBUSY;
+ if (!sdata && local->_oper_channel_type == channel_type)
return 0;
- return -EBUSY;
+ break;
case CHAN_MODE_UNDEFINED:
break;
}
local->oper_channel = chan;
- local->oper_channel_type = channel_type;
- return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+ if (!ieee80211_set_channel_type(local, sdata, channel_type))
+ return -EBUSY;
+
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+ if (sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR)
+ ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT);
+
+ return 0;
}
#ifdef CONFIG_PM
@@ -1407,7 +1418,7 @@ int __ieee80211_request_smps(struct ieee
* association, there's no need to send an action frame.
*/
if (!sdata->u.mgd.associated ||
- sdata->local->oper_channel_type == NL80211_CHAN_NO_HT) {
+ sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) {
mutex_lock(&sdata->local->iflist_mtx);
ieee80211_recalc_smps(sdata->local, sdata);
mutex_unlock(&sdata->local->iflist_mtx);
--- wireless-testing.orig/net/mac80211/chan.c 2010-05-05 15:21:53.000000000 +0200
+++ wireless-testing/net/mac80211/chan.c 2010-05-05 15:23:27.000000000 +0200
@@ -2,6 +2,7 @@
* mac80211 - channel management
*/
+#include <linux/nl80211.h>
#include "ieee80211_i.h"
enum ieee80211_chan_mode
@@ -55,3 +56,72 @@ ieee80211_get_channel_mode(struct ieee80
return mode;
}
+
+bool ieee80211_set_channel_type(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ enum nl80211_channel_type chantype)
+{
+ struct ieee80211_sub_if_data *tmp;
+ enum nl80211_channel_type superchan = NL80211_CHAN_NO_HT;
+ bool result;
+
+ mutex_lock(&local->iflist_mtx);
+
+ list_for_each_entry(tmp, &local->interfaces, list) {
+ if (tmp == sdata)
+ continue;
+
+ if (!ieee80211_sdata_running(tmp))
+ continue;
+
+ switch (tmp->vif.bss_conf.channel_type) {
+ case NL80211_CHAN_NO_HT:
+ case NL80211_CHAN_HT20:
+ superchan = tmp->vif.bss_conf.channel_type;
+ break;
+ case NL80211_CHAN_HT40PLUS:
+ WARN_ON(superchan == NL80211_CHAN_HT40MINUS);
+ superchan = NL80211_CHAN_HT40PLUS;
+ break;
+ case NL80211_CHAN_HT40MINUS:
+ WARN_ON(superchan == NL80211_CHAN_HT40PLUS);
+ superchan = NL80211_CHAN_HT40MINUS;
+ break;
+ }
+ }
+
+ switch (superchan) {
+ case NL80211_CHAN_NO_HT:
+ case NL80211_CHAN_HT20:
+ /*
+ * allow any change that doesn't go to no-HT
+ * (if it already is no-HT no change is needed)
+ */
+ if (chantype == NL80211_CHAN_NO_HT)
+ break;
+ superchan = chantype;
+ break;
+ case NL80211_CHAN_HT40PLUS:
+ case NL80211_CHAN_HT40MINUS:
+ /* allow smaller bandwidth and same */
+ if (chantype == NL80211_CHAN_NO_HT)
+ break;
+ if (chantype == NL80211_CHAN_HT20)
+ break;
+ if (superchan == chantype)
+ break;
+ result = false;
+ goto out;
+ }
+
+ local->_oper_channel_type = superchan;
+
+ if (sdata)
+ sdata->vif.bss_conf.channel_type = chantype;
+
+ result = true;
+ out:
+ mutex_unlock(&local->iflist_mtx);
+
+ return result;
+}
--- wireless-testing.orig/net/mac80211/ibss.c 2010-05-05 15:21:54.000000000 +0200
+++ wireless-testing/net/mac80211/ibss.c 2010-05-05 15:23:27.000000000 +0200
@@ -103,7 +103,7 @@ static void __ieee80211_sta_join_ibss(st
sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
local->oper_channel = chan;
- local->oper_channel_type = NL80211_CHAN_NO_HT;
+ WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
sband = local->hw.wiphy->bands[chan->band];
@@ -911,7 +911,8 @@ int ieee80211_ibss_join(struct ieee80211
/* fix ourselves to that channel now already */
if (params->channel_fixed) {
sdata->local->oper_channel = params->channel;
- sdata->local->oper_channel_type = NL80211_CHAN_NO_HT;
+ WARN_ON(!ieee80211_set_channel_type(sdata->local, sdata,
+ NL80211_CHAN_NO_HT));
}
if (params->ie) {
--- wireless-testing.orig/net/mac80211/ieee80211_i.h 2010-05-05 15:21:53.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h 2010-05-05 15:23:27.000000000 +0200
@@ -768,7 +768,7 @@ struct ieee80211_local {
enum mac80211_scan_state next_scan_state;
struct delayed_work scan_work;
struct ieee80211_sub_if_data *scan_sdata;
- enum nl80211_channel_type oper_channel_type;
+ enum nl80211_channel_type _oper_channel_type;
struct ieee80211_channel *oper_channel, *csa_channel;
/* Temporary remain-on-channel for off-channel operations */
@@ -1239,6 +1239,9 @@ enum ieee80211_chan_mode {
enum ieee80211_chan_mode
ieee80211_get_channel_mode(struct ieee80211_local *local,
struct ieee80211_sub_if_data *ignore);
+bool ieee80211_set_channel_type(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ enum nl80211_channel_type chantype);
#ifdef CONFIG_MAC80211_NOINLINE
#define debug_noinline noinline
--- wireless-testing.orig/net/mac80211/main.c 2010-05-05 15:21:53.000000000 +0200
+++ wireless-testing/net/mac80211/main.c 2010-05-05 15:23:27.000000000 +0200
@@ -111,7 +111,7 @@ int ieee80211_hw_config(struct ieee80211
channel_type = local->tmp_channel_type;
} else {
chan = local->oper_channel;
- channel_type = local->oper_channel_type;
+ channel_type = local->_oper_channel_type;
}
if (chan != local->hw.conf.channel ||
--- wireless-testing.orig/net/mac80211/mlme.c 2010-05-05 15:21:54.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c 2010-05-05 15:23:27.000000000 +0200
@@ -137,11 +137,14 @@ static u32 ieee80211_enable_ht(struct ie
struct sta_info *sta;
u32 changed = 0;
u16 ht_opmode;
- bool enable_ht = true, ht_changed;
+ bool enable_ht = true;
+ enum nl80211_channel_type prev_chantype;
enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+ prev_chantype = sdata->vif.bss_conf.channel_type;
+
/* HT is not supported */
if (!sband->ht_cap.ht_supported)
enable_ht = false;
@@ -172,38 +175,37 @@ static u32 ieee80211_enable_ht(struct ie
}
}
- ht_changed = conf_is_ht(&local->hw.conf) != enable_ht ||
- channel_type != local->hw.conf.channel_type;
-
if (local->tmp_channel)
local->tmp_channel_type = channel_type;
- local->oper_channel_type = channel_type;
- if (ht_changed) {
- /* channel_type change automatically detected */
- ieee80211_hw_config(local, 0);
+ if (!ieee80211_set_channel_type(local, sdata, channel_type)) {
+ /* can only fail due to HT40+/- mismatch */
+ channel_type = NL80211_CHAN_HT20;
+ WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type));
+ }
+ /* channel_type change automatically detected */
+ ieee80211_hw_config(local, 0);
+
+ if (prev_chantype != channel_type) {
rcu_read_lock();
sta = sta_info_get(sdata, bssid);
if (sta)
rate_control_rate_update(local, sband, sta,
IEEE80211_RC_HT_CHANGED,
- local->oper_channel_type);
+ channel_type);
rcu_read_unlock();
- }
-
- /* disable HT */
- if (!enable_ht)
- return 0;
+ }
ht_opmode = le16_to_cpu(hti->operation_mode);
/* if bss configuration changed store the new one */
- if (!sdata->ht_opmode_valid ||
- sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
+ if (sdata->ht_opmode_valid != enable_ht ||
+ sdata->vif.bss_conf.ht_operation_mode != ht_opmode ||
+ prev_chantype != channel_type) {
changed |= BSS_CHANGED_HT;
sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
- sdata->ht_opmode_valid = true;
+ sdata->ht_opmode_valid = enable_ht;
}
return changed;
@@ -866,7 +868,7 @@ static void ieee80211_set_disassoc(struc
ieee80211_set_wmm_default(sdata);
/* channel(_type) changes are handled by ieee80211_hw_config */
- local->oper_channel_type = NL80211_CHAN_NO_HT;
+ WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
/* on the next assoc, re-program HT parameters */
sdata->ht_opmode_valid = false;
@@ -883,8 +885,8 @@ static void ieee80211_set_disassoc(struc
ieee80211_hw_config(local, config_changed);
- /* And the BSSID changed -- not very interesting here */
- changed |= BSS_CHANGED_BSSID;
+ /* The BSSID (not really interesting) and HT changed */
+ changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
ieee80211_bss_info_change_notify(sdata, changed);
if (remove_sta)
@@ -2266,7 +2268,7 @@ int ieee80211_mgd_action(struct ieee8021
if ((chan != local->tmp_channel ||
channel_type != local->tmp_channel_type) &&
(chan != local->oper_channel ||
- channel_type != local->oper_channel_type))
+ channel_type != local->_oper_channel_type))
return -EBUSY;
skb = dev_alloc_skb(local->hw.extra_tx_headroom + len);
--- wireless-testing.orig/drivers/net/wireless/mac80211_hwsim.c 2010-05-05 15:21:54.000000000 +0200
+++ wireless-testing/drivers/net/wireless/mac80211_hwsim.c 2010-05-05 15:24:09.000000000 +0200
@@ -652,17 +652,17 @@ static void mac80211_hwsim_beacon(unsign
add_timer(&data->beacon_timer);
}
+static const char *hwsim_chantypes[] = {
+ [NL80211_CHAN_NO_HT] = "noht",
+ [NL80211_CHAN_HT20] = "ht20",
+ [NL80211_CHAN_HT40MINUS] = "ht40-",
+ [NL80211_CHAN_HT40PLUS] = "ht40+",
+};
static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
{
struct mac80211_hwsim_data *data = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
- static const char *chantypes[4] = {
- [NL80211_CHAN_NO_HT] = "noht",
- [NL80211_CHAN_HT20] = "ht20",
- [NL80211_CHAN_HT40MINUS] = "ht40-",
- [NL80211_CHAN_HT40PLUS] = "ht40+",
- };
static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = {
[IEEE80211_SMPS_AUTOMATIC] = "auto",
[IEEE80211_SMPS_OFF] = "off",
@@ -673,7 +673,7 @@ static int mac80211_hwsim_config(struct
printk(KERN_DEBUG "%s:%s (freq=%d/%s idle=%d ps=%d smps=%s)\n",
wiphy_name(hw->wiphy), __func__,
conf->channel->center_freq,
- chantypes[conf->channel_type],
+ hwsim_chantypes[conf->channel_type],
!!(conf->flags & IEEE80211_CONF_IDLE),
!!(conf->flags & IEEE80211_CONF_PS),
smps_modes[conf->smps_mode]);
@@ -761,9 +761,10 @@ static void mac80211_hwsim_bss_info_chan
}
if (changed & BSS_CHANGED_HT) {
- printk(KERN_DEBUG " %s: HT: op_mode=0x%x\n",
+ printk(KERN_DEBUG " %s: HT: op_mode=0x%x, chantype=%s\n",
wiphy_name(hw->wiphy),
- info->ht_operation_mode);
+ info->ht_operation_mode,
+ hwsim_chantypes[info->channel_type]);
}
if (changed & BSS_CHANGED_BASIC_RATES) {
^ permalink raw reply
* [PATCH v2] cfg80211/mac80211: better channel handling
From: Johannes Berg @ 2010-05-05 13:25 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1273061543.3728.16.camel@jlt3.sipsolutions.net>
Currently (all tested with hwsim) you can do stupid
things like setting up an AP on a certain channel,
then adding another virtual interface and making
that associate on another channel -- this will make
the beaconing to move channel but obviously without
the necessary IEs data update.
In order to improve this situation, first make the
configuration APIs (cfg80211 and nl80211) aware of
multi-channel operation -- we'll eventually need
that in the future anyway. There's one userland API
change and one API addition. The API change is that
now SET_WIPHY must be called with virtual interface
index rather than only wiphy index in order to take
effect for that interface -- luckily all current
users (hostapd) do that. For monitor interfaces, the
old setting is preserved, but monitors are always
slaved to other devices anyway so no guarantees.
The second userland API change is the introduction
of a per virtual interface SET_CHANNEL command, that
hostapd should use going forward to make it easier
to understand what's going on (it can automatically
detect a kernel with this command).
Other than mac80211, no existing cfg80211 drivers
are affected by this change because they only allow
a single virtual interface.
mac80211, however, now needs to be aware that the
channel settings are per interface now, and needs
to disallow (for now) real multi-channel operation,
which is another important part of this patch.
One of the immediate benefits is that you can now
start hostapd to operate on a hardware that already
has a connection on another virtual interface, as
long as you specify the same channel.
Note that two things are left unhandled (this is an
improvement -- not a complete fix):
* different HT/no-HT modes
currently you could start an HT AP and then
connect to a non-HT network on the same channel
which would configure the hardware for no HT;
that can be fixed fairly easily
* CSA
An AP we're connected to on a virtual interface
might indicate switching channels, and in that
case we would follow it, regardless of how many
other interfaces are operating; this requires
more effort to fix but is pretty rare after all
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
drivers/net/wireless/libertas/cfg.c | 1
drivers/net/wireless/orinoco/cfg.c | 1
drivers/net/wireless/rndis_wlan.c | 4
include/linux/nl80211.h | 13 ++
include/net/cfg80211.h | 11 +-
net/mac80211/Makefile | 3
net/mac80211/cfg.c | 41 ++++++++
net/mac80211/chan.c | 57 ++++++++++++
net/mac80211/ieee80211_i.h | 11 ++
net/wireless/chan.c | 56 +++--------
net/wireless/core.h | 12 --
net/wireless/ibss.c | 5 -
net/wireless/nl80211.c | 171 +++++++++++++++++++++++++++---------
net/wireless/sme.c | 5 -
net/wireless/wext-compat.c | 15 ++-
net/wireless/wext-sme.c | 2
16 files changed, 300 insertions(+), 108 deletions(-)
--- wireless-testing.orig/include/linux/nl80211.h 2010-05-05 12:32:12.000000000 +0200
+++ wireless-testing/include/linux/nl80211.h 2010-05-05 12:32:49.000000000 +0200
@@ -52,6 +52,8 @@
* %NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT,
* %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
* and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD.
+ * However, for setting the channel, see %NL80211_CMD_SET_CHANNEL
+ * instead, the support here is for backward compatibility only.
* @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request
* or rename notification. Has attributes %NL80211_ATTR_WIPHY and
* %NL80211_ATTR_WIPHY_NAME.
@@ -329,6 +331,15 @@
* @NL80211_CMD_NOTIFY_CQM: Connection quality monitor notification. This
* command is used as an event to indicate the that a trigger level was
* reached.
+ * @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ
+ * and %NL80211_ATTR_WIPHY_CHANNEL_TYPE) the given interface (identifed
+ * by %NL80211_ATTR_IFINDEX) shall operate on.
+ * In case multiple channels are supported by the device, the mechanism
+ * with which it switches channels is implementation-defined.
+ * When a monitor interface is given, it can only switch channel while
+ * no other interfaces are operating to avoid disturbing the operation
+ * of any other interfaces, and other interfaces will again take
+ * precedence when they are used.
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
@@ -428,6 +439,8 @@ enum nl80211_commands {
NL80211_CMD_SET_CQM,
NL80211_CMD_NOTIFY_CQM,
+ NL80211_CMD_SET_CHANNEL,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
--- wireless-testing.orig/net/wireless/nl80211.c 2010-05-05 12:32:12.000000000 +0200
+++ wireless-testing/net/wireless/nl80211.c 2010-05-05 15:22:21.000000000 +0200
@@ -589,6 +589,7 @@ static int nl80211_send_wiphy(struct sk_
i++;
NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
}
+ CMD(set_channel, SET_CHANNEL);
#undef CMD
@@ -689,10 +690,90 @@ static int parse_txq_params(struct nlatt
return 0;
}
+static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
+{
+ /*
+ * You can only set the channel explicitly for AP, mesh
+ * and WDS type interfaces; all others have their channel
+ * managed via their respective "establish a connection"
+ * command (connect, join, ...)
+ *
+ * Monitors are special as they are normally slaved to
+ * whatever else is going on, so they behave as though
+ * you tried setting the wiphy channel itself.
+ */
+ return !wdev ||
+ wdev->iftype == NL80211_IFTYPE_AP ||
+ wdev->iftype == NL80211_IFTYPE_WDS ||
+ wdev->iftype == NL80211_IFTYPE_MESH_POINT ||
+ wdev->iftype == NL80211_IFTYPE_MONITOR;
+}
+
+static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ struct genl_info *info)
+{
+ enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
+ u32 freq;
+ int result;
+
+ if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
+ return -EINVAL;
+
+ if (!nl80211_can_set_dev_channel(wdev))
+ return -EOPNOTSUPP;
+
+ if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
+ channel_type = nla_get_u32(info->attrs[
+ NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
+ if (channel_type != NL80211_CHAN_NO_HT &&
+ channel_type != NL80211_CHAN_HT20 &&
+ channel_type != NL80211_CHAN_HT40PLUS &&
+ channel_type != NL80211_CHAN_HT40MINUS)
+ return -EINVAL;
+ }
+
+ freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
+
+ mutex_lock(&rdev->devlist_mtx);
+ if (wdev) {
+ wdev_lock(wdev);
+ result = cfg80211_set_freq(rdev, wdev, freq, channel_type);
+ wdev_unlock(wdev);
+ } else {
+ result = cfg80211_set_freq(rdev, NULL, freq, channel_type);
+ }
+ mutex_unlock(&rdev->devlist_mtx);
+
+ return result;
+}
+
+static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev;
+ struct net_device *netdev;
+ int result;
+
+ rtnl_lock();
+
+ result = get_rdev_dev_by_info_ifindex(info, &rdev, &netdev);
+ if (result)
+ goto unlock;
+
+ result = __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info);
+
+ unlock:
+ rtnl_unlock();
+
+ return result;
+}
+
static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev;
- int result = 0, rem_txq_params = 0;
+ struct net_device *netdev = NULL;
+ struct wireless_dev *wdev;
+ int result, rem_txq_params = 0;
struct nlattr *nl_txq_params;
u32 changed;
u8 retry_short = 0, retry_long = 0;
@@ -701,16 +782,50 @@ static int nl80211_set_wiphy(struct sk_b
rtnl_lock();
+ /*
+ * Try to find the wiphy and netdev. Normally this
+ * function shouldn't need the netdev, but this is
+ * done for backward compatibility -- previously
+ * setting the channel was done per wiphy, but now
+ * it is per netdev. Previous userland like hostapd
+ * also passed a netdev to set_wiphy, so that it is
+ * possible to let that go to the right netdev!
+ */
mutex_lock(&cfg80211_mutex);
- rdev = __cfg80211_rdev_from_info(info);
- if (IS_ERR(rdev)) {
- mutex_unlock(&cfg80211_mutex);
- result = PTR_ERR(rdev);
- goto unlock;
+ if (info->attrs[NL80211_ATTR_IFINDEX]) {
+ int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
+
+ netdev = dev_get_by_index(genl_info_net(info), ifindex);
+ if (netdev && netdev->ieee80211_ptr) {
+ rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy);
+ mutex_lock(&rdev->mtx);
+ } else
+ netdev = NULL;
}
- mutex_lock(&rdev->mtx);
+ if (!netdev) {
+ rdev = __cfg80211_rdev_from_info(info);
+ if (IS_ERR(rdev)) {
+ mutex_unlock(&cfg80211_mutex);
+ result = PTR_ERR(rdev);
+ goto unlock;
+ }
+ wdev = NULL;
+ netdev = NULL;
+ result = 0;
+
+ mutex_lock(&rdev->mtx);
+ } else if (netif_running(netdev) &&
+ nl80211_can_set_dev_channel(netdev->ieee80211_ptr))
+ wdev = netdev->ieee80211_ptr;
+ else
+ wdev = NULL;
+
+ /*
+ * end workaround code, by now the rdev is available
+ * and locked, and wdev may or may not be NULL.
+ */
if (info->attrs[NL80211_ATTR_WIPHY_NAME])
result = cfg80211_dev_rename(
@@ -749,26 +864,7 @@ static int nl80211_set_wiphy(struct sk_b
}
if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
- enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
- u32 freq;
-
- result = -EINVAL;
-
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
- channel_type = nla_get_u32(info->attrs[
- NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
- if (channel_type != NL80211_CHAN_NO_HT &&
- channel_type != NL80211_CHAN_HT20 &&
- channel_type != NL80211_CHAN_HT40PLUS &&
- channel_type != NL80211_CHAN_HT40MINUS)
- goto bad_res;
- }
-
- freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
-
- mutex_lock(&rdev->devlist_mtx);
- result = rdev_set_freq(rdev, NULL, freq, channel_type);
- mutex_unlock(&rdev->devlist_mtx);
+ result = __nl80211_set_channel(rdev, wdev, info);
if (result)
goto bad_res;
}
@@ -865,6 +961,8 @@ static int nl80211_set_wiphy(struct sk_b
bad_res:
mutex_unlock(&rdev->mtx);
+ if (netdev)
+ dev_put(netdev);
unlock:
rtnl_unlock();
return result;
@@ -3562,9 +3660,8 @@ static int nl80211_associate(struct sk_b
{
struct cfg80211_registered_device *rdev;
struct net_device *dev;
- struct wireless_dev *wdev;
struct cfg80211_crypto_settings crypto;
- struct ieee80211_channel *chan, *fixedchan;
+ struct ieee80211_channel *chan;
const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
int err, ssid_len, ie_len = 0;
bool use_mfp = false;
@@ -3607,16 +3704,6 @@ static int nl80211_associate(struct sk_b
goto out;
}
- mutex_lock(&rdev->devlist_mtx);
- wdev = dev->ieee80211_ptr;
- fixedchan = rdev_fixed_channel(rdev, wdev);
- if (fixedchan && chan != fixedchan) {
- err = -EBUSY;
- mutex_unlock(&rdev->devlist_mtx);
- goto out;
- }
- mutex_unlock(&rdev->devlist_mtx);
-
ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
@@ -5186,6 +5273,12 @@ static struct genl_ops nl80211_ops[] = {
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
},
+ {
+ .cmd = NL80211_CMD_SET_CHANNEL,
+ .doit = nl80211_set_channel,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
};
static struct genl_multicast_group nl80211_mlme_mcgrp = {
--- wireless-testing.orig/include/net/cfg80211.h 2010-05-05 12:32:12.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h 2010-05-05 12:32:49.000000000 +0200
@@ -966,7 +966,11 @@ struct cfg80211_pmksa {
*
* @set_txq_params: Set TX queue parameters
*
- * @set_channel: Set channel
+ * @set_channel: Set channel for a given wireless interface. Some devices
+ * may support multi-channel operation (by channel hopping) so cfg80211
+ * doesn't verify much. Note, however, that the passed netdev may be
+ * %NULL as well if the user requested changing the channel for the
+ * device itself, or for a monitor interface.
*
* @scan: Request to do a scan. If returning zero, the scan request is given
* the driver, and will be valid until passed to cfg80211_scan_done().
@@ -1095,7 +1099,7 @@ struct cfg80211_ops {
int (*set_txq_params)(struct wiphy *wiphy,
struct ieee80211_txq_params *params);
- int (*set_channel)(struct wiphy *wiphy,
+ int (*set_channel)(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type);
@@ -1461,6 +1465,8 @@ struct cfg80211_cached_keys;
* @list: (private) Used to collect the interfaces
* @netdev: (private) Used to reference back to the netdev
* @current_bss: (private) Used by the internal configuration code
+ * @channel: (private) Used by the internal configuration code to track
+ * user-set AP, monitor and WDS channels for wireless extensions
* @bssid: (private) Used by the internal configuration code
* @ssid: (private) Used by the internal configuration code
* @ssid_len: (private) Used by the internal configuration code
@@ -1507,6 +1513,7 @@ struct wireless_dev {
struct cfg80211_internal_bss *authtry_bsses[MAX_AUTH_BSSES];
struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES];
struct cfg80211_internal_bss *current_bss; /* associated / joined */
+ struct ieee80211_channel *channel;
bool ps;
int ps_timeout;
--- wireless-testing.orig/net/wireless/chan.c 2010-05-05 12:32:12.000000000 +0200
+++ wireless-testing/net/wireless/chan.c 2010-05-05 12:32:49.000000000 +0200
@@ -10,38 +10,6 @@
#include "core.h"
struct ieee80211_channel *
-rdev_fixed_channel(struct cfg80211_registered_device *rdev,
- struct wireless_dev *for_wdev)
-{
- struct wireless_dev *wdev;
- struct ieee80211_channel *result = NULL;
-
- WARN_ON(!mutex_is_locked(&rdev->devlist_mtx));
-
- list_for_each_entry(wdev, &rdev->netdev_list, list) {
- if (wdev == for_wdev)
- continue;
-
- /*
- * Lock manually to tell lockdep about allowed
- * nesting here if for_wdev->mtx is held already.
- * This is ok as it's all under the rdev devlist
- * mutex and as such can only be done once at any
- * given time.
- */
- mutex_lock_nested(&wdev->mtx, SINGLE_DEPTH_NESTING);
- if (wdev->current_bss)
- result = wdev->current_bss->pub.channel;
- wdev_unlock(wdev);
-
- if (result)
- break;
- }
-
- return result;
-}
-
-struct ieee80211_channel *
rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
int freq, enum nl80211_channel_type channel_type)
{
@@ -75,15 +43,22 @@ rdev_freq_to_chan(struct cfg80211_regist
return chan;
}
-int rdev_set_freq(struct cfg80211_registered_device *rdev,
- struct wireless_dev *for_wdev,
- int freq, enum nl80211_channel_type channel_type)
+int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev, int freq,
+ enum nl80211_channel_type channel_type)
{
struct ieee80211_channel *chan;
int result;
- if (rdev_fixed_channel(rdev, for_wdev))
- return -EBUSY;
+ if (wdev->iftype == NL80211_IFTYPE_MONITOR)
+ wdev = NULL;
+
+ if (wdev) {
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (!netif_running(wdev->netdev))
+ return -ENETDOWN;
+ }
if (!rdev->ops->set_channel)
return -EOPNOTSUPP;
@@ -92,11 +67,14 @@ int rdev_set_freq(struct cfg80211_regist
if (!chan)
return -EINVAL;
- result = rdev->ops->set_channel(&rdev->wiphy, chan, channel_type);
+ result = rdev->ops->set_channel(&rdev->wiphy,
+ wdev ? wdev->netdev : NULL,
+ chan, channel_type);
if (result)
return result;
- rdev->channel = chan;
+ if (wdev)
+ wdev->channel = chan;
return 0;
}
--- wireless-testing.orig/net/wireless/core.h 2010-05-05 12:32:12.000000000 +0200
+++ wireless-testing/net/wireless/core.h 2010-05-05 12:32:49.000000000 +0200
@@ -70,9 +70,6 @@ struct cfg80211_registered_device {
struct work_struct conn_work;
struct work_struct event_work;
- /* current channel */
- struct ieee80211_channel *channel;
-
/* must be last because of the way we do wiphy_priv(),
* and it should at least be aligned to NETDEV_ALIGN */
struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN)));
@@ -388,14 +385,11 @@ int cfg80211_change_iface(struct cfg8021
void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
struct ieee80211_channel *
-rdev_fixed_channel(struct cfg80211_registered_device *rdev,
- struct wireless_dev *for_wdev);
-struct ieee80211_channel *
rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
int freq, enum nl80211_channel_type channel_type);
-int rdev_set_freq(struct cfg80211_registered_device *rdev,
- struct wireless_dev *for_wdev,
- int freq, enum nl80211_channel_type channel_type);
+int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev, int freq,
+ enum nl80211_channel_type channel_type);
u16 cfg80211_calculate_bitrate(struct rate_info *rate);
--- wireless-testing.orig/net/wireless/wext-compat.c 2010-05-05 12:32:12.000000000 +0200
+++ wireless-testing/net/wireless/wext-compat.c 2010-05-05 12:32:49.000000000 +0200
@@ -782,16 +782,22 @@ int cfg80211_wext_siwfreq(struct net_dev
return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
case NL80211_IFTYPE_ADHOC:
return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
- default:
+ case NL80211_IFTYPE_MONITOR:
+ case NL80211_IFTYPE_WDS:
+ case NL80211_IFTYPE_MESH_POINT:
freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
if (freq < 0)
return freq;
if (freq == 0)
return -EINVAL;
+ wdev_lock(wdev);
mutex_lock(&rdev->devlist_mtx);
- err = rdev_set_freq(rdev, NULL, freq, NL80211_CHAN_NO_HT);
+ err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT);
mutex_unlock(&rdev->devlist_mtx);
+ wdev_unlock(wdev);
return err;
+ default:
+ return -EOPNOTSUPP;
}
}
EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq);
@@ -801,7 +807,6 @@ int cfg80211_wext_giwfreq(struct net_dev
struct iw_freq *freq, char *extra)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
@@ -809,9 +814,9 @@ int cfg80211_wext_giwfreq(struct net_dev
case NL80211_IFTYPE_ADHOC:
return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
default:
- if (!rdev->channel)
+ if (!wdev->channel)
return -EINVAL;
- freq->m = rdev->channel->center_freq;
+ freq->m = wdev->channel->center_freq;
freq->e = 6;
return 0;
}
--- wireless-testing.orig/net/wireless/wext-sme.c 2010-05-05 12:32:12.000000000 +0200
+++ wireless-testing/net/wireless/wext-sme.c 2010-05-05 12:32:49.000000000 +0200
@@ -108,7 +108,7 @@ int cfg80211_mgd_wext_siwfreq(struct net
/* SSID is not set, we just want to switch channel */
if (chan && !wdev->wext.connect.ssid_len) {
- err = rdev_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT);
+ err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT);
goto out;
}
--- wireless-testing.orig/net/wireless/ibss.c 2010-05-05 12:32:12.000000000 +0200
+++ wireless-testing/net/wireless/ibss.c 2010-05-05 12:32:49.000000000 +0200
@@ -81,15 +81,10 @@ int __cfg80211_join_ibss(struct cfg80211
struct cfg80211_cached_keys *connkeys)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct ieee80211_channel *chan;
int err;
ASSERT_WDEV_LOCK(wdev);
- chan = rdev_fixed_channel(rdev, wdev);
- if (chan && chan != params->channel)
- return -EBUSY;
-
if (wdev->ssid_len)
return -EALREADY;
--- wireless-testing.orig/net/wireless/sme.c 2010-05-05 12:32:12.000000000 +0200
+++ wireless-testing/net/wireless/sme.c 2010-05-05 12:32:49.000000000 +0200
@@ -741,7 +741,6 @@ int __cfg80211_connect(struct cfg80211_r
const u8 *prev_bssid)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct ieee80211_channel *chan;
struct cfg80211_bss *bss = NULL;
int err;
@@ -750,10 +749,6 @@ int __cfg80211_connect(struct cfg80211_r
if (wdev->sme_state != CFG80211_SME_IDLE)
return -EALREADY;
- chan = rdev_fixed_channel(rdev, wdev);
- if (chan && chan != connect->channel)
- return -EBUSY;
-
if (WARN_ON(wdev->connect_keys)) {
kfree(wdev->connect_keys);
wdev->connect_keys = NULL;
--- wireless-testing.orig/drivers/net/wireless/libertas/cfg.c 2010-05-05 12:32:12.000000000 +0200
+++ wireless-testing/drivers/net/wireless/libertas/cfg.c 2010-05-05 12:32:49.000000000 +0200
@@ -79,6 +79,7 @@ static const u32 cipher_suites[] = {
static int lbs_cfg_set_channel(struct wiphy *wiphy,
+ struct net_device *netdev,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type)
{
--- wireless-testing.orig/drivers/net/wireless/orinoco/cfg.c 2010-05-05 12:32:12.000000000 +0200
+++ wireless-testing/drivers/net/wireless/orinoco/cfg.c 2010-05-05 12:32:49.000000000 +0200
@@ -159,6 +159,7 @@ static int orinoco_scan(struct wiphy *wi
}
static int orinoco_set_channel(struct wiphy *wiphy,
+ struct net_device *netdev,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type)
{
--- wireless-testing.orig/drivers/net/wireless/rndis_wlan.c 2010-05-05 12:32:12.000000000 +0200
+++ wireless-testing/drivers/net/wireless/rndis_wlan.c 2010-05-05 12:32:49.000000000 +0200
@@ -535,7 +535,7 @@ static int rndis_join_ibss(struct wiphy
static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev);
-static int rndis_set_channel(struct wiphy *wiphy,
+static int rndis_set_channel(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_channel *chan, enum nl80211_channel_type channel_type);
static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
@@ -2291,7 +2291,7 @@ static int rndis_leave_ibss(struct wiphy
return deauthenticate(usbdev);
}
-static int rndis_set_channel(struct wiphy *wiphy,
+static int rndis_set_channel(struct wiphy *wiphy, struct net_device *netdev,
struct ieee80211_channel *chan, enum nl80211_channel_type channel_type)
{
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
--- wireless-testing.orig/net/mac80211/cfg.c 2010-05-05 12:32:12.000000000 +0200
+++ wireless-testing/net/mac80211/cfg.c 2010-05-05 15:21:53.000000000 +0200
@@ -1162,11 +1162,24 @@ static int ieee80211_set_txq_params(stru
}
static int ieee80211_set_channel(struct wiphy *wiphy,
+ struct net_device *netdev,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
+ switch (ieee80211_get_channel_mode(local, NULL)) {
+ case CHAN_MODE_HOPPING:
+ return -EBUSY;
+ case CHAN_MODE_FIXED:
+ if (local->oper_channel == chan &&
+ local->oper_channel_type == channel_type)
+ return 0;
+ return -EBUSY;
+ case CHAN_MODE_UNDEFINED:
+ break;
+ }
+
local->oper_channel = chan;
local->oper_channel_type = channel_type;
@@ -1214,6 +1227,20 @@ static int ieee80211_auth(struct wiphy *
static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_assoc_request *req)
{
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ switch (ieee80211_get_channel_mode(local, sdata)) {
+ case CHAN_MODE_HOPPING:
+ return -EBUSY;
+ case CHAN_MODE_FIXED:
+ if (local->oper_channel == req->bss->channel)
+ break;
+ return -EBUSY;
+ case CHAN_MODE_UNDEFINED:
+ break;
+ }
+
return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req);
}
@@ -1236,8 +1263,22 @@ static int ieee80211_disassoc(struct wip
static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ibss_params *params)
{
+ struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ switch (ieee80211_get_channel_mode(local, sdata)) {
+ case CHAN_MODE_HOPPING:
+ return -EBUSY;
+ case CHAN_MODE_FIXED:
+ if (!params->channel_fixed)
+ return -EBUSY;
+ if (local->oper_channel == params->channel)
+ break;
+ return -EBUSY;
+ case CHAN_MODE_UNDEFINED:
+ break;
+ }
+
return ieee80211_ibss_join(sdata, params);
}
--- wireless-testing.orig/net/mac80211/Makefile 2010-05-05 12:32:12.000000000 +0200
+++ wireless-testing/net/mac80211/Makefile 2010-05-05 12:32:49.000000000 +0200
@@ -23,7 +23,8 @@ mac80211-y := \
key.o \
util.o \
wme.o \
- event.o
+ event.o \
+ chan.o
mac80211-$(CONFIG_MAC80211_LEDS) += led.o
mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ wireless-testing/net/mac80211/chan.c 2010-05-05 15:21:53.000000000 +0200
@@ -0,0 +1,57 @@
+/*
+ * mac80211 - channel management
+ */
+
+#include "ieee80211_i.h"
+
+enum ieee80211_chan_mode
+__ieee80211_get_channel_mode(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *ignore)
+{
+ struct ieee80211_sub_if_data *sdata;
+
+ WARN_ON(!mutex_is_locked(&local->iflist_mtx));
+
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (sdata == ignore)
+ continue;
+
+ if (!ieee80211_sdata_running(sdata))
+ continue;
+
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+ continue;
+
+ if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+ !sdata->u.mgd.associated)
+ continue;
+
+ if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+ if (!sdata->u.ibss.ssid_len)
+ continue;
+ if (!sdata->u.ibss.fixed_channel)
+ return CHAN_MODE_HOPPING;
+ }
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP &&
+ !sdata->u.ap.beacon)
+ continue;
+
+ return CHAN_MODE_FIXED;
+ }
+
+ return CHAN_MODE_UNDEFINED;
+}
+
+enum ieee80211_chan_mode
+ieee80211_get_channel_mode(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *ignore)
+{
+ enum ieee80211_chan_mode mode;
+
+ mutex_lock(&local->iflist_mtx);
+ mode = __ieee80211_get_channel_mode(local, ignore);
+ mutex_unlock(&local->iflist_mtx);
+
+ return mode;
+}
--- wireless-testing.orig/net/mac80211/ieee80211_i.h 2010-05-05 12:32:12.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h 2010-05-05 15:21:53.000000000 +0200
@@ -1229,6 +1229,17 @@ int ieee80211_wk_remain_on_channel(struc
int ieee80211_wk_cancel_remain_on_channel(
struct ieee80211_sub_if_data *sdata, u64 cookie);
+/* channel management */
+enum ieee80211_chan_mode {
+ CHAN_MODE_UNDEFINED,
+ CHAN_MODE_HOPPING,
+ CHAN_MODE_FIXED,
+};
+
+enum ieee80211_chan_mode
+ieee80211_get_channel_mode(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *ignore);
+
#ifdef CONFIG_MAC80211_NOINLINE
#define debug_noinline noinline
#else
^ permalink raw reply
* Re: [PATCH] cfg80211/mac80211: better channel handling
From: Johannes Berg @ 2010-05-05 12:12 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
In-Reply-To: <1273055797.3728.14.camel@jlt3.sipsolutions.net>
On Wed, 2010-05-05 at 12:36 +0200, Johannes Berg wrote:
> In order to improve this situation, first make the
> configuration APIs (cfg80211 and nl80211) aware of
> multi-channel operation -- we'll eventually need
> that in the future anyway. There's one userland API
> change and one API addition. The API change is that
> now SET_WIPHY must be called with virtual interface
> index rather than only wiphy index in order to take
> effect for that interface -- luckily all current
> users (hostapd) do that. For monitor interfaces, the
> old setting is preserved, but monitors are always
> slaved to other devices anyway so no guarantees.
Withdrawn, contains a locking bug, sorry!
johannes
^ permalink raw reply
* Re: [PATCH] mac80211: Add HT IE to IBSS beacons and probe responses.
From: Johannes Berg @ 2010-05-05 11:46 UTC (permalink / raw)
To: Benoit Papillault; +Cc: linux-wireless
In-Reply-To: <1272955622-6987-3-git-send-email-benoit.papillault@free.fr>
On Tue, 2010-05-04 at 08:47 +0200, Benoit Papillault wrote:
> When an HT IBSS is configured, we add HT Information and HT Capabilities
> IE to beacon & probe responses. This is done according to channel_type
> transmitted by iw/cfg80211.
Just noticed something else -- this allows creating an HT40 IBSS on an
invalid channel pair -- do we want to catch that?
johannse
^ permalink raw reply
* [PATCH] cfg80211/mac80211: better channel handling
From: Johannes Berg @ 2010-05-05 10:36 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
Currently (all tested with hwsim) you can do stupid
things like setting up an AP on a certain channel,
then adding another virtual interface and making
that associate on another channel -- this will make
the beaconing to move channel but obviously without
the necessary IEs data update.
In order to improve this situation, first make the
configuration APIs (cfg80211 and nl80211) aware of
multi-channel operation -- we'll eventually need
that in the future anyway. There's one userland API
change and one API addition. The API change is that
now SET_WIPHY must be called with virtual interface
index rather than only wiphy index in order to take
effect for that interface -- luckily all current
users (hostapd) do that. For monitor interfaces, the
old setting is preserved, but monitors are always
slaved to other devices anyway so no guarantees.
The second userland API change is the introduction
of a per virtual interface SET_CHANNEL command, that
hostapd should use going forward to make it easier
to understand what's going on (it can automatically
detect a kernel with this command).
Other than mac80211, no existing cfg80211 drivers
are affected by this change because they only allow
a single virtual interface.
mac80211, however, now needs to be aware that the
channel settings are per interface now, and needs
to disallow (for now) real multi-channel operation,
which is another important part of this patch.
One of the immediate benefits is that you can now
start hostapd to operate on a hardware that already
has a connection on another virtual interface, as
long as you specify the same channel.
Note that two things are left unhandled (this is an
improvement -- not a complete fix):
* different HT/no-HT modes
currently you could start an HT AP and then
connect to a non-HT network on the same channel
which would configure the hardware for no HT;
that can be fixed fairly easily
* CSA
An AP we're connected to on a virtual interface
might indicate switching channels, and in that
case we would follow it, regardless of how many
other interfaces are operating; this requires
more effort to fix but is pretty rare after all
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
drivers/net/wireless/libertas/cfg.c | 1
drivers/net/wireless/orinoco/cfg.c | 1
drivers/net/wireless/rndis_wlan.c | 4
include/linux/nl80211.h | 13 ++
include/net/cfg80211.h | 11 +-
net/mac80211/Makefile | 3
net/mac80211/cfg.c | 41 +++++++++
net/mac80211/chan.c | 57 ++++++++++++
net/mac80211/ieee80211_i.h | 11 ++
net/wireless/chan.c | 56 +++---------
net/wireless/core.h | 12 --
net/wireless/ibss.c | 5 -
net/wireless/nl80211.c | 164 +++++++++++++++++++++++++++---------
net/wireless/sme.c | 5 -
net/wireless/wext-compat.c | 15 ++-
net/wireless/wext-sme.c | 2
16 files changed, 292 insertions(+), 109 deletions(-)
--- wireless-testing.orig/include/linux/nl80211.h 2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/include/linux/nl80211.h 2010-05-02 17:47:51.000000000 +0200
@@ -52,6 +52,8 @@
* %NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT,
* %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
* and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD.
+ * However, for setting the channel, see %NL80211_CMD_SET_CHANNEL
+ * instead, the support here is for backward compatibility only.
* @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request
* or rename notification. Has attributes %NL80211_ATTR_WIPHY and
* %NL80211_ATTR_WIPHY_NAME.
@@ -329,6 +331,15 @@
* @NL80211_CMD_NOTIFY_CQM: Connection quality monitor notification. This
* command is used as an event to indicate the that a trigger level was
* reached.
+ * @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ
+ * and %NL80211_ATTR_WIPHY_CHANNEL_TYPE) the given interface (identifed
+ * by %NL80211_ATTR_IFINDEX) shall operate on.
+ * In case multiple channels are supported by the device, the mechanism
+ * with which it switches channels is implementation-defined.
+ * When a monitor interface is given, it can only switch channel while
+ * no other interfaces are operating to avoid disturbing the operation
+ * of any other interfaces, and other interfaces will again take
+ * precedence when they are used.
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
@@ -428,6 +439,8 @@ enum nl80211_commands {
NL80211_CMD_SET_CQM,
NL80211_CMD_NOTIFY_CQM,
+ NL80211_CMD_SET_CHANNEL,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
--- wireless-testing.orig/net/wireless/nl80211.c 2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/wireless/nl80211.c 2010-05-03 08:55:32.000000000 +0200
@@ -589,6 +589,7 @@ static int nl80211_send_wiphy(struct sk_
i++;
NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
}
+ CMD(set_channel, SET_CHANNEL);
#undef CMD
@@ -689,10 +690,90 @@ static int parse_txq_params(struct nlatt
return 0;
}
+static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
+{
+ /*
+ * You can only set the channel explicitly for AP, mesh
+ * and WDS type interfaces; all others have their channel
+ * managed via their respective "establish a connection"
+ * command (connect, join, ...)
+ *
+ * Monitors are special as they are normally slaved to
+ * whatever else is going on, so they behave as though
+ * you tried setting the wiphy channel itself.
+ */
+ return !wdev ||
+ wdev->iftype == NL80211_IFTYPE_AP ||
+ wdev->iftype == NL80211_IFTYPE_WDS ||
+ wdev->iftype == NL80211_IFTYPE_MESH_POINT ||
+ wdev->iftype == NL80211_IFTYPE_MONITOR;
+}
+
+static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ struct genl_info *info)
+{
+ enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
+ u32 freq;
+ int result;
+
+ if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
+ return -EINVAL;
+
+ if (!nl80211_can_set_dev_channel(wdev))
+ return -EOPNOTSUPP;
+
+ if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
+ channel_type = nla_get_u32(info->attrs[
+ NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
+ if (channel_type != NL80211_CHAN_NO_HT &&
+ channel_type != NL80211_CHAN_HT20 &&
+ channel_type != NL80211_CHAN_HT40PLUS &&
+ channel_type != NL80211_CHAN_HT40MINUS)
+ return -EINVAL;
+ }
+
+ freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
+
+ mutex_lock(&rdev->devlist_mtx);
+ if (wdev) {
+ wdev_lock(wdev);
+ result = cfg80211_set_freq(rdev, wdev, freq, channel_type);
+ wdev_unlock(wdev);
+ } else {
+ result = cfg80211_set_freq(rdev, NULL, freq, channel_type);
+ }
+ mutex_unlock(&rdev->devlist_mtx);
+
+ return result;
+}
+
+static int nl80211_set_channel(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev;
+ struct net_device *netdev;
+ int result;
+
+ rtnl_lock();
+
+ result = get_rdev_dev_by_info_ifindex(info, &rdev, &netdev);
+ if (result)
+ goto unlock;
+
+ result = __nl80211_set_channel(rdev, netdev->ieee80211_ptr, info);
+
+ unlock:
+ rtnl_unlock();
+
+ return result;
+}
+
static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev;
- int result = 0, rem_txq_params = 0;
+ struct net_device *netdev;
+ struct wireless_dev *wdev;
+ int result, rem_txq_params = 0;
struct nlattr *nl_txq_params;
u32 changed;
u8 retry_short = 0, retry_long = 0;
@@ -701,16 +782,41 @@ static int nl80211_set_wiphy(struct sk_b
rtnl_lock();
+ /*
+ * Try to find the wiphy and netdev. Normally this
+ * function shouldn't need the netdev, but this is
+ * done for backward compatibility -- previously
+ * setting the channel was done per wiphy, but now
+ * it is per netdev. Previous userland like hostapd
+ * also passed a netdev to set_wiphy, so that it is
+ * possible to let that go to the right netdev!
+ */
+ result = get_rdev_dev_by_info_ifindex(info, &rdev, &netdev);
+
mutex_lock(&cfg80211_mutex);
+ if (result) {
+ rdev = __cfg80211_rdev_from_info(info);
+ if (IS_ERR(rdev)) {
+ mutex_unlock(&cfg80211_mutex);
+ result = PTR_ERR(rdev);
+ goto unlock;
+ }
+ wdev = NULL;
+ netdev = NULL;
+ result = 0;
+
+ mutex_lock(&rdev->mtx);
+ } else if (netif_running(netdev) &&
+ nl80211_can_set_dev_channel(netdev->ieee80211_ptr))
+ wdev = netdev->ieee80211_ptr;
+ else
+ wdev = NULL;
- rdev = __cfg80211_rdev_from_info(info);
- if (IS_ERR(rdev)) {
- mutex_unlock(&cfg80211_mutex);
- result = PTR_ERR(rdev);
- goto unlock;
- }
+ /*
+ * end workaround code, by now the rdev is available
+ * and locked, and wdev may or may not be NULL
+ */
- mutex_lock(&rdev->mtx);
if (info->attrs[NL80211_ATTR_WIPHY_NAME])
result = cfg80211_dev_rename(
@@ -749,26 +855,7 @@ static int nl80211_set_wiphy(struct sk_b
}
if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
- enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
- u32 freq;
-
- result = -EINVAL;
-
- if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
- channel_type = nla_get_u32(info->attrs[
- NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
- if (channel_type != NL80211_CHAN_NO_HT &&
- channel_type != NL80211_CHAN_HT20 &&
- channel_type != NL80211_CHAN_HT40PLUS &&
- channel_type != NL80211_CHAN_HT40MINUS)
- goto bad_res;
- }
-
- freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
-
- mutex_lock(&rdev->devlist_mtx);
- result = rdev_set_freq(rdev, NULL, freq, channel_type);
- mutex_unlock(&rdev->devlist_mtx);
+ result = __nl80211_set_channel(rdev, wdev, info);
if (result)
goto bad_res;
}
@@ -865,6 +952,8 @@ static int nl80211_set_wiphy(struct sk_b
bad_res:
mutex_unlock(&rdev->mtx);
+ if (netdev)
+ dev_put(netdev);
unlock:
rtnl_unlock();
return result;
@@ -3562,9 +3651,8 @@ static int nl80211_associate(struct sk_b
{
struct cfg80211_registered_device *rdev;
struct net_device *dev;
- struct wireless_dev *wdev;
struct cfg80211_crypto_settings crypto;
- struct ieee80211_channel *chan, *fixedchan;
+ struct ieee80211_channel *chan;
const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
int err, ssid_len, ie_len = 0;
bool use_mfp = false;
@@ -3607,16 +3695,6 @@ static int nl80211_associate(struct sk_b
goto out;
}
- mutex_lock(&rdev->devlist_mtx);
- wdev = dev->ieee80211_ptr;
- fixedchan = rdev_fixed_channel(rdev, wdev);
- if (fixedchan && chan != fixedchan) {
- err = -EBUSY;
- mutex_unlock(&rdev->devlist_mtx);
- goto out;
- }
- mutex_unlock(&rdev->devlist_mtx);
-
ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
@@ -5186,6 +5264,12 @@ static struct genl_ops nl80211_ops[] = {
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
},
+ {
+ .cmd = NL80211_CMD_SET_CHANNEL,
+ .doit = nl80211_set_channel,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
};
static struct genl_multicast_group nl80211_mlme_mcgrp = {
--- wireless-testing.orig/include/net/cfg80211.h 2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h 2010-05-02 17:47:51.000000000 +0200
@@ -966,7 +966,11 @@ struct cfg80211_pmksa {
*
* @set_txq_params: Set TX queue parameters
*
- * @set_channel: Set channel
+ * @set_channel: Set channel for a given wireless interface. Some devices
+ * may support multi-channel operation (by channel hopping) so cfg80211
+ * doesn't verify much. Note, however, that the passed netdev may be
+ * %NULL as well if the user requested changing the channel for the
+ * device itself, or for a monitor interface.
*
* @scan: Request to do a scan. If returning zero, the scan request is given
* the driver, and will be valid until passed to cfg80211_scan_done().
@@ -1095,7 +1099,7 @@ struct cfg80211_ops {
int (*set_txq_params)(struct wiphy *wiphy,
struct ieee80211_txq_params *params);
- int (*set_channel)(struct wiphy *wiphy,
+ int (*set_channel)(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type);
@@ -1461,6 +1465,8 @@ struct cfg80211_cached_keys;
* @list: (private) Used to collect the interfaces
* @netdev: (private) Used to reference back to the netdev
* @current_bss: (private) Used by the internal configuration code
+ * @channel: (private) Used by the internal configuration code to track
+ * user-set AP, monitor and WDS channels for wireless extensions
* @bssid: (private) Used by the internal configuration code
* @ssid: (private) Used by the internal configuration code
* @ssid_len: (private) Used by the internal configuration code
@@ -1507,6 +1513,7 @@ struct wireless_dev {
struct cfg80211_internal_bss *authtry_bsses[MAX_AUTH_BSSES];
struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES];
struct cfg80211_internal_bss *current_bss; /* associated / joined */
+ struct ieee80211_channel *channel;
bool ps;
int ps_timeout;
--- wireless-testing.orig/net/wireless/chan.c 2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/wireless/chan.c 2010-05-02 17:47:51.000000000 +0200
@@ -10,38 +10,6 @@
#include "core.h"
struct ieee80211_channel *
-rdev_fixed_channel(struct cfg80211_registered_device *rdev,
- struct wireless_dev *for_wdev)
-{
- struct wireless_dev *wdev;
- struct ieee80211_channel *result = NULL;
-
- WARN_ON(!mutex_is_locked(&rdev->devlist_mtx));
-
- list_for_each_entry(wdev, &rdev->netdev_list, list) {
- if (wdev == for_wdev)
- continue;
-
- /*
- * Lock manually to tell lockdep about allowed
- * nesting here if for_wdev->mtx is held already.
- * This is ok as it's all under the rdev devlist
- * mutex and as such can only be done once at any
- * given time.
- */
- mutex_lock_nested(&wdev->mtx, SINGLE_DEPTH_NESTING);
- if (wdev->current_bss)
- result = wdev->current_bss->pub.channel;
- wdev_unlock(wdev);
-
- if (result)
- break;
- }
-
- return result;
-}
-
-struct ieee80211_channel *
rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
int freq, enum nl80211_channel_type channel_type)
{
@@ -75,15 +43,22 @@ rdev_freq_to_chan(struct cfg80211_regist
return chan;
}
-int rdev_set_freq(struct cfg80211_registered_device *rdev,
- struct wireless_dev *for_wdev,
- int freq, enum nl80211_channel_type channel_type)
+int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev, int freq,
+ enum nl80211_channel_type channel_type)
{
struct ieee80211_channel *chan;
int result;
- if (rdev_fixed_channel(rdev, for_wdev))
- return -EBUSY;
+ if (wdev->iftype == NL80211_IFTYPE_MONITOR)
+ wdev = NULL;
+
+ if (wdev) {
+ ASSERT_WDEV_LOCK(wdev);
+
+ if (!netif_running(wdev->netdev))
+ return -ENETDOWN;
+ }
if (!rdev->ops->set_channel)
return -EOPNOTSUPP;
@@ -92,11 +67,14 @@ int rdev_set_freq(struct cfg80211_regist
if (!chan)
return -EINVAL;
- result = rdev->ops->set_channel(&rdev->wiphy, chan, channel_type);
+ result = rdev->ops->set_channel(&rdev->wiphy,
+ wdev ? wdev->netdev : NULL,
+ chan, channel_type);
if (result)
return result;
- rdev->channel = chan;
+ if (wdev)
+ wdev->channel = chan;
return 0;
}
--- wireless-testing.orig/net/wireless/core.h 2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/wireless/core.h 2010-05-02 17:47:51.000000000 +0200
@@ -70,9 +70,6 @@ struct cfg80211_registered_device {
struct work_struct conn_work;
struct work_struct event_work;
- /* current channel */
- struct ieee80211_channel *channel;
-
/* must be last because of the way we do wiphy_priv(),
* and it should at least be aligned to NETDEV_ALIGN */
struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN)));
@@ -388,14 +385,11 @@ int cfg80211_change_iface(struct cfg8021
void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
struct ieee80211_channel *
-rdev_fixed_channel(struct cfg80211_registered_device *rdev,
- struct wireless_dev *for_wdev);
-struct ieee80211_channel *
rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
int freq, enum nl80211_channel_type channel_type);
-int rdev_set_freq(struct cfg80211_registered_device *rdev,
- struct wireless_dev *for_wdev,
- int freq, enum nl80211_channel_type channel_type);
+int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev, int freq,
+ enum nl80211_channel_type channel_type);
u16 cfg80211_calculate_bitrate(struct rate_info *rate);
--- wireless-testing.orig/net/wireless/wext-compat.c 2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/wireless/wext-compat.c 2010-05-02 17:47:51.000000000 +0200
@@ -782,16 +782,22 @@ int cfg80211_wext_siwfreq(struct net_dev
return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
case NL80211_IFTYPE_ADHOC:
return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
- default:
+ case NL80211_IFTYPE_MONITOR:
+ case NL80211_IFTYPE_WDS:
+ case NL80211_IFTYPE_MESH_POINT:
freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
if (freq < 0)
return freq;
if (freq == 0)
return -EINVAL;
+ wdev_lock(wdev);
mutex_lock(&rdev->devlist_mtx);
- err = rdev_set_freq(rdev, NULL, freq, NL80211_CHAN_NO_HT);
+ err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT);
mutex_unlock(&rdev->devlist_mtx);
+ wdev_unlock(wdev);
return err;
+ default:
+ return -EOPNOTSUPP;
}
}
EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq);
@@ -801,7 +807,6 @@ int cfg80211_wext_giwfreq(struct net_dev
struct iw_freq *freq, char *extra)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
@@ -809,9 +814,9 @@ int cfg80211_wext_giwfreq(struct net_dev
case NL80211_IFTYPE_ADHOC:
return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
default:
- if (!rdev->channel)
+ if (!wdev->channel)
return -EINVAL;
- freq->m = rdev->channel->center_freq;
+ freq->m = wdev->channel->center_freq;
freq->e = 6;
return 0;
}
--- wireless-testing.orig/net/wireless/wext-sme.c 2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/wireless/wext-sme.c 2010-05-02 17:47:51.000000000 +0200
@@ -108,7 +108,7 @@ int cfg80211_mgd_wext_siwfreq(struct net
/* SSID is not set, we just want to switch channel */
if (chan && !wdev->wext.connect.ssid_len) {
- err = rdev_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT);
+ err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT);
goto out;
}
--- wireless-testing.orig/net/wireless/ibss.c 2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/wireless/ibss.c 2010-05-02 17:47:51.000000000 +0200
@@ -81,15 +81,10 @@ int __cfg80211_join_ibss(struct cfg80211
struct cfg80211_cached_keys *connkeys)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct ieee80211_channel *chan;
int err;
ASSERT_WDEV_LOCK(wdev);
- chan = rdev_fixed_channel(rdev, wdev);
- if (chan && chan != params->channel)
- return -EBUSY;
-
if (wdev->ssid_len)
return -EALREADY;
--- wireless-testing.orig/net/wireless/sme.c 2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/wireless/sme.c 2010-05-02 17:47:51.000000000 +0200
@@ -741,7 +741,6 @@ int __cfg80211_connect(struct cfg80211_r
const u8 *prev_bssid)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct ieee80211_channel *chan;
struct cfg80211_bss *bss = NULL;
int err;
@@ -750,10 +749,6 @@ int __cfg80211_connect(struct cfg80211_r
if (wdev->sme_state != CFG80211_SME_IDLE)
return -EALREADY;
- chan = rdev_fixed_channel(rdev, wdev);
- if (chan && chan != connect->channel)
- return -EBUSY;
-
if (WARN_ON(wdev->connect_keys)) {
kfree(wdev->connect_keys);
wdev->connect_keys = NULL;
--- wireless-testing.orig/drivers/net/wireless/libertas/cfg.c 2010-05-02 17:47:48.000000000 +0200
+++ wireless-testing/drivers/net/wireless/libertas/cfg.c 2010-05-02 17:47:51.000000000 +0200
@@ -79,6 +79,7 @@ static const u32 cipher_suites[] = {
static int lbs_cfg_set_channel(struct wiphy *wiphy,
+ struct net_device *netdev,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type)
{
--- wireless-testing.orig/drivers/net/wireless/orinoco/cfg.c 2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/drivers/net/wireless/orinoco/cfg.c 2010-05-02 17:47:51.000000000 +0200
@@ -159,6 +159,7 @@ static int orinoco_scan(struct wiphy *wi
}
static int orinoco_set_channel(struct wiphy *wiphy,
+ struct net_device *netdev,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type)
{
--- wireless-testing.orig/drivers/net/wireless/rndis_wlan.c 2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/drivers/net/wireless/rndis_wlan.c 2010-05-02 17:47:51.000000000 +0200
@@ -535,7 +535,7 @@ static int rndis_join_ibss(struct wiphy
static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev);
-static int rndis_set_channel(struct wiphy *wiphy,
+static int rndis_set_channel(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_channel *chan, enum nl80211_channel_type channel_type);
static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
@@ -2291,7 +2291,7 @@ static int rndis_leave_ibss(struct wiphy
return deauthenticate(usbdev);
}
-static int rndis_set_channel(struct wiphy *wiphy,
+static int rndis_set_channel(struct wiphy *wiphy, struct net_device *netdev,
struct ieee80211_channel *chan, enum nl80211_channel_type channel_type)
{
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
--- wireless-testing.orig/net/mac80211/cfg.c 2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/mac80211/cfg.c 2010-05-02 17:47:51.000000000 +0200
@@ -1162,11 +1162,24 @@ static int ieee80211_set_txq_params(stru
}
static int ieee80211_set_channel(struct wiphy *wiphy,
+ struct net_device *netdev,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
+ switch (ieee80211_get_channel_mode(local, NULL)) {
+ case CHAN_MODE_HOPPING:
+ return -EBUSY;
+ case CHAN_MODE_FIXED:
+ if (local->oper_channel == chan &&
+ local->oper_channel_type == channel_type)
+ return 0;
+ return -EBUSY;
+ case CHAN_MODE_UNDEFINED:
+ break;
+ }
+
local->oper_channel = chan;
local->oper_channel_type = channel_type;
@@ -1214,6 +1227,20 @@ static int ieee80211_auth(struct wiphy *
static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_assoc_request *req)
{
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ switch (ieee80211_get_channel_mode(local, sdata)) {
+ case CHAN_MODE_HOPPING:
+ return -EBUSY;
+ case CHAN_MODE_FIXED:
+ if (local->oper_channel == req->bss->channel)
+ break;
+ return -EBUSY;
+ case CHAN_MODE_UNDEFINED:
+ break;
+ }
+
return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req);
}
@@ -1236,8 +1263,22 @@ static int ieee80211_disassoc(struct wip
static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ibss_params *params)
{
+ struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ switch (ieee80211_get_channel_mode(local, sdata)) {
+ case CHAN_MODE_HOPPING:
+ return -EBUSY;
+ case CHAN_MODE_FIXED:
+ if (!params->channel_fixed)
+ return -EBUSY;
+ if (local->oper_channel == params->channel)
+ break;
+ return -EBUSY;
+ case CHAN_MODE_UNDEFINED:
+ break;
+ }
+
return ieee80211_ibss_join(sdata, params);
}
--- wireless-testing.orig/net/mac80211/Makefile 2010-05-02 17:47:47.000000000 +0200
+++ wireless-testing/net/mac80211/Makefile 2010-05-02 17:47:51.000000000 +0200
@@ -23,7 +23,8 @@ mac80211-y := \
key.o \
util.o \
wme.o \
- event.o
+ event.o \
+ chan.o
mac80211-$(CONFIG_MAC80211_LEDS) += led.o
mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ wireless-testing/net/mac80211/chan.c 2010-05-02 17:47:51.000000000 +0200
@@ -0,0 +1,57 @@
+/*
+ * mac80211 - channel management
+ */
+
+#include "ieee80211_i.h"
+
+enum ieee80211_chan_mode
+__ieee80211_get_channel_mode(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *ignore)
+{
+ struct ieee80211_sub_if_data *sdata;
+
+ WARN_ON(!mutex_is_locked(&local->iflist_mtx));
+
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (sdata == ignore)
+ continue;
+
+ if (!ieee80211_sdata_running(sdata))
+ continue;
+
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+ continue;
+
+ if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+ !sdata->u.mgd.associated)
+ continue;
+
+ if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+ if (!sdata->u.ibss.ssid_len)
+ continue;
+ if (!sdata->u.ibss.fixed_channel)
+ return CHAN_MODE_HOPPING;
+ }
+
+ if (sdata->vif.type == NL80211_IFTYPE_AP &&
+ !sdata->u.ap.beacon)
+ continue;
+
+ return CHAN_MODE_FIXED;
+ }
+
+ return CHAN_MODE_UNDEFINED;
+}
+
+enum ieee80211_chan_mode
+ieee80211_get_channel_mode(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *ignore)
+{
+ enum ieee80211_chan_mode mode;
+
+ mutex_lock(&local->iflist_mtx);
+ mode = __ieee80211_get_channel_mode(local, ignore);
+ mutex_unlock(&local->iflist_mtx);
+
+ return mode;
+}
--- wireless-testing.orig/net/mac80211/ieee80211_i.h 2010-05-02 17:47:50.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h 2010-05-02 17:47:51.000000000 +0200
@@ -1229,6 +1229,17 @@ int ieee80211_wk_remain_on_channel(struc
int ieee80211_wk_cancel_remain_on_channel(
struct ieee80211_sub_if_data *sdata, u64 cookie);
+/* channel management */
+enum ieee80211_chan_mode {
+ CHAN_MODE_UNDEFINED,
+ CHAN_MODE_HOPPING,
+ CHAN_MODE_FIXED,
+};
+
+enum ieee80211_chan_mode
+ieee80211_get_channel_mode(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *ignore);
+
#ifdef CONFIG_MAC80211_NOINLINE
#define debug_noinline noinline
#else
^ permalink raw reply
* 2.6.33.2: Turn tx power off/on for Atheros card
From: Yegor Yefremov @ 2010-05-05 10:26 UTC (permalink / raw)
To: linux-wireless
I'm using kernel 2.6.33.2 with AR2413 WLAN card. Issuing
iwconfig wlan0 txpower off
turns txpower off. I can see this status by iwconfig wlan0 and the
communication with AP terminates. But when I turn the txpower on
iwconfig wlan0 txpower on
nothing happens. Though iwconfig shows the previous tx power value.
Only ifconfig wlan0 down and then up recovers the transmission.
Is it a known bug or I'm doing something wrong?
Regards,
Yegor
^ permalink raw reply
* [PATCH] compat-wireless: rt2x00 added to driver-select
From: Walter Goldens @ 2010-05-05 9:44 UTC (permalink / raw)
To: Luis R. Rodriguez; +Cc: linux-wireless, users
Signed-off-by: Walter Goldens <goldenstranger@yahoo.com>
---
With the ever expanding and improving rt2x00 supporting myriad of devices, I think its about time we enabled faster compilation via scripts/driver-select.
--- a/scripts/driver-select 2010-05-05 12:02:23.000000000 +0300
+++ b/scripts/driver-select 2010-05-05 12:02:01.000000000 +0300
@@ -7,6 +7,7 @@
DRIVERS_MAKEFILE="drivers/net/wireless/Makefile"
ATH_MAKEFILE="drivers/net/wireless/ath/Makefile"
ATH9K_MAKEFILE="drivers/net/wireless/ath/ath9k/Makefile"
+RT2X00_MAKEFILE="drivers/net/wireless/rt2x00/Makefile"
NET_WIRELESS_MAKEFILE="net/wireless/Makefile"
EEPROM_MAKEFILE="drivers/misc/eeprom/Makefile"
DRIVERS_NET="drivers/net/Makefile"
@@ -29,7 +30,7 @@ PURPLE="\033[35m"
CYAN="\033[36m"
UNDERLINE="\033[02m"
-SUPPORTED_DRIVERS="ath5k ath9k ath9k_htc ar9170 b43 zd1211rw"
+SUPPORTED_DRIVERS="ath5k ath9k ath9k_htc ar9170 b43 zd1211rw rt2x00"
function usage {
echo -e "${GREEN}Usage${NORMAL}: ${CYAN}$0${NORMAL} [ ${PURPLE}<driver-name>${NORMAL} | ${PURPLE}<driver-group-name>${NORMAL} | ${GREEN}restore${NORMAL} ]"
@@ -293,6 +294,10 @@ case $1 in
disable_var_03
select_driver CONFIG_B43
;;
+ rt2x00)
+ select_driver CONFIG_RT2X00
+ disable_var_02
+ ;;
*)
echo "Unsupported driver"
exit
^ permalink raw reply
* Re: [PATCH] mac80211: fix BSS info reconfiguration
From: Johannes Berg @ 2010-05-05 7:47 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Reinette Chatre
In-Reply-To: <1273045442.3728.1.camel@jlt3.sipsolutions.net>
On Wed, 2010-05-05 at 09:44 +0200, Johannes Berg wrote:
> When reconfiguring an interface due to a previous
> hardware restart, mac80211 will currently include
> the new IBSS flag on non-IBSS interfaces which may
> confuse drivers.
>
> Instead of doing the ~0 trick, simply spell out
> which things are going to be reconfigured.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Oops, that might get confusing.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
though I'm still me either way I think.
> ---
> include/net/mac80211.h | 2 ++
> net/mac80211/util.c | 25 ++++++++++++++++++++-----
> 2 files changed, 22 insertions(+), 5 deletions(-)
>
> --- wireless-testing.orig/include/net/mac80211.h 2010-05-01 08:47:54.000000000 +0200
> +++ wireless-testing/include/net/mac80211.h 2010-05-05 09:41:46.000000000 +0200
> @@ -160,6 +160,8 @@ enum ieee80211_bss_change {
> BSS_CHANGED_BEACON_ENABLED = 1<<9,
> BSS_CHANGED_CQM = 1<<10,
> BSS_CHANGED_IBSS = 1<<11,
> +
> + /* when adding here, make sure to change ieee80211_reconfig */
> };
>
> /**
> --- wireless-testing.orig/net/mac80211/util.c 2010-04-09 11:46:46.000000000 +0200
> +++ wireless-testing/net/mac80211/util.c 2010-05-05 09:41:46.000000000 +0200
> @@ -1160,18 +1160,33 @@ int ieee80211_reconfig(struct ieee80211_
>
> /* Finally also reconfigure all the BSS information */
> list_for_each_entry(sdata, &local->interfaces, list) {
> - u32 changed = ~0;
> + u32 changed;
> +
> if (!ieee80211_sdata_running(sdata))
> continue;
> +
> + /* common change flags for all interface types */
> + changed = BSS_CHANGED_ERP_CTS_PROT |
> + BSS_CHANGED_ERP_PREAMBLE |
> + BSS_CHANGED_ERP_SLOT |
> + BSS_CHANGED_HT |
> + BSS_CHANGED_BASIC_RATES |
> + BSS_CHANGED_BEACON_INT |
> + BSS_CHANGED_BSSID |
> + BSS_CHANGED_CQM;
> +
> switch (sdata->vif.type) {
> case NL80211_IFTYPE_STATION:
> - /* disable beacon change bits */
> - changed &= ~(BSS_CHANGED_BEACON |
> - BSS_CHANGED_BEACON_ENABLED);
> - /* fall through */
> + changed |= BSS_CHANGED_ASSOC;
> + ieee80211_bss_info_change_notify(sdata, changed);
> + break;
> case NL80211_IFTYPE_ADHOC:
> + changed |= BSS_CHANGED_IBSS;
> + /* fall through */
> case NL80211_IFTYPE_AP:
> case NL80211_IFTYPE_MESH_POINT:
> + changed |= BSS_CHANGED_BEACON |
> + BSS_CHANGED_BEACON_ENABLED;
> ieee80211_bss_info_change_notify(sdata, changed);
> break;
> case NL80211_IFTYPE_WDS:
>
>
> --
> 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
>
^ permalink raw reply
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