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
19static struct option set_opts[] = {
20	{"perf-bias", required_argument, NULL, 'b'},
21	{ },
22};
23
24static void print_wrong_arg_exit(void)
25{
26	printf(_("invalid or unknown argument\n"));
27	exit(EXIT_FAILURE);
28}
29
30int cmd_set(int argc, char **argv)
31{
32	extern char *optarg;
33	extern int optind, opterr, optopt;
34	unsigned int cpu;
35	struct utsname uts;
36
37	union {
38		struct {
39			int perf_bias:1;
40		};
41		int params;
42	} params;
43	int perf_bias = 0;
44	int ret = 0;
45
46	ret = uname(&uts);
47	if (!ret && (!strcmp(uts.machine, "ppc64le") ||
48		     !strcmp(uts.machine, "ppc64"))) {
49		fprintf(stderr, _("Subcommand not supported on POWER.\n"));
50		return ret;
51	}
52
53	setlocale(LC_ALL, "");
54	textdomain(PACKAGE);
55
56	params.params = 0;
57	/* parameter parsing */
58	while ((ret = getopt_long(argc, argv, "b:",
59						set_opts, NULL)) != -1) {
60		switch (ret) {
61		case 'b':
62			if (params.perf_bias)
63				print_wrong_arg_exit();
64			perf_bias = atoi(optarg);
65			if (perf_bias < 0 || perf_bias > 15) {
66				printf(_("--perf-bias param out "
67					 "of range [0-%d]\n"), 15);
68				print_wrong_arg_exit();
69			}
70			params.perf_bias = 1;
71			break;
72		default:
73			print_wrong_arg_exit();
74		}
75	}
76
77	if (!params.params)
78		print_wrong_arg_exit();
79
80	/* Default is: set all CPUs */
81	if (bitmask_isallclear(cpus_chosen))
82		bitmask_setall(cpus_chosen);
83
84	/* loop over CPUs */
85	for (cpu = bitmask_first(cpus_chosen);
86	     cpu <= bitmask_last(cpus_chosen); cpu++) {
87
88		if (!bitmask_isbitset(cpus_chosen, cpu))
89			continue;
90
91		if (sysfs_is_cpu_online(cpu) != 1){
92			fprintf(stderr, _("Cannot set values on CPU %d:"), cpu);
93			fprintf(stderr, _(" *is offline\n"));
94			continue;
95		}
96
97		if (params.perf_bias) {
98			ret = msr_intel_set_perf_bias(cpu, perf_bias);
99			if (ret) {
100				fprintf(stderr, _("Error setting perf-bias "
101						  "value on CPU %d\n"), cpu);
102				break;
103			}
104		}
105	}
106	return ret;
107}
108