xref: /openbmc/linux/tools/power/cpupower/utils/cpupower-set.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
14f19048fSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
27fe2f639SDominik Brodowski /*
37fe2f639SDominik Brodowski  *  (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
47fe2f639SDominik Brodowski  */
57fe2f639SDominik Brodowski 
67fe2f639SDominik Brodowski 
77fe2f639SDominik Brodowski #include <unistd.h>
87fe2f639SDominik Brodowski #include <stdio.h>
97fe2f639SDominik Brodowski #include <stdlib.h>
107fe2f639SDominik Brodowski #include <errno.h>
117fe2f639SDominik Brodowski #include <string.h>
127fe2f639SDominik Brodowski #include <getopt.h>
13d80a4ac2SAbhishek Goel #include <sys/utsname.h>
147fe2f639SDominik Brodowski 
157fe2f639SDominik Brodowski #include "helpers/helpers.h"
167fe2f639SDominik Brodowski #include "helpers/sysfs.h"
177fe2f639SDominik Brodowski #include "helpers/bitmask.h"
187fe2f639SDominik Brodowski 
197fe2f639SDominik Brodowski static struct option set_opts[] = {
2057ab3b08SSriram Raghunathan 	{"perf-bias", required_argument, NULL, 'b'},
21f2ab5557SWyes Karny 	{"epp", required_argument, NULL, 'e'},
22df8776b0SWyes Karny 	{"amd-pstate-mode", required_argument, NULL, 'm'},
23*eb426fc6SWyes Karny 	{"turbo-boost", required_argument, NULL, 't'},
247fe2f639SDominik Brodowski 	{ },
257fe2f639SDominik Brodowski };
267fe2f639SDominik Brodowski 
print_wrong_arg_exit(void)277fe2f639SDominik Brodowski static void print_wrong_arg_exit(void)
287fe2f639SDominik Brodowski {
297fe2f639SDominik Brodowski 	printf(_("invalid or unknown argument\n"));
307fe2f639SDominik Brodowski 	exit(EXIT_FAILURE);
317fe2f639SDominik Brodowski }
327fe2f639SDominik Brodowski 
cmd_set(int argc,char ** argv)337fe2f639SDominik Brodowski int cmd_set(int argc, char **argv)
347fe2f639SDominik Brodowski {
357fe2f639SDominik Brodowski 	extern char *optarg;
367fe2f639SDominik Brodowski 	extern int optind, opterr, optopt;
377fe2f639SDominik Brodowski 	unsigned int cpu;
38d80a4ac2SAbhishek Goel 	struct utsname uts;
397fe2f639SDominik Brodowski 
407fe2f639SDominik Brodowski 	union {
417fe2f639SDominik Brodowski 		struct {
427fe2f639SDominik Brodowski 			int perf_bias:1;
43f2ab5557SWyes Karny 			int epp:1;
44df8776b0SWyes Karny 			int mode:1;
45*eb426fc6SWyes Karny 			int turbo_boost:1;
467fe2f639SDominik Brodowski 		};
477fe2f639SDominik Brodowski 		int params;
487fe2f639SDominik Brodowski 	} params;
49*eb426fc6SWyes Karny 	int perf_bias = 0, turbo_boost = 1;
507fe2f639SDominik Brodowski 	int ret = 0;
51df8776b0SWyes Karny 	char epp[30], mode[20];
527fe2f639SDominik Brodowski 
53d80a4ac2SAbhishek Goel 	ret = uname(&uts);
54d80a4ac2SAbhishek Goel 	if (!ret && (!strcmp(uts.machine, "ppc64le") ||
55d80a4ac2SAbhishek Goel 		     !strcmp(uts.machine, "ppc64"))) {
56d80a4ac2SAbhishek Goel 		fprintf(stderr, _("Subcommand not supported on POWER.\n"));
57d80a4ac2SAbhishek Goel 		return ret;
58d80a4ac2SAbhishek Goel 	}
59d80a4ac2SAbhishek Goel 
607fe2f639SDominik Brodowski 	setlocale(LC_ALL, "");
617fe2f639SDominik Brodowski 	textdomain(PACKAGE);
627fe2f639SDominik Brodowski 
637fe2f639SDominik Brodowski 	params.params = 0;
647fe2f639SDominik Brodowski 	/* parameter parsing */
65df8776b0SWyes Karny 	while ((ret = getopt_long(argc, argv, "b:e:m:",
66a1ce5ba2SDominik Brodowski 						set_opts, NULL)) != -1) {
677fe2f639SDominik Brodowski 		switch (ret) {
687fe2f639SDominik Brodowski 		case 'b':
697fe2f639SDominik Brodowski 			if (params.perf_bias)
707fe2f639SDominik Brodowski 				print_wrong_arg_exit();
717fe2f639SDominik Brodowski 			perf_bias = atoi(optarg);
727fe2f639SDominik Brodowski 			if (perf_bias < 0 || perf_bias > 15) {
737fe2f639SDominik Brodowski 				printf(_("--perf-bias param out "
747fe2f639SDominik Brodowski 					 "of range [0-%d]\n"), 15);
757fe2f639SDominik Brodowski 				print_wrong_arg_exit();
767fe2f639SDominik Brodowski 			}
777fe2f639SDominik Brodowski 			params.perf_bias = 1;
787fe2f639SDominik Brodowski 			break;
79f2ab5557SWyes Karny 		case 'e':
80f2ab5557SWyes Karny 			if (params.epp)
81f2ab5557SWyes Karny 				print_wrong_arg_exit();
82f2ab5557SWyes Karny 			if (sscanf(optarg, "%29s", epp) != 1) {
83f2ab5557SWyes Karny 				print_wrong_arg_exit();
84f2ab5557SWyes Karny 				return -EINVAL;
85f2ab5557SWyes Karny 			}
86f2ab5557SWyes Karny 			params.epp = 1;
87f2ab5557SWyes Karny 			break;
88df8776b0SWyes Karny 		case 'm':
89df8776b0SWyes Karny 			if (cpupower_cpu_info.vendor != X86_VENDOR_AMD)
90df8776b0SWyes Karny 				print_wrong_arg_exit();
91df8776b0SWyes Karny 			if (params.mode)
92df8776b0SWyes Karny 				print_wrong_arg_exit();
93df8776b0SWyes Karny 			if (sscanf(optarg, "%19s", mode) != 1) {
94df8776b0SWyes Karny 				print_wrong_arg_exit();
95df8776b0SWyes Karny 				return -EINVAL;
96df8776b0SWyes Karny 			}
97df8776b0SWyes Karny 			params.mode = 1;
98df8776b0SWyes Karny 			break;
99*eb426fc6SWyes Karny 		case 't':
100*eb426fc6SWyes Karny 			if (params.turbo_boost)
101*eb426fc6SWyes Karny 				print_wrong_arg_exit();
102*eb426fc6SWyes Karny 			turbo_boost = atoi(optarg);
103*eb426fc6SWyes Karny 			if (turbo_boost < 0 || turbo_boost > 1) {
104*eb426fc6SWyes Karny 				printf("--turbo-boost param out of range [0-1]\n");
105*eb426fc6SWyes Karny 				print_wrong_arg_exit();
106*eb426fc6SWyes Karny 			}
107*eb426fc6SWyes Karny 			params.turbo_boost = 1;
108*eb426fc6SWyes Karny 			break;
109*eb426fc6SWyes Karny 
110*eb426fc6SWyes Karny 
1117fe2f639SDominik Brodowski 		default:
1127fe2f639SDominik Brodowski 			print_wrong_arg_exit();
1137fe2f639SDominik Brodowski 		}
1147b0bf99bSZou Wei 	}
1157fe2f639SDominik Brodowski 
116498ca793SDominik Brodowski 	if (!params.params)
117498ca793SDominik Brodowski 		print_wrong_arg_exit();
1187fe2f639SDominik Brodowski 
119df8776b0SWyes Karny 	if (params.mode) {
120df8776b0SWyes Karny 		ret = cpupower_set_amd_pstate_mode(mode);
121df8776b0SWyes Karny 		if (ret)
122df8776b0SWyes Karny 			fprintf(stderr, "Error setting mode\n");
123df8776b0SWyes Karny 	}
124df8776b0SWyes Karny 
125*eb426fc6SWyes Karny 	if (params.turbo_boost) {
126*eb426fc6SWyes Karny 		ret = cpupower_set_turbo_boost(turbo_boost);
127*eb426fc6SWyes Karny 		if (ret)
128*eb426fc6SWyes Karny 			fprintf(stderr, "Error setting turbo-boost\n");
129*eb426fc6SWyes Karny 	}
130*eb426fc6SWyes Karny 
1317fe2f639SDominik Brodowski 	/* Default is: set all CPUs */
1327fe2f639SDominik Brodowski 	if (bitmask_isallclear(cpus_chosen))
1337fe2f639SDominik Brodowski 		bitmask_setall(cpus_chosen);
1347fe2f639SDominik Brodowski 
1357fe2f639SDominik Brodowski 	/* loop over CPUs */
1367fe2f639SDominik Brodowski 	for (cpu = bitmask_first(cpus_chosen);
1377fe2f639SDominik Brodowski 	     cpu <= bitmask_last(cpus_chosen); cpu++) {
1387fe2f639SDominik Brodowski 
139ce512b84SThomas Renninger 		if (!bitmask_isbitset(cpus_chosen, cpu))
1407fe2f639SDominik Brodowski 			continue;
1417fe2f639SDominik Brodowski 
142ce512b84SThomas Renninger 		if (sysfs_is_cpu_online(cpu) != 1){
143ce512b84SThomas Renninger 			fprintf(stderr, _("Cannot set values on CPU %d:"), cpu);
144ce512b84SThomas Renninger 			fprintf(stderr, _(" *is offline\n"));
145ce512b84SThomas Renninger 			continue;
146ce512b84SThomas Renninger 		}
147ce512b84SThomas Renninger 
1487fe2f639SDominik Brodowski 		if (params.perf_bias) {
1498113ab20SBorislav Petkov 			ret = cpupower_intel_set_perf_bias(cpu, perf_bias);
1507fe2f639SDominik Brodowski 			if (ret) {
1517fe2f639SDominik Brodowski 				fprintf(stderr, _("Error setting perf-bias "
1527fe2f639SDominik Brodowski 						  "value on CPU %d\n"), cpu);
1537fe2f639SDominik Brodowski 				break;
1547fe2f639SDominik Brodowski 			}
1557fe2f639SDominik Brodowski 		}
156f2ab5557SWyes Karny 
157f2ab5557SWyes Karny 		if (params.epp) {
158f2ab5557SWyes Karny 			ret = cpupower_set_epp(cpu, epp);
159f2ab5557SWyes Karny 			if (ret) {
160f2ab5557SWyes Karny 				fprintf(stderr,
161f2ab5557SWyes Karny 					"Error setting epp value on CPU %d\n", cpu);
162f2ab5557SWyes Karny 				break;
163f2ab5557SWyes Karny 			}
164f2ab5557SWyes Karny 		}
165df8776b0SWyes Karny 
1667fe2f639SDominik Brodowski 	}
1677fe2f639SDominik Brodowski 	return ret;
1687fe2f639SDominik Brodowski }
169