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