Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH] b43: Fix hardware key index handling
From: Michael Buesch @ 2009-08-07 18:27 UTC (permalink / raw)
  To: John W. Linville; +Cc: wireless, bcm43xx-dev, gregor kowski
In-Reply-To: <20090807143726.GB7545@tuxdriver.com>

On Friday 07 August 2009 16:37:26 John W. Linville wrote:
> On Thu, Aug 06, 2009 at 10:36:50AM +0200, Michael Buesch wrote:
> > This fixes the hardware encryption keys index and array size handling.
> > 
> > Thanks to Gregor Kowski for reporting this issue.
> > 
> > Signed-off-by: Michael Buesch <mb@bu3sch.de>
> > 
> > ---
> > 
> > This should probably go as a bugfix.
> > (Does this actually fix the PHY transmission errors? I don't see them anymore...
> > Note that you need to enable debugging to see them.)
> 
> It's getting a bit late in the cycle, especially for a patch so large
> and (at least to me) non-obvious.  What is the actual bug being fixed?
> What is the effect of leaving it for 2.6.32?

AP mode might break under certain conditions (lots of STAs connected).
Please leave it for .32

-- 
Greetings, Michael.

^ permalink raw reply

* Re: [PATCH] mac80211: allow DMA optimisation
From: Ivo van Doorn @ 2009-08-07 18:21 UTC (permalink / raw)
  To: Johannes Berg; +Cc: John Linville, linux-wireless
In-Reply-To: <1249668106.7194.10.camel@johannes.local>

On Friday 07 August 2009, Johannes Berg wrote:
> On Fri, 2009-08-07 at 18:55 +0200, Ivo van Doorn wrote:
> 
> > > If we have a lot of frames to transmit at once, for
> > > instance with fragmentation, it can be an optimisation
> > > to only tell the DMA engine about them on the last
> > > fragment/frame to avoid banging the IO too much. This
> > > patch allows implementation such an optimisation by
> > > telling the driver when more frames can be expected.
> > 
> > Wouldn't this be the same as the
> > 	if (ieee80211_has_morefrags())
> > 		.. kick queue ...
> 
> Initially, yes, but I think we should eventually use it for sending out
> multiple frames after restarting queues etc. For instance after
> scanning, we could send out a bunch of frames at once.

This would work for PCI devices, but USB devices can spoil the
fun (as usual) because those devices use the queue in the hardware
and you can't control the actual "kick".

> > > Currently, this is used by mac80211 only on fragmented
> > > frames, but could also be used in the future on other
> > > frames when the queue was full and there are multiple
> > > frames pending.
> > >
> > > Note that drivers need to be careful when using this
> > > flag, they need to kick their DMA engines not just
> > > when this flag is clear, but also when the queue gets
> > > full so that progress can be made.
> > 
> > What would a good value be for the threshold?
> > rt2x00 currently uses 10% of the queue, which means that
> > 2 or 3 entries are kept available at all times.
> 
> Well, for fragmentation I think the maximum number of fragments is 9.

Ok, I'll look into increasing the queue size and theshold to something
closer to 9. :)

Ivo

^ permalink raw reply

* Re: ath5k - strange regulatory domain change
From: John W. Linville @ 2009-08-07 18:00 UTC (permalink / raw)
  To: Luis R. Rodriguez; +Cc: Frans Pop, Chris Clayton, linux-wireless, linux-kernel
In-Reply-To: <43e72e890908071051w1f306349rfab32de80759006e@mail.gmail.com>

On Fri, Aug 07, 2009 at 10:51:17AM -0700, Luis R. Rodriguez wrote:
> On Fri, Aug 7, 2009 at 10:39 AM, Frans Pop<elendil@planet.nl> wrote:

> > Probably the simplest option would be to just display some identification
> > of the domain group itself and point users to documentation which
> > explains what countries fall under what groups. That would at least avoid
> > the confusion caused by randomly picking a matching country.
> > Variation could be to display the country if the group only contains one
> > country, but that could also be considered an inconsistent user
> > interface.
> 
> Or maybe see if the currently set regulatory domain matches an alpha2
> in the group, if so then just display the same alpha2. Will take a
> look.

That makes sense to me...

-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: [PATCH] mac80211: allow DMA optimisation
From: Johannes Berg @ 2009-08-07 18:01 UTC (permalink / raw)
  To: Ivo van Doorn; +Cc: John Linville, linux-wireless
In-Reply-To: <200908071855.38921.IvDoorn@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1368 bytes --]

On Fri, 2009-08-07 at 18:55 +0200, Ivo van Doorn wrote:

> > If we have a lot of frames to transmit at once, for
> > instance with fragmentation, it can be an optimisation
> > to only tell the DMA engine about them on the last
> > fragment/frame to avoid banging the IO too much. This
> > patch allows implementation such an optimisation by
> > telling the driver when more frames can be expected.
> 
> Wouldn't this be the same as the
> 	if (ieee80211_has_morefrags())
> 		.. kick queue ...

Initially, yes, but I think we should eventually use it for sending out
multiple frames after restarting queues etc. For instance after
scanning, we could send out a bunch of frames at once.

> > Currently, this is used by mac80211 only on fragmented
> > frames, but could also be used in the future on other
> > frames when the queue was full and there are multiple
> > frames pending.
> >
> > Note that drivers need to be careful when using this
> > flag, they need to kick their DMA engines not just
> > when this flag is clear, but also when the queue gets
> > full so that progress can be made.
> 
> What would a good value be for the threshold?
> rt2x00 currently uses 10% of the queue, which means that
> 2 or 3 entries are kept available at all times.

Well, for fragmentation I think the maximum number of fragments is 9.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply

* Re: ath5k - strange regulatory domain change
From: Luis R. Rodriguez @ 2009-08-07 17:51 UTC (permalink / raw)
  To: Frans Pop; +Cc: John W. Linville, Chris Clayton, linux-wireless, linux-kernel
In-Reply-To: <200908071939.49627.elendil@planet.nl>

On Fri, Aug 7, 2009 at 10:39 AM, Frans Pop<elendil@planet.nl> wrote:
> On Friday 07 August 2009, you wrote:
>> The way the EEPROM was programmed for this type of
>> regulatory domain was to give you a group number under which other
>> countries fall under. If you ended up getting a direct alpha2
>> programmed in the EEPROM instead you would still end up matching the
>> alpha2 to a group number. The group number leads you to a regulatory
>> domain that all those countries in that group number adhere to. So it
>> was a way to group up regulatory domain rules between countries. The
>> "CN" you see just so happens to be the alpha2 for the first country in
>> the same group regulatory domain group.
>>
>> What we can do is to elaborate on that on the dmesg and also maybe
>
> That would be very welcome.
>
>> pick the most common country on the group so it will tend to match the
>> country users are on.
>
> I think that would just be moving the problem from one group of users to
> another, possibly only marginally smaller, group of users.
>
> As far as I can see the largest group is ETSI1_WORLD and contains 33
> countries, followed by NULL1_WORLD (is that a real group?) with 22.
> That's probably too many to list them all.
> OTOH, all other groups contain at most 7 countries, which could possibly
> be listed.
>
> Probably the simplest option would be to just display some identification
> of the domain group itself and point users to documentation which
> explains what countries fall under what groups. That would at least avoid
> the confusion caused by randomly picking a matching country.
> Variation could be to display the country if the group only contains one
> country, but that could also be considered an inconsistent user
> interface.

Or maybe see if the currently set regulatory domain matches an alpha2
in the group, if so then just display the same alpha2. Will take a
look.

  Luis

^ permalink raw reply

* Re: ath5k - strange regulatory domain change
From: Frans Pop @ 2009-08-07 17:39 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: John W. Linville, Chris Clayton, linux-wireless, linux-kernel
In-Reply-To: <43e72e890908071013w28644e70h5323e19d19da33a2@mail.gmail.com>

On Friday 07 August 2009, you wrote:
> The way the EEPROM was programmed for this type of
> regulatory domain was to give you a group number under which other
> countries fall under. If you ended up getting a direct alpha2
> programmed in the EEPROM instead you would still end up matching the
> alpha2 to a group number. The group number leads you to a regulatory
> domain that all those countries in that group number adhere to. So it
> was a way to group up regulatory domain rules between countries. The
> "CN" you see just so happens to be the alpha2 for the first country in
> the same group regulatory domain group.
>
> What we can do is to elaborate on that on the dmesg and also maybe

That would be very welcome.

> pick the most common country on the group so it will tend to match the
> country users are on.

I think that would just be moving the problem from one group of users to 
another, possibly only marginally smaller, group of users.

As far as I can see the largest group is ETSI1_WORLD and contains 33 
countries, followed by NULL1_WORLD (is that a real group?) with 22. 
That's probably too many to list them all.
OTOH, all other groups contain at most 7 countries, which could possibly 
be listed.

Probably the simplest option would be to just display some identification 
of the domain group itself and point users to documentation which 
explains what countries fall under what groups. That would at least avoid 
the confusion caused by randomly picking a matching country.
Variation could be to display the country if the group only contains one 
country, but that could also be considered an inconsistent user 
interface.

Cheers,
FJP

^ permalink raw reply

* [PATCH 2/2] p54: implement rfkill
From: Christian Lamparter @ 2009-08-07 17:39 UTC (permalink / raw)
  To: wireless; +Cc: John W. Linville, Larry Finger

This patch implements a basic rfkill support for p54 hardware and
removes a rfkill related WARNING:

fwio.c: In function ‘p54_setup_mac’:
fwio.c:323: warning: ‘radio_enabled’ is deprecated.

by abandoning radio_enable in flavour for IEEE80211_CONF_CHANGE_IDLE. 

Tested-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Christian Lamparter <chunkeey@web.de>
---
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c
index 21f1901..e7b9e9c 100644
--- a/drivers/net/wireless/p54/fwio.c
+++ b/drivers/net/wireless/p54/fwio.c
@@ -320,7 +320,7 @@ int p54_setup_mac(struct p54_common *priv)
 		return -ENOMEM;
 
 	setup = (struct p54_setup_mac *) skb_put(skb, sizeof(*setup));
-	if (priv->hw->conf.radio_enabled) {
+	if (!(priv->hw->conf.flags & IEEE80211_CONF_IDLE)) {
 		switch (priv->mode) {
 		case NL80211_IFTYPE_STATION:
 			mode = P54_FILTER_TYPE_STATION;
@@ -348,8 +348,9 @@ int p54_setup_mac(struct p54_common *priv)
 		     (priv->filter_flags & FIF_OTHER_BSS)) &&
 		    (mode != P54_FILTER_TYPE_PROMISCUOUS))
 			mode |= P54_FILTER_TYPE_TRANSPARENT;
-	} else
+	} else {
 		mode = P54_FILTER_TYPE_HIBERNATE;
+	}
 
 	setup->mac_mode = cpu_to_le16(mode);
 	memcpy(setup->mac_addr, priv->mac_addr, ETH_ALEN);
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index bcab4c6..c3c00a1 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -288,6 +288,11 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed)
 		if (ret)
 			goto out;
 	}
