summaryrefslogtreecommitdiff
path: root/drivers/platform/x86/intel/speed_select_if
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/intel/speed_select_if')
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_if_common.c38
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_if_mbox_msr.c15
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c106
3 files changed, 120 insertions, 39 deletions
diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
index 31239a93dd71..71e104a068e9 100644
--- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
+++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
@@ -21,6 +21,7 @@
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
+#include <asm/msr.h>
#include "isst_if_common.h"
@@ -191,32 +192,13 @@ void isst_resume_common(void)
if (cb->registered)
isst_mbox_resume_command(cb, sst_cmd);
} else {
- wrmsrl_safe_on_cpu(sst_cmd->cpu, sst_cmd->cmd,
+ wrmsrq_safe_on_cpu(sst_cmd->cpu, sst_cmd->cmd,
sst_cmd->data);
}
}
}
EXPORT_SYMBOL_GPL(isst_resume_common);
-static void isst_restore_msr_local(int cpu)
-{
- struct isst_cmd *sst_cmd;
- int i;
-
- mutex_lock(&isst_hash_lock);
- for (i = 0; i < ARRAY_SIZE(punit_msr_white_list); ++i) {
- if (!punit_msr_white_list[i])
- break;
-
- hash_for_each_possible(isst_hash, sst_cmd, hnode,
- punit_msr_white_list[i]) {
- if (!sst_cmd->mbox_cmd_type && sst_cmd->cpu == cpu)
- wrmsrl_safe(sst_cmd->cmd, sst_cmd->data);
- }
- }
- mutex_unlock(&isst_hash_lock);
-}
-
/**
* isst_if_mbox_cmd_invalid() - Check invalid mailbox commands
* @cmd: Pointer to the command structure to verify.
@@ -406,7 +388,7 @@ static int isst_if_cpu_online(unsigned int cpu)
isst_cpu_info[cpu].numa_node = cpu_to_node(cpu);
- ret = rdmsrl_safe(MSR_CPU_BUS_NUMBER, &data);
+ ret = rdmsrq_safe(MSR_CPU_BUS_NUMBER, &data);
if (ret) {
/* This is not a fatal error on MSR mailbox only I/F */
isst_cpu_info[cpu].bus_info[0] = -1;
@@ -420,12 +402,12 @@ static int isst_if_cpu_online(unsigned int cpu)
if (isst_hpm_support) {
- ret = rdmsrl_safe(MSR_PM_LOGICAL_ID, &data);
+ ret = rdmsrq_safe(MSR_PM_LOGICAL_ID, &data);
if (!ret)
goto set_punit_id;
}
- ret = rdmsrl_safe(MSR_THREAD_ID_INFO, &data);
+ ret = rdmsrq_safe(MSR_THREAD_ID_INFO, &data);
if (ret) {
isst_cpu_info[cpu].punit_cpu_id = -1;
return ret;
@@ -434,8 +416,6 @@ static int isst_if_cpu_online(unsigned int cpu)
set_punit_id:
isst_cpu_info[cpu].punit_cpu_id = data;
- isst_restore_msr_local(cpu);
-
return 0;
}
@@ -524,7 +504,7 @@ static long isst_if_msr_cmd_req(u8 *cmd_ptr, int *write_only, int resume)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- ret = wrmsrl_safe_on_cpu(msr_cmd->logical_cpu,
+ ret = wrmsrq_safe_on_cpu(msr_cmd->logical_cpu,
msr_cmd->msr,
msr_cmd->data);
*write_only = 1;
@@ -535,7 +515,7 @@ static long isst_if_msr_cmd_req(u8 *cmd_ptr, int *write_only, int resume)
} else {
u64 data;
- ret = rdmsrl_safe_on_cpu(msr_cmd->logical_cpu,
+ ret = rdmsrq_safe_on_cpu(msr_cmd->logical_cpu,
msr_cmd->msr, &data);
if (!ret) {
msr_cmd->data = data;
@@ -831,8 +811,8 @@ static int __init isst_if_common_init(void)
u64 data;
/* Can fail only on some Skylake-X generations */
- if (rdmsrl_safe(MSR_OS_MAILBOX_INTERFACE, &data) ||
- rdmsrl_safe(MSR_OS_MAILBOX_DATA, &data))
+ if (rdmsrq_safe(MSR_OS_MAILBOX_INTERFACE, &data) ||
+ rdmsrq_safe(MSR_OS_MAILBOX_DATA, &data))
return -ENODEV;
}
diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_mbox_msr.c b/drivers/platform/x86/intel/speed_select_if/isst_if_mbox_msr.c
index c4b7af00352b..22745b217c6f 100644
--- a/drivers/platform/x86/intel/speed_select_if/isst_if_mbox_msr.c
+++ b/drivers/platform/x86/intel/speed_select_if/isst_if_mbox_msr.c
@@ -18,6 +18,7 @@
#include <uapi/linux/isst_if.h>
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
+#include <asm/msr.h>
#include "isst_if_common.h"
@@ -39,7 +40,7 @@ static int isst_if_send_mbox_cmd(u8 command, u8 sub_command, u32 parameter,
/* Poll for rb bit == 0 */
retries = OS_MAILBOX_RETRY_COUNT;
do {
- rdmsrl(MSR_OS_MAILBOX_INTERFACE, data);
+ rdmsrq(MSR_OS_MAILBOX_INTERFACE, data);
if (data & BIT_ULL(MSR_OS_MAILBOX_BUSY_BIT)) {
ret = -EBUSY;
continue;
@@ -52,19 +53,19 @@ static int isst_if_send_mbox_cmd(u8 command, u8 sub_command, u32 parameter,
return ret;
/* Write DATA register */
- wrmsrl(MSR_OS_MAILBOX_DATA, command_data);
+ wrmsrq(MSR_OS_MAILBOX_DATA, command_data);
/* Write command register */
data = BIT_ULL(MSR_OS_MAILBOX_BUSY_BIT) |
(parameter & GENMASK_ULL(13, 0)) << 16 |
(sub_command << 8) |
command;
- wrmsrl(MSR_OS_MAILBOX_INTERFACE, data);
+ wrmsrq(MSR_OS_MAILBOX_INTERFACE, data);
/* Poll for rb bit == 0 */
retries = OS_MAILBOX_RETRY_COUNT;
do {
- rdmsrl(MSR_OS_MAILBOX_INTERFACE, data);
+ rdmsrq(MSR_OS_MAILBOX_INTERFACE, data);
if (data & BIT_ULL(MSR_OS_MAILBOX_BUSY_BIT)) {
ret = -EBUSY;
continue;
@@ -74,7 +75,7 @@ static int isst_if_send_mbox_cmd(u8 command, u8 sub_command, u32 parameter,
return -ENXIO;
if (response_data) {
- rdmsrl(MSR_OS_MAILBOX_DATA, data);
+ rdmsrq(MSR_OS_MAILBOX_DATA, data);
*response_data = data;
}
ret = 0;
@@ -176,11 +177,11 @@ static int __init isst_if_mbox_init(void)
return -ENODEV;
/* Check presence of mailbox MSRs */
- ret = rdmsrl_safe(MSR_OS_MAILBOX_INTERFACE, &data);
+ ret = rdmsrq_safe(MSR_OS_MAILBOX_INTERFACE, &data);
if (ret)
return ret;
- ret = rdmsrl_safe(MSR_OS_MAILBOX_DATA, &data);
+ ret = rdmsrq_safe(MSR_OS_MAILBOX_DATA, &data);
if (ret)
return ret;
diff --git a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c
index 9978cdd19851..18c035710eb9 100644
--- a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c
+++ b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c
@@ -27,6 +27,7 @@
#include <linux/kernel.h>
#include <linux/minmax.h>
#include <linux/module.h>
+#include <asm/msr.h>
#include <uapi/linux/isst_if.h>
#include "isst_tpmi_core.h"
@@ -34,7 +35,7 @@
/* Supported SST hardware version by this driver */
#define ISST_MAJOR_VERSION 0
-#define ISST_MINOR_VERSION 1
+#define ISST_MINOR_VERSION 2
/*
* Used to indicate if value read from MMIO needs to get multiplied
@@ -380,7 +381,7 @@ static int sst_main(struct auxiliary_device *auxdev, struct tpmi_per_power_domai
return -ENODEV;
}
- if (TPMI_MINOR_VERSION(pd_info->sst_header.interface_version) != ISST_MINOR_VERSION)
+ if (TPMI_MINOR_VERSION(pd_info->sst_header.interface_version) > ISST_MINOR_VERSION)
dev_info(dev, "SST: Ignore: Unsupported minor version:%lx\n",
TPMI_MINOR_VERSION(pd_info->sst_header.interface_version));
@@ -556,7 +557,7 @@ static bool disable_dynamic_sst_features(void)
{
u64 value;
- rdmsrl(MSR_PM_ENABLE, value);
+ rdmsrq(MSR_PM_ENABLE, value);
return !(value & 0x1);
}
@@ -1016,6 +1017,7 @@ static int isst_if_set_perf_feature(void __user *argp)
#define SST_PP_INFO_10_OFFSET 80
#define SST_PP_INFO_11_OFFSET 88
+#define SST_PP_INFO_12_OFFSET 96
#define SST_PP_P1_SSE_START 0
#define SST_PP_P1_SSE_WIDTH 8
@@ -1068,6 +1070,15 @@ static int isst_if_set_perf_feature(void __user *argp)
#define SST_PP_CORE_RATIO_PM_FABRIC_START 48
#define SST_PP_CORE_RATIO_PM_FABRIC_WIDTH 8
+#define SST_PP_CORE_RATIO_P0_FABRIC_1_START 0
+#define SST_PP_CORE_RATIO_P0_FABRIC_1_WIDTH 8
+
+#define SST_PP_CORE_RATIO_P1_FABRIC_1_START 8
+#define SST_PP_CORE_RATIO_P1_FABRIC_1_WIDTH 8
+
+#define SST_PP_CORE_RATIO_PM_FABRIC_1_START 16
+#define SST_PP_CORE_RATIO_PM_FABRIC_1_WIDTH 8
+
static int isst_if_get_perf_level_info(void __user *argp)
{
struct isst_perf_level_data_info perf_level;
@@ -1167,6 +1178,59 @@ static int isst_if_get_perf_level_info(void __user *argp)
return 0;
}
+static int isst_if_get_perf_level_fabric_info(void __user *argp)
+{
+ struct isst_perf_level_fabric_info perf_level_fabric;
+ struct tpmi_per_power_domain_info *power_domain_info;
+ int start = SST_PP_CORE_RATIO_P0_FABRIC_START;
+ int width = SST_PP_CORE_RATIO_P0_FABRIC_WIDTH;
+ int offset = SST_PP_INFO_11_OFFSET;
+ int i;
+
+ if (copy_from_user(&perf_level_fabric, argp, sizeof(perf_level_fabric)))
+ return -EFAULT;
+
+ power_domain_info = get_instance(perf_level_fabric.socket_id,
+ perf_level_fabric.power_domain_id);
+ if (!power_domain_info)
+ return -EINVAL;
+
+ if (perf_level_fabric.level > power_domain_info->max_level)
+ return -EINVAL;
+
+ if (power_domain_info->pp_header.feature_rev < 2)
+ return -EINVAL;
+
+ if (!(power_domain_info->pp_header.level_en_mask & BIT(perf_level_fabric.level)))
+ return -EINVAL;
+
+ /* For revision 2, maximum number of fabrics is 2 */
+ perf_level_fabric.max_fabrics = 2;
+
+ for (i = 0; i < perf_level_fabric.max_fabrics; i++) {
+ _read_pp_level_info("p0_fabric_freq_mhz", perf_level_fabric.p0_fabric_freq_mhz[i],
+ perf_level_fabric.level, offset, start, width,
+ SST_MUL_FACTOR_FREQ)
+ start += width;
+
+ _read_pp_level_info("p1_fabric_freq_mhz", perf_level_fabric.p1_fabric_freq_mhz[i],
+ perf_level_fabric.level, offset, start, width,
+ SST_MUL_FACTOR_FREQ)
+ start += width;
+
+ _read_pp_level_info("pm_fabric_freq_mhz", perf_level_fabric.pm_fabric_freq_mhz[i],
+ perf_level_fabric.level, offset, start, width,
+ SST_MUL_FACTOR_FREQ)
+ offset = SST_PP_INFO_12_OFFSET;
+ start = SST_PP_CORE_RATIO_P0_FABRIC_1_START;
+ }
+
+ if (copy_to_user(argp, &perf_level_fabric, sizeof(perf_level_fabric)))
+ return -EFAULT;
+
+ return 0;
+}
+
#define SST_PP_FUSED_CORE_COUNT_START 0
#define SST_PP_FUSED_CORE_COUNT_WIDTH 8
@@ -1328,9 +1392,14 @@ static int isst_if_get_tpmi_instance_count(void __user *argp)
#define SST_TF_INFO_0_OFFSET 0
#define SST_TF_INFO_1_OFFSET 8
#define SST_TF_INFO_2_OFFSET 16
+#define SST_TF_INFO_8_OFFSET 64
+#define SST_TF_INFO_8_BUCKETS 3
#define SST_TF_MAX_LP_CLIP_RATIOS TRL_MAX_LEVELS
+#define SST_TF_FEATURE_REV_START 4
+#define SST_TF_FEATURE_REV_WIDTH 8
+
#define SST_TF_LP_CLIP_RATIO_0_START 16
#define SST_TF_LP_CLIP_RATIO_0_WIDTH 8
@@ -1340,10 +1409,14 @@ static int isst_if_get_tpmi_instance_count(void __user *argp)
#define SST_TF_NUM_CORE_0_START 0
#define SST_TF_NUM_CORE_0_WIDTH 8
+#define SST_TF_NUM_MOD_0_START 0
+#define SST_TF_NUM_MOD_0_WIDTH 16
+
static int isst_if_get_turbo_freq_info(void __user *argp)
{
static struct isst_turbo_freq_info turbo_freq;
struct tpmi_per_power_domain_info *power_domain_info;
+ u8 feature_rev;
int i, j;
if (copy_from_user(&turbo_freq, argp, sizeof(turbo_freq)))
@@ -1360,6 +1433,10 @@ static int isst_if_get_turbo_freq_info(void __user *argp)
turbo_freq.max_trl_levels = TRL_MAX_LEVELS;
turbo_freq.max_clip_freqs = SST_TF_MAX_LP_CLIP_RATIOS;
+ _read_tf_level_info("feature_rev", feature_rev, turbo_freq.level,
+ SST_TF_INFO_0_OFFSET, SST_TF_FEATURE_REV_START,
+ SST_TF_FEATURE_REV_WIDTH, SST_MUL_FACTOR_NONE);
+
for (i = 0; i < turbo_freq.max_clip_freqs; ++i)
_read_tf_level_info("lp_clip*", turbo_freq.lp_clip_freq_mhz[i],
turbo_freq.level, SST_TF_INFO_0_OFFSET,
@@ -1376,12 +1453,32 @@ static int isst_if_get_turbo_freq_info(void __user *argp)
SST_MUL_FACTOR_FREQ)
}
+ if (feature_rev >= 2) {
+ bool has_tf_info_8 = false;
+
+ for (i = 0; i < SST_TF_INFO_8_BUCKETS; ++i) {
+ _read_tf_level_info("bucket_*_mod_count", turbo_freq.bucket_core_counts[i],
+ turbo_freq.level, SST_TF_INFO_8_OFFSET,
+ SST_TF_NUM_MOD_0_WIDTH * i, SST_TF_NUM_MOD_0_WIDTH,
+ SST_MUL_FACTOR_NONE)
+
+ if (turbo_freq.bucket_core_counts[i])
+ has_tf_info_8 = true;
+ }
+
+ if (has_tf_info_8)
+ goto done_core_count;
+ }
+
for (i = 0; i < TRL_MAX_BUCKETS; ++i)
_read_tf_level_info("bucket_*_core_count", turbo_freq.bucket_core_counts[i],
turbo_freq.level, SST_TF_INFO_1_OFFSET,
SST_TF_NUM_CORE_0_WIDTH * i, SST_TF_NUM_CORE_0_WIDTH,
SST_MUL_FACTOR_NONE)
+
+done_core_count:
+
if (copy_to_user(argp, &turbo_freq, sizeof(turbo_freq)))
return -EFAULT;
@@ -1420,6 +1517,9 @@ static long isst_if_def_ioctl(struct file *file, unsigned int cmd,
case ISST_IF_GET_PERF_LEVEL_INFO:
ret = isst_if_get_perf_level_info(argp);
break;
+ case ISST_IF_GET_PERF_LEVEL_FABRIC_INFO:
+ ret = isst_if_get_perf_level_fabric_info(argp);
+ break;
case ISST_IF_GET_PERF_LEVEL_CPU_MASK:
ret = isst_if_get_perf_level_mask(argp);
break;