summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@linux.intel.com>2026-10-27 09:28:35 +0200
committerTakashi Iwai <tiwai@suse.de>2026-10-27 10:32:14 +0100
commita4311e9447bbb219044db38897f95be112f46a8a (patch)
treec83dbddc3fae1da1b885b4d46a4a9faa9b7114db
parent31ce8c24dfc8210e80ff610b35e5465cf2066323 (diff)
downloadlinux-next-a4311e9447bbb219044db38897f95be112f46a8a.tar.gz
linux-next-a4311e9447bbb219044db38897f95be112f46a8a.zip
ALSA: hda: Reject codec reset on ASoC (ext_ops) buses
Writing to the reconfig or clear sysfs nodes of a codec handled by ASoC (SOF via hdac_hda, AVS via codecs/hda) hangs the writer. snd_hda_codec_reset() sets card->shutdown and calls device_release_driver(). With ext_ops the driver unbind unregisters the ASoC component, which unbinds and frees the whole ASoC card: - snd_card_disconnect() returns early as card->shutdown is already set, so the card's child devices are not removed and snd_card_free() waits for the card release forever. - Even without that, freeing the card removes the codec's hwdep device, which owns the sysfs node the reset was issued from, deadlocking in kernfs while waiting for the active write to finish. The legacy HDA driver keeps the card across a driver rebind, ASoC does not, so the reset cannot be supported there. Return -EOPNOTSUPP and skip the misleading "codec is being used" messages in the callers. Fixes: 6bae5ea94989 ("ASoC: hdac_hda: add asoc extension for legacy HDA codec drivers") Cc: stable@vger.kernel.org Closes: https://bugzilla.kernel.org/show_bug.cgi?id=222182 Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com> Link: https://patch.msgid.link/20261027072835.4796-1-peter.ujfalusi@linux.intel.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/hda/common/codec.c6
-rw-r--r--sound/hda/common/sysfs.c4
2 files changed, 10 insertions, 0 deletions
diff --git a/sound/hda/common/codec.c b/sound/hda/common/codec.c
index 31e5fad78b0f..e367cc1c6e78 100644
--- a/sound/hda/common/codec.c
+++ b/sound/hda/common/codec.c
@@ -1807,6 +1807,12 @@ int snd_hda_codec_reset(struct hda_codec *codec)
{
struct hda_bus *bus = codec->bus;
+ /* ASoC: driver unbind frees the card, incl. the hwdep issuing the reset */
+ if (bus->core.ext_ops) {
+ codec_err(codec, "Codec reset is not supported with ASoC\n");
+ return -EOPNOTSUPP;
+ }
+
if (snd_hda_lock_devices(bus) < 0)
return -EBUSY;
diff --git a/sound/hda/common/sysfs.c b/sound/hda/common/sysfs.c
index bedf10b30885..bf65223fde10 100644
--- a/sound/hda/common/sysfs.c
+++ b/sound/hda/common/sysfs.c
@@ -117,6 +117,8 @@ static int clear_codec(struct hda_codec *codec)
int err;
err = snd_hda_codec_reset(codec);
+ if (err == -EOPNOTSUPP)
+ return err;
if (err < 0) {
codec_err(codec, "The codec is being used, can't free.\n");
return err;
@@ -132,6 +134,8 @@ static int reconfig_codec(struct hda_codec *codec)
CLASS(snd_hda_power, pm)(codec);
codec_info(codec, "hda-codec: reconfiguring\n");
err = snd_hda_codec_reset(codec);
+ if (err == -EOPNOTSUPP)
+ return err;
if (err < 0) {
codec_err(codec,
"The codec is being used, can't reconfigure.\n");