Module Name:    src
Committed By:   jruoho
Date:           Sat Apr 24 06:31:44 UTC 2010

Modified Files:
        src/sys/dev/acpi: acpi_power.c acpi_power.h acpi_tz.c

Log Message:
Now that we are able to remove references to power resources, provide a
detachment routine for acpitz(4). Add comments explaining the relationship
between power resources and active cooling. Also some improvements to code
readability.


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/acpi/acpi_power.c
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/acpi/acpi_power.h
cvs rdiff -u -r1.67 -r1.68 src/sys/dev/acpi/acpi_tz.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/dev/acpi/acpi_power.c
diff -u src/sys/dev/acpi/acpi_power.c:1.5 src/sys/dev/acpi/acpi_power.c:1.6
--- src/sys/dev/acpi/acpi_power.c:1.5	Fri Apr 23 19:00:58 2010
+++ src/sys/dev/acpi/acpi_power.c	Sat Apr 24 06:31:44 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_power.c,v 1.5 2010/04/23 19:00:58 jruoho Exp $ */
+/* $NetBSD: acpi_power.c,v 1.6 2010/04/24 06:31:44 jruoho Exp $ */
 
 /*-
  * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
@@ -56,7 +56,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_power.c,v 1.5 2010/04/23 19:00:58 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_power.c,v 1.6 2010/04/24 06:31:44 jruoho Exp $");
 
 #include <sys/param.h>
 #include <sys/kmem.h>
@@ -240,6 +240,25 @@
 	    (void)acpi_power_res_deref(res, ad->ad_handle);
 }
 
+void
+acpi_power_deregister_from_handle(ACPI_HANDLE hdl)
+{
+	struct acpi_softc *sc = acpi_softc; /* XXX. */
+	struct acpi_devnode *ad;
+
+	if (sc == NULL)
+		return;
+
+	SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
+
+		if (ad->ad_handle == hdl)
+			return acpi_power_deregister(ad);
+	}
+
+	aprint_error_dev(sc->sc_dev, "%s: failed to "
+	    "find node %s\n", __func__, acpi_xname(hdl));
+}
+
 /*
  * Get the D-state of an ACPI device node.
  */

Index: src/sys/dev/acpi/acpi_power.h
diff -u src/sys/dev/acpi/acpi_power.h:1.2 src/sys/dev/acpi/acpi_power.h:1.3
--- src/sys/dev/acpi/acpi_power.h:1.2	Fri Apr 23 18:51:31 2010
+++ src/sys/dev/acpi/acpi_power.h	Sat Apr 24 06:31:44 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_power.h,v 1.2 2010/04/23 18:51:31 jruoho Exp $ */
+/* $NetBSD: acpi_power.h,v 1.3 2010/04/24 06:31:44 jruoho Exp $ */
 
 /*-
  * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
@@ -37,6 +37,7 @@
 void	acpi_power_res_add(struct acpi_devnode *);
 bool	acpi_power_register(struct acpi_devnode *);
 void	acpi_power_deregister(struct acpi_devnode *);
+void	acpi_power_deregister_from_handle(ACPI_HANDLE);
 bool	acpi_power_get(struct acpi_devnode *, int *);
 bool	acpi_power_set(struct acpi_devnode *, int);
 bool	acpi_power_set_from_handle(ACPI_HANDLE, int);

Index: src/sys/dev/acpi/acpi_tz.c
diff -u src/sys/dev/acpi/acpi_tz.c:1.67 src/sys/dev/acpi/acpi_tz.c:1.68
--- src/sys/dev/acpi/acpi_tz.c:1.67	Thu Apr 22 18:40:09 2010
+++ src/sys/dev/acpi/acpi_tz.c	Sat Apr 24 06:31:44 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_tz.c,v 1.67 2010/04/22 18:40:09 jruoho Exp $ */
+/* $NetBSD: acpi_tz.c,v 1.68 2010/04/24 06:31:44 jruoho Exp $ */
 
 /*
  * Copyright (c) 2003 Jared D. McNeill <jmcne...@invisible.ca>
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_tz.c,v 1.67 2010/04/22 18:40:09 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_tz.c,v 1.68 2010/04/24 06:31:44 jruoho Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -65,9 +65,6 @@
 /* sensor indexes */
 #define ATZ_SENSOR_TEMP	0	/* thermal zone temperature */
 
