diff options
author | Francois Romieu <romieu@fr.zoreil.com> | 2007-04-13 22:57:48 +0200 |
---|---|---|
committer | Adrian Bunk <bunk@stusta.de> | 2007-04-13 22:57:48 +0200 |
commit | 1ee709383b60148263f139af790c8b5a22c2e586 (patch) | |
tree | b9512bf25774325ae2e53083b6a2b519cd40cf33 /drivers | |
parent | 34215e7b2e7021740a562595218411e91d921d9f (diff) |
r8169: issue request_irq after the private data are completely initialized
The irq handler schedules a NAPI poll request unconditionally as soon as
the status register is not clean. It has been there - and wrong - for
ages but a recent timing change made it apparently easier to trigger.
Adrian Bunk:
backported to 2.6.16
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/r8169.c | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 6885a73eb83..55f182b800d 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -66,6 +66,7 @@ VERSION 2.2LK <2005/01/25> #include <linux/init.h> #include <linux/dma-mapping.h> +#include <asm/system.h> #include <asm/io.h> #include <asm/irq.h> @@ -481,6 +482,7 @@ static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, void __iomem *); static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); static void rtl8169_down(struct net_device *dev); +static void rtl8169_rx_clear(struct rtl8169_private *tp); #ifdef CONFIG_R8169_NAPI static int rtl8169_poll(struct net_device *dev, int *budget); @@ -1724,16 +1726,10 @@ static int rtl8169_open(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); struct pci_dev *pdev = tp->pci_dev; - int retval; + int retval = -ENOMEM; - rtl8169_set_rxbufsize(tp, dev); - - retval = - request_irq(dev->irq, rtl8169_interrupt, SA_SHIRQ, dev->name, dev); - if (retval < 0) - goto out; - retval = -ENOMEM; + rtl8169_set_rxbufsize(tp, dev); /* * Rx and Tx desscriptors needs 256 bytes alignment. @@ -1742,19 +1738,26 @@ static int rtl8169_open(struct net_device *dev) tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, &tp->TxPhyAddr); if (!tp->TxDescArray) - goto err_free_irq; + goto out; tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, &tp->RxPhyAddr); if (!tp->RxDescArray) - goto err_free_tx; + goto err_free_tx_0; retval = rtl8169_init_ring(dev); if (retval < 0) - goto err_free_rx; + goto err_free_rx_1; INIT_WORK(&tp->task, NULL, dev); + smp_mb(); + + retval = request_irq(dev->irq, rtl8169_interrupt, SA_SHIRQ, + dev->name, dev); + if (retval < 0) + goto err_release_ring_2; + rtl8169_hw_start(dev); rtl8169_request_timer(dev); @@ -1763,14 +1766,14 @@ static int rtl8169_open(struct net_device *dev) out: return retval; -err_free_rx: +err_release_ring_2: + rtl8169_rx_clear(tp); +err_free_rx_1: pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, tp->RxPhyAddr); -err_free_tx: +err_free_tx_0: pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, tp->TxPhyAddr); -err_free_irq: - free_irq(dev->irq, dev); goto out; } |