aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorBarry K. Nathan <barryn@pobox.com>2005-01-10 17:12:33 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-10 17:12:33 -0800
commita20a26f360e95684260c4f0036779aed77f9327b (patch)
treee5d771a6d15fc8a0c2f1d2e5bf8967214c5100a1 /kernel
parentbf17b0cb528a4ccafbd969bfbcef85a2fa2006bf (diff)
downloadhistory-a20a26f360e95684260c4f0036779aed77f9327b.tar.gz
[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>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/power/swsusp.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index dfac617c4f39b2..210d102a7dc465 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;
}