From 35f2138b80dfad1d209c49cd49aa137f1a9f33e1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Romieu?= Date: Wed, 23 Feb 2005 08:19:19 -0500 Subject: [PATCH] [PATCH] r8169: IRQ races during change of mtu IRQ races during change of mtu - NAPI poll must be enabled prior to IRQ activation or the IRQ handler will not know what to do with an incoming packet; - rtl8169_down() needs to try twice to sync with the IRQ handler when it is not issued under !netif_running() protection. Both changes make it safe to request a change of mtu on a live device. Signed-off-by: Francois Romieu Signed-off-by: Jeff Garzik --- drivers/net/r8169.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 3e5a103b315b..b356788d898c 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1648,10 +1648,10 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) if (ret < 0) goto out; - rtl8169_hw_start(dev); - netif_poll_enable(dev); + rtl8169_hw_start(dev); + rtl8169_request_timer(dev); out: @@ -2352,6 +2352,7 @@ static void rtl8169_down(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; + unsigned int poll_locked = 0; rtl8169_delete_timer(dev); @@ -2359,6 +2360,7 @@ static void rtl8169_down(struct net_device *dev) flush_scheduled_work(); +core_down: spin_lock_irq(&tp->lock); /* Stop the chip's Tx and Rx DMA processes. */ @@ -2375,11 +2377,28 @@ static void rtl8169_down(struct net_device *dev) synchronize_irq(dev->irq); - netif_poll_disable(dev); + if (!poll_locked) { + netif_poll_disable(dev); + poll_locked++; + } /* Give a racing hard_start_xmit a few cycles to complete. */ synchronize_kernel(); + /* + * And now for the 50k$ question: are IRQ disabled or not ? + * + * Two paths lead here: + * 1) dev->close + * -> netif_running() is available to sync the current code and the + * IRQ handler. See rtl8169_interrupt for details. + * 2) dev->change_mtu + * -> rtl8169_poll can not be issued again and re-enable the + * interruptions. Let's simply issue the IRQ down sequence again. + */ + if (RTL_R16(IntrMask)) + goto core_down; + rtl8169_tx_clear(tp); rtl8169_rx_clear(tp); -- 2.39.5