From a2c5d6feeb3d5d33491bd4c0bdadef9bfa7692ca Mon Sep 17 00:00:00 2001 From: Xingui Yang Date: Tue, 5 Sep 2023 02:48:33 +0000 Subject: [PATCH 01/12] seq_file: add helper macro to define attribute for rw file commit 9cba82bba500e3ce875381350f289cfb3aa633ba upstream. Patch series "Add helper macro DEFINE_SHOW_STORE_ATTRIBUTE() at seq_file.c", v6. We already own DEFINE_SHOW_ATTRIBUTE() helper macro for defining attribute for read-only file, but we found many of drivers also want a helper macro for read-write file too. So we add this helper macro to reduce duplicated code. This patch (of 3): We already own DEFINE_SHOW_ATTRIBUTE() helper macro for defining attribute for read-only file, but many of drivers want a helper macro for read-write file too. So we add DEFINE_SHOW_STORE_ATTRIBUTE() helper to reduce duplicated code. Intel-SIG: commit 9cba82bba500 seq_file: add helper macro to define attribute for rw file Backport PLR (Power Limit Reasons) TPMI driver Link: https://lkml.kernel.org/r/20230905024835.43219-1-yangxingui@huawei.com Link: https://lkml.kernel.org/r/20230905024835.43219-2-yangxingui@huawei.com Signed-off-by: Luo Jiaxing Co-developed-by: Xingui Yang Signed-off-by: Xingui Yang Reviewed-by: Andy Shevchenko Cc: Al Viro Cc: Animesh Manna Cc: Anshuman Gupta Cc: Damien Le Moal Cc: Felipe Balbi Cc: Greg Kroah-Hartman Cc: Himanshu Madhani Cc: James Bottomley Cc: John Garry Cc: Martin K. Petersen Cc: Uma Shankar Cc: Xiang Chen Cc: Zeng Tao Signed-off-by: Andrew Morton [ Zhang Rui: amend commit log ] Signed-off-by: Zhang Rui --- include/linux/seq_file.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h index 386ab580b839b..234bcdb1fba45 100644 --- a/include/linux/seq_file.h +++ b/include/linux/seq_file.h @@ -207,6 +207,21 @@ static const struct file_operations __name ## _fops = { \ .release = single_release, \ } +#define DEFINE_SHOW_STORE_ATTRIBUTE(__name) \ +static int __name ## _open(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, __name ## _show, inode->i_private); \ +} \ + \ +static const struct file_operations __name ## _fops = { \ + .owner = THIS_MODULE, \ + .open = __name ## _open, \ + .read = seq_read, \ + .write = __name ## _write, \ + .llseek = seq_lseek, \ + .release = single_release, \ +} + #define DEFINE_PROC_SHOW_ATTRIBUTE(__name) \ static int __name ## _open(struct inode *inode, struct file *file) \ { \ From 99d7ae0375cc183a6014bbb0d9ddb363b87e55c9 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Tue, 3 Oct 2023 14:59:53 +0300 Subject: [PATCH 02/12] kernel.h: Move ARRAY_SIZE() to a separate header commit 3cd39bc3b11b8d34b7d7c961a35fdfd18b0ebf75 upstream. Touching files so used for the kernel, forces 'make' to recompile most of the kernel. Having those definitions in more granular files helps avoid recompiling so much of the kernel. Intel-SIG: commit 3cd39bc3b11b kernel.h: Move ARRAY_SIZE() to a separate header Backport PLR (Power Limit Reasons) TPMI driver Signed-off-by: Alejandro Colomar Reviewed-by: Giovanni Cabiddu Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20230817143352.132583-2-lucas.segarra.fernandez@intel.com [andy: reduced to cover only string.h for now] Signed-off-by: Andy Shevchenko [ Zhang Rui: amend commit log ] Signed-off-by: Zhang Rui --- include/linux/array_size.h | 13 +++++++++++++ include/linux/kernel.h | 7 +------ include/linux/string.h | 1 + 3 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 include/linux/array_size.h diff --git a/include/linux/array_size.h b/include/linux/array_size.h new file mode 100644 index 0000000000000..06d7d83196ca3 --- /dev/null +++ b/include/linux/array_size.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_ARRAY_SIZE_H +#define _LINUX_ARRAY_SIZE_H + +#include + +/** + * ARRAY_SIZE - get the number of elements in array @arr + * @arr: array to be sized + */ +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) + +#endif /* _LINUX_ARRAY_SIZE_H */ diff --git a/include/linux/kernel.h b/include/linux/kernel.h index cee8fe87e9f4f..d9ad21058eed9 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -50,12 +51,6 @@ #define READ 0 #define WRITE 1 -/** - * ARRAY_SIZE - get the number of elements in array @arr - * @arr: array to be sized - */ -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) - #define PTR_IF(cond, ptr) ((cond) ? (ptr) : NULL) #define u64_to_user_ptr(x) ( \ diff --git a/include/linux/string.h b/include/linux/string.h index 5077776e995e0..ce137830a0b99 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -2,6 +2,7 @@ #ifndef _LINUX_STRING_H_ #define _LINUX_STRING_H_ +#include #include /* for inline */ #include /* for size_t */ #include /* for NULL */ From d01d49fad679ab144c7680edeef5ae0b690f145a Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Mon, 13 Nov 2023 16:27:45 +0100 Subject: [PATCH 03/12] batman-adv: Switch to linux/array_size.h commit c3ed16a64c0b0a5b116c9753bf48496d49daffb5 upstream. The commit 3cd39bc3b11b ("kernel.h: Move ARRAY_SIZE() to a separate header") introduced a new header for the ARRAY_SIZE macro which was previously exposed via linux/kernel.h. Intel-SIG: commit c3ed16a64c0b batman-adv: Switch to linux/array_size.h Backport PLR (Power Limit Reasons) TPMI driver Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich [ Zhang Rui: amend commit log ] Signed-off-by: Zhang Rui --- net/batman-adv/main.c | 2 +- net/batman-adv/netlink.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index e8a4499155667..357b3a6a3b4c9 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -6,6 +6,7 @@ #include "main.h" +#include #include #include #include @@ -20,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 0c64d81a77617..1f7ed9d4f6fdf 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -7,6 +7,7 @@ #include "netlink.h" #include "main.h" +#include #include #include #include @@ -20,7 +21,6 @@ #include #include #include -#include #include #include #include From 01b567e371a9daed207e1d38269750709df81b5d Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 27 May 2024 16:29:33 +0300 Subject: [PATCH 04/12] platform/x86/intel/tpmi: Add support for performance limit reasons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit b44d79d6bad16c30978c2cee3421133d3f181494 upstream. Add TPMI ID 0x0C (Perf Limit Reasons) to the list of supported TPMI IDs. Intel-SIG: commit b44d79d6bad1 platform/x86/intel/tpmi: Add support for performance limit reasons Backport PLR (Power Limit Reasons) TPMI driver Reviewed-by: Andy Shevchenko Reviewed-by: Ilpo Järvinen Signed-off-by: Tero Kristo Link: https://lore.kernel.org/r/20240527133400.483634-2-tero.kristo@linux.intel.com Signed-off-by: Ilpo Järvinen [ Zhang Rui: amend commit log ] Signed-off-by: Zhang Rui --- drivers/platform/x86/intel/tpmi.c | 2 ++ include/linux/intel_tpmi.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/platform/x86/intel/tpmi.c b/drivers/platform/x86/intel/tpmi.c index 060f9b86bc030..437c1a06d77f6 100644 --- a/drivers/platform/x86/intel/tpmi.c +++ b/drivers/platform/x86/intel/tpmi.c @@ -576,6 +576,8 @@ static const char *intel_tpmi_name(enum intel_tpmi_id id) return "uncore"; case TPMI_ID_SST: return "sst"; + case TPMI_ID_PLR: + return "plr"; default: return NULL; } diff --git a/include/linux/intel_tpmi.h b/include/linux/intel_tpmi.h index 1e880cb0f4541..a88ac937d2c29 100644 --- a/include/linux/intel_tpmi.h +++ b/include/linux/intel_tpmi.h @@ -21,6 +21,7 @@ enum intel_tpmi_id { TPMI_ID_PEM = 1, /* Power and Perf excursion Monitor */ TPMI_ID_UNCORE = 2, /* Uncore Frequency Scaling */ TPMI_ID_SST = 5, /* Speed Select Technology */ + TPMI_ID_PLR = 0xc, /* Performance Limit Reasons */ TPMI_CONTROL_ID = 0x80, /* Special ID for getting feature status */ TPMI_INFO_ID = 0x81, /* Special ID for PCI BDF and Package ID information */ }; From 4735b52e791cf790aaff4ec0e3bf065a61e80beb Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 27 May 2024 16:29:34 +0300 Subject: [PATCH 05/12] platform/x86/intel/tpmi: Add API to get debugfs root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit d36842bacf8e3491f555059f27de57b3436cc3ff upstream. Add new API to get the debugfs root directory for TPMI. This allows any TPMI devices to add their own debugfs items under the same directory structure. Intel-SIG: commit d36842bacf8e platform/x86/intel/tpmi: Add API to get debugfs root Backport PLR (Power Limit Reasons) TPMI driver Reviewed-by: Andy Shevchenko Reviewed-by: Ilpo Järvinen Signed-off-by: Tero Kristo Link: https://lore.kernel.org/r/20240527133400.483634-3-tero.kristo@linux.intel.com Signed-off-by: Ilpo Järvinen [ Zhang Rui: amend commit log ] Signed-off-by: Zhang Rui --- drivers/platform/x86/intel/tpmi.c | 9 +++++++++ include/linux/intel_tpmi.h | 1 + 2 files changed, 10 insertions(+) diff --git a/drivers/platform/x86/intel/tpmi.c b/drivers/platform/x86/intel/tpmi.c index 437c1a06d77f6..a3430abeb9869 100644 --- a/drivers/platform/x86/intel/tpmi.c +++ b/drivers/platform/x86/intel/tpmi.c @@ -357,6 +357,15 @@ int tpmi_get_feature_status(struct auxiliary_device *auxdev, } EXPORT_SYMBOL_NS_GPL(tpmi_get_feature_status, INTEL_TPMI); +struct dentry *tpmi_get_debugfs_dir(struct auxiliary_device *auxdev) +{ + struct intel_vsec_device *intel_vsec_dev = dev_to_ivdev(auxdev->dev.parent); + struct intel_tpmi_info *tpmi_info = auxiliary_get_drvdata(&intel_vsec_dev->auxdev); + + return tpmi_info->dbgfs_dir; +} +EXPORT_SYMBOL_NS_GPL(tpmi_get_debugfs_dir, INTEL_TPMI); + static int tpmi_pfs_dbg_show(struct seq_file *s, void *unused) { struct intel_tpmi_info *tpmi_info = s->private; diff --git a/include/linux/intel_tpmi.h b/include/linux/intel_tpmi.h index a88ac937d2c29..ff480b47ae642 100644 --- a/include/linux/intel_tpmi.h +++ b/include/linux/intel_tpmi.h @@ -54,4 +54,5 @@ struct resource *tpmi_get_resource_at_index(struct auxiliary_device *auxdev, int int tpmi_get_resource_count(struct auxiliary_device *auxdev); int tpmi_get_feature_status(struct auxiliary_device *auxdev, int feature_id, bool *read_blocked, bool *write_blocked); +struct dentry *tpmi_get_debugfs_dir(struct auxiliary_device *auxdev); #endif From e043d0c42992beaab7261ee3c5fbeec12770586f Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Tue, 28 May 2024 10:34:57 +0300 Subject: [PATCH 06/12] platform/x86/intel: TPMI domain id and CPU mapping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 17ca2780458cdb0afc623e3432b1977847da3d15 upstream. Each TPMI power domain includes a group of CPUs. Several power management settings in this case applicable to a group of CPUs. There can be several power domains in a CPU package. So, provide interfaces for: - Get power domain id for a Linux CPU - Get mask of Linux CPUs in a power domain Hardware Punit uses different CPU numbering, which is not based on APIC (Advanced Programmable Interrupt Controller) CPU numbering. The Linux CPU numbering is based on APIC CPU numbering. Some PM features like Intel Speed Select, the CPU core mask provided by the hardware is based on the Punit CPU numbering. To use the core mask, this mask needs to be converted to a Linux CPUs mask. So, provide interfaces for: - Convert to a Linux CPU number from a Punit CPU number - Convert to a Punit CPU number from a Linux CPU number On each CPU online, MSR 0x54 is used to read the mapping and stores in a per cpu array. Create a hash for faster searching of a Linux CPU number from a Punit CPU number. Intel-SIG: commit 17ca2780458c platform/x86/intel: TPMI domain id and CPU mapping Backport PLR (Power Limit Reasons) TPMI driver Signed-off-by: Srinivas Pandruvada [tero.kristo: minor updates] Reviewed-by: Andy Shevchenko Reviewed-by: Ilpo Järvinen Signed-off-by: Tero Kristo Link: https://lore.kernel.org/r/20240528073457.497816-1-tero.kristo@linux.intel.com Signed-off-by: Ilpo Järvinen [ Zhang Rui: amend commit log ] Signed-off-by: Zhang Rui --- drivers/platform/x86/intel/Kconfig | 4 + drivers/platform/x86/intel/Makefile | 3 + .../platform/x86/intel/tpmi_power_domains.c | 235 ++++++++++++++++++ .../platform/x86/intel/tpmi_power_domains.h | 18 ++ 4 files changed, 260 insertions(+) create mode 100644 drivers/platform/x86/intel/tpmi_power_domains.c create mode 100644 drivers/platform/x86/intel/tpmi_power_domains.h diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/intel/Kconfig index e9dc0c0210299..e97a97355d5aa 100644 --- a/drivers/platform/x86/intel/Kconfig +++ b/drivers/platform/x86/intel/Kconfig @@ -192,10 +192,14 @@ config INTEL_SMARTCONNECT This driver checks to determine whether the device has Intel Smart Connect enabled, and if so disables it. +config INTEL_TPMI_POWER_DOMAINS + tristate + config INTEL_TPMI tristate "Intel Topology Aware Register and PM Capsule Interface (TPMI)" depends on INTEL_VSEC depends on X86_64 + select INTEL_TPMI_POWER_DOMAINS help The Intel Topology Aware Register and PM Capsule Interface (TPMI), provides enumerable MMIO interface for power management features. diff --git a/drivers/platform/x86/intel/Makefile b/drivers/platform/x86/intel/Makefile index c1d5fe05e3f30..10437e56027dd 100644 --- a/drivers/platform/x86/intel/Makefile +++ b/drivers/platform/x86/intel/Makefile @@ -53,6 +53,9 @@ obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o intel_vsec_tpmi-y := tpmi.o obj-$(CONFIG_INTEL_TPMI) += intel_vsec_tpmi.o +intel_tpmi_power_domains-y := tpmi_power_domains.o +obj-$(CONFIG_INTEL_TPMI_POWER_DOMAINS) += intel_tpmi_power_domains.o + # Intel Uncore drivers intel-rst-y := rst.o obj-$(CONFIG_INTEL_RST) += intel-rst.o diff --git a/drivers/platform/x86/intel/tpmi_power_domains.c b/drivers/platform/x86/intel/tpmi_power_domains.c new file mode 100644 index 0000000000000..4eb02553957cf --- /dev/null +++ b/drivers/platform/x86/intel/tpmi_power_domains.c @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Mapping of TPMI power domains CPU mapping + * + * Copyright (c) 2024, Intel Corporation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "tpmi_power_domains.h" + +#define MSR_PM_LOGICAL_ID 0x54 + +/* + * Struct of MSR 0x54 + * [15:11] PM_DOMAIN_ID + * [10:3] MODULE_ID (aka IDI_AGENT_ID) + * [2:0] LP_ID + * For Atom: + * [2] Always 0 + * [1:0] core ID within module + * For Core + * [2:1] Always 0 + * [0] thread ID + */ + +#define LP_ID_MASK GENMASK_ULL(2, 0) +#define MODULE_ID_MASK GENMASK_ULL(10, 3) +#define PM_DOMAIN_ID_MASK GENMASK_ULL(15, 11) + +/** + * struct tpmi_cpu_info - Mapping information for a CPU + * @hnode: Used to add mapping information to hash list + * @linux_cpu: Linux CPU number + * @pkg_id: Package ID of this CPU + * @punit_thread_id: Punit thread id of this CPU + * @punit_core_id: Punit core id + * @punit_domain_id: Power domain id from Punit + * + * Structure to store mapping information for a Linux CPU + * to a Punit core, thread and power domain. + */ +struct tpmi_cpu_info { + struct hlist_node hnode; + int linux_cpu; + u8 pkg_id; + u8 punit_thread_id; + u8 punit_core_id; + u8 punit_domain_id; +}; + +static DEFINE_PER_CPU(struct tpmi_cpu_info, tpmi_cpu_info); + +/* The dynamically assigned cpu hotplug state to free later */ +static enum cpuhp_state tpmi_hp_state __read_mostly; + +#define MAX_POWER_DOMAINS 8 + +static cpumask_t *tpmi_power_domain_mask; + +/* Lock to protect tpmi_power_domain_mask and tpmi_cpu_hash */ +static DEFINE_MUTEX(tpmi_lock); + +static const struct x86_cpu_id tpmi_cpu_ids[] = { + X86_MATCH_VFM(INTEL_GRANITERAPIDS_X, NULL), + X86_MATCH_VFM(INTEL_ATOM_CRESTMONT_X, NULL), + X86_MATCH_VFM(INTEL_ATOM_CRESTMONT, NULL), + X86_MATCH_VFM(INTEL_GRANITERAPIDS_D, NULL), + {} +}; +MODULE_DEVICE_TABLE(x86cpu, tpmi_cpu_ids); + +static DECLARE_HASHTABLE(tpmi_cpu_hash, 8); + +static bool tpmi_domain_is_valid(struct tpmi_cpu_info *info) +{ + return info->pkg_id < topology_max_packages() && + info->punit_domain_id < MAX_POWER_DOMAINS; +} + +int tpmi_get_linux_cpu_number(int package_id, int domain_id, int punit_core_id) +{ + struct tpmi_cpu_info *info; + int ret = -EINVAL; + + guard(mutex)(&tpmi_lock); + hash_for_each_possible(tpmi_cpu_hash, info, hnode, punit_core_id) { + if (info->punit_domain_id == domain_id && info->pkg_id == package_id) { + ret = info->linux_cpu; + break; + } + } + + return ret; +} +EXPORT_SYMBOL_NS_GPL(tpmi_get_linux_cpu_number, INTEL_TPMI_POWER_DOMAIN); + +int tpmi_get_punit_core_number(int cpu_no) +{ + if (cpu_no >= num_possible_cpus()) + return -EINVAL; + + return per_cpu(tpmi_cpu_info, cpu_no).punit_core_id; +} +EXPORT_SYMBOL_NS_GPL(tpmi_get_punit_core_number, INTEL_TPMI_POWER_DOMAIN); + +int tpmi_get_power_domain_id(int cpu_no) +{ + if (cpu_no >= num_possible_cpus()) + return -EINVAL; + + return per_cpu(tpmi_cpu_info, cpu_no).punit_domain_id; +} +EXPORT_SYMBOL_NS_GPL(tpmi_get_power_domain_id, INTEL_TPMI_POWER_DOMAIN); + +cpumask_t *tpmi_get_power_domain_mask(int cpu_no) +{ + struct tpmi_cpu_info *info; + cpumask_t *mask; + int index; + + if (cpu_no >= num_possible_cpus()) + return NULL; + + info = &per_cpu(tpmi_cpu_info, cpu_no); + if (!tpmi_domain_is_valid(info)) + return NULL; + + index = info->pkg_id * MAX_POWER_DOMAINS + info->punit_domain_id; + guard(mutex)(&tpmi_lock); + mask = &tpmi_power_domain_mask[index]; + + return mask; +} +EXPORT_SYMBOL_NS_GPL(tpmi_get_power_domain_mask, INTEL_TPMI_POWER_DOMAIN); + +static int tpmi_get_logical_id(unsigned int cpu, struct tpmi_cpu_info *info) +{ + u64 data; + int ret; + + ret = rdmsrl_safe(MSR_PM_LOGICAL_ID, &data); + if (ret) + return ret; + + info->punit_domain_id = FIELD_GET(PM_DOMAIN_ID_MASK, data); + if (info->punit_domain_id >= MAX_POWER_DOMAINS) + return -EINVAL; + + info->punit_thread_id = FIELD_GET(LP_ID_MASK, data); + info->punit_core_id = FIELD_GET(MODULE_ID_MASK, data); + info->pkg_id = topology_physical_package_id(cpu); + info->linux_cpu = cpu; + + return 0; +} + +static int tpmi_cpu_online(unsigned int cpu) +{ + struct tpmi_cpu_info *info = &per_cpu(tpmi_cpu_info, cpu); + int ret, index; + + /* Don't fail CPU online for some bad mapping of CPUs */ + ret = tpmi_get_logical_id(cpu, info); + if (ret) + return 0; + + index = info->pkg_id * MAX_POWER_DOMAINS + info->punit_domain_id; + + guard(mutex)(&tpmi_lock); + cpumask_set_cpu(cpu, &tpmi_power_domain_mask[index]); + hash_add(tpmi_cpu_hash, &info->hnode, info->punit_core_id); + + return 0; +} + +static int __init tpmi_init(void) +{ + const struct x86_cpu_id *id; + u64 data; + int ret; + + id = x86_match_cpu(tpmi_cpu_ids); + if (!id) + return -ENODEV; + + /* Check for MSR 0x54 presence */ + ret = rdmsrl_safe(MSR_PM_LOGICAL_ID, &data); + if (ret) + return ret; + + tpmi_power_domain_mask = kcalloc(size_mul(topology_max_packages(), MAX_POWER_DOMAINS), + sizeof(*tpmi_power_domain_mask), GFP_KERNEL); + if (!tpmi_power_domain_mask) + return -ENOMEM; + + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, + "platform/x86/tpmi_power_domains:online", + tpmi_cpu_online, NULL); + if (ret < 0) { + kfree(tpmi_power_domain_mask); + return ret; + } + + tpmi_hp_state = ret; + + return 0; +} +module_init(tpmi_init) + +static void __exit tpmi_exit(void) +{ + cpuhp_remove_state(tpmi_hp_state); + kfree(tpmi_power_domain_mask); +} +module_exit(tpmi_exit) + +MODULE_DESCRIPTION("TPMI Power Domains Mapping"); +MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/intel/tpmi_power_domains.h b/drivers/platform/x86/intel/tpmi_power_domains.h new file mode 100644 index 0000000000000..e35750dd92736 --- /dev/null +++ b/drivers/platform/x86/intel/tpmi_power_domains.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Mapping of TPMI power domain and CPUs + * + * Copyright (c) 2024, Intel Corporation. + */ + +#ifndef _TPMI_POWER_DOMAINS_H_ +#define _TPMI_POWER_DOMAINS_H_ + +#include + +int tpmi_get_linux_cpu_number(int package_id, int die_id, int punit_core_id); +int tpmi_get_punit_core_number(int cpu_no); +int tpmi_get_power_domain_id(int cpu_no); +cpumask_t *tpmi_get_power_domain_mask(int cpu_no); + +#endif From 8b5eaa7548f49de73f20fecb5a5f346e8209aecb Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 27 May 2024 16:29:36 +0300 Subject: [PATCH 07/12] platform/x86/intel/tpmi: Add new auxiliary driver for performance limits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 811f67c51636d43791995bf483c5c1904900b531 upstream. Add new auxiliary driver that exposes the SoC performance limit reasons via debugfs interface. Intel-SIG: commit 811f67c51636 platform/x86/intel/tpmi: Add new auxiliary driver for performance limits Backport PLR (Power Limit Reasons) TPMI driver Reviewed-by: Andy Shevchenko Reviewed-by: Ilpo Järvinen Signed-off-by: Tero Kristo Link: https://lore.kernel.org/r/20240527133400.483634-5-tero.kristo@linux.intel.com Signed-off-by: Ilpo Järvinen [ Zhang Rui: amend commit log ] Signed-off-by: Zhang Rui --- drivers/platform/x86/intel/Kconfig | 7 + drivers/platform/x86/intel/Makefile | 1 + drivers/platform/x86/intel/intel_plr_tpmi.c | 204 ++++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 drivers/platform/x86/intel/intel_plr_tpmi.c diff --git a/drivers/platform/x86/intel/Kconfig b/drivers/platform/x86/intel/Kconfig index e97a97355d5aa..ad50bbabec615 100644 --- a/drivers/platform/x86/intel/Kconfig +++ b/drivers/platform/x86/intel/Kconfig @@ -209,6 +209,13 @@ config INTEL_TPMI To compile this driver as a module, choose M here: the module will be called intel_vsec_tpmi. +config INTEL_PLR_TPMI + tristate "Intel SoC TPMI Power Limit Reasons driver" + depends on INTEL_TPMI + help + This driver provides the TPMI power limit reasons status information + via debugfs files. + config INTEL_TURBO_MAX_3 bool "Intel Turbo Boost Max Technology 3.0 enumeration driver" depends on X86_64 && SCHED_MC_PRIO diff --git a/drivers/platform/x86/intel/Makefile b/drivers/platform/x86/intel/Makefile index 10437e56027dd..74db065c82d61 100644 --- a/drivers/platform/x86/intel/Makefile +++ b/drivers/platform/x86/intel/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o # TPMI drivers intel_vsec_tpmi-y := tpmi.o obj-$(CONFIG_INTEL_TPMI) += intel_vsec_tpmi.o +obj-$(CONFIG_INTEL_PLR_TPMI) += intel_plr_tpmi.o intel_tpmi_power_domains-y := tpmi_power_domains.o obj-$(CONFIG_INTEL_TPMI_POWER_DOMAINS) += intel_tpmi_power_domains.o diff --git a/drivers/platform/x86/intel/intel_plr_tpmi.c b/drivers/platform/x86/intel/intel_plr_tpmi.c new file mode 100644 index 0000000000000..3c51e50bd244f --- /dev/null +++ b/drivers/platform/x86/intel/intel_plr_tpmi.c @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Performance Limit Reasons via TPMI + * + * Copyright (c) 2024, Intel Corporation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PLR_HEADER 0x00 +#define PLR_DIE_LEVEL 0x18 + +#define PLR_INVALID GENMASK_ULL(63, 0) + +struct tpmi_plr_die { + void __iomem *base; +}; + +struct tpmi_plr { + struct dentry *dbgfs_dir; + struct tpmi_plr_die *die_info; + int num_dies; +}; + +static const char * const plr_coarse_reasons[] = { + "FREQUENCY", + "CURRENT", + "POWER", + "THERMAL", + "PLATFORM", + "MCP", + "RAS", + "MISC", + "QOS", + "DFC", +}; + +static u64 plr_read(struct tpmi_plr_die *plr_die, int offset) +{ + return readq(plr_die->base + offset); +} + +static void plr_write(u64 val, struct tpmi_plr_die *plr_die, int offset) +{ + writeq(val, plr_die->base + offset); +} + +static void plr_print_bits(struct seq_file *s, u64 val, int bits) +{ + const unsigned long mask[] = { BITMAP_FROM_U64(val) }; + int bit; + + for_each_set_bit(bit, mask, bits) { + if (bit >= ARRAY_SIZE(plr_coarse_reasons)) + seq_printf(s, " UNKNOWN(%d)", bit); + else + seq_printf(s, " %s", plr_coarse_reasons[bit]); + } + + if (!val) + seq_puts(s, " none"); + + seq_putc(s, '\n'); +} + +static int plr_status_show(struct seq_file *s, void *unused) +{ + struct tpmi_plr_die *plr_die = s->private; + u64 val; + + val = plr_read(plr_die, PLR_DIE_LEVEL); + seq_puts(s, "cpus"); + plr_print_bits(s, val, 32); + + return 0; +} + +static ssize_t plr_status_write(struct file *filp, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct seq_file *s = filp->private_data; + struct tpmi_plr_die *plr_die = s->private; + bool val; + int ret; + + ret = kstrtobool_from_user(ubuf, count, &val); + if (ret) + return ret; + + if (val != 0) + return -EINVAL; + + plr_write(0, plr_die, PLR_DIE_LEVEL); + + return count; +} +DEFINE_SHOW_STORE_ATTRIBUTE(plr_status); + +static int intel_plr_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id) +{ + struct intel_tpmi_plat_info *plat_info; + struct dentry *dentry; + int i, num_resources; + struct resource *res; + struct tpmi_plr *plr; + void __iomem *base; + char name[16]; + int err; + + plat_info = tpmi_get_platform_data(auxdev); + if (!plat_info) + return dev_err_probe(&auxdev->dev, -EINVAL, "No platform info\n"); + + dentry = tpmi_get_debugfs_dir(auxdev); + if (!dentry) + return dev_err_probe(&auxdev->dev, -ENODEV, "No TPMI debugfs directory.\n"); + + num_resources = tpmi_get_resource_count(auxdev); + if (!num_resources) + return -EINVAL; + + plr = devm_kzalloc(&auxdev->dev, sizeof(*plr), GFP_KERNEL); + if (!plr) + return -ENOMEM; + + plr->die_info = devm_kcalloc(&auxdev->dev, num_resources, sizeof(*plr->die_info), + GFP_KERNEL); + if (!plr->die_info) + return -ENOMEM; + + plr->num_dies = num_resources; + plr->dbgfs_dir = debugfs_create_dir("plr", dentry); + + for (i = 0; i < num_resources; i++) { + res = tpmi_get_resource_at_index(auxdev, i); + if (!res) { + err = dev_err_probe(&auxdev->dev, -EINVAL, "No resource\n"); + goto err; + } + + base = devm_ioremap_resource(&auxdev->dev, res); + if (IS_ERR(base)) { + err = PTR_ERR(base); + goto err; + } + + plr->die_info[i].base = base; + + if (plr_read(&plr->die_info[i], PLR_HEADER) == PLR_INVALID) + continue; + + snprintf(name, sizeof(name), "domain%d", i); + + dentry = debugfs_create_dir(name, plr->dbgfs_dir); + debugfs_create_file("status", 0444, dentry, &plr->die_info[i], + &plr_status_fops); + } + + auxiliary_set_drvdata(auxdev, plr); + + return 0; + +err: + debugfs_remove_recursive(plr->dbgfs_dir); + return err; +} + +static void intel_plr_remove(struct auxiliary_device *auxdev) +{ + struct tpmi_plr *plr = auxiliary_get_drvdata(auxdev); + + debugfs_remove_recursive(plr->dbgfs_dir); +} + +static const struct auxiliary_device_id intel_plr_id_table[] = { + { .name = "intel_vsec.tpmi-plr" }, + {} +}; +MODULE_DEVICE_TABLE(auxiliary, intel_plr_id_table); + +static struct auxiliary_driver intel_plr_aux_driver = { + .id_table = intel_plr_id_table, + .remove = intel_plr_remove, + .probe = intel_plr_probe, +}; +module_auxiliary_driver(intel_plr_aux_driver); + +MODULE_IMPORT_NS(INTEL_TPMI); +MODULE_DESCRIPTION("Intel TPMI PLR Driver"); +MODULE_LICENSE("GPL"); From 6aef0c8e68fb5de7e48ca89110ccc54dfaa114c6 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 27 May 2024 16:29:37 +0300 Subject: [PATCH 08/12] platform/x86/intel/tpmi/plr: Add support for the plr mailbox MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 9e9397a41b7b1db10603edcb13913034bd41cce0 upstream. Add support for reading fine grained power limit reasons via the PLR mailbox. Intel-SIG: commit 9e9397a41b7b platform/x86/intel/tpmi/plr: Add support for the plr mailbox Backport PLR (Power Limit Reasons) TPMI driver Reviewed-by: Andy Shevchenko Reviewed-by: Ilpo Järvinen Signed-off-by: Tero Kristo Link: https://lore.kernel.org/r/20240527133400.483634-6-tero.kristo@linux.intel.com Signed-off-by: Ilpo Järvinen [ Zhang Rui: amend commit log ] Signed-off-by: Zhang Rui --- drivers/platform/x86/intel/intel_plr_tpmi.c | 157 +++++++++++++++++++- 1 file changed, 153 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/intel/intel_plr_tpmi.c b/drivers/platform/x86/intel/intel_plr_tpmi.c index 3c51e50bd244f..c1aa52c23d256 100644 --- a/drivers/platform/x86/intel/intel_plr_tpmi.c +++ b/drivers/platform/x86/intel/intel_plr_tpmi.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -14,26 +15,50 @@ #include #include #include +#include #include +#include #include #include +#include #include #include #include +#include "tpmi_power_domains.h" + #define PLR_HEADER 0x00 +#define PLR_MAILBOX_INTERFACE 0x08 +#define PLR_MAILBOX_DATA 0x10 #define PLR_DIE_LEVEL 0x18 +#define PLR_MODULE_ID_MASK GENMASK_ULL(19, 12) +#define PLR_RUN_BUSY BIT_ULL(63) + +#define PLR_COMMAND_WRITE 1 + #define PLR_INVALID GENMASK_ULL(63, 0) +#define PLR_TIMEOUT_US 5 +#define PLR_TIMEOUT_MAX_US 1000 + +#define PLR_COARSE_REASON_BITS 32 + +struct tpmi_plr; + struct tpmi_plr_die { void __iomem *base; + struct mutex lock; /* Protect access to PLR mailbox */ + int package_id; + int die_id; + struct tpmi_plr *plr; }; struct tpmi_plr { struct dentry *dbgfs_dir; struct tpmi_plr_die *die_info; int num_dies; + struct auxiliary_device *auxdev; }; static const char * const plr_coarse_reasons[] = { @@ -49,6 +74,39 @@ static const char * const plr_coarse_reasons[] = { "DFC", }; +static const char * const plr_fine_reasons[] = { + "FREQUENCY_CDYN0", + "FREQUENCY_CDYN1", + "FREQUENCY_CDYN2", + "FREQUENCY_CDYN3", + "FREQUENCY_CDYN4", + "FREQUENCY_CDYN5", + "FREQUENCY_FCT", + "FREQUENCY_PCS_TRL", + "CURRENT_MTPMAX", + "POWER_FAST_RAPL", + "POWER_PKG_PL1_MSR_TPMI", + "POWER_PKG_PL1_MMIO", + "POWER_PKG_PL1_PCS", + "POWER_PKG_PL2_MSR_TPMI", + "POWER_PKG_PL2_MMIO", + "POWER_PKG_PL2_PCS", + "POWER_PLATFORM_PL1_MSR_TPMI", + "POWER_PLATFORM_PL1_MMIO", + "POWER_PLATFORM_PL1_PCS", + "POWER_PLATFORM_PL2_MSR_TPMI", + "POWER_PLATFORM_PL2_MMIO", + "POWER_PLATFORM_PL2_PCS", + "UNKNOWN(22)", + "THERMAL_PER_CORE", + "DFC_UFS", + "PLATFORM_PROCHOT", + "PLATFORM_HOT_VR", + "UNKNOWN(27)", + "UNKNOWN(28)", + "MISC_PCS_PSTATE", +}; + static u64 plr_read(struct tpmi_plr_die *plr_die, int offset) { return readq(plr_die->base + offset); @@ -59,16 +117,68 @@ static void plr_write(u64 val, struct tpmi_plr_die *plr_die, int offset) writeq(val, plr_die->base + offset); } +static int plr_read_cpu_status(struct tpmi_plr_die *plr_die, int cpu, + u64 *status) +{ + u64 regval; + int ret; + + lockdep_assert_held(&plr_die->lock); + + regval = FIELD_PREP(PLR_MODULE_ID_MASK, tpmi_get_punit_core_number(cpu)); + regval |= PLR_RUN_BUSY; + + plr_write(regval, plr_die, PLR_MAILBOX_INTERFACE); + + ret = readq_poll_timeout(plr_die->base + PLR_MAILBOX_INTERFACE, regval, + !(regval & PLR_RUN_BUSY), PLR_TIMEOUT_US, + PLR_TIMEOUT_MAX_US); + if (ret) + return ret; + + *status = plr_read(plr_die, PLR_MAILBOX_DATA); + + return 0; +} + +static int plr_clear_cpu_status(struct tpmi_plr_die *plr_die, int cpu) +{ + u64 regval; + + lockdep_assert_held(&plr_die->lock); + + regval = FIELD_PREP(PLR_MODULE_ID_MASK, tpmi_get_punit_core_number(cpu)); + regval |= PLR_RUN_BUSY | PLR_COMMAND_WRITE; + + plr_write(0, plr_die, PLR_MAILBOX_DATA); + + plr_write(regval, plr_die, PLR_MAILBOX_INTERFACE); + + return readq_poll_timeout(plr_die->base + PLR_MAILBOX_INTERFACE, regval, + !(regval & PLR_RUN_BUSY), PLR_TIMEOUT_US, + PLR_TIMEOUT_MAX_US); +} + static void plr_print_bits(struct seq_file *s, u64 val, int bits) { const unsigned long mask[] = { BITMAP_FROM_U64(val) }; - int bit; + const char *str; + int bit, index; for_each_set_bit(bit, mask, bits) { - if (bit >= ARRAY_SIZE(plr_coarse_reasons)) - seq_printf(s, " UNKNOWN(%d)", bit); + if (bit < PLR_COARSE_REASON_BITS) { + if (bit < ARRAY_SIZE(plr_coarse_reasons)) + str = plr_coarse_reasons[bit]; + } else { + index = bit - PLR_COARSE_REASON_BITS; + if (index < ARRAY_SIZE(plr_fine_reasons)) + str = plr_fine_reasons[index]; + } + + if (str) + seq_printf(s, " %s", str); else - seq_printf(s, " %s", plr_coarse_reasons[bit]); + seq_printf(s, " UNKNOWN(%d)", bit); } if (!val) @@ -80,12 +190,33 @@ static void plr_print_bits(struct seq_file *s, u64 val, int bits) static int plr_status_show(struct seq_file *s, void *unused) { struct tpmi_plr_die *plr_die = s->private; + int ret; u64 val; val = plr_read(plr_die, PLR_DIE_LEVEL); seq_puts(s, "cpus"); plr_print_bits(s, val, 32); + guard(mutex)(&plr_die->lock); + + for (int cpu = 0; cpu < nr_cpu_ids; cpu++) { + if (plr_die->die_id != tpmi_get_power_domain_id(cpu)) + continue; + + if (plr_die->package_id != topology_physical_package_id(cpu)) + continue; + + seq_printf(s, "cpu%d", cpu); + ret = plr_read_cpu_status(plr_die, cpu, &val); + if (ret) { + dev_err(&plr_die->plr->auxdev->dev, "Failed to read PLR for cpu %d, ret=%d\n", + cpu, ret); + return ret; + } + + plr_print_bits(s, val, 64); + } + return 0; } @@ -106,6 +237,18 @@ static ssize_t plr_status_write(struct file *filp, const char __user *ubuf, plr_write(0, plr_die, PLR_DIE_LEVEL); + guard(mutex)(&plr_die->lock); + + for (int cpu = 0; cpu < nr_cpu_ids; cpu++) { + if (plr_die->die_id != tpmi_get_power_domain_id(cpu)) + continue; + + if (plr_die->package_id != topology_physical_package_id(cpu)) + continue; + + plr_clear_cpu_status(plr_die, cpu); + } + return count; } DEFINE_SHOW_STORE_ATTRIBUTE(plr_status); @@ -144,6 +287,7 @@ static int intel_plr_probe(struct auxiliary_device *auxdev, const struct auxilia plr->num_dies = num_resources; plr->dbgfs_dir = debugfs_create_dir("plr", dentry); + plr->auxdev = auxdev; for (i = 0; i < num_resources; i++) { res = tpmi_get_resource_at_index(auxdev, i); @@ -159,6 +303,10 @@ static int intel_plr_probe(struct auxiliary_device *auxdev, const struct auxilia } plr->die_info[i].base = base; + plr->die_info[i].package_id = plat_info->package_id; + plr->die_info[i].die_id = i; + plr->die_info[i].plr = plr; + mutex_init(&plr->die_info[i].lock); if (plr_read(&plr->die_info[i], PLR_HEADER) == PLR_INVALID) continue; @@ -200,5 +348,6 @@ static struct auxiliary_driver intel_plr_aux_driver = { module_auxiliary_driver(intel_plr_aux_driver); MODULE_IMPORT_NS(INTEL_TPMI); +MODULE_IMPORT_NS(INTEL_TPMI_POWER_DOMAIN); MODULE_DESCRIPTION("Intel TPMI PLR Driver"); MODULE_LICENSE("GPL"); From a7a3b6335e8a52d9572d7fb063d462b770d61506 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 15 Jul 2024 15:22:55 -0500 Subject: [PATCH 09/12] platform/x86/intel/tpmi/plr: Fix output in plr_print_bits() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 182c6941c55347c735e70ffca77741cd000cbec7 upstream. Smatch complains that 'str' can be used without being initialized: drivers/platform/x86/intel/intel_plr_tpmi.c:178 plr_print_bits() error: uninitialized symbol 'str'. In this loop, we iterate over all the set bits and print the name of the bit. The intention is that if there is a bit which is between 0-31 we look for the name in the first array plr_coarse_reasons[] which has 10 elements. If the bit is in the 32-63 range we look for it in the plr_fine_reasons[] array which has 30 elements. If the bit is in the invalid ranges, 10-31 or 62-63, then we should print "UNKNOWN(%d)". The problem is that 'str' needs to be initialized at the start of each iteration, otherwise if we can't find the string then instead of printing "UNKNOWN(%d)", we will re-print whatever the previous bit was. Intel-SIG: commit 182c6941c553 platform/x86/intel/tpmi/plr: Fix output in plr_print_bits() Backport PLR (Power Limit Reasons) TPMI driver Fixes: 9e9397a41b7b ("platform/x86/intel/tpmi/plr: Add support for the plr mailbox") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/b0084e70-4144-445a-9b89-fb19f6b8336a@stanley.mountain Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen [ Zhang Rui: amend commit log ] Signed-off-by: Zhang Rui --- drivers/platform/x86/intel/intel_plr_tpmi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/intel/intel_plr_tpmi.c b/drivers/platform/x86/intel/intel_plr_tpmi.c index c1aa52c23d256..69ace6a629bc7 100644 --- a/drivers/platform/x86/intel/intel_plr_tpmi.c +++ b/drivers/platform/x86/intel/intel_plr_tpmi.c @@ -162,10 +162,11 @@ static int plr_clear_cpu_status(struct tpmi_plr_die *plr_die, int cpu) static void plr_print_bits(struct seq_file *s, u64 val, int bits) { const unsigned long mask[] = { BITMAP_FROM_U64(val) }; - const char *str; int bit, index; for_each_set_bit(bit, mask, bits) { + const char *str = NULL; + if (bit < PLR_COARSE_REASON_BITS) { if (bit < ARRAY_SIZE(plr_coarse_reasons)) str = plr_coarse_reasons[bit]; From 0e36d40dda3715db13eed6cdb57eec982bd9bcfb Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 3 Jan 2025 07:52:53 -0800 Subject: [PATCH 10/12] platform/x86/intel: power-domains: Add Clearwater Forest support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit bee9a0838fd223823e5a6d85c055ab1691dc738e upstream. Add Clearwater Forest support (INTEL_ATOM_DARKMONT_X) to tpmi_cpu_ids to support domaid id mappings. Intel-SIG: commit bee9a0838fd2 platform/x86/intel: power-domains: Add Clearwater Forest support Backport PLR (Power Limit Reasons) TPMI driver Signed-off-by: Srinivas Pandruvada Link: https://lore.kernel.org/r/20250103155255.1488139-1-srinivas.pandruvada@linux.intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen [ Zhang Rui: amend commit log ] Signed-off-by: Zhang Rui --- drivers/platform/x86/intel/tpmi_power_domains.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/intel/tpmi_power_domains.c b/drivers/platform/x86/intel/tpmi_power_domains.c index 4eb02553957cf..6b7933fab0f1f 100644 --- a/drivers/platform/x86/intel/tpmi_power_domains.c +++ b/drivers/platform/x86/intel/tpmi_power_domains.c @@ -81,6 +81,7 @@ static const struct x86_cpu_id tpmi_cpu_ids[] = { X86_MATCH_VFM(INTEL_GRANITERAPIDS_X, NULL), X86_MATCH_VFM(INTEL_ATOM_CRESTMONT_X, NULL), X86_MATCH_VFM(INTEL_ATOM_CRESTMONT, NULL), + X86_MATCH_VFM(INTEL_ATOM_DARKMONT_X, NULL), X86_MATCH_VFM(INTEL_GRANITERAPIDS_D, NULL), {} }; From e772ef3e28bec9fcaec44c81b0ae1ec32cd661e6 Mon Sep 17 00:00:00 2001 From: David Arcari Date: Fri, 29 Aug 2025 07:38:59 -0400 Subject: [PATCH 11/12] platform/x86/intel: power-domains: Use topology_logical_package_id() for package ID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit aa28991fd5dc4c01a40caab2bd9af8c5e06f9899 upstream. Currently, tpmi_get_logical_id() calls topology_physical_package_id() to set the pkg_id of the info structure. Since some VM hosts assign non contiguous package IDs, topology_physical_package_id() can return a larger value than topology_max_packages(). This will result in an invalid reference into tpmi_power_domain_mask[] as that is allocatead based on topology_max_packages() as the maximum package ID. Intel-SIG: commit aa28991fd5dc platform/x86/intel: power-domains: Use topology_logical_package_id() for package ID Backport PLR (Power Limit Reasons) TPMI driver Fixes: 17ca2780458c ("platform/x86/intel: TPMI domain id and CPU mapping") Signed-off-by: David Arcari Acked-by: Srinivas Pandruvada Link: https://lore.kernel.org/r/20250829113859.1772827-1-darcari@redhat.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen [ Zhang Rui: amend commit log ] Signed-off-by: Zhang Rui --- drivers/platform/x86/intel/tpmi_power_domains.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/intel/tpmi_power_domains.c b/drivers/platform/x86/intel/tpmi_power_domains.c index 6b7933fab0f1f..e44d19b9db1b5 100644 --- a/drivers/platform/x86/intel/tpmi_power_domains.c +++ b/drivers/platform/x86/intel/tpmi_power_domains.c @@ -166,7 +166,7 @@ static int tpmi_get_logical_id(unsigned int cpu, struct tpmi_cpu_info *info) info->punit_thread_id = FIELD_GET(LP_ID_MASK, data); info->punit_core_id = FIELD_GET(MODULE_ID_MASK, data); - info->pkg_id = topology_physical_package_id(cpu); + info->pkg_id = topology_logical_package_id(cpu); info->linux_cpu = cpu; return 0; From 08b75c423990cc787ceaa86ef60d5c2fd332800e Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 4 Dec 2025 09:08:08 +0800 Subject: [PATCH 12/12] config: enable CONFIG_INTEL_PLR_TPMI Enable PLR (Perf Limit Reasons) driver. Signed-off-by: Zhang Rui --- config.x86_64 | 1 + 1 file changed, 1 insertion(+) diff --git a/config.x86_64 b/config.x86_64 index 6cd53619fa6c9..4c60c0e8e0e05 100644 --- a/config.x86_64 +++ b/config.x86_64 @@ -8196,6 +8196,7 @@ CONFIG_INTEL_OAKTRAIL=m CONFIG_INTEL_RST=m CONFIG_INTEL_SMARTCONNECT=m CONFIG_INTEL_TPMI=m +CONFIG_INTEL_PLR_TPMI=m # CONFIG_INTEL_TURBO_MAX_3 is not set CONFIG_INTEL_VSEC=m # CONFIG_MSI_EC is not set