diff options
Diffstat (limited to 'kernel/power/disk.c')
-rw-r--r-- | kernel/power/disk.c | 49 |
1 files changed, 48 insertions, 1 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); |