From: Tao Hu Date: Wed, 11 Nov 2009 02:55:17 +0000 (-0800) Subject: omap: Fix race condition in omap dma driver X-Git-Tag: firefly_0821_release~11898^2~8 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ee90732456fe8e75406fdd3cd136a4bfb7ce31f5;p=firefly-linux-kernel-4.4.55.git omap: Fix race condition in omap dma driver The bug could cause irq enable bit of one DMA channel is cleared/set unexpectedly when 2 (or more) drivers are calling omap_request_dma()/omap_free_dma() simultaneously Signed-off-by: Fei Yang Signed-off-by: Tao Hu Signed-off-by: Tony Lindgren --- diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index b53125f41293..02ed94526aa3 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -691,13 +691,16 @@ static inline void disable_lnk(int lch) static inline void omap2_enable_irq_lch(int lch) { u32 val; + unsigned long flags; if (!cpu_class_is_omap2()) return; + spin_lock_irqsave(&dma_chan_lock, flags); val = dma_read(IRQENABLE_L0); val |= 1 << lch; dma_write(val, IRQENABLE_L0); + spin_unlock_irqrestore(&dma_chan_lock, flags); } int omap_request_dma(int dev_id, const char *dev_name, @@ -799,10 +802,13 @@ void omap_free_dma(int lch) if (cpu_class_is_omap2()) { u32 val; + + spin_lock_irqsave(&dma_chan_lock, flags); /* Disable interrupts */ val = dma_read(IRQENABLE_L0); val &= ~(1 << lch); dma_write(val, IRQENABLE_L0); + spin_unlock_irqrestore(&dma_chan_lock, flags); /* Clear the CSR register and IRQ status register */ dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch));