xref: /freebsd/sys/dev/acpica/Osd/OsdSchedule.c (revision 1b6c76a2fe091c74f08427e6c870851025a9cf67)
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  *	$FreeBSD$
28  */
29 
30 /*
31  * 6.3 : Scheduling services
32  */
33 
34 #include "acpi.h"
35 
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/proc.h>
39 #include <sys/taskqueue.h>
40 #include <machine/clock.h>
41 
42 #define _COMPONENT	ACPI_OS_SERVICES
43 MODULE_NAME("SCHEDULE")
44 
45 /*
46  * This is a little complicated due to the fact that we need to build and then
47  * free a 'struct task' for each task we enqueue.
48  *
49  * We use the default taskqueue_swi queue, since it really doesn't matter what
50  * else we're queued along with.
51  */
52 
53 MALLOC_DEFINE(M_ACPITASK, "acpitask", "ACPI deferred task");
54 
55 static void	AcpiOsExecuteQueue(void *arg, int pending);
56 
57 struct acpi_task {
58     struct task			at_task;
59     OSD_EXECUTION_CALLBACK	at_function;
60     void			*at_context;
61 };
62 
63 ACPI_STATUS
64 AcpiOsQueueForExecution(UINT32 Priority, OSD_EXECUTION_CALLBACK Function, void *Context)
65 {
66     struct acpi_task	*at;
67 
68     FUNCTION_TRACE(__func__);
69 
70     if (Function == NULL)
71 	return_ACPI_STATUS(AE_BAD_PARAMETER);
72 
73     at = malloc(sizeof(*at), M_ACPITASK, M_NOWAIT);	/* Interrupt Context */
74     if (at == NULL)
75 	return_ACPI_STATUS(AE_NO_MEMORY);
76     bzero(at, sizeof(*at));
77 
78     at->at_function = Function;
79     at->at_context = Context;
80     at->at_task.ta_func = AcpiOsExecuteQueue;
81     at->at_task.ta_context = at;
82     switch (Priority) {
83     case OSD_PRIORITY_GPE:
84 	at->at_task.ta_priority = 4;
85 	break;
86     case OSD_PRIORITY_HIGH:
87 	at->at_task.ta_priority = 3;
88 	break;
89     case OSD_PRIORITY_MED:
90 	at->at_task.ta_priority = 2;
91 	break;
92     case OSD_PRIORITY_LO:
93 	at->at_task.ta_priority = 1;
94 	break;
95     default:
96 	free(at, M_ACPITASK);
97 	return_ACPI_STATUS(AE_BAD_PARAMETER);
98     }
99 
100     taskqueue_enqueue(taskqueue_swi, (struct task *)at);
101     return_ACPI_STATUS(AE_OK);
102 }
103 
104 static void
105 AcpiOsExecuteQueue(void *arg, int pending)
106 {
107     struct acpi_task		*at = (struct acpi_task *)arg;
108     OSD_EXECUTION_CALLBACK	Function;
109     void			*Context;
110 
111     FUNCTION_TRACE(__func__);
112 
113     Function = (OSD_EXECUTION_CALLBACK)at->at_function;
114     Context = at->at_context;
115 
116     free(at, M_ACPITASK);
117 
118     Function(Context);
119     return_VOID;
120 }
121 
122 /*
123  * We don't have any sleep granularity better than hz, so
124  * make do with that.
125  */
126 void
127 AcpiOsSleep (UINT32 Seconds, UINT32 Milliseconds)
128 {
129     int		timo;
130     static int	dummy;
131 
132     FUNCTION_TRACE(__func__);
133 
134     timo = (Seconds * hz) + Milliseconds * hz / 1000;
135     if (timo == 0)
136 	timo = 1;
137     tsleep(&dummy, 0, "acpislp", timo);
138     return_VOID;
139 }
140 
141 void
142 AcpiOsSleepUsec (UINT32 Microseconds)
143 {
144     FUNCTION_TRACE(__func__);
145 
146     if (Microseconds > 1000) {	/* long enough to be worth the overhead of sleeping */
147 	AcpiOsSleep(0, Microseconds / 1000);
148     } else {
149 	DELAY(Microseconds);
150     }
151     return_VOID;
152 }
153 
154 UINT32
155 AcpiOsGetThreadId (void)
156 {
157     /* XXX do not add FUNCTION_TRACE here, results in recursive call */
158 
159     KASSERT(curproc != NULL, (__func__ ": curproc is NULL!"));
160     return(curproc->p_pid + 1);	/* can't return 0 */
161 }
162