All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
To: linux-sh@vger.kernel.org
Subject: [PATCH] dmaengine: rcar-dmac: Wait for IRQs completion when freeing channel
Date: Mon, 14 Sep 2015 12:26:13 +0000	[thread overview]
Message-ID: <1442233573-26684-1-git-send-email-laurent.pinchart+renesas@ideasonboard.com> (raw)

When freeing channel resources we need to ensure that no IRQ will occur
for the given channel. In order to do so the driver stops the hardware,
but an IRQ handler could still be running, especially given that the
channel IRQ is threaded. Fix it by waiting for pending IRQs completion
with synchronize_irq()

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/dma/sh/rcar-dmac.c | 37 +++++++++++++++++++------------------
 1 file changed, 19 insertions(+), 18 deletions(-)

Hi Morimoto-san,

This patch is compile-tested only. Would you be able to check if it fixes the
issue you've reported with SDHI and rcar-dmac ?

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 7820d07e7bee..da50c8f4d533 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -121,6 +121,7 @@ struct rcar_dmac_desc_page {
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
+ * @irq: channel IRQ number
  * @index: index of this channel in the controller
  * @src_xfer_size: size (in bytes) of hardware transfers on the source side
  * @dst_xfer_size: size (in bytes) of hardware transfers on the destination side
@@ -140,6 +141,7 @@ struct rcar_dmac_desc_page {
 struct rcar_dmac_chan {
 	struct dma_chan chan;
 	void __iomem *iomem;
+	int irq;
 	unsigned int index;
 
 	unsigned int src_xfer_size;
@@ -726,6 +728,15 @@ static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan)
 	rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr);
 }
 
+static void rcar_dmac_chan_halt_and_wait(struct rcar_dmac_chan *chan)
+{
+	spin_lock_irq(&chan->lock);
+	rcar_dmac_chan_halt(chan);
+	spin_unlock_irq(&chan->lock);
+
+	synchronize_irq(chan->irq);
+}
+
 static void rcar_dmac_chan_reinit(struct rcar_dmac_chan *chan)
 {
 	struct rcar_dmac_desc *desc, *_desc;
@@ -972,9 +983,7 @@ static void rcar_dmac_free_chan_resources(struct dma_chan *chan)
 	LIST_HEAD(list);
 
 	/* Protect against ISR */
-	spin_lock_irq(&rchan->lock);
-	rcar_dmac_chan_halt(rchan);
-	spin_unlock_irq(&rchan->lock);
+	rcar_dmac_chan_halt_and_wait(rchan);
 
 	/* Now no new interrupts will occur */
 
@@ -1121,17 +1130,8 @@ static int rcar_dmac_device_config(struct dma_chan *chan,
 static int rcar_dmac_chan_terminate_all(struct dma_chan *chan)
 {
 	struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
-	unsigned long flags;
-
-	spin_lock_irqsave(&rchan->lock, flags);
-	rcar_dmac_chan_halt(rchan);
-	spin_unlock_irqrestore(&rchan->lock, flags);
-
-	/*
-	 * FIXME: No new interrupt can occur now, but the IRQ thread might still
-	 * be running.
-	 */
 
+	rcar_dmac_chan_halt_and_wait(rchan);
 	rcar_dmac_chan_reinit(rchan);
 
 	return 0;
@@ -1524,7 +1524,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;
@@ -1541,8 +1540,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;
 	}
@@ -1552,11 +1551,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;
 	}
 
-- 
Regards,

Laurent Pinchart


             reply	other threads:[~2015-09-14 12:26 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-14 12:26 Laurent Pinchart [this message]
2015-09-15  0:11 ` [PATCH] dmaengine: rcar-dmac: Wait for IRQs completion when freeing channel Kuninori Morimoto
2015-10-05 14:11 ` Vinod Koul
2015-10-08 14:22 ` Laurent Pinchart
2015-10-08 14:51 ` Lars-Peter Clausen
2015-10-14 10:47 ` Vinod Koul
2015-10-14 11:02 ` Lars-Peter Clausen
2015-10-15  3:52 ` Vinod Koul
2015-10-15  7:35 ` Lars-Peter Clausen
2015-10-15 17:04 ` Laurent Pinchart
2015-10-15 17:09 ` Laurent Pinchart
2015-10-15 17:15 ` Lars-Peter Clausen
2015-10-16 13:47 ` Lars-Peter Clausen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1442233573-26684-1-git-send-email-laurent.pinchart+renesas@ideasonboard.com \
    --to=laurent.pinchart+renesas@ideasonboard.com \
    --cc=linux-sh@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.