linux/tools/power/cpupower/utils/cpuidle-info.c
<<
>>
Prefs
   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
  24static 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
  75static 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
  98static 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
 126static struct option info_opts[] = {
 127        {"silent", no_argument, NULL, 's'},
 128        {"proc", no_argument, NULL, 'o'},
 129        { },
 130};
 131
 132static inline void cpuidle_exit(int fail)
 133{
 134        exit(EXIT_FAILURE);
 135}
 136
 137int 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