Thermal control updates for 7.1-rc1

- Fix thermal core issues related to thermal zone removal and
    registration errors that may lead to a use-after-free or a memory
    leak in some cases (Rafael Wysocki)
 
  - Drop a redundant check from thermal_zone_device_update(), adjust
    thermal workqueue allocation flags, and switch over thermal_class
    allocation to static (Rafael Wysocki)
 
  - Relocate the suspend and resume of thermal zones closer to the
    suspend and resume of devices, respectively (Rafael Wysocki)
 
  - Remove a pointless variable used in the thermal core when
    registering a cooling device (Daniel Lezcano)
 
  - Replace sprintf() in thermal_bind_cdev_to_trip() and use
    str_enabled_disabled() helper in mode_show() (Thorsten Blum)
 
  - Replace cpumask_weight() in intel_hfi_offline() with cpumask_empty()
    which is generally more efficient (Yury Norov)
 
  - Add support for reading DDR data rate from PCI config space on Nova
    Lake platforms to the int340x thermal driver (Srinivas Pandruvada)
 
  - Add an OF node address to output message to make sensor names more
    distinguishable (Alexander Stein)
 
  - Add hwmon support for the i.MX97 thermal sensor (Alexander Stein)
 
  - Clamp correctly the results when doing value/temperature conversion
    in the Spreadtrum driver (Thorsten Blum)
 
  - Add SDM670 compatible DT bindings for the Tsens and the lMH thermal
    drivers (Richard Acayan)
 
  - Add SM8750 compatible DT bindings for the Tsens thermal driver (Manaf
    Meethalavalappu Pallikunhi)
 
  - Add Eliza SoC compatible DT bindings for the Tsens driver (Krzysztof
    Kozlowski)
 
  - Fix inverted condition check on error in the Spear thermal control
    driver (Gopi Krishna Menon)
 
  - Convert DT bindings documentation into DT schema (Gopi Krishna Menon)
 
  - Use max() macro to increase readability in the Broadcom STB thermal
    sensor (Thorsten Blum)
 
  - Remove a stale @trim_offset kernel-doc entry (John Madieu)
 -----BEGIN PGP SIGNATURE-----
 
 iQFGBAABCAAwFiEEcM8Aw/RY0dgsiRUR7l+9nS/U47UFAmnZBFwSHHJqd0Byand5
 c29ja2kubmV0AAoJEO5fvZ0v1OO1CIAH/jT/z4QMvfBCIlTgwTN6ArqmbEPBoufI
 yhwyH/9gYEoJ5qvBBYWRu+NbiKIcQGdQ4bIVMbrYREqUAqZtD0ICTyysWKyxN0xC
 2Y+a1uyx5Q73Ac4s2+GNhNIykpFLeODSkHX4wHmA8DSjCdSLvqtfewK09XxoFKiP
 Gdb1mhihdEQREC2nfqOpWtxeRp90AK3Ak1Obvf4+95i2KYrQgrmaxXIGFH1Q7IQu
 4Va4/7ZEdFPmBTS3vpI3wNjFb5SDHtaP8/FUc/vVohs7if4mGT2JI94oE5ic/+bc
 RpCHvii51hHIs0VUJAqkzJwNIH1/3F3UDbiJtkV0sW9tYj02I8dLYPM=
 =m1xx
 -----END PGP SIGNATURE-----

