Add OS layer ACPI mutex and threading support.

- Temporary fix a bug of Intel ACPI CA core code.
 - Add OS layer ACPI mutex support.  This can be disabled by
   specifying option ACPI_NO_SEMAPHORES.
 - Add ACPI threading support.  Now that we have a dedicate taskqueue for
   ACPI tasks and more ACPI task threads can be created by specifying option
   ACPI_MAX_THREADS.
 - Change acpi_EvaluateIntoBuffer() behavior slightly to reuse given
   caller's buffer unless AE_BUFFER_OVERFLOW occurs.  Also CM battery's
   evaluations were changed to use acpi_EvaluateIntoBuffer().
 - Add new utility function acpi_ConvertBufferToInteger().
 - Add simple locking for CM battery and temperature updating.
 - Fix a minor problem on EC locking.
 - Make the thermal zone polling rate to be changeable.
 - Change minor things on AcpiOsSignal(); in ACPI_SIGNAL_FATAL case,
   entering Debugger is easier to investigate the problem rather than panic.
This commit is contained in:
Mitsuru IWASAKI 2001-12-22 16:05:41 +00:00
parent 1b3d626a13
commit c573e654b7
12 changed files with 379 additions and 120 deletions

View File

@ -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

View File

@ -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);
}
}

View File

@ -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:

View File

@ -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;
free(at, M_ACPITASK);
Function(Context);
free(at, M_ACPITASK);
#endif
return_VOID;
}

View File

@ -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(&currenttv);
timevaladd(&timeouttv, &currenttv);
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(&currenttv);
timevalsub(&timelefttv, &currenttv);
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);

View File

@ -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.

View File

@ -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;
}
if ((as = acpi_EvaluateIntoBuffer(h, "_BST", NULL, &sc->bst_buffer)) != AE_OK) {
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) {
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 @@ acpi_cmbat_get_bst(void *context)
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;
}
if ((as = acpi_EvaluateIntoBuffer(h, "_BIF", NULL, &sc->bif_buffer)) != AE_OK) {
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) {
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 @@ acpi_cmbat_get_bif(void *context)
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);

View File

@ -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);
}

View File

@ -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)));

View File

@ -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;
}

View File

@ -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

View File

@ -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