Hendrik Sattler wrote:
Am Sonntag 29 Oktober 2006 00:52 schrieb Larry Finger:
From: Michael Buesch <[EMAIL PROTECTED]>

This fixes a netdev watchdog timeout problem.
The software needs to call netif_tx_disable before running the
hardware calibration code. The problem condition can be shown by the
following timegraph.

|---5secs - ~10 jiffies time---|---|OOPS

^                              ^
last real TX                   periodic work stops netif

Is this patch also available for 2.6.18.x?

It will not be submitted to -stable; however, the full netdev watchdog timeout patch for 2.6.18.1 is attached. Please let me know if it still breaks.

Thanks,

Larry
Index: linux-2.6.18/drivers/net/wireless/bcm43xx/bcm43xx_main.c
===================================================================
--- linux-2.6.18.orig/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ linux-2.6.18/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -3159,24 +3159,42 @@ static int estimate_periodic_work_badnes
 static void bcm43xx_periodic_work_handler(void *d)
 {
        struct bcm43xx_private *bcm = d;
+       struct net_device *net_dev = bcm->net_dev;
        unsigned long flags;
        u32 savedirqs = 0;
        int badness;
+       unsigned long orig_trans_start = 0;
 
-       badness = estimate_periodic_work_badness(bcm->periodic_state);
        mutex_lock(&bcm->mutex);
-       netif_tx_disable(bcm->net_dev);
-       spin_lock_irqsave(&bcm->irq_lock, flags);
+       badness = estimate_periodic_work_badness(bcm->periodic_state);
        if (badness > BADNESS_LIMIT) {
                /* Periodic work will take a long time, so we want it to
                 * be preemtible.
                 */
+
+               netif_tx_lock_bh(net_dev);
+               /* We must fake a started transmission here, as we are going to
+                * disable TX. If we wouldn't fake a TX, it would be possible to
+                * trigger the netdev watchdog, if the last real TX is already
+                * some time on the past (slightly less than 5secs)
+                */
+               orig_trans_start = net_dev->trans_start;
+               net_dev->trans_start = jiffies;
+               netif_stop_queue(net_dev);
+               netif_tx_unlock_bh(net_dev);
+
+               spin_lock_irqsave(&bcm->irq_lock, flags);
                bcm43xx_mac_suspend(bcm);
                if (bcm43xx_using_pio(bcm))
                        bcm43xx_pio_freeze_txqueues(bcm);
                savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
                spin_unlock_irqrestore(&bcm->irq_lock, flags);
                bcm43xx_synchronize_irq(bcm);
+       } else {
+               /* Periodic work should take short time, so we want low
+                * locking overhead.
+                */
+               spin_lock_irqsave(&bcm->irq_lock, flags);
        }
 
        do_periodic_work(bcm);
@@ -3188,10 +3206,11 @@ static void bcm43xx_periodic_work_handle
                if (bcm43xx_using_pio(bcm))
                        bcm43xx_pio_thaw_txqueues(bcm);
                bcm43xx_mac_enable(bcm);
+               netif_wake_queue(bcm->net_dev);
+               net_dev->trans_start = orig_trans_start;
        }
        mmiowb();
        spin_unlock_irqrestore(&bcm->irq_lock, flags);
-       netif_wake_queue(bcm->net_dev);
        mutex_unlock(&bcm->mutex);
 }
 
_______________________________________________
Bcm43xx-dev mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/bcm43xx-dev

Reply via email to