summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorjruoho <jruoho@NetBSD.org>2010-04-24 06:31:44 +0000
committerjruoho <jruoho@NetBSD.org>2010-04-24 06:31:44 +0000
commit1b81a62b62674f3dd4eeadbc6934d7503cebc322 (patch)
tree00c3c7a74a9d0aad6e1667215be8b915813afbdf /sys/dev
parente4759b9b176e734de5c5061e301acd2369fecb76 (diff)
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.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/acpi/acpi_power.c23
-rw-r--r--sys/dev/acpi/acpi_power.h3
-rw-r--r--sys/dev/acpi/acpi_tz.c111
3 files changed, 105 insertions, 32 deletions
diff --git a/sys/dev/acpi/acpi_power.c b/sys/dev/acpi/acpi_power.c
index 300ee49672f..cd875f05d9d 100644
--- a/sys/dev/acpi/acpi_power.c
+++ b/sys/dev/acpi/acpi_power.c
@@ -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 @@ acpi_power_deregister(struct acpi_devnode *ad)
(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.
*/
diff --git a/sys/dev/acpi/acpi_power.h b/sys/dev/acpi/acpi_power.h
index 8e7ae65e21b..1fa1fc28eb6 100644
--- a/sys/dev/acpi/acpi_power.h
+++ b/sys/dev/acpi/acpi_power.h
@@ -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);
diff --git a/sys/dev/acpi/acpi_tz.c b/sys/dev/acpi/acpi_tz.c
index 361957f17fb..8c0f63e5d2e 100644
--- a/sys/dev/acpi/acpi_tz.c
+++ b/sys/dev/acpi/acpi_tz.c
@@ -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 <jmcneill@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 @@ ACPI_MODULE_NAME ("acpi_tz")
/* 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 @@ struct acpitz_softc {
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 @@ static ACPI_STATUS
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 @@ acpitz_attach(device_t parent, device_t self, void *aux)
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_attach(device_t parent, device_t self, void *aux)
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 @@ acpitz_print_status(device_t dv)
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 @@ acpitz_tick(void *opaque)
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