diff options
Diffstat (limited to 'drivers/platform/x86/intel/speed_select_if')
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; |