summaryrefslogtreecommitdiff
path: root/drivers/dma
diff options
context:
space:
mode:
authorMagnus Damm <damm@opensource.se>2011-05-24 14:31:20 +0400
committerPaul Mundt <lethal@linux-sh.org>2011-05-25 06:36:15 +0400
commit300e5f97d2a32196cbe03104cd6ffe2af97d9338 (patch)
tree1863d889aa757365d321e5b6a48db3c92979ac79 /drivers/dma
parent26fc02ab5551349b2e593829a76cb44328ee7f61 (diff)
downloadlinux-300e5f97d2a32196cbe03104cd6ffe2af97d9338.tar.xz
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)
unsigned long irqflags = IRQF_DISABLED,
chan_flag[SH_DMAC_MAX_CHANNELS] = {};
int errirq, chan_irq[SH_DMAC_MAX_CHANNELS];
- int err, i, irq_cnt = 0, irqres = 0;
+ int err, i, irq_cnt = 0, irqres = 0, irq_cap = 0;
struct sh_dmae_device *shdev;
struct resource *chan, *dmars, *errirq_res, *chanirq_res;
@@ -1208,8 +1208,13 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
!platform_get_resource(pdev, IORESOURCE_IRQ, 1)) {
/* Special case - all multiplexed */
for (; irq_cnt < pdata->channel_num; irq_cnt++) {
- chan_irq[irq_cnt] = chanirq_res->start;
- chan_flag[irq_cnt] = IRQF_SHARED;
+ if (irq_cnt < SH_DMAC_MAX_CHANNELS) {
+ chan_irq[irq_cnt] = chanirq_res->start;
+ chan_flag[irq_cnt] = IRQF_SHARED;
+ } else {
+ irq_cap = 1;
+ break;
+ }
}
} else {
do {
@@ -1223,22 +1228,32 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
"Found IRQ %d for channel %d\n",
i, irq_cnt);
chan_irq[irq_cnt++] = i;
+
+ if (irq_cnt >= SH_DMAC_MAX_CHANNELS)
+ break;
+ }
+
+ if (irq_cnt >= SH_DMAC_MAX_CHANNELS) {
+ irq_cap = 1;
+ break;
}
chanirq_res = platform_get_resource(pdev,
IORESOURCE_IRQ, ++irqres);
} while (irq_cnt < pdata->channel_num && chanirq_res);
}
- if (irq_cnt < pdata->channel_num)
- goto eirqres;
-
/* Create DMA Channel */
- for (i = 0; i < pdata->channel_num; i++) {
+ for (i = 0; i < irq_cnt; i++) {
err = sh_dmae_chan_probe(shdev, i, chan_irq[i], chan_flag[i]);
if (err)
goto chan_probe_err;
}
+ if (irq_cap)
+ dev_notice(&pdev->dev, "Attempting to register %d DMA "
+ "channels when a maximum of %d are supported.\n",
+ pdata->channel_num, SH_DMAC_MAX_CHANNELS);
+
pm_runtime_put(&pdev->dev);
platform_set_drvdata(pdev, shdev);
@@ -1248,7 +1263,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
chan_probe_err:
sh_dmae_chan_remove(shdev);
-eirqres:
+
#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
free_irq(errirq, shdev);
eirq_err: