Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'thermal-6.11-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull thermal control fix from Rafael Wysocki:
"Fix a Bang-bang thermal governor issue causing it to fail to reset the
state of cooling devices if they are 'on' to start with, but the
thermal zone temperature is always below the corresponding trip point
(Rafael Wysocki)"

* tag 'thermal-6.11-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
thermal: gov_bang_bang: Use governor_data to reduce overhead
thermal: gov_bang_bang: Add .manage() callback
thermal: gov_bang_bang: Split bang_bang_control()
thermal: gov_bang_bang: Call __thermal_cdev_update() directly

+69 -18
+66 -17
drivers/thermal/gov_bang_bang.c
··· 13 13 14 14 #include "thermal_core.h" 15 15 16 + static void bang_bang_set_instance_target(struct thermal_instance *instance, 17 + unsigned int target) 18 + { 19 + if (instance->target != 0 && instance->target != 1 && 20 + instance->target != THERMAL_NO_TARGET) 21 + pr_debug("Unexpected state %ld of thermal instance %s in bang-bang\n", 22 + instance->target, instance->name); 23 + 24 + /* 25 + * Enable the fan when the trip is crossed on the way up and disable it 26 + * when the trip is crossed on the way down. 27 + */ 28 + instance->target = target; 29 + instance->initialized = true; 30 + 31 + dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target); 32 + 33 + mutex_lock(&instance->cdev->lock); 34 + __thermal_cdev_update(instance->cdev); 35 + mutex_unlock(&instance->cdev->lock); 36 + } 37 + 16 38 /** 17 39 * bang_bang_control - controls devices associated with the given zone 18 40 * @tz: thermal_zone_device ··· 76 54 tz->temperature, trip->hysteresis); 77 55 78 56 list_for_each_entry(instance, &tz->thermal_instances, tz_node) { 79 - if (instance->trip != trip) 57 + if (instance->trip == trip) 58 + bang_bang_set_instance_target(instance, crossed_up); 59 + } 60 + } 61 + 62 + static void bang_bang_manage(struct thermal_zone_device *tz) 63 + { 64 + const struct thermal_trip_desc *td; 65 + struct thermal_instance *instance; 66 + 67 + /* If the code below has run already, nothing needs to be done. */ 68 + if (tz->governor_data) 69 + return; 70 + 71 + for_each_trip_desc(tz, td) { 72 + const struct thermal_trip *trip = &td->trip; 73 + 74 + if (tz->temperature >= td->threshold || 75 + trip->temperature == THERMAL_TEMP_INVALID || 76 + trip->type == THERMAL_TRIP_CRITICAL || 77 + trip->type == THERMAL_TRIP_HOT) 80 78 continue; 81 79 82 - if (instance->target != 0 && instance->target != 1 && 83 - instance->target != THERMAL_NO_TARGET) 84 - pr_debug("Unexpected state %ld of thermal instance %s in bang-bang\n", 85 - instance->target, instance->name); 86 - 87 80 /* 88 - * Enable the fan when the trip is crossed on the way up and 89 - * disable it when the trip is crossed on the way down. 81 + * If the initial cooling device state is "on", but the zone 82 + * temperature is not above the trip point, the core will not 83 + * call bang_bang_control() until the zone temperature reaches 84 + * the trip point temperature which may be never. In those 85 + * cases, set the initial state of the cooling device to 0. 90 86 */ 91 - instance->target = crossed_up; 92 - 93 - dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target); 94 - 95 - mutex_lock(&instance->cdev->lock); 96 - instance->cdev->updated = false; /* cdev needs update */ 97 - mutex_unlock(&instance->cdev->lock); 87 + list_for_each_entry(instance, &tz->thermal_instances, tz_node) { 88 + if (!instance->initialized && instance->trip == trip) 89 + bang_bang_set_instance_target(instance, 0); 90 + } 98 91 } 99 92 100 - list_for_each_entry(instance, &tz->thermal_instances, tz_node) 101 - thermal_cdev_update(instance->cdev); 93 + tz->governor_data = (void *)true; 94 + } 95 + 96 + static void bang_bang_update_tz(struct thermal_zone_device *tz, 97 + enum thermal_notify_event reason) 98 + { 99 + /* 100 + * Let bang_bang_manage() know that it needs to walk trips after binding 101 + * a new cdev and after system resume. 102 + */ 103 + if (reason == THERMAL_TZ_BIND_CDEV || reason == THERMAL_TZ_RESUME) 104 + tz->governor_data = NULL; 102 105 } 103 106 104 107 static struct thermal_governor thermal_gov_bang_bang = { 105 108 .name = "bang_bang", 106 109 .trip_crossed = bang_bang_control, 110 + .manage = bang_bang_manage, 111 + .update_tz = bang_bang_update_tz, 107 112 }; 108 113 THERMAL_GOVERNOR_DECLARE(thermal_gov_bang_bang);
+2 -1
drivers/thermal/thermal_core.c
··· 1728 1728 1729 1729 thermal_debug_tz_resume(tz); 1730 1730 thermal_zone_device_init(tz); 1731 - __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); 1731 + thermal_governor_update_tz(tz, THERMAL_TZ_RESUME); 1732 + __thermal_zone_device_update(tz, THERMAL_TZ_RESUME); 1732 1733 1733 1734 complete(&tz->resume); 1734 1735 tz->resuming = false;
+1
include/linux/thermal.h
··· 55 55 THERMAL_TZ_BIND_CDEV, /* Cooling dev is bind to the thermal zone */ 56 56 THERMAL_TZ_UNBIND_CDEV, /* Cooling dev is unbind from the thermal zone */ 57 57 THERMAL_INSTANCE_WEIGHT_CHANGED, /* Thermal instance weight changed */ 58 + THERMAL_TZ_RESUME, /* Thermal zone is resuming after system sleep */ 58 59 }; 59 60 60 61 /**