| From d10a574d06078872edede8042bd1d741493bfae0 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 13 Jun 2024 13:13:05 +0100 |
| Subject: ASoC: q6apm-lpass-dai: close graph on prepare errors |
| |
| From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> |
| |
| [ Upstream commit be1fae62cf253a5b67526cee9fbc07689b97c125 ] |
| |
| There is an issue around with error handling and graph management with |
| the exising code, none of the error paths close the graph, which result in |
| leaving the loaded graph in dsp, however the driver thinks otherwise. |
| |
| This can have a nasty side effect specially when we try to load the same |
| graph to dsp, dsp returns error which leaves the board with no sound and |
| requires restart. |
| |
| Fix this by properly closing the graph when we hit errors between |
| open and close. |
| |
| Fixes: 30ad723b93ad ("ASoC: qdsp6: audioreach: add q6apm lpass dai support") |
| Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> |
| Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> |
| Tested-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> # X13s |
| Link: https://lore.kernel.org/r/20240613-q6apm-fixes-v1-1-d88953675ab3@linaro.org |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| sound/soc/qcom/qdsp6/q6apm-lpass-dais.c | 32 +++++++++++++++---------- |
| 1 file changed, 20 insertions(+), 12 deletions(-) |
| |
| diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c |
| index 68a38f63a2dbf..66b911b49e3f4 100644 |
| --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c |
| +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c |
| @@ -141,14 +141,17 @@ static void q6apm_lpass_dai_shutdown(struct snd_pcm_substream *substream, struct |
| struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); |
| int rc; |
| |
| - if (!dai_data->is_port_started[dai->id]) |
| - return; |
| - rc = q6apm_graph_stop(dai_data->graph[dai->id]); |
| - if (rc < 0) |
| - dev_err(dai->dev, "fail to close APM port (%d)\n", rc); |
| + if (dai_data->is_port_started[dai->id]) { |
| + rc = q6apm_graph_stop(dai_data->graph[dai->id]); |
| + dai_data->is_port_started[dai->id] = false; |
| + if (rc < 0) |
| + dev_err(dai->dev, "fail to close APM port (%d)\n", rc); |
| + } |
| |
| - q6apm_graph_close(dai_data->graph[dai->id]); |
| - dai_data->is_port_started[dai->id] = false; |
| + if (dai_data->graph[dai->id]) { |
| + q6apm_graph_close(dai_data->graph[dai->id]); |
| + dai_data->graph[dai->id] = NULL; |
| + } |
| } |
| |
| static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) |
| @@ -163,8 +166,10 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s |
| q6apm_graph_stop(dai_data->graph[dai->id]); |
| dai_data->is_port_started[dai->id] = false; |
| |
| - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
| + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| q6apm_graph_close(dai_data->graph[dai->id]); |
| + dai_data->graph[dai->id] = NULL; |
| + } |
| } |
| |
| /** |
| @@ -183,26 +188,29 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s |
| |
| cfg->direction = substream->stream; |
| rc = q6apm_graph_media_format_pcm(dai_data->graph[dai->id], cfg); |
| - |
| if (rc) { |
| dev_err(dai->dev, "Failed to set media format %d\n", rc); |
| - return rc; |
| + goto err; |
| } |
| |
| rc = q6apm_graph_prepare(dai_data->graph[dai->id]); |
| if (rc) { |
| dev_err(dai->dev, "Failed to prepare Graph %d\n", rc); |
| - return rc; |
| + goto err; |
| } |
| |
| rc = q6apm_graph_start(dai_data->graph[dai->id]); |
| if (rc < 0) { |
| dev_err(dai->dev, "fail to start APM port %x\n", dai->id); |
| - return rc; |
| + goto err; |
| } |
| dai_data->is_port_started[dai->id] = true; |
| |
| return 0; |
| +err: |
| + q6apm_graph_close(dai_data->graph[dai->id]); |
| + dai_data->graph[dai->id] = NULL; |
| + return rc; |
| } |
| |
| static int q6apm_lpass_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) |
| -- |
| 2.43.0 |
| |