ALSA: hda - Explicitly keep codec powered up in hdmi_present_sense
authorDavid Henningsson <david.henningsson@canonical.com>
Wed, 18 Dec 2013 09:46:04 +0000 (10:46 +0100)
committerJiri Slaby <jslaby@suse.cz>
Wed, 12 Mar 2014 12:25:32 +0000 (13:25 +0100)
commit da4a7a3926d09c13ae052ede67feb7285e01e3f5 upstream.

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@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
sound/pci/hda/patch_hdmi.c

index aee3021042902ac2e918ca7fbbb595cbb3ac05b1..adb374babd185481aca64f2c829f3dfa8447e3a5 100644 (file)
@@ -1431,11 +1431,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);
+
        mutex_lock(&per_pin->lock);
        pin_eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE);
        if (pin_eld->monitor_present)
@@ -1505,6 +1508,7 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
        else
                ret = !repoll || !pin_eld->monitor_present || pin_eld->eld_valid;
        mutex_unlock(&per_pin->lock);
+       snd_hda_power_down(codec);
        return ret;
 }