diff mbox

[OMAP,sDMA] Fix for possible race condition in omap_free_dma()

Message ID EAF47CD23C76F840A9E7FCE10091EFAB02A93B8033@dbde02.ent.ti.com (mailing list archive)
State Accepted
Commit 77d75dad3c728ec6c6822c6c2a131c4dc3123fde
Headers show

Commit Message

Santosh Shilimkar March 29, 2009, 11:58 a.m. UTC
From: Santosh Shilimkar <santosh.shilimkar@ti.com>

Fix the possible race condition in omap_free_dma(). Function omap_free_dma() 
sets the dev_id = -1 and then accesses the channel afterwards to clear it.
But setting the dev_id=-1 makes the channel available for allocation again.
So it is possible someone else can grab it and results are unpredictable.
To avod this DMA channle is cleared first and then the dev_id = -1 is set.

Thanks to McNeil, Sean <sean.mcneil@ti.com> for ointing out this issue.

Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 arch/arm/plat-omap/dma.c |   13 ++++++-------
 1 files changed, 6 insertions(+), 7 deletions(-)


Regards,
Santosh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Artem Bityutskiy April 7, 2009, noon UTC | #1
Hi Tony,

I wonder, what happened to this patch?

Shilimkar, Santosh wrote:
> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
> 
> Fix the possible race condition in omap_free_dma(). Function omap_free_dma() 
> sets the dev_id = -1 and then accesses the channel afterwards to clear it.
> But setting the dev_id=-1 makes the channel available for allocation again.
> So it is possible someone else can grab it and results are unpredictable.
> To avod this DMA channle is cleared first and then the dev_id = -1 is set.
> 
> Thanks to McNeil, Sean <sean.mcneil@ti.com> for ointing out this issue.
> 
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> ---
>  arch/arm/plat-omap/dma.c |   13 ++++++-------
>  1 files changed, 6 insertions(+), 7 deletions(-)
> 
> Index: omapkernel/arch/arm/plat-omap/dma.c
> ===================================================================
> --- omapkernel.orig/arch/arm/plat-omap/dma.c
> +++ omapkernel/arch/arm/plat-omap/dma.c
> @@ -785,19 +785,12 @@ void omap_free_dma(int lch)
>  {
>  	unsigned long flags;
>  
> -	spin_lock_irqsave(&dma_chan_lock, flags);
>  	if (dma_chan[lch].dev_id == -1) {
>  		pr_err("omap_dma: trying to free unallocated DMA channel %d\n",
>  		       lch);
> -		spin_unlock_irqrestore(&dma_chan_lock, flags);
>  		return;
>  	}
>  
> -	dma_chan[lch].dev_id = -1;
> -	dma_chan[lch].next_lch = -1;
> -	dma_chan[lch].callback = NULL;
> -	spin_unlock_irqrestore(&dma_chan_lock, flags);
> -
>  	if (cpu_class_is_omap1()) {
>  		/* Disable all DMA interrupts for the channel. */
>  		dma_write(0, CICR(lch));
> @@ -823,6 +816,12 @@ void omap_free_dma(int lch)
>  		dma_write(0, CCR(lch));
>  		omap_clear_dma(lch);
>  	}
> +
> +	spin_lock_irqsave(&dma_chan_lock, flags);
> +	dma_chan[lch].dev_id = -1;
> +	dma_chan[lch].next_lch = -1;
> +	dma_chan[lch].callback = NULL;
> +	spin_unlock_irqrestore(&dma_chan_lock, flags);
>  }
>  EXPORT_SYMBOL(omap_free_dma);
>  
> 
> Regards,
> Santosh
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tony Lindgren April 7, 2009, 5:24 p.m. UTC | #2
This patch has been applied to the linux-omap
by youw fwiendly patch wobot.

Initial commit ID (Likely to change): 77d75dad3c728ec6c6822c6c2a131c4dc3123fde

PatchWorks
http://patchwork.kernel.org/patch/14966/

Git
http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git;a=commit;h=77d75dad3c728ec6c6822c6c2a131c4dc3123fde


--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

Index: omapkernel/arch/arm/plat-omap/dma.c
===================================================================
--- omapkernel.orig/arch/arm/plat-omap/dma.c
+++ omapkernel/arch/arm/plat-omap/dma.c
@@ -785,19 +785,12 @@  void omap_free_dma(int lch)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&dma_chan_lock, flags);
 	if (dma_chan[lch].dev_id == -1) {
 		pr_err("omap_dma: trying to free unallocated DMA channel %d\n",
 		       lch);
-		spin_unlock_irqrestore(&dma_chan_lock, flags);
 		return;
 	}
 
-	dma_chan[lch].dev_id = -1;
-	dma_chan[lch].next_lch = -1;
-	dma_chan[lch].callback = NULL;
-	spin_unlock_irqrestore(&dma_chan_lock, flags);
-
 	if (cpu_class_is_omap1()) {
 		/* Disable all DMA interrupts for the channel. */
 		dma_write(0, CICR(lch));
@@ -823,6 +816,12 @@  void omap_free_dma(int lch)
 		dma_write(0, CCR(lch));
 		omap_clear_dma(lch);
 	}
+
+	spin_lock_irqsave(&dma_chan_lock, flags);
+	dma_chan[lch].dev_id = -1;
+	dma_chan[lch].next_lch = -1;
+	dma_chan[lch].callback = NULL;
+	spin_unlock_irqrestore(&dma_chan_lock, flags);
 }
 EXPORT_SYMBOL(omap_free_dma);