* Re: PATCHv3 2.6.17-rc5 tulip free_irq() called too late
From: Grant Grundler @ 2006-06-14 22:30 UTC (permalink / raw)
To: Francois Romieu
Cc: Grant Grundler, Jeff Garzik, Valerie Henson, Andrew Morton,
netdev
In-Reply-To: <20060614204720.GA17887@electric-eye.fr.zoreil.com>
On Wed, Jun 14, 2006 at 10:47:20PM +0200, Francois Romieu wrote:
> Grant Grundler <grundler@parisc-linux.org> :
> [...]
> > I'm not keen on adding more code to tulip_interrupt() routine
> > for something that rarely happens (compared to IRQs) and is handled
> > outside the interrupt routine. I'm pretty sure stopping interrupts
> > before stopping DMA is sufficient.
> > Can you show an example where it doesn't work?
>
> Shared irq.
>
> The device has not quiesced, the kernel stop listening to it and the
> neighbor device receives a late interruption from the network device.
I thought we've worked through that already:
http://www.spinics.net/lists/netdev/msg05902.html
Patch v3 takes care of that problem.
The first step in the sequence is to mask IRQs on the tulip.
The "neighbor" device sharing the IRQ will not see any interrupts from
the tulip after that.
thanks,
grant
^ permalink raw reply
* Re: PATCHv3 2.6.17-rc5 tulip free_irq() called too late
From: Grant Grundler @ 2006-06-14 22:25 UTC (permalink / raw)
To: Jeff Garzik; +Cc: Grant Grundler, Valerie Henson, Andrew Morton, netdev
In-Reply-To: <449068C9.1010304@pobox.com>
On Wed, Jun 14, 2006 at 03:51:37PM -0400, Jeff Garzik wrote:
> You need to turn off the thing that generates work (DMA engine), before
> turning off the thing that reaps work (irq handler).
...
> It should be completely obvious that the chip is still generating
> work...
Yes, I agree it still generates work. ie we can still RX packets.
But those will get discarded anyway.
In other words, If work is generated and I don't know it and
don't care, was it really work? :)
> You don't want to leave the hardware in a position where it has
> unacknowledged events.
Ok. Let me repeat two questions I asked a while ago:
| Are you worried about a masked, pending interrupt causing
| problems when the driver is re-opened or resumed?
The answer to "Yes" it seems.
And we will disagree on that since I've proven it's not a problem.
And it can't be a problem anyone else has seen since it's been
this way for 5+ years.
| If firmware left the device in that state at boot time wouldn't
| the driver be required to handle it?
Can you comment on this please?
thanks,
grant
^ permalink raw reply
* [Ubuntu PATCH] forcedeth: Let the driver work when no PHY is found
From: Randy Dunlap @ 2006-06-14 23:23 UTC (permalink / raw)
To: netdev; +Cc: akpm, manfred, jgarzik
From: Ben Collins <bcollins@ubuntu.com>
[UBUNTU:forcedeth] Let the driver work when no PHY is found
This matches breezy behavior.
Reference: https://launchpad.net/products/launchpad/+bug/45257
http://www.kernel.org/git/?p=linux/kernel/git/bcollins/ubuntu-dapper.git;a=commitdiff;h=38c1aaedc1f907e138698e54ceadeb9ae560b0d7
Signed-off-by: Ben Collins <bcollins@ubuntu.com>
---
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -2582,14 +2582,13 @@ static int __devinit nv_probe(struct pci
np->phy_oui = id1 | id2;
break;
}
- if (i == 33) {
+
+ /* Let the damn card work if it can */
+ if (i == 33)
printk(KERN_INFO "%s: open: Could not find a valid PHY.\n",
pci_name(pci_dev));
- goto out_freering;
- }
-
- /* reset it */
- phy_init(dev);
+ else
+ phy_init(dev);
/* set default link speed settings */
np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
^ permalink raw reply
* [Ubuntu PATCH] Make tulip driver not handle Davicom NICs
From: Randy Dunlap @ 2006-06-14 23:23 UTC (permalink / raw)
To: netdev, akpm, val_henson
Make tulip driver not handle Davicom NICs, let dmfe take over"
Reference: https://launchpad.net/bugs/48287
Source URL of Patch:
http://www.kernel.org/git/?p=linux/kernel/git/bcollins/ubuntu-dapper.git;a=commitdiff;h=1804482911a71bee9114cae1c2079507a38e9e7f
--- linux-2.6.17-rc5/drivers/net/tulip/tulip_core.c 2006-06-05 09:20:30.000000000 +0800
+++ ubuntu-kernel/drivers/net/tulip/tulip_core.c 2006-06-05 09:56:55.000000000 +0800
@@ -223,8 +223,12 @@
{ 0x1259, 0xa120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x11F6, 0x9881, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMPEX9881 },
{ 0x8086, 0x0039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, I21145 },
+ /* dmfe module seems to handle these better. See:
+ * https://launchpad.net/bugs/48287 */
+#if 0
{ 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X },
{ 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X },
+#endif
{ 0x1113, 0x1216, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1113, 0x1217, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 },
{ 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
^ permalink raw reply
* [Ubuntu PATCH] IRDA: Add some IBM think pads
From: Randy Dunlap @ 2006-06-14 23:23 UTC (permalink / raw)
To: netdev; +Cc: akpm, samuel
From: Ben Collins <bcollins@ubuntu.com>
[UBUNTU:nsc-ircc] Add some IBM think pads
Add Thinkpad T60/X60/Z60/T43/R52 Infrared driver support.
http://www.kernel.org/git/?p=linux/kernel/git/bcollins/ubuntu-dapper.git;a=commitdiff;h=7b8d2713435a9fb69719a282ba75e117f3f76a5b
Signed-off-by: Ben Collins <bcollins@ubuntu.com>
---
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -115,8 +115,12 @@ static nsc_chip_t chips[] = {
/* Contributed by Jan Frey - IBM A30/A31 */
{ "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff,
nsc_ircc_probe_39x, nsc_ircc_init_39x },
- { "IBM", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff,
- nsc_ircc_probe_39x, nsc_ircc_init_39x },
+ /* IBM ThinkPads using PC8738x (T60/X60/Z60) */
+ { "IBM-PC8738x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff,
+ nsc_ircc_probe_39x, nsc_ircc_init_39x },
+ /* IBM ThinkPads using PC8394T (T43/R52/?) */
+ { "IBM-PC8394T", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf9, 0xff,
+ nsc_ircc_probe_39x, nsc_ircc_init_39x },
{ NULL }
};
^ permalink raw reply
* [Ubuntu PATCH] Broadcom wireless patch, PCIE/Mactel support
From: Randy Dunlap @ 2006-06-14 23:22 UTC (permalink / raw)
To: lkml, netdev; +Cc: mb, akpm
From: Matthew Garrett <mjg59@srcf.ucam.org>
Broadcom wireless patch, PCIE/Mactel support
http://www.kernel.org/git/?p=linux/kernel/git/bcollins/ubuntu-dapper.git;a=commitdiff;h=1373a8487e911b5ee204f4422ddea00929c8a4cc
This patch adds support for PCIE cores to the bcm43xx driver. This is
needed for wireless to work on the Intel imacs. I've submitted it to
bcm43xx upstream.
(cherry picked from d88edf6a433074323a1805365a8dfc9c26fceae3 commit)
(cherry picked from 7dbd83ed3255fde4371edcbb6ad1d30f3e6ddf08 commit)
---
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -202,6 +202,8 @@
#define BCM43xx_COREID_USB20_HOST 0x819
#define BCM43xx_COREID_USB20_DEV 0x81a
#define BCM43xx_COREID_SDIO_HOST 0x81b
+#define BCM43xx_COREID_PCIE 0x820
+#define BCM43xx_COREID_CHIPCOMMON_NEW 0x900
/* Core Information Registers */
#define BCM43xx_CIR_BASE 0xf00
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -130,6 +130,8 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for
{ PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4307 802.11b */
{ PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ /* Broadcom 4312 80211a/b/g */
+ { PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
/* Broadcom 4318 802.11b/g */
{ PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4319 802.11a/b/g */
@@ -2580,7 +2582,8 @@ static int bcm43xx_probe_cores(struct bc
core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
/* if present, chipcommon is always core 0; read the chipid from it */
- if (core_id == BCM43xx_COREID_CHIPCOMMON) {
+ if (core_id == BCM43xx_COREID_CHIPCOMMON ||
+ core_id == BCM43xx_COREID_CHIPCOMMON_NEW) {
chip_id_32 = bcm43xx_read32(bcm, 0);
chip_id_16 = chip_id_32 & 0xFFFF;
bcm->core_chipcommon.available = 1;
@@ -2614,7 +2617,8 @@ static int bcm43xx_probe_cores(struct bc
/* ChipCommon with Core Rev >=4 encodes number of cores,
* otherwise consult hardcoded table */
- if ((core_id == BCM43xx_COREID_CHIPCOMMON) && (core_rev >= 4)) {
+ if (((core_id == BCM43xx_COREID_CHIPCOMMON) && (core_rev >= 4)) ||
+ core_id == BCM43xx_COREID_CHIPCOMMON_NEW) {
core_count = (chip_id_32 & 0x0F000000) >> 24;
} else {
switch (chip_id_16) {
@@ -2686,6 +2690,7 @@ static int bcm43xx_probe_cores(struct bc
core = NULL;
switch (core_id) {
case BCM43xx_COREID_PCI:
+ case BCM43xx_COREID_PCIE:
core = &bcm->core_pci;
if (core->available) {
printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
@@ -2724,6 +2729,7 @@ static int bcm43xx_probe_cores(struct bc
case 6:
case 7:
case 9:
+ case 10:
break;
default:
printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n",
@@ -3002,7 +3008,7 @@ static int bcm43xx_setup_backplane_pci_c
if (err)
goto out;
- if (bcm->core_pci.rev < 6) {
+ if (bcm->core_pci.rev < 6 && bcm->core_pci.id != BCM43xx_COREID_PCIE) {
value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC);
value |= (1 << backplane_flag_nr);
bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value);
@@ -3024,7 +3030,7 @@ static int bcm43xx_setup_backplane_pci_c
value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
- if (bcm->core_pci.rev < 5) {
+ if (bcm->core_pci.rev < 5 && bcm->core_pci.id != BCM43xx_COREID_PCIE) {
value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
& BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
@@ -3351,7 +3357,7 @@ static int bcm43xx_read_phyinfo(struct b
bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
break;
case BCM43xx_PHYTYPE_G:
- if (phy_rev > 7)
+ if (phy_rev > 8)
phy_rev_ok = 0;
bcm->ieee->modulation = IEEE80211_OFDM_MODULATION |
IEEE80211_CCK_MODULATION;
^ permalink raw reply
* Re: [patch] ipv4: fix lock usage in udp_ioctl
From: David Miller @ 2006-06-14 22:16 UTC (permalink / raw)
To: heiko.carstens; +Cc: jgarzik, akpm, linux-kernel, netdev, mingo, fpavlic
In-Reply-To: <20060614194305.GB10391@osiris.ibm.com>
From: Heiko Carstens <heiko.carstens@de.ibm.com>
Date: Wed, 14 Jun 2006 21:43:05 +0200
> From: Heiko Carstens <heiko.carstens@de.ibm.com>
>
> Fix lock usage in udp_ioctl().
>
> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
More likely the qeth driver shouldn't call into the socket code in
hardware interrupt context. From your logs that's what it seems is
happening.
The socket receive queue should only be touched in software
interrupt context, never in hardware interrupt context. That's
why the locking does BH disabling at best.
^ permalink raw reply
* type of sadb_x_kmprivate_reserved in pfkeyv2.h
From: Tushar Gohad @ 2006-06-14 22:13 UTC (permalink / raw)
To: netdev
[-- Attachment #1: Type: text/plain, Size: 701 bytes --]
Hi David and folks,
In include/linux/pfkeyv2.h, is the type 'u_int32_t' for
sadb_x_kmprivate_reserved intentional or just an error while bringing in
the PF_KEY IPsec extensions from KAME?
struct sadb_x_kmprivate {
uint16_t sadb_x_kmprivate_len;
uint16_t sadb_x_kmprivate_exttype;
u_int32_t sadb_x_kmprivate_reserved; <====
} __attribute__((packed));
This is causing erroneous ipsec-tools builds. How does the
__BIT_TYPES_DEFINED define work? Seems like u_int32_t does not get
defined in include/linux/types.h when building a userland program such
as ipsec-tools.
An easy fix is to change the type to uint32_t. Patch attached.
Thanks.
- Tushar
[-- Attachment #2: common_fix_pfkeyv2_type.patch --]
[-- Type: text/x-patch, Size: 849 bytes --]
Source: MontaVista Software, Inc.
MR: 19039
Type: Defect Fix
Disposition: needs submitting to kernel.org
Signed-off-by: Tushar Gohad <tgohad@mvista.com>
Description:
When bringing over the PF_KEY extensions for IPsec from the
KAME stack, folks probably forgot to change this only variable
to be of type uint32_t. Or otherwise. This is the easiest and
harmless fix.
Index: linux-p4/include/linux/pfkeyv2.h
===================================================================
--- linux-p4.orig/include/linux/pfkeyv2.h
+++ linux-p4/include/linux/pfkeyv2.h
@@ -159,7 +159,7 @@ struct sadb_spirange {
struct sadb_x_kmprivate {
uint16_t sadb_x_kmprivate_len;
uint16_t sadb_x_kmprivate_exttype;
- u_int32_t sadb_x_kmprivate_reserved;
+ uint32_t sadb_x_kmprivate_reserved;
} __attribute__((packed));
/* sizeof(struct sadb_x_kmprivate) == 8 */
^ permalink raw reply
* skge wake on lan failing
From: Sitsofe Wheeler @ 2006-06-14 21:10 UTC (permalink / raw)
To: netdev
Hello,
We have a bunch of PCI D-Link System Inc DGE-530T Gigabit Ethernet cards
which use the skge driver. However, the link light for a given card goes
off at the switch during a suspend to ram or power down even though an
"ethtool -s eth0 wol g" has been issued.
Can anyone shed any light on the problem?
--
Sitsofe | http://sucs.org/~sits/
^ permalink raw reply
* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Sridhar Samudrala @ 2006-06-14 20:52 UTC (permalink / raw)
To: Daniel Phillips, davem
Cc: Harald Welte, bidulock, Stephen Hemminger, netdev, linux-kernel
In-Reply-To: <44904C08.6020307@google.com>
On Wed, 2006-06-14 at 10:48 -0700, Daniel Phillips wrote:
>
> Did we settle the question of whether these particular exports should be
> EXPORT_SYMBOL_GPL?
When i submitted this patch, i didn't really think about the different
ways to export these symbols. I simply used the EXPORT_SYMBOL() that is
used by all the other exports in net/socket.c including kernel_sendmsg()
and kernel_recvmsg().
I am OK with either option(EXPORT_SYMBOL or EXPORT_SYMBOL_GPL) and i will
leave it to David Miller to make that decision at this point.
Thanks
Sridhar
^ permalink raw reply
* Re: PATCHv3 2.6.17-rc5 tulip free_irq() called too late
From: Francois Romieu @ 2006-06-14 20:47 UTC (permalink / raw)
To: Grant Grundler; +Cc: Jeff Garzik, Valerie Henson, Andrew Morton, netdev
In-Reply-To: <20060614181419.GA10365@colo.lackof.org>
Grant Grundler <grundler@parisc-linux.org> :
[...]
> I'm not keen on adding more code to tulip_interrupt() routine
> for something that rarely happens (compared to IRQs) and is handled
> outside the interrupt routine. I'm pretty sure stopping interrupts
> before stopping DMA is sufficient.
> Can you show an example where it doesn't work?
Shared irq.
The device has not quiesced, the kernel stop listening to it and the
neighbor device receives a late interruption from the network device.
--
Ueimor
^ permalink raw reply
* Re: [PATCH 1/2] e1000: fix netpoll with NAPI
From: Neil Horman @ 2006-06-14 20:41 UTC (permalink / raw)
To: Mitch Williams
Cc: Jeff Moyer, Kok, Auke-jan H, Matt Mackall, Garzik, Jeff, netdev,
Brandeburg, Jesse, Kok, Auke
In-Reply-To: <20060612180600.GB3790@hmsreliant.homelinux.net>
On Mon, Jun 12, 2006 at 02:06:00PM -0400, Neil Horman wrote:
> On Mon, Jun 12, 2006 at 09:42:14AM -0700, Mitch Williams wrote:
> > On Sun, 2006-06-11 at 17:13 -0700, Neil Horman wrote:
> > > Any further thoughts on this guys? I still think my last solution
> > > solves all of
> > > the netpoll problems, and isn't going to have any noticable impact on
> > > performance.
> > >
> > I haven't had time to evaluate performance on your patch (sorry!), but
> > after thinking about it, I agree that it should not have any noticeable
> > impact. OTOH, performance tuning is a funny thing, and things you think
> > won't cause problems often do.
> >
> Thats ok, I just didn't hear out of anyone on friday, so I was curious as to
> where we were on this. I don't have the ability to do any real world
> performance testing here, but I'll try to record the run time of the interrupt
> routine on a limited number of frames here.
>
Hey, as promised, I've done some rudimentary performance benchmarking on various
ways that we have talked about to solve this problem. As I previously mentioned
I didn't have the equipment to do any real full scale testing here, so what I
did was take a read of the real time counter at the start and end of the
e1000_intr routine with various patches applied, and I recorded the number of
ticks elapsed on the tsc during its run. I did this on my single cpu x86_64
machine here, using the latest unpatched e1000 driver as a base, and then
comparing it to the e1000 driver using my patch and separately with a patch that
spinlocks the e1000_clean_rx_irq routine (so as to serialize the critical
section that would otherwise be subject to data corruption. Here are my
results:
Base line:
Avg. 8145 Ticks on the tsc.
With my patch: http://marc.theaimsgroup.com/?l=linux-netdev&m=114970807606096&w=2
Avg. 8159 Ticks on the tsc. (+0.17% increase)
With a spinlock added to e1000_clean_rx_irq:
Avg. 8238 Ticks on the tsc. (+1.1% increase)
If you like I can send you the time stamp counter patch that I used, as well as
the patch which adds spinlocks to the clean routine. Note that the free running
counter values will vary so you probably want to look at percentage increase.
Either way, I think either solution provides very little impact on interrupt run
time. Given that my patch (granted using my test methodology here) is the
faster of the two, and arguably the more correct in terms of not using the poll
controller method to recieve frames, We should go with that patch.
Thoughts/opinions?
Neil
--
/***************************************************
*Neil Horman
*Software Engineer
*gpg keyid: 1024D / 0x92A74FA1 - http://pgp.mit.edu
***************************************************/
^ permalink raw reply
* Re: PATCHv3 2.6.17-rc5 tulip free_irq() called too late
From: Jeff Garzik @ 2006-06-14 19:51 UTC (permalink / raw)
To: Grant Grundler; +Cc: Valerie Henson, Andrew Morton, netdev
In-Reply-To: <20060614181419.GA10365@colo.lackof.org>
Grant Grundler wrote:
> On Wed, Jun 14, 2006 at 11:03:48AM -0400, Jeff Garzik wrote:
>> Grant Grundler wrote:
>>> Switching the order to be:
>>> tulip_stop_rxtx(tp); /* Stop DMA */
>>> free_irq (dev->irq, dev); /* no more races after this */
>>>
>>> still leaves us open to IRQs being delivered _after_ we've stopped DMA.
>> Correct. And that is the preferred, natural, logical, obvious order:
>>
>> 1) Turn things off.
>> 2) Wait for activity to cease.
>
> Patch v3 does this in two stages:
> 1) turn off tulip interrupts
> 2) free_irq() calls syncronize_irq() to handle pending IRQs
>
> then calls tulip_stop_rxtx() which:
> 1) tells tulip to stop DMA
> 2) poll until DMA completes
>
> After this we can free remaining resources.
You need to turn off the thing that generates work (DMA engine), before
turning off the thing that reaps work (irq handler).
>>> That in turn allows the interrupt handler to re-enable DMA again.
>> Then that would be a problem to solve... Some interrupt handlers will
>> test netif_running() or a driver-specific shutting-down flag,
>> specifically to avoid such behaviors.
>
> I'm not keen on adding more code to tulip_interrupt() routine
> for something that rarely happens (compared to IRQs) and is handled
> outside the interrupt routine. I'm pretty sure stopping interrupts
> before stopping DMA is sufficient.
> Can you show an example where it doesn't work?
It should be completely obvious that the chip is still generating
work... You don't want to leave the hardware in a position where it has
unacknowledged events.
Jeff
^ permalink raw reply
* [patch] ipv4: fix lock usage in udp_ioctl
From: Heiko Carstens @ 2006-06-14 19:43 UTC (permalink / raw)
To: David S. Miller, Jeff Garzik, Andrew Morton
Cc: linux-kernel, netdev, Ingo Molnar, Frank Pavlic
From: Heiko Carstens <heiko.carstens@de.ibm.com>
Fix lock usage in udp_ioctl().
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
---
udp_poll() seems to have the same problem, right?
As reported by the lock validator:
============================
[ BUG: illegal lock usage! ]
----------------------------
illegal {in-hardirq-W} -> {hardirq-on-W} usage.
syslogd/739 [HC0[0]:SC0[1]:HE1:SE0] takes:
(&list->lock){++..}, at: [<002e36d6>] udp_ioctl+0x96/0x100
{in-hardirq-W} state was registered at:
[<00062128>] lock_acquire+0x9c/0xc0
[<0036209e>] _spin_lock_irqsave+0x66/0x84
[<002912ce>] skb_dequeue+0x32/0xb0
[<00263160>] qeth_qdio_output_handler+0x3e8/0xf8c
[<00219fdc>] tiqdio_thinint_handler+0xde0/0x2234
[<0020448c>] do_adapter_IO+0x5c/0xa8
[<0020842c>] do_IRQ+0x13c/0x18c
[<000208a2>] io_no_vtime+0x16/0x1c
[<0001978c>] cpu_idle+0x1d0/0x20c
irq event stamp: 1694
hardirqs last enabled at (1693): [<003629c2>] _spin_unlock_irqrestore+0x92/0xa8
hardirqs last disabled at (1692): [<00362074>] _spin_lock_irqsave+0x3c/0x84
softirqs last enabled at (1682): [<0028c7c4>] release_sock+0xe4/0xf4
softirqs last disabled at (1694): [<00361f7e>] _spin_lock_bh+0x2e/0x70
other info that might help us debug this:
no locks held by syslogd/739.
stack backtrace:
000000000fd6c148 000000000de2f960 0000000000000002 0000000000000000
000000000de2fa00 000000000de2f978 000000000de2f978 000000000001737c
0000000000000000 0000000000000000 0000000000000000 0000000000000000
000000000de2f960 000000000000000c 000000000de2f960 000000000de2f9d0
000000000036fe70 000000000001737c 000000000de2f960 000000000de2f9b0
Call Trace:
([<000000000001730a>] show_trace+0x166/0x16c)
[<00000000000173d6>] show_stack+0xc6/0xf8
[<0000000000017436>] dump_stack+0x2e/0x3c
[<000000000005f978>] print_usage_bug+0x23c/0x250
[<00000000000607cc>] mark_lock+0x594/0x714
[<00000000000613be>] __lock_acquire+0x252/0xf20
[<0000000000062128>] lock_acquire+0x9c/0xc0
[<0000000000361fa8>] _spin_lock_bh+0x58/0x70
[<00000000002e36d6>] udp_ioctl+0x96/0x100
[<00000000002eadd6>] inet_ioctl+0x72/0x11c
[<00000000002893f2>] sock_ioctl+0x1ca/0x2c0
[<00000000000c13ee>] do_ioctl+0x56/0xe0
[<00000000000c14f2>] vfs_ioctl+0x7a/0x384
[<00000000000c184e>] sys_ioctl+0x52/0x84
[<00000000000e80a2>] do_ioctl32_pointer+0x2a/0x3c
[<00000000000e55c8>] compat_sys_ioctl+0x168/0x378
[<0000000000020338>] sysc_noemu+0x10/0x16
diffstat:
net/ipv4/udp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 3f93292..b15a17b 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -740,7 +740,7 @@ int udp_ioctl(struct sock *sk, int cmd,
unsigned long amount;
amount = 0;
- spin_lock_bh(&sk->sk_receive_queue.lock);
+ spin_lock_irq(&sk->sk_receive_queue.lock);
skb = skb_peek(&sk->sk_receive_queue);
if (skb != NULL) {
/*
@@ -750,7 +750,7 @@ int udp_ioctl(struct sock *sk, int cmd,
*/
amount = skb->len - sizeof(struct udphdr);
}
- spin_unlock_bh(&sk->sk_receive_queue.lock);
+ spin_unlock_irq(&sk->sk_receive_queue.lock);
return put_user(amount, (int __user *)arg);
}
^ permalink raw reply related
* Re: Remove Prism II support from Orinoco
From: Mike Kershaw @ 2006-06-14 19:09 UTC (permalink / raw)
To: Jar; +Cc: netdev
In-Reply-To: <448F02F1.3070001@pcuf.fi>
[-- Attachment #1: Type: text/plain, Size: 662 bytes --]
On Tue, Jun 13, 2006 at 09:24:49PM +0300, Jar wrote:
> It always loads itself with or without blacklist. That's why I have to
> do 'rm -f orinoco*.* && depmod -a' when the new kernel arrives. Seems
> that users are directed to use unsecure orinoco (wep) driver rather than
> secure hostap (wpa/wpa2,tkip,aes) driver for their prism2 hardware.
The hostap drivers are also much better behaved for rfmon than the
orinoco drivers for prism2.
-m
--
Mike Kershaw/Dragorn <dragorn@kismetwireless.net>
GPG Fingerprint: 3546 89DF 3C9D ED80 3381 A661 D7B2 8822 738B BDB1
Bus Error at 008BE426 while reading byte from DEADBEEF in User data space
[-- Attachment #2: Type: application/pgp-signature, Size: 191 bytes --]
^ permalink raw reply
* Re: [PATCH 6/5] rt2x00: per-queue TX flow control
From: Ivo van Doorn @ 2006-06-14 18:35 UTC (permalink / raw)
To: Jiri Benc; +Cc: netdev, John W. Linville
In-Reply-To: <20060614183635.546d3346@griffin.suse.cz>
[-- Attachment #1: Type: text/plain, Size: 17271 bytes --]
Hi,
On Wednesday 14 June 2006 18:36, Jiri Benc wrote:
> This is a patch for rt2x00 driver to do TX flow control.
>
> It is compile-tested only.
>
> Signed-off-by: Jiri Benc <jbenc@suse.cz>
I'll put my comments for the rt2400pci driver only,
since the same changes are made for each rt2x00 driver.
> --- dscape.orig/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
> +++ dscape/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
> @@ -1001,7 +1001,7 @@ rt2400pci_txdone(void *data)
> struct data_entry *entry;
> struct txd *txd;
> int tx_status;
> - int ack;
> + int ack, wake, queue;
>
> while (!rt2x00_ring_empty(ring)) {
> entry = rt2x00_get_data_entry_done(ring);
> @@ -1048,7 +1048,11 @@ rt2400pci_txdone(void *data)
> rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
> entry->skb = NULL;
>
> + wake = rt2x00_ring_full(ring);
> + queue = entry->tx_status.control.queue;
> rt2x00_ring_index_done_inc(ring);
> + if (wake)
> + ieee80211_wake_queue(ring->net_dev, queue);
> }
This will not give the correct result I fear, and it would cause (unwanted)
overhead of checking if the queue was full.
Queue_full can be checked when the loop starts, and the
waking of the queue can best be done after freeing all entries
and after the second check if the queue is still not full. (There is no guarentee
the while() loop will end while there are free entries in the queue)
> /*
> @@ -1541,24 +1545,31 @@ rt2400pci_tx(struct net_device *net_dev,
> ERROR("Attempt to send packet over invalid queue %d.\n"
> "Please file bug report to %s.\n",
> control->queue, DRV_PROJECT);
> - return NET_XMIT_DROP;
> + dev_kfree_skb_any(skb);
> + return NETDEV_TX_OK;
> }
>
> - if (rt2x00_ring_full(ring))
> - return NET_XMIT_DROP;
> + if (rt2x00_ring_full(ring)) {
> + ieee80211_stop_queue(net_dev, control->queue);
> + return NETDEV_TX_BUSY;
> + }
>
> entry = rt2x00_get_data_entry(ring);
> txd = entry->desc_addr;
>
> - if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC)
> - || rt2x00_get_field32(txd->word0, TXD_W0_VALID))
> - return NET_XMIT_DROP;
> + if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC) ||
> + rt2x00_get_field32(txd->word0, TXD_W0_VALID)) {
> + ieee80211_stop_queue(net_dev, control->queue);
> + return NETDEV_TX_BUSY;
> + }
Not sure if I am happy with this one. When this check is made,
it occurs after the ring_full check. This means that when this statement
is true, the queue is not full. Instead it has more of a meaning that something
has gone wrong with the queue and this should not have happened.
But this is not really a problem in the patch itself, just a problem I only
now recognize thanks to your patch. ;)
For the time being I'll add a debug message, but I need to find a method
to clean up the ring if this occurs.
This check currently does not happen in the rt2570 and rt73 USB drivers,
but it is safer to add them in there as well.
> memcpy(entry->data_addr, skb->data, skb->len);
> rt2400pci_write_tx_desc(rt2x00pci, txd, skb, control);
> entry->skb = skb;
>
> rt2x00_ring_index_inc(ring);
> + if (rt2x00_ring_full(ring))
> + ieee80211_stop_queue(net_dev, control->queue);
>
> rt2x00_register_read(rt2x00pci, TXCSR0, ®);
> if (control->queue == IEEE80211_TX_QUEUE_DATA0)
> @@ -1668,6 +1679,7 @@ rt2400pci_open(struct net_device *net_de
> rt2x00_register_write(rt2x00pci, CSR8, reg);
>
> SET_FLAG(rt2x00pci, RADIO_ENABLED);
> + ieee80211_start_queues(net_dev);
>
> return 0;
Based on Jiri's patch for rt2x00 driver to do TX flow control.
Signed-off-by Ivo van Doorn <IvDoorn@gmail.com>
---
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
index 8b856dd..946cf86 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
@@ -1002,6 +1002,12 @@ rt2400pci_txdone(void *data)
struct txd *txd;
int tx_status;
int ack;
+ int ring_full;
+
+ /*
+ * Store the current status of the ring.
+ */
+ ring_full = rt2x00_ring_full(ring);
while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
@@ -1062,6 +1068,16 @@ rt2400pci_txdone(void *data)
rt2x00pci->scan->status = SCANNING_READY;
complete(&rt2x00pci->scan->completion);
}
+
+ /*
+ * If the data ring was full before the txdone handler
+ * we must make sure the packet queue in the d80211 stack
+ * is reenabled when the txdone handler has finished.
+ */
+ entry = ring->entry;
+ if (ring_full && !rt2x00_ring_full(ring))
+ ieee80211_wake_queue(ring->net_dev,
+ entry->tx_status.control.queue);
}
static irqreturn_t
@@ -1541,18 +1557,26 @@ rt2400pci_tx(struct net_device *net_dev,
ERROR("Attempt to send packet over invalid queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
- return NET_XMIT_DROP;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
}
- if (rt2x00_ring_full(ring))
- return NET_XMIT_DROP;
+ if (rt2x00_ring_full(ring)) {
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
entry = rt2x00_get_data_entry(ring);
txd = entry->desc_addr;
if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC)
- || rt2x00_get_field32(txd->word0, TXD_W0_VALID))
- return NET_XMIT_DROP;
+ || rt2x00_get_field32(txd->word0, TXD_W0_VALID)) {
+ ERROR("Arrived at non-free entry in the non-full queue %d.\n"
+ "Please file bug report to %s.\n",
+ control->queue, DRV_PROJECT);
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
memcpy(entry->data_addr, skb->data, skb->len);
rt2400pci_write_tx_desc(rt2x00pci, txd, skb, control);
@@ -1560,6 +1584,9 @@ rt2400pci_tx(struct net_device *net_dev,
rt2x00_ring_index_inc(ring);
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue(net_dev, control->queue);
+
rt2x00_register_read(rt2x00pci, TXCSR0, ®);
if (control->queue == IEEE80211_TX_QUEUE_DATA0)
rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1);
@@ -1569,7 +1596,7 @@ rt2400pci_tx(struct net_device *net_dev,
rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1);
rt2x00_register_write(rt2x00pci, TXCSR0, reg);
- return 0;
+ return NETDEV_TX_OK;
}
static int
@@ -1669,6 +1696,8 @@ rt2400pci_open(struct net_device *net_de
SET_FLAG(rt2x00pci, RADIO_ENABLED);
+ ieee80211_start_queues(net_dev);
+
return 0;
exit_fail:
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500pci.c b/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
index 6aeaf1a..ca0edd5 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
@@ -1090,6 +1090,12 @@ rt2500pci_txdone(void *data)
struct txd *txd;
int tx_status;
int ack;
+ int ring_full;
+
+ /*
+ * Store the current status of the ring.
+ */
+ ring_full = rt2x00_ring_full(ring);
while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
@@ -1150,6 +1156,16 @@ rt2500pci_txdone(void *data)
rt2x00pci->scan->status = SCANNING_READY;
complete(&rt2x00pci->scan->completion);
}
+
+ /*
+ * If the data ring was full before the txdone handler
+ * we must make sure the packet queue in the d80211 stack
+ * is reenabled when the txdone handler has finished.
+ */
+ entry = ring->entry;
+ if (ring_full && !rt2x00_ring_full(ring))
+ ieee80211_wake_queue(ring->net_dev,
+ entry->tx_status.control.queue);
}
static irqreturn_t
@@ -1664,18 +1680,26 @@ rt2500pci_tx(struct net_device *net_dev,
ERROR("Attempt to send packet over invalid queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
- return NET_XMIT_DROP;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
}
- if (rt2x00_ring_full(ring))
- return NET_XMIT_DROP;
+ if (rt2x00_ring_full(ring)) {
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
entry = rt2x00_get_data_entry(ring);
txd = entry->desc_addr;
if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC)
- || rt2x00_get_field32(txd->word0, TXD_W0_VALID))
- return NET_XMIT_DROP;
+ || rt2x00_get_field32(txd->word0, TXD_W0_VALID)) {
+ ERROR("Arrived at non-free entry in the non-full queue %d.\n"
+ "Please file bug report to %s.\n",
+ control->queue, DRV_PROJECT);
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
memcpy(entry->data_addr, skb->data, skb->len);
rt2500pci_write_tx_desc(rt2x00pci, txd, skb, control);
@@ -1683,6 +1707,9 @@ rt2500pci_tx(struct net_device *net_dev,
rt2x00_ring_index_inc(ring);
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue(net_dev, control->queue);
+
rt2x00_register_read(rt2x00pci, TXCSR0, ®);
if (control->queue == IEEE80211_TX_QUEUE_DATA0)
rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1);
@@ -1692,7 +1719,7 @@ rt2500pci_tx(struct net_device *net_dev,
rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1);
rt2x00_register_write(rt2x00pci, TXCSR0, reg);
- return 0;
+ return NETDEV_TX_OK;
}
static int
@@ -1792,6 +1819,8 @@ rt2500pci_open(struct net_device *net_de
SET_FLAG(rt2x00pci, RADIO_ENABLED);
+ ieee80211_start_queues(net_dev);
+
return 0;
exit_fail:
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500usb.c b/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
index 1193e60..76c3a68 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
@@ -930,6 +930,12 @@ rt2500usb_txdone(void *data)
struct data_entry *entry;
struct txd *txd;
int ack;
+ int ring_full;
+
+ /*
+ * Store the current status of the ring.
+ */
+ ring_full = rt2x00_ring_full(ring);
while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
@@ -982,6 +988,16 @@ rt2500usb_txdone(void *data)
rt2x00usb->scan->status = SCANNING_READY;
complete(&rt2x00usb->scan->completion);
}
+
+ /*
+ * If the data ring was full before the txdone handler
+ * we must make sure the packet queue in the d80211 stack
+ * is reenabled when the txdone handler has finished.
+ */
+ entry = ring->entry;
+ if (ring_full && !rt2x00_ring_full(ring))
+ ieee80211_wake_queue(ring->net_dev,
+ entry->tx_status.control.queue);
}
static void
@@ -1376,15 +1392,26 @@ rt2500usb_tx(struct net_device *net_dev,
ERROR("Attempt to send packet over invalid queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
- return NET_XMIT_DROP;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
}
- if (rt2x00_ring_full(ring))
- return NET_XMIT_DROP;
+ if (rt2x00_ring_full(ring)) {
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
entry = rt2x00_get_data_entry(ring);
txd = rt2x00usb_txdesc_addr(entry);
+ if (GET_FLAG(entry, ENTRY_OWNER_NIC)) {
+ ERROR("Arrived at non-free entry in the non-full queue %d.\n"
+ "Please file bug report to %s.\n",
+ control->queue, DRV_PROJECT);
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
+
memcpy(rt2x00usb_txdata_addr(entry), skb->data, skb->len);
rt2500usb_write_tx_desc(rt2x00usb, txd, skb, control);
entry->skb = skb;
@@ -1402,7 +1429,10 @@ rt2500usb_tx(struct net_device *net_dev,
rt2x00_ring_index_inc(ring);
- return 0;
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue(net_dev, control->queue);
+
+ return NETDEV_TX_OK;
}
static inline void
@@ -1469,6 +1499,8 @@ rt2500usb_open(struct net_device *net_de
SET_FLAG(rt2x00usb, RADIO_ENABLED);
+ ieee80211_start_queues(net_dev);
+
return 0;
exit_fail:
diff --git a/drivers/net/wireless/d80211/rt2x00/rt61pci.c b/drivers/net/wireless/d80211/rt2x00/rt61pci.c
index fdbfa60..0799f9f 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt61pci.c
@@ -1353,6 +1353,12 @@ rt61pci_txdone(void *data)
int tx_status;
int ack;
int reg;
+ int ring_full;
+
+ /*
+ * Store the current status of the ring.
+ */
+ ring_full = rt2x00_ring_full(ring);
while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
@@ -1418,6 +1424,16 @@ rt61pci_txdone(void *data)
rt2x00pci->scan->status = SCANNING_READY;
complete(&rt2x00pci->scan->completion);
}
+
+ /*
+ * If the data ring was full before the txdone handler
+ * we must make sure the packet queue in the d80211 stack
+ * is reenabled when the txdone handler has finished.
+ */
+ entry = ring->entry;
+ if (ring_full && !rt2x00_ring_full(ring))
+ ieee80211_wake_queue(ring->net_dev,
+ entry->tx_status.control.queue);
}
static irqreturn_t
@@ -2100,18 +2116,26 @@ rt61pci_tx(struct net_device *net_dev,
ERROR("Attempt to send packet over invalid queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
- return NET_XMIT_DROP;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
}
- if (rt2x00_ring_full(ring))
- return NET_XMIT_DROP;
+ if (rt2x00_ring_full(ring)) {
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
entry = rt2x00_get_data_entry(ring);
txd = entry->desc_addr;
if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC)
- || rt2x00_get_field32(txd->word0, TXD_W0_VALID))
- return NET_XMIT_DROP;
+ || rt2x00_get_field32(txd->word0, TXD_W0_VALID)) {
+ ERROR("Arrived at non-free entry in the non-full queue %d.\n"
+ "Please file bug report to %s.\n",
+ control->queue, DRV_PROJECT);
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
memcpy(entry->data_addr, skb->data, skb->len);
rt61pci_write_tx_desc(rt2x00pci, txd, skb, control);
@@ -2119,6 +2143,9 @@ rt61pci_tx(struct net_device *net_dev,
rt2x00_ring_index_inc(ring);
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue(net_dev, control->queue);
+
rt2x00_register_read(rt2x00pci, TX_CNTL_CSR, ®);
if (control->queue == IEEE80211_TX_QUEUE_DATA0)
rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, 1);
@@ -2132,7 +2159,7 @@ rt61pci_tx(struct net_device *net_dev,
rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_MGMT, 1);
rt2x00_register_write(rt2x00pci, TX_CNTL_CSR, reg);
- return 0;
+ return NETDEV_TX_OK;
}
static int
@@ -2249,6 +2276,8 @@ rt61pci_open(struct net_device *net_dev)
SET_FLAG(rt2x00pci, RADIO_ENABLED);
+ ieee80211_start_queues(net_dev);
+
return 0;
exit_fail:
diff --git a/drivers/net/wireless/d80211/rt2x00/rt73usb.c b/drivers/net/wireless/d80211/rt2x00/rt73usb.c
index 48e9917..1871204 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt73usb.c
@@ -1094,6 +1094,12 @@ rt73usb_txdone(void *data)
struct data_entry *entry;
struct txd *txd;
int ack;
+ int ring_full;
+
+ /*
+ * Store the current status of the ring.
+ */
+ ring_full = rt2x00_ring_full(ring);
while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
@@ -1148,6 +1154,16 @@ rt73usb_txdone(void *data)
rt2x00usb->scan->status = SCANNING_READY;
complete(&rt2x00usb->scan->completion);
}
+
+ /*
+ * If the data ring was full before the txdone handler
+ * we must make sure the packet queue in the d80211 stack
+ * is reenabled when the txdone handler has finished.
+ */
+ entry = ring->entry;
+ if (ring_full && !rt2x00_ring_full(ring))
+ ieee80211_wake_queue(ring->net_dev,
+ entry->tx_status.control.queue);
}
static void
@@ -1668,15 +1684,26 @@ rt73usb_tx(struct net_device *net_dev,
ERROR("Attempt to send packet over invalid queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
- return NET_XMIT_DROP;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
}
- if (rt2x00_ring_full(ring))
- return NET_XMIT_DROP;
+ if (rt2x00_ring_full(ring)) {
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
entry = rt2x00_get_data_entry(ring);
txd = rt2x00usb_txdesc_addr(entry);
+ if (GET_FLAG(entry, ENTRY_OWNER_NIC)) {
+ ERROR("Arrived at non-free entry in the non-full queue %d.\n"
+ "Please file bug report to %s.\n",
+ control->queue, DRV_PROJECT);
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
+
memcpy(rt2x00usb_txdata_addr(entry), skb->data, skb->len);
rt73usb_write_tx_desc(rt2x00usb, txd, skb, control);
entry->skb = skb;
@@ -1694,7 +1721,10 @@ rt73usb_tx(struct net_device *net_dev,
rt2x00_ring_index_inc(ring);
- return 0;
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue(net_dev, control->queue);
+
+ return NETDEV_TX_OK;
}
static inline void
@@ -1766,6 +1796,8 @@ rt73usb_open(struct net_device *net_dev)
SET_FLAG(rt2x00usb, RADIO_ENABLED);
+ ieee80211_start_queues(net_dev);
+
return 0;
exit_fail:
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply related
* Re: PATCHv3 2.6.17-rc5 tulip free_irq() called too late
From: Grant Grundler @ 2006-06-14 18:14 UTC (permalink / raw)
To: Jeff Garzik; +Cc: Grant Grundler, Valerie Henson, Andrew Morton, netdev
In-Reply-To: <44902554.7010703@pobox.com>
On Wed, Jun 14, 2006 at 11:03:48AM -0400, Jeff Garzik wrote:
> Grant Grundler wrote:
> >Switching the order to be:
> > tulip_stop_rxtx(tp); /* Stop DMA */
> > free_irq (dev->irq, dev); /* no more races after this */
> >
> >still leaves us open to IRQs being delivered _after_ we've stopped DMA.
>
> Correct. And that is the preferred, natural, logical, obvious order:
>
> 1) Turn things off.
> 2) Wait for activity to cease.
Patch v3 does this in two stages:
1) turn off tulip interrupts
2) free_irq() calls syncronize_irq() to handle pending IRQs
then calls tulip_stop_rxtx() which:
1) tells tulip to stop DMA
2) poll until DMA completes
After this we can free remaining resources.
> >That in turn allows the interrupt handler to re-enable DMA again.
>
> Then that would be a problem to solve... Some interrupt handlers will
> test netif_running() or a driver-specific shutting-down flag,
> specifically to avoid such behaviors.
I'm not keen on adding more code to tulip_interrupt() routine
for something that rarely happens (compared to IRQs) and is handled
outside the interrupt routine. I'm pretty sure stopping interrupts
before stopping DMA is sufficient.
Can you show an example where it doesn't work?
This is important since I'm going to propose a new Documentation/pci.txt
based on this experience.
thanks,
grant
^ permalink raw reply
* RE: [openib-general] [PATCH v2 1/2] iWARP Connection Manager.
From: Caitlin Bestler @ 2006-06-14 18:06 UTC (permalink / raw)
To: Steve Wise, Sean Hefty
Cc: Andrew Morton, netdev, rdreier, linux-kernel, openib-general
netdev-owner@vger.kernel.org wrote:
> On Tue, 2006-06-13 at 16:46 -0500, Steve Wise wrote:
>> On Tue, 2006-06-13 at 14:36 -0700, Sean Hefty wrote:
>>>>> Er...no. It will lose this event. Depending on the event...the
>>>>> carnage varies. We'll take a look at this.
>>>>>
>>>>
>>>> This behavior is consistent with the Infiniband CM (see
>>>> drivers/infiniband/core/cm.c function cm_recv_handler()). But I
>>>> think we should at least log an error because a lost event will
>>>> usually stall the rdma connection.
>>>
>>> I believe that there's a difference here. For the Infiniband CM, an
>>> allocation error behaves the same as if the received MAD were lost
>>> or dropped. Since MADs are unreliable anyway, it's not so much that
>>> an IB CM event gets lost, as it doesn't ever occur. A remote CM
>>> should retry the send, which hopefully allows the
> connection to make forward progress.
>>>
>>
>> hmm. Ok. I see. I misunderstood the code in cm_recv_handler().
>>
>> Tom and I have been talking about what we can do to not drop the
>> event. Stay tuned.
>
> Here's a simple solution that solves the problem:
>
> For any given cm_id, there are a finite (and small) number of
> outstanding CM events that can be posted. So we just
> pre-allocate them when the cm_id is created and keep them on
> a free list hanging off of the cm_id struct. Then the event
> handler function will pull from this free list.
>
> The only case where there is any non-finite issue is on the
> passive listening cm_id. Each incoming connection request
> will consume a work struct. So based on client connects, we
> could run out of work structs.
> However, the CMA has the concept of a backlog, which is
> defined as the max number of pending unaccepted connection
> requests. So we allocate these work structs based on that
> number (or a computation based on that number), and if we run
> out, we simply drop the incoming connection request due to
> backlog overflow (I suggest we log the drop event too).
> When a MPA connection request is dropped, the (IETF
> conforming) MPA client will eventually time out the
> connection and the consumer can retry.
>
> Comments?
>
If the IWCM cannot accept a Connection Request event from
the driver then *someone* should generate a non-peer reject
MPA Response frame. Since the IWCM does not have the resources
to relay the event, it probably does not have the resources
to generate the MPA Response frame either. So simply returning
an "I'm Busy" error and expecting the driver to handle it
makes sense to me.
^ permalink raw reply
* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Brian F. G. Bidulock @ 2006-06-14 18:03 UTC (permalink / raw)
To: Daniel Phillips
Cc: Harald Welte, Stephen Hemminger, Sridhar Samudrala, netdev,
linux-kernel
In-Reply-To: <44904C08.6020307@google.com>
Daniel,
On Wed, 14 Jun 2006, Daniel Phillips wrote:
>
> Speaking as a former member of a "grey market" binary module vendor that
> came in from the cold I can assure you that the distinction between EXPORT
> and EXPORT_GPL _is_ meaningful. That tainted flag makes it extremely
> difficult to do deals with mainstream Linux companies and there is always
> the fear that it will turn into a legal problem. The latter bit tends to
> make venture capitalists nervous.
>
EXPORT_SYMBOL_GPL and the Tainted flag have nothing to do with each other.
^ permalink raw reply
* Re: [RFC/PATCH 1/2] in-kernel sockets API
From: Daniel Phillips @ 2006-06-14 17:48 UTC (permalink / raw)
To: Harald Welte
Cc: bidulock, Stephen Hemminger, Sridhar Samudrala, netdev,
linux-kernel
In-Reply-To: <20060614133022.GU11863@sunbeam.de.gnumonks.org>
Hi Harald,
You wrote:
> On Tue, Jun 13, 2006 at 02:12:41PM -0700, I wrote:
>
>>This has the makings of a nice stable internal kernel api. Why do we want
>>to provide this nice stable internal api to proprietary modules?
>
> because there is IMHO legally nothing we can do about it anyway.
Speaking as a former member of a "grey market" binary module vendor that
came in from the cold I can assure you that the distinction between EXPORT
and EXPORT_GPL _is_ meaningful. That tainted flag makes it extremely
difficult to do deals with mainstream Linux companies and there is always
the fear that it will turn into a legal problem. The latter bit tends to
make venture capitalists nervous.
That said, the EXPORT_GPL issue is not about black and white legal issues,
it is about gentle encouragement. In this case we are offering a clumsy,
on-the-metal, guaranteed-to-change-and-make-you-edit-code interface to
non-GPL-compatible modules and a decent, stable (in the deserves to live
sense) interface for the pure of heart. Gentle encouragement at exactly
the right level.
Did we settle the question of whether these particular exports should be
EXPORT_SYMBOL_GPL?
Regards,
Daniel
^ permalink raw reply
* Interrupt handling on SMP system
From: Majid Khan @ 2006-06-14 17:20 UTC (permalink / raw)
To: netdev
Hi all,
I had a few question regarding how interrupt handling work on linux
within a SMP systems.
1. Which processor gets the interrupt when a new packet arrives? Is
there any policy mechanism which can guide the interrupt to the idle
processor etc? Do the processors share an interrupt line and an
interrupt controller assign it to a specific processor?
2. When a soft IRQ is scheduled by the driver and picked up by a
ksoftirqd thread, does it get processed entirely on the same
processor? Does ksoftirqd/i thread processes the packets in the ith
processor queue only?
Regards,
Majid
^ permalink raw reply
* Re: tcp_slow_start_after_idle
From: Zach Brown @ 2006-06-14 17:09 UTC (permalink / raw)
To: David Miller; +Cc: netdev, jheffner
In-Reply-To: <20060613.223538.24611602.davem@davemloft.net>
David Miller wrote:
> Bringing back up this old topic:
>
> http://marc.theaimsgroup.com/?l=linux-netdev&m=114564962420171&w=2
>
> I've decided to add this tunable to the net-2.6.18 tree, patch below.
Nice, thanks for the heads-up. I'll pass the notice on to the guys who
were asking about this in that thread.
- z
^ permalink raw reply
* Re: tcp_slow_start_after_idle
From: Rick Jones @ 2006-06-14 16:46 UTC (permalink / raw)
To: David Miller; +Cc: netdev, zach.brown, jheffner
In-Reply-To: <20060613.223538.24611602.davem@davemloft.net>
> +tcp_slow_start_after_idle - BOOLEAN
> + If set, provide RFC2861 behavior and time out the congestion
> + window after an idle period. An idle period is defined at
> + the current RTO. If unset, the congestion window will not
> + be timed out after an idle period.
> + Default: 1
Did you mean "defined as" rather than "defined at?"
Also, does the congestion window "time out" or does it decay?
Perhaps:
tcp_slow_start_after_idle - BOOLEAN
If set, provide RFC2861 behavior and decay the congestion
window after the connection has been idle for the connection's
current RTO. If unset, the congestion window will not decay
when the connection has been idle.
Default: 1
> diff --git a/include/net/tcp.h b/include/net/tcp.h
> index de88c54..bfc71f9 100644
> --- a/include/net/tcp.h
> +++ b/include/net/tcp.h
> @@ -227,6 +227,7 @@ extern int sysctl_tcp_abc;
> extern int sysctl_tcp_mtu_probing;
> extern int sysctl_tcp_base_mss;
> extern int sysctl_tcp_workaround_signed_windows;
> +extern int sysctl_tcp_slow_start_after_idle;
> diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
> index 743016b..be6d929 100644
> --- a/net/ipv4/tcp_output.c
> +++ b/net/ipv4/tcp_output.c
> @@ -59,6 +59,9 @@ int sysctl_tcp_tso_win_divisor = 3;
> int sysctl_tcp_mtu_probing = 0;
> int sysctl_tcp_base_mss = 512;
>
> +/* By default, RFC2861 behavior. */
> +int sysctl_tcp_slow_start_after_idle = 1;
> +
Is this a candidate for "readmostly?"
rick jones
^ permalink raw reply
* [PATCH 6/5] rt2x00: per-queue TX flow control
From: Jiri Benc @ 2006-06-14 16:36 UTC (permalink / raw)
To: netdev; +Cc: John W. Linville, Ivo van Doorn
In-Reply-To: <20060612211454.409884000.midnight@suse.cz>
This is a patch for rt2x00 driver to do TX flow control.
It is compile-tested only.
Signed-off-by: Jiri Benc <jbenc@suse.cz>
---
drivers/net/wireless/d80211/rt2x00/rt2400pci.c | 26 ++++++++++++++++++-------
drivers/net/wireless/d80211/rt2x00/rt2500pci.c | 26 ++++++++++++++++++-------
drivers/net/wireless/d80211/rt2x00/rt2500usb.c | 18 +++++++++++++----
drivers/net/wireless/d80211/rt2x00/rt61pci.c | 26 ++++++++++++++++++-------
drivers/net/wireless/d80211/rt2x00/rt73usb.c | 18 +++++++++++++----
5 files changed, 85 insertions(+), 29 deletions(-)
--- dscape.orig/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
+++ dscape/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
@@ -1001,7 +1001,7 @@ rt2400pci_txdone(void *data)
struct data_entry *entry;
struct txd *txd;
int tx_status;
- int ack;
+ int ack, wake, queue;
while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
@@ -1048,7 +1048,11 @@ rt2400pci_txdone(void *data)
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
entry->skb = NULL;
+ wake = rt2x00_ring_full(ring);
+ queue = entry->tx_status.control.queue;
rt2x00_ring_index_done_inc(ring);
+ if (wake)
+ ieee80211_wake_queue(ring->net_dev, queue);
}
/*
@@ -1541,24 +1545,31 @@ rt2400pci_tx(struct net_device *net_dev,
ERROR("Attempt to send packet over invalid queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
- return NET_XMIT_DROP;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
}
- if (rt2x00_ring_full(ring))
- return NET_XMIT_DROP;
+ if (rt2x00_ring_full(ring)) {
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
entry = rt2x00_get_data_entry(ring);
txd = entry->desc_addr;
- if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC)
- || rt2x00_get_field32(txd->word0, TXD_W0_VALID))
- return NET_XMIT_DROP;
+ if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC) ||
+ rt2x00_get_field32(txd->word0, TXD_W0_VALID)) {
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
memcpy(entry->data_addr, skb->data, skb->len);
rt2400pci_write_tx_desc(rt2x00pci, txd, skb, control);
entry->skb = skb;
rt2x00_ring_index_inc(ring);
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue(net_dev, control->queue);
rt2x00_register_read(rt2x00pci, TXCSR0, ®);
if (control->queue == IEEE80211_TX_QUEUE_DATA0)
@@ -1668,6 +1679,7 @@ rt2400pci_open(struct net_device *net_de
rt2x00_register_write(rt2x00pci, CSR8, reg);
SET_FLAG(rt2x00pci, RADIO_ENABLED);
+ ieee80211_start_queues(net_dev);
return 0;
--- dscape.orig/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
+++ dscape/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
@@ -1089,7 +1089,7 @@ rt2500pci_txdone(void *data)
struct data_entry *entry;
struct txd *txd;
int tx_status;
- int ack;
+ int ack, wake, queue;
while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
@@ -1136,7 +1136,11 @@ rt2500pci_txdone(void *data)
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
entry->skb = NULL;
+ wake = rt2x00_ring_full(ring);
+ queue = entry->tx_status.control.queue;
rt2x00_ring_index_done_inc(ring);
+ if (wake)
+ ieee80211_wake_queue(ring->net_dev, queue);
}
/*
@@ -1664,24 +1668,31 @@ rt2500pci_tx(struct net_device *net_dev,
ERROR("Attempt to send packet over invalid queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
- return NET_XMIT_DROP;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
}
- if (rt2x00_ring_full(ring))
- return NET_XMIT_DROP;
+ if (rt2x00_ring_full(ring)) {
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
entry = rt2x00_get_data_entry(ring);
txd = entry->desc_addr;
- if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC)
- || rt2x00_get_field32(txd->word0, TXD_W0_VALID))
- return NET_XMIT_DROP;
+ if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC) ||
+ rt2x00_get_field32(txd->word0, TXD_W0_VALID)) {
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
memcpy(entry->data_addr, skb->data, skb->len);
rt2500pci_write_tx_desc(rt2x00pci, txd, skb, control);
entry->skb = skb;
rt2x00_ring_index_inc(ring);
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue(net_dev, control->queue);
rt2x00_register_read(rt2x00pci, TXCSR0, ®);
if (control->queue == IEEE80211_TX_QUEUE_DATA0)
@@ -1791,6 +1802,7 @@ rt2500pci_open(struct net_device *net_de
rt2x00_register_write(rt2x00pci, CSR8, reg);
SET_FLAG(rt2x00pci, RADIO_ENABLED);
+ ieee80211_start_queues(net_dev);
return 0;
--- dscape.orig/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
+++ dscape/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
@@ -929,7 +929,7 @@ rt2500usb_txdone(void *data)
ieee80211_dev_hw_data(ring->net_dev);
struct data_entry *entry;
struct txd *txd;
- int ack;
+ int ack, wake, queue;
while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
@@ -968,7 +968,11 @@ rt2500usb_txdone(void *data)
entry->skb = NULL;
+ wake = rt2x00_ring_full(ring);
+ queue = entry->tx_status.control.queue;
rt2x00_ring_index_done_inc(entry->ring);
+ if (wake)
+ ieee80211_wake_queue(ring->net_dev, queue);
}
/*
@@ -1376,11 +1380,14 @@ rt2500usb_tx(struct net_device *net_dev,
ERROR("Attempt to send packet over invalid queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
- return NET_XMIT_DROP;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_BUSY;
}
- if (rt2x00_ring_full(ring))
- return NET_XMIT_DROP;
+ if (rt2x00_ring_full(ring)) {
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
entry = rt2x00_get_data_entry(ring);
txd = rt2x00usb_txdesc_addr(entry);
@@ -1401,6 +1408,8 @@ rt2500usb_tx(struct net_device *net_dev,
usb_submit_urb(entry->urb, GFP_ATOMIC);
rt2x00_ring_index_inc(ring);
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue(net_dev, control->queue);
return 0;
}
@@ -1468,6 +1477,7 @@ rt2500usb_open(struct net_device *net_de
rt2500usb_enable_led(rt2x00usb);
SET_FLAG(rt2x00usb, RADIO_ENABLED);
+ ieee80211_start_queues(net_dev);
return 0;
--- dscape.orig/drivers/net/wireless/d80211/rt2x00/rt61pci.c
+++ dscape/drivers/net/wireless/d80211/rt2x00/rt61pci.c
@@ -1351,7 +1351,7 @@ rt61pci_txdone(void *data)
struct data_entry *entry;
struct txd *txd;
int tx_status;
- int ack;
+ int ack, wake, queue;
int reg;
while (!rt2x00_ring_empty(ring)) {
@@ -1402,7 +1402,11 @@ rt61pci_txdone(void *data)
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
entry->skb = NULL;
+ wake = rt2x00_ring_full(ring);
+ queue = entry->tx_status.control.queue;
rt2x00_ring_index_done_inc(ring);
+ if (wake)
+ ieee80211_wake_queue(ring->net_dev, queue);
}
/*
@@ -2100,24 +2104,31 @@ rt61pci_tx(struct net_device *net_dev,
ERROR("Attempt to send packet over invalid queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
- return NET_XMIT_DROP;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
}
- if (rt2x00_ring_full(ring))
- return NET_XMIT_DROP;
+ if (rt2x00_ring_full(ring)) {
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
entry = rt2x00_get_data_entry(ring);
txd = entry->desc_addr;
- if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC)
- || rt2x00_get_field32(txd->word0, TXD_W0_VALID))
- return NET_XMIT_DROP;
+ if (rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC) ||
+ rt2x00_get_field32(txd->word0, TXD_W0_VALID)) {
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
memcpy(entry->data_addr, skb->data, skb->len);
rt61pci_write_tx_desc(rt2x00pci, txd, skb, control);
entry->skb = skb;
rt2x00_ring_index_inc(ring);
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue(net_dev, control->queue);
rt2x00_register_read(rt2x00pci, TX_CNTL_CSR, ®);
if (control->queue == IEEE80211_TX_QUEUE_DATA0)
@@ -2248,6 +2259,7 @@ rt61pci_open(struct net_device *net_dev)
rt2x00_register_write(rt2x00pci, INT_SOURCE_CSR, reg);
SET_FLAG(rt2x00pci, RADIO_ENABLED);
+ ieee80211_start_queues(net_dev);
return 0;
--- dscape.orig/drivers/net/wireless/d80211/rt2x00/rt73usb.c
+++ dscape/drivers/net/wireless/d80211/rt2x00/rt73usb.c
@@ -1093,7 +1093,7 @@ rt73usb_txdone(void *data)
ieee80211_dev_hw_data(ring->net_dev);
struct data_entry *entry;
struct txd *txd;
- int ack;
+ int ack, wake, queue;
while (!rt2x00_ring_empty(ring)) {
entry = rt2x00_get_data_entry_done(ring);
@@ -1132,7 +1132,11 @@ rt73usb_txdone(void *data)
entry->skb = NULL;
+ wake = rt2x00_ring_full(ring);
+ queue = entry->tx_status.control.queue;
rt2x00_ring_index_done_inc(entry->ring);
+ if (wake)
+ ieee80211_wake_queue(ring->net_dev, queue);
}
/*
@@ -1668,11 +1672,14 @@ rt73usb_tx(struct net_device *net_dev,
ERROR("Attempt to send packet over invalid queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
- return NET_XMIT_DROP;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
}
- if (rt2x00_ring_full(ring))
- return NET_XMIT_DROP;
+ if (rt2x00_ring_full(ring)) {
+ ieee80211_stop_queue(net_dev, control->queue);
+ return NETDEV_TX_BUSY;
+ }
entry = rt2x00_get_data_entry(ring);
txd = rt2x00usb_txdesc_addr(entry);
@@ -1693,6 +1700,8 @@ rt73usb_tx(struct net_device *net_dev,
usb_submit_urb(entry->urb, GFP_ATOMIC);
rt2x00_ring_index_inc(ring);
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue(net_dev, control->queue);
return 0;
}
@@ -1765,6 +1774,7 @@ rt73usb_open(struct net_device *net_dev)
rt73usb_enable_led(rt2x00usb);
SET_FLAG(rt2x00usb, RADIO_ENABLED);
+ ieee80211_start_queues(net_dev);
return 0;
^ permalink raw reply
* Re: [openib-general] [PATCH v2 1/2] iWARP Connection Manager.
From: Steve Wise @ 2006-06-14 16:11 UTC (permalink / raw)
To: Sean Hefty; +Cc: Andrew Morton, netdev, rdreier, linux-kernel, openib-general
In-Reply-To: <1150235196.17394.91.camel@stevo-desktop>
On Tue, 2006-06-13 at 16:46 -0500, Steve Wise wrote:
> On Tue, 2006-06-13 at 14:36 -0700, Sean Hefty wrote:
> > >> Er...no. It will lose this event. Depending on the event...the carnage
> > >> varies. We'll take a look at this.
> > >>
> > >
> > >This behavior is consistent with the Infiniband CM (see
> > >drivers/infiniband/core/cm.c function cm_recv_handler()). But I think
> > >we should at least log an error because a lost event will usually stall
> > >the rdma connection.
> >
> > I believe that there's a difference here. For the Infiniband CM, an allocation
> > error behaves the same as if the received MAD were lost or dropped. Since MADs
> > are unreliable anyway, it's not so much that an IB CM event gets lost, as it
> > doesn't ever occur. A remote CM should retry the send, which hopefully allows
> > the connection to make forward progress.
> >
>
> hmm. Ok. I see. I misunderstood the code in cm_recv_handler().
>
> Tom and I have been talking about what we can do to not drop the event.
> Stay tuned.
Here's a simple solution that solves the problem:
For any given cm_id, there are a finite (and small) number of
outstanding CM events that can be posted. So we just pre-allocate them
when the cm_id is created and keep them on a free list hanging off of
the cm_id struct. Then the event handler function will pull from this
free list.
The only case where there is any non-finite issue is on the passive
listening cm_id. Each incoming connection request will consume a work
struct. So based on client connects, we could run out of work structs.
However, the CMA has the concept of a backlog, which is defined as the
max number of pending unaccepted connection requests. So we allocate
these work structs based on that number (or a computation based on that
number), and if we run out, we simply drop the incoming connection
request due to backlog overflow (I suggest we log the drop event too).
When a MPA connection request is dropped, the (IETF conforming) MPA
client will eventually time out the connection and the consumer can
retry.
Comments?
^ 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