Module Name:    src
Committed By:   macallan
Date:           Fri Sep  3 17:18:40 UTC 2021

Modified Files:
        src/sys/arch/macppc/conf: files.macppc
        src/sys/arch/macppc/dev: smu.c

Log Message:
switch smu to common fan control code


To generate a diff of this commit:
cvs rdiff -u -r1.121 -r1.122 src/sys/arch/macppc/conf/files.macppc
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/macppc/dev/smu.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/macppc/conf/files.macppc
diff -u src/sys/arch/macppc/conf/files.macppc:1.121 src/sys/arch/macppc/conf/files.macppc:1.122
--- src/sys/arch/macppc/conf/files.macppc:1.121	Tue Jul 27 23:38:42 2021
+++ src/sys/arch/macppc/conf/files.macppc	Fri Sep  3 17:18:39 2021
@@ -1,4 +1,4 @@
-#	$NetBSD: files.macppc,v 1.121 2021/07/27 23:38:42 macallan Exp $
+#	$NetBSD: files.macppc,v 1.122 2021/09/03 17:18:39 macallan Exp $
 #
 # macppc-specific configuration info
 
@@ -180,7 +180,7 @@ define fancontrol
 file arch/macppc/dev/fancontrol.c		fancontrol
 defflag	opt_fancontrol.h	FANCONTROL_DEBUG
 
-device smu { } : fancontrol
+device smu { } : sysmon_envsys, fancontrol
 attach smu at mainbus
 file arch/macppc/dev/smu.c			smu needs-flag
 defflag	opt_smu.h	SMU_DEBUG

Index: src/sys/arch/macppc/dev/smu.c
diff -u src/sys/arch/macppc/dev/smu.c:1.14 src/sys/arch/macppc/dev/smu.c:1.15
--- src/sys/arch/macppc/dev/smu.c:1.14	Sat Aug  7 16:18:58 2021
+++ src/sys/arch/macppc/dev/smu.c	Fri Sep  3 17:18:40 2021
@@ -46,6 +46,7 @@
 
 #include <macppc/dev/obiovar.h>
 #include <macppc/dev/smuvar.h>
+#include <macppc/dev/fancontrolvar.h>
 
 #include "opt_smu.h"
 
@@ -67,7 +68,9 @@ struct smu_fan {
 	int min_rpm;
 	int max_rpm;
 	int default_rpm;
+	int wanted_rpm;
 	int current_rpm;
+	int fault;
 	time_t last_update;
 };
 
@@ -82,19 +85,11 @@ struct smu_iicbus {
 #define SMU_MAX_IICBUS		3
 #define SMU_MAX_SME_SENSORS	(SMU_MAX_FANS + 8)
 
-struct smu_zone {
-	bool (*filter)(const envsys_data_t *);
-	int nfans;
-	int fans[SMU_MAX_FANS];
-	int threshold, step;
-	int duty;
-};
-
 
-#define SMU_ZONE_CPUS	0
-#define SMU_ZONE_DRIVES	1
-#define SMU_ZONE_SLOTS	2
-#define SMU_ZONES	3
+#define SMU_ZONE_CPU		0
+#define SMU_ZONE_CASE		1
+#define SMU_ZONE_DRIVEBAY	2
+#define SMU_ZONES		3
 
 #define C_TO_uK(n) (n * 1000000 + 273150000)
 
@@ -123,7 +118,7 @@ struct smu_softc {
 	uint32_t cpu_m;
 	int32_t  cpu_b;
 
-	struct smu_zone sc_zones[SMU_ZONES];
+	fancontrol_zone_t sc_zones[SMU_ZONES];
 	lwp_t *sc_thread;
 	bool sc_dying;
 };
@@ -165,20 +160,19 @@ static int smu_dbell_gpio_intr(void *);
 static int smu_todr_gettime_ymdhms(todr_chip_handle_t, struct clock_ymdhms *);
 static int smu_todr_settime_ymdhms(todr_chip_handle_t, struct clock_ymdhms *);
 static int smu_fan_update_rpm(struct smu_fan *);
-static int smu_fan_get_rpm(struct smu_fan *, int *);
-static int smu_fan_set_rpm(struct smu_fan *, int);
 static int smu_read_adc(struct smu_softc *, int);
 
 static int smu_iicbus_exec(void *, i2c_op_t, i2c_addr_t, const void *,
     size_t, void *, size_t, int);
-static int smu_sysctl_fan_rpm(SYSCTLFN_ARGS);
 
 static void smu_setup_zones(struct smu_softc *);
-static void smu_adjust_zone(struct smu_softc *, int);
 static void smu_adjust(void *);
+
 static bool is_cpu_sensor(const envsys_data_t *);
 static bool is_drive_sensor(const envsys_data_t *);
 static bool is_slots_sensor(const envsys_data_t *);
+static int smu_fan_get_rpm(void *, int);
+static int smu_fan_set_rpm(void *, int, int);
 
 int smu_get_datablock(int, uint8_t *, size_t);
 
@@ -299,9 +293,8 @@ static void
 smu_setup_fans(struct smu_softc *sc)
 {
 	struct smu_fan *fan;
-	struct sysctlnode *sysctl_fans, *sysctl_fan, *sysctl_node;
-	char type[32], sysctl_fan_name[32];
-	int node, i, j;
+	char type[32];
+	int node, i;
 	const char *fans[] = { "fans", "rpm-fans", 0 };
 	int n = 0;
 	
@@ -349,6 +342,8 @@ smu_setup_fans(struct smu_softc *sc)
 			    fan->location, fan->reg, fan->zone, fan->rpm_ctl,
 			    fan->min_rpm, fan->max_rpm, fan->default_rpm);
 
+			fan->wanted_rpm = fan->default_rpm;
+			fan->fault = 0; 
 			sc->sc_num_fans++;
 		}
 		n++;
