From mboxrd@z Thu Jan 1 00:00:00 1970 From: ShuoX Liu Subject: [PATCH 2/3] cpuidle: Add a debugfs entry to disable specific C state for debug purpose. Date: Mon, 12 Mar 2012 17:21:33 +0800 Message-ID: <4F5DC01D.7040006@intel.com> References: <4F545A4E.8010801@linux.vnet.ibm.com> <4F5466C4.2090808@intel.com> <20120305101827.GA19408@khazad-dum.debian.net> <1330998885.1916.89.camel@ymzhang> <20120306052236.GA19416@kroah.com> <1331013078.1916.103.camel@ymzhang> <20120306143935.GA23346@kroah.com> <1331082051.1916.124.camel@ymzhang> <20120308180106.GD26516@kroah.com> <4F5DBFA8.3080300@intel.com> Reply-To: shuox.liu@intel.com Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <4F5DBFA8.3080300@intel.com> Sender: linux-kernel-owner@vger.kernel.org To: "linux-kernel@vger.kernel.org" Cc: Greg KH , Yanmin Zhang , "H. Peter Anvin" , "Valentin, Eduardo" , Henrique de Moraes Holschuh , "Brown, Len" , Thomas Gleixner , Andrew Morton , Ingo Molnar , "Kleen, Andi" , "linux-pm@lists.linux-foundation.org" List-Id: linux-pm@vger.kernel.org From: ShuoX Liu Some C states of new CPU might be not good. One reason is BIOS might configure them incorrectly. To help developers root cause it quickly, the patch adds a new debugfs entry, so developers could disable specific C state manually. In addition, C state might have much impact on performance tuning, as it takes much time to enter/exit C states, which might delay interrupt processing. With the new debug option, developers could check if a deep C state could impact performance and how much impact it could cause. Also add this option in Documentation/cpuidle/debugfs.txt. Signed-off-by: ShuoX Liu Reviewed-by: Yanmin Zhang --- Documentation/cpuidle/debugfs.txt | 5 +++++ drivers/cpuidle/cpuidle.c | 1 + drivers/cpuidle/debugfs.c | 4 ++++ drivers/cpuidle/governors/menu.c | 5 ++++- include/linux/cpuidle.h | 1 + 5 files changed, 15 insertions(+), 1 deletions(-) diff --git a/Documentation/cpuidle/debugfs.txt b/Documentation/cpuidle/debugfs.txt index 7724a69..ca393ba 100644 --- a/Documentation/cpuidle/debugfs.txt +++ b/Documentation/cpuidle/debugfs.txt @@ -20,6 +20,7 @@ drwxr-xr-x 2 root root 0 Feb 8 10:42 state3 /sys/kernel/debug/cpu/cpu0/cpuidle/state0: total 0 -r--r--r-- 1 root root 4096 Feb 8 10:42 desc +-rw-r--r-- 1 root root 4096 Feb 8 10:42 disable -r--r--r-- 1 root root 4096 Feb 8 10:42 latency -r--r--r-- 1 root root 4096 Feb 8 10:42 name -r--r--r-- 1 root root 4096 Feb 8 10:42 power @@ -29,6 +30,7 @@ total 0 /sys/kernel/debug/cpu/cpu0/cpuidle/state1: total 0 -r--r--r-- 1 root root 4096 Feb 8 10:42 desc +-rw-r--r-- 1 root root 4096 Feb 8 10:42 disable -r--r--r-- 1 root root 4096 Feb 8 10:42 latency -r--r--r-- 1 root root 4096 Feb 8 10:42 name -r--r--r-- 1 root root 4096 Feb 8 10:42 power @@ -38,6 +40,7 @@ total 0 /sys/kernel/debug/cpu/cpu0/cpuidle/state2: total 0 -r--r--r-- 1 root root 4096 Feb 8 10:42 desc +-rw-r--r-- 1 root root 4096 Feb 8 10:42 disable -r--r--r-- 1 root root 4096 Feb 8 10:42 latency -r--r--r-- 1 root root 4096 Feb 8 10:42 name -r--r--r-- 1 root root 4096 Feb 8 10:42 power @@ -47,6 +50,7 @@ total 0 /sys/kernel/debug/cpu/cpu0/cpuidle/state3: total 0 -r--r--r-- 1 root root 4096 Feb 8 10:42 desc +-rw-r--r-- 1 root root 4096 Feb 8 10:42 disable -r--r--r-- 1 root root 4096 Feb 8 10:42 latency -r--r--r-- 1 root root 4096 Feb 8 10:42 name -r--r--r-- 1 root root 4096 Feb 8 10:42 power @@ -56,6 +60,7 @@ total 0 * desc : Small description about the idle state (string) +* disable : Option to disable this idle state (bool) * latency : Latency to exit out of this idle state (in microseconds) * name : Name of the idle state (string) * power : Power consumed while in this idle state (in milliwatts) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index b4946bc..fdaadb3 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -197,6 +197,7 @@ static void poll_idle_init(struct cpuidle_driver *drv) state->power_usage = -1; state->flags = 0; state->enter = poll_idle; + state->disable = 0; } #else static void poll_idle_init(struct cpuidle_driver *drv) {} diff --git a/drivers/cpuidle/debugfs.c b/drivers/cpuidle/debugfs.c index 67ddc44..197ce72 100644 --- a/drivers/cpuidle/debugfs.c +++ b/drivers/cpuidle/debugfs.c @@ -87,6 +87,10 @@ static void debugfs_add_state_attrs(struct cpuidle_dev_state *dev_state) parent, &state_usage->time)) goto error; + if (!debugfs_create_bool("disable", S_IRUGO | S_IWUSR, + parent, &state->disable)) + goto error; + return; error: debugfs_remove_recursive(parent); diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index ad09526..5c17ca1 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -280,7 +280,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) * We want to default to C1 (hlt), not to busy polling * unless the timer is happening really really soon. */ - if (data->expected_us > 5) + if (data->expected_us > 5 && + drv->states[CPUIDLE_DRIVER_STATE_START].disable == 0) data->last_state_idx = CPUIDLE_DRIVER_STATE_START; /* @@ -290,6 +291,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { struct cpuidle_state *s = &drv->states[i]; + if (s->disable) + continue; if (s->target_residency > data->predicted_us) continue; if (s->exit_latency > latency_req) diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index f605d28..a85877d 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -45,6 +45,7 @@ struct cpuidle_state { unsigned int exit_latency; /* in US */ unsigned int power_usage; /* in mW */ unsigned int target_residency; /* in US */ + unsigned int disable; int (*enter) (struct cpuidle_device *dev, struct cpuidle_driver *drv, -- 1.7.1