cpupower: Introduce idle-set subcommand and C-state enabling/disabling
authorThomas Renninger <trenn@suse.de>
Fri, 28 Jun 2013 13:34:31 +0000 (15:34 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 4 Jul 2013 23:52:19 +0000 (01:52 +0200)
Example:

cpupower idle-set -d 3

will disable C-state 3 on all processors (set commands are active on
all CPUs by default), same as:

cpupower -c all idle-set -d 3

Signed-off-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
tools/power/cpupower/Makefile
tools/power/cpupower/man/cpupower-monitor.1
tools/power/cpupower/utils/builtin.h
tools/power/cpupower/utils/cpuidle-info.c
tools/power/cpupower/utils/cpuidle-set.c [new file with mode: 0644]
tools/power/cpupower/utils/cpupower.c

index d875a74a3bdf874def9f54780b00f0ecd5528e56..ce17f30f04ba142d27b25fee1b8d0f0b61430fff 100644 (file)
@@ -131,7 +131,8 @@ UTIL_OBJS =  utils/helpers/amd.o utils/helpers/topology.o utils/helpers/msr.o \
        utils/idle_monitor/amd_fam14h_idle.o utils/idle_monitor/cpuidle_sysfs.o \
        utils/idle_monitor/mperf_monitor.o utils/idle_monitor/cpupower-monitor.o \
        utils/cpupower.o utils/cpufreq-info.o utils/cpufreq-set.o \
-       utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o
+       utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o \
+       utils/cpuidle-set.o
 
 UTIL_SRC := $(UTIL_OBJS:.o=.c)
 
index e01c35d13b6ed0c98c8afb1db3f9b21375aebd9b..914cbb9d9cd007fa8c3c8b9202991e5d51c9c648 100644 (file)
@@ -110,13 +110,21 @@ May work poorly on Linux-2.6.20 through 2.6.29, as the \fBacpi-cpufreq \fP
 kernel frequency driver periodically cleared aperf/mperf registers in those
 kernels.
 
-.SS "Nehalem" "SandyBridge"
+.SS "Nehalem" "SandyBridge" "HaswellExtended"
 Intel Core and Package sleep state counters.
 Threads (hyperthreaded cores) may not be able to enter deeper core states if
 its sibling is utilized.
 Deepest package sleep states may in reality show up as machine/platform wide
 sleep states and can only be entered if all cores are idle. Look up Intel
 manuals (some are provided in the References section) for further details.
+The monitors are named after the CPU family where the sleep state capabilities
+got introduced and may not match exactly the CPU name of the platform.
+For example an IvyBridge processor has sleep state capabilities which got
+introduced in Nehalem and SandyBridge processor families.
+Thus on an IvyBridge processor one will get Nehalem and SandyBridge sleep
+state monitors.
+HaswellExtended extra package sleep state capabilities are available only in a
+specific Haswell (family 0x45) and probably also other future processors.
 
 .SS "Fam_12h" "Fam_14h"
 AMD laptop and desktop processor (family 12h and 14h) sleep state counters.
index c10496fbe3c629c270d6b9ab406f587c8b4736c6..2284c8ea4e2a51262e33897087ce5dace9acdeeb 100644 (file)
@@ -5,6 +5,7 @@ extern int cmd_set(int argc, const char **argv);
 extern int cmd_info(int argc, const char **argv);
 extern int cmd_freq_set(int argc, const char **argv);
 extern int cmd_freq_info(int argc, const char **argv);
+extern int cmd_idle_set(int argc, const char **argv);
 extern int cmd_idle_info(int argc, const char **argv);
 extern int cmd_monitor(int argc, const char **argv);
 
index edd5dba3e2499f19a8caaa981cba127d38b3e41c..75e66de7e7a7fc9934ec005667c6857cff42ff04 100644 (file)
@@ -48,10 +48,14 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
                return;
 
        for (idlestate = 0; idlestate < idlestates; idlestate++) {
+               int disabled = sysfs_is_idlestate_disabled(cpu, idlestate);
+               /* Disabled interface not supported on older kernels */
+               if (disabled < 0)
+                       disabled = 0;
                tmp = sysfs_get_idlestate_name(cpu, idlestate);
                if (!tmp)
                        continue;
-               printf("%s:\n", tmp);
+               printf("%s%s:\n", tmp, (disabled) ? " (DISABLED) " : "");
                free(tmp);
 
                tmp = sysfs_get_idlestate_desc(cpu, idlestate);
diff --git a/tools/power/cpupower/utils/cpuidle-set.c b/tools/power/cpupower/utils/cpuidle-set.c
new file mode 100644 (file)
index 0000000..c78141c
--- /dev/null
@@ -0,0 +1,118 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <getopt.h>
+
+#include "cpufreq.h"
+#include "helpers/helpers.h"
+#include "helpers/sysfs.h"
+
+static struct option info_opts[] = {
+       { .name = "disable",    .has_arg = required_argument,   .flag = NULL,   .val = 'd'},
+       { .name = "enable",     .has_arg = required_argument,   .flag = NULL,   .val = 'e'},
+       { },
+};
+
+
+int cmd_idle_set(int argc, char **argv)
+{
+       extern char *optarg;
+       extern int optind, opterr, optopt;
+       int ret = 0, cont = 1, param = 0, idlestate = 0;
+       unsigned int cpu = 0;
+
+       do {
+               ret = getopt_long(argc, argv, "d:e:", info_opts, NULL);
+               if (ret == -1)
+                       break;
+               switch (ret) {
+               case '?':
+                       param = '?';
+                       cont = 0;
+                       break;
+               case 'd':
+                       if (param) {
+                               param = -1;
+                               cont = 0;
+                               break;
+                       }
+                       param = ret;
+                       idlestate = atoi(optarg);
+                       break;
+               case 'e':
+                       if (param) {
+                               param = -1;
+                               cont = 0;
+                               break;
+                       }
+                       param = ret;
+                       idlestate = atoi(optarg);
+                       break;
+               case -1:
+                       cont = 0;
+                       break;
+               }
+       } while (cont);
+
+       switch (param) {
+       case -1:
+               printf(_("You can't specify more than one "
+                        "output-specific argument\n"));
+               exit(EXIT_FAILURE);
+       case '?':
+               printf(_("invalid or unknown argument\n"));
+               exit(EXIT_FAILURE);
+       }
+
+       /* Default is: set all CPUs */
+       if (bitmask_isallclear(cpus_chosen))
+               bitmask_setall(cpus_chosen);
+
+       for (cpu = bitmask_first(cpus_chosen);
+            cpu <= bitmask_last(cpus_chosen); cpu++) {
+
+               if (!bitmask_isbitset(cpus_chosen, cpu))
+                       continue;
+
+               switch (param) {
+
+               case 'd':
+                       ret = sysfs_idlestate_disable(cpu, idlestate, 1);
+                       if (ret == 0)
+               printf(_("Idlestate %u disabled on CPU %u\n"),  idlestate, cpu);
+                       else if (ret == -1)
+               printf(_("Idlestate %u not available on CPU %u\n"),
+                      idlestate, cpu);
+                       else if (ret == -2)
+               printf(_("Idlestate disabling not supported by kernel\n"));
+                       else
+               printf(_("Idlestate %u not disabled on CPU %u\n"),
+                      idlestate, cpu);
+                       break;
+               case 'e':
+                       ret = sysfs_idlestate_disable(cpu, idlestate, 0);
+                       if (ret == 0)
+               printf(_("Idlestate %u enabled on CPU %u\n"),  idlestate, cpu);
+                       else if (ret == -1)
+               printf(_("Idlestate %u not available on CPU %u\n"),
+                      idlestate, cpu);
+                       else if (ret == -2)
+               printf(_("Idlestate enabling not supported by kernel\n"));
+                       else
+               printf(_("Idlestate %u not enabled on CPU %u\n"),
+                      idlestate, cpu);
+                       break;
+               default:
+                       /* Not reachable with proper args checking */
+                       printf(_("Invalid or unknown argument\n"));
+                       exit(EXIT_FAILURE);
+                       break;
+               }
+       }
+       return EXIT_SUCCESS;
+}
index 52bee591c1c565f3bf9760505c7a824122d2537c..7efc570ffbaaeadf40347880d3f2c0e7a7799f8d 100644 (file)
 #include "helpers/helpers.h"
 #include "helpers/bitmask.h"
 
-struct cmd_struct {
-       const char *cmd;
-       int (*main)(int, const char **);
-       int needs_root;
-};
-
 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
 
 static int cmd_help(int argc, const char **argv);
@@ -43,10 +37,17 @@ int be_verbose;
 
 static void print_help(void);
 
+struct cmd_struct {
+       const char *cmd;
+       int (*main)(int, const char **);
+       int needs_root;
+};
+
 static struct cmd_struct commands[] = {
        { "frequency-info",     cmd_freq_info,  0       },
        { "frequency-set",      cmd_freq_set,   1       },
        { "idle-info",          cmd_idle_info,  0       },
+       { "idle-set",           cmd_idle_set,   1       },
        { "set",                cmd_set,        1       },
        { "info",               cmd_info,       0       },
        { "monitor",            cmd_monitor,    0       },