summaryrefslogtreecommitdiffstats
path: root/drivers/thermal
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2023-01-23 21:44:03 +0100
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2023-01-25 16:51:19 +0100
commit9e0a9be24bdd61a160631227ee995b579be566a5 (patch)
treef50e89f0baff57015e23a4e0af154bfb254b5abe /drivers/thermal
parent5b8de18ee9027c647db4c1905f7fd0550d17d67a (diff)
downloadlinux-stable-9e0a9be24bdd61a160631227ee995b579be566a5.tar.gz
linux-stable-9e0a9be24bdd61a160631227ee995b579be566a5.tar.bz2
linux-stable-9e0a9be24bdd61a160631227ee995b579be566a5.zip
thermal: Fail object registration if thermal class is not registered
If thermal_class is not registered with the driver core, there is no way to expose the interfaces used by the thermal control framework, so prevent thermal zones and cooling devices from being registered in that case by returning an error from object registration functions. For this purpose, use a thermal_class pointer that will be NULL if the class is not registered. To avoid wasting memory in that case, allocate the thermal class object dynamically and if it fails to register, free it and clear the thermal_class pointer to NULL. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Reviewed-by: Zhang Rui <rui.zhang@intel.com> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/thermal')
-rw-r--r--drivers/thermal/thermal_core.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 2f6ecb7be8de..0675df54c8e6 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -777,10 +777,7 @@ static void thermal_release(struct device *dev)
}
}
-static struct class thermal_class = {
- .name = "thermal",
- .dev_release = thermal_release,
-};
+static struct class *thermal_class;
static inline
void print_bind_err_msg(struct thermal_zone_device *tz,
@@ -883,6 +880,9 @@ __thermal_cooling_device_register(struct device_node *np,
!ops->set_cur_state)
return ERR_PTR(-EINVAL);
+ if (!thermal_class)
+ return ERR_PTR(-ENODEV);
+
cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
if (!cdev)
return ERR_PTR(-ENOMEM);
@@ -904,7 +904,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);
@@ -1256,6 +1256,9 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
if (num_trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp) && !trips)
return ERR_PTR(-EINVAL);
+ if (!thermal_class)
+ return ERR_PTR(-ENODEV);
+
tz = kzalloc(sizeof(*tz), GFP_KERNEL);
if (!tz)
return ERR_PTR(-ENOMEM);
@@ -1277,7 +1280,7 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
tz->ops = ops;
tz->tzp = tzp;
- tz->device.class = &thermal_class;
+ tz->device.class = thermal_class;
tz->devdata = devdata;
tz->trips = trips;
tz->num_trips = num_trips;
@@ -1522,9 +1525,21 @@ static int __init thermal_init(void)
if (result)
goto unregister_netlink;
- result = class_register(&thermal_class);
- if (result)
+ thermal_class = kzalloc(sizeof(*thermal_class), GFP_KERNEL);
+ 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;
goto unregister_governors;
+ }
result = register_pm_notifier(&thermal_pm_nb);
if (result)