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;