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 <[EMAIL PROTECTED]>

diff -puN drivers/net/r8169.c~r8169-450 drivers/net/r8169.c
--- a/drivers/net/r8169.c~r8169-450     2005-02-23 21:35:21.112521942 +0100
+++ b/drivers/net/r8169.c       2005-02-23 21:35:21.117521120 +0100
@@ -1648,10 +1648,10 @@ static int rtl8169_change_mtu(struct net
        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_devi
 {
        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_devi
 
        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_devi
 
        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);

_
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to