Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/acpi Complete the support for wakeup devices. As imp...
details: https://anonhg.NetBSD.org/src/rev/5a6486016fa3
branches: trunk
changeset: 755420:5a6486016fa3
user: jruoho <jruoho%NetBSD.org@localhost>
date: Sat Jun 05 15:31:21 2010 +0000
description:
Complete the support for wakeup devices. As imposed by the standard, all
power resources should be turned on for wakeup devices. This follows common
sense: a device cannot wake if the power of it is turned off.
ok jmcneill@
diffstat:
sys/dev/acpi/acpi_wakedev.c | 87 +++++++++++++++++++++++++++++++++++---------
1 files changed, 68 insertions(+), 19 deletions(-)
diffs (168 lines):
diff -r b5a5f2f6a463 -r 5a6486016fa3 sys/dev/acpi/acpi_wakedev.c
--- a/sys/dev/acpi/acpi_wakedev.c Sat Jun 05 13:59:39 2010 +0000
+++ b/sys/dev/acpi/acpi_wakedev.c Sat Jun 05 15:31:21 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_wakedev.c,v 1.12 2010/04/18 14:05:26 jruoho Exp $ */
+/* $NetBSD: acpi_wakedev.c,v 1.13 2010/06/05 15:31:21 jruoho Exp $ */
/*-
* Copyright (c) 2009, 2010 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_wakedev.c,v 1.12 2010/04/18 14:05:26 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_wakedev.c,v 1.13 2010/06/05 15:31:21 jruoho Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -36,10 +36,11 @@
#include <dev/acpi/acpireg.h>
#include <dev/acpi/acpivar.h>
+#include <dev/acpi/acpi_power.h>
#include <dev/acpi/acpi_wakedev.h>
-#define _COMPONENT ACPI_BUS_COMPONENT
-ACPI_MODULE_NAME ("acpi_wakedev")
+#define _COMPONENT ACPI_BUS_COMPONENT
+ACPI_MODULE_NAME ("acpi_wakedev")
static const char * const acpi_wakedev_default[] = {
"PNP0C0C", /* power button */
@@ -51,8 +52,9 @@
static const struct sysctlnode *rnode = NULL;
-static void acpi_wakedev_prepare(struct acpi_devnode *, int, int);
-static void acpi_wakedev_gpe(struct acpi_devnode *, int);
+static void acpi_wakedev_method(struct acpi_devnode *, int, int);
+static void acpi_wakedev_gpe(struct acpi_devnode *, int, int);
+static void acpi_wakedev_power(ACPI_OBJECT *);
SYSCTL_SETUP(sysctl_acpi_wakedev_setup, "sysctl hw.acpi.wake subtree setup")
{
@@ -121,27 +123,26 @@
struct acpi_devnode *ad;
/*
- * As noted in ACPI 3.0 (p. 243), preparing
- * a device for wakeup is a two-step process:
+ * To prepare a device for wakeup:
+ *
+ * 1. Set appropriate GPEs.
*
- * 1. Enable all power resources in _PRW.
+ * 2. Enable all power resources in _PRW.
*
- * 2. If present, execute _DSW/_PSW method.
- *
- * XXX: The first one is yet to be implemented.
+ * 3. If present, execute _DSW/_PSW method.
*/
SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
if ((ad->ad_flags & ACPI_DEVICE_WAKEUP) == 0)
continue;
- acpi_wakedev_gpe(ad, ad->ad_wake);
- acpi_wakedev_prepare(ad, ad->ad_wake, state);
+ acpi_wakedev_gpe(ad, ad->ad_wake, state);
+ acpi_wakedev_method(ad, ad->ad_wake, state);
}
}
static void
-acpi_wakedev_prepare(struct acpi_devnode *ad, int enable, int state)
+acpi_wakedev_method(struct acpi_devnode *ad, int enable, int state)
{
ACPI_OBJECT_LIST arg;
ACPI_OBJECT obj[3];
@@ -194,9 +195,10 @@
}
static void
-acpi_wakedev_gpe(struct acpi_devnode *ad, int enable)
+acpi_wakedev_gpe(struct acpi_devnode *ad, int enable, int state)
{
ACPI_OBJECT *elm, *obj;
+ ACPI_HANDLE hdl = NULL;
ACPI_INTEGER val;
ACPI_BUFFER buf;
ACPI_STATUS rv;
@@ -237,6 +239,7 @@
if (elm->Package.Elements[1].Type != ACPI_TYPE_INTEGER)
goto out;
+ hdl = elm->Package.Elements[0].Reference.Handle;
val = elm->Package.Elements[1].Integer.Value;
break;
@@ -244,14 +247,35 @@
goto out;
}
+ /*
+ * The second element is an integer that contains the
+ * lowest sleep state that can be entered while still
+ * providing wake-up functionality. The rest of the
+ * elements are references to power resources.
+ */
+ elm = &obj->Package.Elements[1];
+
+ if (elm->Type != ACPI_TYPE_INTEGER)
+ goto out;
+
+ if (state > elm->Integer.Value)
+ aprint_error_dev(ad->ad_root, "sleep state S%d "
+ "loses wake for %s\n", state, ad->ad_name);
+
+ /*
+ * Turn on power resources.
+ */
+ if (enable != 0)
+ acpi_wakedev_power(obj);
+
/*
* Set or unset a GPE as both runtime and wake.
*/
if (enable == 0)
- (void)AcpiDisableGpe(NULL, val, ACPI_NOT_ISR);
+ (void)AcpiDisableGpe(hdl, val, ACPI_NOT_ISR);
else {
- (void)AcpiSetGpeType(NULL, val, ACPI_GPE_TYPE_WAKE_RUN);
- (void)AcpiEnableGpe(NULL, val, ACPI_NOT_ISR);
+ (void)AcpiSetGpeType(hdl, val, ACPI_GPE_TYPE_WAKE_RUN);
+ (void)AcpiEnableGpe(hdl, val, ACPI_NOT_ISR);
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "wake GPE %s for %s\n",
@@ -260,3 +284,28 @@
out:
ACPI_FREE(buf.Pointer);
}
+
+static void
+acpi_wakedev_power(ACPI_OBJECT *obj)
+{
+ ACPI_OBJECT *elm;
+ ACPI_HANDLE hdl;
+ ACPI_STATUS rv;
+ uint32_t i, n;
+
+ n = obj->Package.Count;
+
+ if (n < 3)
+ return;
+
+ for (i = 2; i < n; i++) {
+
+ elm = &obj->Package.Elements[i];
+ rv = acpi_eval_reference_handle(elm, &hdl);
+
+ if (ACPI_FAILURE(rv))
+ continue;
+
+ (void)acpi_power_set_from_handle(hdl, ACPI_STATE_D0);
+ }
+}
Home |
Main Index |
Thread Index |
Old Index