aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2011-05-02 03:59:02 -0400
committerPaul Mundt <lethal@linux-sh.org>2011-05-22 23:49:59 -0400
commit31705e21f9b5a0628c043f88ff4d20488b47b8ab (patch)
tree220d1a8c0a83fec0450b7944d1af94ff9902b77f
parent467017b83b5bc445be5d275cf727b4f7ba3d2b2d (diff)
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 <g.liakhovetski@gmx.de> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--drivers/dma/shdma.c16
1 files changed, 8 insertions, 8 deletions
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)
1077 struct sh_dmae_pdata *pdata = pdev->dev.platform_data; 1077 struct sh_dmae_pdata *pdata = pdev->dev.platform_data;
1078 unsigned long irqflags = IRQF_DISABLED, 1078 unsigned long irqflags = IRQF_DISABLED,
1079 chan_flag[SH_DMAC_MAX_CHANNELS] = {}; 1079 chan_flag[SH_DMAC_MAX_CHANNELS] = {};
1080 unsigned long flags;
1081 int errirq, chan_irq[SH_DMAC_MAX_CHANNELS]; 1080 int errirq, chan_irq[SH_DMAC_MAX_CHANNELS];
1082 int err, i, irq_cnt = 0, irqres = 0; 1081 int err, i, irq_cnt = 0, irqres = 0;
1083 struct sh_dmae_device *shdev; 1082 struct sh_dmae_device *shdev;
@@ -1143,9 +1142,9 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
1143 pm_runtime_enable(&pdev->dev); 1142 pm_runtime_enable(&pdev->dev);
1144 pm_runtime_get_sync(&pdev->dev); 1143 pm_runtime_get_sync(&pdev->dev);
1145 1144
1146 spin_lock_irqsave(&sh_dmae_lock, flags); 1145 spin_lock_irq(&sh_dmae_lock);
1147 list_add_tail_rcu(&shdev->node, &sh_dmae_devices); 1146 list_add_tail_rcu(&shdev->node, &sh_dmae_devices);
1148 spin_unlock_irqrestore(&sh_dmae_lock, flags); 1147 spin_unlock_irq(&sh_dmae_lock);
1149 1148
1150 /* reset dma controller - only needed as a test */ 1149 /* reset dma controller - only needed as a test */
1151 err = sh_dmae_rst(shdev); 1150 err = sh_dmae_rst(shdev);
@@ -1250,9 +1249,9 @@ eirqres:
1250eirq_err: 1249eirq_err:
1251#endif 1250#endif
1252rst_err: 1251rst_err:
1253 spin_lock_irqsave(&sh_dmae_lock, flags); 1252 spin_lock_irq(&sh_dmae_lock);
1254 list_del_rcu(&shdev->node); 1253 list_del_rcu(&shdev->node);
1255 spin_unlock_irqrestore(&sh_dmae_lock, flags); 1254 spin_unlock_irq(&sh_dmae_lock);
1256 1255
1257 pm_runtime_put(&pdev->dev); 1256 pm_runtime_put(&pdev->dev);
1258 pm_runtime_disable(&pdev->dev); 1257 pm_runtime_disable(&pdev->dev);
@@ -1261,6 +1260,7 @@ rst_err:
1261 iounmap(shdev->dmars); 1260 iounmap(shdev->dmars);
1262emapdmars: 1261emapdmars:
1263 iounmap(shdev->chan_reg); 1262 iounmap(shdev->chan_reg);
1263 synchronize_rcu();
1264emapchan: 1264emapchan:
1265 kfree(shdev); 1265 kfree(shdev);
1266ealloc: 1266ealloc:
@@ -1276,7 +1276,6 @@ static int __exit sh_dmae_remove(struct platform_device *pdev)
1276{ 1276{
1277 struct sh_dmae_device *shdev = platform_get_drvdata(pdev); 1277 struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
1278 struct resource *res; 1278 struct resource *res;
1279 unsigned long flags;
1280 int errirq = platform_get_irq(pdev, 0); 1279 int errirq = platform_get_irq(pdev, 0);
1281 1280
1282 dma_async_device_unregister(&shdev->common); 1281 dma_async_device_unregister(&shdev->common);
@@ -1284,9 +1283,9 @@ static int __exit sh_dmae_remove(struct platform_device *pdev)
1284 if (errirq > 0) 1283 if (errirq > 0)
1285 free_irq(errirq, shdev); 1284 free_irq(errirq, shdev);
1286 1285
1287 spin_lock_irqsave(&sh_dmae_lock, flags); 1286 spin_lock_irq(&sh_dmae_lock);
1288 list_del_rcu(&shdev->node); 1287 list_del_rcu(&shdev->node);
1289 spin_unlock_irqrestore(&sh_dmae_lock, flags); 1288 spin_unlock_irq(&sh_dmae_lock);
1290 1289
1291 /* channel data remove */ 1290 /* channel data remove */
1292 sh_dmae_chan_remove(shdev); 1291 sh_dmae_chan_remove(shdev);
@@ -1297,6 +1296,7 @@ static int __exit sh_dmae_remove(struct platform_device *pdev)
1297 iounmap(shdev->dmars); 1296 iounmap(shdev->dmars);
1298 iounmap(shdev->chan_reg); 1297 iounmap(shdev->chan_reg);
1299 1298
1299 synchronize_rcu();
1300 kfree(shdev); 1300 kfree(shdev);
1301 1301
1302 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1302 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);