[alsa-devel] async between dmaengine_pcm_dma_complete and snd_pcm_release

Vinod Koul vinod.koul at intel.com
Thu Oct 10 18:10:10 CEST 2013


On Thu, Oct 10, 2013 at 09:46:34AM +0200, Lars-Peter Clausen wrote:

+ Dan

> [...]
> > 
> >>>> On the other hand that last part could get tricky as the
> >>>> dmaengine_terminate_all() might be call from within the callback.
> >>> It's tricky indeed in case xrun happens. we should avoid possible deadlock.
> >>
> >> I think we'll eventually need to versions of dmaengine_terminate_all(). A
> >> sync version which makes sure that the tasklet has finished and a non-sync
> >> version that only makes sure that no new callbacks are started. I think the
> >> sync version should be the default with an optional async version which must
> >> be used, if it can run from within the callback. So we'd call the async
> >> version in the pcm_trigger callback and the sync version in the pcm_close
> >> callback.
> > Yes this can be done. We can name this disable_callback cmd. The cmd will tell
> > dma driver to disable all callback on the channel. This can be invoked from the
> > TRIGEGR_STOP and then terminate_all in the free
> > 
> 
> I think we should make it the default behavior of dmaengine_terminate_all()
> to wait for the tasklet to finish.
No we cant since terminate can get invoked from callback itself!

> Since this is what almost always want,
> except in this case where you might end up calling dmaeinge_terminate_all()
> from within the callback. Internally this can be implemented as two separate
> commands. So leave the DMA_TERMINATE_ALL as it is and add a new
> DMA_SYNC_CALLBACKS (or whatever it will be named) command. This command will
> internally call tasklet_kill().
Implementations will have tasklet for dmaengine and not per channel. So
tasklet_kill is not option!

>Then we have two new functions
> dmaengine_terminate_all_async() which will just issue the DMA_TERMINATE_ALL
> command, the other function is dmaengine_sync_callbacks() which will issue
> the DMA_SYNC_CALLBACKS command. dmaengine_terminate_all() will then first
> call dmaengine_terminate_all_async() and then dmaengine_sync_callbacks().
> The ALSA code would have to be updated first to call
> dmaengine_terminate_all_async() for TRIGGER_STOP and
> dmaengine_sync_callbacks() on the pcm_close path.
In order to avoid the complication for getting called from the callback itself,
I was thinking that we tell dma driver explictly that from now on dont invoke
the callbacks (we might be in callback context), then we return. DMA engine will
not issue any new callbacks. And also give chance to existing callback to
return.
Then the client can safely call terminate_all() to abort the channel from non
callback context!

The only issue here is that we get called from callback context as well as
thread of client and all this cna happen while callback is executing.

This make API similistic IMO.

--
~Vinod


More information about the Alsa-devel mailing list