@@ -356,88 +351,8 @@ smu_setup_fans(struct smu_softc *sc)
 
 	for (i = 0; i < sc->sc_num_fans; i++) {
 		fan = &sc->sc_fans[i];
-		smu_fan_set_rpm(fan, fan->default_rpm);
-		smu_fan_get_rpm(fan, &fan->current_rpm);
-	}
-
-	/* Create sysctl nodes for each fan */
-
-	sysctl_createv(NULL, 0, NULL, (void *) &sysctl_fans,
-	    CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
-	    CTLTYPE_NODE, "fans", NULL,
-	    NULL, 0, NULL, 0,
-	    CTL_MACHDEP,
-	    sc->sc_sysctl_me->sysctl_num,
-	    CTL_CREATE, CTL_EOL);
-
-	for (i = 0; i < sc->sc_num_fans; i++) {
-		fan = &sc->sc_fans[i];
-
-		for (j = 0; j < strlen(fan->location); j++) {
-			sysctl_fan_name[j] = tolower(fan->location[j]);
-			if (sysctl_fan_name[j] == ' ')
-				sysctl_fan_name[j] = '_';
-		}
-		sysctl_fan_name[j] = '\0';
-
-		sysctl_createv(NULL, 0, NULL, (void *) &sysctl_fan,
-		    CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
-		    CTLTYPE_NODE, sysctl_fan_name, "fan information",
-		    NULL, 0, NULL, 0,
-		    CTL_MACHDEP,
-		    sc->sc_sysctl_me->sysctl_num,
-		    sysctl_fans->sysctl_num,
-		    CTL_CREATE, CTL_EOL);
-
-		sysctl_createv(NULL, 0, NULL, (void *) &sysctl_node,
-		    CTLFLAG_READONLY | CTLFLAG_OWNDESC,
-		    CTLTYPE_INT, "zone", "fan zone",
-		    NULL, 0, &fan->zone, 0,
-		    CTL_MACHDEP,
-		    sc->sc_sysctl_me->sysctl_num,
-		    sysctl_fans->sysctl_num,
-		    sysctl_fan->sysctl_num,
-		    CTL_CREATE, CTL_EOL);
-
-		sysctl_createv(NULL, 0, NULL, (void *) &sysctl_node,
-		    CTLFLAG_READONLY | CTLFLAG_OWNDESC,
-		    CTLTYPE_INT, "min_rpm", "fan minimum rpm",
-		    NULL, 0, &fan->min_rpm, 0,
-		    CTL_MACHDEP,
-		    sc->sc_sysctl_me->sysctl_num,
-		    sysctl_fans->sysctl_num,
-		    sysctl_fan->sysctl_num,
-		    CTL_CREATE, CTL_EOL);
-
-		sysctl_createv(NULL, 0, NULL, (void *) &sysctl_node,
-		    CTLFLAG_READONLY | CTLFLAG_OWNDESC,
-		    CTLTYPE_INT, "max_rpm", "fan maximum rpm",
-		    NULL, 0, &fan->max_rpm, 0,
-		    CTL_MACHDEP,
-		    sc->sc_sysctl_me->sysctl_num,
-		    sysctl_fans->sysctl_num,
-		    sysctl_fan->sysctl_num,
-		    CTL_CREATE, CTL_EOL);
-
-		sysctl_createv(NULL, 0, NULL, (void *) &sysctl_node,
-		    CTLFLAG_READONLY | CTLFLAG_OWNDESC,
-		    CTLTYPE_INT, "default_rpm", "fan default rpm",
-		    NULL, 0, &fan->default_rpm, 0,
-		    CTL_MACHDEP,
-		    sc->sc_sysctl_me->sysctl_num,
-		    sysctl_fans->sysctl_num,
-		    sysctl_fan->sysctl_num,
-		    CTL_CREATE, CTL_EOL);
-
-		sysctl_createv(NULL, 0, NULL, (void *) &sysctl_node,
-		    CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
-		    CTLTYPE_INT, "rpm", "fan current rpm",
-		    smu_sysctl_fan_rpm, 0, (void *) fan, 0,
-		    CTL_MACHDEP,
-		    sc->sc_sysctl_me->sysctl_num,
-		    sysctl_fans->sysctl_num,
-		    sysctl_fan->sysctl_num,
-		    CTL_CREATE, CTL_EOL);
+		smu_fan_set_rpm(sc, i, fan->default_rpm);
+		smu_fan_update_rpm(fan);
 	}
 }
 
