diff options
| author | Rafael J. Wysocki <rjw@sisk.pl> | 2007-12-07 20:04:21 -0500 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2008-02-01 18:30:54 -0500 |
| commit | 72df68ca8e006a0107933c4fb13c741a0a48163f (patch) | |
| tree | c6d0d36bffc54989fffcebc8ec1368a47cfa6d65 /kernel/power | |
| parent | 2ed43b63285c394cb5e1829c199cc94c7b8233b9 (diff) | |
Hibernation: Move low level resume to disk.c
Move the low level restore code to kernel/power/disk.c , since the
corresponding low level hibernation code is already there.
Make restore fail if device_power_down(PMSG_PRETHAW) returns an
error.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'kernel/power')
| -rw-r--r-- | kernel/power/disk.c | 49 | ||||
| -rw-r--r-- | kernel/power/power.h | 1 | ||||
| -rw-r--r-- | kernel/power/swsusp.c | 35 |
3 files changed, 48 insertions, 37 deletions
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 0866b163c6bb..2a4bada184ed 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
| @@ -275,6 +275,53 @@ int hibernation_snapshot(int platform_mode) | |||
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | /** | 277 | /** |
| 278 | * resume_target_kernel - prepare devices that need to be suspended with | ||
| 279 | * interrupts off, restore the contents of highmem that have not been | ||
| 280 | * restored yet from the image and run the low level code that will restore | ||
| 281 | * the remaining contents of memory and switch to the just restored target | ||
| 282 | * kernel. | ||
| 283 | */ | ||
| 284 | |||
| 285 | static int resume_target_kernel(void) | ||
| 286 | { | ||
| 287 | int error; | ||
| 288 | |||
| 289 | local_irq_disable(); | ||
| 290 | error = device_power_down(PMSG_PRETHAW); | ||
| 291 | if (error) { | ||
| 292 | printk(KERN_ERR "Some devices failed to power down, " | ||
| 293 | "aborting resume\n"); | ||
| 294 | goto Enable_irqs; | ||
| 295 | } | ||
| 296 | /* We'll ignore saved state, but this gets preempt count (etc) right */ | ||
| 297 | save_processor_state(); | ||
| 298 | error = restore_highmem(); | ||
| 299 | if (!error) { | ||
| 300 | error = swsusp_arch_resume(); | ||
| 301 | /* | ||
| 302 | * The code below is only ever reached in case of a failure. | ||
| 303 | * Otherwise execution continues at place where | ||
| 304 | * swsusp_arch_suspend() was called | ||
| 305 | */ | ||
| 306 | BUG_ON(!error); | ||
| 307 | /* This call to restore_highmem() undos the previous one */ | ||
| 308 | restore_highmem(); | ||
| 309 | } | ||
| 310 | /* | ||
| 311 | * The only reason why swsusp_arch_resume() can fail is memory being | ||
| 312 | * very tight, so we have to free it as soon as we can to avoid | ||
| 313 | * subsequent failures | ||
| 314 | */ | ||
| 315 | swsusp_free(); | ||
| 316 | restore_processor_state(); | ||
| 317 | touch_softlockup_watchdog(); | ||
| 318 | device_power_up(); | ||
| 319 | Enable_irqs: | ||
| 320 | local_irq_enable(); | ||
| 321 | return error; | ||
| 322 | } | ||
| 323 | |||
| 324 | /** | ||
| 278 | * hibernation_restore - quiesce devices and restore the hibernation | 325 | * hibernation_restore - quiesce devices and restore the hibernation |
| 279 | * snapshot image. If successful, control returns in hibernation_snaphot() | 326 | * snapshot image. If successful, control returns in hibernation_snaphot() |
| 280 | * @platform_mode - if set, use the platform driver, if available, to | 327 | * @platform_mode - if set, use the platform driver, if available, to |
| @@ -297,7 +344,7 @@ int hibernation_restore(int platform_mode) | |||
| 297 | if (!error) { | 344 | if (!error) { |
| 298 | error = disable_nonboot_cpus(); | 345 | error = disable_nonboot_cpus(); |
| 299 | if (!error) | 346 | if (!error) |
| 300 | error = swsusp_resume(); | 347 | error = resume_target_kernel(); |
| 301 | enable_nonboot_cpus(); | 348 | enable_nonboot_cpus(); |
| 302 | } | 349 | } |
| 303 | platform_restore_cleanup(platform_mode); | 350 | platform_restore_cleanup(platform_mode); |
diff --git a/kernel/power/power.h b/kernel/power/power.h index a9732fd12239..8ec5499c5ce1 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h | |||
| @@ -152,7 +152,6 @@ extern int swsusp_swap_in_use(void); | |||
| 152 | extern int swsusp_check(void); | 152 | extern int swsusp_check(void); |
| 153 | extern int swsusp_shrink_memory(void); | 153 | extern int swsusp_shrink_memory(void); |
| 154 | extern void swsusp_free(void); | 154 | extern void swsusp_free(void); |
| 155 | extern int swsusp_resume(void); | ||
| 156 | extern int swsusp_read(unsigned int *flags_p); | 155 | extern int swsusp_read(unsigned int *flags_p); |
| 157 | extern int swsusp_write(unsigned int flags); | 156 | extern int swsusp_write(unsigned int flags); |
| 158 | extern void swsusp_close(void); | 157 | extern void swsusp_close(void); |
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 605c536795ba..dc29a20aff41 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c | |||
| @@ -261,38 +261,3 @@ int swsusp_shrink_memory(void) | |||
| 261 | 261 | ||
| 262 | return 0; | 262 | return 0; |
| 263 | } | 263 | } |
| 264 | |||
| 265 | int swsusp_resume(void) | ||
| 266 | { | ||
| 267 | int error; | ||
| 268 | |||
| 269 | local_irq_disable(); | ||
| 270 | /* NOTE: device_power_down() is just a suspend() with irqs off; | ||
| 271 | * it has no special "power things down" semantics | ||
| 272 | */ | ||
| 273 | if (device_power_down(PMSG_PRETHAW)) | ||
| 274 | printk(KERN_ERR "Some devices failed to power down, very bad\n"); | ||
| 275 | /* We'll ignore saved state, but this gets preempt count (etc) right */ | ||
| 276 | save_processor_state(); | ||
| 277 | error = restore_highmem(); | ||
| 278 | if (!error) { | ||
| 279 | error = swsusp_arch_resume(); | ||
| 280 | /* The code below is only ever reached in case of a failure. | ||
| 281 | * Otherwise execution continues at place where | ||
| 282 | * swsusp_arch_suspend() was called | ||
| 283 | */ | ||
| 284 | BUG_ON(!error); | ||
| 285 | /* This call to restore_highmem() undos the previous one */ | ||
| 286 | restore_highmem(); | ||
| 287 | } | ||
| 288 | /* The only reason why swsusp_arch_resume() can fail is memory being | ||
| 289 | * very tight, so we have to free it as soon as we can to avoid | ||
| 290 | * subsequent failures | ||
| 291 | */ | ||
| 292 | swsusp_free(); | ||
| 293 | restore_processor_state(); | ||
| 294 | touch_softlockup_watchdog(); | ||
| 295 | device_power_up(); | ||
| 296 | local_irq_enable(); | ||
| 297 | return error; | ||
| 298 | } | ||
