[alsa-devel] [RFC PATCH] ALSA: hda - Explicitly keep codec powered up in hdmi_present_sense

David Henningsson david.henningsson at canonical.com
Wed Dec 18 10:46:04 CET 2013

This should help us avoid the following mutex deadlock:

[] mutex_lock+0x2a/0x50
[] hdmi_present_sense+0x53/0x3a0 [snd_hda_codec_hdmi]
[] generic_hdmi_resume+0x5a/0x70 [snd_hda_codec_hdmi]
[] hda_call_codec_resume+0xec/0x1d0 [snd_hda_codec]
[] snd_hda_power_save+0x1e4/0x280 [snd_hda_codec]
[] codec_exec_verb+0x5f/0x290 [snd_hda_codec]
[] snd_hda_codec_read+0x5b/0x90 [snd_hda_codec]
[] snd_hdmi_get_eld_size+0x1e/0x20 [snd_hda_codec_hdmi]
[] snd_hdmi_get_eld+0x2c/0xd0 [snd_hda_codec_hdmi]
[] hdmi_present_sense+0x9a/0x3a0 [snd_hda_codec_hdmi]
[] hdmi_repoll_eld+0x34/0x50 [snd_hda_codec_hdmi]

Signed-off-by: David Henningsson <david.henningsson at canonical.com>
 sound/pci/hda/patch_hdmi.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

So; I came across the above stack trace when testing the latest daily HDA driver.
It only happened once, and jack polling was enabled while testing, if that matters.

As you can see, the hdmi_present_sense is called recursively, and my patch doesn't
really fix that; it should only make the consequences less severe (because now
the recursion would be in the very beginning, i e, at snd_hda_power_up).

I first thought just unlocking the mutex before calling pin_get_eld could do,
but not sure if we really want to do that. Nevertheless, I haven't done much
of the power management work anyway, so I'd like you to double check it and potentially
come up with better ideas if you have any.

diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index f5060fc..977db17 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1496,11 +1496,14 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
 	 * specification worked this way. Hence, we just ignore the data in
 	 * the unsolicited response to avoid custom WARs.
-	int present = snd_hda_pin_sense(codec, pin_nid);
+	int present;
 	bool update_eld = false;
 	bool eld_changed = false;
 	bool ret;
+	snd_hda_power_up(codec);
+	present = snd_hda_pin_sense(codec, pin_nid);
 	pin_eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE);
 	if (pin_eld->monitor_present)
@@ -1573,6 +1576,7 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
 		jack->block_report = !ret;
+	snd_hda_power_down(codec);
 	return ret;

More information about the Alsa-devel mailing list