f-stack/dpdk/lib/power/rte_power_uncore.c

194 lines
5.2 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2010-2014 Intel Corporation
* Copyright(c) 2023 AMD Corporation
*/
#include <errno.h>
#include <rte_errno.h>
#include <rte_spinlock.h>
#include "rte_power_uncore.h"
#include "power_intel_uncore.h"
enum rte_uncore_power_mgmt_env default_uncore_env = RTE_UNCORE_PM_ENV_NOT_SET;
static rte_spinlock_t global_env_cfg_lock = RTE_SPINLOCK_INITIALIZER;
static uint32_t
power_get_dummy_uncore_freq(unsigned int pkg __rte_unused,
unsigned int die __rte_unused)
{
return 0;
}
static int
power_set_dummy_uncore_freq(unsigned int pkg __rte_unused,
unsigned int die __rte_unused, uint32_t index __rte_unused)
{
return 0;
}
static int
power_dummy_uncore_freq_max(unsigned int pkg __rte_unused,
unsigned int die __rte_unused)
{
return 0;
}
static int
power_dummy_uncore_freq_min(unsigned int pkg __rte_unused,
unsigned int die __rte_unused)
{
return 0;
}
static int
power_dummy_uncore_freqs(unsigned int pkg __rte_unused, unsigned int die __rte_unused,
uint32_t *freqs __rte_unused, uint32_t num __rte_unused)
{
return 0;
}
static int
power_dummy_uncore_get_num_freqs(unsigned int pkg __rte_unused,
unsigned int die __rte_unused)
{
return 0;
}
static unsigned int
power_dummy_uncore_get_num_pkgs(void)
{
return 0;
}
static unsigned int
power_dummy_uncore_get_num_dies(unsigned int pkg __rte_unused)
{
return 0;
}
/* function pointers */
rte_power_get_uncore_freq_t rte_power_get_uncore_freq = power_get_dummy_uncore_freq;
rte_power_set_uncore_freq_t rte_power_set_uncore_freq = power_set_dummy_uncore_freq;
rte_power_uncore_freq_change_t rte_power_uncore_freq_max = power_dummy_uncore_freq_max;
rte_power_uncore_freq_change_t rte_power_uncore_freq_min = power_dummy_uncore_freq_min;
rte_power_uncore_freqs_t rte_power_uncore_freqs = power_dummy_uncore_freqs;
rte_power_uncore_get_num_freqs_t rte_power_uncore_get_num_freqs = power_dummy_uncore_get_num_freqs;
rte_power_uncore_get_num_pkgs_t rte_power_uncore_get_num_pkgs = power_dummy_uncore_get_num_pkgs;
rte_power_uncore_get_num_dies_t rte_power_uncore_get_num_dies = power_dummy_uncore_get_num_dies;
static void
reset_power_uncore_function_ptrs(void)
{
rte_power_get_uncore_freq = power_get_dummy_uncore_freq;
rte_power_set_uncore_freq = power_set_dummy_uncore_freq;
rte_power_uncore_freq_max = power_dummy_uncore_freq_max;
rte_power_uncore_freq_min = power_dummy_uncore_freq_min;
rte_power_uncore_freqs = power_dummy_uncore_freqs;
rte_power_uncore_get_num_freqs = power_dummy_uncore_get_num_freqs;
rte_power_uncore_get_num_pkgs = power_dummy_uncore_get_num_pkgs;
rte_power_uncore_get_num_dies = power_dummy_uncore_get_num_dies;
}
int
rte_power_set_uncore_env(enum rte_uncore_power_mgmt_env env)
{
int ret;
rte_spinlock_lock(&global_env_cfg_lock);
if (default_uncore_env != RTE_UNCORE_PM_ENV_NOT_SET) {
RTE_LOG(ERR, POWER, "Uncore Power Management Env already set.\n");
rte_spinlock_unlock(&global_env_cfg_lock);
return -1;
}
if (env == RTE_UNCORE_PM_ENV_AUTO_DETECT)
/* Currently only intel_uncore is supported.
* This will be extended with auto-detection support
* for multiple uncore implementations.
*/
env = RTE_UNCORE_PM_ENV_INTEL_UNCORE;
ret = 0;
if (env == RTE_UNCORE_PM_ENV_INTEL_UNCORE) {
rte_power_get_uncore_freq = power_get_intel_uncore_freq;
rte_power_set_uncore_freq = power_set_intel_uncore_freq;
rte_power_uncore_freq_min = power_intel_uncore_freq_min;
rte_power_uncore_freq_max = power_intel_uncore_freq_max;
rte_power_uncore_freqs = power_intel_uncore_freqs;
rte_power_uncore_get_num_freqs = power_intel_uncore_get_num_freqs;
rte_power_uncore_get_num_pkgs = power_intel_uncore_get_num_pkgs;
rte_power_uncore_get_num_dies = power_intel_uncore_get_num_dies;
} else {
RTE_LOG(ERR, POWER, "Invalid Power Management Environment(%d) set\n", env);
ret = -1;
goto out;
}
default_uncore_env = env;
out:
rte_spinlock_unlock(&global_env_cfg_lock);
return ret;
}
void
rte_power_unset_uncore_env(void)
{
rte_spinlock_lock(&global_env_cfg_lock);
default_uncore_env = RTE_UNCORE_PM_ENV_NOT_SET;
reset_power_uncore_function_ptrs();
rte_spinlock_unlock(&global_env_cfg_lock);
}
enum rte_uncore_power_mgmt_env
rte_power_get_uncore_env(void)
{
return default_uncore_env;
}
int
rte_power_uncore_init(unsigned int pkg, unsigned int die)
{
int ret = -1;
switch (default_uncore_env) {
case RTE_UNCORE_PM_ENV_INTEL_UNCORE:
return power_intel_uncore_init(pkg, die);
default:
RTE_LOG(INFO, POWER, "Uncore Env isn't set yet!\n");
break;
}
/* Auto detect Environment */
RTE_LOG(INFO, POWER, "Attempting to initialise Intel Uncore power mgmt...\n");
ret = power_intel_uncore_init(pkg, die);
if (ret == 0) {
rte_power_set_uncore_env(RTE_UNCORE_PM_ENV_INTEL_UNCORE);
goto out;
}
if (default_uncore_env == RTE_UNCORE_PM_ENV_NOT_SET) {
RTE_LOG(ERR, POWER, "Unable to set Power Management Environment "
"for package %u Die %u\n", pkg, die);
ret = 0;
}
out:
return ret;
}
int
rte_power_uncore_exit(unsigned int pkg, unsigned int die)
{
switch (default_uncore_env) {
case RTE_UNCORE_PM_ENV_INTEL_UNCORE:
return power_intel_uncore_exit(pkg, die);
default:
RTE_LOG(ERR, POWER, "Uncore Env has not been set, unable to exit gracefully\n");
break;
}
return -1;
}