All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: linux-sh@vger.kernel.org
Subject: Re: Issues with rcar-dmac and sh-sci
Date: Fri, 14 Aug 2015 23:42:21 +0000	[thread overview]
Message-ID: <1862788.NYkJDoIfhG@avalon> (raw)
In-Reply-To: <alpine.DEB.2.10.1507162026200.821@ayla.of.borg>

Hi Geert,

On Thursday 16 July 2015 20:36:49 Geert Uytterhoeven wrote:
> 	Hi Laurent,
> 
> While working on DMA for R-Car Gen2 using the sh-sci serial driver with
> rcar-dmac, I ran into two issues:
>
>   1. Unlike the old shdmac DMA engine driver, the new rcar-dmac DMA
>      engine driver does not support resubmitting a DMA descriptor.
>      I first tried the patch below, until I ran into the race condition,
>      after which I changed sh-sci to not reuse DMA descriptors.

Is reusing descriptors something that the DMA engine API explicitly allows ?

>   2. rcar_dmac_chan_get_residue() has:
> 
> static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan,
>                                                dma_cookie_t cookie)
> {
>         struct rcar_dmac_desc *desc = chan->desc.running;
>         ...
> 
>         /*
>          * If the cookie doesn't correspond to the currently running
> transfer * then the descriptor hasn't been processed yet, and the residue
> is       * equal to the full descriptor size.
>          */
>         if (cookie != desc->async_tx.cookie)
>                 return desc->size;
> 
>      If the cookie doesn't correspond to the currently running transfer,
>      it returns the full descriptor size of the _currently running
>      transfer_, not the transfer the cookie corresponds to.

How about the following (untested) patch ?

From 131968befd5de3400631b879b1574beea27b8239 Mon Sep 17 00:00:00 2001
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Date: Sat, 15 Aug 2015 01:28:28 +0300
Subject: [PATCH] dmaengine: rcar-dmac: Fix residue reporting for pending
 descriptors

Cookies corresponding to pending transfers have a residue value equal to
the full size of the corresponding descriptor. The driver miscomputes
that and uses the size of the active descriptor instead. Fix it.

Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/dma/sh/rcar-dmac.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 7820d07e7bee..a98596a1f12f 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -1143,19 +1143,43 @@ static unsigned int rcar_dmac_chan_get_residue(struct 
rcar_dmac_chan *chan,
 	struct rcar_dmac_desc *desc = chan->desc.running;
 	struct rcar_dmac_xfer_chunk *running = NULL;
 	struct rcar_dmac_xfer_chunk *chunk;
+	enum dma_status status;
 	unsigned int residue = 0;
 	unsigned int dptr = 0;
 
 	if (!desc)
 		return 0;
 
+
+	/*
+	 * If the cookie corresponds to a descriptor that has been completed
+	 * there is no residue. The same check has already been performed by the
+	 * caller but without holding the channel lock, so the descriptor could
+	 * now be complete.
+	 */
+	status = dma_cookie_status(&chan->chan, cookie, NULL);
+	if (status = DMA_COMPLETE)
+		return 0;
+
 	/*
 	 * If the cookie doesn't correspond to the currently running transfer
 	 * then the descriptor hasn't been processed yet, and the residue is
 	 * equal to the full descriptor size.
 	 */
-	if (cookie != desc->async_tx.cookie)
-		return desc->size;
+	if (cookie != desc->async_tx.cookie) {
+		list_for_each_entry(desc, &chan->desc.pending, node) {
+			if (cookie = desc->async_tx.cookie)
+				return desc->size;
+		}
+
+		/*
+		 * No descriptor found for the cookie, there's thus no residue.
+		 * This shouldn't happen if the calling driver passes a correct
+		 * cookie value.
+		 */
+		WARN(1, "No descriptor for cookie!");
+		return 0;
+	}
 
 	/*
 	 * In descriptor mode the descriptor running pointer is not maintained

>      I believe this the reason why the sh-sci driver once thought DMA
>      transfered 4294967265 (= -31) bytes (for SCIF, descriptor lengths
>      are either 1 or 32 bytes, and (length) 1 - (residue) 32 >      (transfered) -31).
> 
> Thanks for your comments!
> 
> From 589dbd908a59dba6efc2a78fca24645962235ec2 Mon Sep 17 00:00:00 2001
> From: Geert Uytterhoeven <geert+renesas@glider.be>
> Date: Tue, 14 Jul 2015 11:27:14 +0200
> Subject: [PATCH] [RFC] dmaengine: rcar-dmac: Allow resubmission of DMA
>  descriptors
> 
> Unlike the old shdmac DMA engine driver, the new rcar-dmac DMA engine
> driver does not support resubmitting a DMA descriptor.  If a DMA slave
> resubmits a descriptor, the descriptor will be added to the "pending
> list", while it wasn't removed from the "wait" list. This will cause
> list corruption, leading to an infinite loop in
> rcar_dmac_chan_reinit().
> 
> Find out if the descriptor is reused by looking at the current cookie
> valie, and remove it from the other list if needed:
>   - cookie is initialized to -EBUSY (by rcar-dma) for fresh and properly
>     recycled descriptors,
>   - cookie is set to a strict-positive value by dma_cookie_assign() (in
>     core dmaengine code) on submission,
>   - cookie is reset to zero by dma_cookie_complete() (in core dmaengine
>     code) on completion,
> 
> Fix this by removing it from a list if the cookie is not -EBUSY.
> 
> FIXME Unfortunately this is racy: the recycled descriptors are not part
>       of a list while the DMA descriptor callback is running.
> 
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
>  drivers/dma/sh/rcar-dmac.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
> index 11e5003a6cc27b40..92a8fddb025e6729 100644
> --- a/drivers/dma/sh/rcar-dmac.c
> +++ b/drivers/dma/sh/rcar-dmac.c
> @@ -437,8 +437,20 @@ static dma_cookie_t rcar_dmac_tx_submit(struct
> dma_async_tx_descriptor *tx) unsigned long flags;
>  	dma_cookie_t cookie;
> 
> +
>  	spin_lock_irqsave(&chan->lock, flags);
> 
> +	if (desc->async_tx.cookie != -EBUSY) {
> +		/*
> +		 * If the descriptor is reused, it's currently part of a list.
> +		 * Hence it must be removed from that list first, before it can
> +		 * be added to the list of pending requests.
> +		 */
> +		dev_dbg(chan->chan.device->dev, "chan%u: resubmit active desc %p\n",
> +			chan->index, desc);
> +		list_del(&desc->node);
> +	}
> +
>  	cookie = dma_cookie_assign(tx);
> 
>  	dev_dbg(chan->chan.device->dev, "chan%u: submit #%d@%p\n",

-- 
Regards,

Laurent Pinchart

  reply	other threads:[~2015-08-14 23:42 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-16 18:36 Issues with rcar-dmac and sh-sci Geert Uytterhoeven
2015-08-14 23:42 ` Laurent Pinchart [this message]
2015-08-15  9:40 ` Lars-Peter Clausen
2015-08-15 10:02 ` Geert Uytterhoeven
2015-08-17 14:03 ` Geert Uytterhoeven
2015-08-18  6:35 ` Laurent Pinchart
2015-09-14 12:39 ` Hamza Farooq

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=1862788.NYkJDoIfhG@avalon \
    --to=laurent.pinchart@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.