Skip to content

Commit

Permalink
dmaengine: rcar-dmac: don't use DMAC error interrupt
Browse files Browse the repository at this point in the history
rcar-dmac has 2 types of interrupt, 1) error IRQ (for all),
2) IRQ for each channels.
If error happens on some channels, the error IRQ will be handled
by 1), and "all" channels will be restarted.
But in this design, error handling itself will be problem for
non error channel users.
This patch removes 1) handler, and handles error IRQ on 2)

Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
[Kuninori: updated patch to adjust DMACHCR/DMAOR]
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tested-by: Nguyen Viet Dung <nv-dung@jinso.co.jp>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Vinod Koul <vkoul@kernel.org>
  • Loading branch information
morimoto authored and vinodkoul committed Jun 28, 2018
1 parent eb9fe60 commit 9203dbe
Showing 1 changed file with 22 additions and 50 deletions.
72 changes: 22 additions & 50 deletions drivers/dma/sh/rcar-dmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,8 @@ static void rcar_dmac_chan_start_xfer(struct rcar_dmac_chan *chan)
chcr |= RCAR_DMACHCR_DPM_DISABLED | RCAR_DMACHCR_IE;
}

rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr | RCAR_DMACHCR_DE);
rcar_dmac_chan_write(chan, RCAR_DMACHCR,
chcr | RCAR_DMACHCR_DE | RCAR_DMACHCR_CAIE);
}

static int rcar_dmac_init(struct rcar_dmac *dmac)
Expand Down Expand Up @@ -783,7 +784,8 @@ static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan)
u32 chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR);

chcr &= ~(RCAR_DMACHCR_DSE | RCAR_DMACHCR_DSIE | RCAR_DMACHCR_IE |
RCAR_DMACHCR_TE | RCAR_DMACHCR_DE);
RCAR_DMACHCR_TE | RCAR_DMACHCR_DE |
RCAR_DMACHCR_CAE | RCAR_DMACHCR_CAIE);
rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr);
rcar_dmac_chcr_de_barrier(chan);
}
Expand Down Expand Up @@ -812,12 +814,7 @@ static void rcar_dmac_chan_reinit(struct rcar_dmac_chan *chan)
}
}

static void rcar_dmac_stop(struct rcar_dmac *dmac)
{
rcar_dmac_write(dmac, RCAR_DMAOR, 0);
}

static void rcar_dmac_abort(struct rcar_dmac *dmac)
static void rcar_dmac_stop_all_chan(struct rcar_dmac *dmac)
{
unsigned int i;

Expand All @@ -829,11 +826,10 @@ static void rcar_dmac_abort(struct rcar_dmac *dmac)
spin_lock(&chan->lock);
rcar_dmac_chan_halt(chan);
spin_unlock(&chan->lock);

rcar_dmac_chan_reinit(chan);
}
}


/* -----------------------------------------------------------------------------
* Descriptors preparation
*/
Expand Down Expand Up @@ -1522,11 +1518,18 @@ static irqreturn_t rcar_dmac_isr_channel(int irq, void *dev)
u32 mask = RCAR_DMACHCR_DSE | RCAR_DMACHCR_TE;
struct rcar_dmac_chan *chan = dev;
irqreturn_t ret = IRQ_NONE;
bool reinit = false;
u32 chcr;

spin_lock(&chan->lock);

chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR);
if (chcr & RCAR_DMACHCR_CAE) {
rcar_dmac_chan_halt(chan);
reinit = true;
goto spin_lock_end;
}

if (chcr & RCAR_DMACHCR_TE)
mask |= RCAR_DMACHCR_DE;
rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr & ~mask);
Expand All @@ -1539,8 +1542,16 @@ static irqreturn_t rcar_dmac_isr_channel(int irq, void *dev)
if (chcr & RCAR_DMACHCR_TE)
ret |= rcar_dmac_isr_transfer_end(chan);

spin_lock_end:
spin_unlock(&chan->lock);

if (reinit) {
dev_err(chan->chan.device->dev, "Channel Address Error\n");

rcar_dmac_chan_reinit(chan);
ret = IRQ_HANDLED;
}

return ret;
}

Expand Down Expand Up @@ -1597,24 +1608,6 @@ static irqreturn_t rcar_dmac_isr_channel_thread(int irq, void *dev)
return IRQ_HANDLED;
}

static irqreturn_t rcar_dmac_isr_error(int irq, void *data)
{
struct rcar_dmac *dmac = data;

if (!(rcar_dmac_read(dmac, RCAR_DMAOR) & RCAR_DMAOR_AE))
return IRQ_NONE;

/*
* An unrecoverable error occurred on an unknown channel. Halt the DMAC,
* abort transfers on all channels, and reinitialize the DMAC.
*/
rcar_dmac_stop(dmac);
rcar_dmac_abort(dmac);
rcar_dmac_init(dmac);

return IRQ_HANDLED;
}

/* -----------------------------------------------------------------------------
* OF xlate and channel filter
*/
Expand Down Expand Up @@ -1784,8 +1777,6 @@ static int rcar_dmac_probe(struct platform_device *pdev)
struct rcar_dmac *dmac;
struct resource *mem;
unsigned int i;
char *irqname;
int irq;
int ret;

dmac = devm_kzalloc(&pdev->dev, sizeof(*dmac), GFP_KERNEL);
Expand Down Expand Up @@ -1824,17 +1815,6 @@ static int rcar_dmac_probe(struct platform_device *pdev)
if (IS_ERR(dmac->iomem))
return PTR_ERR(dmac->iomem);

irq = platform_get_irq_byname(pdev, "error");
if (irq < 0) {
dev_err(&pdev->dev, "no error IRQ specified\n");
return -ENODEV;
}

irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:error",
dev_name(dmac->dev));
if (!irqname)
return -ENOMEM;

/* Enable runtime PM and initialize the device. */
pm_runtime_enable(&pdev->dev);
ret = pm_runtime_get_sync(&pdev->dev);
Expand Down Expand Up @@ -1885,14 +1865,6 @@ static int rcar_dmac_probe(struct platform_device *pdev)
goto error;
}

ret = devm_request_irq(&pdev->dev, irq, rcar_dmac_isr_error, 0,
irqname, dmac);
if (ret) {
dev_err(&pdev->dev, "failed to request IRQ %u (%d)\n",
irq, ret);
return ret;
}

/* Register the DMAC as a DMA provider for DT. */
ret = of_dma_controller_register(pdev->dev.of_node, rcar_dmac_of_xlate,
NULL);
Expand Down Expand Up @@ -1932,7 +1904,7 @@ static void rcar_dmac_shutdown(struct platform_device *pdev)
{
struct rcar_dmac *dmac = platform_get_drvdata(pdev);

rcar_dmac_stop(dmac);
rcar_dmac_stop_all_chan(dmac);
}

static const struct of_device_id rcar_dmac_of_ids[] = {
Expand Down

0 comments on commit 9203dbe

Please sign in to comment.