From b894685cb8e09305b3cb82bc39f2c4a3d154ce3a Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 28 Aug 2023 17:23:40 -0700 Subject: [PATCH 001/111] thermal: int340x: processor_thermal: Move mailbox code to common module The processor thermal mailbox is used for workload type request and also in the processor thermal RFIM module. So, move the workload type request code to its own module from the current processor thermal mailbox module. processor_thermal_mailbox.c contains only mailbox read/write related source code. The source related to workload_types requests is moved to a module processor_thermal_wt_req.c. In addition - Rename PROC_THERMAL_FEATURE_MBOX to PROC_THERMAL_FEATURE_WT_REQ. - proc_thermal_mbox_add(), which adds workload type sysfs attribute group is renamed to proc_thermal_wt_req_add(). - proc_thermal_mbox_remove() is renamed to proc_thermal_wt_req_remove(). While here, resolve check patch warnings for 100 columns for only modified lines. No functional changes are expected. Signed-off-by: Srinivas Pandruvada Reviewed-by: Zhang Rui Signed-off-by: Rafael J. Wysocki --- .../thermal/intel/int340x_thermal/Makefile | 1 + .../processor_thermal_device.c | 8 +- .../processor_thermal_device.h | 12 +- .../processor_thermal_device_pci.c | 10 +- .../processor_thermal_device_pci_legacy.c | 3 +- .../int340x_thermal/processor_thermal_mbox.c | 130 ----------------- .../processor_thermal_wt_req.c | 136 ++++++++++++++++++ 7 files changed, 159 insertions(+), 141 deletions(-) create mode 100644 drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c diff --git a/drivers/thermal/intel/int340x_thermal/Makefile b/drivers/thermal/intel/int340x_thermal/Makefile index 4e852ce4a5d5..7e40aebb0556 100644 --- a/drivers/thermal/intel/int340x_thermal/Makefile +++ b/drivers/thermal/intel/int340x_thermal/Makefile @@ -10,5 +10,6 @@ obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device_pci.o obj-$(CONFIG_PROC_THERMAL_MMIO_RAPL) += processor_thermal_rapl.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_rfim.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_mbox.o +obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_wt_req.o obj-$(CONFIG_INT3406_THERMAL) += int3406_thermal.o obj-$(CONFIG_ACPI_THERMAL_REL) += acpi_thermal_rel.o diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c index 3ca0a2f5937f..3f0eac6cb4da 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c @@ -346,8 +346,8 @@ int proc_thermal_mmio_add(struct pci_dev *pdev, } } - if (feature_mask & PROC_THERMAL_FEATURE_MBOX) { - ret = proc_thermal_mbox_add(pdev, proc_priv); + if (feature_mask & PROC_THERMAL_FEATURE_WT_REQ) { + ret = proc_thermal_wt_req_add(pdev, proc_priv); if (ret) { dev_err(&pdev->dev, "failed to add MBOX interface\n"); goto err_rem_rfim; @@ -374,8 +374,8 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device * proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS) proc_thermal_rfim_remove(pdev); - if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_MBOX) - proc_thermal_mbox_remove(pdev); + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_REQ) + proc_thermal_wt_req_remove(pdev); } EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove); diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h index 7acaa8f1b896..bae6e3e4e22e 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h @@ -59,7 +59,7 @@ struct rapl_mmio_regs { #define PROC_THERMAL_FEATURE_RAPL 0x01 #define PROC_THERMAL_FEATURE_FIVR 0x02 #define PROC_THERMAL_FEATURE_DVFS 0x04 -#define PROC_THERMAL_FEATURE_MBOX 0x08 +#define PROC_THERMAL_FEATURE_WT_REQ 0x08 #define PROC_THERMAL_FEATURE_DLVR 0x10 #if IS_ENABLED(CONFIG_PROC_THERMAL_MMIO_RAPL) @@ -80,8 +80,14 @@ static void __maybe_unused proc_thermal_rapl_remove(void) int proc_thermal_rfim_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); void proc_thermal_rfim_remove(struct pci_dev *pdev); -int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); -void proc_thermal_mbox_remove(struct pci_dev *pdev); +int proc_thermal_wt_req_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); +void proc_thermal_wt_req_remove(struct pci_dev *pdev); + +#define MBOX_CMD_WORKLOAD_TYPE_READ 0x0E +#define MBOX_CMD_WORKLOAD_TYPE_WRITE 0x0F + +#define MBOX_DATA_BIT_AC_DC 30 +#define MBOX_DATA_BIT_VALID 31 int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp); int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data); 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 0d1e98007270..314a726f35c7 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -350,9 +350,13 @@ static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend, proc_thermal_pci_resume); static const struct pci_device_id proc_thermal_pci_ids[] = { - { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, - { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX | PROC_THERMAL_FEATURE_DLVR) }, - { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, + { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | + PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, + { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | + PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ | + PROC_THERMAL_FEATURE_DLVR) }, + { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | + PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, { }, }; diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c index 16fd9df5f36d..ccfdd2f9d973 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c @@ -137,7 +137,8 @@ static const struct pci_device_id proc_thermal_pci_ids[] = { { PCI_DEVICE_DATA(INTEL, ICL_THERMAL, PROC_THERMAL_FEATURE_RAPL) }, { PCI_DEVICE_DATA(INTEL, JSL_THERMAL, 0) }, { PCI_DEVICE_DATA(INTEL, SKL_THERMAL, PROC_THERMAL_FEATURE_RAPL) }, - { PCI_DEVICE_DATA(INTEL, TGL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_MBOX) }, + { PCI_DEVICE_DATA(INTEL, TGL_THERMAL, PROC_THERMAL_FEATURE_RAPL | + PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_WT_REQ) }, { }, }; diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c index 0b89a4340ff4..ec766c5615b7 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c @@ -10,18 +10,12 @@ #include #include "processor_thermal_device.h" -#define MBOX_CMD_WORKLOAD_TYPE_READ 0x0E -#define MBOX_CMD_WORKLOAD_TYPE_WRITE 0x0F - #define MBOX_OFFSET_DATA 0x5810 #define MBOX_OFFSET_INTERFACE 0x5818 #define MBOX_BUSY_BIT 31 #define MBOX_RETRY_COUNT 100 -#define MBOX_DATA_BIT_VALID 31 -#define MBOX_DATA_BIT_AC_DC 30 - static DEFINE_MUTEX(mbox_lock); static int wait_for_mbox_ready(struct proc_thermal_device *proc_priv) @@ -114,128 +108,4 @@ int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data } EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_write_cmd, INT340X_THERMAL); -/* List of workload types */ -static const char * const workload_types[] = { - "none", - "idle", - "semi_active", - "bursty", - "sustained", - "battery_life", - NULL -}; - -static ssize_t workload_available_types_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int i = 0; - int ret = 0; - - while (workload_types[i] != NULL) - ret += sprintf(&buf[ret], "%s ", workload_types[i++]); - - ret += sprintf(&buf[ret], "\n"); - - return ret; -} - -static DEVICE_ATTR_RO(workload_available_types); - -static ssize_t workload_type_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct pci_dev *pdev = to_pci_dev(dev); - char str_preference[15]; - u32 data = 0; - ssize_t ret; - - ret = sscanf(buf, "%14s", str_preference); - if (ret != 1) - return -EINVAL; - - ret = match_string(workload_types, -1, str_preference); - if (ret < 0) - return ret; - - ret &= 0xff; - - if (ret) - data = BIT(MBOX_DATA_BIT_VALID) | BIT(MBOX_DATA_BIT_AC_DC); - - data |= ret; - - ret = send_mbox_write_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_WRITE, data); - if (ret) - return false; - - return count; -} - -static ssize_t workload_type_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct pci_dev *pdev = to_pci_dev(dev); - u64 cmd_resp; - int ret; - - ret = send_mbox_read_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, &cmd_resp); - if (ret) - return false; - - cmd_resp &= 0xff; - - if (cmd_resp > ARRAY_SIZE(workload_types) - 1) - return -EINVAL; - - return sprintf(buf, "%s\n", workload_types[cmd_resp]); -} - -static DEVICE_ATTR_RW(workload_type); - -static struct attribute *workload_req_attrs[] = { - &dev_attr_workload_available_types.attr, - &dev_attr_workload_type.attr, - NULL -}; - -static const struct attribute_group workload_req_attribute_group = { - .attrs = workload_req_attrs, - .name = "workload_request" -}; - -static bool workload_req_created; - -int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) -{ - u64 cmd_resp; - int ret; - - /* Check if there is a mailbox support, if fails return success */ - ret = send_mbox_read_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, &cmd_resp); - if (ret) - return 0; - - ret = sysfs_create_group(&pdev->dev.kobj, &workload_req_attribute_group); - if (ret) - return ret; - - workload_req_created = true; - - return 0; -} -EXPORT_SYMBOL_GPL(proc_thermal_mbox_add); - -void proc_thermal_mbox_remove(struct pci_dev *pdev) -{ - if (workload_req_created) - sysfs_remove_group(&pdev->dev.kobj, &workload_req_attribute_group); - - workload_req_created = false; - -} -EXPORT_SYMBOL_GPL(proc_thermal_mbox_remove); - MODULE_LICENSE("GPL v2"); diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c new file mode 100644 index 000000000000..711c4f761c9a --- /dev/null +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * processor thermal device for Workload type hints + * update from user space + * + * Copyright (c) 2020-2023, Intel Corporation. + */ + +#include +#include "processor_thermal_device.h" + +/* List of workload types */ +static const char * const workload_types[] = { + "none", + "idle", + "semi_active", + "bursty", + "sustained", + "battery_life", + NULL +}; + +static ssize_t workload_available_types_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int i = 0; + int ret = 0; + + while (workload_types[i] != NULL) + ret += sprintf(&buf[ret], "%s ", workload_types[i++]); + + ret += sprintf(&buf[ret], "\n"); + + return ret; +} + +static DEVICE_ATTR_RO(workload_available_types); + +static ssize_t workload_type_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct pci_dev *pdev = to_pci_dev(dev); + char str_preference[15]; + u32 data = 0; + ssize_t ret; + + ret = sscanf(buf, "%14s", str_preference); + if (ret != 1) + return -EINVAL; + + ret = match_string(workload_types, -1, str_preference); + if (ret < 0) + return ret; + + ret &= 0xff; + + if (ret) + data = BIT(MBOX_DATA_BIT_VALID) | BIT(MBOX_DATA_BIT_AC_DC); + + data |= ret; + + ret = processor_thermal_send_mbox_write_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_WRITE, data); + if (ret) + return false; + + return count; +} + +static ssize_t workload_type_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct pci_dev *pdev = to_pci_dev(dev); + u64 cmd_resp; + int ret; + + ret = processor_thermal_send_mbox_read_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, &cmd_resp); + if (ret) + return false; + + cmd_resp &= 0xff; + + if (cmd_resp > ARRAY_SIZE(workload_types) - 1) + return -EINVAL; + + return sprintf(buf, "%s\n", workload_types[cmd_resp]); +} + +static DEVICE_ATTR_RW(workload_type); + +static struct attribute *workload_req_attrs[] = { + &dev_attr_workload_available_types.attr, + &dev_attr_workload_type.attr, + NULL +}; + +static const struct attribute_group workload_req_attribute_group = { + .attrs = workload_req_attrs, + .name = "workload_request" +}; + +static bool workload_req_created; + +int proc_thermal_wt_req_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) +{ + u64 cmd_resp; + int ret; + + /* Check if there is a mailbox support, if fails return success */ + ret = processor_thermal_send_mbox_read_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, &cmd_resp); + if (ret) + return 0; + + ret = sysfs_create_group(&pdev->dev.kobj, &workload_req_attribute_group); + if (ret) + return ret; + + workload_req_created = true; + + return 0; +} +EXPORT_SYMBOL_GPL(proc_thermal_wt_req_add); + +void proc_thermal_wt_req_remove(struct pci_dev *pdev) +{ + if (workload_req_created) + sysfs_remove_group(&pdev->dev.kobj, &workload_req_attribute_group); + + workload_req_created = false; +} +EXPORT_SYMBOL_GPL(proc_thermal_wt_req_remove); + +MODULE_IMPORT_NS(INT340X_THERMAL); +MODULE_LICENSE("GPL"); From dd28a3cb92389deb2d5a0ab3e91b97007c8bc366 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 28 Aug 2023 17:23:41 -0700 Subject: [PATCH 002/111] thermal: int340x: processor_thermal: Add interrupt configuration function Some features like workload type prediction and power floor events require interrupt support to avoid polling. Here interrupts are enabled and disabled via sending mailbox commands. The mailbox command ID is 0x1E for read and 0x1F for write. The interrupt configuration will require mutex protection as it involves read-modify-write operation. Since mutex are already used in the mailbox read/write functions: send_mbox_write_cmd() and send_mbox_read_cmd(), there will be double locking. But, this can be avoided by moving mutexes from mailbox read/write processing functions to the callers: processor_thermal_send_mbox_[read|write]_cmd(). Signed-off-by: Srinivas Pandruvada [ rjw: Adjust subject, fix up computation ] Signed-off-by: Rafael J. Wysocki --- .../processor_thermal_device.h | 2 + .../int340x_thermal/processor_thermal_mbox.c | 85 ++++++++++++++----- 2 files changed, 68 insertions(+), 19 deletions(-) diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h index bae6e3e4e22e..0e7725829c24 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h @@ -91,6 +91,8 @@ void proc_thermal_wt_req_remove(struct pci_dev *pdev); int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp); int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data); +int processor_thermal_mbox_interrupt_config(struct pci_dev *pdev, bool enable, int enable_bit, + int time_window); int proc_thermal_add(struct device *dev, struct proc_thermal_device *priv); void proc_thermal_remove(struct proc_thermal_device *proc_priv); int proc_thermal_suspend(struct device *dev); diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c index ec766c5615b7..4d3bd32ff9ea 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c @@ -45,23 +45,16 @@ static int send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data) int ret; proc_priv = pci_get_drvdata(pdev); - - mutex_lock(&mbox_lock); - ret = wait_for_mbox_ready(proc_priv); if (ret) - goto unlock_mbox; + return ret; writel(data, (proc_priv->mmio_base + MBOX_OFFSET_DATA)); /* Write command register */ reg_data = BIT_ULL(MBOX_BUSY_BIT) | id; writel(reg_data, (proc_priv->mmio_base + MBOX_OFFSET_INTERFACE)); - ret = wait_for_mbox_ready(proc_priv); - -unlock_mbox: - mutex_unlock(&mbox_lock); - return ret; + return wait_for_mbox_ready(proc_priv); } static int send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp) @@ -71,12 +64,9 @@ static int send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp) int ret; proc_priv = pci_get_drvdata(pdev); - - mutex_lock(&mbox_lock); - ret = wait_for_mbox_ready(proc_priv); if (ret) - goto unlock_mbox; + return ret; /* Write command register */ reg_data = BIT_ULL(MBOX_BUSY_BIT) | id; @@ -84,28 +74,85 @@ static int send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp) ret = wait_for_mbox_ready(proc_priv); if (ret) - goto unlock_mbox; + return ret; if (id == MBOX_CMD_WORKLOAD_TYPE_READ) *resp = readl(proc_priv->mmio_base + MBOX_OFFSET_DATA); else *resp = readq(proc_priv->mmio_base + MBOX_OFFSET_DATA); -unlock_mbox: - mutex_unlock(&mbox_lock); - return ret; + return 0; } int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp) { - return send_mbox_read_cmd(pdev, id, resp); + int ret; + + mutex_lock(&mbox_lock); + ret = send_mbox_read_cmd(pdev, id, resp); + mutex_unlock(&mbox_lock); + + return ret; } EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_read_cmd, INT340X_THERMAL); int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data) { - return send_mbox_write_cmd(pdev, id, data); + int ret; + + mutex_lock(&mbox_lock); + ret = send_mbox_write_cmd(pdev, id, data); + mutex_unlock(&mbox_lock); + + return ret; } EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_write_cmd, INT340X_THERMAL); +#define MBOX_CAMARILLO_RD_INTR_CONFIG 0x1E +#define MBOX_CAMARILLO_WR_INTR_CONFIG 0x1F +#define WLT_TW_MASK GENMASK_ULL(30, 24) +#define SOC_PREDICTION_TW_SHIFT 24 + +int processor_thermal_mbox_interrupt_config(struct pci_dev *pdev, bool enable, + int enable_bit, int time_window) +{ + u64 data; + int ret; + + if (!pdev) + return -ENODEV; + + mutex_lock(&mbox_lock); + + /* Do read modify write for MBOX_CAMARILLO_RD_INTR_CONFIG */ + + ret = send_mbox_read_cmd(pdev, MBOX_CAMARILLO_RD_INTR_CONFIG, &data); + if (ret) { + dev_err(&pdev->dev, "MBOX_CAMARILLO_RD_INTR_CONFIG failed\n"); + goto unlock; + } + + if (time_window >= 0) { + data &= ~WLT_TW_MASK; + + /* Program notification delay */ + data |= ((u64)time_window << SOC_PREDICTION_TW_SHIFT) & WLT_TW_MASK; + } + + if (enable) + data |= BIT(enable_bit); + else + data &= ~BIT(enable_bit); + + ret = send_mbox_write_cmd(pdev, MBOX_CAMARILLO_WR_INTR_CONFIG, data); + if (ret) + dev_err(&pdev->dev, "MBOX_CAMARILLO_WR_INTR_CONFIG failed\n"); + +unlock: + mutex_unlock(&mbox_lock); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(processor_thermal_mbox_interrupt_config, INT340X_THERMAL); + MODULE_LICENSE("GPL v2"); From f0658708e8636f64458fe69e0037700ab57124e1 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 28 Aug 2023 17:23:42 -0700 Subject: [PATCH 003/111] thermal: int340x: processor_thermal: Use non MSI interrupts by default There are issues in using MSI interrupts for processor thermal device. The support is not consistent across generations. But the legacy PCI interrupts work on all current generations. Hence always use legacy PCI interrupts by default, instead of MSI. Add a module param to use of MSI, so that MSI can be still used. Signed-off-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- .../processor_thermal_device_pci.c | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) 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 314a726f35c7..f736688abe9b 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -15,6 +15,11 @@ #define DRV_NAME "proc_thermal_pci" +static bool use_msi; +module_param(use_msi, bool, 0644); +MODULE_PARM_DESC(use_msi, + "Use PCI MSI based interrupts for processor thermal device."); + struct proc_thermal_pci { struct pci_dev *pdev; struct proc_thermal_device *proc_priv; @@ -203,6 +208,7 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ struct proc_thermal_device *proc_priv; struct proc_thermal_pci *pci_info; int irq_flag = 0, irq, ret; + bool msi_irq = false; proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL); if (!proc_priv) @@ -248,16 +254,21 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ goto err_ret_mmio; } - /* request and enable interrupt */ - ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to allocate vectors!\n"); - goto err_ret_tzone; - } - if (!pdev->msi_enabled && !pdev->msix_enabled) - irq_flag = IRQF_SHARED; + if (use_msi && (pdev->msi_enabled || pdev->msix_enabled)) { + /* request and enable interrupt */ + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to allocate vectors!\n"); + goto err_ret_tzone; + } + + irq = pci_irq_vector(pdev, 0); + msi_irq = true; + } else { + irq_flag = IRQF_SHARED; + irq = pdev->irq; + } - irq = pci_irq_vector(pdev, 0); ret = devm_request_threaded_irq(&pdev->dev, irq, proc_thermal_irq_handler, NULL, irq_flag, KBUILD_MODNAME, pci_info); @@ -273,7 +284,8 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ return 0; err_free_vectors: - pci_free_irq_vectors(pdev); + if (msi_irq) + pci_free_irq_vectors(pdev); err_ret_tzone: thermal_zone_device_unregister(pci_info->tzone); err_ret_mmio: From 2f0b31c02662962b9e51d2a07661089ffddf6bbe Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 28 Aug 2023 17:23:43 -0700 Subject: [PATCH 004/111] thermal: int340x: Remove PROC_THERMAL_FEATURE_WLT_REQ for Meteor Lake Meteor Lake processor supports firmware hints for predicting workload type. So, remove support for passing workload hints to the firmware. Signed-off-by: Srinivas Pandruvada Reviewed-by: Zhang Rui [ rjw: Subject adjustment ] Signed-off-by: Rafael J. Wysocki --- .../intel/int340x_thermal/processor_thermal_device_pci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 f736688abe9b..db30c11fd1f7 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -365,8 +365,7 @@ static const struct pci_device_id proc_thermal_pci_ids[] = { { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | - PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ | - PROC_THERMAL_FEATURE_DLVR) }, + PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR) }, { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, { }, From 4b029a81c24e6b249022bab37fa0b61bfcb5c242 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 28 Aug 2023 17:23:44 -0700 Subject: [PATCH 005/111] thermal: int340x: processor_thermal: Add workload type hint interface Prior to Meteor Lake processor generation, user space can pass workload type request to the firmware. Then firmware can optimize power based on the indicated workload type. User space also uses workload type requests to implement its own heuristics. The firmware in Meteor Lake processor generation is capable of predicting workload type without software help. To avoid duplicate processing, add a sysfs interface allowing user space to obtain the workload hint from the firmware instead of trying to predict the workload type by itself. This workload hint is passed from the firmware via MMIO offset 0x5B18 of the processor thermal PCI device. Before workload hints can be produced by the firmware, it needs to be configured via a mailbox command. This mailbox command turns ON the workload hint and it allows to program a notification delay to control the rate of notifications. The notification delay can be changed from user space vis sysfs. Attribute group 'workload_hint' in sysfs is used for implementing the workload hints interface between user space and the kernel. It contains the following attributes: workload_type_enable: Enables/disables workload type hints from the firmware. notification_delay_ms: Notification delay in milliseconds. workload_type_index: The current workload type index predicted by the firmware (see the documentation changes below for supported index values and their meaning). Signed-off-by: Srinivas Pandruvada [ rjw: Changelog edits, documentation edits, whitespace adjustments ] Signed-off-by: Rafael J. Wysocki --- .../driver-api/thermal/intel_dptf.rst | 54 ++++ .../thermal/intel/int340x_thermal/Makefile | 1 + .../processor_thermal_device.c | 9 + .../processor_thermal_device.h | 7 + .../processor_thermal_device_pci.c | 3 +- .../processor_thermal_wt_hint.c | 258 ++++++++++++++++++ 6 files changed, 331 insertions(+), 1 deletion(-) create mode 100644 drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c diff --git a/Documentation/driver-api/thermal/intel_dptf.rst b/Documentation/driver-api/thermal/intel_dptf.rst index 9ab4316322a1..2d11e74ac665 100644 --- a/Documentation/driver-api/thermal/intel_dptf.rst +++ b/Documentation/driver-api/thermal/intel_dptf.rst @@ -315,3 +315,57 @@ DPTF Fan Control ---------------------------------------- Refer to Documentation/admin-guide/acpi/fan_performance_states.rst + +Workload Type Hints +---------------------------------------- + +The firmware in Meteor Lake processor generation is capable of identifying +workload type and passing hints regarding it to the OS. A special sysfs +interface is provided to allow user space to obtain workload type hints from +the firmware and control the rate at which they are provided. + +User space can poll attribute "workload_type_index" for the current hint or +can receive a notification whenever the value of this attribute is updated. + +file:`/sys/bus/pci/devices/0000:00:04.0/workload_hint/` +Segment 0, bus 0, device 4, function 0 is reserved for the processor thermal +device on all Intel client processors. So, the above path doesn't change +based on the processor generation. + +``workload_hint_enable`` (RW) + Enable firmware to send 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 + the workload type prediction in the firmware and notifying the OS about + the change. The default delay is 1024 ms. The delay of 0 is invalid. + The delay is rounded up to the nearest power of 2 to simplify firmware + programming of the delay value. The read of notification_delay_ms + attribute shows the effective value used. + +``workload_type_index`` (RO) + Predicted workload type index. User space can get notification of + change via existing sysfs attribute change notification mechanism. + + The supported index values and their meaning for the Meteor Lake + processor generation are as follows: + + 0 - Idle: System performs no tasks, power and idle residency are + consistently low for long periods of time. + + 1 – Battery Life: Power is relatively low, but the processor may + still be actively performing a task, such as video playback for + a long period of time. + + 2 – Sustained: Power level that is relatively high for a long period + of time, with very few to no periods of idleness, which will + eventually exhaust RAPL Power Limit 1 and 2. + + 3 – Bursty: Consumes a relatively constant average amount of power, but + periods of relative idleness are interrupted by bursts of + activity. The bursts are relatively short and the periods of + relative idleness between them typically prevent RAPL Power + Limit 1 from being exhausted. + + 4 – Unknown: Can't classify. diff --git a/drivers/thermal/intel/int340x_thermal/Makefile b/drivers/thermal/intel/int340x_thermal/Makefile index 7e40aebb0556..f33a3ad3bef3 100644 --- a/drivers/thermal/intel/int340x_thermal/Makefile +++ b/drivers/thermal/intel/int340x_thermal/Makefile @@ -11,5 +11,6 @@ obj-$(CONFIG_PROC_THERMAL_MMIO_RAPL) += processor_thermal_rapl.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_rfim.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_mbox.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_wt_req.o +obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_wt_hint.o obj-$(CONFIG_INT3406_THERMAL) += int3406_thermal.o obj-$(CONFIG_ACPI_THERMAL_REL) += acpi_thermal_rel.o diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c index 3f0eac6cb4da..29ed7d0f7022 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c @@ -352,6 +352,12 @@ int proc_thermal_mmio_add(struct pci_dev *pdev, dev_err(&pdev->dev, "failed to add MBOX interface\n"); goto err_rem_rfim; } + } else if (feature_mask & PROC_THERMAL_FEATURE_WT_HINT) { + ret = proc_thermal_wt_hint_add(pdev, proc_priv); + if (ret) { + dev_err(&pdev->dev, "failed to add WT Hint\n"); + goto err_rem_rfim; + } } return 0; @@ -376,10 +382,13 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device * if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_REQ) proc_thermal_wt_req_remove(pdev); + else if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT) + proc_thermal_wt_hint_remove(pdev); } EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove); MODULE_IMPORT_NS(INTEL_TCC); +MODULE_IMPORT_NS(INT340X_THERMAL); MODULE_AUTHOR("Srinivas Pandruvada "); MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h index 0e7725829c24..b974583c5c11 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h @@ -61,6 +61,7 @@ struct rapl_mmio_regs { #define PROC_THERMAL_FEATURE_DVFS 0x04 #define PROC_THERMAL_FEATURE_WT_REQ 0x08 #define PROC_THERMAL_FEATURE_DLVR 0x10 +#define PROC_THERMAL_FEATURE_WT_HINT 0x20 #if IS_ENABLED(CONFIG_PROC_THERMAL_MMIO_RAPL) int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); @@ -95,6 +96,12 @@ int processor_thermal_mbox_interrupt_config(struct pci_dev *pdev, bool enable, i int time_window); int proc_thermal_add(struct device *dev, struct proc_thermal_device *priv); void proc_thermal_remove(struct proc_thermal_device *proc_priv); + +int proc_thermal_wt_hint_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); +void proc_thermal_wt_hint_remove(struct pci_dev *pdev); +void proc_thermal_wt_intr_callback(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); +bool proc_thermal_check_wt_intr(struct proc_thermal_device *proc_priv); + int proc_thermal_suspend(struct device *dev); int proc_thermal_resume(struct device *dev); int proc_thermal_mmio_add(struct pci_dev *pdev, 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 db30c11fd1f7..eed59630fe59 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -365,7 +365,8 @@ static const struct pci_device_id proc_thermal_pci_ids[] = { { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | - PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR) }, + PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | + PROC_THERMAL_FEATURE_WT_HINT) }, { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, { }, diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c new file mode 100644 index 000000000000..fabd8a363abb --- /dev/null +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * processor thermal device interface for reading workload type hints + * from the user space. The hints are provided by the firmware. + * + * Operation: + * When user space enables workload type prediction: + * - Use mailbox to: + * Configure notification delay + * Enable processor thermal device interrupt + * + * - The predicted workload type can be read from MMIO: + * Offset 0x5B18 shows if there was an interrupt + * active for change in workload type and also + * predicted workload type. + * + * Two interface functions are provided to call when there is a + * thermal device interrupt: + * - proc_thermal_check_wt_intr(): + * Check if the interrupt is for change in workload type. Called from + * interrupt context. + * + * - proc_thermal_wt_intr_callback(): + * Callback for interrupt processing in thread context. This involves + * sending notification to user space that there is a change in the + * workload type. + * + * Copyright (c) 2023, Intel Corporation. + */ + +#include +#include +#include "processor_thermal_device.h" + +#define SOC_WT_RES_INT_STATUS_OFFSET 0x5B18 +#define SOC_WT GENMASK_ULL(47, 40) + +#define SOC_WT_PREDICTION_INT_ENABLE_BIT 23 + +#define SOC_WT_PREDICTION_INT_ACTIVE BIT(2) + +/* + * Closest possible to 1 Second is 1024 ms with programmed time delay + * of 0x0A. + */ +static u8 notify_delay = 0x0A; +static u16 notify_delay_ms = 1024; + +static DEFINE_MUTEX(wt_lock); +static u8 wt_enable; + +/* Show current predicted workload type index */ +static ssize_t workload_type_index_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct proc_thermal_device *proc_priv; + struct pci_dev *pdev = to_pci_dev(dev); + u64 status = 0; + int wt; + + mutex_lock(&wt_lock); + if (!wt_enable) { + mutex_unlock(&wt_lock); + return -ENODATA; + } + + proc_priv = pci_get_drvdata(pdev); + + status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); + + mutex_unlock(&wt_lock); + + wt = FIELD_GET(SOC_WT, status); + + return sysfs_emit(buf, "%d\n", wt); +} + +static DEVICE_ATTR_RO(workload_type_index); + +static ssize_t workload_hint_enable_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + 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) +{ + struct pci_dev *pdev = to_pci_dev(dev); + u8 mode; + int ret; + + if (kstrtou8(buf, 10, &mode) || mode > 1) + return -EINVAL; + + mutex_lock(&wt_lock); + + if (mode) + ret = processor_thermal_mbox_interrupt_config(pdev, true, + SOC_WT_PREDICTION_INT_ENABLE_BIT, + notify_delay); + else + ret = processor_thermal_mbox_interrupt_config(pdev, false, + SOC_WT_PREDICTION_INT_ENABLE_BIT, 0); + + if (ret) + goto ret_enable_store; + + ret = size; + wt_enable = mode; + +ret_enable_store: + mutex_unlock(&wt_lock); + + return ret; +} + +static DEVICE_ATTR_RW(workload_hint_enable); + +static ssize_t notification_delay_ms_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%u\n", notify_delay_ms); +} + +static ssize_t notification_delay_ms_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct pci_dev *pdev = to_pci_dev(dev); + u16 new_tw; + int ret; + u8 tm; + + /* + * Time window register value: + * Formula: (1 + x/4) * power(2,y) + * x = 2 msbs, that is [30:29] y = 5 [28:24] + * in INTR_CONFIG register. + * The result will be in milli seconds. + * Here, just keep x = 0, and just change y. + * First round up the user value to power of 2 and + * then take log2, to get "y" value to program. + */ + ret = kstrtou16(buf, 10, &new_tw); + if (ret) + return ret; + + if (!new_tw) + return -EINVAL; + + new_tw = roundup_pow_of_two(new_tw); + tm = ilog2(new_tw); + if (tm > 31) + return -EINVAL; + + mutex_lock(&wt_lock); + + /* If the workload hint was already enabled, then update with the new delay */ + if (wt_enable) + ret = processor_thermal_mbox_interrupt_config(pdev, true, + SOC_WT_PREDICTION_INT_ENABLE_BIT, + tm); + + if (!ret) { + ret = size; + notify_delay = tm; + notify_delay_ms = new_tw; + } + + mutex_unlock(&wt_lock); + + return ret; +} + +static DEVICE_ATTR_RW(notification_delay_ms); + +static struct attribute *workload_hint_attrs[] = { + &dev_attr_workload_type_index.attr, + &dev_attr_workload_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" +}; + +/* + * Callback to check if the interrupt for prediction is active. + * Caution: Called from the interrupt context. + */ +bool proc_thermal_check_wt_intr(struct proc_thermal_device *proc_priv) +{ + u64 int_status; + + int_status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); + if (int_status & SOC_WT_PREDICTION_INT_ACTIVE) + return true; + + return false; +} +EXPORT_SYMBOL_NS_GPL(proc_thermal_check_wt_intr, INT340X_THERMAL); + +/* Callback to notify user space */ +void proc_thermal_wt_intr_callback(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) +{ + u64 status; + + status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); + if (!(status & SOC_WT_PREDICTION_INT_ACTIVE)) + return; + + writeq(status & ~SOC_WT_PREDICTION_INT_ACTIVE, + proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); + sysfs_notify(&pdev->dev.kobj, "workload_hint", "workload_type_index"); +} +EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_intr_callback, INT340X_THERMAL); + +static bool workload_hint_created; + +int proc_thermal_wt_hint_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) +{ + int ret; + + ret = sysfs_create_group(&pdev->dev.kobj, &workload_hint_attribute_group); + if (ret) + return ret; + + workload_hint_created = true; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_hint_add, INT340X_THERMAL); + +void proc_thermal_wt_hint_remove(struct pci_dev *pdev) +{ + mutex_lock(&wt_lock); + if (wt_enable) + processor_thermal_mbox_interrupt_config(pdev, false, + SOC_WT_PREDICTION_INT_ENABLE_BIT, + 0); + mutex_unlock(&wt_lock); + + if (workload_hint_created) + sysfs_remove_group(&pdev->dev.kobj, &workload_hint_attribute_group); + + workload_hint_created = false; +} +EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_hint_remove, INT340X_THERMAL); + +MODULE_IMPORT_NS(INT340X_THERMAL); +MODULE_LICENSE("GPL"); From e682b86211a1f6d5f1f6286a4296bcab1b18a4f8 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 28 Aug 2023 17:23:45 -0700 Subject: [PATCH 006/111] thermal: int340x: Handle workload hint interrupts On thermal device interrupt, if the interrupt is generated for passing workload hint, call the callback to pass notification to the user space. First call proc_thermal_check_wt_intr() to check interrupt, if this callback returns true, wake the IRQ thread to call proc_thermal_wt_intr_callback() to notify user space. Signed-off-by: Srinivas Pandruvada [ rjw: Subject adjustment, changelog edits ] Signed-off-by: Rafael J. Wysocki --- .../processor_thermal_device_pci.c | 41 +++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) 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 eed59630fe59..7253277e476a 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -122,20 +122,43 @@ static void pkg_thermal_schedule_work(struct delayed_work *work) schedule_delayed_work(work, ms); } +static irqreturn_t proc_thermal_irq_thread_handler(int irq, void *devid) +{ + struct proc_thermal_pci *pci_info = devid; + + proc_thermal_wt_intr_callback(pci_info->pdev, pci_info->proc_priv); + + return IRQ_HANDLED; +} + static irqreturn_t proc_thermal_irq_handler(int irq, void *devid) { struct proc_thermal_pci *pci_info = devid; + struct proc_thermal_device *proc_priv; + int ret = IRQ_HANDLED; u32 status; + proc_priv = pci_info->proc_priv; + + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT) { + if (proc_thermal_check_wt_intr(pci_info->proc_priv)) + ret = IRQ_WAKE_THREAD; + } + + /* + * Since now there are two sources of interrupts: one from thermal threshold + * and another from workload hint, add a check if there was really a threshold + * interrupt before scheduling work function for thermal threshold. + */ proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status); + if (status) { + /* Disable enable interrupt flag */ + proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); + pci_write_config_byte(pci_info->pdev, 0xdc, 0x01); + pkg_thermal_schedule_work(&pci_info->work); + } - /* Disable enable interrupt flag */ - proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); - pci_write_config_byte(pci_info->pdev, 0xdc, 0x01); - - pkg_thermal_schedule_work(&pci_info->work); - - return IRQ_HANDLED; + return ret; } static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp) @@ -270,7 +293,7 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ } ret = devm_request_threaded_irq(&pdev->dev, irq, - proc_thermal_irq_handler, NULL, + proc_thermal_irq_handler, proc_thermal_irq_thread_handler, irq_flag, KBUILD_MODNAME, pci_info); if (ret) { dev_err(&pdev->dev, "Request IRQ %d failed\n", pdev->irq); @@ -384,6 +407,8 @@ static struct pci_driver proc_thermal_pci_driver = { module_pci_driver(proc_thermal_pci_driver); +MODULE_IMPORT_NS(INT340X_THERMAL); + MODULE_AUTHOR("Srinivas Pandruvada "); MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); MODULE_LICENSE("GPL v2"); From 27801542b2b815dad2759b7b1f85858627671a3b Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 28 Aug 2023 17:23:46 -0700 Subject: [PATCH 007/111] selftests/thermel/intel: Add test to read workload hint Some SoCs have in built firmware support to classify current running workload and pass to OS for making power management decisions. This test program waits for notification of workload type change and prints. This program can be used to test this feature and also allows other user space programs to use as a reference. Signed-off-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- tools/testing/selftests/Makefile | 1 + .../thermal/intel/workload_hint/Makefile | 12 ++ .../intel/workload_hint/workload_hint_test.c | 157 ++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 tools/testing/selftests/thermal/intel/workload_hint/Makefile create mode 100644 tools/testing/selftests/thermal/intel/workload_hint/workload_hint_test.c diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 42806add0114..725ce59e4637 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -85,6 +85,7 @@ TARGETS += syscall_user_dispatch TARGETS += sysctl TARGETS += tc-testing TARGETS += tdx +TARGETS += thermal/intel/workload_hint TARGETS += timens ifneq (1, $(quicktest)) TARGETS += timers diff --git a/tools/testing/selftests/thermal/intel/workload_hint/Makefile b/tools/testing/selftests/thermal/intel/workload_hint/Makefile new file mode 100644 index 000000000000..37ff3286283b --- /dev/null +++ b/tools/testing/selftests/thermal/intel/workload_hint/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +ifndef CROSS_COMPILE +uname_M := $(shell uname -m 2>/dev/null || echo not) +ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) + +ifeq ($(ARCH),x86) +TEST_GEN_PROGS := workload_hint_test + +include ../../../lib.mk + +endif +endif 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 new file mode 100644 index 000000000000..217c3a641c53 --- /dev/null +++ b/tools/testing/selftests/thermal/intel/workload_hint/workload_hint_test.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#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_TYPE_INDEX_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/workload_type_index" + +static const char * const workload_types[] = { + "idle", + "battery_life", + "sustained", + "bursty", + NULL +}; + +#define WORKLOAD_TYPE_MAX_INDEX 3 + +void workload_hint_exit(int signum) +{ + int fd; + + /* Disable feature via sysfs knob */ + + fd = open(WORKLOAD_ENABLE_ATTRIBUTE, O_RDWR); + if (fd < 0) { + perror("Unable to open workload type feature enable file\n"); + exit(1); + } + + if (write(fd, "0\n", 2) < 0) { + perror("Can' disable workload hints\n"); + exit(1); + } + + printf("Disabled workload type prediction\n"); + + close(fd); +} + +int main(int argc, char **argv) +{ + struct pollfd ufd; + char index_str[4]; + int fd, ret, index; + char delay_str[64]; + int delay = 0; + + printf("Usage: workload_hint_test [notification delay in milli seconds]\n"); + + if (argc > 1) { + ret = sscanf(argv[1], "%d", &delay); + if (ret < 0) { + printf("Invalid delay\n"); + exit(1); + } + + printf("Setting notification delay to %d ms\n", delay); + if (delay < 0) + exit(1); + + sprintf(delay_str, "%s\n", argv[1]); + + 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\n"); + exit(1); + } + + if (write(fd, delay_str, strlen(delay_str)) < 0) { + perror("Can't set delay\n"); + exit(1); + } + + close(fd); + } + + if (signal(SIGINT, workload_hint_exit) == SIG_IGN) + signal(SIGINT, SIG_IGN); + if (signal(SIGHUP, workload_hint_exit) == SIG_IGN) + signal(SIGHUP, SIG_IGN); + if (signal(SIGTERM, workload_hint_exit) == SIG_IGN) + signal(SIGTERM, SIG_IGN); + + /* Enable feature via sysfs knob */ + fd = open(WORKLOAD_ENABLE_ATTRIBUTE, O_RDWR); + if (fd < 0) { + perror("Unable to open workload type feature enable file\n"); + exit(1); + } + + if (write(fd, "1\n", 2) < 0) { + perror("Can' enable workload hints\n"); + exit(1); + } + + close(fd); + + printf("Enabled workload type prediction\n"); + + while (1) { + fd = open(WORKLOAD_TYPE_INDEX_ATTRIBUTE, O_RDONLY); + if (fd < 0) { + perror("Unable to open workload type file\n"); + exit(1); + } + + if ((lseek(fd, 0L, SEEK_SET)) < 0) { + fprintf(stderr, "Failed to set pointer to beginning\n"); + exit(1); + } + + if (read(fd, index_str, sizeof(index_str)) < 0) { + fprintf(stderr, "Failed to read from:%s\n", + WORKLOAD_TYPE_INDEX_ATTRIBUTE); + exit(1); + } + + ufd.fd = fd; + ufd.events = POLLPRI; + + ret = poll(&ufd, 1, -1); + if (ret < 0) { + perror("poll error"); + exit(1); + } else if (ret == 0) { + printf("Poll Timeout\n"); + } else { + if ((lseek(fd, 0L, SEEK_SET)) < 0) { + fprintf(stderr, "Failed to set pointer to beginning\n"); + exit(1); + } + + if (read(fd, index_str, sizeof(index_str)) < 0) + exit(0); + + ret = sscanf(index_str, "%d", &index); + if (ret < 0) + break; + if (index > WORKLOAD_TYPE_MAX_INDEX) + printf("Invalid workload type index\n"); + else + printf("workload type:%s\n", workload_types[index]); + } + + close(fd); + } +} From a966a0da3bae94d671bbd146ff2e3059eb07d5b0 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 13 Sep 2023 10:35:10 -0700 Subject: [PATCH 008/111] thermal: int340x: Add ArrowLake-S PCI ID Add ArrowLake-S PCI ID for processor thermal device. Signed-off-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- .../thermal/intel/int340x_thermal/processor_thermal_device.h | 1 + .../intel/int340x_thermal/processor_thermal_device_pci.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h index b974583c5c11..dd025c8c2bac 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h @@ -10,6 +10,7 @@ #include #define PCI_DEVICE_ID_INTEL_ADL_THERMAL 0x461d +#define PCI_DEVICE_ID_INTEL_ARL_S_THERMAL 0xAD03 #define PCI_DEVICE_ID_INTEL_BDW_THERMAL 0x1603 #define PCI_DEVICE_ID_INTEL_BSW_THERMAL 0x22DC 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 7253277e476a..44b179ce9bc9 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -390,6 +390,8 @@ static const struct pci_device_id proc_thermal_pci_ids[] = { { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_WT_HINT) }, + { PCI_DEVICE_DATA(INTEL, ARL_S_THERMAL, PROC_THERMAL_FEATURE_RAPL | + PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_WT_HINT) }, { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, { }, From 1ced5dce63d0a43eda3e81d2dd74e17f9c4a30b5 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 20 Sep 2023 11:51:53 -0700 Subject: [PATCH 009/111] thermal: int340x: processor_thermal: Ack all PCI interrupts All interrupts from the processor thermal PCI device require ACK. This is done by writing 0x01 at offset 0xDC in the config space. This is already done for the thereshold interrupt. Extend this for the workload hint interrupt. Fixes: e682b86211a1 ("thermal: int340x: Handle workload hint interrupts") Signed-off-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- .../intel/int340x_thermal/processor_thermal_device_pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 44b179ce9bc9..3c5ced79ead0 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -154,10 +154,11 @@ static irqreturn_t proc_thermal_irq_handler(int irq, void *devid) if (status) { /* Disable enable interrupt flag */ proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); - pci_write_config_byte(pci_info->pdev, 0xdc, 0x01); pkg_thermal_schedule_work(&pci_info->work); } + pci_write_config_byte(pci_info->pdev, 0xdc, 0x01); + return ret; } From 950210887670cbb7d2eb9af6fb743b70f1a1ebdc Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 19 Sep 2023 20:54:37 +0200 Subject: [PATCH 010/111] thermal: core: Drop trips_disabled bitmask After recent changes, thermal_zone_get_trip() cannot fail, as invoked from thermal_zone_device_register_with_trips(), so the only role of the trips_disabled bitmask is struct thermal_zone_device is to make handle_thermal_trip() skip trip points whose temperature was initially zero. However, since the unit of temperature in the thermal core is millicelsius, zero may very well be a valid temperature value at least in some usage scenarios and the trip temperature may as well change later. Thus there is no reason to permanently disable trip points with initial temperature equal to zero. Accordingly, drop the trips_disabled bitmask along with the code related to it. Signed-off-by: Rafael J. Wysocki Tested-by: Ido Schimmel Acked-by: Daniel Lezcano --- drivers/thermal/thermal_core.c | 13 ------------- include/linux/thermal.h | 2 -- 2 files changed, 15 deletions(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 58533ea75cd9..38d393f139d8 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -347,10 +347,6 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip_id) { struct thermal_trip trip; - /* Ignore disabled trip points */ - if (test_bit(trip_id, &tz->trips_disabled)) - return; - __thermal_zone_get_trip(tz, trip_id, &trip); if (trip.temperature == THERMAL_TEMP_INVALID) @@ -1231,7 +1227,6 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t struct thermal_zone_device *tz; int id; int result; - int count; struct thermal_governor *governor; if (!type || strlen(type) == 0) { @@ -1328,14 +1323,6 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t if (result) goto release_device; - for (count = 0; count < num_trips; count++) { - struct thermal_trip trip; - - result = thermal_zone_get_trip(tz, count, &trip); - if (result || !trip.temperature) - set_bit(count, &tz->trips_disabled); - } - /* Update 'this' zone's governor information */ mutex_lock(&thermal_governor_lock); diff --git a/include/linux/thermal.h b/include/linux/thermal.h index a5ae4af955ff..6cfcae22ba12 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -122,7 +122,6 @@ struct thermal_cooling_device { * @devdata: private pointer for device private data * @trips: an array of struct thermal_trip * @num_trips: number of trip points the thermal zone supports - * @trips_disabled; bitmap for disabled trips * @passive_delay_jiffies: number of jiffies to wait between polls when * performing passive cooling. * @polling_delay_jiffies: number of jiffies to wait between polls when @@ -163,7 +162,6 @@ struct thermal_zone_device { void *devdata; struct thermal_trip *trips; int num_trips; - unsigned long trips_disabled; /* bitmap for disabled trips */ unsigned long passive_delay_jiffies; unsigned long polling_delay_jiffies; int temperature; From 4be32333d941a53dcfb48e342c808c63a3b25576 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 12 Sep 2023 20:35:40 +0200 Subject: [PATCH 011/111] ACPI: thermal: Simplify initialization of critical and hot trips Use the observation that the critical and hot trip points are never updated by the ACPI thermal driver, because the flags passed from acpi_thermal_notify() to acpi_thermal_trips_update() do not include ACPI_TRIPS_CRITICAL or ACPI_TRIPS_HOT, to move the initialization of those trip points directly into acpi_thermal_get_trip_points() and reduce the size of __acpi_thermal_trips_update(). Also make the critical and hot trip points initialization code more straightforward and drop the flags that are not needed any more. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/acpi/thermal.c | 130 +++++++++++++++++++++-------------------- 1 file changed, 66 insertions(+), 64 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 312730f8272e..fe64347ff925 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -43,17 +43,13 @@ #define ACPI_THERMAL_MAX_ACTIVE 10 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65 -#define ACPI_TRIPS_CRITICAL BIT(0) -#define ACPI_TRIPS_HOT BIT(1) -#define ACPI_TRIPS_PASSIVE BIT(2) -#define ACPI_TRIPS_ACTIVE BIT(3) -#define ACPI_TRIPS_DEVICES BIT(4) +#define ACPI_TRIPS_PASSIVE BIT(0) +#define ACPI_TRIPS_ACTIVE BIT(1) +#define ACPI_TRIPS_DEVICES BIT(2) #define ACPI_TRIPS_THRESHOLDS (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE) -#define ACPI_TRIPS_INIT (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \ - ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE | \ - ACPI_TRIPS_DEVICES) +#define ACPI_TRIPS_INIT (ACPI_TRIPS_THRESHOLDS | ACPI_TRIPS_DEVICES) /* * This exception is thrown out in two cases: @@ -196,62 +192,6 @@ static void __acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) bool valid = false; int i; - /* Critical Shutdown */ - if (flag & ACPI_TRIPS_CRITICAL) { - status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &tmp); - tz->trips.critical.temperature = tmp; - /* - * Treat freezing temperatures as invalid as well; some - * BIOSes return really low values and cause reboots at startup. - * Below zero (Celsius) values clearly aren't right for sure.. - * ... so lets discard those as invalid. - */ - if (ACPI_FAILURE(status)) { - tz->trips.critical.valid = false; - acpi_handle_debug(tz->device->handle, - "No critical threshold\n"); - } else if (tmp <= 2732) { - pr_info(FW_BUG "Invalid critical threshold (%llu)\n", tmp); - tz->trips.critical.valid = false; - } else { - tz->trips.critical.valid = true; - acpi_handle_debug(tz->device->handle, - "Found critical threshold [%lu]\n", - tz->trips.critical.temperature); - } - if (tz->trips.critical.valid) { - if (crt == -1) { - tz->trips.critical.valid = false; - } else if (crt > 0) { - unsigned long crt_k = celsius_to_deci_kelvin(crt); - - /* - * Allow override critical threshold - */ - if (crt_k > tz->trips.critical.temperature) - pr_info("Critical threshold %d C\n", crt); - - tz->trips.critical.temperature = crt_k; - } - } - } - - /* Critical Sleep (optional) */ - if (flag & ACPI_TRIPS_HOT) { - status = acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, &tmp); - if (ACPI_FAILURE(status)) { - tz->trips.hot.valid = false; - acpi_handle_debug(tz->device->handle, - "No hot threshold\n"); - } else { - tz->trips.hot.temperature = tmp; - tz->trips.hot.valid = true; - acpi_handle_debug(tz->device->handle, - "Found hot threshold [%lu]\n", - tz->trips.hot.temperature); - } - } - /* Passive (optional) */ if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.trip.valid) || flag == ACPI_TRIPS_INIT) { @@ -451,11 +391,73 @@ static void acpi_thermal_trips_update(struct acpi_thermal *tz, u32 event) dev_name(&adev->dev), event, 0); } +static void acpi_thermal_get_critical_trip(struct acpi_thermal *tz) +{ + unsigned long long tmp; + acpi_status status; + + if (crt > 0) { + tmp = celsius_to_deci_kelvin(crt); + goto set; + } + if (crt == -1) { + acpi_handle_debug(tz->device->handle, "Critical threshold disabled\n"); + goto fail; + } + + status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &tmp); + if (ACPI_FAILURE(status)) { + acpi_handle_debug(tz->device->handle, "No critical threshold\n"); + goto fail; + } + if (tmp <= 2732) { + /* + * Below zero (Celsius) values clearly aren't right for sure, + * so discard them as invalid. + */ + pr_info(FW_BUG "Invalid critical threshold (%llu)\n", tmp); + goto fail; + } + +set: + tz->trips.critical.valid = true; + tz->trips.critical.temperature = tmp; + acpi_handle_debug(tz->device->handle, "Critical threshold [%lu]\n", + tz->trips.critical.temperature); + return; + +fail: + tz->trips.critical.valid = false; + tz->trips.critical.temperature = THERMAL_TEMP_INVALID; +} + +static void acpi_thermal_get_hot_trip(struct acpi_thermal *tz) +{ + unsigned long long tmp; + acpi_status status; + + status = acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, &tmp); + if (ACPI_FAILURE(status)) { + tz->trips.hot.valid = false; + tz->trips.hot.temperature = THERMAL_TEMP_INVALID; + acpi_handle_debug(tz->device->handle, "No hot threshold\n"); + return; + } + + tz->trips.hot.valid = true; + tz->trips.hot.temperature = tmp; + acpi_handle_debug(tz->device->handle, "Hot threshold [%lu]\n", + tz->trips.hot.temperature); +} + static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) { bool valid; int i; + acpi_thermal_get_critical_trip(tz); + acpi_thermal_get_hot_trip(tz); + /* Passive and active trip points (optional). */ __acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); valid = tz->trips.critical.valid | From b09872a652d386207600fcd001077251c0eae15a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 12 Sep 2023 20:36:21 +0200 Subject: [PATCH 012/111] ACPI: thermal: Fold acpi_thermal_get_info() into its caller There is only one caller of acpi_thermal_get_info() and the code from it can be folded into its caller just fine, so do that. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/acpi/thermal.c | 52 +++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index fe64347ff925..b2705e67a6bd 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -846,38 +846,6 @@ static void acpi_thermal_aml_dependency_fix(struct acpi_thermal *tz) acpi_evaluate_integer(handle, "_TMP", NULL, &value); } -static int acpi_thermal_get_info(struct acpi_thermal *tz) -{ - int result; - - if (!tz) - return -EINVAL; - - acpi_thermal_aml_dependency_fix(tz); - - /* Get trip points [_CRT, _PSV, etc.] (required) */ - result = acpi_thermal_get_trip_points(tz); - if (result) - return result; - - /* Get temperature [_TMP] (required) */ - result = acpi_thermal_get_temperature(tz); - if (result) - return result; - - /* Set the cooling mode [_SCP] to active cooling (default) */ - acpi_execute_simple_method(tz->device->handle, "_SCP", - ACPI_THERMAL_MODE_ACTIVE); - - /* Get default polling frequency [_TZP] (optional) */ - if (tzp) - tz->polling_frequency = tzp; - else - acpi_thermal_get_polling_frequency(tz); - - return 0; -} - /* * The exact offset between Kelvin and degree Celsius is 273.15. However ACPI * handles temperature values with a single decimal place. As a consequence, @@ -940,10 +908,28 @@ static int acpi_thermal_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS); device->driver_data = tz; - result = acpi_thermal_get_info(tz); + acpi_thermal_aml_dependency_fix(tz); + + /* Get trip points [_CRT, _PSV, etc.] (required). */ + result = acpi_thermal_get_trip_points(tz); if (result) goto free_memory; + /* Get temperature [_TMP] (required). */ + result = acpi_thermal_get_temperature(tz); + if (result) + goto free_memory; + + /* Set the cooling mode [_SCP] to active cooling. */ + acpi_execute_simple_method(tz->device->handle, "_SCP", + ACPI_THERMAL_MODE_ACTIVE); + + /* Determine the default polling frequency [_TZP]. */ + if (tzp) + tz->polling_frequency = tzp; + else + acpi_thermal_get_polling_frequency(tz); + acpi_thermal_guess_offset(tz); result = acpi_thermal_register_thermal_zone(tz); From f04256a8f7de2c13619b636cec1109e596804229 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 12 Sep 2023 20:37:59 +0200 Subject: [PATCH 013/111] ACPI: thermal: Determine the number of trip points earlier Compute the number of trip points in acpi_thermal_add() so as to allow the driver's data structures to be simplified going forward. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/acpi/thermal.c | 56 ++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index b2705e67a6bd..79452315fdf3 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -452,7 +452,7 @@ static void acpi_thermal_get_hot_trip(struct acpi_thermal *tz) static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) { - bool valid; + unsigned int count = 0; int i; acpi_thermal_get_critical_trip(tz); @@ -460,18 +460,24 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) /* Passive and active trip points (optional). */ __acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); - valid = tz->trips.critical.valid | - tz->trips.hot.valid | - tz->trips.passive.trip.valid; + if (tz->trips.critical.valid) + count++; - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) - valid = valid || tz->trips.active[i].trip.valid; + if (tz->trips.hot.valid) + count++; + + if (tz->trips.passive.trip.valid) + count++; + + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { + if (tz->trips.active[i].trip.valid) + count++; + else + break; - if (!valid) { - pr_warn(FW_BUG "No valid trip found\n"); - return -ENODEV; } - return 0; + + return count; } /* sys I/F for generic thermal sysfs support */ @@ -681,29 +687,15 @@ static void acpi_thermal_zone_sysfs_remove(struct acpi_thermal *tz) sysfs_remove_link(&tzdev->kobj, "device"); } -static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) +static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz, + unsigned int trip_count) { struct acpi_thermal_trip *acpi_trip; struct thermal_trip *trip; int passive_delay = 0; - int trip_count = 0; int result; int i; - if (tz->trips.critical.valid) - trip_count++; - - if (tz->trips.hot.valid) - trip_count++; - - if (tz->trips.passive.trip.valid) { - trip_count++; - passive_delay = tz->trips.passive.tsp * 100; - } - - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].trip.valid; i++) - trip_count++; - trip = kcalloc(trip_count, sizeof(*trip), GFP_KERNEL); if (!trip) return -ENOMEM; @@ -724,6 +716,8 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) acpi_trip = &tz->trips.passive.trip; if (acpi_trip->valid) { + passive_delay = tz->trips.passive.tsp * 100; + trip->type = THERMAL_TRIP_PASSIVE; trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); trip->priv = acpi_trip; @@ -893,6 +887,7 @@ static void acpi_thermal_check_fn(struct work_struct *work) static int acpi_thermal_add(struct acpi_device *device) { struct acpi_thermal *tz; + unsigned int trip_count; int result; if (!device) @@ -911,9 +906,12 @@ static int acpi_thermal_add(struct acpi_device *device) acpi_thermal_aml_dependency_fix(tz); /* Get trip points [_CRT, _PSV, etc.] (required). */ - result = acpi_thermal_get_trip_points(tz); - if (result) + trip_count = acpi_thermal_get_trip_points(tz); + if (!trip_count) { + pr_warn(FW_BUG "No valid trip points!\n"); + result = -ENODEV; goto free_memory; + } /* Get temperature [_TMP] (required). */ result = acpi_thermal_get_temperature(tz); @@ -932,7 +930,7 @@ static int acpi_thermal_add(struct acpi_device *device) acpi_thermal_guess_offset(tz); - result = acpi_thermal_register_thermal_zone(tz); + result = acpi_thermal_register_thermal_zone(tz, trip_count); if (result) goto free_memory; From 06a5f76ee104c17022425ade32b970c1d7793e01 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 12 Sep 2023 20:39:15 +0200 Subject: [PATCH 014/111] ACPI: thermal: Create and populate trip points table earlier Create and populate the driver's trip points table in acpi_thermal_add() so as to allow the its data structures to be simplified going forward. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/acpi/thermal.c | 105 ++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 79452315fdf3..d10e8cec4dd8 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -688,53 +688,10 @@ static void acpi_thermal_zone_sysfs_remove(struct acpi_thermal *tz) } static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz, - unsigned int trip_count) + unsigned int trip_count, + int passive_delay) { - struct acpi_thermal_trip *acpi_trip; - struct thermal_trip *trip; - int passive_delay = 0; int result; - int i; - - trip = kcalloc(trip_count, sizeof(*trip), GFP_KERNEL); - if (!trip) - return -ENOMEM; - - tz->trip_table = trip; - - if (tz->trips.critical.valid) { - trip->type = THERMAL_TRIP_CRITICAL; - trip->temperature = acpi_thermal_temp(tz, tz->trips.critical.temperature); - trip++; - } - - if (tz->trips.hot.valid) { - trip->type = THERMAL_TRIP_HOT; - trip->temperature = acpi_thermal_temp(tz, tz->trips.hot.temperature); - trip++; - } - - acpi_trip = &tz->trips.passive.trip; - if (acpi_trip->valid) { - passive_delay = tz->trips.passive.tsp * 100; - - trip->type = THERMAL_TRIP_PASSIVE; - trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); - trip->priv = acpi_trip; - trip++; - } - - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - acpi_trip = &tz->trips.active[i].trip; - - if (!acpi_trip->valid) - break; - - trip->type = THERMAL_TRIP_ACTIVE; - trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); - trip->priv = acpi_trip; - trip++; - } tz->thermal_zone = thermal_zone_device_register_with_trips("acpitz", tz->trip_table, @@ -744,10 +701,8 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz, NULL, passive_delay, tz->polling_frequency * 100); - if (IS_ERR(tz->thermal_zone)) { - result = PTR_ERR(tz->thermal_zone); - goto free_trip_table; - } + if (IS_ERR(tz->thermal_zone)) + return PTR_ERR(tz->thermal_zone); result = acpi_thermal_zone_sysfs_add(tz); if (result) @@ -766,8 +721,6 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz, acpi_thermal_zone_sysfs_remove(tz); unregister_tzd: thermal_zone_device_unregister(tz->thermal_zone); -free_trip_table: - kfree(tz->trip_table); return result; } @@ -886,9 +839,13 @@ static void acpi_thermal_check_fn(struct work_struct *work) static int acpi_thermal_add(struct acpi_device *device) { + struct acpi_thermal_trip *acpi_trip; + struct thermal_trip *trip; struct acpi_thermal *tz; unsigned int trip_count; + int passive_delay = 0; int result; + int i; if (!device) return -EINVAL; @@ -930,9 +887,49 @@ static int acpi_thermal_add(struct acpi_device *device) acpi_thermal_guess_offset(tz); - result = acpi_thermal_register_thermal_zone(tz, trip_count); + trip = kcalloc(trip_count, sizeof(*trip), GFP_KERNEL); + if (!trip) + return -ENOMEM; + + tz->trip_table = trip; + + if (tz->trips.critical.valid) { + trip->type = THERMAL_TRIP_CRITICAL; + trip->temperature = acpi_thermal_temp(tz, tz->trips.critical.temperature); + trip++; + } + + if (tz->trips.hot.valid) { + trip->type = THERMAL_TRIP_HOT; + trip->temperature = acpi_thermal_temp(tz, tz->trips.hot.temperature); + trip++; + } + + acpi_trip = &tz->trips.passive.trip; + if (acpi_trip->valid) { + passive_delay = tz->trips.passive.tsp * 100; + + trip->type = THERMAL_TRIP_PASSIVE; + trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); + trip->priv = acpi_trip; + trip++; + } + + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { + acpi_trip = &tz->trips.active[i].trip; + + if (!acpi_trip->valid) + break; + + trip->type = THERMAL_TRIP_ACTIVE; + trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); + trip->priv = acpi_trip; + trip++; + } + + result = acpi_thermal_register_thermal_zone(tz, trip_count, passive_delay); if (result) - goto free_memory; + goto free_trips; refcount_set(&tz->thermal_check_count, 3); mutex_init(&tz->thermal_check_lock); @@ -951,6 +948,8 @@ static int acpi_thermal_add(struct acpi_device *device) flush_wq: flush_workqueue(acpi_thermal_pm_queue); acpi_thermal_unregister_thermal_zone(tz); +free_trips: + kfree(tz->trip_table); free_memory: kfree(tz); From 30f04c7535e464f1824edb02e736a50be018777b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 12 Sep 2023 20:41:06 +0200 Subject: [PATCH 015/111] ACPI: thermal: Simplify critical and hot trips representation Notice that the only piece of information regarding the critical and hot trips that needs to be stored in the driver's local data structures is whether or not these trips are valid, so drop all of the redundant information from there and adjust the code accordingly. Among other things, this requires acpi_thermal_add() to be rearranged so as to obtain the critical trip temperature before populating the trip points table and for symmetry, the hot trip temperature is obtained earlier too. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/acpi/thermal.c | 69 ++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index d10e8cec4dd8..f60f3633f3ef 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -107,10 +107,10 @@ struct acpi_thermal_active { }; struct acpi_thermal_trips { - struct acpi_thermal_trip critical; - struct acpi_thermal_trip hot; struct acpi_thermal_passive passive; struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE]; + bool critical_valid; + bool hot_valid; }; struct acpi_thermal { @@ -391,7 +391,7 @@ static void acpi_thermal_trips_update(struct acpi_thermal *tz, u32 event) dev_name(&adev->dev), event, 0); } -static void acpi_thermal_get_critical_trip(struct acpi_thermal *tz) +static long acpi_thermal_get_critical_trip(struct acpi_thermal *tz) { unsigned long long tmp; acpi_status status; @@ -420,34 +420,30 @@ static void acpi_thermal_get_critical_trip(struct acpi_thermal *tz) } set: - tz->trips.critical.valid = true; - tz->trips.critical.temperature = tmp; - acpi_handle_debug(tz->device->handle, "Critical threshold [%lu]\n", - tz->trips.critical.temperature); - return; + tz->trips.critical_valid = true; + acpi_handle_debug(tz->device->handle, "Critical threshold [%llu]\n", tmp); + return tmp; fail: - tz->trips.critical.valid = false; - tz->trips.critical.temperature = THERMAL_TEMP_INVALID; + tz->trips.critical_valid = false; + return THERMAL_TEMP_INVALID; } -static void acpi_thermal_get_hot_trip(struct acpi_thermal *tz) +static long acpi_thermal_get_hot_trip(struct acpi_thermal *tz) { unsigned long long tmp; acpi_status status; status = acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, &tmp); if (ACPI_FAILURE(status)) { - tz->trips.hot.valid = false; - tz->trips.hot.temperature = THERMAL_TEMP_INVALID; + tz->trips.hot_valid = false; acpi_handle_debug(tz->device->handle, "No hot threshold\n"); - return; + return THERMAL_TEMP_INVALID; } - tz->trips.hot.valid = true; - tz->trips.hot.temperature = tmp; - acpi_handle_debug(tz->device->handle, "Hot threshold [%lu]\n", - tz->trips.hot.temperature); + tz->trips.hot_valid = true; + acpi_handle_debug(tz->device->handle, "Hot threshold [%llu]\n", tmp); + return tmp; } static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) @@ -455,17 +451,9 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) unsigned int count = 0; int i; - acpi_thermal_get_critical_trip(tz); - acpi_thermal_get_hot_trip(tz); /* Passive and active trip points (optional). */ __acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); - if (tz->trips.critical.valid) - count++; - - if (tz->trips.hot.valid) - count++; - if (tz->trips.passive.trip.valid) count++; @@ -578,10 +566,10 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, int trip = -1; int result = 0; - if (tz->trips.critical.valid) + if (tz->trips.critical_valid) trip++; - if (tz->trips.hot.valid) + if (tz->trips.hot_valid) trip++; if (tz->trips.passive.trip.valid) { @@ -803,10 +791,9 @@ static void acpi_thermal_aml_dependency_fix(struct acpi_thermal *tz) * The heuristic below should work for all ACPI thermal zones which have a * critical trip point with a value being a multiple of 0.5 degree Celsius. */ -static void acpi_thermal_guess_offset(struct acpi_thermal *tz) +static void acpi_thermal_guess_offset(struct acpi_thermal *tz, long crit_temp) { - if (tz->trips.critical.valid && - (tz->trips.critical.temperature % 5) == 1) + if (tz->trips.critical_valid && crit_temp % 5 == 1) tz->kelvin_offset = 273100; else tz->kelvin_offset = 273200; @@ -843,6 +830,7 @@ static int acpi_thermal_add(struct acpi_device *device) struct thermal_trip *trip; struct acpi_thermal *tz; unsigned int trip_count; + int crit_temp, hot_temp; int passive_delay = 0; int result; int i; @@ -864,6 +852,15 @@ static int acpi_thermal_add(struct acpi_device *device) /* Get trip points [_CRT, _PSV, etc.] (required). */ trip_count = acpi_thermal_get_trip_points(tz); + + crit_temp = acpi_thermal_get_critical_trip(tz); + if (tz->trips.critical_valid) + trip_count++; + + hot_temp = acpi_thermal_get_hot_trip(tz); + if (tz->trips.hot_valid) + trip_count++; + if (!trip_count) { pr_warn(FW_BUG "No valid trip points!\n"); result = -ENODEV; @@ -885,7 +882,7 @@ static int acpi_thermal_add(struct acpi_device *device) else acpi_thermal_get_polling_frequency(tz); - acpi_thermal_guess_offset(tz); + acpi_thermal_guess_offset(tz, crit_temp); trip = kcalloc(trip_count, sizeof(*trip), GFP_KERNEL); if (!trip) @@ -893,15 +890,15 @@ static int acpi_thermal_add(struct acpi_device *device) tz->trip_table = trip; - if (tz->trips.critical.valid) { + if (tz->trips.critical_valid) { trip->type = THERMAL_TRIP_CRITICAL; - trip->temperature = acpi_thermal_temp(tz, tz->trips.critical.temperature); + trip->temperature = acpi_thermal_temp(tz, crit_temp); trip++; } - if (tz->trips.hot.valid) { + if (tz->trips.hot_valid) { trip->type = THERMAL_TRIP_HOT; - trip->temperature = acpi_thermal_temp(tz, tz->trips.hot.temperature); + trip->temperature = acpi_thermal_temp(tz, hot_temp); trip++; } From 64c512edf97735ecd882b532a5c5351edde39676 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 12 Sep 2023 20:43:52 +0200 Subject: [PATCH 016/111] ACPI: thermal: Untangle initialization and updates of the passive trip Separate the code needed to update the passive trip (in a response to a notification from the platform firmware) as well as to initialize it from the code that is only necessary for its initialization and cleanly divide it into functions that each carry out a specific action. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/acpi/thermal.c | 198 ++++++++++++++++++++++++++--------------- 1 file changed, 125 insertions(+), 73 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index f60f3633f3ef..bd8d9bfd5df9 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -192,73 +192,6 @@ static void __acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) bool valid = false; int i; - /* Passive (optional) */ - if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.trip.valid) || - flag == ACPI_TRIPS_INIT) { - valid = tz->trips.passive.trip.valid; - if (psv == -1) { - status = AE_SUPPORT; - } else if (psv > 0) { - tmp = celsius_to_deci_kelvin(psv); - status = AE_OK; - } else { - status = acpi_evaluate_integer(tz->device->handle, - "_PSV", NULL, &tmp); - } - - if (ACPI_FAILURE(status)) { - tz->trips.passive.trip.valid = false; - } else { - tz->trips.passive.trip.temperature = tmp; - tz->trips.passive.trip.valid = true; - if (flag == ACPI_TRIPS_INIT) { - status = acpi_evaluate_integer(tz->device->handle, - "_TC1", NULL, &tmp); - if (ACPI_FAILURE(status)) - tz->trips.passive.trip.valid = false; - else - tz->trips.passive.tc1 = tmp; - - status = acpi_evaluate_integer(tz->device->handle, - "_TC2", NULL, &tmp); - if (ACPI_FAILURE(status)) - tz->trips.passive.trip.valid = false; - else - tz->trips.passive.tc2 = tmp; - - status = acpi_evaluate_integer(tz->device->handle, - "_TSP", NULL, &tmp); - if (ACPI_FAILURE(status)) - tz->trips.passive.trip.valid = false; - else - tz->trips.passive.tsp = tmp; - } - } - } - if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.trip.valid) { - memset(&devices, 0, sizeof(struct acpi_handle_list)); - status = acpi_evaluate_reference(tz->device->handle, "_PSL", - NULL, &devices); - if (ACPI_FAILURE(status)) { - acpi_handle_info(tz->device->handle, - "Invalid passive threshold\n"); - tz->trips.passive.trip.valid = false; - } else { - tz->trips.passive.trip.valid = true; - } - - if (memcmp(&tz->trips.passive.devices, &devices, - sizeof(struct acpi_handle_list))) { - memcpy(&tz->trips.passive.devices, &devices, - sizeof(struct acpi_handle_list)); - ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device"); - } - } - if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) { - if (valid != tz->trips.passive.trip.valid) - ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state"); - } - /* Active (optional) */ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { char name[5] = { '_', 'A', 'C', ('0' + i), '\0' }; @@ -339,6 +272,72 @@ static void __acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) } } +static void update_acpi_thermal_trip_temp(struct acpi_thermal_trip *acpi_trip, + int temp) +{ + acpi_trip->valid = temp != THERMAL_TEMP_INVALID; + acpi_trip->temperature = temp; +} + +static long get_passive_temp(struct acpi_thermal *tz) +{ + unsigned long long tmp; + acpi_status status; + + status = acpi_evaluate_integer(tz->device->handle, "_PSV", NULL, &tmp); + if (ACPI_FAILURE(status)) + return THERMAL_TEMP_INVALID; + + return tmp; +} + +static void acpi_thermal_update_passive_trip(struct acpi_thermal *tz) +{ + struct acpi_thermal_trip *acpi_trip = &tz->trips.passive.trip; + + if (!acpi_trip->valid || psv > 0) + return; + + update_acpi_thermal_trip_temp(acpi_trip, get_passive_temp(tz)); + if (!acpi_trip->valid) + ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_PASSIVE, tz, "state"); +} + +static bool update_passive_devices(struct acpi_thermal *tz, bool compare) +{ + struct acpi_handle_list devices; + acpi_status status; + + memset(&devices, 0, sizeof(devices)); + + status = acpi_evaluate_reference(tz->device->handle, "_PSL", NULL, &devices); + if (ACPI_FAILURE(status)) { + acpi_handle_info(tz->device->handle, + "Missing device list for passive threshold\n"); + return false; + } + + if (compare && memcmp(&tz->trips.passive.devices, &devices, sizeof(devices))) + ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_PASSIVE, tz, "device"); + + memcpy(&tz->trips.passive.devices, &devices, sizeof(devices)); + return true; +} + +static void acpi_thermal_update_passive_devices(struct acpi_thermal *tz) +{ + struct acpi_thermal_trip *acpi_trip = &tz->trips.passive.trip; + + if (!acpi_trip->valid) + return; + + if (update_passive_devices(tz, true)) + return; + + update_acpi_thermal_trip_temp(acpi_trip, THERMAL_TEMP_INVALID); + ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_PASSIVE, tz, "state"); +} + static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data) { struct acpi_thermal_trip *acpi_trip = trip->priv; @@ -359,8 +358,15 @@ static void acpi_thermal_adjust_thermal_zone(struct thermal_zone_device *thermal unsigned long data) { struct acpi_thermal *tz = thermal_zone_device_priv(thermal); - int flag = data == ACPI_THERMAL_NOTIFY_THRESHOLDS ? - ACPI_TRIPS_THRESHOLDS : ACPI_TRIPS_DEVICES; + int flag; + + if (data == ACPI_THERMAL_NOTIFY_THRESHOLDS) { + acpi_thermal_update_passive_trip(tz); + flag = ACPI_TRIPS_THRESHOLDS; + } else { + acpi_thermal_update_passive_devices(tz); + flag = ACPI_TRIPS_DEVICES; + } __acpi_thermal_trips_update(tz, flag); @@ -446,17 +452,63 @@ static long acpi_thermal_get_hot_trip(struct acpi_thermal *tz) return tmp; } +static bool acpi_thermal_init_passive_trip(struct acpi_thermal *tz) +{ + unsigned long long tmp; + acpi_status status; + int temp; + + if (psv == -1) + goto fail; + + if (psv > 0) { + temp = celsius_to_deci_kelvin(psv); + } else { + temp = get_passive_temp(tz); + if (temp == THERMAL_TEMP_INVALID) + goto fail; + } + + status = acpi_evaluate_integer(tz->device->handle, "_TC1", NULL, &tmp); + if (ACPI_FAILURE(status)) + goto fail; + + tz->trips.passive.tc1 = tmp; + + status = acpi_evaluate_integer(tz->device->handle, "_TC2", NULL, &tmp); + if (ACPI_FAILURE(status)) + goto fail; + + tz->trips.passive.tc2 = tmp; + + status = acpi_evaluate_integer(tz->device->handle, "_TSP", NULL, &tmp); + if (ACPI_FAILURE(status)) + goto fail; + + tz->trips.passive.tsp = tmp; + + if (!update_passive_devices(tz, false)) + goto fail; + + update_acpi_thermal_trip_temp(&tz->trips.passive.trip, temp); + return true; + +fail: + update_acpi_thermal_trip_temp(&tz->trips.passive.trip, THERMAL_TEMP_INVALID); + return false; +} + static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) { unsigned int count = 0; int i; - /* Passive and active trip points (optional). */ - __acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); - - if (tz->trips.passive.trip.valid) + if (acpi_thermal_init_passive_trip(tz)) count++; + /* Active trip points (optional). */ + __acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { if (tz->trips.active[i].trip.valid) count++; From cdfe09df04a0706f3926c0643ba2218fae04003b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 20 Sep 2023 14:35:46 +0200 Subject: [PATCH 017/111] ACPI: thermal: Untangle initialization and updates of active trips Separate the code needed to update active trips (in a response to a notification from the platform firmware) as well as to initialize them from the code that is only necessary for their initialization and cleanly divide it into functions that each carry out a specific action. Signed-off-by: Rafael J. Wysocki Acked-by: Daniel Lezcano --- drivers/acpi/thermal.c | 197 +++++++++++++++++++++-------------------- 1 file changed, 100 insertions(+), 97 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index bd8d9bfd5df9..a6599b19dba8 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -184,94 +184,6 @@ static int acpi_thermal_temp(struct acpi_thermal *tz, int temp_deci_k) tz->kelvin_offset); } -static void __acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) -{ - acpi_status status; - unsigned long long tmp; - struct acpi_handle_list devices; - bool valid = false; - int i; - - /* Active (optional) */ - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - char name[5] = { '_', 'A', 'C', ('0' + i), '\0' }; - valid = tz->trips.active[i].trip.valid; - - if (act == -1) - break; /* disable all active trip points */ - - if (flag == ACPI_TRIPS_INIT || ((flag & ACPI_TRIPS_ACTIVE) && - tz->trips.active[i].trip.valid)) { - status = acpi_evaluate_integer(tz->device->handle, - name, NULL, &tmp); - if (ACPI_FAILURE(status)) { - tz->trips.active[i].trip.valid = false; - if (i == 0) - break; - - if (act <= 0) - break; - - if (i == 1) - tz->trips.active[0].trip.temperature = - celsius_to_deci_kelvin(act); - else - /* - * Don't allow override higher than - * the next higher trip point - */ - tz->trips.active[i-1].trip.temperature = - min_t(unsigned long, - tz->trips.active[i-2].trip.temperature, - celsius_to_deci_kelvin(act)); - - break; - } else { - tz->trips.active[i].trip.temperature = tmp; - tz->trips.active[i].trip.valid = true; - } - } - - name[2] = 'L'; - if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].trip.valid) { - memset(&devices, 0, sizeof(struct acpi_handle_list)); - status = acpi_evaluate_reference(tz->device->handle, - name, NULL, &devices); - if (ACPI_FAILURE(status)) { - acpi_handle_info(tz->device->handle, - "Invalid active%d threshold\n", i); - tz->trips.active[i].trip.valid = false; - } else { - tz->trips.active[i].trip.valid = true; - } - - if (memcmp(&tz->trips.active[i].devices, &devices, - sizeof(struct acpi_handle_list))) { - memcpy(&tz->trips.active[i].devices, &devices, - sizeof(struct acpi_handle_list)); - ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device"); - } - } - if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES)) - if (valid != tz->trips.active[i].trip.valid) - ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state"); - - if (!tz->trips.active[i].trip.valid) - break; - } - - if (flag & ACPI_TRIPS_DEVICES) { - memset(&devices, 0, sizeof(devices)); - status = acpi_evaluate_reference(tz->device->handle, "_TZD", - NULL, &devices); - if (ACPI_SUCCESS(status) && - memcmp(&tz->devices, &devices, sizeof(devices))) { - tz->devices = devices; - ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device"); - } - } -} - static void update_acpi_thermal_trip_temp(struct acpi_thermal_trip *acpi_trip, int temp) { @@ -338,6 +250,78 @@ static void acpi_thermal_update_passive_devices(struct acpi_thermal *tz) ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_PASSIVE, tz, "state"); } +static long get_active_temp(struct acpi_thermal *tz, int index) +{ + char method[] = { '_', 'A', 'C', '0' + index, '\0' }; + unsigned long long tmp; + acpi_status status; + + status = acpi_evaluate_integer(tz->device->handle, method, NULL, &tmp); + if (ACPI_FAILURE(status)) + return THERMAL_TEMP_INVALID; + + /* + * If an override has been provided, apply it so there are no active + * trips with thresholds greater than the override. + */ + if (act > 0) { + unsigned long long override = celsius_to_deci_kelvin(act); + + if (tmp > override) + tmp = override; + } + return tmp; +} + +static void acpi_thermal_update_active_trip(struct acpi_thermal *tz, int index) +{ + struct acpi_thermal_trip *acpi_trip = &tz->trips.active[index].trip; + + if (!acpi_trip->valid) + return; + + update_acpi_thermal_trip_temp(acpi_trip, get_active_temp(tz, index)); + if (!acpi_trip->valid) + ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_ACTIVE, tz, "state"); +} + +static bool update_active_devices(struct acpi_thermal *tz, int index, bool compare) +{ + char method[] = { '_', 'A', 'L', '0' + index, '\0' }; + struct acpi_handle_list devices; + acpi_status status; + + memset(&devices, 0, sizeof(devices)); + + status = acpi_evaluate_reference(tz->device->handle, method, NULL, &devices); + if (ACPI_FAILURE(status)) { + acpi_handle_info(tz->device->handle, + "Missing device list for active threshold %d\n", + index); + return false; + } + + if (compare && memcmp(&tz->trips.active[index].devices, &devices, sizeof(devices))) + ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_ACTIVE, tz, "device"); + + memcpy(&tz->trips.active[index].devices, &devices, sizeof(devices)); + return true; +} + +static void acpi_thermal_update_active_devices(struct acpi_thermal *tz, int index) +{ + struct acpi_thermal_trip *acpi_trip = &tz->trips.active[index].trip; + + if (!acpi_trip->valid) + return; + + if (update_active_devices(tz, index, true)) + return; + + update_acpi_thermal_trip_temp(acpi_trip, THERMAL_TEMP_INVALID); + ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_ACTIVE, tz, "state"); +} + static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data) { struct acpi_thermal_trip *acpi_trip = trip->priv; @@ -358,18 +342,18 @@ static void acpi_thermal_adjust_thermal_zone(struct thermal_zone_device *thermal unsigned long data) { struct acpi_thermal *tz = thermal_zone_device_priv(thermal); - int flag; + int i; if (data == ACPI_THERMAL_NOTIFY_THRESHOLDS) { acpi_thermal_update_passive_trip(tz); - flag = ACPI_TRIPS_THRESHOLDS; + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) + acpi_thermal_update_active_trip(tz, i); } else { acpi_thermal_update_passive_devices(tz); - flag = ACPI_TRIPS_DEVICES; + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) + acpi_thermal_update_active_devices(tz, i); } - __acpi_thermal_trips_update(tz, flag); - for_each_thermal_trip(tz->thermal_zone, acpi_thermal_adjust_trip, tz); } @@ -498,6 +482,28 @@ static bool acpi_thermal_init_passive_trip(struct acpi_thermal *tz) return false; } +static bool acpi_thermal_init_active_trip(struct acpi_thermal *tz, int index) +{ + long temp; + + if (act == -1) + goto fail; + + temp = get_active_temp(tz, index); + if (temp == THERMAL_TEMP_INVALID) + goto fail; + + if (!update_active_devices(tz, index, false)) + goto fail; + + update_acpi_thermal_trip_temp(&tz->trips.active[index].trip, temp); + return true; + +fail: + update_acpi_thermal_trip_temp(&tz->trips.active[index].trip, THERMAL_TEMP_INVALID); + return false; +} + static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) { unsigned int count = 0; @@ -506,11 +512,8 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) if (acpi_thermal_init_passive_trip(tz)) count++; - /* Active trip points (optional). */ - __acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - if (tz->trips.active[i].trip.valid) + if (acpi_thermal_init_active_trip(tz, i)) count++; else break; From 4175a24f01eb4bfde7d57a9a3ea254649f440034 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 12 Sep 2023 20:46:02 +0200 Subject: [PATCH 018/111] ACPI: thermal: Drop redundant trip point flags Trip point flags previously used by the driver need not be used any more after the preceding changes, so drop them and adjust the code accordingly. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/acpi/thermal.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index a6599b19dba8..c5ff542bcbf3 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -43,14 +43,6 @@ #define ACPI_THERMAL_MAX_ACTIVE 10 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65 -#define ACPI_TRIPS_PASSIVE BIT(0) -#define ACPI_TRIPS_ACTIVE BIT(1) -#define ACPI_TRIPS_DEVICES BIT(2) - -#define ACPI_TRIPS_THRESHOLDS (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE) - -#define ACPI_TRIPS_INIT (ACPI_TRIPS_THRESHOLDS | ACPI_TRIPS_DEVICES) - /* * This exception is thrown out in two cases: * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid @@ -58,12 +50,11 @@ * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change. * We need to re-bind the cooling devices of a thermal zone when this occurs. */ -#define ACPI_THERMAL_TRIPS_EXCEPTION(flags, tz, str) \ +#define ACPI_THERMAL_TRIPS_EXCEPTION(tz, str) \ do { \ - if (flags != ACPI_TRIPS_INIT) \ - acpi_handle_info(tz->device->handle, \ - "ACPI thermal trip point %s changed\n" \ - "Please report to linux-acpi@vger.kernel.org\n", str); \ + acpi_handle_info(tz->device->handle, \ + "ACPI thermal trip point %s changed\n" \ + "Please report to linux-acpi@vger.kernel.org\n", str); \ } while (0) static int act; @@ -212,7 +203,7 @@ static void acpi_thermal_update_passive_trip(struct acpi_thermal *tz) update_acpi_thermal_trip_temp(acpi_trip, get_passive_temp(tz)); if (!acpi_trip->valid) - ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_PASSIVE, tz, "state"); + ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } static bool update_passive_devices(struct acpi_thermal *tz, bool compare) @@ -230,7 +221,7 @@ static bool update_passive_devices(struct acpi_thermal *tz, bool compare) } if (compare && memcmp(&tz->trips.passive.devices, &devices, sizeof(devices))) - ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_PASSIVE, tz, "device"); + ACPI_THERMAL_TRIPS_EXCEPTION(tz, "device"); memcpy(&tz->trips.passive.devices, &devices, sizeof(devices)); return true; @@ -247,7 +238,7 @@ static void acpi_thermal_update_passive_devices(struct acpi_thermal *tz) return; update_acpi_thermal_trip_temp(acpi_trip, THERMAL_TEMP_INVALID); - ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_PASSIVE, tz, "state"); + ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } static long get_active_temp(struct acpi_thermal *tz, int index) @@ -282,7 +273,7 @@ static void acpi_thermal_update_active_trip(struct acpi_thermal *tz, int index) update_acpi_thermal_trip_temp(acpi_trip, get_active_temp(tz, index)); if (!acpi_trip->valid) - ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_ACTIVE, tz, "state"); + ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } static bool update_active_devices(struct acpi_thermal *tz, int index, bool compare) @@ -302,7 +293,7 @@ static bool update_active_devices(struct acpi_thermal *tz, int index, bool compa } if (compare && memcmp(&tz->trips.active[index].devices, &devices, sizeof(devices))) - ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_ACTIVE, tz, "device"); + ACPI_THERMAL_TRIPS_EXCEPTION(tz, "device"); memcpy(&tz->trips.active[index].devices, &devices, sizeof(devices)); return true; @@ -319,7 +310,7 @@ static void acpi_thermal_update_active_devices(struct acpi_thermal *tz, int inde return; update_acpi_thermal_trip_temp(acpi_trip, THERMAL_TEMP_INVALID); - ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_ACTIVE, tz, "state"); + ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data) From 058f5e407deb8d21b0a04e50e8efbd25b1fcbd1b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 20 Sep 2023 15:03:46 +0200 Subject: [PATCH 019/111] ACPI: thermal: Drop valid flag from struct acpi_thermal_trip Notice that the valid flag in struct acpi_thermal_trip is in fact redundant, because the temperature field of invalid trips is always equal to THERMAL_TEMP_INVALID, so drop it from there and adjust the code accordingly. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/acpi/thermal.c | 49 ++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index c5ff542bcbf3..10720a038846 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -81,7 +81,6 @@ static struct workqueue_struct *acpi_thermal_pm_queue; struct acpi_thermal_trip { unsigned long temperature; - bool valid; }; struct acpi_thermal_passive { @@ -175,11 +174,9 @@ static int acpi_thermal_temp(struct acpi_thermal *tz, int temp_deci_k) tz->kelvin_offset); } -static void update_acpi_thermal_trip_temp(struct acpi_thermal_trip *acpi_trip, - int temp) +static bool acpi_thermal_trip_valid(struct acpi_thermal_trip *acpi_trip) { - acpi_trip->valid = temp != THERMAL_TEMP_INVALID; - acpi_trip->temperature = temp; + return acpi_trip->temperature != THERMAL_TEMP_INVALID; } static long get_passive_temp(struct acpi_thermal *tz) @@ -198,11 +195,11 @@ static void acpi_thermal_update_passive_trip(struct acpi_thermal *tz) { struct acpi_thermal_trip *acpi_trip = &tz->trips.passive.trip; - if (!acpi_trip->valid || psv > 0) + if (!acpi_thermal_trip_valid(acpi_trip) || psv > 0) return; - update_acpi_thermal_trip_temp(acpi_trip, get_passive_temp(tz)); - if (!acpi_trip->valid) + acpi_trip->temperature = get_passive_temp(tz); + if (!acpi_thermal_trip_valid(acpi_trip)) ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } @@ -231,13 +228,13 @@ static void acpi_thermal_update_passive_devices(struct acpi_thermal *tz) { struct acpi_thermal_trip *acpi_trip = &tz->trips.passive.trip; - if (!acpi_trip->valid) + if (!acpi_thermal_trip_valid(acpi_trip)) return; if (update_passive_devices(tz, true)) return; - update_acpi_thermal_trip_temp(acpi_trip, THERMAL_TEMP_INVALID); + acpi_trip->temperature = THERMAL_TEMP_INVALID; ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } @@ -268,11 +265,11 @@ static void acpi_thermal_update_active_trip(struct acpi_thermal *tz, int index) { struct acpi_thermal_trip *acpi_trip = &tz->trips.active[index].trip; - if (!acpi_trip->valid) + if (!acpi_thermal_trip_valid(acpi_trip)) return; - update_acpi_thermal_trip_temp(acpi_trip, get_active_temp(tz, index)); - if (!acpi_trip->valid) + acpi_trip->temperature = get_active_temp(tz, index); + if (!acpi_thermal_trip_valid(acpi_trip)) ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } @@ -303,13 +300,13 @@ static void acpi_thermal_update_active_devices(struct acpi_thermal *tz, int inde { struct acpi_thermal_trip *acpi_trip = &tz->trips.active[index].trip; - if (!acpi_trip->valid) + if (!acpi_thermal_trip_valid(acpi_trip)) return; if (update_active_devices(tz, index, true)) return; - update_acpi_thermal_trip_temp(acpi_trip, THERMAL_TEMP_INVALID); + acpi_trip->temperature = THERMAL_TEMP_INVALID; ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } @@ -321,7 +318,7 @@ static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data) if (!acpi_trip) return 0; - if (acpi_trip->valid) + if (acpi_thermal_trip_valid(acpi_trip)) trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); else trip->temperature = THERMAL_TEMP_INVALID; @@ -465,11 +462,11 @@ static bool acpi_thermal_init_passive_trip(struct acpi_thermal *tz) if (!update_passive_devices(tz, false)) goto fail; - update_acpi_thermal_trip_temp(&tz->trips.passive.trip, temp); + tz->trips.passive.trip.temperature = temp; return true; fail: - update_acpi_thermal_trip_temp(&tz->trips.passive.trip, THERMAL_TEMP_INVALID); + tz->trips.passive.trip.temperature = THERMAL_TEMP_INVALID; return false; } @@ -487,11 +484,11 @@ static bool acpi_thermal_init_active_trip(struct acpi_thermal *tz, int index) if (!update_active_devices(tz, index, false)) goto fail; - update_acpi_thermal_trip_temp(&tz->trips.active[index].trip, temp); + tz->trips.active[index].trip.temperature = temp; return true; fail: - update_acpi_thermal_trip_temp(&tz->trips.active[index].trip, THERMAL_TEMP_INVALID); + tz->trips.active[index].trip.temperature = THERMAL_TEMP_INVALID; return false; } @@ -545,7 +542,7 @@ static int thermal_get_trend(struct thermal_zone_device *thermal, return -EINVAL; acpi_trip = trip->priv; - if (!acpi_trip || !acpi_trip->valid) + if (!acpi_trip || !acpi_thermal_trip_valid(acpi_trip)) return -EINVAL; switch (trip->type) { @@ -618,7 +615,7 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, if (tz->trips.hot_valid) trip++; - if (tz->trips.passive.trip.valid) { + if (acpi_thermal_trip_valid(&tz->trips.passive.trip)) { trip++; for (i = 0; i < tz->trips.passive.devices.count; i++) { handle = tz->trips.passive.devices.handles[i]; @@ -643,7 +640,7 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, } for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - if (!tz->trips.active[i].trip.valid) + if (!acpi_thermal_trip_valid(&tz->trips.active[i].trip)) break; trip++; @@ -949,7 +946,7 @@ static int acpi_thermal_add(struct acpi_device *device) } acpi_trip = &tz->trips.passive.trip; - if (acpi_trip->valid) { + if (acpi_thermal_trip_valid(acpi_trip)) { passive_delay = tz->trips.passive.tsp * 100; trip->type = THERMAL_TRIP_PASSIVE; @@ -961,7 +958,7 @@ static int acpi_thermal_add(struct acpi_device *device) for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { acpi_trip = &tz->trips.active[i].trip; - if (!acpi_trip->valid) + if (!acpi_thermal_trip_valid(acpi_trip)) break; trip->type = THERMAL_TRIP_ACTIVE; @@ -1038,7 +1035,7 @@ static int acpi_thermal_resume(struct device *dev) return -EINVAL; for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - if (!tz->trips.active[i].trip.valid) + if (!acpi_thermal_trip_valid(&tz->trips.active[i].trip)) break; for (j = 0; j < tz->trips.active[i].devices.count; j++) { From a15ffa783ea4210877886c59566a0d20f6b2bc09 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 19 Sep 2023 20:59:53 +0200 Subject: [PATCH 020/111] thermal: trip: Drop redundant trips check from for_each_thermal_trip() It is invalid to call for_each_thermal_trip() on an unregistered thermal zone anyway, and as per thermal_zone_device_register_with_trips(), the trips[] table must be present if num_trips is greater than zero for the given thermal zone. Hence, the trips check in for_each_thermal_trip() is redundant and so it can be dropped. Signed-off-by: Rafael J. Wysocki Acked-by: Daniel Lezcano --- drivers/thermal/thermal_trip.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/thermal/thermal_trip.c b/drivers/thermal/thermal_trip.c index 024e2e365a26..1cadb3b5d104 100644 --- a/drivers/thermal/thermal_trip.c +++ b/drivers/thermal/thermal_trip.c @@ -17,9 +17,6 @@ int for_each_thermal_trip(struct thermal_zone_device *tz, lockdep_assert_held(&tz->lock); - if (!tz->trips) - return -ENODATA; - for (i = 0; i < tz->num_trips; i++) { ret = cb(&tz->trips[i], data); if (ret) From 0d9741abd1c583e7bedb178358a9abd0981f49ba Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 27 Sep 2023 15:37:26 +0300 Subject: [PATCH 021/111] ACPI: thermal: Fix a small leak in acpi_thermal_add() Free "tz" if the "trip" allocation fails. Fixes: 5fc2189f9335 ("ACPI: thermal: Create and populate trip points table earlier") Signed-off-by: Dan Carpenter Signed-off-by: Rafael J. Wysocki --- drivers/acpi/thermal.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 10720a038846..f8a95939c88d 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -928,8 +928,10 @@ static int acpi_thermal_add(struct acpi_device *device) acpi_thermal_guess_offset(tz, crit_temp); trip = kcalloc(trip_count, sizeof(*trip), GFP_KERNEL); - if (!trip) - return -ENOMEM; + if (!trip) { + result = -ENOMEM; + goto free_memory; + } tz->trip_table = trip; From 0fa1bf34980eba19a5f07f97297bbd60b796e6d1 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 21 Sep 2023 19:48:33 +0200 Subject: [PATCH 022/111] ACPI: thermal: Add device list to struct acpi_thermal_trip The device lists present in struct acpi_thermal_passive and struct acpi_thermal_active can be located in struct acpi_thermal_trip which then will allow the same code to be used for handling both the passive and active trip points, so make that change. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/acpi/thermal.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index f8a95939c88d..4248669eb228 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -81,11 +81,11 @@ static struct workqueue_struct *acpi_thermal_pm_queue; struct acpi_thermal_trip { unsigned long temperature; + struct acpi_handle_list devices; }; struct acpi_thermal_passive { struct acpi_thermal_trip trip; - struct acpi_handle_list devices; unsigned long tc1; unsigned long tc2; unsigned long tsp; @@ -93,7 +93,6 @@ struct acpi_thermal_passive { struct acpi_thermal_active { struct acpi_thermal_trip trip; - struct acpi_handle_list devices; }; struct acpi_thermal_trips { @@ -205,6 +204,7 @@ static void acpi_thermal_update_passive_trip(struct acpi_thermal *tz) static bool update_passive_devices(struct acpi_thermal *tz, bool compare) { + struct acpi_thermal_trip *acpi_trip = &tz->trips.passive.trip; struct acpi_handle_list devices; acpi_status status; @@ -217,10 +217,10 @@ static bool update_passive_devices(struct acpi_thermal *tz, bool compare) return false; } - if (compare && memcmp(&tz->trips.passive.devices, &devices, sizeof(devices))) + if (compare && memcmp(&acpi_trip->devices, &devices, sizeof(devices))) ACPI_THERMAL_TRIPS_EXCEPTION(tz, "device"); - memcpy(&tz->trips.passive.devices, &devices, sizeof(devices)); + memcpy(&acpi_trip->devices, &devices, sizeof(devices)); return true; } @@ -276,6 +276,7 @@ static void acpi_thermal_update_active_trip(struct acpi_thermal *tz, int index) static bool update_active_devices(struct acpi_thermal *tz, int index, bool compare) { char method[] = { '_', 'A', 'L', '0' + index, '\0' }; + struct acpi_thermal_trip *acpi_trip = &tz->trips.active[index].trip; struct acpi_handle_list devices; acpi_status status; @@ -289,10 +290,10 @@ static bool update_active_devices(struct acpi_thermal *tz, int index, bool compa return false; } - if (compare && memcmp(&tz->trips.active[index].devices, &devices, sizeof(devices))) + if (compare && memcmp(&acpi_trip->devices, &devices, sizeof(devices))) ACPI_THERMAL_TRIPS_EXCEPTION(tz, "device"); - memcpy(&tz->trips.active[index].devices, &devices, sizeof(devices)); + memcpy(&acpi_trip->devices, &devices, sizeof(devices)); return true; } @@ -602,6 +603,7 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, { struct acpi_device *device = cdev->devdata; struct acpi_thermal *tz = thermal_zone_device_priv(thermal); + struct acpi_thermal_trip *acpi_trip; struct acpi_device *dev; acpi_handle handle; int i; @@ -615,10 +617,11 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, if (tz->trips.hot_valid) trip++; - if (acpi_thermal_trip_valid(&tz->trips.passive.trip)) { + acpi_trip = &tz->trips.passive.trip; + if (acpi_thermal_trip_valid(acpi_trip)) { trip++; - for (i = 0; i < tz->trips.passive.devices.count; i++) { - handle = tz->trips.passive.devices.handles[i]; + for (i = 0; i < acpi_trip->devices.count; i++) { + handle = acpi_trip->devices.handles[i]; dev = acpi_fetch_acpi_dev(handle); if (dev != device) continue; @@ -640,12 +643,13 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, } for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - if (!acpi_thermal_trip_valid(&tz->trips.active[i].trip)) + acpi_trip = &tz->trips.active[i].trip; + if (!acpi_thermal_trip_valid(acpi_trip)) break; trip++; - for (j = 0; j < tz->trips.active[i].devices.count; j++) { - handle = tz->trips.active[i].devices.handles[j]; + for (j = 0; j < acpi_trip->devices.count; j++) { + handle = acpi_trip->devices.handles[j]; dev = acpi_fetch_acpi_dev(handle); if (dev != device) continue; @@ -1037,11 +1041,13 @@ static int acpi_thermal_resume(struct device *dev) return -EINVAL; for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - if (!acpi_thermal_trip_valid(&tz->trips.active[i].trip)) + struct acpi_thermal_trip *acpi_trip = &tz->trips.active[i].trip; + + if (!acpi_thermal_trip_valid(acpi_trip)) break; - for (j = 0; j < tz->trips.active[i].devices.count; j++) { - acpi_bus_update_power(tz->trips.active[i].devices.handles[j], + for (j = 0; j < acpi_trip->devices.count; j++) { + acpi_bus_update_power(acpi_trip->devices.handles[j], &power_state); } } From 317508c65f1f966367553ef84f5d8eba16720f32 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 21 Sep 2023 19:49:24 +0200 Subject: [PATCH 023/111] ACPI: thermal: Collapse trip devices update functions In order to reduce code duplication, merge update_passive_devices() and update_active_devices() into one function called update_trip_devices() that will be used for updating both the passive and active trip points. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/acpi/thermal.c | 53 ++++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 33 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 4248669eb228..93d2ab552686 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -43,6 +43,8 @@ #define ACPI_THERMAL_MAX_ACTIVE 10 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65 +#define ACPI_THERMAL_TRIP_PASSIVE (-1) + /* * This exception is thrown out in two cases: * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid @@ -202,18 +204,25 @@ static void acpi_thermal_update_passive_trip(struct acpi_thermal *tz) ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } -static bool update_passive_devices(struct acpi_thermal *tz, bool compare) +static bool update_trip_devices(struct acpi_thermal *tz, + struct acpi_thermal_trip *acpi_trip, + int index, bool compare) { - struct acpi_thermal_trip *acpi_trip = &tz->trips.passive.trip; struct acpi_handle_list devices; + char method[] = "_PSL"; acpi_status status; + if (index != ACPI_THERMAL_TRIP_PASSIVE) { + method[1] = 'A'; + method[2] = 'L'; + method[3] = '0' + index; + } + memset(&devices, 0, sizeof(devices)); - status = acpi_evaluate_reference(tz->device->handle, "_PSL", NULL, &devices); + status = acpi_evaluate_reference(tz->device->handle, method, NULL, &devices); if (ACPI_FAILURE(status)) { - acpi_handle_info(tz->device->handle, - "Missing device list for passive threshold\n"); + acpi_handle_info(tz->device->handle, "%s evaluation failure\n", method); return false; } @@ -231,8 +240,9 @@ static void acpi_thermal_update_passive_devices(struct acpi_thermal *tz) if (!acpi_thermal_trip_valid(acpi_trip)) return; - if (update_passive_devices(tz, true)) + if (update_trip_devices(tz, acpi_trip, ACPI_THERMAL_TRIP_PASSIVE, true)) { return; + } acpi_trip->temperature = THERMAL_TEMP_INVALID; ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); @@ -273,30 +283,6 @@ static void acpi_thermal_update_active_trip(struct acpi_thermal *tz, int index) ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } -static bool update_active_devices(struct acpi_thermal *tz, int index, bool compare) -{ - char method[] = { '_', 'A', 'L', '0' + index, '\0' }; - struct acpi_thermal_trip *acpi_trip = &tz->trips.active[index].trip; - struct acpi_handle_list devices; - acpi_status status; - - memset(&devices, 0, sizeof(devices)); - - status = acpi_evaluate_reference(tz->device->handle, method, NULL, &devices); - if (ACPI_FAILURE(status)) { - acpi_handle_info(tz->device->handle, - "Missing device list for active threshold %d\n", - index); - return false; - } - - if (compare && memcmp(&acpi_trip->devices, &devices, sizeof(devices))) - ACPI_THERMAL_TRIPS_EXCEPTION(tz, "device"); - - memcpy(&acpi_trip->devices, &devices, sizeof(devices)); - return true; -} - static void acpi_thermal_update_active_devices(struct acpi_thermal *tz, int index) { struct acpi_thermal_trip *acpi_trip = &tz->trips.active[index].trip; @@ -304,7 +290,7 @@ static void acpi_thermal_update_active_devices(struct acpi_thermal *tz, int inde if (!acpi_thermal_trip_valid(acpi_trip)) return; - if (update_active_devices(tz, index, true)) + if (update_trip_devices(tz, acpi_trip, index, true)) return; acpi_trip->temperature = THERMAL_TEMP_INVALID; @@ -460,7 +446,8 @@ static bool acpi_thermal_init_passive_trip(struct acpi_thermal *tz) tz->trips.passive.tsp = tmp; - if (!update_passive_devices(tz, false)) + if (!update_trip_devices(tz, &tz->trips.passive.trip, + ACPI_THERMAL_TRIP_PASSIVE, false)) goto fail; tz->trips.passive.trip.temperature = temp; @@ -482,7 +469,7 @@ static bool acpi_thermal_init_active_trip(struct acpi_thermal *tz, int index) if (temp == THERMAL_TEMP_INVALID) goto fail; - if (!update_active_devices(tz, index, false)) + if (!update_trip_devices(tz, &tz->trips.active[index].trip, index, false)) goto fail; tz->trips.active[index].trip.temperature = temp; From 54fc61a106c9b7fb55a3c6a595349826c0548468 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 21 Sep 2023 19:50:08 +0200 Subject: [PATCH 024/111] ACPI: thermal: Collapse trip devices update function wrappers In order to reduce code duplicationeve further, merge acpi_thermal_update_passive/active_devices() into one function called acpi_thermal_update_trip_devices() that will be used for updating both the passive and active trip points. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/acpi/thermal.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 93d2ab552686..ebe11288d7e0 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -233,14 +233,16 @@ static bool update_trip_devices(struct acpi_thermal *tz, return true; } -static void acpi_thermal_update_passive_devices(struct acpi_thermal *tz) +static void acpi_thermal_update_trip_devices(struct acpi_thermal *tz, int index) { - struct acpi_thermal_trip *acpi_trip = &tz->trips.passive.trip; + struct acpi_thermal_trip *acpi_trip; + acpi_trip = index == ACPI_THERMAL_TRIP_PASSIVE ? + &tz->trips.passive.trip : &tz->trips.active[index].trip; if (!acpi_thermal_trip_valid(acpi_trip)) return; - if (update_trip_devices(tz, acpi_trip, ACPI_THERMAL_TRIP_PASSIVE, true)) { + if (update_trip_devices(tz, acpi_trip, index, true)) { return; } @@ -283,20 +285,6 @@ static void acpi_thermal_update_active_trip(struct acpi_thermal *tz, int index) ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } -static void acpi_thermal_update_active_devices(struct acpi_thermal *tz, int index) -{ - struct acpi_thermal_trip *acpi_trip = &tz->trips.active[index].trip; - - if (!acpi_thermal_trip_valid(acpi_trip)) - return; - - if (update_trip_devices(tz, acpi_trip, index, true)) - return; - - acpi_trip->temperature = THERMAL_TEMP_INVALID; - ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); -} - static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data) { struct acpi_thermal_trip *acpi_trip = trip->priv; @@ -324,9 +312,9 @@ static void acpi_thermal_adjust_thermal_zone(struct thermal_zone_device *thermal for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) acpi_thermal_update_active_trip(tz, i); } else { - acpi_thermal_update_passive_devices(tz); + acpi_thermal_update_trip_devices(tz, ACPI_THERMAL_TRIP_PASSIVE); for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) - acpi_thermal_update_active_devices(tz, i); + acpi_thermal_update_trip_devices(tz, i); } for_each_thermal_trip(tz->thermal_zone, acpi_thermal_adjust_trip, tz); From 3e7d6f396d74a3e40c390bb53947938957426097 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 21 Sep 2023 19:51:19 +0200 Subject: [PATCH 025/111] ACPI: thermal: Merge trip initialization functions In order to reduce code duplicationeve further, merge acpi_thermal_init_passive/active_trip() into one function called acpi_thermal_init_trip() that will be used for initializing both the passive and active trip points. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/acpi/thermal.c | 64 ++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index ebe11288d7e0..c303688ead71 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -399,72 +399,68 @@ static long acpi_thermal_get_hot_trip(struct acpi_thermal *tz) return tmp; } -static bool acpi_thermal_init_passive_trip(struct acpi_thermal *tz) +static bool passive_trip_params_init(struct acpi_thermal *tz) { unsigned long long tmp; acpi_status status; - int temp; - - if (psv == -1) - goto fail; - - if (psv > 0) { - temp = celsius_to_deci_kelvin(psv); - } else { - temp = get_passive_temp(tz); - if (temp == THERMAL_TEMP_INVALID) - goto fail; - } status = acpi_evaluate_integer(tz->device->handle, "_TC1", NULL, &tmp); if (ACPI_FAILURE(status)) - goto fail; + return false; tz->trips.passive.tc1 = tmp; status = acpi_evaluate_integer(tz->device->handle, "_TC2", NULL, &tmp); if (ACPI_FAILURE(status)) - goto fail; + return false; tz->trips.passive.tc2 = tmp; status = acpi_evaluate_integer(tz->device->handle, "_TSP", NULL, &tmp); if (ACPI_FAILURE(status)) - goto fail; + return false; tz->trips.passive.tsp = tmp; - if (!update_trip_devices(tz, &tz->trips.passive.trip, - ACPI_THERMAL_TRIP_PASSIVE, false)) - goto fail; - - tz->trips.passive.trip.temperature = temp; return true; - -fail: - tz->trips.passive.trip.temperature = THERMAL_TEMP_INVALID; - return false; } -static bool acpi_thermal_init_active_trip(struct acpi_thermal *tz, int index) +static bool acpi_thermal_init_trip(struct acpi_thermal *tz, int index) { + struct acpi_thermal_trip *acpi_trip; long temp; - if (act == -1) - goto fail; + if (index == ACPI_THERMAL_TRIP_PASSIVE) { + acpi_trip = &tz->trips.passive.trip; + + if (psv == -1) + goto fail; + + if (!passive_trip_params_init(tz)) + goto fail; + + temp = psv > 0 ? celsius_to_deci_kelvin(psv) : + get_passive_temp(tz); + } else { + acpi_trip = &tz->trips.active[index].trip; + + if (act == -1) + goto fail; + + temp = get_active_temp(tz, index); + } - temp = get_active_temp(tz, index); if (temp == THERMAL_TEMP_INVALID) goto fail; - if (!update_trip_devices(tz, &tz->trips.active[index].trip, index, false)) + if (!update_trip_devices(tz, acpi_trip, index, false)) goto fail; - tz->trips.active[index].trip.temperature = temp; + acpi_trip->temperature = temp; return true; fail: - tz->trips.active[index].trip.temperature = THERMAL_TEMP_INVALID; + acpi_trip->temperature = THERMAL_TEMP_INVALID; return false; } @@ -473,11 +469,11 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) unsigned int count = 0; int i; - if (acpi_thermal_init_passive_trip(tz)) + if (acpi_thermal_init_trip(tz, ACPI_THERMAL_TRIP_PASSIVE)) count++; for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - if (acpi_thermal_init_active_trip(tz, i)) + if (acpi_thermal_init_trip(tz, i)) count++; else break; From 2c7b4bfadef08cc0995c24a7b9eb120fe897165f Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 21 Sep 2023 19:52:44 +0200 Subject: [PATCH 026/111] thermal: core: Store trip pointer in struct thermal_instance Replace the integer trip number stored in struct thermal_instance with a pointer to the relevant trip and adjust the code using the structure in question accordingly. The main reason for making this change is to allow the trip point to cooling device binding code more straightforward, as illustrated by subsequent modifications of the ACPI thermal driver, but it also helps to clarify the overall design and allows the governor code overhead to be reduced (through subsequent modifications). The only case in which it adds complexity is trip_point_show() that needs to walk the trips[] table to find the index of the given trip point, but this is not a critical path and the interface that trip_point_show() belongs to is problematic anyway (for instance, it doesn't cover the case when the same cooling devices is associated with multiple trip points). This is a preliminary change and the affected code will be refined by a series of subsequent modifications of thermal governors, the core and the ACPI thermal driver. The general functionality is not expected to be affected by this change. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/thermal/gov_bang_bang.c | 23 ++++++++--------------- drivers/thermal/gov_fair_share.c | 5 +++-- drivers/thermal/gov_power_allocator.c | 11 ++++++++--- drivers/thermal/gov_step_wise.c | 16 +++++++--------- drivers/thermal/thermal_core.c | 15 ++++++++++----- drivers/thermal/thermal_core.h | 4 +++- drivers/thermal/thermal_helpers.c | 5 ++++- drivers/thermal/thermal_sysfs.c | 3 ++- drivers/thermal/thermal_trip.c | 15 +++++++++++++++ 9 files changed, 60 insertions(+), 37 deletions(-) diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c index 1b121066521f..49cdfaa3a927 100644 --- a/drivers/thermal/gov_bang_bang.c +++ b/drivers/thermal/gov_bang_bang.c @@ -13,28 +13,21 @@ #include "thermal_core.h" -static int thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_id) +static int thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_index) { - struct thermal_trip trip; + const struct thermal_trip *trip = &tz->trips[trip_index]; struct thermal_instance *instance; - int ret; - ret = __thermal_zone_get_trip(tz, trip_id, &trip); - if (ret) { - pr_warn_once("Failed to retrieve trip point %d\n", trip_id); - return ret; - } - - if (!trip.hysteresis) + if (!trip->hysteresis) dev_info_once(&tz->device, "Zero hysteresis value for thermal zone %s\n", tz->type); dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n", - trip_id, trip.temperature, tz->temperature, - trip.hysteresis); + trip_index, trip->temperature, tz->temperature, + trip->hysteresis); list_for_each_entry(instance, &tz->thermal_instances, tz_node) { - if (instance->trip != trip_id) + if (instance->trip != trip) continue; /* in case fan is in initial state, switch the fan off */ @@ -52,10 +45,10 @@ static int thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_id) * enable fan when temperature exceeds trip_temp and disable * the fan in case it falls below trip_temp minus hysteresis */ - if (instance->target == 0 && tz->temperature >= trip.temperature) + if (instance->target == 0 && tz->temperature >= trip->temperature) instance->target = 1; else if (instance->target == 1 && - tz->temperature <= trip.temperature - trip.hysteresis) + tz->temperature <= trip->temperature - trip->hysteresis) instance->target = 0; dev_dbg(&instance->cdev->device, "target=%d\n", diff --git a/drivers/thermal/gov_fair_share.c b/drivers/thermal/gov_fair_share.c index 03c2daeb6ee8..2abeb8979f50 100644 --- a/drivers/thermal/gov_fair_share.c +++ b/drivers/thermal/gov_fair_share.c @@ -49,7 +49,7 @@ static long get_target_state(struct thermal_zone_device *tz, /** * fair_share_throttle - throttles devices associated with the given zone * @tz: thermal_zone_device - * @trip: trip point index + * @trip_index: trip point index * * Throttling Logic: This uses three parameters to calculate the new * throttle state of the cooling devices associated with the given zone. @@ -65,8 +65,9 @@ static long get_target_state(struct thermal_zone_device *tz, * (Heavily assumes the trip points are in ascending order) * new_state of cooling device = P3 * P2 * P1 */ -static int fair_share_throttle(struct thermal_zone_device *tz, int trip) +static int fair_share_throttle(struct thermal_zone_device *tz, int trip_index) { + const struct thermal_trip *trip = &tz->trips[trip_index]; struct thermal_instance *instance; int total_weight = 0; int total_instance = 0; diff --git a/drivers/thermal/gov_power_allocator.c b/drivers/thermal/gov_power_allocator.c index 8642f1096b91..1faf55446ba2 100644 --- a/drivers/thermal/gov_power_allocator.c +++ b/drivers/thermal/gov_power_allocator.c @@ -90,12 +90,14 @@ static u32 estimate_sustainable_power(struct thermal_zone_device *tz) u32 sustainable_power = 0; struct thermal_instance *instance; struct power_allocator_params *params = tz->governor_data; + const struct thermal_trip *trip_max_desired_temperature = + &tz->trips[params->trip_max_desired_temperature]; list_for_each_entry(instance, &tz->thermal_instances, tz_node) { struct thermal_cooling_device *cdev = instance->cdev; u32 min_power; - if (instance->trip != params->trip_max_desired_temperature) + if (instance->trip != trip_max_desired_temperature) continue; if (!cdev_is_power_actor(cdev)) @@ -383,12 +385,13 @@ static int allocate_power(struct thermal_zone_device *tz, { struct thermal_instance *instance; struct power_allocator_params *params = tz->governor_data; + const struct thermal_trip *trip_max_desired_temperature = + &tz->trips[params->trip_max_desired_temperature]; u32 *req_power, *max_power, *granted_power, *extra_actor_power; u32 *weighted_req_power; u32 total_req_power, max_allocatable_power, total_weighted_req_power; u32 total_granted_power, power_range; int i, num_actors, total_weight, ret = 0; - int trip_max_desired_temperature = params->trip_max_desired_temperature; num_actors = 0; total_weight = 0; @@ -564,12 +567,14 @@ static void allow_maximum_power(struct thermal_zone_device *tz, bool update) { struct thermal_instance *instance; struct power_allocator_params *params = tz->governor_data; + const struct thermal_trip *trip_max_desired_temperature = + &tz->trips[params->trip_max_desired_temperature]; u32 req_power; list_for_each_entry(instance, &tz->thermal_instances, tz_node) { struct thermal_cooling_device *cdev = instance->cdev; - if ((instance->trip != params->trip_max_desired_temperature) || + if ((instance->trip != trip_max_desired_temperature) || (!cdev_is_power_actor(instance->cdev))) continue; diff --git a/drivers/thermal/gov_step_wise.c b/drivers/thermal/gov_step_wise.c index 1050fb4d94c2..849dc1ec8d27 100644 --- a/drivers/thermal/gov_step_wise.c +++ b/drivers/thermal/gov_step_wise.c @@ -81,26 +81,24 @@ static void update_passive_instance(struct thermal_zone_device *tz, static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_id) { + const struct thermal_trip *trip = &tz->trips[trip_id]; enum thermal_trend trend; struct thermal_instance *instance; - struct thermal_trip trip; bool throttle = false; int old_target; - __thermal_zone_get_trip(tz, trip_id, &trip); - trend = get_tz_trend(tz, trip_id); - if (tz->temperature >= trip.temperature) { + if (tz->temperature >= trip->temperature) { throttle = true; - trace_thermal_zone_trip(tz, trip_id, trip.type); + trace_thermal_zone_trip(tz, trip_id, trip->type); } dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n", - trip_id, trip.type, trip.temperature, trend, throttle); + trip_id, trip->type, trip->temperature, trend, throttle); list_for_each_entry(instance, &tz->thermal_instances, tz_node) { - if (instance->trip != trip_id) + if (instance->trip != trip) continue; old_target = instance->target; @@ -114,11 +112,11 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_id /* Activate a passive thermal instance */ if (old_target == THERMAL_NO_TARGET && instance->target != THERMAL_NO_TARGET) - update_passive_instance(tz, trip.type, 1); + update_passive_instance(tz, trip->type, 1); /* Deactivate a passive thermal instance */ else if (old_target != THERMAL_NO_TARGET && instance->target == THERMAL_NO_TARGET) - update_passive_instance(tz, trip.type, -1); + update_passive_instance(tz, trip->type, -1); instance->initialized = true; mutex_lock(&instance->cdev->lock); diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 38d393f139d8..31fe14a96d13 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -602,7 +602,7 @@ struct thermal_zone_device *thermal_zone_get_by_id(int id) /** * thermal_zone_bind_cooling_device() - bind a cooling device to a thermal zone * @tz: pointer to struct thermal_zone_device - * @trip: indicates which trip point the cooling devices is + * @trip_index: indicates which trip point the cooling devices is * associated with in this thermal zone. * @cdev: pointer to struct thermal_cooling_device * @upper: the Maximum cooling state for this trip point. @@ -622,7 +622,7 @@ struct thermal_zone_device *thermal_zone_get_by_id(int id) * Return: 0 on success, the proper error value otherwise. */ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, - int trip, + int trip_index, struct thermal_cooling_device *cdev, unsigned long upper, unsigned long lower, unsigned int weight) @@ -631,12 +631,15 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, struct thermal_instance *pos; struct thermal_zone_device *pos1; struct thermal_cooling_device *pos2; + const struct thermal_trip *trip; bool upper_no_limit; int result; - if (trip >= tz->num_trips || trip < 0) + if (trip_index >= tz->num_trips || trip_index < 0) return -EINVAL; + trip = &tz->trips[trip_index]; + list_for_each_entry(pos1, &thermal_tz_list, node) { if (pos1 == tz) break; @@ -739,7 +742,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_bind_cooling_device); * thermal_zone_unbind_cooling_device() - unbind a cooling device from a * thermal zone. * @tz: pointer to a struct thermal_zone_device. - * @trip: indicates which trip point the cooling devices is + * @trip_index: indicates which trip point the cooling devices is * associated with in this thermal zone. * @cdev: pointer to a struct thermal_cooling_device. * @@ -750,13 +753,15 @@ EXPORT_SYMBOL_GPL(thermal_zone_bind_cooling_device); * Return: 0 on success, the proper error value otherwise. */ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, - int trip, + int trip_index, struct thermal_cooling_device *cdev) { struct thermal_instance *pos, *next; + const struct thermal_trip *trip; mutex_lock(&tz->lock); mutex_lock(&cdev->lock); + trip = &tz->trips[trip_index]; list_for_each_entry_safe(pos, next, &tz->thermal_instances, tz_node) { if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { list_del(&pos->tz_node); diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index de884bea28b6..024e82ebf592 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -87,7 +87,7 @@ struct thermal_instance { char name[THERMAL_NAME_LENGTH]; struct thermal_zone_device *tz; struct thermal_cooling_device *cdev; - int trip; + const struct thermal_trip *trip; bool initialized; unsigned long upper; /* Highest cooling state for this trip point */ unsigned long lower; /* Lowest cooling state for this trip point */ @@ -119,6 +119,8 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz, void __thermal_zone_set_trips(struct thermal_zone_device *tz); int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id, struct thermal_trip *trip); +int thermal_zone_trip_id(struct thermal_zone_device *tz, + const struct thermal_trip *trip); int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp); /* sysfs I/F */ diff --git a/drivers/thermal/thermal_helpers.c b/drivers/thermal/thermal_helpers.c index 4d66372c9629..c1d0af73c85d 100644 --- a/drivers/thermal/thermal_helpers.c +++ b/drivers/thermal/thermal_helpers.c @@ -42,14 +42,17 @@ int get_tz_trend(struct thermal_zone_device *tz, int trip_index) struct thermal_instance * get_thermal_instance(struct thermal_zone_device *tz, - struct thermal_cooling_device *cdev, int trip) + struct thermal_cooling_device *cdev, int trip_index) { struct thermal_instance *pos = NULL; struct thermal_instance *target_instance = NULL; + const struct thermal_trip *trip; mutex_lock(&tz->lock); mutex_lock(&cdev->lock); + trip = &tz->trips[trip_index]; + list_for_each_entry(pos, &tz->thermal_instances, tz_node) { if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { target_instance = pos; diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c index 4e6a97db894e..eef40d4f3063 100644 --- a/drivers/thermal/thermal_sysfs.c +++ b/drivers/thermal/thermal_sysfs.c @@ -943,7 +943,8 @@ trip_point_show(struct device *dev, struct device_attribute *attr, char *buf) instance = container_of(attr, struct thermal_instance, attr); - return sprintf(buf, "%d\n", instance->trip); + return sprintf(buf, "%d\n", + thermal_zone_trip_id(instance->tz, instance->trip)); } ssize_t diff --git a/drivers/thermal/thermal_trip.c b/drivers/thermal/thermal_trip.c index 1cadb3b5d104..a8e92a89b2b8 100644 --- a/drivers/thermal/thermal_trip.c +++ b/drivers/thermal/thermal_trip.c @@ -157,3 +157,18 @@ int thermal_zone_set_trip(struct thermal_zone_device *tz, int trip_id, return 0; } + +int thermal_zone_trip_id(struct thermal_zone_device *tz, + const struct thermal_trip *trip) +{ + int i; + + lockdep_assert_held(&tz->lock); + + for (i = 0; i < tz->num_trips; i++) { + if (&tz->trips[i] == trip) + return i; + } + + return -ENODATA; +} From d069ed6b752f91cea6341a9c60be42837678a7f5 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 21 Sep 2023 20:01:43 +0200 Subject: [PATCH 027/111] thermal: core: Allow trip pointers to be used for cooling device binding Add new helper functions, thermal_bind_cdev_to_trip() and thermal_unbind_cdev_from_trip(), to allow a trip pointer to be used for binding a cooling device to a trip point and unbinding it, respectively, and redefine the existing helpers, thermal_zone_bind_cooling_device() and thermal_zone_unbind_cooling_device(), as wrappers around the new ones, respectively. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/thermal/thermal_core.c | 54 +++++++++++++++++++++------------- include/linux/thermal.h | 8 +++++ 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 31fe14a96d13..45d0aa0b69b7 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -600,10 +600,9 @@ struct thermal_zone_device *thermal_zone_get_by_id(int id) */ /** - * thermal_zone_bind_cooling_device() - bind a cooling device to a thermal zone + * thermal_bind_cdev_to_trip - bind a cooling device to a thermal zone * @tz: pointer to struct thermal_zone_device - * @trip_index: indicates which trip point the cooling devices is - * associated with in this thermal zone. + * @trip: trip point the cooling devices is associated with in this zone. * @cdev: pointer to struct thermal_cooling_device * @upper: the Maximum cooling state for this trip point. * THERMAL_NO_LIMIT means no upper limit, @@ -621,8 +620,8 @@ struct thermal_zone_device *thermal_zone_get_by_id(int id) * * Return: 0 on success, the proper error value otherwise. */ -int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, - int trip_index, +int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz, + const struct thermal_trip *trip, struct thermal_cooling_device *cdev, unsigned long upper, unsigned long lower, unsigned int weight) @@ -631,15 +630,9 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, struct thermal_instance *pos; struct thermal_zone_device *pos1; struct thermal_cooling_device *pos2; - const struct thermal_trip *trip; bool upper_no_limit; int result; - if (trip_index >= tz->num_trips || trip_index < 0) - return -EINVAL; - - trip = &tz->trips[trip_index]; - list_for_each_entry(pos1, &thermal_tz_list, node) { if (pos1 == tz) break; @@ -736,14 +729,26 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, kfree(dev); return result; } +EXPORT_SYMBOL_GPL(thermal_bind_cdev_to_trip); + +int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, + int trip_index, + struct thermal_cooling_device *cdev, + unsigned long upper, unsigned long lower, + unsigned int weight) +{ + if (trip_index < 0 || trip_index >= tz->num_trips) + return -EINVAL; + + return thermal_bind_cdev_to_trip(tz, &tz->trips[trip_index], cdev, + upper, lower, weight); +} EXPORT_SYMBOL_GPL(thermal_zone_bind_cooling_device); /** - * thermal_zone_unbind_cooling_device() - unbind a cooling device from a - * thermal zone. + * thermal_unbind_cdev_from_trip - unbind a cooling device from a thermal zone. * @tz: pointer to a struct thermal_zone_device. - * @trip_index: indicates which trip point the cooling devices is - * associated with in this thermal zone. + * @trip: trip point the cooling devices is associated with in this zone. * @cdev: pointer to a struct thermal_cooling_device. * * This interface function unbind a thermal cooling device from the certain @@ -752,16 +757,14 @@ EXPORT_SYMBOL_GPL(thermal_zone_bind_cooling_device); * * Return: 0 on success, the proper error value otherwise. */ -int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, - int trip_index, - struct thermal_cooling_device *cdev) +int thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz, + const struct thermal_trip *trip, + struct thermal_cooling_device *cdev) { struct thermal_instance *pos, *next; - const struct thermal_trip *trip; mutex_lock(&tz->lock); mutex_lock(&cdev->lock); - trip = &tz->trips[trip_index]; list_for_each_entry_safe(pos, next, &tz->thermal_instances, tz_node) { if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { list_del(&pos->tz_node); @@ -784,6 +787,17 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, kfree(pos); return 0; } +EXPORT_SYMBOL_GPL(thermal_unbind_cdev_from_trip); + +int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, + int trip_index, + struct thermal_cooling_device *cdev) +{ + if (trip_index < 0 || trip_index >= tz->num_trips) + return -EINVAL; + + return thermal_unbind_cdev_from_trip(tz, &tz->trips[trip_index], cdev); +} EXPORT_SYMBOL_GPL(thermal_zone_unbind_cooling_device); static void thermal_release(struct device *dev) diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 6cfcae22ba12..6710a4ace992 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -320,10 +320,18 @@ const char *thermal_zone_device_type(struct thermal_zone_device *tzd); int thermal_zone_device_id(struct thermal_zone_device *tzd); struct device *thermal_zone_device(struct thermal_zone_device *tzd); +int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz, + const struct thermal_trip *trip, + struct thermal_cooling_device *cdev, + unsigned long upper, unsigned long lower, + unsigned int weight); int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int, struct thermal_cooling_device *, unsigned long, unsigned long, unsigned int); +int thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz, + const struct thermal_trip *trip, + struct thermal_cooling_device *cdev); int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int, struct thermal_cooling_device *); void thermal_zone_device_update(struct thermal_zone_device *, From 2713b83cb3b0ca78dc16a6968d58bee1342c4bc7 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 28 Sep 2023 17:45:59 +0200 Subject: [PATCH 028/111] ACPI: thermal: Mark uninitialized active trips as invalid After removing the valid flag from struct acpi_thermal_trip, the trip temperature value is used in validity checks, so it must be THERMAL_TEMP_INVALID for the active trip entries in struct acpi_thermal_trips that are not going to be used (because the corresponding objects are not present in the ACPI tables, for example). Accordingly, modify acpi_thermal_get_trip_points() to set the temperature value to THERMAL_TEMP_INVALID for trip point entries skipped by it after acpi_thermal_init_trip() has returned 'false' for an active trip. Fixes: 058f5e407deb ("ACPI: thermal: Drop valid flag from struct acpi_thermal_trip") Signed-off-by: Rafael J. Wysocki --- drivers/acpi/thermal.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index c303688ead71..0c3160c04d65 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -480,6 +480,9 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) } + while (++i < ACPI_THERMAL_MAX_ACTIVE) + tz->trips.active[i].trip.temperature = THERMAL_TEMP_INVALID; + return count; } From d5ea889246b112e228433a5f27f57af90ca0c1fb Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 21 Sep 2023 20:02:59 +0200 Subject: [PATCH 029/111] ACPI: thermal: Do not use trip indices for cooling device binding Rearrange the ACPI thermal driver's callback functions used for cooling device binding and unbinding, acpi_thermal_bind_cooling_device() and acpi_thermal_unbind_cooling_device(), respectively, so that they use trip pointers instead of trip indices which is more straightforward and allows the driver to become independent of the ordering of trips in the thermal zone structure. The general functionality is not expected to be changed. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/acpi/thermal.c | 106 ++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 64 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 0c3160c04d65..03cc42064467 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -571,94 +571,72 @@ static void acpi_thermal_zone_device_critical(struct thermal_zone_device *therma thermal_zone_device_critical(thermal); } -static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, - struct thermal_cooling_device *cdev, - bool bind) +struct acpi_thermal_bind_data { + struct thermal_zone_device *thermal; + struct thermal_cooling_device *cdev; + bool bind; +}; + +static int bind_unbind_cdev_cb(struct thermal_trip *trip, void *arg) { - struct acpi_device *device = cdev->devdata; - struct acpi_thermal *tz = thermal_zone_device_priv(thermal); - struct acpi_thermal_trip *acpi_trip; - struct acpi_device *dev; - acpi_handle handle; + struct acpi_thermal_trip *acpi_trip = trip->priv; + struct acpi_thermal_bind_data *bd = arg; + struct thermal_zone_device *thermal = bd->thermal; + struct thermal_cooling_device *cdev = bd->cdev; + struct acpi_device *cdev_adev = cdev->devdata; int i; - int j; - int trip = -1; - int result = 0; - if (tz->trips.critical_valid) - trip++; + /* Skip critical and hot trips. */ + if (!acpi_trip) + return 0; - if (tz->trips.hot_valid) - trip++; + for (i = 0; i < acpi_trip->devices.count; i++) { + acpi_handle handle = acpi_trip->devices.handles[i]; + struct acpi_device *adev = acpi_fetch_acpi_dev(handle); - acpi_trip = &tz->trips.passive.trip; - if (acpi_thermal_trip_valid(acpi_trip)) { - trip++; - for (i = 0; i < acpi_trip->devices.count; i++) { - handle = acpi_trip->devices.handles[i]; - dev = acpi_fetch_acpi_dev(handle); - if (dev != device) - continue; + if (adev != cdev_adev) + continue; - if (bind) - result = thermal_zone_bind_cooling_device( - thermal, trip, cdev, - THERMAL_NO_LIMIT, - THERMAL_NO_LIMIT, - THERMAL_WEIGHT_DEFAULT); - else - result = - thermal_zone_unbind_cooling_device( - thermal, trip, cdev); + if (bd->bind) { + int ret; - if (result) - goto failed; + ret = thermal_bind_cdev_to_trip(thermal, trip, cdev, + THERMAL_NO_LIMIT, + THERMAL_NO_LIMIT, + THERMAL_WEIGHT_DEFAULT); + if (ret) + return ret; + } else { + thermal_unbind_cdev_from_trip(thermal, trip, cdev); } } - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - acpi_trip = &tz->trips.active[i].trip; - if (!acpi_thermal_trip_valid(acpi_trip)) - break; + return 0; +} - trip++; - for (j = 0; j < acpi_trip->devices.count; j++) { - handle = acpi_trip->devices.handles[j]; - dev = acpi_fetch_acpi_dev(handle); - if (dev != device) - continue; +static int acpi_thermal_bind_unbind_cdev(struct thermal_zone_device *thermal, + struct thermal_cooling_device *cdev, + bool bind) +{ + struct acpi_thermal_bind_data bd = { + .thermal = thermal, .cdev = cdev, .bind = bind + }; - if (bind) - result = thermal_zone_bind_cooling_device( - thermal, trip, cdev, - THERMAL_NO_LIMIT, - THERMAL_NO_LIMIT, - THERMAL_WEIGHT_DEFAULT); - else - result = thermal_zone_unbind_cooling_device( - thermal, trip, cdev); - - if (result) - goto failed; - } - } - -failed: - return result; + return for_each_thermal_trip(thermal, bind_unbind_cdev_cb, &bd); } static int acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal, struct thermal_cooling_device *cdev) { - return acpi_thermal_cooling_device_cb(thermal, cdev, true); + return acpi_thermal_bind_unbind_cdev(thermal, cdev, true); } static int acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal, struct thermal_cooling_device *cdev) { - return acpi_thermal_cooling_device_cb(thermal, cdev, false); + return acpi_thermal_bind_unbind_cdev(thermal, cdev, false); } static struct thermal_zone_device_ops acpi_thermal_zone_ops = { From c8f46f43a1db7a9a46cd9313aa434380238e874f Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 21 Sep 2023 20:04:49 +0200 Subject: [PATCH 030/111] ACPI: thermal: Drop critical_valid and hot_valid trip flags The critical_valid and hot_valid flags in struct acpi_thermal_trips are only used during initialization and they are only false if the corresponding trip temperatures are equal to THERMAL_TEMP_INVALID, so drop them and use THERMAL_TEMP_INVALID checks instead of them where applicable. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/acpi/thermal.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 03cc42064467..95464e578ac9 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -100,8 +100,6 @@ struct acpi_thermal_active { struct acpi_thermal_trips { struct acpi_thermal_passive passive; struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE]; - bool critical_valid; - bool hot_valid; }; struct acpi_thermal { @@ -355,13 +353,13 @@ static long acpi_thermal_get_critical_trip(struct acpi_thermal *tz) } if (crt == -1) { acpi_handle_debug(tz->device->handle, "Critical threshold disabled\n"); - goto fail; + return THERMAL_TEMP_INVALID; } status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &tmp); if (ACPI_FAILURE(status)) { acpi_handle_debug(tz->device->handle, "No critical threshold\n"); - goto fail; + return THERMAL_TEMP_INVALID; } if (tmp <= 2732) { /* @@ -369,17 +367,12 @@ static long acpi_thermal_get_critical_trip(struct acpi_thermal *tz) * so discard them as invalid. */ pr_info(FW_BUG "Invalid critical threshold (%llu)\n", tmp); - goto fail; + return THERMAL_TEMP_INVALID; } set: - tz->trips.critical_valid = true; acpi_handle_debug(tz->device->handle, "Critical threshold [%llu]\n", tmp); return tmp; - -fail: - tz->trips.critical_valid = false; - return THERMAL_TEMP_INVALID; } static long acpi_thermal_get_hot_trip(struct acpi_thermal *tz) @@ -389,12 +382,10 @@ static long acpi_thermal_get_hot_trip(struct acpi_thermal *tz) status = acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, &tmp); if (ACPI_FAILURE(status)) { - tz->trips.hot_valid = false; acpi_handle_debug(tz->device->handle, "No hot threshold\n"); return THERMAL_TEMP_INVALID; } - tz->trips.hot_valid = true; acpi_handle_debug(tz->device->handle, "Hot threshold [%llu]\n", tmp); return tmp; } @@ -792,7 +783,7 @@ static void acpi_thermal_aml_dependency_fix(struct acpi_thermal *tz) */ static void acpi_thermal_guess_offset(struct acpi_thermal *tz, long crit_temp) { - if (tz->trips.critical_valid && crit_temp % 5 == 1) + if (crit_temp != THERMAL_TEMP_INVALID && crit_temp % 5 == 1) tz->kelvin_offset = 273100; else tz->kelvin_offset = 273200; @@ -853,11 +844,11 @@ static int acpi_thermal_add(struct acpi_device *device) trip_count = acpi_thermal_get_trip_points(tz); crit_temp = acpi_thermal_get_critical_trip(tz); - if (tz->trips.critical_valid) + if (crit_temp != THERMAL_TEMP_INVALID) trip_count++; hot_temp = acpi_thermal_get_hot_trip(tz); - if (tz->trips.hot_valid) + if (hot_temp != THERMAL_TEMP_INVALID) trip_count++; if (!trip_count) { @@ -891,13 +882,13 @@ static int acpi_thermal_add(struct acpi_device *device) tz->trip_table = trip; - if (tz->trips.critical_valid) { + if (crit_temp != THERMAL_TEMP_INVALID) { trip->type = THERMAL_TRIP_CRITICAL; trip->temperature = acpi_thermal_temp(tz, crit_temp); trip++; } - if (tz->trips.hot_valid) { + if (hot_temp != THERMAL_TEMP_INVALID) { trip->type = THERMAL_TRIP_HOT; trip->temperature = acpi_thermal_temp(tz, hot_temp); trip++; From 03a6d5986c9dea51f05c66a5f2fee6a15e498160 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 21 Sep 2023 20:06:58 +0200 Subject: [PATCH 031/111] ACPI: thermal: Rename structure fields holding temperature in deci-Kelvin Rename structure fields holding temperature values in deci-Kelvin so as to avoid temperature units confusion. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Acked-by: Daniel Lezcano --- drivers/acpi/thermal.c | 46 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 95464e578ac9..d3d6429b98c5 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -82,7 +82,7 @@ MODULE_PARM_DESC(psv, "Disable or override all passive trip points."); static struct workqueue_struct *acpi_thermal_pm_queue; struct acpi_thermal_trip { - unsigned long temperature; + unsigned long temp_dk; struct acpi_handle_list devices; }; @@ -105,8 +105,8 @@ struct acpi_thermal_trips { struct acpi_thermal { struct acpi_device *device; acpi_bus_id name; - unsigned long temperature; - unsigned long last_temperature; + unsigned long temp_dk; + unsigned long last_temp_dk; unsigned long polling_frequency; volatile u8 zombie; struct acpi_thermal_trips trips; @@ -131,16 +131,16 @@ static int acpi_thermal_get_temperature(struct acpi_thermal *tz) if (!tz) return -EINVAL; - tz->last_temperature = tz->temperature; + tz->last_temp_dk = tz->temp_dk; status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp); if (ACPI_FAILURE(status)) return -ENODEV; - tz->temperature = tmp; + tz->temp_dk = tmp; acpi_handle_debug(tz->device->handle, "Temperature is %lu dK\n", - tz->temperature); + tz->temp_dk); return 0; } @@ -175,7 +175,7 @@ static int acpi_thermal_temp(struct acpi_thermal *tz, int temp_deci_k) static bool acpi_thermal_trip_valid(struct acpi_thermal_trip *acpi_trip) { - return acpi_trip->temperature != THERMAL_TEMP_INVALID; + return acpi_trip->temp_dk != THERMAL_TEMP_INVALID; } static long get_passive_temp(struct acpi_thermal *tz) @@ -197,7 +197,7 @@ static void acpi_thermal_update_passive_trip(struct acpi_thermal *tz) if (!acpi_thermal_trip_valid(acpi_trip) || psv > 0) return; - acpi_trip->temperature = get_passive_temp(tz); + acpi_trip->temp_dk = get_passive_temp(tz); if (!acpi_thermal_trip_valid(acpi_trip)) ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } @@ -244,7 +244,7 @@ static void acpi_thermal_update_trip_devices(struct acpi_thermal *tz, int index) return; } - acpi_trip->temperature = THERMAL_TEMP_INVALID; + acpi_trip->temp_dk = THERMAL_TEMP_INVALID; ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } @@ -278,7 +278,7 @@ static void acpi_thermal_update_active_trip(struct acpi_thermal *tz, int index) if (!acpi_thermal_trip_valid(acpi_trip)) return; - acpi_trip->temperature = get_active_temp(tz, index); + acpi_trip->temp_dk = get_active_temp(tz, index); if (!acpi_thermal_trip_valid(acpi_trip)) ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } @@ -292,7 +292,7 @@ static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data) return 0; if (acpi_thermal_trip_valid(acpi_trip)) - trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); + trip->temperature = acpi_thermal_temp(tz, acpi_trip->temp_dk); else trip->temperature = THERMAL_TEMP_INVALID; @@ -447,11 +447,11 @@ static bool acpi_thermal_init_trip(struct acpi_thermal *tz, int index) if (!update_trip_devices(tz, acpi_trip, index, false)) goto fail; - acpi_trip->temperature = temp; + acpi_trip->temp_dk = temp; return true; fail: - acpi_trip->temperature = THERMAL_TEMP_INVALID; + acpi_trip->temp_dk = THERMAL_TEMP_INVALID; return false; } @@ -472,7 +472,7 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) } while (++i < ACPI_THERMAL_MAX_ACTIVE) - tz->trips.active[i].trip.temperature = THERMAL_TEMP_INVALID; + tz->trips.active[i].trip.temp_dk = THERMAL_TEMP_INVALID; return count; } @@ -491,7 +491,7 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp) if (result) return result; - *temp = deci_kelvin_to_millicelsius_with_offset(tz->temperature, + *temp = deci_kelvin_to_millicelsius_with_offset(tz->temp_dk, tz->kelvin_offset); return 0; } @@ -513,10 +513,10 @@ static int thermal_get_trend(struct thermal_zone_device *thermal, switch (trip->type) { case THERMAL_TRIP_PASSIVE: - t = tz->trips.passive.tc1 * (tz->temperature - - tz->last_temperature) + - tz->trips.passive.tc2 * (tz->temperature - - acpi_trip->temperature); + t = tz->trips.passive.tc1 * (tz->temp_dk - + tz->last_temp_dk) + + tz->trips.passive.tc2 * (tz->temp_dk - + acpi_trip->temp_dk); if (t > 0) *trend = THERMAL_TREND_RAISING; else if (t < 0) @@ -527,7 +527,7 @@ static int thermal_get_trend(struct thermal_zone_device *thermal, return 0; case THERMAL_TRIP_ACTIVE: - t = acpi_thermal_temp(tz, tz->temperature); + t = acpi_thermal_temp(tz, tz->temp_dk); if (t <= trip->temperature) break; @@ -899,7 +899,7 @@ static int acpi_thermal_add(struct acpi_device *device) passive_delay = tz->trips.passive.tsp * 100; trip->type = THERMAL_TRIP_PASSIVE; - trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); + trip->temperature = acpi_thermal_temp(tz, acpi_trip->temp_dk); trip->priv = acpi_trip; trip++; } @@ -911,7 +911,7 @@ static int acpi_thermal_add(struct acpi_device *device) break; trip->type = THERMAL_TRIP_ACTIVE; - trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); + trip->temperature = acpi_thermal_temp(tz, acpi_trip->temp_dk); trip->priv = acpi_trip; trip++; } @@ -925,7 +925,7 @@ static int acpi_thermal_add(struct acpi_device *device) INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn); pr_info("%s [%s] (%ld C)\n", acpi_device_name(device), - acpi_device_bid(device), deci_kelvin_to_celsius(tz->temperature)); + acpi_device_bid(device), deci_kelvin_to_celsius(tz->temp_dk)); result = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY, acpi_thermal_notify); From 4347e7d0b4e8e1cb9ef4576cc94d122b02ee6f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:07 +0200 Subject: [PATCH 032/111] thermal: armada: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/armada_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index f00765bfc22e..f783547ef964 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -965,19 +965,17 @@ static int armada_thermal_probe(struct platform_device *pdev) return 0; } -static int armada_thermal_exit(struct platform_device *pdev) +static void armada_thermal_exit(struct platform_device *pdev) { struct armada_drvdata *drvdata = platform_get_drvdata(pdev); if (drvdata->type == LEGACY) thermal_zone_device_unregister(drvdata->data.tz); - - return 0; } static struct platform_driver armada_thermal_driver = { .probe = armada_thermal_probe, - .remove = armada_thermal_exit, + .remove_new = armada_thermal_exit, .driver = { .name = "armada_thermal", .of_match_table = armada_thermal_id_table, From f29ecd3748a28d0b52512afc81b3c13fd4a00c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:08 +0200 Subject: [PATCH 033/111] thermal: bcm2835: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/broadcom/bcm2835_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c index 3acc9288b310..5c1cebe07580 100644 --- a/drivers/thermal/broadcom/bcm2835_thermal.c +++ b/drivers/thermal/broadcom/bcm2835_thermal.c @@ -282,19 +282,17 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) return err; } -static int bcm2835_thermal_remove(struct platform_device *pdev) +static void bcm2835_thermal_remove(struct platform_device *pdev) { struct bcm2835_thermal_data *data = platform_get_drvdata(pdev); debugfs_remove_recursive(data->debugfsdir); clk_disable_unprepare(data->clk); - - return 0; } static struct platform_driver bcm2835_thermal_driver = { .probe = bcm2835_thermal_probe, - .remove = bcm2835_thermal_remove, + .remove_new = bcm2835_thermal_remove, .driver = { .name = "bcm2835_thermal", .of_match_table = bcm2835_thermal_of_match_table, From aa599650d26f6588723bc4c903704a7fa3df6c1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:09 +0200 Subject: [PATCH 034/111] thermal: ns: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/broadcom/ns-thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/broadcom/ns-thermal.c b/drivers/thermal/broadcom/ns-thermal.c index d255aa879fc0..5eaf79c490f0 100644 --- a/drivers/thermal/broadcom/ns-thermal.c +++ b/drivers/thermal/broadcom/ns-thermal.c @@ -65,13 +65,11 @@ static int ns_thermal_probe(struct platform_device *pdev) return 0; } -static int ns_thermal_remove(struct platform_device *pdev) +static void ns_thermal_remove(struct platform_device *pdev) { void __iomem *pvtmon = platform_get_drvdata(pdev); iounmap(pvtmon); - - return 0; } static const struct of_device_id ns_thermal_of_match[] = { @@ -82,7 +80,7 @@ MODULE_DEVICE_TABLE(of, ns_thermal_of_match); static struct platform_driver ns_thermal_driver = { .probe = ns_thermal_probe, - .remove = ns_thermal_remove, + .remove_new = ns_thermal_remove, .driver = { .name = "ns-thermal", .of_match_table = ns_thermal_of_match, From 0d0f8b2c4df0e9b8010344c6ad0d8b02c7cb6487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:10 +0200 Subject: [PATCH 035/111] thermal: da9062: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/da9062-thermal.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/thermal/da9062-thermal.c b/drivers/thermal/da9062-thermal.c index 2d31b1f73423..160d64913057 100644 --- a/drivers/thermal/da9062-thermal.c +++ b/drivers/thermal/da9062-thermal.c @@ -239,19 +239,18 @@ static int da9062_thermal_probe(struct platform_device *pdev) return ret; } -static int da9062_thermal_remove(struct platform_device *pdev) +static void da9062_thermal_remove(struct platform_device *pdev) { struct da9062_thermal *thermal = platform_get_drvdata(pdev); free_irq(thermal->irq, thermal); cancel_delayed_work_sync(&thermal->work); thermal_zone_device_unregister(thermal->zone); - return 0; } static struct platform_driver da9062_thermal_driver = { .probe = da9062_thermal_probe, - .remove = da9062_thermal_remove, + .remove_new = da9062_thermal_remove, .driver = { .name = "da9062-thermal", .of_match_table = da9062_compatible_reg_id_table, From 7aa234e99fa2e007f004df8ef5b01f045378977d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:11 +0200 Subject: [PATCH 036/111] thermal: dove: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/dove_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c index 7a18cb960bee..ac30de3c0a5f 100644 --- a/drivers/thermal/dove_thermal.c +++ b/drivers/thermal/dove_thermal.c @@ -158,21 +158,19 @@ static int dove_thermal_probe(struct platform_device *pdev) return 0; } -static int dove_thermal_exit(struct platform_device *pdev) +static void dove_thermal_exit(struct platform_device *pdev) { struct thermal_zone_device *dove_thermal = platform_get_drvdata(pdev); thermal_zone_device_unregister(dove_thermal); - - return 0; } MODULE_DEVICE_TABLE(of, dove_thermal_id_table); static struct platform_driver dove_thermal_driver = { .probe = dove_thermal_probe, - .remove = dove_thermal_exit, + .remove_new = dove_thermal_exit, .driver = { .name = "dove_thermal", .of_match_table = dove_thermal_id_table, From 6abe2f00d27aa4f337e7a2e5f1bc6accd9474698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:12 +0200 Subject: [PATCH 037/111] thermal: hisi: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/hisi_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index fb54ed4bf6f0..dd751ae63608 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -597,7 +597,7 @@ static int hisi_thermal_probe(struct platform_device *pdev) return 0; } -static int hisi_thermal_remove(struct platform_device *pdev) +static void hisi_thermal_remove(struct platform_device *pdev) { struct hisi_thermal_data *data = platform_get_drvdata(pdev); int i; @@ -608,8 +608,6 @@ static int hisi_thermal_remove(struct platform_device *pdev) hisi_thermal_toggle_sensor(sensor, false); data->ops->disable_sensor(sensor); } - - return 0; } static int hisi_thermal_suspend(struct device *dev) @@ -644,7 +642,7 @@ static struct platform_driver hisi_thermal_driver = { .of_match_table = of_hisi_thermal_match, }, .probe = hisi_thermal_probe, - .remove = hisi_thermal_remove, + .remove_new = hisi_thermal_remove, }; module_platform_driver(hisi_thermal_driver); From 5568f642bb7a16ba75aceadc4f264be92365e677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:13 +0200 Subject: [PATCH 038/111] thermal: imx8mm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/imx8mm_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/imx8mm_thermal.c b/drivers/thermal/imx8mm_thermal.c index 14111ccf6e4c..c58fc73c0744 100644 --- a/drivers/thermal/imx8mm_thermal.c +++ b/drivers/thermal/imx8mm_thermal.c @@ -363,7 +363,7 @@ static int imx8mm_tmu_probe(struct platform_device *pdev) return ret; } -static int imx8mm_tmu_remove(struct platform_device *pdev) +static void imx8mm_tmu_remove(struct platform_device *pdev) { struct imx8mm_tmu *tmu = platform_get_drvdata(pdev); @@ -372,8 +372,6 @@ static int imx8mm_tmu_remove(struct platform_device *pdev) clk_disable_unprepare(tmu->clk); platform_set_drvdata(pdev, NULL); - - return 0; } static struct thermal_soc_data imx8mm_tmu_data = { @@ -401,7 +399,7 @@ static struct platform_driver imx8mm_tmu = { .of_match_table = imx8mm_tmu_table, }, .probe = imx8mm_tmu_probe, - .remove = imx8mm_tmu_remove, + .remove_new = imx8mm_tmu_remove, }; module_platform_driver(imx8mm_tmu); From 02e7baaf5165a11f5075fa23c10f5834d92b19bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:14 +0200 Subject: [PATCH 039/111] thermal: imx: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/imx_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 826358cbe810..7019c4fdd549 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -771,7 +771,7 @@ static int imx_thermal_probe(struct platform_device *pdev) return ret; } -static int imx_thermal_remove(struct platform_device *pdev) +static void imx_thermal_remove(struct platform_device *pdev) { struct imx_thermal_data *data = platform_get_drvdata(pdev); @@ -780,8 +780,6 @@ static int imx_thermal_remove(struct platform_device *pdev) thermal_zone_device_unregister(data->tz); imx_thermal_unregister_legacy_cooling(data); - - return 0; } static int __maybe_unused imx_thermal_suspend(struct device *dev) @@ -880,7 +878,7 @@ static struct platform_driver imx_thermal = { .of_match_table = of_imx_thermal_match, }, .probe = imx_thermal_probe, - .remove = imx_thermal_remove, + .remove_new = imx_thermal_remove, }; module_platform_driver(imx_thermal); From 75b66d7e599395c844c85fad6d0a97c8b7e609fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:15 +0200 Subject: [PATCH 040/111] thermal: int3400: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/intel/int340x_thermal/int3400_thermal.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c index ffc2871a021c..427d370648d5 100644 --- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c @@ -674,7 +674,7 @@ static int int3400_thermal_probe(struct platform_device *pdev) return result; } -static int int3400_thermal_remove(struct platform_device *pdev) +static void int3400_thermal_remove(struct platform_device *pdev) { struct int3400_thermal_priv *priv = platform_get_drvdata(pdev); @@ -698,7 +698,6 @@ static int int3400_thermal_remove(struct platform_device *pdev) kfree(priv->trts); kfree(priv->arts); kfree(priv); - return 0; } static const struct acpi_device_id int3400_thermal_match[] = { @@ -714,7 +713,7 @@ MODULE_DEVICE_TABLE(acpi, int3400_thermal_match); static struct platform_driver int3400_thermal_driver = { .probe = int3400_thermal_probe, - .remove = int3400_thermal_remove, + .remove_new = int3400_thermal_remove, .driver = { .name = "int3400 thermal", .acpi_match_table = ACPI_PTR(int3400_thermal_match), From 8cc099170f615d7b40a849d389207c9c4268f57a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:16 +0200 Subject: [PATCH 041/111] thermal: int3401: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/intel/int340x_thermal/int3401_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/intel/int340x_thermal/int3401_thermal.c b/drivers/thermal/intel/int340x_thermal/int3401_thermal.c index c93a28eec4db..193645a73861 100644 --- a/drivers/thermal/intel/int340x_thermal/int3401_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3401_thermal.c @@ -36,11 +36,9 @@ static int int3401_add(struct platform_device *pdev) return ret; } -static int int3401_remove(struct platform_device *pdev) +static void int3401_remove(struct platform_device *pdev) { proc_thermal_remove(platform_get_drvdata(pdev)); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -62,7 +60,7 @@ static SIMPLE_DEV_PM_OPS(int3401_proc_thermal_pm, int3401_thermal_suspend, static struct platform_driver int3401_driver = { .probe = int3401_add, - .remove = int3401_remove, + .remove_new = int3401_remove, .driver = { .name = "int3401 thermal", .acpi_match_table = int3401_device_ids, From f287083ba7bff4924e0d18c085bcae53eabf36e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:17 +0200 Subject: [PATCH 042/111] thermal: int3402: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/intel/int340x_thermal/int3402_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/intel/int340x_thermal/int3402_thermal.c b/drivers/thermal/intel/int340x_thermal/int3402_thermal.c index 43fa351e2b9e..ab8bfb5a3946 100644 --- a/drivers/thermal/intel/int340x_thermal/int3402_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3402_thermal.c @@ -71,15 +71,13 @@ static int int3402_thermal_probe(struct platform_device *pdev) return 0; } -static int int3402_thermal_remove(struct platform_device *pdev) +static void int3402_thermal_remove(struct platform_device *pdev) { struct int3402_thermal_data *d = platform_get_drvdata(pdev); acpi_remove_notify_handler(d->handle, ACPI_DEVICE_NOTIFY, int3402_notify); int340x_thermal_zone_remove(d->int340x_zone); - - return 0; } static const struct acpi_device_id int3402_thermal_match[] = { @@ -91,7 +89,7 @@ MODULE_DEVICE_TABLE(acpi, int3402_thermal_match); static struct platform_driver int3402_thermal_driver = { .probe = int3402_thermal_probe, - .remove = int3402_thermal_remove, + .remove_new = int3402_thermal_remove, .driver = { .name = "int3402 thermal", .acpi_match_table = int3402_thermal_match, From 2570108311433217cc0ba78707067e728a5f03d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:18 +0200 Subject: [PATCH 043/111] thermal: int3403: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/intel/int340x_thermal/int3403_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/intel/int340x_thermal/int3403_thermal.c b/drivers/thermal/intel/int340x_thermal/int3403_thermal.c index e418d270bc76..9b33fd3a66da 100644 --- a/drivers/thermal/intel/int340x_thermal/int3403_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3403_thermal.c @@ -262,7 +262,7 @@ static int int3403_add(struct platform_device *pdev) return result; } -static int int3403_remove(struct platform_device *pdev) +static void int3403_remove(struct platform_device *pdev) { struct int3403_priv *priv = platform_get_drvdata(pdev); @@ -277,8 +277,6 @@ static int int3403_remove(struct platform_device *pdev) default: break; } - - return 0; } static const struct acpi_device_id int3403_device_ids[] = { @@ -293,7 +291,7 @@ MODULE_DEVICE_TABLE(acpi, int3403_device_ids); static struct platform_driver int3403_driver = { .probe = int3403_add, - .remove = int3403_remove, + .remove_new = int3403_remove, .driver = { .name = "int3403 thermal", .acpi_match_table = int3403_device_ids, From a876f99d120dd81ff1e195260901f4a68fc4b498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:19 +0200 Subject: [PATCH 044/111] thermal: int3406: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/intel/int340x_thermal/int3406_thermal.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/thermal/intel/int340x_thermal/int3406_thermal.c b/drivers/thermal/intel/int340x_thermal/int3406_thermal.c index f5e42fc2acc0..1c266493c1aa 100644 --- a/drivers/thermal/intel/int340x_thermal/int3406_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3406_thermal.c @@ -178,13 +178,12 @@ static int int3406_thermal_probe(struct platform_device *pdev) return -ENODEV; } -static int int3406_thermal_remove(struct platform_device *pdev) +static void int3406_thermal_remove(struct platform_device *pdev) { struct int3406_thermal_data *d = platform_get_drvdata(pdev); thermal_cooling_device_unregister(d->cooling_dev); kfree(d->br); - return 0; } static const struct acpi_device_id int3406_thermal_match[] = { @@ -196,7 +195,7 @@ MODULE_DEVICE_TABLE(acpi, int3406_thermal_match); static struct platform_driver int3406_thermal_driver = { .probe = int3406_thermal_probe, - .remove = int3406_thermal_remove, + .remove_new = int3406_thermal_remove, .driver = { .name = "int3406 thermal", .acpi_match_table = int3406_thermal_match, From ff96e615ea49cd1910a6367efe19ebec9516ca2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:20 +0200 Subject: [PATCH 045/111] thermal: k3_bandgap: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/k3_bandgap.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/k3_bandgap.c b/drivers/thermal/k3_bandgap.c index 4a918c1e92f9..e88192d2afea 100644 --- a/drivers/thermal/k3_bandgap.c +++ b/drivers/thermal/k3_bandgap.c @@ -235,12 +235,10 @@ static int k3_bandgap_probe(struct platform_device *pdev) return ret; } -static int k3_bandgap_remove(struct platform_device *pdev) +static void k3_bandgap_remove(struct platform_device *pdev) { pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } static const struct of_device_id of_k3_bandgap_match[] = { @@ -253,7 +251,7 @@ MODULE_DEVICE_TABLE(of, of_k3_bandgap_match); static struct platform_driver k3_bandgap_sensor_driver = { .probe = k3_bandgap_probe, - .remove = k3_bandgap_remove, + .remove_new = k3_bandgap_remove, .driver = { .name = "k3-soc-thermal", .of_match_table = of_k3_bandgap_match, From 3c9e0f218c0fa5bcff18091d13519c9411c328f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:21 +0200 Subject: [PATCH 046/111] thermal: k3_j72xx_bandgap: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/k3_j72xx_bandgap.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/k3_j72xx_bandgap.c b/drivers/thermal/k3_j72xx_bandgap.c index 2fc799b07b90..c74094a86982 100644 --- a/drivers/thermal/k3_j72xx_bandgap.c +++ b/drivers/thermal/k3_j72xx_bandgap.c @@ -521,12 +521,10 @@ static int k3_j72xx_bandgap_probe(struct platform_device *pdev) return ret; } -static int k3_j72xx_bandgap_remove(struct platform_device *pdev) +static void k3_j72xx_bandgap_remove(struct platform_device *pdev) { pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } static const struct k3_j72xx_bandgap_data k3_j72xx_bandgap_j721e_data = { @@ -552,7 +550,7 @@ MODULE_DEVICE_TABLE(of, of_k3_j72xx_bandgap_match); static struct platform_driver k3_j72xx_bandgap_sensor_driver = { .probe = k3_j72xx_bandgap_probe, - .remove = k3_j72xx_bandgap_remove, + .remove_new = k3_j72xx_bandgap_remove, .driver = { .name = "k3-j72xx-soc-thermal", .of_match_table = of_k3_j72xx_bandgap_match, From 3ebaf0f244d4cd1a4a018edd46f642f241ef97f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:22 +0200 Subject: [PATCH 047/111] thermal: kirkwood: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/kirkwood_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c index acb10d24256d..a18158ebe65f 100644 --- a/drivers/thermal/kirkwood_thermal.c +++ b/drivers/thermal/kirkwood_thermal.c @@ -90,21 +90,19 @@ static int kirkwood_thermal_probe(struct platform_device *pdev) return 0; } -static int kirkwood_thermal_exit(struct platform_device *pdev) +static void kirkwood_thermal_exit(struct platform_device *pdev) { struct thermal_zone_device *kirkwood_thermal = platform_get_drvdata(pdev); thermal_zone_device_unregister(kirkwood_thermal); - - return 0; } MODULE_DEVICE_TABLE(of, kirkwood_thermal_id_table); static struct platform_driver kirkwood_thermal_driver = { .probe = kirkwood_thermal_probe, - .remove = kirkwood_thermal_exit, + .remove_new = kirkwood_thermal_exit, .driver = { .name = "kirkwood_thermal", .of_match_table = kirkwood_thermal_id_table, From 2d3c823df218fa30b63a00819b179c95c0199fbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:23 +0200 Subject: [PATCH 048/111] thermal: lvts: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/mediatek/lvts_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index effd9b00a424..877a0e5ac3fd 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -1241,7 +1241,7 @@ static int lvts_probe(struct platform_device *pdev) return 0; } -static int lvts_remove(struct platform_device *pdev) +static void lvts_remove(struct platform_device *pdev) { struct lvts_domain *lvts_td; int i; @@ -1252,8 +1252,6 @@ static int lvts_remove(struct platform_device *pdev) lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false); lvts_debugfs_exit(lvts_td); - - return 0; } static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { @@ -1354,7 +1352,7 @@ MODULE_DEVICE_TABLE(of, lvts_of_match); static struct platform_driver lvts_driver = { .probe = lvts_probe, - .remove = lvts_remove, + .remove_new = lvts_remove, .driver = { .name = "mtk-lvts-thermal", .of_match_table = lvts_of_match, From 2128ba4639e37f39c73e2e07baed24038d47b973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:24 +0200 Subject: [PATCH 049/111] thermal: tsens: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/qcom/tsens.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index 98c356acfe98..6d7c16ccb44d 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -1319,7 +1319,7 @@ static int tsens_probe(struct platform_device *pdev) return ret; } -static int tsens_remove(struct platform_device *pdev) +static void tsens_remove(struct platform_device *pdev) { struct tsens_priv *priv = platform_get_drvdata(pdev); @@ -1327,13 +1327,11 @@ static int tsens_remove(struct platform_device *pdev) tsens_disable_irq(priv); if (priv->ops->disable) priv->ops->disable(priv); - - return 0; } static struct platform_driver tsens_driver = { .probe = tsens_probe, - .remove = tsens_remove, + .remove_new = tsens_remove, .driver = { .name = "qcom-tsens", .pm = &tsens_pm_ops, From a07f4487bc49f5af8bd7d194890e5ed1dd7c4994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:25 +0200 Subject: [PATCH 050/111] thermal: rcar_gen3: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Reviewed-by: Wolfram Sang Reviewed-by: Geert Uytterhoeven Signed-off-by: Rafael J. Wysocki --- drivers/thermal/rcar_gen3_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index bd2fb8c2e968..cafcb6d6e235 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -432,14 +432,12 @@ static const struct of_device_id rcar_gen3_thermal_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids); -static int rcar_gen3_thermal_remove(struct platform_device *pdev) +static void rcar_gen3_thermal_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; pm_runtime_put(dev); pm_runtime_disable(dev); - - return 0; } static void rcar_gen3_hwmon_action(void *data) @@ -594,7 +592,7 @@ static struct platform_driver rcar_gen3_thermal_driver = { .of_match_table = rcar_gen3_thermal_dt_ids, }, .probe = rcar_gen3_thermal_probe, - .remove = rcar_gen3_thermal_remove, + .remove_new = rcar_gen3_thermal_remove, }; module_platform_driver(rcar_gen3_thermal_driver); From 03a5a75a6ad26afdb8b507cf26ef6dea45239911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:26 +0200 Subject: [PATCH 051/111] thermal: rcar: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Reviewed-by: Wolfram Sang Reviewed-by: Geert Uytterhoeven Signed-off-by: Rafael J. Wysocki --- drivers/thermal/rcar_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 293f8dd9fe0a..feb848d595fa 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -371,7 +371,7 @@ static irqreturn_t rcar_thermal_irq(int irq, void *data) /* * platform functions */ -static int rcar_thermal_remove(struct platform_device *pdev) +static void rcar_thermal_remove(struct platform_device *pdev) { struct rcar_thermal_common *common = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; @@ -388,8 +388,6 @@ static int rcar_thermal_remove(struct platform_device *pdev) pm_runtime_put(dev); pm_runtime_disable(dev); - - return 0; } static int rcar_thermal_probe(struct platform_device *pdev) @@ -581,7 +579,7 @@ static struct platform_driver rcar_thermal_driver = { .of_match_table = rcar_thermal_dt_ids, }, .probe = rcar_thermal_probe, - .remove = rcar_thermal_remove, + .remove_new = rcar_thermal_remove, }; module_platform_driver(rcar_thermal_driver); From c6767334185e50121b66eae9f882d2832d2d2ad1 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 28 Sep 2023 20:47:31 +0200 Subject: [PATCH 052/111] ACPI: thermal: Drop list of device ACPI handles from struct acpi_thermal Notice that the list of device ACPI handles in struct acpi_thermal is not used and drop it. No functional impact. Signed-off-by: Rafael J. Wysocki Acked-by: Daniel Lezcano --- drivers/acpi/thermal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index d3d6429b98c5..17bcf4185fef 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -111,7 +111,6 @@ struct acpi_thermal { volatile u8 zombie; struct acpi_thermal_trips trips; struct thermal_trip *trip_table; - struct acpi_handle_list devices; struct thermal_zone_device *thermal_zone; int kelvin_offset; /* in millidegrees */ struct work_struct thermal_check_work; From cc86ac43e555ea40a22825f1eec5fb72c8e59522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:27 +0200 Subject: [PATCH 053/111] thermal: rockchip: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Reviewed-by: Heiko Stuebner Signed-off-by: Rafael J. Wysocki --- drivers/thermal/rockchip_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index 77231a9d28ff..086ed42dd16c 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -1601,7 +1601,7 @@ static int rockchip_thermal_probe(struct platform_device *pdev) return 0; } -static int rockchip_thermal_remove(struct platform_device *pdev) +static void rockchip_thermal_remove(struct platform_device *pdev) { struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev); int i; @@ -1614,8 +1614,6 @@ static int rockchip_thermal_remove(struct platform_device *pdev) } thermal->chip->control(thermal->regs, false); - - return 0; } static int __maybe_unused rockchip_thermal_suspend(struct device *dev) @@ -1691,7 +1689,7 @@ static struct platform_driver rockchip_thermal_driver = { .of_match_table = of_rockchip_thermal_match, }, .probe = rockchip_thermal_probe, - .remove = rockchip_thermal_remove, + .remove_new = rockchip_thermal_remove, }; module_platform_driver(rockchip_thermal_driver); From 24bbbfb73e9bf3188177950d420d059225070250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:28 +0200 Subject: [PATCH 054/111] thermal: rzg2l: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/rzg2l_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/rzg2l_thermal.c b/drivers/thermal/rzg2l_thermal.c index 6b2bf3426f52..04efd824ac4c 100644 --- a/drivers/thermal/rzg2l_thermal.c +++ b/drivers/thermal/rzg2l_thermal.c @@ -150,14 +150,12 @@ static void rzg2l_thermal_reset_assert_pm_disable_put(struct platform_device *pd reset_control_assert(priv->rstc); } -static int rzg2l_thermal_remove(struct platform_device *pdev) +static void rzg2l_thermal_remove(struct platform_device *pdev) { struct rzg2l_thermal_priv *priv = dev_get_drvdata(&pdev->dev); thermal_remove_hwmon_sysfs(priv->zone); rzg2l_thermal_reset_assert_pm_disable_put(pdev); - - return 0; } static int rzg2l_thermal_probe(struct platform_device *pdev) @@ -242,7 +240,7 @@ static struct platform_driver rzg2l_thermal_driver = { .of_match_table = rzg2l_thermal_dt_ids, }, .probe = rzg2l_thermal_probe, - .remove = rzg2l_thermal_remove, + .remove_new = rzg2l_thermal_remove, }; module_platform_driver(rzg2l_thermal_driver); From 0b478d7b867b9c1621b0bb31ee0c416bed376631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:29 +0200 Subject: [PATCH 055/111] thermal: exynos_tmu: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/samsung/exynos_tmu.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index e5bc2c82010f..123ec81e1943 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -1124,7 +1124,7 @@ static int exynos_tmu_probe(struct platform_device *pdev) return ret; } -static int exynos_tmu_remove(struct platform_device *pdev) +static void exynos_tmu_remove(struct platform_device *pdev) { struct exynos_tmu_data *data = platform_get_drvdata(pdev); @@ -1137,8 +1137,6 @@ static int exynos_tmu_remove(struct platform_device *pdev) if (!IS_ERR(data->regulator)) regulator_disable(data->regulator); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1173,7 +1171,7 @@ static struct platform_driver exynos_tmu_driver = { .of_match_table = exynos_tmu_match, }, .probe = exynos_tmu_probe, - .remove = exynos_tmu_remove, + .remove_new = exynos_tmu_remove, }; module_platform_driver(exynos_tmu_driver); From 7c2714a1e6895e49e002ad136280e47671843443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:30 +0200 Subject: [PATCH 056/111] thermal: spear: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/spear_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c index 96d99289799a..60a871998b07 100644 --- a/drivers/thermal/spear_thermal.c +++ b/drivers/thermal/spear_thermal.c @@ -150,7 +150,7 @@ static int spear_thermal_probe(struct platform_device *pdev) return ret; } -static int spear_thermal_exit(struct platform_device *pdev) +static void spear_thermal_exit(struct platform_device *pdev) { unsigned int actual_mask = 0; struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev); @@ -163,8 +163,6 @@ static int spear_thermal_exit(struct platform_device *pdev) writel_relaxed(actual_mask & ~stdev->flags, stdev->thermal_base); clk_disable(stdev->clk); - - return 0; } static const struct of_device_id spear_thermal_id_table[] = { @@ -175,7 +173,7 @@ MODULE_DEVICE_TABLE(of, spear_thermal_id_table); static struct platform_driver spear_thermal_driver = { .probe = spear_thermal_probe, - .remove = spear_thermal_exit, + .remove_new = spear_thermal_exit, .driver = { .name = "spear_thermal", .pm = &spear_thermal_pm_ops, From 295b117645814de05ab863e9f890cbd79d7a2a38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:31 +0200 Subject: [PATCH 057/111] thermal: sprd: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/sprd_thermal.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/thermal/sprd_thermal.c b/drivers/thermal/sprd_thermal.c index e27c4bdc8912..874192546548 100644 --- a/drivers/thermal/sprd_thermal.c +++ b/drivers/thermal/sprd_thermal.c @@ -516,7 +516,7 @@ static int sprd_thm_resume(struct device *dev) } #endif -static int sprd_thm_remove(struct platform_device *pdev) +static void sprd_thm_remove(struct platform_device *pdev) { struct sprd_thermal_data *thm = platform_get_drvdata(pdev); int i; @@ -528,7 +528,6 @@ static int sprd_thm_remove(struct platform_device *pdev) } clk_disable_unprepare(thm->clk); - return 0; } static const struct of_device_id sprd_thermal_of_match[] = { @@ -543,7 +542,7 @@ static const struct dev_pm_ops sprd_thermal_pm_ops = { static struct platform_driver sprd_thermal_driver = { .probe = sprd_thm_probe, - .remove = sprd_thm_remove, + .remove_new = sprd_thm_remove, .driver = { .name = "sprd-thermal", .pm = &sprd_thermal_pm_ops, From ca92bdec592f59ae7a1ca1da6ce77e7de84acdee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:32 +0200 Subject: [PATCH 058/111] thermal: stm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/st/stm_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/st/stm_thermal.c b/drivers/thermal/st/stm_thermal.c index 142a7e5d12f4..34785b9276fc 100644 --- a/drivers/thermal/st/stm_thermal.c +++ b/drivers/thermal/st/stm_thermal.c @@ -569,14 +569,12 @@ static int stm_thermal_probe(struct platform_device *pdev) return ret; } -static int stm_thermal_remove(struct platform_device *pdev) +static void stm_thermal_remove(struct platform_device *pdev) { struct stm_thermal_sensor *sensor = platform_get_drvdata(pdev); stm_thermal_sensor_off(sensor); thermal_remove_hwmon_sysfs(sensor->th_dev); - - return 0; } static struct platform_driver stm_thermal_driver = { @@ -586,7 +584,7 @@ static struct platform_driver stm_thermal_driver = { .of_match_table = stm_thermal_of_match, }, .probe = stm_thermal_probe, - .remove = stm_thermal_remove, + .remove_new = stm_thermal_remove, }; module_platform_driver(stm_thermal_driver); From f1afede9e24cb06f409d855aa546e99bbe4817fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:33 +0200 Subject: [PATCH 059/111] thermal: soctherm: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/tegra/soctherm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c index ea66cba09e56..e7fe8683bfc5 100644 --- a/drivers/thermal/tegra/soctherm.c +++ b/drivers/thermal/tegra/soctherm.c @@ -2219,15 +2219,13 @@ static int tegra_soctherm_probe(struct platform_device *pdev) return err; } -static int tegra_soctherm_remove(struct platform_device *pdev) +static void tegra_soctherm_remove(struct platform_device *pdev) { struct tegra_soctherm *tegra = platform_get_drvdata(pdev); debugfs_remove_recursive(tegra->debugfs_dir); soctherm_clk_enable(pdev, false); - - return 0; } static int __maybe_unused soctherm_suspend(struct device *dev) @@ -2274,7 +2272,7 @@ static SIMPLE_DEV_PM_OPS(tegra_soctherm_pm, soctherm_suspend, soctherm_resume); static struct platform_driver tegra_soctherm_driver = { .probe = tegra_soctherm_probe, - .remove = tegra_soctherm_remove, + .remove_new = tegra_soctherm_remove, .driver = { .name = "tegra_soctherm", .pm = &tegra_soctherm_pm, From f021f0526274834ae941f5ab9b06d56e13d75db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:34 +0200 Subject: [PATCH 060/111] thermal: tegra-bpmp: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/tegra/tegra-bpmp-thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/tegra/tegra-bpmp-thermal.c b/drivers/thermal/tegra/tegra-bpmp-thermal.c index 4ffc3bb3bf35..72ce14c980cd 100644 --- a/drivers/thermal/tegra/tegra-bpmp-thermal.c +++ b/drivers/thermal/tegra/tegra-bpmp-thermal.c @@ -300,13 +300,11 @@ static int tegra_bpmp_thermal_probe(struct platform_device *pdev) return 0; } -static int tegra_bpmp_thermal_remove(struct platform_device *pdev) +static void tegra_bpmp_thermal_remove(struct platform_device *pdev) { struct tegra_bpmp_thermal *tegra = platform_get_drvdata(pdev); tegra_bpmp_free_mrq(tegra->bpmp, MRQ_THERMAL, tegra); - - return 0; } static const struct of_device_id tegra_bpmp_thermal_of_match[] = { @@ -317,7 +315,7 @@ MODULE_DEVICE_TABLE(of, tegra_bpmp_thermal_of_match); static struct platform_driver tegra_bpmp_thermal_driver = { .probe = tegra_bpmp_thermal_probe, - .remove = tegra_bpmp_thermal_remove, + .remove_new = tegra_bpmp_thermal_remove, .driver = { .name = "tegra-bpmp-thermal", .of_match_table = tegra_bpmp_thermal_of_match, From f3e38da002571ca76bcd75000c847d7a4ccb2c73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:35 +0200 Subject: [PATCH 061/111] thermal: ti-bandgap: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/ti-soc-thermal/ti-bandgap.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index 0c2eb9c6e58b..caadfc61be93 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c @@ -1069,7 +1069,7 @@ int ti_bandgap_probe(struct platform_device *pdev) } static -int ti_bandgap_remove(struct platform_device *pdev) +void ti_bandgap_remove(struct platform_device *pdev) { struct ti_bandgap *bgp = platform_get_drvdata(pdev); int i; @@ -1098,8 +1098,6 @@ int ti_bandgap_remove(struct platform_device *pdev) if (TI_BANDGAP_HAS(bgp, TSHUT)) free_irq(gpiod_to_irq(bgp->tshut_gpiod), NULL); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1283,7 +1281,7 @@ MODULE_DEVICE_TABLE(of, of_ti_bandgap_match); static struct platform_driver ti_bandgap_sensor_driver = { .probe = ti_bandgap_probe, - .remove = ti_bandgap_remove, + .remove_new = ti_bandgap_remove, .driver = { .name = "ti-soc-thermal", .pm = DEV_PM_OPS, From 439f0bb3a7c529feadce975cf96e8cf8fcf929bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:36 +0200 Subject: [PATCH 062/111] thermal: uniphier: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/uniphier_thermal.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/uniphier_thermal.c b/drivers/thermal/uniphier_thermal.c index 6f32ab61d174..274f36358b21 100644 --- a/drivers/thermal/uniphier_thermal.c +++ b/drivers/thermal/uniphier_thermal.c @@ -317,14 +317,12 @@ static int uniphier_tm_probe(struct platform_device *pdev) return 0; } -static int uniphier_tm_remove(struct platform_device *pdev) +static void uniphier_tm_remove(struct platform_device *pdev) { struct uniphier_tm_dev *tdev = platform_get_drvdata(pdev); /* disable sensor */ uniphier_tm_disable_sensor(tdev); - - return 0; } static const struct uniphier_tm_soc_data uniphier_pxs2_tm_data = { @@ -362,7 +360,7 @@ MODULE_DEVICE_TABLE(of, uniphier_tm_dt_ids); static struct platform_driver uniphier_tm_driver = { .probe = uniphier_tm_probe, - .remove = uniphier_tm_remove, + .remove_new = uniphier_tm_remove, .driver = { .name = "uniphier-thermal", .of_match_table = uniphier_tm_dt_ids, From eea6c26207255461c1d5b59d74ee460442113ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 27 Sep 2023 21:37:06 +0200 Subject: [PATCH 063/111] thermal: amlogic: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). amlogic_thermal_disable() always returned zero. Change it to return no value and then trivially convert the driver to .remove_new() and fix a whitespace inconsitency en passant. Signed-off-by: Uwe Kleine-König Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/thermal/amlogic_thermal.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/amlogic_thermal.c b/drivers/thermal/amlogic_thermal.c index 81ebbf6de0de..5877cde25b79 100644 --- a/drivers/thermal/amlogic_thermal.c +++ b/drivers/thermal/amlogic_thermal.c @@ -291,11 +291,11 @@ static int amlogic_thermal_probe(struct platform_device *pdev) return ret; } -static int amlogic_thermal_remove(struct platform_device *pdev) +static void amlogic_thermal_remove(struct platform_device *pdev) { struct amlogic_thermal *data = platform_get_drvdata(pdev); - return amlogic_thermal_disable(data); + amlogic_thermal_disable(data); } static int __maybe_unused amlogic_thermal_suspend(struct device *dev) @@ -321,8 +321,8 @@ static struct platform_driver amlogic_thermal_driver = { .pm = &amlogic_thermal_pm_ops, .of_match_table = of_amlogic_thermal_match, }, - .probe = amlogic_thermal_probe, - .remove = amlogic_thermal_remove, + .probe = amlogic_thermal_probe, + .remove_new = amlogic_thermal_remove, }; module_platform_driver(amlogic_thermal_driver); From 1dd72ce0c125110033e65051c9f8b2676e425cfd Mon Sep 17 00:00:00 2001 From: Jonathan Bergh Date: Fri, 29 Sep 2023 00:13:44 +0200 Subject: [PATCH 064/111] ACPI: thermal: Fix up function header formatting in two places Fix up the following formatting issues: * braces following function declarations should be on a new line * empty line should be present between function declarations Signed-off-by: Jonathan Bergh [ rjw: Subject and changelog edits ] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/thermal.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 17bcf4185fef..c01ba4ad8009 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -1021,7 +1021,8 @@ static struct acpi_driver acpi_thermal_driver = { .drv.pm = &acpi_thermal_pm, }; -static int thermal_act(const struct dmi_system_id *d) { +static int thermal_act(const struct dmi_system_id *d) +{ if (act == 0) { pr_notice("%s detected: disabling all active thermal trip points\n", d->ident); @@ -1029,13 +1030,17 @@ static int thermal_act(const struct dmi_system_id *d) { } return 0; } -static int thermal_nocrt(const struct dmi_system_id *d) { + +static int thermal_nocrt(const struct dmi_system_id *d) +{ pr_notice("%s detected: disabling all critical thermal trip point actions.\n", d->ident); crt = -1; return 0; } -static int thermal_tzp(const struct dmi_system_id *d) { + +static int thermal_tzp(const struct dmi_system_id *d) +{ if (tzp == 0) { pr_notice("%s detected: enabling thermal zone polling\n", d->ident); @@ -1043,7 +1048,9 @@ static int thermal_tzp(const struct dmi_system_id *d) { } return 0; } -static int thermal_psv(const struct dmi_system_id *d) { + +static int thermal_psv(const struct dmi_system_id *d) +{ if (psv == 0) { pr_notice("%s detected: disabling all passive thermal trip points\n", d->ident); From a56cc0a8338523f709892696cc229527617c1316 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 3 Oct 2023 15:17:24 +0200 Subject: [PATCH 065/111] thermal: core: Add function to walk trips under zone lock Add a wrapper around for_each_thermal_trip(), called thermal_zone_for_each_trip(), that will invoke the former under the thermal zone lock and pass its return value to the caller. Two drivers will be modified subsequently to use this new function. No functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/thermal/thermal_trip.c | 14 ++++++++++++++ include/linux/thermal.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/drivers/thermal/thermal_trip.c b/drivers/thermal/thermal_trip.c index a8e92a89b2b8..8c649a899537 100644 --- a/drivers/thermal/thermal_trip.c +++ b/drivers/thermal/thermal_trip.c @@ -27,6 +27,20 @@ int for_each_thermal_trip(struct thermal_zone_device *tz, } EXPORT_SYMBOL_GPL(for_each_thermal_trip); +int thermal_zone_for_each_trip(struct thermal_zone_device *tz, + int (*cb)(struct thermal_trip *, void *), + void *data) +{ + int ret; + + mutex_lock(&tz->lock); + ret = for_each_thermal_trip(tz, cb, data); + mutex_unlock(&tz->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(thermal_zone_for_each_trip); + int thermal_zone_get_num_trips(struct thermal_zone_device *tz) { return tz->num_trips; diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 6710a4ace992..2bab72149bbf 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -286,6 +286,9 @@ int thermal_zone_set_trip(struct thermal_zone_device *tz, int trip_id, int for_each_thermal_trip(struct thermal_zone_device *tz, int (*cb)(struct thermal_trip *, void *), void *data); +int thermal_zone_for_each_trip(struct thermal_zone_device *tz, + int (*cb)(struct thermal_trip *, void *), + void *data); int thermal_zone_get_num_trips(struct thermal_zone_device *tz); int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp); From 44babd829a7e0c13b57040fc8234f64fabab1efd Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 3 Oct 2023 15:18:31 +0200 Subject: [PATCH 066/111] ACPI: thermal: Move get_active_temp() Put the get_active_temp() function next to the analogous get_passive_temp() one to allow subsequent changes to be easier to follow. No functional impact. Signed-off-by: Rafael J. Wysocki Acked-by: Daniel Lezcano --- drivers/acpi/thermal.c | 46 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index c01ba4ad8009..71a1ca18c97c 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -189,6 +189,29 @@ static long get_passive_temp(struct acpi_thermal *tz) return tmp; } +static long get_active_temp(struct acpi_thermal *tz, int index) +{ + char method[] = { '_', 'A', 'C', '0' + index, '\0' }; + unsigned long long tmp; + acpi_status status; + + status = acpi_evaluate_integer(tz->device->handle, method, NULL, &tmp); + if (ACPI_FAILURE(status)) + return THERMAL_TEMP_INVALID; + + /* + * If an override has been provided, apply it so there are no active + * trips with thresholds greater than the override. + */ + if (act > 0) { + unsigned long long override = celsius_to_deci_kelvin(act); + + if (tmp > override) + tmp = override; + } + return tmp; +} + static void acpi_thermal_update_passive_trip(struct acpi_thermal *tz) { struct acpi_thermal_trip *acpi_trip = &tz->trips.passive.trip; @@ -247,29 +270,6 @@ static void acpi_thermal_update_trip_devices(struct acpi_thermal *tz, int index) ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } -static long get_active_temp(struct acpi_thermal *tz, int index) -{ - char method[] = { '_', 'A', 'C', '0' + index, '\0' }; - unsigned long long tmp; - acpi_status status; - - status = acpi_evaluate_integer(tz->device->handle, method, NULL, &tmp); - if (ACPI_FAILURE(status)) - return THERMAL_TEMP_INVALID; - - /* - * If an override has been provided, apply it so there are no active - * trips with thresholds greater than the override. - */ - if (act > 0) { - unsigned long long override = celsius_to_deci_kelvin(act); - - if (tmp > override) - tmp = override; - } - return tmp; -} - static void acpi_thermal_update_active_trip(struct acpi_thermal *tz, int index) { struct acpi_thermal_trip *acpi_trip = &tz->trips.active[index].trip; From 4f9cf91e4102fe77ef3393febab72612b594172f Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 3 Oct 2023 15:21:30 +0200 Subject: [PATCH 067/111] ACPI: thermal: Combine passive and active trip update functions Combine acpi_thermal_update_passive_trip() and acpi_thermal_update_active_trip() into one common function called acpi_thermal_update_trip(), so as to reduce code duplication and prepare the code in question for subsequent changes. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/acpi/thermal.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 71a1ca18c97c..d527db0f1144 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -212,14 +212,25 @@ static long get_active_temp(struct acpi_thermal *tz, int index) return tmp; } -static void acpi_thermal_update_passive_trip(struct acpi_thermal *tz) +static void acpi_thermal_update_trip(struct acpi_thermal *tz, + int index) { - struct acpi_thermal_trip *acpi_trip = &tz->trips.passive.trip; + struct acpi_thermal_trip *acpi_trip; - if (!acpi_thermal_trip_valid(acpi_trip) || psv > 0) + acpi_trip = index == ACPI_THERMAL_TRIP_PASSIVE ? + &tz->trips.passive.trip : &tz->trips.active[index].trip; + if (!acpi_thermal_trip_valid(acpi_trip)) return; - acpi_trip->temp_dk = get_passive_temp(tz); + if (index == ACPI_THERMAL_TRIP_PASSIVE) { + if (psv > 0) + return; + + acpi_trip->temp_dk = get_passive_temp(tz); + } else { + acpi_trip->temp_dk = get_active_temp(tz, index); + } + if (!acpi_thermal_trip_valid(acpi_trip)) ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } @@ -270,18 +281,6 @@ static void acpi_thermal_update_trip_devices(struct acpi_thermal *tz, int index) ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } -static void acpi_thermal_update_active_trip(struct acpi_thermal *tz, int index) -{ - struct acpi_thermal_trip *acpi_trip = &tz->trips.active[index].trip; - - if (!acpi_thermal_trip_valid(acpi_trip)) - return; - - acpi_trip->temp_dk = get_active_temp(tz, index); - if (!acpi_thermal_trip_valid(acpi_trip)) - ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); -} - static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data) { struct acpi_thermal_trip *acpi_trip = trip->priv; @@ -305,9 +304,9 @@ static void acpi_thermal_adjust_thermal_zone(struct thermal_zone_device *thermal int i; if (data == ACPI_THERMAL_NOTIFY_THRESHOLDS) { - acpi_thermal_update_passive_trip(tz); + acpi_thermal_update_trip(tz, ACPI_THERMAL_TRIP_PASSIVE); for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) - acpi_thermal_update_active_trip(tz, i); + acpi_thermal_update_trip(tz, i); } else { acpi_thermal_update_trip_devices(tz, ACPI_THERMAL_TRIP_PASSIVE); for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) From cd3c00e7760905270541981f4c5d1e31f38c2e47 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 3 Oct 2023 15:26:35 +0200 Subject: [PATCH 068/111] thermal: int340x: Use thermal_zone_for_each_trip() Modify int340x_thermal_update_trips() to use thermal_zone_for_each_trip() for walking trips instead of using the trips[] table passed to the thermal zone registration function. For this purpose, store active trip point indices in the priv fieids of the corresponding thermal_trip structures. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Acked-by: Daniel Lezcano --- .../int340x_thermal/int340x_thermal_zone.c | 80 ++++++++++--------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c index 89cf007146ea..a03b67579dd9 100644 --- a/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c +++ b/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c @@ -67,6 +67,16 @@ static struct thermal_zone_device_ops int340x_thermal_zone_ops = { .critical = int340x_thermal_critical, }; +static inline void *int_to_trip_priv(int i) +{ + return (void *)(long)i; +} + +static inline int trip_priv_to_int(const struct thermal_trip *trip) +{ + return (long)trip->priv; +} + static int int340x_thermal_read_trips(struct acpi_device *zone_adev, struct thermal_trip *zone_trips, int trip_cnt) @@ -101,6 +111,7 @@ static int int340x_thermal_read_trips(struct acpi_device *zone_adev, break; zone_trips[trip_cnt].type = THERMAL_TRIP_ACTIVE; + zone_trips[trip_cnt].priv = int_to_trip_priv(i); trip_cnt++; } @@ -212,45 +223,40 @@ void int340x_thermal_zone_remove(struct int34x_thermal_zone *int34x_zone) } EXPORT_SYMBOL_GPL(int340x_thermal_zone_remove); +static int int340x_update_one_trip(struct thermal_trip *trip, void *arg) +{ + struct acpi_device *zone_adev = arg; + int temp, err; + + switch (trip->type) { + case THERMAL_TRIP_CRITICAL: + err = thermal_acpi_critical_trip_temp(zone_adev, &temp); + break; + case THERMAL_TRIP_HOT: + err = thermal_acpi_hot_trip_temp(zone_adev, &temp); + break; + case THERMAL_TRIP_PASSIVE: + err = thermal_acpi_passive_trip_temp(zone_adev, &temp); + break; + case THERMAL_TRIP_ACTIVE: + err = thermal_acpi_active_trip_temp(zone_adev, + trip_priv_to_int(trip), + &temp); + break; + default: + err = -ENODEV; + } + if (err) + temp = THERMAL_TEMP_INVALID; + + trip->temperature = temp; + return 0; +} + void int340x_thermal_update_trips(struct int34x_thermal_zone *int34x_zone) { - struct acpi_device *zone_adev = int34x_zone->adev; - struct thermal_trip *zone_trips = int34x_zone->trips; - int trip_cnt = int34x_zone->zone->num_trips; - int act_trip_nr = 0; - int i; - - mutex_lock(&int34x_zone->zone->lock); - - for (i = int34x_zone->aux_trip_nr; i < trip_cnt; i++) { - int temp, err; - - switch (zone_trips[i].type) { - case THERMAL_TRIP_CRITICAL: - err = thermal_acpi_critical_trip_temp(zone_adev, &temp); - break; - case THERMAL_TRIP_HOT: - err = thermal_acpi_hot_trip_temp(zone_adev, &temp); - break; - case THERMAL_TRIP_PASSIVE: - err = thermal_acpi_passive_trip_temp(zone_adev, &temp); - break; - case THERMAL_TRIP_ACTIVE: - err = thermal_acpi_active_trip_temp(zone_adev, act_trip_nr++, - &temp); - break; - default: - err = -ENODEV; - } - if (err) { - zone_trips[i].temperature = THERMAL_TEMP_INVALID; - continue; - } - - zone_trips[i].temperature = temp; - } - - mutex_unlock(&int34x_zone->zone->lock); + thermal_zone_for_each_trip(int34x_zone->zone, int340x_update_one_trip, + int34x_zone->adev); } EXPORT_SYMBOL_GPL(int340x_thermal_update_trips); From b251ab28caeb5a4a63d832dcd53d29ad2dd5318f Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 3 Oct 2023 15:24:12 +0200 Subject: [PATCH 069/111] ACPI: thermal: Use thermal_zone_for_each_trip() for updating trips Rearrange the code handling notifications from the platform firmware regarding trip point updates to carry out one loop over trip points instead of two of them by using thermal_zone_for_each_trip() for that, which is more straightforward than using a combination of thermal_zone_device_exec() and for_each_thermal_trip(), each with its own callback function. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Acked-by: Daniel Lezcano --- drivers/acpi/thermal.c | 78 ++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index d527db0f1144..fb9da37a79d8 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -177,6 +177,15 @@ static bool acpi_thermal_trip_valid(struct acpi_thermal_trip *acpi_trip) return acpi_trip->temp_dk != THERMAL_TEMP_INVALID; } +static int active_trip_index(struct acpi_thermal *tz, + struct acpi_thermal_trip *acpi_trip) +{ + struct acpi_thermal_active *active; + + active = container_of(acpi_trip, struct acpi_thermal_active, trip); + return active - tz->trips.active; +} + static long get_passive_temp(struct acpi_thermal *tz) { unsigned long long tmp; @@ -213,21 +222,18 @@ static long get_active_temp(struct acpi_thermal *tz, int index) } static void acpi_thermal_update_trip(struct acpi_thermal *tz, - int index) + const struct thermal_trip *trip) { - struct acpi_thermal_trip *acpi_trip; + struct acpi_thermal_trip *acpi_trip = trip->priv; - acpi_trip = index == ACPI_THERMAL_TRIP_PASSIVE ? - &tz->trips.passive.trip : &tz->trips.active[index].trip; - if (!acpi_thermal_trip_valid(acpi_trip)) - return; - - if (index == ACPI_THERMAL_TRIP_PASSIVE) { + if (trip->type == THERMAL_TRIP_PASSIVE) { if (psv > 0) return; acpi_trip->temp_dk = get_passive_temp(tz); } else { + int index = active_trip_index(tz, acpi_trip); + acpi_trip->temp_dk = get_active_temp(tz, index); } @@ -264,31 +270,39 @@ static bool update_trip_devices(struct acpi_thermal *tz, return true; } -static void acpi_thermal_update_trip_devices(struct acpi_thermal *tz, int index) +static void acpi_thermal_update_trip_devices(struct acpi_thermal *tz, + const struct thermal_trip *trip) { - struct acpi_thermal_trip *acpi_trip; + struct acpi_thermal_trip *acpi_trip = trip->priv; + int index = trip->type == THERMAL_TRIP_PASSIVE ? + ACPI_THERMAL_TRIP_PASSIVE : active_trip_index(tz, acpi_trip); - acpi_trip = index == ACPI_THERMAL_TRIP_PASSIVE ? - &tz->trips.passive.trip : &tz->trips.active[index].trip; - if (!acpi_thermal_trip_valid(acpi_trip)) + if (update_trip_devices(tz, acpi_trip, index, true)) return; - if (update_trip_devices(tz, acpi_trip, index, true)) { - return; - } - acpi_trip->temp_dk = THERMAL_TEMP_INVALID; ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); } +struct adjust_trip_data { + struct acpi_thermal *tz; + u32 event; +}; + static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data) { struct acpi_thermal_trip *acpi_trip = trip->priv; - struct acpi_thermal *tz = data; + struct adjust_trip_data *atd = data; + struct acpi_thermal *tz = atd->tz; - if (!acpi_trip) + if (!acpi_trip || !acpi_thermal_trip_valid(acpi_trip)) return 0; + if (atd->event == ACPI_THERMAL_NOTIFY_THRESHOLDS) + acpi_thermal_update_trip(tz, trip); + else + acpi_thermal_update_trip_devices(tz, trip); + if (acpi_thermal_trip_valid(acpi_trip)) trip->temperature = acpi_thermal_temp(tz, acpi_trip->temp_dk); else @@ -297,25 +311,6 @@ static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data) return 0; } -static void acpi_thermal_adjust_thermal_zone(struct thermal_zone_device *thermal, - unsigned long data) -{ - struct acpi_thermal *tz = thermal_zone_device_priv(thermal); - int i; - - if (data == ACPI_THERMAL_NOTIFY_THRESHOLDS) { - acpi_thermal_update_trip(tz, ACPI_THERMAL_TRIP_PASSIVE); - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) - acpi_thermal_update_trip(tz, i); - } else { - acpi_thermal_update_trip_devices(tz, ACPI_THERMAL_TRIP_PASSIVE); - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) - acpi_thermal_update_trip_devices(tz, i); - } - - for_each_thermal_trip(tz->thermal_zone, acpi_thermal_adjust_trip, tz); -} - static void acpi_queue_thermal_check(struct acpi_thermal *tz) { if (!work_pending(&tz->thermal_check_work)) @@ -324,17 +319,18 @@ static void acpi_queue_thermal_check(struct acpi_thermal *tz) static void acpi_thermal_trips_update(struct acpi_thermal *tz, u32 event) { + struct adjust_trip_data atd = { .tz = tz, .event = event }; struct acpi_device *adev = tz->device; /* - * Use thermal_zone_device_exec() to carry out the trip points + * Use thermal_zone_for_each_trip() to carry out the trip points * update, so as to protect thermal_get_trend() from getting stale * trip point temperatures and to prevent thermal_zone_device_update() * invoked from acpi_thermal_check_fn() from producing inconsistent * results. */ - thermal_zone_device_exec(tz->thermal_zone, - acpi_thermal_adjust_thermal_zone, event); + thermal_zone_for_each_trip(tz->thermal_zone, + acpi_thermal_adjust_trip, &atd); acpi_queue_thermal_check(tz); acpi_bus_generate_netlink_event(adev->pnp.device_class, dev_name(&adev->dev), event, 0); From 4963e34ce7b95237021575d208fa576f88697839 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 3 Oct 2023 15:25:33 +0200 Subject: [PATCH 070/111] thermal: core: Drop thermal_zone_device_exec() Because thermal_zone_device_exec() has no users any more and there are no plans to use it anywhere, revert commit 9a99a996d1ec ("thermal: core: Introduce thermal_zone_device_exec()") that introduced it. No functional impact. Signed-off-by: Rafael J. Wysocki Acked-by: Daniel Lezcano --- drivers/thermal/thermal_core.c | 19 ------------------- include/linux/thermal.h | 4 ---- 2 files changed, 23 deletions(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 45d0aa0b69b7..8ee22eb804d3 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -495,25 +495,6 @@ void thermal_zone_device_update(struct thermal_zone_device *tz, } EXPORT_SYMBOL_GPL(thermal_zone_device_update); -/** - * thermal_zone_device_exec - Run a callback under the zone lock. - * @tz: Thermal zone. - * @cb: Callback to run. - * @data: Data to pass to the callback. - */ -void thermal_zone_device_exec(struct thermal_zone_device *tz, - void (*cb)(struct thermal_zone_device *, - unsigned long), - unsigned long data) -{ - mutex_lock(&tz->lock); - - cb(tz, data); - - mutex_unlock(&tz->lock); -} -EXPORT_SYMBOL_GPL(thermal_zone_device_exec); - static void thermal_zone_device_check(struct work_struct *work) { struct thermal_zone_device *tz = container_of(work, struct diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 2bab72149bbf..c8600e313909 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -339,10 +339,6 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int, struct thermal_cooling_device *); void thermal_zone_device_update(struct thermal_zone_device *, enum thermal_notify_event); -void thermal_zone_device_exec(struct thermal_zone_device *tz, - void (*cb)(struct thermal_zone_device *, - unsigned long), - unsigned long data); struct thermal_cooling_device *thermal_cooling_device_register(const char *, void *, const struct thermal_cooling_device_ops *); From fae633cfb729da2771b5433f6b84ae7e8b4aa5f7 Mon Sep 17 00:00:00 2001 From: David Arcari Date: Thu, 5 Oct 2023 07:17:57 -0400 Subject: [PATCH 071/111] thermal: intel: powerclamp: fix mismatch in get function for max_idle KASAN reported this [ 444.853098] BUG: KASAN: global-out-of-bounds in param_get_int+0x77/0x90 [ 444.853111] Read of size 4 at addr ffffffffc16c9220 by task cat/2105 ... [ 444.853442] The buggy address belongs to the variable: [ 444.853443] max_idle+0x0/0xffffffffffffcde0 [intel_powerclamp] There is a mismatch between the param_get_int and the definition of max_idle. Replacing param_get_int with param_get_byte resolves this issue. Fixes: ebf519710218 ("thermal: intel: powerclamp: Add two module parameters") Cc: 6.3+ # 6.3+ Signed-off-by: David Arcari Reviewed-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- drivers/thermal/intel/intel_powerclamp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/intel/intel_powerclamp.c b/drivers/thermal/intel/intel_powerclamp.c index 36243a3972fd..5ac5cb60bae6 100644 --- a/drivers/thermal/intel/intel_powerclamp.c +++ b/drivers/thermal/intel/intel_powerclamp.c @@ -256,7 +256,7 @@ static int max_idle_set(const char *arg, const struct kernel_param *kp) static const struct kernel_param_ops max_idle_ops = { .set = max_idle_set, - .get = param_get_int, + .get = param_get_byte, }; module_param_cb(max_idle, &max_idle_ops, &max_idle, 0644); From b44444027ce7714f309e96b804b7fb088a40d708 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 7 Oct 2023 13:29:22 +0200 Subject: [PATCH 072/111] thermal: trip: Remove lockdep assertion from for_each_thermal_trip() The lockdep assertion in for_each_thermal_trip() was added to possibly catch incorrect usage of that function without the thermal zone lock. However, it turns out that the ACPI thermal driver has a legitimate reason to call for_each_thermal_trip() without locking. Namely, it is called by acpi_thermal_bind_unbind_cdev() in the thermal zone registration and unregistration paths. That function cannot acquire the thermal zone lock by itself, because it calls functions that acquire it, thermal_bind_cdev_to_trip() or thermal_unbind_cdev_from_trip(). However, it is invoked when the ACPI notify handler for the thermal zone in question has not been registered yet (in the registration path) or after that handler has been unregistered (in the unregistration path). Therefore, when for_each_thermal_trip() is called by acpi_thermal_bind_unbind_cdev(), thermal trip changes induced by the platform firmware cannot take place and so the thermal zone's trips[] table is effectively immutable. Hence, it is valid to call for_each_thermal_trip() from acpi_thermal_bind_unbind_cdev() without locking and the lockdep assertion in the former is in fact incorrect, so remove it. Fixes: d5ea889246b1 ("ACPI: thermal: Do not use trip indices for cooling device binding") Signed-off-by: Rafael J. Wysocki --- drivers/thermal/thermal_trip.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/thermal/thermal_trip.c b/drivers/thermal/thermal_trip.c index 8c649a899537..9f10e2ff9248 100644 --- a/drivers/thermal/thermal_trip.c +++ b/drivers/thermal/thermal_trip.c @@ -15,8 +15,6 @@ int for_each_thermal_trip(struct thermal_zone_device *tz, { int i, ret; - lockdep_assert_held(&tz->lock); - for (i = 0; i < tz->num_trips; i++) { ret = cb(&tz->trips[i], data); if (ret) From b0e82ae3bf41fd45cca5ed4ef492d8af339f87be Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 7 Oct 2023 13:36:27 +0200 Subject: [PATCH 073/111] thermal: Remove Amit Kucheria from MAINTAINERS Amit Kucheria has not been participating in kernel development in any way or form for quite some time, so it is not useful to list him as a designated reviewer for the thermal subsystem or as the thermal zone DT binding maintainer. Remove him from the THERMAL entry in MAINTAINERS and list Daniel Lezcano as the new thermal zone DT binding maintainer. Signed-off-by: Rafael J. Wysocki Acked-by: Daniel Lezcano Acked-by: Krzysztof Kozlowski Acked-by: Amit Kucheria --- Documentation/devicetree/bindings/thermal/thermal-zones.yaml | 2 +- MAINTAINERS | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/thermal/thermal-zones.yaml b/Documentation/devicetree/bindings/thermal/thermal-zones.yaml index 4f3acdc4dec0..4a8dabc48170 100644 --- a/Documentation/devicetree/bindings/thermal/thermal-zones.yaml +++ b/Documentation/devicetree/bindings/thermal/thermal-zones.yaml @@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/base.yaml# title: Thermal zone maintainers: - - Amit Kucheria + - Daniel Lezcano description: | Thermal management is achieved in devicetree by describing the sensor hardware diff --git a/MAINTAINERS b/MAINTAINERS index b19995690904..6aeb83731d80 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21362,7 +21362,6 @@ F: drivers/media/radio/radio-raremono.c THERMAL M: Rafael J. Wysocki M: Daniel Lezcano -R: Amit Kucheria R: Zhang Rui L: linux-pm@vger.kernel.org S: Supported From e17ea8a1b1707f11df900adbd0764880aea2b1e1 Mon Sep 17 00:00:00 2001 From: Lukasz Luba Date: Fri, 6 Oct 2023 14:54:34 +0100 Subject: [PATCH 074/111] thermal: Add myself as thermal reviewer in MAINTAINERS Become designated reviewer and help thermal subsystem in development process. Signed-off-by: Lukasz Luba Signed-off-by: Rafael J. Wysocki --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 6aeb83731d80..65289d939097 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21363,6 +21363,7 @@ THERMAL M: Rafael J. Wysocki M: Daniel Lezcano R: Zhang Rui +R: Lukasz Luba L: linux-pm@vger.kernel.org S: Supported Q: https://patchwork.kernel.org/project/linux-pm/list/ From c99626092efca3061b387043d4a7399bf75fbdd5 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 7 Oct 2023 11:59:39 +0300 Subject: [PATCH 075/111] thermal: core: prevent potential string overflow The dev->id value comes from ida_alloc() so it's a number between zero and INT_MAX. If it's too high then these sprintf()s will overflow. Fixes: 203d3d4aa482 ("the generic thermal sysfs driver") Signed-off-by: Dan Carpenter Signed-off-by: Rafael J. Wysocki --- drivers/thermal/thermal_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 45d0aa0b69b7..61f0b5a3b00c 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -681,7 +681,8 @@ int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz, if (result) goto release_ida; - sprintf(dev->attr_name, "cdev%d_trip_point", dev->id); + snprintf(dev->attr_name, sizeof(dev->attr_name), "cdev%d_trip_point", + dev->id); sysfs_attr_init(&dev->attr.attr); dev->attr.attr.name = dev->attr_name; dev->attr.attr.mode = 0444; @@ -690,7 +691,8 @@ int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz, if (result) goto remove_symbol_link; - sprintf(dev->weight_attr_name, "cdev%d_weight", dev->id); + snprintf(dev->weight_attr_name, sizeof(dev->weight_attr_name), + "cdev%d_weight", dev->id); sysfs_attr_init(&dev->weight_attr.attr); dev->weight_attr.attr.name = dev->weight_attr_name; dev->weight_attr.attr.mode = S_IWUSR | S_IRUGO; From 108ffd12be24ba1d74b3314df8db32a0a6d55ba5 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 11 Oct 2023 17:45:42 +0200 Subject: [PATCH 076/111] thermal: trip: Drop lockdep assertion from thermal_zone_trip_id() The lockdep assertion in thermal_zone_trip_id() triggers when the trip point sysfs attribute of a thermal instance is read, because there is no thermal zone locking in that code path. This is not verly useful, though, because there is no mechanism by which the location of the trips[] table in a thermal zone or its size can change after binding cooling devices to the trips in that thermal zone and before those cooling devices are unbound from them. Thus it is not in fact necessary to hold the thermal zone lock when thermal_zone_trip_id() is called from trip_point_show() and so the lockdep asserion in the former is invalid. Accordingly, drop that lockdep assertion. Fixes: 2c7b4bfadef0 ("thermal: core: Store trip pointer in struct thermal_instance") Signed-off-by: Rafael J. Wysocki --- drivers/thermal/thermal_trip.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/thermal/thermal_trip.c b/drivers/thermal/thermal_trip.c index 9f10e2ff9248..80f3cdb2f30e 100644 --- a/drivers/thermal/thermal_trip.c +++ b/drivers/thermal/thermal_trip.c @@ -175,8 +175,6 @@ int thermal_zone_trip_id(struct thermal_zone_device *tz, { int i; - lockdep_assert_held(&tz->lock); - for (i = 0; i < tz->num_trips; i++) { if (&tz->trips[i] == trip) return i; From 24e4c26202801f31392a04965b539e70223d9026 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 9 Oct 2023 12:05:32 -0700 Subject: [PATCH 077/111] thermal: int340x: processor_thermal: Move interrupt status MMIO offset to common header Move define SOC_WT_RES_INT_STATUS_OFFSET to processor_thermal_device.h. This way it can be reused in other modules. Signed-off-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- .../thermal/intel/int340x_thermal/processor_thermal_device.h | 2 ++ .../thermal/intel/int340x_thermal/processor_thermal_wt_hint.c | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h index dd025c8c2bac..8ed6e8e94c8a 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h @@ -91,6 +91,8 @@ void proc_thermal_wt_req_remove(struct pci_dev *pdev); #define MBOX_DATA_BIT_AC_DC 30 #define MBOX_DATA_BIT_VALID 31 +#define SOC_WT_RES_INT_STATUS_OFFSET 0x5B18 + int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp); int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data); int processor_thermal_mbox_interrupt_config(struct pci_dev *pdev, bool enable, int enable_bit, 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 fabd8a363abb..c08838eb10c8 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c @@ -32,7 +32,6 @@ #include #include "processor_thermal_device.h" -#define SOC_WT_RES_INT_STATUS_OFFSET 0x5B18 #define SOC_WT GENMASK_ULL(47, 40) #define SOC_WT_PREDICTION_INT_ENABLE_BIT 23 From 088f16f35257becaed1c3deececda6080bc77ee3 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 9 Oct 2023 12:05:33 -0700 Subject: [PATCH 078/111] thermal: int340x: processor_thermal: Common function to clear SOC interrupt The SOC interrupt status register contains multiple interrupt sources (workload hint interrupt and power floor interrupt). It is not possible to clear individual interrupt source with read-modify-write, as it may clear the new interrupt from the firmware after a read operation. It is also not possible to set the interrupt status bit to 1 for the other interrupt source, which is not part of clearing. Hence, create a common function, to clear all status bits at once. Call this function after processing all interrupt sources. Signed-off-by: Srinivas Pandruvada [ rjw: Changelog edits ] Signed-off-by: Rafael J. Wysocki --- .../int340x_thermal/processor_thermal_device.h | 1 + .../int340x_thermal/processor_thermal_device_pci.c | 13 +++++++++++++ .../int340x_thermal/processor_thermal_wt_hint.c | 2 -- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h index 8ed6e8e94c8a..f9a381b3e55c 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h @@ -92,6 +92,7 @@ void proc_thermal_wt_req_remove(struct pci_dev *pdev); #define MBOX_DATA_BIT_VALID 31 #define SOC_WT_RES_INT_STATUS_OFFSET 0x5B18 +#define SOC_WT_RES_INT_STATUS_MASK GENMASK_ULL(3, 2) int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp); int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data); 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 3c5ced79ead0..d353a190ce44 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -122,11 +122,24 @@ static void pkg_thermal_schedule_work(struct delayed_work *work) schedule_delayed_work(work, ms); } +static void proc_thermal_clear_soc_int_status(struct proc_thermal_device *proc_priv) +{ + u64 status; + + if (!(proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT)) + return; + + status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); + writeq(status & ~SOC_WT_RES_INT_STATUS_MASK, + proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); +} + static irqreturn_t proc_thermal_irq_thread_handler(int irq, void *devid) { struct proc_thermal_pci *pci_info = devid; proc_thermal_wt_intr_callback(pci_info->pdev, pci_info->proc_priv); + proc_thermal_clear_soc_int_status(pci_info->proc_priv); return IRQ_HANDLED; } 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 c08838eb10c8..9d5e4c169d1b 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c @@ -215,8 +215,6 @@ void proc_thermal_wt_intr_callback(struct pci_dev *pdev, struct proc_thermal_dev if (!(status & SOC_WT_PREDICTION_INT_ACTIVE)) return; - writeq(status & ~SOC_WT_PREDICTION_INT_ACTIVE, - proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); sysfs_notify(&pdev->dev.kobj, "workload_hint", "workload_type_index"); } EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_intr_callback, INT340X_THERMAL); From 6ebc25d8b053a208786295bab58abbb66b39c318 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 9 Oct 2023 12:05:34 -0700 Subject: [PATCH 079/111] thermal: int340x: processor_thermal: Set feature mask before proc_thermal_add The function proc_thermal_add() adds sysfs entries for power limits. The feature mask of available features is not present at that time, so it cannot be used by proc_thermal_add() to selectively create sysfs attributes. The feature mask is set by proc_thermal_mmio_add(), so modify the code to call it before proc_thermal_add() so as to allow the latter to use the feature mask. There is no functional impact with this change. Signed-off-by: Srinivas Pandruvada [ rjw: Changelog edits ] Signed-off-by: Rafael J. Wysocki --- .../processor_thermal_device_pci.c | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) 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 d353a190ce44..ae70fabffb2d 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -266,19 +266,19 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ INIT_DELAYED_WORK(&pci_info->work, proc_thermal_threshold_work_fn); - ret = proc_thermal_add(&pdev->dev, proc_priv); - if (ret) { - dev_err(&pdev->dev, "error: proc_thermal_add, will continue\n"); - pci_info->no_legacy = 1; - } - proc_priv->priv_data = pci_info; pci_info->proc_priv = proc_priv; pci_set_drvdata(pdev, proc_priv); ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data); if (ret) - goto err_ret_thermal; + return ret; + + ret = proc_thermal_add(&pdev->dev, proc_priv); + if (ret) { + dev_err(&pdev->dev, "error: proc_thermal_add, will continue\n"); + pci_info->no_legacy = 1; + } psv_trip.temperature = get_trip_temp(pci_info); @@ -288,7 +288,7 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ &tzone_params, 0, 0); if (IS_ERR(pci_info->tzone)) { ret = PTR_ERR(pci_info->tzone); - goto err_ret_mmio; + goto err_del_legacy; } if (use_msi && (pdev->msi_enabled || pdev->msix_enabled)) { @@ -325,11 +325,10 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ pci_free_irq_vectors(pdev); err_ret_tzone: thermal_zone_device_unregister(pci_info->tzone); -err_ret_mmio: - proc_thermal_mmio_remove(pdev, proc_priv); -err_ret_thermal: +err_del_legacy: if (!pci_info->no_legacy) proc_thermal_remove(proc_priv); + proc_thermal_mmio_remove(pdev, proc_priv); pci_disable_device(pdev); return ret; From b473d6a9d68f5bc27c7e35f5c98172d5f2206039 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 9 Oct 2023 12:05:35 -0700 Subject: [PATCH 080/111] thermal: int340x: processor_thermal: Support power floor notifications When the hardware reduces the power to the minimum possible, the power floor is notified via an interrupt. This can happen when user space requests a power limit via powercap RAPL interface, which forces the system to enter to the lowest power. This power floor indication can be used as a hint to resort to other methods of reducing power than via RAPL power limit. Before power floor status can be read or the firmware can trigger notifications regarding it, it needs to be configured via a mailbox command. The actual power floor status is read via bit 39 of MMIO offset 0x5B18 of the processor thermal PCI device. To show the current power floor status and get notification on a sysfs attribute, add 2 new attributes to /sys/bus/pci/devices/0000\:00\:04.0/power_limits/ power_floor_enable : This attribute is present when power floor notifications are supported. This attribute allows to enable/disable power floor notifications. power_floor_status : This attribute is present when power floor notifications are supported. When enabled via power_floor_enable, this attribute shows the current power floor status. The power floor implementation provides interfaces which are called from the sysfs callbacks to enable/disable and read power floor status. It also provides two additional interfaces to check if the current processor thermal device interrupt is for power floor status and to send notifications to user space. Signed-off-by: Srinivas Pandruvada [ rjw: Changelog and documentation changes edits ] Signed-off-by: Rafael J. Wysocki --- .../driver-api/thermal/intel_dptf.rst | 10 ++ .../thermal/intel/int340x_thermal/Makefile | 1 + .../processor_thermal_device.c | 68 +++++++++- .../processor_thermal_device.h | 8 ++ .../processor_thermal_power_floor.c | 126 ++++++++++++++++++ 5 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c diff --git a/Documentation/driver-api/thermal/intel_dptf.rst b/Documentation/driver-api/thermal/intel_dptf.rst index 2d11e74ac665..8fb8c5b2d685 100644 --- a/Documentation/driver-api/thermal/intel_dptf.rst +++ b/Documentation/driver-api/thermal/intel_dptf.rst @@ -164,6 +164,16 @@ ABI. ``power_limit_1_tmax_us`` (RO) Maximum powercap sysfs constraint_1_time_window_us for Intel RAPL +``power_floor_status`` (RO) + When set to 1, the power floor of the system in the current + configuration has been reached. It needs to be reconfigured to allow + power to be reduced any further. + +``power_floor_enable`` (RW) + When set to 1, enable reading and notification of the power floor + status. Notifications are triggered for the power_floor_status + attribute value changes. + :file:`/sys/bus/pci/devices/0000\:00\:04.0/` ``tcc_offset_degree_celsius`` (RW) diff --git a/drivers/thermal/intel/int340x_thermal/Makefile b/drivers/thermal/intel/int340x_thermal/Makefile index f33a3ad3bef3..fe3f43924525 100644 --- a/drivers/thermal/intel/int340x_thermal/Makefile +++ b/drivers/thermal/intel/int340x_thermal/Makefile @@ -12,5 +12,6 @@ obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_rfim.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_mbox.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_wt_req.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_wt_hint.o +obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_power_floor.o obj-$(CONFIG_INT3406_THERMAL) += int3406_thermal.o obj-$(CONFIG_ACPI_THERMAL_REL) += acpi_thermal_rel.o diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c index 29ed7d0f7022..649f67fdf345 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c @@ -26,6 +26,48 @@ static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \ (unsigned long)proc_dev->power_limits[index].suffix * 1000); \ } +static ssize_t power_floor_status_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct proc_thermal_device *proc_dev = dev_get_drvdata(dev); + int ret; + + ret = proc_thermal_read_power_floor_status(proc_dev); + + return sysfs_emit(buf, "%d\n", ret); +} + +static ssize_t power_floor_enable_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct proc_thermal_device *proc_dev = dev_get_drvdata(dev); + bool ret; + + ret = proc_thermal_power_floor_get_state(proc_dev); + + return sysfs_emit(buf, "%d\n", ret); +} + +static ssize_t power_floor_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct proc_thermal_device *proc_dev = dev_get_drvdata(dev); + u8 state; + int ret; + + if (kstrtou8(buf, 0, &state)) + return -EINVAL; + + ret = proc_thermal_power_floor_set_state(proc_dev, !!state); + if (ret) + return ret; + + return count; +} + POWER_LIMIT_SHOW(0, min_uw) POWER_LIMIT_SHOW(0, max_uw) POWER_LIMIT_SHOW(0, step_uw) @@ -50,6 +92,9 @@ static DEVICE_ATTR_RO(power_limit_1_step_uw); static DEVICE_ATTR_RO(power_limit_1_tmin_us); static DEVICE_ATTR_RO(power_limit_1_tmax_us); +static DEVICE_ATTR_RO(power_floor_status); +static DEVICE_ATTR_RW(power_floor_enable); + static struct attribute *power_limit_attrs[] = { &dev_attr_power_limit_0_min_uw.attr, &dev_attr_power_limit_1_min_uw.attr, @@ -61,12 +106,30 @@ static struct attribute *power_limit_attrs[] = { &dev_attr_power_limit_1_tmin_us.attr, &dev_attr_power_limit_0_tmax_us.attr, &dev_attr_power_limit_1_tmax_us.attr, + &dev_attr_power_floor_status.attr, + &dev_attr_power_floor_enable.attr, NULL }; +static umode_t power_limit_attr_visible(struct kobject *kobj, struct attribute *attr, int unused) +{ + struct device *dev = kobj_to_dev(kobj); + struct proc_thermal_device *proc_dev; + + if (attr != &dev_attr_power_floor_status.attr && attr != &dev_attr_power_floor_enable.attr) + return attr->mode; + + proc_dev = dev_get_drvdata(dev); + if (!proc_dev || !(proc_dev->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR)) + return 0; + + return attr->mode; +} + static const struct attribute_group power_limit_attribute_group = { .attrs = power_limit_attrs, - .name = "power_limits" + .name = "power_limits", + .is_visible = power_limit_attr_visible, }; static ssize_t tcc_offset_degree_celsius_show(struct device *dev, @@ -380,6 +443,9 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device * proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS) proc_thermal_rfim_remove(pdev); + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR) + proc_thermal_power_floor_set_state(proc_priv, false); + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_REQ) proc_thermal_wt_req_remove(pdev); else if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT) diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h index f9a381b3e55c..95c6013a33fb 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h @@ -63,6 +63,7 @@ struct rapl_mmio_regs { #define PROC_THERMAL_FEATURE_WT_REQ 0x08 #define PROC_THERMAL_FEATURE_DLVR 0x10 #define PROC_THERMAL_FEATURE_WT_HINT 0x20 +#define PROC_THERMAL_FEATURE_POWER_FLOOR 0x40 #if IS_ENABLED(CONFIG_PROC_THERMAL_MMIO_RAPL) int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); @@ -94,6 +95,13 @@ void proc_thermal_wt_req_remove(struct pci_dev *pdev); #define SOC_WT_RES_INT_STATUS_OFFSET 0x5B18 #define SOC_WT_RES_INT_STATUS_MASK GENMASK_ULL(3, 2) +int proc_thermal_read_power_floor_status(struct proc_thermal_device *proc_priv); +int proc_thermal_power_floor_set_state(struct proc_thermal_device *proc_priv, bool enable); +bool proc_thermal_power_floor_get_state(struct proc_thermal_device *proc_priv); +void proc_thermal_power_floor_intr_callback(struct pci_dev *pdev, + struct proc_thermal_device *proc_priv); +bool proc_thermal_check_power_floor_intr(struct proc_thermal_device *proc_priv); + int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp); int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data); int processor_thermal_mbox_interrupt_config(struct pci_dev *pdev, bool enable, int enable_bit, diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c new file mode 100644 index 000000000000..a1a108407f0f --- /dev/null +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Processor thermal device module for registering and processing + * power floor. When the hardware reduces the power to the minimum + * possible, the power floor is notified via an interrupt. + * + * Operation: + * When user space enables power floor reporting: + * - Use mailbox to: + * Enable processor thermal device interrupt + * + * - Current status of power floor is read from offset 0x5B18 + * bit 39. + * + * Two interface functions are provided to call when there is a + * thermal device interrupt: + * - proc_thermal_power_floor_intr(): + * Check if the interrupt is for change in power floor. + * Called from interrupt context. + * + * - proc_thermal_power_floor_intr_callback(): + * Callback for interrupt processing in thread context. This involves + * sending notification to user space that there is a change in the + * power floor status. + * + * Copyright (c) 2023, Intel Corporation. + */ + +#include +#include "processor_thermal_device.h" + +#define SOC_POWER_FLOOR_STATUS BIT(39) +#define SOC_POWER_FLOOR_SHIFT 39 + +#define SOC_POWER_FLOOR_INT_ENABLE_BIT 31 +#define SOC_POWER_FLOOR_INT_ACTIVE BIT(3) + +int proc_thermal_read_power_floor_status(struct proc_thermal_device *proc_priv) +{ + u64 status = 0; + + status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); + return (status & SOC_POWER_FLOOR_STATUS) >> SOC_POWER_FLOOR_SHIFT; +} +EXPORT_SYMBOL_NS_GPL(proc_thermal_read_power_floor_status, INT340X_THERMAL); + +static bool enable_state; +static DEFINE_MUTEX(pf_lock); + +int proc_thermal_power_floor_set_state(struct proc_thermal_device *proc_priv, bool enable) +{ + int ret = 0; + + mutex_lock(&pf_lock); + if (enable_state == enable) + goto pf_unlock; + + /* + * Time window parameter is not applicable to power floor interrupt configuration. + * Hence use -1 for time window. + */ + ret = processor_thermal_mbox_interrupt_config(to_pci_dev(proc_priv->dev), enable, + SOC_POWER_FLOOR_INT_ENABLE_BIT, -1); + if (!ret) + enable_state = enable; + +pf_unlock: + mutex_unlock(&pf_lock); + + return ret; +} +EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_set_state, INT340X_THERMAL); + +bool proc_thermal_power_floor_get_state(struct proc_thermal_device *proc_priv) +{ + return enable_state; +} +EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_get_state, INT340X_THERMAL); + +/** + * proc_thermal_check_power_floor_intr() - Check power floor interrupt. + * @proc_priv: Processor thermal device instance. + * + * Callback to check if the interrupt for power floor is active. + * + * Context: Called from interrupt context. + * + * Return: true if power floor is active, false when not active. + */ +bool proc_thermal_check_power_floor_intr(struct proc_thermal_device *proc_priv) +{ + u64 int_status; + + int_status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); + return !!(int_status & SOC_POWER_FLOOR_INT_ACTIVE); +} +EXPORT_SYMBOL_NS_GPL(proc_thermal_check_power_floor_intr, INT340X_THERMAL); + +/** + * proc_thermal_power_floor_intr_callback() - Process power floor notification + * @pdev: PCI device instance + * @proc_priv: Processor thermal device instance. + * + * Check if the power floor interrupt is active, if active send notification to + * user space for the attribute "power_limits", so that user can read the attribute + * and take action. + * + * Context: Called from interrupt thread context. + * + * Return: None. + */ +void proc_thermal_power_floor_intr_callback(struct pci_dev *pdev, + struct proc_thermal_device *proc_priv) +{ + u64 status; + + status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); + if (!(status & SOC_POWER_FLOOR_INT_ACTIVE)) + return; + + sysfs_notify(&pdev->dev.kobj, "power_limits", "power_floor_status"); +} +EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_intr_callback, INT340X_THERMAL); + +MODULE_IMPORT_NS(INT340X_THERMAL); +MODULE_LICENSE("GPL"); From 8cd5ad18ddc3caab734c376eda5214f01eeb932c Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 9 Oct 2023 12:05:36 -0700 Subject: [PATCH 081/111] thermal: int340x: processor_thermal: Handle power floor interrupts On thermal device interrupt, if the interrupt is generated for passing power floor status, call the callback to pass notification to the user space. First call proc_thermal_check_power_floor_intr() to check interrupt, if this callback returns true, wake the IRQ thread to call proc_thermal_power_floor_intr_callback() to notify user space. Signed-off-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- .../intel/int340x_thermal/processor_thermal_device_pci.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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 ae70fabffb2d..4c2194f19ed2 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -126,7 +126,8 @@ static void proc_thermal_clear_soc_int_status(struct proc_thermal_device *proc_p { u64 status; - if (!(proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT)) + if (!(proc_priv->mmio_feature_mask & + (PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR))) return; status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); @@ -139,6 +140,7 @@ static irqreturn_t proc_thermal_irq_thread_handler(int irq, void *devid) struct proc_thermal_pci *pci_info = devid; proc_thermal_wt_intr_callback(pci_info->pdev, pci_info->proc_priv); + proc_thermal_power_floor_intr_callback(pci_info->pdev, pci_info->proc_priv); proc_thermal_clear_soc_int_status(pci_info->proc_priv); return IRQ_HANDLED; @@ -158,6 +160,11 @@ static irqreturn_t proc_thermal_irq_handler(int irq, void *devid) ret = IRQ_WAKE_THREAD; } + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR) { + if (proc_thermal_check_power_floor_intr(pci_info->proc_priv)) + ret = IRQ_WAKE_THREAD; + } + /* * Since now there are two sources of interrupts: one from thermal threshold * and another from workload hint, add a check if there was really a threshold From 0e509253924b5eed886029a3b49dcef9f6001c49 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 9 Oct 2023 12:05:37 -0700 Subject: [PATCH 082/111] thermal: int340x: processor_thermal: Enable power floor support Enable power floor feature support for Meteor Lake processors. Signed-off-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- .../intel/int340x_thermal/processor_thermal_device_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 4c2194f19ed2..d7495571dd5d 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c @@ -409,7 +409,7 @@ static const struct pci_device_id proc_thermal_pci_ids[] = { PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | - PROC_THERMAL_FEATURE_WT_HINT) }, + PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR) }, { PCI_DEVICE_DATA(INTEL, ARL_S_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_WT_HINT) }, { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | From d4d27e5a1a88f433a4fabf748e00d626be48cd75 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 9 Oct 2023 12:05:38 -0700 Subject: [PATCH 083/111] selftests/thermel/intel: Add test to read power floor status Some SoCs have firmware support to notify, if the system can't lower power limit to a value requested from user space via RAPL constraints. This test program waits for notification of power floor and prints. This program can be used to test this feature and also allows other user space programs to use as a reference. Signed-off-by: Srinivas Pandruvada Signed-off-by: Rafael J. Wysocki --- tools/testing/selftests/Makefile | 1 + .../thermal/intel/power_floor/Makefile | 12 ++ .../intel/power_floor/power_floor_test.c | 108 ++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 tools/testing/selftests/thermal/intel/power_floor/Makefile create mode 100644 tools/testing/selftests/thermal/intel/power_floor/power_floor_test.c diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 725ce59e4637..c99de76fb20d 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -85,6 +85,7 @@ TARGETS += syscall_user_dispatch TARGETS += sysctl TARGETS += tc-testing TARGETS += tdx +TARGETS += thermal/intel/power_floor TARGETS += thermal/intel/workload_hint TARGETS += timens ifneq (1, $(quicktest)) diff --git a/tools/testing/selftests/thermal/intel/power_floor/Makefile b/tools/testing/selftests/thermal/intel/power_floor/Makefile new file mode 100644 index 000000000000..9b88e57dbba5 --- /dev/null +++ b/tools/testing/selftests/thermal/intel/power_floor/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0 +ifndef CROSS_COMPILE +uname_M := $(shell uname -m 2>/dev/null || echo not) +ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) + +ifeq ($(ARCH),x86) +TEST_GEN_PROGS := power_floor_test + +include ../../../lib.mk + +endif +endif diff --git a/tools/testing/selftests/thermal/intel/power_floor/power_floor_test.c b/tools/testing/selftests/thermal/intel/power_floor/power_floor_test.c new file mode 100644 index 000000000000..0326b39a11b9 --- /dev/null +++ b/tools/testing/selftests/thermal/intel/power_floor/power_floor_test.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#define POWER_FLOOR_ENABLE_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/power_limits/power_floor_enable" +#define POWER_FLOOR_STATUS_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/power_limits/power_floor_status" + +void power_floor_exit(int signum) +{ + int fd; + + /* Disable feature via sysfs knob */ + + fd = open(POWER_FLOOR_ENABLE_ATTRIBUTE, O_RDWR); + if (fd < 0) { + perror("Unable to open power floor enable file\n"); + exit(1); + } + + if (write(fd, "0\n", 2) < 0) { + perror("Can' disable power floor notifications\n"); + exit(1); + } + + printf("Disabled power floor notifications\n"); + + close(fd); +} + +int main(int argc, char **argv) +{ + struct pollfd ufd; + char status_str[3]; + int fd, ret; + + if (signal(SIGINT, power_floor_exit) == SIG_IGN) + signal(SIGINT, SIG_IGN); + if (signal(SIGHUP, power_floor_exit) == SIG_IGN) + signal(SIGHUP, SIG_IGN); + if (signal(SIGTERM, power_floor_exit) == SIG_IGN) + signal(SIGTERM, SIG_IGN); + + /* Enable feature via sysfs knob */ + fd = open(POWER_FLOOR_ENABLE_ATTRIBUTE, O_RDWR); + if (fd < 0) { + perror("Unable to open power floor enable file\n"); + exit(1); + } + + if (write(fd, "1\n", 2) < 0) { + perror("Can' enable power floor notifications\n"); + exit(1); + } + + close(fd); + + printf("Enabled power floor notifications\n"); + + while (1) { + fd = open(POWER_FLOOR_STATUS_ATTRIBUTE, O_RDONLY); + if (fd < 0) { + perror("Unable to power floor status file\n"); + exit(1); + } + + if ((lseek(fd, 0L, SEEK_SET)) < 0) { + fprintf(stderr, "Failed to set pointer to beginning\n"); + exit(1); + } + + if (read(fd, status_str, sizeof(status_str)) < 0) { + fprintf(stderr, "Failed to read from:%s\n", + POWER_FLOOR_STATUS_ATTRIBUTE); + exit(1); + } + + ufd.fd = fd; + ufd.events = POLLPRI; + + ret = poll(&ufd, 1, -1); + if (ret < 0) { + perror("poll error"); + exit(1); + } else if (ret == 0) { + printf("Poll Timeout\n"); + } else { + if ((lseek(fd, 0L, SEEK_SET)) < 0) { + fprintf(stderr, "Failed to set pointer to beginning\n"); + exit(1); + } + + if (read(fd, status_str, sizeof(status_str)) < 0) + exit(0); + + printf("power floor status: %s\n", status_str); + } + + close(fd); + } +} From d8b877d60d77a5989061ebed7d6a84850f89d23b Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Fri, 22 Sep 2023 07:50:17 +0200 Subject: [PATCH 084/111] dt-bindings: thermal: mediatek: Add mt7988 lvts compatible Add compatible string for mt7988 lvts application processor. Signed-off-by: Frank Wunderlich Reviewed-by: AngeloGioacchino Del Regno Acked-by: Krzysztof Kozlowski Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230922055020.6436-2-linux@fw-web.de --- .../devicetree/bindings/thermal/mediatek,lvts-thermal.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml b/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml index fe9ae4c425c0..e6665af52ee6 100644 --- a/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml +++ b/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml @@ -18,6 +18,7 @@ description: | properties: compatible: enum: + - mediatek,mt7988-lvts-ap - mediatek,mt8192-lvts-ap - mediatek,mt8192-lvts-mcu - mediatek,mt8195-lvts-ap From be2cc09bd5b46f13629d4fcdeac7ad1b18bb1a0b Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Fri, 22 Sep 2023 07:50:18 +0200 Subject: [PATCH 085/111] dt-bindings: thermal: mediatek: Add LVTS thermal sensors for mt7988 Add sensor constants for MT7988. Signed-off-by: Frank Wunderlich Reviewed-by: AngeloGioacchino Del Regno Acked-by: Conor Dooley Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230922055020.6436-3-linux@fw-web.de --- include/dt-bindings/thermal/mediatek,lvts-thermal.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/dt-bindings/thermal/mediatek,lvts-thermal.h b/include/dt-bindings/thermal/mediatek,lvts-thermal.h index 8fa5a46675c4..8c1fdc18cf34 100644 --- a/include/dt-bindings/thermal/mediatek,lvts-thermal.h +++ b/include/dt-bindings/thermal/mediatek,lvts-thermal.h @@ -7,6 +7,15 @@ #ifndef __MEDIATEK_LVTS_DT_H #define __MEDIATEK_LVTS_DT_H +#define MT7988_CPU_0 0 +#define MT7988_CPU_1 1 +#define MT7988_ETH2P5G_0 2 +#define MT7988_ETH2P5G_1 3 +#define MT7988_TOPS_0 4 +#define MT7988_TOPS_1 5 +#define MT7988_ETHWARP_0 6 +#define MT7988_ETHWARP_1 7 + #define MT8195_MCU_BIG_CPU0 0 #define MT8195_MCU_BIG_CPU1 1 #define MT8195_MCU_BIG_CPU2 2 From 6725a29321e48b1dece66fc1ba7b458f0c1d6d77 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Fri, 22 Sep 2023 07:50:19 +0200 Subject: [PATCH 086/111] thermal/drivers/mediatek/lvts_thermal: Make coeff configurable The upcoming mt7988 has different temperature coefficients so we cannot use constants in the functions lvts_golden_temp_init, lvts_golden_temp_init and lvts_raw_to_temp anymore. Add a field in the lvts_ctrl pointing to the lvts_data which now contains the soc-specific temperature coefficents. To make the code better readable, rename static int coeff_b to golden_temp_offset, COEFF_A to temp_factor and COEFF_B to temp_offset. Signed-off-by: Frank Wunderlich Reviewed-by: AngeloGioacchino Del Regno Tested-by: Daniel Golle Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230922055020.6436-4-linux@fw-web.de --- drivers/thermal/mediatek/lvts_thermal.c | 51 ++++++++++++++++--------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index 877a0e5ac3fd..f9dcc50f4fd4 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -80,8 +80,8 @@ #define LVTS_SENSOR_MAX 4 #define LVTS_GOLDEN_TEMP_MAX 62 #define LVTS_GOLDEN_TEMP_DEFAULT 50 -#define LVTS_COEFF_A -250460 -#define LVTS_COEFF_B 250460 +#define LVTS_COEFF_A_MT8195 -250460 +#define LVTS_COEFF_B_MT8195 250460 #define LVTS_MSR_IMMEDIATE_MODE 0 #define LVTS_MSR_FILTERED_MODE 1 @@ -94,7 +94,7 @@ #define LVTS_MINIMUM_THRESHOLD 20000 static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT; -static int coeff_b = LVTS_COEFF_B; +static int golden_temp_offset; struct lvts_sensor_data { int dt_id; @@ -112,6 +112,8 @@ struct lvts_ctrl_data { struct lvts_data { const struct lvts_ctrl_data *lvts_ctrl; int num_lvts_ctrl; + int temp_factor; + int temp_offset; }; struct lvts_sensor { @@ -126,6 +128,7 @@ struct lvts_sensor { struct lvts_ctrl { struct lvts_sensor sensors[LVTS_SENSOR_MAX]; + const struct lvts_data *lvts_data; u32 calibration[LVTS_SENSOR_MAX]; u32 hw_tshut_raw_temp; int num_lvts_sensor; @@ -247,21 +250,21 @@ static void lvts_debugfs_exit(struct lvts_domain *lvts_td) { } #endif -static int lvts_raw_to_temp(u32 raw_temp) +static int lvts_raw_to_temp(u32 raw_temp, int temp_factor) { int temperature; - temperature = ((s64)(raw_temp & 0xFFFF) * LVTS_COEFF_A) >> 14; - temperature += coeff_b; + temperature = ((s64)(raw_temp & 0xFFFF) * temp_factor) >> 14; + temperature += golden_temp_offset; return temperature; } -static u32 lvts_temp_to_raw(int temperature) +static u32 lvts_temp_to_raw(int temperature, int temp_factor) { - u32 raw_temp = ((s64)(coeff_b - temperature)) << 14; + u32 raw_temp = ((s64)(golden_temp_offset - temperature)) << 14; - raw_temp = div_s64(raw_temp, -LVTS_COEFF_A); + raw_temp = div_s64(raw_temp, -temp_factor); return raw_temp; } @@ -269,6 +272,9 @@ static u32 lvts_temp_to_raw(int temperature) static int lvts_get_temp(struct thermal_zone_device *tz, int *temp) { struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); + struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, + sensors[lvts_sensor->id]); + const struct lvts_data *lvts_data = lvts_ctrl->lvts_data; void __iomem *msr = lvts_sensor->msr; u32 value; int rc; @@ -301,7 +307,7 @@ static int lvts_get_temp(struct thermal_zone_device *tz, int *temp) if (rc) return -EAGAIN; - *temp = lvts_raw_to_temp(value & 0xFFFF); + *temp = lvts_raw_to_temp(value & 0xFFFF, lvts_data->temp_factor); return 0; } @@ -348,10 +354,13 @@ static bool lvts_should_update_thresh(struct lvts_ctrl *lvts_ctrl, int high) static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high) { struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); - struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, sensors[lvts_sensor->id]); + struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, + sensors[lvts_sensor->id]); + const struct lvts_data *lvts_data = lvts_ctrl->lvts_data; void __iomem *base = lvts_sensor->base; - u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD); - u32 raw_high = lvts_temp_to_raw(high); + u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD, + lvts_data->temp_factor); + u32 raw_high = lvts_temp_to_raw(high, lvts_data->temp_factor); bool should_update_thresh; lvts_sensor->low_thresh = low; @@ -692,7 +701,7 @@ static int lvts_calibration_read(struct device *dev, struct lvts_domain *lvts_td return 0; } -static int lvts_golden_temp_init(struct device *dev, u32 *value) +static int lvts_golden_temp_init(struct device *dev, u32 *value, int temp_offset) { u32 gt; @@ -701,7 +710,7 @@ static int lvts_golden_temp_init(struct device *dev, u32 *value) if (gt && gt < LVTS_GOLDEN_TEMP_MAX) golden_temp = gt; - coeff_b = golden_temp * 500 + LVTS_COEFF_B; + golden_temp_offset = golden_temp * 500 + temp_offset; return 0; } @@ -724,7 +733,7 @@ static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td, * The golden temp information is contained in the first chunk * of efuse data. */ - ret = lvts_golden_temp_init(dev, (u32 *)lvts_td->calib); + ret = lvts_golden_temp_init(dev, (u32 *)lvts_td->calib, lvts_data->temp_offset); if (ret) return ret; @@ -735,6 +744,7 @@ static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td, for (i = 0; i < lvts_data->num_lvts_ctrl; i++) { lvts_ctrl[i].base = lvts_td->base + lvts_data->lvts_ctrl[i].offset; + lvts_ctrl[i].lvts_data = lvts_data; ret = lvts_sensor_init(dev, &lvts_ctrl[i], &lvts_data->lvts_ctrl[i]); @@ -758,7 +768,8 @@ static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td, * after initializing the calibration. */ lvts_ctrl[i].hw_tshut_raw_temp = - lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp); + lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp, + lvts_data->temp_factor); lvts_ctrl[i].low_thresh = INT_MIN; lvts_ctrl[i].high_thresh = INT_MIN; @@ -1223,6 +1234,8 @@ static int lvts_probe(struct platform_device *pdev) if (irq < 0) return irq; + golden_temp_offset = lvts_data->temp_offset; + ret = lvts_domain_init(dev, lvts_td, lvts_data); if (ret) return dev_err_probe(dev, ret, "Failed to initialize the lvts domain\n"); @@ -1336,11 +1349,15 @@ static const struct lvts_ctrl_data mt8195_lvts_ap_data_ctrl[] = { static const struct lvts_data mt8195_lvts_mcu_data = { .lvts_ctrl = mt8195_lvts_mcu_data_ctrl, .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_mcu_data_ctrl), + .temp_factor = LVTS_COEFF_A_MT8195, + .temp_offset = LVTS_COEFF_B_MT8195, }; static const struct lvts_data mt8195_lvts_ap_data = { .lvts_ctrl = mt8195_lvts_ap_data_ctrl, .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_ap_data_ctrl), + .temp_factor = LVTS_COEFF_A_MT8195, + .temp_offset = LVTS_COEFF_B_MT8195, }; static const struct of_device_id lvts_of_match[] = { From 585e92e6a79f2de0e9356ee399891a5fa3c0fbbf Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Fri, 22 Sep 2023 07:50:20 +0200 Subject: [PATCH 087/111] thermal/drivers/mediatek/lvts_thermal: Add mt7988 support Add Support for Mediatek Filogic 880/MT7988 LVTS. Signed-off-by: Frank Wunderlich Tested-by: Daniel Golle Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230922055020.6436-5-linux@fw-web.de --- drivers/thermal/mediatek/lvts_thermal.c | 38 +++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index f9dcc50f4fd4..f1feaa1ace2e 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -82,6 +82,8 @@ #define LVTS_GOLDEN_TEMP_DEFAULT 50 #define LVTS_COEFF_A_MT8195 -250460 #define LVTS_COEFF_B_MT8195 250460 +#define LVTS_COEFF_A_MT7988 -204650 +#define LVTS_COEFF_B_MT7988 204650 #define LVTS_MSR_IMMEDIATE_MODE 0 #define LVTS_MSR_FILTERED_MODE 1 @@ -89,6 +91,7 @@ #define LVTS_MSR_READ_TIMEOUT_US 400 #define LVTS_MSR_READ_WAIT_US (LVTS_MSR_READ_TIMEOUT_US / 2) +#define LVTS_HW_SHUTDOWN_MT7988 105000 #define LVTS_HW_SHUTDOWN_MT8195 105000 #define LVTS_MINIMUM_THRESHOLD 20000 @@ -1267,6 +1270,33 @@ static void lvts_remove(struct platform_device *pdev) lvts_debugfs_exit(lvts_td); } +static const struct lvts_ctrl_data mt7988_lvts_ap_data_ctrl[] = { + { + .cal_offset = { 0x00, 0x04, 0x08, 0x0c }, + .lvts_sensor = { + { .dt_id = MT7988_CPU_0 }, + { .dt_id = MT7988_CPU_1 }, + { .dt_id = MT7988_ETH2P5G_0 }, + { .dt_id = MT7988_ETH2P5G_1 } + }, + .num_lvts_sensor = 4, + .offset = 0x0, + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT7988, + }, + { + .cal_offset = { 0x14, 0x18, 0x1c, 0x20 }, + .lvts_sensor = { + { .dt_id = MT7988_TOPS_0}, + { .dt_id = MT7988_TOPS_1}, + { .dt_id = MT7988_ETHWARP_0}, + { .dt_id = MT7988_ETHWARP_1} + }, + .num_lvts_sensor = 4, + .offset = 0x100, + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT7988, + } +}; + static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { { .cal_offset = { 0x04, 0x07 }, @@ -1346,6 +1376,13 @@ static const struct lvts_ctrl_data mt8195_lvts_ap_data_ctrl[] = { } }; +static const struct lvts_data mt7988_lvts_ap_data = { + .lvts_ctrl = mt7988_lvts_ap_data_ctrl, + .num_lvts_ctrl = ARRAY_SIZE(mt7988_lvts_ap_data_ctrl), + .temp_factor = LVTS_COEFF_A_MT7988, + .temp_offset = LVTS_COEFF_B_MT7988, +}; + static const struct lvts_data mt8195_lvts_mcu_data = { .lvts_ctrl = mt8195_lvts_mcu_data_ctrl, .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_mcu_data_ctrl), @@ -1361,6 +1398,7 @@ static const struct lvts_data mt8195_lvts_ap_data = { }; static const struct of_device_id lvts_of_match[] = { + { .compatible = "mediatek,mt7988-lvts-ap", .data = &mt7988_lvts_ap_data }, { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data }, { .compatible = "mediatek,mt8195-lvts-ap", .data = &mt8195_lvts_ap_data }, {}, From 6644c6291eec478874c9c4591282746da893bca5 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 26 Sep 2023 11:44:52 -0500 Subject: [PATCH 088/111] dt-bindings: thermal: nvidia,tegra124-soctherm: Add missing unevaluatedProperties on child node schemas Just as unevaluatedProperties or additionalProperties are required at the top level of schemas, they should (and will) also be required for child node schemas. That ensures only documented properties are present for any node. Add unevaluatedProperties as needed, and then add any missing properties flagged by the addition. Signed-off-by: Rob Herring Acked-by: Conor Dooley Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230926164500.101593-1-robh@kernel.org --- .../bindings/thermal/nvidia,tegra124-soctherm.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.yaml b/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.yaml index 04a2ba1aa946..b0237d236021 100644 --- a/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.yaml +++ b/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.yaml @@ -68,7 +68,12 @@ properties: patternProperties: "^(light|heavy|oc1)$": type: object + additionalProperties: false + properties: + "#cooling-cells": + const: 2 + nvidia,priority: $ref: /schemas/types.yaml#/definitions/uint32 minimum: 1 From f84f6e0f4588650e22543376d3333d65d578ff73 Mon Sep 17 00:00:00 2001 From: Bragatheswaran Manickavel Date: Sun, 17 Sep 2023 14:04:43 +0530 Subject: [PATCH 089/111] thermal/drivers/imx8mm_thermal: Fix function pointer declaration by adding identifier name Added identifier names to respective definitions for fix warnings reported by checkpatch.pl WARNING: function definition argument 'void *' should also have an identifier name WARNING: function definition argument 'int *' should also have an identifier name Signed-off-by: Bragatheswaran Manickavel Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230917083443.3220-1-bragathemanick0908@gmail.com --- drivers/thermal/imx8mm_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/imx8mm_thermal.c b/drivers/thermal/imx8mm_thermal.c index c58fc73c0744..d74ed6ce2974 100644 --- a/drivers/thermal/imx8mm_thermal.c +++ b/drivers/thermal/imx8mm_thermal.c @@ -78,7 +78,7 @@ struct thermal_soc_data { u32 num_sensors; u32 version; - int (*get_temp)(void *, int *); + int (*get_temp)(void *data, int *temp); }; struct tmu_sensor { From ebd1dea94b2e9b60ca8630c7de7602bae08d401d Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 26 Sep 2023 09:29:54 -0300 Subject: [PATCH 090/111] dt-bindings: thermal: fsl,scu-thermal: Document imx8dl imx8dxl also contains the SCU thermal block. Add an entry for 'fsl,imx8dxl-sc-thermal'. Cc: Rafael J. Wysocki Cc: Daniel Lezcano Cc: Amit Kucheria Signed-off-by: Fabio Estevam Acked-by: Conor Dooley Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230926122957.341094-5-festevam@gmail.com --- .../devicetree/bindings/thermal/fsl,scu-thermal.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/thermal/fsl,scu-thermal.yaml b/Documentation/devicetree/bindings/thermal/fsl,scu-thermal.yaml index 3721c8c8ec64..e02d04d4f71e 100644 --- a/Documentation/devicetree/bindings/thermal/fsl,scu-thermal.yaml +++ b/Documentation/devicetree/bindings/thermal/fsl,scu-thermal.yaml @@ -18,7 +18,9 @@ allOf: properties: compatible: items: - - const: fsl,imx8qxp-sc-thermal + - enum: + - fsl,imx8dxl-sc-thermal + - fsl,imx8qxp-sc-thermal - const: fsl,imx-sc-thermal '#thermal-sensor-cells': From de84da588f35423c5c2e6a46f2bc8a07f8eaf793 Mon Sep 17 00:00:00 2001 From: Kuan-Wei Chiu Date: Wed, 27 Sep 2023 01:37:36 +0800 Subject: [PATCH 091/111] tools/thermal: Remove unused 'mds' and 'nrhandler' variables In the previous code, the 'mds' and 'nrhandler' variables were not utilized in the codebase. Additionally, there was a potential NULL pointer dereference and memory leak due to improper handling of memory reallocation failure. This patch removes the unused 'mds' and 'nrhandler' variables along with the associated code, addressing the unused variable issue, NULL pointer dereference issue and the memory leak issue. Signed-off-by: Kuan-Wei Chiu Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230926173736.1142420-1-visitorckw@gmail.com --- tools/thermal/lib/mainloop.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/tools/thermal/lib/mainloop.c b/tools/thermal/lib/mainloop.c index 94cbbcbd1c14..bf4c1b730d7b 100644 --- a/tools/thermal/lib/mainloop.c +++ b/tools/thermal/lib/mainloop.c @@ -9,7 +9,6 @@ #include "log.h" static int epfd = -1; -static unsigned short nrhandler; static sig_atomic_t exit_mainloop; struct mainloop_data { @@ -18,8 +17,6 @@ struct mainloop_data { int fd; }; -static struct mainloop_data **mds; - #define MAX_EVENTS 10 int mainloop(unsigned int timeout) @@ -61,13 +58,6 @@ int mainloop_add(int fd, mainloop_callback_t cb, void *data) struct mainloop_data *md; - if (fd >= nrhandler) { - mds = realloc(mds, sizeof(*mds) * (fd + 1)); - if (!mds) - return -1; - nrhandler = fd + 1; - } - md = malloc(sizeof(*md)); if (!md) return -1; @@ -76,7 +66,6 @@ int mainloop_add(int fd, mainloop_callback_t cb, void *data) md->cb = cb; md->fd = fd; - mds[fd] = md; ev.data.ptr = md; if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0) { @@ -89,14 +78,9 @@ int mainloop_add(int fd, mainloop_callback_t cb, void *data) int mainloop_del(int fd) { - if (fd >= nrhandler) - return -1; - if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) < 0) return -1; - free(mds[fd]); - return 0; } From 2ffa39c83b39f555d9a61daec3ed1cc79c4ba7ef Mon Sep 17 00:00:00 2001 From: Minjie Du Date: Thu, 21 Sep 2023 17:10:50 +0800 Subject: [PATCH 092/111] thermal/drivers/mediatek/lvts_thermal: Fix error check in lvts_debugfs_init() debugfs_create_dir() function returns an error value embedded in the pointer (PTR_ERR). Evaluate the return value using IS_ERR rather than checking for NULL. Signed-off-by: Minjie Du Reviewed-by: Alexandre Mergnat Reviewed-by: Chen-Yu Tsai Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230921091057.3812-1-duminjie@vivo.com --- drivers/thermal/mediatek/lvts_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index f1feaa1ace2e..704b22d12e27 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -219,7 +219,7 @@ static int lvts_debugfs_init(struct device *dev, struct lvts_domain *lvts_td) sprintf(name, "controller%d", i); dentry = debugfs_create_dir(name, lvts_td->dom_dentry); - if (!dentry) + if (IS_ERR(dentry)) continue; regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL); From 50ab53095326d4aa56a5a7e5f2ebc1568b4924a8 Mon Sep 17 00:00:00 2001 From: Priyansh Jain Date: Tue, 26 Sep 2023 14:29:47 +0530 Subject: [PATCH 093/111] dt-bindings: thermal: tsens: Add sa8775p compatible Add compatibility string for the thermal sensors on sa8775p platform. Signed-off-by: Priyansh Jain Acked-by: Krzysztof Kozlowski Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230926085948.23046-2-quic_priyjain@quicinc.com --- Documentation/devicetree/bindings/thermal/qcom-tsens.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml index 27e9e16e6455..437b74732886 100644 --- a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml +++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml @@ -51,6 +51,7 @@ properties: - qcom,msm8996-tsens - qcom,msm8998-tsens - qcom,qcm2290-tsens + - qcom,sa8775p-tsens - qcom,sc7180-tsens - qcom,sc7280-tsens - qcom,sc8180x-tsens From 98bcee251e608345c272fd89bccd948071fc0bf5 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Thu, 12 Oct 2023 10:00:31 +0200 Subject: [PATCH 094/111] dt-bindings: imx-thermal: Add #thermal-sensor-cells property This property is defined in thermal-sensor.yaml. Reference this file and constraint '#thermal-sensor-cells' to 0 for imx-thermal. Fixes the warning: arch/arm/boot/dts/nxp/imx/imx6q-mba6a.dtb: tempmon: '#thermal-sensor-cells' does not match any of the regexes: 'pinctrl-[0-9]+' From schema: Documentation/devicetree/bindings/thermal/imx-thermal.yaml Signed-off-by: Alexander Stein Acked-by: Conor Dooley Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20231012080033.2715241-2-alexander.stein@ew.tq-group.com --- Documentation/devicetree/bindings/thermal/imx-thermal.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/thermal/imx-thermal.yaml b/Documentation/devicetree/bindings/thermal/imx-thermal.yaml index 3aecea77869f..808d987bd8d1 100644 --- a/Documentation/devicetree/bindings/thermal/imx-thermal.yaml +++ b/Documentation/devicetree/bindings/thermal/imx-thermal.yaml @@ -60,6 +60,9 @@ properties: clocks: maxItems: 1 + "#thermal-sensor-cells": + const: 0 + required: - compatible - interrupts @@ -67,6 +70,9 @@ required: - nvmem-cells - nvmem-cell-names +allOf: + - $ref: thermal-sensor.yaml# + additionalProperties: false examples: @@ -104,5 +110,6 @@ examples: nvmem-cells = <&tempmon_calib>, <&tempmon_temp_grade>; nvmem-cell-names = "calib", "temp_grade"; clocks = <&clks IMX6SX_CLK_PLL3_USB_OTG>; + #thermal-sensor-cells = <0>; }; }; From 438a15b16f6140b521371468d2bf31f45ca96767 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Thu, 12 Oct 2023 10:00:32 +0200 Subject: [PATCH 095/111] dt-bindings: net: microchip: Allow nvmem-cell usage MAC address can be provided by a nvmem-cell, thus allow referencing a source for the address. Fixes the warning: arch/arm/boot/dts/nxp/imx/imx6q-mba6a.dtb: ethernet@1: 'nvmem-cell-names', 'nvmem-cells' do not match any of the regexes: 'pinctrl-[0-9]+' From schema: Documentation/devicetree/bindings/net/microchip,lan95xx.yaml Signed-off-by: Alexander Stein Acked-by: Conor Dooley Reviewed-by: Rob Herring Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20231012080033.2715241-3-alexander.stein@ew.tq-group.com --- Documentation/devicetree/bindings/net/microchip,lan95xx.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/net/microchip,lan95xx.yaml b/Documentation/devicetree/bindings/net/microchip,lan95xx.yaml index 77c9bbf987e1..accff93d38f8 100644 --- a/Documentation/devicetree/bindings/net/microchip,lan95xx.yaml +++ b/Documentation/devicetree/bindings/net/microchip,lan95xx.yaml @@ -44,6 +44,8 @@ properties: local-mac-address: true mac-address: true + nvmem-cells: true + nvmem-cell-names: true required: - compatible From e9cdce582390ade0429f76c2251d7bc65ec52f10 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Thu, 12 Oct 2023 10:00:33 +0200 Subject: [PATCH 096/111] dt-bindings: timer: add imx7d compatible Currently the dtbs_check for imx6ul generates warnings like this: ['fsl,imx7d-gpt', 'fsl,imx6sx-gpt'] is too long The driver has no special handling for fsl,imx7d-gpt, so fsl,imx6sx-gpt is used. Therefore make imx7d GPT compatible to the imx6sx one to fix the warning. Signed-off-by: Alexander Stein Acked-by: Conor Dooley Reviewed-by: Rob Herring Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20231012080033.2715241-4-alexander.stein@ew.tq-group.com --- Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml b/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml index dbe1267af06a..c5d3be8c1d68 100644 --- a/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml +++ b/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml @@ -36,7 +36,9 @@ properties: - fsl,imxrt1170-gpt - const: fsl,imx6dl-gpt - items: - - const: fsl,imx6ul-gpt + - enum: + - fsl,imx6ul-gpt + - fsl,imx7d-gpt - const: fsl,imx6sx-gpt reg: From 5368084c39369f31ef026565b676791b5b38e6a5 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 13 Oct 2023 17:51:04 +0200 Subject: [PATCH 097/111] thermal/drivers/max77620: Remove duplicate error message The thermal_of_zone_register() function already prints an error message when appropriate, so remove the extra one from the MAX77620 thermal driver. This fixes a spurious error message when no thermal zone was defined for the MAX77620 in device tree. Reported-by: Nicolas Chauvet Signed-off-by: Thierry Reding Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20231013155104.1781197-1-thierry.reding@gmail.com --- drivers/thermal/max77620_thermal.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/thermal/max77620_thermal.c b/drivers/thermal/max77620_thermal.c index 919b6ee208d8..85a12e98d6dc 100644 --- a/drivers/thermal/max77620_thermal.c +++ b/drivers/thermal/max77620_thermal.c @@ -114,12 +114,8 @@ static int max77620_thermal_probe(struct platform_device *pdev) mtherm->tz_device = devm_thermal_of_zone_register(&pdev->dev, 0, mtherm, &max77620_thermal_ops); - if (IS_ERR(mtherm->tz_device)) { - ret = PTR_ERR(mtherm->tz_device); - dev_err(&pdev->dev, "Failed to register thermal zone: %d\n", - ret); - return ret; - } + if (IS_ERR(mtherm->tz_device)) + return PTR_ERR(mtherm->tz_device); ret = devm_request_threaded_irq(&pdev->dev, mtherm->irq_tjalarm1, NULL, max77620_thermal_irq, From 5055fadfa7e16f2427d5b3c40b2bf563ddfdab22 Mon Sep 17 00:00:00 2001 From: Markus Schneider-Pargmann Date: Mon, 18 Sep 2023 12:07:06 +0200 Subject: [PATCH 098/111] thermal/drivers/mediatek: Fix probe for THERMAL_V2 Fix the probe function to call mtk_thermal_release_periodic_ts for everything != MTK_THERMAL_V1. This was accidentally changed from V1 to V2 in the original patch. Reported-by: Frank Wunderlich Closes: https://lore.kernel.org/lkml/B0B3775B-B8D1-4284-814F-4F41EC22F532@public-files.de/ Reported-by: Daniel Lezcano Closes: https://lore.kernel.org/lkml/07a569b9-e691-64ea-dd65-3b49842af33d@linaro.org/ Fixes: 33140e668b10 ("thermal/drivers/mediatek: Control buffer enablement tweaks") Signed-off-by: Markus Schneider-Pargmann Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20230918100706.1229239-1-msp@baylibre.com --- drivers/thermal/mediatek/auxadc_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/mediatek/auxadc_thermal.c b/drivers/thermal/mediatek/auxadc_thermal.c index 843214d30bd8..8b0edb204844 100644 --- a/drivers/thermal/mediatek/auxadc_thermal.c +++ b/drivers/thermal/mediatek/auxadc_thermal.c @@ -1267,7 +1267,7 @@ static int mtk_thermal_probe(struct platform_device *pdev) mtk_thermal_turn_on_buffer(mt, apmixed_base); - if (mt->conf->version != MTK_THERMAL_V2) + if (mt->conf->version != MTK_THERMAL_V1) mtk_thermal_release_periodic_ts(mt, auxadc_base); if (mt->conf->version == MTK_THERMAL_V1) From 0bb4937b58ab712f158588376dbac97f8e9df68e Mon Sep 17 00:00:00 2001 From: Balsam CHIHI Date: Tue, 17 Oct 2023 21:05:41 +0200 Subject: [PATCH 099/111] dt-bindings: thermal: mediatek: Add LVTS thermal controller definition for mt8192 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add LVTS thermal controller definition for MT8192. Signed-off-by: Balsam CHIHI Reviewed-by: AngeloGioacchino Del Regno Acked-by: Krzysztof Kozlowski Signed-off-by: Bernhard Rosenkränzer Reviewed-by: Matthias Brugger Reviewed-by: Alexandre Mergnat Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20231017190545.157282-2-bero@baylibre.com --- .../thermal/mediatek,lvts-thermal.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/dt-bindings/thermal/mediatek,lvts-thermal.h b/include/dt-bindings/thermal/mediatek,lvts-thermal.h index 8c1fdc18cf34..997e2f55128a 100644 --- a/include/dt-bindings/thermal/mediatek,lvts-thermal.h +++ b/include/dt-bindings/thermal/mediatek,lvts-thermal.h @@ -35,4 +35,23 @@ #define MT8195_AP_CAM0 15 #define MT8195_AP_CAM1 16 +#define MT8192_MCU_BIG_CPU0 0 +#define MT8192_MCU_BIG_CPU1 1 +#define MT8192_MCU_BIG_CPU2 2 +#define MT8192_MCU_BIG_CPU3 3 +#define MT8192_MCU_LITTLE_CPU0 4 +#define MT8192_MCU_LITTLE_CPU1 5 +#define MT8192_MCU_LITTLE_CPU2 6 +#define MT8192_MCU_LITTLE_CPU3 7 + +#define MT8192_AP_VPU0 8 +#define MT8192_AP_VPU1 9 +#define MT8192_AP_GPU0 10 +#define MT8192_AP_GPU1 11 +#define MT8192_AP_INFRA 12 +#define MT8192_AP_CAM 13 +#define MT8192_AP_MD0 14 +#define MT8192_AP_MD1 15 +#define MT8192_AP_MD2 16 + #endif /* __MEDIATEK_LVTS_DT_H */ From 8137bb90600d70eda524854ce3047a5681988dd6 Mon Sep 17 00:00:00 2001 From: Balsam CHIHI Date: Tue, 17 Oct 2023 21:05:42 +0200 Subject: [PATCH 100/111] thermal/drivers/mediatek/lvts_thermal: Add suspend and resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add suspend and resume support to LVTS driver. Signed-off-by: Balsam CHIHI [bero@baylibre.com: suspend/resume in noirq phase] Co-developed-by: Bernhard Rosenkränzer Signed-off-by: Bernhard Rosenkränzer Reviewed-by: Matthias Brugger Reviewed-by: Alexandre Mergnat Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20231017190545.157282-3-bero@baylibre.com --- drivers/thermal/mediatek/lvts_thermal.c | 37 +++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index 704b22d12e27..4ac6ae37a1ee 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -1297,6 +1297,38 @@ static const struct lvts_ctrl_data mt7988_lvts_ap_data_ctrl[] = { } }; +static int lvts_suspend(struct device *dev) +{ + struct lvts_domain *lvts_td; + int i; + + lvts_td = dev_get_drvdata(dev); + + for (i = 0; i < lvts_td->num_lvts_ctrl; i++) + lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false); + + clk_disable_unprepare(lvts_td->clk); + + return 0; +} + +static int lvts_resume(struct device *dev) +{ + struct lvts_domain *lvts_td; + int i, ret; + + lvts_td = dev_get_drvdata(dev); + + ret = clk_prepare_enable(lvts_td->clk); + if (ret) + return ret; + + for (i = 0; i < lvts_td->num_lvts_ctrl; i++) + lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], true); + + return 0; +} + static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { { .cal_offset = { 0x04, 0x07 }, @@ -1405,12 +1437,17 @@ static const struct of_device_id lvts_of_match[] = { }; MODULE_DEVICE_TABLE(of, lvts_of_match); +static const struct dev_pm_ops lvts_pm_ops = { + NOIRQ_SYSTEM_SLEEP_PM_OPS(lvts_suspend, lvts_resume) +}; + static struct platform_driver lvts_driver = { .probe = lvts_probe, .remove_new = lvts_remove, .driver = { .name = "mtk-lvts-thermal", .of_match_table = lvts_of_match, + .pm = &lvts_pm_ops, }, }; module_platform_driver(lvts_driver); From 288732242db4980e2edbb3a21729c9fba58c3726 Mon Sep 17 00:00:00 2001 From: Balsam CHIHI Date: Tue, 17 Oct 2023 21:05:43 +0200 Subject: [PATCH 101/111] thermal/drivers/mediatek/lvts_thermal: Add mt8192 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add LVTS Driver support for MT8192. Co-developed-by: Nícolas F. R. A. Prado Signed-off-by: Nícolas F. R. A. Prado Signed-off-by: Balsam CHIHI Reviewed-by: Nícolas F. R. A. Prado [bero@baylibre.com: cosmetic changes, rebase] Signed-off-by: Bernhard Rosenkränzer Reviewed-by: Matthias Brugger Reviewed-by: Alexandre Mergnat Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20231017190545.157282-4-bero@baylibre.com --- drivers/thermal/mediatek/lvts_thermal.c | 95 +++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index 4ac6ae37a1ee..0fc8899a8fcb 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -92,6 +92,7 @@ #define LVTS_MSR_READ_WAIT_US (LVTS_MSR_READ_TIMEOUT_US / 2) #define LVTS_HW_SHUTDOWN_MT7988 105000 +#define LVTS_HW_SHUTDOWN_MT8192 105000 #define LVTS_HW_SHUTDOWN_MT8195 105000 #define LVTS_MINIMUM_THRESHOLD 20000 @@ -1329,6 +1330,88 @@ static int lvts_resume(struct device *dev) return 0; } +static const struct lvts_ctrl_data mt8192_lvts_mcu_data_ctrl[] = { + { + .cal_offset = { 0x04, 0x08 }, + .lvts_sensor = { + { .dt_id = MT8192_MCU_BIG_CPU0 }, + { .dt_id = MT8192_MCU_BIG_CPU1 } + }, + .num_lvts_sensor = 2, + .offset = 0x0, + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, + .mode = LVTS_MSR_FILTERED_MODE, + }, + { + .cal_offset = { 0x0c, 0x10 }, + .lvts_sensor = { + { .dt_id = MT8192_MCU_BIG_CPU2 }, + { .dt_id = MT8192_MCU_BIG_CPU3 } + }, + .num_lvts_sensor = 2, + .offset = 0x100, + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, + .mode = LVTS_MSR_FILTERED_MODE, + }, + { + .cal_offset = { 0x14, 0x18, 0x1c, 0x20 }, + .lvts_sensor = { + { .dt_id = MT8192_MCU_LITTLE_CPU0 }, + { .dt_id = MT8192_MCU_LITTLE_CPU1 }, + { .dt_id = MT8192_MCU_LITTLE_CPU2 }, + { .dt_id = MT8192_MCU_LITTLE_CPU3 } + }, + .num_lvts_sensor = 4, + .offset = 0x200, + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, + .mode = LVTS_MSR_FILTERED_MODE, + } +}; + +static const struct lvts_ctrl_data mt8192_lvts_ap_data_ctrl[] = { + { + .cal_offset = { 0x24, 0x28 }, + .lvts_sensor = { + { .dt_id = MT8192_AP_VPU0 }, + { .dt_id = MT8192_AP_VPU1 } + }, + .num_lvts_sensor = 2, + .offset = 0x0, + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, + }, + { + .cal_offset = { 0x2c, 0x30 }, + .lvts_sensor = { + { .dt_id = MT8192_AP_GPU0 }, + { .dt_id = MT8192_AP_GPU1 } + }, + .num_lvts_sensor = 2, + .offset = 0x100, + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, + }, + { + .cal_offset = { 0x34, 0x38 }, + .lvts_sensor = { + { .dt_id = MT8192_AP_INFRA }, + { .dt_id = MT8192_AP_CAM }, + }, + .num_lvts_sensor = 2, + .offset = 0x200, + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, + }, + { + .cal_offset = { 0x3c, 0x40, 0x44 }, + .lvts_sensor = { + { .dt_id = MT8192_AP_MD0 }, + { .dt_id = MT8192_AP_MD1 }, + { .dt_id = MT8192_AP_MD2 } + }, + .num_lvts_sensor = 3, + .offset = 0x300, + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, + } +}; + static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { { .cal_offset = { 0x04, 0x07 }, @@ -1415,6 +1498,16 @@ static const struct lvts_data mt7988_lvts_ap_data = { .temp_offset = LVTS_COEFF_B_MT7988, }; +static const struct lvts_data mt8192_lvts_mcu_data = { + .lvts_ctrl = mt8192_lvts_mcu_data_ctrl, + .num_lvts_ctrl = ARRAY_SIZE(mt8192_lvts_mcu_data_ctrl), +}; + +static const struct lvts_data mt8192_lvts_ap_data = { + .lvts_ctrl = mt8192_lvts_ap_data_ctrl, + .num_lvts_ctrl = ARRAY_SIZE(mt8192_lvts_ap_data_ctrl), +}; + static const struct lvts_data mt8195_lvts_mcu_data = { .lvts_ctrl = mt8195_lvts_mcu_data_ctrl, .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_mcu_data_ctrl), @@ -1431,6 +1524,8 @@ static const struct lvts_data mt8195_lvts_ap_data = { static const struct of_device_id lvts_of_match[] = { { .compatible = "mediatek,mt7988-lvts-ap", .data = &mt7988_lvts_ap_data }, + { .compatible = "mediatek,mt8192-lvts-mcu", .data = &mt8192_lvts_mcu_data }, + { .compatible = "mediatek,mt8192-lvts-ap", .data = &mt8192_lvts_ap_data }, { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data }, { .compatible = "mediatek,mt8195-lvts-ap", .data = &mt8195_lvts_ap_data }, {}, From 5437d14d94c8b0b3a960f616dfe02dc153806225 Mon Sep 17 00:00:00 2001 From: Balsam CHIHI Date: Tue, 17 Oct 2023 21:05:45 +0200 Subject: [PATCH 102/111] thermal/drivers/mediatek/lvts_thermal: Update calibration data documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update LVTS calibration data documentation for mt8192 and mt8195. Signed-off-by: Balsam CHIHI Reviewed-by: Nícolas F. R. A. Prado [bero@baylibre.com: Fix issues pointed out by Nícolas F. R. A. Prado ] Signed-off-by: Bernhard Rosenkränzer Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Alexandre Mergnat Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20231017190545.157282-6-bero@baylibre.com --- drivers/thermal/mediatek/lvts_thermal.c | 31 +++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index 0fc8899a8fcb..98d9c80bd4c6 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -616,7 +616,34 @@ static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, * The efuse blob values follows the sensor enumeration per thermal * controller. The decoding of the stream is as follow: * - * stream index map for MCU Domain : + * MT8192 : + * Stream index map for MCU Domain mt8192 : + * + * <-----mcu-tc#0-----> <-----sensor#0-----> <-----sensor#1-----> + * 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09 | 0x0A | 0x0B + * + * <-----sensor#2-----> <-----sensor#3-----> + * 0x0C | 0x0D | 0x0E | 0x0F | 0x10 | 0x11 | 0x12 | 0x13 + * + * <-----sensor#4-----> <-----sensor#5-----> <-----sensor#6-----> <-----sensor#7-----> + * 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x1B | 0x1C | 0x1D | 0x1E | 0x1F | 0x20 | 0x21 | 0x22 | 0x23 + * + * Stream index map for AP Domain mt8192 : + * + * <-----sensor#0-----> <-----sensor#1-----> + * 0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2A | 0x2B + * + * <-----sensor#2-----> <-----sensor#3-----> + * 0x2C | 0x2D | 0x2E | 0x2F | 0x30 | 0x31 | 0x32 | 0x33 + * + * <-----sensor#4-----> <-----sensor#5-----> + * 0x34 | 0x35 | 0x36 | 0x37 | 0x38 | 0x39 | 0x3A | 0x3B + * + * <-----sensor#6-----> <-----sensor#7-----> <-----sensor#8-----> + * 0x3C | 0x3D | 0x3E | 0x3F | 0x40 | 0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x46 | 0x47 + * + * MT8195 : + * Stream index map for MCU Domain mt8195 : * * <-----mcu-tc#0-----> <-----sensor#0-----> <-----sensor#1-----> * 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09 @@ -627,7 +654,7 @@ static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl, * <-----mcu-tc#2-----> <-----sensor#4-----> <-----sensor#5-----> <-----sensor#6-----> <-----sensor#7-----> * 0x13 | 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x1B | 0x1C | 0x1D | 0x1E | 0x1F | 0x20 | 0x21 * - * stream index map for AP Domain : + * Stream index map for AP Domain mt8195 : * * <-----ap--tc#0-----> <-----sensor#0-----> <-----sensor#1-----> * 0x22 | 0x23 | 0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2A From 9618efe343ead954ca5c23856ae23d0a29e7d4b9 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 19 Oct 2023 17:43:11 +0300 Subject: [PATCH 103/111] thermal/qcom/tsens: Drop ops_v0_1 Since the commit 6812d1dfbca9 ("thermal/drivers/qcom/tsens-v0_1: Fix mdm9607 slope values") the default v0.1 implementation of tsens options is unused by the driver. Drop it now to stop compiler complaining about the unused static const. If it appears there is the need for the default v0.1 ops struct, this commit can be easily reverted without further considerations. Fixes: 6812d1dfbca9 ("thermal/drivers/qcom/tsens-v0_1: Fix mdm9607 slope values") Signed-off-by: Dmitry Baryshkov Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20231019144311.1035181-1-dmitry.baryshkov@linaro.org --- drivers/thermal/qcom/tsens-v0_1.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c index 87c09f62ee81..32d2d3e33287 100644 --- a/drivers/thermal/qcom/tsens-v0_1.c +++ b/drivers/thermal/qcom/tsens-v0_1.c @@ -325,12 +325,6 @@ static const struct reg_field tsens_v0_1_regfields[MAX_REGFIELDS] = { [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0), }; -static const struct tsens_ops ops_v0_1 = { - .init = init_common, - .calibrate = tsens_calibrate_common, - .get_temp = get_temp_common, -}; - static const struct tsens_ops ops_8226 = { .init = init_8226, .calibrate = tsens_calibrate_common, From 78869767f2ad3a98d2c830b718a503d8b0a94b26 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 12 Oct 2023 20:25:06 +0200 Subject: [PATCH 104/111] thermal: trip: Simplify computing trip indices A trip index can be computed right away as a difference between the value of a trip pointer pointing to the given trip object and the start of the trips[] table in the given thermal zone, so change thermal_zone_trip_id() accordingly. No intentional functional impact (except for some speedup). Signed-off-by: Rafael J. Wysocki Acked-by: Daniel Lezcano Reviewed-by: Lukasz Luba Tested-by: Lukasz Luba --- drivers/thermal/thermal_trip.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/thermal/thermal_trip.c b/drivers/thermal/thermal_trip.c index 80f3cdb2f30e..6dff0dae6ef6 100644 --- a/drivers/thermal/thermal_trip.c +++ b/drivers/thermal/thermal_trip.c @@ -173,12 +173,9 @@ int thermal_zone_set_trip(struct thermal_zone_device *tz, int trip_id, int thermal_zone_trip_id(struct thermal_zone_device *tz, const struct thermal_trip *trip) { - int i; - - for (i = 0; i < tz->num_trips; i++) { - if (&tz->trips[i] == trip) - return i; - } - - return -ENODATA; + /* + * Assume the trip to be located within the bounds of the thermal + * zone's trips[] table. + */ + return trip - tz->trips; } From 234ed6f5fbedf7bc84f9adc08c3e11ca8588ffd8 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 12 Oct 2023 20:26:46 +0200 Subject: [PATCH 105/111] thermal: trip: Define for_each_trip() macro Define a new macro for_each_trip() to be used by the thermal core code and thermal governors for walking trips in a given thermal zone. Modify for_each_thermal_trip() to use this macro instead of an open- coded loop over trips. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Acked-by: Daniel Lezcano Reviewed-by: Lukasz Luba --- drivers/thermal/thermal_core.h | 3 +++ drivers/thermal/thermal_trip.c | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index 024e82ebf592..4702d3a152f9 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -116,6 +116,9 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz, enum thermal_notify_event event); /* Helpers */ +#define for_each_trip(__tz, __trip) \ + for (__trip = __tz->trips; __trip - __tz->trips < __tz->num_trips; __trip++) + void __thermal_zone_set_trips(struct thermal_zone_device *tz); int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id, struct thermal_trip *trip); diff --git a/drivers/thermal/thermal_trip.c b/drivers/thermal/thermal_trip.c index 6dff0dae6ef6..9e07535d99bb 100644 --- a/drivers/thermal/thermal_trip.c +++ b/drivers/thermal/thermal_trip.c @@ -13,10 +13,11 @@ int for_each_thermal_trip(struct thermal_zone_device *tz, int (*cb)(struct thermal_trip *, void *), void *data) { - int i, ret; + struct thermal_trip *trip; + int ret; - for (i = 0; i < tz->num_trips; i++) { - ret = cb(&tz->trips[i], data); + for_each_trip(tz, trip) { + ret = cb(trip, data); if (ret) return ret; } From 276f1ede95164b54f55c82d40e9df218109704d6 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 12 Oct 2023 20:29:43 +0200 Subject: [PATCH 106/111] thermal: gov_fair_share: Rearrange get_trip_level() Make get_trip_level() use for_each_trip() to iterate over trip points and make it call thermal_zone_trip_id() to obtain the integer ID of a given trip point so as to avoid relying on the knowledge of struct thermal_zone_device internals. The general functionality is not expected to be changed. This change causes the governor to use trip pointers instead of trip indices everywhere except for the fair_share_throttle() second argument that will be modified subsequently along with the definition of the governor .throttle() callback. Signed-off-by: Rafael J. Wysocki Acked-by: Daniel Lezcano --- drivers/thermal/gov_fair_share.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/thermal/gov_fair_share.c b/drivers/thermal/gov_fair_share.c index 2abeb8979f50..41effa87d3cd 100644 --- a/drivers/thermal/gov_fair_share.c +++ b/drivers/thermal/gov_fair_share.c @@ -15,29 +15,27 @@ #include "thermal_core.h" -/** - * get_trip_level: - obtains the current trip level for a zone - * @tz: thermal zone device - */ static int get_trip_level(struct thermal_zone_device *tz) { - struct thermal_trip trip; - int count; + const struct thermal_trip *trip, *level_trip = NULL; + int trip_level; - for (count = 0; count < tz->num_trips; count++) { - __thermal_zone_get_trip(tz, count, &trip); - if (tz->temperature < trip.temperature) + for_each_trip(tz, trip) { + if (trip->temperature >= tz->temperature) break; + + level_trip = trip; } - /* - * count > 0 only if temperature is greater than first trip - * point, in which case, trip_point = count - 1 - */ - if (count > 0) - trace_thermal_zone_trip(tz, count - 1, trip.type); + /* Bail out if the temperature is not greater than any trips. */ + if (!level_trip) + return 0; - return count; + trip_level = thermal_zone_trip_id(tz, level_trip); + + trace_thermal_zone_trip(tz, trip_level, level_trip->type); + + return trip_level; } static long get_target_state(struct thermal_zone_device *tz, From 94be1d27aa8d6f0a9e09517445abf468de24fab3 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 12 Oct 2023 20:31:38 +0200 Subject: [PATCH 107/111] thermal: gov_power_allocator: Use trip pointers instead of trip indices Modify the power allocator thermal governor to use trip pointers instead of trip indices everywhere except for the power_allocator_throttle() second argument that will be changed subsequently along with the definition of the .throttle() governor callback. The general functionality is not expected to be changed. Signed-off-by: Rafael J. Wysocki Acked-by: Daniel Lezcano Reviewed-by: Lukasz Luba Tested-by: Lukasz Luba --- drivers/thermal/gov_power_allocator.c | 125 ++++++++++---------------- 1 file changed, 48 insertions(+), 77 deletions(-) diff --git a/drivers/thermal/gov_power_allocator.c b/drivers/thermal/gov_power_allocator.c index 1faf55446ba2..c0d29d286374 100644 --- a/drivers/thermal/gov_power_allocator.c +++ b/drivers/thermal/gov_power_allocator.c @@ -16,8 +16,6 @@ #include "thermal_core.h" -#define INVALID_TRIP -1 - #define FRAC_BITS 10 #define int_to_frac(x) ((x) << FRAC_BITS) #define frac_to_int(x) ((x) >> FRAC_BITS) @@ -55,23 +53,23 @@ static inline s64 div_frac(s64 x, s64 y) * @err_integral: accumulated error in the PID controller. * @prev_err: error in the previous iteration of the PID controller. * Used to calculate the derivative term. + * @sustainable_power: Sustainable power (heat) that this thermal zone can + * dissipate * @trip_switch_on: first passive trip point of the thermal zone. The * governor switches on when this trip point is crossed. * If the thermal zone only has one passive trip point, - * @trip_switch_on should be INVALID_TRIP. + * @trip_switch_on should be NULL. * @trip_max_desired_temperature: last passive trip point of the thermal * zone. The temperature we are * controlling for. - * @sustainable_power: Sustainable power (heat) that this thermal zone can - * dissipate */ struct power_allocator_params { bool allocated_tzp; s64 err_integral; s32 prev_err; - int trip_switch_on; - int trip_max_desired_temperature; u32 sustainable_power; + const struct thermal_trip *trip_switch_on; + const struct thermal_trip *trip_max_desired_temperature; }; /** @@ -90,14 +88,12 @@ static u32 estimate_sustainable_power(struct thermal_zone_device *tz) u32 sustainable_power = 0; struct thermal_instance *instance; struct power_allocator_params *params = tz->governor_data; - const struct thermal_trip *trip_max_desired_temperature = - &tz->trips[params->trip_max_desired_temperature]; list_for_each_entry(instance, &tz->thermal_instances, tz_node) { struct thermal_cooling_device *cdev = instance->cdev; u32 min_power; - if (instance->trip != trip_max_desired_temperature) + if (instance->trip != params->trip_max_desired_temperature) continue; if (!cdev_is_power_actor(cdev)) @@ -116,24 +112,22 @@ static u32 estimate_sustainable_power(struct thermal_zone_device *tz) * estimate_pid_constants() - Estimate the constants for the PID controller * @tz: thermal zone for which to estimate the constants * @sustainable_power: sustainable power for the thermal zone - * @trip_switch_on: trip point number for the switch on temperature + * @trip_switch_on: trip point for the switch on temperature * @control_temp: target temperature for the power allocator governor * * This function is used to update the estimation of the PID * controller constants in struct thermal_zone_parameters. */ static void estimate_pid_constants(struct thermal_zone_device *tz, - u32 sustainable_power, int trip_switch_on, + u32 sustainable_power, + const struct thermal_trip *trip_switch_on, int control_temp) { - struct thermal_trip trip; u32 temperature_threshold = control_temp; - int ret; s32 k_i; - ret = __thermal_zone_get_trip(tz, trip_switch_on, &trip); - if (!ret) - temperature_threshold -= trip.temperature; + if (trip_switch_on) + temperature_threshold -= trip_switch_on->temperature; /* * estimate_pid_constants() tries to find appropriate default @@ -386,7 +380,7 @@ static int allocate_power(struct thermal_zone_device *tz, struct thermal_instance *instance; struct power_allocator_params *params = tz->governor_data; const struct thermal_trip *trip_max_desired_temperature = - &tz->trips[params->trip_max_desired_temperature]; + params->trip_max_desired_temperature; u32 *req_power, *max_power, *granted_power, *extra_actor_power; u32 *weighted_req_power; u32 total_req_power, max_allocatable_power, total_weighted_req_power; @@ -496,7 +490,7 @@ static int allocate_power(struct thermal_zone_device *tz, } /** - * get_governor_trips() - get the number of the two trip points that are key for this governor + * get_governor_trips() - get the two trip points that are key for this governor * @tz: thermal zone to operate on * @params: pointer to private data for this governor * @@ -513,46 +507,36 @@ static int allocate_power(struct thermal_zone_device *tz, static void get_governor_trips(struct thermal_zone_device *tz, struct power_allocator_params *params) { - int i, last_active, last_passive; - bool found_first_passive; + const struct thermal_trip *first_passive = NULL; + const struct thermal_trip *last_passive = NULL; + const struct thermal_trip *last_active = NULL; + const struct thermal_trip *trip; - found_first_passive = false; - last_active = INVALID_TRIP; - last_passive = INVALID_TRIP; - - for (i = 0; i < tz->num_trips; i++) { - struct thermal_trip trip; - int ret; - - ret = __thermal_zone_get_trip(tz, i, &trip); - if (ret) { - dev_warn(&tz->device, - "Failed to get trip point %d type: %d\n", i, - ret); - continue; - } - - if (trip.type == THERMAL_TRIP_PASSIVE) { - if (!found_first_passive) { - params->trip_switch_on = i; - found_first_passive = true; - } else { - last_passive = i; + for_each_trip(tz, trip) { + switch (trip->type) { + case THERMAL_TRIP_PASSIVE: + if (!first_passive) { + first_passive = trip; + break; } - } else if (trip.type == THERMAL_TRIP_ACTIVE) { - last_active = i; - } else { + last_passive = trip; + break; + case THERMAL_TRIP_ACTIVE: + last_active = trip; + break; + default: break; } } - if (last_passive != INVALID_TRIP) { + if (last_passive) { + params->trip_switch_on = first_passive; params->trip_max_desired_temperature = last_passive; - } else if (found_first_passive) { - params->trip_max_desired_temperature = params->trip_switch_on; - params->trip_switch_on = INVALID_TRIP; + } else if (first_passive) { + params->trip_switch_on = NULL; + params->trip_max_desired_temperature = first_passive; } else { - params->trip_switch_on = INVALID_TRIP; + params->trip_switch_on = NULL; params->trip_max_desired_temperature = last_active; } } @@ -567,14 +551,12 @@ static void allow_maximum_power(struct thermal_zone_device *tz, bool update) { struct thermal_instance *instance; struct power_allocator_params *params = tz->governor_data; - const struct thermal_trip *trip_max_desired_temperature = - &tz->trips[params->trip_max_desired_temperature]; u32 req_power; list_for_each_entry(instance, &tz->thermal_instances, tz_node) { struct thermal_cooling_device *cdev = instance->cdev; - if ((instance->trip != trip_max_desired_temperature) || + if (instance->trip != params->trip_max_desired_temperature || (!cdev_is_power_actor(instance->cdev))) continue; @@ -636,7 +618,6 @@ static int power_allocator_bind(struct thermal_zone_device *tz) { int ret; struct power_allocator_params *params; - struct thermal_trip trip; ret = check_power_actors(tz); if (ret) @@ -661,13 +642,11 @@ static int power_allocator_bind(struct thermal_zone_device *tz) get_governor_trips(tz, params); - if (tz->num_trips > 0) { - ret = __thermal_zone_get_trip(tz, params->trip_max_desired_temperature, - &trip); - if (!ret) - estimate_pid_constants(tz, tz->tzp->sustainable_power, - params->trip_switch_on, - trip.temperature); + if (params->trip_max_desired_temperature) { + int temp = params->trip_max_desired_temperature->temperature; + + estimate_pid_constants(tz, tz->tzp->sustainable_power, + params->trip_switch_on, temp); } reset_pid_controller(params); @@ -697,11 +676,10 @@ static void power_allocator_unbind(struct thermal_zone_device *tz) tz->governor_data = NULL; } -static int power_allocator_throttle(struct thermal_zone_device *tz, int trip_id) +static int power_allocator_throttle(struct thermal_zone_device *tz, int trip_index) { struct power_allocator_params *params = tz->governor_data; - struct thermal_trip trip; - int ret; + const struct thermal_trip *trip = &tz->trips[trip_index]; bool update; lockdep_assert_held(&tz->lock); @@ -710,12 +688,12 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip_id) * We get called for every trip point but we only need to do * our calculations once */ - if (trip_id != params->trip_max_desired_temperature) + if (trip != params->trip_max_desired_temperature) return 0; - ret = __thermal_zone_get_trip(tz, params->trip_switch_on, &trip); - if (!ret && (tz->temperature < trip.temperature)) { - update = (tz->last_temperature >= trip.temperature); + trip = params->trip_switch_on; + if (trip && tz->temperature < trip->temperature) { + update = tz->last_temperature >= trip->temperature; tz->passive = 0; reset_pid_controller(params); allow_maximum_power(tz, update); @@ -724,14 +702,7 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip_id) tz->passive = 1; - ret = __thermal_zone_get_trip(tz, params->trip_max_desired_temperature, &trip); - if (ret) { - dev_warn(&tz->device, "Failed to get the maximum desired temperature: %d\n", - ret); - return ret; - } - - return allocate_power(tz, trip.temperature); + return allocate_power(tz, params->trip_max_desired_temperature->temperature); } static struct thermal_governor thermal_gov_power_allocator = { From fdcf70ed4e1606cd5a5a48f666583053ae4c3978 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 12 Oct 2023 20:33:28 +0200 Subject: [PATCH 108/111] thermal: gov_step_wise: Fold update_passive_instance() into its caller Fold update_passive_instance() into thermal_zone_trip_update() that is its only caller so as to make the code in question easier to follow. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Acked-by: Daniel Lezcano Reviewed-by: Lukasz Luba --- drivers/thermal/gov_step_wise.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/drivers/thermal/gov_step_wise.c b/drivers/thermal/gov_step_wise.c index 849dc1ec8d27..8bc63a1d361e 100644 --- a/drivers/thermal/gov_step_wise.c +++ b/drivers/thermal/gov_step_wise.c @@ -68,17 +68,6 @@ static unsigned long get_target_state(struct thermal_instance *instance, return next_target; } -static void update_passive_instance(struct thermal_zone_device *tz, - enum thermal_trip_type type, int value) -{ - /* - * If value is +1, activate a passive instance. - * If value is -1, deactivate a passive instance. - */ - if (type == THERMAL_TRIP_PASSIVE) - tz->passive += value; -} - static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_id) { const struct thermal_trip *trip = &tz->trips[trip_id]; @@ -109,14 +98,17 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_id if (instance->initialized && old_target == instance->target) continue; - /* Activate a passive thermal instance */ if (old_target == THERMAL_NO_TARGET && - instance->target != THERMAL_NO_TARGET) - update_passive_instance(tz, trip->type, 1); - /* Deactivate a passive thermal instance */ - else if (old_target != THERMAL_NO_TARGET && - instance->target == THERMAL_NO_TARGET) - update_passive_instance(tz, trip->type, -1); + instance->target != THERMAL_NO_TARGET) { + /* Activate a passive thermal instance */ + if (trip->type == THERMAL_TRIP_PASSIVE) + tz->passive++; + } else if (old_target != THERMAL_NO_TARGET && + instance->target == THERMAL_NO_TARGET) { + /* Deactivate a passive thermal instance */ + if (trip->type == THERMAL_TRIP_PASSIVE) + tz->passive--; + } instance->initialized = true; mutex_lock(&instance->cdev->lock); From 8c35b1f472533b0df1b8f1f1afcaf4395cdb2256 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 12 Oct 2023 20:34:50 +0200 Subject: [PATCH 109/111] thermal: core: Pass trip pointer to governor throttle callback Modify the governor .throttle() callback definition so that it takes a trip pointer instead of a trip index as its second argument, adjust the governors accordingly and update the core code invoking .throttle(). This causes the governors to become independent of the representation of the list of trips in the thermal zone structure. This change is not expected to alter the general functionality. Signed-off-by: Rafael J. Wysocki Reviewed-by: Daniel Lezcano --- drivers/thermal/gov_bang_bang.c | 8 +++-- drivers/thermal/gov_fair_share.c | 6 ++-- drivers/thermal/gov_power_allocator.c | 4 +-- drivers/thermal/gov_step_wise.c | 12 ++++--- drivers/thermal/gov_user_space.c | 8 +++-- drivers/thermal/thermal_core.c | 50 +++++++++++++-------------- drivers/thermal/thermal_core.h | 2 +- drivers/thermal/thermal_helpers.c | 3 +- include/linux/thermal.h | 3 +- 9 files changed, 51 insertions(+), 45 deletions(-) diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c index 49cdfaa3a927..6ddf0accdc98 100644 --- a/drivers/thermal/gov_bang_bang.c +++ b/drivers/thermal/gov_bang_bang.c @@ -13,9 +13,10 @@ #include "thermal_core.h" -static int thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_index) +static int thermal_zone_trip_update(struct thermal_zone_device *tz, + const struct thermal_trip *trip) { - const struct thermal_trip *trip = &tz->trips[trip_index]; + int trip_index = thermal_zone_trip_id(tz, trip); struct thermal_instance *instance; if (!trip->hysteresis) @@ -89,7 +90,8 @@ static int thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_ind * (trip_temp - hyst) so that the fan gets turned off again. * */ -static int bang_bang_control(struct thermal_zone_device *tz, int trip) +static int bang_bang_control(struct thermal_zone_device *tz, + const struct thermal_trip *trip) { struct thermal_instance *instance; int ret; diff --git a/drivers/thermal/gov_fair_share.c b/drivers/thermal/gov_fair_share.c index 41effa87d3cd..538abb7de4e2 100644 --- a/drivers/thermal/gov_fair_share.c +++ b/drivers/thermal/gov_fair_share.c @@ -47,7 +47,7 @@ static long get_target_state(struct thermal_zone_device *tz, /** * fair_share_throttle - throttles devices associated with the given zone * @tz: thermal_zone_device - * @trip_index: trip point index + * @trip: trip point * * Throttling Logic: This uses three parameters to calculate the new * throttle state of the cooling devices associated with the given zone. @@ -63,9 +63,9 @@ static long get_target_state(struct thermal_zone_device *tz, * (Heavily assumes the trip points are in ascending order) * new_state of cooling device = P3 * P2 * P1 */ -static int fair_share_throttle(struct thermal_zone_device *tz, int trip_index) +static int fair_share_throttle(struct thermal_zone_device *tz, + const struct thermal_trip *trip) { - const struct thermal_trip *trip = &tz->trips[trip_index]; struct thermal_instance *instance; int total_weight = 0; int total_instance = 0; diff --git a/drivers/thermal/gov_power_allocator.c b/drivers/thermal/gov_power_allocator.c index c0d29d286374..83d4f451b1a9 100644 --- a/drivers/thermal/gov_power_allocator.c +++ b/drivers/thermal/gov_power_allocator.c @@ -676,10 +676,10 @@ static void power_allocator_unbind(struct thermal_zone_device *tz) tz->governor_data = NULL; } -static int power_allocator_throttle(struct thermal_zone_device *tz, int trip_index) +static int power_allocator_throttle(struct thermal_zone_device *tz, + const struct thermal_trip *trip) { struct power_allocator_params *params = tz->governor_data; - const struct thermal_trip *trip = &tz->trips[trip_index]; bool update; lockdep_assert_held(&tz->lock); diff --git a/drivers/thermal/gov_step_wise.c b/drivers/thermal/gov_step_wise.c index 8bc63a1d361e..5436aa58d41e 100644 --- a/drivers/thermal/gov_step_wise.c +++ b/drivers/thermal/gov_step_wise.c @@ -68,15 +68,16 @@ static unsigned long get_target_state(struct thermal_instance *instance, return next_target; } -static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_id) +static void thermal_zone_trip_update(struct thermal_zone_device *tz, + const struct thermal_trip *trip) { - const struct thermal_trip *trip = &tz->trips[trip_id]; + int trip_id = thermal_zone_trip_id(tz, trip); enum thermal_trend trend; struct thermal_instance *instance; bool throttle = false; int old_target; - trend = get_tz_trend(tz, trip_id); + trend = get_tz_trend(tz, trip); if (tz->temperature >= trip->temperature) { throttle = true; @@ -120,7 +121,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_id /** * step_wise_throttle - throttles devices associated with the given zone * @tz: thermal_zone_device - * @trip: trip point index + * @trip: trip point * * Throttling Logic: This uses the trend of the thermal zone to throttle. * If the thermal zone is 'heating up' this throttles all the cooling @@ -128,7 +129,8 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_id * step. If the zone is 'cooling down' it brings back the performance of * the devices by one step. */ -static int step_wise_throttle(struct thermal_zone_device *tz, int trip) +static int step_wise_throttle(struct thermal_zone_device *tz, + const struct thermal_trip *trip) { struct thermal_instance *instance; diff --git a/drivers/thermal/gov_user_space.c b/drivers/thermal/gov_user_space.c index 8bc1c22aaf03..7a1790b7e8f5 100644 --- a/drivers/thermal/gov_user_space.c +++ b/drivers/thermal/gov_user_space.c @@ -25,11 +25,12 @@ static int user_space_bind(struct thermal_zone_device *tz) /** * notify_user_space - Notifies user space about thermal events * @tz: thermal_zone_device - * @trip: trip point index + * @trip: trip point * * This function notifies the user space through UEvents. */ -static int notify_user_space(struct thermal_zone_device *tz, int trip) +static int notify_user_space(struct thermal_zone_device *tz, + const struct thermal_trip *trip) { char *thermal_prop[5]; int i; @@ -38,7 +39,8 @@ static int notify_user_space(struct thermal_zone_device *tz, int trip) thermal_prop[0] = kasprintf(GFP_KERNEL, "NAME=%s", tz->type); thermal_prop[1] = kasprintf(GFP_KERNEL, "TEMP=%d", tz->temperature); - thermal_prop[2] = kasprintf(GFP_KERNEL, "TRIP=%d", trip); + thermal_prop[2] = kasprintf(GFP_KERNEL, "TRIP=%d", + thermal_zone_trip_id(tz, trip)); thermal_prop[3] = kasprintf(GFP_KERNEL, "EVENT=%d", tz->notify_event); thermal_prop[4] = NULL; kobject_uevent_env(&tz->device.kobj, KOBJ_CHANGE, thermal_prop); diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 2b345f25dfa4..9c17d35ccbbd 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -307,7 +307,8 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz) thermal_zone_device_set_polling(tz, tz->polling_delay_jiffies); } -static void handle_non_critical_trips(struct thermal_zone_device *tz, int trip) +static void handle_non_critical_trips(struct thermal_zone_device *tz, + const struct thermal_trip *trip) { tz->governor ? tz->governor->throttle(tz, trip) : def_governor->throttle(tz, trip); @@ -329,44 +330,43 @@ void thermal_zone_device_critical(struct thermal_zone_device *tz) EXPORT_SYMBOL(thermal_zone_device_critical); static void handle_critical_trips(struct thermal_zone_device *tz, - int trip, int trip_temp, enum thermal_trip_type trip_type) + const struct thermal_trip *trip) { /* If we have not crossed the trip_temp, we do not care. */ - if (trip_temp <= 0 || tz->temperature < trip_temp) + if (trip->temperature <= 0 || tz->temperature < trip->temperature) return; - trace_thermal_zone_trip(tz, trip, trip_type); + trace_thermal_zone_trip(tz, thermal_zone_trip_id(tz, trip), trip->type); - if (trip_type == THERMAL_TRIP_HOT && tz->ops->hot) - tz->ops->hot(tz); - else if (trip_type == THERMAL_TRIP_CRITICAL) + if (trip->type == THERMAL_TRIP_CRITICAL) tz->ops->critical(tz); + else if (tz->ops->hot) + tz->ops->hot(tz); } -static void handle_thermal_trip(struct thermal_zone_device *tz, int trip_id) +static void handle_thermal_trip(struct thermal_zone_device *tz, + const struct thermal_trip *trip) { - struct thermal_trip trip; - - __thermal_zone_get_trip(tz, trip_id, &trip); - - if (trip.temperature == THERMAL_TEMP_INVALID) + if (trip->temperature == THERMAL_TEMP_INVALID) return; if (tz->last_temperature != THERMAL_TEMP_INVALID) { - if (tz->last_temperature < trip.temperature && - tz->temperature >= trip.temperature) - thermal_notify_tz_trip_up(tz->id, trip_id, + if (tz->last_temperature < trip->temperature && + tz->temperature >= trip->temperature) + thermal_notify_tz_trip_up(tz->id, + thermal_zone_trip_id(tz, trip), tz->temperature); - if (tz->last_temperature >= trip.temperature && - tz->temperature < (trip.temperature - trip.hysteresis)) - thermal_notify_tz_trip_down(tz->id, trip_id, + if (tz->last_temperature >= trip->temperature && + tz->temperature < trip->temperature - trip->hysteresis) + thermal_notify_tz_trip_down(tz->id, + thermal_zone_trip_id(tz, trip), tz->temperature); } - if (trip.type == THERMAL_TRIP_CRITICAL || trip.type == THERMAL_TRIP_HOT) - handle_critical_trips(tz, trip_id, trip.temperature, trip.type); + if (trip->type == THERMAL_TRIP_CRITICAL || trip->type == THERMAL_TRIP_HOT) + handle_critical_trips(tz, trip); else - handle_non_critical_trips(tz, trip_id); + handle_non_critical_trips(tz, trip); } static void update_temperature(struct thermal_zone_device *tz) @@ -403,7 +403,7 @@ static void thermal_zone_device_init(struct thermal_zone_device *tz) void __thermal_zone_device_update(struct thermal_zone_device *tz, enum thermal_notify_event event) { - int count; + const struct thermal_trip *trip; if (atomic_read(&in_suspend)) return; @@ -422,8 +422,8 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz, tz->notify_event = event; - for (count = 0; count < tz->num_trips; count++) - handle_thermal_trip(tz, count); + for_each_trip(tz, trip) + handle_thermal_trip(tz, trip); monitor_thermal_zone(tz); } diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index 4702d3a152f9..0a3b3ec5120b 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -70,7 +70,7 @@ static inline bool cdev_is_power_actor(struct thermal_cooling_device *cdev) void thermal_cdev_update(struct thermal_cooling_device *); void __thermal_cdev_update(struct thermal_cooling_device *cdev); -int get_tz_trend(struct thermal_zone_device *tz, int trip_index); +int get_tz_trend(struct thermal_zone_device *tz, const struct thermal_trip *trip); struct thermal_instance * get_thermal_instance(struct thermal_zone_device *tz, diff --git a/drivers/thermal/thermal_helpers.c b/drivers/thermal/thermal_helpers.c index c1d0af73c85d..69e8ea4aa908 100644 --- a/drivers/thermal/thermal_helpers.c +++ b/drivers/thermal/thermal_helpers.c @@ -22,9 +22,8 @@ #include "thermal_core.h" #include "thermal_trace.h" -int get_tz_trend(struct thermal_zone_device *tz, int trip_index) +int get_tz_trend(struct thermal_zone_device *tz, const struct thermal_trip *trip) { - struct thermal_trip *trip = tz->trips ? &tz->trips[trip_index] : NULL; enum thermal_trend trend; if (tz->emul_temperature || !tz->ops->get_trend || diff --git a/include/linux/thermal.h b/include/linux/thermal.h index c8600e313909..cee814d5d1ac 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -199,7 +199,8 @@ struct thermal_governor { char name[THERMAL_NAME_LENGTH]; int (*bind_to_tz)(struct thermal_zone_device *tz); void (*unbind_from_tz)(struct thermal_zone_device *tz); - int (*throttle)(struct thermal_zone_device *tz, int trip); + int (*throttle)(struct thermal_zone_device *tz, + const struct thermal_trip *trip); struct list_head governor_list; }; From cf3986f8c01d355490d0ac6024391b989a9d1e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Fri, 22 Sep 2023 14:44:03 -0400 Subject: [PATCH 110/111] thermal: core: Don't update trip points inside the hysteresis range MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When searching for the trip points that need to be set, the nearest higher trip point's temperature is used for the high trip, while the nearest lower trip point's temperature minus the hysteresis is used for the low trip. The issue with this logic is that when the current temperature is inside a trip point's hysteresis range, both high and low trips will come from the same trip point. As a consequence instability can still occur like this: * the temperature rises slightly and enters the hysteresis range of a trip point * polling happens and updates the trip points to the hysteresis range * the temperature falls slightly, exiting the hysteresis range, crossing the trip point and triggering an IRQ, the trip points are updated * repeat So even though the current hysteresis implementation prevents instability from happening due to IRQs triggering on the same temperature value, both ways, it doesn't prevent it from happening due to an IRQ on one way and polling on the other. To properly implement a hysteresis behavior, when inside the hysteresis range, don't update the trip points. This way, the previously set trip points will stay in effect, which will in a way remember the previous state (if the temperature signal came from above or below the range) and therefore have the right trip point already set. The exception is if there was no previous trip point set, in which case a previous state doesn't exist, and so it's sensible to allow the hysteresis range as trip points. The following logs show the current behavior when running on a real machine: [ 202.524658] thermal thermal_zone0: new temperature boundaries: -2147483647 < x < 40000 203.562817: thermal_temperature: thermal_zone=vpu0-thermal id=0 temp_prev=36986 temp=37979 [ 203.562845] thermal thermal_zone0: new temperature boundaries: 37000 < x < 40000 204.176059: thermal_temperature: thermal_zone=vpu0-thermal id=0 temp_prev=37979 temp=40028 [ 204.176089] thermal thermal_zone0: new temperature boundaries: 37000 < x < 100000 205.226813: thermal_temperature: thermal_zone=vpu0-thermal id=0 temp_prev=40028 temp=38652 [ 205.226842] thermal thermal_zone0: new temperature boundaries: 37000 < x < 40000 And with this patch applied: [ 184.933415] thermal thermal_zone0: new temperature boundaries: -2147483647 < x < 40000 185.981182: thermal_temperature: thermal_zone=vpu0-thermal id=0 temp_prev=36986 temp=37872 186.744685: thermal_temperature: thermal_zone=vpu0-thermal id=0 temp_prev=37872 temp=40058 [ 186.744716] thermal thermal_zone0: new temperature boundaries: 37000 < x < 100000 187.773284: thermal_temperature: thermal_zone=vpu0-thermal id=0 temp_prev=40058 temp=38698 Fixes: 060c034a9741 ("thermal: Add support for hardware-tracked trip points") Signed-off-by: Nícolas F. R. A. Prado Reviewed-by: AngeloGioacchino Del Regno Co-developed-by: Rafael J. Wysocki Signed-off-by: Rafael J. Wysocki --- drivers/thermal/thermal_trip.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/thermal_trip.c b/drivers/thermal/thermal_trip.c index 9e07535d99bb..e42456442c68 100644 --- a/drivers/thermal/thermal_trip.c +++ b/drivers/thermal/thermal_trip.c @@ -65,6 +65,7 @@ void __thermal_zone_set_trips(struct thermal_zone_device *tz) { struct thermal_trip trip; int low = -INT_MAX, high = INT_MAX; + bool same_trip = false; int i, ret; lockdep_assert_held(&tz->lock); @@ -73,6 +74,7 @@ void __thermal_zone_set_trips(struct thermal_zone_device *tz) return; for (i = 0; i < tz->num_trips; i++) { + bool low_set = false; int trip_low; ret = __thermal_zone_get_trip(tz, i , &trip); @@ -81,18 +83,31 @@ void __thermal_zone_set_trips(struct thermal_zone_device *tz) trip_low = trip.temperature - trip.hysteresis; - if (trip_low < tz->temperature && trip_low > low) + if (trip_low < tz->temperature && trip_low > low) { low = trip_low; + low_set = true; + same_trip = false; + } if (trip.temperature > tz->temperature && - trip.temperature < high) + trip.temperature < high) { high = trip.temperature; + same_trip = low_set; + } } /* No need to change trip points */ if (tz->prev_low_trip == low && tz->prev_high_trip == high) return; + /* + * If "high" and "low" are the same, skip the change unless this is the + * first time. + */ + if (same_trip && (tz->prev_low_trip != -INT_MAX || + tz->prev_high_trip != INT_MAX)) + return; + tz->prev_low_trip = low; tz->prev_high_trip = high; From c27d08f786aca71a94b06437d983a5518ec90ee8 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 13 Oct 2023 17:14:05 +0200 Subject: [PATCH 111/111] thermal: ACPI: Include the right header file It is not necessary to include thermal_core.h into thermal_acpi.c, because none of the code in there depends on anything in the former, except for the linux/thermal.h, but it is better to include that one directly instead of including the entire thermal_core.h, so make that change. No functional impact. Fixes: 7a0e39748861 ("thermal: ACPI: Add ACPI trip point routines") Signed-off-by: Rafael J. Wysocki Acked-by: Daniel Lezcano --- drivers/thermal/thermal_acpi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/thermal/thermal_acpi.c b/drivers/thermal/thermal_acpi.c index 0e5698818f69..43eaf0f2ff49 100644 --- a/drivers/thermal/thermal_acpi.c +++ b/drivers/thermal/thermal_acpi.c @@ -8,8 +8,7 @@ */ #include #include - -#include "thermal_core.h" +#include /* * Minimum temperature for full military grade is 218°K (-55°C) and