Skip to content

Commit a930da9

Browse files
committed
thermal/core: Move the mutex inside the thermal_zone_device_update() function
All the different calls inside the thermal_zone_device_update() function take the mutex. The previous changes move the mutex out of the different functions, like the throttling ops. Now that the mutexes are all at the same level in the call stack for the thermal_zone_device_update() function, they can be moved inside this one. That has the benefit of: 1. Simplify the code by not having a plethora of places where the lock is taken 2. Probably closes more race windows because releasing the lock from one line to another can give the opportunity to the thermal zone to change its state in the meantime. For example, the thermal zone can be enabled right after checking it is disabled. Signed-off-by: Daniel Lezcano <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 670a5e3 commit a930da9

File tree

4 files changed

+61
-52
lines changed

4 files changed

+61
-52
lines changed

drivers/thermal/thermal_core.c

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -297,24 +297,18 @@ static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
297297

298298
static void monitor_thermal_zone(struct thermal_zone_device *tz)
299299
{
300-
mutex_lock(&tz->lock);
301-
302300
if (tz->mode != THERMAL_DEVICE_ENABLED)
303301
thermal_zone_device_set_polling(tz, 0);
304302
else if (tz->passive)
305303
thermal_zone_device_set_polling(tz, tz->passive_delay_jiffies);
306304
else if (tz->polling_delay_jiffies)
307305
thermal_zone_device_set_polling(tz, tz->polling_delay_jiffies);
308-
309-
mutex_unlock(&tz->lock);
310306
}
311307

312308
static void handle_non_critical_trips(struct thermal_zone_device *tz, int trip)
313309
{
314-
mutex_lock(&tz->lock);
315310
tz->governor ? tz->governor->throttle(tz, trip) :
316311
def_governor->throttle(tz, trip);
317-
mutex_unlock(&tz->lock);
318312
}
319313

320314
void thermal_zone_device_critical(struct thermal_zone_device *tz)
@@ -382,7 +376,7 @@ static void update_temperature(struct thermal_zone_device *tz)
382376
{
383377
int temp, ret;
384378

385-
ret = thermal_zone_get_temp(tz, &temp);
379+
ret = __thermal_zone_get_temp(tz, &temp);
386380
if (ret) {
387381
if (ret != -EAGAIN)
388382
dev_warn(&tz->device,
@@ -391,10 +385,8 @@ static void update_temperature(struct thermal_zone_device *tz)
391385
return;
392386
}
393387

394-
mutex_lock(&tz->lock);
395388
tz->last_temperature = tz->temperature;
396389
tz->temperature = temp;
397-
mutex_unlock(&tz->lock);
398390

399391
trace_thermal_temperature(tz);
400392

@@ -457,42 +449,40 @@ EXPORT_SYMBOL_GPL(thermal_zone_device_disable);
457449

458450
int thermal_zone_device_is_enabled(struct thermal_zone_device *tz)
459451
{
460-
enum thermal_device_mode mode;
461-
462-
mutex_lock(&tz->lock);
463-
464-
mode = tz->mode;
452+
lockdep_assert_held(&tz->lock);
465453

466-
mutex_unlock(&tz->lock);
467-
468-
return mode == THERMAL_DEVICE_ENABLED;
454+
return tz->mode == THERMAL_DEVICE_ENABLED;
469455
}
470456

471457
void thermal_zone_device_update(struct thermal_zone_device *tz,
472458
enum thermal_notify_event event)
473459
{
474460
int count;
475461

476-
if (!thermal_zone_device_is_enabled(tz))
477-
return;
478-
479462
if (atomic_read(&in_suspend))
480463
return;
481464

482465
if (WARN_ONCE(!tz->ops->get_temp, "'%s' must not be called without "
483466
"'get_temp' ops set\n", __func__))
484467
return;
485468

469+
mutex_lock(&tz->lock);
470+
471+
if (!thermal_zone_device_is_enabled(tz))
472+
goto out;
473+
486474
update_temperature(tz);
487475

488-
thermal_zone_set_trips(tz);
476+
__thermal_zone_set_trips(tz);
489477

490478
tz->notify_event = event;
491479

492480
for (count = 0; count < tz->num_trips; count++)
493481
handle_thermal_trip(tz, count);
494482

495483
monitor_thermal_zone(tz);
484+
out:
485+
mutex_unlock(&tz->lock);
496486
}
497487
EXPORT_SYMBOL_GPL(thermal_zone_device_update);
498488

drivers/thermal/thermal_core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ int thermal_build_list_of_policies(char *buf);
112112

113113
/* Helpers */
114114
void thermal_zone_set_trips(struct thermal_zone_device *tz);
115+
void __thermal_zone_set_trips(struct thermal_zone_device *tz);
116+
int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
115117

116118
/* sysfs I/F */
117119
int thermal_zone_create_device_groups(struct thermal_zone_device *, int);

drivers/thermal/thermal_helpers.c

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -64,27 +64,17 @@ get_thermal_instance(struct thermal_zone_device *tz,
6464
}
6565
EXPORT_SYMBOL(get_thermal_instance);
6666

67-
/**
68-
* thermal_zone_get_temp() - returns the temperature of a thermal zone
69-
* @tz: a valid pointer to a struct thermal_zone_device
70-
* @temp: a valid pointer to where to store the resulting temperature.
71-
*
72-
* When a valid thermal zone reference is passed, it will fetch its
73-
* temperature and fill @temp.
74-
*
75-
* Return: On success returns 0, an error code otherwise
76-
*/
77-
int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
67+
int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
7868
{
7969
int ret = -EINVAL;
8070
int count;
8171
int crit_temp = INT_MAX;
8272
enum thermal_trip_type type;
8373

84-
if (!tz || IS_ERR(tz) || !tz->ops->get_temp)
85-
goto exit;
74+
lockdep_assert_held(&tz->lock);
8675

87-
mutex_lock(&tz->lock);
76+
if (!tz || IS_ERR(tz) || !tz->ops->get_temp)
77+
return -EINVAL;
8878

8979
ret = tz->ops->get_temp(tz, temp);
9080

@@ -107,35 +97,42 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
10797
*temp = tz->emul_temperature;
10898
}
10999

110-
mutex_unlock(&tz->lock);
111-
exit:
112100
return ret;
113101
}
114-
EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
115102

116103
/**
117-
* thermal_zone_set_trips - Computes the next trip points for the driver
118-
* @tz: a pointer to a thermal zone device structure
104+
* thermal_zone_get_temp() - returns the temperature of a thermal zone
105+
* @tz: a valid pointer to a struct thermal_zone_device
106+
* @temp: a valid pointer to where to store the resulting temperature.
119107
*
120-
* The function computes the next temperature boundaries by browsing
121-
* the trip points. The result is the closer low and high trip points
122-
* to the current temperature. These values are passed to the backend
123-
* driver to let it set its own notification mechanism (usually an
124-
* interrupt).
108+
* When a valid thermal zone reference is passed, it will fetch its
109+
* temperature and fill @temp.
125110
*
126-
* It does not return a value
111+
* Return: On success returns 0, an error code otherwise
127112
*/
128-
void thermal_zone_set_trips(struct thermal_zone_device *tz)
113+
int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
114+
{
115+
int ret;
116+
117+
mutex_lock(&tz->lock);
118+
ret = __thermal_zone_get_temp(tz, temp);
119+
mutex_unlock(&tz->lock);
120+
121+
return ret;
122+
}
123+
EXPORT_SYMBOL_GPL(thermal_zone_get_temp);
124+
125+
void __thermal_zone_set_trips(struct thermal_zone_device *tz)
129126
{
130127
int low = -INT_MAX;
131128
int high = INT_MAX;
132129
int trip_temp, hysteresis;
133130
int i, ret;
134131

135-
mutex_lock(&tz->lock);
132+
lockdep_assert_held(&tz->lock);
136133

137134
if (!tz->ops->set_trips || !tz->ops->get_trip_hyst)
138-
goto exit;
135+
return;
139136

140137
for (i = 0; i < tz->num_trips; i++) {
141138
int trip_low;
@@ -154,7 +151,7 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz)
154151

155152
/* No need to change trip points */
156153
if (tz->prev_low_trip == low && tz->prev_high_trip == high)
157-
goto exit;
154+
return;
158155

159156
tz->prev_low_trip = low;
160157
tz->prev_high_trip = high;
@@ -169,8 +166,24 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz)
169166
ret = tz->ops->set_trips(tz, low, high);
170167
if (ret)
171168
dev_err(&tz->device, "Failed to set trips: %d\n", ret);
169+
}
172170

173-
exit:
171+
/**
172+
* thermal_zone_set_trips - Computes the next trip points for the driver
173+
* @tz: a pointer to a thermal zone device structure
174+
*
175+
* The function computes the next temperature boundaries by browsing
176+
* the trip points. The result is the closer low and high trip points
177+
* to the current temperature. These values are passed to the backend
178+
* driver to let it set its own notification mechanism (usually an
179+
* interrupt).
180+
*
181+
* It does not return a value
182+
*/
183+
void thermal_zone_set_trips(struct thermal_zone_device *tz)
184+
{
185+
mutex_lock(&tz->lock);
186+
__thermal_zone_set_trips(tz);
174187
mutex_unlock(&tz->lock);
175188
}
176189

drivers/thermal/thermal_sysfs.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ static ssize_t
4949
mode_show(struct device *dev, struct device_attribute *attr, char *buf)
5050
{
5151
struct thermal_zone_device *tz = to_thermal_zone(dev);
52-
int enabled = thermal_zone_device_is_enabled(tz);
52+
int enabled;
53+
54+
mutex_lock(&tz->lock);
55+
enabled = thermal_zone_device_is_enabled(tz);
56+
mutex_unlock(&tz->lock);
5357

5458
return sprintf(buf, "%s\n", enabled ? "enabled" : "disabled");
5559
}

0 commit comments

Comments
 (0)