summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Weingartner <weingart@cvs.openbsd.org>2007-11-05 03:15:23 +0000
committerTobias Weingartner <weingart@cvs.openbsd.org>2007-11-05 03:15:23 +0000
commitb66f62f3a029d7c622b111734d8d067d06d581cb (patch)
tree9a93679346327d790ff28f8de91c03e91f60f8a1
parentf754ea84cf2b01540d109fa80b2c776879a072b1 (diff)
Use the acpi_{acquire,release}_global_lock() to implement the global
functionality for ACPI. Has not shown any regressions, and may solve some EC race conditions. Ok gwk@, canacar@, ckuethe@
-rw-r--r--sys/dev/acpi/dsdt.c46
1 files changed, 40 insertions, 6 deletions
diff --git a/sys/dev/acpi/dsdt.c b/sys/dev/acpi/dsdt.c
index e3f38ea0094..9c5d8848186 100644
--- a/sys/dev/acpi/dsdt.c
+++ b/sys/dev/acpi/dsdt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dsdt.c,v 1.96 2007/11/03 21:13:48 ckuethe Exp $ */
+/* $OpenBSD: dsdt.c,v 1.97 2007/11/05 03:15:22 weingart Exp $ */
/*
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
*
@@ -1025,20 +1025,54 @@ aml_getbufint(struct aml_value *src, int bitpos, int bitlen,
}
}
+long acpi_acquire_global_lock(void*);
+long acpi_release_global_lock(void*);
+static long global_lock_count = 0;
+
void
aml_lockfield(struct aml_scope *scope, struct aml_value *field)
{
- if (AML_FIELD_LOCK(field->v_field.flags) == AML_FIELD_LOCK_ON) {
- /* XXX: do locking here */
+ int st = 0;
+
+ if (AML_FIELD_LOCK(field->v_field.flags) != AML_FIELD_LOCK_ON)
+ return;
+
+ /* If lock is already ours, just continue */
+ if (global_lock_count++)
+ return;
+
+ /* Spin to acquire lock */
+ while (!st) {
+ st = acpi_acquire_global_lock(&dsdt_softc->sc_facs->global_lock);
+ /* XXX - yield/delay? */
}
+
+ return;
}
void
aml_unlockfield(struct aml_scope *scope, struct aml_value *field)
{
- if (AML_FIELD_LOCK(field->v_field.flags) == AML_FIELD_LOCK_ON) {
- /* XXX: do unlocking here */
- }
+ int st, x;
+
+ if (AML_FIELD_LOCK(field->v_field.flags) != AML_FIELD_LOCK_ON)
+ return;
+
+ /* If we are the last ones, turn out the lights */
+ if (--global_lock_count)
+ return;
+
+ /* Release lock */
+ st = acpi_release_global_lock(&dsdt_softc->sc_facs->global_lock);
+ if (!st)
+ return;
+
+ /* Signal others if someone waiting */
+ x = acpi_read_pmreg(dsdt_softc, ACPIREG_PM1_CNT, 0);
+ x |= ACPI_PM1_GBL_RLS;
+ acpi_write_pmreg(dsdt_softc, ACPIREG_PM1_CNT, 0, x);
+
+ return;
}
void *aml_getbuffer(struct aml_value *, int *);