Hibernation: Add PM_RESTORE_PREPARE and PM_POST_RESTORE notifiers (rev. 2)
authorAlan Stern <stern@rowland.harvard.edu>
Mon, 19 Nov 2007 22:38:25 +0000 (23:38 +0100)
committerLen Brown <len.brown@intel.com>
Fri, 1 Feb 2008 23:30:53 +0000 (18:30 -0500)
Add PM_RESTORE_PREPARE and PM_POST_RESTORE notifiers to the PM core, to be used
in analogy with the existing PM_HIBERNATION_PREPARE and PM_POST_HIBERNATION
notifiers.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: "Rafael J. Wysocki" <rjw@sisk.pl>
Signed-off-by: Len Brown <len.brown@intel.com>
Documentation/power/notifiers.txt
include/linux/notifier.h
kernel/power/disk.c
kernel/power/user.c

index 9293e4bc857c6bb7a049b8951c97ee42ab306d9c..ae1b7ec07684bad822171767bba66fc9798cc204 100644 (file)
@@ -28,6 +28,14 @@ PM_POST_HIBERNATION  The system memory state has been restored from a
                        hibernation.  Device drivers' .resume() callbacks have
                        been executed and tasks have been thawed.
 
+PM_RESTORE_PREPARE     The system is going to restore a hibernation image.
+                       If all goes well the restored kernel will issue a
+                       PM_POST_HIBERNATION notification.
+
+PM_POST_RESTORE                An error occurred during the hibernation restore.
+                       Device drivers' .resume() callbacks have been executed
+                       and tasks have been thawed.
+
 PM_SUSPEND_PREPARE     The system is preparing for a suspend.
 
 PM_POST_SUSPEND                The system has just resumed or an error occured during
index 5dfbc684ce7daab792ca9ddf40e842fe5a5cc1c7..f4df40038f0c4cb54d2596cbe051dfd9bd241f0e 100644 (file)
@@ -228,6 +228,8 @@ static inline int notifier_to_errno(int ret)
 #define PM_POST_HIBERNATION    0x0002 /* Hibernation finished */
 #define PM_SUSPEND_PREPARE     0x0003 /* Going to suspend the system */
 #define PM_POST_SUSPEND                0x0004 /* Suspend finished */
+#define PM_RESTORE_PREPARE     0x0005 /* Going to restore a saved image */
+#define PM_POST_RESTORE                0x0006 /* Restore failed */
 
 /* Console keyboard events.
  * Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and
index b138b431e27135aa7b2716335288069ea00beeee..6597365082393718923b7fb861c1210c714b7bf1 100644 (file)
@@ -499,6 +499,10 @@ static int software_resume(void)
                goto Unlock;
        }
 
+       error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
+       if (error)
+               goto Finish;
+
        error = create_basic_memory_bitmaps();
        if (error)
                goto Finish;
@@ -522,6 +526,7 @@ static int software_resume(void)
  Done:
        free_basic_memory_bitmaps();
  Finish:
+       pm_notifier_call_chain(PM_POST_RESTORE);
        atomic_inc(&snapshot_device_available);
        /* For success case, the suspend path will release the lock */
  Unlock:
index b902a7e3bd12084e8f3a479826d22ce0bc00b411..f5512cb3aa86f61e98caec04c82a01a0dc9f6dcf 100644 (file)
@@ -67,6 +67,7 @@ atomic_t snapshot_device_available = ATOMIC_INIT(1);
 static int snapshot_open(struct inode *inode, struct file *filp)
 {
        struct snapshot_data *data;
+       int error;
 
        if (!atomic_add_unless(&snapshot_device_available, -1, 0))
                return -EBUSY;
@@ -87,9 +88,19 @@ static int snapshot_open(struct inode *inode, struct file *filp)
                data->swap = swsusp_resume_device ?
                        swap_type_of(swsusp_resume_device, 0, NULL) : -1;
                data->mode = O_RDONLY;
+               error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
+               if (error)
+                       pm_notifier_call_chain(PM_POST_RESTORE);
        } else {
                data->swap = -1;
                data->mode = O_WRONLY;
+               error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
+               if (error)
+                       pm_notifier_call_chain(PM_POST_HIBERNATION);
+       }
+       if (error) {
+               atomic_inc(&snapshot_device_available);
+               return error;
        }
        data->frozen = 0;
        data->ready = 0;
@@ -111,6 +122,8 @@ static int snapshot_release(struct inode *inode, struct file *filp)
                thaw_processes();
                mutex_unlock(&pm_mutex);
        }
+       pm_notifier_call_chain(data->mode == O_WRONLY ?
+                       PM_POST_HIBERNATION : PM_POST_RESTORE);
        atomic_inc(&snapshot_device_available);
        return 0;
 }
@@ -174,18 +187,13 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                if (data->frozen)
                        break;
                mutex_lock(&pm_mutex);
-               error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
-               if (!error) {
-                       printk("Syncing filesystems ... ");
-                       sys_sync();
-                       printk("done.\n");
-
-                       error = freeze_processes();
-                       if (error)
-                               thaw_processes();
-               }
+               printk("Syncing filesystems ... ");
+               sys_sync();
+               printk("done.\n");
+
+               error = freeze_processes();
                if (error)
-                       pm_notifier_call_chain(PM_POST_HIBERNATION);
+                       thaw_processes();
                mutex_unlock(&pm_mutex);
                if (!error)
                        data->frozen = 1;
@@ -196,7 +204,6 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                        break;
                mutex_lock(&pm_mutex);
                thaw_processes();
-               pm_notifier_call_chain(PM_POST_HIBERNATION);
                mutex_unlock(&pm_mutex);
                data->frozen = 0;
                break;