From a20a26f360e95684260c4f0036779aed77f9327b Mon Sep 17 00:00:00 2001 From: "Barry K. Nathan" <barryn@pobox.com> Date: Mon, 10 Jan 2005 17:12:33 -0800 Subject: [PATCH] [PATCH] swsusp: device power management fix Since at least kernel 2.6.9, if not earlier, swsusp fails to properly suspend and resume all devices. The most notable effect is that resuming fails to properly reconfigure interrupt routers. In 2.6.9 this was obscured by other kernel code, but in 2.6.10 this often causes post-resume APIC errors and near-total failure of some PCI devices (e.g. network, sound and USB controllers). Even in cases where interrupt routing is unaffected, this bug causes other problems. For instance, on one of my systems I have to run "ifdown eth0;ifup eth0" after resume in order to have functional networking, if I do not apply this patch. By itself, this patch is not theoretically complete; my next patch fixes that. However, this patch is the critical one for fixing swsusp's behavior in the real world. Signed-off-by: Barry K. Nathan <barryn@pobox.com> Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org> --- kernel/power/swsusp.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index dfac617c4f39..210d102a7dc4 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -843,11 +843,22 @@ int swsusp_suspend(void) if ((error = arch_prepare_suspend())) return error; local_irq_disable(); + /* At this point, device_suspend() has been called, but *not* + * device_power_down(). We *must* device_power_down() now. + * Otherwise, drivers for some devices (e.g. interrupt controllers) + * become desynchronized with the actual state of the hardware + * at resume time, and evil weirdness ensues. + */ + if ((error = device_power_down(PM_SUSPEND_DISK))) { + local_irq_enable(); + return error; + } save_processor_state(); error = swsusp_arch_suspend(); /* Restore control flow magically appears here */ restore_processor_state(); restore_highmem(); + device_power_up(); local_irq_enable(); return error; } -- 2.30.9