Sophie

Sophie

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

kernel-2.6.18-238.el5.src.rpm

From: Matthew Garrett <mjg@redhat.com>
Date: Thu, 10 Jul 2008 13:27:11 +0100
Subject: [acpi] enable deep C states for idle efficiency
Message-id: 20080710122711.GA7691@srcf.ucam.org
O-Subject: Re: [RHEL 5.3 PATCH] BZ#443516: FEAT: RHEL5.3: enable deep C states on Nehalem for idle efficiency
Bugzilla: 443516
RH-Acked-by: Prarit Bhargava <prarit@redhat.com>
RH-Acked-by: Brian Maly <bmaly@redhat.com>

This time with a patch...

The ACPI spec includes (but does not require) a field for the OS to
handshake with the firmware when entering deep C states. Older versions
of the kernel would only enable these deep C states when this field was
present. The check is unnecessary - if the hardware provides deep C
states and does not provide the field, it's because it doesn't require
the OS handshaking. Recent hardware no longer provides this field, so
we're losing power efficiency on them.

This is simply a backport of the relevant code from current upstream
Linux and has been tested on Nehalem hardware.

diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 7106606..90a2aaf 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -382,7 +382,17 @@ static void acpi_processor_idle(void)
 
 	case ACPI_STATE_C3:
 
-		if (pr->flags.bm_check) {
+		/*
+		 * disable bus master
+		 * bm_check implies we need ARB_DIS
+		 * !bm_check implies we need cache flush
+		 * bm_control implies whether we can do ARB_DIS
+		 *
+		 * That leaves a case where bm_check is set and bm_control is
+		 * not set. In that case we cannot do much, we enter C3
+		 * without doing anything.
+		 */
+		if (pr->flags.bm_check && pr->flags.bm_control) {
 			if (atomic_inc_return(&c3_cpu_count) ==
 			    num_online_cpus()) {
 				/*
@@ -392,7 +402,7 @@ static void acpi_processor_idle(void)
 				acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
 						  ACPI_MTX_DO_NOT_LOCK);
 			}
-		} else {
+		} else if (!pr->flags.bm_check) {
 			/* SMP with no shared cache... Invalidate cache  */
 			ACPI_FLUSH_CPU_CACHE();
 		}
@@ -405,7 +415,7 @@ static void acpi_processor_idle(void)
 		t2 = inl(acpi_fadt.xpm_tmr_blk.address);
 		/* Get end time (ticks) */
 		t2 = inl(acpi_fadt.xpm_tmr_blk.address);
-		if (pr->flags.bm_check) {
+		if (pr->flags.bm_check && pr->flags.bm_control) {
 			/* Enable bus master arbitration */
 			atomic_dec(&c3_cpu_count);
 			acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0,
@@ -843,9 +853,9 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
 	if (pr->flags.bm_check) {
 		/* bus mastering control is necessary */
 		if (!pr->flags.bm_control) {
+			/* In this case we enter C3 without bus mastering */
 			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-					  "C3 support requires bus mastering control\n"));
-			return;
+				"C3 support without bus mastering control\n"));
 		}
 	} else {
 		/*