|
@@ -92,6 +92,17 @@ static int platform_pre_snapshot(int platform_mode)
|
|
hibernation_ops->pre_snapshot() : 0;
|
|
hibernation_ops->pre_snapshot() : 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * platform_leave - prepare the machine for switching to the normal mode
|
|
|
|
+ * of operation using the platform driver (called with interrupts disabled)
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+static void platform_leave(int platform_mode)
|
|
|
|
+{
|
|
|
|
+ if (platform_mode && hibernation_ops)
|
|
|
|
+ hibernation_ops->leave();
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* platform_finish - switch the machine to the normal mode of operation
|
|
* platform_finish - switch the machine to the normal mode of operation
|
|
* using the platform driver (must be called after platform_prepare())
|
|
* using the platform driver (must be called after platform_prepare())
|
|
@@ -128,6 +139,51 @@ static void platform_restore_cleanup(int platform_mode)
|
|
hibernation_ops->restore_cleanup();
|
|
hibernation_ops->restore_cleanup();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * create_image - freeze devices that need to be frozen with interrupts
|
|
|
|
+ * off, create the hibernation image and thaw those devices. Control
|
|
|
|
+ * reappears in this routine after a restore.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+int create_image(int platform_mode)
|
|
|
|
+{
|
|
|
|
+ int error;
|
|
|
|
+
|
|
|
|
+ error = arch_prepare_suspend();
|
|
|
|
+ if (error)
|
|
|
|
+ return error;
|
|
|
|
+
|
|
|
|
+ local_irq_disable();
|
|
|
|
+ /* At this point, device_suspend() has been called, but *not*
|
|
|
|
+ * device_power_down(). We *must* call device_power_down() now.
|
|
|
|
+ * Otherwise, drivers for some devices (e.g. interrupt controllers)
|
|
|
|
+ * become desynchronized with the actual state of the hardware
|
|
|
|
+ * at resume time, and evil weirdness ensues.
|
|
|
|
+ */
|
|
|
|
+ error = device_power_down(PMSG_FREEZE);
|
|
|
|
+ if (error) {
|
|
|
|
+ printk(KERN_ERR "Some devices failed to power down, "
|
|
|
|
+ KERN_ERR "aborting suspend\n");
|
|
|
|
+ goto Enable_irqs;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ save_processor_state();
|
|
|
|
+ error = swsusp_arch_suspend();
|
|
|
|
+ if (error)
|
|
|
|
+ printk(KERN_ERR "Error %d while creating the image\n", error);
|
|
|
|
+ /* Restore control flow magically appears here */
|
|
|
|
+ restore_processor_state();
|
|
|
|
+ if (!in_suspend)
|
|
|
|
+ platform_leave(platform_mode);
|
|
|
|
+ /* NOTE: device_power_up() is just a resume() for devices
|
|
|
|
+ * that suspended with irqs off ... no overall powerup.
|
|
|
|
+ */
|
|
|
|
+ device_power_up();
|
|
|
|
+ Enable_irqs:
|
|
|
|
+ local_irq_enable();
|
|
|
|
+ return error;
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* hibernation_snapshot - quiesce devices and create the hibernation
|
|
* hibernation_snapshot - quiesce devices and create the hibernation
|
|
* snapshot image.
|
|
* snapshot image.
|
|
@@ -163,7 +219,7 @@ int hibernation_snapshot(int platform_mode)
|
|
if (!error) {
|
|
if (!error) {
|
|
if (hibernation_mode != HIBERNATION_TEST) {
|
|
if (hibernation_mode != HIBERNATION_TEST) {
|
|
in_suspend = 1;
|
|
in_suspend = 1;
|
|
- error = swsusp_suspend();
|
|
|
|
|
|
+ error = create_image(platform_mode);
|
|
/* Control returns here after successful restore */
|
|
/* Control returns here after successful restore */
|
|
} else {
|
|
} else {
|
|
printk("swsusp debug: Waiting for 5 seconds.\n");
|
|
printk("swsusp debug: Waiting for 5 seconds.\n");
|