From 2bedc0640478b6e714dd2e82875d8cc3c758f6a7 Mon Sep 17 00:00:00 2001 From: Ricardo Neri Date: Sat, 13 Jun 2026 15:17:49 -0700 Subject: [PATCH] thermal: intel: Add resources to handle directed package-level thermal interrupts When supported by hardware, a CPU requests to receive directed package- level thermal interrupts by setting a designated bit in IA32_THERM_INTERRUPT. It is sufficient to have one CPU per package handling the interrupt. Add an array to keep track of those CPUs as well as init and cleanup functions. A subsequent changeset will designate a CPU per package to handle the interrupt. Signed-off-by: Ricardo Neri Link: https://patch.msgid.link/20260613-rneri-directed-therm-intr-v3-3-3a26d1e47fc8@linux.intel.com Signed-off-by: Rafael J. Wysocki --- drivers/thermal/intel/therm_throt.c | 53 ++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/intel/therm_throt.c b/drivers/thermal/intel/therm_throt.c index 45a8ef4a608b..8e259c4e5fe8 100644 --- a/drivers/thermal/intel/therm_throt.c +++ b/drivers/thermal/intel/therm_throt.c @@ -524,6 +524,50 @@ static void thermal_throttle_remove_dev(struct device *dev) sysfs_remove_group(&dev->kobj, &thermal_attr_group); } +/* + * Accessed from CPU hotplug callbacks and from code that runs while CPU + * hotplug is inactive: the init and cleanup paths. + * No extra locking needed. + */ +static unsigned int *directed_intr_handler_cpus; + +static bool directed_thermal_pkg_intr_supported(void) +{ + if (!boot_cpu_has(X86_FEATURE_DPTI)) + return false; + + if (!directed_intr_handler_cpus) + return false; + + return true; +} + +static __init void init_directed_pkg_intr(void) +{ + int i; + + if (!boot_cpu_has(X86_FEATURE_DPTI)) + return; + + directed_intr_handler_cpus = kmalloc_array(topology_max_packages(), + sizeof(*directed_intr_handler_cpus), + GFP_KERNEL); + if (!directed_intr_handler_cpus) + return; + + for (i = 0; i < topology_max_packages(); i++) + directed_intr_handler_cpus[i] = nr_cpu_ids; +} + +static void cleanup_directed_pkg_thermal_intr(void) +{ + if (!directed_thermal_pkg_intr_supported()) + return; + + kfree(directed_intr_handler_cpus); + directed_intr_handler_cpus = NULL; +} + /* Get notified when a cpu comes on/off. Be hotplug friendly. */ static int thermal_throttle_online(unsigned int cpu) { @@ -585,12 +629,19 @@ static __init int thermal_throttle_init_device(void) if (!atomic_read(&therm_throt_en)) return 0; + init_directed_pkg_intr(); + intel_hfi_init(); ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/therm:online", thermal_throttle_online, thermal_throttle_offline); - return ret < 0 ? ret : 0; + if (ret >= 0) + return 0; + + cleanup_directed_pkg_thermal_intr(); + + return ret; } device_initcall(thermal_throttle_init_device);