aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2007-12-07 20:04:21 -0500
committerLen Brown <len.brown@intel.com>2008-02-01 18:30:54 -0500
commit72df68ca8e006a0107933c4fb13c741a0a48163f (patch)
treec6d0d36bffc54989fffcebc8ec1368a47cfa6d65
parent2ed43b63285c394cb5e1829c199cc94c7b8233b9 (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>
-rw-r--r--kernel/power/disk.c49
-rw-r--r--kernel/power/power.h1
-rw-r--r--kernel/power/swsusp.c35
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
285static 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);
152extern int swsusp_check(void); 152extern int swsusp_check(void);
153extern int swsusp_shrink_memory(void); 153extern int swsusp_shrink_memory(void);
154extern void swsusp_free(void); 154extern void swsusp_free(void);
155extern int swsusp_resume(void);
156extern int swsusp_read(unsigned int *flags_p); 155extern int swsusp_read(unsigned int *flags_p);
157extern int swsusp_write(unsigned int flags); 156extern int swsusp_write(unsigned int flags);
158extern void swsusp_close(void); 157extern 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
265int 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}