summaryrefslogtreecommitdiff
path: root/drivers/thermal/thermal_core.c
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@linaro.org>2023-04-04 10:51:37 +0300
committerDaniel Lezcano <daniel.lezcano@linaro.org>2023-04-07 19:36:28 +0300
commit3d439b1a2ad36c8b4ea151c8de25309d60d17407 (patch)
tree5fc9e9468c9bd6190ef32a5c32d6086bf9b3759c /drivers/thermal/thermal_core.c
parentac614a9b4c35bf766dec40d73cbbc7f37c1734f7 (diff)
downloadlinux-3d439b1a2ad36c8b4ea151c8de25309d60d17407.tar.xz
thermal/core: Alloc-copy-free the thermal zone parameters structure
The caller of the function thermal_zone_device_register_with_trips() can pass a thermal_zone_params structure parameter. This one is used by the thermal core code until the thermal zone is destroyed. That forces the caller, so the driver, to keep the pointer valid until it unregisters the thermal zone if we want to make the thermal zone device structure private the core code. As the thermal zone device structure would be private, the driver can not access to thermal zone device structure to retrieve the tzp field after it passed it to register the thermal zone. So instead of forcing the users of the function to deal with the tzp structure life cycle, make the usage easier by allocating our own thermal zone params, copying the parameter content and by freeing at unregister time. The user can then create the parameters on the stack, pass it to the registering function and forget about it. Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://lore.kernel.org/r/20230404075138.2914680-3-daniel.lezcano@linaro.org
Diffstat (limited to 'drivers/thermal/thermal_core.c')
-rw-r--r--drivers/thermal/thermal_core.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 237430f1b565..c5025aca22ee 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1256,13 +1256,21 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
if (!tz)
return ERR_PTR(-ENOMEM);
+ if (tzp) {
+ tz->tzp = kmemdup(tzp, sizeof(*tzp), GFP_KERNEL);
+ if (!tz->tzp) {
+ result = -ENOMEM;
+ goto free_tz;
+ }
+ }
+
INIT_LIST_HEAD(&tz->thermal_instances);
ida_init(&tz->ida);
mutex_init(&tz->lock);
id = ida_alloc(&thermal_tz_ida, GFP_KERNEL);
if (id < 0) {
result = id;
- goto free_tz;
+ goto free_tzp;
}
tz->id = id;
@@ -1272,7 +1280,6 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
ops->critical = thermal_zone_device_critical;
tz->ops = ops;
- tz->tzp = tzp;
tz->device.class = thermal_class;
tz->devdata = devdata;
tz->trips = trips;
@@ -1354,6 +1361,8 @@ release_device:
tz = NULL;
remove_id:
ida_free(&thermal_tz_ida, id);
+free_tzp:
+ kfree(tz->tzp);
free_tz:
kfree(tz);
return ERR_PTR(result);
@@ -1434,6 +1443,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
device_del(&tz->device);
mutex_unlock(&tz->lock);
+ kfree(tz->tzp);
+
put_device(&tz->device);
thermal_notify_tz_delete(tz_id);