From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965532AbXAWWBr (ORCPT ); Tue, 23 Jan 2007 17:01:47 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S965528AbXAWWB3 (ORCPT ); Tue, 23 Jan 2007 17:01:29 -0500 Received: from www.osadl.org ([213.239.205.134]:35902 "EHLO mail.tglx.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S965507AbXAWWBN (ORCPT ); Tue, 23 Jan 2007 17:01:13 -0500 Message-Id: <20070123211207.568201000@localhost.localdomain> References: <20070123211159.178138000@localhost.localdomain> Date: Tue, 23 Jan 2007 22:01:26 -0000 From: Thomas Gleixner To: Andrew Morton Cc: LKML , Ingo Molnar , John Stultz , Arjan van de Veen , Roman Zippel Subject: [patch 30/46] ACPI keep track of timer broadcasting Content-Disposition: inline; filename=acpi-keep-track-of-timer-broadcast.patch Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org From: Thomas Gleixner This is a preperatory patch for highres/dyntick: - replace the big #ifdef ARCH_APICTIMER_STOPS_ON_C3 hackery by functions - remove the double switch in the power verify function (in the worst case we switched ipi to apic and 20usec later apic to ipi) - keep track of the the state which stops local APIC timer Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar Cc: Len Brown Cc: Cc: Andi Kleen Signed-off-by: Andrew Morton --- drivers/acpi/processor_idle.c | 67 ++++++++++++++++++++++++++++++------------ include/acpi/processor.h | 1 2 files changed, 49 insertions(+), 19 deletions(-) Index: linux-2.6.20-rc4-mm1-bo/drivers/acpi/processor_idle.c =================================================================== --- linux-2.6.20-rc4-mm1-bo.orig/drivers/acpi/processor_idle.c +++ linux-2.6.20-rc4-mm1-bo/drivers/acpi/processor_idle.c @@ -250,6 +250,49 @@ static void acpi_cstate_enter(struct acp } } +#ifdef ARCH_APICTIMER_STOPS_ON_C3 + +/* + * Some BIOS implementations switch to C3 in the published C2 state. This seems + * to be a common problem on AMD boxen. + */ +static void acpi_timer_check_state(int state, struct acpi_processor *pr, + struct acpi_processor_cx *cx) +{ + struct acpi_processor_power *pwr = &pr->power; + + /* + * Check, if one of the previous states already marked the lapic + * unstable + */ + if (pwr->timer_broadcast_on_state < state) + return; + + if(cx->type == ACPI_STATE_C3 || + boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { + pr->power.timer_broadcast_on_state = state; + return; + } +} + +static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) +{ + cpumask_t mask = cpumask_of_cpu(pr->id); + + if (pr->power.timer_broadcast_on_state < INT_MAX) + on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1); + else + on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1); +} + +#else + +static void acpi_timer_check_state(int state, struct acpi_processor *pr, + struct acpi_processor_cx *cstate) { } +static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) { } + +#endif + static void acpi_processor_idle(void) { struct acpi_processor *pr = NULL; @@ -920,11 +963,7 @@ static int acpi_processor_power_verify(s unsigned int i; unsigned int working = 0; -#ifdef ARCH_APICTIMER_STOPS_ON_C3 - int timer_broadcast = 0; - cpumask_t mask = cpumask_of_cpu(pr->id); - on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1); -#endif + pr->power.timer_broadcast_on_state = INT_MAX; for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) { struct acpi_processor_cx *cx = &pr->power.states[i]; @@ -936,21 +975,14 @@ static int acpi_processor_power_verify(s case ACPI_STATE_C2: acpi_processor_power_verify_c2(cx); -#ifdef ARCH_APICTIMER_STOPS_ON_C3 - /* Some AMD systems fake C3 as C2, but still - have timer troubles */ - if (cx->valid && - boot_cpu_data.x86_vendor == X86_VENDOR_AMD) - timer_broadcast++; -#endif + if (cx->valid) + acpi_timer_check_state(i, pr, cx); break; case ACPI_STATE_C3: acpi_processor_power_verify_c3(pr, cx); -#ifdef ARCH_APICTIMER_STOPS_ON_C3 if (cx->valid) - timer_broadcast++; -#endif + acpi_timer_check_state(i, pr, cx); break; } @@ -958,10 +990,7 @@ static int acpi_processor_power_verify(s working++; } -#ifdef ARCH_APICTIMER_STOPS_ON_C3 - if (timer_broadcast) - on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1); -#endif + acpi_propagate_timer_broadcast(pr); return (working); } Index: linux-2.6.20-rc4-mm1-bo/include/acpi/processor.h =================================================================== --- linux-2.6.20-rc4-mm1-bo.orig/include/acpi/processor.h +++ linux-2.6.20-rc4-mm1-bo/include/acpi/processor.h @@ -79,6 +79,7 @@ struct acpi_processor_power { u32 bm_activity; int count; struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER]; + int timer_broadcast_on_state; }; /* Performance Management */ --