|
@@ -228,13 +228,22 @@ static int create_image(int platform_mode)
|
|
goto Unlock;
|
|
goto Unlock;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ error = platform_pre_snapshot(platform_mode);
|
|
|
|
+ if (error || hibernation_test(TEST_PLATFORM))
|
|
|
|
+ goto Platform_finish;
|
|
|
|
+
|
|
|
|
+ error = disable_nonboot_cpus();
|
|
|
|
+ if (error || hibernation_test(TEST_CPUS)
|
|
|
|
+ || hibernation_testmode(HIBERNATION_TEST))
|
|
|
|
+ goto Enable_cpus;
|
|
|
|
+
|
|
local_irq_disable();
|
|
local_irq_disable();
|
|
|
|
|
|
sysdev_suspend(PMSG_FREEZE);
|
|
sysdev_suspend(PMSG_FREEZE);
|
|
if (error) {
|
|
if (error) {
|
|
printk(KERN_ERR "PM: Some devices failed to power down, "
|
|
printk(KERN_ERR "PM: Some devices failed to power down, "
|
|
"aborting hibernation\n");
|
|
"aborting hibernation\n");
|
|
- goto Power_up_devices;
|
|
|
|
|
|
+ goto Enable_irqs;
|
|
}
|
|
}
|
|
|
|
|
|
if (hibernation_test(TEST_CORE))
|
|
if (hibernation_test(TEST_CORE))
|
|
@@ -250,15 +259,22 @@ static int create_image(int platform_mode)
|
|
restore_processor_state();
|
|
restore_processor_state();
|
|
if (!in_suspend)
|
|
if (!in_suspend)
|
|
platform_leave(platform_mode);
|
|
platform_leave(platform_mode);
|
|
|
|
+
|
|
Power_up:
|
|
Power_up:
|
|
sysdev_resume();
|
|
sysdev_resume();
|
|
/* NOTE: device_power_up() is just a resume() for devices
|
|
/* NOTE: device_power_up() is just a resume() for devices
|
|
* that suspended with irqs off ... no overall powerup.
|
|
* that suspended with irqs off ... no overall powerup.
|
|
*/
|
|
*/
|
|
|
|
|
|
- Power_up_devices:
|
|
|
|
|
|
+ Enable_irqs:
|
|
local_irq_enable();
|
|
local_irq_enable();
|
|
|
|
|
|
|
|
+ Enable_cpus:
|
|
|
|
+ enable_nonboot_cpus();
|
|
|
|
+
|
|
|
|
+ Platform_finish:
|
|
|
|
+ platform_finish(platform_mode);
|
|
|
|
+
|
|
device_power_up(in_suspend ?
|
|
device_power_up(in_suspend ?
|
|
(error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
|
|
(error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
|
|
|
|
|
|
@@ -298,25 +314,9 @@ int hibernation_snapshot(int platform_mode)
|
|
if (hibernation_test(TEST_DEVICES))
|
|
if (hibernation_test(TEST_DEVICES))
|
|
goto Recover_platform;
|
|
goto Recover_platform;
|
|
|
|
|
|
- error = platform_pre_snapshot(platform_mode);
|
|
|
|
- if (error || hibernation_test(TEST_PLATFORM))
|
|
|
|
- goto Finish;
|
|
|
|
-
|
|
|
|
- error = disable_nonboot_cpus();
|
|
|
|
- if (!error) {
|
|
|
|
- if (hibernation_test(TEST_CPUS))
|
|
|
|
- goto Enable_cpus;
|
|
|
|
-
|
|
|
|
- if (hibernation_testmode(HIBERNATION_TEST))
|
|
|
|
- goto Enable_cpus;
|
|
|
|
|
|
+ error = create_image(platform_mode);
|
|
|
|
+ /* Control returns here after successful restore */
|
|
|
|
|
|
- error = create_image(platform_mode);
|
|
|
|
- /* Control returns here after successful restore */
|
|
|
|
- }
|
|
|
|
- Enable_cpus:
|
|
|
|
- enable_nonboot_cpus();
|
|
|
|
- Finish:
|
|
|
|
- platform_finish(platform_mode);
|
|
|
|
Resume_devices:
|
|
Resume_devices:
|
|
device_resume(in_suspend ?
|
|
device_resume(in_suspend ?
|
|
(error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
|
|
(error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
|
|
@@ -338,7 +338,7 @@ int hibernation_snapshot(int platform_mode)
|
|
* kernel.
|
|
* kernel.
|
|
*/
|
|
*/
|
|
|
|
|
|
-static int resume_target_kernel(void)
|
|
|
|
|
|
+static int resume_target_kernel(bool platform_mode)
|
|
{
|
|
{
|
|
int error;
|
|
int error;
|
|
|
|
|
|
@@ -351,9 +351,20 @@ static int resume_target_kernel(void)
|
|
goto Unlock;
|
|
goto Unlock;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ error = platform_pre_restore(platform_mode);
|
|
|
|
+ if (error)
|
|
|
|
+ goto Cleanup;
|
|
|
|
+
|
|
|
|
+ error = disable_nonboot_cpus();
|
|
|
|
+ if (error)
|
|
|
|
+ goto Enable_cpus;
|
|
|
|
+
|
|
local_irq_disable();
|
|
local_irq_disable();
|
|
|
|
|
|
- sysdev_suspend(PMSG_QUIESCE);
|
|
|
|
|
|
+ error = sysdev_suspend(PMSG_QUIESCE);
|
|
|
|
+ if (error)
|
|
|
|
+ goto Enable_irqs;
|
|
|
|
+
|
|
/* We'll ignore saved state, but this gets preempt count (etc) right */
|
|
/* We'll ignore saved state, but this gets preempt count (etc) right */
|
|
save_processor_state();
|
|
save_processor_state();
|
|
error = restore_highmem();
|
|
error = restore_highmem();
|
|
@@ -379,8 +390,15 @@ static int resume_target_kernel(void)
|
|
|
|
|
|
sysdev_resume();
|
|
sysdev_resume();
|
|
|
|
|
|
|
|
+ Enable_irqs:
|
|
local_irq_enable();
|
|
local_irq_enable();
|
|
|
|
|
|
|
|
+ Enable_cpus:
|
|
|
|
+ enable_nonboot_cpus();
|
|
|
|
+
|
|
|
|
+ Cleanup:
|
|
|
|
+ platform_restore_cleanup(platform_mode);
|
|
|
|
+
|
|
device_power_up(PMSG_RECOVER);
|
|
device_power_up(PMSG_RECOVER);
|
|
|
|
|
|
Unlock:
|
|
Unlock:
|
|
@@ -405,19 +423,10 @@ int hibernation_restore(int platform_mode)
|
|
pm_prepare_console();
|
|
pm_prepare_console();
|
|
suspend_console();
|
|
suspend_console();
|
|
error = device_suspend(PMSG_QUIESCE);
|
|
error = device_suspend(PMSG_QUIESCE);
|
|
- if (error)
|
|
|
|
- goto Finish;
|
|
|
|
-
|
|
|
|
- error = platform_pre_restore(platform_mode);
|
|
|
|
if (!error) {
|
|
if (!error) {
|
|
- error = disable_nonboot_cpus();
|
|
|
|
- if (!error)
|
|
|
|
- error = resume_target_kernel();
|
|
|
|
- enable_nonboot_cpus();
|
|
|
|
|
|
+ error = resume_target_kernel(platform_mode);
|
|
|
|
+ device_resume(PMSG_RECOVER);
|
|
}
|
|
}
|
|
- platform_restore_cleanup(platform_mode);
|
|
|
|
- device_resume(PMSG_RECOVER);
|
|
|
|
- Finish:
|
|
|
|
resume_console();
|
|
resume_console();
|
|
pm_restore_console();
|
|
pm_restore_console();
|
|
return error;
|
|
return error;
|
|
@@ -453,34 +462,38 @@ int hibernation_platform_enter(void)
|
|
goto Resume_devices;
|
|
goto Resume_devices;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ device_pm_lock();
|
|
|
|
+
|
|
|
|
+ error = device_power_down(PMSG_HIBERNATE);
|
|
|
|
+ if (error)
|
|
|
|
+ goto Unlock;
|
|
|
|
+
|
|
error = hibernation_ops->prepare();
|
|
error = hibernation_ops->prepare();
|
|
if (error)
|
|
if (error)
|
|
- goto Resume_devices;
|
|
|
|
|
|
+ goto Platofrm_finish;
|
|
|
|
|
|
error = disable_nonboot_cpus();
|
|
error = disable_nonboot_cpus();
|
|
if (error)
|
|
if (error)
|
|
- goto Finish;
|
|
|
|
-
|
|
|
|
- device_pm_lock();
|
|
|
|
-
|
|
|
|
- error = device_power_down(PMSG_HIBERNATE);
|
|
|
|
- if (!error) {
|
|
|
|
- local_irq_disable();
|
|
|
|
- sysdev_suspend(PMSG_HIBERNATE);
|
|
|
|
- hibernation_ops->enter();
|
|
|
|
- /* We should never get here */
|
|
|
|
- while (1);
|
|
|
|
- }
|
|
|
|
|
|
+ goto Platofrm_finish;
|
|
|
|
|
|
- device_pm_unlock();
|
|
|
|
|
|
+ local_irq_disable();
|
|
|
|
+ sysdev_suspend(PMSG_HIBERNATE);
|
|
|
|
+ hibernation_ops->enter();
|
|
|
|
+ /* We should never get here */
|
|
|
|
+ while (1);
|
|
|
|
|
|
/*
|
|
/*
|
|
* We don't need to reenable the nonboot CPUs or resume consoles, since
|
|
* We don't need to reenable the nonboot CPUs or resume consoles, since
|
|
* the system is going to be halted anyway.
|
|
* the system is going to be halted anyway.
|
|
*/
|
|
*/
|
|
- Finish:
|
|
|
|
|
|
+ Platofrm_finish:
|
|
hibernation_ops->finish();
|
|
hibernation_ops->finish();
|
|
|
|
|
|
|
|
+ device_power_up(PMSG_RESTORE);
|
|
|
|
+
|
|
|
|
+ Unlock:
|
|
|
|
+ device_pm_unlock();
|
|
|
|
+
|
|
Resume_devices:
|
|
Resume_devices:
|
|
entering_platform_hibernation = false;
|
|
entering_platform_hibernation = false;
|
|
device_resume(PMSG_RESTORE);
|
|
device_resume(PMSG_RESTORE);
|