Commit 35f2138b authored by François Romieu's avatar François Romieu Committed by Jeff Garzik

[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: default avatarFrancois Romieu <romieu@fr.zoreil.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent c2a201dd
...@@ -1648,10 +1648,10 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) ...@@ -1648,10 +1648,10 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
if (ret < 0) if (ret < 0)
goto out; goto out;
rtl8169_hw_start(dev);
netif_poll_enable(dev); netif_poll_enable(dev);
rtl8169_hw_start(dev);
rtl8169_request_timer(dev); rtl8169_request_timer(dev);
out: out:
...@@ -2352,6 +2352,7 @@ static void rtl8169_down(struct net_device *dev) ...@@ -2352,6 +2352,7 @@ static void rtl8169_down(struct net_device *dev)
{ {
struct rtl8169_private *tp = netdev_priv(dev); struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr; void __iomem *ioaddr = tp->mmio_addr;
unsigned int poll_locked = 0;
rtl8169_delete_timer(dev); rtl8169_delete_timer(dev);
...@@ -2359,6 +2360,7 @@ static void rtl8169_down(struct net_device *dev) ...@@ -2359,6 +2360,7 @@ static void rtl8169_down(struct net_device *dev)
flush_scheduled_work(); flush_scheduled_work();
core_down:
spin_lock_irq(&tp->lock); spin_lock_irq(&tp->lock);
/* Stop the chip's Tx and Rx DMA processes. */ /* Stop the chip's Tx and Rx DMA processes. */
...@@ -2375,11 +2377,28 @@ static void rtl8169_down(struct net_device *dev) ...@@ -2375,11 +2377,28 @@ static void rtl8169_down(struct net_device *dev)
synchronize_irq(dev->irq); 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. */ /* Give a racing hard_start_xmit a few cycles to complete. */
synchronize_kernel(); 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_tx_clear(tp);
rtl8169_rx_clear(tp); rtl8169_rx_clear(tp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment