diff options
author | Magnus Damm <damm@opensource.se> | 2011-05-24 06:31:20 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-05-24 22:36:15 -0400 |
commit | 300e5f97d2a32196cbe03104cd6ffe2af97d9338 (patch) | |
tree | 1863d889aa757365d321e5b6a48db3c92979ac79 /drivers/dma/shdma.c | |
parent | 26fc02ab5551349b2e593829a76cb44328ee7f61 (diff) |
dmaengine: shdma: Fix SH_DMAC_MAX_CHANNELS handling
Fix the shdma.c handing of SH_DMAC_MAX_CHANNELS
to avoid overwriting the chan_irq[] and chan_flag[]
arrays in the case of pdata->channel_num is larger
than SH_DMAC_MAX_CHANNELS.
With this patch applied up to SH_DMAC_MAX_CHANNELS
will be used by the shdma.c driver. If more channels
are available in the platform data the user will
be notified on the console.
Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/dma/shdma.c')
-rw-r--r-- | drivers/dma/shdma.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 3391b157d057..636e40925b16 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c | |||
@@ -1083,7 +1083,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) | |||
1083 | unsigned long irqflags = IRQF_DISABLED, | 1083 | unsigned long irqflags = IRQF_DISABLED, |
1084 | chan_flag[SH_DMAC_MAX_CHANNELS] = {}; | 1084 | chan_flag[SH_DMAC_MAX_CHANNELS] = {}; |
1085 | int errirq, chan_irq[SH_DMAC_MAX_CHANNELS]; | 1085 | int errirq, chan_irq[SH_DMAC_MAX_CHANNELS]; |
1086 | int err, i, irq_cnt = 0, irqres = 0; | 1086 | int err, i, irq_cnt = 0, irqres = 0, irq_cap = 0; |
1087 | struct sh_dmae_device *shdev; | 1087 | struct sh_dmae_device *shdev; |
1088 | struct resource *chan, *dmars, *errirq_res, *chanirq_res; | 1088 | struct resource *chan, *dmars, *errirq_res, *chanirq_res; |
1089 | 1089 | ||
@@ -1208,8 +1208,13 @@ static int __init sh_dmae_probe(struct platform_device *pdev) | |||
1208 | !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) { | 1208 | !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) { |
1209 | /* Special case - all multiplexed */ | 1209 | /* Special case - all multiplexed */ |
1210 | for (; irq_cnt < pdata->channel_num; irq_cnt++) { | 1210 | for (; irq_cnt < pdata->channel_num; irq_cnt++) { |
1211 | chan_irq[irq_cnt] = chanirq_res->start; | 1211 | if (irq_cnt < SH_DMAC_MAX_CHANNELS) { |
1212 | chan_flag[irq_cnt] = IRQF_SHARED; | 1212 | chan_irq[irq_cnt] = chanirq_res->start; |
1213 | chan_flag[irq_cnt] = IRQF_SHARED; | ||
1214 | } else { | ||
1215 | irq_cap = 1; | ||
1216 | break; | ||
1217 | } | ||
1213 | } | 1218 | } |
1214 | } else { | 1219 | } else { |
1215 | do { | 1220 | do { |
@@ -1223,22 +1228,32 @@ static int __init sh_dmae_probe(struct platform_device *pdev) | |||
1223 | "Found IRQ %d for channel %d\n", | 1228 | "Found IRQ %d for channel %d\n", |
1224 | i, irq_cnt); | 1229 | i, irq_cnt); |
1225 | chan_irq[irq_cnt++] = i; | 1230 | chan_irq[irq_cnt++] = i; |
1231 | |||
1232 | if (irq_cnt >= SH_DMAC_MAX_CHANNELS) | ||
1233 | break; | ||
1234 | } | ||
1235 | |||
1236 | if (irq_cnt >= SH_DMAC_MAX_CHANNELS) { | ||
1237 | irq_cap = 1; | ||
1238 | break; | ||
1226 | } | 1239 | } |
1227 | chanirq_res = platform_get_resource(pdev, | 1240 | chanirq_res = platform_get_resource(pdev, |
1228 | IORESOURCE_IRQ, ++irqres); | 1241 | IORESOURCE_IRQ, ++irqres); |
1229 | } while (irq_cnt < pdata->channel_num && chanirq_res); | 1242 | } while (irq_cnt < pdata->channel_num && chanirq_res); |
1230 | } | 1243 | } |
1231 | 1244 | ||
1232 | if (irq_cnt < pdata->channel_num) | ||
1233 | goto eirqres; | ||
1234 | |||
1235 | /* Create DMA Channel */ | 1245 | /* Create DMA Channel */ |
1236 | for (i = 0; i < pdata->channel_num; i++) { | 1246 | for (i = 0; i < irq_cnt; i++) { |
1237 | err = sh_dmae_chan_probe(shdev, i, chan_irq[i], chan_flag[i]); | 1247 | err = sh_dmae_chan_probe(shdev, i, chan_irq[i], chan_flag[i]); |
1238 | if (err) | 1248 | if (err) |
1239 | goto chan_probe_err; | 1249 | goto chan_probe_err; |
1240 | } | 1250 | } |
1241 | 1251 | ||
1252 | if (irq_cap) | ||
1253 | dev_notice(&pdev->dev, "Attempting to register %d DMA " | ||
1254 | "channels when a maximum of %d are supported.\n", | ||
1255 | pdata->channel_num, SH_DMAC_MAX_CHANNELS); | ||
1256 | |||
1242 | pm_runtime_put(&pdev->dev); | 1257 | pm_runtime_put(&pdev->dev); |
1243 | 1258 | ||
1244 | platform_set_drvdata(pdev, shdev); | 1259 | platform_set_drvdata(pdev, shdev); |
@@ -1248,7 +1263,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) | |||
1248 | 1263 | ||
1249 | chan_probe_err: | 1264 | chan_probe_err: |
1250 | sh_dmae_chan_remove(shdev); | 1265 | sh_dmae_chan_remove(shdev); |
1251 | eirqres: | 1266 | |
1252 | #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) | 1267 | #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) |
1253 | free_irq(errirq, shdev); | 1268 | free_irq(errirq, shdev); |
1254 | eirq_err: | 1269 | eirq_err: |