Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/acpi Add a per ACPI CPU mutex for C-states. Protect ...



details:   https://anonhg.NetBSD.org/src/rev/9db3f6d86df4
branches:  trunk
changeset: 756721:9db3f6d86df4
user:      jruoho <jruoho%NetBSD.org@localhost>
date:      Thu Jul 29 22:42:58 2010 +0000

description:
Add a per ACPI CPU mutex for C-states. Protect the _CST update with this:
when the idle-information is being updated (e.g. due acpiacad(4) events),
we can not enter the idle-loop. The lock must run at the same priority
(IPL_NONE) as ACPICA's mutexes obtained via AcpiOsCreateMutex() a.k.a.
AcpiOsCreateSemaphore(). Also check want_resched as the first thing and
clarify the suspend/resume path.

There is still one race condition identified: when the driver is loaded as a
module, we must gracefully kick all CPUs out from the ACPI idle-loop upon
detachment.

diffstat:

 sys/dev/acpi/acpi_cpu.c        |   9 +++++-
 sys/dev/acpi/acpi_cpu.h        |   6 +++-
 sys/dev/acpi/acpi_cpu_cstate.c |  55 ++++++++++++++++++++++++++++-------------
 3 files changed, 48 insertions(+), 22 deletions(-)

diffs (200 lines):

diff -r 4bdc9337ddc1 -r 9db3f6d86df4 sys/dev/acpi/acpi_cpu.c
--- a/sys/dev/acpi/acpi_cpu.c   Thu Jul 29 18:36:34 2010 +0000
+++ b/sys/dev/acpi/acpi_cpu.c   Thu Jul 29 22:42:58 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_cpu.c,v 1.8 2010/07/26 15:14:33 jruoho Exp $ */
+/* $NetBSD: acpi_cpu.c,v 1.9 2010/07/29 22:42:58 jruoho Exp $ */
 
 /*-
  * Copyright (c) 2010 Jukka Ruohonen <jruohonen%iki.fi@localhost>
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_cpu.c,v 1.8 2010/07/26 15:14:33 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_cpu.c,v 1.9 2010/07/29 22:42:58 jruoho Exp $");
 
 #include <sys/param.h>
 #include <sys/cpu.h>
@@ -114,6 +114,7 @@
        KASSERT(acpicpu_sc != NULL);
 
        sc->sc_dev = self;
+       sc->sc_cold = false;
        sc->sc_iot = aa->aa_iot;
        sc->sc_node = aa->aa_node;
        sc->sc_cpuid = acpicpu_id(sc->sc_object.ao_procid);
@@ -468,6 +469,8 @@
 {
        struct acpicpu_softc *sc = device_private(self);
 
+       sc->sc_cold = true;
+
        if ((sc->sc_flags & ACPICPU_FLAG_C) != 0)
                (void)acpicpu_cstate_suspend(self);
 
@@ -479,6 +482,8 @@
 {
        struct acpicpu_softc *sc = device_private(self);
 
+       sc->sc_cold = false;
+
        if ((sc->sc_flags & ACPICPU_FLAG_C) != 0)
                (void)acpicpu_cstate_resume(self);
 
diff -r 4bdc9337ddc1 -r 9db3f6d86df4 sys/dev/acpi/acpi_cpu.h
--- a/sys/dev/acpi/acpi_cpu.h   Thu Jul 29 18:36:34 2010 +0000
+++ b/sys/dev/acpi/acpi_cpu.h   Thu Jul 29 22:42:58 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_cpu.h,v 1.6 2010/07/27 05:11:32 jruoho Exp $ */
+/* $NetBSD: acpi_cpu.h,v 1.7 2010/07/29 22:42:58 jruoho Exp $ */
 
 /*-
  * Copyright (c) 2010 Jukka Ruohonen <jruohonen%iki.fi@localhost>
@@ -120,14 +120,16 @@
 struct acpicpu_softc {
        device_t                 sc_dev;
        struct acpi_devnode     *sc_node;
+       struct acpicpu_object    sc_object;
        struct acpicpu_cstate    sc_cstate[ACPI_C_STATE_COUNT];
-       struct acpicpu_object    sc_object;
+       kmutex_t                 sc_cstate_mtx;
        bus_space_tag_t          sc_iot;
        bus_space_handle_t       sc_ioh;
        uint32_t                 sc_sleep;
        uint32_t                 sc_cpuid;
        uint32_t                 sc_cap;
        uint32_t                 sc_flags;
+       bool                     sc_cold;
 };
 
 /*
diff -r 4bdc9337ddc1 -r 9db3f6d86df4 sys/dev/acpi/acpi_cpu_cstate.c
--- a/sys/dev/acpi/acpi_cpu_cstate.c    Thu Jul 29 18:36:34 2010 +0000
+++ b/sys/dev/acpi/acpi_cpu_cstate.c    Thu Jul 29 22:42:58 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_cpu_cstate.c,v 1.11 2010/07/27 05:11:33 jruoho Exp $ */
+/* $NetBSD: acpi_cpu_cstate.c,v 1.12 2010/07/29 22:42:58 jruoho Exp $ */
 
 /*-
  * Copyright (c) 2010 Jukka Ruohonen <jruohonen%iki.fi@localhost>
@@ -27,13 +27,14 @@
  * SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_cstate.c,v 1.11 2010/07/27 05:11:33 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_cstate.c,v 1.12 2010/07/29 22:42:58 jruoho Exp $");
 
 #include <sys/param.h>
 #include <sys/cpu.h>
 #include <sys/device.h>
 #include <sys/kernel.h>
 #include <sys/once.h>
+#include <sys/mutex.h>
 #include <sys/timetc.h>
 
 #include <dev/pci/pcivar.h>
@@ -63,7 +64,6 @@
 static void             acpicpu_cstate_idle_enter(struct acpicpu_softc *,int);
 
 extern struct acpicpu_softc **acpicpu_sc;
-extern int                   acpi_suspended;
 
 /*
  * XXX:        The local APIC timer (as well as TSC) is typically
@@ -101,6 +101,8 @@
 
        acpicpu_cstate_quirks(sc);
        acpicpu_cstate_attach_print(sc);
+
+       mutex_init(&sc->sc_cstate_mtx, MUTEX_DEFAULT, IPL_NONE);
 }
 
 void
@@ -175,9 +177,19 @@
 int
 acpicpu_cstate_detach(device_t self)
 {
+       struct acpicpu_softc *sc = device_private(self);
        static ONCE_DECL(once_detach);
+       int rv;
+
+       rv = RUN_ONCE(&once_detach, acpicpu_md_idle_stop);
 
-       return RUN_ONCE(&once_detach, acpicpu_md_idle_stop);
+       if (rv != 0)
+               return rv;
+
+       sc->sc_flags &= ~ACPICPU_FLAG_C;
+       mutex_destroy(&sc->sc_cstate_mtx);
+
+       return 0;
 }
 
 int
@@ -241,9 +253,9 @@
                return;
        }
 
-       (void)acpicpu_md_idle_stop();
+       mutex_enter(&sc->sc_cstate_mtx);
        (void)acpicpu_cstate_cst(sc);
-       (void)acpicpu_md_idle_start();
+       mutex_exit(&sc->sc_cstate_mtx);
 }
 
 static ACPI_STATUS
@@ -702,6 +714,9 @@
        struct acpicpu_softc *sc;
        int state;
 
+       if (__predict_false(ci->ci_want_resched) != 0)
+               return;
+
        acpi_md_OsDisableInterrupt();
 
        KASSERT(acpicpu_sc != NULL);
@@ -710,20 +725,19 @@
 
        sc = acpicpu_sc[ci->ci_cpuid];
 
-       /*
-        * If all CPUs do not have their ACPI counterparts, the softc
-        * may be NULL. In this case fall back to normal C1 with HALT.
-        */
-       if (__predict_false(sc == NULL)) {
-               acpicpu_md_idle_enter(ACPICPU_C_STATE_HALT, ACPI_STATE_C1);
-               return;
-       }
+       if (__predict_false(sc == NULL))
+               goto halt;
+
+       if (__predict_false(sc->sc_cold != false))
+               goto halt;
 
-       if (__predict_false(acpi_suspended != 0)) {
-               acpicpu_md_idle_enter(ACPICPU_C_STATE_HALT, ACPI_STATE_C1);
-               return;
-       }
+       if (__predict_false((sc->sc_flags & ACPICPU_FLAG_C) == 0))
+               goto halt;
 
+       if (__predict_false(mutex_tryenter(&sc->sc_cstate_mtx) == 0))
+               goto halt;
+
+       mutex_exit(&sc->sc_cstate_mtx);
        state = acpicpu_cstate_latency(sc);
 
        /*
@@ -780,6 +794,11 @@
 
        if ((sc->sc_flags & ACPICPU_FLAG_C_ARB) != 0)
                (void)AcpiWriteBitRegister(ACPI_BITREG_ARB_DISABLE, 0);
+
+       return;
+
+halt:
+       acpicpu_md_idle_enter(ACPICPU_C_STATE_HALT, ACPI_STATE_C1);
 }
 
 static void



Home | Main Index | Thread Index | Old Index