xref: /linux/tools/power/cpupower/utils/cpupower-set.c (revision 1ccd4b7bfdcfcc8cc7ffc4a9c11d3ac5b6da8ca0)
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 }
154