162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
262306a36Sopenharmony_ci/******************************************************************************
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Module Name: exsystem - Interface to OS services
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci *****************************************************************************/
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <acpi/acpi.h>
1162306a36Sopenharmony_ci#include "accommon.h"
1262306a36Sopenharmony_ci#include "acinterp.h"
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#define _COMPONENT          ACPI_EXECUTER
1562306a36Sopenharmony_ciACPI_MODULE_NAME("exsystem")
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/*******************************************************************************
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * FUNCTION:    acpi_ex_system_wait_semaphore
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci * PARAMETERS:  semaphore       - Semaphore to wait on
2262306a36Sopenharmony_ci *              timeout         - Max time to wait
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * RETURN:      Status
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci * DESCRIPTION: Implements a semaphore wait with a check to see if the
2762306a36Sopenharmony_ci *              semaphore is available immediately. If it is not, the
2862306a36Sopenharmony_ci *              interpreter is released before waiting.
2962306a36Sopenharmony_ci *
3062306a36Sopenharmony_ci ******************************************************************************/
3162306a36Sopenharmony_ciacpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	acpi_status status;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ex_system_wait_semaphore);
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	status = acpi_os_wait_semaphore(semaphore, 1, ACPI_DO_NOT_WAIT);
3862306a36Sopenharmony_ci	if (ACPI_SUCCESS(status)) {
3962306a36Sopenharmony_ci		return_ACPI_STATUS(status);
4062306a36Sopenharmony_ci	}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	if (status == AE_TIME) {
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci		/* We must wait, so unlock the interpreter */
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci		acpi_ex_exit_interpreter();
4762306a36Sopenharmony_ci		status = acpi_os_wait_semaphore(semaphore, 1, timeout);
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
5062306a36Sopenharmony_ci				  "*** Thread awake after blocking, %s\n",
5162306a36Sopenharmony_ci				  acpi_format_exception(status)));
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci		/* Reacquire the interpreter */
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci		acpi_ex_enter_interpreter();
5662306a36Sopenharmony_ci	}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	return_ACPI_STATUS(status);
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci/*******************************************************************************
6262306a36Sopenharmony_ci *
6362306a36Sopenharmony_ci * FUNCTION:    acpi_ex_system_wait_mutex
6462306a36Sopenharmony_ci *
6562306a36Sopenharmony_ci * PARAMETERS:  mutex           - Mutex to wait on
6662306a36Sopenharmony_ci *              timeout         - Max time to wait
6762306a36Sopenharmony_ci *
6862306a36Sopenharmony_ci * RETURN:      Status
6962306a36Sopenharmony_ci *
7062306a36Sopenharmony_ci * DESCRIPTION: Implements a mutex wait with a check to see if the
7162306a36Sopenharmony_ci *              mutex is available immediately. If it is not, the
7262306a36Sopenharmony_ci *              interpreter is released before waiting.
7362306a36Sopenharmony_ci *
7462306a36Sopenharmony_ci ******************************************************************************/
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ciacpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	acpi_status status;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ex_system_wait_mutex);
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	status = acpi_os_acquire_mutex(mutex, ACPI_DO_NOT_WAIT);
8362306a36Sopenharmony_ci	if (ACPI_SUCCESS(status)) {
8462306a36Sopenharmony_ci		return_ACPI_STATUS(status);
8562306a36Sopenharmony_ci	}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	if (status == AE_TIME) {
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci		/* We must wait, so unlock the interpreter */
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci		acpi_ex_exit_interpreter();
9262306a36Sopenharmony_ci		status = acpi_os_acquire_mutex(mutex, timeout);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
9562306a36Sopenharmony_ci				  "*** Thread awake after blocking, %s\n",
9662306a36Sopenharmony_ci				  acpi_format_exception(status)));
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci		/* Reacquire the interpreter */
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci		acpi_ex_enter_interpreter();
10162306a36Sopenharmony_ci	}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	return_ACPI_STATUS(status);
10462306a36Sopenharmony_ci}
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci/*******************************************************************************
10762306a36Sopenharmony_ci *
10862306a36Sopenharmony_ci * FUNCTION:    acpi_ex_system_do_stall
10962306a36Sopenharmony_ci *
11062306a36Sopenharmony_ci * PARAMETERS:  how_long_us     - The amount of time to stall,
11162306a36Sopenharmony_ci *                                in microseconds
11262306a36Sopenharmony_ci *
11362306a36Sopenharmony_ci * RETURN:      Status
11462306a36Sopenharmony_ci *
11562306a36Sopenharmony_ci * DESCRIPTION: Suspend running thread for specified amount of time.
11662306a36Sopenharmony_ci *              Note: ACPI specification requires that Stall() does not
11762306a36Sopenharmony_ci *              relinquish the processor, and delays longer than 100 usec
11862306a36Sopenharmony_ci *              should use Sleep() instead. We allow stalls up to 255 usec
11962306a36Sopenharmony_ci *              for compatibility with other interpreters and existing BIOSs.
12062306a36Sopenharmony_ci *
12162306a36Sopenharmony_ci ******************************************************************************/
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ciacpi_status acpi_ex_system_do_stall(u32 how_long_us)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	acpi_status status = AE_OK;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	ACPI_FUNCTION_ENTRY();
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	if (how_long_us > 255) {
13062306a36Sopenharmony_ci		/*
13162306a36Sopenharmony_ci		 * Longer than 255 microseconds, this is an error
13262306a36Sopenharmony_ci		 *
13362306a36Sopenharmony_ci		 * (ACPI specifies 100 usec as max, but this gives some slack in
13462306a36Sopenharmony_ci		 * order to support existing BIOSs)
13562306a36Sopenharmony_ci		 */
13662306a36Sopenharmony_ci		ACPI_ERROR((AE_INFO,
13762306a36Sopenharmony_ci			    "Time parameter is too large (%u)", how_long_us));
13862306a36Sopenharmony_ci		status = AE_AML_OPERAND_VALUE;
13962306a36Sopenharmony_ci	} else {
14062306a36Sopenharmony_ci		if (how_long_us > 100) {
14162306a36Sopenharmony_ci			ACPI_WARNING((AE_INFO,
14262306a36Sopenharmony_ci				      "Time parameter %u us > 100 us violating ACPI spec, please fix the firmware.",
14362306a36Sopenharmony_ci				      how_long_us));
14462306a36Sopenharmony_ci		}
14562306a36Sopenharmony_ci		acpi_os_stall(how_long_us);
14662306a36Sopenharmony_ci	}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	return (status);
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci/*******************************************************************************
15262306a36Sopenharmony_ci *
15362306a36Sopenharmony_ci * FUNCTION:    acpi_ex_system_do_sleep
15462306a36Sopenharmony_ci *
15562306a36Sopenharmony_ci * PARAMETERS:  how_long_ms     - The amount of time to sleep,
15662306a36Sopenharmony_ci *                                in milliseconds
15762306a36Sopenharmony_ci *
15862306a36Sopenharmony_ci * RETURN:      None
15962306a36Sopenharmony_ci *
16062306a36Sopenharmony_ci * DESCRIPTION: Sleep the running thread for specified amount of time.
16162306a36Sopenharmony_ci *
16262306a36Sopenharmony_ci ******************************************************************************/
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ciacpi_status acpi_ex_system_do_sleep(u64 how_long_ms)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	ACPI_FUNCTION_ENTRY();
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	/* Since this thread will sleep, we must release the interpreter */
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	acpi_ex_exit_interpreter();
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	/*
17362306a36Sopenharmony_ci	 * For compatibility with other ACPI implementations and to prevent
17462306a36Sopenharmony_ci	 * accidental deep sleeps, limit the sleep time to something reasonable.
17562306a36Sopenharmony_ci	 */
17662306a36Sopenharmony_ci	if (how_long_ms > ACPI_MAX_SLEEP) {
17762306a36Sopenharmony_ci		how_long_ms = ACPI_MAX_SLEEP;
17862306a36Sopenharmony_ci	}
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	acpi_os_sleep(how_long_ms);
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	/* And now we must get the interpreter again */
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	acpi_ex_enter_interpreter();
18562306a36Sopenharmony_ci	return (AE_OK);
18662306a36Sopenharmony_ci}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci/*******************************************************************************
18962306a36Sopenharmony_ci *
19062306a36Sopenharmony_ci * FUNCTION:    acpi_ex_system_signal_event
19162306a36Sopenharmony_ci *
19262306a36Sopenharmony_ci * PARAMETERS:  obj_desc        - The object descriptor for this op
19362306a36Sopenharmony_ci *
19462306a36Sopenharmony_ci * RETURN:      Status
19562306a36Sopenharmony_ci *
19662306a36Sopenharmony_ci * DESCRIPTION: Provides an access point to perform synchronization operations
19762306a36Sopenharmony_ci *              within the AML.
19862306a36Sopenharmony_ci *
19962306a36Sopenharmony_ci ******************************************************************************/
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ciacpi_status acpi_ex_system_signal_event(union acpi_operand_object * obj_desc)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci	acpi_status status = AE_OK;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ex_system_signal_event);
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	if (obj_desc) {
20862306a36Sopenharmony_ci		status =
20962306a36Sopenharmony_ci		    acpi_os_signal_semaphore(obj_desc->event.os_semaphore, 1);
21062306a36Sopenharmony_ci	}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	return_ACPI_STATUS(status);
21362306a36Sopenharmony_ci}
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci/*******************************************************************************
21662306a36Sopenharmony_ci *
21762306a36Sopenharmony_ci * FUNCTION:    acpi_ex_system_wait_event
21862306a36Sopenharmony_ci *
21962306a36Sopenharmony_ci * PARAMETERS:  time_desc       - The 'time to delay' object descriptor
22062306a36Sopenharmony_ci *              obj_desc        - The object descriptor for this op
22162306a36Sopenharmony_ci *
22262306a36Sopenharmony_ci * RETURN:      Status
22362306a36Sopenharmony_ci *
22462306a36Sopenharmony_ci * DESCRIPTION: Provides an access point to perform synchronization operations
22562306a36Sopenharmony_ci *              within the AML. This operation is a request to wait for an
22662306a36Sopenharmony_ci *              event.
22762306a36Sopenharmony_ci *
22862306a36Sopenharmony_ci ******************************************************************************/
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ciacpi_status
23162306a36Sopenharmony_ciacpi_ex_system_wait_event(union acpi_operand_object *time_desc,
23262306a36Sopenharmony_ci			  union acpi_operand_object *obj_desc)
23362306a36Sopenharmony_ci{
23462306a36Sopenharmony_ci	acpi_status status = AE_OK;
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ex_system_wait_event);
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	if (obj_desc) {
23962306a36Sopenharmony_ci		status =
24062306a36Sopenharmony_ci		    acpi_ex_system_wait_semaphore(obj_desc->event.os_semaphore,
24162306a36Sopenharmony_ci						  (u16) time_desc->integer.
24262306a36Sopenharmony_ci						  value);
24362306a36Sopenharmony_ci	}
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci	return_ACPI_STATUS(status);
24662306a36Sopenharmony_ci}
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci/*******************************************************************************
24962306a36Sopenharmony_ci *
25062306a36Sopenharmony_ci * FUNCTION:    acpi_ex_system_reset_event
25162306a36Sopenharmony_ci *
25262306a36Sopenharmony_ci * PARAMETERS:  obj_desc        - The object descriptor for this op
25362306a36Sopenharmony_ci *
25462306a36Sopenharmony_ci * RETURN:      Status
25562306a36Sopenharmony_ci *
25662306a36Sopenharmony_ci * DESCRIPTION: Reset an event to a known state.
25762306a36Sopenharmony_ci *
25862306a36Sopenharmony_ci ******************************************************************************/
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ciacpi_status acpi_ex_system_reset_event(union acpi_operand_object *obj_desc)
26162306a36Sopenharmony_ci{
26262306a36Sopenharmony_ci	acpi_status status = AE_OK;
26362306a36Sopenharmony_ci	acpi_semaphore temp_semaphore;
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	ACPI_FUNCTION_ENTRY();
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	/*
26862306a36Sopenharmony_ci	 * We are going to simply delete the existing semaphore and
26962306a36Sopenharmony_ci	 * create a new one!
27062306a36Sopenharmony_ci	 */
27162306a36Sopenharmony_ci	status =
27262306a36Sopenharmony_ci	    acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore);
27362306a36Sopenharmony_ci	if (ACPI_SUCCESS(status)) {
27462306a36Sopenharmony_ci		(void)acpi_os_delete_semaphore(obj_desc->event.os_semaphore);
27562306a36Sopenharmony_ci		obj_desc->event.os_semaphore = temp_semaphore;
27662306a36Sopenharmony_ci	}
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	return (status);
27962306a36Sopenharmony_ci}
280