Preparing a device for wakeup involves:

(a) turning on all power resources required by the device; and
  (b) executing _DSW (or _PSW) control method.

This implements (b). Ok jmcneill@.
This commit is contained in:
jruoho 2010-03-05 21:01:44 +00:00
parent effc302a58
commit c38f7a7cda
4 changed files with 80 additions and 64 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: acpi.c,v 1.155 2010/03/05 14:00:16 jruoho Exp $ */
/* $NetBSD: acpi.c,v 1.156 2010/03/05 21:01:44 jruoho Exp $ */
/*-
* Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.155 2010/03/05 14:00:16 jruoho Exp $");
__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.156 2010/03/05 21:01:44 jruoho Exp $");
#include "opt_acpi.h"
#include "opt_pcifixup.h"
@ -1519,7 +1519,7 @@ acpi_enter_sleep_state(struct acpi_softc *sc, int state)
break;
}
acpi_wakedev_commit(sc);
acpi_wakedev_commit(sc, state);
if (state != ACPI_STATE_S1 && !pmf_system_suspend(PMF_Q_NONE)) {
aprint_error_dev(sc->sc_dev, "aborting suspend\n");

View File

@ -1,4 +1,4 @@
/* $NetBSD: acpi_lid.c,v 1.36 2010/03/05 14:00:16 jruoho Exp $ */
/* $NetBSD: acpi_lid.c,v 1.37 2010/03/05 21:01:44 jruoho Exp $ */
/*
* Copyright 2001, 2003 Wasabi Systems, Inc.
@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: acpi_lid.c,v 1.36 2010/03/05 14:00:16 jruoho Exp $");
__KERNEL_RCSID(0, "$NetBSD: acpi_lid.c,v 1.37 2010/03/05 21:01:44 jruoho Exp $");
#include <sys/param.h>
#include <sys/device.h>
@ -69,8 +69,6 @@ static void acpilid_attach(device_t, device_t, void *);
static int acpilid_detach(device_t, int);
static void acpilid_status_changed(void *);
static void acpilid_notify_handler(ACPI_HANDLE, UINT32, void *);
static void acpilid_wake_event(device_t, bool);
static bool acpilid_suspend(device_t, const pmf_qual_t *);
CFATTACH_DECL_NEW(acpilid, sizeof(struct acpilid_softc),
acpilid_match, acpilid_attach, acpilid_detach, NULL);
@ -111,8 +109,8 @@ acpilid_attach(device_t parent, device_t self, void *aux)
sc->sc_smpsw.smpsw_name = device_xname(self);
sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_LID;
(void)pmf_device_register(self, NULL, NULL);
(void)sysmon_pswitch_register(&sc->sc_smpsw);
(void)pmf_device_register(self, acpilid_suspend, NULL);
rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle,
ACPI_DEVICE_NOTIFY, acpilid_notify_handler, self);
@ -139,47 +137,6 @@ acpilid_detach(device_t self, int flags)
return 0;
}
static void
acpilid_wake_event(device_t dv, bool enable)
{
struct acpilid_softc *sc = device_private(dv);
ACPI_OBJECT_LIST arg;
ACPI_OBJECT obj[3];
ACPI_STATUS rv;
/*
* First try to call the Device Sleep Wake control method, _DSW.
* Only if this is not available, resort to to the Power State
* Wake control method, _PSW, which was deprecated in ACPI 3.0.
*/
obj[0].Integer.Value = enable ? 1 : 0;
obj[1].Integer.Value = obj[2].Integer.Value = 0;
obj[0].Type = obj[1].Type = obj[2].Type = ACPI_TYPE_INTEGER;
arg.Count = 3;
arg.Pointer = obj;
rv = AcpiEvaluateObject(sc->sc_node->ad_handle, "_DSW", &arg, NULL);
if (ACPI_SUCCESS(rv))
return;
if (rv != AE_NOT_FOUND)
goto fail;
rv = acpi_eval_set_integer(sc->sc_node->ad_handle, "_PSW",
enable ? 1 : 0);
if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND)
goto fail;
return;
fail:
aprint_error_dev(dv, "unable to evaluate wake control method: %s\n",
AcpiFormatException(rv));
}
/*
* acpilid_status_changed:
*
@ -223,16 +180,6 @@ acpilid_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context)
}
}
static bool
acpilid_suspend(device_t dv, const pmf_qual_t *qual)
{
struct acpilid_softc *sc = device_private(dv);
acpilid_wake_event(dv, sc->sc_status == 0);
return true;
}
#ifdef _MODULE
MODULE(MODULE_CLASS_DRIVER, acpilid, NULL);

View File

@ -1,4 +1,4 @@
/* $NetBSD: acpi_wakedev.c,v 1.3 2010/03/05 14:00:17 jruoho Exp $ */
/* $NetBSD: acpi_wakedev.c,v 1.4 2010/03/05 21:01:44 jruoho Exp $ */
/*-
* Copyright (c) 2009 Jared D. McNeill <jmcneill@invisible.ca>
@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: acpi_wakedev.c,v 1.3 2010/03/05 14:00:17 jruoho Exp $");
__KERNEL_RCSID(0, "$NetBSD: acpi_wakedev.c,v 1.4 2010/03/05 21:01:44 jruoho Exp $");
#include <sys/param.h>
#include <sys/device.h>
@ -40,6 +40,8 @@ __KERNEL_RCSID(0, "$NetBSD: acpi_wakedev.c,v 1.3 2010/03/05 14:00:17 jruoho Exp
#include <dev/acpi/acpivar.h>
#include <dev/acpi/acpi_wakedev.h>
static void acpi_wakedev_prepare(struct acpi_devnode *, int, int);
struct acpi_wakedev;
static TAILQ_HEAD(, acpi_wakedev) acpi_wakedevlist =
@ -173,16 +175,83 @@ acpi_wakedev_scan(struct acpi_softc *sc)
}
void
acpi_wakedev_commit(struct acpi_softc *sc)
acpi_wakedev_commit(struct acpi_softc *sc, int state)
{
struct acpi_wakedev *aw;
/*
* As noted in ACPI 3.0 (p. 243), preparing
* a device for wakeup is a two-step process:
*
* 1. Enable all power resources in _PRW.
*
* 2. If present, execute _DSW/_PSW method.
*
* XXX: The first one is yet to be implemented.
*/
TAILQ_FOREACH(aw, &acpi_wakedevlist, aw_list) {
if (aw->aw_enabled) {
aprint_debug_dev(sc->sc_dev, "set wake GPE (%s)\n",
aw->aw_node->ad_name);
acpi_set_wake_gpe(aw->aw_node->ad_handle);
} else
acpi_clear_wake_gpe(aw->aw_node->ad_handle);
acpi_wakedev_prepare(aw->aw_node, aw->aw_enabled, state);
}
}
static void
acpi_wakedev_prepare(struct acpi_devnode *ad, int enable, int state)
{
ACPI_OBJECT_LIST arg;
ACPI_OBJECT obj[3];
ACPI_STATUS rv;
/*
* First try to call the Device Sleep Wake control method, _DSW.
* Only if this is not available, resort to to the Power State
* Wake control method, _PSW, which was deprecated in ACPI 3.0.
*
* The arguments to these methods are as follows:
*
* arg0 arg1 arg2
* ---- ---- ----
* _PSW 0: disable
* 1: enable
*
* _DSW 0: disable 0: S0 0: D0
* 1: enable 1: S1 1: D0 or D1
* 2: D0, D1, or D2
* x: Sx 3: D0, D1, D2 or D3
*/
arg.Count = 3;
arg.Pointer = obj;
obj[0].Integer.Value = enable;
obj[1].Integer.Value = state;
obj[2].Integer.Value = 3;
obj[0].Type = obj[1].Type = obj[2].Type = ACPI_TYPE_INTEGER;
rv = AcpiEvaluateObject(ad->ad_handle, "_DSW", &arg, NULL);
if (ACPI_SUCCESS(rv))
return;
if (rv != AE_NOT_FOUND)
goto fail;
rv = acpi_eval_set_integer(ad->ad_handle, "_PSW", enable);
if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND)
goto fail;
return;
fail:
aprint_error_dev(ad->ad_device, "failed to evaluate wake "
"control method: %s\n", AcpiFormatException(rv));
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: acpi_wakedev.h,v 1.2 2010/03/05 08:30:48 jruoho Exp $ */
/* $NetBSD: acpi_wakedev.h,v 1.3 2010/03/05 21:01:44 jruoho Exp $ */
/*-
* Copyright (c) 2009 Jared D. McNeill <jmcneill@invisible.ca>
@ -30,6 +30,6 @@
#define _SYS_DEV_ACPI_ACPI_WAKEDEV_H
int acpi_wakedev_scan(struct acpi_softc *);
void acpi_wakedev_commit(struct acpi_softc *);
void acpi_wakedev_commit(struct acpi_softc *, int);
#endif /* !_SYS_DEV_ACPI_ACPI_WAKEDEV_H */