ARM: PL08x: fix locking in tasklet
authorRussell King - ARM Linux <linux@arm.linux.org.uk>
Mon, 3 Jan 2011 22:31:24 +0000 (22:31 +0000)
committerDan Williams <dan.j.williams@intel.com>
Wed, 5 Jan 2011 03:16:10 +0000 (19:16 -0800)
Tasklets are run from an interruptible context.  The slave DMA functions
can be called from within IRQ handlers.  Taking the spinlock without
disabling interrupts allows an interrupt handler to run, which may try
to take the spinlock again, resulting in deadlock.  Fix this by using
the irqsave spinlocks.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Acked-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/dma/amba-pl08x.c

index 5d9a15652dba8846eba33447c5b5c1abcb61bf54..69cfb05e4d3ceb1361a060d0d5b0dcda8b218d84 100644 (file)
@@ -1627,11 +1627,12 @@ static void pl08x_tasklet(unsigned long data)
        struct pl08x_dma_chan *plchan = (struct pl08x_dma_chan *) data;
        struct pl08x_phy_chan *phychan = plchan->phychan;
        struct pl08x_driver_data *pl08x = plchan->host;
+       unsigned long flags;
 
        if (!plchan)
                BUG();
 
-       spin_lock(&plchan->lock);
+       spin_lock_irqsave(&plchan->lock, flags);
 
        if (plchan->at) {
                dma_async_tx_callback callback =
@@ -1728,7 +1729,7 @@ static void pl08x_tasklet(unsigned long data)
                }
        }
 
-       spin_unlock(&plchan->lock);
+       spin_unlock_irqrestore(&plchan->lock, flags);
 }
 
 static irqreturn_t pl08x_irq(int irq, void *dev)