b44: fix resume, request_irq after hw reset
authorJames Hogan <james@albanarts.com>
Sun, 17 Oct 2010 01:48:59 +0000 (01:48 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 21 Oct 2010 11:25:50 +0000 (04:25 -0700)
On resume, call request_irq() after resetting the hardware rather than
before. It's a shared interrupt so the handler could be called
immediately if another device on the same irq interrupts (and will be
called immediately if CONFIG_DEBUG_SHIRQ=y), but unless the hardware is
reinitialised with b44_init_hw() the read of the interrupt status
register will hang the system.

Signed-off-by: James Hogan <james@albanarts.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/b44.c

index 8e7c8a8e61c7756231191e6dc379732432a0e9b4..171da7f751085acbecb90191634c2daa032e7247 100644 (file)
@@ -2296,18 +2296,27 @@ static int b44_resume(struct ssb_device *sdev)
        if (!netif_running(dev))
                return 0;
 
+       spin_lock_irq(&bp->lock);
+       b44_init_rings(bp);
+       b44_init_hw(bp, B44_FULL_RESET);
+       spin_unlock_irq(&bp->lock);
+
+       /*
+        * As a shared interrupt, the handler can be called immediately. To be
+        * able to check the interrupt status the hardware must already be
+        * powered back on (b44_init_hw).
+        */
        rc = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev);
        if (rc) {
                netdev_err(dev, "request_irq failed\n");
+               spin_lock_irq(&bp->lock);
+               b44_halt(bp);
+               b44_free_rings(bp);
+               spin_unlock_irq(&bp->lock);
                return rc;
        }
 
-       spin_lock_irq(&bp->lock);
-
-       b44_init_rings(bp);
-       b44_init_hw(bp, B44_FULL_RESET);
        netif_device_attach(bp->dev);
-       spin_unlock_irq(&bp->lock);
 
        b44_enable_ints(bp);
        netif_wake_queue(dev);