From: Guennadi Liakhovetski Date: Mon, 2 May 2011 07:59:02 +0000 (+0000) Subject: dmaengine: shdma: synchronize RCU before freeing, simplify spinlock X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=31705e21f9b5a0628c043f88ff4d20488b47b8ab;p=GitHub%2Fmoto-9609%2Fandroid_kernel_motorola_exynos9610.git dmaengine: shdma: synchronize RCU before freeing, simplify spinlock List elements, deleted using list_del_rcu(), cannot be freed without synchronising RCU. Further, the spinlock, used to protect the RCU writer, is called in process context, so, we don't have to save flags. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 00b5f320b0e8..dcc1b2139fff 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -1077,7 +1077,6 @@ static int __init sh_dmae_probe(struct platform_device *pdev) struct sh_dmae_pdata *pdata = pdev->dev.platform_data; unsigned long irqflags = IRQF_DISABLED, chan_flag[SH_DMAC_MAX_CHANNELS] = {}; - unsigned long flags; int errirq, chan_irq[SH_DMAC_MAX_CHANNELS]; int err, i, irq_cnt = 0, irqres = 0; struct sh_dmae_device *shdev; @@ -1143,9 +1142,9 @@ static int __init sh_dmae_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); - spin_lock_irqsave(&sh_dmae_lock, flags); + spin_lock_irq(&sh_dmae_lock); list_add_tail_rcu(&shdev->node, &sh_dmae_devices); - spin_unlock_irqrestore(&sh_dmae_lock, flags); + spin_unlock_irq(&sh_dmae_lock); /* reset dma controller - only needed as a test */ err = sh_dmae_rst(shdev); @@ -1250,9 +1249,9 @@ eirqres: eirq_err: #endif rst_err: - spin_lock_irqsave(&sh_dmae_lock, flags); + spin_lock_irq(&sh_dmae_lock); list_del_rcu(&shdev->node); - spin_unlock_irqrestore(&sh_dmae_lock, flags); + spin_unlock_irq(&sh_dmae_lock); pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -1261,6 +1260,7 @@ rst_err: iounmap(shdev->dmars); emapdmars: iounmap(shdev->chan_reg); + synchronize_rcu(); emapchan: kfree(shdev); ealloc: @@ -1276,7 +1276,6 @@ static int __exit sh_dmae_remove(struct platform_device *pdev) { struct sh_dmae_device *shdev = platform_get_drvdata(pdev); struct resource *res; - unsigned long flags; int errirq = platform_get_irq(pdev, 0); dma_async_device_unregister(&shdev->common); @@ -1284,9 +1283,9 @@ static int __exit sh_dmae_remove(struct platform_device *pdev) if (errirq > 0) free_irq(errirq, shdev); - spin_lock_irqsave(&sh_dmae_lock, flags); + spin_lock_irq(&sh_dmae_lock); list_del_rcu(&shdev->node); - spin_unlock_irqrestore(&sh_dmae_lock, flags); + spin_unlock_irq(&sh_dmae_lock); /* channel data remove */ sh_dmae_chan_remove(shdev); @@ -1297,6 +1296,7 @@ static int __exit sh_dmae_remove(struct platform_device *pdev) iounmap(shdev->dmars); iounmap(shdev->chan_reg); + synchronize_rcu(); kfree(shdev); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);