Skip to content

Commit 68f4f03

Browse files
committed
ACPI: thermal: Carry out trip point updates under zone lock
There is a race condition between acpi_thermal_trips_update() and acpi_thermal_check_fn(), because the trip points may get updated while the latter is running which in theory may lead to inconsistent results. For example, if two trips are updated together, using the temperature value of one of them from before the update and the temperature value of the other one from after the update may not lead to the expected outcome. Moreover, if thermal_get_trend() runs when a trip points update is in progress, it may end up using stale trip point temperatures. To address this, make acpi_thermal_trips_update() call thermal_zone_device_exec() to carry out the trip points update and use a new acpi_thermal_adjust_thermal_zone() wrapper around __acpi_thermal_trips_update() as the callback function for the latter. While at it, change the acpi_thermal_trips_update() return data type to void as that function always returns 0 anyway. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent bf07b4a commit 68f4f03

1 file changed

Lines changed: 28 additions & 13 deletions

File tree

drivers/acpi/thermal.c

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
185185
return 0;
186186
}
187187

188-
static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
188+
static void __acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
189189
{
190190
acpi_status status;
191191
unsigned long long tmp;
@@ -393,17 +393,40 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
393393
ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device");
394394
}
395395
}
396+
}
396397

397-
return 0;
398+
static void acpi_thermal_adjust_thermal_zone(struct thermal_zone_device *thermal,
399+
unsigned long data)
400+
{
401+
__acpi_thermal_trips_update(thermal_zone_device_priv(thermal), data);
402+
}
403+
404+
static void acpi_queue_thermal_check(struct acpi_thermal *tz)
405+
{
406+
if (!work_pending(&tz->thermal_check_work))
407+
queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work);
408+
}
409+
410+
static void acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
411+
{
412+
/*
413+
* Use thermal_zone_device_exec() to carry out the trip points
414+
* update, so as to protect thermal_get_trend() from getting stale
415+
* trip point temperatures and to prevent thermal_zone_device_update()
416+
* invoked from acpi_thermal_check_fn() from producing inconsistent
417+
* results.
418+
*/
419+
thermal_zone_device_exec(tz->thermal_zone,
420+
acpi_thermal_adjust_thermal_zone, flag);
421+
acpi_queue_thermal_check(tz);
398422
}
399423

400424
static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
401425
{
402-
int i, ret = acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
403426
bool valid;
427+
int i;
404428

405-
if (ret)
406-
return ret;
429+
__acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
407430

408431
valid = tz->trips.critical.valid |
409432
tz->trips.hot.valid |
@@ -799,12 +822,6 @@ static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
799822
Driver Interface
800823
-------------------------------------------------------------------------- */
801824

802-
static void acpi_queue_thermal_check(struct acpi_thermal *tz)
803-
{
804-
if (!work_pending(&tz->thermal_check_work))
805-
queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work);
806-
}
807-
808825
static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
809826
{
810827
struct acpi_device *device = data;
@@ -819,13 +836,11 @@ static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
819836
break;
820837
case ACPI_THERMAL_NOTIFY_THRESHOLDS:
821838
acpi_thermal_trips_update(tz, ACPI_TRIPS_THRESHOLDS);
822-
acpi_queue_thermal_check(tz);
823839
acpi_bus_generate_netlink_event(device->pnp.device_class,
824840
dev_name(&device->dev), event, 0);
825841
break;
826842
case ACPI_THERMAL_NOTIFY_DEVICES:
827843
acpi_thermal_trips_update(tz, ACPI_TRIPS_DEVICES);
828-
acpi_queue_thermal_check(tz);
829844
acpi_bus_generate_netlink_event(device->pnp.device_class,
830845
dev_name(&device->dev), event, 0);
831846
break;

0 commit comments

Comments
 (0)