Merge tag 'thermal-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull thermal control updates from Rafael Wysocki:
 "These include thermal core fixes and simplifications, driver fixes and
  new hardware support (SDM670, Eliza SoC), new driver features (hwmon
  support in imx91, DDR data rate on Nova Lake in int340x), and a
  handful of cleanups:

   - Fix thermal core issues related to thermal zone removal and
     registration errors that may lead to a use-after-free or a memory
     leak in some cases (Rafael Wysocki)

   - Drop a redundant check from thermal_zone_device_update(), adjust
     thermal workqueue allocation flags, and switch over thermal_class
     allocation to static (Rafael Wysocki)

   - Relocate the suspend and resume of thermal zones closer to the
     suspend and resume of devices, respectively (Rafael Wysocki)

   - Remove a pointless variable used in the thermal core when
     registering a cooling device (Daniel Lezcano)

   - Replace sprintf() in thermal_bind_cdev_to_trip() and use
     str_enabled_disabled() helper in mode_show() (Thorsten Blum)

   - Replace cpumask_weight() in intel_hfi_offline() with
     cpumask_empty() which is generally more efficient (Yury Norov)

   - Add support for reading DDR data rate from PCI config space on Nova
     Lake platforms to the int340x thermal driver (Srinivas Pandruvada)

   - Add an OF node address to output message to make sensor names more
     distinguishable (Alexander Stein)

   - Add hwmon support for the i.MX97 thermal sensor (Alexander Stein)

   - Clamp correctly the results when doing value/temperature conversion
     in the Spreadtrum driver (Thorsten Blum)

   - Add SDM670 compatible DT bindings for the Tsens and the lMH thermal
     drivers (Richard Acayan)

   - Add SM8750 compatible DT bindings for the Tsens thermal driver
     (Manaf Meethalavalappu Pallikunhi)

   - Add Eliza SoC compatible DT bindings for the Tsens driver
     (Krzysztof Kozlowski)

   - Fix inverted condition check on error in the Spear thermal control
     driver (Gopi Krishna Menon)

   - Convert DT bindings documentation into DT schema (Gopi Krishna
     Menon)

   - Use max() macro to increase readability in the Broadcom STB thermal
     sensor (Thorsten Blum)

   - Remove a stale @trim_offset kernel-doc entry (John Madieu)"

* tag 'thermal-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (25 commits)
  thermal: renesas: rzg3e: Remove stale @trim_offset kernel-doc entry
  thermal: core: Suspend thermal zones later and resume them earlier
  thermal: core: Allocate thermal_class statically
  thermal: core: Adjust thermal_wq allocation flags
  thermal: core: Drop redundant check from thermal_zone_device_update()
  thermal: core: Free thermal zone ID later during removal
  thermal: core: Fix thermal zone governor cleanup issues
  thermal/core: Remove pointless variable when registering a cooling device
  thermal/drivers/brcmstb_thermal: Use max to simplify brcmstb_get_temp
  dt-bindings: thermal: st,thermal-spear1340: convert to dtschema
  thermal/drivers/spear: Fix error condition for reading st,thermal-flags
  dt-bindings: thermal: qcom-tsens: Add Eliza SoC TSENS
  thermal: devfreq_cooling: avoid unnecessary kfree of freq_table
  thermal: intel: hfi: use cpumask_empty() in intel_hfi_offline()
  thermal: sysfs: Use str_enabled_disabled() helper in mode_show()
  dt-bindings: thermal: qcom-tsens: Document the SM8750 Temperature Sensor
  thermal/drivers/sprd: Use min instead of clamp in sprd_thm_temp_to_rawdata
  dt-bindings: thermal: lmh: Add SDM670 compatible
  dt-bindings: thermal: tsens: add SDM670 compatible
  thermal/drivers/sprd: Fix raw temperature clamping in sprd_thm_rawdata_to_temp
  ...
This commit is contained in:
Linus Torvalds 2026-04-13 20:01:50 -07:00
commit fbfb6bd927
17 changed files with 144 additions and 124 deletions

View File

@ -22,6 +22,9 @@ properties:
- qcom,sc8180x-lmh
- qcom,sdm845-lmh
- qcom,sm8150-lmh
- items:
- const: qcom,sdm670-lmh
- const: qcom,sdm845-lmh
- items:
- const: qcom,qcm2290-lmh
- const: qcom,sm8150-lmh

View File

@ -54,6 +54,7 @@ properties:
- description: v2 of TSENS
items:
- enum:
- qcom,eliza-tsens
- qcom,glymur-tsens
- qcom,kaanapali-tsens
- qcom,milos-tsens
@ -71,6 +72,7 @@ properties:
- qcom,sc8180x-tsens
- qcom,sc8280xp-tsens
- qcom,sdm630-tsens
- qcom,sdm670-tsens
- qcom,sdm845-tsens
- qcom,sm6115-tsens
- qcom,sm6350-tsens
@ -81,6 +83,7 @@ properties:
- qcom,sm8450-tsens
- qcom,sm8550-tsens
- qcom,sm8650-tsens
- qcom,sm8750-tsens
- qcom,x1e80100-tsens
- const: qcom,tsens-v2

View File

