1fcf670e50
SST BF and TF can be enabled/disabled per level. So check the current level support from the mask of supported levels. This change from a single level to mask for info.sst_tf_support and info.sst_tf_support is indicated by API version change. Use as mask for API version above 2. In this way there is no change in behavior when running on older kernel with API version 2. Since the tool can support now API version 3, update the supported API version. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
821 lines
19 KiB
C
821 lines
19 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Intel Speed Select -- Enumerate and control features for TPMI Interface
|
|
* Copyright (c) 2022 Intel Corporation.
|
|
*/
|
|
|
|
#include <linux/isst_if.h>
|
|
#include "isst.h"
|
|
|
|
int tpmi_process_ioctl(int ioctl_no, void *info)
|
|
{
|
|
const char *pathname = "/dev/isst_interface";
|
|
int fd;
|
|
|
|
if (is_debug_enabled()) {
|
|
debug_printf("Issue IOCTL: ");
|
|
switch (ioctl_no) {
|
|
case ISST_IF_CORE_POWER_STATE:
|
|
debug_printf("ISST_IF_CORE_POWER_STATE\n");
|
|
break;
|
|
case ISST_IF_CLOS_PARAM:
|
|
debug_printf("ISST_IF_CLOS_PARAM\n");
|
|
break;
|
|
case ISST_IF_CLOS_ASSOC:
|
|
debug_printf("ISST_IF_CLOS_ASSOC\n");
|
|
break;
|
|
case ISST_IF_PERF_LEVELS:
|
|
debug_printf("ISST_IF_PERF_LEVELS\n");
|
|
break;
|
|
case ISST_IF_PERF_SET_LEVEL:
|
|
debug_printf("ISST_IF_PERF_SET_LEVEL\n");
|
|
break;
|
|
case ISST_IF_PERF_SET_FEATURE:
|
|
debug_printf("ISST_IF_PERF_SET_FEATURE\n");
|
|
break;
|
|
case ISST_IF_GET_PERF_LEVEL_INFO:
|
|
debug_printf("ISST_IF_GET_PERF_LEVEL_INFO\n");
|
|
break;
|
|
case ISST_IF_GET_PERF_LEVEL_CPU_MASK:
|
|
debug_printf("ISST_IF_GET_PERF_LEVEL_CPU_MASK\n");
|
|
break;
|
|
case ISST_IF_GET_BASE_FREQ_INFO:
|
|
debug_printf("ISST_IF_GET_BASE_FREQ_INFO\n");
|
|
break;
|
|
case ISST_IF_GET_BASE_FREQ_CPU_MASK:
|
|
debug_printf("ISST_IF_GET_BASE_FREQ_CPU_MASK\n");
|
|
break;
|
|
case ISST_IF_GET_TURBO_FREQ_INFO:
|
|
debug_printf("ISST_IF_GET_TURBO_FREQ_INFO\n");
|
|
break;
|
|
case ISST_IF_COUNT_TPMI_INSTANCES:
|
|
debug_printf("ISST_IF_COUNT_TPMI_INSTANCES\n");
|
|
break;
|
|
default:
|
|
debug_printf("%d\n", ioctl_no);
|
|
break;
|
|
}
|
|
}
|
|
|
|
fd = open(pathname, O_RDWR);
|
|
if (fd < 0)
|
|
return -1;
|
|
|
|
if (ioctl(fd, ioctl_no, info) == -1) {
|
|
debug_printf("IOCTL %d Failed\n", ioctl_no);
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
|
|
close(fd);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tpmi_get_disp_freq_multiplier(void)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static int tpmi_get_trl_max_levels(void)
|
|
{
|
|
return TRL_MAX_LEVELS;
|
|
}
|
|
|
|
static char *tpmi_get_trl_level_name(int level)
|
|
{
|
|
switch (level) {
|
|
case 0:
|
|
return "level-0";
|
|
case 1:
|
|
return "level-1";
|
|
case 2:
|
|
return "level-2";
|
|
case 3:
|
|
return "level-3";
|
|
case 4:
|
|
return "level-4";
|
|
case 5:
|
|
return "level-5";
|
|
case 6:
|
|
return "level-6";
|
|
case 7:
|
|
return "level-7";
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
static void tpmi_update_platform_param(enum isst_platform_param param, int value)
|
|
{
|
|
/* No params need to be updated for now */
|
|
}
|
|
|
|
static int tpmi_is_punit_valid(struct isst_id *id)
|
|
{
|
|
struct isst_tpmi_instance_count info;
|
|
int ret;
|
|
|
|
if (id->punit < 0)
|
|
return 0;
|
|
|
|
info.socket_id = id->pkg;
|
|
ret = tpmi_process_ioctl(ISST_IF_COUNT_TPMI_INSTANCES, &info);
|
|
if (ret == -1)
|
|
return 0;
|
|
|
|
if (info.valid_mask & BIT(id->punit))
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tpmi_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
|
|
{
|
|
struct isst_core_power info;
|
|
int ret;
|
|
|
|
info.get_set = 0;
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
|
|
if (ret == -1)
|
|
return ret;
|
|
|
|
*cp_state = info.enable;
|
|
*cp_cap = info.supported;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int tpmi_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
|
|
{
|
|
struct isst_perf_level_info info;
|
|
int ret;
|
|
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
|
|
ret = tpmi_process_ioctl(ISST_IF_PERF_LEVELS, &info);
|
|
if (ret == -1)
|
|
return ret;
|
|
|
|
pkg_dev->version = info.feature_rev;
|
|
pkg_dev->levels = info.max_level;
|
|
pkg_dev->locked = info.locked;
|
|
pkg_dev->current_level = info.current_level;
|
|
pkg_dev->locked = info.locked;
|
|
pkg_dev->enabled = info.enabled;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tpmi_get_ctdp_control(struct isst_id *id, int config_index,
|
|
struct isst_pkg_ctdp_level_info *ctdp_level)
|
|
{
|
|
struct isst_core_power core_power_info;
|
|
struct isst_perf_level_info info;
|
|
int level_mask;
|
|
int ret;
|
|
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
|
|
ret = tpmi_process_ioctl(ISST_IF_PERF_LEVELS, &info);
|
|
if (ret == -1)
|
|
return -1;
|
|
|
|
if (config_index != 0xff)
|
|
level_mask = 1 << config_index;
|
|
else
|
|
level_mask = config_index;
|
|
|
|
if (!(info.level_mask & level_mask))
|
|
return -1;
|
|
|
|
if (api_version() > 2) {
|
|
ctdp_level->fact_support = info.sst_tf_support & BIT(config_index);
|
|
ctdp_level->pbf_support = info.sst_bf_support & BIT(config_index);
|
|
} else {
|
|
ctdp_level->fact_support = info.sst_tf_support;
|
|
ctdp_level->pbf_support = info.sst_bf_support;
|
|
}
|
|
|
|
ctdp_level->fact_enabled = !!(info.feature_state & BIT(1));
|
|
ctdp_level->pbf_enabled = !!(info.feature_state & BIT(0));
|
|
|
|
core_power_info.get_set = 0;
|
|
core_power_info.socket_id = id->pkg;
|
|
core_power_info.power_domain_id = id->punit;
|
|
|
|
ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &core_power_info);
|
|
if (ret == -1)
|
|
return ret;
|
|
|
|
ctdp_level->sst_cp_support = core_power_info.supported;
|
|
ctdp_level->sst_cp_enabled = core_power_info.enable;
|
|
|
|
debug_printf
|
|
("cpu:%d CONFIG_TDP_GET_TDP_CONTROL fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
|
|
id->cpu, ctdp_level->fact_support, ctdp_level->pbf_support,
|
|
ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tpmi_get_tdp_info(struct isst_id *id, int config_index,
|
|
struct isst_pkg_ctdp_level_info *ctdp_level)
|
|
{
|
|
struct isst_perf_level_data_info info;
|
|
int ret;
|
|
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
info.level = config_index;
|
|
|
|
ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
|
|
if (ret == -1)
|
|
return ret;
|
|
|
|
ctdp_level->pkg_tdp = info.thermal_design_power_w;
|
|
ctdp_level->tdp_ratio = info.tdp_ratio;
|
|
ctdp_level->sse_p1 = info.base_freq_mhz;
|
|
ctdp_level->avx2_p1 = info.base_freq_avx2_mhz;
|
|
ctdp_level->avx512_p1 = info.base_freq_avx512_mhz;
|
|
ctdp_level->amx_p1 = info.base_freq_amx_mhz;
|
|
|
|
ctdp_level->t_proc_hot = info.tjunction_max_c;
|
|
ctdp_level->mem_freq = info.max_memory_freq_mhz;
|
|
ctdp_level->cooling_type = info.cooling_type;
|
|
|
|
ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz;
|
|
ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz;
|
|
ctdp_level->uncore_pm = info.pm_fabric_freq_mhz;
|
|
|
|
debug_printf
|
|
("cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO tdp_ratio:%d pkg_tdp:%d ctdp_level->t_proc_hot:%d\n",
|
|
id->cpu, config_index, ctdp_level->tdp_ratio, ctdp_level->pkg_tdp,
|
|
ctdp_level->t_proc_hot);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tpmi_get_pwr_info(struct isst_id *id, int config_index,
|
|
struct isst_pkg_ctdp_level_info *ctdp_level)
|
|
{
|
|
/* TBD */
|
|
ctdp_level->pkg_max_power = 0;
|
|
ctdp_level->pkg_min_power = 0;
|
|
|
|
debug_printf
|
|
("cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO pkg_max_power:%d pkg_min_power:%d\n",
|
|
id->cpu, config_index, ctdp_level->pkg_max_power,
|
|
ctdp_level->pkg_min_power);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int tpmi_get_coremask_info(struct isst_id *id, int config_index,
|
|
struct isst_pkg_ctdp_level_info *ctdp_level)
|
|
{
|
|
struct isst_perf_level_cpu_mask info;
|
|
int ret, cpu_count;
|
|
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
info.level = config_index;
|
|
info.punit_cpu_map = 1;
|
|
|
|
ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_CPU_MASK, &info);
|
|
if (ret == -1)
|
|
return ret;
|
|
|
|
set_cpu_mask_from_punit_coremask(id, info.mask,
|
|
ctdp_level->core_cpumask_size,
|
|
ctdp_level->core_cpumask, &cpu_count);
|
|
ctdp_level->cpu_count = cpu_count;
|
|
|
|
debug_printf("cpu:%d ctdp:%d core_mask ino cpu count:%d\n",
|
|
id->cpu, config_index, ctdp_level->cpu_count);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tpmi_get_get_trls(struct isst_id *id, int config_index,
|
|
struct isst_pkg_ctdp_level_info *ctdp_level)
|
|
{
|
|
struct isst_perf_level_data_info info;
|
|
int ret, i, j;
|
|
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
info.level = config_index;
|
|
|
|
ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
|
|
if (ret == -1)
|
|
return ret;
|
|
|
|
if (info.max_buckets > TRL_MAX_BUCKETS)
|
|
info.max_buckets = TRL_MAX_BUCKETS;
|
|
|
|
if (info.max_trl_levels > TRL_MAX_LEVELS)
|
|
info.max_trl_levels = TRL_MAX_LEVELS;
|
|
|
|
for (i = 0; i < info.max_trl_levels; ++i)
|
|
for (j = 0; j < info.max_buckets; ++j)
|
|
ctdp_level->trl_ratios[i][j] = info.trl_freq_mhz[i][j];
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tpmi_get_get_trl(struct isst_id *id, int level, int config_index,
|
|
int *trl)
|
|
{
|
|
struct isst_pkg_ctdp_level_info ctdp_level;
|
|
int ret, i;
|
|
|
|
ret = tpmi_get_get_trls(id, config_index, &ctdp_level);
|
|
if (ret)
|
|
return ret;
|
|
|
|
/* FIX ME: Just return for level 0 */
|
|
for (i = 0; i < 8; ++i)
|
|
trl[i] = ctdp_level.trl_ratios[0][i];
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tpmi_get_trl_bucket_info(struct isst_id *id, int config_index,
|
|
unsigned long long *buckets_info)
|
|
{
|
|
struct isst_perf_level_data_info info;
|
|
unsigned char *mask = (unsigned char *)buckets_info;
|
|
int ret, i;
|
|
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
info.level = config_index;
|
|
|
|
ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
|
|
if (ret == -1)
|
|
return ret;
|
|
|
|
if (info.max_buckets > TRL_MAX_BUCKETS)
|
|
info.max_buckets = TRL_MAX_BUCKETS;
|
|
|
|
for (i = 0; i < info.max_buckets; ++i)
|
|
mask[i] = info.bucket_core_counts[i];
|
|
|
|
debug_printf("cpu:%d TRL bucket info: 0x%llx\n", id->cpu,
|
|
*buckets_info);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tpmi_set_tdp_level(struct isst_id *id, int tdp_level)
|
|
{
|
|
struct isst_perf_level_control info;
|
|
int ret;
|
|
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
info.level = tdp_level;
|
|
|
|
ret = tpmi_process_ioctl(ISST_IF_PERF_SET_LEVEL, &info);
|
|
if (ret == -1)
|
|
return ret;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int _pbf_get_coremask_info(struct isst_id *id, int config_index,
|
|
struct isst_pbf_info *pbf_info)
|
|
{
|
|
struct isst_perf_level_cpu_mask info;
|
|
int ret, cpu_count;
|
|
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
info.level = config_index;
|
|
info.punit_cpu_map = 1;
|
|
|
|
ret = tpmi_process_ioctl(ISST_IF_GET_BASE_FREQ_CPU_MASK, &info);
|
|
if (ret == -1)
|
|
return ret;
|
|
|
|
set_cpu_mask_from_punit_coremask(id, info.mask,
|
|
pbf_info->core_cpumask_size,
|
|
pbf_info->core_cpumask, &cpu_count);
|
|
|
|
debug_printf("cpu:%d ctdp:%d pbf core_mask info cpu count:%d\n",
|
|
id->cpu, config_index, cpu_count);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tpmi_get_pbf_info(struct isst_id *id, int level,
|
|
struct isst_pbf_info *pbf_info)
|
|
{
|
|
struct isst_base_freq_info info;
|
|
int ret;
|
|
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
info.level = level;
|
|
|
|
ret = tpmi_process_ioctl(ISST_IF_GET_BASE_FREQ_INFO, &info);
|
|
if (ret == -1)
|
|
return ret;
|
|
|
|
pbf_info->p1_low = info.low_base_freq_mhz;
|
|
pbf_info->p1_high = info.high_base_freq_mhz;
|
|
pbf_info->tdp = info.thermal_design_power_w;
|
|
pbf_info->t_prochot = info.tjunction_max_c;
|
|
|
|
debug_printf("cpu:%d ctdp:%d pbf info:%d:%d:%d:%d\n",
|
|
id->cpu, level, pbf_info->p1_low, pbf_info->p1_high,
|
|
pbf_info->tdp, pbf_info->t_prochot);
|
|
|
|
return _pbf_get_coremask_info(id, level, pbf_info);
|
|
}
|
|
|
|
static int tpmi_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
|
|
{
|
|
struct isst_pkg_ctdp pkg_dev;
|
|
struct isst_pkg_ctdp_level_info ctdp_level;
|
|
int current_level;
|
|
struct isst_perf_feature_control info;
|
|
int ret;
|
|
|
|
ret = isst_get_ctdp_levels(id, &pkg_dev);
|
|
if (ret)
|
|
debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);
|
|
|
|
current_level = pkg_dev.current_level;
|
|
|
|
ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
|
|
if (ret)
|
|
return ret;
|
|
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
|
|
info.feature = 0;
|
|
|
|
if (pbf) {
|
|
if (ctdp_level.fact_enabled)
|
|
info.feature |= BIT(1);
|
|
|
|
if (enable)
|
|
info.feature |= BIT(0);
|
|
else
|
|
info.feature &= ~BIT(0);
|
|
} else {
|
|
|
|
if (enable && !ctdp_level.sst_cp_enabled)
|
|
isst_display_error_info_message(0,
|
|
"Make sure to execute before: core-power enable",
|
|
0, 0);
|
|
|
|
if (ctdp_level.pbf_enabled)
|
|
info.feature |= BIT(0);
|
|
|
|
if (enable)
|
|
info.feature |= BIT(1);
|
|
else
|
|
info.feature &= ~BIT(1);
|
|
}
|
|
|
|
ret = tpmi_process_ioctl(ISST_IF_PERF_SET_FEATURE, &info);
|
|
if (ret == -1)
|
|
return ret;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tpmi_get_fact_info(struct isst_id *id, int level, int fact_bucket,
|
|
struct isst_fact_info *fact_info)
|
|
{
|
|
struct isst_turbo_freq_info info;
|
|
int i, j;
|
|
int ret;
|
|
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
info.level = level;
|
|
|
|
ret = tpmi_process_ioctl(ISST_IF_GET_TURBO_FREQ_INFO, &info);
|
|
if (ret == -1)
|
|
return ret;
|
|
|
|
for (i = 0; i < info.max_clip_freqs; ++i)
|
|
fact_info->lp_ratios[i] = info.lp_clip_freq_mhz[i];
|
|
|
|
if (info.max_buckets > TRL_MAX_BUCKETS)
|
|
info.max_buckets = TRL_MAX_BUCKETS;
|
|
|
|
if (info.max_trl_levels > TRL_MAX_LEVELS)
|
|
info.max_trl_levels = TRL_MAX_LEVELS;
|
|
|
|
for (i = 0; i < info.max_trl_levels; ++i) {
|
|
for (j = 0; j < info.max_buckets; ++j)
|
|
fact_info->bucket_info[j].hp_ratios[i] =
|
|
info.trl_freq_mhz[i][j];
|
|
}
|
|
|
|
for (i = 0; i < info.max_buckets; ++i)
|
|
fact_info->bucket_info[i].hp_cores = info.bucket_core_counts[i];
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void _set_uncore_min_max(struct isst_id *id, int max, int freq)
|
|
{
|
|
DIR *dir;
|
|
FILE *filep;
|
|
struct dirent *entry;
|
|
char buffer[512];
|
|
unsigned int tmp_id;
|
|
int ret;
|
|
|
|
dir = opendir("/sys/devices/system/cpu/intel_uncore_frequency/");
|
|
if (!dir)
|
|
return;
|
|
|
|
while ((entry = readdir(dir)) != NULL ) {
|
|
/* Check domain_id */
|
|
snprintf(buffer, sizeof(buffer),
|
|
"/sys/devices/system/cpu/intel_uncore_frequency/%s/domain_id", entry->d_name);
|
|
|
|
filep = fopen(buffer, "r");
|
|
if (!filep)
|
|
goto end;
|
|
|
|
ret = fscanf(filep, "%u", &tmp_id);
|
|
fclose(filep);
|
|
if (ret != 1)
|
|
goto end;
|
|
|
|
if (tmp_id != id->punit)
|
|
continue;
|
|
|
|
/* Check package_id */
|
|
snprintf(buffer, sizeof(buffer),
|
|
"/sys/devices/system/cpu/intel_uncore_frequency/%s/package_id", entry->d_name);
|
|
|
|
filep = fopen(buffer, "r");
|
|
if (!filep)
|
|
goto end;
|
|
|
|
ret = fscanf(filep, "%u", &tmp_id);
|
|
fclose(filep);
|
|
|
|
if (ret != 1)
|
|
goto end;
|
|
|
|
if (tmp_id != id->pkg)
|
|
continue;
|
|
|
|
/* Found the right sysfs path, adjust and quit */
|
|
if (max)
|
|
snprintf(buffer, sizeof(buffer),
|
|
"/sys/devices/system/cpu/intel_uncore_frequency/%s/max_freq_khz", entry->d_name);
|
|
else
|
|
snprintf(buffer, sizeof(buffer),
|
|
"/sys/devices/system/cpu/intel_uncore_frequency/%s/min_freq_khz", entry->d_name);
|
|
|
|
filep = fopen(buffer, "w");
|
|
if (!filep)
|
|
goto end;
|
|
|
|
fprintf(filep, "%d\n", freq);
|
|
fclose(filep);
|
|
break;
|
|
}
|
|
|
|
end:
|
|
closedir(dir);
|
|
}
|
|
|
|
static void tpmi_adjust_uncore_freq(struct isst_id *id, int config_index,
|
|
struct isst_pkg_ctdp_level_info *ctdp_level)
|
|
{
|
|
struct isst_perf_level_data_info info;
|
|
int ret;
|
|
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
info.level = config_index;
|
|
|
|
ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
|
|
if (ret == -1)
|
|
return;
|
|
|
|
ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz;
|
|
ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz;
|
|
ctdp_level->uncore_pm = info.pm_fabric_freq_mhz;
|
|
|
|
if (ctdp_level->uncore_pm)
|
|
_set_uncore_min_max(id, 0, ctdp_level->uncore_pm * 100000);
|
|
|
|
if (ctdp_level->uncore_p0)
|
|
_set_uncore_min_max(id, 1, ctdp_level->uncore_p0 * 100000);
|
|
|
|
return;
|
|
}
|
|
|
|
static int tpmi_get_clos_information(struct isst_id *id, int *enable, int *type)
|
|
{
|
|
struct isst_core_power info;
|
|
int ret;
|
|
|
|
info.get_set = 0;
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
|
|
if (ret == -1)
|
|
return ret;
|
|
|
|
*enable = info.enable;
|
|
*type = info.priority_type;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tpmi_pm_qos_config(struct isst_id *id, int enable_clos,
|
|
int priority_type)
|
|
{
|
|
struct isst_core_power info;
|
|
int i, ret, saved_punit;
|
|
|
|
info.get_set = 1;
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
info.enable = enable_clos;
|
|
info.priority_type = priority_type;
|
|
|
|
saved_punit = id->punit;
|
|
|
|
/* Set for all other dies also. This is per package setting */
|
|
for (i = 0; i < MAX_PUNIT_PER_DIE; i++) {
|
|
id->punit = i;
|
|
if (isst_is_punit_valid(id)) {
|
|
info.power_domain_id = i;
|
|
ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
|
|
if (ret == -1) {
|
|
id->punit = saved_punit;
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
id->punit = saved_punit;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int tpmi_pm_get_clos(struct isst_id *id, int clos,
|
|
struct isst_clos_config *clos_config)
|
|
{
|
|
struct isst_clos_param info;
|
|
int ret;
|
|
|
|
info.get_set = 0;
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
info.clos = clos;
|
|
|
|
ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info);
|
|
if (ret == -1)
|
|
return ret;
|
|
|
|
clos_config->epp = 0;
|
|
clos_config->clos_prop_prio = info.prop_prio;
|
|
clos_config->clos_min = info.min_freq_mhz;
|
|
clos_config->clos_max = info.max_freq_mhz;
|
|
clos_config->clos_desired = 0;
|
|
|
|
debug_printf("cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos,
|
|
clos_config->clos_min, clos_config->clos_max);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int tpmi_set_clos(struct isst_id *id, int clos,
|
|
struct isst_clos_config *clos_config)
|
|
{
|
|
struct isst_clos_param info;
|
|
int i, ret, saved_punit;
|
|
|
|
info.get_set = 1;
|
|
info.socket_id = id->pkg;
|
|
info.power_domain_id = id->punit;
|
|
info.clos = clos;
|
|
info.prop_prio = clos_config->clos_prop_prio;
|
|
|
|
info.min_freq_mhz = clos_config->clos_min;
|
|
info.max_freq_mhz = clos_config->clos_max;
|
|
|
|
if (info.min_freq_mhz <= 0xff)
|
|
info.min_freq_mhz *= 100;
|
|
if (info.max_freq_mhz <= 0xff)
|
|
info.max_freq_mhz *= 100;
|
|
|
|
saved_punit = id->punit;
|
|
|
|
/* Set for all other dies also. This is per package setting */
|
|
for (i = 0; i < MAX_PUNIT_PER_DIE; i++) {
|
|
id->punit = i;
|
|
if (isst_is_punit_valid(id)) {
|
|
info.power_domain_id = i;
|
|
ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info);
|
|
if (ret == -1) {
|
|
id->punit = saved_punit;
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
id->punit = saved_punit;
|
|
|
|
debug_printf("set cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos,
|
|
clos_config->clos_min, clos_config->clos_max);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tpmi_clos_get_assoc_status(struct isst_id *id, int *clos_id)
|
|
{
|
|
struct isst_if_clos_assoc_cmds assoc_cmds;
|
|
int ret;
|
|
|
|
assoc_cmds.cmd_count = 1;
|
|
assoc_cmds.get_set = 0;
|
|
assoc_cmds.punit_cpu_map = 1;
|
|
assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu);
|
|
assoc_cmds.assoc_info[0].socket_id = id->pkg;
|
|
assoc_cmds.assoc_info[0].power_domain_id = id->punit;
|
|
|
|
ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds);
|
|
if (ret == -1)
|
|
return ret;
|
|
|
|
*clos_id = assoc_cmds.assoc_info[0].clos;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tpmi_clos_associate(struct isst_id *id, int clos_id)
|
|
{
|
|
struct isst_if_clos_assoc_cmds assoc_cmds;
|
|
int ret;
|
|
|
|
assoc_cmds.cmd_count = 1;
|
|
assoc_cmds.get_set = 1;
|
|
assoc_cmds.punit_cpu_map = 1;
|
|
assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu);
|
|
assoc_cmds.assoc_info[0].clos = clos_id;
|
|
assoc_cmds.assoc_info[0].socket_id = id->pkg;
|
|
assoc_cmds.assoc_info[0].power_domain_id = id->punit;
|
|
|
|
ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds);
|
|
if (ret == -1)
|
|
return ret;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct isst_platform_ops tpmi_ops = {
|
|
.get_disp_freq_multiplier = tpmi_get_disp_freq_multiplier,
|
|
.get_trl_max_levels = tpmi_get_trl_max_levels,
|
|
.get_trl_level_name = tpmi_get_trl_level_name,
|
|
.update_platform_param = tpmi_update_platform_param,
|
|
.is_punit_valid = tpmi_is_punit_valid,
|
|
.read_pm_config = tpmi_read_pm_config,
|
|
.get_config_levels = tpmi_get_config_levels,
|
|
.get_ctdp_control = tpmi_get_ctdp_control,
|
|
.get_tdp_info = tpmi_get_tdp_info,
|
|
.get_pwr_info = tpmi_get_pwr_info,
|
|
.get_coremask_info = tpmi_get_coremask_info,
|
|
.get_get_trl = tpmi_get_get_trl,
|
|
.get_get_trls = tpmi_get_get_trls,
|
|
.get_trl_bucket_info = tpmi_get_trl_bucket_info,
|
|
.set_tdp_level = tpmi_set_tdp_level,
|
|
.get_pbf_info = tpmi_get_pbf_info,
|
|
.set_pbf_fact_status = tpmi_set_pbf_fact_status,
|
|
.get_fact_info = tpmi_get_fact_info,
|
|
.adjust_uncore_freq = tpmi_adjust_uncore_freq,
|
|
.get_clos_information = tpmi_get_clos_information,
|
|
.pm_qos_config = tpmi_pm_qos_config,
|
|
.pm_get_clos = tpmi_pm_get_clos,
|
|
.set_clos = tpmi_set_clos,
|
|
.clos_get_assoc_status = tpmi_clos_get_assoc_status,
|
|
.clos_associate = tpmi_clos_associate,
|
|
};
|
|
|
|
struct isst_platform_ops *tpmi_get_platform_ops(void)
|
|
{
|
|
return &tpmi_ops;
|
|
}
|