1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Intel Corporation
13 #include <rte_memcpy.h>
15 #include "rte_power_pmd_mgmt.h"
16 #include "power_pstate_cpufreq.h"
17 #include "power_common.h"
19 /* macros used for rounding frequency to nearest 100000 */
20 #define FREQ_ROUNDING_DELTA 50000
21 #define ROUND_FREQ_TO_N_100000 100000
23 #define BUS_FREQ 100000
25 #define POWER_GOVERNOR_PERF "performance"
26 #define POWER_SYSFILE_MAX_FREQ \
27 "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_max_freq"
28 #define POWER_SYSFILE_MIN_FREQ \
29 "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_min_freq"
30 #define POWER_SYSFILE_CUR_FREQ \
31 "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq"
32 #define POWER_SYSFILE_BASE_MAX_FREQ \
33 "/sys/devices/system/cpu/cpu%u/cpufreq/cpuinfo_max_freq"
34 #define POWER_SYSFILE_BASE_MIN_FREQ \
35 "/sys/devices/system/cpu/cpu%u/cpufreq/cpuinfo_min_freq"
36 #define POWER_SYSFILE_BASE_FREQ \
37 "/sys/devices/system/cpu/cpu%u/cpufreq/base_frequency"
38 #define POWER_PSTATE_DRIVER "intel_pstate"
39 #define POWER_MSR_PATH "/dev/cpu/%u/msr"
44 #define PLATFORM_INFO 0x0CE
45 #define NON_TURBO_MASK 0xFF00
46 #define NON_TURBO_OFFSET 0x8
56 struct pstate_power_info {
57 unsigned int lcore_id; /**< Logical core id */
58 uint32_t freqs[RTE_MAX_LCORE_FREQS]; /**< Frequency array */
59 uint32_t nb_freqs; /**< number of available freqs */
60 FILE *f_cur_min; /**< FD of scaling_min */
61 FILE *f_cur_max; /**< FD of scaling_max */
62 char governor_ori[32]; /**< Original governor name */
63 uint32_t curr_idx; /**< Freq index in freqs array */
64 uint32_t non_turbo_max_ratio; /**< Non Turbo Max ratio */
65 uint32_t sys_max_freq; /**< system wide max freq */
66 uint32_t core_base_freq; /**< core base freq */
67 uint32_t state; /**< Power in use state */
68 uint16_t turbo_available; /**< Turbo Boost available */
69 uint16_t turbo_enable; /**< Turbo Boost enable/disable */
70 uint16_t priority_core; /**< High Performance core */
71 } __rte_cache_aligned;
74 static struct pstate_power_info lcore_power_info[RTE_MAX_LCORE];
77 * It is to read the specific MSR.
81 power_rdmsr(int msr, uint64_t *val, unsigned int lcore_id)
84 char fullpath[PATH_MAX];
86 snprintf(fullpath, sizeof(fullpath), POWER_MSR_PATH, lcore_id);
88 fd = open(fullpath, O_RDONLY);
91 RTE_LOG(ERR, POWER, "Error opening '%s': %s\n", fullpath,
96 ret = pread(fd, val, sizeof(uint64_t), msr);
99 RTE_LOG(ERR, POWER, "Error reading '%s': %s\n", fullpath,
104 POWER_DEBUG_TRACE("MSR Path %s, offset 0x%X for lcore %u\n",
105 fullpath, msr, lcore_id);
107 POWER_DEBUG_TRACE("Ret value %d, content is 0x%"PRIx64"\n", ret, *val);
114 * It is to fopen the sys file for the future setting the lcore frequency.
117 power_init_for_setting_freq(struct pstate_power_info *pi)
119 FILE *f_base = NULL, *f_base_max = NULL, *f_min = NULL, *f_max = NULL;
120 uint32_t base_ratio, base_max_ratio;
121 uint64_t max_non_turbo;
124 /* open all files we expect to have open */
125 open_core_sysfs_file(&f_base_max, "r", POWER_SYSFILE_BASE_MAX_FREQ,
127 if (f_base_max == NULL) {
128 RTE_LOG(ERR, POWER, "failed to open %s\n",
129 POWER_SYSFILE_BASE_MAX_FREQ);
133 open_core_sysfs_file(&f_min, "rw+", POWER_SYSFILE_MIN_FREQ,
136 RTE_LOG(ERR, POWER, "failed to open %s\n",
137 POWER_SYSFILE_MIN_FREQ);
141 open_core_sysfs_file(&f_max, "rw+", POWER_SYSFILE_MAX_FREQ,
144 RTE_LOG(ERR, POWER, "failed to open %s\n",
145 POWER_SYSFILE_MAX_FREQ);
149 open_core_sysfs_file(&f_base, "r", POWER_SYSFILE_BASE_FREQ,
151 /* base ratio file may not exist in some kernels, so no error check */
153 /* read base max ratio */
154 ret = read_core_sysfs_u32(f_base_max, &base_max_ratio);
156 RTE_LOG(ERR, POWER, "Failed to read %s\n",
157 POWER_SYSFILE_BASE_MAX_FREQ);
161 /* base ratio may not exist */
162 if (f_base != NULL) {
163 ret = read_core_sysfs_u32(f_base, &base_ratio);
165 RTE_LOG(ERR, POWER, "Failed to read %s\n",
166 POWER_SYSFILE_BASE_FREQ);
173 /* Add MSR read to detect turbo status */
174 if (power_rdmsr(PLATFORM_INFO, &max_non_turbo, pi->lcore_id) < 0)
176 /* no errors after this point */
178 /* convert ratios to bins */
179 base_max_ratio /= BUS_FREQ;
180 base_ratio /= BUS_FREQ;
182 /* assign file handles */
183 pi->f_cur_min = f_min;
184 pi->f_cur_max = f_max;
186 max_non_turbo = (max_non_turbo&NON_TURBO_MASK)>>NON_TURBO_OFFSET;
188 POWER_DEBUG_TRACE("no turbo perf %"PRIu64"\n", max_non_turbo);
190 pi->non_turbo_max_ratio = (uint32_t)max_non_turbo;
193 * If base_frequency is reported as greater than the maximum
194 * turbo frequency, that's a known issue with some kernels.
195 * Set base_frequency to max_non_turbo as a workaround.
197 if (base_ratio > base_max_ratio) {
198 /* base_ratio is greater than max turbo. Kernel bug. */
199 pi->priority_core = 0;
204 * If base_frequency is reported as greater than the maximum
205 * non-turbo frequency, then mark it as a high priority core.
207 if (base_ratio > max_non_turbo)
208 pi->priority_core = 1;
210 pi->priority_core = 0;
211 pi->core_base_freq = base_ratio * BUS_FREQ;
217 /* f_min and f_max are stored, no need to close */
223 if (f_base_max != NULL)
233 set_freq_internal(struct pstate_power_info *pi, uint32_t idx)
235 uint32_t target_freq = 0;
237 if (idx >= RTE_MAX_LCORE_FREQS || idx >= pi->nb_freqs) {
238 RTE_LOG(ERR, POWER, "Invalid frequency index %u, which "
239 "should be less than %u\n", idx, pi->nb_freqs);
243 /* Check if it is the same as current */
244 if (idx == pi->curr_idx)
247 /* Because Intel Pstate Driver only allow user change min/max hint
248 * User need change the min/max as same value.
250 if (fseek(pi->f_cur_min, 0, SEEK_SET) < 0) {
251 RTE_LOG(ERR, POWER, "Fail to set file position indicator to 0 "
252 "for setting frequency for lcore %u\n",
257 if (fseek(pi->f_cur_max, 0, SEEK_SET) < 0) {
258 RTE_LOG(ERR, POWER, "Fail to set file position indicator to 0 "
259 "for setting frequency for lcore %u\n",
264 /* Turbo is available and enabled, first freq bucket is sys max freq */
265 if (pi->turbo_available && idx == 0) {
266 if (pi->turbo_enable)
267 target_freq = pi->sys_max_freq;
269 RTE_LOG(ERR, POWER, "Turbo is off, frequency can't be scaled up more %u\n",
274 target_freq = pi->freqs[idx];
276 /* Decrease freq, the min freq should be updated first */
277 if (idx > pi->curr_idx) {
279 if (fprintf(pi->f_cur_min, "%u", target_freq) < 0) {
280 RTE_LOG(ERR, POWER, "Fail to write new frequency for "
281 "lcore %u\n", pi->lcore_id);
285 if (fprintf(pi->f_cur_max, "%u", target_freq) < 0) {
286 RTE_LOG(ERR, POWER, "Fail to write new frequency for "
287 "lcore %u\n", pi->lcore_id);
291 POWER_DEBUG_TRACE("Frequency '%u' to be set for lcore %u\n",
292 target_freq, pi->lcore_id);
294 fflush(pi->f_cur_min);
295 fflush(pi->f_cur_max);
299 /* Increase freq, the max freq should be updated first */
300 if (idx < pi->curr_idx) {
302 if (fprintf(pi->f_cur_max, "%u", target_freq) < 0) {
303 RTE_LOG(ERR, POWER, "Fail to write new frequency for "
304 "lcore %u\n", pi->lcore_id);
308 if (fprintf(pi->f_cur_min, "%u", target_freq) < 0) {
309 RTE_LOG(ERR, POWER, "Fail to write new frequency for "
310 "lcore %u\n", pi->lcore_id);
314 POWER_DEBUG_TRACE("Frequency '%u' to be set for lcore %u\n",
315 target_freq, pi->lcore_id);
317 fflush(pi->f_cur_max);
318 fflush(pi->f_cur_min);
327 * It is to check the current scaling governor by reading sys file, and then
328 * set it into 'performance' if it is not by writing the sys file. The original
329 * governor will be saved for rolling back.
332 power_set_governor_performance(struct pstate_power_info *pi)
334 return power_set_governor(pi->lcore_id, POWER_GOVERNOR_PERF,
335 pi->governor_ori, sizeof(pi->governor_ori));
339 * It is to check the governor and then set the original governor back if
340 * needed by writing the sys file.
343 power_set_governor_original(struct pstate_power_info *pi)
345 return power_set_governor(pi->lcore_id, pi->governor_ori, NULL, 0);
349 * It is to get the available frequencies of the specific lcore by reading the
353 power_get_available_freqs(struct pstate_power_info *pi)
355 FILE *f_min = NULL, *f_max = NULL;
357 uint32_t sys_min_freq = 0, sys_max_freq = 0, base_max_freq = 0;
358 int config_min_freq, config_max_freq;
359 uint32_t i, num_freqs = 0;
362 open_core_sysfs_file(&f_max, "r", POWER_SYSFILE_BASE_MAX_FREQ,
365 RTE_LOG(ERR, POWER, "failed to open %s\n",
366 POWER_SYSFILE_BASE_MAX_FREQ);
370 open_core_sysfs_file(&f_min, "r", POWER_SYSFILE_BASE_MIN_FREQ,
373 RTE_LOG(ERR, POWER, "failed to open %s\n",
374 POWER_SYSFILE_BASE_MIN_FREQ);
378 /* read base ratios */
379 ret = read_core_sysfs_u32(f_max, &sys_max_freq);
381 RTE_LOG(ERR, POWER, "Failed to read %s\n",
382 POWER_SYSFILE_BASE_MAX_FREQ);
386 ret = read_core_sysfs_u32(f_min, &sys_min_freq);
388 RTE_LOG(ERR, POWER, "Failed to read %s\n",
389 POWER_SYSFILE_BASE_MIN_FREQ);
393 /* check for config set by user or application to limit frequency range */
394 config_min_freq = rte_power_pmd_mgmt_get_scaling_freq_min(pi->lcore_id);
395 if (config_min_freq < 0)
397 config_max_freq = rte_power_pmd_mgmt_get_scaling_freq_max(pi->lcore_id);
398 if (config_max_freq < 0)
401 sys_min_freq = RTE_MAX(sys_min_freq, (uint32_t)config_min_freq);
402 if (config_max_freq > 0) /* Only use config_max_freq if a value has been set */
403 sys_max_freq = RTE_MIN(sys_max_freq, (uint32_t)config_max_freq);
405 if (sys_max_freq < sys_min_freq)
408 pi->sys_max_freq = sys_max_freq;
410 if (pi->priority_core == 1)
411 base_max_freq = pi->core_base_freq;
413 base_max_freq = pi->non_turbo_max_ratio * BUS_FREQ;
415 POWER_DEBUG_TRACE("sys min %u, sys max %u, base_max %u\n",
420 if (base_max_freq < sys_max_freq)
421 pi->turbo_available = 1;
423 pi->turbo_available = 0;
425 /* If turbo is available then there is one extra freq bucket
426 * to store the sys max freq which value is base_max +1
428 num_freqs = (RTE_MIN(base_max_freq, sys_max_freq) - sys_min_freq) / BUS_FREQ
429 + 1 + pi->turbo_available;
430 if (num_freqs >= RTE_MAX_LCORE_FREQS) {
431 RTE_LOG(ERR, POWER, "Too many available frequencies: %d\n",
436 /* Generate the freq bucket array.
437 * If turbo is available the freq bucket[0] value is base_max +1
438 * the bucket[1] is base_max, bucket[2] is base_max - BUS_FREQ
440 * If turbo is not available bucket[0] is base_max and so on
442 for (i = 0, pi->nb_freqs = 0; i < num_freqs; i++) {
443 if ((i == 0) && pi->turbo_available)
444 pi->freqs[pi->nb_freqs++] = RTE_MIN(base_max_freq, sys_max_freq) + 1;
446 pi->freqs[pi->nb_freqs++] = RTE_MIN(base_max_freq, sys_max_freq) -
447 (i - pi->turbo_available) * BUS_FREQ;
452 POWER_DEBUG_TRACE("%d frequency(s) of lcore %u are available\n",
453 num_freqs, pi->lcore_id);
465 power_get_cur_idx(struct pstate_power_info *pi)
469 uint32_t sys_cur_freq = 0;
472 open_core_sysfs_file(&f_cur, "r", POWER_SYSFILE_CUR_FREQ,
475 RTE_LOG(ERR, POWER, "failed to open %s\n",
476 POWER_SYSFILE_CUR_FREQ);
480 ret = read_core_sysfs_u32(f_cur, &sys_cur_freq);
482 RTE_LOG(ERR, POWER, "Failed to read %s\n",
483 POWER_SYSFILE_CUR_FREQ);
487 /* convert the frequency to nearest 100000 value
488 * Ex: if sys_cur_freq=1396789 then freq_conv=1400000
489 * Ex: if sys_cur_freq=800030 then freq_conv=800000
490 * Ex: if sys_cur_freq=800030 then freq_conv=800000
492 unsigned int freq_conv = 0;
493 freq_conv = (sys_cur_freq + FREQ_ROUNDING_DELTA)
494 / ROUND_FREQ_TO_N_100000;
495 freq_conv = freq_conv * ROUND_FREQ_TO_N_100000;
497 for (i = 0; i < pi->nb_freqs; i++) {
498 if (freq_conv == pi->freqs[i]) {
512 power_pstate_cpufreq_check_supported(void)
514 return cpufreq_check_scaling_driver(POWER_PSTATE_DRIVER);
518 power_pstate_cpufreq_init(unsigned int lcore_id)
520 struct pstate_power_info *pi;
523 if (lcore_id >= RTE_MAX_LCORE) {
524 RTE_LOG(ERR, POWER, "Lcore id %u can not exceed %u\n",
525 lcore_id, RTE_MAX_LCORE - 1U);
529 pi = &lcore_power_info[lcore_id];
530 exp_state = POWER_IDLE;
531 /* The power in use state works as a guard variable between
532 * the CPU frequency control initialization and exit process.
533 * The ACQUIRE memory ordering here pairs with the RELEASE
534 * ordering below as lock to make sure the frequency operations
535 * in the critical section are done under the correct state.
537 if (!__atomic_compare_exchange_n(&(pi->state), &exp_state,
539 __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) {
540 RTE_LOG(INFO, POWER, "Power management of lcore %u is "
541 "in use\n", lcore_id);
545 pi->lcore_id = lcore_id;
546 /* Check and set the governor */
547 if (power_set_governor_performance(pi) < 0) {
548 RTE_LOG(ERR, POWER, "Cannot set governor of lcore %u to "
549 "performance\n", lcore_id);
552 /* Init for setting lcore frequency */
553 if (power_init_for_setting_freq(pi) < 0) {
554 RTE_LOG(ERR, POWER, "Cannot init for setting frequency for "
555 "lcore %u\n", lcore_id);
559 /* Get the available frequencies */
560 if (power_get_available_freqs(pi) < 0) {
561 RTE_LOG(ERR, POWER, "Cannot get available frequencies of "
562 "lcore %u\n", lcore_id);
566 if (power_get_cur_idx(pi) < 0) {
567 RTE_LOG(ERR, POWER, "Cannot get current frequency "
568 "index of lcore %u\n", lcore_id);
572 /* Set freq to max by default */
573 if (power_pstate_cpufreq_freq_max(lcore_id) < 0) {
574 RTE_LOG(ERR, POWER, "Cannot set frequency of lcore %u "
575 "to max\n", lcore_id);
579 RTE_LOG(INFO, POWER, "Initialized successfully for lcore %u "
580 "power management\n", lcore_id);
581 exp_state = POWER_ONGOING;
582 __atomic_compare_exchange_n(&(pi->state), &exp_state, POWER_USED,
583 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
588 exp_state = POWER_ONGOING;
589 __atomic_compare_exchange_n(&(pi->state), &exp_state, POWER_UNKNOWN,
590 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
596 power_pstate_cpufreq_exit(unsigned int lcore_id)
598 struct pstate_power_info *pi;
601 if (lcore_id >= RTE_MAX_LCORE) {
602 RTE_LOG(ERR, POWER, "Lcore id %u can not exceeds %u\n",
603 lcore_id, RTE_MAX_LCORE - 1U);
606 pi = &lcore_power_info[lcore_id];
608 exp_state = POWER_USED;
609 /* The power in use state works as a guard variable between
610 * the CPU frequency control initialization and exit process.
611 * The ACQUIRE memory ordering here pairs with the RELEASE
612 * ordering below as lock to make sure the frequency operations
613 * in the critical section are under done the correct state.
615 if (!__atomic_compare_exchange_n(&(pi->state), &exp_state,
617 __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) {
618 RTE_LOG(INFO, POWER, "Power management of lcore %u is "
619 "not used\n", lcore_id);
623 /* Close FD of setting freq */
624 fclose(pi->f_cur_min);
625 fclose(pi->f_cur_max);
626 pi->f_cur_min = NULL;
627 pi->f_cur_max = NULL;
629 /* Set the governor back to the original */
630 if (power_set_governor_original(pi) < 0) {
631 RTE_LOG(ERR, POWER, "Cannot set the governor of %u back "
632 "to the original\n", lcore_id);
636 RTE_LOG(INFO, POWER, "Power management of lcore %u has exited from "
637 "'performance' mode and been set back to the "
638 "original\n", lcore_id);
639 exp_state = POWER_ONGOING;
640 __atomic_compare_exchange_n(&(pi->state), &exp_state, POWER_IDLE,
641 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
646 exp_state = POWER_ONGOING;
647 __atomic_compare_exchange_n(&(pi->state), &exp_state, POWER_UNKNOWN,
648 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
655 power_pstate_cpufreq_freqs(unsigned int lcore_id, uint32_t *freqs, uint32_t num)
657 struct pstate_power_info *pi;
659 if (lcore_id >= RTE_MAX_LCORE) {
660 RTE_LOG(ERR, POWER, "Invalid lcore ID\n");
665 RTE_LOG(ERR, POWER, "NULL buffer supplied\n");
669 pi = &lcore_power_info[lcore_id];
670 if (num < pi->nb_freqs) {
671 RTE_LOG(ERR, POWER, "Buffer size is not enough\n");
674 rte_memcpy(freqs, pi->freqs, pi->nb_freqs * sizeof(uint32_t));
680 power_pstate_cpufreq_get_freq(unsigned int lcore_id)
682 if (lcore_id >= RTE_MAX_LCORE) {
683 RTE_LOG(ERR, POWER, "Invalid lcore ID\n");
684 return RTE_POWER_INVALID_FREQ_INDEX;
687 return lcore_power_info[lcore_id].curr_idx;
692 power_pstate_cpufreq_set_freq(unsigned int lcore_id, uint32_t index)
694 if (lcore_id >= RTE_MAX_LCORE) {
695 RTE_LOG(ERR, POWER, "Invalid lcore ID\n");
699 return set_freq_internal(&(lcore_power_info[lcore_id]), index);
703 power_pstate_cpufreq_freq_up(unsigned int lcore_id)
705 struct pstate_power_info *pi;
707 if (lcore_id >= RTE_MAX_LCORE) {
708 RTE_LOG(ERR, POWER, "Invalid lcore ID\n");
712 pi = &lcore_power_info[lcore_id];
713 if (pi->curr_idx == 0 ||
714 (pi->curr_idx == 1 && pi->turbo_available && !pi->turbo_enable))
717 /* Frequencies in the array are from high to low. */
718 return set_freq_internal(pi, pi->curr_idx - 1);
722 power_pstate_cpufreq_freq_down(unsigned int lcore_id)
724 struct pstate_power_info *pi;
726 if (lcore_id >= RTE_MAX_LCORE) {
727 RTE_LOG(ERR, POWER, "Invalid lcore ID\n");
731 pi = &lcore_power_info[lcore_id];
732 if (pi->curr_idx + 1 == pi->nb_freqs)
735 /* Frequencies in the array are from high to low. */
736 return set_freq_internal(pi, pi->curr_idx + 1);
740 power_pstate_cpufreq_freq_max(unsigned int lcore_id)
742 if (lcore_id >= RTE_MAX_LCORE) {
743 RTE_LOG(ERR, POWER, "Invalid lcore ID\n");
747 /* Frequencies in the array are from high to low. */
748 if (lcore_power_info[lcore_id].turbo_available) {
749 if (lcore_power_info[lcore_id].turbo_enable)
751 return set_freq_internal(
752 &lcore_power_info[lcore_id], 0);
754 /* Set to max non-turbo */
755 return set_freq_internal(
756 &lcore_power_info[lcore_id], 1);
758 return set_freq_internal(&lcore_power_info[lcore_id], 0);
763 power_pstate_cpufreq_freq_min(unsigned int lcore_id)
765 struct pstate_power_info *pi;
767 if (lcore_id >= RTE_MAX_LCORE) {
768 RTE_LOG(ERR, POWER, "Invalid lcore ID\n");
772 pi = &lcore_power_info[lcore_id];
774 /* Frequencies in the array are from high to low. */
775 return set_freq_internal(pi, pi->nb_freqs - 1);
780 power_pstate_turbo_status(unsigned int lcore_id)
782 struct pstate_power_info *pi;
784 if (lcore_id >= RTE_MAX_LCORE) {
785 RTE_LOG(ERR, POWER, "Invalid lcore ID\n");
789 pi = &lcore_power_info[lcore_id];
791 return pi->turbo_enable;
795 power_pstate_enable_turbo(unsigned int lcore_id)
797 struct pstate_power_info *pi;
799 if (lcore_id >= RTE_MAX_LCORE) {
800 RTE_LOG(ERR, POWER, "Invalid lcore ID\n");
804 pi = &lcore_power_info[lcore_id];
806 if (pi->turbo_available)
807 pi->turbo_enable = 1;
809 pi->turbo_enable = 0;
811 "Failed to enable turbo on lcore %u\n",
821 power_pstate_disable_turbo(unsigned int lcore_id)
823 struct pstate_power_info *pi;
825 if (lcore_id >= RTE_MAX_LCORE) {
826 RTE_LOG(ERR, POWER, "Invalid lcore ID\n");
830 pi = &lcore_power_info[lcore_id];
832 pi->turbo_enable = 0;
834 if (pi->turbo_available && pi->curr_idx <= 1) {
835 /* Try to set freq to max by default coming out of turbo */
836 if (power_pstate_cpufreq_freq_max(lcore_id) < 0) {
838 "Failed to set frequency of lcore %u to max\n",
848 int power_pstate_get_capabilities(unsigned int lcore_id,
849 struct rte_power_core_capabilities *caps)
851 struct pstate_power_info *pi;
853 if (lcore_id >= RTE_MAX_LCORE) {
854 RTE_LOG(ERR, POWER, "Invalid lcore ID\n");
858 RTE_LOG(ERR, POWER, "Invalid argument\n");
862 pi = &lcore_power_info[lcore_id];
863 caps->capabilities = 0;
864 caps->turbo = !!(pi->turbo_available);
865 caps->priority = pi->priority_core;