Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Feb 2015 06:19:24 +0000 (UTC)
From:      Justin Hibbits <jhibbits@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r279045 - head/sys/powerpc/powermac
Message-ID:  <201502200619.t1K6JOUv062952@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhibbits
Date: Fri Feb 20 06:19:23 2015
New Revision: 279045
URL: https://svnweb.freebsd.org/changeset/base/279045

Log:
  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

Modified:
  head/sys/powerpc/powermac/powermac_thermal.c

Modified: head/sys/powerpc/powermac/powermac_thermal.c
==============================================================================
--- head/sys/powerpc/powermac/powermac_thermal.c	Fri Feb 20 06:13:52 2015	(r279044)
+++ head/sys/powerpc/powermac/powermac_thermal.c	Fri Feb 20 06:19:23 2015	(r279045)
@@ -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, "pmact
 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);
 	}
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201502200619.t1K6JOUv062952>