summaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb
diff options
context:
space:
mode:
authorSwaminathan S <swami.iyer@ti.com>2009-12-15 12:30:00 +0100
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-23 20:34:17 +0100
commit93aa3dab008421789aa0f8865a62a52ae13269a3 (patch)
tree820ee4a9ffa037b121ee0308cc34c141c2a3df08 /drivers/usb/musb
parentUSB: musb: do not work if no gadget driver is loaded (diff)
downloadlinux-93aa3dab008421789aa0f8865a62a52ae13269a3.tar.xz
linux-93aa3dab008421789aa0f8865a62a52ae13269a3.zip
USB: musb: fix for crash in DM646x USB when (CPPI)DMA is enabled
Race condition exists between the cppi_interrupt handler and davinci_interrupt handler w.r.t completing a TX IO. Since DM646x has seperate DMA and USB endpoint interrupts cppi_interrupt handler needs to hold the lock while operating on the endpoint. Update over previous patch to avoid taking the lock if already taken. Tested on DM644x, DM355 and DM646x platforms. Signed-off-by: Swaminathan S <swami.iyer@ti.com> Acked-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> Acked-by: Anand Gadiyar <gadiyar@ti.com> Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/musb')
-rw-r--r--drivers/usb/musb/cppi_dma.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
index ef2332a9941d..a44a450c860d 100644
--- a/drivers/usb/musb/cppi_dma.c
+++ b/drivers/usb/musb/cppi_dma.c
@@ -1154,8 +1154,11 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id)
struct musb_hw_ep *hw_ep = NULL;
u32 rx, tx;
int i, index;
+ unsigned long flags;
cppi = container_of(musb->dma_controller, struct cppi, controller);
+ if (cppi->irq)
+ spin_lock_irqsave(&musb->lock, flags);
tibase = musb->ctrl_base;
@@ -1285,6 +1288,9 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id)
/* write to CPPI EOI register to re-enable interrupts */
musb_writel(tibase, DAVINCI_CPPI_EOI_REG, 0);
+ if (cppi->irq)
+ spin_unlock_irqrestore(&musb->lock, flags);
+
return IRQ_HANDLED;
}