i386,x86-64 (take 2) Handle missing local APIC timer interrupts on C3 state
PATCH 2/3 i386,x86-64 (take 2) Handle missing local APIC timer interrupts on C3 state
Whenever we see that a CPU is capable of C3 (during ACPI cstate init), we disable local APIC timer and switch to using a broadcast from external timer interrupt (IRQ 0).
Patch below adds the code for i386 and also the ACPI hunk.
arch/i386/kernel/time.c +6 -0
@@ -302,6 +302,12 @@ irqreturn_t timer_interrupt(int irq, voido_timer_interrupt (irq, regs);write_sequnlock (&xtime_lock); + +#ifdef CONFIG_X86_LOCAL_APIC +if (using_apic_timer) +smp_send_timer_broadcast_ipi (regs); +#endif +return IRQ_HANDLED ; }
include/asm-i386/apic.h +5 -0
@@ -132,6 +132,11 @@ extern unsigned int nmi_watchdog;extern int disable_timer_pin_1; +void smp_send_timer_broadcast_ipi (struct pt_regs *regs); +void switch_APIC_timer_to_ipi (void *cpumask); +void switch_ipi_to_APIC_timer (void *cpumask); +#define ARCH_APICTIMER_STOPS_ON_C3 1 +#else /* !CONFIG_X86_LOCAL_APIC */ static inline void lapic_shutdown (void ) { }
arch/i386/kernel/apic.c +76 -2
129 lines not on this page · raw message
drivers/acpi/processor_idle.c +15 -0
@@ -929,6 +929,15 @@ static int acpi_processor_power_verify(sunsigned int i;unsigned int working =0 ; +#ifdef ARCH_APICTIMER_STOPS_ON_C3 +struct cpuinfo_x86 *c = cpu_data + pr->id; +cpumask_t mask =cpumask_of_cpu (pr->id); + +if (c->x86_vendor ==X86_VENDOR_INTEL ) { +on_each_cpu (switch_ipi_to_APIC_timer, &mask,1 ,1 ); + } +#endif +for (i =1 ; i <ACPI_PROCESSOR_MAX_POWER ; i++) {struct acpi_processor_cx *cx = &pr->power.states[i];
@@ -943,6 +952,12 @@ static int acpi_processor_power_verify(scase ACPI_STATE_C3 :acpi_processor_power_verify_c3 (pr, cx); +#ifdef ARCH_APICTIMER_STOPS_ON_C3 +if (c->x86_vendor ==X86_VENDOR_INTEL ) { +on_each_cpu (switch_APIC_timer_to_ipi, + &mask,1 ,1 ); + } +#endif break ; }
Re: [PATCH 2/3]i386,x86-64 (take 3) Handle missing local APIC timer interrupts on C3 state
My bad....
take 2 version of this patch was broken too. Here is take 3.
Whenever we see that a CPU is capable of C3 (during ACPI cstate init), we disable local APIC timer and switch to using a broadcast from external timer interrupt (IRQ 0).
Patch below adds the code for i386 and also the ACPI hunk.
arch/i386/kernel/time.c +6 -0
@@ -302,6 +302,12 @@ irqreturn_t timer_interrupt(int irq, voido_timer_interrupt (irq, regs);write_sequnlock (&xtime_lock); + +#ifdef CONFIG_X86_LOCAL_APIC +if (using_apic_timer) +smp_send_timer_broadcast_ipi (regs); +#endif +return IRQ_HANDLED ; }
include/asm-i386/apic.h +5 -0
@@ -132,6 +132,11 @@ extern unsigned int nmi_watchdog;extern int disable_timer_pin_1; +void smp_send_timer_broadcast_ipi (struct pt_regs *regs); +void switch_APIC_timer_to_ipi (void *cpumask); +void switch_ipi_to_APIC_timer (void *cpumask); +#define ARCH_APICTIMER_STOPS_ON_C3 1 +#else /* !CONFIG_X86_LOCAL_APIC */ static inline void lapic_shutdown (void ) { }
arch/i386/kernel/apic.c +76 -2
129 lines not on this page · raw message
drivers/acpi/processor_idle.c +15 -0
@@ -929,6 +929,15 @@ static int acpi_processor_power_verify(sunsigned int i;unsigned int working =0 ; +#ifdef ARCH_APICTIMER_STOPS_ON_C3 +struct cpuinfo_x86 *c = cpu_data + pr->id; +cpumask_t mask =cpumask_of_cpu (pr->id); + +if (c->x86_vendor ==X86_VENDOR_INTEL ) { +on_each_cpu (switch_ipi_to_APIC_timer, &mask,1 ,1 ); + } +#endif +for (i =1 ; i <ACPI_PROCESSOR_MAX_POWER ; i++) {struct acpi_processor_cx *cx = &pr->power.states[i];
@@ -943,6 +952,12 @@ static int acpi_processor_power_verify(scase ACPI_STATE_C3 :acpi_processor_power_verify_c3 (pr, cx); +#ifdef ARCH_APICTIMER_STOPS_ON_C3 +if (c->x86_vendor ==X86_VENDOR_INTEL ) { +on_each_cpu (switch_APIC_timer_to_ipi, + &mask,1 ,1 ); + } +#endif break ; }