aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorMagnus Damm <damm@opensource.se>2011-05-24 06:31:20 -0400
committerPaul Mundt <lethal@linux-sh.org>2011-05-24 22:36:15 -0400
commit300e5f97d2a32196cbe03104cd6ffe2af97d9338 (patch)
tree1863d889aa757365d321e5b6a48db3c92979ac79 /drivers/dma
parent26fc02ab5551349b2e593829a76cb44328ee7f61 (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')
-rw-r--r--drivers/dma/shdma.c31
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
1249chan_probe_err: 1264chan_probe_err:
1250 sh_dmae_chan_remove(shdev); 1265 sh_dmae_chan_remove(shdev);
1251eirqres: 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);
1254eirq_err: 1269eirq_err: