linux/drivers/acpi/acpica/exsystem.c
<<
>>
Prefs
   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 - 2021, Intel Corp.
   7 *
   8 *****************************************************************************/
   9
  10#include <acpi/acpi.h>
  11#include "accommon.h"
  12#include "acinterp.h"
  13
  14#define _COMPONENT          ACPI_EXECUTER
  15ACPI_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 ******************************************************************************/
  31acpi_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
  76acpi_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        - 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
 123acpi_status acpi_ex_system_do_stall(u32 how_long)
 124{
 125        acpi_status status = AE_OK;
 126
 127        ACPI_FUNCTION_ENTRY();
 128
 129        if (how_long > 255) {   /* 255 microseconds */
 130                /*
 131                 * Longer than 255 usec, 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));
 138                status = AE_AML_OPERAND_VALUE;
 139        } else {
 140                acpi_os_stall(how_long);
 141        }
 142
 143        return (status);
 144}
 145
 146/*******************************************************************************
 147 *
 148 * FUNCTION:    acpi_ex_system_do_sleep
 149 *
 150 * PARAMETERS:  how_long        - The amount of time to sleep,
 151 *                                in milliseconds
 152 *
 153 * RETURN:      None
 154 *
 155 * DESCRIPTION: Sleep the running thread for specified amount of time.
 156 *
 157 ******************************************************************************/
 158
 159acpi_status acpi_ex_system_do_sleep(u64 how_long)
 160{
 161        ACPI_FUNCTION_ENTRY();
 162
 163        /* Since this thread will sleep, we must release the interpreter */
 164
 165        acpi_ex_exit_interpreter();
 166
 167        /*
 168         * For compatibility with other ACPI implementations and to prevent
 169         * accidental deep sleeps, limit the sleep time to something reasonable.
 170         */
 171        if (how_long > ACPI_MAX_SLEEP) {
 172                how_long = ACPI_MAX_SLEEP;
 173        }
 174
 175        acpi_os_sleep(how_long);
 176
 177        /* And now we must get the interpreter again */
 178
 179        acpi_ex_enter_interpreter();
 180        return (AE_OK);
 181}
 182
 183/*******************************************************************************
 184 *
 185 * FUNCTION:    acpi_ex_system_signal_event
 186 *
 187 * PARAMETERS:  obj_desc        - The object descriptor for this op
 188 *
 189 * RETURN:      Status
 190 *
 191 * DESCRIPTION: Provides an access point to perform synchronization operations
 192 *              within the AML.
 193 *
 194 ******************************************************************************/
 195
 196acpi_status acpi_ex_system_signal_event(union acpi_operand_object * obj_desc)
 197{
 198        acpi_status status = AE_OK;
 199
 200        ACPI_FUNCTION_TRACE(ex_system_signal_event);
 201
 202        if (obj_desc) {
 203                status =
 204                    acpi_os_signal_semaphore(obj_desc->event.os_semaphore, 1);
 205        }
 206
 207        return_ACPI_STATUS(status);
 208}
 209
 210/*******************************************************************************
 211 *
 212 * FUNCTION:    acpi_ex_system_wait_event
 213 *
 214 * PARAMETERS:  time_desc       - The 'time to delay' object descriptor
 215 *              obj_desc        - The object descriptor for this op
 216 *
 217 * RETURN:      Status
 218 *
 219 * DESCRIPTION: Provides an access point to perform synchronization operations
 220 *              within the AML. This operation is a request to wait for an
 221 *              event.
 222 *
 223 ******************************************************************************/
 224
 225acpi_status
 226acpi_ex_system_wait_event(union acpi_operand_object *time_desc,
 227                          union acpi_operand_object *obj_desc)
 228{
 229        acpi_status status = AE_OK;
 230
 231        ACPI_FUNCTION_TRACE(ex_system_wait_event);
 232
 233        if (obj_desc) {
 234                status =
 235                    acpi_ex_system_wait_semaphore(obj_desc->event.os_semaphore,
 236                                                  (u16) time_desc->integer.
 237                                                  value);
 238        }
 239
 240        return_ACPI_STATUS(status);
 241}
 242
 243/*******************************************************************************
 244 *
 245 * FUNCTION:    acpi_ex_system_reset_event
 246 *
 247 * PARAMETERS:  obj_desc        - The object descriptor for this op
 248 *
 249 * RETURN:      Status
 250 *
 251 * DESCRIPTION: Reset an event to a known state.
 252 *
 253 ******************************************************************************/
 254
 255acpi_status acpi_ex_system_reset_event(union acpi_operand_object *obj_desc)
 256{
 257        acpi_status status = AE_OK;
 258        acpi_semaphore temp_semaphore;
 259
 260        ACPI_FUNCTION_ENTRY();
 261
 262        /*
 263         * We are going to simply delete the existing semaphore and
 264         * create a new one!
 265         */
 266        status =
 267            acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore);
 268        if (ACPI_SUCCESS(status)) {
 269                (void)acpi_os_delete_semaphore(obj_desc->event.os_semaphore);
 270                obj_desc->event.os_semaphore = temp_semaphore;
 271        }
 272
 273        return (status);
 274}
 275