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