^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <limits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <getopt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "cpufreq.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "helpers/sysfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "helpers/helpers.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "helpers/bitmask.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define LINE_LEN 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static unsigned int count_cpus(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) FILE *fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) char value[LINE_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) unsigned int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned int cpunr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) fp = fopen("/proc/stat", "r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (!fp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) printf(_("Couldn't count the number of CPUs (%s: %s), assuming 1\n"), "/proc/stat", strerror(errno));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) while (!feof(fp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (!fgets(value, LINE_LEN, fp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) value[LINE_LEN - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (strlen(value) < (LINE_LEN - 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (strstr(value, "cpu "))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (sscanf(value, "cpu%d ", &cpunr) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (cpunr > ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ret = cpunr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) fclose(fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* cpu count starts from 0, on error return 1 (UP) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return ret + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static void proc_cpufreq_output(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned int cpu, nr_cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct cpufreq_policy *policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned int min_pctg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned int max_pctg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned long min, max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) printf(_(" minimum CPU frequency - maximum CPU frequency - governor\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) nr_cpus = count_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) for (cpu = 0; cpu < nr_cpus; cpu++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) policy = cpufreq_get_policy(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (!policy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (cpufreq_get_hardware_limits(cpu, &min, &max)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) min_pctg = (policy->min * 100) / max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) max_pctg = (policy->max * 100) / max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) printf("CPU%3d %9lu kHz (%3d %%) - %9lu kHz (%3d %%) - %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) cpu , policy->min, max ? min_pctg : 0, policy->max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) max ? max_pctg : 0, policy->governor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) cpufreq_put_policy(policy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static int no_rounding;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static void print_speed(unsigned long speed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) unsigned long tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (no_rounding) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (speed > 1000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) printf("%u.%06u GHz", ((unsigned int) speed/1000000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) ((unsigned int) speed%1000000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) else if (speed > 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) printf("%u.%03u MHz", ((unsigned int) speed/1000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) (unsigned int) (speed%1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) printf("%lu kHz", speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (speed > 1000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) tmp = speed%10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (tmp >= 5000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) speed += 10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) printf("%u.%02u GHz", ((unsigned int) speed/1000000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) ((unsigned int) (speed%1000000)/10000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) } else if (speed > 100000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) tmp = speed%1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (tmp >= 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) speed += 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) printf("%u MHz", ((unsigned int) speed/1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) } else if (speed > 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) tmp = speed%100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (tmp >= 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) speed += 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) printf("%u.%01u MHz", ((unsigned int) speed/1000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ((unsigned int) (speed%1000)/100));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static void print_duration(unsigned long duration)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) unsigned long tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (no_rounding) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (duration > 1000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) printf("%u.%06u ms", ((unsigned int) duration/1000000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ((unsigned int) duration%1000000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) else if (duration > 100000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) printf("%u us", ((unsigned int) duration/1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) else if (duration > 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) printf("%u.%03u us", ((unsigned int) duration/1000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ((unsigned int) duration%1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) printf("%lu ns", duration);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (duration > 1000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) tmp = duration%10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (tmp >= 5000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) duration += 10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) printf("%u.%02u ms", ((unsigned int) duration/1000000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ((unsigned int) (duration%1000000)/10000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) } else if (duration > 100000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) tmp = duration%1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (tmp >= 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) duration += 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) printf("%u us", ((unsigned int) duration / 1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) } else if (duration > 1000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) tmp = duration%100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (tmp >= 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) duration += 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) printf("%u.%01u us", ((unsigned int) duration/1000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ((unsigned int) (duration%1000)/100));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) printf("%lu ns", duration);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static int get_boost_mode_x86(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) int support, active, b_states = 0, ret, pstate_no, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /* ToDo: Make this more global */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) unsigned long pstates[MAX_HW_PSTATES] = {0,};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ret = cpufreq_has_boost_support(cpu, &support, &active, &b_states);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) printf(_("Error while evaluating Boost Capabilities"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) " on CPU %d -- are you root?\n"), cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /* P state changes via MSR are identified via cpuid 80000007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) on Intel and AMD, but we assume boost capable machines can do that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (cpuid_eax(0x80000000) >= 0x80000007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) && (cpuid_edx(0x80000007) & (1 << 7)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) printf(_(" boost state support:\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) printf(_(" Supported: %s\n"), support ? _("yes") : _("no"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) printf(_(" Active: %s\n"), active ? _("yes") : _("no"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if ((cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) cpupower_cpu_info.family >= 0x10) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) cpupower_cpu_info.vendor == X86_VENDOR_HYGON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ret = decode_pstates(cpu, cpupower_cpu_info.family, b_states,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) pstates, &pstate_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) printf(_(" Boost States: %d\n"), b_states);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) printf(_(" Total States: %d\n"), pstate_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) for (i = 0; i < pstate_no; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (!pstates[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (i < b_states)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) printf(_(" Pstate-Pb%d: %luMHz (boost state)"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) "\n"), i, pstates[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) printf(_(" Pstate-P%d: %luMHz\n"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) i - b_states, pstates[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_HAS_TURBO_RATIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) double bclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) unsigned long long intel_turbo_ratio = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) unsigned int ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /* Any way to autodetect this ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (cpupower_cpu_info.caps & CPUPOWER_CAP_IS_SNB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) bclk = 100.00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) bclk = 133.33;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) intel_turbo_ratio = msr_intel_get_turbo_ratio(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) dprint (" Ratio: 0x%llx - bclk: %f\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) intel_turbo_ratio, bclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) ratio = (intel_turbo_ratio >> 24) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (ratio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) printf(_(" %.0f MHz max turbo 4 active cores\n"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) ratio * bclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) ratio = (intel_turbo_ratio >> 16) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (ratio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) printf(_(" %.0f MHz max turbo 3 active cores\n"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ratio * bclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ratio = (intel_turbo_ratio >> 8) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (ratio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) printf(_(" %.0f MHz max turbo 2 active cores\n"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) ratio * bclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ratio = (intel_turbo_ratio >> 0) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (ratio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) printf(_(" %.0f MHz max turbo 1 active cores\n"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) ratio * bclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* --boost / -b */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static int get_boost_mode(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct cpufreq_available_frequencies *freqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (cpupower_cpu_info.vendor == X86_VENDOR_AMD ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) cpupower_cpu_info.vendor == X86_VENDOR_HYGON ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) cpupower_cpu_info.vendor == X86_VENDOR_INTEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return get_boost_mode_x86(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) freqs = cpufreq_get_boost_frequencies(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (freqs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) printf(_(" boost frequency steps: "));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) while (freqs->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) print_speed(freqs->frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) printf(", ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) freqs = freqs->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) print_speed(freqs->frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) cpufreq_put_available_frequencies(freqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* --freq / -f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static int get_freq_kernel(unsigned int cpu, unsigned int human)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) unsigned long freq = cpufreq_get_freq_kernel(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) printf(_(" current CPU frequency: "));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (!freq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) printf(_(" Unable to call to kernel\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (human) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) print_speed(freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) printf("%lu", freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) printf(_(" (asserted by call to kernel)\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* --hwfreq / -w */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static int get_freq_hardware(unsigned int cpu, unsigned int human)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) unsigned long freq = cpufreq_get_freq_hardware(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) printf(_(" current CPU frequency: "));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (!freq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) printf("Unable to call hardware\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (human) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) print_speed(freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) printf("%lu", freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) printf(_(" (asserted by call to hardware)\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) /* --hwlimits / -l */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static int get_hardware_limits(unsigned int cpu, unsigned int human)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) unsigned long min, max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (cpufreq_get_hardware_limits(cpu, &min, &max)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) printf(_("Not Available\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (human) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) printf(_(" hardware limits: "));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) print_speed(min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) printf(" - ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) print_speed(max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) printf("%lu %lu\n", min, max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* --driver / -d */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) static int get_driver(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) char *driver = cpufreq_get_driver(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (!driver) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) printf(_(" no or unknown cpufreq driver is active on this CPU\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) printf(" driver: %s\n", driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) cpufreq_put_driver(driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) /* --policy / -p */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static int get_policy(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct cpufreq_policy *policy = cpufreq_get_policy(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (!policy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) printf(_(" Unable to determine current policy\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) printf(_(" current policy: frequency should be within "));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) print_speed(policy->min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) printf(_(" and "));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) print_speed(policy->max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) printf(".\n ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) printf(_("The governor \"%s\" may decide which speed to use\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) " within this range.\n"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) policy->governor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) cpufreq_put_policy(policy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* --governors / -g */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static int get_available_governors(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) struct cpufreq_available_governors *governors =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) cpufreq_get_available_governors(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) printf(_(" available cpufreq governors: "));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (!governors) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) printf(_("Not Available\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) while (governors->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) printf("%s ", governors->governor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) governors = governors->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) printf("%s\n", governors->governor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) cpufreq_put_available_governors(governors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /* --affected-cpus / -a */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static int get_affected_cpus(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) struct cpufreq_affected_cpus *cpus = cpufreq_get_affected_cpus(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) printf(_(" CPUs which need to have their frequency coordinated by software: "));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (!cpus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) printf(_("Not Available\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) while (cpus->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) printf("%d ", cpus->cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) cpus = cpus->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) printf("%d\n", cpus->cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) cpufreq_put_affected_cpus(cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) /* --related-cpus / -r */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static int get_related_cpus(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) struct cpufreq_affected_cpus *cpus = cpufreq_get_related_cpus(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) printf(_(" CPUs which run at the same hardware frequency: "));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (!cpus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) printf(_("Not Available\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) while (cpus->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) printf("%d ", cpus->cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) cpus = cpus->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) printf("%d\n", cpus->cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) cpufreq_put_related_cpus(cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /* --stats / -s */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) static int get_freq_stats(unsigned int cpu, unsigned int human)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) unsigned long total_trans = cpufreq_get_transitions(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) unsigned long long total_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) while (stats) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (human) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) print_speed(stats->frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) printf(":%.2f%%",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) (100.0 * stats->time_in_state) / total_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) printf("%lu:%llu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) stats->frequency, stats->time_in_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) stats = stats->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) printf(", ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) cpufreq_put_stats(stats);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (total_trans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) printf(" (%lu)\n", total_trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /* --latency / -y */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static int get_latency(unsigned int cpu, unsigned int human)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) unsigned long latency = cpufreq_get_transition_latency(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) printf(_(" maximum transition latency: "));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (!latency || latency == UINT_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) printf(_(" Cannot determine or is not supported.\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (human) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) print_duration(latency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) printf("%lu\n", latency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) static void debug_output_one(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) struct cpufreq_available_frequencies *freqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) get_driver(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) get_related_cpus(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) get_affected_cpus(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) get_latency(cpu, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) get_hardware_limits(cpu, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) freqs = cpufreq_get_available_frequencies(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (freqs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) printf(_(" available frequency steps: "));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) while (freqs->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) print_speed(freqs->frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) printf(", ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) freqs = freqs->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) print_speed(freqs->frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) cpufreq_put_available_frequencies(freqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) get_available_governors(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) get_policy(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (get_freq_hardware(cpu, 1) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) get_freq_kernel(cpu, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) get_boost_mode(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static struct option info_opts[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {"debug", no_argument, NULL, 'e'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {"boost", no_argument, NULL, 'b'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) {"freq", no_argument, NULL, 'f'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) {"hwfreq", no_argument, NULL, 'w'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {"hwlimits", no_argument, NULL, 'l'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) {"driver", no_argument, NULL, 'd'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {"policy", no_argument, NULL, 'p'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) {"governors", no_argument, NULL, 'g'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) {"related-cpus", no_argument, NULL, 'r'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {"affected-cpus", no_argument, NULL, 'a'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {"stats", no_argument, NULL, 's'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {"latency", no_argument, NULL, 'y'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) {"proc", no_argument, NULL, 'o'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {"human", no_argument, NULL, 'm'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) {"no-rounding", no_argument, NULL, 'n'},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) int cmd_freq_info(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) extern char *optarg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) extern int optind, opterr, optopt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) int ret = 0, cont = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) unsigned int cpu = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) unsigned int human = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) int output_param = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) ret = getopt_long(argc, argv, "oefwldpgrasmybn", info_opts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) switch (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) case '?':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) output_param = '?';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) cont = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) case -1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) cont = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) case 'b':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) case 'o':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) case 'a':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) case 'r':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) case 'g':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) case 'p':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) case 'l':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) case 'w':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) case 'f':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) case 'e':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) case 'y':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (output_param) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) output_param = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) cont = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) output_param = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) case 'm':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (human) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) output_param = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) cont = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) human = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) case 'n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) no_rounding = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) fprintf(stderr, "invalid or unknown argument\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return EXIT_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) } while (cont);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) switch (output_param) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) case 'o':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (!bitmask_isallclear(cpus_chosen)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) printf(_("The argument passed to this tool can't be "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) "combined with passing a --cpu argument\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) output_param = 'e';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) /* Default is: show output of CPU 0 only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (bitmask_isallclear(cpus_chosen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) bitmask_setbit(cpus_chosen, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) switch (output_param) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) case -1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) printf(_("You can't specify more than one --cpu parameter and/or\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) "more than one output-specific argument\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) case '?':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) printf(_("invalid or unknown argument\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) case 'o':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) proc_cpufreq_output();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return EXIT_SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) for (cpu = bitmask_first(cpus_chosen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) cpu <= bitmask_last(cpus_chosen); cpu++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (!bitmask_isbitset(cpus_chosen, cpu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) printf(_("analyzing CPU %d:\n"), cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (sysfs_is_cpu_online(cpu) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) printf(_(" *is offline\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) switch (output_param) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) case 'b':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) get_boost_mode(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) case 'e':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) debug_output_one(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) case 'a':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) ret = get_affected_cpus(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) case 'r':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) ret = get_related_cpus(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) case 'g':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) ret = get_available_governors(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) case 'p':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) ret = get_policy(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) ret = get_driver(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) case 'l':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) ret = get_hardware_limits(cpu, human);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) case 'w':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) ret = get_freq_hardware(cpu, human);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) case 'f':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) ret = get_freq_kernel(cpu, human);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) ret = get_freq_stats(cpu, human);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) case 'y':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) ret = get_latency(cpu, human);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }