Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/acpi Initial pass for issues observed by dyoung@ on ...
details: https://anonhg.NetBSD.org/src/rev/4c0dd17786cd
branches: trunk
changeset: 754781:4c0dd17786cd
user: jruoho <jruoho%NetBSD.org@localhost>
date: Wed May 12 15:59:52 2010 +0000
description:
Initial pass for issues observed by dyoung@ on HP Pavilion N3270. In this
laptop there is a PNP0C0B ("ACPI fan") with the following properties:
_PSC : Power state for D3 (alone).
_PR0 : Power resources for D0.
_PSx : Power state switch for D0 and D3.
Thus, it is impossible to get or set the D3 power state via power resources
alone; there is only a single PowerResource() and it is for D0.
To tackle this:
1. Evaluate the direct _PSC control method if and only if there is no
given _PRx. The order is important; it is known that some other
systems implement the _PSC method (like _STA) incorrectly.
2. If no _PRx is available (and thus no _ON or _OFF), do not error out.
Instead, if we have AE_NOT_FOUND, continue to evaluate the power state
switch method, _PSx, which (on this laptop) should alone suffice for
the D0 -> D3 transition.
diffstat:
sys/dev/acpi/acpi_power.c | 47 +++++++++++++++++++++++++----------------------
1 files changed, 25 insertions(+), 22 deletions(-)
diffs (131 lines):
diff -r 561cdb629f2f -r 4c0dd17786cd sys/dev/acpi/acpi_power.c
--- a/sys/dev/acpi/acpi_power.c Wed May 12 15:54:47 2010 +0000
+++ b/sys/dev/acpi/acpi_power.c Wed May 12 15:59:52 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_power.c,v 1.11 2010/04/27 05:34:14 jruoho Exp $ */
+/* $NetBSD: acpi_power.c,v 1.12 2010/05/12 15:59:52 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.11 2010/04/27 05:34:14 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_power.c,v 1.12 2010/05/12 15:59:52 jruoho Exp $");
#include <sys/param.h>
#include <sys/kmem.h>
@@ -104,10 +104,7 @@
static struct acpi_power_res *acpi_power_res_init(ACPI_HANDLE);
static struct acpi_power_res *acpi_power_res_get(ACPI_HANDLE);
-#if 0
static ACPI_STATUS acpi_power_get_direct(struct acpi_devnode *);
-#endif
-
static ACPI_STATUS acpi_power_get_indirect(struct acpi_devnode *);
static ACPI_STATUS acpi_power_switch(struct acpi_devnode *,
int, bool);
@@ -267,9 +264,18 @@
goto fail;
}
+ /*
+ * Because the _PSC control method, like _STA,
+ * is known to be implemented incorrectly in
+ * many systems, we first try to retrieve the
+ * power state indirectly via power resources.
+ */
rv = acpi_power_get_indirect(ad);
if (ACPI_FAILURE(rv))
+ rv = acpi_power_get_direct(ad);
+
+ if (ACPI_FAILURE(rv))
goto fail;
KASSERT(ad->ad_state != ACPI_STATE_ERROR);
@@ -296,11 +302,6 @@
return false;
}
-#if 0
-/*
- * Unfortunately, comparable to _STA, there are systems
- * where the convenient _PSC is implemented incorrectly.
- */
static ACPI_STATUS
acpi_power_get_direct(struct acpi_devnode *ad)
{
@@ -315,7 +316,6 @@
return rv;
}
-#endif
static ACPI_STATUS
acpi_power_get_indirect(struct acpi_devnode *ad)
@@ -410,27 +410,25 @@
}
/*
- * We first sweep through the resources required
- * for the target state, turning things on and
- * building references. After this we dereference
- * the resources required for the current state,
+ * We first sweep through the resources required for the target
+ * state, turning things on and building references. After this
+ * we dereference the resources required for the current state,
* turning the resources off as we go.
*/
rv = acpi_power_switch(ad, state, true);
- if (ACPI_FAILURE(rv))
+ if (ACPI_FAILURE(rv) && rv != AE_CTRL_CONTINUE)
goto fail;
rv = acpi_power_switch(ad, ad->ad_state, false);
- if (ACPI_FAILURE(rv))
+ if (ACPI_FAILURE(rv) && rv != AE_CTRL_CONTINUE)
goto fail;
- ad->ad_state = state;
-
/*
- * Last but not least, invoke the power
- * state switch method, if available.
+ * Last but not least, invoke the power state switch method,
+ * if available. Because some systems use only _PSx for the
+ * power state transitions, we do this even if there is no _PRx.
*/
(void)snprintf(path, sizeof(path), "_PS%d", state);
(void)AcpiEvaluateObject(ad->ad_handle, path, NULL, NULL);
@@ -438,6 +436,8 @@
aprint_debug_dev(ad->ad_root, "%s turned from "
"D%d to D%d\n", ad->ad_name, old, state);
+ ad->ad_state = state;
+
return true;
fail:
@@ -472,13 +472,16 @@
pkg = acpi_power_pkg_get(ad->ad_handle, state);
if (pkg == NULL)
- return AE_NOT_EXIST;
+ return AE_CTRL_CONTINUE;
if (on != false)
rv = acpi_foreach_package_object(pkg, acpi_power_res_on, ad);
else
rv = acpi_foreach_package_object(pkg, acpi_power_res_off, ad);
+ if (rv == AE_CTRL_CONTINUE)
+ rv = AE_ERROR;
+
ACPI_FREE(pkg);
return rv;
Home |
Main Index |
Thread Index |
Old Index