[alsa-devel] issue of shdma-base library

Guennadi Liakhovetski g.liakhovetski at gmx.de
Fri Oct 5 11:18:56 CEST 2012


Mark, could you take this patch or would you like me to resend it with 
"subject" in the actual mail subject line or does it also work from the 
mail body?

Thanks
Guennadi

On Thu, 4 Oct 2012, Do Q.Thang wrote:

> Hi Guennadi-san
> 
> Thank you for your hard work.
> 
> On 10/03/2012 09:33 PM, Guennadi Liakhovetski wrote:
> > Subject: [PATCH] ASoC: fsi: don't reschedule DMA from an atomic context
> > 
> > shdma doesn't support transfer re-scheduling or triggering from callbacks
> > or from atomic context. The fsi driver issues DMA transfers from a tasklet
> > context, which is a bug. To fix it convert tasklet to a work.
> > 
> > Reported-by: Do Q.Thang <dq-thang at jinso.co.jp>
> > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski at gmx.de>
> > ---
> > 
> > Thang-san, Please, check, whether the attached patch fixes your issues. It
> > seems to fix them for me.
> 
> This patch also fix them for me.
> 
> Thanks
> ---
> Thang
> 
> > Mark, please, wait with committing this patch until the guys confirm, it
> > really helps. It then will also have to go to 3.6-stable.
> > 
> > Thanks
> > Guennadi
> > 
> > On Tue, 2 Oct 2012, Do Q.Thang wrote:
> > 
> > > Hi Guennadi-san,
> > > 
> > > I'm testing uptream kernel (v3.6-rc3 ~) on the kzm-a9-gt &
> > > armadillo-800eva
> > > board.
> > > I found 2 issues with the sh-dma driver while testing audio playback.
> > > 
> > > issue 1: this log appeared while playback with the aplay, then aplay was
> > > stopped.
> > > 
> > > ------- log -----------------------------
> > > # aplay audio_s16le_44100.wav
> > >   Playing WAVE 'audio_s16le_44100.wav' : Signed 16 bit Little Endian, Rate
> > > 44100 Hz, Stereo
> > >   aplay: pcm_write:1710: write error: Input/output error
> > > -----------------------------------------
> > > 
> > > issue 2: this log appeared while playback with the aplay, then aplay was
> > > stopped.
> > > ( this issue isn't appear on the kzm-a9-gt board only )
> > > 
> > > ------- log -----------------------------
> > > # aplay audio_s16le_44100.wav
> > >   Playing WAVE 'audio.wav' : Signed 16 bit Little Endian, Rate 44100 Hz,
> > > Stereo
> > >   BUG: scheduling while atomic: kworker/1:1/273/0x00000103
> > >   aplay: pcm_write:1710: write error: Input/output error
> > > -----------------------------------------
> > > 
> > > I think these issues are introduced by "dmaengine:add an shdma-base
> > > library"
> > > commit.
> > > 
> > > ---------- commit -----------------------
> > > commit 9a7b8e002e331d0599127f16613c32f425a14f2c
> > > Author: Guennadi Liakhovetski <g.liakhovetski at gmx.de>
> > > Date:   Wed May 9 17:09:13 2012 +0200
> > > 
> > >      dmaengine: add an shdma-base library
> > > 
> > >      This patch extracts code from shdma.c, that does not directly deal
> > > with
> > >      hardware implementation details and can be re-used with diverse DMA
> > >      controller variants, found on SH-based SoCs.
> > > 
> > >      Signed-off-by: Guennadi Liakhovetski <g.liakhovetski at gmx.de>
> > >      Cc: Sascha Hauer <s.hauer at pengutronix.de>
> > >      Signed-off-by: Vinod Koul <vinod.koul at linux.intel.com>
> > > ------------------------------------------
> > > 
> > > About issue 1: I found that
> > > The fsi.c uses fsi_dma_do_tasklet() to setup dma-transfer.This is a
> > > function
> > > of a tasklet.
> > > When one dma-transfer is finished shdma_chan_ld_cleanup() is called.In
> > > this
> > > function
> > > __ld_cleanup() is called to cleanup the schan->ld_queue. In behavior of
> > > __ld_cleanup()
> > > if descriptor is the last chunk its callback is called, then its node is
> > > cleanup in the
> > > next call of __ld_cleanup().In callback of the last descriptor,
> > > fsi_dma_do_tasklet() is
> > > scheduled then is called after the shdma_chan_ld_cleanup() is finished.
> > > But when this issue appear, shdma_chan_ld_cleanup() is called while
> > > shdma_chan_ld_cleanup()
> > > is not finished.At that time, schan->ld_queue is not empty, so in
> > > shdma_tx_submit()
> > > schan->pm_state is set to SHDMA_PM_PENDING, and then dma-transfer isn't
> > > started in
> > > shdma_issue_pending().
> > > 
> > > About issue 2:
> > > I found that this issue is appear when pm_runtime_barrier() is running.
> > > This issue is not appear when disable CONFIG_PM_RUNTIME config.
> > > 
> > > What do you think about these issues?
> > > 
> > > Best regards
> > > ---
> > > Thang
> > diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
> > index 0540408..1bb0d58c 100644
> > --- a/sound/soc/sh/fsi.c
> > +++ b/sound/soc/sh/fsi.c
> > @@ -20,6 +20,7 @@
> >   #include <linux/sh_dma.h>
> >   #include <linux/slab.h>
> >   #include <linux/module.h>
> > +#include <linux/workqueue.h>
> >   #include <sound/soc.h>
> >   #include <sound/sh_fsi.h>
> >   @@ -223,7 +224,7 @@ struct fsi_stream {
> >   	 */
> >   	struct dma_chan		*chan;
> >   	struct sh_dmae_slave	slave; /* see fsi_handler_init() */
> > -	struct tasklet_struct	tasklet;
> > +	struct work_struct	work;
> >   	dma_addr_t		dma;
> >   };
> >   @@ -1085,9 +1086,9 @@ static void fsi_dma_complete(void *data)
> >   	snd_pcm_period_elapsed(io->substream);
> >   }
> >   -static void fsi_dma_do_tasklet(unsigned long data)
> > +static void fsi_dma_do_work(struct work_struct *work)
> >   {
> > -	struct fsi_stream *io = (struct fsi_stream *)data;
> > +	struct fsi_stream *io = container_of(work, struct fsi_stream, work);
> >   	struct fsi_priv *fsi = fsi_stream_to_priv(io);
> >   	struct snd_soc_dai *dai;
> >   	struct dma_async_tx_descriptor *desc;
> > @@ -1129,7 +1130,7 @@ static void fsi_dma_do_tasklet(unsigned long data)
> >   	 * FIXME
> >   	 *
> >   	 * In DMAEngine case, codec and FSI cannot be started simultaneously
> > -	 * since FSI is using tasklet.
> > +	 * since FSI is using the scheduler work queue.
> >   	 * Therefore, in capture case, probably FSI FIFO will have got
> >   	 * overflow error in this point.
> >   	 * in that case, DMA cannot start transfer until error was cleared.
> > @@ -1153,7 +1154,7 @@ static bool fsi_dma_filter(struct dma_chan *chan, void
> > *param)
> >     static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
> >   {
> > -	tasklet_schedule(&io->tasklet);
> > +	schedule_work(&io->work);
> >     	return 0;
> >   }
> > @@ -1195,14 +1196,14 @@ static int fsi_dma_probe(struct fsi_priv *fsi,
> > struct fsi_stream *io, struct dev
> >   		return fsi_stream_probe(fsi, dev);
> >   	}
> >   -	tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io);
> > +	INIT_WORK(&io->work, fsi_dma_do_work);
> >     	return 0;
> >   }
> >     static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
> >   {
> > -	tasklet_kill(&io->tasklet);
> > +	cancel_work_sync(&io->work);
> >     	fsi_stream_stop(fsi, io);
> >   
> > 
> 

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/


More information about the Alsa-devel mailing list