Thermal control fixes for 6.13-rc4

Fix two issues with the user thermal thresholds feature introduced
 in this development cycle (Daniel Lezcano).
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEE4fcc61cGeeHD/fCwgsRv/nhiVHEFAmdl1h4SHHJqd0Byand5
 c29ja2kubmV0AAoJEILEb/54YlRxCYoP/iPLKylOVCn1/PjzEfYSVDkGdOQEusRo
 Abwq0agYbyAPsWGOXgGVRUpHFh2otpTKM2W77Q3YNs7DmgeHAPUAxx1uhy+c3d2N
 dlGpj8ZdQrBWE+98SdMsooMb9+GMMX94nTXng9qvlpKFqSyjVM9oUuLsOu/vshkf
 esWmLQlnmCaenW7cEaL/xV3izRLJBrdvq+SFa7Rh991VzhV24n7ucItctTJKzJHN
 ZqH+pSvcFU2Kr2Quf3GnoY+HHfY3691lSpT+HwLEm3IdMrk3opt5pCxM8eA1D4Cn
 nHYOVRfyW54ZDBSNP1upUMJq77cBQRxzMZCGjPxyH75qzC4qwVJZhLShetPOe37i
 doQssU/TkYedR+p/z6EQBqA4LukUoYRl8tGyD+5WxKEzj0QlBAxFRsmVrFln4CMf
 pIlKTB9ZYyXVUBd7iMSMTF0tqp+GTd6FF6v5N7bmH72LQbMX3anmXEzS41suDENE
 tuFSM1j3n6EYkrWhKnqezRyh5OPVYfo55p2GTN1OgETb+k/kB/uQQZHnscvx/SDC
 GkNsAIIkLvUIWpYldfh+CRW2xX+jvZ1Ys7Hn3iVKf2RDYB6LO4Xk3n1E85mGcp3S
 rzIl2hdj2+v6iL6fsDgF2SM09DmC3GTlvTsVENhpZ9sYWIPuAaCAEYAcg1q+oLGC
 GLKuPwzgics0
 =O+vp
 -----END PGP SIGNATURE-----

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

Pull thermal control fixes from Rafael Wysocki:
 "Fix two issues with the user thermal thresholds feature introduced in
  this development cycle (Daniel Lezcano)"

* tag 'thermal-6.13-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  thermal/thresholds: Fix boundaries and detection routine
  thermal/thresholds: Fix uapi header macros leading to a compilation error
This commit is contained in:
Linus Torvalds 2024-12-21 10:44:44 -08:00
commit be6bb3619e
2 changed files with 42 additions and 38 deletions

View File

@ -69,40 +69,18 @@ static struct user_threshold *__thermal_thresholds_find(const struct list_head *
return NULL;
}
static bool __thermal_threshold_is_crossed(struct user_threshold *threshold, int temperature,
int last_temperature, int direction,
int *low, int *high)
{
if (temperature >= threshold->temperature) {
if (threshold->temperature > *low &&
THERMAL_THRESHOLD_WAY_DOWN & threshold->direction)
*low = threshold->temperature;
if (last_temperature < threshold->temperature &&
threshold->direction & direction)
return true;
} else {
if (threshold->temperature < *high && THERMAL_THRESHOLD_WAY_UP
& threshold->direction)
*high = threshold->temperature;
if (last_temperature >= threshold->temperature &&
threshold->direction & direction)
return true;
}
return false;
}
static bool thermal_thresholds_handle_raising(struct list_head *thresholds, int temperature,
int last_temperature, int *low, int *high)
int last_temperature)
{
struct user_threshold *t;
list_for_each_entry(t, thresholds, list_node) {
if (__thermal_threshold_is_crossed(t, temperature, last_temperature,
THERMAL_THRESHOLD_WAY_UP, low, high))
if (!(t->direction & THERMAL_THRESHOLD_WAY_UP))
continue;
if (temperature >= t->temperature &&
last_temperature < t->temperature)
return true;
}
@ -110,19 +88,43 @@ static bool thermal_thresholds_handle_raising(struct list_head *thresholds, int
}
static bool thermal_thresholds_handle_dropping(struct list_head *thresholds, int temperature,
int last_temperature, int *low, int *high)
int last_temperature)
{
struct user_threshold *t;
list_for_each_entry_reverse(t, thresholds, list_node) {
if (__thermal_threshold_is_crossed(t, temperature, last_temperature,
THERMAL_THRESHOLD_WAY_DOWN, low, high))
if (!(t->direction & THERMAL_THRESHOLD_WAY_DOWN))
continue;
if (temperature <= t->temperature &&
last_temperature > t->temperature)
return true;
}
return false;
}
static void thermal_threshold_find_boundaries(struct list_head *thresholds, int temperature,
int *low, int *high)
{
struct user_threshold *t;
list_for_each_entry(t, thresholds, list_node) {
if (temperature < t->temperature &&
(t->direction & THERMAL_THRESHOLD_WAY_UP) &&
*high > t->temperature)
*high = t->temperature;
}
list_for_each_entry_reverse(t, thresholds, list_node) {
if (temperature > t->temperature &&
(t->direction & THERMAL_THRESHOLD_WAY_DOWN) &&
*low < t->temperature)
*low = t->temperature;
}
}
void thermal_thresholds_handle(struct thermal_zone_device *tz, int *low, int *high)
{
struct list_head *thresholds = &tz->user_thresholds;
@ -132,6 +134,8 @@ void thermal_thresholds_handle(struct thermal_zone_device *tz, int *low, int *hi
lockdep_assert_held(&tz->lock);
thermal_threshold_find_boundaries(thresholds, temperature, low, high);
/*
* We need a second update in order to detect a threshold being crossed
*/
@ -151,12 +155,12 @@ void thermal_thresholds_handle(struct thermal_zone_device *tz, int *low, int *hi
* - decreased : thresholds are crossed the way down
*/
if (temperature > last_temperature) {
if (thermal_thresholds_handle_raising(thresholds, temperature,
last_temperature, low, high))
if (thermal_thresholds_handle_raising(thresholds,
temperature, last_temperature))
thermal_notify_threshold_up(tz);
} else {
if (thermal_thresholds_handle_dropping(thresholds, temperature,
last_temperature, low, high))
if (thermal_thresholds_handle_dropping(thresholds,
temperature, last_temperature))
thermal_notify_threshold_down(tz);
}
}

View File

@ -3,8 +3,8 @@
#define _UAPI_LINUX_THERMAL_H
#define THERMAL_NAME_LENGTH 20
#define THERMAL_THRESHOLD_WAY_UP BIT(0)
#define THERMAL_THRESHOLD_WAY_DOWN BIT(1)
#define THERMAL_THRESHOLD_WAY_UP 0x1
#define THERMAL_THRESHOLD_WAY_DOWN 0x2
enum thermal_device_mode {
THERMAL_DEVICE_DISABLED = 0,