Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 97

kernel-2.6.18-238.el5.src.rpm

From: Matthew Garrett <mjg@redhat.com>
Date: Wed, 27 Aug 2008 17:33:01 +0100
Subject: [acpi] increase deep idle state residency on platforms-2
Message-id: 20080827163301.GA10872@srcf.ucam.org
O-Subject: [RHEL5 patch] BZ#455449 - FEAT: RHEL 5.3: (2/2) Increase deep idle state residency on idle platforms using Nehalem class processors
Bugzilla: 455449

When using the local APIC timer, we currently send an IPI to each CPU in
sequence. This patch changes behaviour to send a broadcast IPI, allowing
the CPU to return to the idle state more rapidly.

This version fixes the i386 build. From looking at how the bizarro
architectures like Summit do their APIC setup, I /think/ this is safe -
none of them actually seem to make use of the APIC abstraction for IPI
stuff. It'd be appreciated if someone who actually knows those platforms
could take a look, though.

diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index e72a37a..9ed9c97 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -1253,20 +1253,26 @@ static void up_apic_timer_interrupt_call(struct pt_regs *regs)
 
 void smp_send_timer_broadcast_ipi(struct pt_regs *regs)
 {
+#ifdef CONFIG_SMP
 	cpumask_t mask;
 
+	if (cpus_equal(cpu_online_map, timer_bcast_ipi)) {
+		__send_IPI_shortcut(APIC_DEST_ALLINC, LOCAL_TIMER_VECTOR);
+		return;
+	}
 	cpus_and(mask, cpu_online_map, timer_bcast_ipi);
 	if (!cpus_empty(mask)) {
-#ifdef CONFIG_SMP
 		send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
+	}
 #else
+	if (!cpus_empty(timer_bcast_ipi)) {
 		/*
 		 * We can directly call the apic timer interrupt handler
 		 * in UP case. Minus all irq related functions
 		 */
 		up_apic_timer_interrupt_call(regs);
-#endif
 	}
+#endif
 }
 
 int setup_profiling_timer(unsigned int multiplier)
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 9798e8e..758fece 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -36,6 +36,7 @@
 #include <asm/idle.h>
 #include <asm/proto.h>
 #include <asm/timex.h>
+#include <asm/ipi.h>
 
 int apic_verbosity;
 int apic_runs_main_timer;
@@ -896,6 +897,12 @@ void smp_send_timer_broadcast_ipi(void)
 {
 	cpumask_t mask;
 
+	if (cpus_equal(cpu_online_map, timer_interrupt_broadcast_ipi_mask)) {
+		__send_IPI_shortcut(APIC_DEST_ALLINC, LOCAL_TIMER_VECTOR,
+					APIC_DEST_LOGICAL);
+		return;
+	}
+
 	cpus_and(mask, cpu_online_map, timer_interrupt_broadcast_ipi_mask);
 	if (!cpus_empty(mask)) {
 		send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
diff --git a/include/asm-i386/mach-generic/mach_ipi.h b/include/asm-i386/mach-generic/mach_ipi.h
index 441b0fe..09203be 100644
--- a/include/asm-i386/mach-generic/mach_ipi.h
+++ b/include/asm-i386/mach-generic/mach_ipi.h
@@ -3,6 +3,7 @@
 
 #include <asm/genapic.h>
 
+void __send_IPI_shortcut(unsigned int shortcut, int vector);
 #define send_IPI_mask (genapic->send_IPI_mask)
 #define send_IPI_allbutself (genapic->send_IPI_allbutself)
 #define send_IPI_all (genapic->send_IPI_all)