diff options
Diffstat (limited to 'tools/power/cpupower/utils/cpupower-info.c')
-rw-r--r-- | tools/power/cpupower/utils/cpupower-info.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/tools/power/cpupower/utils/cpupower-info.c b/tools/power/cpupower/utils/cpupower-info.c new file mode 100644 index 00000000000..3f68632c28c --- /dev/null +++ b/tools/power/cpupower/utils/cpupower-info.c @@ -0,0 +1,135 @@ +/* + * (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc. + * + * Licensed under the terms of the GNU GPL License version 2. + */ + + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <getopt.h> + +#include <cpufreq.h> +#include "helpers/helpers.h" +#include "helpers/sysfs.h" + +static struct option set_opts[] = { + { .name = "perf-bias", .has_arg = optional_argument, .flag = NULL, .val = 'b'}, + { .name = "sched-mc", .has_arg = optional_argument, .flag = NULL, .val = 'm'}, + { .name = "sched-smt", .has_arg = optional_argument, .flag = NULL, .val = 's'}, + { }, +}; + +static void print_wrong_arg_exit(void) +{ + printf(_("invalid or unknown argument\n")); + exit(EXIT_FAILURE); +} + +int cmd_info(int argc, char **argv) +{ + extern char *optarg; + extern int optind, opterr, optopt; + unsigned int cpu; + + union { + struct { + int sched_mc:1; + int sched_smt:1; + int perf_bias:1; + }; + int params; + } params = {}; + int ret = 0; + + setlocale(LC_ALL, ""); + textdomain(PACKAGE); + + /* parameter parsing */ + while ((ret = getopt_long(argc, argv, "msb", set_opts, NULL)) != -1) { + switch (ret) { + case 'b': + if (params.perf_bias) + print_wrong_arg_exit(); + params.perf_bias = 1; + break; + case 'm': + if (params.sched_mc) + print_wrong_arg_exit(); + params.sched_mc = 1; + break; + case 's': + if (params.sched_smt) + print_wrong_arg_exit(); + params.sched_smt = 1; + break; + default: + print_wrong_arg_exit(); + } + }; + + if (!params.params) + params.params = 0x7; + + /* Default is: show output of CPU 0 only */ + if (bitmask_isallclear(cpus_chosen)) + bitmask_setbit(cpus_chosen, 0); + + if (params.sched_mc) { + ret = sysfs_get_sched("mc"); + printf(_("System's multi core scheduler setting: ")); + if (ret < 0) + /* if sysfs file is missing it's: errno == ENOENT */ + printf(_("not supported\n")); + else + printf("%d\n", ret); + } + if (params.sched_smt) { + ret = sysfs_get_sched("smt"); + printf(_("System's thread sibling scheduler setting: ")); + if (ret < 0) + /* if sysfs file is missing it's: errno == ENOENT */ + printf(_("not supported\n")); + else + printf("%d\n", ret); + } + + /* Add more per cpu options here */ + if (!params.perf_bias) + return ret; + + if (params.perf_bias) { + if (!run_as_root) { + params.perf_bias = 0; + printf(_("Intel's performance bias setting needs root privileges\n")); + } else if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS)) { + printf(_("System does not support Intel's performance" + " bias setting\n")); + params.perf_bias = 0; + } + } + + /* loop over CPUs */ + for (cpu = bitmask_first(cpus_chosen); + cpu <= bitmask_last(cpus_chosen); cpu++) { + + if (!bitmask_isbitset(cpus_chosen, cpu) || + cpufreq_cpu_exists(cpu)) + continue; + + printf(_("analyzing CPU %d:\n"), cpu); + + if (params.perf_bias) { + ret = msr_intel_get_perf_bias(cpu); + if (ret < 0) { + printf(_("Could not read perf-bias value\n")); + break; + } else + printf(_("perf-bias: %d\n"), ret); + } + } + return ret; +} |