summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2007-06-02 19:21:40 +0000
committernjl <njl@FreeBSD.org>2007-06-02 19:21:40 +0000
commit1567a26ec017c50e317867657611d6dbd1b816a0 (patch)
treedaa0853e0ceddab48782ebf16e6bf45a87924925
parentc14d50d1f4e55e7ade7d712cdf40128fb46c3ebb (diff)
downloadFreeBSD-src-1567a26ec017c50e317867657611d6dbd1b816a0.zip
FreeBSD-src-1567a26ec017c50e317867657611d6dbd1b816a0.tar.gz
AcpiAcquireGlobalLock() can sometimes sleep if the mutex is contested.
The global lock is a memory region shared with the BIOS and thus has some strange behavior like the fact that the sleep is 1 ms max. We use standard mutexes to synchronize with the SCI so acquiring the global lock after locking the mutex resulted in a witness warning. To deal with this for now, acquire the global lock before all other locks, similar to Giant. This should fix the witness "sleeping with mutex held" issue on boot that occurred after the last ACPI-CA import. In the future, we hope to move to the new mutex interface in ACPI-CA instead of the pseudo-semaphore version we have now. Reviewed by: jkim
-rw-r--r--sys/dev/acpica/acpi_ec.c23
1 files changed, 10 insertions, 13 deletions
diff --git a/sys/dev/acpica/acpi_ec.c b/sys/dev/acpica/acpi_ec.c
index 350fc86..2ba7958 100644
--- a/sys/dev/acpica/acpi_ec.c
+++ b/sys/dev/acpica/acpi_ec.c
@@ -312,37 +312,34 @@ EcLock(struct acpi_ec_softc *sc, int serialize)
{
ACPI_STATUS status;
+ /* If _GLK is non-zero, acquire the global lock. */
+ status = AE_OK;
+ if (sc->ec_glk) {
+ status = AcpiAcquireGlobalLock(EC_LOCK_TIMEOUT, &sc->ec_glkhandle);
+ if (ACPI_FAILURE(status))
+ return (status);
+ }
+
/*
* If caller is executing a series of commands, acquire the exclusive lock
* to serialize with other users.
* To sync with bottom-half interrupt handler, always acquire the mutex.
*/
- status = AE_OK;
if (serialize)
ACPI_SERIAL_BEGIN(ec);
mtx_lock(&sc->ec_mtx);
- /* If _GLK is non-zero, also acquire the global lock. */
- if (sc->ec_glk) {
- status = AcpiAcquireGlobalLock(EC_LOCK_TIMEOUT, &sc->ec_glkhandle);
- if (ACPI_FAILURE(status)) {
- mtx_unlock(&sc->ec_mtx);
- if (serialize)
- ACPI_SERIAL_END(ec);
- }
- }
-
return (status);
}
static __inline void
EcUnlock(struct acpi_ec_softc *sc)
{
- if (sc->ec_glk)
- AcpiReleaseGlobalLock(sc->ec_glkhandle);
mtx_unlock(&sc->ec_mtx);
if (sx_xlocked(&ec_sxlock))
ACPI_SERIAL_END(ec);
+ if (sc->ec_glk)
+ AcpiReleaseGlobalLock(sc->ec_glkhandle);
}
static uint32_t EcGpeHandler(void *Context);
OpenPOWER on IntegriCloud