1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
4  */
5 
6 
7 #include <unistd.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <errno.h>
11 #include <string.h>
12 #include <getopt.h>
13 #include <sys/utsname.h>
14 
15 #include "helpers/helpers.h"
16 #include "helpers/sysfs.h"
17 #include "helpers/bitmask.h"
18 
19 static struct option set_opts[] = {
20 	{"perf-bias", required_argument, NULL, 'b'},
21 	{"epp", required_argument, NULL, 'e'},
22 	{"amd-pstate-mode", required_argument, NULL, 'm'},
23 	{"turbo-boost", required_argument, NULL, 't'},
24 	{ },
25 };
26 
print_wrong_arg_exit(void)27 static void print_wrong_arg_exit(void)
28 {
29 	printf(_("invalid or unknown argument\n"));
30 	exit(EXIT_FAILURE);
31 }
32 
cmd_set(int argc,char ** argv)33 int cmd_set(int argc, char **argv)
34 {
35 	extern char *optarg;
36 	extern int optind, opterr, optopt;
37 	unsigned int cpu;
38 	struct utsname uts;
39 
40 	union {
41 		struct {
42 			int perf_bias:1;
43 			int epp:1;
44 			int mode:1;
45 			int turbo_boost:1;
46 		};
47 		int params;
48 	} params;
49 	int perf_bias = 0, turbo_boost = 1;
50 	int ret = 0;
51 	char epp[30], mode[20];
52 
53 	ret = uname(&uts);
54 	if (!ret && (!strcmp(uts.machine, "ppc64le") ||
55 		     !strcmp(uts.machine, "ppc64"))) {
56 		fprintf(stderr, _("Subcommand not supported on POWER.\n"));
57 		return ret;
58 	}
59 
60 	setlocale(LC_ALL, "");
61 	textdomain(PACKAGE);
62 
63 	params.params = 0;
64 	/* parameter parsing */
65 	while ((ret = getopt_long(argc, argv, "b:e:m:",
66 						set_opts, NULL)) != -1) {
67 		switch (ret) {
68 		case 'b':
69 			if (params.perf_bias)
70 				print_wrong_arg_exit();
71 			perf_bias = atoi(optarg);
72 			if (perf_bias < 0 || perf_bias > 15) {
73 				printf(_("--perf-bias param out "
74 					 "of range [0-%d]\n"), 15);
75 				print_wrong_arg_exit();
76 			}
77 			params.perf_bias = 1;
78 			break;
79 		case 'e':
80 			if (params.epp)
81 				print_wrong_arg_exit();
82 			if (sscanf(optarg, "%29s", epp) != 1) {
83 				print_wrong_arg_exit();
84 				return -EINVAL;
85 			}
86 			params.epp = 1;
87 			break;
88 		case 'm':
89 			if (cpupower_cpu_info.vendor != X86_VENDOR_AMD)
90 				print_wrong_arg_exit();
91 			if (params.mode)
92 				print_wrong_arg_exit();
93 			if (sscanf(optarg, "%19s", mode) != 1) {
94 				print_wrong_arg_exit();
95 				return -EINVAL;
96 			}
97 			params.mode = 1;
98 			break;
99 		case 't':
100 			if (params.turbo_boost)
101 				print_wrong_arg_exit();
102 			turbo_boost = atoi(optarg);
103 			if (turbo_boost < 0 || turbo_boost > 1) {
104 				printf("--turbo-boost param out of range [0-1]\n");
105 				print_wrong_arg_exit();
106 			}
107 			params.turbo_boost = 1;
108 			break;
109 
110 
111 		default:
112 			print_wrong_arg_exit();
113 		}
114 	}
115 
116 	if (!params.params)
117 		print_wrong_arg_exit();
118 
119 	if (params.mode) {
120 		ret = cpupower_set_amd_pstate_mode(mode);
121 		if (ret)
122 			fprintf(stderr, "Error setting mode\n");
123 	}
124 
125 	if (params.turbo_boost) {
126 		ret = cpupower_set_turbo_boost(turbo_boost);
127 		if (ret)
128 			fprintf(stderr, "Error setting turbo-boost\n");
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 			continue;
141 
142 		if (sysfs_is_cpu_online(cpu) != 1){
143 			fprintf(stderr, _("Cannot set values on CPU %d:"), cpu);
144 			fprintf(stderr, _(" *is offline\n"));
145 			continue;
146 		}
147 
148 		if (params.perf_bias) {
149 			ret = cpupower_intel_set_perf_bias(cpu, perf_bias);
150 			if (ret) {
151 				fprintf(stderr, _("Error setting perf-bias "
152 						  "value on CPU %d\n"), cpu);
153 				break;
154 			}
155 		}
156 
157 		if (params.epp) {
158 			ret = cpupower_set_epp(cpu, epp);
159 			if (ret) {
160 				fprintf(stderr,
161 					"Error setting epp value on CPU %d\n", cpu);
162 				break;
163 			}
164 		}
165 
166 	}
167 	return ret;
168 }
169