diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-04-14 06:01:50 +0300 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-04-14 06:01:50 +0300 |
| commit | fbfb6bd927c9ac6ea155471cc7ced8e16b37c2cb (patch) | |
| tree | 5d0223c4c3cb8025c9ef6f3a198b0359b2047893 | |
| parent | d7c8087a9cd8979d70edfe7c7feda9423feae3ab (diff) | |
| parent | cd1a3b2ff0553e987de71ff0aa675e418de22898 (diff) | |
| download | linux-fbfb6bd927c9ac6ea155471cc7ced8e16b37c2cb.tar.xz | |
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
...
| -rw-r--r-- | Documentation/devicetree/bindings/thermal/qcom-lmh.yaml | 3 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/thermal/qcom-tsens.yaml | 3 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/thermal/spear-thermal.txt | 14 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/thermal/st,thermal-spear1340.yaml | 36 | ||||
| -rw-r--r-- | drivers/base/power/main.c | 5 | ||||
| -rw-r--r-- | drivers/thermal/broadcom/brcmstb_thermal.c | 8 | ||||
| -rw-r--r-- | drivers/thermal/devfreq_cooling.c | 3 | ||||
| -rw-r--r-- | drivers/thermal/imx91_thermal.c | 4 | ||||
| -rw-r--r-- | drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c | 25 | ||||
| -rw-r--r-- | drivers/thermal/intel/intel_hfi.c | 2 | ||||
| -rw-r--r-- | drivers/thermal/renesas/rzg3e_thermal.c | 1 | ||||
| -rw-r--r-- | drivers/thermal/spear_thermal.c | 2 | ||||
| -rw-r--r-- | drivers/thermal/sprd_thermal.c | 6 | ||||
| -rw-r--r-- | drivers/thermal/thermal_core.c | 121 | ||||
| -rw-r--r-- | drivers/thermal/thermal_of.c | 20 | ||||
| -rw-r--r-- | drivers/thermal/thermal_sysfs.c | 7 | ||||
| -rw-r--r-- | include/linux/thermal.h | 6 |
17 files changed, 143 insertions, 123 deletions
diff --git a/Documentation/devicetree/bindings/thermal/qcom-lmh.yaml b/Documentation/devicetree/bindings/thermal/qcom-lmh.yaml index 1175bb358382..ce72347e29d1 100644 --- a/Documentation/devicetree/bindings/thermal/qcom-lmh.yaml +++ b/Documentation/devicetree/bindings/thermal/qcom-lmh.yaml @@ -23,6 +23,9 @@ properties: - qcom,sdm845-lmh - qcom,sm8150-lmh - items: + - const: qcom,sdm670-lmh + - const: qcom,sdm845-lmh + - items: - const: qcom,qcm2290-lmh - const: qcom,sm8150-lmh diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml index 3c5256b0cd9f..7d34ba00e684 100644 --- a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml +++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml @@ -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 diff --git a/Documentation/devicetree/bindings/thermal/spear-thermal.txt b/Documentation/devicetree/bindings/thermal/spear-thermal.txt deleted file mode 100644 index 93e3b67c102d..000000000000 --- a/Documentation/devicetree/bindings/thermal/spear-thermal.txt +++ /dev/null @@ -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>; - }; diff --git a/Documentation/devicetree/bindings/thermal/st,thermal-spear1340.yaml b/Documentation/devicetree/bindings/thermal/st,thermal-spear1340.yaml new file mode 100644 index 000000000000..e3462a974691 --- /dev/null +++ b/Documentation/devicetree/bindings/thermal/st,thermal-spear1340.yaml @@ -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>; + }; diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 189de5250f25..e1b550664bab 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -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) { diff --git a/drivers/thermal/broadcom/brcmstb_thermal.c b/drivers/thermal/broadcom/brcmstb_thermal.c index f46f2ddc174e..a9ffa596f7c0 100644 --- a/drivers/thermal/broadcom/brcmstb_thermal.c +++ b/drivers/thermal/broadcom/brcmstb_thermal.c @@ -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; } diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c index 597e86d16a4e..1c7dffc8d45f 100644 --- a/drivers/thermal/devfreq_cooling.c +++ b/drivers/thermal/devfreq_cooling.c @@ -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); diff --git a/drivers/thermal/imx91_thermal.c b/drivers/thermal/imx91_thermal.c index 9b20be03d6de..25915bb702be 100644 --- a/drivers/thermal/imx91_thermal.c +++ b/drivers/thermal/imx91_thermal.c @@ -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; diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c index 314fbc1f490f..1a7e134dfcf8 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c @@ -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, ®_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; diff --git a/drivers/thermal/intel/intel_hfi.c b/drivers/thermal/intel/intel_hfi.c index 1a1a95b39405..8c4ae75231f8 100644 --- a/drivers/thermal/intel/intel_hfi.c +++ b/drivers/thermal/intel/intel_hfi.c @@ -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); diff --git a/drivers/thermal/renesas/rzg3e_thermal.c b/drivers/thermal/renesas/rzg3e_thermal.c index dde021e283b7..f0e29fe633db 100644 --- a/drivers/thermal/renesas/rzg3e_thermal.c +++ b/drivers/thermal/renesas/rzg3e_thermal.c @@ -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 { diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c index 603dadcd3df5..5e3e9c1f32f8 100644 --- a/drivers/thermal/spear_thermal.c +++ b/drivers/thermal/spear_thermal.c @@ -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; } diff --git a/drivers/thermal/sprd_thermal.c b/drivers/thermal/sprd_thermal.c index e546067c9621..d683fcb0f8ab 100644 --- a/drivers/thermal/sprd_thermal.c +++ b/drivers/thermal/sprd_thermal.c @@ -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) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index d1beee9e15f8..2f4e2dc46b8f 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -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 @@ out_cooling_dev: 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; + result = class_register(&thermal_class); + if (result) goto unregister_governors; - } - result = register_pm_notifier(&thermal_pm_nb); - if (result) - pr_warn("Thermal: Can not register suspend notifier, return %d\n", - result); + thermal_class_unavailable = false; return 0; diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 6ebb83cb70b2..99085c806a1f 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -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; } diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c index 46b3b2df935c..5eecae13f07d 100644 --- a/drivers/thermal/thermal_sysfs.c +++ b/drivers/thermal/thermal_sysfs.c @@ -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 diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 0b5ed6821080..0ddc77aeeca2 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -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__ */ |
