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