diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2008-06-12 17:24:06 -0400 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2008-06-12 17:25:09 -0400 |
commit | d8f3de0d2412bb91639cfefc5b3c79dbf3812212 (patch) | |
tree | 05d0530d06e898b7eeac5c781ee9f00972a7f67a /kernel/power/main.c | |
parent | 53eb2fbeb9e68e1a9a23945de8450999c46270ce (diff) |
Suspend-related patches for 2.6.27
ACPI PM: Add possibility to change suspend sequence
There are some systems out there that don't work correctly with
our current suspend/hibernation code ordering. Provide a workaround
for these systems allowing them to pass 'acpi_sleep=old_ordering' in
the kernel command line so that it will use the pre-ACPI 2.0 ("old")
suspend code ordering.
Unfortunately, this requires us to add a platform hook to the
resuming of devices for recovering the platform in case one of the
device drivers' .suspend() routines returns error code. Namely,
ACPI 1.0 specifies that _PTS should be called before suspending
devices, but _WAK still should be called before resuming them in
order to undo the changes made by _PTS. However, if there is an
error during suspending devices, they are automatically resumed
without returning control to the PM core, so the _WAK has to be
called from within device_resume() in that cases.
The patch also reorders and refactors the ACPI suspend/hibernation
code to avoid duplication as far as reasonably possible.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@suse.cz>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'kernel/power/main.c')
-rw-r--r-- | kernel/power/main.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/kernel/power/main.c b/kernel/power/main.c index d023b6b584e5..3398f4651aa1 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
@@ -269,11 +269,11 @@ int suspend_devices_and_enter(suspend_state_t state) | |||
269 | error = device_suspend(PMSG_SUSPEND); | 269 | error = device_suspend(PMSG_SUSPEND); |
270 | if (error) { | 270 | if (error) { |
271 | printk(KERN_ERR "PM: Some devices failed to suspend\n"); | 271 | printk(KERN_ERR "PM: Some devices failed to suspend\n"); |
272 | goto Resume_console; | 272 | goto Recover_platform; |
273 | } | 273 | } |
274 | 274 | ||
275 | if (suspend_test(TEST_DEVICES)) | 275 | if (suspend_test(TEST_DEVICES)) |
276 | goto Resume_devices; | 276 | goto Recover_platform; |
277 | 277 | ||
278 | if (suspend_ops->prepare) { | 278 | if (suspend_ops->prepare) { |
279 | error = suspend_ops->prepare(); | 279 | error = suspend_ops->prepare(); |
@@ -294,12 +294,16 @@ int suspend_devices_and_enter(suspend_state_t state) | |||
294 | suspend_ops->finish(); | 294 | suspend_ops->finish(); |
295 | Resume_devices: | 295 | Resume_devices: |
296 | device_resume(PMSG_RESUME); | 296 | device_resume(PMSG_RESUME); |
297 | Resume_console: | ||
298 | resume_console(); | 297 | resume_console(); |
299 | Close: | 298 | Close: |
300 | if (suspend_ops->end) | 299 | if (suspend_ops->end) |
301 | suspend_ops->end(); | 300 | suspend_ops->end(); |
302 | return error; | 301 | return error; |
302 | |||
303 | Recover_platform: | ||
304 | if (suspend_ops->recover) | ||
305 | suspend_ops->recover(); | ||
306 | goto Resume_devices; | ||
303 | } | 307 | } |
304 | 308 | ||
305 | /** | 309 | /** |