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 | |
27 | static void print_wrong_arg_exit(void) |
28 | { |
29 | printf(_("invalid or unknown argument\n" )); |
30 | exit(EXIT_FAILURE); |
31 | } |
32 | |
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(bmp: cpus_chosen)) |
133 | bitmask_setall(bmp: cpus_chosen); |
134 | |
135 | /* loop over CPUs */ |
136 | for (cpu = bitmask_first(bmp: cpus_chosen); |
137 | cpu <= bitmask_last(bmp: cpus_chosen); cpu++) { |
138 | |
139 | if (!bitmask_isbitset(bmp: cpus_chosen, i: 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, val: 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 | |