aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2007-09-22 18:29:05 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-09-22 20:15:34 -0400
commitb04e7bdb984e3b7f62fb7f44146a529f88cc7639 (patch)
tree57fa4b6ab2e6bd20b0a2eed12db2a484e928fe17 /drivers
parent1f0cff6e4d579ab0fe671c02fcd842694e46b90f (diff)
ACPI: disable lower idle C-states across suspend/resume
device_suspend() calls ACPI suspend functions, which seems to have undesired side effects on lower idle C-states. It took me some time to realize that especially the VAIO BIOSes (both Andrews jinxed UP and my elfstruck SMP one) show this effect. I'm quite sure that other bug reports against suspend/resume about turning the system into a brick have the same root cause. After fishing in the dark for quite some time, I realized that removing the ACPI processor module before suspend (this removes the lower C-state functionality) made the problem disappear. Interestingly enough the propability of having a bricked box is influenced by various factors (interrupts, size of the ram image, ...). Even adding a bunch of printks in the wrong places made the problem go away. The previous periodic tick implementation simply pampered over the problem, which explains why the dyntick / clockevents changes made this more prominent. We avoid complex functionality during the boot process and we have to do the same during suspend/resume. It is a similar scenario and equaly fragile. Add suspend / resume functions to the ACPI processor code and disable the lower idle C-states across suspend/resume. Fall back to the default idle implementation (halt) instead. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Andrew Morton <akpm@linux-foundation.org> Cc: Len Brown <lenb@kernel.org> Cc: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Cc: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/processor_core.c2
-rw-r--r--drivers/acpi/processor_idle.c19
2 files changed, 20 insertions, 1 deletions
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 2afb3d2086b3..9f11dc296cdd 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -102,6 +102,8 @@ static struct acpi_driver acpi_processor_driver = {
102 .add = acpi_processor_add, 102 .add = acpi_processor_add,
103 .remove = acpi_processor_remove, 103 .remove = acpi_processor_remove,
104 .start = acpi_processor_start, 104 .start = acpi_processor_start,
105 .suspend = acpi_processor_suspend,
106 .resume = acpi_processor_resume,
105 }, 107 },
106}; 108};
107 109
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index d9b8af763e1e..f18261368e76 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -325,6 +325,23 @@ static void acpi_state_timer_broadcast(struct acpi_processor *pr,
325 325
326#endif 326#endif
327 327
328/*
329 * Suspend / resume control
330 */
331static int acpi_idle_suspend;
332
333int acpi_processor_suspend(struct acpi_device * device, pm_message_t state)
334{
335 acpi_idle_suspend = 1;
336 return 0;
337}
338
339int acpi_processor_resume(struct acpi_device * device)
340{
341 acpi_idle_suspend = 0;
342 return 0;
343}
344
328static void acpi_processor_idle(void) 345static void acpi_processor_idle(void)
329{ 346{
330 struct acpi_processor *pr = NULL; 347 struct acpi_processor *pr = NULL;
@@ -355,7 +372,7 @@ static void acpi_processor_idle(void)
355 } 372 }
356 373
357 cx = pr->power.state; 374 cx = pr->power.state;
358 if (!cx) { 375 if (!cx || acpi_idle_suspend) {
359 if (pm_idle_save) 376 if (pm_idle_save)
360 pm_idle_save(); 377 pm_idle_save();
361 else 378 else