* [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* 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
* [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* 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
* [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* 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 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
* [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 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-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 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 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