+	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
+		ret = p54_setup_mac(priv);
+		if (ret)
+			goto out;
+	}
 
 out:
 	mutex_unlock(&priv->conf_mutex);
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index 704685f..6fc0b61 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -552,6 +552,12 @@ static void p54_rx_trap(struct p54_common *priv, struct sk_buff *skb)
 		break;
 	case P54_TRAP_TIMER:
 		break;
+	case P54_TRAP_FAA_RADIO_OFF:
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
+		break;
+	case P54_TRAP_FAA_RADIO_ON:
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy, false);
+		break;
 	default:
 		printk(KERN_INFO "%s: received event:%x freq:%d\n",
 		       wiphy_name(priv->hw->wiphy), event, freq);

^ permalink raw reply related

* [PATCH 1/2] p54: Write outside array bounds
From: Christian Lamparter @ 2009-08-07 17:38 UTC (permalink / raw)
  To: wireless; +Cc: John W. Linville, Dan Carpenter

This patch fixes a coding error which allowed the to upper-layer to
corrupt limited portions of the phy data.

Signed-off-by: Christian Lamparter <chunkeey@web.de>
---
Note:

mac80211 guarantees that params is a valid pointer, so
the _other_ check is no longer needed.
---
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index a0d0e72..bcab4c6 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -317,7 +317,7 @@ static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue,
 	int ret;
 
 	mutex_lock(&priv->conf_mutex);
