|
@@ -5,6 +5,7 @@
|
|
|
* Copyright (c) 2003 Open Source Development Lab
|
|
|
* Copyright (c) 2004 Pavel Machek <pavel@ucw.cz>
|
|
|
* Copyright (c) 2009 Rafael J. Wysocki, Novell Inc.
|
|
|
+ * Copyright (C) 2012 Bojan Smojver <bojan@rexursive.com>
|
|
|
*
|
|
|
* This file is released under the GPLv2.
|
|
|
*/
|
|
@@ -46,6 +47,9 @@ enum {
|
|
|
HIBERNATION_PLATFORM,
|
|
|
HIBERNATION_SHUTDOWN,
|
|
|
HIBERNATION_REBOOT,
|
|
|
+#ifdef CONFIG_SUSPEND
|
|
|
+ HIBERNATION_SUSPEND,
|
|
|
+#endif
|
|
|
/* keep last */
|
|
|
__HIBERNATION_AFTER_LAST
|
|
|
};
|
|
@@ -574,6 +578,10 @@ int hibernation_platform_enter(void)
|
|
|
*/
|
|
|
static void power_down(void)
|
|
|
{
|
|
|
+#ifdef CONFIG_SUSPEND
|
|
|
+ int error;
|
|
|
+#endif
|
|
|
+
|
|
|
switch (hibernation_mode) {
|
|
|
case HIBERNATION_REBOOT:
|
|
|
kernel_restart(NULL);
|
|
@@ -583,6 +591,25 @@ static void power_down(void)
|
|
|
case HIBERNATION_SHUTDOWN:
|
|
|
kernel_power_off();
|
|
|
break;
|
|
|
+#ifdef CONFIG_SUSPEND
|
|
|
+ case HIBERNATION_SUSPEND:
|
|
|
+ error = suspend_devices_and_enter(PM_SUSPEND_MEM);
|
|
|
+ if (error) {
|
|
|
+ if (hibernation_ops)
|
|
|
+ hibernation_mode = HIBERNATION_PLATFORM;
|
|
|
+ else
|
|
|
+ hibernation_mode = HIBERNATION_SHUTDOWN;
|
|
|
+ power_down();
|
|
|
+ }
|
|
|
+ /*
|
|
|
+ * Restore swap signature.
|
|
|
+ */
|
|
|
+ error = swsusp_unmark();
|
|
|
+ if (error)
|
|
|
+ printk(KERN_ERR "PM: Swap will be unusable! "
|
|
|
+ "Try swapon -a.\n");
|
|
|
+ return;
|
|
|
+#endif
|
|
|
}
|
|
|
kernel_halt();
|
|
|
/*
|
|
@@ -827,6 +854,9 @@ static const char * const hibernation_modes[] = {
|
|
|
[HIBERNATION_PLATFORM] = "platform",
|
|
|
[HIBERNATION_SHUTDOWN] = "shutdown",
|
|
|
[HIBERNATION_REBOOT] = "reboot",
|
|
|
+#ifdef CONFIG_SUSPEND
|
|
|
+ [HIBERNATION_SUSPEND] = "suspend",
|
|
|
+#endif
|
|
|
};
|
|
|
|
|
|
/*
|
|
@@ -867,6 +897,9 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
switch (i) {
|
|
|
case HIBERNATION_SHUTDOWN:
|
|
|
case HIBERNATION_REBOOT:
|
|
|
+#ifdef CONFIG_SUSPEND
|
|
|
+ case HIBERNATION_SUSPEND:
|
|
|
+#endif
|
|
|
break;
|
|
|
case HIBERNATION_PLATFORM:
|
|
|
if (hibernation_ops)
|
|
@@ -907,6 +940,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|
|
switch (mode) {
|
|
|
case HIBERNATION_SHUTDOWN:
|
|
|
case HIBERNATION_REBOOT:
|
|
|
+#ifdef CONFIG_SUSPEND
|
|
|
+ case HIBERNATION_SUSPEND:
|
|
|
+#endif
|
|
|
hibernation_mode = mode;
|
|
|
break;
|
|
|
case HIBERNATION_PLATFORM:
|