Merge branch 'linus' into perf/urgent
[pandora-kernel.git] / tools / power / cpupower / utils / cpupower-set.c
1 /*
2  *  (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3  *
4  *  Licensed under the terms of the GNU GPL License version 2.
5  */
6
7
8 #include <unistd.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <errno.h>
12 #include <string.h>
13 #include <getopt.h>
14
15 #include <cpufreq.h>
16 #include "helpers/helpers.h"
17 #include "helpers/sysfs.h"
18 #include "helpers/bitmask.h"
19
20 void set_help(void)
21 {
22         printf(_("Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"));
23         printf(_("Options:\n"));
24         printf(_("  -b, --perf-bias [VAL]    Sets CPU's power vs performance policy on some\n"
25                "                           Intel models [0-15], see manpage for details\n"));
26         printf(_("  -m, --sched-mc  [VAL]    Sets the kernel's multi core scheduler policy.\n"));
27         printf(_("  -s, --sched-smt [VAL]    Sets the kernel's thread sibling scheduler policy.\n"));
28         printf(_("  -h, --help               Prints out this screen\n"));
29         printf("\n");
30 }
31
32 static struct option set_opts[] = {
33         { .name = "perf-bias",  .has_arg = optional_argument,   .flag = NULL,   .val = 'b'},
34         { .name = "sched-mc",   .has_arg = optional_argument,   .flag = NULL,   .val = 'm'},
35         { .name = "sched-smt",  .has_arg = optional_argument,   .flag = NULL,   .val = 's'},
36         { .name = "help",       .has_arg = no_argument,         .flag = NULL,   .val = 'h'},
37         { },
38 };
39
40 static void print_wrong_arg_exit(void)
41 {
42         printf(_("invalid or unknown argument\n"));
43         set_help();
44         exit(EXIT_FAILURE);
45 }
46
47 int cmd_set(int argc, char **argv)
48 {
49         extern char *optarg;
50         extern int optind, opterr, optopt;
51         unsigned int cpu;
52
53         union {
54                 struct {
55                         int sched_mc:1;
56                         int sched_smt:1;
57                         int perf_bias:1;
58                 };
59                 int params;
60         } params;
61         int sched_mc = 0, sched_smt = 0, perf_bias = 0;
62         int ret = 0;
63
64         setlocale(LC_ALL, "");
65         textdomain(PACKAGE);
66
67         params.params = 0;
68         /* parameter parsing */
69         while ((ret = getopt_long(argc, argv, "m:s:b:h",
70                                                 set_opts, NULL)) != -1) {
71                 switch (ret) {
72                 case 'h':
73                         set_help();
74                         return 0;
75                 case 'b':
76                         if (params.perf_bias)
77                                 print_wrong_arg_exit();
78                         perf_bias = atoi(optarg);
79                         if (perf_bias < 0 || perf_bias > 15) {
80                                 printf(_("--perf-bias param out "
81                                          "of range [0-%d]\n"), 15);
82                                 print_wrong_arg_exit();
83                         }
84                         params.perf_bias = 1;
85                         break;
86                 case 'm':
87                         if (params.sched_mc)
88                                 print_wrong_arg_exit();
89                         sched_mc = atoi(optarg);
90                         if (sched_mc < 0 || sched_mc > 2) {
91                                 printf(_("--sched-mc param out "
92                                          "of range [0-%d]\n"), 2);
93                                 print_wrong_arg_exit();
94                         }
95                         params.sched_mc = 1;
96                         break;
97                 case 's':
98                         if (params.sched_smt)
99                                 print_wrong_arg_exit();
100                         sched_smt = atoi(optarg);
101                         if (sched_smt < 0 || sched_smt > 2) {
102                                 printf(_("--sched-smt param out "
103                                          "of range [0-%d]\n"), 2);
104                                 print_wrong_arg_exit();
105                         }
106                         params.sched_smt = 1;
107                         break;
108                 default:
109                         print_wrong_arg_exit();
110                 }
111         };
112
113         if (!params.params) {
114                 set_help();
115                 return -EINVAL;
116         }
117
118         if (params.sched_mc) {
119                 ret = sysfs_set_sched("mc", sched_mc);
120                 if (ret)
121                         fprintf(stderr, _("Error setting sched-mc %s\n"),
122                                 (ret == -ENODEV) ? "not supported" : "");
123         }
124         if (params.sched_smt) {
125                 ret = sysfs_set_sched("smt", sched_smt);
126                 if (ret)
127                         fprintf(stderr, _("Error setting sched-smt %s\n"),
128                                 (ret == -ENODEV) ? "not supported" : "");
129         }
130
131         /* Default is: set all CPUs */
132         if (bitmask_isallclear(cpus_chosen))
133                 bitmask_setall(cpus_chosen);
134
135         /* loop over CPUs */
136         for (cpu = bitmask_first(cpus_chosen);
137              cpu <= bitmask_last(cpus_chosen); cpu++) {
138
139                 if (!bitmask_isbitset(cpus_chosen, cpu) ||
140                     cpufreq_cpu_exists(cpu))
141                         continue;
142
143                 if (params.perf_bias) {
144                         ret = msr_intel_set_perf_bias(cpu, perf_bias);
145                         if (ret) {
146                                 fprintf(stderr, _("Error setting perf-bias "
147                                                   "value on CPU %d\n"), cpu);
148                                 break;
149                         }
150                 }
151         }
152         return ret;
153 }