From 0fda6b403f0eca66ad8a7c946b3996e359100443 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Wed, 9 Apr 2008 21:31:46 -0400 Subject: 2.6.25 regression: powertop says 120K wakeups/sec Patch to fix huge number of wakeups reported due to recent changes in processor_idle.c. The problem was that the entry_method determination was broken due to one of the recent commits (bc71bec91f987) causing C1 entry to not to go to halt. http://lkml.org/lkml/2008/3/22/124 Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/acpi/processor_idle.c') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 788da9781f80..836362b50faa 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -848,6 +848,7 @@ static int acpi_processor_get_power_info_default(struct acpi_processor *pr) /* all processors need to support C1 */ pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; pr->power.states[ACPI_STATE_C1].valid = 1; + pr->power.states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_HALT; } /* the C0 state only exists as a filler in our array */ pr->power.states[ACPI_STATE_C0].valid = 1; @@ -960,6 +961,9 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) cx.address); } + if (cx.type == ACPI_STATE_C1) { + cx.valid = 1; + } obj = &(element->package.elements[2]); if (obj->type != ACPI_TYPE_INTEGER) -- cgit v1.2.1 From 7f424a8b08c26dc14ac5c17164014539ac9a5c65 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 25 Apr 2008 17:39:01 +0200 Subject: fix idle (arch, acpi and apm) and lockdep OK, so 25-mm1 gave a lockdep error which made me look into this. The first thing that I noticed was the horrible mess; the second thing I saw was hacks like: 71e93d15612c61c2e26a169567becf088e71b8ff The problem is that arch idle routines are somewhat inconsitent with their IRQ state handling and instead of fixing _that_, we go paper over the problem. So the thing I've tried to do is set a standard for idle routines and fix them all up to adhere to that. So the rules are: idle routines are entered with IRQs disabled idle routines will exit with IRQs enabled Nearly all already did this in one form or another. Merge the 32 and 64 bit bits so they no longer have different bugs. As for the actual lockdep warning; __sti_mwait() did a plainly un-annotated irq-enable. Signed-off-by: Peter Zijlstra Tested-by: Bob Copeland Signed-off-by: Ingo Molnar --- drivers/acpi/processor_idle.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers/acpi/processor_idle.c') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 788da9781f80..0d90ff5fd117 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -418,13 +418,12 @@ static void acpi_processor_idle(void) cx = pr->power.state; if (!cx || acpi_idle_suspend) { - if (pm_idle_save) - pm_idle_save(); - else + if (pm_idle_save) { + pm_idle_save(); /* enables IRQs */ + } else { acpi_safe_halt(); - - if (irqs_disabled()) local_irq_enable(); + } return; } @@ -520,10 +519,12 @@ static void acpi_processor_idle(void) * Use the appropriate idle routine, the one that would * be used without acpi C-states. */ - if (pm_idle_save) - pm_idle_save(); - else + if (pm_idle_save) { + pm_idle_save(); /* enables IRQs */ + } else { acpi_safe_halt(); + local_irq_enable(); + } /* * TBD: Can't get time duration while in C1, as resumes @@ -534,8 +535,6 @@ static void acpi_processor_idle(void) * skew otherwise. */ sleep_ticks = 0xFFFFFFFF; - if (irqs_disabled()) - local_irq_enable(); break; -- cgit v1.2.1 From 36a913586597cab1cd565e9bf348d037f0df955b Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Wed, 30 Apr 2008 13:57:15 -0400 Subject: ACPI: Fix acpi_processor_idle and idle= boot parameters interaction acpi_processor_idle and "idle=" boot parameter interaction is broken. The problem is that, at boot time acpi driver is checking for "idle=" boot option and not registering the acpi idle handler. But, when there is a CST changed callback (typically when switching AC <-> battery or suspend-resume) there are no checks for boot_option_idle_override and acpi idle handler tries to get installed with nasty side effects. With CPU_IDLE configured this issue causes results in a nasty oops on CST change callback and without CPU_IDLE there is no oops, but boot option of "idle=" gets ignored and acpi idle handler gets installed. Change the behavior to not do anything in acpi idle handler when there is a "idle=" boot option. Note that the problem is only there when "idle=" boot option is used. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/acpi/processor_idle.c') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 836362b50faa..47b167c731a0 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -1299,6 +1299,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) { int result = 0; + if (boot_option_idle_override) + return 0; if (!pr) return -EINVAL; @@ -1738,6 +1740,9 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) { int ret; + if (boot_option_idle_override) + return 0; + if (!pr) return -EINVAL; @@ -1768,6 +1773,8 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, struct proc_dir_entry *entry = NULL; unsigned int i; + if (boot_option_idle_override) + return 0; if (!first_run) { dmi_check_system(processor_power_dmi_table); @@ -1803,7 +1810,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, * Note that we use previously set idle handler will be used on * platforms that only support C1. */ - if ((pr->flags.power) && (!boot_option_idle_override)) { + if (pr->flags.power) { #ifdef CONFIG_CPU_IDLE acpi_processor_setup_cpuidle(pr); pr->power.dev.cpu = pr->id; @@ -1843,8 +1850,11 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, int acpi_processor_power_exit(struct acpi_processor *pr, struct acpi_device *device) { + if (boot_option_idle_override) + return 0; + #ifdef CONFIG_CPU_IDLE - if ((pr->flags.power) && (!boot_option_idle_override)) + if (pr->flags.power) cpuidle_unregister_device(&pr->power.dev); #endif pr->flags.power_setup_done = 0; -- cgit v1.2.1