From affb807246886a23e43a584732801b073f774a72 Mon Sep 17 00:00:00 2001 From: Bard liao Date: Mon, 22 Apr 2019 01:16:36 +0800 Subject: [PATCH 1/2] ALSA: hda: fix unregister device twice on ASoC driver snd_hda_codec_device_new() is used by both legacy HDA and ASoC driver. However, we will call snd_hdac_device_unregister() in snd_hdac_ext_bus_device_remove() for ASoC device. This patch uses the type flag in hdac_device struct to determine is it a ASoC device or legacy HDA device and call snd_hdac_device_unregister() in snd_hda_codec_dev_free() only if it is a legacy HDA device. Signed-off-by: Bard liao --- sound/pci/hda/hda_codec.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 9f8d59e7e89f46..ae1b7475dc81fb 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -841,7 +841,13 @@ static int snd_hda_codec_dev_free(struct snd_device *device) struct hda_codec *codec = device->device_data; codec->in_freeing = 1; - snd_hdac_device_unregister(&codec->core); + /* + * snd_hda_codec_device_new() is used by legacy HDA and ASoC driver. + * We can't unregister ASoC device since it will be unregistered in + * snd_hdac_ext_bus_device_remove(). + */ + if (codec->core.type == HDA_DEV_LEGACY) + snd_hdac_device_unregister(&codec->core); codec_display_power(codec, false); put_device(hda_codec_dev(codec)); return 0; From 51bf3ff24b1ace6834defdfb7b55a62eea3a9ce3 Mon Sep 17 00:00:00 2001 From: Bard liao Date: Mon, 22 Apr 2019 03:03:27 +0800 Subject: [PATCH 2/2] ASoC: hdac_hda: overwrite hdev type to HDA_DEV_ASOC In ASoC driver, snd_hdac_device_register() will be called by snd_hdac_ext_bus_device_init() and snd_hdac_device_unregister() will called by snd_hdac_ext_bus_device_remove(). However when ASoC codec driver call snd_hda_codec_device_new() to create a new hda codec, it will assign snd_hda_codec_dev_free() to the dev_free ops and snd_hda_codec_dev_free() will call snd_hdac_device_unregister(). As a result, snd_hdac_device_unregister() will be called twice in ASoC driver. To prevent it, we use hdev type to determine if the hda codec is registered by legacy HDA driver or ASoC driver and unregister device in snd_hda_codec_dev_free() only if it is a legacy HDA device. This patch will overwrite the hdev type so that we can know it is a ASoC device. Signed-off-by: Bard liao --- sound/soc/codecs/hdac_hda.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/soc/codecs/hdac_hda.c b/sound/soc/codecs/hdac_hda.c index f889d94c8e3cf7..7d494025691498 100644 --- a/sound/soc/codecs/hdac_hda.c +++ b/sound/soc/codecs/hdac_hda.c @@ -328,6 +328,12 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) dev_err(&hdev->dev, "failed to create hda codec %d\n", ret); goto error_no_pm; } + /* + * Overwrite type to HDA_DEV_ASOC since it is a ASoC driver + * hda_codec.c will check this flag to determine if unregister + * device is needed. + */ + hdev->type = HDA_DEV_ASOC; /* * snd_hda_codec_device_new decrements the usage count so call get pm