Skip to content

Commit 900af0d

Browse files
committed
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 <[email protected]> Acked-by: Ingo Molnar <[email protected]>
1 parent 2ed8d2b commit 900af0d

File tree

1 file changed

+22
-16
lines changed

1 file changed

+22
-16
lines changed

kernel/power/main.c

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,19 @@ static int suspend_enter(suspend_state_t state)
297297
goto Done;
298298
}
299299

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+
300313
arch_suspend_disable_irqs();
301314
BUG_ON(!irqs_disabled());
302315

@@ -310,6 +323,14 @@ static int suspend_enter(suspend_state_t state)
310323
arch_suspend_enable_irqs();
311324
BUG_ON(irqs_disabled());
312325

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:
313334
device_power_up(PMSG_RESUME);
314335

315336
Done:
@@ -346,23 +367,8 @@ int suspend_devices_and_enter(suspend_state_t state)
346367
if (suspend_test(TEST_DEVICES))
347368
goto Recover_platform;
348369

349-
if (suspend_ops->prepare) {
350-
error = suspend_ops->prepare();
351-
if (error)
352-
goto Resume_devices;
353-
}
354-
355-
if (suspend_test(TEST_PLATFORM))
356-
goto Finish;
370+
suspend_enter(state);
357371

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();
366372
Resume_devices:
367373
suspend_test_start();
368374
device_resume(PMSG_RESUME);

0 commit comments

Comments
 (0)