summaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2022-07-11 16:18:13 +0100
committerMark Brown <broonie@kernel.org>2022-07-11 16:18:13 +0100
commit3585da93a2762f32a718361721359eb8bec100f9 (patch)
tree37e0ad76a70175a9032906c09b56bab14c6c4be4 /sound/soc
parentfd1c769d33872d6c7ec474c199f6a910d3555927 (diff)
parentdc4fc0ae94cf87f1017f158b6fa2b7536ef29b4e (diff)
downloadlinux-3585da93a2762f32a718361721359eb8bec100f9.tar.bz2
ASoC: SOF: ipc4-topology: fix error and memory handling
Merge series from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>: Two patches to improve error and memory handling. When IPC4 is used, some of the flows were incorrect.
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/sof/ipc4-topology.c59
1 files changed, 55 insertions, 4 deletions
diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c
index 34f805431f2e..22ea628d78d0 100644
--- a/sound/soc/sof/ipc4-topology.c
+++ b/sound/soc/sof/ipc4-topology.c
@@ -263,6 +263,16 @@ err_in:
return ret;
}
+/* release the memory allocated in sof_ipc4_get_audio_fmt */
+static void sof_ipc4_free_audio_fmt(struct sof_ipc4_available_audio_format *available_fmt)
+
+{
+ kfree(available_fmt->base_config);
+ available_fmt->base_config = NULL;
+ kfree(available_fmt->out_audio_fmt);
+ available_fmt->out_audio_fmt = NULL;
+}
+
static void sof_ipc4_widget_free_comp(struct snd_sof_widget *swidget)
{
kfree(swidget->private);
@@ -341,7 +351,7 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget)
GFP_KERNEL);
if (!available_fmt->dma_buffer_size) {
ret = -ENOMEM;
- goto free_copier;
+ goto free_available_fmt;
}
ret = sof_update_ipc_object(scomp, available_fmt->dma_buffer_size,
@@ -392,8 +402,11 @@ free_gtw_attr:
kfree(ipc4_copier->gtw_attr);
err:
kfree(available_fmt->dma_buffer_size);
+free_available_fmt:
+ sof_ipc4_free_audio_fmt(available_fmt);
free_copier:
kfree(ipc4_copier);
+ swidget->private = NULL;
return ret;
}
@@ -439,7 +452,7 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget)
GFP_KERNEL);
if (!available_fmt->dma_buffer_size) {
ret = -ENOMEM;
- goto free_copier;
+ goto free_available_fmt;
}
ret = sof_update_ipc_object(scomp, available_fmt->dma_buffer_size,
@@ -539,8 +552,12 @@ free_copier_config:
kfree(ipc4_copier->copier_config);
err:
kfree(available_fmt->dma_buffer_size);
+free_available_fmt:
+ sof_ipc4_free_audio_fmt(available_fmt);
free_copier:
kfree(ipc4_copier);
+ dai->private = NULL;
+ dai->scomp = NULL;
return ret;
}
@@ -553,6 +570,12 @@ static void sof_ipc4_widget_free_comp_dai(struct snd_sof_widget *swidget)
if (!dai)
return;
+ if (!dai->private) {
+ kfree(dai);
+ swidget->private = NULL;
+ return;
+ }
+
ipc4_copier = dai->private;
available_fmt = &ipc4_copier->available_fmt;
@@ -668,10 +691,24 @@ static int sof_ipc4_widget_setup_comp_pga(struct snd_sof_widget *swidget)
return 0;
err:
+ sof_ipc4_free_audio_fmt(&gain->available_fmt);
kfree(gain);
+ swidget->private = NULL;
return ret;
}
+static void sof_ipc4_widget_free_comp_pga(struct snd_sof_widget *swidget)
+{
+ struct sof_ipc4_gain *gain = swidget->private;
+
+ if (!gain)
+ return;
+
+ sof_ipc4_free_audio_fmt(&gain->available_fmt);
+ kfree(swidget->private);
+ swidget->private = NULL;
+}
+
static int sof_ipc4_widget_setup_comp_mixer(struct snd_sof_widget *swidget)
{
struct snd_soc_component *scomp = swidget->scomp;
@@ -697,10 +734,24 @@ static int sof_ipc4_widget_setup_comp_mixer(struct snd_sof_widget *swidget)
return 0;
err:
+ sof_ipc4_free_audio_fmt(&mixer->available_fmt);
kfree(mixer);
+ swidget->private = NULL;
return ret;
}
+static void sof_ipc4_widget_free_comp_mixer(struct snd_sof_widget *swidget)
+{
+ struct sof_ipc4_mixer *mixer = swidget->private;
+
+ if (!mixer)
+ return;
+
+ sof_ipc4_free_audio_fmt(&mixer->available_fmt);
+ kfree(swidget->private);
+ swidget->private = NULL;
+}
+
static void
sof_ipc4_update_pipeline_mem_usage(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget,
struct sof_ipc4_base_module_cfg *base_config)
@@ -1735,11 +1786,11 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TY
[snd_soc_dapm_scheduler] = {sof_ipc4_widget_setup_comp_pipeline, sof_ipc4_widget_free_comp,
pipeline_token_list, ARRAY_SIZE(pipeline_token_list), NULL,
NULL, NULL},
- [snd_soc_dapm_pga] = {sof_ipc4_widget_setup_comp_pga, sof_ipc4_widget_free_comp,
+ [snd_soc_dapm_pga] = {sof_ipc4_widget_setup_comp_pga, sof_ipc4_widget_free_comp_pga,
pga_token_list, ARRAY_SIZE(pga_token_list), NULL,
sof_ipc4_prepare_gain_module,
sof_ipc4_unprepare_generic_module},
- [snd_soc_dapm_mixer] = {sof_ipc4_widget_setup_comp_mixer, sof_ipc4_widget_free_comp,
+ [snd_soc_dapm_mixer] = {sof_ipc4_widget_setup_comp_mixer, sof_ipc4_widget_free_comp_mixer,
mixer_token_list, ARRAY_SIZE(mixer_token_list),
NULL, sof_ipc4_prepare_mixer_module,
sof_ipc4_unprepare_generic_module},