summaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorCezary Rojewski <cezary.rojewski@intel.com>2022-07-06 14:02:25 +0200
committerTakashi Iwai <tiwai@suse.de>2022-07-09 18:39:23 +0200
commitebe043a3dfcade2756a41a3956365e1bfe4198cf (patch)
tree4620207134290ff1b11baaf99d7ecbf06757ad8b /sound/pci
parent9c76958b396a1342f08f205c350447b4bb54b26a (diff)
downloadlinux-ebe043a3dfcade2756a41a3956365e1bfe4198cf.tar.bz2
ALSA: hda: Fix put_device() inconsistency in error path
AVS HDAudio bus driver does not tie with codec drivers tighly. Codec device and its respective driver cleanup procedures are split and may not occur one after the other. Device cleanup is performed only on snd_hdac_ext_bus_device_remove() i.e. it's the bus driver's responsibility. If codec component probing fails, put_device() found in snd_hda_codec_device_new() may lead to page fault. Relocate it to snd_hda_codec_new() to address the problem on ASoC side while keeping status quo for snd_hda_intel. Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com> Link: https://lore.kernel.org/r/20220706120230.427296-5-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/hda_codec.c23
1 files changed, 11 insertions, 12 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 018067addd86..e8a5d0e4105b 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -950,6 +950,7 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
unsigned int codec_addr, struct hda_codec **codecp)
{
struct hda_codec *codec;
+ int ret;
codec = snd_hda_codec_device_init(bus, codec_addr, "hdaudioC%dD%d",
card->number, codec_addr);
@@ -957,7 +958,11 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
return PTR_ERR(codec);
*codecp = codec;
- return snd_hda_codec_device_new(bus, card, codec_addr, *codecp, true);
+ ret = snd_hda_codec_device_new(bus, card, codec_addr, *codecp, true);
+ if (ret)
+ put_device(hda_codec_dev(*codecp));
+
+ return ret;
}
EXPORT_SYMBOL_GPL(snd_hda_codec_new);
@@ -1012,19 +1017,17 @@ int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card,
if (codec->bus->modelname) {
codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
- if (!codec->modelname) {
- err = -ENOMEM;
- goto error;
- }
+ if (!codec->modelname)
+ return -ENOMEM;
}
fg = codec->core.afg ? codec->core.afg : codec->core.mfg;
err = read_widget_caps(codec, fg);
if (err < 0)
- goto error;
+ return err;
err = read_pin_defaults(codec);
if (err < 0)
- goto error;
+ return err;
/* power-up all before initialization */
hda_set_power_state(codec, AC_PWRST_D0);
@@ -1042,7 +1045,7 @@ int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card,
/* ASoC features component management instead */
err = snd_device_new(card, SNDRV_DEV_CODEC, codec, &dev_ops);
if (err < 0)
- goto error;
+ return err;
}
#ifdef CONFIG_PM
@@ -1055,10 +1058,6 @@ int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card,
#endif
return 0;
-
- error:
- put_device(hda_codec_dev(codec));
- return err;
}
EXPORT_SYMBOL_GPL(snd_hda_codec_device_new);