diff options
-rw-r--r-- | sys/conf/options | 2 | ||||
-rw-r--r-- | sys/contrib/dev/acpica/exsystem.c | 10 | ||||
-rw-r--r-- | sys/dev/acpica/Osd/OsdDebug.c | 3 | ||||
-rw-r--r-- | sys/dev/acpica/Osd/OsdSchedule.c | 131 | ||||
-rw-r--r-- | sys/dev/acpica/Osd/OsdSynch.c | 160 | ||||
-rw-r--r-- | sys/dev/acpica/acpi.c | 50 | ||||
-rw-r--r-- | sys/dev/acpica/acpi_cmbat.c | 83 | ||||
-rw-r--r-- | sys/dev/acpica/acpi_ec.c | 4 | ||||
-rw-r--r-- | sys/dev/acpica/acpi_powerres.c | 3 | ||||
-rw-r--r-- | sys/dev/acpica/acpi_thermal.c | 36 | ||||
-rw-r--r-- | sys/dev/acpica/acpivar.h | 9 | ||||
-rw-r--r-- | sys/modules/acpi/Makefile | 6 |
12 files changed, 378 insertions, 119 deletions
diff --git a/sys/conf/options b/sys/conf/options index 3ec6231..066911f 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -513,6 +513,8 @@ WITNESS_SKIPSPIN opt_witness.h ACPI_DEBUG opt_acpi.h AML_DEBUG opt_acpi.h ACPI_NO_ENABLE_ON_BOOT opt_acpi.h +ACPI_NO_SEMAPHORES opt_acpi.h +ACPI_MAX_THREADS opt_acpi.h # options for DEVFS, see sys/fs/devfs/devfs.h NDEVFSINO opt_devfs.h diff --git a/sys/contrib/dev/acpica/exsystem.c b/sys/contrib/dev/acpica/exsystem.c index df03448..b462597 100644 --- a/sys/contrib/dev/acpica/exsystem.c +++ b/sys/contrib/dev/acpica/exsystem.c @@ -147,7 +147,7 @@ AcpiExSystemWaitSemaphore ( ACPI_HANDLE Semaphore, UINT32 Timeout) { - ACPI_STATUS Status; + ACPI_STATUS Status, Status2; FUNCTION_TRACE ("ExSystemWaitSemaphore"); @@ -172,12 +172,12 @@ AcpiExSystemWaitSemaphore ( /* Reacquire the interpreter */ - Status = AcpiExEnterInterpreter (); - if (ACPI_SUCCESS (Status)) + Status2 = AcpiExEnterInterpreter (); + if (ACPI_FAILURE (Status2)) { - /* Restore the timeout exception */ + /* Report fatal error, could not acquire interpreter */ - Status = AE_TIME; + return_ACPI_STATUS (Status2); } } diff --git a/sys/dev/acpica/Osd/OsdDebug.c b/sys/dev/acpica/Osd/OsdDebug.c index 776e871..cfcf5b6 100644 --- a/sys/dev/acpica/Osd/OsdDebug.c +++ b/sys/dev/acpica/Osd/OsdDebug.c @@ -84,8 +84,9 @@ AcpiOsSignal ( switch(Function) { case ACPI_SIGNAL_FATAL: fatal = (ACPI_SIGNAL_FATAL_INFO *)Info; - panic("ACPI fatal signal, type 0x%x code 0x%x argument 0x%x", + printf("ACPI fatal signal, type 0x%x code 0x%x argument 0x%x", fatal->Type, fatal->Code, fatal->Argument); + Debugger("AcpiOsSignal"); break; case ACPI_SIGNAL_BREAKPOINT: diff --git a/sys/dev/acpica/Osd/OsdSchedule.c b/sys/dev/acpica/Osd/OsdSchedule.c index 8a952df..60a8f48 100644 --- a/sys/dev/acpica/Osd/OsdSchedule.c +++ b/sys/dev/acpica/Osd/OsdSchedule.c @@ -33,21 +33,30 @@ #include "acpi.h" +#include "opt_acpi.h" +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/interrupt.h> #include <sys/kernel.h> +#include <sys/kthread.h> +#include <sys/lock.h> #include <sys/malloc.h> +#include <sys/mutex.h> #include <sys/proc.h> #include <sys/taskqueue.h> #include <machine/clock.h> +#include <sys/bus.h> + +#include <dev/acpica/acpivar.h> + #define _COMPONENT ACPI_OS_SERVICES MODULE_NAME("SCHEDULE") /* * This is a little complicated due to the fact that we need to build and then * free a 'struct task' for each task we enqueue. - * - * We use the default taskqueue_swi queue, since it really doesn't matter what - * else we're queued along with. */ MALLOC_DEFINE(M_ACPITASK, "acpitask", "ACPI deferred task"); @@ -60,6 +69,95 @@ struct acpi_task { void *at_context; }; +struct acpi_task_queue { + STAILQ_ENTRY(acpi_task_queue) at_q; + struct acpi_task *at; +}; + +/* + * Private task queue definition for ACPI + */ +TASKQUEUE_DECLARE(acpi); +static void *taskqueue_acpi_ih; + +static void +taskqueue_acpi_enqueue(void *context) +{ + swi_sched(taskqueue_acpi_ih, SWI_NOSWITCH); +} + +static void +taskqueue_acpi_run(void *dummy) +{ + taskqueue_run(taskqueue_acpi); +} + +TASKQUEUE_DEFINE(acpi, taskqueue_acpi_enqueue, 0, + swi_add(NULL, "acpitaskq", taskqueue_acpi_run, NULL, + SWI_TQ, 0, &taskqueue_acpi_ih)); + +#if defined(ACPI_MAX_THREADS) && ACPI_MAX_THREADS > 0 +#define ACPI_USE_THREADS +#endif + +#ifdef ACPI_USE_THREADS +STAILQ_HEAD(, acpi_task_queue) acpi_task_queue; +static struct mtx acpi_task_mtx; + +static void +acpi_task_thread(void *arg) +{ + struct acpi_task_queue *atq; + OSD_EXECUTION_CALLBACK Function; + void *Context; + + for (;;) { + mtx_lock(&acpi_task_mtx); + if ((atq = STAILQ_FIRST(&acpi_task_queue)) == NULL) { + msleep(&acpi_task_queue, &acpi_task_mtx, PCATCH, "actask", 0); + mtx_unlock(&acpi_task_mtx); + continue; + } + + STAILQ_REMOVE_HEAD(&acpi_task_queue, at_q); + mtx_unlock(&acpi_task_mtx); + + Function = (OSD_EXECUTION_CALLBACK)atq->at->at_function; + Context = atq->at->at_context; + + mtx_lock(&Giant); + Function(Context); + + free(atq->at, M_ACPITASK); + free(atq, M_ACPITASK); + mtx_unlock(&Giant); + } + + kthread_exit(0); +} + +int +acpi_task_thread_init(void) +{ + int i, err; + struct proc *acpi_kthread_proc; + + err = 0; + STAILQ_INIT(&acpi_task_queue); + mtx_init(&acpi_task_mtx, "ACPI task", MTX_DEF); + + for (i = 0; i < ACPI_MAX_THREADS; i++) { + err = kthread_create(acpi_task_thread, NULL, &acpi_kthread_proc, + 0, "acpi_task%d", i); + if (err != 0) { + printf("%s: kthread_create failed(%d)\n", __func__, err); + break; + } + } + return (err); +} +#endif + ACPI_STATUS AcpiOsQueueForExecution(UINT32 Priority, OSD_EXECUTION_CALLBACK Function, void *Context) { @@ -97,25 +195,46 @@ AcpiOsQueueForExecution(UINT32 Priority, OSD_EXECUTION_CALLBACK Function, void * } TASK_INIT(&at->at_task, pri, AcpiOsExecuteQueue, at); - taskqueue_enqueue(taskqueue_swi, (struct task *)at); + taskqueue_enqueue(taskqueue_acpi, (struct task *)at); return_ACPI_STATUS(AE_OK); } static void AcpiOsExecuteQueue(void *arg, int pending) { - struct acpi_task *at = (struct acpi_task *)arg; + struct acpi_task *at; + struct acpi_task_queue *atq; OSD_EXECUTION_CALLBACK Function; void *Context; FUNCTION_TRACE(__func__); + at = (struct acpi_task *)arg; + atq = NULL; + Function = NULL; + Context = NULL; + +#ifdef ACPI_USE_THREADS + atq = malloc(sizeof(*atq), M_ACPITASK, M_NOWAIT); + if (atq == NULL) { + printf("%s: no memory\n", __func__); + return; + } + + atq->at = at; + + mtx_lock(&acpi_task_mtx); + STAILQ_INSERT_TAIL(&acpi_task_queue, atq, at_q); + mtx_unlock(&acpi_task_mtx); + wakeup_one(&acpi_task_queue); +#else Function = (OSD_EXECUTION_CALLBACK)at->at_function; Context = at->at_context; + Function(Context); free(at, M_ACPITASK); +#endif - Function(Context); return_VOID; } diff --git a/sys/dev/acpica/Osd/OsdSynch.c b/sys/dev/acpica/Osd/OsdSynch.c index 5c5141d..1d5533f 100644 --- a/sys/dev/acpica/Osd/OsdSynch.c +++ b/sys/dev/acpica/Osd/OsdSynch.c @@ -33,19 +33,18 @@ #include "acpi.h" +#include "opt_acpi.h" #include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> #include <sys/mutex.h> +#include <sys/sysctl.h> #define _COMPONENT ACPI_OS_SERVICES MODULE_NAME("SYNCH") static MALLOC_DEFINE(M_ACPISEM, "acpisem", "ACPI semaphore"); -/* disable semaphores - AML in the field doesn't use them correctly */ -#define ACPI_NO_SEMAPHORES - /* * Simple counting semaphore implemented using a mutex. (Subsequently used * in the OSI code to implement a mutex. Go figure.) @@ -54,8 +53,21 @@ struct acpi_semaphore { struct mtx as_mtx; UINT32 as_units; UINT32 as_maxunits; + UINT32 as_pendings; + UINT32 as_resetting; + UINT32 as_timeouts; }; +#ifndef ACPI_NO_SEMAPHORES +#ifndef ACPI_SEMAPHORES_MAX_PENDING +#define ACPI_SEMAPHORES_MAX_PENDING 4 +#endif +static int acpi_semaphore_debug = 0; +TUNABLE_INT("debug.acpi_semaphore_debug", &acpi_semaphore_debug); +SYSCTL_INT(_debug, OID_AUTO, acpi_semaphore_debug, CTLFLAG_RW, + &acpi_semaphore_debug, 0, ""); +#endif + ACPI_STATUS AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits, ACPI_HANDLE *OutHandle) { @@ -72,12 +84,15 @@ AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits, ACPI_HANDLE *OutHand if ((as = malloc(sizeof(*as), M_ACPISEM, M_NOWAIT)) == NULL) return_ACPI_STATUS(AE_NO_MEMORY); + bzero(as, sizeof(*as)); mtx_init(&as->as_mtx, "ACPI semaphore", MTX_DEF); as->as_units = InitialUnits; as->as_maxunits = MaxUnits; + as->as_pendings = as->as_resetting = as->as_timeouts = 0; - DEBUG_PRINT(TRACE_MUTEX, ("created semaphore %p max %d, initial %d\n", - as, InitialUnits, MaxUnits)); + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "created semaphore %p max %d, initial %d\n", + as, InitialUnits, MaxUnits)); *OutHandle = (ACPI_HANDLE)as; return_ACPI_STATUS(AE_OK); @@ -95,7 +110,7 @@ AcpiOsDeleteSemaphore (ACPI_HANDLE Handle) FUNCTION_TRACE(__func__); - DEBUG_PRINT(TRACE_MUTEX, ("destroyed semaphore %p\n", as)); + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "destroyed semaphore %p\n", as)); mtx_destroy(&as->as_mtx); free(Handle, M_ACPISEM); return_ACPI_STATUS(AE_OK); @@ -116,27 +131,58 @@ AcpiOsWaitSemaphore(ACPI_HANDLE Handle, UINT32 Units, UINT32 Timeout) struct acpi_semaphore *as = (struct acpi_semaphore *)Handle; ACPI_STATUS result; int rv, tmo; + struct timeval timeouttv, currenttv, timelefttv; FUNCTION_TRACE(__func__); if (as == NULL) return_ACPI_STATUS(AE_BAD_PARAMETER); - /* a timeout of -1 means "forever" */ - if (Timeout == -1) { + if (cold) + return_ACPI_STATUS(AE_OK); + +#if 0 + if (as->as_units < Units && as->as_timeouts > 10) { + printf("%s: semaphore %p too many timeouts, resetting\n", __func__, as); + mtx_lock(&as->as_mtx); + as->as_units = as->as_maxunits; + if (as->as_pendings) + as->as_resetting = 1; + as->as_timeouts = 0; + wakeup(as); + mtx_unlock(&as->as_mtx); + return_ACPI_STATUS(AE_TIME); + } + + if (as->as_resetting) { + return_ACPI_STATUS(AE_TIME); + } +#endif + + /* a timeout of WAIT_FOREVER means "forever" */ + if (Timeout == WAIT_FOREVER) { tmo = 0; + timeouttv.tv_sec = ((0xffff/1000) + 1); /* cf. ACPI spec */ + timeouttv.tv_usec = 0; } else { /* compute timeout using microseconds per tick */ tmo = (Timeout * 1000) / (1000000 / hz); if (tmo <= 0) tmo = 1; + timeouttv.tv_sec = Timeout / 1000; + timeouttv.tv_usec = (Timeout % 1000) * 1000; } + /* calculate timeout value in timeval */ + getmicrotime(¤ttv); + timevaladd(&timeouttv, ¤ttv); + mtx_lock(&as->as_mtx); - DEBUG_PRINT(TRACE_MUTEX, ("get %d units from semaphore %p (has %d), timeout %d\n", - Units, as, as->as_units, Timeout)); + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "get %d units from semaphore %p (has %d), timeout %d\n", + Units, as, as->as_units, Timeout)); for (;;) { - if (as->as_inits == ACPI_NO_UNIT_LIMIT) { + if (as->as_units == ACPI_NO_UNIT_LIMIT) { result = AE_OK; break; } @@ -145,20 +191,89 @@ AcpiOsWaitSemaphore(ACPI_HANDLE Handle, UINT32 Units, UINT32 Timeout) result = AE_OK; break; } - if (Timeout < 0) { + + /* limit number of pending treads */ + if (as->as_pendings >= ACPI_SEMAPHORES_MAX_PENDING) { result = AE_TIME; break; } - DEBUG_PRINT(TRACE_MUTEX, ("semaphore blocked, calling msleep(%p, %p, %d, \"acpisem\", %d)\n", - as, as->as_mtx, 0, tmo)); - - rv = msleep(as, &as->as_mtx, 0, "acpisem", tmo); - DEBUG_PRINT(TRACE_MUTEX, ("msleep returned %d\n", rv)); + + /* if timeout values of zero is specified, return immediately */ + if (Timeout == 0) { + result = AE_TIME; + break; + } + + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "semaphore blocked, calling msleep(%p, %p, %d, \"acsem\", %d)\n", + as, &as->as_mtx, PCATCH, tmo)); + + as->as_pendings++; + + if (acpi_semaphore_debug) { + printf("%s: Sleep %d, pending %d, semaphore %p, thread %d\n", + __func__, Timeout, as->as_pendings, as, AcpiOsGetThreadId()); + } + + rv = msleep(as, &as->as_mtx, PCATCH, "acsem", tmo); + + as->as_pendings--; + +#if 0 + if (as->as_resetting) { + /* semaphore reset, return immediately */ + if (as->as_pendings == 0) { + as->as_resetting = 0; + } + result = AE_TIME; + break; + } +#endif + + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "msleep(%d) returned %d\n", tmo, rv)); if (rv == EWOULDBLOCK) { result = AE_TIME; break; } + + /* check if we already awaited enough */ + timelefttv = timeouttv; + getmicrotime(¤ttv); + timevalsub(&timelefttv, ¤ttv); + if (timelefttv.tv_sec < 0) { + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "await semaphore %p timeout\n", as)); + result = AE_TIME; + break; + } + + /* adjust timeout for the next sleep */ + tmo = (timelefttv.tv_sec * 1000000 + timelefttv.tv_usec) / (1000000 / hz); + if (tmo <= 0) + tmo = 1; + + if (acpi_semaphore_debug) { + printf("%s: Wakeup timeleft(%lu, %lu), tmo %u, semaphore %p, thread %d\n", + __func__, timelefttv.tv_sec, timelefttv.tv_usec, tmo, as, AcpiOsGetThreadId()); + } + } + + if (acpi_semaphore_debug) { + if (result == AE_TIME && Timeout > 0) { + printf("%s: Timeout %d, pending %d, semaphore %p\n", + __func__, Timeout, as->as_pendings, as); + } + if (result == AE_OK && (as->as_timeouts > 0 || as->as_pendings > 0)) { + printf("%s: Acquire %d, units %d, pending %d, semaphore %p, thread %d\n", + __func__, Units, as->as_units, as->as_pendings, as, AcpiOsGetThreadId()); + } + } + + if (result == AE_TIME) { + as->as_timeouts++; + } else { + as->as_timeouts = 0; } + mtx_unlock(&as->as_mtx); return_ACPI_STATUS(result); @@ -179,13 +294,20 @@ AcpiOsSignalSemaphore(ACPI_HANDLE Handle, UINT32 Units) return_ACPI_STATUS(AE_BAD_PARAMETER); mtx_lock(&as->as_mtx); - DEBUG_PRINT(TRACE_MUTEX, ("return %d units to semaphore %p (has %d)\n", - Units, as, as->as_units)); + ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, + "return %d units to semaphore %p (has %d)\n", + Units, as, as->as_units)); if (as->as_units != ACPI_NO_UNIT_LIMIT) { as->as_units += Units; if (as->as_units > as->as_maxunits) as->as_units = as->as_maxunits; } + + if (acpi_semaphore_debug && (as->as_timeouts > 0 || as->as_pendings > 0)) { + printf("%s: Release %d, units %d, pending %d, semaphore %p, thread %d\n", + __func__, Units, as->as_units, as->as_pendings, as, AcpiOsGetThreadId()); + } + wakeup(as); mtx_unlock(&as->as_mtx); return_ACPI_STATUS(AE_OK); diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index 5bbc688..6ebce70 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -471,6 +471,12 @@ acpi_attach(device_t dev) acpi_EnterDebugger(); #endif +#if defined(ACPI_MAX_THREADS) && ACPI_MAX_THREADS > 0 + if ((error = acpi_task_thread_init())) { + goto out; + } +#endif + if ((error = acpi_machdep_init(dev))) { goto out; } @@ -1078,7 +1084,7 @@ acpi_GetTableIntoBuffer(ACPI_TABLE_TYPE table, UINT32 instance, ACPI_BUFFER *buf /* * Perform the tedious double-evaluate procedure for evaluating something into - * an ACPI_BUFFER that has not been initialised. Note that this evaluates + * an ACPI_BUFFER if it has not been initialised. Note that this evaluates * twice, so avoid applying this to things that may have side-effects. * * This is like AcpiEvaluateObject with automatic buffer allocation. @@ -1091,11 +1097,10 @@ acpi_EvaluateIntoBuffer(ACPI_HANDLE object, ACPI_STRING pathname, ACPI_OBJECT_LI ACPI_ASSERTLOCK; - buf->Length = 0; - buf->Pointer = NULL; - if ((status = AcpiEvaluateObject(object, pathname, params, buf)) != AE_BUFFER_OVERFLOW) return(status); + if (buf->Pointer != NULL) + AcpiOsFree(buf->Pointer); if ((buf->Pointer = AcpiOsCallocate(buf->Length)) == NULL) return(AE_NO_MEMORY); return(AcpiEvaluateObject(object, pathname, params, buf)); @@ -1109,8 +1114,7 @@ acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int *number) { ACPI_STATUS error; ACPI_BUFFER buf; - ACPI_OBJECT param, *p; - int i; + ACPI_OBJECT param; ACPI_ASSERTLOCK; @@ -1144,18 +1148,7 @@ acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int *number) error = AE_NO_MEMORY; } else { if ((error = AcpiEvaluateObject(handle, path, NULL, &buf)) == AE_OK) { - p = (ACPI_OBJECT *)buf.Pointer; - if (p->Type != ACPI_TYPE_BUFFER) { - error = AE_TYPE; - } else { - if (p->Buffer.Length > sizeof(int)) { - error = AE_BAD_DATA; - } else { - *number = 0; - for (i = 0; i < p->Buffer.Length; i++) - *number += (*(p->Buffer.Pointer + i) << (i * 8)); - } - } + error = acpi_ConvertBufferToInteger(&buf, number); } } AcpiOsFree(buf.Pointer); @@ -1163,6 +1156,27 @@ acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int *number) return(error); } +ACPI_STATUS +acpi_ConvertBufferToInteger(ACPI_BUFFER *bufp, int *number) +{ + ACPI_OBJECT *p; + int i; + + p = (ACPI_OBJECT *)bufp->Pointer; + if (p->Type == ACPI_TYPE_INTEGER) { + *number = p->Integer.Value; + return(AE_OK); + } + if (p->Type != ACPI_TYPE_BUFFER) + return(AE_TYPE); + if (p->Buffer.Length > sizeof(int)) + return(AE_BAD_DATA); + *number = 0; + for (i = 0; i < p->Buffer.Length; i++) + *number += (*(p->Buffer.Pointer + i) << (i * 8)); + return(AE_OK); +} + /* * Iterate over the elements of an a package object, calling the supplied * function for each element. diff --git a/sys/dev/acpica/acpi_cmbat.c b/sys/dev/acpica/acpi_cmbat.c index dc78c42..ccab956 100644 --- a/sys/dev/acpica/acpi_cmbat.c +++ b/sys/dev/acpica/acpi_cmbat.c @@ -108,6 +108,8 @@ struct acpi_cmbat_softc { ACPI_BUFFER bst_buffer; struct timespec bif_lastupdated; struct timespec bst_lastupdated; + int bif_updating; + int bst_updating; int not_present; int cap; @@ -195,42 +197,17 @@ acpi_cmbat_get_bst(void *context) return; } - untimeout(acpi_cmbat_timeout, (caddr_t)dev, sc->cmbat_timeout); -retry: - if (sc->bst_buffer.Length == 0) { - if (sc->bst_buffer.Pointer != NULL) { - free(sc->bst_buffer.Pointer, M_ACPICMBAT); - sc->bst_buffer.Pointer = NULL; - } - as = AcpiEvaluateObject(h, "_BST", NULL, &sc->bst_buffer); - if (as != AE_BUFFER_OVERFLOW) { - ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "couldn't find _BST - %s\n", AcpiFormatException(as)); - goto end; - } - - sc->bst_buffer.Pointer = malloc(sc->bst_buffer.Length, M_ACPICMBAT, M_NOWAIT); - if (sc->bst_buffer.Pointer == NULL) { - device_printf(dev, "malloc failed"); - goto end; - } + if (sc->bst_updating) { + return; } + sc->bst_updating = 1; - bzero(sc->bst_buffer.Pointer, sc->bst_buffer.Length); - as = AcpiEvaluateObject(h, "_BST", NULL, &sc->bst_buffer); + untimeout(acpi_cmbat_timeout, (caddr_t)dev, sc->cmbat_timeout); - if (as == AE_BUFFER_OVERFLOW) { - if (sc->bst_buffer.Pointer != NULL) { - free(sc->bst_buffer.Pointer, M_ACPICMBAT); - sc->bst_buffer.Pointer = NULL; - } - ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "bst size changed to %d\n", sc->bst_buffer.Length); - sc->bst_buffer.Length = 0; - goto retry; - } else if (as != AE_OK) { + if ((as = acpi_EvaluateIntoBuffer(h, "_BST", NULL, &sc->bst_buffer)) != AE_OK) { ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "couldn't find _BST - %s\n", AcpiFormatException(as)); + "error fetching current battery status -- %s\n", + AcpiFormatException(as)); goto end; } @@ -248,6 +225,7 @@ retry: PKG_GETINT(res, tmp, 3, sc->bst.volt, end); acpi_cmbat_info_updated(&sc->bst_lastupdated); end: + sc->bst_updating = 0; sc->cmbat_timeout = timeout(acpi_cmbat_timeout, dev, CMBAT_POLLRATE); } @@ -268,42 +246,17 @@ acpi_cmbat_get_bif(void *context) return; } - untimeout(acpi_cmbat_timeout, (caddr_t)dev, sc->cmbat_timeout); -retry: - if (sc->bif_buffer.Length == 0) { - if (sc->bif_buffer.Pointer != NULL) { - free(sc->bif_buffer.Pointer, M_ACPICMBAT); - sc->bif_buffer.Pointer = NULL; - } - as = AcpiEvaluateObject(h, "_BIF", NULL, &sc->bif_buffer); - if (as != AE_BUFFER_OVERFLOW) { - ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "couldn't find _BIF - %s\n", AcpiFormatException(as)); - goto end; - } - - sc->bif_buffer.Pointer = malloc(sc->bif_buffer.Length, M_ACPICMBAT, M_NOWAIT); - if (sc->bif_buffer.Pointer == NULL) { - device_printf(dev, "malloc failed"); - goto end; - } + if (sc->bif_updating) { + return; } + sc->bif_updating = 1; - bzero(sc->bif_buffer.Pointer, sc->bif_buffer.Length); - as = AcpiEvaluateObject(h, "_BIF", NULL, &sc->bif_buffer); + untimeout(acpi_cmbat_timeout, (caddr_t)dev, sc->cmbat_timeout); - if (as == AE_BUFFER_OVERFLOW) { - if (sc->bif_buffer.Pointer != NULL) { - free(sc->bif_buffer.Pointer, M_ACPICMBAT); - sc->bif_buffer.Pointer = NULL; - } - ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "bif size changed to %d\n", sc->bif_buffer.Length); - sc->bif_buffer.Length = 0; - goto retry; - } else if (as != AE_OK) { + if ((as = acpi_EvaluateIntoBuffer(h, "_BIF", NULL, &sc->bif_buffer)) != AE_OK) { ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), - "couldn't find _BIF - %s\n", AcpiFormatException(as)); + "error fetching current battery info -- %s\n", + AcpiFormatException(as)); goto end; } @@ -330,6 +283,7 @@ retry: PKG_GETSTR(res, tmp, 12, sc->bif.oeminfo, ACPI_CMBAT_MAXSTRLEN, end); acpi_cmbat_info_updated(&sc->bif_lastupdated); end: + sc->bif_updating = 0; sc->cmbat_timeout = timeout(acpi_cmbat_timeout, dev, CMBAT_POLLRATE); } @@ -391,6 +345,7 @@ acpi_cmbat_attach(device_t dev) bzero(&sc->bif_buffer, sizeof(sc->bif_buffer)); bzero(&sc->bst_buffer, sizeof(sc->bst_buffer)); + sc->bif_updating = sc->bst_updating = 0; sc->dev = dev; timespecclear(&sc->bif_lastupdated); diff --git a/sys/dev/acpica/acpi_ec.c b/sys/dev/acpica/acpi_ec.c index adc09a6..331d389 100644 --- a/sys/dev/acpica/acpi_ec.c +++ b/sys/dev/acpica/acpi_ec.c @@ -251,7 +251,9 @@ EcLock(struct acpi_ec_softc *sc) ACPI_STATUS status; status = AcpiAcquireGlobalLock(); - (sc)->ec_locked = 1; + if (status == AE_OK) + (sc)->ec_locked = 1; + return(status); } diff --git a/sys/dev/acpica/acpi_powerres.c b/sys/dev/acpica/acpi_powerres.c index a274549..c6415fd 100644 --- a/sys/dev/acpica/acpi_powerres.c +++ b/sys/dev/acpica/acpi_powerres.c @@ -166,6 +166,7 @@ acpi_pwr_register_resource(ACPI_HANDLE res) rp->ap_resource = res; /* get the Power Resource object */ + bzero(&buf, sizeof(buf)); if ((status = acpi_EvaluateIntoBuffer(res, NULL, NULL, &buf)) != AE_OK) { ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "no power resource object\n")); goto out; @@ -373,6 +374,7 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state) if (AcpiGetHandle(consumer, "_PR0", &pr0_handle) != AE_OK) { goto bad; } + bzero(&reslist_buffer, sizeof(reslist_buffer)); status = acpi_EvaluateIntoBuffer(pr0_handle, NULL, NULL, &reslist_buffer); if (status != AE_OK) { goto bad; @@ -389,6 +391,7 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state) * Check that we can actually fetch the list of power resources */ if (reslist_handle != NULL) { + bzero(&reslist_buffer, sizeof(reslist_buffer)); if ((status = acpi_EvaluateIntoBuffer(reslist_handle, NULL, NULL, &reslist_buffer)) != AE_OK) { ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "can't evaluate resource list %s\n", acpi_name(reslist_handle))); diff --git a/sys/dev/acpica/acpi_thermal.c b/sys/dev/acpica/acpi_thermal.c index a2e10c8..9cde5f4 100644 --- a/sys/dev/acpica/acpi_thermal.c +++ b/sys/dev/acpica/acpi_thermal.c @@ -51,7 +51,7 @@ MODULE_NAME("THERMAL") #define TZ_NOTIFY_DEVICES 0x81 #define TZ_NOTIFY_LEVELS 0x82 -#define TZ_POLLRATE (hz * 10) /* every ten seconds */ +#define TZ_POLLRATE 30 /* every 30 seconds by default */ #define TZ_NUMLEVELS 10 /* defined by ACPI spec */ struct acpi_tz_zone { @@ -90,6 +90,8 @@ struct acpi_tz_softc { struct sysctl_oid *tz_sysctl_tree; struct acpi_tz_zone tz_zone; /* thermal zone parameters */ + ACPI_BUFFER tz_tmp_buffer; + int tz_tmp_updating; }; static int acpi_tz_probe(device_t dev); @@ -127,6 +129,7 @@ static struct sysctl_ctx_list acpi_tz_sysctl_ctx; static struct sysctl_oid *acpi_tz_sysctl_tree; static int acpi_tz_min_runtime = 0;/* minimum cooling run time */ +static int acpi_tz_polling_rate = TZ_POLLRATE; /* * Match an ACPI thermal zone. @@ -170,6 +173,8 @@ acpi_tz_attach(device_t dev) sc->tz_dev = dev; sc->tz_handle = acpi_get_handle(dev); sc->tz_requested = TZ_ACTIVE_NONE; + bzero(&sc->tz_tmp_buffer, sizeof(sc->tz_tmp_buffer)); + sc->tz_tmp_updating = 0; /* * Parse the current state of the thermal zone and build control @@ -199,6 +204,10 @@ acpi_tz_attach(device_t dev) SYSCTL_CHILDREN(acpi_tz_sysctl_tree), OID_AUTO, "min_runtime", CTLFLAG_RD | CTLFLAG_RW, &acpi_tz_min_runtime, 0, "minimum cooling run time in sec"); + SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx, + SYSCTL_CHILDREN(acpi_tz_sysctl_tree), + OID_AUTO, "polling_rate", CTLFLAG_RD | CTLFLAG_RW, + &acpi_tz_polling_rate, 0, "monitor polling rate"); } sysctl_ctx_init(&sc->tz_sysctl_ctx); sprintf(oidname, "tz%d", device_get_unit(dev)); @@ -249,7 +258,7 @@ acpi_tz_attach(device_t dev) * Start the timeout routine, with enough delay for the rest of the * subsystem to come up. */ - sc->tz_timeout = timeout(acpi_tz_timeout, sc, TZ_POLLRATE); + sc->tz_timeout = timeout(acpi_tz_timeout, sc, acpi_tz_polling_rate * hz); return_VALUE(error); } @@ -288,6 +297,7 @@ acpi_tz_establish(struct acpi_tz_softc *sc) sprintf(nbuf, "_AC%d", i); acpi_tz_getparam(sc, nbuf, &sc->tz_zone.ac[i]); sprintf(nbuf, "_AL%d", i); + bzero(&sc->tz_zone.al[i], sizeof(sc->tz_zone.al[i])); acpi_EvaluateIntoBuffer(sc->tz_handle, nbuf, NULL, &sc->tz_zone.al[i]); obj = (ACPI_OBJECT *)sc->tz_zone.al[i].Pointer; if (obj != NULL) { @@ -301,6 +311,7 @@ acpi_tz_establish(struct acpi_tz_softc *sc) } acpi_tz_getparam(sc, "_CRT", &sc->tz_zone.crt); acpi_tz_getparam(sc, "_HOT", &sc->tz_zone.hot); + bzero(&sc->tz_zone.psl, sizeof(sc->tz_zone.psl)); acpi_EvaluateIntoBuffer(sc->tz_handle, "_PSL", NULL, &sc->tz_zone.psl); acpi_tz_getparam(sc, "_PSV", &sc->tz_zone.psv); acpi_tz_getparam(sc, "_TC1", &sc->tz_zone.tc1); @@ -358,16 +369,29 @@ acpi_tz_monitor(struct acpi_tz_softc *sc) ACPI_ASSERTLOCK; + if (sc->tz_tmp_updating) { + goto out; + } + sc->tz_tmp_updating = 1; + /* * Get the current temperature. */ - if ((status = acpi_EvaluateInteger(sc->tz_handle, "_TMP", &temp)) != AE_OK) { + if ((status = acpi_EvaluateIntoBuffer(sc->tz_handle, "_TMP", NULL, &sc->tz_tmp_buffer)) != AE_OK) { ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev), "error fetching current temperature -- %s\n", AcpiFormatException(status)); /* XXX disable zone? go to max cooling? */ - return_VOID; + goto out; } + if ((status = acpi_ConvertBufferToInteger(&sc->tz_tmp_buffer, &temp)) != AE_OK) { + ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev), + "error fetching current temperature -- %s\n", + AcpiFormatException(status)); + /* XXX disable zone? go to max cooling? */ + goto out; + } + ACPI_DEBUG_PRINT((ACPI_DB_VALUES, "got %d.%dC\n", TZ_KELVTOC(temp))); sc->tz_temperature = temp; @@ -454,6 +478,8 @@ acpi_tz_monitor(struct acpi_tz_softc *sc) } sc->tz_thflags = newflags; +out: + sc->tz_tmp_updating = 0; return_VOID; } @@ -693,7 +719,7 @@ acpi_tz_timeout(void *arg) /* XXX passive cooling actions? */ /* re-register ourself */ - sc->tz_timeout = timeout(acpi_tz_timeout, sc, TZ_POLLRATE); + sc->tz_timeout = timeout(acpi_tz_timeout, sc, acpi_tz_polling_rate * hz); ACPI_UNLOCK; } diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h index 6191859..2ab2e15 100644 --- a/sys/dev/acpica/acpivar.h +++ b/sys/dev/acpica/acpivar.h @@ -244,6 +244,7 @@ extern ACPI_STATUS acpi_GetTableIntoBuffer(ACPI_TABLE_TYPE table, UINT32 instanc extern ACPI_STATUS acpi_EvaluateIntoBuffer(ACPI_HANDLE object, ACPI_STRING pathname, ACPI_OBJECT_LIST *params, ACPI_BUFFER *buf); extern ACPI_STATUS acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int *number); +extern ACPI_STATUS acpi_ConvertBufferToInteger(ACPI_BUFFER *bufp, int *number); extern ACPI_STATUS acpi_ForeachPackageObject(ACPI_OBJECT *obj, void (* func)(ACPI_OBJECT *comp, void *arg), void *arg); @@ -362,3 +363,11 @@ extern void powerprofile_set_state(int state); typedef void (*powerprofile_change_hook)(void *); EVENTHANDLER_DECLARE(powerprofile_change, powerprofile_change_hook); + +#ifndef ACPI_NO_THREADS +/* + * ACPI task kernel thread initialization. + */ +extern int acpi_task_thread_init(void); +#endif + diff --git a/sys/modules/acpi/Makefile b/sys/modules/acpi/Makefile index 4b33d7d..42a39df 100644 --- a/sys/modules/acpi/Makefile +++ b/sys/modules/acpi/Makefile @@ -36,6 +36,12 @@ SRCS+= OsdHardware.c OsdInterrupt.c OsdMemory.c OsdSchedule.c SRCS+= OsdStream.c OsdSynch.c OsdEnvironment.c SRCS+= opt_acpi.h opt_ddb.h SRCS+= device_if.h bus_if.h pci_if.h pcib_if.h isa_if.h +.if ACPI_NO_SEMAPHORES +CFLAGS+=-DACPI_NO_SEMAPHORES +.endif +.if ACPI_MAX_THREADS +CFLAGS+=-DACPI_MAX_THREADS=${ACPI_MAX_THREADS} +.endif # Debugging support .if ACPI_DEBUG |