diff options
| -rw-r--r-- | Documentation/cpuidle/sysfs.txt | 5 | ||||
| -rw-r--r-- | drivers/cpuidle/cpuidle.c | 1 | ||||
| -rw-r--r-- | drivers/cpuidle/governors/menu.c | 5 | ||||
| -rw-r--r-- | drivers/cpuidle/sysfs.c | 40 | ||||
| -rw-r--r-- | include/linux/cpuidle.h | 1 |
5 files changed, 51 insertions, 1 deletions
diff --git a/Documentation/cpuidle/sysfs.txt b/Documentation/cpuidle/sysfs.txt index 50d7b1642759..9d28a3406e74 100644 --- a/Documentation/cpuidle/sysfs.txt +++ b/Documentation/cpuidle/sysfs.txt | |||
| @@ -36,6 +36,7 @@ drwxr-xr-x 2 root root 0 Feb 8 10:42 state3 | |||
| 36 | /sys/devices/system/cpu/cpu0/cpuidle/state0: | 36 | /sys/devices/system/cpu/cpu0/cpuidle/state0: |
| 37 | total 0 | 37 | total 0 |
| 38 | -r--r--r-- 1 root root 4096 Feb 8 10:42 desc | 38 | -r--r--r-- 1 root root 4096 Feb 8 10:42 desc |
| 39 | -rw-r--r-- 1 root root 4096 Feb 8 10:42 disable | ||
| 39 | -r--r--r-- 1 root root 4096 Feb 8 10:42 latency | 40 | -r--r--r-- 1 root root 4096 Feb 8 10:42 latency |
| 40 | -r--r--r-- 1 root root 4096 Feb 8 10:42 name | 41 | -r--r--r-- 1 root root 4096 Feb 8 10:42 name |
| 41 | -r--r--r-- 1 root root 4096 Feb 8 10:42 power | 42 | -r--r--r-- 1 root root 4096 Feb 8 10:42 power |
| @@ -45,6 +46,7 @@ total 0 | |||
| 45 | /sys/devices/system/cpu/cpu0/cpuidle/state1: | 46 | /sys/devices/system/cpu/cpu0/cpuidle/state1: |
| 46 | total 0 | 47 | total 0 |
| 47 | -r--r--r-- 1 root root 4096 Feb 8 10:42 desc | 48 | -r--r--r-- 1 root root 4096 Feb 8 10:42 desc |
| 49 | -rw-r--r-- 1 root root 4096 Feb 8 10:42 disable | ||
| 48 | -r--r--r-- 1 root root 4096 Feb 8 10:42 latency | 50 | -r--r--r-- 1 root root 4096 Feb 8 10:42 latency |
| 49 | -r--r--r-- 1 root root 4096 Feb 8 10:42 name | 51 | -r--r--r-- 1 root root 4096 Feb 8 10:42 name |
| 50 | -r--r--r-- 1 root root 4096 Feb 8 10:42 power | 52 | -r--r--r-- 1 root root 4096 Feb 8 10:42 power |
| @@ -54,6 +56,7 @@ total 0 | |||
| 54 | /sys/devices/system/cpu/cpu0/cpuidle/state2: | 56 | /sys/devices/system/cpu/cpu0/cpuidle/state2: |
| 55 | total 0 | 57 | total 0 |
| 56 | -r--r--r-- 1 root root 4096 Feb 8 10:42 desc | 58 | -r--r--r-- 1 root root 4096 Feb 8 10:42 desc |
| 59 | -rw-r--r-- 1 root root 4096 Feb 8 10:42 disable | ||
| 57 | -r--r--r-- 1 root root 4096 Feb 8 10:42 latency | 60 | -r--r--r-- 1 root root 4096 Feb 8 10:42 latency |
| 58 | -r--r--r-- 1 root root 4096 Feb 8 10:42 name | 61 | -r--r--r-- 1 root root 4096 Feb 8 10:42 name |
| 59 | -r--r--r-- 1 root root 4096 Feb 8 10:42 power | 62 | -r--r--r-- 1 root root 4096 Feb 8 10:42 power |
| @@ -63,6 +66,7 @@ total 0 | |||
| 63 | /sys/devices/system/cpu/cpu0/cpuidle/state3: | 66 | /sys/devices/system/cpu/cpu0/cpuidle/state3: |
| 64 | total 0 | 67 | total 0 |
| 65 | -r--r--r-- 1 root root 4096 Feb 8 10:42 desc | 68 | -r--r--r-- 1 root root 4096 Feb 8 10:42 desc |
| 69 | -rw-r--r-- 1 root root 4096 Feb 8 10:42 disable | ||
| 66 | -r--r--r-- 1 root root 4096 Feb 8 10:42 latency | 70 | -r--r--r-- 1 root root 4096 Feb 8 10:42 latency |
| 67 | -r--r--r-- 1 root root 4096 Feb 8 10:42 name | 71 | -r--r--r-- 1 root root 4096 Feb 8 10:42 name |
| 68 | -r--r--r-- 1 root root 4096 Feb 8 10:42 power | 72 | -r--r--r-- 1 root root 4096 Feb 8 10:42 power |
| @@ -72,6 +76,7 @@ total 0 | |||
| 72 | 76 | ||
| 73 | 77 | ||
| 74 | * 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) | ||
| 75 | * latency : Latency to exit out of this idle state (in microseconds) | 80 | * latency : Latency to exit out of this idle state (in microseconds) |
| 76 | * name : Name of the idle state (string) | 81 | * name : Name of the idle state (string) |
| 77 | * power : Power consumed while in this idle state (in milliwatts) | 82 | * power : Power consumed while in this idle state (in milliwatts) |
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 4869b5500234..77304b6b8aef 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
| @@ -245,6 +245,7 @@ static void poll_idle_init(struct cpuidle_driver *drv) | |||
| 245 | state->power_usage = -1; | 245 | state->power_usage = -1; |
| 246 | state->flags = 0; | 246 | state->flags = 0; |
| 247 | state->enter = poll_idle; | 247 | state->enter = poll_idle; |
| 248 | state->disable = 0; | ||
| 248 | } | 249 | } |
| 249 | #else | 250 | #else |
| 250 | static void poll_idle_init(struct cpuidle_driver *drv) {} | 251 | static void poll_idle_init(struct cpuidle_driver *drv) {} |
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index ad0952601ae2..5c17ca112fc2 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) | |||
| 280 | * We want to default to C1 (hlt), not to busy polling | 280 | * We want to default to C1 (hlt), not to busy polling |
| 281 | * unless the timer is happening really really soon. | 281 | * unless the timer is happening really really soon. |
| 282 | */ | 282 | */ |
| 283 | if (data->expected_us > 5) | 283 | if (data->expected_us > 5 && |
| 284 | drv->states[CPUIDLE_DRIVER_STATE_START].disable == 0) | ||
| 284 | data->last_state_idx = CPUIDLE_DRIVER_STATE_START; | 285 | data->last_state_idx = CPUIDLE_DRIVER_STATE_START; |
| 285 | 286 | ||
| 286 | /* | 287 | /* |
| @@ -290,6 +291,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
| 290 | for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { | 291 | for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { |
| 291 | struct cpuidle_state *s = &drv->states[i]; | 292 | struct cpuidle_state *s = &drv->states[i]; |
| 292 | 293 | ||
| 294 | if (s->disable) | ||
| 295 | continue; | ||
| 293 | if (s->target_residency > data->predicted_us) | 296 | if (s->target_residency > data->predicted_us) |
| 294 | continue; | 297 | continue; |
| 295 | if (s->exit_latency > latency_req) | 298 | if (s->exit_latency > latency_req) |
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 3fe41fe4851a..88032b4dc6d2 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/sysfs.h> | 11 | #include <linux/sysfs.h> |
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/cpu.h> | 13 | #include <linux/cpu.h> |
| 14 | #include <linux/capability.h> | ||
| 14 | 15 | ||
| 15 | #include "cpuidle.h" | 16 | #include "cpuidle.h" |
| 16 | 17 | ||
| @@ -222,6 +223,9 @@ struct cpuidle_state_attr { | |||
| 222 | #define define_one_state_ro(_name, show) \ | 223 | #define define_one_state_ro(_name, show) \ |
| 223 | static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0444, show, NULL) | 224 | static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0444, show, NULL) |
| 224 | 225 | ||
| 226 | #define define_one_state_rw(_name, show, store) \ | ||
| 227 | static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0644, show, store) | ||
| 228 | |||
| 225 | #define define_show_state_function(_name) \ | 229 | #define define_show_state_function(_name) \ |
| 226 | static ssize_t show_state_##_name(struct cpuidle_state *state, \ | 230 | static ssize_t show_state_##_name(struct cpuidle_state *state, \ |
| 227 | struct cpuidle_state_usage *state_usage, char *buf) \ | 231 | struct cpuidle_state_usage *state_usage, char *buf) \ |
| @@ -229,6 +233,24 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \ | |||
| 229 | return sprintf(buf, "%u\n", state->_name);\ | 233 | return sprintf(buf, "%u\n", state->_name);\ |
| 230 | } | 234 | } |
| 231 | 235 | ||
| 236 | #define define_store_state_function(_name) \ | ||
| 237 | static ssize_t store_state_##_name(struct cpuidle_state *state, \ | ||
| 238 | const char *buf, size_t size) \ | ||
| 239 | { \ | ||
| 240 | long value; \ | ||
| 241 | int err; \ | ||
| 242 | if (!capable(CAP_SYS_ADMIN)) \ | ||
| 243 | return -EPERM; \ | ||
| 244 | err = kstrtol(buf, 0, &value); \ | ||
| 245 | if (err) \ | ||
| 246 | return err; \ | ||
| 247 | if (value) \ | ||
| 248 | state->disable = 1; \ | ||
| 249 | else \ | ||
| 250 | state->disable = 0; \ | ||
| 251 | return size; \ | ||
| 252 | } | ||
| 253 | |||
| 232 | #define define_show_state_ull_function(_name) \ | 254 | #define define_show_state_ull_function(_name) \ |
| 233 | static ssize_t show_state_##_name(struct cpuidle_state *state, \ | 255 | static ssize_t show_state_##_name(struct cpuidle_state *state, \ |
| 234 | struct cpuidle_state_usage *state_usage, char *buf) \ | 256 | struct cpuidle_state_usage *state_usage, char *buf) \ |
| @@ -251,6 +273,8 @@ define_show_state_ull_function(usage) | |||
| 251 | define_show_state_ull_function(time) | 273 | define_show_state_ull_function(time) |
| 252 | define_show_state_str_function(name) | 274 | define_show_state_str_function(name) |
| 253 | define_show_state_str_function(desc) | 275 | define_show_state_str_function(desc) |
| 276 | define_show_state_function(disable) | ||
| 277 | define_store_state_function(disable) | ||
| 254 | 278 | ||
| 255 | define_one_state_ro(name, show_state_name); | 279 | define_one_state_ro(name, show_state_name); |
| 256 | define_one_state_ro(desc, show_state_desc); | 280 | define_one_state_ro(desc, show_state_desc); |
| @@ -258,6 +282,7 @@ define_one_state_ro(latency, show_state_exit_latency); | |||
| 258 | define_one_state_ro(power, show_state_power_usage); | 282 | define_one_state_ro(power, show_state_power_usage); |
| 259 | define_one_state_ro(usage, show_state_usage); | 283 | define_one_state_ro(usage, show_state_usage); |
| 260 | define_one_state_ro(time, show_state_time); | 284 | define_one_state_ro(time, show_state_time); |
| 285 | define_one_state_rw(disable, show_state_disable, store_state_disable); | ||
| 261 | 286 | ||
| 262 | static struct attribute *cpuidle_state_default_attrs[] = { | 287 | static struct attribute *cpuidle_state_default_attrs[] = { |
| 263 | &attr_name.attr, | 288 | &attr_name.attr, |
| @@ -266,6 +291,7 @@ static struct attribute *cpuidle_state_default_attrs[] = { | |||
| 266 | &attr_power.attr, | 291 | &attr_power.attr, |
| 267 | &attr_usage.attr, | 292 | &attr_usage.attr, |
| 268 | &attr_time.attr, | 293 | &attr_time.attr, |
| 294 | &attr_disable.attr, | ||
| 269 | NULL | 295 | NULL |
| 270 | }; | 296 | }; |
| 271 | 297 | ||
| @@ -287,8 +313,22 @@ static ssize_t cpuidle_state_show(struct kobject * kobj, | |||
| 287 | return ret; | 313 | return ret; |
| 288 | } | 314 | } |
| 289 | 315 | ||
| 316 | static ssize_t cpuidle_state_store(struct kobject *kobj, | ||
| 317 | struct attribute *attr, const char *buf, size_t size) | ||
| 318 | { | ||
| 319 | int ret = -EIO; | ||
| 320 | struct cpuidle_state *state = kobj_to_state(kobj); | ||
| 321 | struct cpuidle_state_attr *cattr = attr_to_stateattr(attr); | ||
| 322 | |||
| 323 | if (cattr->store) | ||
| 324 | ret = cattr->store(state, buf, size); | ||
| 325 | |||
| 326 | return ret; | ||
| 327 | } | ||
| 328 | |||
| 290 | static const struct sysfs_ops cpuidle_state_sysfs_ops = { | 329 | static const struct sysfs_ops cpuidle_state_sysfs_ops = { |
| 291 | .show = cpuidle_state_show, | 330 | .show = cpuidle_state_show, |
| 331 | .store = cpuidle_state_store, | ||
| 292 | }; | 332 | }; |
| 293 | 333 | ||
| 294 | static void cpuidle_state_sysfs_release(struct kobject *kobj) | 334 | static void cpuidle_state_sysfs_release(struct kobject *kobj) |
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 927db28a2a4c..ca4e4983773f 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h | |||
| @@ -46,6 +46,7 @@ struct cpuidle_state { | |||
| 46 | unsigned int exit_latency; /* in US */ | 46 | unsigned int exit_latency; /* in US */ |
| 47 | unsigned int power_usage; /* in mW */ | 47 | unsigned int power_usage; /* in mW */ |
| 48 | unsigned int target_residency; /* in US */ | 48 | unsigned int target_residency; /* in US */ |
| 49 | unsigned int disable; | ||
| 49 | 50 | ||
| 50 | int (*enter) (struct cpuidle_device *dev, | 51 | int (*enter) (struct cpuidle_device *dev, |
| 51 | struct cpuidle_driver *drv, | 52 | struct cpuidle_driver *drv, |
