On Thu, Jun 25, 2020 at 09:16:51PM +0530, Vinod Koul wrote:
On partial_drain completion we should be in SNDRV_PCM_STATE_RUNNING state, so set that for partially draining streams in snd_compr_drain_notify() and use a flag for partially draining streams
While at it, add locks for stream state change in snd_compr_drain_notify() as well.
Fixes: f44f2a5417b2 ("ALSA: compress: fix drain calls blocking other compress functions (v6)") Reviewed-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Tested-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org Signed-off-by: Vinod Koul vkoul@kernel.org
@@ -187,7 +189,15 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream) if (snd_BUG_ON(!stream)) return;
- stream->runtime->state = SNDRV_PCM_STATE_SETUP;
- mutex_lock(&stream->device->lock);
- /* for partial_drain case we are back to running state on success */
- if (stream->partial_drain) {
stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
stream->partial_drain = false; /* clear this flag as well */
- } else {
stream->runtime->state = SNDRV_PCM_STATE_SETUP;
- }
- mutex_unlock(&stream->device->lock);
You have added locking here in snd_compr_drain_notify but....
wake_up(&stream->runtime->sleep); } diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index e618580feac4..1c4b2cf450a0 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -803,6 +803,9 @@ static int snd_compr_stop(struct snd_compr_stream *stream)
retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP); if (!retval) {
/* clear flags and stop any drain wait */
stream->partial_drain = false;
snd_compr_drain_notify(stream);stream->metadata_set = false;
that can be called from snd_compr_stop here which is already holding the lock resulting in deadlock.
Thanks, Charles