* [PATCH 0/4] thermal/core: Decouple release paths for tz and cdev
@ 2026-05-08 18:05 Daniel Lezcano
2026-05-08 18:05 ` [PATCH 1/4] thermal/core: Add dedicated release callback for cooling devices Daniel Lezcano
` (4 more replies)
0 siblings, 5 replies; 18+ messages in thread
From: Daniel Lezcano @ 2026-05-08 18:05 UTC (permalink / raw)
To: daniel.lezcano, lukasz.luba, rafael; +Cc: rui.zhang, linux-pm, linux-kernel
This series cleans up the lifetime handling of thermal devices.
Currently, the thermal class release callback handles both thermal
zones and cooling devices by checking the device name prefix. This
approach is fragile and mixes responsibilities across different object
types.
The first two patches introduce dedicated struct device release
callbacks for thermal zones and cooling devices. This removes the need
to rely on device names and keeps the lifetime management local to
each object.
The last two patches convert the thermal class to a dynamically
allocated object and simplify the initialization logic by using the
class pointer itself as a guard instead of a separate boolean flag.
Overall, this results in a clearer separation of responsibilities and
more robust lifetime management aligned with the device model.
No functional change intended.
---
Daniel Lezcano (4):
thermal/core: Add dedicated release callback for cooling devices
thermal/core: Add dedicated release callback for thermal zones
thermal/core: Allocate the thermal class dynamically
thermal/core: Use the thermal class pointer as init guard
drivers/thermal/thermal_core.c | 73 ++++++++++++++++------------------
1 file changed, 35 insertions(+), 38 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 1/4] thermal/core: Add dedicated release callback for cooling devices
2026-05-08 18:05 [PATCH 0/4] thermal/core: Decouple release paths for tz and cdev Daniel Lezcano
@ 2026-05-08 18:05 ` Daniel Lezcano
2026-05-13 15:02 ` Lukasz Luba
2026-05-08 18:05 ` [PATCH 2/4] thermal/core: Add dedicated release callback for thermal zones Daniel Lezcano
` (3 subsequent siblings)
4 siblings, 1 reply; 18+ messages in thread
From: Daniel Lezcano @ 2026-05-08 18:05 UTC (permalink / raw)
To: daniel.lezcano, lukasz.luba, rafael; +Cc: rui.zhang, linux-pm, linux-kernel
The thermal class release callback currently handles both thermal
zones and cooling devices by checking the device name prefix.
Move the cooling device cleanup to a dedicated struct device release
callback. This avoids relying on device names to select the release
path and keeps the cooling device lifetime handling local to the
cooling device object.
Signed-off-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
---
drivers/thermal/thermal_core.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 2f4e2dc46b8f..cf5d4a9c11fe 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -952,7 +952,6 @@ static void thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz,
static void thermal_release(struct device *dev)
{
struct thermal_zone_device *tz;
- struct thermal_cooling_device *cdev;
if (!strncmp(dev_name(dev), "thermal_zone",
sizeof("thermal_zone") - 1)) {
@@ -962,13 +961,6 @@ static void thermal_release(struct device *dev)
ida_destroy(&tz->ida);
mutex_destroy(&tz->lock);
complete(&tz->removal);
- } else if (!strncmp(dev_name(dev), "cooling_device",
- sizeof("cooling_device") - 1)) {
- cdev = to_cooling_device(dev);
- thermal_cooling_device_destroy_sysfs(cdev);
- kfree_const(cdev->type);
- ida_free(&thermal_cdev_ida, cdev->id);
- kfree(cdev);
}
}
@@ -1040,6 +1032,16 @@ static void thermal_cooling_device_init_complete(struct thermal_cooling_device *
thermal_zone_cdev_bind(tz, cdev);
}
+static void thermal_cdev_release(struct device *dev)
+{
+ struct thermal_cooling_device *cdev = to_cooling_device(dev);
+
+ thermal_cooling_device_destroy_sysfs(cdev);
+ kfree_const(cdev->type);
+ ida_free(&thermal_cdev_ida, cdev->id);
+ kfree(cdev);
+}
+
/**
* __thermal_cooling_device_register() - register a new thermal cooling device
* @np: a pointer to a device tree node.
@@ -1093,6 +1095,7 @@ __thermal_cooling_device_register(struct device_node *np,
cdev->ops = ops;
cdev->updated = false;
cdev->device.class = &thermal_class;
+ cdev->device.release = thermal_cdev_release;
cdev->devdata = devdata;
ret = cdev->ops->get_max_state(cdev, &cdev->max_state);
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 2/4] thermal/core: Add dedicated release callback for thermal zones
2026-05-08 18:05 [PATCH 0/4] thermal/core: Decouple release paths for tz and cdev Daniel Lezcano
2026-05-08 18:05 ` [PATCH 1/4] thermal/core: Add dedicated release callback for cooling devices Daniel Lezcano
@ 2026-05-08 18:05 ` Daniel Lezcano
2026-05-13 15:02 ` Lukasz Luba
2026-05-08 18:05 ` [PATCH 3/4] thermal/core: Allocate the thermal class dynamically Daniel Lezcano
` (2 subsequent siblings)
4 siblings, 1 reply; 18+ messages in thread
From: Daniel Lezcano @ 2026-05-08 18:05 UTC (permalink / raw)
To: daniel.lezcano, lukasz.luba, rafael; +Cc: rui.zhang, linux-pm, linux-kernel
The thermal class release callback currently handles thermal zone
cleanup by checking the device name prefix.
Move the thermal zone cleanup to a dedicated struct device release
callback. This avoids relying on device names to select the release
path and keeps the thermal zone lifetime handling local to the thermal
zone object.
Signed-off-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
---
drivers/thermal/thermal_core.c | 28 ++++++++++++----------------
1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index cf5d4a9c11fe..a79fc4cdb078 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -949,24 +949,8 @@ static void thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz,
kfree(pos);
}
-static void thermal_release(struct device *dev)
-{
- struct thermal_zone_device *tz;
-
- if (!strncmp(dev_name(dev), "thermal_zone",
- 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);
- }
-}
-
static const struct class thermal_class = {
.name = "thermal",
- .dev_release = thermal_release,
};
static bool thermal_class_unavailable __ro_after_init = true;
@@ -1473,6 +1457,17 @@ static void thermal_zone_init_complete(struct thermal_zone_device *tz)
__thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
}
+static void thermal_zone_device_release(struct device *dev)
+{
+ struct thermal_zone_device *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);
+}
+
/**
* thermal_zone_device_register_with_trips() - register a new thermal zone device
* @type: the thermal zone device type
@@ -1580,6 +1575,7 @@ thermal_zone_device_register_with_trips(const char *type,
tz->ops.critical = thermal_zone_device_critical;
tz->device.class = &thermal_class;
+ tz->device.release = thermal_zone_device_release;
tz->devdata = devdata;
tz->num_trips = num_trips;
for_each_trip_desc(tz, td) {
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 3/4] thermal/core: Allocate the thermal class dynamically
2026-05-08 18:05 [PATCH 0/4] thermal/core: Decouple release paths for tz and cdev Daniel Lezcano
2026-05-08 18:05 ` [PATCH 1/4] thermal/core: Add dedicated release callback for cooling devices Daniel Lezcano
2026-05-08 18:05 ` [PATCH 2/4] thermal/core: Add dedicated release callback for thermal zones Daniel Lezcano
@ 2026-05-08 18:05 ` Daniel Lezcano
2026-05-08 18:24 ` Rafael J. Wysocki
2026-05-13 15:03 ` Lukasz Luba
2026-05-08 18:05 ` [PATCH 4/4] thermal/core: Use the thermal class pointer as init guard Daniel Lezcano
2026-05-08 18:10 ` [PATCH 0/4] thermal/core: Decouple release paths for tz and cdev Daniel Lezcano
4 siblings, 2 replies; 18+ messages in thread
From: Daniel Lezcano @ 2026-05-08 18:05 UTC (permalink / raw)
To: daniel.lezcano, lukasz.luba, rafael; +Cc: rui.zhang, linux-pm, linux-kernel
Use class_create() instead of a statically allocated struct class.
This allows the thermal class to be managed through a dynamically
allocated class object and avoids keeping a static class instance
around.
Signed-off-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
---
drivers/thermal/thermal_core.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index a79fc4cdb078..748ab76823a3 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -949,9 +949,7 @@ static void thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz,
kfree(pos);
}
-static const struct class thermal_class = {
- .name = "thermal",
-};
+static struct class *thermal_class;
static bool thermal_class_unavailable __ro_after_init = true;
static inline
@@ -1078,7 +1076,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->device.release = thermal_cdev_release;
cdev->devdata = devdata;
@@ -1574,7 +1572,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->device.release = thermal_zone_device_release;
tz->devdata = devdata;
tz->num_trips = num_trips;
@@ -1898,15 +1896,18 @@ static int __init thermal_init(void)
if (result)
goto destroy_workqueue;
- result = class_register(&thermal_class);
- if (result)
+ thermal_class = class_create("thermal");
+ if (IS_ERR(thermal_class)) {
+ result = PTR_ERR(thermal_class);
goto unregister_governors;
+ }
thermal_class_unavailable = false;
return 0;
unregister_governors:
+ thermal_class = NULL;
thermal_unregister_governors();
destroy_workqueue:
destroy_workqueue(thermal_wq);
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 4/4] thermal/core: Use the thermal class pointer as init guard
2026-05-08 18:05 [PATCH 0/4] thermal/core: Decouple release paths for tz and cdev Daniel Lezcano
` (2 preceding siblings ...)
2026-05-08 18:05 ` [PATCH 3/4] thermal/core: Allocate the thermal class dynamically Daniel Lezcano
@ 2026-05-08 18:05 ` Daniel Lezcano
2026-05-13 15:03 ` Lukasz Luba
2026-05-08 18:10 ` [PATCH 0/4] thermal/core: Decouple release paths for tz and cdev Daniel Lezcano
4 siblings, 1 reply; 18+ messages in thread
From: Daniel Lezcano @ 2026-05-08 18:05 UTC (permalink / raw)
To: daniel.lezcano, lukasz.luba, rafael; +Cc: rui.zhang, linux-pm, linux-kernel
The thermal class is now dynamically allocated and stored as a
pointer.
Use the thermal_class pointer itself to check whether the thermal
class has been created instead of keeping a separate
thermal_class_unavailable flag.
Signed-off-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
---
drivers/thermal/thermal_core.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 748ab76823a3..81f6bbaded65 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -950,7 +950,6 @@ static void thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz,
}
static struct class *thermal_class;
-static bool thermal_class_unavailable __ro_after_init = true;
static inline
void print_bind_err_msg(struct thermal_zone_device *tz,
@@ -1053,7 +1052,7 @@ __thermal_cooling_device_register(struct device_node *np,
!ops->set_cur_state)
return ERR_PTR(-EINVAL);
- if (thermal_class_unavailable)
+ if (!thermal_class)
return ERR_PTR(-ENODEV);
cdev = kzalloc_obj(*cdev);
@@ -1536,7 +1535,7 @@ thermal_zone_device_register_with_trips(const char *type,
if (polling_delay && passive_delay > polling_delay)
return ERR_PTR(-EINVAL);
- if (thermal_class_unavailable)
+ if (!thermal_class)
return ERR_PTR(-ENODEV);
tz = kzalloc_flex(*tz, trips, num_trips);
@@ -1834,7 +1833,7 @@ static void __thermal_pm_prepare(void)
void thermal_pm_prepare(void)
{
- if (thermal_class_unavailable)
+ if (!thermal_class)
return;
__thermal_pm_prepare();
@@ -1865,7 +1864,7 @@ void thermal_pm_complete(void)
{
struct thermal_zone_device *tz;
- if (thermal_class_unavailable)
+ if (!thermal_class)
return;
guard(mutex)(&thermal_list_lock);
@@ -1902,8 +1901,6 @@ static int __init thermal_init(void)
goto unregister_governors;
}
- thermal_class_unavailable = false;
-
return 0;
unregister_governors:
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 0/4] thermal/core: Decouple release paths for tz and cdev
2026-05-08 18:05 [PATCH 0/4] thermal/core: Decouple release paths for tz and cdev Daniel Lezcano
` (3 preceding siblings ...)
2026-05-08 18:05 ` [PATCH 4/4] thermal/core: Use the thermal class pointer as init guard Daniel Lezcano
@ 2026-05-08 18:10 ` Daniel Lezcano
2026-05-13 14:22 ` Daniel Lezcano
4 siblings, 1 reply; 18+ messages in thread
From: Daniel Lezcano @ 2026-05-08 18:10 UTC (permalink / raw)
To: lukasz.luba, rafael; +Cc: rui.zhang, linux-pm, linux-kernel
On 5/8/26 20:05, Daniel Lezcano wrote:
> This series cleans up the lifetime handling of thermal devices.
>
> Currently, the thermal class release callback handles both thermal
> zones and cooling devices by checking the device name prefix. This
> approach is fragile and mixes responsibilities across different object
> types.
>
> The first two patches introduce dedicated struct device release
> callbacks for thermal zones and cooling devices. This removes the need
> to rely on device names and keeps the lifetime management local to
> each object.
>
> The last two patches convert the thermal class to a dynamically
> allocated object and simplify the initialization logic by using the
> class pointer itself as a guard instead of a separate boolean flag.
>
> Overall, this results in a clearer separation of responsibilities and
> more robust lifetime management aligned with the device model.
>
> No functional change intended.
Unless I’m mistaken, the patch sent to split the cooling device
registration is correct with this cleanup.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/4] thermal/core: Allocate the thermal class dynamically
2026-05-08 18:05 ` [PATCH 3/4] thermal/core: Allocate the thermal class dynamically Daniel Lezcano
@ 2026-05-08 18:24 ` Rafael J. Wysocki
2026-05-08 19:22 ` Daniel Lezcano
2026-05-13 15:03 ` Lukasz Luba
1 sibling, 1 reply; 18+ messages in thread
From: Rafael J. Wysocki @ 2026-05-08 18:24 UTC (permalink / raw)
To: Daniel Lezcano; +Cc: lukasz.luba, rafael, rui.zhang, linux-pm, linux-kernel
On Fri, May 8, 2026 at 8:05 PM Daniel Lezcano
<daniel.lezcano@oss.qualcomm.com> wrote:
>
> Use class_create() instead of a statically allocated struct class.
>
> This allows the thermal class to be managed through a dynamically
> allocated class object and avoids keeping a static class instance
> around.
I changed it the other way around during the last cycle, so is it
really worth changing again?
> Signed-off-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
> ---
> drivers/thermal/thermal_core.c | 15 ++++++++-------
> 1 file changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
> index a79fc4cdb078..748ab76823a3 100644
> --- a/drivers/thermal/thermal_core.c
> +++ b/drivers/thermal/thermal_core.c
> @@ -949,9 +949,7 @@ static void thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz,
> kfree(pos);
> }
>
> -static const struct class thermal_class = {
> - .name = "thermal",
> -};
> +static struct class *thermal_class;
> static bool thermal_class_unavailable __ro_after_init = true;
>
> static inline
> @@ -1078,7 +1076,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->device.release = thermal_cdev_release;
> cdev->devdata = devdata;
>
> @@ -1574,7 +1572,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->device.release = thermal_zone_device_release;
> tz->devdata = devdata;
> tz->num_trips = num_trips;
> @@ -1898,15 +1896,18 @@ static int __init thermal_init(void)
> if (result)
> goto destroy_workqueue;
>
> - result = class_register(&thermal_class);
> - if (result)
> + thermal_class = class_create("thermal");
> + if (IS_ERR(thermal_class)) {
> + result = PTR_ERR(thermal_class);
> goto unregister_governors;
> + }
>
> thermal_class_unavailable = false;
>
> return 0;
>
> unregister_governors:
> + thermal_class = NULL;
> thermal_unregister_governors();
> destroy_workqueue:
> destroy_workqueue(thermal_wq);
> --
> 2.43.0
>
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/4] thermal/core: Allocate the thermal class dynamically
2026-05-08 18:24 ` Rafael J. Wysocki
@ 2026-05-08 19:22 ` Daniel Lezcano
2026-05-08 19:26 ` Rafael J. Wysocki
0 siblings, 1 reply; 18+ messages in thread
From: Daniel Lezcano @ 2026-05-08 19:22 UTC (permalink / raw)
To: Rafael J. Wysocki; +Cc: lukasz.luba, rui.zhang, linux-pm, linux-kernel
On 5/8/26 20:24, Rafael J. Wysocki wrote:
> On Fri, May 8, 2026 at 8:05 PM Daniel Lezcano
> <daniel.lezcano@oss.qualcomm.com> wrote:
>>
>> Use class_create() instead of a statically allocated struct class.
>>
>> This allows the thermal class to be managed through a dynamically
>> allocated class object and avoids keeping a static class instance
>> around.
>
> I changed it the other way around during the last cycle, so is it
> really worth changing again?
Yes, I think it is because it does not reintroduce this change:
- thermal_class = kzalloc_obj(*thermal_class);
- if (!thermal_class) {
- result = -ENOMEM;
+ result = class_register(&thermal_class);
+ if (result)
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;
- }
It is replaced by thermal_create("thermal") which allocates and
registers the class and we get rid of two global variables. But up to you.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/4] thermal/core: Allocate the thermal class dynamically
2026-05-08 19:22 ` Daniel Lezcano
@ 2026-05-08 19:26 ` Rafael J. Wysocki
2026-05-08 19:28 ` Daniel Lezcano
0 siblings, 1 reply; 18+ messages in thread
From: Rafael J. Wysocki @ 2026-05-08 19:26 UTC (permalink / raw)
To: Daniel Lezcano
Cc: Rafael J. Wysocki, lukasz.luba, rui.zhang, linux-pm, linux-kernel
On Fri, May 8, 2026 at 9:22 PM Daniel Lezcano
<daniel.lezcano@oss.qualcomm.com> wrote:
>
> On 5/8/26 20:24, Rafael J. Wysocki wrote:
> > On Fri, May 8, 2026 at 8:05 PM Daniel Lezcano
> > <daniel.lezcano@oss.qualcomm.com> wrote:
> >>
> >> Use class_create() instead of a statically allocated struct class.
> >>
> >> This allows the thermal class to be managed through a dynamically
> >> allocated class object and avoids keeping a static class instance
> >> around.
> >
> > I changed it the other way around during the last cycle, so is it
> > really worth changing again?
>
> Yes, I think it is because it does not reintroduce this change:
>
> - thermal_class = kzalloc_obj(*thermal_class);
> - if (!thermal_class) {
> - result = -ENOMEM;
> + result = class_register(&thermal_class);
> + if (result)
> 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;
> - }
>
> It is replaced by thermal_create("thermal") which allocates and
> registers the class and we get rid of two global variables. But up to you.
Fair enough.
I'll queue up these changes for 7.2 early next week.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/4] thermal/core: Allocate the thermal class dynamically
2026-05-08 19:26 ` Rafael J. Wysocki
@ 2026-05-08 19:28 ` Daniel Lezcano
0 siblings, 0 replies; 18+ messages in thread
From: Daniel Lezcano @ 2026-05-08 19:28 UTC (permalink / raw)
To: Rafael J. Wysocki; +Cc: lukasz.luba, rui.zhang, linux-pm, linux-kernel
On 5/8/26 21:26, Rafael J. Wysocki wrote:
> On Fri, May 8, 2026 at 9:22 PM Daniel Lezcano
> <daniel.lezcano@oss.qualcomm.com> wrote:
>>
>> On 5/8/26 20:24, Rafael J. Wysocki wrote:
>>> On Fri, May 8, 2026 at 8:05 PM Daniel Lezcano
>>> <daniel.lezcano@oss.qualcomm.com> wrote:
>>>>
>>>> Use class_create() instead of a statically allocated struct class.
>>>>
>>>> This allows the thermal class to be managed through a dynamically
>>>> allocated class object and avoids keeping a static class instance
>>>> around.
>>>
>>> I changed it the other way around during the last cycle, so is it
>>> really worth changing again?
>>
>> Yes, I think it is because it does not reintroduce this change:
>>
>> - thermal_class = kzalloc_obj(*thermal_class);
>> - if (!thermal_class) {
>> - result = -ENOMEM;
>> + result = class_register(&thermal_class);
>> + if (result)
>> 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;
>> - }
>>
>> It is replaced by thermal_create("thermal") which allocates and
>> registers the class and we get rid of two global variables. But up to you.
>
> Fair enough.
>
> I'll queue up these changes for 7.2 early next week.
Thanks
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 0/4] thermal/core: Decouple release paths for tz and cdev
2026-05-08 18:10 ` [PATCH 0/4] thermal/core: Decouple release paths for tz and cdev Daniel Lezcano
@ 2026-05-13 14:22 ` Daniel Lezcano
2026-05-13 15:06 ` Rafael J. Wysocki
0 siblings, 1 reply; 18+ messages in thread
From: Daniel Lezcano @ 2026-05-13 14:22 UTC (permalink / raw)
To: lukasz.luba, rafael; +Cc: rui.zhang, linux-pm, linux-kernel
Hi Rafael,
On 5/8/26 20:10, Daniel Lezcano wrote:
> On 5/8/26 20:05, Daniel Lezcano wrote:
>> This series cleans up the lifetime handling of thermal devices.
>>
>> Currently, the thermal class release callback handles both thermal
>> zones and cooling devices by checking the device name prefix. This
>> approach is fragile and mixes responsibilities across different object
>> types.
>>
>> The first two patches introduce dedicated struct device release
>> callbacks for thermal zones and cooling devices. This removes the need
>> to rely on device names and keeps the lifetime management local to
>> each object.
>>
>> The last two patches convert the thermal class to a dynamically
>> allocated object and simplify the initialization logic by using the
>> class pointer itself as a guard instead of a separate boolean flag.
>>
>> Overall, this results in a clearer separation of responsibilities and
>> more robust lifetime management aligned with the device model.
>>
>> No functional change intended.
> Unless I’m mistaken, the patch sent to split the cooling device
> registration is correct with this cleanup.
Were you able to apply the patch splitting the cooling device
registration on top of this series ?
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/4] thermal/core: Add dedicated release callback for cooling devices
2026-05-08 18:05 ` [PATCH 1/4] thermal/core: Add dedicated release callback for cooling devices Daniel Lezcano
@ 2026-05-13 15:02 ` Lukasz Luba
0 siblings, 0 replies; 18+ messages in thread
From: Lukasz Luba @ 2026-05-13 15:02 UTC (permalink / raw)
To: Daniel Lezcano; +Cc: rui.zhang, linux-pm, linux-kernel, rafael
Hi Daniel
On 5/8/26 19:05, Daniel Lezcano wrote:
> The thermal class release callback currently handles both thermal
> zones and cooling devices by checking the device name prefix.
>
> Move the cooling device cleanup to a dedicated struct device release
> callback. This avoids relying on device names to select the release
> path and keeps the cooling device lifetime handling local to the
> cooling device object.
>
> Signed-off-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
> ---
> drivers/thermal/thermal_core.c | 19 +++++++++++--------
> 1 file changed, 11 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
> index 2f4e2dc46b8f..cf5d4a9c11fe 100644
> --- a/drivers/thermal/thermal_core.c
> +++ b/drivers/thermal/thermal_core.c
> @@ -952,7 +952,6 @@ static void thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz,
> static void thermal_release(struct device *dev)
> {
> struct thermal_zone_device *tz;
> - struct thermal_cooling_device *cdev;
>
> if (!strncmp(dev_name(dev), "thermal_zone",
> sizeof("thermal_zone") - 1)) {
> @@ -962,13 +961,6 @@ static void thermal_release(struct device *dev)
> ida_destroy(&tz->ida);
> mutex_destroy(&tz->lock);
> complete(&tz->removal);
> - } else if (!strncmp(dev_name(dev), "cooling_device",
> - sizeof("cooling_device") - 1)) {
> - cdev = to_cooling_device(dev);
> - thermal_cooling_device_destroy_sysfs(cdev);
> - kfree_const(cdev->type);
> - ida_free(&thermal_cdev_ida, cdev->id);
> - kfree(cdev);
> }
> }
>
> @@ -1040,6 +1032,16 @@ static void thermal_cooling_device_init_complete(struct thermal_cooling_device *
> thermal_zone_cdev_bind(tz, cdev);
> }
>
> +static void thermal_cdev_release(struct device *dev)
> +{
> + struct thermal_cooling_device *cdev = to_cooling_device(dev);
> +
> + thermal_cooling_device_destroy_sysfs(cdev);
> + kfree_const(cdev->type);
> + ida_free(&thermal_cdev_ida, cdev->id);
> + kfree(cdev);
> +}
> +
> /**
> * __thermal_cooling_device_register() - register a new thermal cooling device
> * @np: a pointer to a device tree node.
> @@ -1093,6 +1095,7 @@ __thermal_cooling_device_register(struct device_node *np,
> cdev->ops = ops;
> cdev->updated = false;
> cdev->device.class = &thermal_class;
> + cdev->device.release = thermal_cdev_release;
> cdev->devdata = devdata;
>
> ret = cdev->ops->get_max_state(cdev, &cdev->max_state);
I hope it's not too late to the party...
This looks good, we avoid the problem we discussed earlier.
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
The whole patch set makes the things more clean.
It should be a good foundation for your next changes.
Thanks Daniel!
Regards,
Lukasz
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/4] thermal/core: Add dedicated release callback for thermal zones
2026-05-08 18:05 ` [PATCH 2/4] thermal/core: Add dedicated release callback for thermal zones Daniel Lezcano
@ 2026-05-13 15:02 ` Lukasz Luba
0 siblings, 0 replies; 18+ messages in thread
From: Lukasz Luba @ 2026-05-13 15:02 UTC (permalink / raw)
To: Daniel Lezcano; +Cc: rui.zhang, linux-pm, linux-kernel, rafael
On 5/8/26 19:05, Daniel Lezcano wrote:
> The thermal class release callback currently handles thermal zone
> cleanup by checking the device name prefix.
>
> Move the thermal zone cleanup to a dedicated struct device release
> callback. This avoids relying on device names to select the release
> path and keeps the thermal zone lifetime handling local to the thermal
> zone object.
>
> Signed-off-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
> ---
> drivers/thermal/thermal_core.c | 28 ++++++++++++----------------
> 1 file changed, 12 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
> index cf5d4a9c11fe..a79fc4cdb078 100644
> --- a/drivers/thermal/thermal_core.c
> +++ b/drivers/thermal/thermal_core.c
> @@ -949,24 +949,8 @@ static void thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz,
> kfree(pos);
> }
>
> -static void thermal_release(struct device *dev)
> -{
> - struct thermal_zone_device *tz;
> -
> - if (!strncmp(dev_name(dev), "thermal_zone",
> - 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);
> - }
> -}
> -
> static const struct class thermal_class = {
> .name = "thermal",
> - .dev_release = thermal_release,
> };
> static bool thermal_class_unavailable __ro_after_init = true;
>
> @@ -1473,6 +1457,17 @@ static void thermal_zone_init_complete(struct thermal_zone_device *tz)
> __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
> }
>
> +static void thermal_zone_device_release(struct device *dev)
> +{
> + struct thermal_zone_device *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);
> +}
> +
> /**
> * thermal_zone_device_register_with_trips() - register a new thermal zone device
> * @type: the thermal zone device type
> @@ -1580,6 +1575,7 @@ thermal_zone_device_register_with_trips(const char *type,
> tz->ops.critical = thermal_zone_device_critical;
>
> tz->device.class = &thermal_class;
> + tz->device.release = thermal_zone_device_release;
> tz->devdata = devdata;
> tz->num_trips = num_trips;
> for_each_trip_desc(tz, td) {
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/4] thermal/core: Allocate the thermal class dynamically
2026-05-08 18:05 ` [PATCH 3/4] thermal/core: Allocate the thermal class dynamically Daniel Lezcano
2026-05-08 18:24 ` Rafael J. Wysocki
@ 2026-05-13 15:03 ` Lukasz Luba
1 sibling, 0 replies; 18+ messages in thread
From: Lukasz Luba @ 2026-05-13 15:03 UTC (permalink / raw)
To: Daniel Lezcano; +Cc: rui.zhang, linux-pm, linux-kernel, rafael
On 5/8/26 19:05, Daniel Lezcano wrote:
> Use class_create() instead of a statically allocated struct class.
>
> This allows the thermal class to be managed through a dynamically
> allocated class object and avoids keeping a static class instance
> around.
>
> Signed-off-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
> ---
> drivers/thermal/thermal_core.c | 15 ++++++++-------
> 1 file changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
> index a79fc4cdb078..748ab76823a3 100644
> --- a/drivers/thermal/thermal_core.c
> +++ b/drivers/thermal/thermal_core.c
> @@ -949,9 +949,7 @@ static void thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz,
> kfree(pos);
> }
>
> -static const struct class thermal_class = {
> - .name = "thermal",
> -};
> +static struct class *thermal_class;
> static bool thermal_class_unavailable __ro_after_init = true;
>
> static inline
> @@ -1078,7 +1076,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->device.release = thermal_cdev_release;
> cdev->devdata = devdata;
>
> @@ -1574,7 +1572,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->device.release = thermal_zone_device_release;
> tz->devdata = devdata;
> tz->num_trips = num_trips;
> @@ -1898,15 +1896,18 @@ static int __init thermal_init(void)
> if (result)
> goto destroy_workqueue;
>
> - result = class_register(&thermal_class);
> - if (result)
> + thermal_class = class_create("thermal");
> + if (IS_ERR(thermal_class)) {
> + result = PTR_ERR(thermal_class);
> goto unregister_governors;
> + }
>
> thermal_class_unavailable = false;
>
> return 0;
>
> unregister_governors:
> + thermal_class = NULL;
> thermal_unregister_governors();
> destroy_workqueue:
> destroy_workqueue(thermal_wq);
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] thermal/core: Use the thermal class pointer as init guard
2026-05-08 18:05 ` [PATCH 4/4] thermal/core: Use the thermal class pointer as init guard Daniel Lezcano
@ 2026-05-13 15:03 ` Lukasz Luba
0 siblings, 0 replies; 18+ messages in thread
From: Lukasz Luba @ 2026-05-13 15:03 UTC (permalink / raw)
To: Daniel Lezcano; +Cc: rui.zhang, linux-pm, linux-kernel, rafael
On 5/8/26 19:05, Daniel Lezcano wrote:
> The thermal class is now dynamically allocated and stored as a
> pointer.
>
> Use the thermal_class pointer itself to check whether the thermal
> class has been created instead of keeping a separate
> thermal_class_unavailable flag.
>
> Signed-off-by: Daniel Lezcano <daniel.lezcano@oss.qualcomm.com>
> ---
> drivers/thermal/thermal_core.c | 11 ++++-------
> 1 file changed, 4 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
> index 748ab76823a3..81f6bbaded65 100644
> --- a/drivers/thermal/thermal_core.c
> +++ b/drivers/thermal/thermal_core.c
> @@ -950,7 +950,6 @@ static void thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz,
> }
>
> static struct class *thermal_class;
> -static bool thermal_class_unavailable __ro_after_init = true;
>
> static inline
> void print_bind_err_msg(struct thermal_zone_device *tz,
> @@ -1053,7 +1052,7 @@ __thermal_cooling_device_register(struct device_node *np,
> !ops->set_cur_state)
> return ERR_PTR(-EINVAL);
>
> - if (thermal_class_unavailable)
> + if (!thermal_class)
> return ERR_PTR(-ENODEV);
>
> cdev = kzalloc_obj(*cdev);
> @@ -1536,7 +1535,7 @@ thermal_zone_device_register_with_trips(const char *type,
> if (polling_delay && passive_delay > polling_delay)
> return ERR_PTR(-EINVAL);
>
> - if (thermal_class_unavailable)
> + if (!thermal_class)
> return ERR_PTR(-ENODEV);
>
> tz = kzalloc_flex(*tz, trips, num_trips);
> @@ -1834,7 +1833,7 @@ static void __thermal_pm_prepare(void)
>
> void thermal_pm_prepare(void)
> {
> - if (thermal_class_unavailable)
> + if (!thermal_class)
> return;
>
> __thermal_pm_prepare();
> @@ -1865,7 +1864,7 @@ void thermal_pm_complete(void)
> {
> struct thermal_zone_device *tz;
>
> - if (thermal_class_unavailable)
> + if (!thermal_class)
> return;
>
> guard(mutex)(&thermal_list_lock);
> @@ -1902,8 +1901,6 @@ static int __init thermal_init(void)
> goto unregister_governors;
> }
>
> - thermal_class_unavailable = false;
> -
> return 0;
>
> unregister_governors:
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 0/4] thermal/core: Decouple release paths for tz and cdev
2026-05-13 14:22 ` Daniel Lezcano
@ 2026-05-13 15:06 ` Rafael J. Wysocki
2026-05-13 15:45 ` Lukasz Luba
0 siblings, 1 reply; 18+ messages in thread
From: Rafael J. Wysocki @ 2026-05-13 15:06 UTC (permalink / raw)
To: Daniel Lezcano; +Cc: lukasz.luba, rafael, rui.zhang, linux-pm, linux-kernel
On Wed, May 13, 2026 at 4:22 PM Daniel Lezcano
<daniel.lezcano@oss.qualcomm.com> wrote:
>
>
> Hi Rafael,
>
> On 5/8/26 20:10, Daniel Lezcano wrote:
> > On 5/8/26 20:05, Daniel Lezcano wrote:
> >> This series cleans up the lifetime handling of thermal devices.
> >>
> >> Currently, the thermal class release callback handles both thermal
> >> zones and cooling devices by checking the device name prefix. This
> >> approach is fragile and mixes responsibilities across different object
> >> types.
> >>
> >> The first two patches introduce dedicated struct device release
> >> callbacks for thermal zones and cooling devices. This removes the need
> >> to rely on device names and keeps the lifetime management local to
> >> each object.
> >>
> >> The last two patches convert the thermal class to a dynamically
> >> allocated object and simplify the initialization logic by using the
> >> class pointer itself as a guard instead of a separate boolean flag.
> >>
> >> Overall, this results in a clearer separation of responsibilities and
> >> more robust lifetime management aligned with the device model.
> >>
> >> No functional change intended.
> > Unless I’m mistaken, the patch sent to split the cooling device
> > registration is correct with this cleanup.
>
> Were you able to apply the patch splitting the cooling device
> registration on top of this series ?
I haven't tried that yet, but I'll do it later today.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 0/4] thermal/core: Decouple release paths for tz and cdev
2026-05-13 15:06 ` Rafael J. Wysocki
@ 2026-05-13 15:45 ` Lukasz Luba
2026-05-13 15:48 ` Daniel Lezcano
0 siblings, 1 reply; 18+ messages in thread
From: Lukasz Luba @ 2026-05-13 15:45 UTC (permalink / raw)
To: Rafael J. Wysocki, Daniel Lezcano; +Cc: rui.zhang, linux-pm, linux-kernel
On 5/13/26 16:06, Rafael J. Wysocki wrote:
> On Wed, May 13, 2026 at 4:22 PM Daniel Lezcano
> <daniel.lezcano@oss.qualcomm.com> wrote:
>>
>>
>> Hi Rafael,
>>
>> On 5/8/26 20:10, Daniel Lezcano wrote:
>>> On 5/8/26 20:05, Daniel Lezcano wrote:
>>>> This series cleans up the lifetime handling of thermal devices.
>>>>
>>>> Currently, the thermal class release callback handles both thermal
>>>> zones and cooling devices by checking the device name prefix. This
>>>> approach is fragile and mixes responsibilities across different object
>>>> types.
>>>>
>>>> The first two patches introduce dedicated struct device release
>>>> callbacks for thermal zones and cooling devices. This removes the need
>>>> to rely on device names and keeps the lifetime management local to
>>>> each object.
>>>>
>>>> The last two patches convert the thermal class to a dynamically
>>>> allocated object and simplify the initialization logic by using the
>>>> class pointer itself as a guard instead of a separate boolean flag.
>>>>
>>>> Overall, this results in a clearer separation of responsibilities and
>>>> more robust lifetime management aligned with the device model.
>>>>
>>>> No functional change intended.
>>> Unless I’m mistaken, the patch sent to split the cooling device
>>> registration is correct with this cleanup.
>>
>> Were you able to apply the patch splitting the cooling device
>> registration on top of this series ?
>
> I haven't tried that yet, but I'll do it later today.
Just to double check, we are talking about this patch (that we discussed
back then):
https://lore.kernel.org/lkml/20260505144447.2853933-1-daniel.lezcano@oss.qualcomm.com/
With the re-work done here, I can put my review tag into
that patch. The error handling paths there should be safe now.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 0/4] thermal/core: Decouple release paths for tz and cdev
2026-05-13 15:45 ` Lukasz Luba
@ 2026-05-13 15:48 ` Daniel Lezcano
0 siblings, 0 replies; 18+ messages in thread
From: Daniel Lezcano @ 2026-05-13 15:48 UTC (permalink / raw)
To: Lukasz Luba, Rafael J. Wysocki; +Cc: rui.zhang, linux-pm, linux-kernel
On 5/13/26 17:45, Lukasz Luba wrote:
>
>
> On 5/13/26 16:06, Rafael J. Wysocki wrote:
>> On Wed, May 13, 2026 at 4:22 PM Daniel Lezcano
>> <daniel.lezcano@oss.qualcomm.com> wrote:
>>>
>>>
>>> Hi Rafael,
>>>
>>> On 5/8/26 20:10, Daniel Lezcano wrote:
>>>> On 5/8/26 20:05, Daniel Lezcano wrote:
>>>>> This series cleans up the lifetime handling of thermal devices.
>>>>>
>>>>> Currently, the thermal class release callback handles both thermal
>>>>> zones and cooling devices by checking the device name prefix. This
>>>>> approach is fragile and mixes responsibilities across different object
>>>>> types.
>>>>>
>>>>> The first two patches introduce dedicated struct device release
>>>>> callbacks for thermal zones and cooling devices. This removes the need
>>>>> to rely on device names and keeps the lifetime management local to
>>>>> each object.
>>>>>
>>>>> The last two patches convert the thermal class to a dynamically
>>>>> allocated object and simplify the initialization logic by using the
>>>>> class pointer itself as a guard instead of a separate boolean flag.
>>>>>
>>>>> Overall, this results in a clearer separation of responsibilities and
>>>>> more robust lifetime management aligned with the device model.
>>>>>
>>>>> No functional change intended.
>>>> Unless I’m mistaken, the patch sent to split the cooling device
>>>> registration is correct with this cleanup.
>>>
>>> Were you able to apply the patch splitting the cooling device
>>> registration on top of this series ?
>>
>> I haven't tried that yet, but I'll do it later today.
>
> Just to double check, we are talking about this patch (that we discussed
> back then):
>
> https://lore.kernel.org/lkml/20260505144447.2853933-1-
> daniel.lezcano@oss.qualcomm.com/
Yes, I'm just wondering if it applies as is
> With the re-work done here, I can put my review tag into
> that patch. The error handling paths there should be safe now.
Great, thanks for your review
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2026-05-13 15:48 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-08 18:05 [PATCH 0/4] thermal/core: Decouple release paths for tz and cdev Daniel Lezcano
2026-05-08 18:05 ` [PATCH 1/4] thermal/core: Add dedicated release callback for cooling devices Daniel Lezcano
2026-05-13 15:02 ` Lukasz Luba
2026-05-08 18:05 ` [PATCH 2/4] thermal/core: Add dedicated release callback for thermal zones Daniel Lezcano
2026-05-13 15:02 ` Lukasz Luba
2026-05-08 18:05 ` [PATCH 3/4] thermal/core: Allocate the thermal class dynamically Daniel Lezcano
2026-05-08 18:24 ` Rafael J. Wysocki
2026-05-08 19:22 ` Daniel Lezcano
2026-05-08 19:26 ` Rafael J. Wysocki
2026-05-08 19:28 ` Daniel Lezcano
2026-05-13 15:03 ` Lukasz Luba
2026-05-08 18:05 ` [PATCH 4/4] thermal/core: Use the thermal class pointer as init guard Daniel Lezcano
2026-05-13 15:03 ` Lukasz Luba
2026-05-08 18:10 ` [PATCH 0/4] thermal/core: Decouple release paths for tz and cdev Daniel Lezcano
2026-05-13 14:22 ` Daniel Lezcano
2026-05-13 15:06 ` Rafael J. Wysocki
2026-05-13 15:45 ` Lukasz Luba
2026-05-13 15:48 ` Daniel Lezcano
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox