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   ******************************************************************************/
acpi_ex_system_wait_semaphore(acpi_semaphore semaphore,u16 timeout)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(semaphore, 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(semaphore, 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  
acpi_ex_system_wait_mutex(acpi_mutex mutex,u16 timeout)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  
acpi_ex_system_do_stall(u32 how_long_us)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_ONCE((AE_INFO,
137  				 "Time parameter is too large (%u)",
138  				 how_long_us));
139  		status = AE_AML_OPERAND_VALUE;
140  	} else {
141  		if (how_long_us > 100) {
142  			ACPI_WARNING_ONCE((AE_INFO,
143  					   "Time parameter %u us > 100 us violating ACPI spec, please fix the firmware.",
144  					   how_long_us));
145  		}
146  		acpi_os_stall(how_long_us);
147  	}
148  
149  	return (status);
150  }
151  
152  /*******************************************************************************
153   *
154   * FUNCTION:    acpi_ex_system_do_sleep
155   *
156   * PARAMETERS:  how_long_ms     - The amount of time to sleep,
157   *                                in milliseconds
158   *
159   * RETURN:      None
160   *
161   * DESCRIPTION: Sleep the running thread for specified amount of time.
162   *
163   ******************************************************************************/
164  
acpi_ex_system_do_sleep(u64 how_long_ms)165  acpi_status acpi_ex_system_do_sleep(u64 how_long_ms)
166  {
167  	ACPI_FUNCTION_ENTRY();
168  
169  	/* Since this thread will sleep, we must release the interpreter */
170  
171  	acpi_ex_exit_interpreter();
172  
173  	/*
174  	 * For compatibility with other ACPI implementations and to prevent
175  	 * accidental deep sleeps, limit the sleep time to something reasonable.
176  	 */
177  	if (how_long_ms > ACPI_MAX_SLEEP) {
178  		how_long_ms = ACPI_MAX_SLEEP;
179  	}
180  
181  	acpi_os_sleep(how_long_ms);
182  
183  	/* And now we must get the interpreter again */
184  
185  	acpi_ex_enter_interpreter();
186  	return (AE_OK);
187  }
188  
189  /*******************************************************************************
190   *
191   * FUNCTION:    acpi_ex_system_signal_event
192   *
193   * PARAMETERS:  obj_desc        - The object descriptor for this op
194   *
195   * RETURN:      Status
196   *
197   * DESCRIPTION: Provides an access point to perform synchronization operations
198   *              within the AML.
199   *
200   ******************************************************************************/
201  
acpi_ex_system_signal_event(union acpi_operand_object * obj_desc)202  acpi_status acpi_ex_system_signal_event(union acpi_operand_object * obj_desc)
203  {
204  	acpi_status status = AE_OK;
205  
206  	ACPI_FUNCTION_TRACE(ex_system_signal_event);
207  
208  	if (obj_desc) {
209  		status =
210  		    acpi_os_signal_semaphore(obj_desc->event.os_semaphore, 1);
211  	}
212  
213  	return_ACPI_STATUS(status);
214  }
215  
216  /*******************************************************************************
217   *
218   * FUNCTION:    acpi_ex_system_wait_event
219   *
220   * PARAMETERS:  time_desc       - The 'time to delay' object descriptor
221   *              obj_desc        - The object descriptor for this op
222   *
223   * RETURN:      Status
224   *
225   * DESCRIPTION: Provides an access point to perform synchronization operations
226   *              within the AML. This operation is a request to wait for an
227   *              event.
228   *
229   ******************************************************************************/
230  
231  acpi_status
acpi_ex_system_wait_event(union acpi_operand_object * time_desc,union acpi_operand_object * obj_desc)232  acpi_ex_system_wait_event(union acpi_operand_object *time_desc,
233  			  union acpi_operand_object *obj_desc)
234  {
235  	acpi_status status = AE_OK;
236  
237  	ACPI_FUNCTION_TRACE(ex_system_wait_event);
238  
239  	if (obj_desc) {
240  		status =
241  		    acpi_ex_system_wait_semaphore(obj_desc->event.os_semaphore,
242  						  (u16) time_desc->integer.
243  						  value);
244  	}
245  
246  	return_ACPI_STATUS(status);
247  }
248  
249  /*******************************************************************************
250   *
251   * FUNCTION:    acpi_ex_system_reset_event
252   *
253   * PARAMETERS:  obj_desc        - The object descriptor for this op
254   *
255   * RETURN:      Status
256   *
257   * DESCRIPTION: Reset an event to a known state.
258   *
259   ******************************************************************************/
260  
acpi_ex_system_reset_event(union acpi_operand_object * obj_desc)261  acpi_status acpi_ex_system_reset_event(union acpi_operand_object *obj_desc)
262  {
263  	acpi_status status = AE_OK;
264  	acpi_semaphore temp_semaphore;
265  
266  	ACPI_FUNCTION_ENTRY();
267  
268  	/*
269  	 * We are going to simply delete the existing semaphore and
270  	 * create a new one!
271  	 */
272  	status =
273  	    acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore);
274  	if (ACPI_SUCCESS(status)) {
275  		(void)acpi_os_delete_semaphore(obj_desc->event.os_semaphore);
276  		obj_desc->event.os_semaphore = temp_semaphore;
277  	}
278  
279  	return (status);
280  }
281