Skip to content

Commit 985131a

Browse files
Srinivas Kandagatlagregkh
authored andcommitted
ASoC: qcom: sdw: fix memory leak for sdw_stream_runtime
[ Upstream commit bcba172 ] For some reason we endedup allocating sdw_stream_runtime for every cpu dai, this has two issues. 1. we never set snd_soc_dai_set_stream for non soundwire dai, which means there is no way that we can free this, resulting in memory leak 2. startup and shutdown callbacks can be called without hw_params callback called. This combination results in memory leak because machine driver sruntime array pointer is only set in hw_params callback. Fix this by 1. adding a helper function to get sdw_runtime for substream which can be used by shutdown callback to get hold of sruntime to free. 2. only allocate sdw_runtime for soundwire dais. Fixes: d32bac9 ("ASoC: qcom: Add helper for allocating Soundwire stream runtime") Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Cc: Stable@vger.kernel.org Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com> Tested-by: Steev Klimaszewski <threeway@gmail.com> # Thinkpad X13s Link: https://patch.msgid.link/20251022143349.1081513-2-srinivas.kandagatla@oss.qualcomm.com Signed-off-by: Mark Brown <broonie@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 28b2ec0 commit 985131a

6 files changed

Lines changed: 64 additions & 50 deletions

File tree

sound/soc/qcom/sc7280.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ static void sc7280_snd_shutdown(struct snd_pcm_substream *substream)
317317
struct snd_soc_card *card = rtd->card;
318318
struct sc7280_snd_data *data = snd_soc_card_get_drvdata(card);
319319
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
320-
struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
320+
struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
321321

322322
switch (cpu_dai->id) {
323323
case MI2S_PRIMARY:

sound/soc/qcom/sc8280xp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ static void sc8280xp_snd_shutdown(struct snd_pcm_substream *substream)
6969
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
7070
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
7171
struct sc8280xp_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card);
72-
struct sdw_stream_runtime *sruntime = pdata->sruntime[cpu_dai->id];
72+
struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
7373

7474
pdata->sruntime[cpu_dai->id] = NULL;
7575
sdw_release_stream(sruntime);

sound/soc/qcom/sdw.c

Lines changed: 59 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,37 @@
77
#include <sound/soc.h>
88
#include "sdw.h"
99

