On Mon, Nov 19, 2012 at 07:41:25PM +0200, Paul Irofti wrote:
> On Mon, Nov 19, 2012 at 10:38:52AM -0700, Theo de Raadt wrote:
> > > +int
> > > +acpi_acquire_global_lock(uint32_t *lock)
> > ...
> > > #define acpi_acquire_global_lock(x) 1
> >
> > That is not a nice thing to do.
>
> I agree. This was there before though.
>
Here's a diff with different names for the release|acquire routines:
Index: arch/amd64/amd64/acpi_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/acpi_machdep.c,v
retrieving revision 1.51
diff -u -p -r1.51 acpi_machdep.c
--- arch/amd64/amd64/acpi_machdep.c 17 Oct 2012 22:49:27 -0000 1.51
+++ arch/amd64/amd64/acpi_machdep.c 19 Nov 2012 17:48:25 -0000
@@ -168,6 +168,44 @@ havebase:
return (1);
}
+/*
+ * Acquire the global lock. If busy, set the pending bit. The caller
+ * will wait for notification from the BIOS that the lock is available
+ * and then attempt to acquire it again.
+ */
+int
+acpi_acquire_glk(uint32_t *lock)
+{
+ uint32_t new, old;
+
+ do {
+ old = *lock;
+ new = (old & ~GL_BIT_PENDING) | GL_BIT_OWNED;
+ if ((old & GL_BIT_OWNED) != 0)
+ new |= GL_BIT_PENDING;
+ } while (x86_atomic_cas_int32(lock, old, new) == 0);
+
+ return ((new & GL_BIT_PENDING) == 0);
+}
+
+/*
+ * Release the global lock, returning whether there is a waiter pending.
+ * If the BIOS set the pending bit, OSPM must notify the BIOS when it
+ * releases the lock.
+ */
+int
+acpi_release_glk(uint32_t *lock)
+{
+ uint32_t new, old;
+
+ do {
+ old = *lock;
+ new = old & ~(GL_BIT_PENDING | GL_BIT_OWNED);
+ } while (x86_atomic_cas_int32(lock, old, new) == 0);
+
+ return ((old & GL_BIT_PENDING) != 0);
+}
+
#ifndef SMALL_KERNEL
void
Index: arch/i386/i386/acpi_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/acpi_machdep.c,v
retrieving revision 1.45
diff -u -p -r1.45 acpi_machdep.c
--- arch/i386/i386/acpi_machdep.c 17 Oct 2012 22:49:27 -0000 1.45
+++ arch/i386/i386/acpi_machdep.c 19 Nov 2012 17:48:26 -0000
@@ -183,6 +183,44 @@ havebase:
return (1);
}
+/*
+ * Acquire the global lock. If busy, set the pending bit. The caller
+ * will wait for notification from the BIOS that the lock is available
+ * and then attempt to acquire it again.
+ */
+int
+acpi_acquire_glk(uint32_t *lock)
+{
+ uint32_t new, old;
+
+ do {
+ old = *lock;
+ new = (old & ~GL_BIT_PENDING) | GL_BIT_OWNED;
+ if ((old & GL_BIT_OWNED) != 0)
+ new |= GL_BIT_PENDING;
+ } while (i386_atomic_cas_int32(lock, old, new) == 0);
+
+ return ((new & GL_BIT_PENDING) == 0);
+}
+
+/*
+ * Release the global lock, returning whether there is a waiter pending.
+ * If the BIOS set the pending bit, OSPM must notify the BIOS when it
+ * releases the lock.
+ */
+int
+acpi_release_glk(uint32_t *lock)
+{
+ uint32_t new, old;
+
+ do {
+ old = *lock;
+ new = old & ~(GL_BIT_PENDING | GL_BIT_OWNED);
+ } while (i386_atomic_cas_int32(lock, old, new) == 0);
+
+ return ((old & GL_BIT_PENDING) != 0);
+}
+
#ifndef SMALL_KERNEL
void
Index: dev/acpi/acpivar.h
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpivar.h,v
retrieving revision 1.74
diff -u -p -r1.74 acpivar.h
--- dev/acpi/acpivar.h 8 Oct 2012 21:47:50 -0000 1.74
+++ dev/acpi/acpivar.h 19 Nov 2012 17:48:27 -0000
@@ -325,6 +325,12 @@ int acpi_dotask(struct acpi_softc *);
void acpi_powerdown_task(void *, int);
void acpi_sleep_task(void *, int);
+/* Section 5.2.10.1: global lock acquire/release functions */
+#define GL_BIT_PENDING 0x01
+#define GL_BIT_OWNED 0x02
+int acpi_acquire_glk(uint32_t *);
+int acpi_release_glk(uint32_t *);
+
void acpi_pciroots_attach(struct device *, void *, cfprint_t);
#endif