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