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:
parent
effc302a58
commit
c38f7a7cda
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue