summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica/Osd/OsdSchedule.c
diff options
context:
space:
mode:
authoriwasaki <iwasaki@FreeBSD.org>2001-12-22 16:05:41 +0000
committeriwasaki <iwasaki@FreeBSD.org>2001-12-22 16:05:41 +0000
commit4c7abcd3372368396a11a120c259afdb0fe2b015 (patch)
tree7c96c678372cc5f9e23154023196e80b72311f86 /sys/dev/acpica/Osd/OsdSchedule.c
parent23a35cbf8dc1e76d3a4e856806e0ee472c65e5af (diff)
downloadFreeBSD-src-4c7abcd3372368396a11a120c259afdb0fe2b015.zip
FreeBSD-src-4c7abcd3372368396a11a120c259afdb0fe2b015.tar.gz
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.
Diffstat (limited to 'sys/dev/acpica/Osd/OsdSchedule.c')
-rw-r--r--sys/dev/acpica/Osd/OsdSchedule.c131
1 files changed, 125 insertions, 6 deletions
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;
}
OpenPOWER on IntegriCloud