* Re: wireless (was Re: 2.6.18 -mm merge plans)
From: Arjan van de Ven @ 2006-06-05 12:48 UTC (permalink / raw)
To: Jeff Garzik
Cc: Christoph Hellwig, Andrew Morton, linux-kernel, netdev, linville
In-Reply-To: <20060605123304.GA6066@havoc.gtf.org>
>
> It's a good thing I pay attention to this issue, too, Mr. Just Go Ahead
> And Merge It.
dude, name calling is way out of line here.
Why is it a good thing you are blocking this driver? Do you have ANY
indication AT ALL that there is anything fishy about it?
(and don't say "they didn't follow cleanroom procedure", because you
know that cleanroom is not the only way to do reverse engineering
properly).
Paying attention to proper reverse engineering is good. Being
overzealous is not.
^ permalink raw reply
* Re: wireless (was Re: 2.6.18 -mm merge plans)
From: Jeff Garzik @ 2006-06-05 12:52 UTC (permalink / raw)
To: Arjan van de Ven
Cc: Christoph Hellwig, Andrew Morton, linux-kernel, netdev, linville
In-Reply-To: <1149511707.3111.57.camel@laptopd505.fenrus.org>
On Mon, Jun 05, 2006 at 02:48:27PM +0200, Arjan van de Ven wrote:
> Why is it a good thing you are blocking this driver? Do you have ANY
> indication AT ALL that there is anything fishy about it?
Yes.
> Paying attention to proper reverse engineering is good. Being
> overzealous is not.
Being overzealous about merging drivers without first checking the legal
ramifications is a good way to torpedo Linux.
Far too many people have a careless "U.S.A. laws suck, merge it anyway"
attitude.
Jeff
^ permalink raw reply
* Re: wireless (was Re: 2.6.18 -mm merge plans)
From: John W. Linville @ 2006-06-05 13:27 UTC (permalink / raw)
To: Christoph Hellwig, Jeff Garzik, Andrew Morton, linux-kernel,
netdev
In-Reply-To: <20060605085451.GA26766@infradead.org>
On Mon, Jun 05, 2006 at 09:54:51AM +0100, Christoph Hellwig wrote:
> On Sun, Jun 04, 2006 at 09:06:36PM -0400, Jeff Garzik wrote:
> > On Sun, Jun 04, 2006 at 01:50:11PM -0700, Andrew Morton wrote:
> > > acx1xx-wireless-driver.patch
> > > fix-tiacx-on-alpha.patch
> > > tiacx-fix-attribute-packed-warnings.patch
> > > tiacx-pci-build-fix.patch
> > > tiacx-ia64-fix.patch
> > >
> > > It is about time we did something with this large and presumably useful
> > > wireless driver.
> >
> > I've never had technical objections to merging this, just AFAIK it had a
> > highly questionable origin, namely being reverse-engineered in a
> > non-clean-room environment that might leave Linux legally vulnerable.
>
> As are at leasdt a fourth of linux drivers. Andrew, please just go ahead
> and merge it (I'll do another review ASAP).
Actually, I was planning to merge the softmac-based version for 2.6.18.
It looks like I may want some of Andrew's patches on top (ia64, alpha, etc).
http://www.kernel.org/pub/linux/kernel/people/linville/wireless-2.6/master/
0003-wireless-add-acx-driver.txt
0004-acxsm-merge-from-acx-0.3.32.txt
0005-tiacx-Let-only-ACX_PCI-ACX_USB-be-user-visible.txt
0007-tiacx-revert-neither-PCI-nor-USB-is-selected-change.txt
0008-tiacx-implement-much-more-flexible-firmware-statistics-parsing.txt
0009-tiacx-Change-acx_ioctl_-get-set-_encode-to-use-kernel-80211-stack.txt
0010-tiacx-fix-breakage-of-Get-rid-of-circular-list-of-adev-s.txt
0011-tiacx-split-module-into-acx-common-acx-pci-acx-usb.txt
Of course, I didn't know there were serious concerns about this
driver's origin. I hope we aren't confusing this with the atheros
driver...?
> Please don't let this reverse engineering idiocy hinder wireless driver
> adoption, we're already falling far behind openbsd who are very successfull
> reverse engineering lots of wireless chipsets.
This bugbear does seem to keep visiting us. It is a bit of a
minefield.
I'm inclined to think that Christoph and Arjan are right, that we
have been too cautious. Of course, neither of these fine gentlemen
are known for their timidity... :-)
Does not the Signed-off-by: line on a patch submission give us some
level of "good faith" protection?
I'm tempted to take contributors at their word, that they have produced
their own work and not copied from others. What else do we need?
John
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply
* Re: wireless (was Re: 2.6.18 -mm merge plans)
From: Christoph Hellwig @ 2006-06-05 13:31 UTC (permalink / raw)
To: Christoph Hellwig, Jeff Garzik, Andrew Morton, linux-kernel,
netdev
In-Reply-To: <20060605132732.GA23350@tuxdriver.com>
On Mon, Jun 05, 2006 at 09:27:37AM -0400, John W. Linville wrote:
> Actually, I was planning to merge the softmac-based version for 2.6.18.
> It looks like I may want some of Andrew's patches on top (ia64, alpha, etc).
duh, didn't know that wasn't in -mm. we want the softmac version of course.
^ permalink raw reply
* Re: [PATCH] hush noisy ieee80211 CCMP printks
From: Jouni Malinen @ 2006-06-05 13:31 UTC (permalink / raw)
To: Jason Lunz; +Cc: linville, netdev
In-Reply-To: <20060605001208.GA4585@opus.vpn-dev.reflex>
On Sun, Jun 04, 2006 at 08:12:09PM -0400, Jason Lunz wrote:
> Don't swamp syslog with
> CCMP: decrypt failed: STA=00:12:17:3a:e2:c7
> and
> CCMP: replay detected: STA=00:12:17:3a:e2:c7 previous PN 000000000004 received PN 000000000004
> messages.
>
> These both seem to be completely normal in regular use, especially
> 'decrypt failed' whenever another wpa-using station on the same AP is
> within range.
These are not normal, i.e., they should not really show up unless
something goes wrong. In many cases, this may be caused by something
missing in local filtering (e.g., retry duplicates are not filtered out
correctly or messages to incorrect addresses are allowed through, etc.).
In other cases, it can indicate incorrect implementation of rekeying or
some other bugs in either end of the connection. Anyway, I don't have
anything against removing the messages in default kernel builds. If
there is a suitable build time debug option, that might be nicer way of
doing this, though, since these can provide valuable information when
figuring out why something does not work.
--
Jouni Malinen PGP id EFC895FA
^ permalink raw reply
* Re: wireless (was Re: 2.6.18 -mm merge plans)
From: Arjan van de Ven @ 2006-06-05 13:42 UTC (permalink / raw)
To: John W. Linville
Cc: Christoph Hellwig, Jeff Garzik, Andrew Morton, linux-kernel,
netdev
In-Reply-To: <20060605132732.GA23350@tuxdriver.com>
> Of course, I didn't know there were serious concerns about this
> driver's origin. I hope we aren't confusing this with the atheros
> driver...?
>
> > Please don't let this reverse engineering idiocy hinder wireless driver
> > adoption, we're already falling far behind openbsd who are very successfull
> > reverse engineering lots of wireless chipsets.
>
> This bugbear does seem to keep visiting us. It is a bit of a
> minefield.
>
> I'm inclined to think that Christoph and Arjan are right, that we
> have been too cautious. Of course, neither of these fine gentlemen
> are known for their timidity... :-)
>
> Does not the Signed-off-by: line on a patch submission give us some
> level of "good faith" protection?
I would suggest asking them an explicit "did you copy anything" and make
sure their "we didn't copy" answer is in the description of the original
patch submission.
>
> I'm tempted to take contributors at their word, that they have produced
> their own work and not copied from others. What else do we need?
to a large degree that's all you can do. (of course you can look at the
code for something that looks "obviously not from here" as well, and we
all tend to do that anyway since such stuff tends to highly violate
coding style anyway)
^ permalink raw reply
* Linux kernel and laws
From: Adrian Bunk @ 2006-06-05 14:02 UTC (permalink / raw)
To: Jeff Garzik
Cc: Arjan van de Ven, Christoph Hellwig, Andrew Morton, linux-kernel,
netdev, linville
In-Reply-To: <20060605125235.GB6066@havoc.gtf.org>
On Mon, Jun 05, 2006 at 08:52:35AM -0400, Jeff Garzik wrote:
>...
> > Paying attention to proper reverse engineering is good. Being
> > overzealous is not.
>
> Being overzealous about merging drivers without first checking the legal
> ramifications is a good way to torpedo Linux.
>
> Far too many people have a careless "U.S.A. laws suck, merge it anyway"
> attitude.
Independent of this issue:
An interesting question is how to handle legal issues properly.
Where is the borderline for rejecting code due to legal issues?
Might not be 100% correct according to laws in the USA.
Might not be 100% correct according to laws in Germany.
Might not be 100% correct according to laws in Finland.
Might not be 100% correct according to laws in Norway.
Might not be 100% correct according to laws in Brasil.
Might not be 100% correct according to laws in Japan.
Might not be 100% correct according to laws in India.
Might not be 100% correct according to laws in Russia.
Might not be 100% correct according to laws in China.
Might not be 100% correct according to laws in Saudi Arabia.
Might not be 100% correct according to laws in Iran.
For me living in Germany, none of these laws except for the German one
has any relevance.
I've never seen people on this list pointing to probable problems with
Chinese laws although these laws are relevant for four times as many
people as US laws.
If someone would state a submission to the kernel might have issues
according to Chinese laws, or Iranian laws, or Russian laws, would this
be enough for keeping code out of the kernel?
This might sound like a theoretical question, but e.g. considering that
the kernel contains cryptography code it's a question that might have
wide practical implications.
> Jeff
cu
Adrian
--
"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon Seed
^ permalink raw reply
* Re: move zd1201 where it belongs
From: John W. Linville @ 2006-06-05 14:13 UTC (permalink / raw)
To: Pavel Machek
Cc: Arjan van de Ven, Jirka Lenost Benc, kernel list, netdev, pe1rxq
In-Reply-To: <20060605113332.GB2132@elf.ucw.cz>
On Mon, Jun 05, 2006 at 01:33:33PM +0200, Pavel Machek wrote:
> On Po 05-06-06 13:15:20, Arjan van de Ven wrote:
> > On Mon, 2006-06-05 at 12:39 +0200, Pavel Machek wrote:
> > > zd1201 is wifi adapter, yet it is hiding in drivers/usb/net where
> > > noone can find it. This moves Kconfig/Makefile to right place; you
> > > still need to manually move .c and .h files.
> > do you think it should at least depend in some form or another on
> > CONFIG_USB ?
>
> Right, added USB && to depends directive.
Did you mean to only copy Jiri and LKML?
It seems like you should have sent at least sent this to
netdev@vger.kernel.org, if not also to me, Jeroen Vreeken and/or
possibly Greg K-H (USB subsystem).
Will you be posting a new version, with the CONFIG_USB change?
Thanks,
John
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply
* Re: Linux kernel and laws
From: linux-os (Dick Johnson) @ 2006-06-05 14:21 UTC (permalink / raw)
To: Adrian Bunk
Cc: Jeff Garzik, Arjan van de Ven, Christoph Hellwig, Andrew Morton,
linux-kernel, netdev, linville
In-Reply-To: <20060605140226.GR3955@stusta.de>
On Mon, 5 Jun 2006, Adrian Bunk wrote:
> On Mon, Jun 05, 2006 at 08:52:35AM -0400, Jeff Garzik wrote:
>> ...
>>> Paying attention to proper reverse engineering is good. Being
>>> overzealous is not.
>>
>> Being overzealous about merging drivers without first checking the legal
>> ramifications is a good way to torpedo Linux.
>>
>> Far too many people have a careless "U.S.A. laws suck, merge it anyway"
>> attitude.
>
> Independent of this issue:
>
> An interesting question is how to handle legal issues properly.
>
> Where is the borderline for rejecting code due to legal issues?
> Might not be 100% correct according to laws in the USA.
> Might not be 100% correct according to laws in Germany.
> Might not be 100% correct according to laws in Finland.
> Might not be 100% correct according to laws in Norway.
> Might not be 100% correct according to laws in Brasil.
> Might not be 100% correct according to laws in Japan.
> Might not be 100% correct according to laws in India.
> Might not be 100% correct according to laws in Russia.
> Might not be 100% correct according to laws in China.
> Might not be 100% correct according to laws in Saudi Arabia.
> Might not be 100% correct according to laws in Iran.
>
> For me living in Germany, none of these laws except for the German one
> has any relevance.
>
> I've never seen people on this list pointing to probable problems with
> Chinese laws although these laws are relevant for four times as many
> people as US laws.
>
> If someone would state a submission to the kernel might have issues
> according to Chinese laws, or Iranian laws, or Russian laws, would this
> be enough for keeping code out of the kernel?
>
> This might sound like a theoretical question, but e.g. considering that
> the kernel contains cryptography code it's a question that might have
> wide practical implications.
>
>> Jeff
>
> cu
> Adrian
If the kernel represented simply a knowledge base, then the burden
about whether or not someone could use it used to rest entirely
upon the user. That's why some Pacific rim governments are reportedly
fire-walling information.
In most western cultures, knowledge was not a crime. For many years,
someone could write a book, telling you how to kill somebody and,
as long as he didn't carry it out, he could not be held culpable.
Recently, in the US and some other countries, knowledge has become
criminalized. If you know how to defeat copy protection, and
you are not in a protected industry, you could be tried and
convicted of a federal crime.
That's one of the reasons why there are now no general guidelines
about kernel code, or any intellectual property use, for that matter.
The conditions could occur where the government thinks that you
know too much and are, therefore, a threat to "national security".
So, again, see a lawyer. The fact that you sought and accepted
legal opinion may in the future be your only viable defense as
governments bring charges against you! Sorry state of affairs for
sure.
Cheers,
Dick Johnson
Penguin : Linux version 2.6.16.4 on an i686 machine (5592.88 BogoMips).
New book: http://www.AbominableFirebug.com/
_
\x1a\x04
****************************************************************
The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to DeliveryErrors@analogic.com - and destroy all copies of this information, including any attachments, without reading or disclosing them.
Thank you.
^ permalink raw reply
* Re: move zd1201 where it belongs
From: Pavel Machek @ 2006-06-05 14:29 UTC (permalink / raw)
To: Arjan van de Ven, Jirka Lenost Benc, kernel list, netdev, pe1rxq
In-Reply-To: <20060605141322.GB23350@tuxdriver.com>
Hi!
> > > > zd1201 is wifi adapter, yet it is hiding in drivers/usb/net where
> > > > noone can find it. This moves Kconfig/Makefile to right place; you
> > > > still need to manually move .c and .h files.
>
> > > do you think it should at least depend in some form or another on
> > > CONFIG_USB ?
> >
> > Right, added USB && to depends directive.
>
> Did you mean to only copy Jiri and LKML?
Yes, because this should go in as a git patch (so it is move, not
create new file), and I was hoping for Jiri to generate proper
git-patch :-).
> It seems like you should have sent at least sent this to
> netdev@vger.kernel.org, if not also to me, Jeroen Vreeken and/or
> possibly Greg K-H (USB subsystem).
>
> Will you be posting a new version, with the CONFIG_USB change?
Here it is, still
Signed-off-by: Pavel Machek <pavel@suse.cz>
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index e0874cb..1eccdb3 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -503,6 +503,23 @@ config PRISM54
say M here and read <file:Documentation/modules.txt>. The module
will be called prism54.ko.
+config USB_ZD1201
+ tristate "USB ZD1201 based Wireless device support"
+ depends on USB && NET_RADIO
+ select FW_LOADER
+ ---help---
+ Say Y if you want to use wireless LAN adapters based on the ZyDAS
+ ZD1201 chip.
+
+ This driver makes the adapter appear as a normal Ethernet interface,
+ typically on wlan0.
+
+ The zd1201 device requires external firmware to be loaded.
+ This can be found at http://linux-lc100020.sourceforge.net/
+
+ To compile this driver as a module, choose M here: the
+ module will be called zd1201.
+
source "drivers/net/wireless/hostap/Kconfig"
source "drivers/net/wireless/bcm43xx/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index c867798..512603d 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -40,3 +40,5 @@ obj-$(CONFIG_BCM43XX) += bcm43xx/
# 16-bit wireless PCMCIA client drivers
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
+
+obj-$(CONFIG_USB_ZD1201) += zd1201.o
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
index efd6ca7..0540596 100644
--- a/drivers/usb/net/Kconfig
+++ b/drivers/usb/net/Kconfig
@@ -301,21 +301,4 @@ config USB_NET_ZAURUS
some cases CDC MDLM) protocol, not "g_ether".
-config USB_ZD1201
- tristate "USB ZD1201 based Wireless device support"
- depends on NET_RADIO
- select FW_LOADER
- ---help---
- Say Y if you want to use wireless LAN adapters based on the ZyDAS
- ZD1201 chip.
-
- This driver makes the adapter appear as a normal Ethernet interface,
- typically on wlan0.
-
- The zd1201 device requires external firmware to be loaded.
- This can be found at http://linux-lc100020.sourceforge.net/
-
- To compile this driver as a module, choose M here: the
- module will be called zd1201.
-
endmenu
diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile
index a21e6ea..160f19d 100644
--- a/drivers/usb/net/Makefile
+++ b/drivers/usb/net/Makefile
@@ -15,7 +15,6 @@ obj-$(CONFIG_USB_NET_RNDIS_HOST) += rndi
obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o
obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o
obj-$(CONFIG_USB_USBNET) += usbnet.o
-obj-$(CONFIG_USB_ZD1201) += zd1201.o
ifeq ($(CONFIG_USB_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply related
* Re: move zd1201 where it belongs
From: Jiri Benc @ 2006-06-05 14:44 UTC (permalink / raw)
To: Pavel Machek; +Cc: Arjan van de Ven, kernel list, netdev, pe1rxq
In-Reply-To: <20060605142912.GF2132@elf.ucw.cz>
On Mon, 5 Jun 2006 16:29:12 +0200, Pavel Machek wrote:
> Yes, because this should go in as a git patch (so it is move, not
> create new file), and I was hoping for Jiri to generate proper
> git-patch :-).
The proper person for this is maintainer of wireless or USB.
> Here it is, still
>
> Signed-off-by: Pavel Machek <pavel@suse.cz>
In addition to this,
mv drivers/usb/net/zd1201.[ch] drivers/net/wireless/
needs to be invoked.
I agree that the patch should be applied to remove confusion (not many
people know about this driver, even among wireless developers).
Jiri
--
Jiri Benc
SUSE Labs
^ permalink raw reply
* Re: move zd1201 where it belongs
From: John W. Linville @ 2006-06-05 14:47 UTC (permalink / raw)
To: Pavel Machek
Cc: Arjan van de Ven, Jirka Lenost Benc, kernel list, netdev, pe1rxq
In-Reply-To: <20060605142912.GF2132@elf.ucw.cz>
On Mon, Jun 05, 2006 at 04:29:12PM +0200, Pavel Machek wrote:
> > Did you mean to only copy Jiri and LKML?
>
> Yes, because this should go in as a git patch (so it is move, not
> create new file), and I was hoping for Jiri to generate proper
> git-patch :-).
Ah, I see. Well, I can handle this just fine.
Thanks,
John
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply
* Re: [PATCH] hush noisy ieee80211 CCMP printks
From: Jason Lunz @ 2006-06-05 16:03 UTC (permalink / raw)
To: Jouni Malinen; +Cc: linville, netdev
In-Reply-To: <20060605133147.GA9567@jm.kir.nu>
On Mon, Jun 05, 2006 at 06:31:48AM -0700, Jouni Malinen wrote:
> These are not normal, i.e., they should not really show up unless
> something goes wrong.
If these are a real problem, I'll gladly help debug it. I'm using
2.6.17-rc5's bcm43xx and the in-kernel ieee80211 softmac stack. I'm
using wpa/ccmp/aes with an openwrt AP.
> In many cases, this may be caused by something missing in local
> filtering (e.g., retry duplicates are not filtered out correctly or
> messages to incorrect addresses are allowed through, etc.).
Is it the driver's responsibility to do this filtering, or the softmac
stack's? Can you show me a code example where this filtering is done
properly?
> In other cases, it can indicate incorrect implementation of rekeying or
> some other bugs in either end of the connection.
I can try different implementations of WPA in the AP if necessary. I
think openwrt has other options. My end is in-kernel ieee80211_softmac -
is there anything you'd like me to look at there?
> Anyway, I don't have anything against removing the messages in default
> kernel builds. If there is a suitable build time debug option, that
> might be nicer way of doing this, though, since these can provide
> valuable information when figuring out why something does not work.
If the messages are actually useful, and unusual, then they should
probably stay. But I get a LOT of them, and my wireless is working just
fine.
I noticed that there are counters being incremented where those printks
are. How do I see those counters from userspace?
Jason
^ permalink raw reply
* Re: wireless (was Re: 2.6.18 -mm merge plans)
From: Alan Cox @ 2006-06-05 16:24 UTC (permalink / raw)
To: John W. Linville
Cc: Christoph Hellwig, Jeff Garzik, Andrew Morton, linux-kernel,
netdev
In-Reply-To: <20060605132732.GA23350@tuxdriver.com>
Ar Llu, 2006-06-05 am 09:27 -0400, ysgrifennodd John W. Linville:
> Does not the Signed-off-by: line on a patch submission give us some
> level of "good faith" protection?
>
> I'm tempted to take contributors at their word, that they have produced
> their own work and not copied from others. What else do we need?
To keep an eye out for problems. Given the questions raised the tiacx
people need to clarify their position and someone needs to look into it.
Until that is done it certainly isn't "good faith" any more.
Alan
^ permalink raw reply
* Re: move zd1201 where it belongs
From: Greg KH @ 2006-06-05 16:16 UTC (permalink / raw)
To: Pavel Machek, Arjan van de Ven, Jirka Lenost Benc, kernel list,
netdev, pe1rxq
In-Reply-To: <20060605144722.GA6068@tuxdriver.com>
On Mon, Jun 05, 2006 at 10:47:26AM -0400, John W. Linville wrote:
> On Mon, Jun 05, 2006 at 04:29:12PM +0200, Pavel Machek wrote:
>
> > > Did you mean to only copy Jiri and LKML?
> >
> > Yes, because this should go in as a git patch (so it is move, not
> > create new file), and I was hoping for Jiri to generate proper
> > git-patch :-).
>
> Ah, I see. Well, I can handle this just fine.
Ack from my side, feel free to move this to your section of the kernel
:)
thanks,
greg k-h
^ permalink raw reply
* Re: TCP Westwood Patch
From: Stephen Hemminger @ 2006-06-05 16:32 UTC (permalink / raw)
To: Luca De Cicco; +Cc: netdev, David S. Miller, Saverio Mascolo
In-Reply-To: <20060524182006.32fd1fcd@localhost>
On Wed, 24 May 2006 18:20:06 +0200
Luca De Cicco <ldecicco@gmail.com> wrote:
> Hi there to the list.
>
> I'm Luca De Cicco a PhD student working on TCP Westwood+ at Politecnico
> di Bari.
>
> I have attached a patch (it applies to 2.6.16.18 but it has been also
> tested on 2.6.15 too) for the TCP Westwood+ congestion control
> algorithm which fixes a bug and adds some new features/improvements:
>
> o BUGFIX. The first sample was wrong
>
> o RTT_min is updated each time a timeout event occurs (in order to
> cope with hard handovers in wireless scenarios)
>
> o The bandwidth estimate filter is now initialized with the first
> bandwidth sample in order to have better performances in the case of
> small file transfers.
>
> Best regards,
>
> Luca De Cicco
> Politecnico di Bari
Are you going to split this up, or do you want me to do it?
You probably are busy with school work.
^ permalink raw reply
* No more worrying needed
From: Garry London @ 2006-06-05 16:45 UTC (permalink / raw)
To: netdev
Life Should be Full of Luxuries....
http://blessthathomepleasee.com/
Yet, only a handful of people can afford the finest products, the luxuries of the elite.
But, here at "Luxury Replica" we are committed to bringing you the finest products, at prices incomparably lower.
All of the top designer brands for Watches, Ties, Handbags and even Mont Blanc.
http://blessthathomepleasee.com/
The finest of products, at the lowest of prices, only a click away:
http://newgunforsalejoke.com/
Regards,
Garry London
^ permalink raw reply
* Re: [RFC] TCP limited slow start
From: Stephen Hemminger @ 2006-06-05 17:17 UTC (permalink / raw)
To: John Heffner; +Cc: David Miller, netdev
In-Reply-To: <4481BD01.9020906@psc.edu>
On Sat, 03 Jun 2006 12:46:57 -0400
John Heffner <jheffner@psc.edu> wrote:
> Stephen Hemminger wrote:
> > Rolled my sleeve's up and gave this a try...
> >
> > This is a implementation of Sally Floyd's Limited Slow Start
> > for Large Congestion Windows.
>
> Limited slow start is useful as a work-around for bottleneck queues that
> are inappropriately short. I don't think it's good to run it all the
> time by default (with a max_ssthresh < infinity), because it slows down
> flows on healthy paths, and introduces another non-scalable parameter to
> TCP.
>
> I see it as potentially useful as a per-route parameter, where you set
> it deliberately to work around some known problematic path. A sysctl
> with a default value of infinity might be okay as well.
>
> Practically speaking, we've had this in the Web100 patch for a long time
> (and still do, look for WAD_MaxSsthresh), but I've never found it all
> that useful. If the bottleneck queue is too short, you usually end up
> getting screwed other ways too.
>
> -John
I moved it off to tcp_highspeed.c only. That is seems appropriate because
that is where you put the related RFC.
^ permalink raw reply
* [PATCH] net.ipv4.ip_autoconfig sysctl removal
From: Stephen Hemminger @ 2006-06-05 17:58 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev
The sysctl net.ipv4.ip_autoconfig is a legacy value that is not used.
Can it finally go in 2.6.18 or do we need to go through the whole
feature-removal process?
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
diff --git a/include/net/ip.h b/include/net/ip.h
index 3d2e5ca..ead233c 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -147,7 +147,6 @@ void ip_send_reply(struct sock *sk, stru
struct ipv4_config
{
int log_martians;
- int autoconfig;
int no_pmtu_disc;
};
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 6b6c3ad..9d2b81e 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -182,14 +182,6 @@ ctl_table ipv4_table[] = {
.strategy = &ipv4_doint_and_flush_strategy,
},
{
- .ctl_name = NET_IPV4_AUTOCONFIG,
- .procname = "ip_autoconfig",
- .data = &ipv4_config.autoconfig,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
.ctl_name = NET_IPV4_NO_PMTU_DISC,
.procname = "ip_no_pmtu_disc",
.data = &ipv4_config.no_pmtu_disc,
^ permalink raw reply related
* [PATCH] TCP changes for 2.6.18
From: Stephen Hemminger @ 2006-06-05 18:03 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev
Dave, please consider adding these for the 2.6.18.
The following changes since commit 672c6108a51bf559d19595d9f8193dfd81f0f752:
Linus Torvalds:
Merge master.kernel.org:/.../jejb/scsi-rc-fixes-2.6
are found in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/tcp-2.6.git
Angelo P. Castellani:
TCP Compound congestion control
Bin Zhou:
TCP Veno congestion control
Stephen Hemminger:
TCP Compound quad root function
TCP minimum congestion window consolidation
TCP Probe congestion window tracing
TCP Limited slow start for Highspeed TCP
Wong Edison:
TCP Low Priority congestion control
include/net/tcp.h | 4
net/Kconfig | 15 ++
net/ipv4/Kconfig | 32 +++
net/ipv4/Makefile | 4
net/ipv4/tcp_bic.c | 7 -
net/ipv4/tcp_compound.c | 448 ++++++++++++++++++++++++++++++++++++++++++++++
net/ipv4/tcp_cong.c | 6 -
net/ipv4/tcp_cubic.c | 6 -
net/ipv4/tcp_highspeed.c | 24 ++
net/ipv4/tcp_htcp.c | 9 -
net/ipv4/tcp_input.c | 13 +
net/ipv4/tcp_lp.c | 338 +++++++++++++++++++++++++++++++++++
net/ipv4/tcp_probe.c | 179 ++++++++++++++++++
net/ipv4/tcp_veno.c | 231 ++++++++++++++++++++++++
net/ipv4/tcp_westwood.c | 18 +-
15 files changed, 1291 insertions(+), 43 deletions(-)
create mode 100644 net/ipv4/tcp_compound.c
create mode 100644 net/ipv4/tcp_lp.c
create mode 100644 net/ipv4/tcp_probe.c
create mode 100644 net/ipv4/tcp_veno.c
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 3c989db..575636f 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -628,7 +628,7 @@ struct tcp_congestion_ops {
/* return slow start threshold (required) */
u32 (*ssthresh)(struct sock *sk);
/* lower bound for congestion window (optional) */
- u32 (*min_cwnd)(struct sock *sk);
+ u32 (*min_cwnd)(const struct sock *sk);
/* do new cwnd calculation (required) */
void (*cong_avoid)(struct sock *sk, u32 ack,
u32 rtt, u32 in_flight, int good_ack);
@@ -663,7 +663,7 @@ extern struct tcp_congestion_ops tcp_ini
extern u32 tcp_reno_ssthresh(struct sock *sk);
extern void tcp_reno_cong_avoid(struct sock *sk, u32 ack,
u32 rtt, u32 in_flight, int flag);
-extern u32 tcp_reno_min_cwnd(struct sock *sk);
+extern u32 tcp_reno_min_cwnd(const struct sock *sk);
extern struct tcp_congestion_ops tcp_reno;
static inline void tcp_set_ca_state(struct sock *sk, const u8 ca_state)
diff --git a/net/Kconfig b/net/Kconfig
index 4193cdc..ff0db80 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -215,6 +215,21 @@ config NET_PKTGEN
To compile this code as a module, choose M here: the
module will be called pktgen.
+config NET_TCPPROBE
+ tristate "TCP connection probing"
+ depends on INET && EXPERIMENTAL && PROC_FS && KPROBES
+ ---help---
+ This module allows for capturing the changes to TCP connection
+ state in response to incoming patckets. It is used for debugging
+ TCP congestion avoidance modules. If you don't understand
+ what was just said, you don't need it: say N.
+
+ Documentation on how to use the packet generator can be found
+ at http://linux-net.osdl.org/index.php/TcpProbe
+
+ To compile this code as a module, choose M here: the
+ module will be called tcp_probe.
+
endmenu
endmenu
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index e40f753..2032411 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -532,6 +532,38 @@ config TCP_CONG_SCALABLE
properties, though is known to have fairness issues.
See http://www-lce.eng.cam.ac.uk/~ctk21/scalable/
+config TCP_CONG_LP
+ tristate "TCP Low Priority"
+ depends on EXPERIMENTAL
+ default n
+ ---help---
+ TCP Low Priority (TCP-LP), a distributed algorithm whose goal is
+ to utiliza only the excess network bandwidth as compared to the
+ ``fair share`` of bandwidth as targeted by TCP.
+ See http://www-ece.rice.edu/networks/TCP-LP/
+
+config TCP_CONG_VENO
+ tristate "TCP Veno"
+ depends on EXPERIMENTAL
+ default n
+ ---help---
+ TCP Veno is a sender-side only enhancement of TCP to obtain better
+ throughput over wireless networks. TCP Veno makes use of state
+ distinguishing to circumvent the difficult judgment of the packet loss
+ type. TCP Veno cuts down less congestion window in response to random
+ loss packets.
+ See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf
+
+config TCP_CONG_COMPOUND
+ tristate "TCP Compound"
+ depends on EXPERIMENTAL
+ default n
+ ---help---
+ TCP Compound is a sender-side only change to TCP that uses
+ a mixed Reno/Vegas approach to calculate the cwnd.
+ For further details look here:
+ ftp://ftp.research.microsoft.com/pub/tr/TR-2005-86.pdf
+
endmenu
config TCP_CONG_BIC
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 9ef50a0..ac7eb0e 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_IP_VS) += ipvs/
obj-$(CONFIG_INET_DIAG) += inet_diag.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o
obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
+obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o
obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
obj-$(CONFIG_TCP_CONG_CUBIC) += tcp_cubic.o
obj-$(CONFIG_TCP_CONG_WESTWOOD) += tcp_westwood.o
@@ -41,7 +42,10 @@ obj-$(CONFIG_TCP_CONG_HSTCP) += tcp_high
obj-$(CONFIG_TCP_CONG_HYBLA) += tcp_hybla.o
obj-$(CONFIG_TCP_CONG_HTCP) += tcp_htcp.o
obj-$(CONFIG_TCP_CONG_VEGAS) += tcp_vegas.o
+obj-$(CONFIG_TCP_CONG_VENO) += tcp_veno.o
obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o
+obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o
+obj-$(CONFIG_TCP_CONG_COMPOUND) += tcp_compound.o
obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
xfrm4_output.o
diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c
index 035f209..b2d9021 100644
--- a/net/ipv4/tcp_bic.c
+++ b/net/ipv4/tcp_bic.c
@@ -198,12 +198,6 @@ static u32 bictcp_undo_cwnd(struct sock
return max(tp->snd_cwnd, ca->last_max_cwnd);
}
-static u32 bictcp_min_cwnd(struct sock *sk)
-{
- const struct tcp_sock *tp = tcp_sk(sk);
- return tp->snd_ssthresh;
-}
-
static void bictcp_state(struct sock *sk, u8 new_state)
{
if (new_state == TCP_CA_Loss)
@@ -231,7 +225,6 @@ static struct tcp_congestion_ops bictcp
.cong_avoid = bictcp_cong_avoid,
.set_state = bictcp_state,
.undo_cwnd = bictcp_undo_cwnd,
- .min_cwnd = bictcp_min_cwnd,
.pkts_acked = bictcp_acked,
.owner = THIS_MODULE,
.name = "bic",
diff --git a/net/ipv4/tcp_compound.c b/net/ipv4/tcp_compound.c
new file mode 100644
index 0000000..bc54f7e
--- /dev/null
+++ b/net/ipv4/tcp_compound.c
@@ -0,0 +1,448 @@
+/*
+ * TCP Vegas congestion control
+ *
+ * This is based on the congestion detection/avoidance scheme described in
+ * Lawrence S. Brakmo and Larry L. Peterson.
+ * "TCP Vegas: End to end congestion avoidance on a global internet."
+ * IEEE Journal on Selected Areas in Communication, 13(8):1465--1480,
+ * October 1995. Available from:
+ * ftp://ftp.cs.arizona.edu/xkernel/Papers/jsac.ps
+ *
+ * See http://www.cs.arizona.edu/xkernel/ for their implementation.
+ * The main aspects that distinguish this implementation from the
+ * Arizona Vegas implementation are:
+ * o We do not change the loss detection or recovery mechanisms of
+ * Linux in any way. Linux already recovers from losses quite well,
+ * using fine-grained timers, NewReno, and FACK.
+ * o To avoid the performance penalty imposed by increasing cwnd
+ * only every-other RTT during slow start, we increase during
+ * every RTT during slow start, just like Reno.
+ * o Largely to allow continuous cwnd growth during slow start,
+ * we use the rate at which ACKs come back as the "actual"
+ * rate, rather than the rate at which data is sent.
+ * o To speed convergence to the right rate, we set the cwnd
+ * to achieve the right ("actual") rate when we exit slow start.
+ * o To filter out the noise caused by delayed ACKs, we use the
+ * minimum RTT sample observed during the last RTT to calculate
+ * the actual rate.
+ * o When the sender re-starts from idle, it waits until it has
+ * received ACKs for an entire flight of new data before making
+ * a cwnd adjustment decision. The original Vegas implementation
+ * assumed senders never went idle.
+ *
+ *
+ * TCP Compound based on TCP Vegas
+ *
+ * further details can be found here:
+ * ftp://ftp.research.microsoft.com/pub/tr/TR-2005-86.pdf
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/inet_diag.h>
+
+#include <net/tcp.h>
+
+/* Default values of the Vegas variables, in fixed-point representation
+ * with V_PARAM_SHIFT bits to the right of the binary point.
+ */
+#define V_PARAM_SHIFT 1
+
+#define TCP_COMPOUND_ALPHA 3U
+#define TCP_COMPOUND_BETA 1U
+#define TCP_COMPOUND_GAMMA 30
+#define TCP_COMPOUND_ZETA 1
+
+/* TCP compound variables */
+struct compound {
+ u32 beg_snd_nxt; /* right edge during last RTT */
+ u32 beg_snd_una; /* left edge during last RTT */
+ u32 beg_snd_cwnd; /* saves the size of the cwnd */
+ u8 doing_vegas_now; /* if true, do vegas for this RTT */
+ u16 cntRTT; /* # of RTTs measured within last RTT */
+ u32 minRTT; /* min of RTTs measured within last RTT (in usec) */
+ u32 baseRTT; /* the min of all Vegas RTT measurements seen (in usec) */
+
+ u32 cwnd;
+ u32 dwnd;
+};
+
+/* There are several situations when we must "re-start" Vegas:
+ *
+ * o when a connection is established
+ * o after an RTO
+ * o after fast recovery
+ * o when we send a packet and there is no outstanding
+ * unacknowledged data (restarting an idle connection)
+ *
+ * In these circumstances we cannot do a Vegas calculation at the
+ * end of the first RTT, because any calculation we do is using
+ * stale info -- both the saved cwnd and congestion feedback are
+ * stale.
+ *
+ * Instead we must wait until the completion of an RTT during
+ * which we actually receive ACKs.
+ */
+static inline void vegas_enable(struct sock *sk)
+{
+ const struct tcp_sock *tp = tcp_sk(sk);
+ struct compound *vegas = inet_csk_ca(sk);
+
+ /* Begin taking Vegas samples next time we send something. */
+ vegas->doing_vegas_now = 1;
+
+ /* Set the beginning of the next send window. */
+ vegas->beg_snd_nxt = tp->snd_nxt;
+
+ vegas->cntRTT = 0;
+ vegas->minRTT = 0x7fffffff;
+}
+
+/* Stop taking Vegas samples for now. */
+static inline void vegas_disable(struct sock *sk)
+{
+ struct compound *vegas = inet_csk_ca(sk);
+
+ vegas->doing_vegas_now = 0;
+}
+
+static void tcp_compound_init(struct sock *sk)
+{
+ struct compound *vegas = inet_csk_ca(sk);
+ const struct tcp_sock *tp = tcp_sk(sk);
+
+ vegas->baseRTT = 0x7fffffff;
+ vegas_enable(sk);
+
+ vegas->dwnd = 0;
+ vegas->cwnd = tp->snd_cwnd;
+}
+
+/* Do RTT sampling needed for Vegas.
+ * Basically we:
+ * o min-filter RTT samples from within an RTT to get the current
+ * propagation delay + queuing delay (we are min-filtering to try to
+ * avoid the effects of delayed ACKs)
+ * o min-filter RTT samples from a much longer window (forever for now)
+ * to find the propagation delay (baseRTT)
+ */
+static void tcp_compound_rtt_calc(struct sock *sk, u32 usrtt)
+{
+ struct compound *vegas = inet_csk_ca(sk);
+ u32 vrtt = usrtt + 1; /* Never allow zero rtt or baseRTT */
+
+ /* Filter to find propagation delay: */
+ if (vrtt < vegas->baseRTT)
+ vegas->baseRTT = vrtt;
+
+ /* Find the min RTT during the last RTT to find
+ * the current prop. delay + queuing delay:
+ */
+
+ vegas->minRTT = min(vegas->minRTT, vrtt);
+ vegas->cntRTT++;
+}
+
+static void tcp_compound_state(struct sock *sk, u8 ca_state)
+{
+
+ if (ca_state == TCP_CA_Open)
+ vegas_enable(sk);
+ else
+ vegas_disable(sk);
+}
+
+
+/* 64bit divisor, dividend and result. dynamic precision */
+static inline u64 div64_64(u64 dividend, u64 divisor)
+{
+ u32 d = divisor;
+
+ if (divisor > 0xffffffffULL) {
+ unsigned int shift = fls(divisor >> 32);
+
+ d = divisor >> shift;
+ dividend >>= shift;
+ }
+
+ /* avoid 64 bit division if possible */
+ if (dividend >> 32)
+ do_div(dividend, d);
+ else
+ dividend = (u32) dividend / d;
+
+ return dividend;
+}
+
+/* calculate the quartic root of "a" using Newton-Raphson */
+static u32 qroot(u64 a)
+{
+ u32 x, x1;
+
+ /* Initial estimate is based on:
+ * qrt(x) = exp(log(x) / 4)
+ */
+ x = 1u << (fls64(a) >> 2);
+
+ /*
+ * Iteration based on:
+ * 3
+ * x = ( 3 * x + a / x ) / 4
+ * k+1 k k
+ */
+ do {
+ u64 x3 = x;
+
+ x1 = x;
+ x3 *= x;
+ x3 *= x;
+
+ x = (3 * x + (u32) div64_64(a, x3)) / 4;
+ } while (abs(x1 - x) > 1);
+
+ return x;
+}
+
+
+/*
+ * If the connection is idle and we are restarting,
+ * then we don't want to do any Vegas calculations
+ * until we get fresh RTT samples. So when we
+ * restart, we reset our Vegas state to a clean
+ * slate. After we get acks for this flight of
+ * packets, _then_ we can make Vegas calculations
+ * again.
+ */
+static void tcp_compound_cwnd_event(struct sock *sk, enum tcp_ca_event event)
+{
+ if (event == CA_EVENT_CWND_RESTART || event == CA_EVENT_TX_START)
+ tcp_compound_init(sk);
+}
+
+static void tcp_compound_cong_avoid(struct sock *sk, u32 ack,
+ u32 seq_rtt, u32 in_flight, int flag)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct compound *vegas = inet_csk_ca(sk);
+ u8 inc = 0;
+
+ if (vegas->cwnd + vegas->dwnd > tp->snd_cwnd) {
+ if (vegas->cwnd > tp->snd_cwnd || vegas->dwnd > tp->snd_cwnd) {
+ vegas->cwnd = tp->snd_cwnd;
+ vegas->dwnd = 0;
+ } else
+ vegas->cwnd = tp->snd_cwnd - vegas->dwnd;
+
+ }
+
+ if (!tcp_is_cwnd_limited(sk, in_flight))
+ return;
+
+ if (vegas->cwnd <= tp->snd_ssthresh)
+ inc = 1;
+ else if (tp->snd_cwnd_cnt < tp->snd_cwnd)
+ tp->snd_cwnd_cnt++;
+
+ if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+ inc = 1;
+ tp->snd_cwnd_cnt = 0;
+ }
+
+ if (inc && tp->snd_cwnd < tp->snd_cwnd_clamp)
+ vegas->cwnd++;
+
+ /* The key players are v_beg_snd_una and v_beg_snd_nxt.
+ *
+ * These are so named because they represent the approximate values
+ * of snd_una and snd_nxt at the beginning of the current RTT. More
+ * precisely, they represent the amount of data sent during the RTT.
+ * At the end of the RTT, when we receive an ACK for v_beg_snd_nxt,
+ * we will calculate that (v_beg_snd_nxt - v_beg_snd_una) outstanding
+ * bytes of data have been ACKed during the course of the RTT, giving
+ * an "actual" rate of:
+ *
+ * (v_beg_snd_nxt - v_beg_snd_una) / (rtt duration)
+ *
+ * Unfortunately, v_beg_snd_una is not exactly equal to snd_una,
+ * because delayed ACKs can cover more than one segment, so they
+ * don't line up nicely with the boundaries of RTTs.
+ *
+ * Another unfortunate fact of life is that delayed ACKs delay the
+ * advance of the left edge of our send window, so that the number
+ * of bytes we send in an RTT is often less than our cwnd will allow.
+ * So we keep track of our cwnd separately, in v_beg_snd_cwnd.
+ */
+
+ if (after(ack, vegas->beg_snd_nxt)) {
+ /* Do the Vegas once-per-RTT cwnd adjustment. */
+ u32 old_wnd, old_snd_cwnd;
+
+ /* Here old_wnd is essentially the window of data that was
+ * sent during the previous RTT, and has all
+ * been acknowledged in the course of the RTT that ended
+ * with the ACK we just received. Likewise, old_snd_cwnd
+ * is the cwnd during the previous RTT.
+ */
+ if (!tp->mss_cache)
+ return;
+
+ old_wnd = (vegas->beg_snd_nxt - vegas->beg_snd_una) /
+ tp->mss_cache;
+ old_snd_cwnd = vegas->beg_snd_cwnd;
+
+ /* Save the extent of the current window so we can use this
+ * at the end of the next RTT.
+ */
+ vegas->beg_snd_una = vegas->beg_snd_nxt;
+ vegas->beg_snd_nxt = tp->snd_nxt;
+ vegas->beg_snd_cwnd = tp->snd_cwnd;
+
+ /* We do the Vegas calculations only if we got enough RTT
+ * samples that we can be reasonably sure that we got
+ * at least one RTT sample that wasn't from a delayed ACK.
+ * If we only had 2 samples total,
+ * then that means we're getting only 1 ACK per RTT, which
+ * means they're almost certainly delayed ACKs.
+ * If we have 3 samples, we should be OK.
+ */
+
+ if (vegas->cntRTT > 2) {
+ u32 rtt, target_cwnd, diff;
+ u32 brtt, dwnd;
+
+ /* We have enough RTT samples, so, using the Vegas
+ * algorithm, we determine if we should increase or
+ * decrease cwnd, and by how much.
+ */
+
+ /* Pluck out the RTT we are using for the Vegas
+ * calculations. This is the min RTT seen during the
+ * last RTT. Taking the min filters out the effects
+ * of delayed ACKs, at the cost of noticing congestion
+ * a bit later.
+ */
+ rtt = vegas->minRTT;
+
+ /* Calculate the cwnd we should have, if we weren't
+ * going too fast.
+ *
+ * This is:
+ * (actual rate in segments) * baseRTT
+ * We keep it as a fixed point number with
+ * V_PARAM_SHIFT bits to the right of the binary point.
+ */
+ if (!rtt)
+ return;
+
+ brtt = vegas->baseRTT;
+ target_cwnd = ((old_wnd * brtt)
+ << V_PARAM_SHIFT) / rtt;
+
+ /* Calculate the difference between the window we had,
+ * and the window we would like to have. This quantity
+ * is the "Diff" from the Arizona Vegas papers.
+ *
+ * Again, this is a fixed point number with
+ * V_PARAM_SHIFT bits to the right of the binary
+ * point.
+ */
+
+ diff = (old_wnd << V_PARAM_SHIFT) - target_cwnd;
+
+ dwnd = vegas->dwnd;
+
+ if (diff < (TCP_COMPOUND_GAMMA << V_PARAM_SHIFT)) {
+ u64 v;
+ u32 x;
+
+ /*
+ * The TCP Compound paper describes the choice
+ * of "k" determines the agressiveness,
+ * ie. slope of the response function.
+ *
+ * For same value as HSTCP would be 0.8
+ * but for computaional reasons, both the
+ * original authors and this implementation
+ * use 0.75.
+ */
+ v = old_wnd;
+ x = qroot(v * v * v) >> TCP_COMPOUND_ALPHA;
+ if (x > 1)
+ dwnd = x - 1;
+ else
+ dwnd = 0;
+
+ dwnd += vegas->dwnd;
+
+ } else if ((dwnd << V_PARAM_SHIFT) <
+ (diff * TCP_COMPOUND_BETA))
+ dwnd = 0;
+ else
+ dwnd =
+ ((dwnd << V_PARAM_SHIFT) -
+ (diff *
+ TCP_COMPOUND_BETA)) >> V_PARAM_SHIFT;
+
+ vegas->dwnd = dwnd;
+
+ }
+
+ /* Wipe the slate clean for the next RTT. */
+ vegas->cntRTT = 0;
+ vegas->minRTT = 0x7fffffff;
+ }
+
+ tp->snd_cwnd = vegas->cwnd + vegas->dwnd;
+}
+
+/* Extract info for Tcp socket info provided via netlink. */
+static void tcp_compound_get_info(struct sock *sk, u32 ext, struct sk_buff *skb)
+{
+ const struct compound *ca = inet_csk_ca(sk);
+ if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) {
+ struct tcpvegas_info *info;
+
+ info = RTA_DATA(__RTA_PUT(skb, INET_DIAG_VEGASINFO,
+ sizeof(*info)));
+
+ info->tcpv_enabled = ca->doing_vegas_now;
+ info->tcpv_rttcnt = ca->cntRTT;
+ info->tcpv_rtt = ca->baseRTT;
+ info->tcpv_minrtt = ca->minRTT;
+ rtattr_failure:;
+ }
+}
+
+static struct tcp_congestion_ops tcp_compound = {
+ .init = tcp_compound_init,
+ .ssthresh = tcp_reno_ssthresh,
+ .cong_avoid = tcp_compound_cong_avoid,
+ .rtt_sample = tcp_compound_rtt_calc,
+ .set_state = tcp_compound_state,
+ .cwnd_event = tcp_compound_cwnd_event,
+ .get_info = tcp_compound_get_info,
+
+ .owner = THIS_MODULE,
+ .name = "compound",
+};
+
+static int __init tcp_compound_register(void)
+{
+ BUG_ON(sizeof(struct compound) > ICSK_CA_PRIV_SIZE);
+ tcp_register_congestion_control(&tcp_compound);
+ return 0;
+}
+
+static void __exit tcp_compound_unregister(void)
+{
+ tcp_unregister_congestion_control(&tcp_compound);
+}
+
+module_init(tcp_compound_register);
+module_exit(tcp_compound_unregister);
+
+MODULE_AUTHOR("Angelo P. Castellani, Stephen Hemminger");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Compound");
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 91c2f41..857eefc 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -38,7 +38,7 @@ int tcp_register_congestion_control(stru
int ret = 0;
/* all algorithms must implement ssthresh and cong_avoid ops */
- if (!ca->ssthresh || !ca->cong_avoid || !ca->min_cwnd) {
+ if (!ca->ssthresh || !ca->cong_avoid) {
printk(KERN_ERR "TCP %s does not implement required ops\n",
ca->name);
return -EINVAL;
@@ -251,8 +251,8 @@ u32 tcp_reno_ssthresh(struct sock *sk)
}
EXPORT_SYMBOL_GPL(tcp_reno_ssthresh);
-/* Lower bound on congestion window. */
-u32 tcp_reno_min_cwnd(struct sock *sk)
+/* Lower bound on congestion window with halving. */
+u32 tcp_reno_min_cwnd(const struct sock *sk)
{
const struct tcp_sock *tp = tcp_sk(sk);
return tp->snd_ssthresh/2;
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
index 31a4986..78b7a6b 100644
--- a/net/ipv4/tcp_cubic.c
+++ b/net/ipv4/tcp_cubic.c
@@ -325,11 +325,6 @@ static u32 bictcp_undo_cwnd(struct sock
return max(tcp_sk(sk)->snd_cwnd, ca->last_max_cwnd);
}
-static u32 bictcp_min_cwnd(struct sock *sk)
-{
- return tcp_sk(sk)->snd_ssthresh;
-}
-
static void bictcp_state(struct sock *sk, u8 new_state)
{
if (new_state == TCP_CA_Loss)
@@ -357,7 +352,6 @@ static struct tcp_congestion_ops cubictc
.cong_avoid = bictcp_cong_avoid,
.set_state = bictcp_state,
.undo_cwnd = bictcp_undo_cwnd,
- .min_cwnd = bictcp_min_cwnd,
.pkts_acked = bictcp_acked,
.owner = THIS_MODULE,
.name = "cubic",
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c
index ba7c63c..1120245 100644
--- a/net/ipv4/tcp_highspeed.c
+++ b/net/ipv4/tcp_highspeed.c
@@ -98,6 +98,10 @@ struct hstcp {
u32 ai;
};
+static int max_ssthresh = 100;
+module_param(max_ssthresh, int, 0644);
+MODULE_PARM_DESC(max_ssthresh, "limited slow start threshold (RFC3742)");
+
static void hstcp_init(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
@@ -119,9 +123,23 @@ static void hstcp_cong_avoid(struct sock
if (!tcp_is_cwnd_limited(sk, in_flight))
return;
- if (tp->snd_cwnd <= tp->snd_ssthresh)
- tcp_slow_start(tp);
- else {
+ if (tp->snd_cwnd <= tp->snd_ssthresh) {
+ /* RFC3742: limited slow start
+ * the window is increased by 1/K MSS for each arriving ACK,
+ * for K = int(cwnd/(0.5 max_ssthresh))
+ */
+ if (max_ssthresh > 0 && tp->snd_cwnd > max_ssthresh) {
+ u32 k = max(tp->snd_cwnd / (max_ssthresh >> 1), 1U);
+ if (++tp->snd_cwnd_cnt >= k) {
+ if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ tp->snd_cwnd++;
+ tp->snd_cwnd_cnt = 0;
+ }
+ } else {
+ if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ tp->snd_cwnd++;
+ }
+ } else {
/* Update AIMD parameters */
if (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd) {
while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd &&
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c
index 1b2ff53..3d92c18 100644
--- a/net/ipv4/tcp_htcp.c
+++ b/net/ipv4/tcp_htcp.c
@@ -246,14 +246,6 @@ static void htcp_cong_avoid(struct sock
}
}
-/* Lower bound on congestion window. */
-static u32 htcp_min_cwnd(struct sock *sk)
-{
- const struct tcp_sock *tp = tcp_sk(sk);
- return tp->snd_ssthresh;
-}
-
-
static void htcp_init(struct sock *sk)
{
struct htcp *ca = inet_csk_ca(sk);
@@ -285,7 +277,6 @@ static void htcp_state(struct sock *sk,
static struct tcp_congestion_ops htcp = {
.init = htcp_init,
.ssthresh = htcp_recalc_ssthresh,
- .min_cwnd = htcp_min_cwnd,
.cong_avoid = htcp_cong_avoid,
.set_state = htcp_state,
.undo_cwnd = htcp_cwnd_undo,
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 4a538bc..718d0f2 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1690,17 +1690,26 @@ static inline void tcp_moderate_cwnd(str
tp->snd_cwnd_stamp = tcp_time_stamp;
}
+/* Lower bound on congestion window is slow start threshold
+ * unless congestion avoidance choice decides to overide it.
+ */
+static inline u32 tcp_cwnd_min(const struct sock *sk)
+{
+ const struct tcp_congestion_ops *ca_ops = inet_csk(sk)->icsk_ca_ops;
+
+ return ca_ops->min_cwnd ? ca_ops->min_cwnd(sk) : tcp_sk(sk)->snd_ssthresh;
+}
+
/* Decrease cwnd each second ack. */
static void tcp_cwnd_down(struct sock *sk)
{
- const struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
int decr = tp->snd_cwnd_cnt + 1;
tp->snd_cwnd_cnt = decr&1;
decr >>= 1;
- if (decr && tp->snd_cwnd > icsk->icsk_ca_ops->min_cwnd(sk))
+ if (decr && tp->snd_cwnd > tcp_cwnd_min(sk))
tp->snd_cwnd -= decr;
tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1);
diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c
new file mode 100644
index 0000000..1f977b6
--- /dev/null
+++ b/net/ipv4/tcp_lp.c
@@ -0,0 +1,338 @@
+/*
+ * TCP Low Priority (TCP-LP)
+ *
+ * TCP Low Priority is a distributed algorithm whose goal is to utilize only
+ * the excess network bandwidth as compared to the ``fair share`` of
+ * bandwidth as targeted by TCP. Available from:
+ * http://www.ece.rice.edu/~akuzma/Doc/akuzma/TCP-LP.pdf
+ *
+ * Original Author:
+ * Aleksandar Kuzmanovic <akuzma@northwestern.edu>
+ *
+ * See http://www-ece.rice.edu/networks/TCP-LP/ for their implementation.
+ * As of 2.6.13, Linux supports pluggable congestion control algorithms.
+ * Due to the limitation of the API, we take the following changes from
+ * the original TCP-LP implementation:
+ * o We use newReno in most core CA handling. Only add some checking
+ * within cong_avoid.
+ * o Error correcting in remote HZ, therefore remote HZ will be keeped
+ * on checking and updating.
+ * o Handling calculation of One-Way-Delay (OWD) within rtt_sample, sicne
+ * OWD have a similar meaning as RTT. Also correct the buggy formular.
+ * o Handle reaction for Early Congestion Indication (ECI) within
+ * pkts_acked, as mentioned within pseudo code.
+ * o OWD is handled in relative format, where local time stamp will in
+ * tcp_time_stamp format.
+ *
+ * Port from 2.4.19 to 2.6.16 as module by:
+ * Wong Hoi Sing Edison <hswong3i@gmail.com>
+ * Hung Hing Lun <hlhung3i@gmail.com>
+ *
+ * Version: $Id: tcp_lp.c,v 1.22 2006-05-02 18:18:19 hswong3i Exp $
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <net/tcp.h>
+
+/* resolution of owd */
+#define LP_RESOL 1000
+
+/**
+ * enum tcp_lp_state
+ * @LP_VALID_RHZ: is remote HZ valid?
+ * @LP_VALID_OWD: is OWD valid?
+ * @LP_WITHIN_THR: are we within threshold?
+ * @LP_WITHIN_INF: are we within inference?
+ *
+ * TCP-LP's state flags.
+ * We create this set of state flag mainly for debugging.
+ */
+enum tcp_lp_state {
+ LP_VALID_RHZ = (1 << 0),
+ LP_VALID_OWD = (1 << 1),
+ LP_WITHIN_THR = (1 << 3),
+ LP_WITHIN_INF = (1 << 4),
+};
+
+/**
+ * struct lp
+ * @flag: TCP-LP state flag
+ * @sowd: smoothed OWD << 3
+ * @owd_min: min OWD
+ * @owd_max: max OWD
+ * @owd_max_rsv: resrved max owd
+ * @remote_hz: estimated remote HZ
+ * @remote_ref_time: remote reference time
+ * @local_ref_time: local reference time
+ * @last_drop: time for last active drop
+ * @inference: current inference
+ *
+ * TCP-LP's private struct.
+ * We get the idea from original TCP-LP implementation where only left those we
+ * found are really useful.
+ */
+struct lp {
+ u32 flag;
+ u32 sowd;
+ u32 owd_min;
+ u32 owd_max;
+ u32 owd_max_rsv;
+ u32 remote_hz;
+ u32 remote_ref_time;
+ u32 local_ref_time;
+ u32 last_drop;
+ u32 inference;
+};
+
+/**
+ * tcp_lp_init
+ *
+ * Init all required variables.
+ * Clone the handling from Vegas module implementation.
+ */
+static void tcp_lp_init(struct sock *sk)
+{
+ struct lp *lp = inet_csk_ca(sk);
+
+ lp->flag = 0;
+ lp->sowd = 0;
+ lp->owd_min = 0xffffffff;
+ lp->owd_max = 0;
+ lp->owd_max_rsv = 0;
+ lp->remote_hz = 0;
+ lp->remote_ref_time = 0;
+ lp->local_ref_time = 0;
+ lp->last_drop = 0;
+ lp->inference = 0;
+}
+
+/**
+ * tcp_lp_cong_avoid
+ *
+ * Implementation of cong_avoid.
+ * Will only call newReno CA when away from inference.
+ * From TCP-LP's paper, this will be handled in additive increasement.
+ */
+static void tcp_lp_cong_avoid(struct sock *sk, u32 ack, u32 rtt, u32 in_flight,
+ int flag)
+{
+ struct lp *lp = inet_csk_ca(sk);
+
+ if (!(lp->flag & LP_WITHIN_INF))
+ tcp_reno_cong_avoid(sk, ack, rtt, in_flight, flag);
+}
+
+/**
+ * tcp_lp_remote_hz_estimator
+ *
+ * Estimate remote HZ.
+ * We keep on updating the estimated value, where original TCP-LP
+ * implementation only guest it for once and use forever.
+ */
+static u32 tcp_lp_remote_hz_estimator(struct sock *sk)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct lp *lp = inet_csk_ca(sk);
+ s64 rhz = lp->remote_hz << 6; /* remote HZ << 6 */
+ s64 m = 0;
+
+ /* not yet record reference time
+ * go away!! record it before come back!! */
+ if (lp->remote_ref_time == 0 || lp->local_ref_time == 0)
+ goto out;
+
+ /* we can't calc remote HZ with no different!! */
+ if (tp->rx_opt.rcv_tsval == lp->remote_ref_time
+ || tp->rx_opt.rcv_tsecr == lp->local_ref_time)
+ goto out;
+
+ m = HZ * (tp->rx_opt.rcv_tsval -
+ lp->remote_ref_time) / (tp->rx_opt.rcv_tsecr -
+ lp->local_ref_time);
+ if (m < 0)
+ m = -m;
+
+ if (rhz != 0) {
+ m -= rhz >> 6; /* m is now error in remote HZ est */
+ rhz += m; /* 63/64 old + 1/64 new */
+ } else
+ rhz = m << 6;
+
+ /* record time for successful remote HZ calc */
+ lp->flag |= LP_VALID_RHZ;
+
+ out:
+ /* record reference time stamp */
+ lp->remote_ref_time = tp->rx_opt.rcv_tsval;
+ lp->local_ref_time = tp->rx_opt.rcv_tsecr;
+
+ return rhz >> 6;
+}
+
+/**
+ * tcp_lp_owd_calculator
+ *
+ * Calculate one way delay (in relative format).
+ * Original implement OWD as minus of remote time difference to local time
+ * difference directly. As this time difference just simply equal to RTT, when
+ * the network status is stable, remote RTT will equal to local RTT, and result
+ * OWD into zero.
+ * It seems to be a bug and so we fixed it.
+ */
+static u32 tcp_lp_owd_calculator(struct sock *sk)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct lp *lp = inet_csk_ca(sk);
+ s64 owd = 0;
+
+ lp->remote_hz = tcp_lp_remote_hz_estimator(sk);
+
+ if (lp->flag & LP_VALID_RHZ) {
+ owd =
+ tp->rx_opt.rcv_tsval * (LP_RESOL / lp->remote_hz) -
+ tp->rx_opt.rcv_tsecr * (LP_RESOL / HZ);
+ if (owd < 0)
+ owd = -owd;
+ }
+
+ if (owd > 0)
+ lp->flag |= LP_VALID_OWD;
+ else
+ lp->flag &= ~LP_VALID_OWD;
+
+ return owd;
+}
+
+/**
+ * tcp_lp_rtt_sample
+ *
+ * Implementation or rtt_sample.
+ * Will take the following action,
+ * 1. calc OWD,
+ * 2. record the min/max OWD,
+ * 3. calc smoothed OWD (SOWD).
+ * Most ideas come from the original TCP-LP implementation.
+ */
+static void tcp_lp_rtt_sample(struct sock *sk, u32 usrtt)
+{
+ struct lp *lp = inet_csk_ca(sk);
+ s64 mowd = tcp_lp_owd_calculator(sk);
+
+ /* sorry that we don't have valid data */
+ if (!(lp->flag & LP_VALID_RHZ) || !(lp->flag & LP_VALID_OWD))
+ return;
+
+ /* record the next min owd */
+ if (mowd < lp->owd_min)
+ lp->owd_min = mowd;
+
+ /* always forget the max of the max
+ * we just set owd_max as one below it */
+ if (mowd > lp->owd_max) {
+ if (mowd > lp->owd_max_rsv) {
+ if (lp->owd_max_rsv == 0)
+ lp->owd_max = mowd;
+ else
+ lp->owd_max = lp->owd_max_rsv;
+ lp->owd_max_rsv = mowd;
+ } else
+ lp->owd_max = mowd;
+ }
+
+ /* calc for smoothed owd */
+ if (lp->sowd != 0) {
+ mowd -= lp->sowd >> 3; /* m is now error in owd est */
+ lp->sowd += mowd; /* owd = 7/8 owd + 1/8 new */
+ } else
+ lp->sowd = mowd << 3; /* take the measured time be owd */
+}
+
+/**
+ * tcp_lp_pkts_acked
+ *
+ * Implementation of pkts_acked.
+ * Deal with active drop under Early Congestion Indication.
+ * Only drop to half and 1 will be handle, because we hope to use back
+ * newReno in increase case.
+ * We work it out by following the idea from TCP-LP's paper directly
+ */
+static void tcp_lp_pkts_acked(struct sock *sk, u32 num_acked)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct lp *lp = inet_csk_ca(sk);
+
+ /* calc inference */
+ if (tcp_time_stamp > tp->rx_opt.rcv_tsecr)
+ lp->inference = 3 * (tcp_time_stamp - tp->rx_opt.rcv_tsecr);
+
+ /* test if within inference */
+ if (lp->last_drop && (tcp_time_stamp - lp->last_drop < lp->inference))
+ lp->flag |= LP_WITHIN_INF;
+ else
+ lp->flag &= ~LP_WITHIN_INF;
+
+ /* test if within threshold */
+ if (lp->sowd >> 3 <
+ lp->owd_min + 15 * (lp->owd_max - lp->owd_min) / 100)
+ lp->flag |= LP_WITHIN_THR;
+ else
+ lp->flag &= ~LP_WITHIN_THR;
+
+ pr_debug("TCP-LP: %05o|%5u|%5u|%15u|%15u|%15u\n", lp->flag,
+ tp->snd_cwnd, lp->remote_hz, lp->owd_min, lp->owd_max,
+ lp->sowd >> 3);
+
+ if (lp->flag & LP_WITHIN_THR)
+ return;
+
+ /* FIXME: try to reset owd_min and owd_max here
+ * so decrease the chance the min/max is no longer suitable
+ * and will usually within threshold when whithin inference */
+ lp->owd_min = lp->sowd >> 3;
+ lp->owd_max = lp->sowd >> 2;
+ lp->owd_max_rsv = lp->sowd >> 2;
+
+ /* happened within inference
+ * drop snd_cwnd into 1 */
+ if (lp->flag & LP_WITHIN_INF)
+ tp->snd_cwnd = 1U;
+
+ /* happened after inference
+ * cut snd_cwnd into half */
+ else
+ tp->snd_cwnd = max(tp->snd_cwnd >> 1U, 1U);
+
+ /* record this drop time */
+ lp->last_drop = tcp_time_stamp;
+}
+
+static struct tcp_congestion_ops tcp_lp = {
+ .init = tcp_lp_init,
+ .ssthresh = tcp_reno_ssthresh,
+ .cong_avoid = tcp_lp_cong_avoid,
+ .min_cwnd = tcp_reno_min_cwnd,
+ .rtt_sample = tcp_lp_rtt_sample,
+ .pkts_acked = tcp_lp_pkts_acked,
+
+ .owner = THIS_MODULE,
+ .name = "lp"
+};
+
+static int __init tcp_lp_register(void)
+{
+ BUG_ON(sizeof(struct lp) > ICSK_CA_PRIV_SIZE);
+ return tcp_register_congestion_control(&tcp_lp);
+}
+
+static void __exit tcp_lp_unregister(void)
+{
+ tcp_unregister_congestion_control(&tcp_lp);
+}
+
+module_init(tcp_lp_register);
+module_exit(tcp_lp_unregister);
+
+MODULE_AUTHOR("Wong Hoi Sing Edison, Hung Hing Lun");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Low Priority");
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
new file mode 100644
index 0000000..be94d52
--- /dev/null
+++ b/net/ipv4/tcp_probe.c
@@ -0,0 +1,179 @@
+/*
+ * tcpprobe - Observe the TCP flow with kprobes.
+ *
+ * The idea for this came from Werner Almesberger's umlsim
+ * Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+#include <linux/socket.h>
+#include <linux/tcp.h>
+#include <linux/proc_fs.h>
+#include <linux/module.h>
+#include <linux/kfifo.h>
+#include <linux/vmalloc.h>
+
+#include <net/tcp.h>
+
+MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_DESCRIPTION("TCP cwnd snooper");
+MODULE_LICENSE("GPL");
+
+static int port = 0;
+MODULE_PARM_DESC(port, "Port to match (0=all)");
+module_param(port, int, 0);
+
+static int bufsize = 64*1024;
+MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)");
+module_param(bufsize, int, 0);
+
+static const char procname[] = "tcpprobe";
+
+struct {
+ struct kfifo *fifo;
+ spinlock_t lock;
+ wait_queue_head_t wait;
+ struct timeval tstart;
+} tcpw;
+
+static void printl(const char *fmt, ...)
+{
+ va_list args;
+ int len;
+ struct timeval now;
+ char tbuf[256];
+
+ va_start(args, fmt);
+ do_gettimeofday(&now);
+
+ now.tv_sec -= tcpw.tstart.tv_sec;
+ now.tv_usec -= tcpw.tstart.tv_usec;
+ if (now.tv_usec < 0) {
+ --now.tv_sec;
+ now.tv_usec += 1000000;
+ }
+
+ len = sprintf(tbuf, "%lu.%06lu ", now.tv_sec, now.tv_usec);
+ len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args);
+ va_end(args);
+
+ kfifo_put(tcpw.fifo, tbuf, len);
+ wake_up(&tcpw.wait);
+}
+
+static int jtcp_sendmsg(struct kiocb *iocb, struct sock *sk,
+ struct msghdr *msg, size_t size)
+{
+ const struct tcp_sock *tp = tcp_sk(sk);
+ const struct inet_sock *inet = inet_sk(sk);
+
+ if (port == 0 || ntohs(inet->dport) == port ||
+ ntohs(inet->sport) == port) {
+ printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d %#x %#x %u %u %u\n",
+ NIPQUAD(inet->saddr), ntohs(inet->sport),
+ NIPQUAD(inet->daddr), ntohs(inet->dport),
+ size, tp->snd_nxt, tp->snd_una,
+ tp->snd_cwnd, tcp_current_ssthresh(sk),
+ tp->snd_wnd);
+ }
+
+ jprobe_return();
+ return 0;
+}
+
+static struct jprobe tcp_send_probe = {
+ .kp = { .addr = (kprobe_opcode_t *) &tcp_sendmsg, },
+ .entry = (kprobe_opcode_t *) &jtcp_sendmsg,
+};
+
+
+static int tcpprobe_open(struct inode * inode, struct file * file)
+{
+ kfifo_reset(tcpw.fifo);
+ do_gettimeofday(&tcpw.tstart);
+ return 0;
+}
+
+static ssize_t tcpprobe_read(struct file *file, char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ int error = 0, cnt;
+ unsigned char *tbuf;
+
+ if (!buf || len < 0)
+ return -EINVAL;
+
+ if (len == 0)
+ return 0;
+
+ tbuf = vmalloc(len);
+ if (!tbuf)
+ return -ENOMEM;
+
+ error = wait_event_interruptible(tcpw.wait,
+ __kfifo_len(tcpw.fifo) != 0);
+ if (error)
+ return error;
+
+ cnt = kfifo_get(tcpw.fifo, tbuf, len);
+ error = copy_to_user(buf, tbuf, cnt);
+
+ vfree(tbuf);
+
+ return error ? error : cnt;
+}
+
+static struct file_operations tcpprobe_fops = {
+ .owner = THIS_MODULE,
+ .open = tcpprobe_open,
+ .read = tcpprobe_read,
+};
+
+static __init int tcpprobe_init(void)
+{
+ int ret = -ENOMEM;
+
+ init_waitqueue_head(&tcpw.wait);
+ spin_lock_init(&tcpw.lock);
+ tcpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &tcpw.lock);
+
+ if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops))
+ goto err0;
+
+ ret = register_jprobe(&tcp_send_probe);
+ if (ret)
+ goto err1;
+
+ pr_info("TCP watch registered (port=%d)\n", port);
+ return 0;
+ err1:
+ proc_net_remove(procname);
+ err0:
+ kfifo_free(tcpw.fifo);
+ return ret;
+}
+module_init(tcpprobe_init);
+
+static __exit void tcpprobe_exit(void)
+{
+ kfifo_free(tcpw.fifo);
+ proc_net_remove(procname);
+ unregister_jprobe(&tcp_send_probe);
+
+}
+module_exit(tcpprobe_exit);
diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c
new file mode 100644
index 0000000..11b42a7
--- /dev/null
+++ b/net/ipv4/tcp_veno.c
@@ -0,0 +1,231 @@
+/*
+ * TCP Veno congestion control
+ *
+ * This is based on the congestion detection/avoidance scheme described in
+ * C. P. Fu, S. C. Liew.
+ * "TCP Veno: TCP Enhancement for Transmission over Wireless Access Networks."
+ * IEEE Journal on Selected Areas in Communication,
+ * Feb. 2003.
+ * See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/inet_diag.h>
+
+#include <net/tcp.h>
+
+/* Default values of the Veno variables, in fixed-point representation
+ * with V_PARAM_SHIFT bits to the right of the binary point.
+ */
+#define V_PARAM_SHIFT 1
+static const int beta = 3 << V_PARAM_SHIFT;
+
+/* Veno variables */
+struct veno {
+ u8 doing_veno_now; /* if true, do veno for this rtt */
+ u16 cntrtt; /* # of rtts measured within last rtt */
+ u32 minrtt; /* min of rtts measured within last rtt (in usec) */
+ u32 basertt; /* the min of all Veno rtt measurements seen (in usec) */
+ u32 inc; /* decide whether to increase cwnd */
+ u32 diff; /* calculate the diff rate */
+};
+
+/* There are several situations when we must "re-start" Veno:
+ *
+ * o when a connection is established
+ * o after an RTO
+ * o after fast recovery
+ * o when we send a packet and there is no outstanding
+ * unacknowledged data (restarting an idle connection)
+ *
+ */
+static inline void veno_enable(struct sock *sk)
+{
+ struct veno *veno = inet_csk_ca(sk);
+
+ /* turn on Veno */
+ veno->doing_veno_now = 1;
+
+ veno->minrtt = 0x7fffffff;
+}
+
+static inline void veno_disable(struct sock *sk)
+{
+ struct veno *veno = inet_csk_ca(sk);
+
+ /* turn off Veno */
+ veno->doing_veno_now = 0;
+}
+
+static void tcp_veno_init(struct sock *sk)
+{
+ struct veno *veno = inet_csk_ca(sk);
+
+ veno->basertt = 0x7fffffff;
+ veno->inc = 1;
+ veno_enable(sk);
+}
+
+/* Do rtt sampling needed for Veno. */
+static void tcp_veno_rtt_calc(struct sock *sk, u32 usrtt)
+{
+ struct veno *veno = inet_csk_ca(sk);
+ u32 vrtt = usrtt + 1; /* Never allow zero rtt or basertt */
+
+ /* Filter to find propagation delay: */
+ if (vrtt < veno->basertt)
+ veno->basertt = vrtt;
+
+ /* Find the min rtt during the last rtt to find
+ * the current prop. delay + queuing delay:
+ */
+ veno->minrtt = min(veno->minrtt, vrtt);
+ veno->cntrtt++;
+}
+
+static void tcp_veno_state(struct sock *sk, u8 ca_state)
+{
+ if (ca_state == TCP_CA_Open)
+ veno_enable(sk);
+ else
+ veno_disable(sk);
+}
+
+/*
+ * If the connection is idle and we are restarting,
+ * then we don't want to do any Veno calculations
+ * until we get fresh rtt samples. So when we
+ * restart, we reset our Veno state to a clean
+ * state. After we get acks for this flight of
+ * packets, _then_ we can make Veno calculations
+ * again.
+ */
+static void tcp_veno_cwnd_event(struct sock *sk, enum tcp_ca_event event)
+{
+ if (event == CA_EVENT_CWND_RESTART || event == CA_EVENT_TX_START)
+ tcp_veno_init(sk);
+}
+
+static void tcp_veno_cong_avoid(struct sock *sk, u32 ack,
+ u32 seq_rtt, u32 in_flight, int flag)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct veno *veno = inet_csk_ca(sk);
+
+ if (!veno->doing_veno_now)
+ return tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag);
+
+ /* limited by applications */
+ if (!tcp_is_cwnd_limited(sk, in_flight))
+ return;
+
+ /* We do the Veno calculations only if we got enough rtt samples */
+ if (veno->cntrtt <= 2) {
+ /* We don't have enough rtt samples to do the Veno
+ * calculation, so we'll behave like Reno.
+ */
+ tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag);
+ } else {
+ u32 rtt, target_cwnd;
+
+ /* We have enough rtt samples, so, using the Veno
+ * algorithm, we determine the state of the network.
+ */
+
+ rtt = veno->minrtt;
+
+ target_cwnd = ((tp->snd_cwnd * veno->basertt)
+ << V_PARAM_SHIFT) / rtt;
+
+ veno->diff = (tp->snd_cwnd << V_PARAM_SHIFT) - target_cwnd;
+
+ if (tp->snd_cwnd <= tp->snd_ssthresh) {
+ /* Slow start. */
+ tcp_slow_start(tp);
+ } else {
+ /* Congestion avoidance. */
+ if (veno->diff < beta) {
+ /* In the "non-congestive state", increase cwnd
+ * every rtt.
+ */
+ if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+ if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ tp->snd_cwnd++;
+ tp->snd_cwnd_cnt = 0;
+ } else
+ tp->snd_cwnd_cnt++;
+ } else {
+ /* In the "congestive state", increase cwnd
+ * every other rtt.
+ */
+ if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+ if (veno->inc
+ && tp->snd_cwnd <
+ tp->snd_cwnd_clamp) {
+ tp->snd_cwnd++;
+ veno->inc = 0;
+ } else
+ veno->inc = 1;
+ tp->snd_cwnd_cnt = 0;
+ } else
+ tp->snd_cwnd_cnt++;
+ }
+
+ }
+ if (tp->snd_cwnd < 2)
+ tp->snd_cwnd = 2;
+ else if (tp->snd_cwnd > tp->snd_cwnd_clamp)
+ tp->snd_cwnd = tp->snd_cwnd_clamp;
+ }
+ /* Wipe the slate clean for the next rtt. */
+ /* veno->cntrtt = 0; */
+ veno->minrtt = 0x7fffffff;
+}
+
+/* Veno MD phase */
+static u32 tcp_veno_ssthresh(struct sock *sk)
+{
+ const struct tcp_sock *tp = tcp_sk(sk);
+ struct veno *veno = inet_csk_ca(sk);
+
+ if (veno->diff < beta)
+ /* in "non-congestive state", cut cwnd by 1/5 */
+ return max(tp->snd_cwnd * 4 / 5, 2U);
+ else
+ /* in "congestive state", cut cwnd by 1/2 */
+ return max(tp->snd_cwnd >> 1U, 2U);
+}
+
+static struct tcp_congestion_ops tcp_veno = {
+ .init = tcp_veno_init,
+ .ssthresh = tcp_veno_ssthresh,
+ .cong_avoid = tcp_veno_cong_avoid,
+ .rtt_sample = tcp_veno_rtt_calc,
+ .set_state = tcp_veno_state,
+ .cwnd_event = tcp_veno_cwnd_event,
+
+ .owner = THIS_MODULE,
+ .name = "veno",
+};
+
+static int __init tcp_veno_register(void)
+{
+ BUG_ON(sizeof(struct veno) > ICSK_CA_PRIV_SIZE);
+ tcp_register_congestion_control(&tcp_veno);
+ return 0;
+}
+
+static void __exit tcp_veno_unregister(void)
+{
+ tcp_unregister_congestion_control(&tcp_veno);
+}
+
+module_init(tcp_veno_register);
+module_exit(tcp_veno_unregister);
+
+MODULE_AUTHOR("Bin Zhou, Cheng Peng Fu");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Veno");
diff --git a/net/ipv4/tcp_westwood.c b/net/ipv4/tcp_westwood.c
index 0c340c3..29eb258 100644
--- a/net/ipv4/tcp_westwood.c
+++ b/net/ipv4/tcp_westwood.c
@@ -162,12 +162,6 @@ static inline u32 westwood_acked_count(s
return w->cumul_ack;
}
-static inline u32 westwood_bw_rttmin(const struct sock *sk)
-{
- const struct tcp_sock *tp = tcp_sk(sk);
- const struct westwood *w = inet_csk_ca(sk);
- return max_t(u32, (w->bw_est * w->rtt_min) / tp->mss_cache, 2);
-}
/*
* TCP Westwood
@@ -175,9 +169,11 @@ static inline u32 westwood_bw_rttmin(con
* in packets we use mss_cache). Rttmin is guaranteed to be >= 2
* so avoids ever returning 0.
*/
-static u32 tcp_westwood_cwnd_min(struct sock *sk)
+static u32 tcp_westwood_bw_rttmin(const struct sock *sk)
{
- return westwood_bw_rttmin(sk);
+ const struct tcp_sock *tp = tcp_sk(sk);
+ const struct westwood *w = inet_csk_ca(sk);
+ return max_t(u32, (w->bw_est * w->rtt_min) / tp->mss_cache, 2);
}
static void tcp_westwood_event(struct sock *sk, enum tcp_ca_event event)
@@ -191,11 +187,11 @@ static void tcp_westwood_event(struct so
break;
case CA_EVENT_COMPLETE_CWR:
- tp->snd_cwnd = tp->snd_ssthresh = westwood_bw_rttmin(sk);
+ tp->snd_cwnd = tp->snd_ssthresh = tcp_westwood_bw_rttmin(sk);
break;
case CA_EVENT_FRTO:
- tp->snd_ssthresh = westwood_bw_rttmin(sk);
+ tp->snd_ssthresh = tcp_westwood_bw_rttmin(sk);
break;
case CA_EVENT_SLOW_ACK:
@@ -235,7 +231,7 @@ static struct tcp_congestion_ops tcp_wes
.init = tcp_westwood_init,
.ssthresh = tcp_reno_ssthresh,
.cong_avoid = tcp_reno_cong_avoid,
- .min_cwnd = tcp_westwood_cwnd_min,
+ .min_cwnd = tcp_westwood_bw_rttmin,
.cwnd_event = tcp_westwood_event,
.get_info = tcp_westwood_info,
.pkts_acked = tcp_westwood_pkts_acked,
^ permalink raw reply related
* [PATCH 1/2] bcm43xx: redesign locking
From: Michael Buesch @ 2006-06-05 18:24 UTC (permalink / raw)
To: John W. Linville; +Cc: netdev, bcm43xx-dev, Jason Lunz, Jory A. Pratt
John, please queue for 2.6.18.
--
Redesign the bcm43xx locking.
This is pre-work to get a preemptible periodic work handler.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx.h
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx.h 2006-06-03 21:04:17.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx.h 2006-06-05 18:19:59.000000000 +0200
@@ -636,6 +636,17 @@
u8 algorithm;
};
+/* Driver initialization status. */
+enum {
+ BCM43xx_STAT_UNINIT, /* Uninitialized. */
+ BCM43xx_STAT_INITIALIZING, /* init_board() in progress. */
+ BCM43xx_STAT_INITIALIZED, /* Fully operational. */
+ BCM43xx_STAT_SHUTTINGDOWN, /* free_board() in progress. */
+ BCM43xx_STAT_RESTARTING, /* controller_restart() called. */
+};
+#define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status)
+#define bcm43xx_set_status(bcm, stat) atomic_set(&(bcm)->init_status, (stat))
+
struct bcm43xx_private {
struct ieee80211_device *ieee;
struct ieee80211softmac_device *softmac;
@@ -647,18 +658,17 @@
void __iomem *mmio_addr;
unsigned int mmio_len;
- /* Do not use the lock directly. Use the bcm43xx_lock* helper
- * functions, to be MMIO-safe. */
- spinlock_t _lock;
-
- /* Driver status flags. */
- u32 initialized:1, /* init_board() succeed */
- was_initialized:1, /* for PCI suspend/resume. */
- shutting_down:1, /* free_board() in progress */
+ /* Locking, see "theory of locking" text below. */
+ spinlock_t irq_lock;
+ struct mutex mutex;
+
+ /* Driver initialization status BCM43xx_STAT_*** */
+ atomic_t init_status;
+
+ u16 was_initialized:1, /* for PCI suspend/resume. */
__using_pio:1, /* Internal, use bcm43xx_using_pio(). */
bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */
reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */
- powersaving:1, /* TRUE if we are in PowerSaving mode. FALSE otherwise. */
short_preamble:1, /* TRUE, if short preamble is enabled. */
firmware_norelease:1; /* Do not release the firmware. Used on suspend. */
@@ -722,7 +732,7 @@
struct tasklet_struct isr_tasklet;
/* Periodic tasks */
- struct timer_list periodic_tasks;
+ struct work_struct periodic_work;
unsigned int periodic_state;
struct work_struct restart_work;
@@ -747,21 +757,55 @@
#endif
};
-/* bcm43xx_(un)lock() protect struct bcm43xx_private.
- * Note that _NO_ MMIO writes are allowed. If you want to
- * write to the device through MMIO in the critical section, use
- * the *_mmio lock functions.
- * MMIO read-access is allowed, though.
- */
-#define bcm43xx_lock(bcm, flags) spin_lock_irqsave(&(bcm)->_lock, flags)
-#define bcm43xx_unlock(bcm, flags) spin_unlock_irqrestore(&(bcm)->_lock, flags)
-/* bcm43xx_(un)lock_mmio() protect struct bcm43xx_private and MMIO.
- * MMIO write-access to the device is allowed.
- * All MMIO writes are flushed on unlock, so it is guaranteed to not
- * interfere with other threads writing MMIO registers.
+
+/* *** THEORY OF LOCKING ***
+ *
+ * We have two different locks in the bcm43xx driver.
+ * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private
+ * and the device registers.
+ * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
+ *
+ * We have three types of helper function pairs to utilize these locks.
+ * (Always use the helper functions.)
+ * 1) bcm43xx_{un}lock_noirq():
+ * Takes bcm->mutex. Does _not_ protect against IRQ concurrency,
+ * so it is almost always unsafe, if device IRQs are enabled.
+ * So only use this, if device IRQs are masked.
+ * Locking may sleep.
+ * You can sleep within the critical section.
+ * 2) bcm43xx_{un}lock_irqonly():
+ * Takes bcm->irq_lock. Does _not_ protect against
+ * bcm43xx_lock_noirq() critical sections.
+ * Does only protect against the IRQ handler path and other
+ * irqonly() critical sections.
+ * Locking does not sleep.
+ * You must not sleep within the critical section.
+ * 3) bcm43xx_{un}lock_irqsafe():
+ * This is the cummulative lock and takes both, mutex and irq_lock.
+ * Protects against noirq() and irqonly() critical sections (and
+ * the IRQ handler path).
+ * Locking may sleep.
+ * You must not sleep within the critical section.
*/
-#define bcm43xx_lock_mmio(bcm, flags) bcm43xx_lock(bcm, flags)
-#define bcm43xx_unlock_mmio(bcm, flags) do { mmiowb(); bcm43xx_unlock(bcm, flags); } while (0)
+
+/* Lock type 1 */
+#define bcm43xx_lock_noirq(bcm) mutex_lock(&(bcm)->mutex)
+#define bcm43xx_unlock_noirq(bcm) mutex_unlock(&(bcm)->mutex)
+/* Lock type 2 */
+#define bcm43xx_lock_irqonly(bcm, flags) \
+ spin_lock_irqsave(&(bcm)->irq_lock, flags)
+#define bcm43xx_unlock_irqonly(bcm, flags) \
+ spin_unlock_irqrestore(&(bcm)->irq_lock, flags)
+/* Lock type 3 */
+#define bcm43xx_lock_irqsafe(bcm, flags) do { \
+ bcm43xx_lock_noirq(bcm); \
+ bcm43xx_lock_irqonly(bcm, flags); \
+ } while (0)
+#define bcm43xx_unlock_irqsafe(bcm, flags) do { \
+ bcm43xx_unlock_irqonly(bcm, flags); \
+ bcm43xx_unlock_noirq(bcm); \
+ } while (0)
+
static inline
struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
@@ -844,16 +888,6 @@
return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio);
}
-/* Are we running in init_board() context? */
-static inline
-int bcm43xx_is_initializing(struct bcm43xx_private *bcm)
-{
- if (bcm->initialized)
- return 0;
- if (bcm->shutting_down)
- return 0;
- return 1;
-}
static inline
struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy,
Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c 2006-04-28 16:13:40.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c 2006-06-05 18:31:30.000000000 +0200
@@ -77,8 +77,8 @@
down(&big_buffer_sem);
- bcm43xx_lock_mmio(bcm, flags);
- if (!bcm->initialized) {
+ bcm43xx_lock_irqsafe(bcm, flags);
+ if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
fappend("Board not initialized.\n");
goto out;
}
@@ -121,7 +121,7 @@
fappend("\n");
out:
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
up(&big_buffer_sem);
return res;
@@ -159,8 +159,8 @@
unsigned long flags;
down(&big_buffer_sem);
- bcm43xx_lock_mmio(bcm, flags);
- if (!bcm->initialized) {
+ bcm43xx_lock_irqsafe(bcm, flags);
+ if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
fappend("Board not initialized.\n");
goto out;
}
@@ -169,7 +169,7 @@
fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
out:
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
up(&big_buffer_sem);
return res;
@@ -188,8 +188,8 @@
u64 tsf;
down(&big_buffer_sem);
- bcm43xx_lock_mmio(bcm, flags);
- if (!bcm->initialized) {
+ bcm43xx_lock_irqsafe(bcm, flags);
+ if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
fappend("Board not initialized.\n");
goto out;
}
@@ -199,7 +199,7 @@
(unsigned int)(tsf & 0xFFFFFFFFULL));
out:
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
up(&big_buffer_sem);
return res;
@@ -221,8 +221,8 @@
res = -EFAULT;
goto out_up;
}
- bcm43xx_lock_mmio(bcm, flags);
- if (!bcm->initialized) {
+ bcm43xx_lock_irqsafe(bcm, flags);
+ if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
res = -EFAULT;
goto out_unlock;
@@ -233,10 +233,11 @@
goto out_unlock;
}
bcm43xx_tsf_write(bcm, tsf);
+ mmiowb();
res = buf_size;
out_unlock:
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
out_up:
up(&big_buffer_sem);
return res;
@@ -257,7 +258,7 @@
int i, cnt, j = 0;
down(&big_buffer_sem);
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
fappend("Last %d logged xmitstatus blobs (Latest first):\n\n",
BCM43xx_NR_LOGGED_XMITSTATUS);
@@ -293,14 +294,14 @@
i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
}
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
if (*ppos == pos) {
/* Done. Drop the copied data. */
e->xmitstatus_printing = 0;
}
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
up(&big_buffer_sem);
return res;
}
Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_leds.c 2006-04-11 06:00:00.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_leds.c 2006-06-03 21:15:23.000000000 +0200
@@ -51,12 +51,12 @@
struct bcm43xx_private *bcm = led->bcm;
unsigned long flags;
- bcm43xx_lock_mmio(bcm, flags);
+ bcm43xx_lock_irqonly(bcm, flags);
if (led->blink_interval) {
bcm43xx_led_changestate(led);
mod_timer(&led->blink_timer, jiffies + led->blink_interval);
}
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqonly(bcm, flags);
}
static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_main.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_main.c 2006-06-03 21:04:17.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_main.c 2006-06-05 20:17:31.000000000 +0200
@@ -502,14 +502,14 @@
u32 old;
unsigned long flags;
- bcm43xx_lock_mmio(bcm, flags);
- if (bcm43xx_is_initializing(bcm) || bcm->shutting_down) {
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_lock_irqonly(bcm, flags);
+ if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) {
+ bcm43xx_unlock_irqonly(bcm, flags);
return -EBUSY;
}
old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
tasklet_disable(&bcm->isr_tasklet);
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqonly(bcm, flags);
if (oldstate)
*oldstate = old;
@@ -1387,7 +1387,7 @@
bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
#endif
}
- if (bcm->shutting_down) {
+ if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) {
bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
& ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002));
@@ -1707,7 +1707,7 @@
# define bcmirq_handled(irq) do { /* nothing */ } while (0)
#endif /* CONFIG_BCM43XX_DEBUG*/
- bcm43xx_lock_mmio(bcm, flags);
+ bcm43xx_lock_irqonly(bcm, flags);
reason = bcm->irq_reason;
dma_reason[0] = bcm->dma_reason[0];
dma_reason[1] = bcm->dma_reason[1];
@@ -1732,7 +1732,8 @@
dma_reason[0], dma_reason[1],
dma_reason[2], dma_reason[3]);
bcm43xx_controller_restart(bcm, "DMA error");
- bcm43xx_unlock_mmio(bcm, flags);
+ mmiowb();
+ bcm43xx_unlock_irqonly(bcm, flags);
return;
}
if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) |
@@ -1819,7 +1820,8 @@
if (!modparam_noleds)
bcm43xx_leds_update(bcm, activity);
bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
- bcm43xx_unlock_mmio(bcm, flags);
+ mmiowb();
+ bcm43xx_unlock_irqonly(bcm, flags);
}
static void pio_irq_workaround(struct bcm43xx_private *bcm,
@@ -1868,7 +1870,7 @@
if (!bcm)
return IRQ_NONE;
- spin_lock(&bcm->_lock);
+ spin_lock(&bcm->irq_lock);
reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
if (reason == 0xffffffff) {
@@ -1897,7 +1899,7 @@
* completely, but some careful work is needed to fix this. I think it
* is best to stay with this cheap workaround for now... .
*/
- if (likely(bcm->initialized)) {
+ if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
/* disable all IRQs. They are enabled again in the bottom half. */
bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
/* save the reason code and call our bottom half. */
@@ -1907,7 +1909,7 @@
out:
mmiowb();
- spin_unlock(&bcm->_lock);
+ spin_unlock(&bcm->irq_lock);
return ret;
}
@@ -3104,15 +3106,14 @@
//TODO for APHY (temperature?)
}
-static void bcm43xx_periodic_task_handler(unsigned long d)
+static void bcm43xx_periodic_work_handler(void *d)
{
- struct bcm43xx_private *bcm = (struct bcm43xx_private *)d;
+ struct bcm43xx_private *bcm = d;
unsigned long flags;
unsigned int state;
- bcm43xx_lock_mmio(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
- assert(bcm->initialized);
state = bcm->periodic_state;
if (state % 8 == 0)
bcm43xx_periodic_every120sec(bcm);
@@ -3123,26 +3124,24 @@
bcm43xx_periodic_every15sec(bcm);
bcm->periodic_state = state + 1;
- mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15));
+ schedule_delayed_work(&bcm->periodic_work, HZ * 15);
- bcm43xx_unlock_mmio(bcm, flags);
+ mmiowb();
+ bcm43xx_unlock_irqsafe(bcm, flags);
}
static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
{
- del_timer_sync(&bcm->periodic_tasks);
+ cancel_rearming_delayed_work(&bcm->periodic_work);
}
static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
{
- struct timer_list *timer = &(bcm->periodic_tasks);
+ struct work_struct *work = &(bcm->periodic_work);
- assert(bcm->initialized);
- setup_timer(timer,
- bcm43xx_periodic_task_handler,
- (unsigned long)bcm);
- timer->expires = jiffies;
- add_timer(timer);
+ assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+ INIT_WORK(work, bcm43xx_periodic_work_handler, bcm);
+ schedule_work(work);
}
static void bcm43xx_security_init(struct bcm43xx_private *bcm)
@@ -3156,16 +3155,12 @@
static void bcm43xx_free_board(struct bcm43xx_private *bcm)
{
int i, err;
- unsigned long flags;
+ bcm43xx_lock_noirq(bcm);
bcm43xx_sysfs_unregister(bcm);
-
bcm43xx_periodic_tasks_delete(bcm);
- bcm43xx_lock(bcm, flags);
- bcm->initialized = 0;
- bcm->shutting_down = 1;
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
if (!bcm->core_80211[i].available)
@@ -3180,23 +3175,19 @@
bcm43xx_pctl_set_crystal(bcm, 0);
- bcm43xx_lock(bcm, flags);
- bcm->shutting_down = 0;
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
+ bcm43xx_unlock_noirq(bcm);
}
static int bcm43xx_init_board(struct bcm43xx_private *bcm)
{
int i, err;
int connect_phy;
- unsigned long flags;
might_sleep();
- bcm43xx_lock(bcm, flags);
- bcm->initialized = 0;
- bcm->shutting_down = 0;
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_lock_noirq(bcm);
+ bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
err = bcm43xx_pctl_set_crystal(bcm, 1);
if (err)
@@ -3263,9 +3254,7 @@
}
/* Initialization of the board is done. Flag it as such. */
- bcm43xx_lock(bcm, flags);
- bcm->initialized = 1;
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
bcm43xx_periodic_tasks_setup(bcm);
bcm43xx_sysfs_register(bcm);
@@ -3273,6 +3262,8 @@
assert(err == 0);
out:
+ bcm43xx_unlock_noirq(bcm);
+
return err;
err_80211_unwind:
@@ -3544,8 +3535,8 @@
struct bcm43xx_radioinfo *radio;
unsigned long flags;
- bcm43xx_lock_mmio(bcm, flags);
- if (bcm->initialized) {
+ bcm43xx_lock_irqsafe(bcm, flags);
+ if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
bcm43xx_mac_suspend(bcm);
bcm43xx_radio_selectchannel(bcm, channel, 0);
bcm43xx_mac_enable(bcm);
@@ -3553,7 +3544,7 @@
radio = bcm43xx_current_radio(bcm);
radio->initial_channel = channel;
}
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
}
/* set_security() callback in struct ieee80211_device */
@@ -3567,7 +3558,7 @@
dprintk(KERN_INFO PFX "set security called\n");
- bcm43xx_lock_mmio(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
if (sec->flags & (1<<keyidx)) {
@@ -3596,7 +3587,8 @@
secinfo->encrypt = sec->encrypt;
dprintk(KERN_INFO PFX " .encrypt = %d\n", sec->encrypt);
}
- if (bcm->initialized && !bcm->ieee->host_encrypt) {
+ if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED &&
+ !bcm->ieee->host_encrypt) {
if (secinfo->enabled) {
/* upload WEP keys to hardware */
char null_address[6] = { 0 };
@@ -3630,7 +3622,7 @@
} else
bcm43xx_clear_keys(bcm);
}
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
}
/* hard_start_xmit() callback in struct ieee80211_device */
@@ -3642,10 +3634,10 @@
int err = -ENODEV;
unsigned long flags;
- bcm43xx_lock_mmio(bcm, flags);
- if (likely(bcm->initialized))
+ bcm43xx_lock_irqonly(bcm, flags);
+ if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED))
err = bcm43xx_tx(bcm, txb);
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqonly(bcm, flags);
return err;
}
@@ -3660,9 +3652,9 @@
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
unsigned long flags;
- bcm43xx_lock_mmio(bcm, flags);
+ bcm43xx_lock_irqonly(bcm, flags);
bcm43xx_controller_restart(bcm, "TX timeout");
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqonly(bcm, flags);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3701,6 +3693,7 @@
{
int err;
+ bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
bcm->ieee = netdev_priv(net_dev);
bcm->softmac = ieee80211_priv(net_dev);
bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
@@ -3709,7 +3702,8 @@
bcm->pci_dev = pci_dev;
bcm->net_dev = net_dev;
bcm->bad_frames_preempt = modparam_bad_frames_preempt;
- spin_lock_init(&bcm->_lock);
+ spin_lock_init(&bcm->irq_lock);
+ mutex_init(&bcm->mutex);
tasklet_init(&bcm->isr_tasklet,
(void (*)(unsigned long))bcm43xx_interrupt_tasklet,
(unsigned long)bcm);
@@ -3840,7 +3834,7 @@
struct net_device *net_dev = bcm->net_dev;
struct pci_dev *pci_dev = bcm->pci_dev;
int err;
- int was_initialized = bcm->initialized;
+ int was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
netif_stop_queue(bcm->net_dev);
tasklet_disable(&bcm->isr_tasklet);
@@ -3875,6 +3869,7 @@
*/
void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
{
+ bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING);
bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
@@ -3893,11 +3888,11 @@
dprintk(KERN_INFO PFX "Suspending...\n");
- bcm43xx_lock(bcm, flags);
- bcm->was_initialized = bcm->initialized;
- if (bcm->initialized)
+ bcm43xx_lock_irqsafe(bcm, flags);
+ bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+ if (bcm->was_initialized)
try_to_shutdown = 1;
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
netif_device_detach(net_dev);
if (try_to_shutdown) {
Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_pio.c 2006-04-28 16:13:40.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_pio.c 2006-06-05 20:17:31.000000000 +0200
@@ -262,7 +262,7 @@
int err;
u16 txctl;
- bcm43xx_lock_mmio(bcm, flags);
+ bcm43xx_lock_irqonly(bcm, flags);
txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
if (txctl & BCM43xx_PIO_TXCTL_SUSPEND)
@@ -298,7 +298,7 @@
continue;
}
out_unlock:
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqonly(bcm, flags);
}
static void setup_txqueues(struct bcm43xx_pioqueue *queue)
@@ -374,7 +374,6 @@
struct bcm43xx_pio_txpacket *packet, *tmp_packet;
netif_tx_disable(queue->bcm->net_dev);
- assert(queue->bcm->shutting_down);
tasklet_disable(&queue->txtask);
list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c 2006-04-28 16:13:40.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c 2006-06-05 18:29:34.000000000 +0200
@@ -120,12 +120,12 @@
GFP_KERNEL);
if (!sprom)
return -ENOMEM;
- bcm43xx_lock_mmio(bcm, flags);
- assert(bcm->initialized);
+ bcm43xx_lock_irqsafe(bcm, flags);
err = bcm43xx_sprom_read(bcm, sprom);
if (!err)
err = sprom2hex(sprom, buf, PAGE_SIZE);
- bcm43xx_unlock_mmio(bcm, flags);
+ mmiowb();
+ bcm43xx_unlock_irqsafe(bcm, flags);
kfree(sprom);
return err;
@@ -150,10 +150,10 @@
err = hex2sprom(sprom, buf, count);
if (err)
goto out_kfree;
- bcm43xx_lock_mmio(bcm, flags);
- assert(bcm->initialized);
+ bcm43xx_lock_irqsafe(bcm, flags);
err = bcm43xx_sprom_write(bcm, sprom);
- bcm43xx_unlock_mmio(bcm, flags);
+ mmiowb();
+ bcm43xx_unlock_irqsafe(bcm, flags);
out_kfree:
kfree(sprom);
@@ -170,15 +170,13 @@
char *buf)
{
struct bcm43xx_private *bcm = dev_to_bcm(dev);
- unsigned long flags;
int err;
ssize_t count = 0;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- bcm43xx_lock(bcm, flags);
- assert(bcm->initialized);
+ bcm43xx_lock_noirq(bcm);
switch (bcm43xx_current_radio(bcm)->interfmode) {
case BCM43xx_RADIO_INTERFMODE_NONE:
@@ -195,7 +193,7 @@
}
err = 0;
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_noirq(bcm);
return err ? err : count;
@@ -231,16 +229,15 @@
return -EINVAL;
}
- bcm43xx_lock_mmio(bcm, flags);
- assert(bcm->initialized);
+ bcm43xx_lock_irqsafe(bcm, flags);
err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
if (err) {
printk(KERN_ERR PFX "Interference Mitigation not "
"supported by device\n");
}
-
- bcm43xx_unlock_mmio(bcm, flags);
+ mmiowb();
+ bcm43xx_unlock_irqsafe(bcm, flags);
return err ? err : count;
}
@@ -254,15 +251,13 @@
char *buf)
{
struct bcm43xx_private *bcm = dev_to_bcm(dev);
- unsigned long flags;
int err;
ssize_t count;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- bcm43xx_lock(bcm, flags);
- assert(bcm->initialized);
+ bcm43xx_lock_noirq(bcm);
if (bcm->short_preamble)
count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
@@ -270,7 +265,7 @@
count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
err = 0;
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_noirq(bcm);
return err ? err : count;
}
@@ -290,13 +285,12 @@
value = get_boolean(buf, count);
if (value < 0)
return value;
- bcm43xx_lock(bcm, flags);
- assert(bcm->initialized);
+ bcm43xx_lock_irqsafe(bcm, flags);
bcm->short_preamble = !!value;
err = 0;
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
return err ? err : count;
}
@@ -310,7 +304,7 @@
struct device *dev = &bcm->pci_dev->dev;
int err;
- assert(bcm->initialized);
+ assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
err = device_create_file(dev, &dev_attr_sprom);
if (err)
Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_wx.c 2006-05-25 20:54:02.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_wx.c 2006-06-05 18:27:12.000000000 +0200
@@ -55,13 +55,13 @@
char *extra)
{
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
- unsigned long flags;
int i;
+ unsigned long flags;
struct bcm43xx_phyinfo *phy;
char suffix[7] = { 0 };
int have_a = 0, have_b = 0, have_g = 0;
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
for (i = 0; i < bcm->nr_80211_available; i++) {
phy = &(bcm->core_80211_ext[i].phy);
switch (phy->type) {
@@ -77,7 +77,7 @@
assert(0);
}
}
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
i = 0;
if (have_a) {
@@ -111,7 +111,7 @@
int freq;
int err = -EINVAL;
- bcm43xx_lock_mmio(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
if ((data->freq.m >= 0) && (data->freq.m <= 1000)) {
channel = data->freq.m;
freq = bcm43xx_channel_to_freq(bcm, channel);
@@ -121,7 +121,7 @@
}
if (!bcm43xx_is_valid_channel(bcm, channel))
goto out_unlock;
- if (bcm->initialized) {
+ if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
//ieee80211softmac_disassoc(softmac, $REASON);
bcm43xx_mac_suspend(bcm);
err = bcm43xx_radio_selectchannel(bcm, channel, 0);
@@ -131,7 +131,7 @@
err = 0;
}
out_unlock:
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
return err;
}
@@ -147,11 +147,10 @@
int err = -ENODEV;
u16 channel;
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
radio = bcm43xx_current_radio(bcm);
channel = radio->channel;
if (channel == 0xFF) {
- assert(!bcm->initialized);
channel = radio->initial_channel;
if (channel == 0xFF)
goto out_unlock;
@@ -163,7 +162,7 @@
err = 0;
out_unlock:
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
return err;
}
@@ -181,13 +180,13 @@
if (mode == IW_MODE_AUTO)
mode = BCM43xx_INITIAL_IWMODE;
- bcm43xx_lock_mmio(bcm, flags);
- if (bcm->initialized) {
+ bcm43xx_lock_irqsafe(bcm, flags);
+ if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
if (bcm->ieee->iw_mode != mode)
bcm43xx_set_iwmode(bcm, mode);
} else
bcm->ieee->iw_mode = mode;
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
return 0;
}
@@ -200,9 +199,9 @@
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
unsigned long flags;
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
data->mode = bcm->ieee->iw_mode;
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
return 0;
}
@@ -255,7 +254,7 @@
IW_ENC_CAPA_CIPHER_TKIP |
IW_ENC_CAPA_CIPHER_CCMP;
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
phy = bcm43xx_current_phy(bcm);
range->num_bitrates = 0;
@@ -302,7 +301,7 @@
}
range->num_frequency = j;
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
return 0;
}
@@ -313,14 +312,13 @@
char *extra)
{
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
- unsigned long flags;
size_t len;
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_noirq(bcm);
len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
memcpy(bcm->nick, extra, len);
bcm->nick[len] = '\0';
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_noirq(bcm);
return 0;
}
@@ -331,15 +329,14 @@
char *extra)
{
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
- unsigned long flags;
size_t len;
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_noirq(bcm);
len = strlen(bcm->nick) + 1;
memcpy(extra, bcm->nick, len);
data->data.length = (__u16)len;
data->data.flags = 1;
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_noirq(bcm);
return 0;
}
@@ -353,7 +350,7 @@
unsigned long flags;
int err = -EINVAL;
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
if (data->rts.disabled) {
bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
err = 0;
@@ -364,7 +361,7 @@
err = 0;
}
}
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
return err;
}
@@ -377,11 +374,11 @@
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
unsigned long flags;
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
data->rts.value = bcm->rts_threshold;
data->rts.fixed = 0;
data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
return 0;
}
@@ -395,7 +392,7 @@
unsigned long flags;
int err = -EINVAL;
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
if (data->frag.disabled) {
bcm->ieee->fts = MAX_FRAG_THRESHOLD;
err = 0;
@@ -406,7 +403,7 @@
err = 0;
}
}
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
return err;
}
@@ -419,11 +416,11 @@
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
unsigned long flags;
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
data->frag.value = bcm->ieee->fts;
data->frag.fixed = 0;
data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
return 0;
}
@@ -445,8 +442,8 @@
return -EOPNOTSUPP;
}
- bcm43xx_lock_mmio(bcm, flags);
- if (!bcm->initialized)
+ bcm43xx_lock_irqsafe(bcm, flags);
+ if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
goto out_unlock;
radio = bcm43xx_current_radio(bcm);
phy = bcm43xx_current_phy(bcm);
@@ -469,7 +466,7 @@
err = 0;
out_unlock:
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
return err;
}
@@ -484,8 +481,8 @@
unsigned long flags;
int err = -ENODEV;
- bcm43xx_lock(bcm, flags);
- if (!bcm->initialized)
+ bcm43xx_lock_irqsafe(bcm, flags);
+ if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
goto out_unlock;
radio = bcm43xx_current_radio(bcm);
/* desired dBm value is in Q5.2 */
@@ -496,7 +493,7 @@
err = 0;
out_unlock:
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
return err;
}
@@ -583,8 +580,8 @@
return -EINVAL;
}
- bcm43xx_lock_mmio(bcm, flags);
- if (bcm->initialized) {
+ bcm43xx_lock_irqsafe(bcm, flags);
+ if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
if (err) {
printk(KERN_ERR PFX "Interference Mitigation not "
@@ -598,7 +595,7 @@
} else
bcm43xx_current_radio(bcm)->interfmode = mode;
}
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
return err;
}
@@ -612,9 +609,9 @@
unsigned long flags;
int mode;
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
mode = bcm43xx_current_radio(bcm)->interfmode;
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
switch (mode) {
case BCM43xx_RADIO_INTERFMODE_NONE:
@@ -644,9 +641,9 @@
int on;
on = *((int *)extra);
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
bcm->short_preamble = !!on;
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
return 0;
}
@@ -660,9 +657,9 @@
unsigned long flags;
int on;
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
on = bcm->short_preamble;
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
if (on)
strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
@@ -684,11 +681,11 @@
on = *((int *)extra);
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
bcm->ieee->host_encrypt = !!on;
bcm->ieee->host_decrypt = !!on;
bcm->ieee->host_build_iv = !on;
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
return 0;
}
@@ -702,9 +699,9 @@
unsigned long flags;
int on;
- bcm43xx_lock(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
on = bcm->ieee->host_encrypt;
- bcm43xx_unlock(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
if (on)
strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
@@ -767,11 +764,11 @@
if (!sprom)
goto out;
- bcm43xx_lock_mmio(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
err = -ENODEV;
- if (bcm->initialized)
+ if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
err = bcm43xx_sprom_read(bcm, sprom);
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
if (!err)
data->data.length = sprom2hex(sprom, extra);
kfree(sprom);
@@ -812,11 +809,11 @@
if (err)
goto out_kfree;
- bcm43xx_lock_mmio(bcm, flags);
+ bcm43xx_lock_irqsafe(bcm, flags);
err = -ENODEV;
- if (bcm->initialized)
+ if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
err = bcm43xx_sprom_write(bcm, sprom);
- bcm43xx_unlock_mmio(bcm, flags);
+ bcm43xx_unlock_irqsafe(bcm, flags);
out_kfree:
kfree(sprom);
out:
Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_phy.c 2006-06-05 17:47:26.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_phy.c 2006-06-05 20:17:31.000000000 +0200
@@ -1648,7 +1648,7 @@
void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
{
static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 };
- const int is_initializing = bcm43xx_is_initializing(bcm);
+ const int is_initializing = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZING);
struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
u16 h, i, oldi = 0, j;
--
Greetings Michael.
^ permalink raw reply
* [PATCH 2/2] bcm43xx: preemptible periodic work
From: Michael Buesch @ 2006-06-05 18:24 UTC (permalink / raw)
To: John W. Linville; +Cc: netdev, bcm43xx-dev, Jason Lunz, Jory A. Pratt
John, please queue for 2.6.18.
This patch depends on
[PATCH 1/2] bcm43xx: redesign locking
--
Make the heavy periodic work preemptible to avoid disabling
local IRQs for several msecs.
Signed-off-by: Michael Buesch <mb@buesch.de>
Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_main.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_main.c 2006-06-05 20:17:31.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_main.c 2006-06-05 20:17:36.000000000 +0200
@@ -496,11 +496,21 @@
return old_mask;
}
+/* Synchronize IRQ top- and bottom-half.
+ * IRQs must be masked before calling this.
+ * This must not be called with the irq_lock held.
+ */
+static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm)
+{
+ synchronize_irq(bcm->irq);
+ tasklet_disable(&bcm->isr_tasklet);
+}
+
/* Make sure we don't receive more data from the device. */
static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate)
{
- u32 old;
unsigned long flags;
+ u32 old;
bcm43xx_lock_irqonly(bcm, flags);
if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) {
@@ -508,8 +518,9 @@
return -EBUSY;
}
old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
- tasklet_disable(&bcm->isr_tasklet);
bcm43xx_unlock_irqonly(bcm, flags);
+ bcm43xx_synchronize_irq(bcm);
+
if (oldstate)
*oldstate = old;
@@ -3106,14 +3117,10 @@
//TODO for APHY (temperature?)
}
-static void bcm43xx_periodic_work_handler(void *d)
+static void do_periodic_work(struct bcm43xx_private *bcm)
{
- struct bcm43xx_private *bcm = d;
- unsigned long flags;
unsigned int state;
- bcm43xx_lock_irqsafe(bcm, flags);
-
state = bcm->periodic_state;
if (state % 8 == 0)
bcm43xx_periodic_every120sec(bcm);
@@ -3121,13 +3128,79 @@
bcm43xx_periodic_every60sec(bcm);
if (state % 2 == 0)
bcm43xx_periodic_every30sec(bcm);
- bcm43xx_periodic_every15sec(bcm);
+ if (state % 1 == 0)
+ bcm43xx_periodic_every15sec(bcm);
bcm->periodic_state = state + 1;
schedule_delayed_work(&bcm->periodic_work, HZ * 15);
+}
- mmiowb();
- bcm43xx_unlock_irqsafe(bcm, flags);
+/* Estimate a "Badness" value based on the periodic work
+ * state-machine state. "Badness" is worse (bigger), if the
+ * periodic work will take longer.
+ */
+static int estimate_periodic_work_badness(unsigned int state)
+{
+ int badness = 0;
+
+ if (state % 8 == 0) /* every 120 sec */
+ badness += 10;
+ if (state % 4 == 0) /* every 60 sec */
+ badness += 5;
+ if (state % 2 == 0) /* every 30 sec */
+ badness += 1;
+ if (state % 1 == 0) /* every 15 sec */
+ badness += 1;
+
+#define BADNESS_LIMIT 4
+ return badness;
+}
+
+static void bcm43xx_periodic_work_handler(void *d)
+{
+ struct bcm43xx_private *bcm = d;
+ unsigned long flags;
+ u32 savedirqs = 0;
+ int badness;
+
+ badness = estimate_periodic_work_badness(bcm->periodic_state);
+ if (badness > BADNESS_LIMIT) {
+ /* Periodic work will take a long time, so we want it to
+ * be preemtible.
+ */
+ bcm43xx_lock_irqonly(bcm, flags);
+ netif_stop_queue(bcm->net_dev);
+ if (bcm43xx_using_pio(bcm))
+ bcm43xx_pio_freeze_txqueues(bcm);
+ savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+ bcm43xx_unlock_irqonly(bcm, flags);
+ bcm43xx_lock_noirq(bcm);
+ bcm43xx_synchronize_irq(bcm);
+ } else {
+ /* Periodic work should take short time, so we want low
+ * locking overhead.
+ */
+ bcm43xx_lock_irqsafe(bcm, flags);
+ }
+
+ do_periodic_work(bcm);
+
+ if (badness > BADNESS_LIMIT) {
+ bcm43xx_lock_irqonly(bcm, flags);
+ if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
+ tasklet_enable(&bcm->isr_tasklet);
+ bcm43xx_interrupt_enable(bcm, savedirqs);
+ if (bcm43xx_using_pio(bcm))
+ bcm43xx_pio_thaw_txqueues(bcm);
+ }
+ netif_wake_queue(bcm->net_dev);
+ mmiowb();
+ bcm43xx_unlock_irqonly(bcm, flags);
+ bcm43xx_unlock_noirq(bcm);
+ } else {
+ mmiowb();
+ bcm43xx_unlock_irqsafe(bcm, flags);
+ }
}
static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
@@ -3679,9 +3752,11 @@
static int bcm43xx_net_stop(struct net_device *net_dev)
{
struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+ int err;
ieee80211softmac_stop(net_dev);
- bcm43xx_disable_interrupts_sync(bcm, NULL);
+ err = bcm43xx_disable_interrupts_sync(bcm, NULL);
+ assert(!err);
bcm43xx_free_board(bcm);
return 0;
Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_phy.c 2006-06-05 20:17:31.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_phy.c 2006-06-05 20:17:36.000000000 +0200
@@ -1410,7 +1410,10 @@
u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
{
struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+ u16 ret;
+ unsigned long flags;
+ local_irq_save(flags);
if (phy->connected) {
bcm43xx_phy_write(bcm, 0x15, 0xE300);
control <<= 8;
@@ -1430,8 +1433,10 @@
bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0);
udelay(8);
}
+ ret = bcm43xx_phy_read(bcm, 0x002D);
+ local_irq_restore(flags);
- return bcm43xx_phy_read(bcm, 0x002D);
+ return ret;
}
static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control)
Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_pio.c 2006-06-05 20:17:31.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_pio.c 2006-06-05 20:17:36.000000000 +0200
@@ -264,6 +264,8 @@
bcm43xx_lock_irqonly(bcm, flags);
+ if (queue->tx_frozen)
+ goto out_unlock;
txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
if (txctl & BCM43xx_PIO_TXCTL_SUSPEND)
goto out_unlock;
@@ -633,5 +635,40 @@
bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
& ~BCM43xx_PIO_TXCTL_SUSPEND);
bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1);
- tasklet_schedule(&queue->txtask);
+ if (!list_empty(&queue->txqueue))
+ tasklet_schedule(&queue->txtask);
+}
+
+void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_pio *pio;
+
+ assert(bcm43xx_using_pio(bcm));
+ pio = bcm43xx_current_pio(bcm);
+ pio->queue0->tx_frozen = 1;
+ pio->queue1->tx_frozen = 1;
+ pio->queue2->tx_frozen = 1;
+ pio->queue3->tx_frozen = 1;
}
+
+void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm)
+{
+ struct bcm43xx_pio *pio;
+
+ assert(bcm43xx_using_pio(bcm));
+ pio = bcm43xx_current_pio(bcm);
+ pio->queue0->tx_frozen = 0;
+ pio->queue1->tx_frozen = 0;
+ pio->queue2->tx_frozen = 0;
+ pio->queue3->tx_frozen = 0;
+ if (!list_empty(&pio->queue0->txqueue))
+ tasklet_schedule(&pio->queue0->txtask);
+ if (!list_empty(&pio->queue1->txqueue))
+ tasklet_schedule(&pio->queue1->txtask);
+ if (!list_empty(&pio->queue2->txqueue))
+ tasklet_schedule(&pio->queue2->txtask);
+ if (!list_empty(&pio->queue3->txqueue))
+ tasklet_schedule(&pio->queue3->txtask);
+}
+
+
Index: wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
===================================================================
--- wireless-dev.orig/drivers/net/wireless/bcm43xx/bcm43xx_pio.h 2006-06-05 20:17:31.000000000 +0200
+++ wireless-dev/drivers/net/wireless/bcm43xx/bcm43xx_pio.h 2006-06-05 20:17:36.000000000 +0200
@@ -54,6 +54,7 @@
u16 mmio_base;
u8 tx_suspended:1,
+ tx_frozen:1,
need_workarounds:1; /* Workarounds needed for core.rev < 3 */
/* Adjusted size of the device internal TX buffer. */
@@ -108,8 +109,12 @@
struct bcm43xx_xmitstatus *status);
void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue);
+/* Suspend a TX queue on hardware level. */
void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue);
void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue);
+/* Suspend (freeze) the TX tasklet (software level). */
+void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm);
+void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm);
#else /* CONFIG_BCM43XX_PIO */
@@ -145,6 +150,14 @@
void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
{
}
+static inline
+void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
+{
+}
+static inline
+void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm)
+{
+}
#endif /* CONFIG_BCM43XX_PIO */
#endif /* BCM43xx_PIO_H_ */
--
Greetings Michael.
^ permalink raw reply
* Re: [PATCH,RFT] bcm43xx: use softmac-suggested TX rate
From: John W. Linville @ 2006-06-05 18:51 UTC (permalink / raw)
To: Michael Buesch; +Cc: Daniel Drake, netdev
In-Reply-To: <200605192032.46673.mb@bu3sch.de>
On Fri, May 19, 2006 at 08:32:46PM +0200, Michael Buesch wrote:
> On Friday 19 May 2006 20:44, you wrote:
> > John W. Linville wrote:
> > > Do you intend for this to be merged? Given recent miscommunication,
> > > I figured I should ask... :-)
> >
> > Nobody has tested it yet, so no, but thanks for asking.
> >
> > I figure it will be easier to find testers once the base patch (softmac
> > suggest txrate) has been pushed by you into 2.6.18-rc1 ;)
>
> Next time, please CC the maintainers, so they don't accidentally delete
> important mail. ;)
> Can you resend that patch to me in private and I will see if it
> is good.
Any more input on this patch? Do we want it, or not?
John
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply
* Re: [PATCH, RTF/RFC] bcm43xx: Enable local IRQs while executing periodic work
From: John W. Linville @ 2006-06-05 18:54 UTC (permalink / raw)
To: Michael Buesch; +Cc: netdev, bcm43xx-dev
In-Reply-To: <200605231723.10028.mb@bu3sch.de>
On Tue, May 23, 2006 at 05:23:09PM +0200, Michael Buesch wrote:
> I would like to get this into wireless-2.6, but before that
> happens I would like to have a few regression tests by people.
> Please apply this and run high network traffic for 10-15 minutes.
> Please enable kernel spinlock lockup and recursion detection
> while testing.
It has almost been two weeks...do we want this patch, or not?
John
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply
* Re: 2.6.17-rc5-mm3
From: Andrew Morton @ 2006-06-05 18:54 UTC (permalink / raw)
To: Mel Gorman; +Cc: linux-kernel, netdev
In-Reply-To: <20060605175637.GA16186@skynet.ie>
On Mon, 5 Jun 2006 18:56:37 +0100
mel@csn.ul.ie (Mel Gorman) wrote:
>
> I am seeing more networking-related funniness with 2.6.17-rc5-mm3 on the
> same machine previously fixed by git-net-llc-fix.patch. The console log is
> below. I've done no investigation work in case it's a known problem.
It's not a known problem, afaik.
> ...
> Starting anacron: [ OK ]
> Starting atd: [ OK ]
> Starting Avahi daemon: [ OK ]
> Starting cups-config-daemon: [ OK ]
> Starting HAL daemon: [ OK ]
> Fedora Core release 5 (Bordeaux)
> Kernel 2.6.17-rc5-mm2-autokern1 on an x86_64
> bl6-13.ltc.austin.ibm.com login: -- 0:conmux-control -- time-stamp -- Jun/05/06 10:47:46 --
> -- 0:conmux-control -- time-stamp -- Jun/05/06 10:51:12 --
> BUG: warning at include/net/dst.h:153/dst_release()
> Call Trace:
> <IRQ> [<ffffffff81228274>] __kfree_skb+0x3c/0xbd
> [<ffffffff81199568>] tg3_poll+0x1a1/0x94f
> [<ffffffff8122d80c>] net_rx_action+0xac/0x160
> [<ffffffff81037904>] __do_softirq+0x48/0xb4
> [<ffffffff8100a496>] call_softirq+0x1e/0x28
> [<ffffffff8100b84e>] do_softirq+0x2c/0x7e
> [<ffffffff8100b6c8>] do_IRQ+0x50/0x59
> [<ffffffff81007807>] default_idle+0x0/0x54
> [<ffffffff810097b8>] ret_from_intr+0x0/0xb
> <EOI>
> Attempt to release alive inet socket ffff81003f8b2780
> BUG: warning at include/net/dst.h:153/dst_release()
> Call Trace:
> <IRQ> [<ffffffff81228274>] __kfree_skb+0x3c/0xbd
> [<ffffffff81268fc4>] icmp_rcv+0x17c/0x184
> [<ffffffff812484ca>] ip_local_deliver+0xfe/0x1bf
> [<ffffffff812489bf>] ip_rcv+0x434/0x475
> [<ffffffff8122d615>] netif_receive_skb+0x2c6/0x2e5
> [<ffffffff81199add>] tg3_poll+0x716/0x94f
> [<ffffffff8122d80c>] net_rx_action+0xac/0x160<7>Losing some ticks... checking if CPU frequency changed.
> [<ffffffff81037904>] __do_softirq+0x48/0xb4
> [<ffffffff8100a496>] call_softirq+0x1e/0x28
> [<ffffffff8100b84e>] do_softirq+0x2c/0x7e
> [<ffffffff8100b6c8>] do_IRQ+0x50/0x59
> [<ffffffff81007807>] default_idle+0x0/0x54
> [<ffffffff810097b8>] ret_from_intr+0x0/0xb
There are quite a few changes in the net tree. I guess the first thing to
investigate would be 2.6.17-rc5+origin.patch+git-net.patch.
^ 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