-static int	acpitz_match(device_t, cfdata_t, void *);
-static void	acpitz_attach(device_t, device_t, void *);
-
 /*
  * ACPI Temperature Zone information. Note all temperatures are reported
  * in 0.1 Kelvin, and that the ACPI specification assumes that
@@ -124,6 +121,10 @@
 	int sc_have_fan;	/* FAN sensor is optional */
 };
 
+static int	acpitz_match(device_t, cfdata_t, void *);
+static void	acpitz_attach(device_t, device_t, void *);
+static int	acpitz_detach(device_t, int);
+
 static void	acpitz_get_status(void *);
 static void	acpitz_get_zone(void *, int);
 static void	acpitz_get_zone_quiet(void *);
@@ -147,8 +148,8 @@
 		acpitz_set_fanspeed(device_t, uint32_t);
 #endif
 
-CFATTACH_DECL_NEW(acpitz, sizeof(struct acpitz_softc), acpitz_match,
-    acpitz_attach, NULL, NULL);
+CFATTACH_DECL_NEW(acpitz, sizeof(struct acpitz_softc),
+    acpitz_match, acpitz_attach, acpitz_detach, NULL);
 
 /*
  * acpitz_match: autoconf(9) match routine
@@ -206,13 +207,14 @@
 
 	rv = acpi_eval_string(sc->sc_devnode->ad_handle,
 	    "REGN", &sc->sc_zone.name);
+
 	if (ACPI_FAILURE(rv))
 		sc->sc_zone.name = __UNCONST("temperature");
 
 	acpitz_get_zone(self, 1);
 	acpitz_get_status(self);
 
-	(void)acpi_power_register(sc->sc_devnode);
+	(void)pmf_device_register(self, NULL, NULL);
 	(void)acpi_register_notify(sc->sc_devnode, acpitz_notify_handler);
 
 	callout_init(&sc->sc_callout, CALLOUT_MPSAFE);
@@ -220,12 +222,53 @@
 
 	acpitz_init_envsys(self);
 
-	if (!pmf_device_register(self, NULL, NULL))
-		aprint_error(": couldn't establish power handler\n");
-
 	callout_schedule(&sc->sc_callout, sc->sc_zone.tzp * hz / 10);
 }
 
+static int
+acpitz_detach(device_t self, int flags)
+{
+	struct acpitz_softc *sc = device_private(self);
+	ACPI_HANDLE hdl;
+	ACPI_BUFFER al;
+	ACPI_STATUS rv;
+	int i;
+
+	callout_halt(&sc->sc_callout, NULL);
+	callout_destroy(&sc->sc_callout);
+
+	pmf_device_deregister(self);
+	acpi_deregister_notify(sc->sc_devnode);
+
+	/*
+	 * Although the device itself should not contain any power
+	 * resources, we have possibly used the resources of active
+	 * cooling devices. To unregister these, first fetch a fresh
+	 * active cooling zone, and then detach the resources from
+	 * the reference handles contained in the cooling zone.
+	 */
+	acpitz_get_zone(self, 0);
+
+	for (i = 0; i < ATZ_NLEVELS; i++) {
+
+		if (sc->sc_zone.al[i].Pointer == NULL)
+			continue;
+
+		al = sc->sc_zone.al[i];
+		rv = acpi_eval_reference_handle(al.Pointer, &hdl);
+
+		if (ACPI_SUCCESS(rv))
+			acpi_power_deregister_from_handle(hdl);
+
+		ACPI_FREE(sc->sc_zone.al[i].Pointer);
+	}
+
+	if (sc->sc_sme != NULL)
+		sysmon_envsys_unregister(sc->sc_sme);
+
+	return 0;
+}
+
 static void
 acpitz_get_zone_quiet(void *opaque)
 {
@@ -374,21 +417,24 @@
 static ACPI_STATUS
 acpitz_switch_cooler(ACPI_OBJECT *obj, void *arg)
 {
+	int flag, pwr_state;
 	ACPI_HANDLE cooler;
-	int pwr_state, flag;
 	ACPI_STATUS rv;
 
+	/*
+	 * The _ALx object is a package in which the elements
+	 * are reference handles to an active cooling device
+	 * (typically PNP0C0B, ACPI fan device). Try to turn
+	 * on (or off) the power resources behind these handles
+	 * to start (or terminate) the active cooling.
+	 */
 	flag = *(int *)arg;
-
-	if (flag)
-		pwr_state = ACPI_STATE_D0;
-	else
-		pwr_state = ACPI_STATE_D3;
+	pwr_state = (flag != 0) ? ACPI_STATE_D0 : ACPI_STATE_D3;
 
 	rv = acpi_eval_reference_handle(obj, &cooler);
 
 	if (ACPI_FAILURE(rv)) {
-		aprint_error("%s: failed to get handle\n", __func__);
+		aprint_error("%s: failed to get reference handle\n", __func__);
 		return rv;
 	}
 
@@ -679,39 +725,46 @@
 static void
 acpitz_init_envsys(device_t dv)
 {
+	const int flags = ENVSYS_FMONLIMITS | ENVSYS_FMONNOTSUPP;
 	struct acpitz_softc *sc = device_private(dv);
 
 	sc->sc_sme = sysmon_envsys_create();
-	sc->sc_sme->sme_get_limits = acpitz_get_limits;
+
 	sc->sc_sme->sme_cookie = sc;
 	sc->sc_sme->sme_name = device_xname(dv);
 	sc->sc_sme->sme_flags = SME_DISABLE_REFRESH;
+	sc->sc_sme->sme_get_limits = acpitz_get_limits;
 
-	sc->sc_temp_sensor.flags = ENVSYS_FMONLIMITS | ENVSYS_FMONNOTSUPP;
+	sc->sc_temp_sensor.flags = flags;
 	sc->sc_temp_sensor.units = ENVSYS_STEMP;
-	strlcpy(sc->sc_temp_sensor.desc,
+
+	(void)strlcpy(sc->sc_temp_sensor.desc,
 	    sc->sc_zone.name, sizeof(sc->sc_temp_sensor.desc));
+
 	if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_temp_sensor))
 		goto out;
 
-	if (sc->sc_have_fan) {
-		sc->sc_fan_sensor.flags =
-		    ENVSYS_FMONLIMITS | ENVSYS_FMONNOTSUPP;
+	if (sc->sc_have_fan != 0) {
+
+		sc->sc_fan_sensor.flags = flags;
 		sc->sc_fan_sensor.units = ENVSYS_SFANRPM;
-		strlcpy(sc->sc_fan_sensor.desc,
+
+		(void)strlcpy(sc->sc_fan_sensor.desc,
 		    "FAN", sizeof(sc->sc_fan_sensor.desc));
-		if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_fan_sensor))
-			/* ignore error because fan sensor is optional */
-			aprint_error_dev(dv, "unable to attach fan sensor\n");
+
+		/* Ignore error because fan sensor is optional. */
+		(void)sysmon_envsys_sensor_attach(sc->sc_sme,
+		    &sc->sc_fan_sensor);
 	}
 
-	/* hook into sysmon */
 	if (sysmon_envsys_register(sc->sc_sme) == 0)
 		return;
 
 out:
 	aprint_error_dev(dv, "unable to register with sysmon\n");
+
 	sysmon_envsys_destroy(sc->sc_sme);
+	sc->sc_sme = NULL;
 }
 
 static void

Reply via email to