aboutsummaryrefslogtreecommitdiff
path: root/sys/powerpc/powermac
diff options
context:
space:
mode:
authorJustin Hibbits <jhibbits@FreeBSD.org>2015-02-20 06:19:23 +0000
committerJustin Hibbits <jhibbits@FreeBSD.org>2015-02-20 06:19:23 +0000
commit7f745b2b49629390398fe094648426cedd576115 (patch)
treeb399c56f44d618ba1483a64585a20939c1f455dd /sys/powerpc/powermac
parent976a0ea071096821513367a7c5535326b914e29a (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.c28
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);
}
}