From patchwork Wed Feb 16 06:22:00 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Len Brown X-Patchwork-Id: 565901 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 p1G6KNdE003825 for ; Wed, 16 Feb 2011 06:22:24 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752357Ab1BPGWV (ORCPT ); Wed, 16 Feb 2011 01:22:21 -0500 Received: from vms173003pub.verizon.net ([206.46.173.3]:63681 "EHLO vms173003pub.verizon.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751606Ab1BPGWV (ORCPT ); Wed, 16 Feb 2011 01:22:21 -0500 Received: from localhost.localdomain ([unknown] [108.7.58.61]) by vms173003.mailsrvcs.net (Sun Java(tm) System Messaging Server 7u2-7.02 32bit (built Apr 16 2009)) with ESMTPA id <0LGP00MT25OR549B@vms173003.mailsrvcs.net>; Wed, 16 Feb 2011 00:22:10 -0600 (CST) Received: from localhost.localdomain (x980 [127.0.0.1]) by localhost.localdomain (8.14.4/8.14.4) with ESMTP id p1G6M1kd003568; Wed, 16 Feb 2011 01:22:02 -0500 Received: from localhost (lenb@localhost) by localhost.localdomain (8.14.4/8.14.4/Submit) with ESMTP id p1G6M02L003563; Wed, 16 Feb 2011 01:22:01 -0500 X-Authentication-warning: localhost.localdomain: lenb owned process doing -bs Date: Wed, 16 Feb 2011 01:22:00 -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, linux-kernel@vger.kernel.org Subject: [PATCH] intel_idle: disable NHM/WSM HW C-state auto-demotion (v3) In-reply-to: Message-id: References: 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, 16 Feb 2011 06:22:26 +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..88998ac 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,12 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state); static struct cpuidle_state *cpuidle_state_table; /* + * Hardware C-state auto-demotion may not always be optimal. + * Indicate which enable bits to clear here. + */ +static unsigned int auto_demotion_disable_flags; + +/* * 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 +292,16 @@ static struct notifier_block __cpuinitdata setup_broadcast_notifier = { .notifier_call = setup_broadcast_cpuhp_notify, }; +static long auto_demotion_disable(void *enable_bits) +{ + unsigned long long msr_bits; + + rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); + msr_bits &= ~((unsigned long long)enable_bits); + wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); + return 0; +} + /* * intel_idle_probe() */ @@ -328,6 +345,7 @@ static int intel_idle_probe(void) case 0x25: /* Westmere */ case 0x2C: /* Westmere */ cpuidle_state_table = nehalem_cstates; + auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE; break; case 0x1C: /* 28 - Atom Processor */ @@ -440,6 +458,8 @@ static int intel_idle_cpuidle_devices_init(void) return -EIO; } } + if (auto_demotion_disable_flags) + smp_call_function(auto_demotion_disable, (void *)auto_demotion_disable_flags, 1); return 0; }