summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds2007-05-17 00:28:14 +0200
committerLinus Torvalds2007-05-17 00:33:19 +0200
commit52ade9b3b97fd3bea42842a056fe0786c28d0555 (patch)
tree70ae152f573b5d0f5078e2506830c3b804ab6816
parentarm: walk_stacktrace() needs to be exported (diff)
downloadkernel-qcow2-linux-52ade9b3b97fd3bea42842a056fe0786c28d0555.tar.gz
kernel-qcow2-linux-52ade9b3b97fd3bea42842a056fe0786c28d0555.tar.xz
kernel-qcow2-linux-52ade9b3b97fd3bea42842a056fe0786c28d0555.zip
Fix ACPI suspend / device suspend ordering problem
In commit e3c7db621bed4afb8e231cb005057f2feb5db557 we fixed the resume ordering, so that the ACPI low-level resume code was called before the actual driver resume was called. However, that broke the nesting logic of suspend and resume, and we continued to suspend the devices _after_ we the ACPI device suspend code was called. That resulted in us saving PCI state for devices that had already been changed by ACPI, and in some cases disabled entirely (causing the PCI save_state to be all-ones). Which in turn caused the wrong state to be written back on resume. This moves the ACPI device suspend to after the device model per-device suspend() calls. This fixes the bogus state save. Thanks to Lukáš Hejtmánek for testing. Acked-by: Lukas Hejtmanek <xhejtman@ics.muni.cz> Acked-by: Rafael J. Wysocki <rjw@sisk.pl> Cc: Len Brown <len.brown@intel.com> Cc: Pavel Machek <pavel@ucw.cz> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Greg KH <greg@kroah.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--kernel/power/main.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 40d56a31245e..b98b80ccf437 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -97,25 +97,26 @@ static int suspend_prepare(suspend_state_t state)
}
}
- if (pm_ops->prepare) {
- if ((error = pm_ops->prepare(state)))
- goto Thaw;
- }
-
suspend_console();
error = device_suspend(PMSG_SUSPEND);
if (error) {
printk(KERN_ERR "Some devices failed to suspend\n");
- goto Resume_devices;
+ goto Resume_console;
}
+ if (pm_ops->prepare) {
+ if ((error = pm_ops->prepare(state)))
+ goto Resume_devices;
+ }
+
error = disable_nonboot_cpus();
if (!error)
return 0;
enable_nonboot_cpus();
- Resume_devices:
pm_finish(state);
+ Resume_devices:
device_resume();
+ Resume_console:
resume_console();
Thaw:
thaw_processes();