summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King - ARM Linux <linux@arm.linux.org.uk>2011-01-03 22:31:24 +0000
committerDan Williams <dan.j.williams@intel.com>2011-01-04 19:16:10 -0800
commitbf072af461c166964fb110cfcafccd752fbb4c64 (patch)
treea30b526ad74c2885ae9f8d9f10f412f6d7ff0f59
parent91aa5fadb831e7b6ea473a526a6b49c6dc4819ce (diff)
ARM: PL08x: fix locking in tasklet
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>
-rw-r--r--drivers/dma/amba-pl08x.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 5d9a15652db..69cfb05e4d3 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -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)