10+
static bool qcom_snd_is_sdw_dai(int id)
11+
{
12+
switch (id) {
13+
case WSA_CODEC_DMA_RX_0:
14+
case WSA_CODEC_DMA_TX_0:
15+
case WSA_CODEC_DMA_RX_1:
16+
case WSA_CODEC_DMA_TX_1:
17+
case WSA_CODEC_DMA_TX_2:
18+
case RX_CODEC_DMA_RX_0:
19+
case TX_CODEC_DMA_TX_0:
20+
case RX_CODEC_DMA_RX_1:
21+
case TX_CODEC_DMA_TX_1:
22+
case RX_CODEC_DMA_RX_2:
23+
case TX_CODEC_DMA_TX_2:
24+
case RX_CODEC_DMA_RX_3:
25+
case TX_CODEC_DMA_TX_3:
26+
case RX_CODEC_DMA_RX_4:
27+
case TX_CODEC_DMA_TX_4:
28+
case RX_CODEC_DMA_RX_5:
29+
case TX_CODEC_DMA_TX_5:
30+
case RX_CODEC_DMA_RX_6:
31+
case RX_CODEC_DMA_RX_7:
32+
case SLIMBUS_0_RX...SLIMBUS_6_TX:
33+
return true;
34+
default:
35+
break;
36+
}
37+
38+
return false;
39+
}
40+
1041
/**
1142
* qcom_snd_sdw_startup() - Helper to start Soundwire stream for SoC audio card
1243
* @substream: The PCM substream from audio, as passed to snd_soc_ops->startup()
@@ -27,6 +58,9 @@ int qcom_snd_sdw_startup(struct snd_pcm_substream *substream)
2758
struct snd_soc_dai *codec_dai;
2859
int ret, i;
2960

61+
if (!qcom_snd_is_sdw_dai(cpu_dai->id))
62+
return 0;
63+
3064
sruntime = sdw_alloc_stream(cpu_dai->name, SDW_STREAM_PCM);
3165
if (!sruntime)
3266
return -ENOMEM;
@@ -61,19 +95,8 @@ int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
6195
if (!sruntime)
6296
return 0;
6397

64-
switch (cpu_dai->id) {
65-
case WSA_CODEC_DMA_RX_0:
66-
case WSA_CODEC_DMA_RX_1:
67-
case RX_CODEC_DMA_RX_0:
68-
case RX_CODEC_DMA_RX_1:
69-
case TX_CODEC_DMA_TX_0:
70-
case TX_CODEC_DMA_TX_1:
71-
case TX_CODEC_DMA_TX_2:
72-
case TX_CODEC_DMA_TX_3:
73-
break;
74-
default:
98+
if (!qcom_snd_is_sdw_dai(cpu_dai->id))
7599
return 0;
76-
}
77100

78101
if (*stream_prepared)
79102
return 0;
@@ -101,31 +124,31 @@ int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
101124
}
102125
EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare);
103126

104-
int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
105-
struct snd_pcm_hw_params *params,
106-
struct sdw_stream_runtime **psruntime)
127+
struct sdw_stream_runtime *qcom_snd_sdw_get_stream(struct snd_pcm_substream *substream)
107128
{
108129
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
109130
struct snd_soc_dai *codec_dai;
110131
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
111132
struct sdw_stream_runtime *sruntime;
112133
int i;
113134

114-
switch (cpu_dai->id) {
115-
case WSA_CODEC_DMA_RX_0:
116-
case RX_CODEC_DMA_RX_0:
117-
case RX_CODEC_DMA_RX_1:
118-
case TX_CODEC_DMA_TX_0:
119-
case TX_CODEC_DMA_TX_1:
120-
case TX_CODEC_DMA_TX_2:
121-
case TX_CODEC_DMA_TX_3:
122-
for_each_rtd_codec_dais(rtd, i, codec_dai) {
123-
sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
124-
if (sruntime != ERR_PTR(-ENOTSUPP))
125-
*psruntime = sruntime;
126-
}
127-
break;
135+
if (!qcom_snd_is_sdw_dai(cpu_dai->id))
136+
return NULL;
137+
138+
for_each_rtd_codec_dais(rtd, i, codec_dai) {
139+
sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
140+
if (sruntime != ERR_PTR(-ENOTSUPP))
141+
return sruntime;
128142
}
143+
return NULL;
144+
}
145+
EXPORT_SYMBOL_GPL(qcom_snd_sdw_get_stream);
146+
147+
int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
148+
struct snd_pcm_hw_params *params,
149+
struct sdw_stream_runtime **psruntime)
150+
{
151+
*psruntime = qcom_snd_sdw_get_stream(substream);
129152

130153
return 0;
131154

@@ -138,23 +161,13 @@ int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
138161
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
139162
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
140163

141-
switch (cpu_dai->id) {
142-
case WSA_CODEC_DMA_RX_0:
143-
case WSA_CODEC_DMA_RX_1:
144-
case RX_CODEC_DMA_RX_0:
145-
case RX_CODEC_DMA_RX_1:
146-
case TX_CODEC_DMA_TX_0:
147-
case TX_CODEC_DMA_TX_1:
148-
case TX_CODEC_DMA_TX_2:
149-
case TX_CODEC_DMA_TX_3:
150-
if (sruntime && *stream_prepared) {
151-
sdw_disable_stream(sruntime);
152-
sdw_deprepare_stream(sruntime);
153-
*stream_prepared = false;
154-
}
155-
break;
156-
default:
157-
break;
164+
if (!qcom_snd_is_sdw_dai(cpu_dai->id))
165+
return 0;
166+
167+
if (sruntime && *stream_prepared) {
168+
sdw_disable_stream(sruntime);
169+
sdw_deprepare_stream(sruntime);
170+
*stream_prepared = false;
158171
}
159172

160173
return 0;

sound/soc/qcom/sdw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ int qcom_snd_sdw_startup(struct snd_pcm_substream *substream);
1010
int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
1111
struct sdw_stream_runtime *runtime,
1212
bool *stream_prepared);
13+
struct sdw_stream_runtime *qcom_snd_sdw_get_stream(struct snd_pcm_substream *stream);
1314
int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
1415
struct snd_pcm_hw_params *params,
1516
struct sdw_stream_runtime **psruntime);

sound/soc/qcom/sm8250.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ static void sm2450_snd_shutdown(struct snd_pcm_substream *substream)
8686
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
8787
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
8888
struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
89-
struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
89+
struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
9090

9191
data->sruntime[cpu_dai->id] = NULL;
9292
sdw_release_stream(sruntime);

sound/soc/qcom/x1e80100.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ static void x1e80100_snd_shutdown(struct snd_pcm_substream *substream)
5555
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
5656
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
5757
struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
58-
struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
58+
struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
5959

6060
data->sruntime[cpu_dai->id] = NULL;
6161
sdw_release_stream(sruntime);

0 commit comments

Comments
 (0)