diff options
| -rw-r--r-- | drivers/acpi/sleep/main.c | 14 | ||||
| -rw-r--r-- | include/linux/suspend.h | 14 | ||||
| -rw-r--r-- | kernel/power/disk.c | 33 |
3 files changed, 45 insertions, 16 deletions
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index c37c4ead95c9..31e8e58e1cec 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c | |||
| @@ -281,7 +281,7 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
| 281 | #endif /* CONFIG_SUSPEND */ | 281 | #endif /* CONFIG_SUSPEND */ |
| 282 | 282 | ||
| 283 | #ifdef CONFIG_HIBERNATION | 283 | #ifdef CONFIG_HIBERNATION |
| 284 | static int acpi_hibernation_start(void) | 284 | static int acpi_hibernation_begin(void) |
| 285 | { | 285 | { |
| 286 | acpi_target_sleep_state = ACPI_STATE_S4; | 286 | acpi_target_sleep_state = ACPI_STATE_S4; |
| 287 | return 0; | 287 | return 0; |
| @@ -341,6 +341,15 @@ static void acpi_hibernation_finish(void) | |||
| 341 | acpi_target_sleep_state = ACPI_STATE_S0; | 341 | acpi_target_sleep_state = ACPI_STATE_S0; |
| 342 | } | 342 | } |
| 343 | 343 | ||
| 344 | static void acpi_hibernation_end(void) | ||
| 345 | { | ||
| 346 | /* | ||
| 347 | * This is necessary in case acpi_hibernation_finish() is not called | ||
| 348 | * during a failing transition to the sleep state. | ||
| 349 | */ | ||
| 350 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
| 351 | } | ||
| 352 | |||
| 344 | static int acpi_hibernation_pre_restore(void) | 353 | static int acpi_hibernation_pre_restore(void) |
| 345 | { | 354 | { |
| 346 | acpi_status status; | 355 | acpi_status status; |
| @@ -356,7 +365,8 @@ static void acpi_hibernation_restore_cleanup(void) | |||
| 356 | } | 365 | } |
| 357 | 366 | ||
| 358 | static struct platform_hibernation_ops acpi_hibernation_ops = { | 367 | static struct platform_hibernation_ops acpi_hibernation_ops = { |
| 359 | .start = acpi_hibernation_start, | 368 | .begin = acpi_hibernation_begin, |
| 369 | .end = acpi_hibernation_end, | ||
| 360 | .pre_snapshot = acpi_hibernation_prepare, | 370 | .pre_snapshot = acpi_hibernation_prepare, |
| 361 | .finish = acpi_hibernation_finish, | 371 | .finish = acpi_hibernation_finish, |
| 362 | .prepare = acpi_hibernation_prepare, | 372 | .prepare = acpi_hibernation_prepare, |
diff --git a/include/linux/suspend.h b/include/linux/suspend.h index a0b1dbb5919f..646ce2d068d4 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h | |||
| @@ -136,14 +136,17 @@ extern void mark_free_pages(struct zone *zone); | |||
| 136 | /** | 136 | /** |
| 137 | * struct platform_hibernation_ops - hibernation platform support | 137 | * struct platform_hibernation_ops - hibernation platform support |
| 138 | * | 138 | * |
| 139 | * The methods in this structure allow a platform to override the default | 139 | * The methods in this structure allow a platform to carry out special |
| 140 | * mechanism of shutting down the machine during a hibernation transition. | 140 | * operations required by it during a hibernation transition. |
| 141 | * | 141 | * |
| 142 | * All three methods must be assigned. | 142 | * All the methods below must be implemented. |
| 143 | * | 143 | * |
| 144 | * @start: Tell the platform driver that we're starting hibernation. | 144 | * @begin: Tell the platform driver that we're starting hibernation. |
| 145 | * Called right after shrinking memory and before freezing devices. | 145 | * Called right after shrinking memory and before freezing devices. |
| 146 | * | 146 | * |
| 147 | * @end: Called by the PM core right after resuming devices, to indicate to | ||
| 148 | * the platform that the system has returned to the working state. | ||
| 149 | * | ||
| 147 | * @pre_snapshot: Prepare the platform for creating the hibernation image. | 150 | * @pre_snapshot: Prepare the platform for creating the hibernation image. |
| 148 | * Called right after devices have been frozen and before the nonboot | 151 | * Called right after devices have been frozen and before the nonboot |
| 149 | * CPUs are disabled (runs with IRQs on). | 152 | * CPUs are disabled (runs with IRQs on). |
| @@ -178,7 +181,8 @@ extern void mark_free_pages(struct zone *zone); | |||
| 178 | * thawing devices (runs with IRQs on). | 181 | * thawing devices (runs with IRQs on). |
| 179 | */ | 182 | */ |
| 180 | struct platform_hibernation_ops { | 183 | struct platform_hibernation_ops { |
| 181 | int (*start)(void); | 184 | int (*begin)(void); |
| 185 | void (*end)(void); | ||
| 182 | int (*pre_snapshot)(void); | 186 | int (*pre_snapshot)(void); |
| 183 | void (*finish)(void); | 187 | void (*finish)(void); |
| 184 | int (*prepare)(void); | 188 | int (*prepare)(void); |
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 64e42ab8b57c..53c22d9cf577 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
| @@ -54,8 +54,8 @@ static struct platform_hibernation_ops *hibernation_ops; | |||
| 54 | 54 | ||
| 55 | void hibernation_set_ops(struct platform_hibernation_ops *ops) | 55 | void hibernation_set_ops(struct platform_hibernation_ops *ops) |
| 56 | { | 56 | { |
| 57 | if (ops && !(ops->start && ops->pre_snapshot && ops->finish | 57 | if (ops && !(ops->begin && ops->end && ops->pre_snapshot |
| 58 | && ops->prepare && ops->enter && ops->pre_restore | 58 | && ops->prepare && ops->finish && ops->enter && ops->pre_restore |
| 59 | && ops->restore_cleanup)) { | 59 | && ops->restore_cleanup)) { |
| 60 | WARN_ON(1); | 60 | WARN_ON(1); |
| 61 | return; | 61 | return; |
| @@ -100,14 +100,25 @@ static int hibernation_test(int level) { return 0; } | |||
| 100 | #endif /* !CONFIG_PM_DEBUG */ | 100 | #endif /* !CONFIG_PM_DEBUG */ |
| 101 | 101 | ||
| 102 | /** | 102 | /** |
| 103 | * platform_start - tell the platform driver that we're starting | 103 | * platform_begin - tell the platform driver that we're starting |
| 104 | * hibernation | 104 | * hibernation |
| 105 | */ | 105 | */ |
| 106 | 106 | ||
| 107 | static int platform_start(int platform_mode) | 107 | static int platform_begin(int platform_mode) |
| 108 | { | 108 | { |
| 109 | return (platform_mode && hibernation_ops) ? | 109 | return (platform_mode && hibernation_ops) ? |
| 110 | hibernation_ops->start() : 0; | 110 | hibernation_ops->begin() : 0; |
| 111 | } | ||
| 112 | |||
| 113 | /** | ||
| 114 | * platform_end - tell the platform driver that we've entered the | ||
| 115 | * working state | ||
| 116 | */ | ||
| 117 | |||
| 118 | static void platform_end(int platform_mode) | ||
| 119 | { | ||
| 120 | if (platform_mode && hibernation_ops) | ||
| 121 | hibernation_ops->end(); | ||
| 111 | } | 122 | } |
| 112 | 123 | ||
| 113 | /** | 124 | /** |
| @@ -237,9 +248,9 @@ int hibernation_snapshot(int platform_mode) | |||
| 237 | if (error) | 248 | if (error) |
| 238 | return error; | 249 | return error; |
| 239 | 250 | ||
| 240 | error = platform_start(platform_mode); | 251 | error = platform_begin(platform_mode); |
| 241 | if (error) | 252 | if (error) |
| 242 | return error; | 253 | goto Close; |
| 243 | 254 | ||
| 244 | suspend_console(); | 255 | suspend_console(); |
| 245 | error = device_suspend(PMSG_FREEZE); | 256 | error = device_suspend(PMSG_FREEZE); |
| @@ -272,6 +283,8 @@ int hibernation_snapshot(int platform_mode) | |||
| 272 | device_resume(); | 283 | device_resume(); |
| 273 | Resume_console: | 284 | Resume_console: |
| 274 | resume_console(); | 285 | resume_console(); |
| 286 | Close: | ||
| 287 | platform_end(platform_mode); | ||
| 275 | return error; | 288 | return error; |
| 276 | } | 289 | } |
| 277 | 290 | ||
| @@ -373,9 +386,9 @@ int hibernation_platform_enter(void) | |||
| 373 | * hibernation_ops->finish() before saving the image, so we should let | 386 | * hibernation_ops->finish() before saving the image, so we should let |
| 374 | * the firmware know that we're going to enter the sleep state after all | 387 | * the firmware know that we're going to enter the sleep state after all |
| 375 | */ | 388 | */ |
| 376 | error = hibernation_ops->start(); | 389 | error = hibernation_ops->begin(); |
| 377 | if (error) | 390 | if (error) |
| 378 | return error; | 391 | goto Close; |
| 379 | 392 | ||
| 380 | suspend_console(); | 393 | suspend_console(); |
| 381 | error = device_suspend(PMSG_SUSPEND); | 394 | error = device_suspend(PMSG_SUSPEND); |
| @@ -409,6 +422,8 @@ int hibernation_platform_enter(void) | |||
| 409 | device_resume(); | 422 | device_resume(); |
| 410 | Resume_console: | 423 | Resume_console: |
| 411 | resume_console(); | 424 | resume_console(); |
| 425 | Close: | ||
| 426 | hibernation_ops->end(); | ||
| 412 | return error; | 427 | return error; |
| 413 | } | 428 | } |
| 414 | 429 | ||
