Deleted Added
sdiff udiff text old ( 148318 ) new ( 150003 )
full compact
1/*-
2 * Copyright (c) 2000 Michael Smith
3 * Copyright (c) 2000 BSDi
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28/*
29 * 6.3 : Scheduling services
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/dev/acpica/Osd/OsdSchedule.c 150003 2005-09-11 18:39:03Z obrien $");
34
35#include "opt_acpi.h"
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/bus.h>
39#include <sys/interrupt.h>
40#include <sys/kernel.h>
41#include <sys/kthread.h>
42#include <sys/malloc.h>
43#include <sys/proc.h>
44#include <sys/taskqueue.h>
45#include <machine/clock.h>
46
47#include <contrib/dev/acpica/acpi.h>
48#include <dev/acpica/acpivar.h>
49
50#define _COMPONENT ACPI_OS_SERVICES
51ACPI_MODULE_NAME("SCHEDULE")
52
53/*
54 * Allow the user to tune the number of task threads we start. It seems
55 * some systems have problems with increased parallelism.
56 */
57static int acpi_max_threads = ACPI_MAX_THREADS;
58TUNABLE_INT("debug.acpi.max_threads", &acpi_max_threads);
59
60MALLOC_DEFINE(M_ACPITASK, "acpitask", "ACPI deferred task");
61
62struct acpi_task_ctx {
63 struct task at_task;
64 ACPI_OSD_EXEC_CALLBACK at_function;
65 void *at_context;
66};
67
68/*
69 * Private task queue definition for ACPI
70 */
71static struct proc *
72acpi_task_start_threads(struct taskqueue **tqp)
73{
74 struct proc *acpi_kthread_proc;
75 int err, i;
76
77 KASSERT(*tqp != NULL, ("acpi taskqueue not created before threads"));
78
79 /* Start one or more threads to service our taskqueue. */
80 for (i = 0; i < acpi_max_threads; i++) {
81 err = kthread_create(taskqueue_thread_loop, tqp, &acpi_kthread_proc,
82 0, 0, "acpi_task%d", i);
83 if (err) {
84 printf("%s: kthread_create failed (%d)\n", __func__, err);
85 break;
86 }
87 }
88 return (acpi_kthread_proc);
89}
90
91TASKQUEUE_DEFINE(acpi, taskqueue_thread_enqueue, &taskqueue_acpi,
92 taskqueue_acpi_proc = acpi_task_start_threads(&taskqueue_acpi));
93
94/*
95 * Bounce through this wrapper function since ACPI-CA doesn't understand
96 * the pending argument for its callbacks.
97 */
98static void
99acpi_task_execute(void *context, int pending)
100{
101 struct acpi_task_ctx *at;
102
103 at = (struct acpi_task_ctx *)context;
104 at->at_function(at->at_context);
105 free(at, M_ACPITASK);
106}
107
108/*
109 * This function may be called in interrupt context, i.e. when a GPE fires.
110 * We allocate and queue a task for one of our taskqueue threads to process.
111 */
112ACPI_STATUS
113AcpiOsQueueForExecution(UINT32 Priority, ACPI_OSD_EXEC_CALLBACK Function,
114 void *Context)
115{
116 struct acpi_task_ctx *at;
117 int pri;
118
119 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
120
121 if (Function == NULL)
122 return_ACPI_STATUS (AE_BAD_PARAMETER);
123
124 at = malloc(sizeof(*at), M_ACPITASK, M_NOWAIT);
125 if (at == NULL)
126 return_ACPI_STATUS (AE_NO_MEMORY);
127
128 at->at_function = Function;
129 at->at_context = Context;
130 switch (Priority) {
131 case OSD_PRIORITY_GPE:
132 pri = 4;
133 break;
134 case OSD_PRIORITY_HIGH:
135 pri = 3;
136 break;
137 case OSD_PRIORITY_MED:
138 pri = 2;
139 break;
140 case OSD_PRIORITY_LO:
141 pri = 1;
142 break;
143 default:
144 free(at, M_ACPITASK);
145 return_ACPI_STATUS (AE_BAD_PARAMETER);
146 }
147
148 TASK_INIT(&at->at_task, pri, acpi_task_execute, at);
149 taskqueue_enqueue(taskqueue_acpi, &at->at_task);
150
151 return_ACPI_STATUS (AE_OK);
152}
153
154void
155AcpiOsSleep(ACPI_INTEGER Milliseconds)
156{
157 int timo;
158 static int dummy;
159
160 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
161
162 timo = Milliseconds * hz / 1000;
163
164 /*
165 * If requested sleep time is less than our hz resolution, use
166 * DELAY instead for better granularity.
167 */
168 if (timo > 0)
169 tsleep(&dummy, 0, "acpislp", timo);
170 else
171 DELAY(Milliseconds * 1000);
172
173 return_VOID;
174}
175
176/*
177 * Return the current time in 100 nanosecond units
178 */
179UINT64
180AcpiOsGetTimer(void)
181{
182 struct bintime bt;
183 UINT64 t;
184
185 /* XXX During early boot there is no (decent) timer available yet. */
186 if (cold)
187 panic("acpi: timer op not yet supported during boot");
188
189 binuptime(&bt);
190 t = ((UINT64)10000000 * (uint32_t)(bt.frac >> 32)) >> 32;
191 t += bt.sec * 10000000;
192
193 return (t);
194}
195
196void
197AcpiOsStall(UINT32 Microseconds)
198{
199 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
200
201 DELAY(Microseconds);
202 return_VOID;
203}
204
205UINT32
206AcpiOsGetThreadId(void)
207{
208 struct proc *p;
209
210 /* XXX do not add ACPI_FUNCTION_TRACE here, results in recursive call. */
211
212 p = curproc;
213 KASSERT(p != NULL, ("%s: curproc is NULL!", __func__));
214
215 /* Returning 0 is not allowed. */
216 return (p->p_pid + 1);
217}