swsusp: remove code duplication between disk.c and user.c
authorRafael J. Wysocki <rjw@sisk.pl>
Thu, 19 Jul 2007 08:47:29 +0000 (01:47 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Thu, 19 Jul 2007 17:04:42 +0000 (10:04 -0700)
Currently, much of the code in kernel/power/disk.c is duplicated in
kernel/power/user.c , mainly for historical reasons.  By eliminating this code
duplication we can reduce the size of user.c quite substantially and remove
the maintenance difficulty resulting from it.

[bunk@stusta.de: kernel/power/disk.c: make code static]
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Cc: Nigel Cunningham <nigel@nigel.suspend2.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
kernel/power/disk.c
kernel/power/power.h
kernel/power/user.c

index f445b9cd60fbdacad64214fd05ceed7364a82ed7..47882bfa610e5b0edb23d7dff3dfb61d9e32f4cc 100644 (file)
@@ -45,7 +45,7 @@ enum {
 
 static int hibernation_mode = HIBERNATION_SHUTDOWN;
 
-struct hibernation_ops *hibernation_ops;
+static struct hibernation_ops *hibernation_ops;
 
 /**
  * hibernation_set_ops - set the global hibernate operations
@@ -74,9 +74,9 @@ void hibernation_set_ops(struct hibernation_ops *ops)
  *     platform driver if so configured and return an error code if it fails
  */
 
-static int platform_prepare(void)
+static int platform_prepare(int platform_mode)
 {
-       return (hibernation_mode == HIBERNATION_PLATFORM && hibernation_ops) ?
+       return (platform_mode && hibernation_ops) ?
                hibernation_ops->prepare() : 0;
 }
 
@@ -85,12 +85,103 @@ static int platform_prepare(void)
  *     using the platform driver (must be called after platform_prepare())
  */
 
-static void platform_finish(void)
+static void platform_finish(int platform_mode)
 {
-       if (hibernation_mode == HIBERNATION_PLATFORM && hibernation_ops)
+       if (platform_mode && hibernation_ops)
                hibernation_ops->finish();
 }
 
+/**
+ *     hibernation_snapshot - quiesce devices and create the hibernation
+ *     snapshot image.
+ *     @platform_mode - if set, use the platform driver, if available, to
+ *                      prepare the platform frimware for the power transition.
+ *
+ *     Must be called with pm_mutex held
+ */
+
+int hibernation_snapshot(int platform_mode)
+{
+       int error;
+
+       /* Free memory before shutting down devices. */
+       error = swsusp_shrink_memory();
+       if (error)
+               goto Finish;
+
+       error = platform_prepare(platform_mode);
+       if (error)
+               goto Finish;
+
+       suspend_console();
+       error = device_suspend(PMSG_FREEZE);
+       if (error)
+               goto Resume_devices;
+
+       error = disable_nonboot_cpus();
+       if (!error) {
+               if (hibernation_mode != HIBERNATION_TEST) {
+                       in_suspend = 1;
+                       error = swsusp_suspend();
+                       /* Control returns here after successful restore */
+               } else {
+                       printk("swsusp debug: Waiting for 5 seconds.\n");
+                       mdelay(5000);
+               }
+       }
+       enable_nonboot_cpus();
+ Resume_devices:
+       platform_finish(platform_mode);
+       device_resume();
+       resume_console();
+ Finish:
+       return error;
+}
+
+/**
+ *     hibernation_restore - quiesce devices and restore the hibernation
+ *     snapshot image.  If successful, control returns in hibernation_snaphot()
+ *
+ *     Must be called with pm_mutex held
+ */
+
+int hibernation_restore(void)
+{
+       int error;
+
+       pm_prepare_console();
+       suspend_console();
+       error = device_suspend(PMSG_PRETHAW);
+       if (error)
+               goto Finish;
+
+       error = disable_nonboot_cpus();
+       if (!error)
+               error = swsusp_resume();
+
+       enable_nonboot_cpus();
+ Finish:
+       device_resume();
+       resume_console();
+       pm_restore_console();
+       return error;
+}
+
+/**
+ *     hibernation_platform_enter - enter the hibernation state using the
+ *     platform driver (if available)
+ */
+
+int hibernation_platform_enter(void)
+{
+       if (hibernation_ops) {
+               kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
+               return hibernation_ops->enter();
+       } else {
+               return -ENOSYS;
+       }
+}
+
 /**
  *     power_down - Shut the machine down for hibernation.
  *
@@ -111,11 +202,7 @@ static void power_down(void)
                kernel_restart(NULL);
                break;
        case HIBERNATION_PLATFORM:
-               if (hibernation_ops) {
-                       kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
-                       hibernation_ops->enter();
-                       break;
-               }
+               hibernation_platform_enter();
        }
        kernel_halt();
        /*
@@ -171,62 +258,17 @@ int hibernate(void)
                mdelay(5000);
                goto Thaw;
        }
-
-       /* Free memory before shutting down devices. */
-       error = swsusp_shrink_memory();
-       if (error)
-               goto Thaw;
-
-       error = platform_prepare();
-       if (error)
-               goto Thaw;
-
-       suspend_console();
-       error = device_suspend(PMSG_FREEZE);
-       if (error) {
-               printk(KERN_ERR "PM: Some devices failed to suspend\n");
-               goto Resume_devices;
-       }
-       error = disable_nonboot_cpus();
-       if (error)
-               goto Enable_cpus;
-
-       if (hibernation_mode == HIBERNATION_TEST) {
-               printk("swsusp debug: Waiting for 5 seconds.\n");
-               mdelay(5000);
-               goto Enable_cpus;
-       }
-
-       pr_debug("PM: snapshotting memory.\n");
-       in_suspend = 1;
-       error = swsusp_suspend();
-       if (error)
-               goto Enable_cpus;
-
-       if (in_suspend) {
-               enable_nonboot_cpus();
-               platform_finish();
-               device_resume();
-               resume_console();
+       error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
+       if (in_suspend && !error) {
                pr_debug("PM: writing image.\n");
                error = swsusp_write();
+               swsusp_free();
                if (!error)
                        power_down();
-               else {
-                       swsusp_free();
-                       goto Thaw;
-               }
        } else {
                pr_debug("PM: Image restored successfully.\n");
+               swsusp_free();
        }
-
-       swsusp_free();
- Enable_cpus:
-       enable_nonboot_cpus();
- Resume_devices:
-       platform_finish();
-       device_resume();
-       resume_console();
  Thaw:
        mutex_unlock(&pm_mutex);
        unprepare_processes();
@@ -301,29 +343,11 @@ static int software_resume(void)
        pr_debug("PM: Reading swsusp image.\n");
 
        error = swsusp_read();
-       if (error) {
-               swsusp_free();
-               goto Thaw;
-       }
-
-       pr_debug("PM: Preparing devices for restore.\n");
-
-       suspend_console();
-       error = device_suspend(PMSG_PRETHAW);
-       if (error)
-               goto Free;
-
-       error = disable_nonboot_cpus();
        if (!error)
-               swsusp_resume();
+               hibernation_restore();
 
-       enable_nonboot_cpus();
- Free:
-       swsusp_free();
-       device_resume();
-       resume_console();
- Thaw:
        printk(KERN_ERR "PM: Restore failed, recovering.\n");
+       swsusp_free();
        unprepare_processes();
  Done:
        free_basic_memory_bitmaps();
@@ -333,7 +357,7 @@ static int software_resume(void)
  Unlock:
        mutex_unlock(&pm_mutex);
        pr_debug("PM: Resume from disk failed.\n");
-       return 0;
+       return error;
 }
 
 late_initcall(software_resume);
index 51381487103ff405263cb48983db8102ce7f73f8..70c378b3f85ae0d6c45dde4341891ff2c797a6d1 100644 (file)
@@ -25,7 +25,10 @@ struct swsusp_info {
  */
 #define SPARE_PAGES    ((1024 * 1024) >> PAGE_SHIFT)
 
-extern struct hibernation_ops *hibernation_ops;
+/* kernel/power/disk.c */
+extern int hibernation_snapshot(int platform_mode);
+extern int hibernation_restore(void);
+extern int hibernation_platform_enter(void);
 #endif
 
 extern int pfn_is_nosave(unsigned long);
index 09468ec61124ff8184d23684e45343a8e81d216a..bfed3b924093579a7dfef33e75a307eb19e4669b 100644 (file)
@@ -128,83 +128,6 @@ static ssize_t snapshot_write(struct file *filp, const char __user *buf,
        return res;
 }
 
-static inline int platform_prepare(void)
-{
-       int error = 0;
-
-       if (hibernation_ops)
-               error = hibernation_ops->prepare();
-
-       return error;
-}
-
-static inline void platform_finish(void)
-{
-       if (hibernation_ops)
-               hibernation_ops->finish();
-}
-
-static inline int snapshot_suspend(int platform_suspend)
-{
-       int error;
-
-       mutex_lock(&pm_mutex);
-       /* Free memory before shutting down devices. */
-       error = swsusp_shrink_memory();
-       if (error)
-               goto Finish;
-
-       if (platform_suspend) {
-               error = platform_prepare();
-               if (error)
-                       goto Finish;
-       }
-       suspend_console();
-       error = device_suspend(PMSG_FREEZE);
-       if (error)
-               goto Resume_devices;
-
-       error = disable_nonboot_cpus();
-       if (!error) {
-               in_suspend = 1;
-               error = swsusp_suspend();
-       }
-       enable_nonboot_cpus();
- Resume_devices:
-       if (platform_suspend)
-               platform_finish();
-
-       device_resume();
-       resume_console();
- Finish:
-       mutex_unlock(&pm_mutex);
-       return error;
-}
-
-static inline int snapshot_restore(void)
-{
-       int error;
-
-       mutex_lock(&pm_mutex);
-       pm_prepare_console();
-       suspend_console();
-       error = device_suspend(PMSG_PRETHAW);
-       if (error)
-               goto Finish;
-
-       error = disable_nonboot_cpus();
-       if (!error)
-               error = swsusp_resume();
-
-       enable_nonboot_cpus();
- Finish:
-       device_resume();
-       resume_console();
-       pm_restore_console();
-       mutex_unlock(&pm_mutex);
-       return error;
-}
-
 static int snapshot_ioctl(struct inode *inode, struct file *filp,
                           unsigned int cmd, unsigned long arg)
 {
@@ -251,7 +174,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                        error = -EPERM;
                        break;
                }
-               error = snapshot_suspend(data->platform_suspend);
+               error = hibernation_snapshot(data->platform_suspend);
                if (!error)
                        error = put_user(in_suspend, (unsigned int __user *)arg);
                if (!error)
@@ -265,7 +188,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                        error = -EPERM;
                        break;
                }
-               error = snapshot_restore();
+               error = hibernation_restore();
                break;
 
        case SNAPSHOT_FREE:
@@ -377,19 +300,14 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                switch (arg) {
 
                case PMOPS_PREPARE:
-                       if (hibernation_ops) {
-                               data->platform_suspend = 1;
-                               error = 0;
-                       } else {
-                               error = -ENOSYS;
-                       }
+                       data->platform_suspend = 1;
+                       error = 0;
                        break;
 
                case PMOPS_ENTER:
-                       if (data->platform_suspend) {
-                               kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
-                               error = hibernation_ops->enter();
-                       }
+                       if (data->platform_suspend)
+                               error = hibernation_platform_enter();
+
                        break;
 
                case PMOPS_FINISH: