From 427d5ecd270bad5b9ba15a42f0414accdfa4e2f8 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Tue, 16 May 2017 01:09:15 +0200 Subject: dmaengine: rcar-dmac: store channel IRQ in struct rcar_dmac_chan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The IRQ number is needed after probe to be able to add synchronisation points in other places in the driver when freeing resources and to implement a device_synchronize() callback. Store the IRQ number in the struct rcar_dmac_chan so that it can be used later. Signed-off-by: Niklas Söderlund Signed-off-by: Vinod Koul --- drivers/dma/sh/rcar-dmac.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index db41795fe42a..c68c3336bdad 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c @@ -144,6 +144,7 @@ struct rcar_dmac_chan_map { * @chan: base DMA channel object * @iomem: channel I/O memory base * @index: index of this channel in the controller + * @irq: channel IRQ * @src: slave memory address and size on the source side * @dst: slave memory address and size on the destination side * @mid_rid: hardware MID/RID for the DMA client using this channel @@ -161,6 +162,7 @@ struct rcar_dmac_chan { struct dma_chan chan; void __iomem *iomem; unsigned int index; + int irq; struct rcar_dmac_chan_slave src; struct rcar_dmac_chan_slave dst; @@ -1647,7 +1649,6 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac, struct dma_chan *chan = &rchan->chan; char pdev_irqname[5]; char *irqname; - int irq; int ret; rchan->index = index; @@ -1664,8 +1665,8 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac, /* Request the channel interrupt. */ sprintf(pdev_irqname, "ch%u", index); - irq = platform_get_irq_byname(pdev, pdev_irqname); - if (irq < 0) { + rchan->irq = platform_get_irq_byname(pdev, pdev_irqname); + if (rchan->irq < 0) { dev_err(dmac->dev, "no IRQ specified for channel %u\n", index); return -ENODEV; } @@ -1675,11 +1676,13 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac, if (!irqname) return -ENOMEM; - ret = devm_request_threaded_irq(dmac->dev, irq, rcar_dmac_isr_channel, + ret = devm_request_threaded_irq(dmac->dev, rchan->irq, + rcar_dmac_isr_channel, rcar_dmac_isr_channel_thread, 0, irqname, rchan); if (ret) { - dev_err(dmac->dev, "failed to request IRQ %u (%d)\n", irq, ret); + dev_err(dmac->dev, "failed to request IRQ %u (%d)\n", + rchan->irq, ret); return ret; } -- cgit v1.2.3-70-g09d2 From 30c45005a46bf55ba52086da5e090ec5a2f1c949 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Tue, 16 May 2017 01:09:16 +0200 Subject: dmaengine: rcar-dmac: implement device_synchronize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement the device_synchronize() callback which wait until a dma channel is stopped to provide a synchronization point. This protects the driver from multiple race conditions when terminating and freeing resources. E.g. the completion callback still running after device_terminate_all() has completed. Signed-off-by: Niklas Söderlund Signed-off-by: Vinod Koul --- drivers/dma/sh/rcar-dmac.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index c68c3336bdad..fb07cd5fe77b 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c @@ -1365,6 +1365,13 @@ done: spin_unlock_irqrestore(&rchan->lock, flags); } +static void rcar_dmac_device_synchronize(struct dma_chan *chan) +{ + struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan); + + synchronize_irq(rchan->irq); +} + /* ----------------------------------------------------------------------------- * IRQ handling */ @@ -1846,6 +1853,7 @@ static int rcar_dmac_probe(struct platform_device *pdev) engine->device_terminate_all = rcar_dmac_chan_terminate_all; engine->device_tx_status = rcar_dmac_tx_status; engine->device_issue_pending = rcar_dmac_issue_pending; + engine->device_synchronize = rcar_dmac_device_synchronize; ret = dma_async_device_register(engine); if (ret < 0) -- cgit v1.2.3-70-g09d2 From a1ed64efc5f68fc830fea08e96363d4459bb07a6 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Tue, 16 May 2017 01:09:17 +0200 Subject: dmaengine: rcar-dmac: wait for ISR to finish before freeing resources MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a race condition where the channel resources could be freed before the ISR had finished running resulting in a NULL pointer reference from the ISR. [ 167.148934] Unable to handle kernel NULL pointer dereference at virtual address 00000000 [ 167.157051] pgd = ffff80003c641000 [ 167.160449] [00000000] *pgd=000000007c507003, *pud=000000007c4ff003, *pmd=0000000000000000 [ 167.168719] Internal error: Oops: 96000046 [#1] PREEMPT SMP [ 167.174289] Modules linked in: [ 167.177348] CPU: 3 PID: 10547 Comm: dma_ioctl Not tainted 4.11.0-rc1-00001-g8d92afddc2f6633a #73 [ 167.186131] Hardware name: Renesas Salvator-X board based on r8a7795 (DT) [ 167.192917] task: ffff80003a411a00 task.stack: ffff80003bcd4000 [ 167.198850] PC is at rcar_dmac_chan_prep_sg+0xe0/0x400 [ 167.203985] LR is at rcar_dmac_chan_prep_sg+0x48/0x400 Based of previous work by: Hiroyuki Yokoyama . Signed-off-by: Niklas Söderlund Signed-off-by: Vinod Koul --- drivers/dma/sh/rcar-dmac.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index fb07cd5fe77b..d2cb4a0916e6 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c @@ -1010,7 +1010,11 @@ static void rcar_dmac_free_chan_resources(struct dma_chan *chan) rcar_dmac_chan_halt(rchan); spin_unlock_irq(&rchan->lock); - /* Now no new interrupts will occur */ + /* + * Now no new interrupts will occur, but one might already be + * running. Wait for it to finish before freeing resources. + */ + synchronize_irq(rchan->irq); if (rchan->mid_rid >= 0) { /* The caller is holding dma_list_mutex */ -- cgit v1.2.3-70-g09d2 From 5466c34f8425ccd24124ebdae6e3b6552195956d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 19 May 2017 09:27:47 +0200 Subject: dt-bindings: rcar-dmac: Document missing error interrupt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The documentation for the "interrupt-names" property only mentions the per-channel interrupts, while the error interrupt has always been mandatory, too. Fixes: 10f5c8438475909a ("dmaengine: rcar-dmac: Add device tree bindings documentation") Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Signed-off-by: Vinod Koul --- Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt index 3316a9c2e638..79a204d50234 100644 --- a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt +++ b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt @@ -30,8 +30,9 @@ Required Properties: - interrupts: interrupt specifiers for the DMAC, one for each entry in interrupt-names. -- interrupt-names: one entry per channel, named "ch%u", where %u is the - channel number ranging from zero to the number of channels minus one. +- interrupt-names: one entry for the error interrupt, named "error", plus one + entry per channel, named "ch%u", where %u is the channel number ranging from + zero to the number of channels minus one. - clock-names: "fck" for the functional clock - clocks: a list of phandle + clock-specifier pairs, one for each entry -- cgit v1.2.3-70-g09d2 From 33cb0880e0544c1553d37f4877fbd7a7a84f444f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 28 May 2017 11:30:44 +0200 Subject: dmaengine: use proper name for the R-Car SoC It is 'R-Car', not 'r-car'. No code or binding changes, only descriptive text. Signed-off-by: Wolfram Sang Acked-by: Geert Uytterhoeven Acked-by: Rob Herring Signed-off-by: Vinod Koul --- Documentation/devicetree/bindings/dma/shdma.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/dma/shdma.txt b/Documentation/devicetree/bindings/dma/shdma.txt index 2a3f3b8946b9..a91920a49433 100644 --- a/Documentation/devicetree/bindings/dma/shdma.txt +++ b/Documentation/devicetree/bindings/dma/shdma.txt @@ -1,6 +1,6 @@ * SHDMA Device Tree bindings -Sh-/r-mobile and r-car systems often have multiple identical DMA controller +Sh-/r-mobile and R-Car systems often have multiple identical DMA controller instances, capable of serving any of a common set of DMA slave devices, using the same configuration. To describe this topology we require all compatible SHDMA DT nodes to be placed under a DMA multiplexer node. All such compatible -- cgit v1.2.3-70-g09d2