]> Pileus Git - ~andy/linux/blobdiff - kernel/power/user.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
[~andy/linux] / kernel / power / user.c
index 8cabc405ca10e3289bdd9a7733a7bde56fe38f28..72825c853cd7251bf73fa13cbea63e78c09d8845 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/swapops.h>
 #include <linux/pm.h>
 #include <linux/fs.h>
+#include <linux/cpu.h>
 
 #include <asm/uaccess.h>
 
@@ -138,16 +139,16 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
        case SNAPSHOT_FREEZE:
                if (data->frozen)
                        break;
-               sys_sync();
                down(&pm_sem);
-               pm_prepare_console();
-               disable_nonboot_cpus();
-               if (freeze_processes()) {
-                       thaw_processes();
-                       enable_nonboot_cpus();
-                       pm_restore_console();
-                       error = -EBUSY;
+               error = disable_nonboot_cpus();
+               if (!error) {
+                       error = freeze_processes();
+                       if (error) {
+                               thaw_processes();
+                               error = -EBUSY;
+                       }
                }
+               enable_nonboot_cpus();
                up(&pm_sem);
                if (!error)
                        data->frozen = 1;
@@ -159,7 +160,6 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                down(&pm_sem);
                thaw_processes();
                enable_nonboot_cpus();
-               pm_restore_console();
                up(&pm_sem);
                data->frozen = 0;
                break;
@@ -193,9 +193,10 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                        error = -EPERM;
                        break;
                }
+               snapshot_free_unused_memory(&data->handle);
                down(&pm_sem);
                pm_prepare_console();
-               error = device_suspend(PMSG_FREEZE);
+               error = device_suspend(PMSG_PRETHAW);
                if (!error) {
                        error = swsusp_resume();
                        device_resume();
@@ -270,6 +271,42 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                }
                break;
 
+       case SNAPSHOT_S2RAM:
+               if (!data->frozen) {
+                       error = -EPERM;
+                       break;
+               }
+
+               if (down_trylock(&pm_sem)) {
+                       error = -EBUSY;
+                       break;
+               }
+
+               if (pm_ops->prepare) {
+                       error = pm_ops->prepare(PM_SUSPEND_MEM);
+                       if (error)
+                               goto OutS3;
+               }
+
+               /* Put devices to sleep */
+               error = device_suspend(PMSG_SUSPEND);
+               if (error) {
+                       printk(KERN_ERR "Failed to suspend some devices.\n");
+               } else {
+                       /* Enter S3, system is already frozen */
+                       suspend_enter(PM_SUSPEND_MEM);
+
+                       /* Wake up devices */
+                       device_resume();
+               }
+
+               if (pm_ops->finish)
+                       pm_ops->finish(PM_SUSPEND_MEM);
+
+OutS3:
+               up(&pm_sem);
+               break;
+
        default:
                error = -ENOTTY;