[...]
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. 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(). 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.
- Lars