Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 300e5f97 authored by Magnus Damm's avatar Magnus Damm Committed by Paul Mundt
Browse files

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: default avatarMagnus Damm <damm@opensource.se>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 26fc02ab
Loading
Loading
Loading
Loading
+23 −8
Original line number Original line Diff line number Diff line
@@ -1083,7 +1083,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
	unsigned long irqflags = IRQF_DISABLED,
	unsigned long irqflags = IRQF_DISABLED,
		chan_flag[SH_DMAC_MAX_CHANNELS] = {};
		chan_flag[SH_DMAC_MAX_CHANNELS] = {};
	int errirq, chan_irq[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 sh_dmae_device *shdev;
	struct resource *chan, *dmars, *errirq_res, *chanirq_res;
	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)) {
	    !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) {
		/* Special case - all multiplexed */
		/* Special case - all multiplexed */
		for (; irq_cnt < pdata->channel_num; irq_cnt++) {
		for (; irq_cnt < pdata->channel_num; irq_cnt++) {
			if (irq_cnt < SH_DMAC_MAX_CHANNELS) {
				chan_irq[irq_cnt] = chanirq_res->start;
				chan_irq[irq_cnt] = chanirq_res->start;
				chan_flag[irq_cnt] = IRQF_SHARED;
				chan_flag[irq_cnt] = IRQF_SHARED;
			} else {
				irq_cap = 1;
				break;
			}
		}
		}
	} else {
	} else {
		do {
		do {
@@ -1223,22 +1228,32 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
					"Found IRQ %d for channel %d\n",
					"Found IRQ %d for channel %d\n",
					i, irq_cnt);
					i, irq_cnt);
				chan_irq[irq_cnt++] = i;
				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,
			chanirq_res = platform_get_resource(pdev,
						IORESOURCE_IRQ, ++irqres);
						IORESOURCE_IRQ, ++irqres);
		} while (irq_cnt < pdata->channel_num && chanirq_res);
		} while (irq_cnt < pdata->channel_num && chanirq_res);
	}
	}


	if (irq_cnt < pdata->channel_num)
		goto eirqres;

	/* Create DMA Channel */
	/* 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]);
		err = sh_dmae_chan_probe(shdev, i, chan_irq[i], chan_flag[i]);
		if (err)
		if (err)
			goto chan_probe_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);
	pm_runtime_put(&pdev->dev);


	platform_set_drvdata(pdev, shdev);
	platform_set_drvdata(pdev, shdev);
@@ -1248,7 +1263,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)


chan_probe_err:
chan_probe_err:
	sh_dmae_chan_remove(shdev);
	sh_dmae_chan_remove(shdev);
eirqres:

#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
	free_irq(errirq, shdev);
	free_irq(errirq, shdev);
eirq_err:
eirq_err: