From 4debc1aa2a051008acfb8ee75273e985f5688ed7 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Fri, 17 Jul 2020 09:47:52 +0800 Subject: [PATCH 1/3] ALSA: hda: fix a runtime pm issue in SOF when integrated GPU is disabled In snd_hdac_device_init pm_runtime_set_active is called to increase child_count in parent device. But when it is failed to build connection with GPU for one case that integrated graphic gpu is disabled, snd_hdac_ext_bus_device_exit will be invoked to clean up a HD-audio extended codec base device. At this time the child_count of parent is not decreased, which makes parent device can't get suspended. This patch calls pm_runtime_set_suspended to decrease child_count in parent device in snd_hdac_device_exit to match with snd_hdac_device_init. pm_runtime_set_suspended can make sure that it will not decrease child_count if the device is already suspended. Signed-off-by: Rander Wang --- sound/hda/hdac_device.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c index 333220f0f8afc0..3e9e9ac804f629 100644 --- a/sound/hda/hdac_device.c +++ b/sound/hda/hdac_device.c @@ -127,6 +127,8 @@ EXPORT_SYMBOL_GPL(snd_hdac_device_init); void snd_hdac_device_exit(struct hdac_device *codec) { pm_runtime_put_noidle(&codec->dev); + /* keep balance of runtime PM child_count in parent device */ + pm_runtime_set_suspended(&codec->dev); snd_hdac_bus_remove_device(codec->bus, codec); kfree(codec->vendor_name); kfree(codec->chip_name); From 161ab37aa354f1da4421ed52c0468e3155d42a7c Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Fri, 17 Jul 2020 16:24:15 +0800 Subject: [PATCH 2/3] ALSA: hda: release resource when snd_hdac_device_init is failed When snd_hdac_device_init is failed, the codec is released by kfree immediately without releasing some resources. The vendor_name should be free if the memory is allocated and the runtime pm status should be restored, especially the runtime pm status of parent device. Signed-off-by: Rander Wang --- sound/hda/hdac_device.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c index 3e9e9ac804f629..8d9d3722570122 100644 --- a/sound/hda/hdac_device.c +++ b/sound/hda/hdac_device.c @@ -109,12 +109,16 @@ int snd_hdac_device_init(struct hdac_device *codec, struct hdac_bus *bus, codec->vendor_id & 0xffff); if (!codec->chip_name) { err = -ENOMEM; - goto error; + goto error_chip; } return 0; + error_chip: + kfree(codec->vendor_name); error: + pm_runtime_put_noidle(&codec->dev); + pm_runtime_set_suspended(&codec->dev); put_device(&codec->dev); return err; } From a4598293dd4f10d79671d505e79756a288622a3d Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Fri, 17 Jul 2020 10:13:23 +0800 Subject: [PATCH 3/3] ASoC: SOF: fix a runtime pm issue in SOF when HDMI codec doesn't work When hda_codec_probe() doesn't initialize audio component, we disable the codec and keep going. However,the resources are not released. The child_count of SOF device is increased in snd_hdac_ext_bus_device_init but is not decrease in error case, so SOF can't get suspended. snd_hdac_ext_bus_device_exit will be invoked in HDA framework if it gets a error. Now copy this behavior to release resources and decrease SOF device child_count to release SOF device. Signed-off-by: Rander Wang --- sound/soc/sof/intel/hda-codec.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 2c5c451fa19d77..1685c143e0a94d 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -151,7 +151,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, if (!hdev->bus->audio_component) { dev_dbg(sdev->dev, "iDisp hw present but no driver\n"); - return -ENOENT; + goto error; } hda_priv->need_display_power = true; } @@ -174,7 +174,7 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, * other return codes without modification */ if (ret == 0) - ret = -ENOENT; + goto error; } return ret; @@ -187,6 +187,10 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, return ret; #endif + +error: + snd_hdac_ext_bus_device_exit(hdev); + return -ENOENT; } /* Codec initialization */