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" 177fe2f639SDominik Brodowski #include "helpers/helpers.h" 187fe2f639SDominik Brodowski #include "helpers/bitmask.h" 197fe2f639SDominik Brodowski 207fe2f639SDominik Brodowski #define LINE_LEN 10 217fe2f639SDominik Brodowski 227fe2f639SDominik Brodowski static unsigned int count_cpus(void) 237fe2f639SDominik Brodowski { 247fe2f639SDominik Brodowski FILE *fp; 257fe2f639SDominik Brodowski char value[LINE_LEN]; 267fe2f639SDominik Brodowski unsigned int ret = 0; 277fe2f639SDominik Brodowski unsigned int cpunr = 0; 287fe2f639SDominik Brodowski 297fe2f639SDominik Brodowski fp = fopen("/proc/stat", "r"); 307fe2f639SDominik Brodowski if (!fp) { 317fe2f639SDominik Brodowski printf(_("Couldn't count the number of CPUs (%s: %s), assuming 1\n"), "/proc/stat", strerror(errno)); 327fe2f639SDominik Brodowski return 1; 337fe2f639SDominik Brodowski } 347fe2f639SDominik Brodowski 357fe2f639SDominik Brodowski while (!feof(fp)) { 367fe2f639SDominik Brodowski if (!fgets(value, LINE_LEN, fp)) 377fe2f639SDominik Brodowski continue; 387fe2f639SDominik Brodowski value[LINE_LEN - 1] = '\0'; 397fe2f639SDominik Brodowski if (strlen(value) < (LINE_LEN - 2)) 407fe2f639SDominik Brodowski continue; 417fe2f639SDominik Brodowski if (strstr(value, "cpu ")) 427fe2f639SDominik Brodowski continue; 437fe2f639SDominik Brodowski if (sscanf(value, "cpu%d ", &cpunr) != 1) 447fe2f639SDominik Brodowski continue; 457fe2f639SDominik Brodowski if (cpunr > ret) 467fe2f639SDominik Brodowski ret = cpunr; 477fe2f639SDominik Brodowski } 487fe2f639SDominik Brodowski fclose(fp); 497fe2f639SDominik Brodowski 507fe2f639SDominik Brodowski /* cpu count starts from 0, on error return 1 (UP) */ 51a1ce5ba2SDominik Brodowski return ret + 1; 527fe2f639SDominik Brodowski } 537fe2f639SDominik Brodowski 547fe2f639SDominik Brodowski 557fe2f639SDominik Brodowski static void proc_cpufreq_output(void) 567fe2f639SDominik Brodowski { 577fe2f639SDominik Brodowski unsigned int cpu, nr_cpus; 587fe2f639SDominik Brodowski struct cpufreq_policy *policy; 597fe2f639SDominik Brodowski unsigned int min_pctg = 0; 607fe2f639SDominik Brodowski unsigned int max_pctg = 0; 617fe2f639SDominik Brodowski unsigned long min, max; 627fe2f639SDominik Brodowski 637fe2f639SDominik Brodowski printf(_(" minimum CPU frequency - maximum CPU frequency - governor\n")); 647fe2f639SDominik Brodowski 657fe2f639SDominik Brodowski nr_cpus = count_cpus(); 667fe2f639SDominik Brodowski for (cpu = 0; cpu < nr_cpus; cpu++) { 677fe2f639SDominik Brodowski policy = cpufreq_get_policy(cpu); 687fe2f639SDominik Brodowski if (!policy) 697fe2f639SDominik Brodowski continue; 707fe2f639SDominik Brodowski 717fe2f639SDominik Brodowski if (cpufreq_get_hardware_limits(cpu, &min, &max)) { 727fe2f639SDominik Brodowski max = 0; 737fe2f639SDominik Brodowski } else { 747fe2f639SDominik Brodowski min_pctg = (policy->min * 100) / max; 757fe2f639SDominik Brodowski max_pctg = (policy->max * 100) / max; 767fe2f639SDominik Brodowski } 777fe2f639SDominik Brodowski printf("CPU%3d %9lu kHz (%3d %%) - %9lu kHz (%3d %%) - %s\n", 78a1ce5ba2SDominik Brodowski cpu , policy->min, max ? min_pctg : 0, policy->max, 79a1ce5ba2SDominik Brodowski max ? max_pctg : 0, policy->governor); 807fe2f639SDominik Brodowski 817fe2f639SDominik Brodowski cpufreq_put_policy(policy); 827fe2f639SDominik Brodowski } 837fe2f639SDominik Brodowski } 847fe2f639SDominik Brodowski 85*e091abc7SPrarit Bhargava static int no_rounding; 867fe2f639SDominik Brodowski static void print_speed(unsigned long speed) 877fe2f639SDominik Brodowski { 887fe2f639SDominik Brodowski unsigned long tmp; 897fe2f639SDominik Brodowski 90*e091abc7SPrarit Bhargava if (no_rounding) { 91*e091abc7SPrarit Bhargava if (speed > 1000000) 92*e091abc7SPrarit Bhargava printf("%u.%06u GHz", ((unsigned int) speed/1000000), 93*e091abc7SPrarit Bhargava ((unsigned int) speed%1000000)); 94*e091abc7SPrarit Bhargava else if (speed > 100000) 95*e091abc7SPrarit Bhargava printf("%u MHz", (unsigned int) speed); 96*e091abc7SPrarit Bhargava else if (speed > 1000) 97*e091abc7SPrarit Bhargava printf("%u.%03u MHz", ((unsigned int) speed/1000), 98*e091abc7SPrarit Bhargava (unsigned int) (speed%1000)); 99*e091abc7SPrarit Bhargava else 100*e091abc7SPrarit Bhargava printf("%lu kHz", speed); 101*e091abc7SPrarit 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)); 119*e091abc7SPrarit Bhargava } 120*e091abc7SPrarit 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 129*e091abc7SPrarit Bhargava if (no_rounding) { 130*e091abc7SPrarit Bhargava if (duration > 1000000) 131*e091abc7SPrarit Bhargava printf("%u.%06u ms", ((unsigned int) duration/1000000), 132*e091abc7SPrarit Bhargava ((unsigned int) duration%1000000)); 133*e091abc7SPrarit Bhargava else if (duration > 100000) 134*e091abc7SPrarit Bhargava printf("%u us", ((unsigned int) duration/1000)); 135*e091abc7SPrarit Bhargava else if (duration > 1000) 136*e091abc7SPrarit Bhargava printf("%u.%03u us", ((unsigned int) duration/1000), 137*e091abc7SPrarit Bhargava ((unsigned int) duration%1000)); 138*e091abc7SPrarit Bhargava else 139*e091abc7SPrarit Bhargava printf("%lu ns", duration); 140*e091abc7SPrarit 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); 160*e091abc7SPrarit 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++) { 2037fe2f639SDominik Brodowski if (i < b_states) 2048fb2e440SThomas Renninger printf(_(" Pstate-Pb%d: %luMHz (boost state)" 2058fb2e440SThomas Renninger "\n"), i, pstates[i]); 2067fe2f639SDominik Brodowski else 2077fe2f639SDominik Brodowski printf(_(" Pstate-P%d: %luMHz\n"), 2087fe2f639SDominik Brodowski i - b_states, pstates[i]); 2097fe2f639SDominik Brodowski } 2108fb2e440SThomas Renninger } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_HAS_TURBO_RATIO) { 2118fb2e440SThomas Renninger double bclk; 2128fb2e440SThomas Renninger unsigned long long intel_turbo_ratio = 0; 2138fb2e440SThomas Renninger unsigned int ratio; 2148fb2e440SThomas Renninger 2158fb2e440SThomas Renninger /* Any way to autodetect this ? */ 2168fb2e440SThomas Renninger if (cpupower_cpu_info.caps & CPUPOWER_CAP_IS_SNB) 2178fb2e440SThomas Renninger bclk = 100.00; 2188fb2e440SThomas Renninger else 2198fb2e440SThomas Renninger bclk = 133.33; 2208fb2e440SThomas Renninger intel_turbo_ratio = msr_intel_get_turbo_ratio(cpu); 2218fb2e440SThomas Renninger dprint (" Ratio: 0x%llx - bclk: %f\n", 2228fb2e440SThomas Renninger intel_turbo_ratio, bclk); 2238fb2e440SThomas Renninger 2248fb2e440SThomas Renninger ratio = (intel_turbo_ratio >> 24) & 0xFF; 2258fb2e440SThomas Renninger if (ratio) 2268fb2e440SThomas Renninger printf(_(" %.0f MHz max turbo 4 active cores\n"), 2278fb2e440SThomas Renninger ratio * bclk); 2288fb2e440SThomas Renninger 2298fb2e440SThomas Renninger ratio = (intel_turbo_ratio >> 16) & 0xFF; 2308fb2e440SThomas Renninger if (ratio) 2318fb2e440SThomas Renninger printf(_(" %.0f MHz max turbo 3 active cores\n"), 2328fb2e440SThomas Renninger ratio * bclk); 2338fb2e440SThomas Renninger 2348fb2e440SThomas Renninger ratio = (intel_turbo_ratio >> 8) & 0xFF; 2358fb2e440SThomas Renninger if (ratio) 2368fb2e440SThomas Renninger printf(_(" %.0f MHz max turbo 2 active cores\n"), 2378fb2e440SThomas Renninger ratio * bclk); 2388fb2e440SThomas Renninger 2398fb2e440SThomas Renninger ratio = (intel_turbo_ratio >> 0) & 0xFF; 2408fb2e440SThomas Renninger if (ratio) 2418fb2e440SThomas Renninger printf(_(" %.0f MHz max turbo 1 active cores\n"), 2428fb2e440SThomas Renninger ratio * bclk); 2438fb2e440SThomas Renninger } 2447fe2f639SDominik Brodowski return 0; 2457fe2f639SDominik Brodowski } 2467fe2f639SDominik Brodowski 2477fe2f639SDominik Brodowski static void debug_output_one(unsigned int cpu) 2487fe2f639SDominik Brodowski { 2497fe2f639SDominik Brodowski char *driver; 2507fe2f639SDominik Brodowski struct cpufreq_affected_cpus *cpus; 2517fe2f639SDominik Brodowski struct cpufreq_available_frequencies *freqs; 2527fe2f639SDominik Brodowski unsigned long min, max, freq_kernel, freq_hardware; 2537fe2f639SDominik Brodowski unsigned long total_trans, latency; 2547fe2f639SDominik Brodowski unsigned long long total_time; 2557fe2f639SDominik Brodowski struct cpufreq_policy *policy; 2567fe2f639SDominik Brodowski struct cpufreq_available_governors *governors; 2577fe2f639SDominik Brodowski struct cpufreq_stats *stats; 2587fe2f639SDominik Brodowski 259a1ce5ba2SDominik Brodowski if (cpufreq_cpu_exists(cpu)) 2607fe2f639SDominik Brodowski return; 2617fe2f639SDominik Brodowski 2627fe2f639SDominik Brodowski freq_kernel = cpufreq_get_freq_kernel(cpu); 2637fe2f639SDominik Brodowski freq_hardware = cpufreq_get_freq_hardware(cpu); 2647fe2f639SDominik Brodowski 2657fe2f639SDominik Brodowski driver = cpufreq_get_driver(cpu); 2667fe2f639SDominik Brodowski if (!driver) { 2677fe2f639SDominik Brodowski printf(_(" no or unknown cpufreq driver is active on this CPU\n")); 2687fe2f639SDominik Brodowski } else { 2697fe2f639SDominik Brodowski printf(_(" driver: %s\n"), driver); 2707fe2f639SDominik Brodowski cpufreq_put_driver(driver); 2717fe2f639SDominik Brodowski } 2727fe2f639SDominik Brodowski 2737fe2f639SDominik Brodowski cpus = cpufreq_get_related_cpus(cpu); 2747fe2f639SDominik Brodowski if (cpus) { 2757fe2f639SDominik Brodowski printf(_(" CPUs which run at the same hardware frequency: ")); 2767fe2f639SDominik Brodowski while (cpus->next) { 2777fe2f639SDominik Brodowski printf("%d ", cpus->cpu); 2787fe2f639SDominik Brodowski cpus = cpus->next; 2797fe2f639SDominik Brodowski } 2807fe2f639SDominik Brodowski printf("%d\n", cpus->cpu); 2817fe2f639SDominik Brodowski cpufreq_put_related_cpus(cpus); 2827fe2f639SDominik Brodowski } 2837fe2f639SDominik Brodowski 2847fe2f639SDominik Brodowski cpus = cpufreq_get_affected_cpus(cpu); 2857fe2f639SDominik Brodowski if (cpus) { 2867fe2f639SDominik Brodowski printf(_(" CPUs which need to have their frequency coordinated by software: ")); 2877fe2f639SDominik Brodowski while (cpus->next) { 2887fe2f639SDominik Brodowski printf("%d ", cpus->cpu); 2897fe2f639SDominik Brodowski cpus = cpus->next; 2907fe2f639SDominik Brodowski } 2917fe2f639SDominik Brodowski printf("%d\n", cpus->cpu); 2927fe2f639SDominik Brodowski cpufreq_put_affected_cpus(cpus); 2937fe2f639SDominik Brodowski } 2947fe2f639SDominik Brodowski 2957fe2f639SDominik Brodowski latency = cpufreq_get_transition_latency(cpu); 2967fe2f639SDominik Brodowski if (latency) { 2977fe2f639SDominik Brodowski printf(_(" maximum transition latency: ")); 2987fe2f639SDominik Brodowski print_duration(latency); 2997fe2f639SDominik Brodowski printf(".\n"); 3007fe2f639SDominik Brodowski } 3017fe2f639SDominik Brodowski 3027fe2f639SDominik Brodowski if (!(cpufreq_get_hardware_limits(cpu, &min, &max))) { 3037fe2f639SDominik Brodowski printf(_(" hardware limits: ")); 3047fe2f639SDominik Brodowski print_speed(min); 3057fe2f639SDominik Brodowski printf(" - "); 3067fe2f639SDominik Brodowski print_speed(max); 3077fe2f639SDominik Brodowski printf("\n"); 3087fe2f639SDominik Brodowski } 3097fe2f639SDominik Brodowski 3107fe2f639SDominik Brodowski freqs = cpufreq_get_available_frequencies(cpu); 3117fe2f639SDominik Brodowski if (freqs) { 3127fe2f639SDominik Brodowski printf(_(" available frequency steps: ")); 3137fe2f639SDominik Brodowski while (freqs->next) { 3147fe2f639SDominik Brodowski print_speed(freqs->frequency); 3157fe2f639SDominik Brodowski printf(", "); 3167fe2f639SDominik Brodowski freqs = freqs->next; 3177fe2f639SDominik Brodowski } 3187fe2f639SDominik Brodowski print_speed(freqs->frequency); 3197fe2f639SDominik Brodowski printf("\n"); 3207fe2f639SDominik Brodowski cpufreq_put_available_frequencies(freqs); 3217fe2f639SDominik Brodowski } 3227fe2f639SDominik Brodowski 3237fe2f639SDominik Brodowski governors = cpufreq_get_available_governors(cpu); 3247fe2f639SDominik Brodowski if (governors) { 3257fe2f639SDominik Brodowski printf(_(" available cpufreq governors: ")); 3267fe2f639SDominik Brodowski while (governors->next) { 3277fe2f639SDominik Brodowski printf("%s, ", governors->governor); 3287fe2f639SDominik Brodowski governors = governors->next; 3297fe2f639SDominik Brodowski } 3307fe2f639SDominik Brodowski printf("%s\n", governors->governor); 3317fe2f639SDominik Brodowski cpufreq_put_available_governors(governors); 3327fe2f639SDominik Brodowski } 3337fe2f639SDominik Brodowski 3347fe2f639SDominik Brodowski policy = cpufreq_get_policy(cpu); 3357fe2f639SDominik Brodowski if (policy) { 3367fe2f639SDominik Brodowski printf(_(" current policy: frequency should be within ")); 3377fe2f639SDominik Brodowski print_speed(policy->min); 3387fe2f639SDominik Brodowski printf(_(" and ")); 3397fe2f639SDominik Brodowski print_speed(policy->max); 3407fe2f639SDominik Brodowski 3417fe2f639SDominik Brodowski printf(".\n "); 3427fe2f639SDominik Brodowski printf(_("The governor \"%s\" may" 3437fe2f639SDominik Brodowski " decide which speed to use\n within this range.\n"), 3447fe2f639SDominik Brodowski policy->governor); 3457fe2f639SDominik Brodowski cpufreq_put_policy(policy); 3467fe2f639SDominik Brodowski } 3477fe2f639SDominik Brodowski 3487fe2f639SDominik Brodowski if (freq_kernel || freq_hardware) { 3497fe2f639SDominik Brodowski printf(_(" current CPU frequency is ")); 3507fe2f639SDominik Brodowski if (freq_hardware) { 3517fe2f639SDominik Brodowski print_speed(freq_hardware); 3527fe2f639SDominik Brodowski printf(_(" (asserted by call to hardware)")); 353a1ce5ba2SDominik Brodowski } else 3547fe2f639SDominik Brodowski print_speed(freq_kernel); 3557fe2f639SDominik Brodowski printf(".\n"); 3567fe2f639SDominik Brodowski } 3577fe2f639SDominik Brodowski stats = cpufreq_get_stats(cpu, &total_time); 3587fe2f639SDominik Brodowski if (stats) { 3597fe2f639SDominik Brodowski printf(_(" cpufreq stats: ")); 3607fe2f639SDominik Brodowski while (stats) { 3617fe2f639SDominik Brodowski print_speed(stats->frequency); 3627fe2f639SDominik Brodowski printf(":%.2f%%", (100.0 * stats->time_in_state) / total_time); 3637fe2f639SDominik Brodowski stats = stats->next; 3647fe2f639SDominik Brodowski if (stats) 3657fe2f639SDominik Brodowski printf(", "); 3667fe2f639SDominik Brodowski } 3677fe2f639SDominik Brodowski cpufreq_put_stats(stats); 3687fe2f639SDominik Brodowski total_trans = cpufreq_get_transitions(cpu); 3697fe2f639SDominik Brodowski if (total_trans) 3707fe2f639SDominik Brodowski printf(" (%lu)\n", total_trans); 3717fe2f639SDominik Brodowski else 3727fe2f639SDominik Brodowski printf("\n"); 3737fe2f639SDominik Brodowski } 3747fe2f639SDominik Brodowski get_boost_mode(cpu); 3757fe2f639SDominik Brodowski 3767fe2f639SDominik Brodowski } 3777fe2f639SDominik Brodowski 3787fe2f639SDominik Brodowski /* --freq / -f */ 3797fe2f639SDominik Brodowski 380a1ce5ba2SDominik Brodowski static int get_freq_kernel(unsigned int cpu, unsigned int human) 381a1ce5ba2SDominik Brodowski { 3827fe2f639SDominik Brodowski unsigned long freq = cpufreq_get_freq_kernel(cpu); 3837fe2f639SDominik Brodowski if (!freq) 3847fe2f639SDominik Brodowski return -EINVAL; 3857fe2f639SDominik Brodowski if (human) { 3867fe2f639SDominik Brodowski print_speed(freq); 3877fe2f639SDominik Brodowski printf("\n"); 3887fe2f639SDominik Brodowski } else 3897fe2f639SDominik Brodowski printf("%lu\n", freq); 3907fe2f639SDominik Brodowski return 0; 3917fe2f639SDominik Brodowski } 3927fe2f639SDominik Brodowski 3937fe2f639SDominik Brodowski 3947fe2f639SDominik Brodowski /* --hwfreq / -w */ 3957fe2f639SDominik Brodowski 396a1ce5ba2SDominik Brodowski static int get_freq_hardware(unsigned int cpu, unsigned int human) 397a1ce5ba2SDominik Brodowski { 3987fe2f639SDominik Brodowski unsigned long freq = cpufreq_get_freq_hardware(cpu); 3997fe2f639SDominik Brodowski if (!freq) 4007fe2f639SDominik Brodowski return -EINVAL; 4017fe2f639SDominik Brodowski if (human) { 4027fe2f639SDominik Brodowski print_speed(freq); 4037fe2f639SDominik Brodowski printf("\n"); 4047fe2f639SDominik Brodowski } else 4057fe2f639SDominik Brodowski printf("%lu\n", freq); 4067fe2f639SDominik Brodowski return 0; 4077fe2f639SDominik Brodowski } 4087fe2f639SDominik Brodowski 4097fe2f639SDominik Brodowski /* --hwlimits / -l */ 4107fe2f639SDominik Brodowski 411a1ce5ba2SDominik Brodowski static int get_hardware_limits(unsigned int cpu) 412a1ce5ba2SDominik Brodowski { 4137fe2f639SDominik Brodowski unsigned long min, max; 4147fe2f639SDominik Brodowski if (cpufreq_get_hardware_limits(cpu, &min, &max)) 4157fe2f639SDominik Brodowski return -EINVAL; 4167fe2f639SDominik Brodowski printf("%lu %lu\n", min, max); 4177fe2f639SDominik Brodowski return 0; 4187fe2f639SDominik Brodowski } 4197fe2f639SDominik Brodowski 4207fe2f639SDominik Brodowski /* --driver / -d */ 4217fe2f639SDominik Brodowski 422a1ce5ba2SDominik Brodowski static int get_driver(unsigned int cpu) 423a1ce5ba2SDominik Brodowski { 4247fe2f639SDominik Brodowski char *driver = cpufreq_get_driver(cpu); 4257fe2f639SDominik Brodowski if (!driver) 4267fe2f639SDominik Brodowski return -EINVAL; 4277fe2f639SDominik Brodowski printf("%s\n", driver); 4287fe2f639SDominik Brodowski cpufreq_put_driver(driver); 4297fe2f639SDominik Brodowski return 0; 4307fe2f639SDominik Brodowski } 4317fe2f639SDominik Brodowski 4327fe2f639SDominik Brodowski /* --policy / -p */ 4337fe2f639SDominik Brodowski 434a1ce5ba2SDominik Brodowski static int get_policy(unsigned int cpu) 435a1ce5ba2SDominik Brodowski { 4367fe2f639SDominik Brodowski struct cpufreq_policy *policy = cpufreq_get_policy(cpu); 4377fe2f639SDominik Brodowski if (!policy) 4387fe2f639SDominik Brodowski return -EINVAL; 4397fe2f639SDominik Brodowski printf("%lu %lu %s\n", policy->min, policy->max, policy->governor); 4407fe2f639SDominik Brodowski cpufreq_put_policy(policy); 4417fe2f639SDominik Brodowski return 0; 4427fe2f639SDominik Brodowski } 4437fe2f639SDominik Brodowski 4447fe2f639SDominik Brodowski /* --governors / -g */ 4457fe2f639SDominik Brodowski 446a1ce5ba2SDominik Brodowski static int get_available_governors(unsigned int cpu) 447a1ce5ba2SDominik Brodowski { 448a1ce5ba2SDominik Brodowski struct cpufreq_available_governors *governors = 449a1ce5ba2SDominik Brodowski cpufreq_get_available_governors(cpu); 4507fe2f639SDominik Brodowski if (!governors) 4517fe2f639SDominik Brodowski return -EINVAL; 4527fe2f639SDominik Brodowski 4537fe2f639SDominik Brodowski while (governors->next) { 4547fe2f639SDominik Brodowski printf("%s ", governors->governor); 4557fe2f639SDominik Brodowski governors = governors->next; 4567fe2f639SDominik Brodowski } 4577fe2f639SDominik Brodowski printf("%s\n", governors->governor); 4587fe2f639SDominik Brodowski cpufreq_put_available_governors(governors); 4597fe2f639SDominik Brodowski return 0; 4607fe2f639SDominik Brodowski } 4617fe2f639SDominik Brodowski 4627fe2f639SDominik Brodowski 4637fe2f639SDominik Brodowski /* --affected-cpus / -a */ 4647fe2f639SDominik Brodowski 465a1ce5ba2SDominik Brodowski static int get_affected_cpus(unsigned int cpu) 466a1ce5ba2SDominik Brodowski { 4677fe2f639SDominik Brodowski struct cpufreq_affected_cpus *cpus = cpufreq_get_affected_cpus(cpu); 4687fe2f639SDominik Brodowski if (!cpus) 4697fe2f639SDominik Brodowski return -EINVAL; 4707fe2f639SDominik Brodowski 4717fe2f639SDominik Brodowski while (cpus->next) { 4727fe2f639SDominik Brodowski printf("%d ", cpus->cpu); 4737fe2f639SDominik Brodowski cpus = cpus->next; 4747fe2f639SDominik Brodowski } 4757fe2f639SDominik Brodowski printf("%d\n", cpus->cpu); 4767fe2f639SDominik Brodowski cpufreq_put_affected_cpus(cpus); 4777fe2f639SDominik Brodowski return 0; 4787fe2f639SDominik Brodowski } 4797fe2f639SDominik Brodowski 4807fe2f639SDominik Brodowski /* --related-cpus / -r */ 4817fe2f639SDominik Brodowski 482a1ce5ba2SDominik Brodowski static int get_related_cpus(unsigned int cpu) 483a1ce5ba2SDominik Brodowski { 4847fe2f639SDominik Brodowski struct cpufreq_affected_cpus *cpus = cpufreq_get_related_cpus(cpu); 4857fe2f639SDominik Brodowski if (!cpus) 4867fe2f639SDominik Brodowski return -EINVAL; 4877fe2f639SDominik Brodowski 4887fe2f639SDominik Brodowski while (cpus->next) { 4897fe2f639SDominik Brodowski printf("%d ", cpus->cpu); 4907fe2f639SDominik Brodowski cpus = cpus->next; 4917fe2f639SDominik Brodowski } 4927fe2f639SDominik Brodowski printf("%d\n", cpus->cpu); 4937fe2f639SDominik Brodowski cpufreq_put_related_cpus(cpus); 4947fe2f639SDominik Brodowski return 0; 4957fe2f639SDominik Brodowski } 4967fe2f639SDominik Brodowski 4977fe2f639SDominik Brodowski /* --stats / -s */ 4987fe2f639SDominik Brodowski 499a1ce5ba2SDominik Brodowski static int get_freq_stats(unsigned int cpu, unsigned int human) 500a1ce5ba2SDominik Brodowski { 5017fe2f639SDominik Brodowski unsigned long total_trans = cpufreq_get_transitions(cpu); 5027fe2f639SDominik Brodowski unsigned long long total_time; 5037fe2f639SDominik Brodowski struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time); 5047fe2f639SDominik Brodowski while (stats) { 5057fe2f639SDominik Brodowski if (human) { 5067fe2f639SDominik Brodowski print_speed(stats->frequency); 507a1ce5ba2SDominik Brodowski printf(":%.2f%%", 508a1ce5ba2SDominik Brodowski (100.0 * stats->time_in_state) / total_time); 509a1ce5ba2SDominik Brodowski } else 510a1ce5ba2SDominik Brodowski printf("%lu:%llu", 511a1ce5ba2SDominik Brodowski stats->frequency, stats->time_in_state); 5127fe2f639SDominik Brodowski stats = stats->next; 5137fe2f639SDominik Brodowski if (stats) 5147fe2f639SDominik Brodowski printf(", "); 5157fe2f639SDominik Brodowski } 5167fe2f639SDominik Brodowski cpufreq_put_stats(stats); 5177fe2f639SDominik Brodowski if (total_trans) 5187fe2f639SDominik Brodowski printf(" (%lu)\n", total_trans); 5197fe2f639SDominik Brodowski return 0; 5207fe2f639SDominik Brodowski } 5217fe2f639SDominik Brodowski 5227fe2f639SDominik Brodowski /* --latency / -y */ 5237fe2f639SDominik Brodowski 524a1ce5ba2SDominik Brodowski static int get_latency(unsigned int cpu, unsigned int human) 525a1ce5ba2SDominik Brodowski { 5267fe2f639SDominik Brodowski unsigned long latency = cpufreq_get_transition_latency(cpu); 5277fe2f639SDominik Brodowski if (!latency) 5287fe2f639SDominik Brodowski return -EINVAL; 5297fe2f639SDominik Brodowski 5307fe2f639SDominik Brodowski if (human) { 5317fe2f639SDominik Brodowski print_duration(latency); 5327fe2f639SDominik Brodowski printf("\n"); 5337fe2f639SDominik Brodowski } else 5347fe2f639SDominik Brodowski printf("%lu\n", latency); 5357fe2f639SDominik Brodowski return 0; 5367fe2f639SDominik Brodowski } 5377fe2f639SDominik Brodowski 5387fe2f639SDominik Brodowski static struct option info_opts[] = { 5397fe2f639SDominik Brodowski { .name = "debug", .has_arg = no_argument, .flag = NULL, .val = 'e'}, 5407fe2f639SDominik Brodowski { .name = "boost", .has_arg = no_argument, .flag = NULL, .val = 'b'}, 5417fe2f639SDominik Brodowski { .name = "freq", .has_arg = no_argument, .flag = NULL, .val = 'f'}, 5427fe2f639SDominik Brodowski { .name = "hwfreq", .has_arg = no_argument, .flag = NULL, .val = 'w'}, 5437fe2f639SDominik Brodowski { .name = "hwlimits", .has_arg = no_argument, .flag = NULL, .val = 'l'}, 5447fe2f639SDominik Brodowski { .name = "driver", .has_arg = no_argument, .flag = NULL, .val = 'd'}, 5457fe2f639SDominik Brodowski { .name = "policy", .has_arg = no_argument, .flag = NULL, .val = 'p'}, 5467fe2f639SDominik Brodowski { .name = "governors", .has_arg = no_argument, .flag = NULL, .val = 'g'}, 5477fe2f639SDominik Brodowski { .name = "related-cpus", .has_arg = no_argument, .flag = NULL, .val = 'r'}, 5487fe2f639SDominik Brodowski { .name = "affected-cpus",.has_arg = no_argument, .flag = NULL, .val = 'a'}, 5497fe2f639SDominik Brodowski { .name = "stats", .has_arg = no_argument, .flag = NULL, .val = 's'}, 5507fe2f639SDominik Brodowski { .name = "latency", .has_arg = no_argument, .flag = NULL, .val = 'y'}, 5517fe2f639SDominik Brodowski { .name = "proc", .has_arg = no_argument, .flag = NULL, .val = 'o'}, 5527fe2f639SDominik Brodowski { .name = "human", .has_arg = no_argument, .flag = NULL, .val = 'm'}, 553*e091abc7SPrarit Bhargava { .name = "no-rounding", .has_arg = no_argument, .flag = NULL, .val = 'n'}, 5547fe2f639SDominik Brodowski { }, 5557fe2f639SDominik Brodowski }; 5567fe2f639SDominik Brodowski 5577fe2f639SDominik Brodowski int cmd_freq_info(int argc, char **argv) 5587fe2f639SDominik Brodowski { 5597fe2f639SDominik Brodowski extern char *optarg; 5607fe2f639SDominik Brodowski extern int optind, opterr, optopt; 5617fe2f639SDominik Brodowski int ret = 0, cont = 1; 5627fe2f639SDominik Brodowski unsigned int cpu = 0; 5637fe2f639SDominik Brodowski unsigned int human = 0; 5647fe2f639SDominik Brodowski int output_param = 0; 5657fe2f639SDominik Brodowski 5667fe2f639SDominik Brodowski do { 567*e091abc7SPrarit Bhargava ret = getopt_long(argc, argv, "oefwldpgrasmybn", info_opts, 568*e091abc7SPrarit Bhargava NULL); 5697fe2f639SDominik Brodowski switch (ret) { 5707fe2f639SDominik Brodowski case '?': 5717fe2f639SDominik Brodowski output_param = '?'; 5727fe2f639SDominik Brodowski cont = 0; 5737fe2f639SDominik Brodowski break; 5747fe2f639SDominik Brodowski case -1: 5757fe2f639SDominik Brodowski cont = 0; 5767fe2f639SDominik Brodowski break; 5777fe2f639SDominik Brodowski case 'b': 5787fe2f639SDominik Brodowski case 'o': 5797fe2f639SDominik Brodowski case 'a': 5807fe2f639SDominik Brodowski case 'r': 5817fe2f639SDominik Brodowski case 'g': 5827fe2f639SDominik Brodowski case 'p': 5837fe2f639SDominik Brodowski case 'd': 5847fe2f639SDominik Brodowski case 'l': 5857fe2f639SDominik Brodowski case 'w': 5867fe2f639SDominik Brodowski case 'f': 5877fe2f639SDominik Brodowski case 'e': 5887fe2f639SDominik Brodowski case 's': 5897fe2f639SDominik Brodowski case 'y': 5907fe2f639SDominik Brodowski if (output_param) { 5917fe2f639SDominik Brodowski output_param = -1; 5927fe2f639SDominik Brodowski cont = 0; 5937fe2f639SDominik Brodowski break; 5947fe2f639SDominik Brodowski } 5957fe2f639SDominik Brodowski output_param = ret; 5967fe2f639SDominik Brodowski break; 5977fe2f639SDominik Brodowski case 'm': 5987fe2f639SDominik Brodowski if (human) { 5997fe2f639SDominik Brodowski output_param = -1; 6007fe2f639SDominik Brodowski cont = 0; 6017fe2f639SDominik Brodowski break; 6027fe2f639SDominik Brodowski } 6037fe2f639SDominik Brodowski human = 1; 6047fe2f639SDominik Brodowski break; 605*e091abc7SPrarit Bhargava case 'n': 606*e091abc7SPrarit Bhargava no_rounding = 1; 607*e091abc7SPrarit Bhargava break; 6087fe2f639SDominik Brodowski default: 6097fe2f639SDominik Brodowski fprintf(stderr, "invalid or unknown argument\n"); 6107fe2f639SDominik Brodowski return EXIT_FAILURE; 6117fe2f639SDominik Brodowski } 6127fe2f639SDominik Brodowski } while (cont); 6137fe2f639SDominik Brodowski 6147fe2f639SDominik Brodowski switch (output_param) { 6157fe2f639SDominik Brodowski case 'o': 6167fe2f639SDominik Brodowski if (!bitmask_isallclear(cpus_chosen)) { 6177fe2f639SDominik Brodowski printf(_("The argument passed to this tool can't be " 6187fe2f639SDominik Brodowski "combined with passing a --cpu argument\n")); 6197fe2f639SDominik Brodowski return -EINVAL; 6207fe2f639SDominik Brodowski } 6217fe2f639SDominik Brodowski break; 6227fe2f639SDominik Brodowski case 0: 6237fe2f639SDominik Brodowski output_param = 'e'; 6247fe2f639SDominik Brodowski } 6257fe2f639SDominik Brodowski 6267fe2f639SDominik Brodowski ret = 0; 6277fe2f639SDominik Brodowski 6287fe2f639SDominik Brodowski /* Default is: show output of CPU 0 only */ 6297fe2f639SDominik Brodowski if (bitmask_isallclear(cpus_chosen)) 6307fe2f639SDominik Brodowski bitmask_setbit(cpus_chosen, 0); 6317fe2f639SDominik Brodowski 6327fe2f639SDominik Brodowski switch (output_param) { 6337fe2f639SDominik Brodowski case -1: 6347fe2f639SDominik Brodowski printf(_("You can't specify more than one --cpu parameter and/or\n" 6357fe2f639SDominik Brodowski "more than one output-specific argument\n")); 6367fe2f639SDominik Brodowski return -EINVAL; 6377fe2f639SDominik Brodowski case '?': 6387fe2f639SDominik Brodowski printf(_("invalid or unknown argument\n")); 6397fe2f639SDominik Brodowski return -EINVAL; 6407fe2f639SDominik Brodowski case 'o': 6417fe2f639SDominik Brodowski proc_cpufreq_output(); 6427fe2f639SDominik Brodowski return EXIT_SUCCESS; 6437fe2f639SDominik Brodowski } 6447fe2f639SDominik Brodowski 6457fe2f639SDominik Brodowski for (cpu = bitmask_first(cpus_chosen); 6467fe2f639SDominik Brodowski cpu <= bitmask_last(cpus_chosen); cpu++) { 6477fe2f639SDominik Brodowski 6487fe2f639SDominik Brodowski if (!bitmask_isbitset(cpus_chosen, cpu)) 6497fe2f639SDominik Brodowski continue; 6507fe2f639SDominik Brodowski if (cpufreq_cpu_exists(cpu)) { 6517fe2f639SDominik Brodowski printf(_("couldn't analyze CPU %d as it doesn't seem to be present\n"), cpu); 6527fe2f639SDominik Brodowski continue; 6537fe2f639SDominik Brodowski } 6547fe2f639SDominik Brodowski printf(_("analyzing CPU %d:\n"), cpu); 6557fe2f639SDominik Brodowski 6567fe2f639SDominik Brodowski switch (output_param) { 6577fe2f639SDominik Brodowski case 'b': 6587fe2f639SDominik Brodowski get_boost_mode(cpu); 6597fe2f639SDominik Brodowski break; 6607fe2f639SDominik Brodowski case 'e': 6617fe2f639SDominik Brodowski debug_output_one(cpu); 6627fe2f639SDominik Brodowski break; 6637fe2f639SDominik Brodowski case 'a': 6647fe2f639SDominik Brodowski ret = get_affected_cpus(cpu); 6657fe2f639SDominik Brodowski break; 6667fe2f639SDominik Brodowski case 'r': 6677fe2f639SDominik Brodowski ret = get_related_cpus(cpu); 6687fe2f639SDominik Brodowski break; 6697fe2f639SDominik Brodowski case 'g': 6707fe2f639SDominik Brodowski ret = get_available_governors(cpu); 6717fe2f639SDominik Brodowski break; 6727fe2f639SDominik Brodowski case 'p': 6737fe2f639SDominik Brodowski ret = get_policy(cpu); 6747fe2f639SDominik Brodowski break; 6757fe2f639SDominik Brodowski case 'd': 6767fe2f639SDominik Brodowski ret = get_driver(cpu); 6777fe2f639SDominik Brodowski break; 6787fe2f639SDominik Brodowski case 'l': 6797fe2f639SDominik Brodowski ret = get_hardware_limits(cpu); 6807fe2f639SDominik Brodowski break; 6817fe2f639SDominik Brodowski case 'w': 6827fe2f639SDominik Brodowski ret = get_freq_hardware(cpu, human); 6837fe2f639SDominik Brodowski break; 6847fe2f639SDominik Brodowski case 'f': 6857fe2f639SDominik Brodowski ret = get_freq_kernel(cpu, human); 6867fe2f639SDominik Brodowski break; 6877fe2f639SDominik Brodowski case 's': 6887fe2f639SDominik Brodowski ret = get_freq_stats(cpu, human); 6897fe2f639SDominik Brodowski break; 6907fe2f639SDominik Brodowski case 'y': 6917fe2f639SDominik Brodowski ret = get_latency(cpu, human); 6927fe2f639SDominik Brodowski break; 6937fe2f639SDominik Brodowski } 6947fe2f639SDominik Brodowski if (ret) 695a1ce5ba2SDominik Brodowski return ret; 6967fe2f639SDominik Brodowski } 6977fe2f639SDominik Brodowski return ret; 6987fe2f639SDominik Brodowski } 699