Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / tools / power / cpupower / utils / cpuidle-info.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
4  *  (C) 2010       Thomas Renninger <trenn@suse.de>
5  */
6
7
8 #include <unistd.h>
9 #include <stdio.h>
10 #include <errno.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <getopt.h>
14
15 #include <cpuidle.h>
16
17 #include "helpers/sysfs.h"
18 #include "helpers/helpers.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         unsigned int idlestates, idlestate;
26         char *tmp;
27
28         idlestates = cpuidle_state_count(cpu);
29         if (idlestates == 0) {
30                 printf(_("CPU %u: No idle states\n"), cpu);
31                 return;
32         }
33
34         printf(_("Number of idle states: %d\n"), idlestates);
35         printf(_("Available idle states:"));
36         for (idlestate = 0; idlestate < idlestates; idlestate++) {
37                 tmp = cpuidle_state_name(cpu, idlestate);
38                 if (!tmp)
39                         continue;
40                 printf(" %s", tmp);
41                 free(tmp);
42         }
43         printf("\n");
44
45         if (!verbose)
46                 return;
47
48         for (idlestate = 0; idlestate < idlestates; idlestate++) {
49                 int disabled = cpuidle_is_state_disabled(cpu, idlestate);
50                 /* Disabled interface not supported on older kernels */
51                 if (disabled < 0)
52                         disabled = 0;
53                 tmp = cpuidle_state_name(cpu, idlestate);
54                 if (!tmp)
55                         continue;
56                 printf("%s%s:\n", tmp, (disabled) ? " (DISABLED) " : "");
57                 free(tmp);
58
59                 tmp = cpuidle_state_desc(cpu, idlestate);
60                 if (!tmp)
61                         continue;
62                 printf(_("Flags/Description: %s\n"), tmp);
63                 free(tmp);
64
65                 printf(_("Latency: %lu\n"),
66                        cpuidle_state_latency(cpu, idlestate));
67                 printf(_("Usage: %lu\n"),
68                        cpuidle_state_usage(cpu, idlestate));
69                 printf(_("Duration: %llu\n"),
70                        cpuidle_state_time(cpu, idlestate));
71         }
72 }
73
74 static void cpuidle_general_output(void)
75 {
76         char *tmp;
77
78         tmp = cpuidle_get_driver();
79         if (!tmp) {
80                 printf(_("Could not determine cpuidle driver\n"));
81                 return;
82         }
83
84         printf(_("CPUidle driver: %s\n"), tmp);
85         free(tmp);
86
87         tmp = cpuidle_get_governor();
88         if (!tmp) {
89                 printf(_("Could not determine cpuidle governor\n"));
90                 return;
91         }
92
93         printf(_("CPUidle governor: %s\n"), tmp);
94         free(tmp);
95 }
96
97 static void proc_cpuidle_cpu_output(unsigned int cpu)
98 {
99         long max_allowed_cstate = 2000000000;
100         unsigned int cstate, cstates;
101
102         cstates = cpuidle_state_count(cpu);
103         if (cstates == 0) {
104                 printf(_("CPU %u: No C-states info\n"), cpu);
105                 return;
106         }
107
108         printf(_("active state:            C0\n"));
109         printf(_("max_cstate:              C%u\n"), cstates-1);
110         printf(_("maximum allowed latency: %lu usec\n"), max_allowed_cstate);
111         printf(_("states:\t\n"));
112         for (cstate = 1; cstate < cstates; cstate++) {
113                 printf(_("    C%d:                  "
114                          "type[C%d] "), cstate, cstate);
115                 printf(_("promotion[--] demotion[--] "));
116                 printf(_("latency[%03lu] "),
117                        cpuidle_state_latency(cpu, cstate));
118                 printf(_("usage[%08lu] "),
119                        cpuidle_state_usage(cpu, cstate));
120                 printf(_("duration[%020Lu] \n"),
121                        cpuidle_state_time(cpu, cstate));
122         }
123 }
124
125 static struct option info_opts[] = {
126         {"silent", no_argument, NULL, 's'},
127         {"proc", no_argument, NULL, 'o'},
128         { },
129 };
130
131 static inline void cpuidle_exit(int fail)
132 {
133         exit(EXIT_FAILURE);
134 }
135
136 int cmd_idle_info(int argc, char **argv)
137 {
138         extern char *optarg;
139         extern int optind, opterr, optopt;
140         int ret = 0, cont = 1, output_param = 0, verbose = 1;
141         unsigned int cpu = 0;
142
143         do {
144                 ret = getopt_long(argc, argv, "os", info_opts, NULL);
145                 if (ret == -1)
146                         break;
147                 switch (ret) {
148                 case '?':
149                         output_param = '?';
150                         cont = 0;
151                         break;
152                 case 's':
153                         verbose = 0;
154                         break;
155                 case -1:
156                         cont = 0;
157                         break;
158                 case 'o':
159                         if (output_param) {
160                                 output_param = -1;
161                                 cont = 0;
162                                 break;
163                         }
164                         output_param = ret;
165                         break;
166                 }
167         } while (cont);
168
169         switch (output_param) {
170         case -1:
171                 printf(_("You can't specify more than one "
172                          "output-specific argument\n"));
173                 cpuidle_exit(EXIT_FAILURE);
174         case '?':
175                 printf(_("invalid or unknown argument\n"));
176                 cpuidle_exit(EXIT_FAILURE);
177         }
178
179         /* Default is: show output of CPU 0 only */
180         if (bitmask_isallclear(cpus_chosen))
181                 bitmask_setbit(cpus_chosen, 0);
182
183         if (output_param == 0)
184                 cpuidle_general_output();
185
186         for (cpu = bitmask_first(cpus_chosen);
187              cpu <= bitmask_last(cpus_chosen); cpu++) {
188
189                 if (!bitmask_isbitset(cpus_chosen, cpu))
190                         continue;
191
192                 printf(_("analyzing CPU %d:\n"), cpu);
193
194                 if (sysfs_is_cpu_online(cpu) != 1) {
195                         printf(_(" *is offline\n"));
196                         printf("\n");
197                         continue;
198                 }
199
200                 switch (output_param) {
201
202                 case 'o':
203                         proc_cpuidle_cpu_output(cpu);
204                         break;
205                 case 0:
206                         printf("\n");
207                         cpuidle_cpu_output(cpu, verbose);
208                         break;
209                 }
210                 printf("\n");
211         }
212         return EXIT_SUCCESS;
213 }