@@ -554,18 +469,17 @@ static void
 smu_sme_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
 {
 	struct smu_softc *sc = sme->sme_cookie;
-	struct smu_fan *fan;
 	int which = edata->sensor;
 	int ret;
 
 	edata->state = ENVSYS_SINVALID;
 
 	if (which < sc->sc_num_fans) {
-		fan = &sc->sc_fans[which];
 
-		ret = smu_fan_get_rpm(fan, &fan->current_rpm);
-		if (ret == 0) {
-			edata->value_cur = fan->current_rpm;
+		ret = smu_fan_get_rpm(sc, which);
+		if (ret != -1) {
+			sc->sc_fans[which].current_rpm = ret;
+			edata->value_cur = ret;
 			edata->state = ENVSYS_SVALID;
 		}
 	} else if (edata->private > 0) {
@@ -738,7 +652,7 @@ smu_fan_update_rpm(struct smu_fan *fan)
 {
 	struct smu_softc *sc = fan->sc;
 	struct smu_cmd cmd;
-	int ret;
+	int ret, diff;
 
 	cmd.cmd = SMU_CMD_FAN;
 	cmd.len = 2;
@@ -761,31 +675,35 @@ smu_fan_update_rpm(struct smu_fan *fan)
 			    cmd.data[2 + fan->reg * 2];
 		}
 	}
-
+	diff = abs(fan->current_rpm - fan->wanted_rpm);
+	if (diff > fan->max_rpm >> 3) {
+		fan->fault++;
+	} else fan->fault = 0;
 	return ret;
 }
 
 static int
-smu_fan_get_rpm(struct smu_fan *fan, int *rpm)
+smu_fan_get_rpm(void *cookie, int which)
 {
+	struct smu_softc *sc = cookie;
+	struct smu_fan *fan = &sc->sc_fans[which];
 	int ret;
 	ret = 0;
 
 	if (time_uptime - fan->last_update > 1) {
 		ret = smu_fan_update_rpm(fan);
 		if (ret != 0)
-			return ret;
+			return -1;
 	}
 
-	*rpm = fan->current_rpm;
-
-	return ret;
+	return fan->current_rpm;
 }
 
 static int
-smu_fan_set_rpm(struct smu_fan *fan, int rpm)
+smu_fan_set_rpm(void *cookie, int which, int rpm)
 {
-	struct smu_softc *sc = fan->sc;
+	struct smu_softc *sc = cookie;
+	struct smu_fan *fan = &sc->sc_fans[which];
 	struct smu_cmd cmd;
 	int ret;
 
@@ -794,6 +712,8 @@ smu_fan_set_rpm(struct smu_fan *fan, int
 	rpm = uimax(fan->min_rpm, rpm);
 	rpm = uimin(fan->max_rpm, rpm);
 
+	fan->wanted_rpm = rpm;
+
 	cmd.cmd = SMU_CMD_FAN;
 	cmd.len = 4;
 	cmd.data[0] = 0x30;
@@ -887,33 +807,6 @@ smu_iicbus_exec(void *cookie, i2c_op_t o
 	return 0;
 }
 
-static int
-smu_sysctl_fan_rpm(SYSCTLFN_ARGS)
-{
-	struct sysctlnode node = *rnode;
-	struct smu_fan *fan = node.sysctl_data;
-	int rpm = 0;
-	int ret;
-
-	node.sysctl_data = &rpm;
-
-	if (newp) {
-		if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) {
-			rpm = *(int *) node.sysctl_data;
-			return smu_fan_set_rpm(fan, rpm);
-		}
-		return EINVAL;
-	} else {
-		ret = smu_fan_get_rpm(fan, &rpm);
-		if (ret != 0)
-			return (ret);
-
-		return sysctl_lookup(SYSCTLFN_CALL(&node));
-	}
-
-	return 0;
-}
-
 SYSCTL_SETUP(smu_sysctl_setup, "SMU sysctl subtree setup")
 {
 	sysctl_createv(NULL, 0, NULL, NULL,
@@ -924,61 +817,86 @@ SYSCTL_SETUP(smu_sysctl_setup, "SMU sysc
 static void
 smu_setup_zones(struct smu_softc *sc)
 {
-	struct smu_zone *z;
 	struct smu_fan *f;
+	fancontrol_zone_t *z;
 	int i;
 
+	/* init zones */
+	sc->sc_zones[SMU_ZONE_CPU].name = "CPUs";
+	sc->sc_zones[SMU_ZONE_CPU].filter = is_cpu_sensor;
+	sc->sc_zones[SMU_ZONE_CPU].cookie = sc;
+	sc->sc_zones[SMU_ZONE_CPU].get_rpm = smu_fan_get_rpm;
+	sc->sc_zones[SMU_ZONE_CPU].set_rpm = smu_fan_set_rpm;
+	sc->sc_zones[SMU_ZONE_CPU].Tmin = 45;
+	sc->sc_zones[SMU_ZONE_CPU].Tmax = 80;
+	sc->sc_zones[SMU_ZONE_CPU].nfans = 0;
+	sc->sc_zones[SMU_ZONE_CASE].name = "Slots";
+	sc->sc_zones[SMU_ZONE_CASE].filter = is_slots_sensor;
+	sc->sc_zones[SMU_ZONE_CASE].cookie = sc;
+	sc->sc_zones[SMU_ZONE_CASE].Tmin = 50;
+	sc->sc_zones[SMU_ZONE_CASE].Tmax = 75;
+	sc->sc_zones[SMU_ZONE_CASE].nfans = 0;
+	sc->sc_zones[SMU_ZONE_CASE].get_rpm = smu_fan_get_rpm;
+	sc->sc_zones[SMU_ZONE_CASE].set_rpm = smu_fan_set_rpm;
+	sc->sc_zones[SMU_ZONE_DRIVEBAY].name = "Drivebays";
+	sc->sc_zones[SMU_ZONE_DRIVEBAY].filter = is_drive_sensor;
+	sc->sc_zones[SMU_ZONE_DRIVEBAY].cookie = sc;
+	sc->sc_zones[SMU_ZONE_DRIVEBAY].get_rpm = smu_fan_get_rpm;
+	sc->sc_zones[SMU_ZONE_DRIVEBAY].set_rpm = smu_fan_set_rpm;
+	sc->sc_zones[SMU_ZONE_DRIVEBAY].Tmin = 30;
+	sc->sc_zones[SMU_ZONE_DRIVEBAY].Tmax = 50;
+	sc->sc_zones[SMU_ZONE_DRIVEBAY].nfans = 0;
+
 	/* find CPU fans */
-	z = &sc->sc_zones[SMU_ZONE_CPUS];
-	z->nfans = 0;
+	z = &sc->sc_zones[SMU_ZONE_CPU];
 	for (i = 0; i < SMU_MAX_FANS; i++) {
 		f = &sc->sc_fans[i];
 		if ((strstr(f->location, "CPU") != NULL) || 
 		    (strstr(f->location, "System") != NULL)) {
-			z->fans[z->nfans] = i;
+			z->fans[z->nfans].num = i;
+			z->fans[z->nfans].min_rpm = f->min_rpm;
+			z->fans[z->nfans].max_rpm = f->max_rpm;
+			z->fans[z->nfans].name = f->location;
 			z->nfans++;
 		}
 	}
 	aprint_normal_dev(sc->sc_dev,
 	    "using %d fans for CPU zone\n", z->nfans);
-	z->threshold = C_TO_uK(45);
-	z->duty = 150;
-	z->step = 3;	
-	z->filter = is_cpu_sensor;
 
-	z = &sc->sc_zones[SMU_ZONE_DRIVES];
-	z->nfans = 0;
+	z = &sc->sc_zones[SMU_ZONE_DRIVEBAY];
 	for (i = 0; i < SMU_MAX_FANS; i++) {
 		f = &sc->sc_fans[i];
 		if ((strstr(f->location, "DRIVE") != NULL) ||
 		    (strstr(f->location, "Drive") != NULL)) {
-			z->fans[z->nfans] = i;
+			z->fans[z->nfans].num = i;
+			z->fans[z->nfans].min_rpm = f->min_rpm;
+			z->fans[z->nfans].max_rpm = f->max_rpm;
+			z->fans[z->nfans].name = f->location;
 			z->nfans++;
 		}
 	}
 	aprint_normal_dev(sc->sc_dev,
 	    "using %d fans for drive bay zone\n", z->nfans);
-	z->threshold = C_TO_uK(40);
-	z->duty = 150;
-	z->step = 2;
-	z->filter = is_drive_sensor;
 
-	z = &sc->sc_zones[SMU_ZONE_SLOTS];
-	z->nfans = 0;
+	z = &sc->sc_zones[SMU_ZONE_CASE];
 	for (i = 0; i < SMU_MAX_FANS; i++) {
 		f = &sc->sc_fans[i];
 		if ((strstr(f->location, "BACKSIDE") != NULL) ||
 		    (strstr(f->location, "SLOTS") != NULL)) {
-			z->fans[z->nfans] = i;
+			z->fans[z->nfans].num = i;
+			z->fans[z->nfans].min_rpm = f->min_rpm;
+			z->fans[z->nfans].max_rpm = f->max_rpm;
+			z->fans[z->nfans].name = f->location;
 			z->nfans++;
 		}
 	}
 	aprint_normal_dev(sc->sc_dev,
 	    "using %d fans for expansion slots zone\n", z->nfans);
-	z->threshold = C_TO_uK(40);
-	z->duty = 150;
-	z->step = 2;
-	z->filter = is_slots_sensor;
+
+	/* setup sysctls for our zones etc. */
+	for (i = 0; i < SMU_ZONES; i++) {
+		fancontrol_init_zone(&sc->sc_zones[i], sc->sc_sysctl_me);
+	}
 
 	sc->sc_dying = false;
 	kthread_create(PRI_NONE, 0, curcpu(), smu_adjust, sc, &sc->sc_thread,
@@ -986,44 +904,6 @@ smu_setup_zones(struct smu_softc *sc)
 }
 
 static void
-smu_adjust_zone(struct smu_softc *sc, int which)
-{
-	struct smu_zone *z = &sc->sc_zones[which];
-	struct smu_fan *f;
-	long temp, newduty, i, speed, diff;
-
-	DPRINTF("%s %d\n", __func__, which);
-
-	temp = sysmon_envsys_get_max_value(z->filter, true);
-	if (temp == 0) {
-		/* no sensor data - leave fan alone */
-		DPRINTF("nodata\n");
-		return;
-	}
-	DPRINTF("temp %ld ", (temp - 273150000) / 1000000);
-	diff = ((temp - z->threshold) / 1000000) * z->step;
-
-	if (diff < 0) newduty = 0;
-	else if (diff > 100) newduty = 100;
-	else newduty = diff;
-
-	DPRINTF("newduty %ld diff %ld \n", newduty, diff);
-	if (newduty == z->duty) {
-		DPRINTF("no change\n");
-		return;
-	}
-	z->duty = newduty;
-	/* now adjust each fan to the new duty cycle */
-	for (i = 0; i < z->nfans; i++) {
-		f = &sc->sc_fans[z->fans[i]];
-		speed = f->min_rpm + ((f->max_rpm - f->min_rpm) * newduty) / 100;
-		DPRINTF("fan %d speed %ld ", z->fans[i], speed);
-		smu_fan_set_rpm(f, speed);
-	}
-	DPRINTF("\n");
-}
-
-static void
 smu_adjust(void *cookie)
 {
 	struct smu_softc *sc = cookie;
@@ -1031,8 +911,9 @@ smu_adjust(void *cookie)
 
 	while (!sc->sc_dying) {
 		for (i = 0; i < SMU_ZONES; i++)
-			smu_adjust_zone(sc, i);
-		kpause("fanctrl", true, mstohz(3000), NULL);
+			if (sc->sc_zones[i].nfans > 0)
+				fancontrol_adjust_zone(&sc->sc_zones[i]);
+		kpause("fanctrl", true, mstohz(2000), NULL);
 	}
 	kthread_exit(0);
 }

Reply via email to