summaryrefslogtreecommitdiffstats
path: root/tools/power/x86/intel-speed-select/isst-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/power/x86/intel-speed-select/isst-core.c')
-rw-r--r--tools/power/x86/intel-speed-select/isst-core.c280
1 files changed, 257 insertions, 23 deletions
diff --git a/tools/power/x86/intel-speed-select/isst-core.c b/tools/power/x86/intel-speed-select/isst-core.c
index 8de4ac39a008..81a119f688a3 100644
--- a/tools/power/x86/intel-speed-select/isst-core.c
+++ b/tools/power/x86/intel-speed-select/isst-core.c
@@ -6,6 +6,44 @@
#include "isst.h"
+int isst_write_pm_config(int cpu, int cp_state)
+{
+ unsigned int req, resp;
+ int ret;
+
+ if (cp_state)
+ req = BIT(16);
+ else
+ req = 0;
+
+ ret = isst_send_mbox_command(cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", cpu, resp);
+
+ return 0;
+}
+
+int isst_read_pm_config(int cpu, int *cp_state, int *cp_cap)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = isst_send_mbox_command(cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d READ_PM_CONFIG resp:%x\n", cpu, resp);
+
+ *cp_state = resp & BIT(16);
+ *cp_cap = resp & BIT(0) ? 1 : 0;
+
+ return 0;
+}
+
int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev)
{
unsigned int resp;
@@ -13,8 +51,14 @@ int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev)
ret = isst_send_mbox_command(cpu, CONFIG_TDP,
CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
- if (ret)
- return ret;
+ if (ret) {
+ pkg_dev->levels = 0;
+ pkg_dev->locked = 1;
+ pkg_dev->current_level = 0;
+ pkg_dev->version = 0;
+ pkg_dev->enabled = 0;
+ return 0;
+ }
debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", cpu, resp);
@@ -30,6 +74,7 @@ int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev)
int isst_get_ctdp_control(int cpu, int config_index,
struct isst_pkg_ctdp_level_info *ctdp_level)
{
+ int cp_state, cp_cap;
unsigned int resp;
int ret;
@@ -44,6 +89,15 @@ int isst_get_ctdp_control(int cpu, int config_index,
ctdp_level->fact_enabled = !!(resp & BIT(16));
ctdp_level->pbf_enabled = !!(resp & BIT(17));
+ ret = isst_read_pm_config(cpu, &cp_state, &cp_cap);
+ if (ret) {
+ debug_printf("cpu:%d pm_config is not supported \n", cpu);
+ } else {
+ debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d \n", cpu, cp_state, cp_cap);
+ ctdp_level->sst_cp_support = cp_cap;
+ ctdp_level->sst_cp_enabled = cp_state;
+ }
+
debug_printf(
"cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
@@ -95,6 +149,69 @@ int isst_get_pwr_info(int cpu, int config_index,
return 0;
}
+void isst_get_uncore_p0_p1_info(int cpu, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
+ config_index, &resp);
+ if (ret) {
+ ctdp_level->uncore_p0 = 0;
+ ctdp_level->uncore_p1 = 0;
+ return;
+ }
+
+ ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
+ ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",
+ cpu, config_index, resp, ctdp_level->uncore_p0,
+ ctdp_level->uncore_p1);
+}
+
+void isst_get_p1_info(int cpu, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
+ config_index, &resp);
+ if (ret) {
+ ctdp_level->sse_p1 = 0;
+ ctdp_level->avx2_p1 = 0;
+ ctdp_level->avx512_p1 = 0;
+ return;
+ }
+
+ ctdp_level->sse_p1 = resp & GENMASK(7, 0);
+ ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;
+ ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d\n",
+ cpu, config_index, resp, ctdp_level->sse_p1,
+ ctdp_level->avx2_p1, ctdp_level->avx512_p1);
+}
+
+void isst_get_uncore_mem_freq(int cpu, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
+ 0, config_index, &resp);
+ if (ret) {
+ ctdp_level->mem_freq = 0;
+ return;
+ }
+
+ ctdp_level->mem_freq = resp & GENMASK(7, 0);
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",
+ cpu, config_index, resp, ctdp_level->mem_freq);
+}
+
int isst_get_tjmax_info(int cpu, int config_index,
struct isst_pkg_ctdp_level_info *ctdp_level)
{
@@ -149,6 +266,27 @@ int isst_get_coremask_info(int cpu, int config_index,
return 0;
}
+int isst_get_get_trl_from_msr(int cpu, int *trl)
+{
+ unsigned long long msr_trl;
+ int ret;
+
+ ret = isst_send_msr_command(cpu, 0x1AD, 0, &msr_trl);
+ if (ret)
+ return ret;
+
+ trl[0] = msr_trl & GENMASK(7, 0);
+ trl[1] = (msr_trl & GENMASK(15, 8)) >> 8;
+ trl[2] = (msr_trl & GENMASK(23, 16)) >> 16;
+ trl[3] = (msr_trl & GENMASK(31, 24)) >> 24;
+ trl[4] = (msr_trl & GENMASK(39, 32)) >> 32;
+ trl[5] = (msr_trl & GENMASK(47, 40)) >> 40;
+ trl[6] = (msr_trl & GENMASK(55, 48)) >> 48;
+ trl[7] = (msr_trl & GENMASK(63, 56)) >> 56;
+
+ return 0;
+}
+
int isst_get_get_trl(int cpu, int level, int avx_level, int *trl)
{
unsigned int req, resp;
@@ -188,8 +326,27 @@ int isst_get_get_trl(int cpu, int level, int avx_level, int *trl)
return 0;
}
+int isst_get_trl_bucket_info(int cpu, unsigned long long *buckets_info)
+{
+ int ret;
+
+ debug_printf("cpu:%d bucket info via MSR\n", cpu);
+
+ *buckets_info = 0;
+
+ ret = isst_send_msr_command(cpu, 0x1ae, 0, buckets_info);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", cpu,
+ *buckets_info);
+
+ return 0;
+}
+
int isst_set_tdp_level_msr(int cpu, int tdp_level)
{
+ unsigned long long level = tdp_level;
int ret;
debug_printf("cpu: tdp_level via MSR %d\n", cpu, tdp_level);
@@ -202,8 +359,7 @@ int isst_set_tdp_level_msr(int cpu, int tdp_level)
if (tdp_level > 2)
return -1; /* invalid value */
- ret = isst_send_msr_command(cpu, 0x64b, 1,
- (unsigned long long *)&tdp_level);
+ ret = isst_send_msr_command(cpu, 0x64b, 1, &level);
if (ret)
return ret;
@@ -227,12 +383,15 @@ int isst_set_tdp_level(int cpu, int tdp_level)
int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info)
{
+ int i, ret, core_cnt, max;
unsigned int req, resp;
- int i, ret;
pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
- for (i = 0; i < 2; ++i) {
+ core_cnt = get_core_count(get_physical_package_id(cpu), get_physical_die_id(cpu));
+ max = core_cnt > 32 ? 2 : 1;
+
+ for (i = 0; i < max; ++i) {
unsigned long long mask;
int count;
@@ -240,7 +399,7 @@ int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info)
CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
0, (i << 8) | level, &resp);
if (ret)
- return ret;
+ break;
debug_printf(
"cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
@@ -305,7 +464,7 @@ int isst_set_pbf_fact_status(int cpu, int pbf, int enable)
ret = isst_get_ctdp_levels(cpu, &pkg_dev);
if (ret)
- return ret;
+ debug_printf("cpu:%d No support for dynamic ISST\n", cpu);
current_level = pkg_dev.current_level;
@@ -535,7 +694,6 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
i);
ctdp_level = &pkg_dev->ctdp_level[i];
- ctdp_level->processed = 1;
ctdp_level->level = i;
ctdp_level->control_cpu = cpu;
ctdp_level->pkg_id = get_physical_package_id(cpu);
@@ -543,7 +701,37 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
ret = isst_get_ctdp_control(cpu, i, ctdp_level);
if (ret)
- return ret;
+ continue;
+
+ pkg_dev->processed = 1;
+ ctdp_level->processed = 1;
+
+ if (ctdp_level->pbf_support) {
+ ret = isst_get_pbf_info(cpu, i, &ctdp_level->pbf_info);
+ if (!ret)
+ ctdp_level->pbf_found = 1;
+ }
+
+ if (ctdp_level->fact_support) {
+ ret = isst_get_fact_info(cpu, i,
+ &ctdp_level->fact_info);
+ if (ret)
+ return ret;
+ }
+
+ if (!pkg_dev->enabled) {
+ int freq;
+
+ freq = get_cpufreq_base_freq(cpu);
+ if (freq > 0) {
+ ctdp_level->sse_p1 = freq / 100000;
+ ctdp_level->tdp_ratio = ctdp_level->sse_p1;
+ }
+
+ isst_get_get_trl_from_msr(cpu, ctdp_level->trl_sse_active_cores);
+ isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info);
+ continue;
+ }
ret = isst_get_tdp_info(cpu, i, ctdp_level);
if (ret)
@@ -563,6 +751,10 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
if (ret)
return ret;
+ ret = isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info);
+ if (ret)
+ return ret;
+
ret = isst_get_get_trl(cpu, i, 0,
ctdp_level->trl_sse_active_cores);
if (ret)
@@ -578,21 +770,35 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
if (ret)
return ret;
- if (ctdp_level->pbf_support) {
- ret = isst_get_pbf_info(cpu, i, &ctdp_level->pbf_info);
- if (!ret)
- ctdp_level->pbf_found = 1;
- }
-
- if (ctdp_level->fact_support) {
- ret = isst_get_fact_info(cpu, i,
- &ctdp_level->fact_info);
- if (ret)
- return ret;
- }
+ isst_get_uncore_p0_p1_info(cpu, i, ctdp_level);
+ isst_get_p1_info(cpu, i, ctdp_level);
+ isst_get_uncore_mem_freq(cpu, i, ctdp_level);
}
- pkg_dev->processed = 1;
+ return 0;
+}
+
+int isst_clos_get_clos_information(int cpu, int *enable, int *type)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp);
+
+ if (resp & BIT(1))
+ *enable = 1;
+ else
+ *enable = 0;
+
+ if (resp & BIT(2))
+ *type = 1;
+ else
+ *type = 0;
return 0;
}
@@ -602,6 +808,34 @@ int isst_pm_qos_config(int cpu, int enable_clos, int priority_type)
unsigned int req, resp;
int ret;
+ if (!enable_clos) {
+ struct isst_pkg_ctdp pkg_dev;
+ struct isst_pkg_ctdp_level_info ctdp_level;
+
+ ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ if (ret) {
+ debug_printf("isst_get_ctdp_levels\n");
+ return ret;
+ }
+
+ ret = isst_get_ctdp_control(cpu, pkg_dev.current_level,
+ &ctdp_level);
+ if (ret)
+ return ret;
+
+ if (ctdp_level.fact_enabled) {
+ debug_printf("Turbo-freq feature must be disabled first\n");
+ return -EINVAL;
+ }
+ ret = isst_write_pm_config(cpu, 0);
+ if (ret)
+ perror("isst_write_pm_config\n");
+ } else {
+ ret = isst_write_pm_config(cpu, 1);
+ if (ret)
+ perror("isst_write_pm_config\n");
+ }
+
ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
&resp);
if (ret)
OpenPOWER on IntegriCloud