Message ID | 2258035.iZASKD2KPV@kreacher |
---|---|
State | New |
Headers | show |
Series | thermal: core: Remove thermal zones during unregistration | expand |
On 08/12/2023 20:20, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > In order to avoid running __thermal_zone_device_update() for thermal > zones going away, the thermal zone lock is held around device_del() > in thermal_zone_device_unregister() and thermal_zone_device_update() > passes the given thermal zone device to device_is_registered(). > This allows thermal_zone_device_update() to skip the > __thermal_zone_device_update() if device_del() has already run for > the thermal zone at hand. > > However, instead of looking at driver core internals, the thermal > subsystem may as well rely on its own data structures for this > purpose. Namely, if the thermal zone is not present in > thermal_tz_list, it can be regarded as unavailable, which in fact is > already the case in thermal_zone_device_unregister(). Accordingly, > the device_is_registered() check in thermal_zone_device_update() can > be replaced with checking whether or not the node list_head in struct > thermal_zone_device is empty, in which case it is not there in > thermal_tz_list. > > To make this work, though, it is necessary to initialize tz->node > in thermal_zone_device_register_with_trips() before registering the > thermal zone device and it needs to be added to thermal_tz_list and > deleted from it under its zone lock. > > After the above modifications, the zone lock does not need to be > held around device_del() in thermal_zone_device_unregister() any more. > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > --- Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Index: linux-pm/drivers/thermal/thermal_core.c =================================================================== --- linux-pm.orig/drivers/thermal/thermal_core.c +++ linux-pm/drivers/thermal/thermal_core.c @@ -505,11 +505,16 @@ int thermal_zone_device_is_enabled(struc return tz->mode == THERMAL_DEVICE_ENABLED; } +static bool thermal_zone_is_present(struct thermal_zone_device *tz) +{ + return !list_empty(&tz->node); +} + void thermal_zone_device_update(struct thermal_zone_device *tz, enum thermal_notify_event event) { mutex_lock(&tz->lock); - if (device_is_registered(&tz->device)) + if (thermal_zone_is_present(tz)) __thermal_zone_device_update(tz, event); mutex_unlock(&tz->lock); } @@ -1304,6 +1309,7 @@ thermal_zone_device_register_with_trips( } INIT_LIST_HEAD(&tz->thermal_instances); + INIT_LIST_HEAD(&tz->node); ida_init(&tz->ida); mutex_init(&tz->lock); init_completion(&tz->removal); @@ -1369,7 +1375,9 @@ thermal_zone_device_register_with_trips( } mutex_lock(&thermal_list_lock); + mutex_lock(&tz->lock); list_add_tail(&tz->node, &thermal_tz_list); + mutex_unlock(&tz->lock); mutex_unlock(&thermal_list_lock); /* Bind cooling devices for this zone */ @@ -1460,7 +1468,10 @@ void thermal_zone_device_unregister(stru mutex_unlock(&thermal_list_lock); return; } + + mutex_lock(&tz->lock); list_del(&tz->node); + mutex_unlock(&tz->lock); /* Unbind all cdevs associated with 'this' thermal zone */ list_for_each_entry(cdev, &thermal_cdev_list, node) @@ -1477,9 +1488,7 @@ void thermal_zone_device_unregister(stru ida_free(&thermal_tz_ida, tz->id); ida_destroy(&tz->ida); - mutex_lock(&tz->lock); device_del(&tz->device); - mutex_unlock(&tz->lock); kfree(tz->tzp);