aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2009-03-16 17:34:15 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2009-03-30 15:46:54 -0400
commit900af0d973856d6feb6fc088c2d0d3fde57707d3 (patch)
tree4502d4108200fa0eb38dd5f0155b205fed166e48 /kernel/power
parent2ed8d2b3a81bdbb0418301628ccdb008ac9f40b7 (diff)
PM: Change suspend code ordering
Change the ordering of the suspend core code so that the platform "prepare" callback is executed and the nonboot CPUs are disabled after calling device drivers' "late suspend" methods. This change will allow us to rework the PCI PM core so that the power state of devices is changed in the "late" phase of suspend (and analogously in the "early" phase of resume), which in turn will allow us to avoid the race condition where a device using shared interrupts is put into a low power state with interrupts enabled and then an interrupt (for another device) comes in and confuses its driver. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/power')
-rw-r--r--kernel/power/main.c38
1 files changed, 22 insertions, 16 deletions
diff --git a/kernel/power/main.c b/kernel/power/main.c
index f0a466736c01..f172f41858bb 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -297,6 +297,19 @@ static int suspend_enter(suspend_state_t state)
297 goto Done; 297 goto Done;
298 } 298 }
299 299
300 if (suspend_ops->prepare) {
301 error = suspend_ops->prepare();
302 if (error)
303 goto Power_up_devices;
304 }
305
306 if (suspend_test(TEST_PLATFORM))
307 goto Platfrom_finish;
308
309 error = disable_nonboot_cpus();
310 if (error || suspend_test(TEST_CPUS))
311 goto Enable_cpus;
312
300 arch_suspend_disable_irqs(); 313 arch_suspend_disable_irqs();
301 BUG_ON(!irqs_disabled()); 314 BUG_ON(!irqs_disabled());
302 315
@@ -310,6 +323,14 @@ static int suspend_enter(suspend_state_t state)
310 arch_suspend_enable_irqs(); 323 arch_suspend_enable_irqs();
311 BUG_ON(irqs_disabled()); 324 BUG_ON(irqs_disabled());
312 325
326 Enable_cpus:
327 enable_nonboot_cpus();
328
329 Platfrom_finish:
330 if (suspend_ops->finish)
331 suspend_ops->finish();
332
333 Power_up_devices:
313 device_power_up(PMSG_RESUME); 334 device_power_up(PMSG_RESUME);
314 335
315 Done: 336 Done:
@@ -346,23 +367,8 @@ int suspend_devices_and_enter(suspend_state_t state)
346 if (suspend_test(TEST_DEVICES)) 367 if (suspend_test(TEST_DEVICES))
347 goto Recover_platform; 368 goto Recover_platform;
348 369
349 if (suspend_ops->prepare) { 370 suspend_enter(state);
350 error = suspend_ops->prepare();
351 if (error)
352 goto Resume_devices;
353 }
354
355 if (suspend_test(TEST_PLATFORM))
356 goto Finish;
357 371
358 error = disable_nonboot_cpus();
359 if (!error && !suspend_test(TEST_CPUS))
360 suspend_enter(state);
361
362 enable_nonboot_cpus();
363 Finish:
364 if (suspend_ops->finish)
365 suspend_ops->finish();
366 Resume_devices: 372 Resume_devices:
367 suspend_test_start(); 373 suspend_test_start();
368 device_resume(PMSG_RESUME); 374 device_resume(PMSG_RESUME);