summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/power/user.c71
1 files changed, 59 insertions, 12 deletions
diff --git a/kernel/power/user.c b/kernel/power/user.c
index b70d83d6b16e..dd09efe7df54 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -37,6 +37,7 @@ static struct snapshot_data {
int mode;
char frozen;
char ready;
+ char platform_suspend;
} snapshot_state;
static atomic_t device_available = ATOMIC_INIT(1);
@@ -66,6 +67,7 @@ static int snapshot_open(struct inode *inode, struct file *filp)
data->bitmap = NULL;
data->frozen = 0;
data->ready = 0;
+ data->platform_suspend = 0;
return 0;
}
@@ -122,7 +124,23 @@ static ssize_t snapshot_write(struct file *filp, const char __user *buf,
return res;
}
-static int snapshot_suspend(void)
+static inline int platform_prepare(void)
+{
+ int error = 0;
+
+ if (pm_ops && pm_ops->prepare)
+ error = pm_ops->prepare(PM_SUSPEND_DISK);
+
+ return error;
+}
+
+static inline void platform_finish(void)
+{
+ if (pm_ops && pm_ops->finish)
+ pm_ops->finish(PM_SUSPEND_DISK);
+}
+
+static inline int snapshot_suspend(int platform_suspend)
{
int error;
@@ -132,6 +150,11 @@ static int snapshot_suspend(void)
if (error)
goto Finish;
+ if (platform_suspend) {
+ error = platform_prepare();
+ if (error)
+ goto Finish;
+ }
suspend_console();
error = device_suspend(PMSG_FREEZE);
if (error)
@@ -144,6 +167,9 @@ static int snapshot_suspend(void)
}
enable_nonboot_cpus();
Resume_devices:
+ if (platform_suspend)
+ platform_finish();
+
device_resume();
resume_console();
Finish:
@@ -151,12 +177,17 @@ static int snapshot_suspend(void)
return error;
}
-static int snapshot_restore(void)
+static inline int snapshot_restore(int platform_suspend)
{
int error;
mutex_lock(&pm_mutex);
pm_prepare_console();
+ if (platform_suspend) {
+ error = platform_prepare();
+ if (error)
+ goto Finish;
+ }
suspend_console();
error = device_suspend(PMSG_PRETHAW);
if (error)
@@ -168,8 +199,12 @@ static int snapshot_restore(void)
enable_nonboot_cpus();
Resume_devices:
+ if (platform_suspend)
+ platform_finish();
+
device_resume();
resume_console();
+ Finish:
pm_restore_console();
mutex_unlock(&pm_mutex);
return error;
@@ -221,7 +256,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
error = -EPERM;
break;
}
- error = snapshot_suspend();
+ error = snapshot_suspend(data->platform_suspend);
if (!error)
error = put_user(in_suspend, (unsigned int __user *)arg);
if (!error)
@@ -235,7 +270,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
error = -EPERM;
break;
}
- error = snapshot_restore();
+ error = snapshot_restore(data->platform_suspend);
break;
case SNAPSHOT_FREE:
@@ -306,6 +341,11 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
break;
case SNAPSHOT_S2RAM:
+ if (!pm_ops) {
+ error = -ENOSYS;
+ break;
+ }
+
if (!data->frozen) {
error = -EPERM;
break;
@@ -343,28 +383,35 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
break;
case SNAPSHOT_PMOPS:
+ error = -EINVAL;
+
switch (arg) {
case PMOPS_PREPARE:
- if (pm_ops->prepare) {
- error = pm_ops->prepare(PM_SUSPEND_DISK);
+ if (pm_ops && pm_ops->enter) {
+ data->platform_suspend = 1;
+ error = 0;
+ } else {
+ error = -ENOSYS;
}
break;
case PMOPS_ENTER:
- kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
- error = pm_ops->enter(PM_SUSPEND_DISK);
+ if (data->platform_suspend) {
+ kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
+ error = pm_ops->enter(PM_SUSPEND_DISK);
+ error = 0;
+ }
break;
case PMOPS_FINISH:
- if (pm_ops && pm_ops->finish) {
- pm_ops->finish(PM_SUSPEND_DISK);
- }
+ if (data->platform_suspend)
+ error = 0;
+
break;
default:
printk(KERN_ERR "SNAPSHOT_PMOPS: invalid argument %ld\n", arg);
- error = -EINVAL;
}
break;
OpenPOWER on IntegriCloud