diff options
Diffstat (limited to 'kernel/power/disk.c')
-rw-r--r-- | kernel/power/disk.c | 55 |
1 files changed, 25 insertions, 30 deletions
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 664eb0469b6e..2d8bf054d036 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
@@ -112,24 +112,12 @@ static inline void platform_finish(void) | |||
112 | } | 112 | } |
113 | } | 113 | } |
114 | 114 | ||
115 | static void finish(void) | ||
116 | { | ||
117 | device_resume(); | ||
118 | platform_finish(); | ||
119 | thaw_processes(); | ||
120 | enable_nonboot_cpus(); | ||
121 | pm_restore_console(); | ||
122 | } | ||
123 | |||
124 | |||
125 | static int prepare_processes(void) | 115 | static int prepare_processes(void) |
126 | { | 116 | { |
127 | int error; | 117 | int error; |
128 | 118 | ||
129 | pm_prepare_console(); | 119 | pm_prepare_console(); |
130 | |||
131 | sys_sync(); | 120 | sys_sync(); |
132 | |||
133 | disable_nonboot_cpus(); | 121 | disable_nonboot_cpus(); |
134 | 122 | ||
135 | if (freeze_processes()) { | 123 | if (freeze_processes()) { |
@@ -162,15 +150,6 @@ static void unprepare_processes(void) | |||
162 | pm_restore_console(); | 150 | pm_restore_console(); |
163 | } | 151 | } |
164 | 152 | ||
165 | static int prepare_devices(void) | ||
166 | { | ||
167 | int error; | ||
168 | |||
169 | if ((error = device_suspend(PMSG_FREEZE))) | ||
170 | printk("Some devices failed to suspend\n"); | ||
171 | return error; | ||
172 | } | ||
173 | |||
174 | /** | 153 | /** |
175 | * pm_suspend_disk - The granpappy of power management. | 154 | * pm_suspend_disk - The granpappy of power management. |
176 | * | 155 | * |
@@ -187,17 +166,14 @@ int pm_suspend_disk(void) | |||
187 | error = prepare_processes(); | 166 | error = prepare_processes(); |
188 | if (error) | 167 | if (error) |
189 | return error; | 168 | return error; |
190 | error = prepare_devices(); | ||
191 | 169 | ||
170 | error = device_suspend(PMSG_FREEZE); | ||
192 | if (error) { | 171 | if (error) { |
172 | printk("Some devices failed to suspend\n"); | ||
193 | unprepare_processes(); | 173 | unprepare_processes(); |
194 | return error; | 174 | return error; |
195 | } | 175 | } |
196 | 176 | ||
197 | pr_debug("PM: Attempting to suspend to disk.\n"); | ||
198 | if (pm_disk_mode == PM_DISK_FIRMWARE) | ||
199 | return pm_ops->enter(PM_SUSPEND_DISK); | ||
200 | |||
201 | pr_debug("PM: snapshotting memory.\n"); | 177 | pr_debug("PM: snapshotting memory.\n"); |
202 | in_suspend = 1; | 178 | in_suspend = 1; |
203 | if ((error = swsusp_suspend())) | 179 | if ((error = swsusp_suspend())) |
@@ -208,11 +184,20 @@ int pm_suspend_disk(void) | |||
208 | error = swsusp_write(); | 184 | error = swsusp_write(); |
209 | if (!error) | 185 | if (!error) |
210 | power_down(pm_disk_mode); | 186 | power_down(pm_disk_mode); |
187 | else { | ||
188 | /* swsusp_write can not fail in device_resume, | ||
189 | no need to do second device_resume */ | ||
190 | swsusp_free(); | ||
191 | unprepare_processes(); | ||
192 | return error; | ||
193 | } | ||
211 | } else | 194 | } else |
212 | pr_debug("PM: Image restored successfully.\n"); | 195 | pr_debug("PM: Image restored successfully.\n"); |
196 | |||
213 | swsusp_free(); | 197 | swsusp_free(); |
214 | Done: | 198 | Done: |
215 | finish(); | 199 | device_resume(); |
200 | unprepare_processes(); | ||
216 | return error; | 201 | return error; |
217 | } | 202 | } |
218 | 203 | ||
@@ -233,9 +218,12 @@ static int software_resume(void) | |||
233 | { | 218 | { |
234 | int error; | 219 | int error; |
235 | 220 | ||
221 | down(&pm_sem); | ||
236 | if (!swsusp_resume_device) { | 222 | if (!swsusp_resume_device) { |
237 | if (!strlen(resume_file)) | 223 | if (!strlen(resume_file)) { |
224 | up(&pm_sem); | ||
238 | return -ENOENT; | 225 | return -ENOENT; |
226 | } | ||
239 | swsusp_resume_device = name_to_dev_t(resume_file); | 227 | swsusp_resume_device = name_to_dev_t(resume_file); |
240 | pr_debug("swsusp: Resume From Partition %s\n", resume_file); | 228 | pr_debug("swsusp: Resume From Partition %s\n", resume_file); |
241 | } else { | 229 | } else { |
@@ -248,6 +236,7 @@ static int software_resume(void) | |||
248 | * FIXME: If noresume is specified, we need to find the partition | 236 | * FIXME: If noresume is specified, we need to find the partition |
249 | * and reset it back to normal swap space. | 237 | * and reset it back to normal swap space. |
250 | */ | 238 | */ |
239 | up(&pm_sem); | ||
251 | return 0; | 240 | return 0; |
252 | } | 241 | } |
253 | 242 | ||
@@ -270,20 +259,24 @@ static int software_resume(void) | |||
270 | 259 | ||
271 | pr_debug("PM: Preparing devices for restore.\n"); | 260 | pr_debug("PM: Preparing devices for restore.\n"); |
272 | 261 | ||
273 | if ((error = prepare_devices())) | 262 | if ((error = device_suspend(PMSG_FREEZE))) { |
263 | printk("Some devices failed to suspend\n"); | ||
274 | goto Free; | 264 | goto Free; |
265 | } | ||
275 | 266 | ||
276 | mb(); | 267 | mb(); |
277 | 268 | ||
278 | pr_debug("PM: Restoring saved image.\n"); | 269 | pr_debug("PM: Restoring saved image.\n"); |
279 | swsusp_resume(); | 270 | swsusp_resume(); |
280 | pr_debug("PM: Restore failed, recovering.n"); | 271 | pr_debug("PM: Restore failed, recovering.n"); |
281 | finish(); | 272 | device_resume(); |
282 | Free: | 273 | Free: |
283 | swsusp_free(); | 274 | swsusp_free(); |
284 | Cleanup: | 275 | Cleanup: |
285 | unprepare_processes(); | 276 | unprepare_processes(); |
286 | Done: | 277 | Done: |
278 | /* For success case, the suspend path will release the lock */ | ||
279 | up(&pm_sem); | ||
287 | pr_debug("PM: Resume from disk failed.\n"); | 280 | pr_debug("PM: Resume from disk failed.\n"); |
288 | return 0; | 281 | return 0; |
289 | } | 282 | } |
@@ -390,7 +383,9 @@ static ssize_t resume_store(struct subsystem * subsys, const char * buf, size_t | |||
390 | if (sscanf(buf, "%u:%u", &maj, &min) == 2) { | 383 | if (sscanf(buf, "%u:%u", &maj, &min) == 2) { |
391 | res = MKDEV(maj,min); | 384 | res = MKDEV(maj,min); |
392 | if (maj == MAJOR(res) && min == MINOR(res)) { | 385 | if (maj == MAJOR(res) && min == MINOR(res)) { |
386 | down(&pm_sem); | ||
393 | swsusp_resume_device = res; | 387 | swsusp_resume_device = res; |
388 | up(&pm_sem); | ||
394 | printk("Attempting manual resume\n"); | 389 | printk("Attempting manual resume\n"); |
395 | noresume = 0; | 390 | noresume = 0; |
396 | software_resume(); | 391 | software_resume(); |