diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-20 11:43:06 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-20 11:43:06 -0400 |
| commit | a939b96cccdb65df80a52447ec8e4a6d79c56dbb (patch) | |
| tree | b2d03cee9f019d360c03518dd447aa0e5b66db33 | |
| parent | 5cab3856e76f4e6dd44731cea054021105e3e02d (diff) | |
| parent | 6a7c7eaf71b636f197d73b381a2ab729ebdcfb2e (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6:
PM/Suspend: Introduce two new platform callbacks to avoid breakage
| -rw-r--r-- | drivers/acpi/sleep.c | 8 | ||||
| -rw-r--r-- | include/linux/suspend.h | 36 | ||||
| -rw-r--r-- | kernel/power/main.c | 24 |
3 files changed, 47 insertions, 21 deletions
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 779e4e500df4..d060e6fd7fd5 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
| @@ -300,9 +300,9 @@ static int acpi_suspend_state_valid(suspend_state_t pm_state) | |||
| 300 | static struct platform_suspend_ops acpi_suspend_ops = { | 300 | static struct platform_suspend_ops acpi_suspend_ops = { |
| 301 | .valid = acpi_suspend_state_valid, | 301 | .valid = acpi_suspend_state_valid, |
| 302 | .begin = acpi_suspend_begin, | 302 | .begin = acpi_suspend_begin, |
| 303 | .prepare = acpi_pm_prepare, | 303 | .prepare_late = acpi_pm_prepare, |
| 304 | .enter = acpi_suspend_enter, | 304 | .enter = acpi_suspend_enter, |
| 305 | .finish = acpi_pm_finish, | 305 | .wake = acpi_pm_finish, |
| 306 | .end = acpi_pm_end, | 306 | .end = acpi_pm_end, |
| 307 | }; | 307 | }; |
| 308 | 308 | ||
| @@ -328,9 +328,9 @@ static int acpi_suspend_begin_old(suspend_state_t pm_state) | |||
| 328 | static struct platform_suspend_ops acpi_suspend_ops_old = { | 328 | static struct platform_suspend_ops acpi_suspend_ops_old = { |
| 329 | .valid = acpi_suspend_state_valid, | 329 | .valid = acpi_suspend_state_valid, |
| 330 | .begin = acpi_suspend_begin_old, | 330 | .begin = acpi_suspend_begin_old, |
| 331 | .prepare = acpi_pm_disable_gpes, | 331 | .prepare_late = acpi_pm_disable_gpes, |
| 332 | .enter = acpi_suspend_enter, | 332 | .enter = acpi_suspend_enter, |
| 333 | .finish = acpi_pm_finish, | 333 | .wake = acpi_pm_finish, |
| 334 | .end = acpi_pm_end, | 334 | .end = acpi_pm_end, |
| 335 | .recover = acpi_pm_finish, | 335 | .recover = acpi_pm_finish, |
| 336 | }; | 336 | }; |
diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 3e3a4364cbff..795032edfc46 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h | |||
| @@ -58,10 +58,17 @@ typedef int __bitwise suspend_state_t; | |||
| 58 | * by @begin(). | 58 | * by @begin(). |
| 59 | * @prepare() is called right after devices have been suspended (ie. the | 59 | * @prepare() is called right after devices have been suspended (ie. the |
| 60 | * appropriate .suspend() method has been executed for each device) and | 60 | * appropriate .suspend() method has been executed for each device) and |
| 61 | * before the nonboot CPUs are disabled (it is executed with IRQs enabled). | 61 | * before device drivers' late suspend callbacks are executed. It returns |
| 62 | * This callback is optional. It returns 0 on success or a negative | 62 | * 0 on success or a negative error code otherwise, in which case the |
| 63 | * error code otherwise, in which case the system cannot enter the desired | 63 | * system cannot enter the desired sleep state (@prepare_late(), @enter(), |
| 64 | * sleep state (@enter() and @finish() will not be called in that case). | 64 | * @wake(), and @finish() will not be called in that case). |
| 65 | * | ||
| 66 | * @prepare_late: Finish preparing the platform for entering the system sleep | ||
| 67 | * state indicated by @begin(). | ||
| 68 | * @prepare_late is called before disabling nonboot CPUs and after | ||
| 69 | * device drivers' late suspend callbacks have been executed. It returns | ||
| 70 | * 0 on success or a negative error code otherwise, in which case the | ||
| 71 | * system cannot enter the desired sleep state (@enter() and @wake()). | ||
| 65 | * | 72 | * |
| 66 | * @enter: Enter the system sleep state indicated by @begin() or represented by | 73 | * @enter: Enter the system sleep state indicated by @begin() or represented by |
| 67 | * the argument if @begin() is not implemented. | 74 | * the argument if @begin() is not implemented. |
| @@ -69,19 +76,26 @@ typedef int __bitwise suspend_state_t; | |||
| 69 | * error code otherwise, in which case the system cannot enter the desired | 76 | * error code otherwise, in which case the system cannot enter the desired |
| 70 | * sleep state. | 77 | * sleep state. |
| 71 | * | 78 | * |
| 72 | * @finish: Called when the system has just left a sleep state, right after | 79 | * @wake: Called when the system has just left a sleep state, right after |
| 73 | * the nonboot CPUs have been enabled and before devices are resumed (it is | 80 | * the nonboot CPUs have been enabled and before device drivers' early |
| 74 | * executed with IRQs enabled). | 81 | * resume callbacks are executed. |
| 82 | * This callback is optional, but should be implemented by the platforms | ||
| 83 | * that implement @prepare_late(). If implemented, it is always called | ||
| 84 | * after @enter(), even if @enter() fails. | ||
| 85 | * | ||
| 86 | * @finish: Finish wake-up of the platform. | ||
| 87 | * @finish is called right prior to calling device drivers' regular suspend | ||
| 88 | * callbacks. | ||
| 75 | * This callback is optional, but should be implemented by the platforms | 89 | * This callback is optional, but should be implemented by the platforms |
| 76 | * that implement @prepare(). If implemented, it is always called after | 90 | * that implement @prepare(). If implemented, it is always called after |
| 77 | * @enter() (even if @enter() fails). | 91 | * @enter() and @wake(), if implemented, even if any of them fails. |
| 78 | * | 92 | * |
| 79 | * @end: Called by the PM core right after resuming devices, to indicate to | 93 | * @end: Called by the PM core right after resuming devices, to indicate to |
| 80 | * the platform that the system has returned to the working state or | 94 | * the platform that the system has returned to the working state or |
| 81 | * the transition to the sleep state has been aborted. | 95 | * the transition to the sleep state has been aborted. |
| 82 | * This callback is optional, but should be implemented by the platforms | 96 | * This callback is optional, but should be implemented by the platforms |
| 83 | * that implement @begin(), but platforms implementing @begin() should | 97 | * that implement @begin(). Accordingly, platforms implementing @begin() |
| 84 | * also provide a @end() which cleans up transitions aborted before | 98 | * should also provide a @end() which cleans up transitions aborted before |
| 85 | * @enter(). | 99 | * @enter(). |
| 86 | * | 100 | * |
| 87 | * @recover: Recover the platform from a suspend failure. | 101 | * @recover: Recover the platform from a suspend failure. |
| @@ -93,7 +107,9 @@ struct platform_suspend_ops { | |||
| 93 | int (*valid)(suspend_state_t state); | 107 | int (*valid)(suspend_state_t state); |
| 94 | int (*begin)(suspend_state_t state); | 108 | int (*begin)(suspend_state_t state); |
| 95 | int (*prepare)(void); | 109 | int (*prepare)(void); |
| 110 | int (*prepare_late)(void); | ||
| 96 | int (*enter)(suspend_state_t state); | 111 | int (*enter)(suspend_state_t state); |
| 112 | void (*wake)(void); | ||
| 97 | void (*finish)(void); | 113 | void (*finish)(void); |
| 98 | void (*end)(void); | 114 | void (*end)(void); |
| 99 | void (*recover)(void); | 115 | void (*recover)(void); |
diff --git a/kernel/power/main.c b/kernel/power/main.c index f172f41858bb..f99ed6a75eac 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
| @@ -291,20 +291,26 @@ static int suspend_enter(suspend_state_t state) | |||
| 291 | 291 | ||
| 292 | device_pm_lock(); | 292 | device_pm_lock(); |
| 293 | 293 | ||
| 294 | if (suspend_ops->prepare) { | ||
| 295 | error = suspend_ops->prepare(); | ||
| 296 | if (error) | ||
| 297 | goto Done; | ||
| 298 | } | ||
| 299 | |||
| 294 | error = device_power_down(PMSG_SUSPEND); | 300 | error = device_power_down(PMSG_SUSPEND); |
| 295 | if (error) { | 301 | if (error) { |
| 296 | printk(KERN_ERR "PM: Some devices failed to power down\n"); | 302 | printk(KERN_ERR "PM: Some devices failed to power down\n"); |
| 297 | goto Done; | 303 | goto Platfrom_finish; |
| 298 | } | 304 | } |
| 299 | 305 | ||
| 300 | if (suspend_ops->prepare) { | 306 | if (suspend_ops->prepare_late) { |
| 301 | error = suspend_ops->prepare(); | 307 | error = suspend_ops->prepare_late(); |
| 302 | if (error) | 308 | if (error) |
| 303 | goto Power_up_devices; | 309 | goto Power_up_devices; |
| 304 | } | 310 | } |
| 305 | 311 | ||
| 306 | if (suspend_test(TEST_PLATFORM)) | 312 | if (suspend_test(TEST_PLATFORM)) |
| 307 | goto Platfrom_finish; | 313 | goto Platform_wake; |
| 308 | 314 | ||
| 309 | error = disable_nonboot_cpus(); | 315 | error = disable_nonboot_cpus(); |
| 310 | if (error || suspend_test(TEST_CPUS)) | 316 | if (error || suspend_test(TEST_CPUS)) |
| @@ -326,13 +332,17 @@ static int suspend_enter(suspend_state_t state) | |||
| 326 | Enable_cpus: | 332 | Enable_cpus: |
| 327 | enable_nonboot_cpus(); | 333 | enable_nonboot_cpus(); |
| 328 | 334 | ||
| 329 | Platfrom_finish: | 335 | Platform_wake: |
| 330 | if (suspend_ops->finish) | 336 | if (suspend_ops->wake) |
| 331 | suspend_ops->finish(); | 337 | suspend_ops->wake(); |
| 332 | 338 | ||
| 333 | Power_up_devices: | 339 | Power_up_devices: |
| 334 | device_power_up(PMSG_RESUME); | 340 | device_power_up(PMSG_RESUME); |
| 335 | 341 | ||
| 342 | Platfrom_finish: | ||
| 343 | if (suspend_ops->finish) | ||
| 344 | suspend_ops->finish(); | ||
| 345 | |||
| 336 | Done: | 346 | Done: |
| 337 | device_pm_unlock(); | 347 | device_pm_unlock(); |
| 338 | 348 | ||
