218 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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 1022 23static 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(_("Residency: %lu\n"),68 cpuidle_state_residency(cpu, idlestate));69 printf(_("Usage: %lu\n"),70 cpuidle_state_usage(cpu, idlestate));71 printf(_("Duration: %llu\n"),72 cpuidle_state_time(cpu, idlestate));73 }74}75 76static void cpuidle_general_output(void)77{78 char *tmp;79 80 tmp = cpuidle_get_driver();81 if (!tmp) {82 printf(_("Could not determine cpuidle driver\n"));83 return;84 }85 86 printf(_("CPUidle driver: %s\n"), tmp);87 free(tmp);88 89 tmp = cpuidle_get_governor();90 if (!tmp) {91 printf(_("Could not determine cpuidle governor\n"));92 return;93 }94 95 printf(_("CPUidle governor: %s\n"), tmp);96 free(tmp);97}98 99static void proc_cpuidle_cpu_output(unsigned int cpu)100{101 long max_allowed_cstate = 2000000000;102 unsigned int cstate, cstates;103 104 cstates = cpuidle_state_count(cpu);105 if (cstates == 0) {106 printf(_("CPU %u: No C-states info\n"), cpu);107 return;108 }109 110 printf(_("active state: C0\n"));111 printf(_("max_cstate: C%u\n"), cstates-1);112 printf(_("maximum allowed latency: %lu usec\n"), max_allowed_cstate);113 printf(_("states:\t\n"));114 for (cstate = 1; cstate < cstates; cstate++) {115 printf(_(" C%d: "116 "type[C%d] "), cstate, cstate);117 printf(_("promotion[--] demotion[--] "));118 printf(_("latency[%03lu] "),119 cpuidle_state_latency(cpu, cstate));120 printf(_("residency[%05lu] "),121 cpuidle_state_residency(cpu, cstate));122 printf(_("usage[%08lu] "),123 cpuidle_state_usage(cpu, cstate));124 printf(_("duration[%020Lu] \n"),125 cpuidle_state_time(cpu, cstate));126 }127}128 129static struct option info_opts[] = {130 {"silent", no_argument, NULL, 's'},131 {"proc", no_argument, NULL, 'o'},132 { },133};134 135static inline void cpuidle_exit(int fail)136{137 exit(EXIT_FAILURE);138}139 140int cmd_idle_info(int argc, char **argv)141{142 extern char *optarg;143 extern int optind, opterr, optopt;144 int ret = 0, cont = 1, output_param = 0, verbose = 1;145 unsigned int cpu = 0;146 147 do {148 ret = getopt_long(argc, argv, "os", info_opts, NULL);149 if (ret == -1)150 break;151 switch (ret) {152 case '?':153 output_param = '?';154 cont = 0;155 break;156 case 's':157 verbose = 0;158 break;159 case -1:160 cont = 0;161 break;162 case 'o':163 if (output_param) {164 output_param = -1;165 cont = 0;166 break;167 }168 output_param = ret;169 break;170 }171 } while (cont);172 173 switch (output_param) {174 case -1:175 printf(_("You can't specify more than one "176 "output-specific argument\n"));177 cpuidle_exit(EXIT_FAILURE);178 case '?':179 printf(_("invalid or unknown argument\n"));180 cpuidle_exit(EXIT_FAILURE);181 }182 183 /* Default is: show output of base_cpu only */184 if (bitmask_isallclear(cpus_chosen))185 bitmask_setbit(cpus_chosen, base_cpu);186 187 if (output_param == 0)188 cpuidle_general_output();189 190 for (cpu = bitmask_first(cpus_chosen);191 cpu <= bitmask_last(cpus_chosen); cpu++) {192 193 if (!bitmask_isbitset(cpus_chosen, cpu))194 continue;195 196 printf(_("analyzing CPU %d:\n"), cpu);197 198 if (sysfs_is_cpu_online(cpu) != 1) {199 printf(_(" *is offline\n"));200 printf("\n");201 continue;202 }203 204 switch (output_param) {205 206 case 'o':207 proc_cpuidle_cpu_output(cpu);208 break;209 case 0:210 printf("\n");211 cpuidle_cpu_output(cpu, verbose);212 break;213 }214 printf("\n");215 }216 return EXIT_SUCCESS;217}218