Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/acpi As explained in the new ACPICA documentation, a...
details: https://anonhg.NetBSD.org/src/rev/3ced66737a41
branches: trunk
changeset: 762231:3ced66737a41
user: jruoho <jruoho%NetBSD.org@localhost>
date: Thu Feb 17 19:36:49 2011 +0000
description:
As explained in the new ACPICA documentation, as of ACPICA 20101207, the
_PRW methods are no longer automatically executed as part of the ACPICA
initialization. Refactor and rewrite the wake-device code to account this.
diffstat:
sys/dev/acpi/acpi.c | 24 ++-
sys/dev/acpi/acpi_wakedev.c | 408 +++++++++++++++++++++++++------------------
sys/dev/acpi/acpi_wakedev.h | 17 +-
sys/dev/acpi/acpivar.h | 5 +-
4 files changed, 273 insertions(+), 181 deletions(-)
diffs (truncated from 596 to 300 lines):
diff -r a55d04e32201 -r 3ced66737a41 sys/dev/acpi/acpi.c
--- a/sys/dev/acpi/acpi.c Thu Feb 17 19:29:41 2011 +0000
+++ b/sys/dev/acpi/acpi.c Thu Feb 17 19:36:49 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi.c,v 1.235 2011/02/15 20:24:11 jruoho Exp $ */
+/* $NetBSD: acpi.c,v 1.236 2011/02/17 19:36:49 jruoho Exp $ */
/*-
* Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
@@ -100,7 +100,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.235 2011/02/15 20:24:11 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.236 2011/02/17 19:36:49 jruoho Exp $");
#include "opt_acpi.h"
#include "opt_pcifixup.h"
@@ -685,6 +685,14 @@
(void)acpi_rescan(sc->sc_dev, NULL, NULL);
/*
+ * Update GPE information.
+ *
+ * Note that this must be called after
+ * all GPE handlers have been installed.
+ */
+ (void)AcpiUpdateAllGpes();
+
+ /*
* Defer rest of the configuration.
*/
(void)config_defer(sc->sc_dev, acpi_rescan_capabilities);
@@ -724,6 +732,7 @@
ad->ad_device = NULL;
ad->ad_notify = NULL;
ad->ad_pciinfo = NULL;
+ ad->ad_wakedev = NULL;
ad->ad_type = type;
ad->ad_handle = handle;
@@ -735,6 +744,13 @@
acpi_set_node(ad);
acpi_make_name(ad, devinfo->Name);
+ /*
+ * Identify wake GPEs from the _PRW. Note that
+ * AcpiUpdateAllGpes() must be called afterwards.
+ */
+ if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE)
+ acpi_wakedev_init(ad);
+
SIMPLEQ_INIT(&ad->ad_child_head);
SIMPLEQ_INSERT_TAIL(&sc->ad_head, ad, ad_list);
@@ -940,9 +956,7 @@
/*
* Scan wake-up capabilities.
*/
- rv = AcpiGetHandle(ad->ad_handle, "_PRW", &tmp);
-
- if (ACPI_SUCCESS(rv)) {
+ if (ad->ad_wakedev != NULL) {
ad->ad_flags |= ACPI_DEVICE_WAKEUP;
acpi_wakedev_add(ad);
}
diff -r a55d04e32201 -r 3ced66737a41 sys/dev/acpi/acpi_wakedev.c
--- a/sys/dev/acpi/acpi_wakedev.c Thu Feb 17 19:29:41 2011 +0000
+++ b/sys/dev/acpi/acpi_wakedev.c Thu Feb 17 19:36:49 2011 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: acpi_wakedev.c,v 1.21 2011/02/17 10:49:29 jruoho Exp $ */
+/* $NetBSD: acpi_wakedev.c,v 1.22 2011/02/17 19:36:49 jruoho Exp $ */
/*-
- * Copyright (c) 2009, 2010 Jared D. McNeill <jmcneill%invisible.ca@localhost>
+ * Copyright (c) 2009, 2010, 2011 Jared D. McNeill <jmcneill%invisible.ca@localhost>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,12 +27,13 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_wakedev.c,v 1.21 2011/02/17 10:49:29 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_wakedev.c,v 1.22 2011/02/17 19:36:49 jruoho Exp $");
#include <sys/param.h>
#include <sys/device.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
+#include <sys/malloc.h>
#include <dev/acpi/acpireg.h>
#include <dev/acpi/acpivar.h>
@@ -51,12 +52,191 @@
NULL,
};
+MALLOC_DECLARE(M_ACPI);
+
static int32_t acpi_wakedev_acpinode = CTL_EOL;
static int32_t acpi_wakedev_wakenode = CTL_EOL;
-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(struct acpi_devnode *, ACPI_OBJECT *);
+static void acpi_wakedev_set(struct acpi_devnode *, int);
+static void acpi_wakedev_method(struct acpi_devnode *, int);
+
+void
+acpi_wakedev_init(struct acpi_devnode *ad)
+{
+ ACPI_OBJECT *elm, *obj;
+ ACPI_HANDLE hdl = NULL;
+ ACPI_INTEGER val = 0;
+ ACPI_BUFFER buf;
+ ACPI_STATUS rv;
+
+ rv = acpi_eval_struct(ad->ad_handle, "_PRW", &buf);
+
+ if (ACPI_FAILURE(rv))
+ goto out;
+
+ obj = buf.Pointer;
+
+ if (obj->Type != ACPI_TYPE_PACKAGE) {
+ rv = AE_TYPE;
+ goto out;
+ }
+
+ if (obj->Package.Count < 2) {
+ rv = AE_LIMIT;
+ goto out;
+ }
+
+ /*
+ * As noted in ACPI 3.0 (section 7.2.10), the _PRW object is
+ * a package in which the first element is either an integer
+ * or again a package. In the latter case the package inside
+ * the package element has two elements, a reference handle
+ * and the GPE number.
+ */
+ elm = &obj->Package.Elements[0];
+
+ switch (elm->Type) {
+
+ case ACPI_TYPE_INTEGER:
+ val = elm->Integer.Value;
+ break;
+
+ case ACPI_TYPE_PACKAGE:
+
+ if (elm->Package.Count < 2) {
+ rv = AE_LIMIT;
+ goto out;
+ }
+
+ rv = AE_TYPE;
+
+ if (elm->Package.Elements[0].Type != ACPI_TYPE_LOCAL_REFERENCE)
+ goto out;
+
+ 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;
+
+ default:
+ rv = AE_TYPE;
+ goto out;
+ }
+
+ ad->ad_wakedev = malloc(sizeof(*ad->ad_wakedev),
+ M_ACPI, M_NOWAIT | M_ZERO);
+
+ if (ad->ad_wakedev == NULL)
+ return;
+
+ ad->ad_wakedev->aw_handle = hdl;
+ ad->ad_wakedev->aw_number = val;
+
+ /*
+ * The second element in _PRW is an integer
+ * that contains the lowest sleep state that
+ * can be entered while still providing wakeup.
+ */
+ elm = &obj->Package.Elements[1];
+
+ if (elm->Type == ACPI_TYPE_INTEGER)
+ ad->ad_wakedev->aw_sleep = elm->Integer.Value;
+
+ /*
+ * Rest of the elements are references
+ * to power resources. Store these.
+ */
+ acpi_wakedev_power(ad, obj);
+
+ /*
+ * Last but not least, mark GPEs for wake.
+ */
+ rv = AcpiSetupGpeForWake(ad->ad_handle, hdl, val);
+
+out:
+ if (buf.Pointer != NULL)
+ ACPI_FREE(buf.Pointer);
+
+ if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND)
+ aprint_error_dev(ad->ad_root, "failed to evaluate _PRW "
+ "for %s: %s\n", ad->ad_name, AcpiFormatException(rv));
+}
+
+static void
+acpi_wakedev_power(struct acpi_devnode *ad, ACPI_OBJECT *obj)
+{
+ struct acpi_wakedev *aw = ad->ad_wakedev;
+ uint32_t i, j, n;
+ ACPI_OBJECT *elm;
+ ACPI_HANDLE hdl;
+ ACPI_STATUS rv;
+
+ for (i = 0; i < __arraycount(aw->aw_power); i++)
+ aw->aw_power[i] = NULL;
+
+ n = obj->Package.Count;
+
+ if (n < 3 || n - 2 > __arraycount(aw->aw_power))
+ return;
+
+ for (i = 2, j = 0; i < n; i++, j++) {
+
+ elm = &obj->Package.Elements[i];
+ rv = acpi_eval_reference_handle(elm, &hdl);
+
+ if (ACPI_FAILURE(rv))
+ continue;
+
+ ad->ad_wakedev->aw_power[j] = hdl;
+ }
+}
+
+void
+acpi_wakedev_add(struct acpi_devnode *ad)
+{
+ struct acpi_wakedev *aw;
+ const char *str = NULL;
+ device_t dev;
+ int err;
+
+ KASSERT(ad != NULL && ad->ad_wakedev != NULL);
+ KASSERT((ad->ad_flags & ACPI_DEVICE_WAKEUP) != 0);
+
+ aw = ad->ad_wakedev;
+ aw->aw_enable = false;
+
+ if (acpi_match_hid(ad->ad_devinfo, acpi_wakedev_default))
+ ad->ad_wakedev->aw_enable = true;
+
+ if (acpi_wakedev_acpinode == CTL_EOL ||
+ acpi_wakedev_wakenode == CTL_EOL)
+ return;
+
+ if (ad->ad_device != NULL)
+ str = device_xname(ad->ad_device);
+ else {
+ dev = acpi_pcidev_find_dev(ad);
+
+ if (dev != NULL)
+ str = device_xname(dev);
+ }
+
+ if (str == NULL)
+ return;
+
+ err = sysctl_createv(NULL, 0, NULL, NULL,
+ CTLFLAG_READWRITE, CTLTYPE_BOOL, str,
+ NULL, NULL, 0, &ad->ad_wakedev->aw_enable, 0, CTL_HW,
+ acpi_wakedev_acpinode, acpi_wakedev_wakenode,
+ CTL_CREATE, CTL_EOL);
+
+ if (err != 0)
+ aprint_error_dev(ad->ad_root, "sysctl_createv"
+ "(hw.acpi.wake.%s) failed (err %d)\n", str, err);
+}
SYSCTL_SETUP(sysctl_acpi_wakedev_setup, "sysctl hw.acpi.wake subtree setup")
{
@@ -94,48 +274,6 @@
}
void
-acpi_wakedev_add(struct acpi_devnode *ad)
-{
- const char *str = NULL;
- device_t dev;
- int err;
-
- KASSERT(ad != NULL && ad->ad_root != NULL);
- KASSERT((ad->ad_flags & ACPI_DEVICE_WAKEUP) != 0);
Home |
Main Index |
Thread Index |
Old Index