From: Vinod Koul vkoul@kernel.org
[ Upstream commit f79a732a8325dfbd570d87f1435019d7e5501c6d ]
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 Reviewed-by: Charles Keepax ckeepax@opensource.cirrus.com Tested-by: Charles Keepax ckeepax@opensource.cirrus.com Signed-off-by: Vinod Koul vkoul@kernel.org Link: https://lore.kernel.org/r/20200629134737.105993-4-vkoul@kernel.org Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- include/sound/compress_driver.h | 10 +++++++++- sound/core/compress_offload.c | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index 127c2713b543a..99855d1c74766 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -57,6 +57,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 */ struct snd_compr_stream { @@ -68,6 +69,7 @@ struct snd_compr_stream { enum snd_compr_direction direction; bool metadata_set; bool next_track; + bool partial_drain; void *private_data; };
@@ -171,7 +173,13 @@ 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; + /* 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; + }
wake_up(&stream->runtime->sleep); } diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 509038d6bccdb..68f016e4929ac 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -723,6 +723,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; @@ -880,6 +883,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");