diff options
| author | Rafael J. Wysocki <rjw@sisk.pl> | 2009-02-22 12:38:50 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-02-22 13:33:44 -0500 |
| commit | 770824bdc421ff58a64db608294323571c949f4c (patch) | |
| tree | 2fbeef604fe982bf322249a53a95dd2ff851d5f4 | |
| parent | 936577c61d0c10b8929608a92c98d839b22053bc (diff) | |
PM: Split up sysdev_[suspend|resume] from device_power_[down|up]
Move the sysdev_suspend/resume from the callee to the callers, with
no real change in semantics, so that we can rework the disabling of
interrupts during suspend/hibernation.
This is based on an earlier patch from Linus.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | arch/x86/kernel/apm_32.c | 4 | ||||
| -rw-r--r-- | drivers/base/base.h | 2 | ||||
| -rw-r--r-- | drivers/base/power/main.c | 3 | ||||
| -rw-r--r-- | drivers/xen/manage.c | 8 | ||||
| -rw-r--r-- | include/linux/pm.h | 2 | ||||
| -rw-r--r-- | kernel/kexec.c | 7 | ||||
| -rw-r--r-- | kernel/power/disk.c | 11 | ||||
| -rw-r--r-- | kernel/power/main.c | 8 |
8 files changed, 38 insertions, 7 deletions
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 98807bb095a..266ec6c18b6 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c | |||
| @@ -1192,6 +1192,7 @@ static int suspend(int vetoable) | |||
| 1192 | device_suspend(PMSG_SUSPEND); | 1192 | device_suspend(PMSG_SUSPEND); |
| 1193 | local_irq_disable(); | 1193 | local_irq_disable(); |
| 1194 | device_power_down(PMSG_SUSPEND); | 1194 | device_power_down(PMSG_SUSPEND); |
| 1195 | sysdev_suspend(PMSG_SUSPEND); | ||
| 1195 | 1196 | ||
| 1196 | local_irq_enable(); | 1197 | local_irq_enable(); |
| 1197 | 1198 | ||
| @@ -1208,6 +1209,7 @@ static int suspend(int vetoable) | |||
| 1208 | if (err != APM_SUCCESS) | 1209 | if (err != APM_SUCCESS) |
| 1209 | apm_error("suspend", err); | 1210 | apm_error("suspend", err); |
| 1210 | err = (err == APM_SUCCESS) ? 0 : -EIO; | 1211 | err = (err == APM_SUCCESS) ? 0 : -EIO; |
| 1212 | sysdev_resume(); | ||
| 1211 | device_power_up(PMSG_RESUME); | 1213 | device_power_up(PMSG_RESUME); |
| 1212 | local_irq_enable(); | 1214 | local_irq_enable(); |
| 1213 | device_resume(PMSG_RESUME); | 1215 | device_resume(PMSG_RESUME); |
| @@ -1228,6 +1230,7 @@ static void standby(void) | |||
| 1228 | 1230 | ||
| 1229 | local_irq_disable(); | 1231 | local_irq_disable(); |
| 1230 | device_power_down(PMSG_SUSPEND); | 1232 | device_power_down(PMSG_SUSPEND); |
| 1233 | sysdev_suspend(PMSG_SUSPEND); | ||
| 1231 | local_irq_enable(); | 1234 | local_irq_enable(); |
| 1232 | 1235 | ||
| 1233 | err = set_system_power_state(APM_STATE_STANDBY); | 1236 | err = set_system_power_state(APM_STATE_STANDBY); |
| @@ -1235,6 +1238,7 @@ static void standby(void) | |||
| 1235 | apm_error("standby", err); | 1238 | apm_error("standby", err); |
| 1236 | 1239 | ||
| 1237 | local_irq_disable(); | 1240 | local_irq_disable(); |
| 1241 | sysdev_resume(); | ||
| 1238 | device_power_up(PMSG_RESUME); | 1242 | device_power_up(PMSG_RESUME); |
| 1239 | local_irq_enable(); | 1243 | local_irq_enable(); |
| 1240 | } | 1244 | } |
diff --git a/drivers/base/base.h b/drivers/base/base.h index 0a5f055dffb..9f50f1b545d 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h | |||
| @@ -88,8 +88,6 @@ extern void driver_detach(struct device_driver *drv); | |||
| 88 | extern int driver_probe_device(struct device_driver *drv, struct device *dev); | 88 | extern int driver_probe_device(struct device_driver *drv, struct device *dev); |
| 89 | 89 | ||
| 90 | extern void sysdev_shutdown(void); | 90 | extern void sysdev_shutdown(void); |
| 91 | extern int sysdev_suspend(pm_message_t state); | ||
| 92 | extern int sysdev_resume(void); | ||
| 93 | 91 | ||
| 94 | extern char *make_class_name(const char *name, struct kobject *kobj); | 92 | extern char *make_class_name(const char *name, struct kobject *kobj); |
| 95 | 93 | ||
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 670c9d6c140..2d14f4ae6c0 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
| @@ -333,7 +333,6 @@ static void dpm_power_up(pm_message_t state) | |||
| 333 | */ | 333 | */ |
| 334 | void device_power_up(pm_message_t state) | 334 | void device_power_up(pm_message_t state) |
| 335 | { | 335 | { |
| 336 | sysdev_resume(); | ||
| 337 | dpm_power_up(state); | 336 | dpm_power_up(state); |
| 338 | } | 337 | } |
| 339 | EXPORT_SYMBOL_GPL(device_power_up); | 338 | EXPORT_SYMBOL_GPL(device_power_up); |
| @@ -577,8 +576,6 @@ int device_power_down(pm_message_t state) | |||
| 577 | } | 576 | } |
| 578 | dev->power.status = DPM_OFF_IRQ; | 577 | dev->power.status = DPM_OFF_IRQ; |
| 579 | } | 578 | } |
| 580 | if (!error) | ||
| 581 | error = sysdev_suspend(state); | ||
| 582 | if (error) | 579 | if (error) |
| 583 | dpm_power_up(resume_event(state)); | 580 | dpm_power_up(resume_event(state)); |
| 584 | return error; | 581 | return error; |
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 9b91617b958..56892a142ee 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
| @@ -45,6 +45,13 @@ static int xen_suspend(void *data) | |||
| 45 | err); | 45 | err); |
| 46 | return err; | 46 | return err; |
| 47 | } | 47 | } |
| 48 | err = sysdev_suspend(PMSG_SUSPEND); | ||
| 49 | if (err) { | ||
| 50 | printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n", | ||
| 51 | err); | ||
| 52 | device_power_up(PMSG_RESUME); | ||
| 53 | return err; | ||
| 54 | } | ||
| 48 | 55 | ||
| 49 | xen_mm_pin_all(); | 56 | xen_mm_pin_all(); |
| 50 | gnttab_suspend(); | 57 | gnttab_suspend(); |
| @@ -61,6 +68,7 @@ static int xen_suspend(void *data) | |||
| 61 | gnttab_resume(); | 68 | gnttab_resume(); |
| 62 | xen_mm_unpin_all(); | 69 | xen_mm_unpin_all(); |
| 63 | 70 | ||
| 71 | sysdev_resume(); | ||
| 64 | device_power_up(PMSG_RESUME); | 72 | device_power_up(PMSG_RESUME); |
| 65 | 73 | ||
| 66 | if (!*cancelled) { | 74 | if (!*cancelled) { |
diff --git a/include/linux/pm.h b/include/linux/pm.h index de2e0a8f672..24ba5f67b3a 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
| @@ -381,10 +381,12 @@ struct dev_pm_info { | |||
| 381 | 381 | ||
| 382 | #ifdef CONFIG_PM_SLEEP | 382 | #ifdef CONFIG_PM_SLEEP |
| 383 | extern void device_pm_lock(void); | 383 | extern void device_pm_lock(void); |
| 384 | extern int sysdev_resume(void); | ||
| 384 | extern void device_power_up(pm_message_t state); | 385 | extern void device_power_up(pm_message_t state); |
| 385 | extern void device_resume(pm_message_t state); | 386 | extern void device_resume(pm_message_t state); |
| 386 | 387 | ||
| 387 | extern void device_pm_unlock(void); | 388 | extern void device_pm_unlock(void); |
| 389 | extern int sysdev_suspend(pm_message_t state); | ||
| 388 | extern int device_power_down(pm_message_t state); | 390 | extern int device_power_down(pm_message_t state); |
| 389 | extern int device_suspend(pm_message_t state); | 391 | extern int device_suspend(pm_message_t state); |
| 390 | extern int device_prepare_suspend(pm_message_t state); | 392 | extern int device_prepare_suspend(pm_message_t state); |
diff --git a/kernel/kexec.c b/kernel/kexec.c index 8a6d7b08864..48389957825 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
| @@ -1465,6 +1465,11 @@ int kernel_kexec(void) | |||
| 1465 | error = device_power_down(PMSG_FREEZE); | 1465 | error = device_power_down(PMSG_FREEZE); |
| 1466 | if (error) | 1466 | if (error) |
| 1467 | goto Enable_irqs; | 1467 | goto Enable_irqs; |
| 1468 | |||
| 1469 | /* Suspend system devices */ | ||
| 1470 | error = sysdev_suspend(PMSG_FREEZE); | ||
| 1471 | if (error) | ||
| 1472 | goto Power_up_devices; | ||
| 1468 | } else | 1473 | } else |
| 1469 | #endif | 1474 | #endif |
| 1470 | { | 1475 | { |
| @@ -1477,6 +1482,8 @@ int kernel_kexec(void) | |||
| 1477 | 1482 | ||
| 1478 | #ifdef CONFIG_KEXEC_JUMP | 1483 | #ifdef CONFIG_KEXEC_JUMP |
| 1479 | if (kexec_image->preserve_context) { | 1484 | if (kexec_image->preserve_context) { |
| 1485 | sysdev_resume(); | ||
| 1486 | Power_up_devices: | ||
| 1480 | device_power_up(PMSG_RESTORE); | 1487 | device_power_up(PMSG_RESTORE); |
| 1481 | Enable_irqs: | 1488 | Enable_irqs: |
| 1482 | local_irq_enable(); | 1489 | local_irq_enable(); |
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 7b40e94b1d4..4a4a206b197 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
| @@ -227,6 +227,12 @@ static int create_image(int platform_mode) | |||
| 227 | "aborting hibernation\n"); | 227 | "aborting hibernation\n"); |
| 228 | goto Enable_irqs; | 228 | goto Enable_irqs; |
| 229 | } | 229 | } |
| 230 | sysdev_suspend(PMSG_FREEZE); | ||
| 231 | if (error) { | ||
| 232 | printk(KERN_ERR "PM: Some devices failed to power down, " | ||
| 233 | "aborting hibernation\n"); | ||
| 234 | goto Power_up_devices; | ||
| 235 | } | ||
| 230 | 236 | ||
| 231 | if (hibernation_test(TEST_CORE)) | 237 | if (hibernation_test(TEST_CORE)) |
| 232 | goto Power_up; | 238 | goto Power_up; |
| @@ -242,9 +248,11 @@ static int create_image(int platform_mode) | |||
| 242 | if (!in_suspend) | 248 | if (!in_suspend) |
| 243 | platform_leave(platform_mode); | 249 | platform_leave(platform_mode); |
| 244 | Power_up: | 250 | Power_up: |
| 251 | sysdev_resume(); | ||
| 245 | /* NOTE: device_power_up() is just a resume() for devices | 252 | /* NOTE: device_power_up() is just a resume() for devices |
| 246 | * that suspended with irqs off ... no overall powerup. | 253 | * that suspended with irqs off ... no overall powerup. |
| 247 | */ | 254 | */ |
| 255 | Power_up_devices: | ||
| 248 | device_power_up(in_suspend ? | 256 | device_power_up(in_suspend ? |
| 249 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); | 257 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); |
| 250 | Enable_irqs: | 258 | Enable_irqs: |
| @@ -335,6 +343,7 @@ static int resume_target_kernel(void) | |||
| 335 | "aborting resume\n"); | 343 | "aborting resume\n"); |
| 336 | goto Enable_irqs; | 344 | goto Enable_irqs; |
| 337 | } | 345 | } |
| 346 | sysdev_suspend(PMSG_QUIESCE); | ||
| 338 | /* We'll ignore saved state, but this gets preempt count (etc) right */ | 347 | /* We'll ignore saved state, but this gets preempt count (etc) right */ |
| 339 | save_processor_state(); | 348 | save_processor_state(); |
| 340 | error = restore_highmem(); | 349 | error = restore_highmem(); |
| @@ -357,6 +366,7 @@ static int resume_target_kernel(void) | |||
| 357 | swsusp_free(); | 366 | swsusp_free(); |
| 358 | restore_processor_state(); | 367 | restore_processor_state(); |
| 359 | touch_softlockup_watchdog(); | 368 | touch_softlockup_watchdog(); |
| 369 | sysdev_resume(); | ||
| 360 | device_power_up(PMSG_RECOVER); | 370 | device_power_up(PMSG_RECOVER); |
| 361 | Enable_irqs: | 371 | Enable_irqs: |
| 362 | local_irq_enable(); | 372 | local_irq_enable(); |
| @@ -440,6 +450,7 @@ int hibernation_platform_enter(void) | |||
| 440 | local_irq_disable(); | 450 | local_irq_disable(); |
| 441 | error = device_power_down(PMSG_HIBERNATE); | 451 | error = device_power_down(PMSG_HIBERNATE); |
| 442 | if (!error) { | 452 | if (!error) { |
| 453 | sysdev_suspend(PMSG_HIBERNATE); | ||
| 443 | hibernation_ops->enter(); | 454 | hibernation_ops->enter(); |
| 444 | /* We should never get here */ | 455 | /* We should never get here */ |
| 445 | while (1); | 456 | while (1); |
diff --git a/kernel/power/main.c b/kernel/power/main.c index b4d219016b6..c9632f841f6 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
| @@ -298,8 +298,12 @@ static int suspend_enter(suspend_state_t state) | |||
| 298 | goto Done; | 298 | goto Done; |
| 299 | } | 299 | } |
| 300 | 300 | ||
| 301 | if (!suspend_test(TEST_CORE)) | 301 | error = sysdev_suspend(PMSG_SUSPEND); |
| 302 | error = suspend_ops->enter(state); | 302 | if (!error) { |
| 303 | if (!suspend_test(TEST_CORE)) | ||
| 304 | error = suspend_ops->enter(state); | ||
| 305 | sysdev_resume(); | ||
| 306 | } | ||
| 303 | 307 | ||
| 304 | device_power_up(PMSG_RESUME); | 308 | device_power_up(PMSG_RESUME); |
| 305 | Done: | 309 | Done: |
