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