diff options
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_main.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index a94c6d8826f..65edb56107f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3163,9 +3163,11 @@ static int estimate_periodic_work_badness(unsigned int state) 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; mutex_lock(&bcm->mutex); badness = estimate_periodic_work_badness(bcm->periodic_state); @@ -3173,7 +3175,18 @@ static void bcm43xx_periodic_work_handler(void *d) /* Periodic work will take a long time, so we want it to * be preemtible. */ - netif_tx_disable(bcm->net_dev); + + 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)) @@ -3198,6 +3211,7 @@ static void bcm43xx_periodic_work_handler(void *d) 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); |