[PATCH v2 3/3] ALSA: hda: Drain PCM users before cleaning up a failed codec probe

From: Cen Zhang

Date: Sat Oct 24 2026 - 07:42:35 EST


A late codec probe on a registered card calls snd_card_register() after
building its PCMs. Some components can be registered and opened before
a later component registration fails. The error path then invokes the
driver's remove callback and frees the codec's PCM resources without
waiting for those users, unlike normal codec removal:

Late HDA codec probe Native PCM user
-------------------- ---------------
snd_card_register()
register PCM A
open PCM A
driver takes codec PCM reference
register PCM B fails
driver->ops->remove()
cleanup_for_unbind()
codec_release_pcms()
use PCM or enter driver close

Disconnect the codec's PCMs and wait for codec PCM references before
calling driver->ops->remove() on the error path. Disconnection drops
the construction references and blocks new driver opens; existing
users can finish while codec-specific state is still alive.

The PCM core's lookup reference and disconnection gate cover pending
openers which have not entered the driver. Waiting here additionally
covers users which already acquired the codec's own usage reference.
The later cleanup disconnection remains harmless because each PCM's
disconnected flag prevents dropping its construction reference twice.

Fixes: bcd96557bd0a ("ALSA: hda - Build PCMs and controls at codec driver probe")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@xxxxxxxxx>
---
sound/hda/common/bind.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/sound/hda/common/bind.c b/sound/hda/common/bind.c
index 957feace0f58..3c249d70ac1c 100644
--- a/sound/hda/common/bind.c
+++ b/sound/hda/common/bind.c
@@ -145,6 +145,9 @@ static int hda_codec_driver_probe(struct device *dev)
error_module:
snd_hdac_device_disable_unsol(&codec->core);
cancel_delayed_work_sync(&codec->jackpoll_work);
+ /* A late probe can already have published working PCM components. */
+ snd_hda_codec_disconnect_pcms(codec);
+ snd_refcount_sync(&codec->pcm_ref);
if (probed && driver->ops->remove)
driver->ops->remove(codec);
error_module_put:
--
2.43.0