diff options
author | Marco Peereboom <marco@cvs.openbsd.org> | 2006-11-25 18:24:55 +0000 |
---|---|---|
committer | Marco Peereboom <marco@cvs.openbsd.org> | 2006-11-25 18:24:55 +0000 |
commit | 11ce40f2401987f5c79c1ba334e59a5f48686d07 (patch) | |
tree | 0c0f2c4cdd596a6cc29417d7e37b28c523140491 /sys/dev/acpi | |
parent | 7535b19446bafa37c29fe0cefdcfcc8d3b16b636 (diff) |
Add mutex.
prodded dlg, ok jordan
Diffstat (limited to 'sys/dev/acpi')
-rw-r--r-- | sys/dev/acpi/acpivar.h | 12 | ||||
-rw-r--r-- | sys/dev/acpi/amltypes.h | 4 | ||||
-rw-r--r-- | sys/dev/acpi/dsdt.c | 88 | ||||
-rw-r--r-- | sys/dev/acpi/dsdt.h | 5 |
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 |