Message ID | 1883976.tdWV9SEqCh@kreacher |
---|---|
State | Superseded |
Headers | show |
Series | thermal: Store trips table and ops in thermal_zone_device | expand |
On 14/02/2024 13:28, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > The current code expects thermal zone creators to pass a pointer to a > writable trips table to thermal_zone_device_register_with_trips() and > that trips table is then used by the thermal core going forward. > > Consequently, the callers of thermal_zone_device_register_with_trips() > are required to hold on to the trips table passed to it until the given > thermal zone is unregistered, at which point the trips table can be > freed, but at the same time they are not expected to access that table > directly. This is both error prone and confusing. > > To address it, turn the trips table pointer in struct thermal_zone_device > into a flex array (counted by its num_trips field), allocate it during > thermal zone device allocation and copy the contents of the trips table > supplied by the zone creator (which can be const now) into it, which > will allow the callers of thermal_zone_device_register_with_trips() to > drop their trip tables right after the zone registration. > > This requires the imx thermal driver to be adjusted to store the new > temperature in its internal trips table in imx_set_trip_temp(), because > it will be separate from the core's trips table now and it has to be > explicitly kept in sync with the latter. > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > Reviewed-by: Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com> Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
On Thu, Feb 22, 2024 at 2:38 PM Daniel Lezcano <daniel.lezcano@linaro.org> wrote: > > On 22/02/2024 14:10, Rafael J. Wysocki wrote: > > [ ... ] > > > Index: linux-pm/drivers/thermal/thermal_of.c > > =================================================================== > > --- linux-pm.orig/drivers/thermal/thermal_of.c > > +++ linux-pm/drivers/thermal/thermal_of.c > > @@ -440,12 +440,10 @@ static int thermal_of_unbind(struct ther > > */ > > static void thermal_of_zone_unregister(struct thermal_zone_device *tz) > > { > > - struct thermal_trip *trips = tz->trips; > > struct thermal_zone_device_ops *ops = tz->ops; > > > > thermal_zone_device_disable(tz); > > thermal_zone_device_unregister(tz); > > - kfree(trips); > > thermal_of_zone_register() must free the allocated trip points after > registering the thermal zone. > > > kfree(ops); > > } Good point. Let me send another update, then.
On 22/02/2024 14:52, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > The current code expects thermal zone creators to pass a pointer to a > writable trips table to thermal_zone_device_register_with_trips() and > that trips table is then used by the thermal core going forward. > > Consequently, the callers of thermal_zone_device_register_with_trips() > are required to hold on to the trips table passed to it until the given > thermal zone is unregistered, at which point the trips table can be > freed, but at the same time they are not expected to access that table > directly. This is both error prone and confusing. > > To address it, turn the trips table pointer in struct thermal_zone_device > into a flex array (counted by its num_trips field), allocate it during > thermal zone device allocation and copy the contents of the trips table > supplied by the zone creator (which can be const now) into it, which > will allow the callers of thermal_zone_device_register_with_trips() to > drop their trip tables right after the zone registration. > > This requires the imx thermal driver to be adjusted to store the new > temperature in its internal trips table in imx_set_trip_temp(), because > it will be separate from the core's trips table now and it has to be > explicitly kept in sync with the latter. > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > Reviewed-by: Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com> > Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org> > --- > > v2.1 -> v2.2: > * Add missing kfree(trips) to thermal_of_zone_register() (Daniel). OK for me
Index: linux-pm/include/linux/thermal.h =================================================================== --- linux-pm.orig/include/linux/thermal.h +++ linux-pm/include/linux/thermal.h @@ -137,7 +137,6 @@ struct thermal_cooling_device { * @trip_hyst_attrs: attributes for trip points for sysfs: trip hysteresis * @mode: current mode of this thermal zone * @devdata: private pointer for device private data - * @trips: an array of struct thermal_trip * @num_trips: number of trip points the thermal zone supports * @passive_delay_jiffies: number of jiffies to wait between polls when * performing passive cooling. @@ -167,6 +166,7 @@ struct thermal_cooling_device { * @poll_queue: delayed work for polling * @notify_event: Last notification event * @suspended: thermal zone suspend indicator + * @trips: array of struct thermal_trip objects */ struct thermal_zone_device { int id; @@ -179,7 +179,6 @@ struct thermal_zone_device { struct thermal_attr *trip_hyst_attrs; enum thermal_device_mode mode; void *devdata; - struct thermal_trip *trips; int num_trips; unsigned long passive_delay_jiffies; unsigned long polling_delay_jiffies; @@ -200,10 +199,11 @@ struct thermal_zone_device { struct list_head node; struct delayed_work poll_queue; enum thermal_notify_event notify_event; + bool suspended; #ifdef CONFIG_THERMAL_DEBUGFS struct thermal_debugfs *debugfs; #endif - bool suspended; + struct thermal_trip trips[] __counted_by(num_trips); }; /** @@ -322,7 +322,7 @@ int thermal_zone_get_crit_temp(struct th #ifdef CONFIG_THERMAL struct thermal_zone_device *thermal_zone_device_register_with_trips( const char *type, - struct thermal_trip *trips, + const struct thermal_trip *trips, int num_trips, void *devdata, struct thermal_zone_device_ops *ops, const struct thermal_zone_params *tzp, @@ -381,7 +381,7 @@ void thermal_zone_device_critical(struct #else static inline struct thermal_zone_device *thermal_zone_device_register_with_trips( const char *type, - struct thermal_trip *trips, + const struct thermal_trip *trips, int num_trips, void *devdata, struct thermal_zone_device_ops *ops, const struct thermal_zone_params *tzp, Index: linux-pm/drivers/thermal/thermal_core.c =================================================================== --- linux-pm.orig/drivers/thermal/thermal_core.c +++ linux-pm/drivers/thermal/thermal_core.c @@ -1227,9 +1227,6 @@ int thermal_zone_get_crit_temp(struct th if (tz->ops->get_crit_temp) return tz->ops->get_crit_temp(tz, temp); - if (!tz->trips) - return -EINVAL; - mutex_lock(&tz->lock); for (i = 0; i < tz->num_trips; i++) { @@ -1271,10 +1268,12 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_crit_ * IS_ERR*() helpers. */ struct thermal_zone_device * -thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *trips, int num_trips, - void *devdata, struct thermal_zone_device_ops *ops, - const struct thermal_zone_params *tzp, int passive_delay, - int polling_delay) +thermal_zone_device_register_with_trips(const char *type, + const struct thermal_trip *trips, + int num_trips, void *devdata, + struct thermal_zone_device_ops *ops, + const struct thermal_zone_params *tzp, + int passive_delay, int polling_delay) { struct thermal_zone_device *tz; int id; @@ -1308,7 +1307,7 @@ thermal_zone_device_register_with_trips( if (!thermal_class) return ERR_PTR(-ENODEV); - tz = kzalloc(sizeof(*tz), GFP_KERNEL); + tz = kzalloc(struct_size(tz, trips, num_trips), GFP_KERNEL); if (!tz) return ERR_PTR(-ENOMEM); @@ -1340,7 +1339,7 @@ thermal_zone_device_register_with_trips( tz->ops = ops; tz->device.class = thermal_class; tz->devdata = devdata; - tz->trips = trips; + memcpy(tz->trips, trips, num_trips * sizeof(*trips)); tz->num_trips = num_trips; thermal_set_delay_jiffies(&tz->passive_delay_jiffies, passive_delay); Index: linux-pm/drivers/thermal/imx_thermal.c =================================================================== --- linux-pm.orig/drivers/thermal/imx_thermal.c +++ linux-pm/drivers/thermal/imx_thermal.c @@ -355,6 +355,7 @@ static int imx_set_trip_temp(struct ther return -EINVAL; imx_set_alarm_temp(data, temp); + trips[IMX_TRIP_PASSIVE].temperature = temp; pm_runtime_put(data->dev); Index: linux-pm/drivers/thermal/thermal_trip.c =================================================================== --- linux-pm.orig/drivers/thermal/thermal_trip.c +++ linux-pm/drivers/thermal/thermal_trip.c @@ -122,7 +122,7 @@ void __thermal_zone_set_trips(struct the int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id, struct thermal_trip *trip) { - if (!tz || !tz->trips || trip_id < 0 || trip_id >= tz->num_trips || !trip) + if (!tz || trip_id < 0 || trip_id >= tz->num_trips || !trip) return -EINVAL; *trip = tz->trips[trip_id];