diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/power/suspend.c | 49 |
1 files changed, 38 insertions, 11 deletions
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index e837dd6783c6..4ca9a33ff620 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c | |||
| @@ -146,17 +146,29 @@ static int platform_suspend_prepare(suspend_state_t state) | |||
| 146 | 146 | ||
| 147 | static int platform_suspend_prepare_late(suspend_state_t state) | 147 | static int platform_suspend_prepare_late(suspend_state_t state) |
| 148 | { | 148 | { |
| 149 | return state == PM_SUSPEND_FREEZE && freeze_ops->prepare ? | ||
| 150 | freeze_ops->prepare() : 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | static int platform_suspend_prepare_noirq(suspend_state_t state) | ||
| 154 | { | ||
| 149 | return state != PM_SUSPEND_FREEZE && suspend_ops->prepare_late ? | 155 | return state != PM_SUSPEND_FREEZE && suspend_ops->prepare_late ? |
| 150 | suspend_ops->prepare_late() : 0; | 156 | suspend_ops->prepare_late() : 0; |
| 151 | } | 157 | } |
| 152 | 158 | ||
| 153 | static void platform_suspend_wake(suspend_state_t state) | 159 | static void platform_resume_noirq(suspend_state_t state) |
| 154 | { | 160 | { |
| 155 | if (state != PM_SUSPEND_FREEZE && suspend_ops->wake) | 161 | if (state != PM_SUSPEND_FREEZE && suspend_ops->wake) |
| 156 | suspend_ops->wake(); | 162 | suspend_ops->wake(); |
| 157 | } | 163 | } |
| 158 | 164 | ||
| 159 | static void platform_suspend_finish(suspend_state_t state) | 165 | static void platform_resume_early(suspend_state_t state) |
| 166 | { | ||
| 167 | if (state == PM_SUSPEND_FREEZE && freeze_ops->restore) | ||
| 168 | freeze_ops->restore(); | ||
| 169 | } | ||
| 170 | |||
| 171 | static void platform_resume_finish(suspend_state_t state) | ||
| 160 | { | 172 | { |
| 161 | if (state != PM_SUSPEND_FREEZE && suspend_ops->finish) | 173 | if (state != PM_SUSPEND_FREEZE && suspend_ops->finish) |
| 162 | suspend_ops->finish(); | 174 | suspend_ops->finish(); |
| @@ -172,7 +184,7 @@ static int platform_suspend_begin(suspend_state_t state) | |||
| 172 | return 0; | 184 | return 0; |
| 173 | } | 185 | } |
| 174 | 186 | ||
| 175 | static void platform_suspend_end(suspend_state_t state) | 187 | static void platform_resume_end(suspend_state_t state) |
| 176 | { | 188 | { |
| 177 | if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->end) | 189 | if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->end) |
| 178 | freeze_ops->end(); | 190 | freeze_ops->end(); |
| @@ -180,7 +192,7 @@ static void platform_suspend_end(suspend_state_t state) | |||
| 180 | suspend_ops->end(); | 192 | suspend_ops->end(); |
| 181 | } | 193 | } |
| 182 | 194 | ||
| 183 | static void platform_suspend_recover(suspend_state_t state) | 195 | static void platform_recover(suspend_state_t state) |
| 184 | { | 196 | { |
| 185 | if (state != PM_SUSPEND_FREEZE && suspend_ops->recover) | 197 | if (state != PM_SUSPEND_FREEZE && suspend_ops->recover) |
| 186 | suspend_ops->recover(); | 198 | suspend_ops->recover(); |
| @@ -265,13 +277,22 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) | |||
| 265 | if (error) | 277 | if (error) |
| 266 | goto Platform_finish; | 278 | goto Platform_finish; |
| 267 | 279 | ||
| 268 | error = dpm_suspend_end(PMSG_SUSPEND); | 280 | error = dpm_suspend_late(PMSG_SUSPEND); |
| 269 | if (error) { | 281 | if (error) { |
| 270 | printk(KERN_ERR "PM: Some devices failed to power down\n"); | 282 | printk(KERN_ERR "PM: late suspend of devices failed\n"); |
| 271 | goto Platform_finish; | 283 | goto Platform_finish; |
| 272 | } | 284 | } |
| 273 | error = platform_suspend_prepare_late(state); | 285 | error = platform_suspend_prepare_late(state); |
| 274 | if (error) | 286 | if (error) |
| 287 | goto Devices_early_resume; | ||
| 288 | |||
| 289 | error = dpm_suspend_noirq(PMSG_SUSPEND); | ||
| 290 | if (error) { | ||
| 291 | printk(KERN_ERR "PM: noirq suspend of devices failed\n"); | ||
| 292 | goto Platform_early_resume; | ||
| 293 | } | ||
| 294 | error = platform_suspend_prepare_noirq(state); | ||
| 295 | if (error) | ||
| 275 | goto Platform_wake; | 296 | goto Platform_wake; |
| 276 | 297 | ||
| 277 | if (suspend_test(TEST_PLATFORM)) | 298 | if (suspend_test(TEST_PLATFORM)) |
| @@ -318,11 +339,17 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) | |||
| 318 | enable_nonboot_cpus(); | 339 | enable_nonboot_cpus(); |
| 319 | 340 | ||
| 320 | Platform_wake: | 341 | Platform_wake: |
| 321 | platform_suspend_wake(state); | 342 | platform_resume_noirq(state); |
| 322 | dpm_resume_start(PMSG_RESUME); | 343 | dpm_resume_noirq(PMSG_RESUME); |
| 344 | |||
| 345 | Platform_early_resume: | ||
| 346 | platform_resume_early(state); | ||
| 347 | |||
| 348 | Devices_early_resume: | ||
| 349 | dpm_resume_early(PMSG_RESUME); | ||
| 323 | 350 | ||
| 324 | Platform_finish: | 351 | Platform_finish: |
| 325 | platform_suspend_finish(state); | 352 | platform_resume_finish(state); |
| 326 | return error; | 353 | return error; |
| 327 | } | 354 | } |
| 328 | 355 | ||
| @@ -366,11 +393,11 @@ int suspend_devices_and_enter(suspend_state_t state) | |||
| 366 | trace_suspend_resume(TPS("resume_console"), state, false); | 393 | trace_suspend_resume(TPS("resume_console"), state, false); |
| 367 | 394 | ||
| 368 | Close: | 395 | Close: |
| 369 | platform_suspend_end(state); | 396 | platform_resume_end(state); |
| 370 | return error; | 397 | return error; |
| 371 | 398 | ||
| 372 | Recover_platform: | 399 | Recover_platform: |
| 373 | platform_suspend_recover(state); | 400 | platform_recover(state); |
| 374 | goto Resume_devices; | 401 | goto Resume_devices; |
| 375 | } | 402 | } |
| 376 | 403 | ||
