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