Loading drivers/thermal/gov_bang_bang.c +38 −59 Original line number Diff line number Diff line Loading @@ -13,60 +13,11 @@ #include "thermal_core.h" static int thermal_zone_trip_update(struct thermal_zone_device *tz, const struct thermal_trip *trip) { int trip_index = thermal_zone_trip_id(tz, trip); struct thermal_instance *instance; if (!trip->hysteresis) dev_info_once(&tz->device, "Zero hysteresis value for thermal zone %s\n", tz->type); dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n", trip_index, trip->temperature, tz->temperature, trip->hysteresis); list_for_each_entry(instance, &tz->thermal_instances, tz_node) { if (instance->trip != trip) continue; /* in case fan is in initial state, switch the fan off */ if (instance->target == THERMAL_NO_TARGET) instance->target = 0; /* in case fan is neither on nor off set the fan to active */ if (instance->target != 0 && instance->target != 1) { pr_warn("Thermal instance %s controlled by bang-bang has unexpected state: %ld\n", instance->name, instance->target); instance->target = 1; } /* * enable fan when temperature exceeds trip_temp and disable * the fan in case it falls below trip_temp minus hysteresis */ if (instance->target == 0 && tz->temperature >= trip->temperature) instance->target = 1; else if (instance->target == 1 && tz->temperature < trip->temperature - trip->hysteresis) instance->target = 0; dev_dbg(&instance->cdev->device, "target=%d\n", (int)instance->target); mutex_lock(&instance->cdev->lock); instance->cdev->updated = false; /* cdev needs update */ mutex_unlock(&instance->cdev->lock); } return 0; } /** * bang_bang_control - controls devices associated with the given zone * @tz: thermal_zone_device * @trip: the trip point * @crossed_up: whether or not the trip has been crossed on the way up * * Regulation Logic: a two point regulation, deliver cooling state depending * on the previous state shown in this diagram: Loading @@ -90,26 +41,54 @@ static int thermal_zone_trip_update(struct thermal_zone_device *tz, * (trip_temp - hyst) so that the fan gets turned off again. * */ static int bang_bang_control(struct thermal_zone_device *tz, const struct thermal_trip *trip) static void bang_bang_control(struct thermal_zone_device *tz, const struct thermal_trip *trip, bool crossed_up) { struct thermal_instance *instance; int ret; lockdep_assert_held(&tz->lock); ret = thermal_zone_trip_update(tz, trip); if (ret) return ret; dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n", thermal_zone_trip_id(tz, trip), trip->temperature, tz->temperature, trip->hysteresis); list_for_each_entry(instance, &tz->thermal_instances, tz_node) { if (instance->trip != trip) continue; if (instance->target == THERMAL_NO_TARGET) instance->target = 0; if (instance->target != 0 && instance->target != 1) { pr_debug("Unexpected state %ld of thermal instance %s in bang-bang\n", instance->target, instance->name); instance->target = 1; } /* * Enable the fan when the trip is crossed on the way up and * disable it when the trip is crossed on the way down. */ if (instance->target == 0 && crossed_up) instance->target = 1; else if (instance->target == 1 && !crossed_up) instance->target = 0; dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target); mutex_lock(&instance->cdev->lock); instance->cdev->updated = false; /* cdev needs update */ mutex_unlock(&instance->cdev->lock); } list_for_each_entry(instance, &tz->thermal_instances, tz_node) thermal_cdev_update(instance->cdev); return 0; } static struct thermal_governor thermal_gov_bang_bang = { .name = "bang_bang", .throttle = bang_bang_control, .trip_crossed = bang_bang_control, }; THERMAL_GOVERNOR_DECLARE(thermal_gov_bang_bang); drivers/thermal/gov_fair_share.c +48 −34 Original line number Diff line number Diff line Loading @@ -17,97 +17,111 @@ static int get_trip_level(struct thermal_zone_device *tz) { const struct thermal_trip *trip, *level_trip = NULL; const struct thermal_trip_desc *level_td = NULL; const struct thermal_trip_desc *td; int trip_level = -1; for_each_trip(tz, trip) { if (trip->temperature >= tz->temperature) for_each_trip_desc(tz, td) { if (td->threshold > tz->temperature) continue; trip_level++; if (!level_trip || trip->temperature > level_trip->temperature) level_trip = trip; if (!level_td || td->threshold > level_td->threshold) level_td = td; } /* Bail out if the temperature is not greater than any trips. */ if (trip_level < 0) return 0; trace_thermal_zone_trip(tz, thermal_zone_trip_id(tz, level_trip), level_trip->type); trace_thermal_zone_trip(tz, thermal_zone_trip_id(tz, &level_td->trip), level_td->trip.type); return trip_level; } static long get_target_state(struct thermal_zone_device *tz, struct thermal_cooling_device *cdev, int percentage, int level) { return (long)(percentage * level * cdev->max_state) / (100 * tz->num_trips); } /** * fair_share_throttle - throttles devices associated with the given zone * @tz: thermal_zone_device * @trip: trip point * @trip_level: number of trips crossed by the zone temperature * * Throttling Logic: This uses three parameters to calculate the new * throttle state of the cooling devices associated with the given zone. * * Parameters used for Throttling: * P1. max_state: Maximum throttle state exposed by the cooling device. * P2. percentage[i]/100: * P2. weight[i]/total_weight: * How 'effective' the 'i'th device is, in cooling the given zone. * P3. cur_trip_level/max_no_of_trips: * P3. trip_level/max_no_of_trips: * This describes the extent to which the devices should be throttled. * We do not want to throttle too much when we trip a lower temperature, * whereas the throttling is at full swing if we trip critical levels. * (Heavily assumes the trip points are in ascending order) * new_state of cooling device = P3 * P2 * P1 */ static int fair_share_throttle(struct thermal_zone_device *tz, const struct thermal_trip *trip) static void fair_share_throttle(struct thermal_zone_device *tz, const struct thermal_trip *trip, int trip_level) { struct thermal_instance *instance; int total_weight = 0; int total_instance = 0; int cur_trip_level = get_trip_level(tz); lockdep_assert_held(&tz->lock); int nr_instances = 0; list_for_each_entry(instance, &tz->thermal_instances, tz_node) { if (instance->trip != trip) continue; total_weight += instance->weight; total_instance++; nr_instances++; } list_for_each_entry(instance, &tz->thermal_instances, tz_node) { int percentage; struct thermal_cooling_device *cdev = instance->cdev; u64 dividend; u32 divisor; if (instance->trip != trip) continue; if (!total_weight) percentage = 100 / total_instance; else percentage = (instance->weight * 100) / total_weight; instance->target = get_target_state(tz, cdev, percentage, cur_trip_level); dividend = trip_level; dividend *= cdev->max_state; divisor = tz->num_trips; if (total_weight) { dividend *= instance->weight; divisor *= total_weight; } else { divisor *= nr_instances; } instance->target = div_u64(dividend, divisor); mutex_lock(&cdev->lock); __thermal_cdev_update(cdev); mutex_unlock(&cdev->lock); } } return 0; static void fair_share_manage(struct thermal_zone_device *tz) { int trip_level = get_trip_level(tz); const struct thermal_trip_desc *td; lockdep_assert_held(&tz->lock); for_each_trip_desc(tz, td) { const struct thermal_trip *trip = &td->trip; if (trip->temperature == THERMAL_TEMP_INVALID || trip->type == THERMAL_TRIP_CRITICAL || trip->type == THERMAL_TRIP_HOT) continue; fair_share_throttle(tz, trip, trip_level); } } static struct thermal_governor thermal_gov_fair_share = { .name = "fair_share", .throttle = fair_share_throttle, .manage = fair_share_manage, }; THERMAL_GOVERNOR_DECLARE(thermal_gov_fair_share); drivers/thermal/gov_power_allocator.c +13 −24 Original line number Diff line number Diff line Loading @@ -395,7 +395,7 @@ static void divvy_up_power(struct power_actor *power, int num_actors, } } static int allocate_power(struct thermal_zone_device *tz, int control_temp) static void allocate_power(struct thermal_zone_device *tz, int control_temp) { struct power_allocator_params *params = tz->governor_data; unsigned int num_actors = params->num_actors; Loading @@ -410,7 +410,7 @@ static int allocate_power(struct thermal_zone_device *tz, int control_temp) int i = 0, ret; if (!num_actors) return -ENODEV; return; /* Clean all buffers for new power estimations */ memset(power, 0, params->buffer_size); Loading Loading @@ -471,8 +471,6 @@ static int allocate_power(struct thermal_zone_device *tz, int control_temp) num_actors, power_range, max_allocatable_power, tz->temperature, control_temp - tz->temperature); return 0; } /** Loading @@ -496,9 +494,11 @@ static void get_governor_trips(struct thermal_zone_device *tz, const struct thermal_trip *first_passive = NULL; const struct thermal_trip *last_passive = NULL; const struct thermal_trip *last_active = NULL; const struct thermal_trip *trip; const struct thermal_trip_desc *td; for_each_trip_desc(tz, td) { const struct thermal_trip *trip = &td->trip; for_each_trip(tz, trip) { switch (trip->type) { case THERMAL_TRIP_PASSIVE: if (!first_passive) { Loading Loading @@ -743,40 +743,29 @@ static void power_allocator_unbind(struct thermal_zone_device *tz) tz->governor_data = NULL; } static int power_allocator_throttle(struct thermal_zone_device *tz, const struct thermal_trip *trip) static void power_allocator_manage(struct thermal_zone_device *tz) { struct power_allocator_params *params = tz->governor_data; bool update; const struct thermal_trip *trip = params->trip_switch_on; lockdep_assert_held(&tz->lock); /* * We get called for every trip point but we only need to do * our calculations once */ if (trip != params->trip_max) return 0; trip = params->trip_switch_on; if (trip && tz->temperature < trip->temperature) { update = tz->passive; tz->passive = 0; reset_pid_controller(params); allow_maximum_power(tz, update); return 0; allow_maximum_power(tz, tz->passive); tz->passive = 0; return; } allocate_power(tz, params->trip_max->temperature); tz->passive = 1; return allocate_power(tz, params->trip_max->temperature); } static struct thermal_governor thermal_gov_power_allocator = { .name = "power_allocator", .bind_to_tz = power_allocator_bind, .unbind_from_tz = power_allocator_unbind, .throttle = power_allocator_throttle, .manage = power_allocator_manage, .update_tz = power_allocator_update_tz, }; THERMAL_GOVERNOR_DECLARE(thermal_gov_power_allocator); drivers/thermal/gov_step_wise.c +48 −52 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ static unsigned long get_target_state(struct thermal_instance *instance, { 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. Loading @@ -40,112 +39,109 @@ static unsigned long get_target_state(struct thermal_instance *instance, * 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 = clamp((cur_state + 1), instance->lower, instance->upper); } else { next_target = THERMAL_NO_TARGET; } if (throttle) return clamp(cur_state + 1, instance->lower, instance->upper); return next_target; return THERMAL_NO_TARGET; } if (throttle) { if (trend == THERMAL_TREND_RAISING) next_target = clamp((cur_state + 1), instance->lower, instance->upper); } else { if (trend == THERMAL_TREND_DROPPING) { return clamp(cur_state + 1, instance->lower, instance->upper); } else if (trend == THERMAL_TREND_DROPPING) { if (cur_state <= instance->lower) next_target = THERMAL_NO_TARGET; else next_target = clamp((cur_state - 1), instance->lower, instance->upper); } return THERMAL_NO_TARGET; return clamp(cur_state - 1, instance->lower, instance->upper); } return next_target; return instance->target; } static void thermal_zone_trip_update(struct thermal_zone_device *tz, const struct thermal_trip *trip) const struct thermal_trip *trip, int trip_threshold) { enum thermal_trend trend = get_tz_trend(tz, trip); int trip_id = thermal_zone_trip_id(tz, trip); enum thermal_trend trend; struct thermal_instance *instance; bool throttle = false; int old_target; trend = get_tz_trend(tz, trip); if (tz->temperature >= trip->temperature) { if (tz->temperature >= trip_threshold) { throttle = true; trace_thermal_zone_trip(tz, trip_id, trip->type); } dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n", trip_id, trip->type, trip->temperature, trend, throttle); trip_id, trip->type, trip_threshold, trend, throttle); list_for_each_entry(instance, &tz->thermal_instances, tz_node) { int old_target; 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); dev_dbg(&instance->cdev->device, "old_target=%d, target=%ld\n", old_target, instance->target); if (instance->initialized && old_target == instance->target) continue; if (trip->type == THERMAL_TRIP_PASSIVE) { /* If needed, update the status of passive polling. */ if (old_target == THERMAL_NO_TARGET && instance->target != THERMAL_NO_TARGET) { /* Activate a passive thermal instance */ if (trip->type == THERMAL_TRIP_PASSIVE) instance->target != THERMAL_NO_TARGET) tz->passive++; } else if (old_target != THERMAL_NO_TARGET && instance->target == THERMAL_NO_TARGET) { /* Deactivate a passive thermal instance */ if (trip->type == THERMAL_TRIP_PASSIVE) else if (old_target != THERMAL_NO_TARGET && instance->target == THERMAL_NO_TARGET) tz->passive--; } instance->initialized = true; mutex_lock(&instance->cdev->lock); instance->cdev->updated = false; /* cdev needs update */ mutex_unlock(&instance->cdev->lock); } } /** * step_wise_throttle - throttles devices associated with the given zone * @tz: thermal_zone_device * @trip: trip point * * Throttling Logic: This uses the trend of the thermal zone to throttle. * If the thermal zone is 'heating up' this throttles all the cooling * devices associated with the zone and its particular trip point, by one * step. If the zone is 'cooling down' it brings back the performance of * the devices by one step. */ static int step_wise_throttle(struct thermal_zone_device *tz, const struct thermal_trip *trip) static void step_wise_manage(struct thermal_zone_device *tz) { const struct thermal_trip_desc *td; struct thermal_instance *instance; lockdep_assert_held(&tz->lock); thermal_zone_trip_update(tz, trip); /* * Throttling Logic: Use the trend of the thermal zone to throttle. * If the thermal zone is 'heating up', throttle all of the cooling * devices associated with each trip point by one step. If the zone * is 'cooling down', it brings back the performance of the devices * by one step. */ for_each_trip_desc(tz, td) { const struct thermal_trip *trip = &td->trip; if (trip->temperature == THERMAL_TEMP_INVALID || trip->type == THERMAL_TRIP_CRITICAL || trip->type == THERMAL_TRIP_HOT) continue; thermal_zone_trip_update(tz, trip, td->threshold); } list_for_each_entry(instance, &tz->thermal_instances, tz_node) thermal_cdev_update(instance->cdev); return 0; } static struct thermal_governor thermal_gov_step_wise = { .name = "step_wise", .throttle = step_wise_throttle, .manage = step_wise_manage, }; THERMAL_GOVERNOR_DECLARE(thermal_gov_step_wise); drivers/thermal/gov_user_space.c +5 −5 Original line number Diff line number Diff line Loading @@ -26,11 +26,13 @@ static int user_space_bind(struct thermal_zone_device *tz) * notify_user_space - Notifies user space about thermal events * @tz: thermal_zone_device * @trip: trip point * @crossed_up: whether or not the trip has been crossed on the way up * * This function notifies the user space through UEvents. */ static int notify_user_space(struct thermal_zone_device *tz, const struct thermal_trip *trip) static void notify_user_space(struct thermal_zone_device *tz, const struct thermal_trip *trip, bool crossed_up) { char *thermal_prop[5]; int i; Loading @@ -46,13 +48,11 @@ static int notify_user_space(struct thermal_zone_device *tz, kobject_uevent_env(&tz->device.kobj, KOBJ_CHANGE, thermal_prop); for (i = 0; i < 4; ++i) kfree(thermal_prop[i]); return 0; } static struct thermal_governor thermal_gov_user_space = { .name = "user_space", .throttle = notify_user_space, .trip_crossed = notify_user_space, .bind_to_tz = user_space_bind, }; THERMAL_GOVERNOR_DECLARE(thermal_gov_user_space); Loading
drivers/thermal/gov_bang_bang.c +38 −59 Original line number Diff line number Diff line Loading @@ -13,60 +13,11 @@ #include "thermal_core.h" static int thermal_zone_trip_update(struct thermal_zone_device *tz, const struct thermal_trip *trip) { int trip_index = thermal_zone_trip_id(tz, trip); struct thermal_instance *instance; if (!trip->hysteresis) dev_info_once(&tz->device, "Zero hysteresis value for thermal zone %s\n", tz->type); dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n", trip_index, trip->temperature, tz->temperature, trip->hysteresis); list_for_each_entry(instance, &tz->thermal_instances, tz_node) { if (instance->trip != trip) continue; /* in case fan is in initial state, switch the fan off */ if (instance->target == THERMAL_NO_TARGET) instance->target = 0; /* in case fan is neither on nor off set the fan to active */ if (instance->target != 0 && instance->target != 1) { pr_warn("Thermal instance %s controlled by bang-bang has unexpected state: %ld\n", instance->name, instance->target); instance->target = 1; } /* * enable fan when temperature exceeds trip_temp and disable * the fan in case it falls below trip_temp minus hysteresis */ if (instance->target == 0 && tz->temperature >= trip->temperature) instance->target = 1; else if (instance->target == 1 && tz->temperature < trip->temperature - trip->hysteresis) instance->target = 0; dev_dbg(&instance->cdev->device, "target=%d\n", (int)instance->target); mutex_lock(&instance->cdev->lock); instance->cdev->updated = false; /* cdev needs update */ mutex_unlock(&instance->cdev->lock); } return 0; } /** * bang_bang_control - controls devices associated with the given zone * @tz: thermal_zone_device * @trip: the trip point * @crossed_up: whether or not the trip has been crossed on the way up * * Regulation Logic: a two point regulation, deliver cooling state depending * on the previous state shown in this diagram: Loading @@ -90,26 +41,54 @@ static int thermal_zone_trip_update(struct thermal_zone_device *tz, * (trip_temp - hyst) so that the fan gets turned off again. * */ static int bang_bang_control(struct thermal_zone_device *tz, const struct thermal_trip *trip) static void bang_bang_control(struct thermal_zone_device *tz, const struct thermal_trip *trip, bool crossed_up) { struct thermal_instance *instance; int ret; lockdep_assert_held(&tz->lock); ret = thermal_zone_trip_update(tz, trip); if (ret) return ret; dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n", thermal_zone_trip_id(tz, trip), trip->temperature, tz->temperature, trip->hysteresis); list_for_each_entry(instance, &tz->thermal_instances, tz_node) { if (instance->trip != trip) continue; if (instance->target == THERMAL_NO_TARGET) instance->target = 0; if (instance->target != 0 && instance->target != 1) { pr_debug("Unexpected state %ld of thermal instance %s in bang-bang\n", instance->target, instance->name); instance->target = 1; } /* * Enable the fan when the trip is crossed on the way up and * disable it when the trip is crossed on the way down. */ if (instance->target == 0 && crossed_up) instance->target = 1; else if (instance->target == 1 && !crossed_up) instance->target = 0; dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target); mutex_lock(&instance->cdev->lock); instance->cdev->updated = false; /* cdev needs update */ mutex_unlock(&instance->cdev->lock); } list_for_each_entry(instance, &tz->thermal_instances, tz_node) thermal_cdev_update(instance->cdev); return 0; } static struct thermal_governor thermal_gov_bang_bang = { .name = "bang_bang", .throttle = bang_bang_control, .trip_crossed = bang_bang_control, }; THERMAL_GOVERNOR_DECLARE(thermal_gov_bang_bang);
drivers/thermal/gov_fair_share.c +48 −34 Original line number Diff line number Diff line Loading @@ -17,97 +17,111 @@ static int get_trip_level(struct thermal_zone_device *tz) { const struct thermal_trip *trip, *level_trip = NULL; const struct thermal_trip_desc *level_td = NULL; const struct thermal_trip_desc *td; int trip_level = -1; for_each_trip(tz, trip) { if (trip->temperature >= tz->temperature) for_each_trip_desc(tz, td) { if (td->threshold > tz->temperature) continue; trip_level++; if (!level_trip || trip->temperature > level_trip->temperature) level_trip = trip; if (!level_td || td->threshold > level_td->threshold) level_td = td; } /* Bail out if the temperature is not greater than any trips. */ if (trip_level < 0) return 0; trace_thermal_zone_trip(tz, thermal_zone_trip_id(tz, level_trip), level_trip->type); trace_thermal_zone_trip(tz, thermal_zone_trip_id(tz, &level_td->trip), level_td->trip.type); return trip_level; } static long get_target_state(struct thermal_zone_device *tz, struct thermal_cooling_device *cdev, int percentage, int level) { return (long)(percentage * level * cdev->max_state) / (100 * tz->num_trips); } /** * fair_share_throttle - throttles devices associated with the given zone * @tz: thermal_zone_device * @trip: trip point * @trip_level: number of trips crossed by the zone temperature * * Throttling Logic: This uses three parameters to calculate the new * throttle state of the cooling devices associated with the given zone. * * Parameters used for Throttling: * P1. max_state: Maximum throttle state exposed by the cooling device. * P2. percentage[i]/100: * P2. weight[i]/total_weight: * How 'effective' the 'i'th device is, in cooling the given zone. * P3. cur_trip_level/max_no_of_trips: * P3. trip_level/max_no_of_trips: * This describes the extent to which the devices should be throttled. * We do not want to throttle too much when we trip a lower temperature, * whereas the throttling is at full swing if we trip critical levels. * (Heavily assumes the trip points are in ascending order) * new_state of cooling device = P3 * P2 * P1 */ static int fair_share_throttle(struct thermal_zone_device *tz, const struct thermal_trip *trip) static void fair_share_throttle(struct thermal_zone_device *tz, const struct thermal_trip *trip, int trip_level) { struct thermal_instance *instance; int total_weight = 0; int total_instance = 0; int cur_trip_level = get_trip_level(tz); lockdep_assert_held(&tz->lock); int nr_instances = 0; list_for_each_entry(instance, &tz->thermal_instances, tz_node) { if (instance->trip != trip) continue; total_weight += instance->weight; total_instance++; nr_instances++; } list_for_each_entry(instance, &tz->thermal_instances, tz_node) { int percentage; struct thermal_cooling_device *cdev = instance->cdev; u64 dividend; u32 divisor; if (instance->trip != trip) continue; if (!total_weight) percentage = 100 / total_instance; else percentage = (instance->weight * 100) / total_weight; instance->target = get_target_state(tz, cdev, percentage, cur_trip_level); dividend = trip_level; dividend *= cdev->max_state; divisor = tz->num_trips; if (total_weight) { dividend *= instance->weight; divisor *= total_weight; } else { divisor *= nr_instances; } instance->target = div_u64(dividend, divisor); mutex_lock(&cdev->lock); __thermal_cdev_update(cdev); mutex_unlock(&cdev->lock); } } return 0; static void fair_share_manage(struct thermal_zone_device *tz) { int trip_level = get_trip_level(tz); const struct thermal_trip_desc *td; lockdep_assert_held(&tz->lock); for_each_trip_desc(tz, td) { const struct thermal_trip *trip = &td->trip; if (trip->temperature == THERMAL_TEMP_INVALID || trip->type == THERMAL_TRIP_CRITICAL || trip->type == THERMAL_TRIP_HOT) continue; fair_share_throttle(tz, trip, trip_level); } } static struct thermal_governor thermal_gov_fair_share = { .name = "fair_share", .throttle = fair_share_throttle, .manage = fair_share_manage, }; THERMAL_GOVERNOR_DECLARE(thermal_gov_fair_share);
drivers/thermal/gov_power_allocator.c +13 −24 Original line number Diff line number Diff line Loading @@ -395,7 +395,7 @@ static void divvy_up_power(struct power_actor *power, int num_actors, } } static int allocate_power(struct thermal_zone_device *tz, int control_temp) static void allocate_power(struct thermal_zone_device *tz, int control_temp) { struct power_allocator_params *params = tz->governor_data; unsigned int num_actors = params->num_actors; Loading @@ -410,7 +410,7 @@ static int allocate_power(struct thermal_zone_device *tz, int control_temp) int i = 0, ret; if (!num_actors) return -ENODEV; return; /* Clean all buffers for new power estimations */ memset(power, 0, params->buffer_size); Loading Loading @@ -471,8 +471,6 @@ static int allocate_power(struct thermal_zone_device *tz, int control_temp) num_actors, power_range, max_allocatable_power, tz->temperature, control_temp - tz->temperature); return 0; } /** Loading @@ -496,9 +494,11 @@ static void get_governor_trips(struct thermal_zone_device *tz, const struct thermal_trip *first_passive = NULL; const struct thermal_trip *last_passive = NULL; const struct thermal_trip *last_active = NULL; const struct thermal_trip *trip; const struct thermal_trip_desc *td; for_each_trip_desc(tz, td) { const struct thermal_trip *trip = &td->trip; for_each_trip(tz, trip) { switch (trip->type) { case THERMAL_TRIP_PASSIVE: if (!first_passive) { Loading Loading @@ -743,40 +743,29 @@ static void power_allocator_unbind(struct thermal_zone_device *tz) tz->governor_data = NULL; } static int power_allocator_throttle(struct thermal_zone_device *tz, const struct thermal_trip *trip) static void power_allocator_manage(struct thermal_zone_device *tz) { struct power_allocator_params *params = tz->governor_data; bool update; const struct thermal_trip *trip = params->trip_switch_on; lockdep_assert_held(&tz->lock); /* * We get called for every trip point but we only need to do * our calculations once */ if (trip != params->trip_max) return 0; trip = params->trip_switch_on; if (trip && tz->temperature < trip->temperature) { update = tz->passive; tz->passive = 0; reset_pid_controller(params); allow_maximum_power(tz, update); return 0; allow_maximum_power(tz, tz->passive); tz->passive = 0; return; } allocate_power(tz, params->trip_max->temperature); tz->passive = 1; return allocate_power(tz, params->trip_max->temperature); } static struct thermal_governor thermal_gov_power_allocator = { .name = "power_allocator", .bind_to_tz = power_allocator_bind, .unbind_from_tz = power_allocator_unbind, .throttle = power_allocator_throttle, .manage = power_allocator_manage, .update_tz = power_allocator_update_tz, }; THERMAL_GOVERNOR_DECLARE(thermal_gov_power_allocator);
drivers/thermal/gov_step_wise.c +48 −52 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ static unsigned long get_target_state(struct thermal_instance *instance, { 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. Loading @@ -40,112 +39,109 @@ static unsigned long get_target_state(struct thermal_instance *instance, * 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 = clamp((cur_state + 1), instance->lower, instance->upper); } else { next_target = THERMAL_NO_TARGET; } if (throttle) return clamp(cur_state + 1, instance->lower, instance->upper); return next_target; return THERMAL_NO_TARGET; } if (throttle) { if (trend == THERMAL_TREND_RAISING) next_target = clamp((cur_state + 1), instance->lower, instance->upper); } else { if (trend == THERMAL_TREND_DROPPING) { return clamp(cur_state + 1, instance->lower, instance->upper); } else if (trend == THERMAL_TREND_DROPPING) { if (cur_state <= instance->lower) next_target = THERMAL_NO_TARGET; else next_target = clamp((cur_state - 1), instance->lower, instance->upper); } return THERMAL_NO_TARGET; return clamp(cur_state - 1, instance->lower, instance->upper); } return next_target; return instance->target; } static void thermal_zone_trip_update(struct thermal_zone_device *tz, const struct thermal_trip *trip) const struct thermal_trip *trip, int trip_threshold) { enum thermal_trend trend = get_tz_trend(tz, trip); int trip_id = thermal_zone_trip_id(tz, trip); enum thermal_trend trend; struct thermal_instance *instance; bool throttle = false; int old_target; trend = get_tz_trend(tz, trip); if (tz->temperature >= trip->temperature) { if (tz->temperature >= trip_threshold) { throttle = true; trace_thermal_zone_trip(tz, trip_id, trip->type); } dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n", trip_id, trip->type, trip->temperature, trend, throttle); trip_id, trip->type, trip_threshold, trend, throttle); list_for_each_entry(instance, &tz->thermal_instances, tz_node) { int old_target; 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); dev_dbg(&instance->cdev->device, "old_target=%d, target=%ld\n", old_target, instance->target); if (instance->initialized && old_target == instance->target) continue; if (trip->type == THERMAL_TRIP_PASSIVE) { /* If needed, update the status of passive polling. */ if (old_target == THERMAL_NO_TARGET && instance->target != THERMAL_NO_TARGET) { /* Activate a passive thermal instance */ if (trip->type == THERMAL_TRIP_PASSIVE) instance->target != THERMAL_NO_TARGET) tz->passive++; } else if (old_target != THERMAL_NO_TARGET && instance->target == THERMAL_NO_TARGET) { /* Deactivate a passive thermal instance */ if (trip->type == THERMAL_TRIP_PASSIVE) else if (old_target != THERMAL_NO_TARGET && instance->target == THERMAL_NO_TARGET) tz->passive--; } instance->initialized = true; mutex_lock(&instance->cdev->lock); instance->cdev->updated = false; /* cdev needs update */ mutex_unlock(&instance->cdev->lock); } } /** * step_wise_throttle - throttles devices associated with the given zone * @tz: thermal_zone_device * @trip: trip point * * Throttling Logic: This uses the trend of the thermal zone to throttle. * If the thermal zone is 'heating up' this throttles all the cooling * devices associated with the zone and its particular trip point, by one * step. If the zone is 'cooling down' it brings back the performance of * the devices by one step. */ static int step_wise_throttle(struct thermal_zone_device *tz, const struct thermal_trip *trip) static void step_wise_manage(struct thermal_zone_device *tz) { const struct thermal_trip_desc *td; struct thermal_instance *instance; lockdep_assert_held(&tz->lock); thermal_zone_trip_update(tz, trip); /* * Throttling Logic: Use the trend of the thermal zone to throttle. * If the thermal zone is 'heating up', throttle all of the cooling * devices associated with each trip point by one step. If the zone * is 'cooling down', it brings back the performance of the devices * by one step. */ for_each_trip_desc(tz, td) { const struct thermal_trip *trip = &td->trip; if (trip->temperature == THERMAL_TEMP_INVALID || trip->type == THERMAL_TRIP_CRITICAL || trip->type == THERMAL_TRIP_HOT) continue; thermal_zone_trip_update(tz, trip, td->threshold); } list_for_each_entry(instance, &tz->thermal_instances, tz_node) thermal_cdev_update(instance->cdev); return 0; } static struct thermal_governor thermal_gov_step_wise = { .name = "step_wise", .throttle = step_wise_throttle, .manage = step_wise_manage, }; THERMAL_GOVERNOR_DECLARE(thermal_gov_step_wise);
drivers/thermal/gov_user_space.c +5 −5 Original line number Diff line number Diff line Loading @@ -26,11 +26,13 @@ static int user_space_bind(struct thermal_zone_device *tz) * notify_user_space - Notifies user space about thermal events * @tz: thermal_zone_device * @trip: trip point * @crossed_up: whether or not the trip has been crossed on the way up * * This function notifies the user space through UEvents. */ static int notify_user_space(struct thermal_zone_device *tz, const struct thermal_trip *trip) static void notify_user_space(struct thermal_zone_device *tz, const struct thermal_trip *trip, bool crossed_up) { char *thermal_prop[5]; int i; Loading @@ -46,13 +48,11 @@ static int notify_user_space(struct thermal_zone_device *tz, kobject_uevent_env(&tz->device.kobj, KOBJ_CHANGE, thermal_prop); for (i = 0; i < 4; ++i) kfree(thermal_prop[i]); return 0; } static struct thermal_governor thermal_gov_user_space = { .name = "user_space", .throttle = notify_user_space, .trip_crossed = notify_user_space, .bind_to_tz = user_space_bind, }; THERMAL_GOVERNOR_DECLARE(thermal_gov_user_space);