[PATCH v2 01/12] thermal/driver/tegra/soctherm: Use devm_ variant when registering a cooling device

From: Daniel Lezcano

Date: Wed Apr 22 2026 - 13:44:05 EST


The driver invokes thermal_of_cooling_device_register() at probe time
but without unregistering it at remove time.

As we have a devm_ variant, use it and the cooling device should be
automatically removed.

While this prevents the cooling device from leaking, the unregistration is now
deferred until devres_release_all() runs (after probe() returns an error or
remove() completes).

A bug can be subtly introduced by this change because the driver still
manually disables the hardware clocks during the probe error path and
in tegra_soctherm_remove(). This creates a window where the cooling
device remains registered and exposed to the thermal core and sysfs
while the underlying hardware is powered down.

In order to prevent this potential issue, use the devm_ variant for the
clk.

Compiled-tested only.

Signed-off-by: Daniel Lezcano <daniel.lezcano@xxxxxxxxxxxxxxxx>
---
drivers/thermal/tegra/soctherm.c | 29 +++++++++--------------------
1 file changed, 9 insertions(+), 20 deletions(-)

diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c
index 5d26b52beaba..790c4c96a9b5 100644
--- a/drivers/thermal/tegra/soctherm.c
+++ b/drivers/thermal/tegra/soctherm.c
@@ -1700,9 +1700,9 @@ static void soctherm_init_hw_throt_cdev(struct platform_device *pdev)
stc->init = true;
} else {

- tcd = thermal_of_cooling_device_register(np_stcc,
- (char *)name, ts,
- &throt_cooling_ops);
+ tcd = devm_thermal_of_cooling_device_register(dev, np_stcc,
+ (char *)name, ts,
+ &throt_cooling_ops);
if (IS_ERR_OR_NULL(tcd)) {
dev_err(dev,
"throttle-cfg: %s: failed to register cooling device\n",
@@ -2133,13 +2133,13 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
return PTR_ERR(tegra->reset);
}

- tegra->clock_tsensor = devm_clk_get(&pdev->dev, "tsensor");
+ tegra->clock_tsensor = devm_clk_get_enabled(&pdev->dev, "tsensor");
if (IS_ERR(tegra->clock_tsensor)) {
dev_err(&pdev->dev, "can't get tsensor clock\n");
return PTR_ERR(tegra->clock_tsensor);
}

- tegra->clock_soctherm = devm_clk_get(&pdev->dev, "soctherm");
+ tegra->clock_soctherm = devm_clk_get_enabled(&pdev->dev, "soctherm");
if (IS_ERR(tegra->clock_soctherm)) {
dev_err(&pdev->dev, "can't get soctherm clock\n");
return PTR_ERR(tegra->clock_soctherm);
@@ -2171,10 +2171,6 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
if (!tegra->thermctl_tzs)
return -ENOMEM;

- err = soctherm_clk_enable(pdev, true);
- if (err)
- return err;
-
soctherm_thermtrips_parse(pdev);

soctherm_init_hw_throt_cdev(pdev);
@@ -2184,10 +2180,8 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
for (i = 0; i < soc->num_ttgs; ++i) {
struct tegra_thermctl_zone *zone =
devm_kzalloc(&pdev->dev, sizeof(*zone), GFP_KERNEL);
- if (!zone) {
- err = -ENOMEM;
- goto disable_clocks;
- }
+ if (!zone)
+ return -ENOMEM;

zone->reg = tegra->regs + soc->ttgs[i]->sensor_temp_offset;
zone->dev = &pdev->dev;
@@ -2201,7 +2195,7 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
err = PTR_ERR(z);
dev_err(&pdev->dev, "failed to register sensor: %d\n",
err);
- goto disable_clocks;
+ return err;
}

zone->tz = z;
@@ -2210,7 +2204,7 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
/* Configure hw trip points */
err = tegra_soctherm_set_hwtrips(&pdev->dev, soc->ttgs[i], z);
if (err)
- goto disable_clocks;
+ return err;
}

err = soctherm_interrupts_init(pdev, tegra);
@@ -2218,11 +2212,6 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
soctherm_debug_init(pdev);

return 0;
-
-disable_clocks:
- soctherm_clk_enable(pdev, false);
-
- return err;
}

static void tegra_soctherm_remove(struct platform_device *pdev)
--
2.43.0