linux/tools/power/cpupower/utils/cpuidle-info.c
<<
>>
Prefs
   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
  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(_("Usage: %lu\n"),
  68                       cpuidle_state_usage(cpu, idlestate));
  69                printf(_("Duration: %llu\n"),
  70                       cpuidle_state_time(cpu, idlestate));
  71        }
  72}
  73
  74static 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
  97static 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
 125static struct option info_opts[] = {
 126        {"silent", no_argument, NULL, 's'},
 127        {"proc", no_argument, NULL, 'o'},
 128        { },
 129};
 130
 131static inline void cpuidle_exit(int fail)
 132{
 133        exit(EXIT_FAILURE);
 134}
 135
 136int 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}
 214