-	if ((params) && !(queue > 4)) {
+	if (queue < dev->queues) {
 		P54_SET_QUEUE(priv->qos_params[queue], params->aifs,
 			params->cw_min, params->cw_max, params->txop);
 		ret = p54_set_edcf(priv);

^ permalink raw reply related

* Re: ath5k - strange regulatory domain change
From: Luis R. Rodriguez @ 2009-08-07 17:13 UTC (permalink / raw)
  To: John W. Linville; +Cc: Chris Clayton, Frans Pop, linux-wireless, linux-kernel
In-Reply-To: <20090807151304.GE7545@tuxdriver.com>

On Fri, Aug 7, 2009 at 8:16 AM, John W. Linville<linville@tuxdriver.com> wrote:
> On Fri, Aug 07, 2009 at 03:57:30PM +0100, Chris Clayton wrote:
>> 2009/8/7 John W. Linville <linville@tuxdriver.com>:
>> > On Fri, Aug 07, 2009 at 01:56:43PM +0100, Chris Clayton wrote:
>
>> >> To sum this up then (as I understand things):
>> >>
>> >> 1. I am the system administrator (root);
>> >> 2. I am using a valid (albeit deprecated from 2.6.31) method to tell
>> >> the wireless infrastructure that I want the regulatory domain set to
>> >> GB;
>> >> 3. GB is a valid code; and
>> >> 4. the wireless infrastructure sets the regulatory domain to CN.
>> >> 5. in 2.6.30, the wireless infrastructure does what I (the root user)
>> >> tell it to do.
>> >>
>> >> That's a regression in my book. Oh well! I do have the iw and crda
>> >> applications installed, so I've taken that route of setting the
>> >> regulatory domain to GB.
>> >
>> > Are you actually getting the wrong regulatory rules enforced?  Or are
>> > you merely bothered that it is reporting "CN" instead of "GB"?
>> >
>>
>> I'm not sure whether it's wrong or not. To these dmesg snippets from
>> my original post look wrong because one of the frequency ranges listed
>> for CN is outside those listed for GB and one of the CN max_eirp
>> entries is not preent in the GB list. Whether that is OK or not I
>> don't know and can't find (lay user) documentation to tell me.
>>
>> cfg80211: Regulatory domain changed to country: GB
>>         (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
>>         (2402000 KHz - 2482000 KHz @ 40000 KHz), (N/A, 2000 mBm)
>>         (5170000 KHz - 5250000 KHz @ 40000 KHz), (N/A, 2000 mBm)
>>         (5250000 KHz - 5330000 KHz @ 40000 KHz), (N/A, 2000 mBm)
>>         (5490000 KHz - 5710000 KHz @ 40000 KHz), (N/A, 2700 mBm)
>>
>> cfg80211: Regulatory domain changed to country: CN
>>         (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
>>         (2402000 KHz - 2482000 KHz @ 40000 KHz), (N/A, 2000 mBm)
>>         (5735000 KHz - 5835000 KHz @ 40000 KHz), (N/A, 3000 mBm)
>
> It looks like a mismatch to me.  Luis, can you sort this out?

There is no regression at all, ath5k *got* regulatory domain as of
2.6.31, before that the EEPROM was never read for regulatory domain
treatment. So what you see happening on 2.6.31 is interpretation of
the EEPROM as the vendor designed it and using the regulatory
infrastructure to help compliance. The "CN" is the first alpha2 that
the atheros card's programmed EEPROM regulatory domain code matches
to, so all there is here is a lack of clarity to the user of what was
done and that can be fixed.

Let me elaborate: Atheros EEPROM can be programmed by 3 types of
regulatory domains, I've documented this on the wiki for the shared
ath.ko module [1]. When you get a "regpair" there is no direct 1-1
country mapping. The way the EEPROM was programmed for this type of
regulatory domain was to give you a group number under which other
countries fall under. If you ended up getting a direct alpha2
programmed in the EEPROM instead you would still end up matching the
alpha2 to a group number. The group number leads you to a regulatory
domain that all those countries in that group number adhere to. So it
was a way to group up regulatory domain rules between countries. The
"CN" you see just so happens to be the alpha2 for the first country in
the same group regulatory domain group.

What we can do is to elaborate on that on the dmesg and also maybe
pick the most common country on the group so it will tend to match the
country users are on.

I am seeing if we can deprecate the group stuff on Atheros EEPROM but
that will take some time.

[1] http://wireless.kernel.org/en/users/Drivers/ath

  Luis

^ permalink raw reply

* Re: [PATCH] mac80211: allow DMA optimisation
From: Ivo van Doorn @ 2009-08-07 16:55 UTC (permalink / raw)
  To: Johannes Berg; +Cc: John Linville, linux-wireless
In-Reply-To: <1249656135.7194.6.camel@johannes.local>

Hi,

> If we have a lot of frames to transmit at once, for
> instance with fragmentation, it can be an optimisation
> to only tell the DMA engine about them on the last
> fragment/frame to avoid banging the IO too much. This
> patch allows implementation such an optimisation by
> telling the driver when more frames can be expected.

Wouldn't this be the same as the
	if (ieee80211_has_morefrags())
		.. kick queue ...

Other then that this flag is very nice, I already had some
similar sort of mechanism build into rt2x00 based on
RTS/CTS and ieee80211_has_morefrags()

> Currently, this is used by mac80211 only on fragmented
> frames, but could also be used in the future on other
> frames when the queue was full and there are multiple
> frames pending.
>
> Note that drivers need to be careful when using this
> flag, they need to kick their DMA engines not just
> when this flag is clear, but also when the queue gets
> full so that progress can be made.

What would a good value be for the threshold?
rt2x00 currently uses 10% of the queue, which means that
2 or 3 entries are kept available at all times.
 
Ivo

^ permalink raw reply

* Re: [RFT] p54: implement rfkill
From: Larry Finger @ 2009-08-07 16:39 UTC (permalink / raw)
  To: John W. Linville, Christian Lamparter; +Cc: wireless
In-Reply-To: <20090807153602.GG7545@tuxdriver.com>

John W. Linville wrote:
> On Sun, Jul 19, 2009 at 11:54:15PM +0200, Christian Lamparter wrote:
>> This patch gets rid of the deprecated radio_enabled
>>
>> fwio.c: In function ‘p54_setup_mac’:
>> fwio.c:323: warning: ‘radio_enabled’ is deprecated (declared at include/net/mac80211.h:607)
> 
> Anyone had a chance to test this?  And report the results to Christian?

Sorry - I missed this one.

I just tested it. With the patch, the warning is removed. As far as
system operation, the following is observed:

1. If b43 is loaded when using p54usb, then the hardware switch will
kill operation. This behavior is the same with or without this patch.

2. If b43 is unloaded, then p54usb no longer follows the hardware
switch, but operation can be killed with the rfkill user-space
utility. Again, this behavior does not depend on the patch.

Based on the code changes in the patch, it looks as if the radio is
turned off when the device is blocked, but I have no way to test that.

Christian - please add a
Tested-by: Larry Finger <Larry.Finger@lwfinger.net> to the patch and
submit. This change should be in 2.6.32.

Larry



^ permalink raw reply

* Re: [ath9k-devel] Kernel panic with ar5418 and compat-wireless 2009-07-29
From: Luis R. Rodriguez @ 2009-08-07 15:59 UTC (permalink / raw)
  To: jords; +Cc: ath9k-devel, linux-wireless
In-Reply-To: <caf5d1ef0908062250k1b207abfk3af487bde38fd0d1@mail.gmail.com>

On Thu, Aug 6, 2009 at 10:50 PM, Jordan Thoms<jords@shadowservices.biz> wrote:
> Hi,
> I have just tried wireless-testing and compiling a whole new kernel, and
> both times i received a oops error.

OK great, good to know it is not a compat specific bug and a real bug.

>  However, I think this could be a
> different issue, because it seemed to be triggered by periods of wireless
> inactivity. I watched a 40 minute TV episode over the wireless with no
> issue, but it then crashed approximately 20 mins after.
> The crash logs:
> Compat-wireless 2009-08-06
>  [ 1428.485778] BUG: unable to handle kernel NULL pointer dereference at
> 00000030
> [ 1428.486742] IP: [<f84a9ba1>] ieee80211_agg_splice_packets+0x37/0x9e
> [mac80211]

Please provide the output of:

gdb net/mac80211/mac80211.ko
l *(ieee80211_agg_splice_packets+0x37)

  Luis

> [ 1428.486742] *pde = 00000000
> [ 1428.486742] Thread overran stack, or stack corrupted
> [ 1428.486742] Oops: 0000 [#1] SMP
> [ 1428.486742] last sysfs file: /sys/devices/system/cpu/cpu1/online
> [ 1428.486742] Modules linked in: vboxnetadp vboxnetflt vboxdrv ath9k
> mac80211 ath cfg80211 rfkill_backport
> [ 1428.486742]
> [ 1428.486742] Pid: 0, comm: swapper Not tainted (2.6.30-gentoo-r4 #4)
> P5L-MX
> [ 1428.486742] EIP: 0060:[<f84a9ba1>] EFLAGS: 00010206 CPU: 0
> [ 1428.486742] EIP is at ieee80211_agg_splice_packets+0x37/0x9e [mac80211]
> [ 1428.486742] EAX: 00000030 EBX: 00000000 ECX: 00000003 EDX: f7076224
> [ 1428.486742] ESI: f54ac000 EDI: 00000002 EBP: c173fed8 ESP: c173fec0
> [ 1428.486742]  DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
> [ 1428.486742] Process swapper (pid: 0, ti=c173e000 task=c16bd300
> task.ti=c173e000)
> [ 1428.486742] Stack:
> [ 1428.486742]  f70761c0 c173fecc c102c788 00000000 f54ac000 f70761c0
> c173fef8 f84aa060
> [ 1428.486742]  f6a34ce0 f54ac020 f54ac12c f6a34cc0 f70761c0 00000001
> c173ff08 f84a6b13
> [ 1428.486742]  f7076280 00000000 c173ff18 c102cc9e 00000020 c17359d4
> c173ff3c c102c886
> [ 1428.486742] Call Trace:
> [ 1428.486742]  [<c102c788>] ? local_bh_disable+0xb/0xd
> [ 1428.486742]  [<f84aa060>] ? ieee80211_stop_tx_ba_cb+0x76/0xb4 [mac80211]
> [ 1428.486742]  [<f84a6b13>] ? ieee80211_tasklet_handler+0x5a/0xc3
> [mac80211]
> [ 1428.486742]  [<c102cc9e>] ? tasklet_action+0x57/0x9e
> [ 1428.486742]  [<c102c886>] ? __do_softirq+0x8e/0x132
> [ 1428.486742]  [<c102c950>] ? do_softirq+0x26/0x2b
> [ 1428.486742]  [<c102cb23>] ? irq_exit+0x29/0x5c
> [ 1428.486742]  [<c1004444>] ? do_IRQ+0x6d/0x83
> [ 1428.486742]  [<c1003129>] ? common_interrupt+0x29/0x30
> [ 1428.486742]  [<c100855d>] ? mwait_idle+0x66/0x79
> [ 1428.486742]  [<c1001d68>] ? cpu_idle+0x44/0x65
> [ 1428.486742]  [<c146adf7>] ? rest_init+0x53/0x55
> [ 1428.486742]  [<c17457fb>] ? start_kernel+0x2ac/0x2b1
> [ 1428.486742]  [<c174506a>] ? __init_begin+0x6a/0x6f
> [ 1428.486742] Code: ec 0c b9 03 00 00 00 89 45 e8 89 d8 83 e0 07 0f b7 3c
> 85 20 a2 4b f8 8b 45 e8 89 fa e8 0b db
> 00 00 8b 84 9e 3c 01 00 00 83 c0 30 <39> 00 74 5b 8b 45 e8 83 c0 64 89 45 ec
> e8 54 dc fd c8 89 45 f0
> [ 1428.486742] EIP: [<f84a9ba1>] ieee80211_agg_splice_packets+0x37/0x9e
> [mac80211] SS:ESP 0068:c173fec0
> [ 1428.486742] CR2: 0000000000000030
> [ 1429.140936] ---[ end trace 28eac1989c1512b0 ]---
> [ 1429.154801] Kernel panic - not syncing: Fatal exception in interrupt
> [ 1429.173894] Pid: 0, comm: swapper Tainted: G      D    2.6.30-gentoo-r4
> #4
> [ 1429.194534] Call Trace:
> [ 1429.201917]  [<c1028a0d>] panic+0x3f/0xdf
> [ 1429.213981]  [<c14881f9>] oops_end+0x8b/0x9a
> [ 1429.226827]  [<c1017745>] no_context+0x10c/0x116
> [ 1429.240715]  [<c10178d2>] __bad_area_nosemaphore+0xe0/0xe8
> [ 1429.257196]  [<c101793e>] bad_area_nosemaphore+0xd/0x10
> [ 1429.272898]  [<c1489187>] do_page_fault+0x102/0x207
> [ 1429.287564]  [<c1489085>] ? do_page_fault+0x0/0x207
> [ 1429.302228]  [<c148795d>] error_code+0x6d/0x74
> [ 1429.315603]  [<f84b007b>] ? ieee80211_open+0x486/0x4e3 [mac80211]
> [ 1429.333898]  [<c1489085>] ? do_page_fault+0x0/0x207
> [ 1429.348572]  [<f84a9ba1>] ? ieee80211_agg_splice_packets+0x37/0x9e
> [mac80211]
> [ 1429.369988]  [<c102c788>] ? local_bh_disable+0xb/0xd
> [ 1429.384921]  [<f84aa060>] ieee80211_stop_tx_ba_cb+0x76/0xb4 [mac80211]
> [ 1429.404525]  [<f84a6b13>] ieee80211_tasklet_handler+0x5a/0xc3 [mac80211]
> [ 1429.424641]  [<c102cc9e>] tasklet_action+0x57/0x9e
> [ 1429.439044]  [<c102c886>] __do_softirq+0x8e/0x132
> [ 1429.453188]  [<c102c950>] do_softirq+0x26/0x2b
> [ 1429.466551]  [<c102cb23>] irq_exit+0x29/0x5c
> [ 1429.479396]  [<c1004444>] do_IRQ+0x6d/0x83
> [ 1429.491721]  [<c1003129>] common_interrupt+0x29/0x30
> [ 1429.506643]  [<c100855d>] ? mwait_idle+0x66/0x79
> [ 1429.520528]  [<c1001d68>] cpu_idle+0x44/0x65
> [ 1429.533372]  [<c146adf7>] rest_init+0x53/0x55
> [ 1429.546476]  [<c17457fb>] start_kernel+0x2ac/0x2b1
> [ 1429.560880]  [<c174506a>] __init_begin+0x6a/0x6f
> Wireless-Testing:
> jords@bender ~ $ [ 3327.864925] BUG: unable to handle kernel NULL pointer
> dereference at 00000030
> [ 3327.865876] IP: [<f8407ba1>] ieee80211_agg_splice_packets+0x37/0x9e
> [mac80211]
> [ 3327.865876] *pde = 00000000
> [ 3327.865876] Thread overran stack, or stack corrupted
> [ 3327.865876] Oops: 0000 [#1] SMP
> [ 3327.865876] last sysfs file:
> /sys/devices/system/cpu/cpu1/cpufreq/scaling_governor
> [ 3327.865876] Modules linked in: ath9k mac80211 ath cfg80211
> [ 3327.865876]
> [ 3327.865876] Pid: 0, comm: swapper Not tainted (2.6.31-rc5-wl #1) P5L-MX
> [ 3327.865876] EIP: 0060:[<f8407ba1>] EFLAGS: 00010206 CPU: 0
> [ 3327.865876] EIP is at ieee80211_agg_splice_packets+0x37/0x9e [mac80211]
> [ 3327.865876] EAX: 00000030 EBX: 00000000 ECX: 00000003 EDX: f708a224
> [ 3327.865876] ESI: f5c44000 EDI: 00000002 EBP: c171ded4 ESP: c171debc
> [ 3327.865876]  DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
> [ 3327.865876] Process swapper (pid: 0, ti=c171c000 task=c1697160
> task.ti=c171c000)
> [ 3327.865876] Stack:
> [ 3327.865876]  f708a1c0 c171dec8 c102e3c6 00000000 f5c44000 f708a1c0
> c171def4 f8408060
> [ 3327.865876] <0> f6b11b60 f5c44020 f5c4412c f6b11b40 f708a1c0 c1713a14
> c171df04 f8404a46
> [ 3327.865876] <0> f708a280 00000000 c171df14 c102eb6e 00000020 00000005
> c171df3c c102e4db
> [ 3327.865876] Call Trace:
> [ 3327.865876]  [<c102e3c6>] ? local_bh_disable+0xb/0xd
> [ 3327.865876]  [<f8408060>] ? ieee80211_stop_tx_ba_cb+0x76/0xb4 [mac80211]
> [ 3327.865876]  [<f8404a46>] ? ieee80211_tasklet_handler+0x5a/0xc3
> [mac80211]
> [ 3327.865876]  [<c102eb6e>] ? tasklet_action+0x57/0x9e
> [ 3327.865876]  [<c102e4db>] ? __do_softirq+0xa5/0x145
> [ 3327.865876]  [<c102e5a1>] ? do_softirq+0x26/0x2b
> [ 3327.865876]  [<c102f11c>] ? irq_exit+0x29/0x5c
> [ 3327.865876]  [<c1004681>] ? do_IRQ+0x72/0x89
> [ 3327.865876]  [<c1003069>] ? common_interrupt+0x29/0x30
> [ 3327.865876]  [<c104007b>] ? __async_schedule+0x37/0x135
> [ 3327.865876]  [<c100883e>] ? mwait_idle+0x66/0x78
> [ 3327.865876]  [<c1001c77>] ? cpu_idle+0x44/0x65
> [ 3327.865876]  [<c1451e57>] ? rest_init+0x53/0x55
> [ 3327.865876]  [<c1723826>] ? start_kernel+0x2b1/0x2b6
> [ 3327.865876]  [<c172306a>] ? __init_begin+0x6a/0x6f
> [ 3327.865876] Code: ec 0c b9 03 00 00 00 89 45 e8 89 d8 83 e0 07 0f b7 3c
> 85 80 7b 41 f8 8b 45 e8 89 fa e8 f7 da
> 00 00 8b 84 9e 3c 01 00 00 83 c0 30 <39> 00 74 5b 8b 45 e8 83 c0 64 89 45 ec
> e8 9c 78 06 c9 89 45 f0
> [ 3327.865876] EIP: [<f8407ba1>] ieee80211_agg_splice_packets+0x37/0x9e
> [mac80211] SS:ESP 0068:c171debc
> [ 3327.865876] CR2: 0000000000000030
> [ 3328.528281] ---[ end trace 289a5951fbc06b5e ]---
> [ 3328.542165] Kernel panic - not syncing: Fatal exception in interrupt
> [ 3328.561251] Pid: 0, comm: swapper Tainted: G      D    2.6.31-rc5-wl #1
> [ 3328.581118] Call Trace:
> [ 3328.588496]  [<c102a3c9>] panic+0x3f/0xdf
> [ 3328.600561]  [<c146fe41>] oops_end+0x8b/0x9a
> [ 3328.613406]  [<c101977b>] no_context+0x10c/0x116
> [ 3328.627290]  [<c1019908>] __bad_area_nosemaphore+0xe0/0xe8
> [ 3328.643775]  [<c1019974>] bad_area_nosemaphore+0xd/0x10
> [ 3328.659478]  [<c1470dd8>] do_page_fault+0x102/0x20e
> [ 3328.674142]  [<c1470cd6>] ? do_page_fault+0x0/0x20e
> [ 3328.688809]  [<c146f59e>] error_code+0x66/0x6c
> [ 3328.702183]  [<f841007b>] ? ieee80211_get_key+0x25/0x160 [mac80211]
> [ 3328.720996]  [<c1470cd6>] ? do_page_fault+0x0/0x20e
> [ 3328.735668]  [<f8407ba1>] ? ieee80211_agg_splice_packets+0x37/0x9e
> [mac80211]
> [ 3328.757089]  [<c102e3c6>] ? local_bh_disable+0xb/0xd
> [ 3328.772023]  [<f8408060>] ieee80211_stop_tx_ba_cb+0x76/0xb4 [mac80211]
> [ 3328.791625]  [<f8404a46>] ieee80211_tasklet_handler+0x5a/0xc3 [mac80211]
> [ 3328.811739]  [<c102eb6e>] tasklet_action+0x57/0x9e
> [ 3328.826137]  [<c102e4db>] __do_softirq+0xa5/0x145
> [ 3328.840286]  [<c102e5a1>] do_softirq+0x26/0x2b
> [ 3328.853649]  [<c102f11c>] irq_exit+0x29/0x5c
> [ 3328.866491]  [<c1004681>] do_IRQ+0x72/0x89
> [ 3328.878814]  [<c1003069>] common_interrupt+0x29/0x30
> [ 3328.893740]  [<c104007b>] ? __async_schedule+0x37/0x135
> [ 3328.909444]  [<c100883e>] ? mwait_idle+0x66/0x78
> [ 3328.923327]  [<c1001c77>] cpu_idle+0x44/0x65
> [ 3328.936171]  [<c1451e57>] rest_init+0x53/0x55
> [ 3328.949275]  [<c1723826>] start_kernel+0x2b1/0x2b6
> [ 3328.963679]  [<c172306a>] __init_begin+0x6a/0x6f
>
> On Fri, Aug 7, 2009 at 9:29 AM, Luis R. Rodriguez <mcgrof@gmail.com> wrote:
>>
>> On Thu, Aug 6, 2009 at 2:06 PM, Jordan Thoms<jords@shadowservices.biz>
>> wrote:
>> > Any progress on this? Did my message get to the list?
>>
>> Please try today's compat-wireless tarball, just updated with the
>> latest patches merged onto wireless-testing. If you still seen an oops
>> it would be appreciated if you can instead just compile an entire
>> kernel using the wireless-testing git tree directly:
>>
>> http://wireless.kernel.org/en/developers/Documentation/git-guide
>>
>> I'm hoping the change is not backport related, and just want to verify.
>>
>>  Luis
>
>

^ permalink raw reply

* [PATCH] cfg80211: fix alignment problem in scan request
From: Johannes Berg @ 2009-08-07 15:54 UTC (permalink / raw)
  To: John Linville; +Cc: Ivan Kuten, Yauhen Kharuzhy, linux-wireless

The memory layout for scan requests was rather wrong,
we put the scan SSIDs before the channels which could
lead to the channel pointers being unaligned in memory.
It turns out that using a pointer to the channel array
isn't necessary anyway since we can embed a zero-length
array into the struct.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 include/net/cfg80211.h     |    4 +++-
 net/mac80211/ieee80211_i.h |    2 +-
 net/mac80211/main.c        |   16 ++++++++--------
 net/mac80211/scan.c        |   10 +++++-----
 net/wireless/nl80211.c     |    3 +--
 net/wireless/scan.c        |    4 ++--
 net/wireless/sme.c         |    3 +--
 7 files changed, 21 insertions(+), 21 deletions(-)

--- wireless-testing.orig/include/net/cfg80211.h	2009-08-07 17:49:05.000000000 +0200
+++ wireless-testing/include/net/cfg80211.h	2009-08-07 17:49:06.000000000 +0200
@@ -559,7 +559,6 @@ struct cfg80211_ssid {
 struct cfg80211_scan_request {
 	struct cfg80211_ssid *ssids;
 	int n_ssids;
-	struct ieee80211_channel **channels;
 	u32 n_channels;
 	const u8 *ie;
 	size_t ie_len;
@@ -568,6 +567,9 @@ struct cfg80211_scan_request {
 	struct wiphy *wiphy;
 	struct net_device *dev;
 	bool aborted;
+
+	/* keep last */
+	struct ieee80211_channel *channels[0];
 };
 
 /**
--- wireless-testing.orig/net/wireless/nl80211.c	2009-08-07 17:49:05.000000000 +0200
+++ wireless-testing/net/wireless/nl80211.c	2009-08-07 17:49:06.000000000 +0200
@@ -3002,10 +3002,9 @@ static int nl80211_trigger_scan(struct s
 		goto out;
 	}
 
-	request->channels = (void *)((char *)request + sizeof(*request));
 	request->n_channels = n_channels;
 	if (n_ssids)
-		request->ssids = (void *)(request->channels + n_channels);
+		request->ssids = (void *)&request->channels[n_channels];
 	request->n_ssids = n_ssids;
 	if (ie_len) {
 		if (request->ssids)
--- wireless-testing.orig/net/wireless/scan.c	2009-08-07 17:49:05.000000000 +0200
+++ wireless-testing/net/wireless/scan.c	2009-08-07 17:49:06.000000000 +0200
@@ -612,8 +612,8 @@ int cfg80211_wext_siwscan(struct net_dev
 
 	creq->wiphy = wiphy;
 	creq->dev = dev;
-	creq->ssids = (void *)(creq + 1);
-	creq->channels = (void *)(creq->ssids + 1);
+	/* SSIDs come after channels */
+	creq->ssids = (void *)&creq->channels[n_channels];
 	creq->n_channels = n_channels;
 	creq->n_ssids = 1;
 
--- wireless-testing.orig/net/wireless/sme.c	2009-08-07 17:49:05.000000000 +0200
+++ wireless-testing/net/wireless/sme.c	2009-08-07 17:49:06.000000000 +0200
@@ -65,7 +65,6 @@ static int cfg80211_conn_scan(struct wir
 	if (!request)
 		return -ENOMEM;
 
-	request->channels = (void *)((char *)request + sizeof(*request));
 	if (wdev->conn->params.channel)
 		request->channels[0] = wdev->conn->params.channel;
 	else {
@@ -82,7 +81,7 @@ static int cfg80211_conn_scan(struct wir
 		}
 	}
 	request->n_channels = n_channels;
-	request->ssids = (void *)(request->channels + n_channels);
+	request->ssids = (void *)&request->channels[n_channels];
 	request->n_ssids = 1;
 
 	memcpy(request->ssids[0].ssid, wdev->conn->params.ssid,
--- wireless-testing.orig/net/mac80211/ieee80211_i.h	2009-08-07 17:49:05.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h	2009-08-07 17:49:06.000000000 +0200
@@ -715,7 +715,7 @@ struct ieee80211_local {
 	struct mutex scan_mtx;
 	unsigned long scanning;
 	struct cfg80211_ssid scan_ssid;
-	struct cfg80211_scan_request int_scan_req;
+	struct cfg80211_scan_request *int_scan_req;
 	struct cfg80211_scan_request *scan_req;
 	struct ieee80211_channel *scan_channel;
 	const u8 *orig_ies;
--- wireless-testing.orig/net/mac80211/main.c	2009-08-07 17:49:05.000000000 +0200
+++ wireless-testing/net/mac80211/main.c	2009-08-07 17:49:06.000000000 +0200
@@ -765,9 +765,9 @@ int ieee80211_register_hw(struct ieee802
 		supp_ht = supp_ht || sband->ht_cap.ht_supported;
 	}
 
-	local->int_scan_req.n_channels = channels;
-	local->int_scan_req.channels = kzalloc(sizeof(void *) * channels, GFP_KERNEL);
-	if (!local->int_scan_req.channels)
+	local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
+				      sizeof(void *) * channels, GFP_KERNEL);
+	if (!local->int_scan_req)
 		return -ENOMEM;
 
 	/* if low-level driver supports AP, we also support VLAN */
@@ -882,13 +882,13 @@ int ieee80211_register_hw(struct ieee802
 
 	/* alloc internal scan request */
 	i = 0;
-	local->int_scan_req.ssids = &local->scan_ssid;
-	local->int_scan_req.n_ssids = 1;
+	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] =
+			local->int_scan_req->channels[i] =
 				&hw->wiphy->bands[band]->channels[j];
 			i++;
 		}
@@ -920,7 +920,7 @@ int ieee80211_register_hw(struct ieee802
  fail_workqueue:
 	wiphy_unregister(local->hw.wiphy);
  fail_wiphy_register:
-	kfree(local->int_scan_req.channels);
+	kfree(local->int_scan_req->channels);
 	return result;
 }
 EXPORT_SYMBOL(ieee80211_register_hw);
@@ -962,7 +962,7 @@ void ieee80211_unregister_hw(struct ieee
 	wiphy_unregister(local->hw.wiphy);
 	ieee80211_wep_free(local);
 	ieee80211_led_exit(local);
-	kfree(local->int_scan_req.channels);
+	kfree(local->int_scan_req);
 }
 EXPORT_SYMBOL(ieee80211_unregister_hw);
 
--- wireless-testing.orig/net/mac80211/scan.c	2009-08-07 17:49:05.000000000 +0200
+++ wireless-testing/net/mac80211/scan.c	2009-08-07 17:49:06.000000000 +0200
@@ -277,7 +277,7 @@ void ieee80211_scan_completed(struct iee
 	if (test_bit(SCAN_HW_SCANNING, &local->scanning))
 		ieee80211_restore_scan_ies(local);
 
-	if (local->scan_req != &local->int_scan_req)
+	if (local->scan_req != local->int_scan_req)
 		cfg80211_scan_done(local->scan_req, aborted);
 	local->scan_req = NULL;
 
@@ -423,7 +423,7 @@ static int __ieee80211_start_scan(struct
 	local->scan_req = req;
 	local->scan_sdata = sdata;
 
-	if (req != &local->int_scan_req &&
+	if (req != local->int_scan_req &&
 	    sdata->vif.type == NL80211_IFTYPE_STATION &&
 	    !list_empty(&ifmgd->work_list)) {
 		/* actually wait for the work it's doing to finish/time out */
@@ -743,10 +743,10 @@ int ieee80211_request_internal_scan(stru
 	if (local->scan_req)
 		goto unlock;
 
-	memcpy(local->int_scan_req.ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
-	local->int_scan_req.ssids[0].ssid_len = ssid_len;
+	memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
+	local->int_scan_req->ssids[0].ssid_len = ssid_len;
 
-	ret = __ieee80211_start_scan(sdata, &sdata->local->int_scan_req);
+	ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req);
  unlock:
 	mutex_unlock(&local->scan_mtx);
 	return ret;



^ permalink raw reply

* Re: [PATCH] wireless: Compare ethernet addresses by unaligned safe way
From: John W. Linville @ 2009-08-07 15:34 UTC (permalink / raw)
  To: Johannes Berg; +Cc: ivan.kuten, linux-wireless, Yauhen Kharuzhy
In-Reply-To: <1248371971.634.0.camel@johannes.local>

On Thu, Jul 23, 2009 at 07:59:31PM +0200, Johannes Berg wrote:
> On Thu, 2009-07-23 at 20:56 +0300, Ivan Kuten wrote:
> > > On Sun, 2009-06-28 at 15:18 +0300, Ivan Kuten wrote:
> > >> Hello,
> > >>
> > >> In net/wireless/scan.c : cfg80211_wext_siwscan there seems also unaligned allocations
> > >> for creq->ssids and creq->channels. Should it be something like that?
> > > 
> > > Seems alright, but there is more than one instance of this, maybe you
> > > can make a function to allocate a scan request properly and have it be
> > > called from all the places it's needed.
> > > 
> > > johannes
> > > 
> > 
> > Hello Johannes,
> > Can you point to that multiple scan allocations? I see only one kzalloc
> > with followed possible alignment violation - it's in cfg80211_wext_siwscan in scan.c
> 
> I'm sure there's one in nl80211.c too

Ivan/Yauhen,

Will you be posted an updated patch?  Time is short before the next merge window...

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: [RFT] p54: implement rfkill
From: John W. Linville @ 2009-08-07 15:36 UTC (permalink / raw)
  To: Christian Lamparter; +Cc: wireless
In-Reply-To: <200907192354.15349.chunkeey@web.de>

On Sun, Jul 19, 2009 at 11:54:15PM +0200, Christian Lamparter wrote:
> This patch gets rid of the deprecated radio_enabled
> 
> fwio.c: In function ‘p54_setup_mac’:
> fwio.c:323: warning: ‘radio_enabled’ is deprecated (declared at include/net/mac80211.h:607)

Anyone had a chance to test this?  And report the results to Christian?

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: ath5k - strange regulatory domain change
From: Frans Pop @ 2009-08-07 15:35 UTC (permalink / raw)
  To: Chris Clayton; +Cc: linux-wireless, linux-kernel
In-Reply-To: <c6b1100b0908070556sb3f4f80sc757d8b100cbcb3c@mail.gmail.com>

Chris Clayton wrote:
> That's a regression in my book. Oh well! I do have the iw and crda
> applications installed, so I've taken that route of setting the
> regulatory domain to GB.

Somewhere in that thread I pointed to Luis explained that using the 
cfg80211 module parameter is deprecated if you're using those 
applications. So I think that is indeed the correct way to solve it.

If you did not have those applications installed, the GB setting from the 
module parameter would still be honored.

Cheers,
FJP

^ permalink raw reply

* Re: ath5k - strange regulatory domain change
From: John W. Linville @ 2009-08-07 15:16 UTC (permalink / raw)
  To: Chris Clayton; +Cc: Frans Pop, linux-wireless, linux-kernel, mcgrof
In-Reply-To: <c6b1100b0908070757t7b973180s17959e0f46347d5d@mail.gmail.com>

On Fri, Aug 07, 2009 at 03:57:30PM +0100, Chris Clayton wrote:
> 2009/8/7 John W. Linville <linville@tuxdriver.com>:
> > On Fri, Aug 07, 2009 at 01:56:43PM +0100, Chris Clayton wrote:

> >> To sum this up then (as I understand things):
> >>
> >> 1. I am the system administrator (root);
> >> 2. I am using a valid (albeit deprecated from 2.6.31) method to tell
> >> the wireless infrastructure that I want the regulatory domain set to
> >> GB;
> >> 3. GB is a valid code; and
> >> 4. the wireless infrastructure sets the regulatory domain to CN.
> >> 5. in 2.6.30, the wireless infrastructure does what I (the root user)
> >> tell it to do.
> >>
> >> That's a regression in my book. Oh well! I do have the iw and crda
> >> applications installed, so I've taken that route of setting the
> >> regulatory domain to GB.
> >
> > Are you actually getting the wrong regulatory rules enforced?  Or are
> > you merely bothered that it is reporting "CN" instead of "GB"?
> >
> 
> I'm not sure whether it's wrong or not. To these dmesg snippets from
> my original post look wrong because one of the frequency ranges listed
> for CN is outside those listed for GB and one of the CN max_eirp
> entries is not preent in the GB list. Whether that is OK or not I
> don't know and can't find (lay user) documentation to tell me.
> 
> cfg80211: Regulatory domain changed to country: GB
>         (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
>         (2402000 KHz - 2482000 KHz @ 40000 KHz), (N/A, 2000 mBm)
>         (5170000 KHz - 5250000 KHz @ 40000 KHz), (N/A, 2000 mBm)
>         (5250000 KHz - 5330000 KHz @ 40000 KHz), (N/A, 2000 mBm)
>         (5490000 KHz - 5710000 KHz @ 40000 KHz), (N/A, 2700 mBm)
> 
> cfg80211: Regulatory domain changed to country: CN
>         (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
>         (2402000 KHz - 2482000 KHz @ 40000 KHz), (N/A, 2000 mBm)
>         (5735000 KHz - 5835000 KHz @ 40000 KHz), (N/A, 3000 mBm)

It looks like a mismatch to me.  Luis, can you sort this out?

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* [PATCH v4] cfg80211: validate channel settings across interfaces
From: Johannes Berg @ 2009-08-07 15:22 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, Luis R. Rodriguez
In-Reply-To: <1249652951.7194.2.camel@johannes.local>

Currently, there's a problem that affects regulatory
enforcement and connection stability, in that it is
possible to switch the channel while connected to a
network or joined to an IBSS.

The problem comes from the fact that we only validate
the channel against the current interface's type, not
against any other interface. Thus, you have any type
of interface up, additionally bring up a monitor mode
interface and switch the channel on the monitor. This
will obviously also switch the channel on the other
interface.

The problem now is that if you do that while sending
beacons for IBSS mode, you can switch to a disabled
channel or a channel that doesn't allow beaconing.
Combined with a managed mode interface connected to
an AP instead of an IBSS interface, you can easily
break the connection that way.

To fix this, this patch validates any channel change
with all available interfaces, and disallows such
changes on secondary interfaces if another interface
is connected to an AP or joined to an IBSS.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
v2: * rebase
v3: * fix error code (-EBUSY instead of -EINVAL)
    * fix locking (need devlist_mtx instead of rdev mtx)
v4: * use SINGLE_DEPTH_NESTING instead of 1

 net/wireless/Makefile      |    3 +
 net/wireless/chan.c        |   88 +++++++++++++++++++++++++++++++++++++++++++++
 net/wireless/core.h        |    6 +++
 net/wireless/ibss.c        |   63 ++++++++++++++++++++------------
 net/wireless/nl80211.c     |   54 ++++++---------------------
 net/wireless/sme.c         |    9 ++++
 net/wireless/wext-compat.c |   55 +++++++++-------------------
 net/wireless/wext-compat.h |    3 -
 net/wireless/wext-sme.c    |   67 ++++++++++++++++++----------------
 9 files changed, 215 insertions(+), 133 deletions(-)

--- wireless-testing.orig/net/wireless/Makefile	2009-08-07 14:50:09.000000000 +0200
+++ wireless-testing/net/wireless/Makefile	2009-08-07 14:50:11.000000000 +0200
@@ -5,7 +5,8 @@ obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib8
 obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
 obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
 
-cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o sme.o
+cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
+cfg80211-y += mlme.o ibss.o sme.o chan.o
 cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
 cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o wext-sme.o
 
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ wireless-testing/net/wireless/chan.c	2009-08-07 17:20:41.000000000 +0200
@@ -0,0 +1,88 @@
+/*
+ * This file contains helper code to handle channel
+ * settings and keeping track of what is possible at
+ * any point in time.
+ *
+ * Copyright 2009	Johannes Berg <johannes@sipsolutions.net>
+ */
+
+#include <net/cfg80211.h>
+#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;
+}
+
+int rdev_set_freq(struct cfg80211_registered_device *rdev,
+		  int freq, enum nl80211_channel_type channel_type)
+{
+	struct ieee80211_channel *chan;
+	struct ieee80211_sta_ht_cap *ht_cap;
+	int result;
+
+	if (rdev_fixed_channel(rdev, NULL))
+		return -EBUSY;
+
+	if (!rdev->ops->set_channel)
+		return -EOPNOTSUPP;
+
+	chan = ieee80211_get_channel(&rdev->wiphy, freq);
+
+	/* Primary channel not allowed */
+	if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
+		return -EINVAL;
+
+	if (channel_type == NL80211_CHAN_HT40MINUS &&
+	    chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
+		return -EINVAL;
+	else if (channel_type == NL80211_CHAN_HT40PLUS &&
+		 chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
+		return -EINVAL;
+
+	ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
+
+	if (channel_type != NL80211_CHAN_NO_HT) {
+		if (!ht_cap->ht_supported)
+			return -EINVAL;
+
+		if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
+		    ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
+			return -EINVAL;
+	}
+
+	result = rdev->ops->set_channel(&rdev->wiphy, chan, channel_type);
+	if (result)
+		return result;
+
+	rdev->channel = chan;
+
+	return 0;
+}
--- wireless-testing.orig/net/wireless/core.h	2009-08-07 14:50:09.000000000 +0200
+++ wireless-testing/net/wireless/core.h	2009-08-07 17:20:31.000000000 +0200
@@ -366,4 +366,10 @@ void cfg80211_sme_disassoc(struct net_de
 void __cfg80211_scan_done(struct work_struct *wk);
 void cfg80211_upload_connect_keys(struct wireless_dev *wdev);
 
+struct ieee80211_channel *
+rdev_fixed_channel(struct cfg80211_registered_device *rdev,
+		   struct wireless_dev *for_wdev);
+int rdev_set_freq(struct cfg80211_registered_device *rdev,
+		  int freq, enum nl80211_channel_type channel_type);
+
 #endif /* __NET_WIRELESS_CORE_H */
--- wireless-testing.orig/net/wireless/nl80211.c	2009-08-07 14:50:09.000000000 +0200
+++ wireless-testing/net/wireless/nl80211.c	2009-08-07 17:20:30.000000000 +0200
@@ -701,15 +701,8 @@ 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;
-		struct ieee80211_channel *chan;
-		struct ieee80211_sta_ht_cap *ht_cap;
 		u32 freq;
 
-		if (!rdev->ops->set_channel) {
-			result = -EOPNOTSUPP;
-			goto bad_res;
-		}
-
 		result = -EINVAL;
 
 		if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
@@ -723,42 +716,12 @@ static int nl80211_set_wiphy(struct sk_b
 		}
 
 		freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
-		chan = ieee80211_get_channel(&rdev->wiphy, freq);
-
-		/* Primary channel not allowed */
-		if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
-			goto bad_res;
-
-		if (channel_type == NL80211_CHAN_HT40MINUS &&
-		    (chan->flags & IEEE80211_CHAN_NO_HT40MINUS))
-			goto bad_res;
-		else if (channel_type == NL80211_CHAN_HT40PLUS &&
-			 (chan->flags & IEEE80211_CHAN_NO_HT40PLUS))
-			goto bad_res;
-
-		/*
-		 * At this point we know if that if HT40 was requested
-		 * we are allowed to use it and the extension channel
-		 * exists.
-		 */
 
-		ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
-
-		/* no HT capabilities or intolerant */
-		if (channel_type != NL80211_CHAN_NO_HT) {
-			if (!ht_cap->ht_supported)
-				goto bad_res;
-			if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
-			    (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT))
-				goto bad_res;
-		}
-
-		result = rdev->ops->set_channel(&rdev->wiphy, chan,
-						channel_type);
+		mutex_lock(&rdev->devlist_mtx);
+		result = rdev_set_freq(rdev, freq, channel_type);
+		mutex_unlock(&rdev->devlist_mtx);
 		if (result)
 			goto bad_res;
-
-		rdev->channel = chan;
 	}
 
 	changed = 0;
@@ -3453,7 +3416,7 @@ static int nl80211_associate(struct sk_b
 	struct cfg80211_registered_device *rdev;
 	struct net_device *dev;
 	struct cfg80211_crypto_settings crypto;
-	struct ieee80211_channel *chan;
+	struct ieee80211_channel *chan, *fixedchan;
 	const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
 	int err, ssid_len, ie_len = 0;
 	bool use_mfp = false;
@@ -3496,6 +3459,15 @@ static int nl80211_associate(struct sk_b
 		goto out;
 	}
 
+	mutex_lock(&rdev->devlist_mtx);
+	fixedchan = rdev_fixed_channel(rdev, NULL);
+	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]);
 
--- wireless-testing.orig/net/wireless/wext-compat.c	2009-08-07 14:50:09.000000000 +0200
+++ wireless-testing/net/wireless/wext-compat.c	2009-08-07 15:38:35.000000000 +0200
@@ -267,39 +267,26 @@ EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange
  * @wiphy: the wiphy
  * @freq: the wext freq encoding
  *
- * Returns a channel, %NULL for auto, or an ERR_PTR for errors!
+ * Returns a frequency, or a negative error code, or 0 for auto.
  */
-struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
-					     struct iw_freq *freq)
+int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq)
 {
-	struct ieee80211_channel *chan;
-	int f;
-
 	/*
-	 * Parse frequency - return NULL for auto and
+	 * Parse frequency - return 0 for auto and
 	 * -EINVAL for impossible things.
 	 */
 	if (freq->e == 0) {
 		if (freq->m < 0)
-			return NULL;
-		f = ieee80211_channel_to_frequency(freq->m);
+			return 0;
+		return ieee80211_channel_to_frequency(freq->m);
 	} else {
 		int i, div = 1000000;
 		for (i = 0; i < freq->e; i++)
 			div /= 10;
 		if (div <= 0)
-			return ERR_PTR(-EINVAL);
-		f = freq->m / div;
+			return -EINVAL;
+		return freq->m / div;
 	}
-
-	/*
-	 * Look up channel struct and return -EINVAL when
-	 * it cannot be found.
-	 */
-	chan = ieee80211_get_channel(wiphy, f);
-	if (!chan)
-		return ERR_PTR(-EINVAL);
-	return chan;
 }
 
 int cfg80211_wext_siwrts(struct net_device *dev,
@@ -761,33 +748,29 @@ EXPORT_SYMBOL_GPL(cfg80211_wext_giwencod
 
 int cfg80211_wext_siwfreq(struct net_device *dev,
 			  struct iw_request_info *info,
-			  struct iw_freq *freq, char *extra)
+			  struct iw_freq *wextfreq, char *extra)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
-	struct ieee80211_channel *chan;
-	int err;
+	int freq, err;
 
 	switch (wdev->iftype) {
 	case NL80211_IFTYPE_STATION:
-		return cfg80211_mgd_wext_siwfreq(dev, info, freq, extra);
+		return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
 	case NL80211_IFTYPE_ADHOC:
-		return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra);
+		return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
 	default:
-		chan = cfg80211_wext_freq(wdev->wiphy, freq);
-		if (!chan)
+		freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
+		if (freq < 0)
+			return freq;
+		if (freq == 0)
 			return -EINVAL;
-		if (IS_ERR(chan))
-			return PTR_ERR(chan);
-		err = rdev->ops->set_channel(wdev->wiphy, chan,
-					     NL80211_CHAN_NO_HT);
-		if (err)
-			return err;
-		rdev->channel = chan;
-		return 0;
+		mutex_lock(&rdev->devlist_mtx);
+		err = rdev_set_freq(rdev, freq, NL80211_CHAN_NO_HT);
+		mutex_unlock(&rdev->devlist_mtx);
+		return err;
 	}
 }
-EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq);
 
 int cfg80211_wext_giwfreq(struct net_device *dev,
 			  struct iw_request_info *info,
--- wireless-testing.orig/net/wireless/wext-compat.h	2009-08-07 14:50:09.000000000 +0200
+++ wireless-testing/net/wireless/wext-compat.h	2009-08-07 14:50:11.000000000 +0200
@@ -42,8 +42,7 @@ int cfg80211_mgd_wext_giwessid(struct ne
 			       struct iw_request_info *info,
 			       struct iw_point *data, char *ssid);
 
-struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
-					     struct iw_freq *freq);
+int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq);
 
 
 extern const struct iw_handler_def cfg80211_wext_handler;
--- wireless-testing.orig/net/wireless/ibss.c	2009-08-07 14:50:09.000000000 +0200
+++ wireless-testing/net/wireless/ibss.c	2009-08-07 15:45:29.000000000 +0200
@@ -78,10 +78,15 @@ 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;
 
@@ -112,9 +117,11 @@ int cfg80211_join_ibss(struct cfg80211_r
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	int err;
 
+	mutex_lock(&rdev->devlist_mtx);
 	wdev_lock(wdev);
 	err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
 	wdev_unlock(wdev);
+	mutex_unlock(&rdev->devlist_mtx);
 
 	return err;
 }
@@ -264,27 +271,32 @@ int cfg80211_ibss_wext_join(struct cfg80
 
 int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
 			       struct iw_request_info *info,
-			       struct iw_freq *freq, char *extra)
+			       struct iw_freq *wextfreq, char *extra)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
-	struct ieee80211_channel *chan;
-	int err;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+	struct ieee80211_channel *chan = NULL;
+	int err, freq;
 
 	/* call only for ibss! */
 	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
 		return -EINVAL;
 
-	if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss)
+	if (!rdev->ops->join_ibss)
 		return -EOPNOTSUPP;
 
-	chan = cfg80211_wext_freq(wdev->wiphy, freq);
-	if (chan && IS_ERR(chan))
-		return PTR_ERR(chan);
-
-	if (chan &&
-	    (chan->flags & IEEE80211_CHAN_NO_IBSS ||
-	     chan->flags & IEEE80211_CHAN_DISABLED))
-		return -EINVAL;
+	freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
+	if (freq < 0)
+		return freq;
+
+	if (freq) {
+		chan = ieee80211_get_channel(wdev->wiphy, freq);
+		if (!chan)
+			return -EINVAL;
+		if (chan->flags & IEEE80211_CHAN_NO_IBSS ||
+		    chan->flags & IEEE80211_CHAN_DISABLED)
+			return -EINVAL;
+	}
 
 	if (wdev->wext.ibss.channel == chan)
 		return 0;
@@ -292,8 +304,7 @@ int cfg80211_ibss_wext_siwfreq(struct ne
 	wdev_lock(wdev);
 	err = 0;
 	if (wdev->ssid_len)
-		err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
-					    dev, true);
+		err = __cfg80211_leave_ibss(rdev, dev, true);
 	wdev_unlock(wdev);
 
 	if (err)
@@ -307,9 +318,11 @@ int cfg80211_ibss_wext_siwfreq(struct ne
 		wdev->wext.ibss.channel_fixed = false;
 	}
 
+	mutex_lock(&rdev->devlist_mtx);
 	wdev_lock(wdev);
-	err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
+	err = cfg80211_ibss_wext_join(rdev, wdev);
 	wdev_unlock(wdev);
+	mutex_unlock(&rdev->devlist_mtx);
 
 	return err;
 }
@@ -347,6 +360,7 @@ int cfg80211_ibss_wext_siwessid(struct n
 				struct iw_point *data, char *ssid)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 	size_t len = data->length;
 	int err;
 
@@ -354,14 +368,13 @@ int cfg80211_ibss_wext_siwessid(struct n
 	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
 		return -EINVAL;
 
-	if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss)
+	if (!rdev->ops->join_ibss)
 		return -EOPNOTSUPP;
 
 	wdev_lock(wdev);
 	err = 0;
 	if (wdev->ssid_len)
-		err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
-					    dev, true);
+		err = __cfg80211_leave_ibss(rdev, dev, true);
 	wdev_unlock(wdev);
 
 	if (err)
@@ -375,9 +388,11 @@ int cfg80211_ibss_wext_siwessid(struct n
 	memcpy(wdev->wext.ibss.ssid, ssid, len);
 	wdev->wext.ibss.ssid_len = len;
 
+	mutex_lock(&rdev->devlist_mtx);
 	wdev_lock(wdev);
-	err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
+	err = cfg80211_ibss_wext_join(rdev, wdev);
 	wdev_unlock(wdev);
+	mutex_unlock(&rdev->devlist_mtx);
 
 	return err;
 }
@@ -414,6 +429,7 @@ int cfg80211_ibss_wext_siwap(struct net_
 			     struct sockaddr *ap_addr, char *extra)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 	u8 *bssid = ap_addr->sa_data;
 	int err;
 
@@ -421,7 +437,7 @@ int cfg80211_ibss_wext_siwap(struct net_
 	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
 		return -EINVAL;
 
-	if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss)
+	if (!rdev->ops->join_ibss)
 		return -EOPNOTSUPP;
 
 	if (ap_addr->sa_family != ARPHRD_ETHER)
@@ -443,8 +459,7 @@ int cfg80211_ibss_wext_siwap(struct net_
 	wdev_lock(wdev);
 	err = 0;
 	if (wdev->ssid_len)
-		err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy),
-					    dev, true);
+		err = __cfg80211_leave_ibss(rdev, dev, true);
 	wdev_unlock(wdev);
 
 	if (err)
@@ -456,9 +471,11 @@ int cfg80211_ibss_wext_siwap(struct net_
 	} else
 		wdev->wext.ibss.bssid = NULL;
 
+	mutex_lock(&rdev->devlist_mtx);
 	wdev_lock(wdev);
-	err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev);
+	err = cfg80211_ibss_wext_join(rdev, wdev);
 	wdev_unlock(wdev);
+	mutex_unlock(&rdev->devlist_mtx);
 
 	return err;
 }
--- wireless-testing.orig/net/wireless/wext-sme.c	2009-08-07 14:50:09.000000000 +0200
+++ wireless-testing/net/wireless/wext-sme.c	2009-08-07 17:20:31.000000000 +0200
@@ -52,25 +52,31 @@ int cfg80211_mgd_wext_connect(struct cfg
 
 int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
 			      struct iw_request_info *info,
-			      struct iw_freq *freq, char *extra)
+			      struct iw_freq *wextfreq, char *extra)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
-	struct ieee80211_channel *chan;
-	int err;
+	struct ieee80211_channel *chan = NULL;
+	int err, freq;
 
 	/* call only for station! */
 	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
 		return -EINVAL;
 
-	chan = cfg80211_wext_freq(wdev->wiphy, freq);
-	if (chan && IS_ERR(chan))
-		return PTR_ERR(chan);
-
-	if (chan && (chan->flags & IEEE80211_CHAN_DISABLED))
-		return -EINVAL;
+	freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
+	if (freq < 0)
+		return freq;
+
+	if (freq) {
+		chan = ieee80211_get_channel(wdev->wiphy, freq);
+		if (!chan)
+			return -EINVAL;
+		if (chan->flags & IEEE80211_CHAN_DISABLED)
+			return -EINVAL;
+	}
 
 	cfg80211_lock_rdev(rdev);
+	mutex_lock(&rdev->devlist_mtx);
 	wdev_lock(wdev);
 
 	if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -84,9 +90,8 @@ int cfg80211_mgd_wext_siwfreq(struct net
 		/* if SSID set, we'll try right again, avoid event */
 		if (wdev->wext.connect.ssid_len)
 			event = false;
-		err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
-					    dev, WLAN_REASON_DEAUTH_LEAVING,
-					    event);
+		err = __cfg80211_disconnect(rdev, dev,
+					    WLAN_REASON_DEAUTH_LEAVING, event);
 		if (err)
 			goto out;
 	}
@@ -95,17 +100,15 @@ int cfg80211_mgd_wext_siwfreq(struct net
 	wdev->wext.connect.channel = chan;
 
 	/* SSID is not set, we just want to switch channel */
-	if (wdev->wext.connect.ssid_len && chan) {
-		err = -EOPNOTSUPP;
-		if (rdev->ops->set_channel)
-			err = rdev->ops->set_channel(wdev->wiphy, chan,
-						     NL80211_CHAN_NO_HT);
+	if (chan && !wdev->wext.connect.ssid_len) {
+		err = rdev_set_freq(rdev, freq, NL80211_CHAN_NO_HT);
 		goto out;
 	}
 
-	err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
+	err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
 	wdev_unlock(wdev);
+	mutex_unlock(&rdev->devlist_mtx);
 	cfg80211_unlock_rdev(rdev);
 	return err;
 }
@@ -143,6 +146,7 @@ int cfg80211_mgd_wext_siwessid(struct ne
 			       struct iw_point *data, char *ssid)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 	size_t len = data->length;
 	int err;
 
@@ -157,7 +161,8 @@ int cfg80211_mgd_wext_siwessid(struct ne
 	if (len > 0 && ssid[len - 1] == '\0')
 		len--;
 
-	cfg80211_lock_rdev(wiphy_to_dev(wdev->wiphy));
+	cfg80211_lock_rdev(rdev);
+	mutex_lock(&rdev->devlist_mtx);
 	wdev_lock(wdev);
 
 	err = 0;
@@ -173,9 +178,8 @@ int cfg80211_mgd_wext_siwessid(struct ne
 		/* if SSID set now, we'll try to connect, avoid event */
 		if (len)
 			event = false;
-		err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
-					    dev, WLAN_REASON_DEAUTH_LEAVING,
-					    event);
+		err = __cfg80211_disconnect(rdev, dev,
+					    WLAN_REASON_DEAUTH_LEAVING, event);
 		if (err)
 			goto out;
 	}
@@ -186,10 +190,11 @@ int cfg80211_mgd_wext_siwessid(struct ne
 
 	wdev->wext.connect.crypto.control_port = false;
 
-	err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
+	err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
 	wdev_unlock(wdev);
-	cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy));
+	mutex_unlock(&rdev->devlist_mtx);
+	cfg80211_unlock_rdev(rdev);
 	return err;
 }
 
@@ -230,6 +235,7 @@ int cfg80211_mgd_wext_siwap(struct net_d
 			    struct sockaddr *ap_addr, char *extra)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
 	u8 *bssid = ap_addr->sa_data;
 	int err;
 
@@ -244,7 +250,8 @@ int cfg80211_mgd_wext_siwap(struct net_d
 	if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
 		bssid = NULL;
 
-	cfg80211_lock_rdev(wiphy_to_dev(wdev->wiphy));
+	cfg80211_lock_rdev(rdev);
+	mutex_lock(&rdev->devlist_mtx);
 	wdev_lock(wdev);
 
 	if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -258,9 +265,8 @@ int cfg80211_mgd_wext_siwap(struct net_d
 		    compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0)
 			goto out;
 
-		err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
-					    dev, WLAN_REASON_DEAUTH_LEAVING,
-					    false);
+		err = __cfg80211_disconnect(rdev, dev,
+					    WLAN_REASON_DEAUTH_LEAVING, false);
 		if (err)
 			goto out;
 	}
@@ -271,10 +277,11 @@ int cfg80211_mgd_wext_siwap(struct net_d
 	} else
 		wdev->wext.connect.bssid = NULL;
 
-	err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
+	err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
 	wdev_unlock(wdev);
-	cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy));
+	mutex_unlock(&rdev->devlist_mtx);
+	cfg80211_unlock_rdev(rdev);
 	return err;
 }
 