@ -1,14 +0,0 @@
* SPEAr Thermal
Required properties:
- compatible : "st,thermal-spear1340"
- reg : Address range of the thermal registers
- st,thermal-flags: flags used to enable thermal sensor
Example:
thermal@fc000000 {
compatible = "st,thermal-spear1340";
reg = <0xfc000000 0x1000>;
st,thermal-flags = <0x7000>;
};

View File

@ -0,0 +1,36 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/thermal/st,thermal-spear1340.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: SPEAr Thermal Sensor
maintainers:
- Viresh Kumar <vireshk@kernel.org>
properties:
compatible:
const: st,thermal-spear1340
reg:
maxItems: 1
st,thermal-flags:
description: flags used to enable thermal sensor
$ref: /schemas/types.yaml#/definitions/uint32
required:
- compatible
- reg
- st,thermal-flags
additionalProperties: false
examples:
- |
thermal@fc000000 {
compatible = "st,thermal-spear1340";
reg = <0xfc000000 0x1000>;
st,thermal-flags = <0x7000>;
};

View File

@ -33,6 +33,7 @@
#include <trace/events/power.h>
#include <linux/cpufreq.h>
#include <linux/devfreq.h>
#include <linux/thermal.h>
#include <linux/timer.h>
#include <linux/nmi.h>
@ -1282,6 +1283,8 @@ void dpm_complete(pm_message_t state)
list_splice(&list, &dpm_list);
mutex_unlock(&dpm_list_mtx);
/* Start resuming thermal control */
thermal_pm_complete();
/* Allow device probing and trigger re-probing of deferred devices */
device_unblock_probing();
trace_suspend_resume(TPS("dpm_complete"), state.event, false);
@ -2225,6 +2228,8 @@ int dpm_prepare(pm_message_t state)
* instead. The normal behavior will be restored in dpm_complete().
*/
device_block_probing();
/* Suspend thermal control. */
thermal_pm_prepare();
mutex_lock(&dpm_list_mtx);
while (!list_empty(&dpm_list) && !error) {

View File

@ -16,6 +16,7 @@
#include <linux/irqreturn.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@ -154,7 +155,7 @@ static int brcmstb_get_temp(struct thermal_zone_device *tz, int *temp)
{
struct brcmstb_thermal_priv *priv = thermal_zone_device_priv(tz);
u32 val;
long t;
int t;
val = __raw_readl(priv->tmon_base + AVS_TMON_STATUS);
@ -164,10 +165,7 @@ static int brcmstb_get_temp(struct thermal_zone_device *tz, int *temp)
val = (val & AVS_TMON_STATUS_data_msk) >> AVS_TMON_STATUS_data_shift;
t = avs_tmon_code_to_temp(priv, val);
if (t < 0)
*temp = 0;
else
*temp = t;
*temp = max(0, t);
return 0;
}

View File

@ -472,7 +472,8 @@ of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,
remove_qos_req:
dev_pm_qos_remove_request(&dfc->req_max_freq);
free_table:
kfree(dfc->freq_table);
if (!dfc->em_pd)
kfree(dfc->freq_table);
free_dfc:
kfree(dfc);

View File

@ -17,6 +17,8 @@
#include <linux/thermal.h>
#include <linux/units.h>
#include "thermal_hwmon.h"
#define REG_SET 0x4
#define REG_CLR 0x8
#define REG_TOG 0xc
@ -318,6 +320,8 @@ static int imx91_tmu_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(tmu->tzd),
"failed to register thermal zone sensor\n");
devm_thermal_add_hwmon_sysfs(dev, tmu->tzd);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;

View File

