Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'linux-cpupower-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux

Pull cpupower utility updates for 5.18-rc1 from Shuah Khan:

"This cpupower update for Linux 5.18-rc1 adds AMD P-State Support to
cpupower tool. AMD P-State kernel support went into 5.17-rc1."

* tag 'linux-cpupower-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux:
cpupower: Add "perf" option to print AMD P-State information
cpupower: Add function to print AMD P-State performance capabilities
cpupower: Move print_speed function into misc helper
cpupower: Enable boost state support for AMD P-State module
cpupower: Add AMD P-State sysfs definition and access helper
cpupower: Introduce ACPI CPPC library
cpupower: Add the function to get the sysfs value from specific table
cpupower: Initial AMD P-State capability
cpupower: Add the function to check AMD P-State enabled
cpupower: Add AMD P-State capability flag

+321 -62
+3 -3
tools/power/cpupower/Makefile
··· 143 143 utils/helpers/bitmask.h \ 144 144 utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def 145 145 146 - LIB_HEADERS = lib/cpufreq.h lib/cpupower.h lib/cpuidle.h 147 - LIB_SRC = lib/cpufreq.c lib/cpupower.c lib/cpuidle.c 148 - LIB_OBJS = lib/cpufreq.o lib/cpupower.o lib/cpuidle.o 146 + LIB_HEADERS = lib/cpufreq.h lib/cpupower.h lib/cpuidle.h lib/acpi_cppc.h 147 + LIB_SRC = lib/cpufreq.c lib/cpupower.c lib/cpuidle.c lib/acpi_cppc.c 148 + LIB_OBJS = lib/cpufreq.o lib/cpupower.o lib/cpuidle.o lib/acpi_cppc.o 149 149 LIB_OBJS := $(addprefix $(OUTPUT),$(LIB_OBJS)) 150 150 151 151 override CFLAGS += -pipe
+59
tools/power/cpupower/lib/acpi_cppc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + #include <stdio.h> 4 + #include <errno.h> 5 + #include <stdlib.h> 6 + #include <string.h> 7 + #include <sys/types.h> 8 + #include <sys/stat.h> 9 + #include <fcntl.h> 10 + #include <unistd.h> 11 + 12 + #include "cpupower_intern.h" 13 + #include "acpi_cppc.h" 14 + 15 + /* ACPI CPPC sysfs access ***********************************************/ 16 + 17 + static int acpi_cppc_read_file(unsigned int cpu, const char *fname, 18 + char *buf, size_t buflen) 19 + { 20 + char path[SYSFS_PATH_MAX]; 21 + 22 + snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/acpi_cppc/%s", 23 + cpu, fname); 24 + return cpupower_read_sysfs(path, buf, buflen); 25 + } 26 + 27 + static const char * const acpi_cppc_value_files[] = { 28 + [HIGHEST_PERF] = "highest_perf", 29 + [LOWEST_PERF] = "lowest_perf", 30 + [NOMINAL_PERF] = "nominal_perf", 31 + [LOWEST_NONLINEAR_PERF] = "lowest_nonlinear_perf", 32 + [LOWEST_FREQ] = "lowest_freq", 33 + [NOMINAL_FREQ] = "nominal_freq", 34 + [REFERENCE_PERF] = "reference_perf", 35 + [WRAPAROUND_TIME] = "wraparound_time" 36 + }; 37 + 38 + unsigned long acpi_cppc_get_data(unsigned int cpu, enum acpi_cppc_value which) 39 + { 40 + unsigned long long value; 41 + unsigned int len; 42 + char linebuf[MAX_LINE_LEN]; 43 + char *endp; 44 + 45 + if (which >= MAX_CPPC_VALUE_FILES) 46 + return 0; 47 + 48 + len = acpi_cppc_read_file(cpu, acpi_cppc_value_files[which], 49 + linebuf, sizeof(linebuf)); 50 + if (len == 0) 51 + return 0; 52 + 53 + value = strtoull(linebuf, &endp, 0); 54 + 55 + if (endp == linebuf || errno == ERANGE) 56 + return 0; 57 + 58 + return value; 59 + }
+21
tools/power/cpupower/lib/acpi_cppc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef __ACPI_CPPC_H__ 4 + #define __ACPI_CPPC_H__ 5 + 6 + enum acpi_cppc_value { 7 + HIGHEST_PERF, 8 + LOWEST_PERF, 9 + NOMINAL_PERF, 10 + LOWEST_NONLINEAR_PERF, 11 + LOWEST_FREQ, 12 + NOMINAL_FREQ, 13 + REFERENCE_PERF, 14 + WRAPAROUND_TIME, 15 + MAX_CPPC_VALUE_FILES 16 + }; 17 + 18 + unsigned long acpi_cppc_get_data(unsigned int cpu, 19 + enum acpi_cppc_value which); 20 + 21 + #endif /* _ACPI_CPPC_H */
+16 -7
tools/power/cpupower/lib/cpufreq.c
··· 83 83 [STATS_NUM_TRANSITIONS] = "stats/total_trans" 84 84 }; 85 85 86 - 87 - static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu, 88 - enum cpufreq_value which) 86 + unsigned long cpufreq_get_sysfs_value_from_table(unsigned int cpu, 87 + const char **table, 88 + unsigned int index, 89 + unsigned int size) 89 90 { 90 91 unsigned long value; 91 92 unsigned int len; 92 93 char linebuf[MAX_LINE_LEN]; 93 94 char *endp; 94 95 95 - if (which >= MAX_CPUFREQ_VALUE_READ_FILES) 96 + if (!table || index >= size || !table[index]) 96 97 return 0; 97 98 98 - len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which], 99 - linebuf, sizeof(linebuf)); 99 + len = sysfs_cpufreq_read_file(cpu, table[index], linebuf, 100 + sizeof(linebuf)); 100 101 101 102 if (len == 0) 102 103 return 0; ··· 108 107 return 0; 109 108 110 109 return value; 110 + } 111 + 112 + static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu, 113 + enum cpufreq_value which) 114 + { 115 + return cpufreq_get_sysfs_value_from_table(cpu, cpufreq_value_files, 116 + which, 117 + MAX_CPUFREQ_VALUE_READ_FILES); 111 118 } 112 119 113 120 /* read access to files which contain one string */ ··· 133 124 134 125 135 126 static char *sysfs_cpufreq_get_one_string(unsigned int cpu, 136 - enum cpufreq_string which) 127 + enum cpufreq_string which) 137 128 { 138 129 char linebuf[MAX_LINE_LEN]; 139 130 char *result;
+12
tools/power/cpupower/lib/cpufreq.h
··· 203 203 int cpufreq_set_frequency(unsigned int cpu, 204 204 unsigned long target_frequency); 205 205 206 + /* 207 + * get the sysfs value from specific table 208 + * 209 + * Read the value with the sysfs file name from specific table. Does 210 + * only work if the cpufreq driver has the specific sysfs interfaces. 211 + */ 212 + 213 + unsigned long cpufreq_get_sysfs_value_from_table(unsigned int cpu, 214 + const char **table, 215 + unsigned int index, 216 + unsigned int size); 217 + 206 218 #ifdef __cplusplus 207 219 } 208 220 #endif
+3
tools/power/cpupower/man/cpupower-frequency-info.1
··· 53 53 \fB\-n\fR \fB\-\-no-rounding\fR 54 54 Output frequencies and latencies without rounding off values. 55 55 .TP 56 + \fB\-c\fR \fB\-\-perf\fR 57 + Get performances and frequencies capabilities of CPPC, by reading it from hardware (only available on the hardware with CPPC). 58 + .TP 56 59 .SH "REMARKS" 57 60 .LP 58 61 By default only values of core zero are displayed. How to display settings of
+35 -52
tools/power/cpupower/utils/cpufreq-info.c
··· 84 84 } 85 85 86 86 static int no_rounding; 87 - static void print_speed(unsigned long speed) 88 - { 89 - unsigned long tmp; 90 - 91 - if (no_rounding) { 92 - if (speed > 1000000) 93 - printf("%u.%06u GHz", ((unsigned int) speed/1000000), 94 - ((unsigned int) speed%1000000)); 95 - else if (speed > 1000) 96 - printf("%u.%03u MHz", ((unsigned int) speed/1000), 97 - (unsigned int) (speed%1000)); 98 - else 99 - printf("%lu kHz", speed); 100 - } else { 101 - if (speed > 1000000) { 102 - tmp = speed%10000; 103 - if (tmp >= 5000) 104 - speed += 10000; 105 - printf("%u.%02u GHz", ((unsigned int) speed/1000000), 106 - ((unsigned int) (speed%1000000)/10000)); 107 - } else if (speed > 100000) { 108 - tmp = speed%1000; 109 - if (tmp >= 500) 110 - speed += 1000; 111 - printf("%u MHz", ((unsigned int) speed/1000)); 112 - } else if (speed > 1000) { 113 - tmp = speed%100; 114 - if (tmp >= 50) 115 - speed += 100; 116 - printf("%u.%01u MHz", ((unsigned int) speed/1000), 117 - ((unsigned int) (speed%1000)/100)); 118 - } 119 - } 120 - 121 - return; 122 - } 123 - 124 87 static void print_duration(unsigned long duration) 125 88 { 126 89 unsigned long tmp; ··· 146 183 printf(_(" Supported: %s\n"), support ? _("yes") : _("no")); 147 184 printf(_(" Active: %s\n"), active ? _("yes") : _("no")); 148 185 149 - if ((cpupower_cpu_info.vendor == X86_VENDOR_AMD && 150 - cpupower_cpu_info.family >= 0x10) || 151 - cpupower_cpu_info.vendor == X86_VENDOR_HYGON) { 186 + if (cpupower_cpu_info.vendor == X86_VENDOR_AMD && 187 + cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATE) { 188 + return 0; 189 + } else if ((cpupower_cpu_info.vendor == X86_VENDOR_AMD && 190 + cpupower_cpu_info.family >= 0x10) || 191 + cpupower_cpu_info.vendor == X86_VENDOR_HYGON) { 152 192 ret = decode_pstates(cpu, b_states, pstates, &pstate_no); 153 193 if (ret) 154 194 return ret; ··· 220 254 if (freqs) { 221 255 printf(_(" boost frequency steps: ")); 222 256 while (freqs->next) { 223 - print_speed(freqs->frequency); 257 + print_speed(freqs->frequency, no_rounding); 224 258 printf(", "); 225 259 freqs = freqs->next; 226 260 } 227 - print_speed(freqs->frequency); 261 + print_speed(freqs->frequency, no_rounding); 228 262 printf("\n"); 229 263 cpufreq_put_available_frequencies(freqs); 230 264 } ··· 243 277 return -EINVAL; 244 278 } 245 279 if (human) { 246 - print_speed(freq); 280 + print_speed(freq, no_rounding); 247 281 } else 248 282 printf("%lu", freq); 249 283 printf(_(" (asserted by call to kernel)\n")); ··· 262 296 return -EINVAL; 263 297 } 264 298 if (human) { 265 - print_speed(freq); 299 + print_speed(freq, no_rounding); 266 300 } else 267 301 printf("%lu", freq); 268 302 printf(_(" (asserted by call to hardware)\n")); ··· 282 316 283 317 if (human) { 284 318 printf(_(" hardware limits: ")); 285 - print_speed(min); 319 + print_speed(min, no_rounding); 286 320 printf(" - "); 287 - print_speed(max); 321 + print_speed(max, no_rounding); 288 322 printf("\n"); 289 323 } else { 290 324 printf("%lu %lu\n", min, max); ··· 316 350 return -EINVAL; 317 351 } 318 352 printf(_(" current policy: frequency should be within ")); 319 - print_speed(policy->min); 353 + print_speed(policy->min, no_rounding); 320 354 printf(_(" and ")); 321 - print_speed(policy->max); 355 + print_speed(policy->max, no_rounding); 322 356 323 357 printf(".\n "); 324 358 printf(_("The governor \"%s\" may decide which speed to use\n" ··· 402 436 struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time); 403 437 while (stats) { 404 438 if (human) { 405 - print_speed(stats->frequency); 439 + print_speed(stats->frequency, no_rounding); 406 440 printf(":%.2f%%", 407 441 (100.0 * stats->time_in_state) / total_time); 408 442 } else ··· 438 472 return 0; 439 473 } 440 474 475 + /* --performance / -c */ 476 + 477 + static int get_perf_cap(unsigned int cpu) 478 + { 479 + if (cpupower_cpu_info.vendor == X86_VENDOR_AMD && 480 + cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATE) 481 + amd_pstate_show_perf_and_freq(cpu, no_rounding); 482 + 483 + return 0; 484 + } 485 + 441 486 static void debug_output_one(unsigned int cpu) 442 487 { 443 488 struct cpufreq_available_frequencies *freqs; ··· 463 486 if (freqs) { 464 487 printf(_(" available frequency steps: ")); 465 488 while (freqs->next) { 466 - print_speed(freqs->frequency); 489 + print_speed(freqs->frequency, no_rounding); 467 490 printf(", "); 468 491 freqs = freqs->next; 469 492 } 470 - print_speed(freqs->frequency); 493 + print_speed(freqs->frequency, no_rounding); 471 494 printf("\n"); 472 495 cpufreq_put_available_frequencies(freqs); 473 496 } ··· 477 500 if (get_freq_hardware(cpu, 1) < 0) 478 501 get_freq_kernel(cpu, 1); 479 502 get_boost_mode(cpu); 503 + get_perf_cap(cpu); 480 504 } 481 505 482 506 static struct option info_opts[] = { ··· 496 518 {"proc", no_argument, NULL, 'o'}, 497 519 {"human", no_argument, NULL, 'm'}, 498 520 {"no-rounding", no_argument, NULL, 'n'}, 521 + {"performance", no_argument, NULL, 'c'}, 499 522 { }, 500 523 }; 501 524 ··· 510 531 int output_param = 0; 511 532 512 533 do { 513 - ret = getopt_long(argc, argv, "oefwldpgrasmybn", info_opts, 534 + ret = getopt_long(argc, argv, "oefwldpgrasmybnc", info_opts, 514 535 NULL); 515 536 switch (ret) { 516 537 case '?': ··· 533 554 case 'e': 534 555 case 's': 535 556 case 'y': 557 + case 'c': 536 558 if (output_param) { 537 559 output_param = -1; 538 560 cont = 0; ··· 639 659 break; 640 660 case 'y': 641 661 ret = get_latency(cpu, human); 662 + break; 663 + case 'c': 664 + ret = get_perf_cap(cpu); 642 665 break; 643 666 } 644 667 if (ret)
+77
tools/power/cpupower/utils/helpers/amd.c
··· 8 8 #include <pci/pci.h> 9 9 10 10 #include "helpers/helpers.h" 11 + #include "cpufreq.h" 12 + #include "acpi_cppc.h" 11 13 14 + /* ACPI P-States Helper Functions for AMD Processors ***************/ 12 15 #define MSR_AMD_PSTATE_STATUS 0xc0010063 13 16 #define MSR_AMD_PSTATE 0xc0010064 14 17 #define MSR_AMD_PSTATE_LIMIT 0xc0010061 ··· 149 146 pci_cleanup(pci_acc); 150 147 return 0; 151 148 } 149 + 150 + /* ACPI P-States Helper Functions for AMD Processors ***************/ 151 + 152 + /* AMD P-State Helper Functions ************************************/ 153 + enum amd_pstate_value { 154 + AMD_PSTATE_HIGHEST_PERF, 155 + AMD_PSTATE_MAX_FREQ, 156 + AMD_PSTATE_LOWEST_NONLINEAR_FREQ, 157 + MAX_AMD_PSTATE_VALUE_READ_FILES, 158 + }; 159 + 160 + static const char *amd_pstate_value_files[MAX_AMD_PSTATE_VALUE_READ_FILES] = { 161 + [AMD_PSTATE_HIGHEST_PERF] = "amd_pstate_highest_perf", 162 + [AMD_PSTATE_MAX_FREQ] = "amd_pstate_max_freq", 163 + [AMD_PSTATE_LOWEST_NONLINEAR_FREQ] = "amd_pstate_lowest_nonlinear_freq", 164 + }; 165 + 166 + static unsigned long amd_pstate_get_data(unsigned int cpu, 167 + enum amd_pstate_value value) 168 + { 169 + return cpufreq_get_sysfs_value_from_table(cpu, 170 + amd_pstate_value_files, 171 + value, 172 + MAX_AMD_PSTATE_VALUE_READ_FILES); 173 + } 174 + 175 + void amd_pstate_boost_init(unsigned int cpu, int *support, int *active) 176 + { 177 + unsigned long highest_perf, nominal_perf, cpuinfo_min, 178 + cpuinfo_max, amd_pstate_max; 179 + 180 + highest_perf = amd_pstate_get_data(cpu, AMD_PSTATE_HIGHEST_PERF); 181 + nominal_perf = acpi_cppc_get_data(cpu, NOMINAL_PERF); 182 + 183 + *support = highest_perf > nominal_perf ? 1 : 0; 184 + if (!(*support)) 185 + return; 186 + 187 + cpufreq_get_hardware_limits(cpu, &cpuinfo_min, &cpuinfo_max); 188 + amd_pstate_max = amd_pstate_get_data(cpu, AMD_PSTATE_MAX_FREQ); 189 + 190 + *active = cpuinfo_max == amd_pstate_max ? 1 : 0; 191 + } 192 + 193 + void amd_pstate_show_perf_and_freq(unsigned int cpu, int no_rounding) 194 + { 195 + printf(_(" AMD PSTATE Highest Performance: %lu. Maximum Frequency: "), 196 + amd_pstate_get_data(cpu, AMD_PSTATE_HIGHEST_PERF)); 197 + /* 198 + * If boost isn't active, the cpuinfo_max doesn't indicate real max 199 + * frequency. So we read it back from amd-pstate sysfs entry. 200 + */ 201 + print_speed(amd_pstate_get_data(cpu, AMD_PSTATE_MAX_FREQ), no_rounding); 202 + printf(".\n"); 203 + 204 + printf(_(" AMD PSTATE Nominal Performance: %lu. Nominal Frequency: "), 205 + acpi_cppc_get_data(cpu, NOMINAL_PERF)); 206 + print_speed(acpi_cppc_get_data(cpu, NOMINAL_FREQ) * 1000, 207 + no_rounding); 208 + printf(".\n"); 209 + 210 + printf(_(" AMD PSTATE Lowest Non-linear Performance: %lu. Lowest Non-linear Frequency: "), 211 + acpi_cppc_get_data(cpu, LOWEST_NONLINEAR_PERF)); 212 + print_speed(amd_pstate_get_data(cpu, AMD_PSTATE_LOWEST_NONLINEAR_FREQ), 213 + no_rounding); 214 + printf(".\n"); 215 + 216 + printf(_(" AMD PSTATE Lowest Performance: %lu. Lowest Frequency: "), 217 + acpi_cppc_get_data(cpu, LOWEST_PERF)); 218 + print_speed(acpi_cppc_get_data(cpu, LOWEST_FREQ) * 1000, no_rounding); 219 + printf(".\n"); 220 + } 221 + 222 + /* AMD P-State Helper Functions ************************************/ 152 223 #endif /* defined(__i386__) || defined(__x86_64__) */
+13
tools/power/cpupower/utils/helpers/cpuid.c
··· 149 149 if (ext_cpuid_level >= 0x80000008 && 150 150 cpuid_ebx(0x80000008) & (1 << 4)) 151 151 cpu_info->caps |= CPUPOWER_CAP_AMD_RDPRU; 152 + 153 + if (cpupower_amd_pstate_enabled()) { 154 + cpu_info->caps |= CPUPOWER_CAP_AMD_PSTATE; 155 + 156 + /* 157 + * If AMD P-State is enabled, the firmware will treat 158 + * AMD P-State function as high priority. 159 + */ 160 + cpu_info->caps &= ~CPUPOWER_CAP_AMD_CPB; 161 + cpu_info->caps &= ~CPUPOWER_CAP_AMD_CPB_MSR; 162 + cpu_info->caps &= ~CPUPOWER_CAP_AMD_HW_PSTATE; 163 + cpu_info->caps &= ~CPUPOWER_CAP_AMD_PSTATEDEF; 164 + } 152 165 } 153 166 154 167 if (cpu_info->vendor == X86_VENDOR_INTEL) {
+22
tools/power/cpupower/utils/helpers/helpers.h
··· 11 11 12 12 #include <libintl.h> 13 13 #include <locale.h> 14 + #include <stdbool.h> 14 15 15 16 #include "helpers/bitmask.h" 16 17 #include <cpupower.h> ··· 74 73 #define CPUPOWER_CAP_AMD_HW_PSTATE 0x00000100 75 74 #define CPUPOWER_CAP_AMD_PSTATEDEF 0x00000200 76 75 #define CPUPOWER_CAP_AMD_CPB_MSR 0x00000400 76 + #define CPUPOWER_CAP_AMD_PSTATE 0x00000800 77 77 78 78 #define CPUPOWER_AMD_CPBDIS 0x02000000 79 79 ··· 137 135 138 136 extern int cpufreq_has_boost_support(unsigned int cpu, int *support, 139 137 int *active, int * states); 138 + 139 + /* AMD P-State stuff **************************/ 140 + bool cpupower_amd_pstate_enabled(void); 141 + void amd_pstate_boost_init(unsigned int cpu, 142 + int *support, int *active); 143 + void amd_pstate_show_perf_and_freq(unsigned int cpu, 144 + int no_rounding); 145 + 146 + /* AMD P-State stuff **************************/ 147 + 140 148 /* 141 149 * CPUID functions returning a single datum 142 150 */ ··· 179 167 int *active, int * states) 180 168 { return -1; } 181 169 170 + static inline bool cpupower_amd_pstate_enabled(void) 171 + { return false; } 172 + static inline void amd_pstate_boost_init(unsigned int cpu, int *support, 173 + int *active) 174 + {} 175 + static inline void amd_pstate_show_perf_and_freq(unsigned int cpu, 176 + int no_rounding) 177 + {} 178 + 182 179 /* cpuid and cpuinfo helpers **************************/ 183 180 184 181 static inline unsigned int cpuid_eax(unsigned int op) { return 0; }; ··· 205 184 void get_cpustate(void); 206 185 void print_online_cpus(void); 207 186 void print_offline_cpus(void); 187 + void print_speed(unsigned long speed, int no_rounding); 208 188 209 189 #endif /* __CPUPOWERUTILS_HELPERS__ */
+60
tools/power/cpupower/utils/helpers/misc.c
··· 3 3 #include <stdio.h> 4 4 #include <errno.h> 5 5 #include <stdlib.h> 6 + #include <string.h> 6 7 7 8 #include "helpers/helpers.h" 8 9 #include "helpers/sysfs.h" 10 + #include "cpufreq.h" 9 11 10 12 #if defined(__i386__) || defined(__x86_64__) 11 13 ··· 41 39 if (ret) 42 40 return ret; 43 41 } 42 + } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATE) { 43 + amd_pstate_boost_init(cpu, support, active); 44 44 } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA) 45 45 *support = *active = 1; 46 46 return 0; ··· 85 81 return -1; 86 82 87 83 return 0; 84 + } 85 + 86 + bool cpupower_amd_pstate_enabled(void) 87 + { 88 + char *driver = cpufreq_get_driver(0); 89 + bool ret = false; 90 + 91 + if (!driver) 92 + return ret; 93 + 94 + if (!strcmp(driver, "amd-pstate")) 95 + ret = true; 96 + 97 + cpufreq_put_driver(driver); 98 + 99 + return ret; 88 100 } 89 101 90 102 #endif /* #if defined(__i386__) || defined(__x86_64__) */ ··· 162 142 bitmask_displaylist(offline_cpus_str, str_len, offline_cpus); 163 143 printf(_("Following CPUs are offline:\n%s\n"), offline_cpus_str); 164 144 printf(_("cpupower set operation was not performed on them\n")); 145 + } 146 + } 147 + 148 + /* 149 + * print_speed 150 + * 151 + * Print the exact CPU frequency with appropriate unit 152 + */ 153 + void print_speed(unsigned long speed, int no_rounding) 154 + { 155 + unsigned long tmp; 156 + 157 + if (no_rounding) { 158 + if (speed > 1000000) 159 + printf("%u.%06u GHz", ((unsigned int)speed / 1000000), 160 + ((unsigned int)speed % 1000000)); 161 + else if (speed > 1000) 162 + printf("%u.%03u MHz", ((unsigned int)speed / 1000), 163 + (unsigned int)(speed % 1000)); 164 + else 165 + printf("%lu kHz", speed); 166 + } else { 167 + if (speed > 1000000) { 168 + tmp = speed % 10000; 169 + if (tmp >= 5000) 170 + speed += 10000; 171 + printf("%u.%02u GHz", ((unsigned int)speed / 1000000), 172 + ((unsigned int)(speed % 1000000) / 10000)); 173 + } else if (speed > 100000) { 174 + tmp = speed % 1000; 175 + if (tmp >= 500) 176 + speed += 1000; 177 + printf("%u MHz", ((unsigned int)speed / 1000)); 178 + } else if (speed > 1000) { 179 + tmp = speed % 100; 180 + if (tmp >= 50) 181 + speed += 100; 182 + printf("%u.%01u MHz", ((unsigned int)speed / 1000), 183 + ((unsigned int)(speed % 1000) / 100)); 184 + } 165 185 } 166 186 }