ASoC: tegra: Fix memory leak in OOT machine driver

Fix a memory leak in the NVIDIA Tegra ASoC machine driver where
allocated DAPM widget lists were never freed. The function
dpcm_runtime_set_dai_fmt() calls snd_soc_dapm_dai_get_connected_widgets()
which allocates memory for a widget list, but was returning without
calling snd_soc_dapm_dai_free_widgets() to free this memory.

The leak was detected by kmemleak:
  unreferenced object 0xffff00008fc7e300 (size 192):
    comm "alsactl", pid 812, jiffies 4294900395
    backtrace:
      kmemleak_alloc+0xc0/0xe8
      __kmalloc+0x2e0/0x4c8
      snd_soc_dapm_dai_get_connected_widgets+0x108/0x2a0

Fix this by using snd_soc_dapm_dai_free_widgets() on
success or failure to ensure the widget list is always freed
before returning.

Bug 5667057
Change-Id: Ied69968884fc0646a3041e54427736ff1fc232ac
Signed-off-by: Sheetal <sheetal@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3500426
(cherry picked from commit 14b3fc2296967968d5972054bff38cf1bf4b518e)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3502770
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Sameer Pujar <spujar@nvidia.com>
Reviewed-by: Mohan kumar <mkumard@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Sheetal
2025-11-27 05:50:22 +00:00
committed by mobile promotions
parent 42b3ff7b23
commit f2c7bd17be

View File

@@ -52,17 +52,19 @@ static int dpcm_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,
#else #else
struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0);
#endif #endif
struct snd_soc_dapm_widget_list *list; struct snd_soc_dapm_widget_list *list = NULL;
int stream = SNDRV_PCM_STREAM_PLAYBACK; int stream = SNDRV_PCM_STREAM_PLAYBACK;
struct snd_soc_pcm_runtime *be; struct snd_soc_pcm_runtime *be;
struct snd_soc_dapm_widget *widget; struct snd_soc_dapm_widget *widget;
int i, ret; int i, ret = 0;
/* nothing to be done if it is a normal sound card */ /* nothing to be done if it is a normal sound card */
if (!rtd->card->component_chaining) if (!rtd->card->component_chaining)
return 0; return 0;
snd_soc_dapm_dai_get_connected_widgets(dai, stream, &list, NULL); ret = snd_soc_dapm_dai_get_connected_widgets(dai, stream, &list, NULL);
if (ret < 0)
return ret;
for_each_dapm_widgets(list, i, widget) { for_each_dapm_widgets(list, i, widget) {
if (widget->id != snd_soc_dapm_dai_in && if (widget->id != snd_soc_dapm_dai_in &&
@@ -75,10 +77,12 @@ static int dpcm_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,
ret = snd_soc_runtime_set_dai_fmt(be, fmt); ret = snd_soc_runtime_set_dai_fmt(be, fmt);
if (ret < 0) if (ret < 0)
return ret; goto out;
} }
return 0; out:
snd_soc_dapm_dai_free_widgets(&list);
return ret;
} }
static int tegra_machine_codec_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, static int tegra_machine_codec_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,