diff options
11 files changed, 133 insertions, 52 deletions
diff --git a/Documentation/driver-api/thermal/intel_dptf.rst b/Documentation/driver-api/thermal/intel_dptf.rst index 916bf0f36a03..4adfa1eb74db 100644 --- a/Documentation/driver-api/thermal/intel_dptf.rst +++ b/Documentation/driver-api/thermal/intel_dptf.rst @@ -375,6 +375,9 @@ based on the processor generation. ``workload_hint_enable`` (RW) Enable firmware to send workload type hints to user space. +``workload_slow_hint_enable`` (RW) + Enable firmware to send slow workload type hints to user space. + ``notification_delay_ms`` (RW) Minimum delay in milliseconds before firmware will notify OS. This is for the rate control of notifications. This delay is between changing diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c index 48e7849d4816..f80dbe2ca7e4 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c @@ -8,6 +8,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/sysfs.h> #include <linux/thermal.h> #include <asm/msr.h> #include "int340x_thermal_zone.h" @@ -23,7 +24,7 @@ static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \ { \ struct proc_thermal_device *proc_dev = dev_get_drvdata(dev); \ \ - return sprintf(buf, "%lu\n",\ + return sysfs_emit(buf, "%lu\n",\ (unsigned long)proc_dev->power_limits[index].suffix * 1000); \ } @@ -143,7 +144,7 @@ static ssize_t tcc_offset_degree_celsius_show(struct device *dev, if (offset < 0) return offset; - return sprintf(buf, "%d\n", offset); + return sysfs_emit(buf, "%d\n", offset); } static ssize_t tcc_offset_degree_celsius_store(struct device *dev, diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c index 589a3a71f0c4..bb9398dfa3c1 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c @@ -7,6 +7,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/sysfs.h> #include "processor_thermal_device.h" MODULE_IMPORT_NS("INT340X_THERMAL"); @@ -211,9 +212,9 @@ static ssize_t suffix##_show(struct device *dev,\ ret = (reg_val >> mmio_regs[ret].shift) & mmio_regs[ret].mask;\ err = get_mapped_string(mapping, attr->attr.name, ret, &str);\ if (!err)\ - return sprintf(buf, "%s\n", str);\ + return sysfs_emit(buf, "%s\n", str);\ if (err == -EOPNOTSUPP)\ - return sprintf(buf, "%u\n", ret);\ + return sysfs_emit(buf, "%u\n", ret);\ return err;\ } @@ -398,7 +399,7 @@ static ssize_t rfi_restriction_show(struct device *dev, if (ret) return ret; - return sprintf(buf, "%llu\n", resp); + return sysfs_emit(buf, "%llu\n", resp); } static ssize_t ddr_data_rate_show(struct device *dev, @@ -413,7 +414,7 @@ static ssize_t ddr_data_rate_show(struct device *dev, if (ret) return ret; - return sprintf(buf, "%llu\n", resp); + return sysfs_emit(buf, "%llu\n", resp); } static DEVICE_ATTR_RW(rfi_restriction); diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c index 68e8391af8f4..f8c33e8e5b7a 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c @@ -34,6 +34,7 @@ #define SOC_WT GENMASK_ULL(47, 40) +#define SOC_WT_SLOW_PREDICTION_INT_ENABLE_BIT 22 #define SOC_WT_PREDICTION_INT_ENABLE_BIT 23 #define SOC_WT_PREDICTION_INT_ACTIVE BIT(2) @@ -47,6 +48,7 @@ static u16 notify_delay_ms = 1024; static DEFINE_MUTEX(wt_lock); static u8 wt_enable; +static u8 wt_slow_enable; /* Show current predicted workload type index */ static ssize_t workload_type_index_show(struct device *dev, @@ -59,7 +61,7 @@ static ssize_t workload_type_index_show(struct device *dev, int wt; mutex_lock(&wt_lock); - if (!wt_enable) { + if (!wt_enable && !wt_slow_enable) { mutex_unlock(&wt_lock); return -ENODATA; } @@ -84,9 +86,9 @@ static ssize_t workload_hint_enable_show(struct device *dev, return sysfs_emit(buf, "%d\n", wt_enable); } -static ssize_t workload_hint_enable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) +static ssize_t workload_hint_enable(struct device *dev, u8 enable_bit, u8 *status, + struct device_attribute *attr, + const char *buf, size_t size) { struct pci_dev *pdev = to_pci_dev(dev); u8 mode; @@ -99,17 +101,17 @@ static ssize_t workload_hint_enable_store(struct device *dev, if (mode) ret = processor_thermal_mbox_interrupt_config(pdev, true, - SOC_WT_PREDICTION_INT_ENABLE_BIT, + enable_bit, notify_delay); else ret = processor_thermal_mbox_interrupt_config(pdev, false, - SOC_WT_PREDICTION_INT_ENABLE_BIT, 0); + enable_bit, 0); if (ret) goto ret_enable_store; ret = size; - wt_enable = mode; + *status = mode; ret_enable_store: mutex_unlock(&wt_lock); @@ -117,8 +119,28 @@ ret_enable_store: return ret; } +static ssize_t workload_hint_enable_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + return workload_hint_enable(dev, SOC_WT_PREDICTION_INT_ENABLE_BIT, &wt_enable, + attr, buf, size); +} static DEVICE_ATTR_RW(workload_hint_enable); +static ssize_t workload_slow_hint_enable_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%d\n", wt_slow_enable); +} + +static ssize_t workload_slow_hint_enable_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + return workload_hint_enable(dev, SOC_WT_SLOW_PREDICTION_INT_ENABLE_BIT, &wt_slow_enable, + attr, buf, size); +} +static DEVICE_ATTR_RW(workload_slow_hint_enable); + static ssize_t notification_delay_ms_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -178,16 +200,35 @@ static ssize_t notification_delay_ms_store(struct device *dev, static DEVICE_ATTR_RW(notification_delay_ms); +static umode_t workload_hint_attr_visible(struct kobject *kobj, struct attribute *attr, int unused) +{ + if (attr != &dev_attr_workload_slow_hint_enable.attr) + return attr->mode; + + switch (to_pci_dev(kobj_to_dev(kobj))->device) { + case PCI_DEVICE_ID_INTEL_LNLM_THERMAL: + case PCI_DEVICE_ID_INTEL_MTLP_THERMAL: + case PCI_DEVICE_ID_INTEL_ARL_S_THERMAL: + return 0; + default: + break; + } + + return attr->mode; +} + static struct attribute *workload_hint_attrs[] = { &dev_attr_workload_type_index.attr, &dev_attr_workload_hint_enable.attr, + &dev_attr_workload_slow_hint_enable.attr, &dev_attr_notification_delay_ms.attr, NULL }; static const struct attribute_group workload_hint_attribute_group = { .attrs = workload_hint_attrs, - .name = "workload_hint" + .name = "workload_hint", + .is_visible = workload_hint_attr_visible }; /* diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c index b95810f4a011..2372f5202019 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c @@ -7,6 +7,7 @@ */ #include <linux/pci.h> +#include <linux/sysfs.h> #include "processor_thermal_device.h" /* List of workload types */ @@ -28,9 +29,9 @@ static ssize_t workload_available_types_show(struct device *dev, int ret = 0; while (workload_types[i] != NULL) - ret += sprintf(&buf[ret], "%s ", workload_types[i++]); + ret += sysfs_emit_at(buf, ret, "%s ", workload_types[i++]); - ret += sprintf(&buf[ret], "\n"); + ret += sysfs_emit_at(buf, ret, "\n"); return ret; } @@ -85,7 +86,7 @@ static ssize_t workload_type_show(struct device *dev, if (cmd_resp > ARRAY_SIZE(workload_types) - 1) return -EINVAL; - return sprintf(buf, "%s\n", workload_types[cmd_resp]); + return sysfs_emit(buf, "%s\n", workload_types[cmd_resp]); } static DEVICE_ATTR_RW(workload_type); diff --git a/drivers/thermal/intel/intel_pch_thermal.c b/drivers/thermal/intel/intel_pch_thermal.c index fc326985796c..52e71af67dc6 100644 --- a/drivers/thermal/intel/intel_pch_thermal.c +++ b/drivers/thermal/intel/intel_pch_thermal.c @@ -269,7 +269,6 @@ static void intel_pch_thermal_remove(struct pci_dev *pdev) thermal_zone_device_unregister(ptd->tzd); iounmap(ptd->hw_base); - pci_set_drvdata(pdev, NULL); pci_release_regions(pdev); pci_disable_device(pdev); } diff --git a/drivers/thermal/intel/intel_tcc.c b/drivers/thermal/intel/intel_tcc.c index b2a615aea7c1..ab61fb122937 100644 --- a/drivers/thermal/intel/intel_tcc.c +++ b/drivers/thermal/intel/intel_tcc.c @@ -172,7 +172,7 @@ static u32 get_temp_mask(bool pkg) /** * intel_tcc_get_tjmax() - returns the default TCC activation Temperature - * @cpu: cpu that the MSR should be run on, nagative value means any cpu. + * @cpu: cpu that the MSR should be run on, negative value means any cpu. * * Get the TjMax value, which is the default thermal throttling or TCC * activation temperature in degrees C. @@ -199,7 +199,7 @@ EXPORT_SYMBOL_NS_GPL(intel_tcc_get_tjmax, "INTEL_TCC"); /** * intel_tcc_get_offset() - returns the TCC Offset value to Tjmax - * @cpu: cpu that the MSR should be run on, nagative value means any cpu. + * @cpu: cpu that the MSR should be run on, negative value means any cpu. * * Get the TCC offset value to Tjmax. The effective thermal throttling or TCC * activation temperature equals "Tjmax" - "TCC Offset", in degrees C. @@ -224,7 +224,7 @@ EXPORT_SYMBOL_NS_GPL(intel_tcc_get_offset, "INTEL_TCC"); /** * intel_tcc_set_offset() - set the TCC offset value to Tjmax - * @cpu: cpu that the MSR should be run on, nagative value means any cpu. + * @cpu: cpu that the MSR should be run on, negative value means any cpu. * @offset: TCC offset value in degree C * * Set the TCC Offset value to Tjmax. The effective thermal throttling or TCC @@ -267,7 +267,7 @@ EXPORT_SYMBOL_NS_GPL(intel_tcc_set_offset, "INTEL_TCC"); /** * intel_tcc_get_temp() - returns the current temperature - * @cpu: cpu that the MSR should be run on, nagative value means any cpu. + * @cpu: cpu that the MSR should be run on, negative value means any cpu. * @temp: pointer to the memory for saving cpu temperature. * @pkg: true: Package Thermal Sensor. false: Core Thermal Sensor. * diff --git a/drivers/thermal/intel/intel_tcc_cooling.c b/drivers/thermal/intel/intel_tcc_cooling.c index f352ecafbedf..6c2ba0ba3178 100644 --- a/drivers/thermal/intel/intel_tcc_cooling.c +++ b/drivers/thermal/intel/intel_tcc_cooling.c @@ -65,6 +65,10 @@ static const struct x86_cpu_id tcc_ids[] __initconst = { X86_MATCH_VFM(INTEL_RAPTORLAKE, NULL), X86_MATCH_VFM(INTEL_RAPTORLAKE_P, NULL), X86_MATCH_VFM(INTEL_RAPTORLAKE_S, NULL), + X86_MATCH_VFM(INTEL_PANTHERLAKE_L, NULL), + X86_MATCH_VFM(INTEL_WILDCATLAKE_L, NULL), + X86_MATCH_VFM(INTEL_NOVALAKE, NULL), + X86_MATCH_VFM(INTEL_NOVALAKE_L, NULL), {} }; @@ -72,10 +76,8 @@ MODULE_DEVICE_TABLE(x86cpu, tcc_ids); static int __init tcc_cooling_init(void) { - int ret; u64 val; const struct x86_cpu_id *id; - int err; id = x86_match_cpu(tcc_ids); @@ -103,10 +105,9 @@ static int __init tcc_cooling_init(void) tcc_cdev = thermal_cooling_device_register("TCC Offset", NULL, &tcc_cooling_ops); - if (IS_ERR(tcc_cdev)) { - ret = PTR_ERR(tcc_cdev); - return ret; - } + if (IS_ERR(tcc_cdev)) + return PTR_ERR(tcc_cdev); + return 0; } diff --git a/drivers/thermal/intel/therm_throt.c b/drivers/thermal/intel/therm_throt.c index debc94e2dc16..44fa4dd15dd1 100644 --- a/drivers/thermal/intel/therm_throt.c +++ b/drivers/thermal/intel/therm_throt.c @@ -23,6 +23,7 @@ #include <linux/types.h> #include <linux/init.h> #include <linux/smp.h> +#include <linux/sysfs.h> #include <linux/cpu.h> #include <asm/processor.h> @@ -144,8 +145,8 @@ static ssize_t therm_throt_device_show_##event##_##name( \ \ preempt_disable(); /* CPU hotplug */ \ if (cpu_online(cpu)) { \ - ret = sprintf(buf, "%lu\n", \ - per_cpu(thermal_state, cpu).event.name); \ + ret = sysfs_emit(buf, "%lu\n", \ + per_cpu(thermal_state, cpu).event.name); \ } else \ ret = 0; \ preempt_enable(); \ diff --git a/drivers/thermal/intel/x86_pkg_temp_thermal.c b/drivers/thermal/intel/x86_pkg_temp_thermal.c index 3fc679b6f11b..aab5f9fca9c3 100644 --- a/drivers/thermal/intel/x86_pkg_temp_thermal.c +++ b/drivers/thermal/intel/x86_pkg_temp_thermal.c @@ -128,6 +128,9 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, u32 l, h, mask, shift, intr; int tj_max, val, ret; + if (temp == THERMAL_TEMP_INVALID) + temp = 0; + tj_max = intel_tcc_get_tjmax(zonedev->cpu); if (tj_max < 0) return tj_max; diff --git a/tools/testing/selftests/thermal/intel/workload_hint/workload_hint_test.c b/tools/testing/selftests/thermal/intel/workload_hint/workload_hint_test.c index ca2bd03154e4..569d44f22835 100644 --- a/tools/testing/selftests/thermal/intel/workload_hint/workload_hint_test.c +++ b/tools/testing/selftests/thermal/intel/workload_hint/workload_hint_test.c @@ -12,6 +12,7 @@ #define WORKLOAD_NOTIFICATION_DELAY_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/notification_delay_ms" #define WORKLOAD_ENABLE_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/workload_hint_enable" +#define WORKLOAD_SLOW_ENABLE_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/workload_slow_hint_enable" #define WORKLOAD_TYPE_INDEX_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/workload_type_index" static const char * const workload_types[] = { @@ -22,6 +23,9 @@ static const char * const workload_types[] = { NULL }; +static int wlt_slow; +static char *wlt_enable_attr; + #define WORKLOAD_TYPE_MAX_INDEX 3 void workload_hint_exit(int signum) @@ -30,7 +34,7 @@ void workload_hint_exit(int signum) /* Disable feature via sysfs knob */ - fd = open(WORKLOAD_ENABLE_ATTRIBUTE, O_RDWR); + fd = open(wlt_enable_attr, O_RDWR); if (fd < 0) { perror("Unable to open workload type feature enable file"); exit(1); @@ -46,6 +50,26 @@ void workload_hint_exit(int signum) close(fd); } +static void update_delay(char *delay_str) +{ + int fd; + + printf("Setting notification delay in ms to %s\n", delay_str); + + fd = open(WORKLOAD_NOTIFICATION_DELAY_ATTRIBUTE, O_RDWR); + if (fd < 0) { + perror("Unable to open workload notification delay"); + exit(1); + } + + if (write(fd, delay_str, strlen(delay_str)) < 0) { + perror("Can't set delay"); + exit(1); + } + + close(fd); +} + int main(int argc, char **argv) { struct pollfd ufd; @@ -54,32 +78,26 @@ int main(int argc, char **argv) char delay_str[64]; int delay = 0; - printf("Usage: workload_hint_test [notification delay in milli seconds]\n"); + printf("Usage: workload_hint_test [notification delay in milli seconds][slow]\n"); if (argc > 1) { - ret = sscanf(argv[1], "%d", &delay); - if (ret < 0) { - printf("Invalid delay\n"); - exit(1); - } + int i; - printf("Setting notification delay to %d ms\n", delay); - if (delay < 0) - exit(1); + for (i = 1; i < argc; ++i) { + if (!strcmp(argv[i], "slow")) { + wlt_slow = 1; + continue; + } - sprintf(delay_str, "%s\n", argv[1]); - fd = open(WORKLOAD_NOTIFICATION_DELAY_ATTRIBUTE, O_RDWR); - if (fd < 0) { - perror("Unable to open workload notification delay"); - exit(1); - } + ret = sscanf(argv[1], "%d", &delay); + if (ret < 0) { + printf("Invalid delay\n"); + exit(1); + } - if (write(fd, delay_str, strlen(delay_str)) < 0) { - perror("Can't set delay"); - exit(1); + sprintf(delay_str, "%s\n", argv[1]); + update_delay(delay_str); } - - close(fd); } if (signal(SIGINT, workload_hint_exit) == SIG_IGN) @@ -89,8 +107,13 @@ int main(int argc, char **argv) if (signal(SIGTERM, workload_hint_exit) == SIG_IGN) signal(SIGTERM, SIG_IGN); + if (wlt_slow) + wlt_enable_attr = WORKLOAD_SLOW_ENABLE_ATTRIBUTE; + else + wlt_enable_attr = WORKLOAD_ENABLE_ATTRIBUTE; + /* Enable feature via sysfs knob */ - fd = open(WORKLOAD_ENABLE_ATTRIBUTE, O_RDWR); + fd = open(wlt_enable_attr, O_RDWR); if (fd < 0) { perror("Unable to open workload type feature enable file"); exit(1); @@ -145,6 +168,13 @@ int main(int argc, char **argv) if (ret < 0) break; + if (wlt_slow) { + if (index & 0x10) + printf("workload type slow:%s\n", "power"); + else + printf("workload type slow:%s\n", "performance"); + } + index &= 0x0f; if (index > WORKLOAD_TYPE_MAX_INDEX) printf("Invalid workload type index\n"); |
