xref: /openbmc/linux/tools/power/cpupower/utils/cpupower-set.c (revision df8776b03689987e3239f3c010b6dc6ab4185d30)
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 	{ },
24 };
25 
26 static void print_wrong_arg_exit(void)
27 {
28 	printf(_("invalid or unknown argument\n"));
29 	exit(EXIT_FAILURE);
30 }
31 
32 int cmd_set(int argc, char **argv)
33 {
34 	extern char *optarg;
35 	extern int optind, opterr, optopt;
36 	unsigned int cpu;
37 	struct utsname uts;
38 
39 	union {
40 		struct {
41 			int perf_bias:1;
42 			int epp:1;
43 			int mode:1;
44 		};
45 		int params;
46 	} params;
47 	int perf_bias = 0;
48 	int ret = 0;
49 	char epp[30], mode[20];
50 
51 	ret = uname(&uts);
52 	if (!ret && (!strcmp(uts.machine, "ppc64le") ||
53 		     !strcmp(uts.machine, "ppc64"))) {
54 		fprintf(stderr, _("Subcommand not supported on POWER.\n"));
55 		return ret;
56 	}
57 
58 	setlocale(LC_ALL, "");
59 	textdomain(PACKAGE);
60 
61 	params.params = 0;
62 	/* parameter parsing */
63 	while ((ret = getopt_long(argc, argv, "b:e:m:",
64 						set_opts, NULL)) != -1) {
65 		switch (ret) {
66 		case 'b':
67 			if (params.perf_bias)
68 				print_wrong_arg_exit();
69 			perf_bias = atoi(optarg);
70 			if (perf_bias < 0 || perf_bias > 15) {
71 				printf(_("--perf-bias param out "
72 					 "of range [0-%d]\n"), 15);
73 				print_wrong_arg_exit();
74 			}
75 			params.perf_bias = 1;
76 			break;
77 		case 'e':
78 			if (params.epp)
79 				print_wrong_arg_exit();
80 			if (sscanf(optarg, "%29s", epp) != 1) {
81 				print_wrong_arg_exit();
82 				return -EINVAL;
83 			}
84 			params.epp = 1;
85 			break;
86 		case 'm':
87 			if (cpupower_cpu_info.vendor != X86_VENDOR_AMD)
88 				print_wrong_arg_exit();
89 			if (params.mode)
90 				print_wrong_arg_exit();
91 			if (sscanf(optarg, "%19s", mode) != 1) {
92 				print_wrong_arg_exit();
93 				return -EINVAL;
94 			}
95 			params.mode = 1;
96 			break;
97 		default:
98 			print_wrong_arg_exit();
99 		}
100 	}
101 
102 	if (!params.params)
103 		print_wrong_arg_exit();
104 
105 	if (params.mode) {
106 		ret = cpupower_set_amd_pstate_mode(mode);
107 		if (ret)
108 			fprintf(stderr, "Error setting mode\n");
109 	}
110 
111 	/* Default is: set all CPUs */
112 	if (bitmask_isallclear(cpus_chosen))
113 		bitmask_setall(cpus_chosen);
114 
115 	/* loop over CPUs */
116 	for (cpu = bitmask_first(cpus_chosen);
117 	     cpu <= bitmask_last(cpus_chosen); cpu++) {
118 
119 		if (!bitmask_isbitset(cpus_chosen, cpu))
120 			continue;
121 
122 		if (sysfs_is_cpu_online(cpu) != 1){
123 			fprintf(stderr, _("Cannot set values on CPU %d:"), cpu);
124 			fprintf(stderr, _(" *is offline\n"));
125 			continue;
126 		}
127 
128 		if (params.perf_bias) {
129 			ret = cpupower_intel_set_perf_bias(cpu, perf_bias);
130 			if (ret) {
131 				fprintf(stderr, _("Error setting perf-bias "
132 						  "value on CPU %d\n"), cpu);
133 				break;
134 			}
135 		}
136 
137 		if (params.epp) {
138 			ret = cpupower_set_epp(cpu, epp);
139 			if (ret) {
140 				fprintf(stderr,
141 					"Error setting epp value on CPU %d\n", cpu);
142 				break;
143 			}
144 		}
145 
146 	}
147 	return ret;
148 }
149