summaryrefslogtreecommitdiff
path: root/sys/dev/acpi
diff options
context:
space:
mode:
authorMarco Peereboom <marco@cvs.openbsd.org>2006-11-25 18:24:55 +0000
committerMarco Peereboom <marco@cvs.openbsd.org>2006-11-25 18:24:55 +0000
commit11ce40f2401987f5c79c1ba334e59a5f48686d07 (patch)
tree0c0f2c4cdd596a6cc29417d7e37b28c523140491 /sys/dev/acpi
parent7535b19446bafa37c29fe0cefdcfcc8d3b16b636 (diff)
Add mutex.
prodded dlg, ok jordan
Diffstat (limited to 'sys/dev/acpi')
-rw-r--r--sys/dev/acpi/acpivar.h12
-rw-r--r--sys/dev/acpi/amltypes.h4
-rw-r--r--sys/dev/acpi/dsdt.c88
-rw-r--r--sys/dev/acpi/dsdt.h5
4 files changed, 97 insertions, 12 deletions
diff --git a/sys/dev/acpi/acpivar.h b/sys/dev/acpi/acpivar.h
index 034434f48e0..0c15514122c 100644
--- a/sys/dev/acpi/acpivar.h
+++ b/sys/dev/acpi/acpivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpivar.h,v 1.28 2006/10/19 08:56:46 marco Exp $ */
+/* $OpenBSD: acpivar.h,v 1.29 2006/11/25 18:24:54 marco Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
*
@@ -19,6 +19,7 @@
#define _DEV_ACPI_ACPIVAR_H_
#include <sys/timeout.h>
+#include <sys/rwlock.h>
/* #define ACPI_DEBUG */
#ifdef ACPI_DEBUG
@@ -99,6 +100,15 @@ struct acpi_thread {
volatile int running;
};
+struct acpi_mutex {
+ struct rwlock amt_lock;
+#define ACPI_MTX_MAXNAME 5
+ char amt_name[ACPI_MTX_MAXNAME + 3]; /* only 4 used */
+ int amt_ref_count;
+ int amt_timeout;
+ int amt_synclevel;
+};
+
struct gpe_block {
int (*handler)(struct acpi_softc *, int, void *);
void *arg;
diff --git a/sys/dev/acpi/amltypes.h b/sys/dev/acpi/amltypes.h
index 6f36a2844f1..3b12dd2c8a0 100644
--- a/sys/dev/acpi/amltypes.h
+++ b/sys/dev/acpi/amltypes.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: amltypes.h,v 1.19 2006/10/24 19:45:06 marco Exp $ */
+/* $OpenBSD: amltypes.h,v 1.20 2006/11/25 18:24:54 marco Exp $ */
/*
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
*
@@ -282,6 +282,7 @@ struct aml_value
u_int8_t pwr_level;
u_int16_t pwr_order;
} vpowerrsrc;
+ struct acpi_mutex *vmutex;
} _;
};
@@ -296,6 +297,7 @@ struct aml_value
#define v_method _.vmethod
#define v_processor _.vprocessor
#define v_powerrsrc _.vpowerrsrc
+#define v_mutex _.vmutex
#define xaml_intval(v) ((v)->v_integer)
#define aml_strlen(v) ((v)->length)
diff --git a/sys/dev/acpi/dsdt.c b/sys/dev/acpi/dsdt.c
index 96e1c2fa652..732d7cbe415 100644
--- a/sys/dev/acpi/dsdt.c
+++ b/sys/dev/acpi/dsdt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dsdt.c,v 1.63 2006/11/11 19:26:01 marco Exp $ */
+/* $OpenBSD: dsdt.c,v 1.64 2006/11/25 18:24:54 marco Exp $ */
/*
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
*
@@ -50,11 +50,10 @@
#define aml_valid(pv) ((pv) != NULL)
-#define acpi_mutex_acquire(ctx,lock,iv) dnprintf(60,"ACQUIRE: %x" #lock "\n", (short)iv)
-#define acpi_mutex_release(ctx,lock) dnprintf(60,"RELEASE: " #lock "\n")
-
#define aml_ipaddr(n) ((n)-aml_root.start)
+extern int hz;
+
struct aml_scope;
/* New jordan code */
@@ -412,8 +411,6 @@ _acpi_os_free(void *ptr, const char *fn, int line)
void
acpi_sleep(int ms)
{
- extern int hz;
-
if (cold)
delay(ms * 1000);
else
@@ -427,6 +424,64 @@ acpi_stall(int us)
delay(us);
}
+int
+acpi_mutex_acquire(struct aml_value *val, int timeout)
+{
+ struct acpi_mutex *mtx = val->v_mutex;
+ int rv = 0, ts, tries = 0;
+
+ if (val->type != AML_OBJTYPE_MUTEX) {
+ printf("acpi_mutex_acquire: invalid mutex\n");
+ return (1);
+ }
+
+ if (timeout == 0xffff)
+ timeout = 0;
+
+ /* lock recursion be damned, panic if that happens */
+ rw_enter_write(&mtx->amt_lock);
+ while (mtx->amt_ref_count) {
+ rw_exit_write(&mtx->amt_lock);
+ /* block access */
+ ts = tsleep(mtx, PWAIT, mtx->amt_name, timeout / hz);
+ if (ts == EWOULDBLOCK) {
+ rv = 1; /* mutex not acquired */
+ goto done;
+ }
+ tries++;
+ rw_enter_write(&mtx->amt_lock);
+ }
+
+ mtx->amt_ref_count++;
+ rw_exit_write(&mtx->amt_lock);
+done:
+ return (rv);
+}
+
+void
+acpi_mutex_release(struct aml_value *val)
+{
+ struct acpi_mutex *mtx = val->v_mutex;
+
+ /* sanity */
+ if (val->type != AML_OBJTYPE_MUTEX) {
+ printf("acpi_mutex_acquire: invalid mutex\n");
+ return;
+ }
+
+ rw_enter_write(&mtx->amt_lock);
+
+ if (mtx->amt_ref_count == 0) {
+ printf("acpi_mutex_release underflow %s\n", mtx->amt_name);
+ goto done;
+ }
+
+ mtx->amt_ref_count--;
+ wakeup(mtx); /* wake all of them up */
+done:
+ rw_exit_write(&mtx->amt_lock);
+}
+
/*
* @@@: Misc utility functions
*/
@@ -1089,7 +1144,9 @@ aml_showvalue(struct aml_value *val, int lvl)
aml_showvalue(val->v_field.ref2, lvl);
break;
case AML_OBJTYPE_MUTEX:
- printf(" mutex: %llx\n", val->v_integer);
+ printf(" mutex: %s ref: %d\n",
+ val->v_mutex ? val->v_mutex->amt_name : "",
+ val->v_mutex ? val->v_mutex->amt_ref_count : 0);
break;
case AML_OBJTYPE_EVENT:
printf(" event:\n");
@@ -2125,6 +2182,7 @@ aml_parsenamed(struct aml_scope *scope, int opcode, struct aml_value *res)
{
uint8_t *name;
u_int64_t pci_addr;
+ int s, offs = 0;
AML_CHECKSTACK();
name = aml_parsename(scope);
@@ -2143,7 +2201,16 @@ aml_parsenamed(struct aml_scope *scope, int opcode, struct aml_value *res)
break;
case AMLOP_MUTEX:
_aml_setvalue(res, AML_OBJTYPE_MUTEX, 0, NULL);
- res->v_integer = aml_parseint(scope, AMLOP_BYTEPREFIX);
+ res->v_mutex = (struct acpi_mutex *)acpi_os_malloc(
+ sizeof(struct acpi_mutex));
+ res->v_mutex->amt_synclevel = aml_parseint(scope,
+ AMLOP_BYTEPREFIX);
+ s = strlen(aml_getname(name));
+ if (s > 4)
+ offs = s - 4;
+ strlcpy(res->v_mutex->amt_name, aml_getname(name) + offs,
+ ACPI_MTX_MAXNAME);
+ rw_init(&res->v_mutex->amt_lock, res->v_mutex->amt_name);
break;
case AMLOP_OPREGION:
_aml_setvalue(res, AML_OBJTYPE_OPREGION, 0, NULL);
@@ -2564,6 +2631,7 @@ aml_parsemuxaction(struct aml_scope *scope, int opcode, struct aml_value *res)
{
struct aml_value *tmparg;
int64_t i1;
+ int rv;
AML_CHECKSTACK();
@@ -2573,11 +2641,13 @@ aml_parsemuxaction(struct aml_scope *scope, int opcode, struct aml_value *res)
case AMLOP_ACQUIRE:
/* Assert: tmparg is AML_OBJTYPE_MUTEX */
i1 = aml_parseint(scope, AMLOP_WORDPREFIX);
+ rv = acpi_mutex_acquire(tmparg->v_objref.ref, i1);
/* Return true if timed out */
- aml_setvalue(scope, res, NULL, 0);
+ aml_setvalue(scope, res, NULL, rv);
break;
case AMLOP_RELEASE:
+ acpi_mutex_release(tmparg->v_objref.ref);
break;
case AMLOP_WAIT:
diff --git a/sys/dev/acpi/dsdt.h b/sys/dev/acpi/dsdt.h
index 1f45c97046c..b679476d45b 100644
--- a/sys/dev/acpi/dsdt.h
+++ b/sys/dev/acpi/dsdt.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dsdt.h,v 1.18 2006/10/24 19:01:48 jordan Exp $ */
+/* $OpenBSD: dsdt.h,v 1.19 2006/11/25 18:24:54 marco Exp $ */
/*
* Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
*
@@ -86,6 +86,9 @@ int aml_evalname(struct acpi_softc *, struct aml_node *,
void aml_fixup_dsdt(u_int8_t *, u_int8_t *, int);
void aml_create_defaultobjects(void);
+int acpi_mutex_acquire(struct aml_value *, int);
+void acpi_mutex_release(struct aml_value *);
+
#define ACPI_E_NOERROR 0x00
#define ACPI_E_BADVALUE 0x01