@ -402,17 +402,31 @@ static ssize_t rfi_restriction_show(struct device *dev,
return sysfs_emit(buf, "%llu\n", resp);
}
/* ddr_data_rate */
static const struct mmio_reg nvl_ddr_data_rate_reg = { 1, 0xE0, 10, 0x3FF, 2};
static const struct mmio_reg *ddr_data_rate_reg;
static ssize_t ddr_data_rate_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
u16 id = 0x0107;
u64 resp;
int ret;
ret = processor_thermal_send_mbox_read_cmd(to_pci_dev(dev), id, &resp);
if (ret)
return ret;
if (ddr_data_rate_reg) {
u16 reg_val;
pci_read_config_word(to_pci_dev(dev), ddr_data_rate_reg->offset, &reg_val);
resp = (reg_val >> ddr_data_rate_reg->shift) & ddr_data_rate_reg->mask;
resp = (resp * 3333) / 100;
} else {
const u16 id = 0x0107;
int ret;
ret = processor_thermal_send_mbox_read_cmd(to_pci_dev(dev), id, &resp);
if (ret)
return ret;
}
return sysfs_emit(buf, "%llu\n", resp);
}
@ -461,6 +475,7 @@ int proc_thermal_rfim_add(struct pci_dev *pdev, struct proc_thermal_device *proc
case PCI_DEVICE_ID_INTEL_NVL_H_THERMAL:
case PCI_DEVICE_ID_INTEL_NVL_S_THERMAL:
dlvr_mmio_regs_table = nvl_dlvr_mmio_regs;
ddr_data_rate_reg = &nvl_ddr_data_rate_reg;
break;
default:
dlvr_mmio_regs_table = dlvr_mmio_regs;

View File

@ -526,7 +526,7 @@ void intel_hfi_offline(unsigned int cpu)
mutex_lock(&hfi_instance_lock);
cpumask_clear_cpu(cpu, hfi_instance->cpus);
if (!cpumask_weight(hfi_instance->cpus))
if (cpumask_empty(hfi_instance->cpus))
hfi_disable();
mutex_unlock(&hfi_instance_lock);

View File

@ -93,7 +93,6 @@ struct rzg3e_thermal_info {
* @info: chip type specific information
* @trmval0: calibration value 0 (b)
* @trmval1: calibration value 1 (c)
* @trim_offset: offset for trim registers in syscon
* @lock: protects hardware access during conversions
*/
struct rzg3e_thermal_priv {

View File

@ -93,7 +93,7 @@ static int spear_thermal_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
int ret = 0, val;
if (!np || !of_property_read_u32(np, "st,thermal-flags", &val)) {
if (!np || of_property_read_u32(np, "st,thermal-flags", &val)) {
dev_err(&pdev->dev, "Failed: DT Pdata not passed\n");
return -EINVAL;
}

View File

@ -178,7 +178,7 @@ static int sprd_thm_sensor_calibration(struct device_node *np,
static int sprd_thm_rawdata_to_temp(struct sprd_thermal_sensor *sen,
u32 rawdata)
{
clamp(rawdata, (u32)SPRD_THM_RAW_DATA_LOW, (u32)SPRD_THM_RAW_DATA_HIGH);
rawdata = clamp(rawdata, SPRD_THM_RAW_DATA_LOW, SPRD_THM_RAW_DATA_HIGH);
/*
* According to the thermal datasheet, the formula of converting
@ -192,7 +192,7 @@ static int sprd_thm_temp_to_rawdata(int temp, struct sprd_thermal_sensor *sen)
{
u32 val;
clamp(temp, (int)SPRD_THM_TEMP_LOW, (int)SPRD_THM_TEMP_HIGH);
temp = clamp(temp, SPRD_THM_TEMP_LOW, SPRD_THM_TEMP_HIGH);
/*
* According to the thermal datasheet, the formula of converting
@ -201,7 +201,7 @@ static int sprd_thm_temp_to_rawdata(int temp, struct sprd_thermal_sensor *sen)
*/
val = (temp + sen->cal_offset) / sen->cal_slope;
return clamp(val, val, (u32)(SPRD_THM_RAW_DATA_HIGH - 1));
return min(val, SPRD_THM_RAW_DATA_HIGH - 1);
}
static int sprd_thm_read_temp(struct thermal_zone_device *tz, int *temp)

View File

@ -695,18 +695,12 @@ int thermal_zone_device_disable(struct thermal_zone_device *tz)
}
EXPORT_SYMBOL_GPL(thermal_zone_device_disable);
static bool thermal_zone_is_present(struct thermal_zone_device *tz)
{
return !list_empty(&tz->node);
}
void thermal_zone_device_update(struct thermal_zone_device *tz,
enum thermal_notify_event event)
{
guard(thermal_zone)(tz);
if (thermal_zone_is_present(tz))
__thermal_zone_device_update(tz, event);
__thermal_zone_device_update(tz, event);
}
EXPORT_SYMBOL_GPL(thermal_zone_device_update);
@ -863,7 +857,7 @@ static int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz,
goto free_mem;
dev->id = result;
sprintf(dev->name, "cdev%d", dev->id);
snprintf(dev->name, sizeof(dev->name), "cdev%d", dev->id);
result =
sysfs_create_link(&tz->device.kobj, &cdev->device.kobj, dev->name);
if (result)
@ -964,6 +958,8 @@ static void thermal_release(struct device *dev)
sizeof("thermal_zone") - 1)) {
tz = to_thermal_zone(dev);
thermal_zone_destroy_device_groups(tz);
thermal_set_governor(tz, NULL);
ida_destroy(&tz->ida);
mutex_destroy(&tz->lock);
complete(&tz->removal);
} else if (!strncmp(dev_name(dev), "cooling_device",
@ -976,7 +972,11 @@ static void thermal_release(struct device *dev)
}
}
static struct class *thermal_class;
static const struct class thermal_class = {
.name = "thermal",
.dev_release = thermal_release,
};
static bool thermal_class_unavailable __ro_after_init = true;
static inline
void print_bind_err_msg(struct thermal_zone_device *tz,
@ -1063,13 +1063,13 @@ __thermal_cooling_device_register(struct device_node *np,
{
struct thermal_cooling_device *cdev;
unsigned long current_state;
int id, ret;
int ret;
if (!ops || !ops->get_max_state || !ops->get_cur_state ||
!ops->set_cur_state)
return ERR_PTR(-EINVAL);
if (!thermal_class)
if (thermal_class_unavailable)
return ERR_PTR(-ENODEV);
cdev = kzalloc_obj(*cdev);
@ -1080,7 +1080,6 @@ __thermal_cooling_device_register(struct device_node *np,
if (ret < 0)
goto out_kfree_cdev;
cdev->id = ret;
id = ret;
cdev->type = kstrdup_const(type ? type : "", GFP_KERNEL);
if (!cdev->type) {
@ -1093,7 +1092,7 @@ __thermal_cooling_device_register(struct device_node *np,
cdev->np = np;
cdev->ops = ops;
cdev->updated = false;
cdev->device.class = thermal_class;
cdev->device.class = &thermal_class;
cdev->devdata = devdata;
ret = cdev->ops->get_max_state(cdev, &cdev->max_state);
@ -1137,7 +1136,7 @@ __thermal_cooling_device_register(struct device_node *np,
out_cdev_type:
kfree_const(cdev->type);
out_ida_remove:
ida_free(&thermal_cdev_ida, id);
ida_free(&thermal_cdev_ida, cdev->id);
out_kfree_cdev:
kfree(cdev);
return ERR_PTR(ret);
@ -1541,7 +1540,7 @@ thermal_zone_device_register_with_trips(const char *type,
if (polling_delay && passive_delay > polling_delay)
return ERR_PTR(-EINVAL);
if (!thermal_class)
if (thermal_class_unavailable)
return ERR_PTR(-ENODEV);
tz = kzalloc_flex(*tz, trips, num_trips);
@ -1577,7 +1576,7 @@ thermal_zone_device_register_with_trips(const char *type,
if (!tz->ops.critical)
tz->ops.critical = thermal_zone_device_critical;
tz->device.class = thermal_class;
tz->device.class = &thermal_class;
tz->devdata = devdata;
tz->num_trips = num_trips;
for_each_trip_desc(tz, td) {
@ -1611,8 +1610,10 @@ thermal_zone_device_register_with_trips(const char *type,
/* sys I/F */
/* Add nodes that are always present via .groups */
result = thermal_zone_create_device_groups(tz);
if (result)
if (result) {
thermal_set_governor(tz, NULL);
goto remove_id;
}
result = device_register(&tz->device);
if (result)
@ -1725,12 +1726,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
cancel_delayed_work_sync(&tz->poll_queue);
thermal_set_governor(tz, NULL);
thermal_thresholds_exit(tz);
thermal_remove_hwmon_sysfs(tz);
ida_free(&thermal_tz_ida, tz->id);
ida_destroy(&tz->ida);
device_del(&tz->device);
put_device(&tz->device);
@ -1738,6 +1735,9 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
thermal_notify_tz_delete(tz);
wait_for_completion(&tz->removal);
ida_free(&thermal_tz_ida, tz->id);
kfree(tz->tzp);
kfree(tz);
}
@ -1823,7 +1823,7 @@ static void thermal_zone_pm_prepare(struct thermal_zone_device *tz)
cancel_delayed_work(&tz->poll_queue);
}
static void thermal_pm_notify_prepare(void)
static void __thermal_pm_prepare(void)
{
struct thermal_zone_device *tz;
@ -1835,6 +1835,19 @@ static void thermal_pm_notify_prepare(void)
thermal_zone_pm_prepare(tz);
}
void thermal_pm_prepare(void)
{
if (thermal_class_unavailable)
return;
__thermal_pm_prepare();
/*
* Allow any leftover thermal work items already on the worqueue to
* complete so they don't get in the way later.
*/
flush_workqueue(thermal_wq);
}
static void thermal_zone_pm_complete(struct thermal_zone_device *tz)
{
guard(thermal_zone)(tz);
@ -1851,10 +1864,13 @@ static void thermal_zone_pm_complete(struct thermal_zone_device *tz)
mod_delayed_work(thermal_wq, &tz->poll_queue, 0);
}
static void thermal_pm_notify_complete(void)
void thermal_pm_complete(void)
{
struct thermal_zone_device *tz;
if (thermal_class_unavailable)
return;
guard(mutex)(&thermal_list_lock);
thermal_pm_suspended = false;
@ -1863,41 +1879,6 @@ static void thermal_pm_notify_complete(void)
thermal_zone_pm_complete(tz);
}
static int thermal_pm_notify(struct notifier_block *nb,
unsigned long mode, void *_unused)
{
switch (mode) {
case PM_HIBERNATION_PREPARE:
case PM_RESTORE_PREPARE:
case PM_SUSPEND_PREPARE:
thermal_pm_notify_prepare();
/*
* Allow any leftover thermal work items already on the
* worqueue to complete so they don't get in the way later.
*/
flush_workqueue(thermal_wq);
break;
case PM_POST_HIBERNATION:
case PM_POST_RESTORE:
case PM_POST_SUSPEND:
thermal_pm_notify_complete();
break;
default:
break;
}
return 0;
}
static struct notifier_block thermal_pm_nb = {
.notifier_call = thermal_pm_notify,
/*
* Run at the lowest priority to avoid interference between the thermal
* zone resume work items spawned by thermal_pm_notify() and the other
* PM notifiers.
*/
.priority = INT_MIN,
};
static int __init thermal_init(void)
{
int result;
@ -1908,8 +1889,7 @@ static int __init thermal_init(void)
if (result)
goto error;
thermal_wq = alloc_workqueue("thermal_events",
WQ_FREEZABLE | WQ_POWER_EFFICIENT | WQ_PERCPU, 0);
thermal_wq = alloc_workqueue("thermal_events", WQ_POWER_EFFICIENT, 0);
if (!thermal_wq) {
result = -ENOMEM;
goto unregister_netlink;
@ -1919,26 +1899,11 @@ static int __init thermal_init(void)
if (result)
goto destroy_workqueue;
thermal_class = kzalloc_obj(*thermal_class);
if (!thermal_class) {
result = -ENOMEM;
goto unregister_governors;
}
thermal_class->name = "thermal";
thermal_class->dev_release = thermal_release;
result = class_register(thermal_class);
if (result) {
kfree(thermal_class);
thermal_class = NULL;
goto unregister_governors;
}
result = register_pm_notifier(&thermal_pm_nb);
result = class_register(&thermal_class);
if (result)
pr_warn("Thermal: Can not register suspend notifier, return %d\n",
result);
goto unregister_governors;
thermal_class_unavailable = false;
return 0;

View File

@ -144,7 +144,7 @@ static struct device_node *of_thermal_zone_find(struct device_node *sensor, int
count = of_count_phandle_with_args(child, "thermal-sensors",
"#thermal-sensor-cells");
if (count <= 0) {
pr_err("%pOFn: missing thermal sensor\n", child);
pr_err("%pOFP: missing thermal sensor\n", child);
return ERR_PTR(-EINVAL);
}
@ -156,14 +156,14 @@ static struct device_node *of_thermal_zone_find(struct device_node *sensor, int
"#thermal-sensor-cells",
i, &sensor_specs);
if (ret < 0) {
pr_err("%pOFn: Failed to read thermal-sensors cells: %d\n", child, ret);
pr_err("%pOFP: Failed to read thermal-sensors cells: %d\n", child, ret);
return ERR_PTR(ret);
}
of_node_put(sensor_specs.np);
if ((sensor == sensor_specs.np) && id == (sensor_specs.args_count ?
sensor_specs.args[0] : 0)) {
pr_debug("sensor %pOFn id=%d belongs to %pOFn\n", sensor, id, child);
pr_debug("sensor %pOFP id=%d belongs to %pOFP\n", sensor, id, child);
return no_free_ptr(child);
}
}
@ -180,7 +180,7 @@ static int thermal_of_monitor_init(struct device_node *np, int *delay, int *pdel
if (ret == -EINVAL) {
*pdelay = 0;
} else if (ret < 0) {
pr_err("%pOFn: Couldn't get polling-delay-passive: %d\n", np, ret);
pr_err("%pOFP: Couldn't get polling-delay-passive: %d\n", np, ret);
return ret;
}
@ -188,7 +188,7 @@ static int thermal_of_monitor_init(struct device_node *np, int *delay, int *pdel
if (ret == -EINVAL) {
*delay = 0;
} else if (ret < 0) {
pr_err("%pOFn: Couldn't get polling-delay: %d\n", np, ret);
pr_err("%pOFP: Couldn't get polling-delay: %d\n", np, ret);
return ret;
}
@ -380,23 +380,23 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node *
np = of_thermal_zone_find(sensor, id);
if (IS_ERR(np)) {
if (PTR_ERR(np) != -ENODEV)
pr_err("Failed to find thermal zone for %pOFn id=%d\n", sensor, id);
pr_err("Failed to find thermal zone for %pOFP id=%d\n", sensor, id);
return ERR_CAST(np);
}
trips = thermal_of_trips_init(np, &ntrips);
if (IS_ERR(trips)) {
pr_err("Failed to parse trip points for %pOFn id=%d\n", sensor, id);
pr_err("Failed to parse trip points for %pOFP id=%d\n", sensor, id);
ret = PTR_ERR(trips);
goto out_of_node_put;
}
if (!trips)
pr_info("No trip points found for %pOFn id=%d\n", sensor, id);
pr_info("No trip points found for %pOFP id=%d\n", sensor, id);
ret = thermal_of_monitor_init(np, &delay, &pdelay);
if (ret) {
pr_err("Failed to initialize monitoring delays from %pOFn\n", np);
pr_err("Failed to initialize monitoring delays from %pOFP\n", np);
goto out_kfree_trips;
}
@ -417,7 +417,7 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node *
pdelay, delay);
if (IS_ERR(tz)) {
ret = PTR_ERR(tz);
pr_err("Failed to register thermal zone %pOFn: %d\n", np, ret);
pr_err("Failed to register thermal zone %pOFP: %d\n", np, ret);
goto out_kfree_trips;
}

View File

@ -18,6 +18,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/string_choices.h>
#include <linux/jiffies.h>
#include "thermal_core.h"
@ -56,10 +57,8 @@ mode_show(struct device *dev, struct device_attribute *attr, char *buf)
guard(thermal_zone)(tz);
if (tz->mode == THERMAL_DEVICE_ENABLED)
return sysfs_emit(buf, "enabled\n");
return sysfs_emit(buf, "disabled\n");
return sysfs_emit(buf, "%s\n",
str_enabled_disabled(tz->mode == THERMAL_DEVICE_ENABLED));
}
static ssize_t

View File

@ -273,6 +273,9 @@ bool thermal_trip_is_bound_to_cdev(struct thermal_zone_device *tz,
int thermal_zone_device_enable(struct thermal_zone_device *tz);
int thermal_zone_device_disable(struct thermal_zone_device *tz);
void thermal_zone_device_critical(struct thermal_zone_device *tz);
void thermal_pm_prepare(void);
void thermal_pm_complete(void);
#else
static inline struct thermal_zone_device *thermal_zone_device_register_with_trips(
const char *type,
@ -350,6 +353,9 @@ static inline int thermal_zone_device_enable(struct thermal_zone_device *tz)
static inline int thermal_zone_device_disable(struct thermal_zone_device *tz)
{ return -ENODEV; }
static inline void thermal_pm_prepare(void) {}
static inline void thermal_pm_complete(void) {}
#endif /* CONFIG_THERMAL */
#endif /* __THERMAL_H__ */