diff options
Diffstat (limited to 'tools/power/cpupower/utils/cpuidle-info.c')
-rw-r--r-- | tools/power/cpupower/utils/cpuidle-info.c | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c new file mode 100644 index 000000000000..70da3574f1e9 --- /dev/null +++ b/tools/power/cpupower/utils/cpuidle-info.c | |||
@@ -0,0 +1,244 @@ | |||
1 | /* | ||
2 | * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de> | ||
3 | * (C) 2010 Thomas Renninger <trenn@suse.de> | ||
4 | * | ||
5 | * Licensed under the terms of the GNU GPL License version 2. | ||
6 | */ | ||
7 | |||
8 | |||
9 | #include <unistd.h> | ||
10 | #include <stdio.h> | ||
11 | #include <errno.h> | ||
12 | #include <stdlib.h> | ||
13 | #include <string.h> | ||
14 | #include <getopt.h> | ||
15 | #include <cpufreq.h> | ||
16 | |||
17 | #include "helpers/helpers.h" | ||
18 | #include "helpers/sysfs.h" | ||
19 | #include "helpers/bitmask.h" | ||
20 | |||
21 | #define LINE_LEN 10 | ||
22 | |||
23 | static void cpuidle_cpu_output(unsigned int cpu, int verbose) | ||
24 | { | ||
25 | int idlestates, idlestate; | ||
26 | char *tmp; | ||
27 | |||
28 | printf(_ ("Analyzing CPU %d:\n"), cpu); | ||
29 | |||
30 | idlestates = sysfs_get_idlestate_count(cpu); | ||
31 | if (idlestates == 0) { | ||
32 | printf(_("CPU %u: No idle states\n"), cpu); | ||
33 | return; | ||
34 | } else if (idlestates <= 0) { | ||
35 | printf(_("CPU %u: Can't read idle state info\n"), cpu); | ||
36 | return; | ||
37 | } | ||
38 | tmp = sysfs_get_idlestate_name(cpu, idlestates - 1); | ||
39 | if (!tmp) { | ||
40 | printf(_("Could not determine max idle state %u\n"), | ||
41 | idlestates - 1); | ||
42 | return; | ||
43 | } | ||
44 | |||
45 | printf(_("Number of idle states: %d\n"), idlestates); | ||
46 | |||
47 | printf(_("Available idle states:")); | ||
48 | for (idlestate = 1; idlestate < idlestates; idlestate++) { | ||
49 | tmp = sysfs_get_idlestate_name(cpu, idlestate); | ||
50 | if (!tmp) | ||
51 | continue; | ||
52 | printf(" %s", tmp); | ||
53 | free(tmp); | ||
54 | } | ||
55 | printf("\n"); | ||
56 | |||
57 | if (!verbose) | ||
58 | return; | ||
59 | |||
60 | for (idlestate = 1; idlestate < idlestates; idlestate++) { | ||
61 | tmp = sysfs_get_idlestate_name(cpu, idlestate); | ||
62 | if (!tmp) | ||
63 | continue; | ||
64 | printf("%s:\n", tmp); | ||
65 | free(tmp); | ||
66 | |||
67 | tmp = sysfs_get_idlestate_desc(cpu, idlestate); | ||
68 | if (!tmp) | ||
69 | continue; | ||
70 | printf(_("Flags/Description: %s\n"), tmp); | ||
71 | free(tmp); | ||
72 | |||
73 | printf(_("Latency: %lu\n"), | ||
74 | sysfs_get_idlestate_latency(cpu, idlestate)); | ||
75 | printf(_("Usage: %lu\n"), | ||
76 | sysfs_get_idlestate_usage(cpu, idlestate)); | ||
77 | printf(_("Duration: %llu\n"), | ||
78 | sysfs_get_idlestate_time(cpu, idlestate)); | ||
79 | } | ||
80 | printf("\n"); | ||
81 | } | ||
82 | |||
83 | static void cpuidle_general_output(void) | ||
84 | { | ||
85 | char *tmp; | ||
86 | |||
87 | tmp = sysfs_get_cpuidle_driver(); | ||
88 | if (!tmp) { | ||
89 | printf(_("Could not determine cpuidle driver\n")); | ||
90 | return; | ||
91 | } | ||
92 | |||
93 | printf(_("CPUidle driver: %s\n"), tmp); | ||
94 | free(tmp); | ||
95 | |||
96 | tmp = sysfs_get_cpuidle_governor(); | ||
97 | if (!tmp) { | ||
98 | printf(_("Could not determine cpuidle governor\n")); | ||
99 | return; | ||
100 | } | ||
101 | |||
102 | printf(_("CPUidle governor: %s\n"), tmp); | ||
103 | free(tmp); | ||
104 | } | ||
105 | |||
106 | static void proc_cpuidle_cpu_output(unsigned int cpu) | ||
107 | { | ||
108 | long max_allowed_cstate = 2000000000; | ||
109 | int cstates, cstate; | ||
110 | |||
111 | cstates = sysfs_get_idlestate_count(cpu); | ||
112 | if (cstates == 0) { | ||
113 | /* | ||
114 | * Go on and print same useless info as you'd see with | ||
115 | * cat /proc/acpi/processor/../power | ||
116 | * printf(_("CPU %u: No C-states available\n"), cpu); | ||
117 | * return; | ||
118 | */ | ||
119 | } else if (cstates <= 0) { | ||
120 | printf(_("CPU %u: Can't read C-state info\n"), cpu); | ||
121 | return; | ||
122 | } | ||
123 | /* printf("Cstates: %d\n", cstates); */ | ||
124 | |||
125 | printf(_("active state: C0\n")); | ||
126 | printf(_("max_cstate: C%u\n"), cstates-1); | ||
127 | printf(_("maximum allowed latency: %lu usec\n"), max_allowed_cstate); | ||
128 | printf(_("states:\t\n")); | ||
129 | for (cstate = 1; cstate < cstates; cstate++) { | ||
130 | printf(_(" C%d: " | ||
131 | "type[C%d] "), cstate, cstate); | ||
132 | printf(_("promotion[--] demotion[--] ")); | ||
133 | printf(_("latency[%03lu] "), | ||
134 | sysfs_get_idlestate_latency(cpu, cstate)); | ||
135 | printf(_("usage[%08lu] "), | ||
136 | sysfs_get_idlestate_usage(cpu, cstate)); | ||
137 | printf(_("duration[%020Lu] \n"), | ||
138 | sysfs_get_idlestate_time(cpu, cstate)); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | /* --freq / -f */ | ||
143 | |||
144 | void idle_info_help(void) | ||
145 | { | ||
146 | printf(_ ("Usage: cpupower idleinfo [options]\n")); | ||
147 | printf(_ ("Options:\n")); | ||
148 | printf(_ (" -s, --silent Only show general C-state information\n")); | ||
149 | printf(_ (" -o, --proc Prints out information like provided by the /proc/acpi/processor/*/power\n" | ||
150 | " interface in older kernels\n")); | ||
151 | printf(_ (" -h, --help Prints out this screen\n")); | ||
152 | |||
153 | printf("\n"); | ||
154 | } | ||
155 | |||
156 | static struct option info_opts[] = { | ||
157 | { .name = "silent", .has_arg = no_argument, .flag = NULL, .val = 's'}, | ||
158 | { .name = "proc", .has_arg = no_argument, .flag = NULL, .val = 'o'}, | ||
159 | { .name = "help", .has_arg = no_argument, .flag = NULL, .val = 'h'}, | ||
160 | { }, | ||
161 | }; | ||
162 | |||
163 | static inline void cpuidle_exit(int fail) | ||
164 | { | ||
165 | idle_info_help(); | ||
166 | exit(EXIT_FAILURE); | ||
167 | } | ||
168 | |||
169 | int cmd_idle_info(int argc, char **argv) | ||
170 | { | ||
171 | extern char *optarg; | ||
172 | extern int optind, opterr, optopt; | ||
173 | int ret = 0, cont = 1, output_param = 0, verbose = 1; | ||
174 | unsigned int cpu = 0; | ||
175 | |||
176 | do { | ||
177 | ret = getopt_long(argc, argv, "hos", info_opts, NULL); | ||
178 | if (ret == -1) | ||
179 | break; | ||
180 | switch (ret) { | ||
181 | case '?': | ||
182 | output_param = '?'; | ||
183 | cont = 0; | ||
184 | break; | ||
185 | case 'h': | ||
186 | output_param = 'h'; | ||
187 | cont = 0; | ||
188 | break; | ||
189 | case 's': | ||
190 | verbose = 0; | ||
191 | break; | ||
192 | case -1: | ||
193 | cont = 0; | ||
194 | break; | ||
195 | case 'o': | ||
196 | if (output_param) { | ||
197 | output_param = -1; | ||
198 | cont = 0; | ||
199 | break; | ||
200 | } | ||
201 | output_param = ret; | ||
202 | break; | ||
203 | } | ||
204 | } while (cont); | ||
205 | |||
206 | switch (output_param) { | ||
207 | case -1: | ||
208 | printf(_("You can't specify more than one " | ||
209 | "output-specific argument\n")); | ||
210 | cpuidle_exit(EXIT_FAILURE); | ||
211 | case '?': | ||
212 | printf(_("invalid or unknown argument\n")); | ||
213 | cpuidle_exit(EXIT_FAILURE); | ||
214 | case 'h': | ||
215 | cpuidle_exit(EXIT_SUCCESS); | ||
216 | } | ||
217 | |||
218 | /* Default is: show output of CPU 0 only */ | ||
219 | if (bitmask_isallclear(cpus_chosen)) | ||
220 | bitmask_setbit(cpus_chosen, 0); | ||
221 | |||
222 | if (output_param == 0) | ||
223 | cpuidle_general_output(); | ||
224 | |||
225 | for (cpu = bitmask_first(cpus_chosen); | ||
226 | cpu <= bitmask_last(cpus_chosen); cpu++) { | ||
227 | |||
228 | if (!bitmask_isbitset(cpus_chosen, cpu) || | ||
229 | cpufreq_cpu_exists(cpu)) | ||
230 | continue; | ||
231 | |||
232 | switch (output_param) { | ||
233 | |||
234 | case 'o': | ||
235 | proc_cpuidle_cpu_output(cpu); | ||
236 | break; | ||
237 | case 0: | ||
238 | printf("\n"); | ||
239 | cpuidle_cpu_output(cpu, verbose); | ||
240 | break; | ||
241 | } | ||
242 | } | ||
243 | return EXIT_SUCCESS; | ||
244 | } | ||