1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /****************************************************************************** |
3 | * |
4 | * Module Name: exsystem - Interface to OS services |
5 | * |
6 | * Copyright (C) 2000 - 2023, Intel Corp. |
7 | * |
8 | *****************************************************************************/ |
9 | |
10 | #include <acpi/acpi.h> |
11 | #include "accommon.h" |
12 | #include "acinterp.h" |
13 | |
14 | #define _COMPONENT ACPI_EXECUTER |
15 | ACPI_MODULE_NAME("exsystem" ) |
16 | |
17 | /******************************************************************************* |
18 | * |
19 | * FUNCTION: acpi_ex_system_wait_semaphore |
20 | * |
21 | * PARAMETERS: semaphore - Semaphore to wait on |
22 | * timeout - Max time to wait |
23 | * |
24 | * RETURN: Status |
25 | * |
26 | * DESCRIPTION: Implements a semaphore wait with a check to see if the |
27 | * semaphore is available immediately. If it is not, the |
28 | * interpreter is released before waiting. |
29 | * |
30 | ******************************************************************************/ |
31 | acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) |
32 | { |
33 | acpi_status status; |
34 | |
35 | ACPI_FUNCTION_TRACE(ex_system_wait_semaphore); |
36 | |
37 | status = acpi_os_wait_semaphore(handle: semaphore, units: 1, ACPI_DO_NOT_WAIT); |
38 | if (ACPI_SUCCESS(status)) { |
39 | return_ACPI_STATUS(status); |
40 | } |
41 | |
42 | if (status == AE_TIME) { |
43 | |
44 | /* We must wait, so unlock the interpreter */ |
45 | |
46 | acpi_ex_exit_interpreter(); |
47 | status = acpi_os_wait_semaphore(handle: semaphore, units: 1, timeout); |
48 | |
49 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
50 | "*** Thread awake after blocking, %s\n" , |
51 | acpi_format_exception(status))); |
52 | |
53 | /* Reacquire the interpreter */ |
54 | |
55 | acpi_ex_enter_interpreter(); |
56 | } |
57 | |
58 | return_ACPI_STATUS(status); |
59 | } |
60 | |
61 | /******************************************************************************* |
62 | * |
63 | * FUNCTION: acpi_ex_system_wait_mutex |
64 | * |
65 | * PARAMETERS: mutex - Mutex to wait on |
66 | * timeout - Max time to wait |
67 | * |
68 | * RETURN: Status |
69 | * |
70 | * DESCRIPTION: Implements a mutex wait with a check to see if the |
71 | * mutex is available immediately. If it is not, the |
72 | * interpreter is released before waiting. |
73 | * |
74 | ******************************************************************************/ |
75 | |
76 | acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) |
77 | { |
78 | acpi_status status; |
79 | |
80 | ACPI_FUNCTION_TRACE(ex_system_wait_mutex); |
81 | |
82 | status = acpi_os_acquire_mutex(mutex, ACPI_DO_NOT_WAIT); |
83 | if (ACPI_SUCCESS(status)) { |
84 | return_ACPI_STATUS(status); |
85 | } |
86 | |
87 | if (status == AE_TIME) { |
88 | |
89 | /* We must wait, so unlock the interpreter */ |
90 | |
91 | acpi_ex_exit_interpreter(); |
92 | status = acpi_os_acquire_mutex(mutex, timeout); |
93 | |
94 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
95 | "*** Thread awake after blocking, %s\n" , |
96 | acpi_format_exception(status))); |
97 | |
98 | /* Reacquire the interpreter */ |
99 | |
100 | acpi_ex_enter_interpreter(); |
101 | } |
102 | |
103 | return_ACPI_STATUS(status); |
104 | } |
105 | |
106 | /******************************************************************************* |
107 | * |
108 | * FUNCTION: acpi_ex_system_do_stall |
109 | * |
110 | * PARAMETERS: how_long_us - The amount of time to stall, |
111 | * in microseconds |
112 | * |
113 | * RETURN: Status |
114 | * |
115 | * DESCRIPTION: Suspend running thread for specified amount of time. |
116 | * Note: ACPI specification requires that Stall() does not |
117 | * relinquish the processor, and delays longer than 100 usec |
118 | * should use Sleep() instead. We allow stalls up to 255 usec |
119 | * for compatibility with other interpreters and existing BIOSs. |
120 | * |
121 | ******************************************************************************/ |
122 | |
123 | acpi_status acpi_ex_system_do_stall(u32 how_long_us) |
124 | { |
125 | acpi_status status = AE_OK; |
126 | |
127 | ACPI_FUNCTION_ENTRY(); |
128 | |
129 | if (how_long_us > 255) { |
130 | /* |
131 | * Longer than 255 microseconds, this is an error |
132 | * |
133 | * (ACPI specifies 100 usec as max, but this gives some slack in |
134 | * order to support existing BIOSs) |
135 | */ |
136 | ACPI_ERROR((AE_INFO, |
137 | "Time parameter is too large (%u)" , how_long_us)); |
138 | status = AE_AML_OPERAND_VALUE; |
139 | } else { |
140 | if (how_long_us > 100) { |
141 | ACPI_WARNING((AE_INFO, |
142 | "Time parameter %u us > 100 us violating ACPI spec, please fix the firmware." , |
143 | how_long_us)); |
144 | } |
145 | acpi_os_stall(microseconds: how_long_us); |
146 | } |
147 | |
148 | return (status); |
149 | } |
150 | |
151 | /******************************************************************************* |
152 | * |
153 | * FUNCTION: acpi_ex_system_do_sleep |
154 | * |
155 | * PARAMETERS: how_long_ms - The amount of time to sleep, |
156 | * in milliseconds |
157 | * |
158 | * RETURN: None |
159 | * |
160 | * DESCRIPTION: Sleep the running thread for specified amount of time. |
161 | * |
162 | ******************************************************************************/ |
163 | |
164 | acpi_status acpi_ex_system_do_sleep(u64 how_long_ms) |
165 | { |
166 | ACPI_FUNCTION_ENTRY(); |
167 | |
168 | /* Since this thread will sleep, we must release the interpreter */ |
169 | |
170 | acpi_ex_exit_interpreter(); |
171 | |
172 | /* |
173 | * For compatibility with other ACPI implementations and to prevent |
174 | * accidental deep sleeps, limit the sleep time to something reasonable. |
175 | */ |
176 | if (how_long_ms > ACPI_MAX_SLEEP) { |
177 | how_long_ms = ACPI_MAX_SLEEP; |
178 | } |
179 | |
180 | acpi_os_sleep(milliseconds: how_long_ms); |
181 | |
182 | /* And now we must get the interpreter again */ |
183 | |
184 | acpi_ex_enter_interpreter(); |
185 | return (AE_OK); |
186 | } |
187 | |
188 | /******************************************************************************* |
189 | * |
190 | * FUNCTION: acpi_ex_system_signal_event |
191 | * |
192 | * PARAMETERS: obj_desc - The object descriptor for this op |
193 | * |
194 | * RETURN: Status |
195 | * |
196 | * DESCRIPTION: Provides an access point to perform synchronization operations |
197 | * within the AML. |
198 | * |
199 | ******************************************************************************/ |
200 | |
201 | acpi_status acpi_ex_system_signal_event(union acpi_operand_object * obj_desc) |
202 | { |
203 | acpi_status status = AE_OK; |
204 | |
205 | ACPI_FUNCTION_TRACE(ex_system_signal_event); |
206 | |
207 | if (obj_desc) { |
208 | status = |
209 | acpi_os_signal_semaphore(handle: obj_desc->event.os_semaphore, units: 1); |
210 | } |
211 | |
212 | return_ACPI_STATUS(status); |
213 | } |
214 | |
215 | /******************************************************************************* |
216 | * |
217 | * FUNCTION: acpi_ex_system_wait_event |
218 | * |
219 | * PARAMETERS: time_desc - The 'time to delay' object descriptor |
220 | * obj_desc - The object descriptor for this op |
221 | * |
222 | * RETURN: Status |
223 | * |
224 | * DESCRIPTION: Provides an access point to perform synchronization operations |
225 | * within the AML. This operation is a request to wait for an |
226 | * event. |
227 | * |
228 | ******************************************************************************/ |
229 | |
230 | acpi_status |
231 | acpi_ex_system_wait_event(union acpi_operand_object *time_desc, |
232 | union acpi_operand_object *obj_desc) |
233 | { |
234 | acpi_status status = AE_OK; |
235 | |
236 | ACPI_FUNCTION_TRACE(ex_system_wait_event); |
237 | |
238 | if (obj_desc) { |
239 | status = |
240 | acpi_ex_system_wait_semaphore(semaphore: obj_desc->event.os_semaphore, |
241 | timeout: (u16) time_desc->integer. |
242 | value); |
243 | } |
244 | |
245 | return_ACPI_STATUS(status); |
246 | } |
247 | |
248 | /******************************************************************************* |
249 | * |
250 | * FUNCTION: acpi_ex_system_reset_event |
251 | * |
252 | * PARAMETERS: obj_desc - The object descriptor for this op |
253 | * |
254 | * RETURN: Status |
255 | * |
256 | * DESCRIPTION: Reset an event to a known state. |
257 | * |
258 | ******************************************************************************/ |
259 | |
260 | acpi_status acpi_ex_system_reset_event(union acpi_operand_object *obj_desc) |
261 | { |
262 | acpi_status status = AE_OK; |
263 | acpi_semaphore temp_semaphore; |
264 | |
265 | ACPI_FUNCTION_ENTRY(); |
266 | |
267 | /* |
268 | * We are going to simply delete the existing semaphore and |
269 | * create a new one! |
270 | */ |
271 | status = |
272 | acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, initial_units: 0, out_handle: &temp_semaphore); |
273 | if (ACPI_SUCCESS(status)) { |
274 | (void)acpi_os_delete_semaphore(handle: obj_desc->event.os_semaphore); |
275 | obj_desc->event.os_semaphore = temp_semaphore; |
276 | } |
277 | |
278 | return (status); |
279 | } |
280 | |