From: Greg Kroah-Hartman Date: Wed, 10 Oct 2012 07:27:09 +0000 (+0900) Subject: 3.6-stable patches X-Git-Tag: v3.0.46~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5832677810b4fa64a0d8d5d7c9b114f70b705a0c;p=thirdparty%2Fkernel%2Fstable-queue.git 3.6-stable patches added patches: alsa-hda-fix-hang-caused-by-race-during-suspend.patch --- diff --git a/queue-3.6/alsa-hda-fix-hang-caused-by-race-during-suspend.patch b/queue-3.6/alsa-hda-fix-hang-caused-by-race-during-suspend.patch new file mode 100644 index 00000000000..f8f2a478678 --- /dev/null +++ b/queue-3.6/alsa-hda-fix-hang-caused-by-race-during-suspend.patch @@ -0,0 +1,78 @@ +From d17344b3547669f5b6ee4fda993d03737a141bd6 Mon Sep 17 00:00:00 2001 +From: Dylan Reid +Date: Fri, 28 Sep 2012 15:57:01 -0700 +Subject: ALSA: hda - Fix hang caused by race during suspend. + +From: Dylan Reid + +commit d17344b3547669f5b6ee4fda993d03737a141bd6 upstream. + +There was a race condition when the system suspends while hda_power_work +is running in the work queue. If system suspend (snd_hda_suspend) +happens after the work queue releases power_lock but before it calls +hda_call_codec_suspend, codec_suspend runs with power_on=0, causing the +codec to power up for register reads, and hanging when it calls +cancel_delayed_work_sync from the running work queue. + +The call chain from the work queue will look like this: +hda_power_work <<- power_on = 1, unlock, then power_on cleard by suspend + hda_call_codec_suspend + hda_set_power_state + snd_hda_codec_read + codec_exec_verb + snd_hda_power_up + snd_hda_power_save + __snd_hda_power_up + cancel_delayed_work_sync <<-- cancelling executing wq + +Fix this by waiting for the work queue to finish before starting suspend +if suspend is not happening on the work queue. + +Signed-off-by: Dylan Reid +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/hda_codec.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/sound/pci/hda/hda_codec.c ++++ b/sound/pci/hda/hda_codec.c +@@ -3580,7 +3580,7 @@ static inline void hda_exec_init_verbs(s + /* + * call suspend and power-down; used both from PM and power-save + */ +-static void hda_call_codec_suspend(struct hda_codec *codec) ++static void hda_call_codec_suspend(struct hda_codec *codec, bool in_wq) + { + if (codec->patch_ops.suspend) + codec->patch_ops.suspend(codec); +@@ -3589,7 +3589,9 @@ static void hda_call_codec_suspend(struc + codec->afg ? codec->afg : codec->mfg, + AC_PWRST_D3); + #ifdef CONFIG_SND_HDA_POWER_SAVE +- cancel_delayed_work(&codec->power_work); ++ /* Cancel delayed work if we aren't currently running from it. */ ++ if (!in_wq) ++ cancel_delayed_work_sync(&codec->power_work); + spin_lock(&codec->power_lock); + snd_hda_update_power_acct(codec); + trace_hda_power_down(codec); +@@ -4410,7 +4412,7 @@ static void hda_power_work(struct work_s + } + spin_unlock(&codec->power_lock); + +- hda_call_codec_suspend(codec); ++ hda_call_codec_suspend(codec, true); + if (bus->ops.pm_notify) + bus->ops.pm_notify(bus); + } +@@ -5076,7 +5078,7 @@ int snd_hda_suspend(struct hda_bus *bus) + + list_for_each_entry(codec, &bus->codec_list, list) { + if (hda_codec_is_power_on(codec)) +- hda_call_codec_suspend(codec); ++ hda_call_codec_suspend(codec, false); + } + return 0; + } diff --git a/queue-3.6/series b/queue-3.6/series index 72341513dca..2ea7ef26cd6 100644 --- a/queue-3.6/series +++ b/queue-3.6/series @@ -106,3 +106,4 @@ efi-initialize-efi.runtime_version-to-make-query_variable_info-update_capsule-wo em28xx-regression-fix-use-drx-k-sync-firmware-requests-on-em28xx.patch sched-fix-load-avg-vs.-cpu-hotplug.patch asix-adds-support-for-lenovo-10-100-usb-dongle.patch +alsa-hda-fix-hang-caused-by-race-during-suspend.patch