linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
To: Krzysztof Kozlowski <k.kozlowski@samsung.com>,
	Vinod Koul <vinod.koul@intel.com>
Cc: k.kozlowski.k@gmail.com, linux-samsung-soc@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org,
	dmaengine@vger.kernel.org, linux-arm-kernel@vger.kernel.org
Subject: Re: [PATCH] dmaengine: pl330: Fix race in residue reporting
Date: Mon, 09 Nov 2015 14:12:16 +0100	[thread overview]
Message-ID: <1447074736.22840.35.camel@collabora.co.uk> (raw)
In-Reply-To: <563DF151.2010307@samsung.com>

On Sat, 2015-11-07 at 21:40 +0900, Krzysztof Kozlowski wrote:
> W dniu 06.11.2015 o 20:11, Sjoerd Simons pisze:
> > When a transfer completes there is a small window between the
> > descriptor
> > being unset as the current active one in the thread and it being
> > marked
> > as done. This causes the residue to be incorrectly set when
> > pl330_tx_status is run in that window. Practically this caused
> > issue for me with audio playback as the residue goes up during a
> > transfer (as the in-progress transfer is no longer accounted for),
> > which makes the higher levels think the audio ringbuffer wrapped
> > around
> > and thus did a sudden big jump forward.
> > 
> > To resolve this, add a field protected by the dma engine lock to
> > indicate the transfer is done but the status hasn't been updated
> > yet.
> > 
> > Also fix the locking in pl330_tx_status, as the function inspects
> > the
> > threads req_running field and queries the dma engine for the
> > current
> > state of the running transfer the dma engine lock needs to be held
> > to
> > ensure the active descriptor doesn't change underneath it.
> > 
> > Signed-off-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
> > 
> > ---
> > 
> >  drivers/dma/pl330.c | 10 +++++++++-
> >  1 file changed, 9 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> > index 17ee758..6c8243b 100644
> > --- a/drivers/dma/pl330.c
> > +++ b/drivers/dma/pl330.c
> > @@ -503,6 +503,8 @@ struct dma_pl330_desc {
> >  	struct pl330_reqcfg rqcfg;
> >  
> >  	enum desc_status status;
> > +	/* Transfer completed, but not yet moved to DONE state */
> > +	bool xferred;
> >  
> >  	int bytes_requested;
> >  	bool last;
> > @@ -1463,6 +1465,9 @@ static void dma_pl330_rqcb(struct
> > dma_pl330_desc *desc, enum pl330_op_err err)
> >  	spin_lock_irqsave(&pch->lock, flags);
> >  
> >  	desc->status = DONE;
> > +	spin_lock(&pch->thread->dmac->lock);
> > +	desc->xferred = false;
> > +	spin_unlock(&pch->thread->dmac->lock);
> >  
> >  	spin_unlock_irqrestore(&pch->lock, flags);
> >  
> > @@ -1595,6 +1600,7 @@ static int pl330_update(struct pl330_dmac
> > *pl330)
> >  
> >  			/* Detach the req */
> >  			descdone = thrd->req[active].desc;
> > +			descdone->xferred = true;
> >  			thrd->req[active].desc = NULL;
> 
> Looking at the code indeed the small window could happen. How can I
> reproduce it? Can you describe your system?

I'm using a Rock 2 square (RK3288 based) board, running Debian Jessie
and simply playing back audio using vlc & pulseaudio.

For some reason when using vlc, pulseaudio is polling the hw pointer
position very very often and seems to hit this tiny window a few times
a minute depending a bit on system load. This causes some audiable
issues and eventually underflowing (as vlc fills the pulseaudio buffer
at a constant rate, but due to this, pulse pushes the data faster then
the actual playback rate every so often).

> As for the change itself, how about adding a new value to
> desc_status?
> Now you are actually introducing a semi-status field.

The reason i picked this way this was was due to the current locking
scheme. The locking order is channel, then controller (when locking
both). While processing the events (and update the active descriptor),
the controller is locked so the status can't be directly updated (as
that's protected by the channel lock). And we can't grab the channel
lock without dopping the controller one first :).

Keeping one status field might well be possible, but would require at
least reworking the locking here.



> Best regards,
> Krzysztof
> 
> >  
> >  			thrd->req_running = -1;
> > @@ -2250,13 +2256,14 @@ pl330_tx_status(struct dma_chan *chan,
> > dma_cookie_t cookie,
> >  		goto out;
> >  
> >  	spin_lock_irqsave(&pch->lock, flags);
> > +	spin_lock(&pch->thread->dmac->lock);
> >  
> >  	if (pch->thread->req_running != -1)
> >  		running = pch->thread->req[pch->thread-
> > >req_running].desc;
> >  
> >  	/* Check in pending list */
> >  	list_for_each_entry(desc, &pch->work_list, node) {
> > -		if (desc->status == DONE)
> > +		if (desc->xferred || desc->status == DONE)
> >  			transferred = desc->bytes_requested;
> >  		else if (running && desc == running)
> >  			transferred =
> > @@ -2281,6 +2288,7 @@ pl330_tx_status(struct dma_chan *chan,
> > dma_cookie_t cookie,
> >  		if (desc->last)
> >  			residual = 0;
> >  	}
> > +	spin_unlock(&pch->thread->dmac->lock);
> >  	spin_unlock_irqrestore(&pch->lock, flags);
> >  
> >  out:
> > 
> 

-- 
Sjoerd Simons
Collabora Ltd.

  reply	other threads:[~2015-11-09 13:21 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-06 11:11 [PATCH] dmaengine: pl330: Fix race in residue reporting Sjoerd Simons
2015-11-07 12:40 ` Krzysztof Kozlowski
2015-11-09 13:12   ` Sjoerd Simons [this message]
2015-11-10  1:44     ` Krzysztof Kozlowski

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=1447074736.22840.35.camel@collabora.co.uk \
    --to=sjoerd.simons@collabora.co.uk \
    --cc=dmaengine@vger.kernel.org \
    --cc=k.kozlowski.k@gmail.com \
    --cc=k.kozlowski@samsung.com \
    --cc=linux-arm-kernel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rockchip@lists.infradead.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=vinod.koul@intel.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).