aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarsten Emde <C.Emde@osadl.org>2012-07-19 16:34:10 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2012-09-03 19:35:44 -0400
commit62d6ae880e3e76098d5e345decd2dce443975889 (patch)
tree5788868e10c08030c5981adae8f5dfd6306b2608
parent4cbe5a555fa58a79b6ecbb6c531b8bab0650778d (diff)
Honor state disabling in the cpuidle ladder governor
There are two cpuidle governors ladder and menu. While the ladder governor is always available, if CONFIG_CPU_IDLE is selected, the menu governor additionally requires CONFIG_NO_HZ. A particular C state can be disabled by writing to the sysfs file /sys/devices/system/cpu/cpuN/cpuidle/stateN/disable, but this mechanism is only implemented in the menu governor. Thus, in a system where CONFIG_NO_HZ is not selected, the ladder governor becomes default and always will walk through all sleep states - irrespective of whether the C state was disabled via sysfs or not. The only way to select a specific C state was to write the related latency to /dev/cpu_dma_latency and keep the file open as long as this setting was required - not very practical and not suitable for setting a single core in an SMP system. With this patch, the ladder governor only will promote to the next C state, if it has not been disabled, and it will demote, if the current C state was disabled. Note that the patch does not make the setting of the sysfs variable "disable" coherent, i.e. if one is disabling a light state, then all deeper states are disabled as well, but the "disable" variable does not reflect it. Likewise, if one enables a deep state but a lighter state still is disabled, then this has no effect. A related section has been added to the documentation. Signed-off-by: Carsten Emde <C.Emde@osadl.org> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-rw-r--r--Documentation/cpuidle/sysfs.txt10
-rw-r--r--drivers/cpuidle/governors/ladder.c4
2 files changed, 12 insertions, 2 deletions
diff --git a/Documentation/cpuidle/sysfs.txt b/Documentation/cpuidle/sysfs.txt
index 9d28a3406e74..b6f44f490ed7 100644
--- a/Documentation/cpuidle/sysfs.txt
+++ b/Documentation/cpuidle/sysfs.txt
@@ -76,9 +76,17 @@ total 0
76 76
77 77
78* desc : Small description about the idle state (string) 78* desc : Small description about the idle state (string)
79* disable : Option to disable this idle state (bool) 79* disable : Option to disable this idle state (bool) -> see note below
80* latency : Latency to exit out of this idle state (in microseconds) 80* latency : Latency to exit out of this idle state (in microseconds)
81* name : Name of the idle state (string) 81* name : Name of the idle state (string)
82* power : Power consumed while in this idle state (in milliwatts) 82* power : Power consumed while in this idle state (in milliwatts)
83* time : Total time spent in this idle state (in microseconds) 83* time : Total time spent in this idle state (in microseconds)
84* usage : Number of times this state was entered (count) 84* usage : Number of times this state was entered (count)
85
86Note:
87The behavior and the effect of the disable variable depends on the
88implementation of a particular governor. In the ladder governor, for
89example, it is not coherent, i.e. if one is disabling a light state,
90then all deeper states are disabled as well, but the disable variable
91does not reflect it. Likewise, if one enables a deep state but a lighter
92state still is disabled, then this has no effect.
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
index b6a09ea859b1..2aef26c520bb 100644
--- a/drivers/cpuidle/governors/ladder.c
+++ b/drivers/cpuidle/governors/ladder.c
@@ -88,6 +88,7 @@ static int ladder_select_state(struct cpuidle_driver *drv,
88 88
89 /* consider promotion */ 89 /* consider promotion */
90 if (last_idx < drv->state_count - 1 && 90 if (last_idx < drv->state_count - 1 &&
91 !dev->states_usage[last_idx + 1].disable &&
91 last_residency > last_state->threshold.promotion_time && 92 last_residency > last_state->threshold.promotion_time &&
92 drv->states[last_idx + 1].exit_latency <= latency_req) { 93 drv->states[last_idx + 1].exit_latency <= latency_req) {
93 last_state->stats.promotion_count++; 94 last_state->stats.promotion_count++;
@@ -100,7 +101,8 @@ static int ladder_select_state(struct cpuidle_driver *drv,
100 101
101 /* consider demotion */ 102 /* consider demotion */
102 if (last_idx > CPUIDLE_DRIVER_STATE_START && 103 if (last_idx > CPUIDLE_DRIVER_STATE_START &&
103 drv->states[last_idx].exit_latency > latency_req) { 104 (dev->states_usage[last_idx].disable ||
105 drv->states[last_idx].exit_latency > latency_req)) {
104 int i; 106 int i;
105 107
106 for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) { 108 for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) {