diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2007-11-19 17:38:25 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2008-02-01 18:30:53 -0500 |
commit | c3e94d899c864e558f938f9845ddb8c2e5d5ccd0 (patch) | |
tree | cdc2d5007e2d8053ab1903f9e66c46dca9a9de81 | |
parent | 2f8ed1c60b06b797bf79a1dc540f0bed8c9d75a0 (diff) |
Hibernation: Add PM_RESTORE_PREPARE and PM_POST_RESTORE notifiers (rev. 2)
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>
-rw-r--r-- | Documentation/power/notifiers.txt | 8 | ||||
-rw-r--r-- | include/linux/notifier.h | 2 | ||||
-rw-r--r-- | kernel/power/disk.c | 5 | ||||
-rw-r--r-- | kernel/power/user.c | 31 |
4 files changed, 34 insertions, 12 deletions
diff --git a/Documentation/power/notifiers.txt b/Documentation/power/notifiers.txt index 9293e4bc857c..ae1b7ec07684 100644 --- a/Documentation/power/notifiers.txt +++ b/Documentation/power/notifiers.txt | |||
@@ -28,6 +28,14 @@ PM_POST_HIBERNATION The system memory state has been restored from a | |||
28 | hibernation. Device drivers' .resume() callbacks have | 28 | hibernation. Device drivers' .resume() callbacks have |
29 | been executed and tasks have been thawed. | 29 | been executed and tasks have been thawed. |
30 | 30 | ||
31 | PM_RESTORE_PREPARE The system is going to restore a hibernation image. | ||
32 | If all goes well the restored kernel will issue a | ||
33 | PM_POST_HIBERNATION notification. | ||
34 | |||
35 | PM_POST_RESTORE An error occurred during the hibernation restore. | ||
36 | Device drivers' .resume() callbacks have been executed | ||
37 | and tasks have been thawed. | ||
38 | |||
31 | PM_SUSPEND_PREPARE The system is preparing for a suspend. | 39 | PM_SUSPEND_PREPARE The system is preparing for a suspend. |
32 | 40 | ||
33 | PM_POST_SUSPEND The system has just resumed or an error occured during | 41 | PM_POST_SUSPEND The system has just resumed or an error occured during |
diff --git a/include/linux/notifier.h b/include/linux/notifier.h index 5dfbc684ce7d..f4df40038f0c 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h | |||
@@ -228,6 +228,8 @@ static inline int notifier_to_errno(int ret) | |||
228 | #define PM_POST_HIBERNATION 0x0002 /* Hibernation finished */ | 228 | #define PM_POST_HIBERNATION 0x0002 /* Hibernation finished */ |
229 | #define PM_SUSPEND_PREPARE 0x0003 /* Going to suspend the system */ | 229 | #define PM_SUSPEND_PREPARE 0x0003 /* Going to suspend the system */ |
230 | #define PM_POST_SUSPEND 0x0004 /* Suspend finished */ | 230 | #define PM_POST_SUSPEND 0x0004 /* Suspend finished */ |
231 | #define PM_RESTORE_PREPARE 0x0005 /* Going to restore a saved image */ | ||
232 | #define PM_POST_RESTORE 0x0006 /* Restore failed */ | ||
231 | 233 | ||
232 | /* Console keyboard events. | 234 | /* Console keyboard events. |
233 | * Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and | 235 | * Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and |
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index b138b431e271..659736508239 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
@@ -499,6 +499,10 @@ static int software_resume(void) | |||
499 | goto Unlock; | 499 | goto Unlock; |
500 | } | 500 | } |
501 | 501 | ||
502 | error = pm_notifier_call_chain(PM_RESTORE_PREPARE); | ||
503 | if (error) | ||
504 | goto Finish; | ||
505 | |||
502 | error = create_basic_memory_bitmaps(); | 506 | error = create_basic_memory_bitmaps(); |
503 | if (error) | 507 | if (error) |
504 | goto Finish; | 508 | goto Finish; |
@@ -522,6 +526,7 @@ static int software_resume(void) | |||
522 | Done: | 526 | Done: |
523 | free_basic_memory_bitmaps(); | 527 | free_basic_memory_bitmaps(); |
524 | Finish: | 528 | Finish: |
529 | pm_notifier_call_chain(PM_POST_RESTORE); | ||
525 | atomic_inc(&snapshot_device_available); | 530 | atomic_inc(&snapshot_device_available); |
526 | /* For success case, the suspend path will release the lock */ | 531 | /* For success case, the suspend path will release the lock */ |
527 | Unlock: | 532 | Unlock: |
diff --git a/kernel/power/user.c b/kernel/power/user.c index b902a7e3bd12..f5512cb3aa86 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c | |||
@@ -67,6 +67,7 @@ atomic_t snapshot_device_available = ATOMIC_INIT(1); | |||
67 | static int snapshot_open(struct inode *inode, struct file *filp) | 67 | static int snapshot_open(struct inode *inode, struct file *filp) |
68 | { | 68 | { |
69 | struct snapshot_data *data; | 69 | struct snapshot_data *data; |
70 | int error; | ||
70 | 71 | ||
71 | if (!atomic_add_unless(&snapshot_device_available, -1, 0)) | 72 | if (!atomic_add_unless(&snapshot_device_available, -1, 0)) |
72 | return -EBUSY; | 73 | return -EBUSY; |
@@ -87,9 +88,19 @@ static int snapshot_open(struct inode *inode, struct file *filp) | |||
87 | data->swap = swsusp_resume_device ? | 88 | data->swap = swsusp_resume_device ? |
88 | swap_type_of(swsusp_resume_device, 0, NULL) : -1; | 89 | swap_type_of(swsusp_resume_device, 0, NULL) : -1; |
89 | data->mode = O_RDONLY; | 90 | data->mode = O_RDONLY; |
91 | error = pm_notifier_call_chain(PM_RESTORE_PREPARE); | ||
92 | if (error) | ||
93 | pm_notifier_call_chain(PM_POST_RESTORE); | ||
90 | } else { | 94 | } else { |
91 | data->swap = -1; | 95 | data->swap = -1; |
92 | data->mode = O_WRONLY; | 96 | data->mode = O_WRONLY; |
97 | error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE); | ||
98 | if (error) | ||
99 | pm_notifier_call_chain(PM_POST_HIBERNATION); | ||
100 | } | ||
101 | if (error) { | ||
102 | atomic_inc(&snapshot_device_available); | ||
103 | return error; | ||
93 | } | 104 | } |
94 | data->frozen = 0; | 105 | data->frozen = 0; |
95 | data->ready = 0; | 106 | data->ready = 0; |
@@ -111,6 +122,8 @@ static int snapshot_release(struct inode *inode, struct file *filp) | |||
111 | thaw_processes(); | 122 | thaw_processes(); |
112 | mutex_unlock(&pm_mutex); | 123 | mutex_unlock(&pm_mutex); |
113 | } | 124 | } |
125 | pm_notifier_call_chain(data->mode == O_WRONLY ? | ||
126 | PM_POST_HIBERNATION : PM_POST_RESTORE); | ||
114 | atomic_inc(&snapshot_device_available); | 127 | atomic_inc(&snapshot_device_available); |
115 | return 0; | 128 | return 0; |
116 | } | 129 | } |
@@ -174,18 +187,13 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
174 | if (data->frozen) | 187 | if (data->frozen) |
175 | break; | 188 | break; |
176 | mutex_lock(&pm_mutex); | 189 | mutex_lock(&pm_mutex); |
177 | error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE); | 190 | printk("Syncing filesystems ... "); |
178 | if (!error) { | 191 | sys_sync(); |
179 | printk("Syncing filesystems ... "); | 192 | printk("done.\n"); |
180 | sys_sync(); | 193 | |
181 | printk("done.\n"); | 194 | error = freeze_processes(); |
182 | |||
183 | error = freeze_processes(); | ||
184 | if (error) | ||
185 | thaw_processes(); | ||
186 | } | ||
187 | if (error) | 195 | if (error) |
188 | pm_notifier_call_chain(PM_POST_HIBERNATION); | 196 | thaw_processes(); |
189 | mutex_unlock(&pm_mutex); | 197 | mutex_unlock(&pm_mutex); |
190 | if (!error) | 198 | if (!error) |
191 | data->frozen = 1; | 199 | data->frozen = 1; |
@@ -196,7 +204,6 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp, | |||
196 | break; | 204 | break; |
197 | mutex_lock(&pm_mutex); | 205 | mutex_lock(&pm_mutex); |
198 | thaw_processes(); | 206 | thaw_processes(); |
199 | pm_notifier_call_chain(PM_POST_HIBERNATION); | ||
200 | mutex_unlock(&pm_mutex); | 207 | mutex_unlock(&pm_mutex); |
201 | data->frozen = 0; | 208 | data->frozen = 0; |
202 | break; | 209 | break; |