17fe2f639SDominik Brodowski /* 27fe2f639SDominik Brodowski * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de> 37fe2f639SDominik Brodowski * 47fe2f639SDominik Brodowski * Licensed under the terms of the GNU GPL License version 2. 57fe2f639SDominik Brodowski */ 67fe2f639SDominik Brodowski 77fe2f639SDominik Brodowski 87fe2f639SDominik Brodowski #include <unistd.h> 97fe2f639SDominik Brodowski #include <stdio.h> 107fe2f639SDominik Brodowski #include <errno.h> 117fe2f639SDominik Brodowski #include <stdlib.h> 127fe2f639SDominik Brodowski #include <string.h> 1338cb76a3SShreyas B. Prabhu #include <limits.h> 147fe2f639SDominik Brodowski 157fe2f639SDominik Brodowski #include <getopt.h> 167fe2f639SDominik Brodowski 177fe2f639SDominik Brodowski #include "cpufreq.h" 18ce512b84SThomas Renninger #include "helpers/sysfs.h" 197fe2f639SDominik Brodowski #include "helpers/helpers.h" 207fe2f639SDominik Brodowski #include "helpers/bitmask.h" 217fe2f639SDominik Brodowski 227fe2f639SDominik Brodowski #define LINE_LEN 10 237fe2f639SDominik Brodowski 247fe2f639SDominik Brodowski static unsigned int count_cpus(void) 257fe2f639SDominik Brodowski { 267fe2f639SDominik Brodowski FILE *fp; 277fe2f639SDominik Brodowski char value[LINE_LEN]; 287fe2f639SDominik Brodowski unsigned int ret = 0; 297fe2f639SDominik Brodowski unsigned int cpunr = 0; 307fe2f639SDominik Brodowski 317fe2f639SDominik Brodowski fp = fopen("/proc/stat", "r"); 327fe2f639SDominik Brodowski if (!fp) { 337fe2f639SDominik Brodowski printf(_("Couldn't count the number of CPUs (%s: %s), assuming 1\n"), "/proc/stat", strerror(errno)); 347fe2f639SDominik Brodowski return 1; 357fe2f639SDominik Brodowski } 367fe2f639SDominik Brodowski 377fe2f639SDominik Brodowski while (!feof(fp)) { 387fe2f639SDominik Brodowski if (!fgets(value, LINE_LEN, fp)) 397fe2f639SDominik Brodowski continue; 407fe2f639SDominik Brodowski value[LINE_LEN - 1] = '\0'; 417fe2f639SDominik Brodowski if (strlen(value) < (LINE_LEN - 2)) 427fe2f639SDominik Brodowski continue; 437fe2f639SDominik Brodowski if (strstr(value, "cpu ")) 447fe2f639SDominik Brodowski continue; 457fe2f639SDominik Brodowski if (sscanf(value, "cpu%d ", &cpunr) != 1) 467fe2f639SDominik Brodowski continue; 477fe2f639SDominik Brodowski if (cpunr > ret) 487fe2f639SDominik Brodowski ret = cpunr; 497fe2f639SDominik Brodowski } 507fe2f639SDominik Brodowski fclose(fp); 517fe2f639SDominik Brodowski 527fe2f639SDominik Brodowski /* cpu count starts from 0, on error return 1 (UP) */ 53a1ce5ba2SDominik Brodowski return ret + 1; 547fe2f639SDominik Brodowski } 557fe2f639SDominik Brodowski 567fe2f639SDominik Brodowski 577fe2f639SDominik Brodowski static void proc_cpufreq_output(void) 587fe2f639SDominik Brodowski { 597fe2f639SDominik Brodowski unsigned int cpu, nr_cpus; 607fe2f639SDominik Brodowski struct cpufreq_policy *policy; 617fe2f639SDominik Brodowski unsigned int min_pctg = 0; 627fe2f639SDominik Brodowski unsigned int max_pctg = 0; 637fe2f639SDominik Brodowski unsigned long min, max; 647fe2f639SDominik Brodowski 657fe2f639SDominik Brodowski printf(_(" minimum CPU frequency - maximum CPU frequency - governor\n")); 667fe2f639SDominik Brodowski 677fe2f639SDominik Brodowski nr_cpus = count_cpus(); 687fe2f639SDominik Brodowski for (cpu = 0; cpu < nr_cpus; cpu++) { 697fe2f639SDominik Brodowski policy = cpufreq_get_policy(cpu); 707fe2f639SDominik Brodowski if (!policy) 717fe2f639SDominik Brodowski continue; 727fe2f639SDominik Brodowski 737fe2f639SDominik Brodowski if (cpufreq_get_hardware_limits(cpu, &min, &max)) { 747fe2f639SDominik Brodowski max = 0; 757fe2f639SDominik Brodowski } else { 767fe2f639SDominik Brodowski min_pctg = (policy->min * 100) / max; 777fe2f639SDominik Brodowski max_pctg = (policy->max * 100) / max; 787fe2f639SDominik Brodowski } 797fe2f639SDominik Brodowski printf("CPU%3d %9lu kHz (%3d %%) - %9lu kHz (%3d %%) - %s\n", 80a1ce5ba2SDominik Brodowski cpu , policy->min, max ? min_pctg : 0, policy->max, 81a1ce5ba2SDominik Brodowski max ? max_pctg : 0, policy->governor); 827fe2f639SDominik Brodowski 837fe2f639SDominik Brodowski cpufreq_put_policy(policy); 847fe2f639SDominik Brodowski } 857fe2f639SDominik Brodowski } 867fe2f639SDominik Brodowski 87e091abc7SPrarit Bhargava static int no_rounding; 887fe2f639SDominik Brodowski static void print_speed(unsigned long speed) 897fe2f639SDominik Brodowski { 907fe2f639SDominik Brodowski unsigned long tmp; 917fe2f639SDominik Brodowski 92e091abc7SPrarit Bhargava if (no_rounding) { 93e091abc7SPrarit Bhargava if (speed > 1000000) 94e091abc7SPrarit Bhargava printf("%u.%06u GHz", ((unsigned int) speed/1000000), 95e091abc7SPrarit Bhargava ((unsigned int) speed%1000000)); 96e091abc7SPrarit Bhargava else if (speed > 1000) 97e091abc7SPrarit Bhargava printf("%u.%03u MHz", ((unsigned int) speed/1000), 98e091abc7SPrarit Bhargava (unsigned int) (speed%1000)); 99e091abc7SPrarit Bhargava else 100e091abc7SPrarit Bhargava printf("%lu kHz", speed); 101e091abc7SPrarit Bhargava } else { 1027fe2f639SDominik Brodowski if (speed > 1000000) { 1037fe2f639SDominik Brodowski tmp = speed%10000; 1047fe2f639SDominik Brodowski if (tmp >= 5000) 1057fe2f639SDominik Brodowski speed += 10000; 1067fe2f639SDominik Brodowski printf("%u.%02u GHz", ((unsigned int) speed/1000000), 1077fe2f639SDominik Brodowski ((unsigned int) (speed%1000000)/10000)); 1087fe2f639SDominik Brodowski } else if (speed > 100000) { 1097fe2f639SDominik Brodowski tmp = speed%1000; 1107fe2f639SDominik Brodowski if (tmp >= 500) 1117fe2f639SDominik Brodowski speed += 1000; 1127fe2f639SDominik Brodowski printf("%u MHz", ((unsigned int) speed/1000)); 1137fe2f639SDominik Brodowski } else if (speed > 1000) { 1147fe2f639SDominik Brodowski tmp = speed%100; 1157fe2f639SDominik Brodowski if (tmp >= 50) 1167fe2f639SDominik Brodowski speed += 100; 1177fe2f639SDominik Brodowski printf("%u.%01u MHz", ((unsigned int) speed/1000), 1187fe2f639SDominik Brodowski ((unsigned int) (speed%1000)/100)); 119e091abc7SPrarit Bhargava } 120e091abc7SPrarit Bhargava } 1217fe2f639SDominik Brodowski 1227fe2f639SDominik Brodowski return; 1237fe2f639SDominik Brodowski } 1247fe2f639SDominik Brodowski 1257fe2f639SDominik Brodowski static void print_duration(unsigned long duration) 1267fe2f639SDominik Brodowski { 1277fe2f639SDominik Brodowski unsigned long tmp; 1287fe2f639SDominik Brodowski 129e091abc7SPrarit Bhargava if (no_rounding) { 130e091abc7SPrarit Bhargava if (duration > 1000000) 131e091abc7SPrarit Bhargava printf("%u.%06u ms", ((unsigned int) duration/1000000), 132e091abc7SPrarit Bhargava ((unsigned int) duration%1000000)); 133e091abc7SPrarit Bhargava else if (duration > 100000) 134e091abc7SPrarit Bhargava printf("%u us", ((unsigned int) duration/1000)); 135e091abc7SPrarit Bhargava else if (duration > 1000) 136e091abc7SPrarit Bhargava printf("%u.%03u us", ((unsigned int) duration/1000), 137e091abc7SPrarit Bhargava ((unsigned int) duration%1000)); 138e091abc7SPrarit Bhargava else 139e091abc7SPrarit Bhargava printf("%lu ns", duration); 140e091abc7SPrarit Bhargava } else { 1417fe2f639SDominik Brodowski if (duration > 1000000) { 1427fe2f639SDominik Brodowski tmp = duration%10000; 1437fe2f639SDominik Brodowski if (tmp >= 5000) 1447fe2f639SDominik Brodowski duration += 10000; 1457fe2f639SDominik Brodowski printf("%u.%02u ms", ((unsigned int) duration/1000000), 1467fe2f639SDominik Brodowski ((unsigned int) (duration%1000000)/10000)); 1477fe2f639SDominik Brodowski } else if (duration > 100000) { 1487fe2f639SDominik Brodowski tmp = duration%1000; 1497fe2f639SDominik Brodowski if (tmp >= 500) 1507fe2f639SDominik Brodowski duration += 1000; 1517fe2f639SDominik Brodowski printf("%u us", ((unsigned int) duration / 1000)); 1527fe2f639SDominik Brodowski } else if (duration > 1000) { 1537fe2f639SDominik Brodowski tmp = duration%100; 1547fe2f639SDominik Brodowski if (tmp >= 50) 1557fe2f639SDominik Brodowski duration += 100; 1567fe2f639SDominik Brodowski printf("%u.%01u us", ((unsigned int) duration/1000), 1577fe2f639SDominik Brodowski ((unsigned int) (duration%1000)/100)); 1587fe2f639SDominik Brodowski } else 1597fe2f639SDominik Brodowski printf("%lu ns", duration); 160e091abc7SPrarit Bhargava } 1617fe2f639SDominik Brodowski return; 1627fe2f639SDominik Brodowski } 1637fe2f639SDominik Brodowski 1647fe2f639SDominik Brodowski /* --boost / -b */ 1657fe2f639SDominik Brodowski 166a1ce5ba2SDominik Brodowski static int get_boost_mode(unsigned int cpu) 167a1ce5ba2SDominik Brodowski { 1687fe2f639SDominik Brodowski int support, active, b_states = 0, ret, pstate_no, i; 1697fe2f639SDominik Brodowski /* ToDo: Make this more global */ 1707fe2f639SDominik Brodowski unsigned long pstates[MAX_HW_PSTATES] = {0,}; 1717fe2f639SDominik Brodowski 1727fe2f639SDominik Brodowski if (cpupower_cpu_info.vendor != X86_VENDOR_AMD && 1737fe2f639SDominik Brodowski cpupower_cpu_info.vendor != X86_VENDOR_INTEL) 1747fe2f639SDominik Brodowski return 0; 1757fe2f639SDominik Brodowski 1767fe2f639SDominik Brodowski ret = cpufreq_has_boost_support(cpu, &support, &active, &b_states); 1777fe2f639SDominik Brodowski if (ret) { 1787fe2f639SDominik Brodowski printf(_("Error while evaluating Boost Capabilities" 1797fe2f639SDominik Brodowski " on CPU %d -- are you root?\n"), cpu); 1807fe2f639SDominik Brodowski return ret; 1817fe2f639SDominik Brodowski } 1827fe2f639SDominik Brodowski /* P state changes via MSR are identified via cpuid 80000007 1837fe2f639SDominik Brodowski on Intel and AMD, but we assume boost capable machines can do that 1847fe2f639SDominik Brodowski if (cpuid_eax(0x80000000) >= 0x80000007 1857fe2f639SDominik Brodowski && (cpuid_edx(0x80000007) & (1 << 7))) 1867fe2f639SDominik Brodowski */ 1877fe2f639SDominik Brodowski 1887fe2f639SDominik Brodowski printf(_(" boost state support:\n")); 1897fe2f639SDominik Brodowski 1907fe2f639SDominik Brodowski printf(_(" Supported: %s\n"), support ? _("yes") : _("no")); 1917fe2f639SDominik Brodowski printf(_(" Active: %s\n"), active ? _("yes") : _("no")); 1927fe2f639SDominik Brodowski 1937fe2f639SDominik Brodowski if (cpupower_cpu_info.vendor == X86_VENDOR_AMD && 1947fe2f639SDominik Brodowski cpupower_cpu_info.family >= 0x10) { 1957fe2f639SDominik Brodowski ret = decode_pstates(cpu, cpupower_cpu_info.family, b_states, 1967fe2f639SDominik Brodowski pstates, &pstate_no); 1977fe2f639SDominik Brodowski if (ret) 1987fe2f639SDominik Brodowski return ret; 1997fe2f639SDominik Brodowski 2007fe2f639SDominik Brodowski printf(_(" Boost States: %d\n"), b_states); 2017fe2f639SDominik Brodowski printf(_(" Total States: %d\n"), pstate_no); 2027fe2f639SDominik Brodowski for (i = 0; i < pstate_no; i++) { 203*f69ffc5dSPrarit Bhargava if (!pstates[i]) 204*f69ffc5dSPrarit Bhargava continue; 2057fe2f639SDominik Brodowski if (i < b_states) 2068fb2e440SThomas Renninger printf(_(" Pstate-Pb%d: %luMHz (boost state)" 2078fb2e440SThomas Renninger "\n"), i, pstates[i]); 2087fe2f639SDominik Brodowski else 2097fe2f639SDominik Brodowski printf(_(" Pstate-P%d: %luMHz\n"), 2107fe2f639SDominik Brodowski i - b_states, pstates[i]); 2117fe2f639SDominik Brodowski } 2128fb2e440SThomas Renninger } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_HAS_TURBO_RATIO) { 2138fb2e440SThomas Renninger double bclk; 2148fb2e440SThomas Renninger unsigned long long intel_turbo_ratio = 0; 2158fb2e440SThomas Renninger unsigned int ratio; 2168fb2e440SThomas Renninger 2178fb2e440SThomas Renninger /* Any way to autodetect this ? */ 2188fb2e440SThomas Renninger if (cpupower_cpu_info.caps & CPUPOWER_CAP_IS_SNB) 2198fb2e440SThomas Renninger bclk = 100.00; 2208fb2e440SThomas Renninger else 2218fb2e440SThomas Renninger bclk = 133.33; 2228fb2e440SThomas Renninger intel_turbo_ratio = msr_intel_get_turbo_ratio(cpu); 2238fb2e440SThomas Renninger dprint (" Ratio: 0x%llx - bclk: %f\n", 2248fb2e440SThomas Renninger intel_turbo_ratio, bclk); 2258fb2e440SThomas Renninger 2268fb2e440SThomas Renninger ratio = (intel_turbo_ratio >> 24) & 0xFF; 2278fb2e440SThomas Renninger if (ratio) 2288fb2e440SThomas Renninger printf(_(" %.0f MHz max turbo 4 active cores\n"), 2298fb2e440SThomas Renninger ratio * bclk); 2308fb2e440SThomas Renninger 2318fb2e440SThomas Renninger ratio = (intel_turbo_ratio >> 16) & 0xFF; 2328fb2e440SThomas Renninger if (ratio) 2338fb2e440SThomas Renninger printf(_(" %.0f MHz max turbo 3 active cores\n"), 2348fb2e440SThomas Renninger ratio * bclk); 2358fb2e440SThomas Renninger 2368fb2e440SThomas Renninger ratio = (intel_turbo_ratio >> 8) & 0xFF; 2378fb2e440SThomas Renninger if (ratio) 2388fb2e440SThomas Renninger printf(_(" %.0f MHz max turbo 2 active cores\n"), 2398fb2e440SThomas Renninger ratio * bclk); 2408fb2e440SThomas Renninger 2418fb2e440SThomas Renninger ratio = (intel_turbo_ratio >> 0) & 0xFF; 2428fb2e440SThomas Renninger if (ratio) 2438fb2e440SThomas Renninger printf(_(" %.0f MHz max turbo 1 active cores\n"), 2448fb2e440SThomas Renninger ratio * bclk); 2458fb2e440SThomas Renninger } 2467fe2f639SDominik Brodowski return 0; 2477fe2f639SDominik Brodowski } 2487fe2f639SDominik Brodowski 2497fe2f639SDominik Brodowski /* --freq / -f */ 2507fe2f639SDominik Brodowski 251a1ce5ba2SDominik Brodowski static int get_freq_kernel(unsigned int cpu, unsigned int human) 252a1ce5ba2SDominik Brodowski { 2537fe2f639SDominik Brodowski unsigned long freq = cpufreq_get_freq_kernel(cpu); 254562e5f1aSJacob Tanenbaum printf(_(" current CPU frequency: ")); 255562e5f1aSJacob Tanenbaum if (!freq) { 256562e5f1aSJacob Tanenbaum printf(_(" Unable to call to kernel\n")); 2577fe2f639SDominik Brodowski return -EINVAL; 258562e5f1aSJacob Tanenbaum } 2597fe2f639SDominik Brodowski if (human) { 2607fe2f639SDominik Brodowski print_speed(freq); 2617fe2f639SDominik Brodowski } else 262562e5f1aSJacob Tanenbaum printf("%lu", freq); 263562e5f1aSJacob Tanenbaum printf(_(" (asserted by call to kernel)\n")); 2647fe2f639SDominik Brodowski return 0; 2657fe2f639SDominik Brodowski } 2667fe2f639SDominik Brodowski 2677fe2f639SDominik Brodowski 2687fe2f639SDominik Brodowski /* --hwfreq / -w */ 2697fe2f639SDominik Brodowski 270a1ce5ba2SDominik Brodowski static int get_freq_hardware(unsigned int cpu, unsigned int human) 271a1ce5ba2SDominik Brodowski { 2727fe2f639SDominik Brodowski unsigned long freq = cpufreq_get_freq_hardware(cpu); 273562e5f1aSJacob Tanenbaum printf(_(" current CPU frequency: ")); 274562e5f1aSJacob Tanenbaum if (!freq) { 275562e5f1aSJacob Tanenbaum printf("Unable to call hardware\n"); 2767fe2f639SDominik Brodowski return -EINVAL; 277562e5f1aSJacob Tanenbaum } 2787fe2f639SDominik Brodowski if (human) { 2797fe2f639SDominik Brodowski print_speed(freq); 2807fe2f639SDominik Brodowski } else 281562e5f1aSJacob Tanenbaum printf("%lu", freq); 282562e5f1aSJacob Tanenbaum printf(_(" (asserted by call to hardware)\n")); 2837fe2f639SDominik Brodowski return 0; 2847fe2f639SDominik Brodowski } 2857fe2f639SDominik Brodowski 2867fe2f639SDominik Brodowski /* --hwlimits / -l */ 2877fe2f639SDominik Brodowski 2884da39cebSStafford Horne static int get_hardware_limits(unsigned int cpu, unsigned int human) 289a1ce5ba2SDominik Brodowski { 2907fe2f639SDominik Brodowski unsigned long min, max; 291562e5f1aSJacob Tanenbaum 292562e5f1aSJacob Tanenbaum if (cpufreq_get_hardware_limits(cpu, &min, &max)) { 293562e5f1aSJacob Tanenbaum printf(_("Not Available\n")); 2947fe2f639SDominik Brodowski return -EINVAL; 295562e5f1aSJacob Tanenbaum } 296562e5f1aSJacob Tanenbaum 2974da39cebSStafford Horne if (human) { 2984da39cebSStafford Horne printf(_(" hardware limits: ")); 299562e5f1aSJacob Tanenbaum print_speed(min); 300562e5f1aSJacob Tanenbaum printf(" - "); 301562e5f1aSJacob Tanenbaum print_speed(max); 302562e5f1aSJacob Tanenbaum printf("\n"); 3034da39cebSStafford Horne } else { 3044da39cebSStafford Horne printf("%lu %lu\n", min, max); 3054da39cebSStafford Horne } 3067fe2f639SDominik Brodowski return 0; 3077fe2f639SDominik Brodowski } 3087fe2f639SDominik Brodowski 3097fe2f639SDominik Brodowski /* --driver / -d */ 3107fe2f639SDominik Brodowski 311a1ce5ba2SDominik Brodowski static int get_driver(unsigned int cpu) 312a1ce5ba2SDominik Brodowski { 3137fe2f639SDominik Brodowski char *driver = cpufreq_get_driver(cpu); 314562e5f1aSJacob Tanenbaum if (!driver) { 315562e5f1aSJacob Tanenbaum printf(_(" no or unknown cpufreq driver is active on this CPU\n")); 3167fe2f639SDominik Brodowski return -EINVAL; 317562e5f1aSJacob Tanenbaum } 318562e5f1aSJacob Tanenbaum printf(" driver: %s\n", driver); 3197fe2f639SDominik Brodowski cpufreq_put_driver(driver); 3207fe2f639SDominik Brodowski return 0; 3217fe2f639SDominik Brodowski } 3227fe2f639SDominik Brodowski 3237fe2f639SDominik Brodowski /* --policy / -p */ 3247fe2f639SDominik Brodowski 325a1ce5ba2SDominik Brodowski static int get_policy(unsigned int cpu) 326a1ce5ba2SDominik Brodowski { 3277fe2f639SDominik Brodowski struct cpufreq_policy *policy = cpufreq_get_policy(cpu); 328562e5f1aSJacob Tanenbaum if (!policy) { 329562e5f1aSJacob Tanenbaum printf(_(" Unable to determine current policy\n")); 3307fe2f639SDominik Brodowski return -EINVAL; 331562e5f1aSJacob Tanenbaum } 332562e5f1aSJacob Tanenbaum printf(_(" current policy: frequency should be within ")); 333562e5f1aSJacob Tanenbaum print_speed(policy->min); 334562e5f1aSJacob Tanenbaum printf(_(" and ")); 335562e5f1aSJacob Tanenbaum print_speed(policy->max); 336562e5f1aSJacob Tanenbaum 337562e5f1aSJacob Tanenbaum printf(".\n "); 338562e5f1aSJacob Tanenbaum printf(_("The governor \"%s\" may decide which speed to use\n" 339562e5f1aSJacob Tanenbaum " within this range.\n"), 340562e5f1aSJacob Tanenbaum policy->governor); 3417fe2f639SDominik Brodowski cpufreq_put_policy(policy); 3427fe2f639SDominik Brodowski return 0; 3437fe2f639SDominik Brodowski } 3447fe2f639SDominik Brodowski 3457fe2f639SDominik Brodowski /* --governors / -g */ 3467fe2f639SDominik Brodowski 347a1ce5ba2SDominik Brodowski static int get_available_governors(unsigned int cpu) 348a1ce5ba2SDominik Brodowski { 349a1ce5ba2SDominik Brodowski struct cpufreq_available_governors *governors = 350a1ce5ba2SDominik Brodowski cpufreq_get_available_governors(cpu); 351562e5f1aSJacob Tanenbaum 352562e5f1aSJacob Tanenbaum printf(_(" available cpufreq governors: ")); 353562e5f1aSJacob Tanenbaum if (!governors) { 354562e5f1aSJacob Tanenbaum printf(_("Not Available\n")); 3557fe2f639SDominik Brodowski return -EINVAL; 356562e5f1aSJacob Tanenbaum } 3577fe2f639SDominik Brodowski 3587fe2f639SDominik Brodowski while (governors->next) { 3597fe2f639SDominik Brodowski printf("%s ", governors->governor); 3607fe2f639SDominik Brodowski governors = governors->next; 3617fe2f639SDominik Brodowski } 3627fe2f639SDominik Brodowski printf("%s\n", governors->governor); 3637fe2f639SDominik Brodowski cpufreq_put_available_governors(governors); 3647fe2f639SDominik Brodowski return 0; 3657fe2f639SDominik Brodowski } 3667fe2f639SDominik Brodowski 3677fe2f639SDominik Brodowski 3687fe2f639SDominik Brodowski /* --affected-cpus / -a */ 3697fe2f639SDominik Brodowski 370a1ce5ba2SDominik Brodowski static int get_affected_cpus(unsigned int cpu) 371a1ce5ba2SDominik Brodowski { 3727fe2f639SDominik Brodowski struct cpufreq_affected_cpus *cpus = cpufreq_get_affected_cpus(cpu); 373562e5f1aSJacob Tanenbaum 374562e5f1aSJacob Tanenbaum printf(_(" CPUs which need to have their frequency coordinated by software: ")); 375562e5f1aSJacob Tanenbaum if (!cpus) { 376562e5f1aSJacob Tanenbaum printf(_("Not Available\n")); 3777fe2f639SDominik Brodowski return -EINVAL; 378562e5f1aSJacob Tanenbaum } 3797fe2f639SDominik Brodowski 3807fe2f639SDominik Brodowski while (cpus->next) { 3817fe2f639SDominik Brodowski printf("%d ", cpus->cpu); 3827fe2f639SDominik Brodowski cpus = cpus->next; 3837fe2f639SDominik Brodowski } 3847fe2f639SDominik Brodowski printf("%d\n", cpus->cpu); 3857fe2f639SDominik Brodowski cpufreq_put_affected_cpus(cpus); 3867fe2f639SDominik Brodowski return 0; 3877fe2f639SDominik Brodowski } 3887fe2f639SDominik Brodowski 3897fe2f639SDominik Brodowski /* --related-cpus / -r */ 3907fe2f639SDominik Brodowski 391a1ce5ba2SDominik Brodowski static int get_related_cpus(unsigned int cpu) 392a1ce5ba2SDominik Brodowski { 3937fe2f639SDominik Brodowski struct cpufreq_affected_cpus *cpus = cpufreq_get_related_cpus(cpu); 394562e5f1aSJacob Tanenbaum 395562e5f1aSJacob Tanenbaum printf(_(" CPUs which run at the same hardware frequency: ")); 396562e5f1aSJacob Tanenbaum if (!cpus) { 397562e5f1aSJacob Tanenbaum printf(_("Not Available\n")); 3987fe2f639SDominik Brodowski return -EINVAL; 399562e5f1aSJacob Tanenbaum } 4007fe2f639SDominik Brodowski 4017fe2f639SDominik Brodowski while (cpus->next) { 4027fe2f639SDominik Brodowski printf("%d ", cpus->cpu); 4037fe2f639SDominik Brodowski cpus = cpus->next; 4047fe2f639SDominik Brodowski } 4057fe2f639SDominik Brodowski printf("%d\n", cpus->cpu); 4067fe2f639SDominik Brodowski cpufreq_put_related_cpus(cpus); 4077fe2f639SDominik Brodowski return 0; 4087fe2f639SDominik Brodowski } 4097fe2f639SDominik Brodowski 4107fe2f639SDominik Brodowski /* --stats / -s */ 4117fe2f639SDominik Brodowski 412a1ce5ba2SDominik Brodowski static int get_freq_stats(unsigned int cpu, unsigned int human) 413a1ce5ba2SDominik Brodowski { 4147fe2f639SDominik Brodowski unsigned long total_trans = cpufreq_get_transitions(cpu); 4157fe2f639SDominik Brodowski unsigned long long total_time; 4167fe2f639SDominik Brodowski struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time); 4177fe2f639SDominik Brodowski while (stats) { 4187fe2f639SDominik Brodowski if (human) { 4197fe2f639SDominik Brodowski print_speed(stats->frequency); 420a1ce5ba2SDominik Brodowski printf(":%.2f%%", 421a1ce5ba2SDominik Brodowski (100.0 * stats->time_in_state) / total_time); 422a1ce5ba2SDominik Brodowski } else 423a1ce5ba2SDominik Brodowski printf("%lu:%llu", 424a1ce5ba2SDominik Brodowski stats->frequency, stats->time_in_state); 4257fe2f639SDominik Brodowski stats = stats->next; 4267fe2f639SDominik Brodowski if (stats) 4277fe2f639SDominik Brodowski printf(", "); 4287fe2f639SDominik Brodowski } 4297fe2f639SDominik Brodowski cpufreq_put_stats(stats); 4307fe2f639SDominik Brodowski if (total_trans) 4317fe2f639SDominik Brodowski printf(" (%lu)\n", total_trans); 4327fe2f639SDominik Brodowski return 0; 4337fe2f639SDominik Brodowski } 4347fe2f639SDominik Brodowski 4357fe2f639SDominik Brodowski /* --latency / -y */ 4367fe2f639SDominik Brodowski 437a1ce5ba2SDominik Brodowski static int get_latency(unsigned int cpu, unsigned int human) 438a1ce5ba2SDominik Brodowski { 4397fe2f639SDominik Brodowski unsigned long latency = cpufreq_get_transition_latency(cpu); 440562e5f1aSJacob Tanenbaum 441562e5f1aSJacob Tanenbaum printf(_(" maximum transition latency: ")); 442e98f033fSJacob Tanenbaum if (!latency || latency == UINT_MAX) { 443e98f033fSJacob Tanenbaum printf(_(" Cannot determine or is not supported.\n")); 4447fe2f639SDominik Brodowski return -EINVAL; 445562e5f1aSJacob Tanenbaum } 4467fe2f639SDominik Brodowski 4477fe2f639SDominik Brodowski if (human) { 4487fe2f639SDominik Brodowski print_duration(latency); 4497fe2f639SDominik Brodowski printf("\n"); 4507fe2f639SDominik Brodowski } else 4517fe2f639SDominik Brodowski printf("%lu\n", latency); 4527fe2f639SDominik Brodowski return 0; 4537fe2f639SDominik Brodowski } 4547fe2f639SDominik Brodowski 455562e5f1aSJacob Tanenbaum static void debug_output_one(unsigned int cpu) 456562e5f1aSJacob Tanenbaum { 457562e5f1aSJacob Tanenbaum struct cpufreq_available_frequencies *freqs; 458562e5f1aSJacob Tanenbaum 459562e5f1aSJacob Tanenbaum get_driver(cpu); 460562e5f1aSJacob Tanenbaum get_related_cpus(cpu); 461562e5f1aSJacob Tanenbaum get_affected_cpus(cpu); 462562e5f1aSJacob Tanenbaum get_latency(cpu, 1); 4634da39cebSStafford Horne get_hardware_limits(cpu, 1); 464562e5f1aSJacob Tanenbaum 465562e5f1aSJacob Tanenbaum freqs = cpufreq_get_available_frequencies(cpu); 466562e5f1aSJacob Tanenbaum if (freqs) { 467562e5f1aSJacob Tanenbaum printf(_(" available frequency steps: ")); 468562e5f1aSJacob Tanenbaum while (freqs->next) { 469562e5f1aSJacob Tanenbaum print_speed(freqs->frequency); 470562e5f1aSJacob Tanenbaum printf(", "); 471562e5f1aSJacob Tanenbaum freqs = freqs->next; 472562e5f1aSJacob Tanenbaum } 473562e5f1aSJacob Tanenbaum print_speed(freqs->frequency); 474562e5f1aSJacob Tanenbaum printf("\n"); 475562e5f1aSJacob Tanenbaum cpufreq_put_available_frequencies(freqs); 476562e5f1aSJacob Tanenbaum } 477562e5f1aSJacob Tanenbaum 478562e5f1aSJacob Tanenbaum get_available_governors(cpu); 479562e5f1aSJacob Tanenbaum get_policy(cpu); 480562e5f1aSJacob Tanenbaum if (get_freq_hardware(cpu, 1) < 0) 481562e5f1aSJacob Tanenbaum get_freq_kernel(cpu, 1); 482562e5f1aSJacob Tanenbaum get_boost_mode(cpu); 483562e5f1aSJacob Tanenbaum } 484562e5f1aSJacob Tanenbaum 4857fe2f639SDominik Brodowski static struct option info_opts[] = { 48657ab3b08SSriram Raghunathan {"debug", no_argument, NULL, 'e'}, 48757ab3b08SSriram Raghunathan {"boost", no_argument, NULL, 'b'}, 48857ab3b08SSriram Raghunathan {"freq", no_argument, NULL, 'f'}, 48957ab3b08SSriram Raghunathan {"hwfreq", no_argument, NULL, 'w'}, 49057ab3b08SSriram Raghunathan {"hwlimits", no_argument, NULL, 'l'}, 49157ab3b08SSriram Raghunathan {"driver", no_argument, NULL, 'd'}, 49257ab3b08SSriram Raghunathan {"policy", no_argument, NULL, 'p'}, 49357ab3b08SSriram Raghunathan {"governors", no_argument, NULL, 'g'}, 49457ab3b08SSriram Raghunathan {"related-cpus", no_argument, NULL, 'r'}, 49557ab3b08SSriram Raghunathan {"affected-cpus", no_argument, NULL, 'a'}, 49657ab3b08SSriram Raghunathan {"stats", no_argument, NULL, 's'}, 49757ab3b08SSriram Raghunathan {"latency", no_argument, NULL, 'y'}, 49857ab3b08SSriram Raghunathan {"proc", no_argument, NULL, 'o'}, 49957ab3b08SSriram Raghunathan {"human", no_argument, NULL, 'm'}, 50057ab3b08SSriram Raghunathan {"no-rounding", no_argument, NULL, 'n'}, 5017fe2f639SDominik Brodowski { }, 5027fe2f639SDominik Brodowski }; 5037fe2f639SDominik Brodowski 5047fe2f639SDominik Brodowski int cmd_freq_info(int argc, char **argv) 5057fe2f639SDominik Brodowski { 5067fe2f639SDominik Brodowski extern char *optarg; 5077fe2f639SDominik Brodowski extern int optind, opterr, optopt; 5087fe2f639SDominik Brodowski int ret = 0, cont = 1; 5097fe2f639SDominik Brodowski unsigned int cpu = 0; 5107fe2f639SDominik Brodowski unsigned int human = 0; 5117fe2f639SDominik Brodowski int output_param = 0; 5127fe2f639SDominik Brodowski 5137fe2f639SDominik Brodowski do { 514e091abc7SPrarit Bhargava ret = getopt_long(argc, argv, "oefwldpgrasmybn", info_opts, 515e091abc7SPrarit Bhargava NULL); 5167fe2f639SDominik Brodowski switch (ret) { 5177fe2f639SDominik Brodowski case '?': 5187fe2f639SDominik Brodowski output_param = '?'; 5197fe2f639SDominik Brodowski cont = 0; 5207fe2f639SDominik Brodowski break; 5217fe2f639SDominik Brodowski case -1: 5227fe2f639SDominik Brodowski cont = 0; 5237fe2f639SDominik Brodowski break; 5247fe2f639SDominik Brodowski case 'b': 5257fe2f639SDominik Brodowski case 'o': 5267fe2f639SDominik Brodowski case 'a': 5277fe2f639SDominik Brodowski case 'r': 5287fe2f639SDominik Brodowski case 'g': 5297fe2f639SDominik Brodowski case 'p': 5307fe2f639SDominik Brodowski case 'd': 5317fe2f639SDominik Brodowski case 'l': 5327fe2f639SDominik Brodowski case 'w': 5337fe2f639SDominik Brodowski case 'f': 5347fe2f639SDominik Brodowski case 'e': 5357fe2f639SDominik Brodowski case 's': 5367fe2f639SDominik Brodowski case 'y': 5377fe2f639SDominik Brodowski if (output_param) { 5387fe2f639SDominik Brodowski output_param = -1; 5397fe2f639SDominik Brodowski cont = 0; 5407fe2f639SDominik Brodowski break; 5417fe2f639SDominik Brodowski } 5427fe2f639SDominik Brodowski output_param = ret; 5437fe2f639SDominik Brodowski break; 5447fe2f639SDominik Brodowski case 'm': 5457fe2f639SDominik Brodowski if (human) { 5467fe2f639SDominik Brodowski output_param = -1; 5477fe2f639SDominik Brodowski cont = 0; 5487fe2f639SDominik Brodowski break; 5497fe2f639SDominik Brodowski } 5507fe2f639SDominik Brodowski human = 1; 5517fe2f639SDominik Brodowski break; 552e091abc7SPrarit Bhargava case 'n': 553e091abc7SPrarit Bhargava no_rounding = 1; 554e091abc7SPrarit Bhargava break; 5557fe2f639SDominik Brodowski default: 5567fe2f639SDominik Brodowski fprintf(stderr, "invalid or unknown argument\n"); 5577fe2f639SDominik Brodowski return EXIT_FAILURE; 5587fe2f639SDominik Brodowski } 5597fe2f639SDominik Brodowski } while (cont); 5607fe2f639SDominik Brodowski 5617fe2f639SDominik Brodowski switch (output_param) { 5627fe2f639SDominik Brodowski case 'o': 5637fe2f639SDominik Brodowski if (!bitmask_isallclear(cpus_chosen)) { 5647fe2f639SDominik Brodowski printf(_("The argument passed to this tool can't be " 5657fe2f639SDominik Brodowski "combined with passing a --cpu argument\n")); 5667fe2f639SDominik Brodowski return -EINVAL; 5677fe2f639SDominik Brodowski } 5687fe2f639SDominik Brodowski break; 5697fe2f639SDominik Brodowski case 0: 5707fe2f639SDominik Brodowski output_param = 'e'; 5717fe2f639SDominik Brodowski } 5727fe2f639SDominik Brodowski 5737fe2f639SDominik Brodowski ret = 0; 5747fe2f639SDominik Brodowski 5757fe2f639SDominik Brodowski /* Default is: show output of CPU 0 only */ 5767fe2f639SDominik Brodowski if (bitmask_isallclear(cpus_chosen)) 5777fe2f639SDominik Brodowski bitmask_setbit(cpus_chosen, 0); 5787fe2f639SDominik Brodowski 5797fe2f639SDominik Brodowski switch (output_param) { 5807fe2f639SDominik Brodowski case -1: 5817fe2f639SDominik Brodowski printf(_("You can't specify more than one --cpu parameter and/or\n" 5827fe2f639SDominik Brodowski "more than one output-specific argument\n")); 5837fe2f639SDominik Brodowski return -EINVAL; 5847fe2f639SDominik Brodowski case '?': 5857fe2f639SDominik Brodowski printf(_("invalid or unknown argument\n")); 5867fe2f639SDominik Brodowski return -EINVAL; 5877fe2f639SDominik Brodowski case 'o': 5887fe2f639SDominik Brodowski proc_cpufreq_output(); 5897fe2f639SDominik Brodowski return EXIT_SUCCESS; 5907fe2f639SDominik Brodowski } 5917fe2f639SDominik Brodowski 5927fe2f639SDominik Brodowski for (cpu = bitmask_first(cpus_chosen); 5937fe2f639SDominik Brodowski cpu <= bitmask_last(cpus_chosen); cpu++) { 5947fe2f639SDominik Brodowski 5957fe2f639SDominik Brodowski if (!bitmask_isbitset(cpus_chosen, cpu)) 5967fe2f639SDominik Brodowski continue; 597ce512b84SThomas Renninger 598ce512b84SThomas Renninger printf(_("analyzing CPU %d:\n"), cpu); 599ce512b84SThomas Renninger 600ce512b84SThomas Renninger if (sysfs_is_cpu_online(cpu) != 1) { 601ce512b84SThomas Renninger printf(_(" *is offline\n")); 602ce512b84SThomas Renninger printf("\n"); 6037fe2f639SDominik Brodowski continue; 6047fe2f639SDominik Brodowski } 6057fe2f639SDominik Brodowski 6067fe2f639SDominik Brodowski switch (output_param) { 6077fe2f639SDominik Brodowski case 'b': 6087fe2f639SDominik Brodowski get_boost_mode(cpu); 6097fe2f639SDominik Brodowski break; 6107fe2f639SDominik Brodowski case 'e': 6117fe2f639SDominik Brodowski debug_output_one(cpu); 6127fe2f639SDominik Brodowski break; 6137fe2f639SDominik Brodowski case 'a': 6147fe2f639SDominik Brodowski ret = get_affected_cpus(cpu); 6157fe2f639SDominik Brodowski break; 6167fe2f639SDominik Brodowski case 'r': 6177fe2f639SDominik Brodowski ret = get_related_cpus(cpu); 6187fe2f639SDominik Brodowski break; 6197fe2f639SDominik Brodowski case 'g': 6207fe2f639SDominik Brodowski ret = get_available_governors(cpu); 6217fe2f639SDominik Brodowski break; 6227fe2f639SDominik Brodowski case 'p': 6237fe2f639SDominik Brodowski ret = get_policy(cpu); 6247fe2f639SDominik Brodowski break; 6257fe2f639SDominik Brodowski case 'd': 6267fe2f639SDominik Brodowski ret = get_driver(cpu); 6277fe2f639SDominik Brodowski break; 6287fe2f639SDominik Brodowski case 'l': 6294da39cebSStafford Horne ret = get_hardware_limits(cpu, human); 6307fe2f639SDominik Brodowski break; 6317fe2f639SDominik Brodowski case 'w': 6327fe2f639SDominik Brodowski ret = get_freq_hardware(cpu, human); 6337fe2f639SDominik Brodowski break; 6347fe2f639SDominik Brodowski case 'f': 6357fe2f639SDominik Brodowski ret = get_freq_kernel(cpu, human); 6367fe2f639SDominik Brodowski break; 6377fe2f639SDominik Brodowski case 's': 6387fe2f639SDominik Brodowski ret = get_freq_stats(cpu, human); 6397fe2f639SDominik Brodowski break; 6407fe2f639SDominik Brodowski case 'y': 6417fe2f639SDominik Brodowski ret = get_latency(cpu, human); 6427fe2f639SDominik Brodowski break; 6437fe2f639SDominik Brodowski } 6447fe2f639SDominik Brodowski if (ret) 645a1ce5ba2SDominik Brodowski return ret; 6467fe2f639SDominik Brodowski } 6477fe2f639SDominik Brodowski return ret; 6487fe2f639SDominik Brodowski } 649