diff options
author | Justin Hibbits <jhibbits@FreeBSD.org> | 2015-02-20 06:19:23 +0000 |
---|---|---|
committer | Justin Hibbits <jhibbits@FreeBSD.org> | 2015-02-20 06:19:23 +0000 |
commit | 7f745b2b49629390398fe094648426cedd576115 (patch) | |
tree | b399c56f44d618ba1483a64585a20939c1f455dd /sys/powerpc/powermac | |
parent | 976a0ea071096821513367a7c5535326b914e29a (diff) |
Make the PowerMac fan control nonlinear
Summary:
Currently, fan control is linear between the target temperature and max
temperature, which is far from ideal. This changes it to be proportional to the
distance between the current temperature and the two endpoints (target and max
temp). This also adds a hysteresis, so that fans keep going when the
temperature drops, for about 10 seconds, before slowing down.
Reviewers: nwhitehorn
Reviewed By: nwhitehorn
Differential Revision: https://reviews.freebsd.org/D1549
MFC after: 3 weeks
Notes
Notes:
svn path=/head/; revision=279045
Diffstat (limited to 'sys/powerpc/powermac')
-rw-r--r-- | sys/powerpc/powermac/powermac_thermal.c | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/sys/powerpc/powermac/powermac_thermal.c b/sys/powerpc/powermac/powermac_thermal.c index 8b9462c5a06e..250c9f0922ac 100644 --- a/sys/powerpc/powermac/powermac_thermal.c +++ b/sys/powerpc/powermac/powermac_thermal.c @@ -42,6 +42,9 @@ __FBSDID("$FreeBSD$"); #include "powermac_thermal.h" +/* A 10 second timer for spinning down fans. */ +#define FAN_HYSTERESIS_TIMER 10 + static void fan_management_proc(void); static void pmac_therm_manage_fans(void); @@ -63,6 +66,7 @@ static MALLOC_DEFINE(M_PMACTHERM, "pmactherm", "Powermac Thermal Management"); struct pmac_fan_le { struct pmac_fan *fan; int last_val; + int timer; SLIST_ENTRY(pmac_fan_le) entries; }; struct pmac_sens_le { @@ -95,6 +99,7 @@ pmac_therm_manage_fans(void) struct pmac_sens_le *sensor; struct pmac_fan_le *fan; int average_excess, max_excess_zone, frac_excess; + int fan_speed; int nsens, nsens_zone; int temp; @@ -137,10 +142,11 @@ pmac_therm_manage_fans(void) nsens = nsens_zone = 0; average_excess = max_excess_zone = 0; SLIST_FOREACH(sensor, &sensors, entries) { - frac_excess = (sensor->last_val - + temp = imin(sensor->last_val, + sensor->sensor->max_temp); + frac_excess = (temp - sensor->sensor->target_temp)*100 / - (sensor->sensor->max_temp - - sensor->sensor->target_temp); + (sensor->sensor->max_temp - temp + 1); if (frac_excess < 0) frac_excess = 0; if (sensor->sensor->zone == fan->fan->zone) { @@ -166,9 +172,21 @@ pmac_therm_manage_fans(void) * Scale the fan linearly in the max temperature in its * thermal zone. */ - fan->fan->set(fan->fan, max_excess_zone * + max_excess_zone = imin(max_excess_zone, 100); + fan_speed = max_excess_zone * (fan->fan->max_rpm - fan->fan->min_rpm)/100 + - fan->fan->min_rpm); + fan->fan->min_rpm; + if (fan_speed >= fan->last_val) { + fan->timer = FAN_HYSTERESIS_TIMER; + fan->last_val = fan_speed; + } else { + fan->timer--; + if (fan->timer == 0) { + fan->last_val = fan_speed; + fan->timer = FAN_HYSTERESIS_TIMER; + } + } + fan->fan->set(fan->fan, fan->last_val); } } |