diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2025-07-22 14:47:07 +0200 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2025-07-22 14:47:07 +0200 |
commit | 1e94cb6c2ae1c2660ed406669f12b90c7052d2b9 (patch) | |
tree | 9b634598aa057e99ef9c26c568b7062f6efe9b07 | |
parent | 9bf3eb1a9eb56fc3466d3a442aed365e88e1dd21 (diff) | |
parent | 866032d5625a761e7e8e9164c22c90b3c9840179 (diff) |
Merge back earlier thermal control updates for 6.17
6 files changed, 92 insertions, 4 deletions
diff --git a/Documentation/driver-api/thermal/intel_dptf.rst b/Documentation/driver-api/thermal/intel_dptf.rst index ec5769accae0..c51ac793dc06 100644 --- a/Documentation/driver-api/thermal/intel_dptf.rst +++ b/Documentation/driver-api/thermal/intel_dptf.rst @@ -206,6 +206,15 @@ All these controls needs admin privilege to update. Update a new temperature target in milli degree celsius for hardware to use for the temperature control. +``thermal_tolerance`` (RW) + This attribute ranges from 0 to 7, where 0 represents + the most aggressive control to avoid any temperature overshoots, and + 7 represents a more graceful approach, favoring performance even at + the expense of temperature overshoots. + Note: This level may not scale linearly. For example, a value of 3 does + not necessarily imply a 50% improvement in performance compared to a + value of 0. + Given that this is platform temperature control, it is expected that a single user-level manager owns and manages the controls. If multiple user-level software applications attempt to write different targets, it diff --git a/drivers/thermal/intel/int340x_thermal/platform_temperature_control.c b/drivers/thermal/intel/int340x_thermal/platform_temperature_control.c index 2d6504514893..0ccc72c93499 100644 --- a/drivers/thermal/intel/int340x_thermal/platform_temperature_control.c +++ b/drivers/thermal/intel/int340x_thermal/platform_temperature_control.c @@ -38,6 +38,7 @@ #include <linux/kernel.h> #include <linux/module.h> +#include <linux/debugfs.h> #include <linux/pci.h> #include "processor_thermal_device.h" @@ -49,14 +50,16 @@ struct mmio_reg { }; #define MAX_ATTR_GROUP_NAME_LEN 32 -#define PTC_MAX_ATTRS 3 +#define PTC_MAX_ATTRS 4 struct ptc_data { u32 offset; + struct pci_dev *pdev; struct attribute_group ptc_attr_group; struct attribute *ptc_attrs[PTC_MAX_ATTRS]; struct device_attribute temperature_target_attr; struct device_attribute enable_attr; + struct device_attribute thermal_tolerance_attr; char group_name[MAX_ATTR_GROUP_NAME_LEN]; }; @@ -78,6 +81,7 @@ static u32 ptc_offsets[PTC_MAX_INSTANCES] = {0x5B20, 0x5B28, 0x5B30}; static const char * const ptc_strings[] = { "temperature_target", "enable", + "thermal_tolerance", NULL }; @@ -177,6 +181,8 @@ PTC_SHOW(temperature_target); PTC_STORE(temperature_target); PTC_SHOW(enable); PTC_STORE(enable); +PTC_SHOW(thermal_tolerance); +PTC_STORE(thermal_tolerance); #define ptc_init_attribute(_name)\ do {\ @@ -193,9 +199,11 @@ static int ptc_create_groups(struct pci_dev *pdev, int instance, struct ptc_data ptc_init_attribute(temperature_target); ptc_init_attribute(enable); + ptc_init_attribute(thermal_tolerance); data->ptc_attrs[index++] = &data->temperature_target_attr.attr; data->ptc_attrs[index++] = &data->enable_attr.attr; + data->ptc_attrs[index++] = &data->thermal_tolerance_attr.attr; data->ptc_attrs[index] = NULL; snprintf(data->group_name, MAX_ATTR_GROUP_NAME_LEN, @@ -209,6 +217,63 @@ static int ptc_create_groups(struct pci_dev *pdev, int instance, struct ptc_data } static struct ptc_data ptc_instance[PTC_MAX_INSTANCES]; +static struct dentry *ptc_debugfs; + +#define PTC_TEMP_OVERRIDE_ENABLE_INDEX 4 +#define PTC_TEMP_OVERRIDE_INDEX 5 + +static ssize_t ptc_temperature_write(struct file *file, const char __user *data, + size_t count, loff_t *ppos) +{ + struct ptc_data *ptc_instance = file->private_data; + struct pci_dev *pdev = ptc_instance->pdev; + char buf[32]; + ssize_t len; + u32 value; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, data, len)) + return -EFAULT; + + buf[len] = '\0'; + if (kstrtouint(buf, 0, &value)) + return -EINVAL; + + if (ptc_mmio_regs[PTC_TEMP_OVERRIDE_INDEX].units) + value /= ptc_mmio_regs[PTC_TEMP_OVERRIDE_INDEX].units; + + if (value > ptc_mmio_regs[PTC_TEMP_OVERRIDE_INDEX].mask) + return -EINVAL; + + if (!value) { + ptc_mmio_write(pdev, ptc_instance->offset, PTC_TEMP_OVERRIDE_ENABLE_INDEX, 0); + } else { + ptc_mmio_write(pdev, ptc_instance->offset, PTC_TEMP_OVERRIDE_INDEX, value); + ptc_mmio_write(pdev, ptc_instance->offset, PTC_TEMP_OVERRIDE_ENABLE_INDEX, 1); + } + + return count; +} + +static const struct file_operations ptc_fops = { + .open = simple_open, + .write = ptc_temperature_write, + .llseek = generic_file_llseek, +}; + +static void ptc_create_debugfs(void) +{ + ptc_debugfs = debugfs_create_dir("platform_temperature_control", NULL); + + debugfs_create_file("temperature_0", 0200, ptc_debugfs, &ptc_instance[0], &ptc_fops); + debugfs_create_file("temperature_1", 0200, ptc_debugfs, &ptc_instance[1], &ptc_fops); + debugfs_create_file("temperature_2", 0200, ptc_debugfs, &ptc_instance[2], &ptc_fops); +} + +static void ptc_delete_debugfs(void) +{ + debugfs_remove_recursive(ptc_debugfs); +} int proc_thermal_ptc_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) { @@ -217,8 +282,11 @@ int proc_thermal_ptc_add(struct pci_dev *pdev, struct proc_thermal_device *proc_ for (i = 0; i < PTC_MAX_INSTANCES; i++) { ptc_instance[i].offset = ptc_offsets[i]; + ptc_instance[i].pdev = pdev; ptc_create_groups(pdev, i, &ptc_instance[i]); } + + ptc_create_debugfs(); } return 0; @@ -234,6 +302,8 @@ void proc_thermal_ptc_remove(struct pci_dev *pdev) for (i = 0; i < PTC_MAX_INSTANCES; i++) sysfs_remove_group(&pdev->dev.kobj, &ptc_instance[i].ptc_attr_group); + + ptc_delete_debugfs(); } } EXPORT_SYMBOL_GPL(proc_thermal_ptc_remove); diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h index 9a6ca43b6fa2..49398794124a 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h @@ -31,6 +31,7 @@ #define PCI_DEVICE_ID_INTEL_SKL_THERMAL 0x1903 #define PCI_DEVICE_ID_INTEL_TGL_THERMAL 0x9A03 #define PCI_DEVICE_ID_INTEL_PTL_THERMAL 0xB01D +#define PCI_DEVICE_ID_INTEL_WCL_THERMAL 0xFD1D struct power_config { u32 index; diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c index 00160936070a..d4d7e8e147d2 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -499,6 +499,10 @@ static const struct pci_device_id proc_thermal_pci_ids[] = { PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MSI_SUPPORT | PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR | PROC_THERMAL_FEATURE_PTC) }, + { PCI_DEVICE_DATA(INTEL, WCL_THERMAL, PROC_THERMAL_FEATURE_MSI_SUPPORT | + PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_DLVR | + PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_HINT | + PROC_THERMAL_FEATURE_POWER_FLOOR | PROC_THERMAL_FEATURE_PTC) }, { }, }; diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c index 3a028b78d9af..1f3d22b659db 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c @@ -442,6 +442,7 @@ int proc_thermal_rfim_add(struct pci_dev *pdev, struct proc_thermal_device *proc switch (pdev->device) { case PCI_DEVICE_ID_INTEL_LNLM_THERMAL: case PCI_DEVICE_ID_INTEL_PTL_THERMAL: + case PCI_DEVICE_ID_INTEL_WCL_THERMAL: dlvr_mmio_regs_table = lnl_dlvr_mmio_regs; dlvr_mapping = lnl_dlvr_mapping; break; diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c index 24b9055a0b6c..d80612506a33 100644 --- a/drivers/thermal/thermal_sysfs.c +++ b/drivers/thermal/thermal_sysfs.c @@ -40,10 +40,13 @@ temp_show(struct device *dev, struct device_attribute *attr, char *buf) ret = thermal_zone_get_temp(tz, &temperature); - if (ret) - return ret; + if (!ret) + return sprintf(buf, "%d\n", temperature); - return sprintf(buf, "%d\n", temperature); + if (ret == -EAGAIN) + return -ENODATA; + + return ret; } static ssize_t |