* [PATCH v2 1/4] ASoC: qcom: sdw: fix memory leak for sdw_stream_runtime
2025-10-21 10:39 [PATCH v2 0/4] ASoC: qcom: sdw: fix memory leak Srinivas Kandagatla
@ 2025-10-21 10:39 ` Srinivas Kandagatla
2025-10-22 0:34 ` [PATCH v2 0/4] ASoC: qcom: sdw: fix memory leak Steev Klimaszewski
2025-10-21 10:40 ` [PATCH v2 2/4] ASoC: qcom: sdw: remove redundant code Srinivas Kandagatla
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Srinivas Kandagatla @ 2025-10-21 10:39 UTC (permalink / raw)
To: broonie
Cc: perex, tiwai, srini, alexey.klimov, linux-sound, linux-kernel,
linux-arm-msm, Srinivas Kandagatla, Krzysztof Kozlowski, Stable
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: d32bac9cb09c ("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>
---
sound/soc/qcom/sc7280.c | 2 +-
sound/soc/qcom/sc8280xp.c | 2 +-
sound/soc/qcom/sdw.c | 105 +++++++++++++++++++++-----------------
sound/soc/qcom/sdw.h | 1 +
sound/soc/qcom/sm8250.c | 2 +-
sound/soc/qcom/x1e80100.c | 2 +-
6 files changed, 64 insertions(+), 50 deletions(-)
diff --git a/sound/soc/qcom/sc7280.c b/sound/soc/qcom/sc7280.c
index af412bd0c89f..c444dae563c7 100644
--- a/sound/soc/qcom/sc7280.c
+++ b/sound/soc/qcom/sc7280.c
@@ -317,7 +317,7 @@ static void sc7280_snd_shutdown(struct snd_pcm_substream *substream)
struct snd_soc_card *card = rtd->card;
struct sc7280_snd_data *data = snd_soc_card_get_drvdata(card);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
+ struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
switch (cpu_dai->id) {
case MI2S_PRIMARY:
diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c
index 78e327bc2f07..9ba536dff667 100644
--- a/sound/soc/qcom/sc8280xp.c
+++ b/sound/soc/qcom/sc8280xp.c
@@ -73,7 +73,7 @@ static void sc8280xp_snd_shutdown(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct sc8280xp_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card);
- struct sdw_stream_runtime *sruntime = pdata->sruntime[cpu_dai->id];
+ struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
pdata->sruntime[cpu_dai->id] = NULL;
sdw_release_stream(sruntime);
diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c
index 7d7981d4295b..7b2cae92c812 100644
--- a/sound/soc/qcom/sdw.c
+++ b/sound/soc/qcom/sdw.c
@@ -7,6 +7,37 @@
#include <sound/soc.h>
#include "sdw.h"
+static bool qcom_snd_is_sdw_dai(int id)
+{
+ switch (id) {
+ case WSA_CODEC_DMA_RX_0:
+ case WSA_CODEC_DMA_TX_0:
+ case WSA_CODEC_DMA_RX_1:
+ case WSA_CODEC_DMA_TX_1:
+ case WSA_CODEC_DMA_TX_2:
+ case RX_CODEC_DMA_RX_0:
+ case TX_CODEC_DMA_TX_0:
+ case RX_CODEC_DMA_RX_1:
+ case TX_CODEC_DMA_TX_1:
+ case RX_CODEC_DMA_RX_2:
+ case TX_CODEC_DMA_TX_2:
+ case RX_CODEC_DMA_RX_3:
+ case TX_CODEC_DMA_TX_3:
+ case RX_CODEC_DMA_RX_4:
+ case TX_CODEC_DMA_TX_4:
+ case RX_CODEC_DMA_RX_5:
+ case TX_CODEC_DMA_TX_5:
+ case RX_CODEC_DMA_RX_6:
+ case RX_CODEC_DMA_RX_7:
+ case SLIMBUS_0_RX...SLIMBUS_6_TX:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
/**
* qcom_snd_sdw_startup() - Helper to start Soundwire stream for SoC audio card
* @substream: The PCM substream from audio, as passed to snd_soc_ops->startup()
@@ -29,6 +60,9 @@ int qcom_snd_sdw_startup(struct snd_pcm_substream *substream)
u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
int ret, i, j;
+ if (!qcom_snd_is_sdw_dai(cpu_dai->id))
+ return 0;
+
sruntime = sdw_alloc_stream(cpu_dai->name, SDW_STREAM_PCM);
if (!sruntime)
return -ENOMEM;
@@ -89,19 +123,8 @@ int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
if (!sruntime)
return 0;
- switch (cpu_dai->id) {
- case WSA_CODEC_DMA_RX_0:
- case WSA_CODEC_DMA_RX_1:
- case RX_CODEC_DMA_RX_0:
- case RX_CODEC_DMA_RX_1:
- case TX_CODEC_DMA_TX_0:
- case TX_CODEC_DMA_TX_1:
- case TX_CODEC_DMA_TX_2:
- case TX_CODEC_DMA_TX_3:
- break;
- default:
+ if (!qcom_snd_is_sdw_dai(cpu_dai->id))
return 0;
- }
if (*stream_prepared)
return 0;
@@ -129,9 +152,7 @@ int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
}
EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare);
-int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct sdw_stream_runtime **psruntime)
+struct sdw_stream_runtime *qcom_snd_sdw_get_stream(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai;
@@ -139,21 +160,23 @@ int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
struct sdw_stream_runtime *sruntime;
int i;
- switch (cpu_dai->id) {
- case WSA_CODEC_DMA_RX_0:
- case RX_CODEC_DMA_RX_0:
- case RX_CODEC_DMA_RX_1:
- case TX_CODEC_DMA_TX_0:
- case TX_CODEC_DMA_TX_1:
- case TX_CODEC_DMA_TX_2:
- case TX_CODEC_DMA_TX_3:
- for_each_rtd_codec_dais(rtd, i, codec_dai) {
- sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
- if (sruntime != ERR_PTR(-ENOTSUPP))
- *psruntime = sruntime;
- }
- break;
+ if (!qcom_snd_is_sdw_dai(cpu_dai->id))
+ return NULL;
+
+ for_each_rtd_codec_dais(rtd, i, codec_dai) {
+ sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
+ if (sruntime != ERR_PTR(-ENOTSUPP))
+ return sruntime;
}
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(qcom_snd_sdw_get_stream);
+
+int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct sdw_stream_runtime **psruntime)
+{
+ *psruntime = qcom_snd_sdw_get_stream(substream);
return 0;
@@ -166,23 +189,13 @@ int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- switch (cpu_dai->id) {
- case WSA_CODEC_DMA_RX_0:
- case WSA_CODEC_DMA_RX_1:
- case RX_CODEC_DMA_RX_0:
- case RX_CODEC_DMA_RX_1:
- case TX_CODEC_DMA_TX_0:
- case TX_CODEC_DMA_TX_1:
- case TX_CODEC_DMA_TX_2:
- case TX_CODEC_DMA_TX_3:
- if (sruntime && *stream_prepared) {
- sdw_disable_stream(sruntime);
- sdw_deprepare_stream(sruntime);
- *stream_prepared = false;
- }
- break;
- default:
- break;
+ if (!qcom_snd_is_sdw_dai(cpu_dai->id))
+ return 0;
+
+ if (sruntime && *stream_prepared) {
+ sdw_disable_stream(sruntime);
+ sdw_deprepare_stream(sruntime);
+ *stream_prepared = false;
}
return 0;
diff --git a/sound/soc/qcom/sdw.h b/sound/soc/qcom/sdw.h
index 392e3455f1b1..b8bc5beb0522 100644
--- a/sound/soc/qcom/sdw.h
+++ b/sound/soc/qcom/sdw.h
@@ -10,6 +10,7 @@ int qcom_snd_sdw_startup(struct snd_pcm_substream *substream);
int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
struct sdw_stream_runtime *runtime,
bool *stream_prepared);
+struct sdw_stream_runtime *qcom_snd_sdw_get_stream(struct snd_pcm_substream *stream);
int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct sdw_stream_runtime **psruntime);
diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c
index f5b75a06e5bd..ce5b0059207f 100644
--- a/sound/soc/qcom/sm8250.c
+++ b/sound/soc/qcom/sm8250.c
@@ -117,7 +117,7 @@ static void sm8250_snd_shutdown(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
+ struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
data->sruntime[cpu_dai->id] = NULL;
sdw_release_stream(sruntime);
diff --git a/sound/soc/qcom/x1e80100.c b/sound/soc/qcom/x1e80100.c
index 444f2162889f..2e3599516aa2 100644
--- a/sound/soc/qcom/x1e80100.c
+++ b/sound/soc/qcom/x1e80100.c
@@ -55,7 +55,7 @@ static void x1e80100_snd_shutdown(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
+ struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
data->sruntime[cpu_dai->id] = NULL;
sdw_release_stream(sruntime);
--
2.51.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2 0/4] ASoC: qcom: sdw: fix memory leak
2025-10-21 10:39 ` [PATCH v2 1/4] ASoC: qcom: sdw: fix memory leak for sdw_stream_runtime Srinivas Kandagatla
@ 2025-10-22 0:34 ` Steev Klimaszewski
2025-10-22 9:52 ` Srinivas Kandagatla
0 siblings, 1 reply; 8+ messages in thread
From: Steev Klimaszewski @ 2025-10-22 0:34 UTC (permalink / raw)
To: srinivas.kandagatla
Cc: Stable, alexey.klimov, broonie, krzysztof.kozlowski,
linux-arm-msm, linux-kernel, linux-sound, perex, srini, tiwai
Hi Srini,
On the Thinkpad X13s, with this patchset applied, we end up seeing a NULL
pointer dereference:
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000020
Mem abort info:
ESR = 0x0000000096000004
EC = 0x25: DABT (current EL), IL = 32 bits
SET = 0, FnV = 0
EA = 0, S1PTW = 0
FSC = 0x04: level 0 translation fault
Data abort info:
ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
CM = 0, WnR = 0, TnD = 0, TagAccess = 0
GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
user pgtable: 4k pages, 48-bit VAs, pgdp=000000010abfe000
pgd=0000000000000000, p4d=0000000000000000
SMP
pdr_interface(E) crc8(E) phy_qcom_qmp_pcie(E) icc_osm_l3(E) gpio_sbu_mux(E) qcom_wdt(E) typec(E) qcom_pdr_msg(E) qmi_helpers(E) smp2p(E) rpmsg_core(E) fixed(E) gpio_keys(E) qnoc_sc8280xp(E) pwm_bl(E) smem(E) efivarfs(E)
CPU: 5 UID: 111 PID: 1501 Comm: wireplumber Tainted: G E 6.17.4 #2 PREEMPTLAZY
Tainted: [E]=UNSIGNED_MODULE
Hardware name: LENOVO 21BX0015US/21BX0015US, BIOS N3HET94W (1.66 ) 09/15/2025
pstate: 60401005 (nZCv daif +PAN -UAO -TCO -DIT +SSBS BTYPE=--)
pc : sdw_stream_add_slave+0x4c/0x440 [soundwire_bus]
lr : sdw_stream_add_slave+0x4c/0x440 [soundwire_bus]
sp : ffff80008bc2b250
x29: ffff80008bc2b250 x28: ffff0000a56b2f88 x27: 0000000000000000
x26: 0000000000000000 x25: ffff0000a301b000 x24: 0000000000000000
x23: ffff0000e8ce0280 x22: 0000000000000000 x21: 0000000000000000
x20: ffff80008bc2b300 x19: ffff0000a305a880 x18: 0000000000000000
x17: 0000000000000000 x16: ffffb9859eb15c48 x15: 0000000000000000
x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
x11: 0000000000000000 x10: 0000000000000000 x9 : ffffb985391c0614
x8 : 0000000000000000 x7 : 0000000000000000 x6 : ffff0000a56b2fd0
x5 : ffff0000a56b2f80 x4 : 0000000000000000 x3 : 0000000000000000
x2 : ffff0000eb005000 x1 : 0000000000000000 x0 : ffff00011de2c890
Call trace:
(P)
wcd938x_sdw_hw_params+0xa8/0x200 [snd_soc_wcd938x_sdw]
wcd938x_codec_hw_params+0x48/0x88 [snd_soc_wcd938x]
snd_soc_dai_hw_params+0x44/0x90 [snd_soc_core]
__soc_pcm_hw_params+0x230/0x620 [snd_soc_core]
dpcm_be_dai_hw_params+0x260/0x888 [snd_soc_core]
dpcm_fe_dai_hw_params+0xc4/0x3b0 [snd_soc_core]
snd_pcm_hw_params+0x180/0x468 [snd_pcm]
snd_pcm_common_ioctl+0xc00/0x18b8 [snd_pcm]
snd_pcm_ioctl+0x38/0x60 [snd_pcm]
__arm64_sys_ioctl+0xac/0x108
invoke_syscall.constprop.0+0x64/0xe8
el0_svc_common.constprop.0+0xc0/0xe8
do_el0_svc+0x24/0x38
el0_svc+0x3c/0x170
el0t_64_sync_handler+0xa0/0xf0
el0t_64_sync+0x198/0x1a0
Code: f9418c00 b9006fe3 91004000 97ffe306 (f8420f43)
---[ end trace 0000000000000000 ]---
-- steev
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 0/4] ASoC: qcom: sdw: fix memory leak
2025-10-22 0:34 ` [PATCH v2 0/4] ASoC: qcom: sdw: fix memory leak Steev Klimaszewski
@ 2025-10-22 9:52 ` Srinivas Kandagatla
2025-10-22 12:00 ` Steev Klimaszewski
0 siblings, 1 reply; 8+ messages in thread
From: Srinivas Kandagatla @ 2025-10-22 9:52 UTC (permalink / raw)
To: Steev Klimaszewski
Cc: Stable, alexey.klimov, broonie, krzysztof.kozlowski,
linux-arm-msm, linux-kernel, linux-sound, perex, srini, tiwai
On 10/22/25 1:34 AM, Steev Klimaszewski wrote:
> Hi Srini,
>
> On the Thinkpad X13s, with this patchset applied, we end up seeing a NULL
> pointer dereference:
>
Thanks Steev,
I think I know the issue, There was a silly typo in 3/4 patch.
Could you please try this change, I will send this in v3 anyway;
-------------------------->cut<------------------------
diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c
index 16bf09db29f5..6576b47a4c8c 100644
--- a/sound/soc/qcom/sdw.c
+++ b/sound/soc/qcom/sdw.c
@@ -31,6 +31,7 @@ static bool qcom_snd_is_sdw_dai(int id)
case RX_CODEC_DMA_RX_6:
case RX_CODEC_DMA_RX_7:
case SLIMBUS_0_RX...SLIMBUS_6_TX:
+ return true;
default:
break;
}
-------------------------->cut<------------------------
thanks,
Srini> Unable to handle kernel NULL pointer dereference at virtual
address 0000000000000020
> Mem abort info:
> ESR = 0x0000000096000004
> EC = 0x25: DABT (current EL), IL = 32 bits
> SET = 0, FnV = 0
> EA = 0, S1PTW = 0
> FSC = 0x04: level 0 translation fault
> Data abort info:
> ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
> CM = 0, WnR = 0, TnD = 0, TagAccess = 0
> GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> user pgtable: 4k pages, 48-bit VAs, pgdp=000000010abfe000
> pgd=0000000000000000, p4d=0000000000000000
> SMP
> pdr_interface(E) crc8(E) phy_qcom_qmp_pcie(E) icc_osm_l3(E) gpio_sbu_mux(E) qcom_wdt(E) typec(E) qcom_pdr_msg(E) qmi_helpers(E) smp2p(E) rpmsg_core(E) fixed(E) gpio_keys(E) qnoc_sc8280xp(E) pwm_bl(E) smem(E) efivarfs(E)
> CPU: 5 UID: 111 PID: 1501 Comm: wireplumber Tainted: G E 6.17.4 #2 PREEMPTLAZY
> Tainted: [E]=UNSIGNED_MODULE
> Hardware name: LENOVO 21BX0015US/21BX0015US, BIOS N3HET94W (1.66 ) 09/15/2025
> pstate: 60401005 (nZCv daif +PAN -UAO -TCO -DIT +SSBS BTYPE=--)
> pc : sdw_stream_add_slave+0x4c/0x440 [soundwire_bus]
> lr : sdw_stream_add_slave+0x4c/0x440 [soundwire_bus]
> sp : ffff80008bc2b250
> x29: ffff80008bc2b250 x28: ffff0000a56b2f88 x27: 0000000000000000
> x26: 0000000000000000 x25: ffff0000a301b000 x24: 0000000000000000
> x23: ffff0000e8ce0280 x22: 0000000000000000 x21: 0000000000000000
> x20: ffff80008bc2b300 x19: ffff0000a305a880 x18: 0000000000000000
> x17: 0000000000000000 x16: ffffb9859eb15c48 x15: 0000000000000000
> x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
> x11: 0000000000000000 x10: 0000000000000000 x9 : ffffb985391c0614
> x8 : 0000000000000000 x7 : 0000000000000000 x6 : ffff0000a56b2fd0
> x5 : ffff0000a56b2f80 x4 : 0000000000000000 x3 : 0000000000000000
> x2 : ffff0000eb005000 x1 : 0000000000000000 x0 : ffff00011de2c890
> Call trace:
> (P)
> wcd938x_sdw_hw_params+0xa8/0x200 [snd_soc_wcd938x_sdw]
> wcd938x_codec_hw_params+0x48/0x88 [snd_soc_wcd938x]
> snd_soc_dai_hw_params+0x44/0x90 [snd_soc_core]
> __soc_pcm_hw_params+0x230/0x620 [snd_soc_core]
> dpcm_be_dai_hw_params+0x260/0x888 [snd_soc_core]
> dpcm_fe_dai_hw_params+0xc4/0x3b0 [snd_soc_core]
> snd_pcm_hw_params+0x180/0x468 [snd_pcm]
> snd_pcm_common_ioctl+0xc00/0x18b8 [snd_pcm]
> snd_pcm_ioctl+0x38/0x60 [snd_pcm]
> __arm64_sys_ioctl+0xac/0x108
> invoke_syscall.constprop.0+0x64/0xe8
> el0_svc_common.constprop.0+0xc0/0xe8
> do_el0_svc+0x24/0x38
> el0_svc+0x3c/0x170
> el0t_64_sync_handler+0xa0/0xf0
> el0t_64_sync+0x198/0x1a0
> Code: f9418c00 b9006fe3 91004000 97ffe306 (f8420f43)
> ---[ end trace 0000000000000000 ]---
>
> -- steev
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 0/4] ASoC: qcom: sdw: fix memory leak
2025-10-22 9:52 ` Srinivas Kandagatla
@ 2025-10-22 12:00 ` Steev Klimaszewski
0 siblings, 0 replies; 8+ messages in thread
From: Steev Klimaszewski @ 2025-10-22 12:00 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: Stable, alexey.klimov, broonie, krzysztof.kozlowski,
linux-arm-msm, linux-kernel, linux-sound, perex, srini, tiwai
Hi Srini,
On Wed, Oct 22, 2025 at 4:52 AM Srinivas Kandagatla
<srinivas.kandagatla@oss.qualcomm.com> wrote:
>
> On 10/22/25 1:34 AM, Steev Klimaszewski wrote:
> > Hi Srini,
> >
> > On the Thinkpad X13s, with this patchset applied, we end up seeing a NULL
> > pointer dereference:
> >
>
> Thanks Steev,
> I think I know the issue, There was a silly typo in 3/4 patch.
> Could you please try this change, I will send this in v3 anyway;
>
>
> -------------------------->cut<------------------------
> diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c
> index 16bf09db29f5..6576b47a4c8c 100644
> --- a/sound/soc/qcom/sdw.c
> +++ b/sound/soc/qcom/sdw.c
> @@ -31,6 +31,7 @@ static bool qcom_snd_is_sdw_dai(int id)
> case RX_CODEC_DMA_RX_6:
> case RX_CODEC_DMA_RX_7:
> case SLIMBUS_0_RX...SLIMBUS_6_TX:
> + return true;
> default:
> break;
> }
>
> -------------------------->cut<------------------------
>
> thanks,
> Srini>
Yep, that does it :) Thanks for the quick fix.
Tested-by: Steev Klimaszewski <threeway@gmail.com> # Thinkpad X13s
-- steev
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 2/4] ASoC: qcom: sdw: remove redundant code
2025-10-21 10:39 [PATCH v2 0/4] ASoC: qcom: sdw: fix memory leak Srinivas Kandagatla
2025-10-21 10:39 ` [PATCH v2 1/4] ASoC: qcom: sdw: fix memory leak for sdw_stream_runtime Srinivas Kandagatla
@ 2025-10-21 10:40 ` Srinivas Kandagatla
2025-10-21 10:40 ` [PATCH v2 3/4] ASoC: qcom: sdm845: make use of common helpers Srinivas Kandagatla
2025-10-21 10:40 ` [PATCH v2 4/4] ASoC: qcom: sc7280: " Srinivas Kandagatla
3 siblings, 0 replies; 8+ messages in thread
From: Srinivas Kandagatla @ 2025-10-21 10:40 UTC (permalink / raw)
To: broonie
Cc: perex, tiwai, srini, alexey.klimov, linux-sound, linux-kernel,
linux-arm-msm, Srinivas Kandagatla
remove redundant code and pointers to handle sdw_stream_runtime by
making use of qcom_snd_sdw_get_stream(). This removes need of machine
specific shutdown and hw_params sdw callbacks and also need to store
sdw_stream_runtime pointers in machine drivers.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/qcom/sc8280xp.c | 33 +++------------------------------
sound/soc/qcom/sdw.c | 24 ++++++++++++------------
sound/soc/qcom/sdw.h | 6 +-----
sound/soc/qcom/sm8250.c | 33 +++------------------------------
sound/soc/qcom/x1e80100.c | 33 +++------------------------------
5 files changed, 22 insertions(+), 107 deletions(-)
diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c
index 9ba536dff667..5bd8e8aa1853 100644
--- a/sound/soc/qcom/sc8280xp.c
+++ b/sound/soc/qcom/sc8280xp.c
@@ -18,7 +18,6 @@
struct sc8280xp_snd_data {
bool stream_prepared[AFE_PORT_MAX];
struct snd_soc_card *card;
- struct sdw_stream_runtime *sruntime[AFE_PORT_MAX];
struct snd_soc_jack jack;
struct snd_soc_jack dp_jack[8];
bool jack_setup;
@@ -68,17 +67,6 @@ static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd)
return qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup);
}
-static void sc8280xp_snd_shutdown(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct sc8280xp_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card);
- struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
-
- pdata->sruntime[cpu_dai->id] = NULL;
- sdw_release_stream(sruntime);
-}
-
static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -108,25 +96,13 @@ static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
return 0;
}
-static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct sc8280xp_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card);
-
- return qcom_snd_sdw_hw_params(substream, params, &pdata->sruntime[cpu_dai->id]);
-}
-
static int sc8280xp_snd_prepare(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
- return qcom_snd_sdw_prepare(substream, sruntime,
- &data->stream_prepared[cpu_dai->id]);
+ return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]);
}
static int sc8280xp_snd_hw_free(struct snd_pcm_substream *substream)
@@ -134,16 +110,13 @@ static int sc8280xp_snd_hw_free(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
- return qcom_snd_sdw_hw_free(substream, sruntime,
- &data->stream_prepared[cpu_dai->id]);
+ return qcom_snd_sdw_hw_free(substream, &data->stream_prepared[cpu_dai->id]);
}
static const struct snd_soc_ops sc8280xp_be_ops = {
.startup = qcom_snd_sdw_startup,
- .shutdown = sc8280xp_snd_shutdown,
- .hw_params = sc8280xp_snd_hw_params,
+ .shutdown = qcom_snd_sdw_shutdown,
.hw_free = sc8280xp_snd_hw_free,
.prepare = sc8280xp_snd_prepare,
};
diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c
index 7b2cae92c812..c44659deea01 100644
--- a/sound/soc/qcom/sdw.c
+++ b/sound/soc/qcom/sdw.c
@@ -113,19 +113,21 @@ int qcom_snd_sdw_startup(struct snd_pcm_substream *substream)
EXPORT_SYMBOL_GPL(qcom_snd_sdw_startup);
int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
- struct sdw_stream_runtime *sruntime,
bool *stream_prepared)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ struct sdw_stream_runtime *sruntime;
int ret;
- if (!sruntime)
- return 0;
if (!qcom_snd_is_sdw_dai(cpu_dai->id))
return 0;
+ sruntime = qcom_snd_sdw_get_stream(substream);
+ if (!sruntime)
+ return 0;
+
if (*stream_prepared)
return 0;
@@ -172,26 +174,24 @@ struct sdw_stream_runtime *qcom_snd_sdw_get_stream(struct snd_pcm_substream *sub
}
EXPORT_SYMBOL_GPL(qcom_snd_sdw_get_stream);
-int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct sdw_stream_runtime **psruntime)
+void qcom_snd_sdw_shutdown(struct snd_pcm_substream *substream)
{
- *psruntime = qcom_snd_sdw_get_stream(substream);
-
- return 0;
+ struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
+ sdw_release_stream(sruntime);
}
-EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params);
+EXPORT_SYMBOL_GPL(qcom_snd_sdw_shutdown);
-int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
- struct sdw_stream_runtime *sruntime, bool *stream_prepared)
+int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, bool *stream_prepared)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ struct sdw_stream_runtime *sruntime;
if (!qcom_snd_is_sdw_dai(cpu_dai->id))
return 0;
+ sruntime = qcom_snd_sdw_get_stream(substream);
if (sruntime && *stream_prepared) {
sdw_disable_stream(sruntime);
sdw_deprepare_stream(sruntime);
diff --git a/sound/soc/qcom/sdw.h b/sound/soc/qcom/sdw.h
index b8bc5beb0522..061a63f1ac52 100644
--- a/sound/soc/qcom/sdw.h
+++ b/sound/soc/qcom/sdw.h
@@ -7,14 +7,10 @@
#include <linux/soundwire/sdw.h>
int qcom_snd_sdw_startup(struct snd_pcm_substream *substream);
+void qcom_snd_sdw_shutdown(struct snd_pcm_substream *substream);
int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
- struct sdw_stream_runtime *runtime,
bool *stream_prepared);
struct sdw_stream_runtime *qcom_snd_sdw_get_stream(struct snd_pcm_substream *stream);
-int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct sdw_stream_runtime **psruntime);
int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
- struct sdw_stream_runtime *sruntime,
bool *stream_prepared);
#endif
diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c
index ce5b0059207f..203a8705a42f 100644
--- a/sound/soc/qcom/sm8250.c
+++ b/sound/soc/qcom/sm8250.c
@@ -21,7 +21,6 @@
struct sm8250_snd_data {
bool stream_prepared[AFE_PORT_MAX];
struct snd_soc_card *card;
- struct sdw_stream_runtime *sruntime[AFE_PORT_MAX];
struct snd_soc_jack jack;
struct snd_soc_jack usb_offload_jack;
bool usb_offload_jack_setup;
@@ -112,36 +111,13 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream)
return qcom_snd_sdw_startup(substream);
}
-static void sm8250_snd_shutdown(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
- struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
-
- data->sruntime[cpu_dai->id] = NULL;
- sdw_release_stream(sruntime);
-}
-
-static int sm8250_snd_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct sm8250_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card);
-
- return qcom_snd_sdw_hw_params(substream, params, &pdata->sruntime[cpu_dai->id]);
-}
-
static int sm8250_snd_prepare(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
- return qcom_snd_sdw_prepare(substream, sruntime,
- &data->stream_prepared[cpu_dai->id]);
+ return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]);
}
static int sm8250_snd_hw_free(struct snd_pcm_substream *substream)
@@ -149,16 +125,13 @@ static int sm8250_snd_hw_free(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
- return qcom_snd_sdw_hw_free(substream, sruntime,
- &data->stream_prepared[cpu_dai->id]);
+ return qcom_snd_sdw_hw_free(substream, &data->stream_prepared[cpu_dai->id]);
}
static const struct snd_soc_ops sm8250_be_ops = {
.startup = sm8250_snd_startup,
- .shutdown = sm8250_snd_shutdown,
- .hw_params = sm8250_snd_hw_params,
+ .shutdown = qcom_snd_sdw_shutdown,
.hw_free = sm8250_snd_hw_free,
.prepare = sm8250_snd_prepare,
};
diff --git a/sound/soc/qcom/x1e80100.c b/sound/soc/qcom/x1e80100.c
index 2e3599516aa2..a3f4785c4bbe 100644
--- a/sound/soc/qcom/x1e80100.c
+++ b/sound/soc/qcom/x1e80100.c
@@ -18,7 +18,6 @@
struct x1e80100_snd_data {
bool stream_prepared[AFE_PORT_MAX];
struct snd_soc_card *card;
- struct sdw_stream_runtime *sruntime[AFE_PORT_MAX];
struct snd_soc_jack jack;
struct snd_soc_jack dp_jack[8];
bool jack_setup;
@@ -50,17 +49,6 @@ static int x1e80100_snd_init(struct snd_soc_pcm_runtime *rtd)
return qcom_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup);
}
-static void x1e80100_snd_shutdown(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
- struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
-
- data->sruntime[cpu_dai->id] = NULL;
- sdw_release_stream(sruntime);
-}
-
static int x1e80100_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -85,16 +73,6 @@ static int x1e80100_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
return 0;
}
-static int x1e80100_snd_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
-
- return qcom_snd_sdw_hw_params(substream, params, &data->sruntime[cpu_dai->id]);
-}
-
static int x1e80100_snd_hw_map_channels(unsigned int *ch_map, int num)
{
switch (num) {
@@ -128,7 +106,6 @@ static int x1e80100_snd_prepare(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
unsigned int channels = substream->runtime->channels;
unsigned int rx_slot[4];
int ret;
@@ -149,8 +126,7 @@ static int x1e80100_snd_prepare(struct snd_pcm_substream *substream)
break;
}
- return qcom_snd_sdw_prepare(substream, sruntime,
- &data->stream_prepared[cpu_dai->id]);
+ return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]);
}
static int x1e80100_snd_hw_free(struct snd_pcm_substream *substream)
@@ -158,16 +134,13 @@ static int x1e80100_snd_hw_free(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
- return qcom_snd_sdw_hw_free(substream, sruntime,
- &data->stream_prepared[cpu_dai->id]);
+ return qcom_snd_sdw_hw_free(substream, &data->stream_prepared[cpu_dai->id]);
}
static const struct snd_soc_ops x1e80100_be_ops = {
.startup = qcom_snd_sdw_startup,
- .shutdown = x1e80100_snd_shutdown,
- .hw_params = x1e80100_snd_hw_params,
+ .shutdown = qcom_snd_sdw_shutdown,
.hw_free = x1e80100_snd_hw_free,
.prepare = x1e80100_snd_prepare,
};
--
2.51.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v2 3/4] ASoC: qcom: sdm845: make use of common helpers
2025-10-21 10:39 [PATCH v2 0/4] ASoC: qcom: sdw: fix memory leak Srinivas Kandagatla
2025-10-21 10:39 ` [PATCH v2 1/4] ASoC: qcom: sdw: fix memory leak for sdw_stream_runtime Srinivas Kandagatla
2025-10-21 10:40 ` [PATCH v2 2/4] ASoC: qcom: sdw: remove redundant code Srinivas Kandagatla
@ 2025-10-21 10:40 ` Srinivas Kandagatla
2025-10-21 10:40 ` [PATCH v2 4/4] ASoC: qcom: sc7280: " Srinivas Kandagatla
3 siblings, 0 replies; 8+ messages in thread
From: Srinivas Kandagatla @ 2025-10-21 10:40 UTC (permalink / raw)
To: broonie
Cc: perex, tiwai, srini, alexey.klimov, linux-sound, linux-kernel,
linux-arm-msm, Srinivas Kandagatla
sdm845 machine driver can make use of common sdw functions to do most of
the soundwire related operations. Remove such redundant code from sdm845
driver.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/qcom/sdm845.c | 53 +++--------------------------------------
1 file changed, 3 insertions(+), 50 deletions(-)
diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
index a233b80049ee..e18a8e44f2db 100644
--- a/sound/soc/qcom/sdm845.c
+++ b/sound/soc/qcom/sdm845.c
@@ -40,7 +40,6 @@ struct sdm845_snd_data {
uint32_t pri_mi2s_clk_count;
uint32_t sec_mi2s_clk_count;
uint32_t quat_tdm_clk_count;
- struct sdw_stream_runtime *sruntime[AFE_PORT_MAX];
};
static struct snd_soc_jack_pin sdm845_jack_pins[] = {
@@ -62,18 +61,11 @@ static int sdm845_slim_snd_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct snd_soc_dai *codec_dai;
- struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card);
u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
- struct sdw_stream_runtime *sruntime;
u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
int ret = 0, i;
for_each_rtd_codec_dais(rtd, i, codec_dai) {
- sruntime = snd_soc_dai_get_stream(codec_dai,
- substream->stream);
- if (sruntime != ERR_PTR(-ENOTSUPP))
- pdata->sruntime[cpu_dai->id] = sruntime;
-
ret = snd_soc_dai_get_channel_map(codec_dai,
&tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
@@ -430,7 +422,6 @@ static void sdm845_snd_shutdown(struct snd_pcm_substream *substream)
struct snd_soc_card *card = rtd->card;
struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
switch (cpu_dai->id) {
case PRIMARY_MI2S_RX:
@@ -471,8 +462,7 @@ static void sdm845_snd_shutdown(struct snd_pcm_substream *substream)
break;
}
- data->sruntime[cpu_dai->id] = NULL;
- sdw_release_stream(sruntime);
+ qcom_snd_sdw_shutdown(substream);
}
static int sdm845_snd_prepare(struct snd_pcm_substream *substream)
@@ -480,38 +470,8 @@ static int sdm845_snd_prepare(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct sdm845_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
- int ret;
-
- if (!sruntime)
- return 0;
-
- if (data->stream_prepared[cpu_dai->id]) {
- sdw_disable_stream(sruntime);
- sdw_deprepare_stream(sruntime);
- data->stream_prepared[cpu_dai->id] = false;
- }
- ret = sdw_prepare_stream(sruntime);
- if (ret)
- return ret;
-
- /**
- * NOTE: there is a strict hw requirement about the ordering of port
- * enables and actual WSA881x PA enable. PA enable should only happen
- * after soundwire ports are enabled if not DC on the line is
- * accumulated resulting in Click/Pop Noise
- * PA enable/mute are handled as part of codec DAPM and digital mute.
- */
-
- ret = sdw_enable_stream(sruntime);
- if (ret) {
- sdw_deprepare_stream(sruntime);
- return ret;
- }
- data->stream_prepared[cpu_dai->id] = true;
-
- return ret;
+ return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]);
}
static int sdm845_snd_hw_free(struct snd_pcm_substream *substream)
@@ -519,15 +479,8 @@ static int sdm845_snd_hw_free(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct sdm845_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
-
- if (sruntime && data->stream_prepared[cpu_dai->id]) {
- sdw_disable_stream(sruntime);
- sdw_deprepare_stream(sruntime);
- data->stream_prepared[cpu_dai->id] = false;
- }
- return 0;
+ return qcom_snd_sdw_hw_free(substream, &data->stream_prepared[cpu_dai->id]);
}
static const struct snd_soc_ops sdm845_be_ops = {
--
2.51.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v2 4/4] ASoC: qcom: sc7280: make use of common helpers
2025-10-21 10:39 [PATCH v2 0/4] ASoC: qcom: sdw: fix memory leak Srinivas Kandagatla
` (2 preceding siblings ...)
2025-10-21 10:40 ` [PATCH v2 3/4] ASoC: qcom: sdm845: make use of common helpers Srinivas Kandagatla
@ 2025-10-21 10:40 ` Srinivas Kandagatla
3 siblings, 0 replies; 8+ messages in thread
From: Srinivas Kandagatla @ 2025-10-21 10:40 UTC (permalink / raw)
To: broonie
Cc: perex, tiwai, srini, alexey.klimov, linux-sound, linux-kernel,
linux-arm-msm, Srinivas Kandagatla
sc7280 machine driver can make use of common sdw functions to do most of
the soundwire related operations. Remove such redundant code from sc7280
driver.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/qcom/sc7280.c | 67 ++---------------------------------------
sound/soc/qcom/sdw.c | 10 ++++++
2 files changed, 13 insertions(+), 64 deletions(-)
diff --git a/sound/soc/qcom/sc7280.c b/sound/soc/qcom/sc7280.c
index c444dae563c7..abdd58c1d0a4 100644
--- a/sound/soc/qcom/sc7280.c
+++ b/sound/soc/qcom/sc7280.c
@@ -31,7 +31,6 @@
struct sc7280_snd_data {
struct snd_soc_card card;
- struct sdw_stream_runtime *sruntime[LPASS_MAX_PORTS];
u32 pri_mi2s_clk_count;
struct snd_soc_jack hs_jack;
struct snd_soc_jack hdmi_jack;
@@ -207,32 +206,12 @@ static int sc7280_snd_hw_params(struct snd_pcm_substream *substream,
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
- struct snd_soc_dai *codec_dai;
- const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct sc7280_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card);
- struct sdw_stream_runtime *sruntime;
- int i;
if (!rtd->dai_link->no_pcm) {
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE, 48000, 48000);
}
- switch (cpu_dai->id) {
- case LPASS_CDC_DMA_TX3:
- case LPASS_CDC_DMA_RX0:
- case RX_CODEC_DMA_RX_0:
- case SECONDARY_MI2S_RX:
- case TX_CODEC_DMA_TX_3:
- case VA_CODEC_DMA_TX_0:
- for_each_rtd_codec_dais(rtd, i, codec_dai) {
- sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
- if (sruntime != ERR_PTR(-ENOTSUPP))
- pdata->sruntime[cpu_dai->id] = sruntime;
- }
- break;
- }
-
return 0;
}
@@ -241,30 +220,8 @@ static int sc7280_snd_swr_prepare(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct sc7280_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
- int ret;
- if (!sruntime)
- return 0;
-
- if (data->stream_prepared[cpu_dai->id]) {
- sdw_disable_stream(sruntime);
- sdw_deprepare_stream(sruntime);
- data->stream_prepared[cpu_dai->id] = false;
- }
-
- ret = sdw_prepare_stream(sruntime);
- if (ret)
- return ret;
-
- ret = sdw_enable_stream(sruntime);
- if (ret) {
- sdw_deprepare_stream(sruntime);
- return ret;
- }
- data->stream_prepared[cpu_dai->id] = true;
-
- return ret;
+ return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]);
}
static int sc7280_snd_prepare(struct snd_pcm_substream *substream)
@@ -291,24 +248,8 @@ static int sc7280_snd_hw_free(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct sc7280_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
- switch (cpu_dai->id) {
- case LPASS_CDC_DMA_RX0:
- case LPASS_CDC_DMA_TX3:
- case RX_CODEC_DMA_RX_0:
- case TX_CODEC_DMA_TX_3:
- case VA_CODEC_DMA_TX_0:
- if (sruntime && data->stream_prepared[cpu_dai->id]) {
- sdw_disable_stream(sruntime);
- sdw_deprepare_stream(sruntime);
- data->stream_prepared[cpu_dai->id] = false;
- }
- break;
- default:
- break;
- }
- return 0;
+ return qcom_snd_sdw_hw_free(substream, &data->stream_prepared[cpu_dai->id]);
}
static void sc7280_snd_shutdown(struct snd_pcm_substream *substream)
@@ -317,7 +258,6 @@ static void sc7280_snd_shutdown(struct snd_pcm_substream *substream)
struct snd_soc_card *card = rtd->card;
struct sc7280_snd_data *data = snd_soc_card_get_drvdata(card);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- struct sdw_stream_runtime *sruntime = qcom_snd_sdw_get_stream(substream);
switch (cpu_dai->id) {
case MI2S_PRIMARY:
@@ -336,8 +276,7 @@ static void sc7280_snd_shutdown(struct snd_pcm_substream *substream)
break;
}
- data->sruntime[cpu_dai->id] = NULL;
- sdw_release_stream(sruntime);
+ qcom_snd_sdw_shutdown(substream);
}
static int sc7280_snd_startup(struct snd_pcm_substream *substream)
diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c
index c44659deea01..16bf09db29f5 100644
--- a/sound/soc/qcom/sdw.c
+++ b/sound/soc/qcom/sdw.c
@@ -2,6 +2,7 @@
// Copyright (c) 2018-2023, Linaro Limited.
// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+#include <dt-bindings/sound/qcom,lpass.h>
#include <dt-bindings/sound/qcom,q6afe.h>
#include <linux/module.h>
#include <sound/soc.h>
@@ -30,6 +31,15 @@ static bool qcom_snd_is_sdw_dai(int id)
case RX_CODEC_DMA_RX_6:
case RX_CODEC_DMA_RX_7:
case SLIMBUS_0_RX...SLIMBUS_6_TX:
+ default:
+ break;
+ }
+
+ /* DSP Bypass usecase, cpu dai index overlaps with DSP dai ids,
+ * DO NOT MERGE into top switch case */
+ switch (id) {
+ case LPASS_CDC_DMA_TX3:
+ case LPASS_CDC_DMA_RX0:
return true;
default:
break;
--
2.51.0
^ permalink raw reply related [flat|nested] 8+ messages in thread