| From 655e436dbe24dc3ef3c0fee9f28a5f8675fde7e9 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 29 Jun 2020 19:17:37 +0530 |
| Subject: ALSA: compress: fix partial_drain completion state |
| |
| 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 bc88d6f964da9..006f019224399 100644 |
| --- a/include/sound/compress_driver.h |
| +++ b/include/sound/compress_driver.h |
| @@ -59,6 +59,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 { |
| @@ -70,6 +71,7 @@ struct snd_compr_stream { |
| enum snd_compr_direction direction; |
| bool metadata_set; |
| bool next_track; |
| + bool partial_drain; |
| void *private_data; |
| }; |
| |
| @@ -173,7 +175,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 f34ce564d92c4..1afa06b80f06c 100644 |
| --- a/sound/core/compress_offload.c |
| +++ b/sound/core/compress_offload.c |
| @@ -722,6 +722,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; |
| @@ -879,6 +882,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"); |
| -- |
| 2.25.1 |
| |