Loading drivers/thermal/Kconfig +12 −0 Original line number Diff line number Diff line Loading @@ -401,6 +401,18 @@ depends on (ARCH_QCOM && OF) || COMPILE_TEST source "drivers/thermal/qcom/Kconfig" endmenu config QTI_THERMAL bool prompt "Enable QTI Thermal Framework enhancements" depends on THERMAL && QGKI default y help Enable the QTI enhancements on the thermal framework. This will enable enhancements like handling passive evaluation on high priority queue, using same trip temperature from sensor to algorithm and enabling user space thermal daemon as a separate client of cooling device. config ZX2967_THERMAL tristate "Thermal sensors on zx2967 SoC" depends on ARCH_ZX || COMPILE_TEST Loading drivers/thermal/step_wise.c +131 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ * if the cooling state already equals lower limit, * deactivate the thermal instance */ #ifdef CONFIG_QTI_THERMAL static unsigned long get_target_state(struct thermal_instance *instance, enum thermal_trend trend, bool throttle) { Loading Loading @@ -110,6 +111,75 @@ static unsigned long get_target_state(struct thermal_instance *instance, return next_target; } #else static unsigned long get_target_state(struct thermal_instance *instance, enum thermal_trend trend, bool throttle) { struct thermal_cooling_device *cdev = instance->cdev; unsigned long cur_state; unsigned long next_target; /* * We keep this instance the way it is by default. * Otherwise, we use the current state of the * cdev in use to determine the next_target. */ cdev->ops->get_cur_state(cdev, &cur_state); next_target = instance->target; dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state); if (!instance->initialized) { if (throttle) { next_target = (cur_state + 1) >= instance->upper ? instance->upper : ((cur_state + 1) < instance->lower ? instance->lower : (cur_state + 1)); } else { next_target = THERMAL_NO_TARGET; } return next_target; } switch (trend) { case THERMAL_TREND_RAISING: if (throttle) { next_target = cur_state < instance->upper ? (cur_state + 1) : instance->upper; if (next_target < instance->lower) next_target = instance->lower; } break; case THERMAL_TREND_RAISE_FULL: if (throttle) next_target = instance->upper; break; case THERMAL_TREND_DROPPING: if (cur_state <= instance->lower) { if (!throttle) next_target = THERMAL_NO_TARGET; } else { if (!throttle) { next_target = cur_state - 1; if (next_target > instance->upper) next_target = instance->upper; } } break; case THERMAL_TREND_DROP_FULL: if (cur_state == instance->lower) { if (!throttle) next_target = THERMAL_NO_TARGET; } else next_target = instance->lower; break; default: break; } return next_target; } #endif static void update_passive_instance(struct thermal_zone_device *tz, enum thermal_trip_type type, int value) Loading @@ -122,6 +192,7 @@ static void update_passive_instance(struct thermal_zone_device *tz, tz->passive += value; } #ifdef CONFIG_QTI_THERMAL static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) { int trip_temp, hyst_temp; Loading Loading @@ -208,6 +279,66 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) mutex_unlock(&tz->lock); } #else static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) { int trip_temp; enum thermal_trip_type trip_type; enum thermal_trend trend; struct thermal_instance *instance; bool throttle = false; int old_target; if (trip == THERMAL_TRIPS_NONE) { trip_temp = tz->forced_passive; trip_type = THERMAL_TRIPS_NONE; } else { tz->ops->get_trip_temp(tz, trip, &trip_temp); tz->ops->get_trip_type(tz, trip, &trip_type); } trend = get_tz_trend(tz, trip); if (tz->temperature >= trip_temp) { throttle = true; trace_thermal_zone_trip(tz, trip, trip_type); } dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n", trip, trip_type, trip_temp, trend, throttle); mutex_lock(&tz->lock); list_for_each_entry(instance, &tz->thermal_instances, tz_node) { if (instance->trip != trip) continue; old_target = instance->target; instance->target = get_target_state(instance, trend, throttle); dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n", old_target, (int)instance->target); if (instance->initialized && old_target == instance->target) continue; /* Activate a passive thermal instance */ if (old_target == THERMAL_NO_TARGET && instance->target != THERMAL_NO_TARGET) update_passive_instance(tz, trip_type, 1); /* Deactivate a passive thermal instance */ else if (old_target != THERMAL_NO_TARGET && instance->target == THERMAL_NO_TARGET) update_passive_instance(tz, trip_type, -1); instance->initialized = true; mutex_lock(&instance->cdev->lock); instance->cdev->updated = false; /* cdev needs update */ mutex_unlock(&instance->cdev->lock); } mutex_unlock(&tz->lock); } #endif /** * step_wise_throttle - throttles devices associated with the given zone Loading drivers/thermal/thermal_core.c +210 −56 Original line number Diff line number Diff line Loading @@ -34,8 +34,6 @@ MODULE_AUTHOR("Zhang Rui"); MODULE_DESCRIPTION("Generic thermal management sysfs support"); MODULE_LICENSE("GPL v2"); #define THERMAL_MAX_ACTIVE 16 static DEFINE_IDA(thermal_tz_ida); static DEFINE_IDA(thermal_cdev_ida); Loading @@ -52,8 +50,6 @@ static bool power_off_triggered; static struct thermal_governor *def_governor; static struct workqueue_struct *thermal_passive_wq; /* * Governor section: set of functions to handle thermal governors * Loading Loading @@ -297,6 +293,10 @@ static int __init thermal_register_governors(void) * - Hot trips will produce a notification to userspace; * - Critical trip point will cause a system shutdown. */ #ifdef CONFIG_QTI_THERMAL #define THERMAL_MAX_ACTIVE 16 static struct workqueue_struct *thermal_passive_wq; static void thermal_zone_device_set_polling(struct workqueue_struct *queue, struct thermal_zone_device *tz, int delay) Loading Loading @@ -327,6 +327,113 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz) mutex_unlock(&tz->lock); } static void store_temperature(struct thermal_zone_device *tz, int temp) { mutex_lock(&tz->lock); tz->last_temperature = tz->temperature; tz->temperature = temp; mutex_unlock(&tz->lock); trace_thermal_temperature(tz); if (tz->last_temperature == THERMAL_TEMP_INVALID) dev_dbg(&tz->device, "last_temperature N/A, current_temperature=%d\n", tz->temperature); else dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n", tz->last_temperature, tz->temperature); } 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; } store_temperature(tz, temp); } static void handle_thermal_trip(struct thermal_zone_device *tz, int trip); void thermal_zone_device_update_temp(struct thermal_zone_device *tz, enum thermal_notify_event event, int temp) { int count; if (atomic_read(&in_suspend) && tz->polling_delay) return; trace_thermal_device_update(tz, event); store_temperature(tz, temp); thermal_zone_set_trips(tz); tz->notify_event = event; for (count = 0; count < tz->trips; count++) handle_thermal_trip(tz, count); } EXPORT_SYMBOL(thermal_zone_device_update_temp); #else static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, int delay) { if (delay > 1000) mod_delayed_work(system_freezable_power_efficient_wq, &tz->poll_queue, round_jiffies(msecs_to_jiffies(delay))); else if (delay) mod_delayed_work(system_freezable_power_efficient_wq, &tz->poll_queue, msecs_to_jiffies(delay)); else cancel_delayed_work_sync(&tz->poll_queue); } static void monitor_thermal_zone(struct thermal_zone_device *tz) { mutex_lock(&tz->lock); if (tz->passive) thermal_zone_device_set_polling(tz, tz->passive_delay); else if (tz->polling_delay) thermal_zone_device_set_polling(tz, tz->polling_delay); else thermal_zone_device_set_polling(tz, 0); mutex_unlock(&tz->lock); } 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; } mutex_lock(&tz->lock); tz->last_temperature = tz->temperature; tz->temperature = temp; mutex_unlock(&tz->lock); trace_thermal_temperature(tz); if (tz->last_temperature == THERMAL_TEMP_INVALID) dev_dbg(&tz->device, "last_temperature N/A, current_temperature=%d\n", tz->temperature); else dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n", tz->last_temperature, tz->temperature); } #endif static void handle_non_critical_trips(struct thermal_zone_device *tz, int trip) { Loading Loading @@ -393,7 +500,9 @@ static void handle_critical_trips(struct thermal_zone_device *tz, if (trip_temp <= 0 || tz->temperature < trip_temp) return; #ifdef CONFIG_QTI_THERMAL trace_thermal_zone_trip(tz, trip, trip_type, true); #endif if (tz->ops->notify) tz->ops->notify(tz, trip, trip_type); Loading Loading @@ -435,38 +544,9 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) * So, start monitoring again. */ monitor_thermal_zone(tz); #ifdef CONFIG_QTI_THERMAL trace_thermal_handle_trip(tz, trip); } static void store_temperature(struct thermal_zone_device *tz, int temp) { mutex_lock(&tz->lock); tz->last_temperature = tz->temperature; tz->temperature = temp; mutex_unlock(&tz->lock); trace_thermal_temperature(tz); if (tz->last_temperature == THERMAL_TEMP_INVALID) dev_dbg(&tz->device, "last_temperature N/A, current_temperature=%d\n", tz->temperature); else dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n", tz->last_temperature, tz->temperature); } 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; } store_temperature(tz, temp); #endif } static void thermal_zone_device_init(struct thermal_zone_device *tz) Loading @@ -483,36 +563,22 @@ static void thermal_zone_device_reset(struct thermal_zone_device *tz) thermal_zone_device_init(tz); } void thermal_zone_device_update_temp(struct thermal_zone_device *tz, enum thermal_notify_event event, int temp) { int count; if (atomic_read(&in_suspend) && tz->polling_delay) return; trace_thermal_device_update(tz, event); store_temperature(tz, temp); thermal_zone_set_trips(tz); tz->notify_event = event; for (count = 0; count < tz->trips; count++) handle_thermal_trip(tz, count); } EXPORT_SYMBOL(thermal_zone_device_update_temp); void thermal_zone_device_update(struct thermal_zone_device *tz, enum thermal_notify_event event) { int count; if (!tz->ops->get_temp) return; #ifdef CONFIG_QTI_THERMAL if (atomic_read(&in_suspend) && tz->polling_delay) return; if (!tz->ops->get_temp) trace_thermal_device_update(tz, event); #else if (atomic_read(&in_suspend)) return; #endif trace_thermal_device_update(tz, event); update_temperature(tz); thermal_zone_set_trips(tz); Loading Loading @@ -741,6 +807,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, if (ret) return ret; #ifdef CONFIG_QTI_THERMAL /* * If upper or lower has a MACRO to define the mitigation state, * based on the MACRO determine the default state to use or the Loading @@ -761,6 +828,11 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, else lower = max_state - (THERMAL_MAX_LIMIT - lower); } #else /* lower default 0, upper default max_state */ lower = lower == THERMAL_NO_LIMIT ? 0 : lower; upper = upper == THERMAL_NO_LIMIT ? max_state : upper; #endif if (lower > upper || upper > max_state) return -EINVAL; Loading Loading @@ -883,6 +955,7 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, } EXPORT_SYMBOL_GPL(thermal_zone_unbind_cooling_device); #ifdef CONFIG_QTI_THERMAL static void thermal_release(struct device *dev) { struct thermal_zone_device *tz; Loading @@ -906,6 +979,24 @@ static void thermal_release(struct device *dev) kfree(cdev); } } #else static void thermal_release(struct device *dev) { struct thermal_zone_device *tz; struct thermal_cooling_device *cdev; if (!strncmp(dev_name(dev), "thermal_zone", sizeof("thermal_zone") - 1)) { tz = to_thermal_zone(dev); thermal_zone_destroy_device_groups(tz); kfree(tz); } else if (!strncmp(dev_name(dev), "cooling_device", sizeof("cooling_device") - 1)) { cdev = to_cooling_device(dev); kfree(cdev); } } #endif static struct class thermal_class = { .name = "thermal", Loading Loading @@ -1008,7 +1099,9 @@ __thermal_cooling_device_register(struct device_node *np, struct thermal_cooling_device *cdev; struct thermal_zone_device *pos = NULL; int result; #ifdef CONFIG_QTI_THERMAL struct thermal_instance *instance; #endif if (type && strlen(type) >= THERMAL_NAME_LENGTH) return ERR_PTR(-EINVAL); Loading @@ -1021,16 +1114,20 @@ __thermal_cooling_device_register(struct device_node *np, if (!cdev) return ERR_PTR(-ENOMEM); #ifdef CONFIG_QTI_THERMAL instance = kzalloc(sizeof(*instance), GFP_KERNEL); if (!instance) { kfree(cdev); return ERR_PTR(-ENOMEM); } #endif result = ida_simple_get(&thermal_cdev_ida, 0, 0, GFP_KERNEL); if (result < 0) { kfree(cdev); #ifdef CONFIG_QTI_THERMAL kfree(instance); #endif return ERR_PTR(result); } Loading @@ -1038,8 +1135,10 @@ __thermal_cooling_device_register(struct device_node *np, strlcpy(cdev->type, type ? : "", sizeof(cdev->type)); mutex_init(&cdev->lock); INIT_LIST_HEAD(&cdev->thermal_instances); #ifdef CONFIG_QTI_THERMAL instance->target = THERMAL_NO_TARGET; list_add_tail(&instance->cdev_node, &cdev->thermal_instances); #endif cdev->np = np; cdev->ops = ops; cdev->updated = false; Loading Loading @@ -1410,7 +1509,11 @@ thermal_zone_device_register(const char *type, int trips, int mask, /* Bind cooling devices for this zone */ bind_tz(tz); #ifdef CONFIG_QTI_THERMAL INIT_DEFERRABLE_WORK(&(tz->poll_queue), thermal_zone_device_check); #else INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check); #endif thermal_zone_device_reset(tz); /* Update the new thermal zone and mark it as already updated. */ Loading Loading @@ -1641,9 +1744,14 @@ static int thermal_pm_notify(struct notifier_block *nb, if (tz->ops->get_mode) tz->ops->get_mode(tz, &tz_mode); #ifdef CONFIG_QTI_THERMAL if (tz_mode == THERMAL_DEVICE_DISABLED || tz->polling_delay == 0) continue; #else if (tz_mode == THERMAL_DEVICE_DISABLED) continue; #endif thermal_zone_device_init(tz); thermal_zone_device_update(tz, Loading @@ -1660,6 +1768,7 @@ static struct notifier_block thermal_pm_nb = { .notifier_call = thermal_pm_notify, }; #ifdef CONFIG_QTI_THERMAL static int __init thermal_init(void) { int result; Loading Loading @@ -1737,3 +1846,48 @@ static int __init thermal_netlink_init(void) subsys_initcall(thermal_init); fs_initcall(thermal_netlink_init); #else static int __init thermal_init(void) { int result; mutex_init(&poweroff_lock); result = thermal_register_governors(); if (result) goto error; result = class_register(&thermal_class); if (result) goto unregister_governors; result = genetlink_init(); if (result) goto unregister_class; result = of_parse_thermal_zones(); if (result) goto exit_netlink; result = register_pm_notifier(&thermal_pm_nb); if (result) pr_warn("Thermal: Can not register suspend notifier, return %d\n", result); return 0; exit_netlink: genetlink_exit(); unregister_class: class_unregister(&thermal_class); unregister_governors: thermal_unregister_governors(); error: ida_destroy(&thermal_tz_ida); ida_destroy(&thermal_cdev_ida); mutex_destroy(&thermal_list_lock); mutex_destroy(&thermal_governor_lock); mutex_destroy(&poweroff_lock); return result; } fs_initcall(thermal_init); #endif drivers/thermal/thermal_core.h +9 −6 Original line number Diff line number Diff line Loading @@ -98,12 +98,6 @@ int of_thermal_get_ntrips(struct thermal_zone_device *); bool of_thermal_is_trip_valid(struct thermal_zone_device *, int); const struct thermal_trip * of_thermal_get_trip_points(struct thermal_zone_device *); int of_thermal_aggregate_trip(struct thermal_zone_device *tz, enum thermal_trip_type type, int *low, int *high); void of_thermal_handle_trip(struct thermal_zone_device *tz); void of_thermal_handle_trip_temp(struct thermal_zone_device *tz, int trip_temp); #else static inline int of_parse_thermal_zones(void) { return 0; } static inline void of_thermal_destroy_zones(void) { } Loading @@ -121,6 +115,15 @@ of_thermal_get_trip_points(struct thermal_zone_device *tz) { return NULL; } #endif #if (defined(CONFIG_QTI_THERMAL) && defined(CONFIG_THERMAL_OF)) int of_thermal_aggregate_trip(struct thermal_zone_device *tz, enum thermal_trip_type type, int *low, int *high); void of_thermal_handle_trip(struct thermal_zone_device *tz); void of_thermal_handle_trip_temp(struct thermal_zone_device *tz, int trip_temp); #else static inline int of_thermal_aggregate_trip(struct thermal_zone_device *tz, enum thermal_trip_type type, int *low, int *high) Loading drivers/thermal/thermal_helpers.c +14 −0 Original line number Diff line number Diff line Loading @@ -107,7 +107,9 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp) if (!ret && *temp < crit_temp) *temp = tz->emul_temperature; } #ifdef CONFIG_QTI_THERMAL trace_thermal_query_temp(tz, *temp); #endif mutex_unlock(&tz->lock); exit: return ret; Loading Loading @@ -141,6 +143,11 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz) high = trip_temp; } #ifndef CONFIG_QTI_THERMAL /* No need to change trip points */ if (tz->prev_low_trip == low && tz->prev_high_trip == high) goto exit; #endif tz->prev_low_trip = low; tz->prev_high_trip = high; Loading @@ -154,7 +161,9 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz) ret = tz->ops->set_trips(tz, low, high); if (ret) dev_err(&tz->device, "Failed to set trips: %d\n", ret); #ifdef CONFIG_QTI_THERMAL trace_thermal_set_trip(tz); #endif exit: mutex_unlock(&tz->lock); Loading @@ -175,6 +184,7 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev) /* Make sure cdev enters the deepest cooling state */ list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) { #ifdef CONFIG_QTI_THERMAL if (list_is_first(&instance->cdev_node, &cdev->thermal_instances)) dev_dbg(&cdev->device, "userspace->target=%lu\n", Loading @@ -182,6 +192,10 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev) else dev_dbg(&cdev->device, "zone%d->target=%lu\n", instance->tz->id, instance->target); #else dev_dbg(&cdev->device, "zone%d->target=%lu\n", instance->tz->id, instance->target); #endif if (instance->target == THERMAL_NO_TARGET) continue; if (instance->target > target) Loading Loading
drivers/thermal/Kconfig +12 −0 Original line number Diff line number Diff line Loading @@ -401,6 +401,18 @@ depends on (ARCH_QCOM && OF) || COMPILE_TEST source "drivers/thermal/qcom/Kconfig" endmenu config QTI_THERMAL bool prompt "Enable QTI Thermal Framework enhancements" depends on THERMAL && QGKI default y help Enable the QTI enhancements on the thermal framework. This will enable enhancements like handling passive evaluation on high priority queue, using same trip temperature from sensor to algorithm and enabling user space thermal daemon as a separate client of cooling device. config ZX2967_THERMAL tristate "Thermal sensors on zx2967 SoC" depends on ARCH_ZX || COMPILE_TEST Loading
drivers/thermal/step_wise.c +131 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ * if the cooling state already equals lower limit, * deactivate the thermal instance */ #ifdef CONFIG_QTI_THERMAL static unsigned long get_target_state(struct thermal_instance *instance, enum thermal_trend trend, bool throttle) { Loading Loading @@ -110,6 +111,75 @@ static unsigned long get_target_state(struct thermal_instance *instance, return next_target; } #else static unsigned long get_target_state(struct thermal_instance *instance, enum thermal_trend trend, bool throttle) { struct thermal_cooling_device *cdev = instance->cdev; unsigned long cur_state; unsigned long next_target; /* * We keep this instance the way it is by default. * Otherwise, we use the current state of the * cdev in use to determine the next_target. */ cdev->ops->get_cur_state(cdev, &cur_state); next_target = instance->target; dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state); if (!instance->initialized) { if (throttle) { next_target = (cur_state + 1) >= instance->upper ? instance->upper : ((cur_state + 1) < instance->lower ? instance->lower : (cur_state + 1)); } else { next_target = THERMAL_NO_TARGET; } return next_target; } switch (trend) { case THERMAL_TREND_RAISING: if (throttle) { next_target = cur_state < instance->upper ? (cur_state + 1) : instance->upper; if (next_target < instance->lower) next_target = instance->lower; } break; case THERMAL_TREND_RAISE_FULL: if (throttle) next_target = instance->upper; break; case THERMAL_TREND_DROPPING: if (cur_state <= instance->lower) { if (!throttle) next_target = THERMAL_NO_TARGET; } else { if (!throttle) { next_target = cur_state - 1; if (next_target > instance->upper) next_target = instance->upper; } } break; case THERMAL_TREND_DROP_FULL: if (cur_state == instance->lower) { if (!throttle) next_target = THERMAL_NO_TARGET; } else next_target = instance->lower; break; default: break; } return next_target; } #endif static void update_passive_instance(struct thermal_zone_device *tz, enum thermal_trip_type type, int value) Loading @@ -122,6 +192,7 @@ static void update_passive_instance(struct thermal_zone_device *tz, tz->passive += value; } #ifdef CONFIG_QTI_THERMAL static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) { int trip_temp, hyst_temp; Loading Loading @@ -208,6 +279,66 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) mutex_unlock(&tz->lock); } #else static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) { int trip_temp; enum thermal_trip_type trip_type; enum thermal_trend trend; struct thermal_instance *instance; bool throttle = false; int old_target; if (trip == THERMAL_TRIPS_NONE) { trip_temp = tz->forced_passive; trip_type = THERMAL_TRIPS_NONE; } else { tz->ops->get_trip_temp(tz, trip, &trip_temp); tz->ops->get_trip_type(tz, trip, &trip_type); } trend = get_tz_trend(tz, trip); if (tz->temperature >= trip_temp) { throttle = true; trace_thermal_zone_trip(tz, trip, trip_type); } dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n", trip, trip_type, trip_temp, trend, throttle); mutex_lock(&tz->lock); list_for_each_entry(instance, &tz->thermal_instances, tz_node) { if (instance->trip != trip) continue; old_target = instance->target; instance->target = get_target_state(instance, trend, throttle); dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n", old_target, (int)instance->target); if (instance->initialized && old_target == instance->target) continue; /* Activate a passive thermal instance */ if (old_target == THERMAL_NO_TARGET && instance->target != THERMAL_NO_TARGET) update_passive_instance(tz, trip_type, 1); /* Deactivate a passive thermal instance */ else if (old_target != THERMAL_NO_TARGET && instance->target == THERMAL_NO_TARGET) update_passive_instance(tz, trip_type, -1); instance->initialized = true; mutex_lock(&instance->cdev->lock); instance->cdev->updated = false; /* cdev needs update */ mutex_unlock(&instance->cdev->lock); } mutex_unlock(&tz->lock); } #endif /** * step_wise_throttle - throttles devices associated with the given zone Loading
drivers/thermal/thermal_core.c +210 −56 Original line number Diff line number Diff line Loading @@ -34,8 +34,6 @@ MODULE_AUTHOR("Zhang Rui"); MODULE_DESCRIPTION("Generic thermal management sysfs support"); MODULE_LICENSE("GPL v2"); #define THERMAL_MAX_ACTIVE 16 static DEFINE_IDA(thermal_tz_ida); static DEFINE_IDA(thermal_cdev_ida); Loading @@ -52,8 +50,6 @@ static bool power_off_triggered; static struct thermal_governor *def_governor; static struct workqueue_struct *thermal_passive_wq; /* * Governor section: set of functions to handle thermal governors * Loading Loading @@ -297,6 +293,10 @@ static int __init thermal_register_governors(void) * - Hot trips will produce a notification to userspace; * - Critical trip point will cause a system shutdown. */ #ifdef CONFIG_QTI_THERMAL #define THERMAL_MAX_ACTIVE 16 static struct workqueue_struct *thermal_passive_wq; static void thermal_zone_device_set_polling(struct workqueue_struct *queue, struct thermal_zone_device *tz, int delay) Loading Loading @@ -327,6 +327,113 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz) mutex_unlock(&tz->lock); } static void store_temperature(struct thermal_zone_device *tz, int temp) { mutex_lock(&tz->lock); tz->last_temperature = tz->temperature; tz->temperature = temp; mutex_unlock(&tz->lock); trace_thermal_temperature(tz); if (tz->last_temperature == THERMAL_TEMP_INVALID) dev_dbg(&tz->device, "last_temperature N/A, current_temperature=%d\n", tz->temperature); else dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n", tz->last_temperature, tz->temperature); } 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; } store_temperature(tz, temp); } static void handle_thermal_trip(struct thermal_zone_device *tz, int trip); void thermal_zone_device_update_temp(struct thermal_zone_device *tz, enum thermal_notify_event event, int temp) { int count; if (atomic_read(&in_suspend) && tz->polling_delay) return; trace_thermal_device_update(tz, event); store_temperature(tz, temp); thermal_zone_set_trips(tz); tz->notify_event = event; for (count = 0; count < tz->trips; count++) handle_thermal_trip(tz, count); } EXPORT_SYMBOL(thermal_zone_device_update_temp); #else static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, int delay) { if (delay > 1000) mod_delayed_work(system_freezable_power_efficient_wq, &tz->poll_queue, round_jiffies(msecs_to_jiffies(delay))); else if (delay) mod_delayed_work(system_freezable_power_efficient_wq, &tz->poll_queue, msecs_to_jiffies(delay)); else cancel_delayed_work_sync(&tz->poll_queue); } static void monitor_thermal_zone(struct thermal_zone_device *tz) { mutex_lock(&tz->lock); if (tz->passive) thermal_zone_device_set_polling(tz, tz->passive_delay); else if (tz->polling_delay) thermal_zone_device_set_polling(tz, tz->polling_delay); else thermal_zone_device_set_polling(tz, 0); mutex_unlock(&tz->lock); } 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; } mutex_lock(&tz->lock); tz->last_temperature = tz->temperature; tz->temperature = temp; mutex_unlock(&tz->lock); trace_thermal_temperature(tz); if (tz->last_temperature == THERMAL_TEMP_INVALID) dev_dbg(&tz->device, "last_temperature N/A, current_temperature=%d\n", tz->temperature); else dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n", tz->last_temperature, tz->temperature); } #endif static void handle_non_critical_trips(struct thermal_zone_device *tz, int trip) { Loading Loading @@ -393,7 +500,9 @@ static void handle_critical_trips(struct thermal_zone_device *tz, if (trip_temp <= 0 || tz->temperature < trip_temp) return; #ifdef CONFIG_QTI_THERMAL trace_thermal_zone_trip(tz, trip, trip_type, true); #endif if (tz->ops->notify) tz->ops->notify(tz, trip, trip_type); Loading Loading @@ -435,38 +544,9 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) * So, start monitoring again. */ monitor_thermal_zone(tz); #ifdef CONFIG_QTI_THERMAL trace_thermal_handle_trip(tz, trip); } static void store_temperature(struct thermal_zone_device *tz, int temp) { mutex_lock(&tz->lock); tz->last_temperature = tz->temperature; tz->temperature = temp; mutex_unlock(&tz->lock); trace_thermal_temperature(tz); if (tz->last_temperature == THERMAL_TEMP_INVALID) dev_dbg(&tz->device, "last_temperature N/A, current_temperature=%d\n", tz->temperature); else dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n", tz->last_temperature, tz->temperature); } 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; } store_temperature(tz, temp); #endif } static void thermal_zone_device_init(struct thermal_zone_device *tz) Loading @@ -483,36 +563,22 @@ static void thermal_zone_device_reset(struct thermal_zone_device *tz) thermal_zone_device_init(tz); } void thermal_zone_device_update_temp(struct thermal_zone_device *tz, enum thermal_notify_event event, int temp) { int count; if (atomic_read(&in_suspend) && tz->polling_delay) return; trace_thermal_device_update(tz, event); store_temperature(tz, temp); thermal_zone_set_trips(tz); tz->notify_event = event; for (count = 0; count < tz->trips; count++) handle_thermal_trip(tz, count); } EXPORT_SYMBOL(thermal_zone_device_update_temp); void thermal_zone_device_update(struct thermal_zone_device *tz, enum thermal_notify_event event) { int count; if (!tz->ops->get_temp) return; #ifdef CONFIG_QTI_THERMAL if (atomic_read(&in_suspend) && tz->polling_delay) return; if (!tz->ops->get_temp) trace_thermal_device_update(tz, event); #else if (atomic_read(&in_suspend)) return; #endif trace_thermal_device_update(tz, event); update_temperature(tz); thermal_zone_set_trips(tz); Loading Loading @@ -741,6 +807,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, if (ret) return ret; #ifdef CONFIG_QTI_THERMAL /* * If upper or lower has a MACRO to define the mitigation state, * based on the MACRO determine the default state to use or the Loading @@ -761,6 +828,11 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, else lower = max_state - (THERMAL_MAX_LIMIT - lower); } #else /* lower default 0, upper default max_state */ lower = lower == THERMAL_NO_LIMIT ? 0 : lower; upper = upper == THERMAL_NO_LIMIT ? max_state : upper; #endif if (lower > upper || upper > max_state) return -EINVAL; Loading Loading @@ -883,6 +955,7 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, } EXPORT_SYMBOL_GPL(thermal_zone_unbind_cooling_device); #ifdef CONFIG_QTI_THERMAL static void thermal_release(struct device *dev) { struct thermal_zone_device *tz; Loading @@ -906,6 +979,24 @@ static void thermal_release(struct device *dev) kfree(cdev); } } #else static void thermal_release(struct device *dev) { struct thermal_zone_device *tz; struct thermal_cooling_device *cdev; if (!strncmp(dev_name(dev), "thermal_zone", sizeof("thermal_zone") - 1)) { tz = to_thermal_zone(dev); thermal_zone_destroy_device_groups(tz); kfree(tz); } else if (!strncmp(dev_name(dev), "cooling_device", sizeof("cooling_device") - 1)) { cdev = to_cooling_device(dev); kfree(cdev); } } #endif static struct class thermal_class = { .name = "thermal", Loading Loading @@ -1008,7 +1099,9 @@ __thermal_cooling_device_register(struct device_node *np, struct thermal_cooling_device *cdev; struct thermal_zone_device *pos = NULL; int result; #ifdef CONFIG_QTI_THERMAL struct thermal_instance *instance; #endif if (type && strlen(type) >= THERMAL_NAME_LENGTH) return ERR_PTR(-EINVAL); Loading @@ -1021,16 +1114,20 @@ __thermal_cooling_device_register(struct device_node *np, if (!cdev) return ERR_PTR(-ENOMEM); #ifdef CONFIG_QTI_THERMAL instance = kzalloc(sizeof(*instance), GFP_KERNEL); if (!instance) { kfree(cdev); return ERR_PTR(-ENOMEM); } #endif result = ida_simple_get(&thermal_cdev_ida, 0, 0, GFP_KERNEL); if (result < 0) { kfree(cdev); #ifdef CONFIG_QTI_THERMAL kfree(instance); #endif return ERR_PTR(result); } Loading @@ -1038,8 +1135,10 @@ __thermal_cooling_device_register(struct device_node *np, strlcpy(cdev->type, type ? : "", sizeof(cdev->type)); mutex_init(&cdev->lock); INIT_LIST_HEAD(&cdev->thermal_instances); #ifdef CONFIG_QTI_THERMAL instance->target = THERMAL_NO_TARGET; list_add_tail(&instance->cdev_node, &cdev->thermal_instances); #endif cdev->np = np; cdev->ops = ops; cdev->updated = false; Loading Loading @@ -1410,7 +1509,11 @@ thermal_zone_device_register(const char *type, int trips, int mask, /* Bind cooling devices for this zone */ bind_tz(tz); #ifdef CONFIG_QTI_THERMAL INIT_DEFERRABLE_WORK(&(tz->poll_queue), thermal_zone_device_check); #else INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check); #endif thermal_zone_device_reset(tz); /* Update the new thermal zone and mark it as already updated. */ Loading Loading @@ -1641,9 +1744,14 @@ static int thermal_pm_notify(struct notifier_block *nb, if (tz->ops->get_mode) tz->ops->get_mode(tz, &tz_mode); #ifdef CONFIG_QTI_THERMAL if (tz_mode == THERMAL_DEVICE_DISABLED || tz->polling_delay == 0) continue; #else if (tz_mode == THERMAL_DEVICE_DISABLED) continue; #endif thermal_zone_device_init(tz); thermal_zone_device_update(tz, Loading @@ -1660,6 +1768,7 @@ static struct notifier_block thermal_pm_nb = { .notifier_call = thermal_pm_notify, }; #ifdef CONFIG_QTI_THERMAL static int __init thermal_init(void) { int result; Loading Loading @@ -1737,3 +1846,48 @@ static int __init thermal_netlink_init(void) subsys_initcall(thermal_init); fs_initcall(thermal_netlink_init); #else static int __init thermal_init(void) { int result; mutex_init(&poweroff_lock); result = thermal_register_governors(); if (result) goto error; result = class_register(&thermal_class); if (result) goto unregister_governors; result = genetlink_init(); if (result) goto unregister_class; result = of_parse_thermal_zones(); if (result) goto exit_netlink; result = register_pm_notifier(&thermal_pm_nb); if (result) pr_warn("Thermal: Can not register suspend notifier, return %d\n", result); return 0; exit_netlink: genetlink_exit(); unregister_class: class_unregister(&thermal_class); unregister_governors: thermal_unregister_governors(); error: ida_destroy(&thermal_tz_ida); ida_destroy(&thermal_cdev_ida); mutex_destroy(&thermal_list_lock); mutex_destroy(&thermal_governor_lock); mutex_destroy(&poweroff_lock); return result; } fs_initcall(thermal_init); #endif
drivers/thermal/thermal_core.h +9 −6 Original line number Diff line number Diff line Loading @@ -98,12 +98,6 @@ int of_thermal_get_ntrips(struct thermal_zone_device *); bool of_thermal_is_trip_valid(struct thermal_zone_device *, int); const struct thermal_trip * of_thermal_get_trip_points(struct thermal_zone_device *); int of_thermal_aggregate_trip(struct thermal_zone_device *tz, enum thermal_trip_type type, int *low, int *high); void of_thermal_handle_trip(struct thermal_zone_device *tz); void of_thermal_handle_trip_temp(struct thermal_zone_device *tz, int trip_temp); #else static inline int of_parse_thermal_zones(void) { return 0; } static inline void of_thermal_destroy_zones(void) { } Loading @@ -121,6 +115,15 @@ of_thermal_get_trip_points(struct thermal_zone_device *tz) { return NULL; } #endif #if (defined(CONFIG_QTI_THERMAL) && defined(CONFIG_THERMAL_OF)) int of_thermal_aggregate_trip(struct thermal_zone_device *tz, enum thermal_trip_type type, int *low, int *high); void of_thermal_handle_trip(struct thermal_zone_device *tz); void of_thermal_handle_trip_temp(struct thermal_zone_device *tz, int trip_temp); #else static inline int of_thermal_aggregate_trip(struct thermal_zone_device *tz, enum thermal_trip_type type, int *low, int *high) Loading
drivers/thermal/thermal_helpers.c +14 −0 Original line number Diff line number Diff line Loading @@ -107,7 +107,9 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp) if (!ret && *temp < crit_temp) *temp = tz->emul_temperature; } #ifdef CONFIG_QTI_THERMAL trace_thermal_query_temp(tz, *temp); #endif mutex_unlock(&tz->lock); exit: return ret; Loading Loading @@ -141,6 +143,11 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz) high = trip_temp; } #ifndef CONFIG_QTI_THERMAL /* No need to change trip points */ if (tz->prev_low_trip == low && tz->prev_high_trip == high) goto exit; #endif tz->prev_low_trip = low; tz->prev_high_trip = high; Loading @@ -154,7 +161,9 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz) ret = tz->ops->set_trips(tz, low, high); if (ret) dev_err(&tz->device, "Failed to set trips: %d\n", ret); #ifdef CONFIG_QTI_THERMAL trace_thermal_set_trip(tz); #endif exit: mutex_unlock(&tz->lock); Loading @@ -175,6 +184,7 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev) /* Make sure cdev enters the deepest cooling state */ list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) { #ifdef CONFIG_QTI_THERMAL if (list_is_first(&instance->cdev_node, &cdev->thermal_instances)) dev_dbg(&cdev->device, "userspace->target=%lu\n", Loading @@ -182,6 +192,10 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev) else dev_dbg(&cdev->device, "zone%d->target=%lu\n", instance->tz->id, instance->target); #else dev_dbg(&cdev->device, "zone%d->target=%lu\n", instance->tz->id, instance->target); #endif if (instance->target == THERMAL_NO_TARGET) continue; if (instance->target > target) Loading