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