xref: /OK3568_Linux_fs/kernel/drivers/acpi/acpica/exsystem.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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