1 // SPDX-License-Identifier: GPL-2.0
2 #include <unistd.h>
3 #include <stdio.h>
4 #include <errno.h>
5 #include <stdlib.h>
6 #include <limits.h>
7 #include <string.h>
8 #include <ctype.h>
9 #include <getopt.h>
10
11 #include <cpufreq.h>
12 #include <cpuidle.h>
13
14 #include "helpers/helpers.h"
15
16 static struct option info_opts[] = {
17 {"disable", required_argument, NULL, 'd'},
18 {"enable", required_argument, NULL, 'e'},
19 {"disable-by-latency", required_argument, NULL, 'D'},
20 {"enable-all", no_argument, NULL, 'E'},
21 { },
22 };
23
24
cmd_idle_set(int argc,char ** argv)25 int cmd_idle_set(int argc, char **argv)
26 {
27 extern char *optarg;
28 extern int optind, opterr, optopt;
29 int ret = 0, cont = 1, param = 0, disabled;
30 unsigned long long latency = 0, state_latency;
31 unsigned int cpu = 0, idlestate = 0, idlestates = 0;
32 char *endptr;
33
34 do {
35 ret = getopt_long(argc, argv, "d:e:ED:", info_opts, NULL);
36 if (ret == -1)
37 break;
38 switch (ret) {
39 case '?':
40 param = '?';
41 cont = 0;
42 break;
43 case 'd':
44 if (param) {
45 param = -1;
46 cont = 0;
47 break;
48 }
49 param = ret;
50 idlestate = atoi(optarg);
51 break;
52 case 'e':
53 if (param) {
54 param = -1;
55 cont = 0;
56 break;
57 }
58 param = ret;
59 idlestate = atoi(optarg);
60 break;
61 case 'D':
62 if (param) {
63 param = -1;
64 cont = 0;
65 break;
66 }
67 param = ret;
68 latency = strtoull(optarg, &endptr, 10);
69 if (*endptr != '\0') {
70 printf(_("Bad latency value: %s\n"), optarg);
71 exit(EXIT_FAILURE);
72 }
73 break;
74 case 'E':
75 if (param) {
76 param = -1;
77 cont = 0;
78 break;
79 }
80 param = ret;
81 break;
82 case -1:
83 cont = 0;
84 break;
85 }
86 } while (cont);
87
88 switch (param) {
89 case -1:
90 printf(_("You can't specify more than one "
91 "output-specific argument\n"));
92 exit(EXIT_FAILURE);
93 case '?':
94 printf(_("invalid or unknown argument\n"));
95 exit(EXIT_FAILURE);
96 }
97
98 get_cpustate();
99
100 /* Default is: set all CPUs */
101 if (bitmask_isallclear(cpus_chosen))
102 bitmask_setall(cpus_chosen);
103
104 for (cpu = bitmask_first(cpus_chosen);
105 cpu <= bitmask_last(cpus_chosen); cpu++) {
106
107 if (!bitmask_isbitset(cpus_chosen, cpu))
108 continue;
109
110 if (cpupower_is_cpu_online(cpu) != 1)
111 continue;
112
113 idlestates = cpuidle_state_count(cpu);
114 if (idlestates <= 0)
115 continue;
116
117 switch (param) {
118 case 'd':
119 ret = cpuidle_state_disable(cpu, idlestate, 1);
120 if (ret == 0)
121 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu);
122 else if (ret == -1)
123 printf(_("Idlestate %u not available on CPU %u\n"),
124 idlestate, cpu);
125 else if (ret == -2)
126 printf(_("Idlestate disabling not supported by kernel\n"));
127 else
128 printf(_("Idlestate %u not disabled on CPU %u\n"),
129 idlestate, cpu);
130 break;
131 case 'e':
132 ret = cpuidle_state_disable(cpu, idlestate, 0);
133 if (ret == 0)
134 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu);
135 else if (ret == -1)
136 printf(_("Idlestate %u not available on CPU %u\n"),
137 idlestate, cpu);
138 else if (ret == -2)
139 printf(_("Idlestate enabling not supported by kernel\n"));
140 else
141 printf(_("Idlestate %u not enabled on CPU %u\n"),
142 idlestate, cpu);
143 break;
144 case 'D':
145 for (idlestate = 0; idlestate < idlestates; idlestate++) {
146 disabled = cpuidle_is_state_disabled
147 (cpu, idlestate);
148 state_latency = cpuidle_state_latency
149 (cpu, idlestate);
150 if (disabled == 1) {
151 if (latency > state_latency){
152 ret = cpuidle_state_disable
153 (cpu, idlestate, 0);
154 if (ret == 0)
155 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu);
156 }
157 continue;
158 }
159 if (latency <= state_latency){
160 ret = cpuidle_state_disable
161 (cpu, idlestate, 1);
162 if (ret == 0)
163 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu);
164 }
165 }
166 break;
167 case 'E':
168 for (idlestate = 0; idlestate < idlestates; idlestate++) {
169 disabled = cpuidle_is_state_disabled
170 (cpu, idlestate);
171 if (disabled == 1) {
172 ret = cpuidle_state_disable
173 (cpu, idlestate, 0);
174 if (ret == 0)
175 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu);
176 }
177 }
178 break;
179 default:
180 /* Not reachable with proper args checking */
181 printf(_("Invalid or unknown argument\n"));
182 exit(EXIT_FAILURE);
183 break;
184 }
185 }
186
187 print_offline_cpus();
188 return EXIT_SUCCESS;
189 }
190