From patchwork Wed Jan 19 02:52:26 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Len Brown X-Patchwork-Id: 488021 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p0J2qZCN029603 for ; Wed, 19 Jan 2011 02:52:35 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751524Ab1ASCwc (ORCPT ); Tue, 18 Jan 2011 21:52:32 -0500 Received: from vms173019pub.verizon.net ([206.46.173.19]:36539 "EHLO vms173019pub.verizon.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751446Ab1ASCwb (ORCPT ); Tue, 18 Jan 2011 21:52:31 -0500 Received: from localhost.localdomain ([unknown] [108.7.58.61]) by vms173019.mailsrvcs.net (Sun Java(tm) System Messaging Server 7u2-7.02 32bit (built Apr 16 2009)) with ESMTPA id <0LF9007331BICWE4@vms173019.mailsrvcs.net> for linux-acpi@vger.kernel.org; Tue, 18 Jan 2011 20:52:31 -0600 (CST) Received: from localhost.localdomain (x980 [127.0.0.1]) by localhost.localdomain (8.14.4/8.14.4) with ESMTP id p0J2qSuR014695; Tue, 18 Jan 2011 21:52:29 -0500 Received: from localhost (lenb@localhost) by localhost.localdomain (8.14.4/8.14.4/Submit) with ESMTP id p0J2qQQc014690; Tue, 18 Jan 2011 21:52:27 -0500 X-Authentication-warning: localhost.localdomain: lenb owned process doing -bs Date: Tue, 18 Jan 2011 21:52:26 -0500 (EST) From: Len Brown X-X-Sender: lenb@x980 To: linux-pm@lists.linux-foundation.org, x86@kernel.org, linux-acpi@vger.kernel.org Subject: [PATCH] intel_idle: disable HW auto-demotion Message-id: User-Agent: Alpine 2.02 (LFD 1266 2009-07-14) MIME-version: 1.0 Content-type: TEXT/PLAIN; charset=US-ASCII Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Wed, 19 Jan 2011 02:52:36 +0000 (UTC) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 4d0dfa0..b75eeab 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -36,6 +36,10 @@ #define MSR_IA32_PERFCTR1 0x000000c2 #define MSR_FSB_FREQ 0x000000cd +#define MSR_NHM_SNB_PKG_CST_CFG_CTL 0x000000e2 +#define NHM_C3_AUTO_DEMOTE (1UL << 25) +#define NHM_C1_AUTO_DEMOTE (1UL << 26) + #define MSR_MTRRcap 0x000000fe #define MSR_IA32_BBL_CR_CTL 0x00000119 diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 7acb32e..3ee8c38 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -62,6 +62,7 @@ #include #include #include +#include #define INTEL_IDLE_VERSION "0.4" #define PREFIX "intel_idle: " @@ -85,6 +86,16 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state); static struct cpuidle_state *cpuidle_state_table; /* + * Disable HW auto demotion on tick-less idle kernels + */ +static unsigned int has_nhm_snb_hw_auto_demotion; +#ifdef CONFIG_NO_HZ +static unsigned int auto_demotion; +#else +static unsigned int auto_demotion = 1; +#endif + +/* * Set this flag for states where the HW flushes the TLB for us * and so we don't need cross-calls to keep it consistent. * If this flag is set, SW flushes the TLB, so even if the @@ -285,6 +296,20 @@ static struct notifier_block __cpuinitdata setup_broadcast_notifier = { .notifier_call = setup_broadcast_cpuhp_notify, }; +static long nhm_snb_auto_demotion_off(void *unused) +{ + unsigned long long msr_bits; + + rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); + + msr_bits &= ~(NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE); + + wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); + + return 0; +} + + /* * intel_idle_probe() */ @@ -328,6 +353,7 @@ static int intel_idle_probe(void) case 0x25: /* Westmere */ case 0x2C: /* Westmere */ cpuidle_state_table = nehalem_cstates; + has_nhm_snb_hw_auto_demotion = 1; break; case 0x1C: /* 28 - Atom Processor */ @@ -338,6 +364,7 @@ static int intel_idle_probe(void) case 0x2A: /* SNB */ case 0x2D: /* SNB Xeon */ cpuidle_state_table = snb_cstates; + has_nhm_snb_hw_auto_demotion = 1; break; default: @@ -439,6 +466,8 @@ static int intel_idle_cpuidle_devices_init(void) intel_idle_cpuidle_devices_uninit(); return -EIO; } + if (has_nhm_snb_hw_auto_demotion && (auto_demotion == 0)) + work_on_cpu(i, nhm_snb_auto_demotion_off, 0); } return 0; @@ -490,6 +519,7 @@ module_init(intel_idle_init); module_exit(intel_idle_exit); module_param(max_cstate, int, 0444); +module_param(auto_demotion, int, 0444); MODULE_AUTHOR("Len Brown "); MODULE_DESCRIPTION("Cpuidle driver for Intel Hardware v" INTEL_IDLE_VERSION);