diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2011-05-02 03:59:02 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-05-22 23:49:59 -0400 |
commit | 31705e21f9b5a0628c043f88ff4d20488b47b8ab (patch) | |
tree | 220d1a8c0a83fec0450b7944d1af94ff9902b77f | |
parent | 467017b83b5bc445be5d275cf727b4f7ba3d2b2d (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.c | 16 |
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: | |||
1250 | eirq_err: | 1249 | eirq_err: |
1251 | #endif | 1250 | #endif |
1252 | rst_err: | 1251 | rst_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); |
1262 | emapdmars: | 1261 | emapdmars: |
1263 | iounmap(shdev->chan_reg); | 1262 | iounmap(shdev->chan_reg); |
1263 | synchronize_rcu(); | ||
1264 | emapchan: | 1264 | emapchan: |
1265 | kfree(shdev); | 1265 | kfree(shdev); |
1266 | ealloc: | 1266 | ealloc: |
@@ -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); |