--- wireless-testing.orig/net/wireless/sme.c	2009-08-07 14:50:09.000000000 +0200
+++ wireless-testing/net/wireless/sme.c	2009-08-07 17:20:31.000000000 +0200
@@ -256,9 +256,11 @@ void cfg80211_sme_scan_done(struct net_d
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 
+	mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
 	wdev_lock(wdev);
 	__cfg80211_sme_scan_done(dev);
 	wdev_unlock(wdev);
+	mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
 }
 
 void cfg80211_sme_rx_auth(struct net_device *dev,
@@ -644,6 +646,7 @@ int __cfg80211_connect(struct cfg80211_r
 		       struct cfg80211_cached_keys *connkeys)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct ieee80211_channel *chan;
 	int err;
 
 	ASSERT_WDEV_LOCK(wdev);
@@ -651,6 +654,10 @@ 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;
@@ -771,9 +778,11 @@ int cfg80211_connect(struct cfg80211_reg
 {
 	int err;
 
+	mutex_lock(&rdev->devlist_mtx);
 	wdev_lock(dev->ieee80211_ptr);
 	err = __cfg80211_connect(rdev, dev, connect, connkeys);
 	wdev_unlock(dev->ieee80211_ptr);
+	mutex_unlock(&rdev->devlist_mtx);
 
 	return err;
 }



^ permalink raw reply

* [PATCH/RFT] mac80211: try uploading key if a slot was freed
From: Johannes Berg @ 2009-08-07 15:03 UTC (permalink / raw)
  To: linux-wireless

When we remove a key from hwaccel, that may mean
that there's a new free item in the hwaccel, and
we could fill it with another station's key. By
keeping track of which keys the driver said it
could not support (-EOPNOTSUPP) and which it had
no space for (-ENOSPC) we can try uploading a
key that was previously rejected due to no space
after another key is removed.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
RFT because I really have no idea how to test this
properly. Maybe with a hacked driver that claims
to support only a single key in hwaccel?

 net/mac80211/key.c |   51 ++++++++++++++++++++++++++++++++++-----------------
 net/mac80211/key.h |    3 +++
 2 files changed, 37 insertions(+), 17 deletions(-)

--- wireless-testing.orig/net/mac80211/key.c	2009-08-07 16:48:46.000000000 +0200
+++ wireless-testing/net/mac80211/key.c	2009-08-07 16:59:01.000000000 +0200
@@ -141,20 +141,21 @@ static void ieee80211_key_enable_hw_acce
 
 	ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf);
 
-	if (!ret) {
-		spin_lock_bh(&todo_lock);
+	spin_lock_bh(&todo_lock);
+	if (!ret)
 		key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
-		spin_unlock_bh(&todo_lock);
-	}
+	else if (ret == -EOPNOTSUPP)
+		key->flags |= KEY_FLAG_HWACCEL_NOT_SUPPORTED;
+	spin_unlock_bh(&todo_lock);
 
-	if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
-		printk(KERN_ERR "mac80211-%s: failed to set key "
-		       "(%d, %pM) to hardware (%d)\n",
-		       wiphy_name(key->local->hw.wiphy),
-		       key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
+	WARN(ret && ret != -ENOSPC && ret != -EOPNOTSUPP,
+	     "mac80211-%s: failed to set key (%d, %pM) to hardware (%d)\n",
+	     wiphy_name(key->local->hw.wiphy), key->conf.keyidx,
+	     sta ? sta->addr : bcast_addr, ret);
 }
 
-static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
+static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key,
+					   bool upload_another)
 {
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_sta *sta;
@@ -184,14 +185,30 @@ static void ieee80211_key_disable_hw_acc
 	ret = drv_set_key(key->local, DISABLE_KEY, &sdata->vif,
 			  sta, &key->conf);
 
-	if (ret)
-		printk(KERN_ERR "mac80211-%s: failed to remove key "
-		       "(%d, %pM) from hardware (%d)\n",
-		       wiphy_name(key->local->hw.wiphy),
-		       key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
+	WARN(ret,
+	     "mac80211-%s: failed to remove key (%d, %pM) from hardware (%d)\n",
+	     wiphy_name(key->local->hw.wiphy), key->conf.keyidx,
+	     sta ? sta->addr : bcast_addr, ret);
 
 	spin_lock_bh(&todo_lock);
 	key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
+
+	list_for_each_entry(key, &sdata->key_list, list) {
+		if (key->flags & KEY_FLAG_HWACCEL_NOT_SUPPORTED)
+			continue;
+		if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
+			continue;
+		if (key->flags & KEY_FLAG_TODO_DELETE)
+			continue;
+		if (key->flags & KEY_FLAG_TODO_HWACCEL_ADD)
+			continue;
+		if (key->flags & KEY_FLAG_TODO_HWACCEL_REMOVE)
+			continue;
+		spin_unlock_bh(&todo_lock);
+		ieee80211_key_enable_hw_accel(key);
+		spin_lock_bh(&todo_lock);
+	}
+
 	spin_unlock_bh(&todo_lock);
 }
 
@@ -527,7 +544,7 @@ static void __ieee80211_key_destroy(stru
 	if (!key)
 		return;
 
-	ieee80211_key_disable_hw_accel(key);
+	ieee80211_key_disable_hw_accel(key, true);
 
 	if (key->conf.alg == ALG_CCMP)
 		ieee80211_aes_key_free(key->u.ccmp.tfm);
@@ -583,7 +600,7 @@ static void __ieee80211_key_todo(void)
 			work_done = true;
 		}
 		if (todoflags & KEY_FLAG_TODO_HWACCEL_REMOVE) {
-			ieee80211_key_disable_hw_accel(key);
+			ieee80211_key_disable_hw_accel(key, false);
 			work_done = true;
 		}
 		if (todoflags & KEY_FLAG_TODO_DELETE) {
--- wireless-testing.orig/net/mac80211/key.h	2009-08-07 16:49:17.000000000 +0200
+++ wireless-testing/net/mac80211/key.h	2009-08-07 16:58:47.000000000 +0200
@@ -48,6 +48,8 @@ struct sta_info;
  * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs.
  * @KEY_FLAG_TODO_DEFMGMTKEY: Key is default management key and debugfs needs
  *	to be updated.
+ * @KEY_FLAG_HWACCEL_NOT_SUPPORTED: hardware acceleration not supported for
+ *	this key type (tried and driver returned -EOPNOTSUPP)
  */
 enum ieee80211_internal_key_flags {
 	KEY_FLAG_UPLOADED_TO_HARDWARE	= BIT(0),
@@ -57,6 +59,7 @@ enum ieee80211_internal_key_flags {
 	KEY_FLAG_TODO_DEFKEY		= BIT(4),
 	KEY_FLAG_TODO_ADD_DEBUGFS	= BIT(5),
 	KEY_FLAG_TODO_DEFMGMTKEY	= BIT(6),
+	KEY_FLAG_HWACCEL_NOT_SUPPORTED	= BIT(7),
 };
 
 struct tkip_ctx {



^ permalink raw reply

* Re: [ath5k-devel] [PATCH 4/4] ath5k: Use SWI to trigger calibration
From: John W. Linville @ 2009-08-07 14:55 UTC (permalink / raw)
  To: Nick Kossifidis; +Cc: Johannes Berg, Jiri Slaby, linux-wireless, ath5k-devel
In-Reply-To: <40f31dec0908031054m3b8231fdrf36f363702218116@mail.gmail.com>

On Mon, Aug 03, 2009 at 08:54:47PM +0300, Nick Kossifidis wrote:
> 2009/8/1 Johannes Berg <johannes@sipsolutions.net>:
> > On Sat, 2009-08-01 at 10:24 +0200, Jiri Slaby wrote:
> >> On 08/01/2009 10:21 AM, Johannes Berg wrote:
> >> > Actually, jiffies are unsigned long
> >>
> >> Yeah, this is what I meant. I agree I messed it up when I didn't write
> >> the unsigned explicitly. It might have been confusing, thanks for
> >> pointing out.
> >
> > And, in addition to what you said, the code shouldn't divide jiffies, it
> > should multiply the timeout, add it to the start time, and then use
> > time_is_after_jiffies() or so.
> >
> > johannes
> 
> ACK will resend asap ;-)

Last I saw in this thread...

Can we have a clean repost of the whole series (including proper
Signed-off-by and any Acked-by, Tested-by, etc)?  Also, in the future
I think it would be good for you to take some of the comments from
Luis to heart -- explain the 'why' not the 'what' in the changelogs,
do one thing per patch, etc.

I'm going to drop the original 1-4 now and wait for a clean repost.

Thanks,

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: ath5k - strange regulatory domain change
From: Chris Clayton @ 2009-08-07 14:57 UTC (permalink / raw)
  To: John W. Linville; +Cc: Frans Pop, linux-wireless, linux-kernel
In-Reply-To: <20090807134803.GA7545@tuxdriver.com>

Hi John,

2009/8/7 John W. Linville <linville@tuxdriver.com>:
> On Fri, Aug 07, 2009 at 01:56:43PM +0100, Chris Clayton wrote:
>> Thanks Frans,
>>
>> 2009/8/7 Frans Pop <elendil@planet.nl>:
>> > Chris Clayton wrote:
>> >> Because of some problems with my Belkin Wireless G card  (model
>> >> F5D7010) and the rt61pci driver, I've started to use a "no-name" card
>> >> that is supported by the ath5k driver.
>> >>
>> >> A problem is that I have come across is that for some reason the CN
>> >> regulatory domain is being set automatically. This doesn't happen with
>> >> the Belkin (rt61) card. I have the following line in
>> >> /etc/modprobe.d/modprobe.conf to set the regulatory domain to GB:
>> >>
>> >> options cfg80211 ieee80211_regdom=GB
>> >
>> > This issue has already been discussed extensively (after I reported it).
>> > Please see the following thread: http://lkml.org/lkml/2009/7/8/421. It
>> > contains a lot of information from the wireless maintainers.
>> >
>>
>> To sum this up then (as I understand things):
>>
>> 1. I am the system administrator (root);
>> 2. I am using a valid (albeit deprecated from 2.6.31) method to tell
>> the wireless infrastructure that I want the regulatory domain set to
>> GB;
>> 3. GB is a valid code; and
>> 4. the wireless infrastructure sets the regulatory domain to CN.
>> 5. in 2.6.30, the wireless infrastructure does what I (the root user)
>> tell it to do.
>>
>> That's a regression in my book. Oh well! I do have the iw and crda
>> applications installed, so I've taken that route of setting the
>> regulatory domain to GB.
>
> Are you actually getting the wrong regulatory rules enforced?  Or are
> you merely bothered that it is reporting "CN" instead of "GB"?
>

I'm not sure whether it's wrong or not. To these dmesg snippets from
my original post look wrong because one of the frequency ranges listed
for CN is outside those listed for GB and one of the CN max_eirp
entries is not preent in the GB list. Whether that is OK or not I
don't know and can't find (lay user) documentation to tell me.

cfg80211: Regulatory domain changed to country: GB
        (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
        (2402000 KHz - 2482000 KHz @ 40000 KHz), (N/A, 2000 mBm)
        (5170000 KHz - 5250000 KHz @ 40000 KHz), (N/A, 2000 mBm)
        (5250000 KHz - 5330000 KHz @ 40000 KHz), (N/A, 2000 mBm)
        (5490000 KHz - 5710000 KHz @ 40000 KHz), (N/A, 2700 mBm)

cfg80211: Regulatory domain changed to country: CN
        (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
        (2402000 KHz - 2482000 KHz @ 40000 KHz), (N/A, 2000 mBm)
        (5735000 KHz - 5835000 KHz @ 40000 KHz), (N/A, 3000 mBm)


Thanks

Chris

> John
> --
> John W. Linville                Someday the world will need a hero, and you
> linville@tuxdriver.com                  might be all we have.  Be ready.
>



-- 
No, Sir; there is nothing which has yet been contrived by man, by which
so much happiness is produced as by a good tavern or inn - Doctor Samuel
Johnson

^ permalink raw reply

* Re: [PATCH] b43: Fix hardware key index handling
From: John W. Linville @ 2009-08-07 14:37 UTC (permalink / raw)
  To: Michael Buesch; +Cc: wireless, bcm43xx-dev, gregor kowski
In-Reply-To: <200908061036.50631.mb@bu3sch.de>

On Thu, Aug 06, 2009 at 10:36:50AM +0200, Michael Buesch wrote:
> This fixes the hardware encryption keys index and array size handling.
> 
> Thanks to Gregor Kowski for reporting this issue.
> 
> Signed-off-by: Michael Buesch <mb@bu3sch.de>
> 
> ---
> 
> This should probably go as a bugfix.
> (Does this actually fix the PHY transmission errors? I don't see them anymore...
> Note that you need to enable debugging to see them.)

It's getting a bit late in the cycle, especially for a patch so large
and (at least to me) non-obvious.  What is the actual bug being fixed?
What is the effect of leaving it for 2.6.32?

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: [PATCH 1/2] ar9170: cleanup of bss_info_changed and beacon config
From: John W. Linville @ 2009-08-07 14:42 UTC (permalink / raw)
  To: Joerg Albert; +Cc: Christian Lamparter, linux-wireless@vger.kernel.org
In-Reply-To: <4A79D7E5.1080604@gmx.de>

On Wed, Aug 05, 2009 at 09:05:09PM +0200, Joerg Albert wrote:
> On 08/05/2009 04:04 AM, Christian Lamparter wrote:
> 
> > no signed/cc here?
> 
> oops, forgot it. Seems like both patches miss some context lines at the end, too.

So for the record, I'm dropping both patches and waiting for a
resend with whatever corrections you need to make base on Christian's
feedback.

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* [PATCH] mac80211: allow DMA optimisation
From: Johannes Berg @ 2009-08-07 14:42 UTC (permalink / raw)
  To: John Linville; +Cc: Ivo van Doorn, linux-wireless

If we have a lot of frames to transmit at once, for
instance with fragmentation, it can be an optimisation
to only tell the DMA engine about them on the last
fragment/frame to avoid banging the IO too much. This
patch allows implementation such an optimisation by
telling the driver when more frames can be expected.

Currently, this is used by mac80211 only on fragmented
frames, but could also be used in the future on other
frames when the queue was full and there are multiple
frames pending.

Note that drivers need to be careful when using this
flag, they need to kick their DMA engines not just
when this flag is clear, but also when the queue gets
full so that progress can be made.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 include/net/mac80211.h |    5 +++++
 net/mac80211/tx.c      |    3 +++
 2 files changed, 8 insertions(+)

--- wireless-testing.orig/include/net/mac80211.h	2009-08-07 16:36:27.000000000 +0200
+++ wireless-testing/include/net/mac80211.h	2009-08-07 16:38:37.000000000 +0200
@@ -268,6 +268,10 @@ struct ieee80211_bss_conf {
  * @IEEE80211_TX_CTL_PSPOLL_RESPONSE: (internal?)
  *	This frame is a response to a PS-poll frame and should be sent
  *	although the station is in powersave mode.
+ * @IEEE80211_TX_CTL_MORE_FRAMES: More frames will be passed to the
+ *	transmit function after the current frame, this can be used
+ *	by drivers to kick the DMA queue only if unset or when the
+ *	queue gets full.
  */
 enum mac80211_tx_control_flags {
 	IEEE80211_TX_CTL_REQ_TX_STATUS		= BIT(0),
@@ -288,6 +292,7 @@ enum mac80211_tx_control_flags {
 	IEEE80211_TX_INTFL_RETRIED		= BIT(15),
 	IEEE80211_TX_INTFL_DONT_ENCRYPT		= BIT(16),
 	IEEE80211_TX_CTL_PSPOLL_RESPONSE	= BIT(17),
+	IEEE80211_TX_CTL_MORE_FRAMES		= BIT(18),
 };
 
 /**
--- wireless-testing.orig/net/mac80211/tx.c	2009-08-07 16:38:44.000000000 +0200
+++ wireless-testing/net/mac80211/tx.c	2009-08-07 16:38:51.000000000 +0200
@@ -1154,6 +1154,9 @@ static int __ieee80211_tx(struct ieee802
 		next = skb->next;
 		len = skb->len;
 
+		if (next)
+			info->flags |= IEEE80211_TX_CTL_MORE_FRAMES;
+
 		sdata = vif_to_sdata(info->control.vif);
 
 		switch (sdata->vif.type) {



^ permalink raw reply

* [PATCH] mac80211: document TX powersave filter requirements
From: Johannes Berg @ 2009-08-07 14:28 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

This documents what's required to implement that TX powersave
filter properly wrt. handling hardware queues.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 include/net/mac80211.h |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

--- wireless-testing.orig/include/net/mac80211.h	2009-08-07 16:24:58.000000000 +0200
+++ wireless-testing/include/net/mac80211.h	2009-08-07 16:26:46.000000000 +0200
@@ -239,7 +239,14 @@ struct ieee80211_bss_conf {
  * @IEEE80211_TX_CTL_AMPDU: this frame should be sent as part of an A-MPDU
  * @IEEE80211_TX_CTL_INJECTED: Frame was injected, internal to mac80211.
  * @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted
- *	because the destination STA was in powersave mode.
+ *	because the destination STA was in powersave mode. Note that to
+ *	avoid race conditions, the filter must be set by the hardware or
+ *	firmware upon receiving a frame that indicates that the station
+ *	went to sleep (must be done on device to filter frames already on
+ *	the queue) and may only be unset after mac80211 gives the OK for
+ *	that by setting the IEEE80211_TX_CTL_CLEAR_PS_FILT (see above),
+ *	since only then is it guaranteed that no more frames are in the
+ *	hardware queue.
  * @IEEE80211_TX_STAT_ACK: Frame was acknowledged
  * @IEEE80211_TX_STAT_AMPDU: The frame was aggregated, so status
  * 	is for the whole aggregation.



^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox