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