diff options
Diffstat (limited to 'drivers/thermal/thermal_core.c')
-rw-r--r-- | drivers/thermal/thermal_core.c | 393 |
1 files changed, 205 insertions, 188 deletions
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 1b0ab2790860..8f03985f971c 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -272,6 +272,44 @@ static int __init thermal_register_governors(void) return ret; } +static int __thermal_zone_device_set_mode(struct thermal_zone_device *tz, + enum thermal_device_mode mode) +{ + if (tz->ops.change_mode) { + int ret; + + ret = tz->ops.change_mode(tz, mode); + if (ret) + return ret; + } + + tz->mode = mode; + + return 0; +} + +static void thermal_zone_broken_disable(struct thermal_zone_device *tz) +{ + struct thermal_trip_desc *td; + + dev_err(&tz->device, "Unable to get temperature, disabling!\n"); + /* + * This function only runs for enabled thermal zones, so no need to + * check for the current mode. + */ + __thermal_zone_device_set_mode(tz, THERMAL_DEVICE_DISABLED); + thermal_notify_tz_disable(tz); + + for_each_trip_desc(tz, td) { + if (td->trip.type == THERMAL_TRIP_CRITICAL && + td->trip.temperature > THERMAL_TEMP_INVALID) { + dev_crit(&tz->device, + "Disabled thermal zone with critical trip point\n"); + return; + } + } +} + /* * Zone update section: main control loop applied to each zone while monitoring * in polling mode. The monitoring is done using a workqueue. @@ -285,18 +323,43 @@ static int __init thermal_register_governors(void) static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, unsigned long delay) { - if (delay) - mod_delayed_work(system_freezable_power_efficient_wq, - &tz->poll_queue, delay); - else - cancel_delayed_work(&tz->poll_queue); + if (delay > HZ) + delay = round_jiffies_relative(delay); + + mod_delayed_work(system_freezable_power_efficient_wq, &tz->poll_queue, delay); +} + +static void thermal_zone_recheck(struct thermal_zone_device *tz, int error) +{ + if (error == -EAGAIN) { + thermal_zone_device_set_polling(tz, THERMAL_RECHECK_DELAY); + return; + } + + /* + * Print the message once to reduce log noise. It will be followed by + * another one if the temperature cannot be determined after multiple + * attempts. + */ + if (tz->recheck_delay_jiffies == THERMAL_RECHECK_DELAY) + dev_info(&tz->device, "Temperature check failed (%d)\n", error); + + thermal_zone_device_set_polling(tz, tz->recheck_delay_jiffies); + + tz->recheck_delay_jiffies += max(tz->recheck_delay_jiffies >> 1, 1ULL); + if (tz->recheck_delay_jiffies > THERMAL_MAX_RECHECK_DELAY) { + thermal_zone_broken_disable(tz); + /* + * Restore the original recheck delay value to allow the thermal + * zone to try to recover when it is reenabled by user space. + */ + tz->recheck_delay_jiffies = THERMAL_RECHECK_DELAY; + } } static void monitor_thermal_zone(struct thermal_zone_device *tz) { - if (tz->mode != THERMAL_DEVICE_ENABLED) - thermal_zone_device_set_polling(tz, 0); - else if (tz->passive > 0) + if (tz->passive > 0 && tz->passive_delay_jiffies) thermal_zone_device_set_polling(tz, tz->passive_delay_jiffies); else if (tz->polling_delay_jiffies) thermal_zone_device_set_polling(tz, tz->polling_delay_jiffies); @@ -380,7 +443,7 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, td->threshold = trip->temperature; if (tz->last_temperature >= old_threshold && - tz->last_temperature != THERMAL_TEMP_INVALID) { + tz->last_temperature != THERMAL_TEMP_INIT) { /* * Mitigation is under way, so it needs to stop if the zone * temperature falls below the low temperature of the trip. @@ -415,27 +478,6 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, } } -static void update_temperature(struct thermal_zone_device *tz) -{ - int temp, ret; - - ret = __thermal_zone_get_temp(tz, &temp); - if (ret) { - if (ret != -EAGAIN) - dev_warn(&tz->device, - "failed to read out thermal zone (%d)\n", - ret); - return; - } - - tz->last_temperature = tz->temperature; - tz->temperature = temp; - - trace_thermal_temperature(tz); - - thermal_genl_sampling_temp(tz->id, temp); -} - static void thermal_zone_device_check(struct work_struct *work) { struct thermal_zone_device *tz = container_of(work, struct @@ -450,7 +492,7 @@ static void thermal_zone_device_init(struct thermal_zone_device *tz) INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check); - tz->temperature = THERMAL_TEMP_INVALID; + tz->temperature = THERMAL_TEMP_INIT; tz->passive = 0; tz->prev_low_trip = -INT_MAX; tz->prev_high_trip = INT_MAX; @@ -463,6 +505,9 @@ static void thermal_governor_trip_crossed(struct thermal_governor *governor, const struct thermal_trip *trip, bool crossed_up) { + if (trip->type == THERMAL_TRIP_HOT || trip->type == THERMAL_TRIP_CRITICAL) + return; + if (governor->trip_crossed) governor->trip_crossed(tz, trip, crossed_up); } @@ -482,16 +527,14 @@ static void thermal_trip_crossed(struct thermal_zone_device *tz, thermal_governor_trip_crossed(governor, tz, trip, crossed_up); } -static int thermal_trip_notify_cmp(void *ascending, const struct list_head *a, +static int thermal_trip_notify_cmp(void *not_used, const struct list_head *a, const struct list_head *b) { struct thermal_trip_desc *tda = container_of(a, struct thermal_trip_desc, notify_list_node); struct thermal_trip_desc *tdb = container_of(b, struct thermal_trip_desc, notify_list_node); - int ret = tdb->notify_temp - tda->notify_temp; - - return ascending ? ret : -ret; + return tda->notify_temp - tdb->notify_temp; } void __thermal_zone_device_update(struct thermal_zone_device *tz, @@ -501,31 +544,55 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz, struct thermal_trip_desc *td; LIST_HEAD(way_down_list); LIST_HEAD(way_up_list); + int low = -INT_MAX, high = INT_MAX; + int temp, ret; - if (tz->suspended) + if (tz->suspended || tz->mode != THERMAL_DEVICE_ENABLED) return; - if (!thermal_zone_device_is_enabled(tz)) + ret = __thermal_zone_get_temp(tz, &temp); + if (ret) { + thermal_zone_recheck(tz, ret); return; + } else if (temp <= THERMAL_TEMP_INVALID) { + /* + * Special case: No valid temperature value is available, but + * the zone owner does not want the core to do anything about + * it. Continue regular zone polling if needed, so that this + * function can be called again, but skip everything else. + */ + goto monitor; + } - update_temperature(tz); + tz->recheck_delay_jiffies = THERMAL_RECHECK_DELAY; - if (tz->temperature == THERMAL_TEMP_INVALID) - return; + tz->last_temperature = tz->temperature; + tz->temperature = temp; + + trace_thermal_temperature(tz); - __thermal_zone_set_trips(tz); + thermal_genl_sampling_temp(tz->id, temp); tz->notify_event = event; - for_each_trip_desc(tz, td) + for_each_trip_desc(tz, td) { handle_thermal_trip(tz, td, &way_up_list, &way_down_list); - list_sort(&way_up_list, &way_up_list, thermal_trip_notify_cmp); + if (td->threshold <= tz->temperature && td->threshold > low) + low = td->threshold; + + if (td->threshold >= tz->temperature && td->threshold < high) + high = td->threshold; + } + + thermal_zone_set_trips(tz, low, high); + + list_sort(NULL, &way_up_list, thermal_trip_notify_cmp); list_for_each_entry(td, &way_up_list, notify_list_node) thermal_trip_crossed(tz, &td->trip, governor, true); list_sort(NULL, &way_down_list, thermal_trip_notify_cmp); - list_for_each_entry(td, &way_down_list, notify_list_node) + list_for_each_entry_reverse(td, &way_down_list, notify_list_node) thermal_trip_crossed(tz, &td->trip, governor, false); if (governor->manage) @@ -533,13 +600,14 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz, thermal_debug_update_trip_stats(tz); +monitor: monitor_thermal_zone(tz); } static int thermal_zone_device_set_mode(struct thermal_zone_device *tz, enum thermal_device_mode mode) { - int ret = 0; + int ret; mutex_lock(&tz->lock); @@ -547,14 +615,15 @@ static int thermal_zone_device_set_mode(struct thermal_zone_device *tz, if (mode == tz->mode) { mutex_unlock(&tz->lock); - return ret; + return 0; } - if (tz->ops.change_mode) - ret = tz->ops.change_mode(tz, mode); + ret = __thermal_zone_device_set_mode(tz, mode); + if (ret) { + mutex_unlock(&tz->lock); - if (!ret) - tz->mode = mode; + return ret; + } __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); @@ -565,7 +634,7 @@ static int thermal_zone_device_set_mode(struct thermal_zone_device *tz, else thermal_notify_tz_disable(tz); - return ret; + return 0; } int thermal_zone_device_enable(struct thermal_zone_device *tz) @@ -580,13 +649,6 @@ int thermal_zone_device_disable(struct thermal_zone_device *tz) } EXPORT_SYMBOL_GPL(thermal_zone_device_disable); -int thermal_zone_device_is_enabled(struct thermal_zone_device *tz) -{ - lockdep_assert_held(&tz->lock); - - return tz->mode == THERMAL_DEVICE_ENABLED; -} - static bool thermal_zone_is_present(struct thermal_zone_device *tz) { return !list_empty(&tz->node); @@ -666,6 +728,7 @@ struct thermal_zone_device *thermal_zone_get_by_id(int id) mutex_lock(&thermal_list_lock); list_for_each_entry(tz, &thermal_tz_list, node) { if (tz->id == id) { + get_device(&tz->device); match = tz; break; } @@ -690,15 +753,7 @@ struct thermal_zone_device *thermal_zone_get_by_id(int id) * @tz: pointer to struct thermal_zone_device * @trip: trip point the cooling devices is associated with in this zone. * @cdev: pointer to struct thermal_cooling_device - * @upper: the Maximum cooling state for this trip point. - * THERMAL_NO_LIMIT means no upper limit, - * and the cooling device can be in max_state. - * @lower: the Minimum cooling state can be used for this trip point. - * THERMAL_NO_LIMIT means no lower limit, - * and the cooling device can be in cooling state 0. - * @weight: The weight of the cooling device to be bound to the - * thermal zone. Use THERMAL_WEIGHT_DEFAULT for the - * default value + * @cool_spec: cooling specification for @trip and @cdev * * This interface function bind a thermal cooling device to the certain trip * point of a thermal zone device. @@ -706,55 +761,41 @@ struct thermal_zone_device *thermal_zone_get_by_id(int id) * * Return: 0 on success, the proper error value otherwise. */ -int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz, +static int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz, const struct thermal_trip *trip, struct thermal_cooling_device *cdev, - unsigned long upper, unsigned long lower, - unsigned int weight) + struct cooling_spec *cool_spec) { struct thermal_instance *dev; struct thermal_instance *pos; - struct thermal_zone_device *pos1; - struct thermal_cooling_device *pos2; bool upper_no_limit; int result; - list_for_each_entry(pos1, &thermal_tz_list, node) { - if (pos1 == tz) - break; - } - list_for_each_entry(pos2, &thermal_cdev_list, node) { - if (pos2 == cdev) - break; - } - - if (tz != pos1 || cdev != pos2) - return -EINVAL; - /* lower default 0, upper default max_state */ - lower = lower == THERMAL_NO_LIMIT ? 0 : lower; + if (cool_spec->lower == THERMAL_NO_LIMIT) + cool_spec->lower = 0; - if (upper == THERMAL_NO_LIMIT) { - upper = cdev->max_state; + if (cool_spec->upper == THERMAL_NO_LIMIT) { + cool_spec->upper = cdev->max_state; upper_no_limit = true; } else { upper_no_limit = false; } - if (lower > upper || upper > cdev->max_state) + if (cool_spec->lower > cool_spec->upper || cool_spec->upper > cdev->max_state) return -EINVAL; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; - dev->tz = tz; + dev->cdev = cdev; dev->trip = trip; - dev->upper = upper; + dev->upper = cool_spec->upper; dev->upper_no_limit = upper_no_limit; - dev->lower = lower; + dev->lower = cool_spec->lower; dev->target = THERMAL_NO_TARGET; - dev->weight = weight; + dev->weight = cool_spec->weight; result = ida_alloc(&tz->ida, GFP_KERNEL); if (result < 0) @@ -788,10 +829,9 @@ int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz, if (result) goto remove_trip_file; - mutex_lock(&tz->lock); mutex_lock(&cdev->lock); list_for_each_entry(pos, &tz->thermal_instances, tz_node) - if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { + if (pos->trip == trip && pos->cdev == cdev) { result = -EEXIST; break; } @@ -803,7 +843,6 @@ int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz, thermal_governor_update_tz(tz, THERMAL_TZ_BIND_CDEV); } mutex_unlock(&cdev->lock); - mutex_unlock(&tz->lock); if (!result) return 0; @@ -819,21 +858,6 @@ free_mem: kfree(dev); return result; } -EXPORT_SYMBOL_GPL(thermal_bind_cdev_to_trip); - -int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, - int trip_index, - struct thermal_cooling_device *cdev, - unsigned long upper, unsigned long lower, - unsigned int weight) -{ - if (trip_index < 0 || trip_index >= tz->num_trips) - return -EINVAL; - - return thermal_bind_cdev_to_trip(tz, &tz->trips[trip_index].trip, cdev, - upper, lower, weight); -} -EXPORT_SYMBOL_GPL(thermal_zone_bind_cooling_device); /** * thermal_unbind_cdev_from_trip - unbind a cooling device from a thermal zone. @@ -844,33 +868,28 @@ EXPORT_SYMBOL_GPL(thermal_zone_bind_cooling_device); * This interface function unbind a thermal cooling device from the certain * trip point of a thermal zone device. * This function is usually called in the thermal zone device .unbind callback. - * - * Return: 0 on success, the proper error value otherwise. */ -int thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz, - const struct thermal_trip *trip, - struct thermal_cooling_device *cdev) +static void thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz, + const struct thermal_trip *trip, + struct thermal_cooling_device *cdev) { struct thermal_instance *pos, *next; - mutex_lock(&tz->lock); mutex_lock(&cdev->lock); list_for_each_entry_safe(pos, next, &tz->thermal_instances, tz_node) { - if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { + if (pos->trip == trip && pos->cdev == cdev) { list_del(&pos->tz_node); list_del(&pos->cdev_node); thermal_governor_update_tz(tz, THERMAL_TZ_UNBIND_CDEV); mutex_unlock(&cdev->lock); - mutex_unlock(&tz->lock); goto unbind; } } mutex_unlock(&cdev->lock); - mutex_unlock(&tz->lock); - return -ENODEV; + return; unbind: device_remove_file(&tz->device, &pos->weight_attr); @@ -878,20 +897,7 @@ unbind: sysfs_remove_link(&tz->device.kobj, pos->name); ida_free(&tz->ida, pos->id); kfree(pos); - return 0; -} -EXPORT_SYMBOL_GPL(thermal_unbind_cdev_from_trip); - -int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, - int trip_index, - struct thermal_cooling_device *cdev) -{ - if (trip_index < 0 || trip_index >= tz->num_trips) - return -EINVAL; - - return thermal_unbind_cdev_from_trip(tz, &tz->trips[trip_index].trip, cdev); } -EXPORT_SYMBOL_GPL(thermal_zone_unbind_cooling_device); static void thermal_release(struct device *dev) { @@ -918,24 +924,41 @@ static struct class *thermal_class; static inline void print_bind_err_msg(struct thermal_zone_device *tz, + const struct thermal_trip *trip, struct thermal_cooling_device *cdev, int ret) { - dev_err(&tz->device, "binding zone %s with cdev %s failed:%d\n", - tz->type, cdev->type, ret); + dev_err(&tz->device, "binding cdev %s to trip %d failed: %d\n", + cdev->type, thermal_zone_trip_id(tz, trip), ret); } -static void bind_cdev(struct thermal_cooling_device *cdev) +static void thermal_zone_cdev_bind(struct thermal_zone_device *tz, + struct thermal_cooling_device *cdev) { - int ret; - struct thermal_zone_device *pos = NULL; + struct thermal_trip_desc *td; - list_for_each_entry(pos, &thermal_tz_list, node) { - if (pos->ops.bind) { - ret = pos->ops.bind(pos, cdev); - if (ret) - print_bind_err_msg(pos, cdev, ret); - } + if (!tz->ops.should_bind) + return; + + mutex_lock(&tz->lock); + + for_each_trip_desc(tz, td) { + struct thermal_trip *trip = &td->trip; + struct cooling_spec c = { + .upper = THERMAL_NO_LIMIT, + .lower = THERMAL_NO_LIMIT, + .weight = THERMAL_WEIGHT_DEFAULT + }; + int ret; + + if (!tz->ops.should_bind(tz, trip, cdev, &c)) + continue; + + ret = thermal_bind_cdev_to_trip(tz, trip, cdev, &c); + if (ret) + print_bind_err_msg(tz, trip, cdev, ret); } + + mutex_unlock(&tz->lock); } /** @@ -1033,7 +1056,8 @@ __thermal_cooling_device_register(struct device_node *np, list_add(&cdev->node, &thermal_cdev_list); /* Update binding information for 'this' new cdev */ - bind_cdev(cdev); + list_for_each_entry(pos, &thermal_tz_list, node) + thermal_zone_cdev_bind(pos, cdev); list_for_each_entry(pos, &thermal_tz_list, node) if (atomic_cmpxchg(&pos->need_update, 1, 0)) @@ -1126,7 +1150,7 @@ static void thermal_cooling_device_release(struct device *dev, void *res) struct thermal_cooling_device * devm_thermal_of_cooling_device_register(struct device *dev, struct device_node *np, - char *type, void *devdata, + const char *type, void *devdata, const struct thermal_cooling_device_ops *ops) { struct thermal_cooling_device **ptr, *tcd; @@ -1234,6 +1258,19 @@ unlock_list: } EXPORT_SYMBOL_GPL(thermal_cooling_device_update); +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); + + mutex_unlock(&tz->lock); +} + /** * thermal_cooling_device_unregister - removes a thermal cooling device * @cdev: the thermal cooling device to remove. @@ -1260,10 +1297,8 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev) list_del(&cdev->node); /* Unbind all thermal zones associated with 'this' cdev */ - list_for_each_entry(tz, &thermal_tz_list, node) { - if (tz->ops.unbind) - tz->ops.unbind(tz, cdev); - } + list_for_each_entry(tz, &thermal_tz_list, node) + thermal_zone_cdev_unbind(tz, cdev); mutex_unlock(&thermal_list_lock); @@ -1271,32 +1306,6 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev) } EXPORT_SYMBOL_GPL(thermal_cooling_device_unregister); -static void bind_tz(struct thermal_zone_device *tz) -{ - int ret; - struct thermal_cooling_device *pos = NULL; - - if (!tz->ops.bind) - return; - - mutex_lock(&thermal_list_lock); - - list_for_each_entry(pos, &thermal_cdev_list, node) { - ret = tz->ops.bind(tz, pos); - if (ret) - print_bind_err_msg(tz, pos, ret); - } - - mutex_unlock(&thermal_list_lock); -} - -static void thermal_set_delay_jiffies(unsigned long *delay_jiffies, int delay_ms) -{ - *delay_jiffies = msecs_to_jiffies(delay_ms); - if (delay_ms > 1000) - *delay_jiffies = round_jiffies(*delay_jiffies); -} - int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp) { const struct thermal_trip_desc *td; @@ -1353,9 +1362,11 @@ thermal_zone_device_register_with_trips(const char *type, int num_trips, void *devdata, const struct thermal_zone_device_ops *ops, const struct thermal_zone_params *tzp, - int passive_delay, int polling_delay) + unsigned int passive_delay, + unsigned int polling_delay) { const struct thermal_trip *trip = trips; + struct thermal_cooling_device *cdev; struct thermal_zone_device *tz; struct thermal_trip_desc *td; int id; @@ -1379,13 +1390,16 @@ thermal_zone_device_register_with_trips(const char *type, } if (!ops || !ops->get_temp) { - pr_err("Thermal zone device ops not defined\n"); + pr_err("Thermal zone device ops not defined or invalid\n"); return ERR_PTR(-EINVAL); } if (num_trips > 0 && !trips) return ERR_PTR(-EINVAL); + if (polling_delay && passive_delay > polling_delay) + return ERR_PTR(-EINVAL); + if (!thermal_class) return ERR_PTR(-ENODEV); @@ -1433,8 +1447,9 @@ thermal_zone_device_register_with_trips(const char *type, td->threshold = INT_MAX; } - thermal_set_delay_jiffies(&tz->passive_delay_jiffies, passive_delay); - thermal_set_delay_jiffies(&tz->polling_delay_jiffies, polling_delay); + tz->polling_delay_jiffies = msecs_to_jiffies(polling_delay); + tz->passive_delay_jiffies = msecs_to_jiffies(passive_delay); + tz->recheck_delay_jiffies = THERMAL_RECHECK_DELAY; /* sys I/F */ /* Add nodes that are always present via .groups */ @@ -1477,13 +1492,16 @@ thermal_zone_device_register_with_trips(const char *type, } 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 */ - bind_tz(tz); + list_for_each_entry(cdev, &thermal_cdev_list, node) + thermal_zone_cdev_bind(tz, cdev); + + mutex_unlock(&thermal_list_lock); thermal_zone_device_init(tz); /* Update the new thermal zone and mark it as already updated. */ @@ -1575,8 +1593,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) /* Unbind all cdevs associated with 'this' thermal zone */ list_for_each_entry(cdev, &thermal_cdev_list, node) - if (tz->ops.unbind) - tz->ops.unbind(tz, cdev); + thermal_zone_cdev_unbind(tz, cdev); mutex_unlock(&thermal_list_lock); @@ -1589,14 +1606,12 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) ida_destroy(&tz->ida); device_del(&tz->device); - - kfree(tz->tzp); - put_device(&tz->device); thermal_notify_tz_delete(tz); wait_for_completion(&tz->removal); + kfree(tz->tzp); kfree(tz); } EXPORT_SYMBOL_GPL(thermal_zone_device_unregister); @@ -1649,8 +1664,10 @@ static void thermal_zone_device_resume(struct work_struct *work) tz->suspended = false; + thermal_debug_tz_resume(tz); thermal_zone_device_init(tz); - __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); + thermal_governor_update_tz(tz, THERMAL_TZ_RESUME); + __thermal_zone_device_update(tz, THERMAL_TZ_RESUME); complete(&tz->resume); tz->resuming = false; |