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> 137fe2f639SDominik Brodowski 147fe2f639SDominik Brodowski #include <getopt.h> 157fe2f639SDominik Brodowski 167fe2f639SDominik Brodowski #include "cpufreq.h" 17ce512b84SThomas Renninger #include "helpers/sysfs.h" 187fe2f639SDominik Brodowski #include "helpers/helpers.h" 197fe2f639SDominik Brodowski #include "helpers/bitmask.h" 207fe2f639SDominik Brodowski 217fe2f639SDominik Brodowski #define LINE_LEN 10 227fe2f639SDominik Brodowski 237fe2f639SDominik Brodowski static unsigned int count_cpus(void) 247fe2f639SDominik Brodowski { 257fe2f639SDominik Brodowski FILE *fp; 267fe2f639SDominik Brodowski char value[LINE_LEN]; 277fe2f639SDominik Brodowski unsigned int ret = 0; 287fe2f639SDominik Brodowski unsigned int cpunr = 0; 297fe2f639SDominik Brodowski 307fe2f639SDominik Brodowski fp = fopen("/proc/stat", "r"); 317fe2f639SDominik Brodowski if (!fp) { 327fe2f639SDominik Brodowski printf(_("Couldn't count the number of CPUs (%s: %s), assuming 1\n"), "/proc/stat", strerror(errno)); 337fe2f639SDominik Brodowski return 1; 347fe2f639SDominik Brodowski } 357fe2f639SDominik Brodowski 367fe2f639SDominik Brodowski while (!feof(fp)) { 377fe2f639SDominik Brodowski if (!fgets(value, LINE_LEN, fp)) 387fe2f639SDominik Brodowski continue; 397fe2f639SDominik Brodowski value[LINE_LEN - 1] = '\0'; 407fe2f639SDominik Brodowski if (strlen(value) < (LINE_LEN - 2)) 417fe2f639SDominik Brodowski continue; 427fe2f639SDominik Brodowski if (strstr(value, "cpu ")) 437fe2f639SDominik Brodowski continue; 447fe2f639SDominik Brodowski if (sscanf(value, "cpu%d ", &cpunr) != 1) 457fe2f639SDominik Brodowski continue; 467fe2f639SDominik Brodowski if (cpunr > ret) 477fe2f639SDominik Brodowski ret = cpunr; 487fe2f639SDominik Brodowski } 497fe2f639SDominik Brodowski fclose(fp); 507fe2f639SDominik Brodowski 517fe2f639SDominik Brodowski /* cpu count starts from 0, on error return 1 (UP) */ 52a1ce5ba2SDominik Brodowski return ret + 1; 537fe2f639SDominik Brodowski } 547fe2f639SDominik Brodowski 557fe2f639SDominik Brodowski 567fe2f639SDominik Brodowski static void proc_cpufreq_output(void) 577fe2f639SDominik Brodowski { 587fe2f639SDominik Brodowski unsigned int cpu, nr_cpus; 597fe2f639SDominik Brodowski struct cpufreq_policy *policy; 607fe2f639SDominik Brodowski unsigned int min_pctg = 0; 617fe2f639SDominik Brodowski unsigned int max_pctg = 0; 627fe2f639SDominik Brodowski unsigned long min, max; 637fe2f639SDominik Brodowski 647fe2f639SDominik Brodowski printf(_(" minimum CPU frequency - maximum CPU frequency - governor\n")); 657fe2f639SDominik Brodowski 667fe2f639SDominik Brodowski nr_cpus = count_cpus(); 677fe2f639SDominik Brodowski for (cpu = 0; cpu < nr_cpus; cpu++) { 687fe2f639SDominik Brodowski policy = cpufreq_get_policy(cpu); 697fe2f639SDominik Brodowski if (!policy) 707fe2f639SDominik Brodowski continue; 717fe2f639SDominik Brodowski 727fe2f639SDominik Brodowski if (cpufreq_get_hardware_limits(cpu, &min, &max)) { 737fe2f639SDominik Brodowski max = 0; 747fe2f639SDominik Brodowski } else { 757fe2f639SDominik Brodowski min_pctg = (policy->min * 100) / max; 767fe2f639SDominik Brodowski max_pctg = (policy->max * 100) / max; 777fe2f639SDominik Brodowski } 787fe2f639SDominik Brodowski printf("CPU%3d %9lu kHz (%3d %%) - %9lu kHz (%3d %%) - %s\n", 79a1ce5ba2SDominik Brodowski cpu , policy->min, max ? min_pctg : 0, policy->max, 80a1ce5ba2SDominik Brodowski max ? max_pctg : 0, policy->governor); 817fe2f639SDominik Brodowski 827fe2f639SDominik Brodowski cpufreq_put_policy(policy); 837fe2f639SDominik Brodowski } 847fe2f639SDominik Brodowski } 857fe2f639SDominik Brodowski 86e091abc7SPrarit Bhargava static int no_rounding; 877fe2f639SDominik Brodowski static void print_speed(unsigned long speed) 887fe2f639SDominik Brodowski { 897fe2f639SDominik Brodowski unsigned long tmp; 907fe2f639SDominik Brodowski 91e091abc7SPrarit Bhargava if (no_rounding) { 92e091abc7SPrarit Bhargava if (speed > 1000000) 93e091abc7SPrarit Bhargava printf("%u.%06u GHz", ((unsigned int) speed/1000000), 94e091abc7SPrarit Bhargava ((unsigned int) speed%1000000)); 95e091abc7SPrarit Bhargava else if (speed > 100000) 96e091abc7SPrarit Bhargava printf("%u MHz", (unsigned int) speed); 97e091abc7SPrarit Bhargava else if (speed > 1000) 98e091abc7SPrarit Bhargava printf("%u.%03u MHz", ((unsigned int) speed/1000), 99e091abc7SPrarit Bhargava (unsigned int) (speed%1000)); 100e091abc7SPrarit Bhargava else 101e091abc7SPrarit Bhargava printf("%lu kHz", speed); 102e091abc7SPrarit Bhargava } else { 1037fe2f639SDominik Brodowski if (speed > 1000000) { 1047fe2f639SDominik Brodowski tmp = speed%10000; 1057fe2f639SDominik Brodowski if (tmp >= 5000) 1067fe2f639SDominik Brodowski speed += 10000; 1077fe2f639SDominik Brodowski printf("%u.%02u GHz", ((unsigned int) speed/1000000), 1087fe2f639SDominik Brodowski ((unsigned int) (speed%1000000)/10000)); 1097fe2f639SDominik Brodowski } else if (speed > 100000) { 1107fe2f639SDominik Brodowski tmp = speed%1000; 1117fe2f639SDominik Brodowski if (tmp >= 500) 1127fe2f639SDominik Brodowski speed += 1000; 1137fe2f639SDominik Brodowski printf("%u MHz", ((unsigned int) speed/1000)); 1147fe2f639SDominik Brodowski } else if (speed > 1000) { 1157fe2f639SDominik Brodowski tmp = speed%100; 1167fe2f639SDominik Brodowski if (tmp >= 50) 1177fe2f639SDominik Brodowski speed += 100; 1187fe2f639SDominik Brodowski printf("%u.%01u MHz", ((unsigned int) speed/1000), 1197fe2f639SDominik Brodowski ((unsigned int) (speed%1000)/100)); 120e091abc7SPrarit Bhargava } 121e091abc7SPrarit Bhargava } 1227fe2f639SDominik Brodowski 1237fe2f639SDominik Brodowski return; 1247fe2f639SDominik Brodowski } 1257fe2f639SDominik Brodowski 1267fe2f639SDominik Brodowski static void print_duration(unsigned long duration) 1277fe2f639SDominik Brodowski { 1287fe2f639SDominik Brodowski unsigned long tmp; 1297fe2f639SDominik Brodowski 130e091abc7SPrarit Bhargava if (no_rounding) { 131e091abc7SPrarit Bhargava if (duration > 1000000) 132e091abc7SPrarit Bhargava printf("%u.%06u ms", ((unsigned int) duration/1000000), 133e091abc7SPrarit Bhargava ((unsigned int) duration%1000000)); 134e091abc7SPrarit Bhargava else if (duration > 100000) 135e091abc7SPrarit Bhargava printf("%u us", ((unsigned int) duration/1000)); 136e091abc7SPrarit Bhargava else if (duration > 1000) 137e091abc7SPrarit Bhargava printf("%u.%03u us", ((unsigned int) duration/1000), 138e091abc7SPrarit Bhargava ((unsigned int) duration%1000)); 139e091abc7SPrarit Bhargava else 140e091abc7SPrarit Bhargava printf("%lu ns", duration); 141e091abc7SPrarit Bhargava } else { 1427fe2f639SDominik Brodowski if (duration > 1000000) { 1437fe2f639SDominik Brodowski tmp = duration%10000; 1447fe2f639SDominik Brodowski if (tmp >= 5000) 1457fe2f639SDominik Brodowski duration += 10000; 1467fe2f639SDominik Brodowski printf("%u.%02u ms", ((unsigned int) duration/1000000), 1477fe2f639SDominik Brodowski ((unsigned int) (duration%1000000)/10000)); 1487fe2f639SDominik Brodowski } else if (duration > 100000) { 1497fe2f639SDominik Brodowski tmp = duration%1000; 1507fe2f639SDominik Brodowski if (tmp >= 500) 1517fe2f639SDominik Brodowski duration += 1000; 1527fe2f639SDominik Brodowski printf("%u us", ((unsigned int) duration / 1000)); 1537fe2f639SDominik Brodowski } else if (duration > 1000) { 1547fe2f639SDominik Brodowski tmp = duration%100; 1557fe2f639SDominik Brodowski if (tmp >= 50) 1567fe2f639SDominik Brodowski duration += 100; 1577fe2f639SDominik Brodowski printf("%u.%01u us", ((unsigned int) duration/1000), 1587fe2f639SDominik Brodowski ((unsigned int) (duration%1000)/100)); 1597fe2f639SDominik Brodowski } else 1607fe2f639SDominik Brodowski printf("%lu ns", duration); 161e091abc7SPrarit Bhargava } 1627fe2f639SDominik Brodowski return; 1637fe2f639SDominik Brodowski } 1647fe2f639SDominik Brodowski 1657fe2f639SDominik Brodowski /* --boost / -b */ 1667fe2f639SDominik Brodowski 167a1ce5ba2SDominik Brodowski static int get_boost_mode(unsigned int cpu) 168a1ce5ba2SDominik Brodowski { 1697fe2f639SDominik Brodowski int support, active, b_states = 0, ret, pstate_no, i; 1707fe2f639SDominik Brodowski /* ToDo: Make this more global */ 1717fe2f639SDominik Brodowski unsigned long pstates[MAX_HW_PSTATES] = {0,}; 1727fe2f639SDominik Brodowski 1737fe2f639SDominik Brodowski if (cpupower_cpu_info.vendor != X86_VENDOR_AMD && 1747fe2f639SDominik Brodowski cpupower_cpu_info.vendor != X86_VENDOR_INTEL) 1757fe2f639SDominik Brodowski return 0; 1767fe2f639SDominik Brodowski 1777fe2f639SDominik Brodowski ret = cpufreq_has_boost_support(cpu, &support, &active, &b_states); 1787fe2f639SDominik Brodowski if (ret) { 1797fe2f639SDominik Brodowski printf(_("Error while evaluating Boost Capabilities" 1807fe2f639SDominik Brodowski " on CPU %d -- are you root?\n"), cpu); 1817fe2f639SDominik Brodowski return ret; 1827fe2f639SDominik Brodowski } 1837fe2f639SDominik Brodowski /* P state changes via MSR are identified via cpuid 80000007 1847fe2f639SDominik Brodowski on Intel and AMD, but we assume boost capable machines can do that 1857fe2f639SDominik Brodowski if (cpuid_eax(0x80000000) >= 0x80000007 1867fe2f639SDominik Brodowski && (cpuid_edx(0x80000007) & (1 << 7))) 1877fe2f639SDominik Brodowski */ 1887fe2f639SDominik Brodowski 1897fe2f639SDominik Brodowski printf(_(" boost state support:\n")); 1907fe2f639SDominik Brodowski 1917fe2f639SDominik Brodowski printf(_(" Supported: %s\n"), support ? _("yes") : _("no")); 1927fe2f639SDominik Brodowski printf(_(" Active: %s\n"), active ? _("yes") : _("no")); 1937fe2f639SDominik Brodowski 1947fe2f639SDominik Brodowski if (cpupower_cpu_info.vendor == X86_VENDOR_AMD && 1957fe2f639SDominik Brodowski cpupower_cpu_info.family >= 0x10) { 1967fe2f639SDominik Brodowski ret = decode_pstates(cpu, cpupower_cpu_info.family, b_states, 1977fe2f639SDominik Brodowski pstates, &pstate_no); 1987fe2f639SDominik Brodowski if (ret) 1997fe2f639SDominik Brodowski return ret; 2007fe2f639SDominik Brodowski 2017fe2f639SDominik Brodowski printf(_(" Boost States: %d\n"), b_states); 2027fe2f639SDominik Brodowski printf(_(" Total States: %d\n"), pstate_no); 2037fe2f639SDominik Brodowski for (i = 0; i < pstate_no; i++) { 2047fe2f639SDominik Brodowski if (i < b_states) 2058fb2e440SThomas Renninger printf(_(" Pstate-Pb%d: %luMHz (boost state)" 2068fb2e440SThomas Renninger "\n"), i, pstates[i]); 2077fe2f639SDominik Brodowski else 2087fe2f639SDominik Brodowski printf(_(" Pstate-P%d: %luMHz\n"), 2097fe2f639SDominik Brodowski i - b_states, pstates[i]); 2107fe2f639SDominik Brodowski } 2118fb2e440SThomas Renninger } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_HAS_TURBO_RATIO) { 2128fb2e440SThomas Renninger double bclk; 2138fb2e440SThomas Renninger unsigned long long intel_turbo_ratio = 0; 2148fb2e440SThomas Renninger unsigned int ratio; 2158fb2e440SThomas Renninger 2168fb2e440SThomas Renninger /* Any way to autodetect this ? */ 2178fb2e440SThomas Renninger if (cpupower_cpu_info.caps & CPUPOWER_CAP_IS_SNB) 2188fb2e440SThomas Renninger bclk = 100.00; 2198fb2e440SThomas Renninger else 2208fb2e440SThomas Renninger bclk = 133.33; 2218fb2e440SThomas Renninger intel_turbo_ratio = msr_intel_get_turbo_ratio(cpu); 2228fb2e440SThomas Renninger dprint (" Ratio: 0x%llx - bclk: %f\n", 2238fb2e440SThomas Renninger intel_turbo_ratio, bclk); 2248fb2e440SThomas Renninger 2258fb2e440SThomas Renninger ratio = (intel_turbo_ratio >> 24) & 0xFF; 2268fb2e440SThomas Renninger if (ratio) 2278fb2e440SThomas Renninger printf(_(" %.0f MHz max turbo 4 active cores\n"), 2288fb2e440SThomas Renninger ratio * bclk); 2298fb2e440SThomas Renninger 2308fb2e440SThomas Renninger ratio = (intel_turbo_ratio >> 16) & 0xFF; 2318fb2e440SThomas Renninger if (ratio) 2328fb2e440SThomas Renninger printf(_(" %.0f MHz max turbo 3 active cores\n"), 2338fb2e440SThomas Renninger ratio * bclk); 2348fb2e440SThomas Renninger 2358fb2e440SThomas Renninger ratio = (intel_turbo_ratio >> 8) & 0xFF; 2368fb2e440SThomas Renninger if (ratio) 2378fb2e440SThomas Renninger printf(_(" %.0f MHz max turbo 2 active cores\n"), 2388fb2e440SThomas Renninger ratio * bclk); 2398fb2e440SThomas Renninger 2408fb2e440SThomas Renninger ratio = (intel_turbo_ratio >> 0) & 0xFF; 2418fb2e440SThomas Renninger if (ratio) 2428fb2e440SThomas Renninger printf(_(" %.0f MHz max turbo 1 active cores\n"), 2438fb2e440SThomas Renninger ratio * bclk); 2448fb2e440SThomas Renninger } 2457fe2f639SDominik Brodowski return 0; 2467fe2f639SDominik Brodowski } 2477fe2f639SDominik Brodowski 2487fe2f639SDominik Brodowski /* --freq / -f */ 2497fe2f639SDominik Brodowski 250a1ce5ba2SDominik Brodowski static int get_freq_kernel(unsigned int cpu, unsigned int human) 251a1ce5ba2SDominik Brodowski { 2527fe2f639SDominik Brodowski unsigned long freq = cpufreq_get_freq_kernel(cpu); 253562e5f1aSJacob Tanenbaum printf(_(" current CPU frequency: ")); 254562e5f1aSJacob Tanenbaum if (!freq) { 255562e5f1aSJacob Tanenbaum printf(_(" Unable to call to kernel\n")); 2567fe2f639SDominik Brodowski return -EINVAL; 257562e5f1aSJacob Tanenbaum } 2587fe2f639SDominik Brodowski if (human) { 2597fe2f639SDominik Brodowski print_speed(freq); 2607fe2f639SDominik Brodowski } else 261562e5f1aSJacob Tanenbaum printf("%lu", freq); 262562e5f1aSJacob Tanenbaum printf(_(" (asserted by call to kernel)\n")); 2637fe2f639SDominik Brodowski return 0; 2647fe2f639SDominik Brodowski } 2657fe2f639SDominik Brodowski 2667fe2f639SDominik Brodowski 2677fe2f639SDominik Brodowski /* --hwfreq / -w */ 2687fe2f639SDominik Brodowski 269a1ce5ba2SDominik Brodowski static int get_freq_hardware(unsigned int cpu, unsigned int human) 270a1ce5ba2SDominik Brodowski { 2717fe2f639SDominik Brodowski unsigned long freq = cpufreq_get_freq_hardware(cpu); 272562e5f1aSJacob Tanenbaum printf(_(" current CPU frequency: ")); 273562e5f1aSJacob Tanenbaum if (!freq) { 274562e5f1aSJacob Tanenbaum printf("Unable to call hardware\n"); 2757fe2f639SDominik Brodowski return -EINVAL; 276562e5f1aSJacob Tanenbaum } 2777fe2f639SDominik Brodowski if (human) { 2787fe2f639SDominik Brodowski print_speed(freq); 2797fe2f639SDominik Brodowski } else 280562e5f1aSJacob Tanenbaum printf("%lu", freq); 281562e5f1aSJacob Tanenbaum printf(_(" (asserted by call to hardware)\n")); 2827fe2f639SDominik Brodowski return 0; 2837fe2f639SDominik Brodowski } 2847fe2f639SDominik Brodowski 2857fe2f639SDominik Brodowski /* --hwlimits / -l */ 2867fe2f639SDominik Brodowski 287a1ce5ba2SDominik Brodowski static int get_hardware_limits(unsigned int cpu) 288a1ce5ba2SDominik Brodowski { 2897fe2f639SDominik Brodowski unsigned long min, max; 290562e5f1aSJacob Tanenbaum 291562e5f1aSJacob Tanenbaum printf(_(" hardware limits: ")); 292562e5f1aSJacob Tanenbaum if (cpufreq_get_hardware_limits(cpu, &min, &max)) { 293562e5f1aSJacob Tanenbaum printf(_("Not Available\n")); 2947fe2f639SDominik Brodowski return -EINVAL; 295562e5f1aSJacob Tanenbaum } 296562e5f1aSJacob Tanenbaum 297562e5f1aSJacob Tanenbaum print_speed(min); 298562e5f1aSJacob Tanenbaum printf(" - "); 299562e5f1aSJacob Tanenbaum print_speed(max); 300562e5f1aSJacob Tanenbaum printf("\n"); 3017fe2f639SDominik Brodowski return 0; 3027fe2f639SDominik Brodowski } 3037fe2f639SDominik Brodowski 3047fe2f639SDominik Brodowski /* --driver / -d */ 3057fe2f639SDominik Brodowski 306a1ce5ba2SDominik Brodowski static int get_driver(unsigned int cpu) 307a1ce5ba2SDominik Brodowski { 3087fe2f639SDominik Brodowski char *driver = cpufreq_get_driver(cpu); 309562e5f1aSJacob Tanenbaum if (!driver) { 310562e5f1aSJacob Tanenbaum printf(_(" no or unknown cpufreq driver is active on this CPU\n")); 3117fe2f639SDominik Brodowski return -EINVAL; 312562e5f1aSJacob Tanenbaum } 313562e5f1aSJacob Tanenbaum printf(" driver: %s\n", driver); 3147fe2f639SDominik Brodowski cpufreq_put_driver(driver); 3157fe2f639SDominik Brodowski return 0; 3167fe2f639SDominik Brodowski } 3177fe2f639SDominik Brodowski 3187fe2f639SDominik Brodowski /* --policy / -p */ 3197fe2f639SDominik Brodowski 320a1ce5ba2SDominik Brodowski static int get_policy(unsigned int cpu) 321a1ce5ba2SDominik Brodowski { 3227fe2f639SDominik Brodowski struct cpufreq_policy *policy = cpufreq_get_policy(cpu); 323562e5f1aSJacob Tanenbaum if (!policy) { 324562e5f1aSJacob Tanenbaum printf(_(" Unable to determine current policy\n")); 3257fe2f639SDominik Brodowski return -EINVAL; 326562e5f1aSJacob Tanenbaum } 327562e5f1aSJacob Tanenbaum printf(_(" current policy: frequency should be within ")); 328562e5f1aSJacob Tanenbaum print_speed(policy->min); 329562e5f1aSJacob Tanenbaum printf(_(" and ")); 330562e5f1aSJacob Tanenbaum print_speed(policy->max); 331562e5f1aSJacob Tanenbaum 332562e5f1aSJacob Tanenbaum printf(".\n "); 333562e5f1aSJacob Tanenbaum printf(_("The governor \"%s\" may decide which speed to use\n" 334562e5f1aSJacob Tanenbaum " within this range.\n"), 335562e5f1aSJacob Tanenbaum policy->governor); 3367fe2f639SDominik Brodowski cpufreq_put_policy(policy); 3377fe2f639SDominik Brodowski return 0; 3387fe2f639SDominik Brodowski } 3397fe2f639SDominik Brodowski 3407fe2f639SDominik Brodowski /* --governors / -g */ 3417fe2f639SDominik Brodowski 342a1ce5ba2SDominik Brodowski static int get_available_governors(unsigned int cpu) 343a1ce5ba2SDominik Brodowski { 344a1ce5ba2SDominik Brodowski struct cpufreq_available_governors *governors = 345a1ce5ba2SDominik Brodowski cpufreq_get_available_governors(cpu); 346562e5f1aSJacob Tanenbaum 347562e5f1aSJacob Tanenbaum printf(_(" available cpufreq governors: ")); 348562e5f1aSJacob Tanenbaum if (!governors) { 349562e5f1aSJacob Tanenbaum printf(_("Not Available\n")); 3507fe2f639SDominik Brodowski return -EINVAL; 351562e5f1aSJacob Tanenbaum } 3527fe2f639SDominik Brodowski 3537fe2f639SDominik Brodowski while (governors->next) { 3547fe2f639SDominik Brodowski printf("%s ", governors->governor); 3557fe2f639SDominik Brodowski governors = governors->next; 3567fe2f639SDominik Brodowski } 3577fe2f639SDominik Brodowski printf("%s\n", governors->governor); 3587fe2f639SDominik Brodowski cpufreq_put_available_governors(governors); 3597fe2f639SDominik Brodowski return 0; 3607fe2f639SDominik Brodowski } 3617fe2f639SDominik Brodowski 3627fe2f639SDominik Brodowski 3637fe2f639SDominik Brodowski /* --affected-cpus / -a */ 3647fe2f639SDominik Brodowski 365a1ce5ba2SDominik Brodowski static int get_affected_cpus(unsigned int cpu) 366a1ce5ba2SDominik Brodowski { 3677fe2f639SDominik Brodowski struct cpufreq_affected_cpus *cpus = cpufreq_get_affected_cpus(cpu); 368562e5f1aSJacob Tanenbaum 369562e5f1aSJacob Tanenbaum printf(_(" CPUs which need to have their frequency coordinated by software: ")); 370562e5f1aSJacob Tanenbaum if (!cpus) { 371562e5f1aSJacob Tanenbaum printf(_("Not Available\n")); 3727fe2f639SDominik Brodowski return -EINVAL; 373562e5f1aSJacob Tanenbaum } 3747fe2f639SDominik Brodowski 3757fe2f639SDominik Brodowski while (cpus->next) { 3767fe2f639SDominik Brodowski printf("%d ", cpus->cpu); 3777fe2f639SDominik Brodowski cpus = cpus->next; 3787fe2f639SDominik Brodowski } 3797fe2f639SDominik Brodowski printf("%d\n", cpus->cpu); 3807fe2f639SDominik Brodowski cpufreq_put_affected_cpus(cpus); 3817fe2f639SDominik Brodowski return 0; 3827fe2f639SDominik Brodowski } 3837fe2f639SDominik Brodowski 3847fe2f639SDominik Brodowski /* --related-cpus / -r */ 3857fe2f639SDominik Brodowski 386a1ce5ba2SDominik Brodowski static int get_related_cpus(unsigned int cpu) 387a1ce5ba2SDominik Brodowski { 3887fe2f639SDominik Brodowski struct cpufreq_affected_cpus *cpus = cpufreq_get_related_cpus(cpu); 389562e5f1aSJacob Tanenbaum 390562e5f1aSJacob Tanenbaum printf(_(" CPUs which run at the same hardware frequency: ")); 391562e5f1aSJacob Tanenbaum if (!cpus) { 392562e5f1aSJacob Tanenbaum printf(_("Not Available\n")); 3937fe2f639SDominik Brodowski return -EINVAL; 394562e5f1aSJacob Tanenbaum } 3957fe2f639SDominik Brodowski 3967fe2f639SDominik Brodowski while (cpus->next) { 3977fe2f639SDominik Brodowski printf("%d ", cpus->cpu); 3987fe2f639SDominik Brodowski cpus = cpus->next; 3997fe2f639SDominik Brodowski } 4007fe2f639SDominik Brodowski printf("%d\n", cpus->cpu); 4017fe2f639SDominik Brodowski cpufreq_put_related_cpus(cpus); 4027fe2f639SDominik Brodowski return 0; 4037fe2f639SDominik Brodowski } 4047fe2f639SDominik Brodowski 4057fe2f639SDominik Brodowski /* --stats / -s */ 4067fe2f639SDominik Brodowski 407a1ce5ba2SDominik Brodowski static int get_freq_stats(unsigned int cpu, unsigned int human) 408a1ce5ba2SDominik Brodowski { 4097fe2f639SDominik Brodowski unsigned long total_trans = cpufreq_get_transitions(cpu); 4107fe2f639SDominik Brodowski unsigned long long total_time; 4117fe2f639SDominik Brodowski struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time); 4127fe2f639SDominik Brodowski while (stats) { 4137fe2f639SDominik Brodowski if (human) { 4147fe2f639SDominik Brodowski print_speed(stats->frequency); 415a1ce5ba2SDominik Brodowski printf(":%.2f%%", 416a1ce5ba2SDominik Brodowski (100.0 * stats->time_in_state) / total_time); 417a1ce5ba2SDominik Brodowski } else 418a1ce5ba2SDominik Brodowski printf("%lu:%llu", 419a1ce5ba2SDominik Brodowski stats->frequency, stats->time_in_state); 4207fe2f639SDominik Brodowski stats = stats->next; 4217fe2f639SDominik Brodowski if (stats) 4227fe2f639SDominik Brodowski printf(", "); 4237fe2f639SDominik Brodowski } 4247fe2f639SDominik Brodowski cpufreq_put_stats(stats); 4257fe2f639SDominik Brodowski if (total_trans) 4267fe2f639SDominik Brodowski printf(" (%lu)\n", total_trans); 4277fe2f639SDominik Brodowski return 0; 4287fe2f639SDominik Brodowski } 4297fe2f639SDominik Brodowski 4307fe2f639SDominik Brodowski /* --latency / -y */ 4317fe2f639SDominik Brodowski 432a1ce5ba2SDominik Brodowski static int get_latency(unsigned int cpu, unsigned int human) 433a1ce5ba2SDominik Brodowski { 4347fe2f639SDominik Brodowski unsigned long latency = cpufreq_get_transition_latency(cpu); 435562e5f1aSJacob Tanenbaum 436562e5f1aSJacob Tanenbaum printf(_(" maximum transition latency: ")); 437*e98f033fSJacob Tanenbaum if (!latency || latency == UINT_MAX) { 438*e98f033fSJacob Tanenbaum printf(_(" Cannot determine or is not supported.\n")); 4397fe2f639SDominik Brodowski return -EINVAL; 440562e5f1aSJacob Tanenbaum } 4417fe2f639SDominik Brodowski 4427fe2f639SDominik Brodowski if (human) { 4437fe2f639SDominik Brodowski print_duration(latency); 4447fe2f639SDominik Brodowski printf("\n"); 4457fe2f639SDominik Brodowski } else 4467fe2f639SDominik Brodowski printf("%lu\n", latency); 4477fe2f639SDominik Brodowski return 0; 4487fe2f639SDominik Brodowski } 4497fe2f639SDominik Brodowski 450562e5f1aSJacob Tanenbaum static void debug_output_one(unsigned int cpu) 451562e5f1aSJacob Tanenbaum { 452562e5f1aSJacob Tanenbaum struct cpufreq_available_frequencies *freqs; 453562e5f1aSJacob Tanenbaum 454562e5f1aSJacob Tanenbaum get_driver(cpu); 455562e5f1aSJacob Tanenbaum get_related_cpus(cpu); 456562e5f1aSJacob Tanenbaum get_affected_cpus(cpu); 457562e5f1aSJacob Tanenbaum get_latency(cpu, 1); 458562e5f1aSJacob Tanenbaum get_hardware_limits(cpu); 459562e5f1aSJacob Tanenbaum 460562e5f1aSJacob Tanenbaum freqs = cpufreq_get_available_frequencies(cpu); 461562e5f1aSJacob Tanenbaum if (freqs) { 462562e5f1aSJacob Tanenbaum printf(_(" available frequency steps: ")); 463562e5f1aSJacob Tanenbaum while (freqs->next) { 464562e5f1aSJacob Tanenbaum print_speed(freqs->frequency); 465562e5f1aSJacob Tanenbaum printf(", "); 466562e5f1aSJacob Tanenbaum freqs = freqs->next; 467562e5f1aSJacob Tanenbaum } 468562e5f1aSJacob Tanenbaum print_speed(freqs->frequency); 469562e5f1aSJacob Tanenbaum printf("\n"); 470562e5f1aSJacob Tanenbaum cpufreq_put_available_frequencies(freqs); 471562e5f1aSJacob Tanenbaum } 472562e5f1aSJacob Tanenbaum 473562e5f1aSJacob Tanenbaum get_available_governors(cpu); 474562e5f1aSJacob Tanenbaum get_policy(cpu); 475562e5f1aSJacob Tanenbaum if (get_freq_hardware(cpu, 1) < 0) 476562e5f1aSJacob Tanenbaum get_freq_kernel(cpu, 1); 477562e5f1aSJacob Tanenbaum get_boost_mode(cpu); 478562e5f1aSJacob Tanenbaum } 479562e5f1aSJacob Tanenbaum 4807fe2f639SDominik Brodowski static struct option info_opts[] = { 48157ab3b08SSriram Raghunathan {"debug", no_argument, NULL, 'e'}, 48257ab3b08SSriram Raghunathan {"boost", no_argument, NULL, 'b'}, 48357ab3b08SSriram Raghunathan {"freq", no_argument, NULL, 'f'}, 48457ab3b08SSriram Raghunathan {"hwfreq", no_argument, NULL, 'w'}, 48557ab3b08SSriram Raghunathan {"hwlimits", no_argument, NULL, 'l'}, 48657ab3b08SSriram Raghunathan {"driver", no_argument, NULL, 'd'}, 48757ab3b08SSriram Raghunathan {"policy", no_argument, NULL, 'p'}, 48857ab3b08SSriram Raghunathan {"governors", no_argument, NULL, 'g'}, 48957ab3b08SSriram Raghunathan {"related-cpus", no_argument, NULL, 'r'}, 49057ab3b08SSriram Raghunathan {"affected-cpus", no_argument, NULL, 'a'}, 49157ab3b08SSriram Raghunathan {"stats", no_argument, NULL, 's'}, 49257ab3b08SSriram Raghunathan {"latency", no_argument, NULL, 'y'}, 49357ab3b08SSriram Raghunathan {"proc", no_argument, NULL, 'o'}, 49457ab3b08SSriram Raghunathan {"human", no_argument, NULL, 'm'}, 49557ab3b08SSriram Raghunathan {"no-rounding", no_argument, NULL, 'n'}, 4967fe2f639SDominik Brodowski { }, 4977fe2f639SDominik Brodowski }; 4987fe2f639SDominik Brodowski 4997fe2f639SDominik Brodowski int cmd_freq_info(int argc, char **argv) 5007fe2f639SDominik Brodowski { 5017fe2f639SDominik Brodowski extern char *optarg; 5027fe2f639SDominik Brodowski extern int optind, opterr, optopt; 5037fe2f639SDominik Brodowski int ret = 0, cont = 1; 5047fe2f639SDominik Brodowski unsigned int cpu = 0; 5057fe2f639SDominik Brodowski unsigned int human = 0; 5067fe2f639SDominik Brodowski int output_param = 0; 5077fe2f639SDominik Brodowski 5087fe2f639SDominik Brodowski do { 509e091abc7SPrarit Bhargava ret = getopt_long(argc, argv, "oefwldpgrasmybn", info_opts, 510e091abc7SPrarit Bhargava NULL); 5117fe2f639SDominik Brodowski switch (ret) { 5127fe2f639SDominik Brodowski case '?': 5137fe2f639SDominik Brodowski output_param = '?'; 5147fe2f639SDominik Brodowski cont = 0; 5157fe2f639SDominik Brodowski break; 5167fe2f639SDominik Brodowski case -1: 5177fe2f639SDominik Brodowski cont = 0; 5187fe2f639SDominik Brodowski break; 5197fe2f639SDominik Brodowski case 'b': 5207fe2f639SDominik Brodowski case 'o': 5217fe2f639SDominik Brodowski case 'a': 5227fe2f639SDominik Brodowski case 'r': 5237fe2f639SDominik Brodowski case 'g': 5247fe2f639SDominik Brodowski case 'p': 5257fe2f639SDominik Brodowski case 'd': 5267fe2f639SDominik Brodowski case 'l': 5277fe2f639SDominik Brodowski case 'w': 5287fe2f639SDominik Brodowski case 'f': 5297fe2f639SDominik Brodowski case 'e': 5307fe2f639SDominik Brodowski case 's': 5317fe2f639SDominik Brodowski case 'y': 5327fe2f639SDominik Brodowski if (output_param) { 5337fe2f639SDominik Brodowski output_param = -1; 5347fe2f639SDominik Brodowski cont = 0; 5357fe2f639SDominik Brodowski break; 5367fe2f639SDominik Brodowski } 5377fe2f639SDominik Brodowski output_param = ret; 5387fe2f639SDominik Brodowski break; 5397fe2f639SDominik Brodowski case 'm': 5407fe2f639SDominik Brodowski if (human) { 5417fe2f639SDominik Brodowski output_param = -1; 5427fe2f639SDominik Brodowski cont = 0; 5437fe2f639SDominik Brodowski break; 5447fe2f639SDominik Brodowski } 5457fe2f639SDominik Brodowski human = 1; 5467fe2f639SDominik Brodowski break; 547e091abc7SPrarit Bhargava case 'n': 548e091abc7SPrarit Bhargava no_rounding = 1; 549e091abc7SPrarit Bhargava break; 5507fe2f639SDominik Brodowski default: 5517fe2f639SDominik Brodowski fprintf(stderr, "invalid or unknown argument\n"); 5527fe2f639SDominik Brodowski return EXIT_FAILURE; 5537fe2f639SDominik Brodowski } 5547fe2f639SDominik Brodowski } while (cont); 5557fe2f639SDominik Brodowski 5567fe2f639SDominik Brodowski switch (output_param) { 5577fe2f639SDominik Brodowski case 'o': 5587fe2f639SDominik Brodowski if (!bitmask_isallclear(cpus_chosen)) { 5597fe2f639SDominik Brodowski printf(_("The argument passed to this tool can't be " 5607fe2f639SDominik Brodowski "combined with passing a --cpu argument\n")); 5617fe2f639SDominik Brodowski return -EINVAL; 5627fe2f639SDominik Brodowski } 5637fe2f639SDominik Brodowski break; 5647fe2f639SDominik Brodowski case 0: 5657fe2f639SDominik Brodowski output_param = 'e'; 5667fe2f639SDominik Brodowski } 5677fe2f639SDominik Brodowski 5687fe2f639SDominik Brodowski ret = 0; 5697fe2f639SDominik Brodowski 5707fe2f639SDominik Brodowski /* Default is: show output of CPU 0 only */ 5717fe2f639SDominik Brodowski if (bitmask_isallclear(cpus_chosen)) 5727fe2f639SDominik Brodowski bitmask_setbit(cpus_chosen, 0); 5737fe2f639SDominik Brodowski 5747fe2f639SDominik Brodowski switch (output_param) { 5757fe2f639SDominik Brodowski case -1: 5767fe2f639SDominik Brodowski printf(_("You can't specify more than one --cpu parameter and/or\n" 5777fe2f639SDominik Brodowski "more than one output-specific argument\n")); 5787fe2f639SDominik Brodowski return -EINVAL; 5797fe2f639SDominik Brodowski case '?': 5807fe2f639SDominik Brodowski printf(_("invalid or unknown argument\n")); 5817fe2f639SDominik Brodowski return -EINVAL; 5827fe2f639SDominik Brodowski case 'o': 5837fe2f639SDominik Brodowski proc_cpufreq_output(); 5847fe2f639SDominik Brodowski return EXIT_SUCCESS; 5857fe2f639SDominik Brodowski } 5867fe2f639SDominik Brodowski 5877fe2f639SDominik Brodowski for (cpu = bitmask_first(cpus_chosen); 5887fe2f639SDominik Brodowski cpu <= bitmask_last(cpus_chosen); cpu++) { 5897fe2f639SDominik Brodowski 5907fe2f639SDominik Brodowski if (!bitmask_isbitset(cpus_chosen, cpu)) 5917fe2f639SDominik Brodowski continue; 592ce512b84SThomas Renninger 593ce512b84SThomas Renninger printf(_("analyzing CPU %d:\n"), cpu); 594ce512b84SThomas Renninger 595ce512b84SThomas Renninger if (sysfs_is_cpu_online(cpu) != 1) { 596ce512b84SThomas Renninger printf(_(" *is offline\n")); 597ce512b84SThomas Renninger printf("\n"); 5987fe2f639SDominik Brodowski continue; 5997fe2f639SDominik Brodowski } 6007fe2f639SDominik Brodowski 6017fe2f639SDominik Brodowski switch (output_param) { 6027fe2f639SDominik Brodowski case 'b': 6037fe2f639SDominik Brodowski get_boost_mode(cpu); 6047fe2f639SDominik Brodowski break; 6057fe2f639SDominik Brodowski case 'e': 6067fe2f639SDominik Brodowski debug_output_one(cpu); 6077fe2f639SDominik Brodowski break; 6087fe2f639SDominik Brodowski case 'a': 6097fe2f639SDominik Brodowski ret = get_affected_cpus(cpu); 6107fe2f639SDominik Brodowski break; 6117fe2f639SDominik Brodowski case 'r': 6127fe2f639SDominik Brodowski ret = get_related_cpus(cpu); 6137fe2f639SDominik Brodowski break; 6147fe2f639SDominik Brodowski case 'g': 6157fe2f639SDominik Brodowski ret = get_available_governors(cpu); 6167fe2f639SDominik Brodowski break; 6177fe2f639SDominik Brodowski case 'p': 6187fe2f639SDominik Brodowski ret = get_policy(cpu); 6197fe2f639SDominik Brodowski break; 6207fe2f639SDominik Brodowski case 'd': 6217fe2f639SDominik Brodowski ret = get_driver(cpu); 6227fe2f639SDominik Brodowski break; 6237fe2f639SDominik Brodowski case 'l': 6247fe2f639SDominik Brodowski ret = get_hardware_limits(cpu); 6257fe2f639SDominik Brodowski break; 6267fe2f639SDominik Brodowski case 'w': 6277fe2f639SDominik Brodowski ret = get_freq_hardware(cpu, human); 6287fe2f639SDominik Brodowski break; 6297fe2f639SDominik Brodowski case 'f': 6307fe2f639SDominik Brodowski ret = get_freq_kernel(cpu, human); 6317fe2f639SDominik Brodowski break; 6327fe2f639SDominik Brodowski case 's': 6337fe2f639SDominik Brodowski ret = get_freq_stats(cpu, human); 6347fe2f639SDominik Brodowski break; 6357fe2f639SDominik Brodowski case 'y': 6367fe2f639SDominik Brodowski ret = get_latency(cpu, human); 6377fe2f639SDominik Brodowski break; 6387fe2f639SDominik Brodowski } 6397fe2f639SDominik Brodowski if (ret) 640a1ce5ba2SDominik Brodowski return ret; 641ce512b84SThomas Renninger printf("\n"); 6427fe2f639SDominik Brodowski } 6437fe2f639SDominik Brodowski return ret; 6447fe2f639SDominik Brodowski } 645