thermal: core: Consolidate thermal zone locking in the exit path

In analogy with a previous change in the thermal zone initialization
path, to avoid acquiring the thermal zone lock and releasing it multiple
times back and forth unnecessarily, move all of the code running under
thermal_list_lock in thermal_zone_device_unregister() into a new
function called thermal_zone_exit() and make the latter acquire the
thermal zone lock only once and release it along with thermal_list_lock.

For this purpose, provide an "unlocked" variant of
thermal_zone_cdev_unbind() to be called by thermal_zone_exit() under the
thermal zone lock.

No intentional functional impact.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://patch.msgid.link/1963152.taCxCBeP46@rjwysocki.net
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
This commit is contained in:
Rafael J. Wysocki 2024-10-04 21:30:26 +02:00
parent 1dae3e70b4
commit fa4f9c9679

View File

@ -1268,15 +1268,21 @@ void thermal_cooling_device_update(struct thermal_cooling_device *cdev)
}
EXPORT_SYMBOL_GPL(thermal_cooling_device_update);
static void thermal_zone_cdev_unbind(struct thermal_zone_device *tz,
struct thermal_cooling_device *cdev)
static void __thermal_zone_cdev_unbind(struct thermal_zone_device *tz,
struct thermal_cooling_device *cdev)
{
struct thermal_trip_desc *td;
mutex_lock(&tz->lock);
for_each_trip_desc(tz, td)
thermal_unbind_cdev_from_trip(tz, &td->trip, cdev);
}
static void thermal_zone_cdev_unbind(struct thermal_zone_device *tz,
struct thermal_cooling_device *cdev)
{
mutex_lock(&tz->lock);
__thermal_zone_cdev_unbind(tz, cdev);
mutex_unlock(&tz->lock);
}
@ -1596,42 +1602,48 @@ struct device *thermal_zone_device(struct thermal_zone_device *tzd)
}
EXPORT_SYMBOL_GPL(thermal_zone_device);
static bool thermal_zone_exit(struct thermal_zone_device *tz)
{
struct thermal_cooling_device *cdev;
bool ret = true;
mutex_lock(&thermal_list_lock);
if (list_empty(&tz->node)) {
ret = false;
goto unlock;
}
mutex_lock(&tz->lock);
tz->state |= TZ_STATE_FLAG_EXIT;
list_del_init(&tz->node);
/* Unbind all cdevs associated with this thermal zone. */
list_for_each_entry(cdev, &thermal_cdev_list, node)
__thermal_zone_cdev_unbind(tz, cdev);
mutex_unlock(&tz->lock);
unlock:
mutex_unlock(&thermal_list_lock);
return ret;
}
/**
* thermal_zone_device_unregister - removes the registered thermal zone device
* @tz: the thermal zone device to remove
*/
void thermal_zone_device_unregister(struct thermal_zone_device *tz)
{
struct thermal_cooling_device *cdev;
struct thermal_zone_device *pos = NULL;
if (!tz)
return;
thermal_debug_tz_remove(tz);
mutex_lock(&thermal_list_lock);
list_for_each_entry(pos, &thermal_tz_list, node)
if (pos == tz)
break;
if (pos != tz) {
/* thermal zone device not found */
mutex_unlock(&thermal_list_lock);
if (!thermal_zone_exit(tz))
return;
}
mutex_lock(&tz->lock);
tz->state |= TZ_STATE_FLAG_EXIT;
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)
thermal_zone_cdev_unbind(tz, cdev);
mutex_unlock(&thermal_list_lock);
cancel_delayed_work_sync(&tz->poll_queue);