Message ID | 20200625154651.99758-4-vkoul@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | ALSA: compress: Document stream states and fix gapless SM | expand |
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; > + stream->metadata_set = false; > snd_compr_drain_notify(stream); that can be called from snd_compr_stop here which is already holding the lock resulting in deadlock. Thanks, Charles
On 26-06-20, 10:35, Charles Keepax wrote: > > - 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; > > + stream->metadata_set = false; > > snd_compr_drain_notify(stream); > > that can be called from snd_compr_stop here which is already > holding the lock resulting in deadlock. Thanks Charles, right somehow my testing missed this, have verified that it is the case. I will remove the locks here, and we should add a comment to note this.. Thanks
diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index 3df8d8c90191..93a5897201ea 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -66,6 +66,7 @@ struct snd_compr_runtime { * @direction: stream direction, playback/recording * @metadata_set: metadata set flag, true when set * @next_track: has userspace signal next track transition, true when set + * @partial_drain: undergoing partial_drain for stream, true when set * @private_data: pointer to DSP private data * @dma_buffer: allocated buffer if any */ @@ -78,6 +79,7 @@ struct snd_compr_stream { enum snd_compr_direction direction; bool metadata_set; bool next_track; + bool partial_drain; void *private_data; struct snd_dma_buffer dma_buffer; }; @@ -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); 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; + stream->metadata_set = false; snd_compr_drain_notify(stream); stream->runtime->total_bytes_available = 0; stream->runtime->total_bytes_transferred = 0; @@ -960,6 +963,7 @@ static int snd_compr_partial_drain(struct snd_compr_stream *stream) if (stream->next_track == false) return -EPERM; + stream->partial_drain = true; retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_PARTIAL_DRAIN); if (retval) { pr_debug("Partial drain returned failure\n");