at v2.6.20 395 lines 12 kB view raw
1 2/****************************************************************************** 3 * 4 * Module Name: exsystem - Interface to OS services 5 * 6 *****************************************************************************/ 7 8/* 9 * Copyright (C) 2000 - 2006, R. Byron Moore 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45#include <acpi/acpi.h> 46#include <acpi/acinterp.h> 47#include <acpi/acevents.h> 48 49#define _COMPONENT ACPI_EXECUTER 50ACPI_MODULE_NAME("exsystem") 51 52/******************************************************************************* 53 * 54 * FUNCTION: acpi_ex_system_wait_semaphore 55 * 56 * PARAMETERS: Semaphore - Semaphore to wait on 57 * Timeout - Max time to wait 58 * 59 * RETURN: Status 60 * 61 * DESCRIPTION: Implements a semaphore wait with a check to see if the 62 * semaphore is available immediately. If it is not, the 63 * interpreter is released before waiting. 64 * 65 ******************************************************************************/ 66acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) 67{ 68 acpi_status status; 69 acpi_status status2; 70 71 ACPI_FUNCTION_TRACE(ex_system_wait_semaphore); 72 73 status = acpi_os_wait_semaphore(semaphore, 1, ACPI_DO_NOT_WAIT); 74 if (ACPI_SUCCESS(status)) { 75 return_ACPI_STATUS(status); 76 } 77 78 if (status == AE_TIME) { 79 80 /* We must wait, so unlock the interpreter */ 81 82 acpi_ex_exit_interpreter(); 83 84 status = acpi_os_wait_semaphore(semaphore, 1, timeout); 85 86 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 87 "*** Thread awake after blocking, %s\n", 88 acpi_format_exception(status))); 89 90 /* Reacquire the interpreter */ 91 92 status2 = acpi_ex_enter_interpreter(); 93 if (ACPI_FAILURE(status2)) { 94 95 /* Report fatal error, could not acquire interpreter */ 96 97 return_ACPI_STATUS(status2); 98 } 99 } 100 101 return_ACPI_STATUS(status); 102} 103 104/******************************************************************************* 105 * 106 * FUNCTION: acpi_ex_system_wait_mutex 107 * 108 * PARAMETERS: Mutex - Mutex to wait on 109 * Timeout - Max time to wait 110 * 111 * RETURN: Status 112 * 113 * DESCRIPTION: Implements a mutex wait with a check to see if the 114 * mutex is available immediately. If it is not, the 115 * interpreter is released before waiting. 116 * 117 ******************************************************************************/ 118 119acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) 120{ 121 acpi_status status; 122 acpi_status status2; 123 124 ACPI_FUNCTION_TRACE(ex_system_wait_mutex); 125 126 status = acpi_os_acquire_mutex(mutex, ACPI_DO_NOT_WAIT); 127 if (ACPI_SUCCESS(status)) { 128 return_ACPI_STATUS(status); 129 } 130 131 if (status == AE_TIME) { 132 133 /* We must wait, so unlock the interpreter */ 134 135 acpi_ex_exit_interpreter(); 136 137 status = acpi_os_acquire_mutex(mutex, timeout); 138 139 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 140 "*** Thread awake after blocking, %s\n", 141 acpi_format_exception(status))); 142 143 /* Reacquire the interpreter */ 144 145 status2 = acpi_ex_enter_interpreter(); 146 if (ACPI_FAILURE(status2)) { 147 148 /* Report fatal error, could not acquire interpreter */ 149 150 return_ACPI_STATUS(status2); 151 } 152 } 153 154 return_ACPI_STATUS(status); 155} 156 157/******************************************************************************* 158 * 159 * FUNCTION: acpi_ex_system_do_stall 160 * 161 * PARAMETERS: how_long - The amount of time to stall, 162 * in microseconds 163 * 164 * RETURN: Status 165 * 166 * DESCRIPTION: Suspend running thread for specified amount of time. 167 * Note: ACPI specification requires that Stall() does not 168 * relinquish the processor, and delays longer than 100 usec 169 * should use Sleep() instead. We allow stalls up to 255 usec 170 * for compatibility with other interpreters and existing BIOSs. 171 * 172 ******************************************************************************/ 173 174acpi_status acpi_ex_system_do_stall(u32 how_long) 175{ 176 acpi_status status = AE_OK; 177 178 ACPI_FUNCTION_ENTRY(); 179 180 if (how_long > 255) { /* 255 microseconds */ 181 /* 182 * Longer than 255 usec, this is an error 183 * 184 * (ACPI specifies 100 usec as max, but this gives some slack in 185 * order to support existing BIOSs) 186 */ 187 ACPI_ERROR((AE_INFO, "Time parameter is too large (%d)", 188 how_long)); 189 status = AE_AML_OPERAND_VALUE; 190 } else { 191 acpi_os_stall(how_long); 192 } 193 194 return (status); 195} 196 197/******************************************************************************* 198 * 199 * FUNCTION: acpi_ex_system_do_suspend 200 * 201 * PARAMETERS: how_long - The amount of time to suspend, 202 * in milliseconds 203 * 204 * RETURN: None 205 * 206 * DESCRIPTION: Suspend running thread for specified amount of time. 207 * 208 ******************************************************************************/ 209 210acpi_status acpi_ex_system_do_suspend(acpi_integer how_long) 211{ 212 acpi_status status; 213 214 ACPI_FUNCTION_ENTRY(); 215 216 /* Since this thread will sleep, we must release the interpreter */ 217 218 acpi_ex_exit_interpreter(); 219 220 acpi_os_sleep(how_long); 221 222 /* And now we must get the interpreter again */ 223 224 status = acpi_ex_enter_interpreter(); 225 return (status); 226} 227 228/******************************************************************************* 229 * 230 * FUNCTION: acpi_ex_system_acquire_mutex 231 * 232 * PARAMETERS: time_desc - Maximum time to wait for the mutex 233 * obj_desc - The object descriptor for this op 234 * 235 * RETURN: Status 236 * 237 * DESCRIPTION: Provides an access point to perform synchronization operations 238 * within the AML. This function will cause a lock to be generated 239 * for the Mutex pointed to by obj_desc. 240 * 241 ******************************************************************************/ 242 243acpi_status 244acpi_ex_system_acquire_mutex(union acpi_operand_object * time_desc, 245 union acpi_operand_object * obj_desc) 246{ 247 acpi_status status = AE_OK; 248 249 ACPI_FUNCTION_TRACE_PTR(ex_system_acquire_mutex, obj_desc); 250 251 if (!obj_desc) { 252 return_ACPI_STATUS(AE_BAD_PARAMETER); 253 } 254 255 /* Support for the _GL_ Mutex object -- go get the global lock */ 256 257 if (obj_desc->mutex.os_mutex == ACPI_GLOBAL_LOCK) { 258 status = 259 acpi_ev_acquire_global_lock((u16) time_desc->integer.value); 260 return_ACPI_STATUS(status); 261 } 262 263 status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, 264 (u16) time_desc->integer.value); 265 return_ACPI_STATUS(status); 266} 267 268/******************************************************************************* 269 * 270 * FUNCTION: acpi_ex_system_release_mutex 271 * 272 * PARAMETERS: obj_desc - The object descriptor for this op 273 * 274 * RETURN: Status 275 * 276 * DESCRIPTION: Provides an access point to perform synchronization operations 277 * within the AML. This operation is a request to release a 278 * previously acquired Mutex. If the Mutex variable is set then 279 * it will be decremented. 280 * 281 ******************************************************************************/ 282 283acpi_status acpi_ex_system_release_mutex(union acpi_operand_object *obj_desc) 284{ 285 acpi_status status = AE_OK; 286 287 ACPI_FUNCTION_TRACE(ex_system_release_mutex); 288 289 if (!obj_desc) { 290 return_ACPI_STATUS(AE_BAD_PARAMETER); 291 } 292 293 /* Support for the _GL_ Mutex object -- release the global lock */ 294 295 if (obj_desc->mutex.os_mutex == ACPI_GLOBAL_LOCK) { 296 status = acpi_ev_release_global_lock(); 297 return_ACPI_STATUS(status); 298 } 299 300 acpi_os_release_mutex(obj_desc->mutex.os_mutex); 301 return_ACPI_STATUS(AE_OK); 302} 303 304/******************************************************************************* 305 * 306 * FUNCTION: acpi_ex_system_signal_event 307 * 308 * PARAMETERS: obj_desc - The object descriptor for this op 309 * 310 * RETURN: Status 311 * 312 * DESCRIPTION: Provides an access point to perform synchronization operations 313 * within the AML. 314 * 315 ******************************************************************************/ 316 317acpi_status acpi_ex_system_signal_event(union acpi_operand_object *obj_desc) 318{ 319 acpi_status status = AE_OK; 320 321 ACPI_FUNCTION_TRACE(ex_system_signal_event); 322 323 if (obj_desc) { 324 status = 325 acpi_os_signal_semaphore(obj_desc->event.os_semaphore, 1); 326 } 327 328 return_ACPI_STATUS(status); 329} 330 331/******************************************************************************* 332 * 333 * FUNCTION: acpi_ex_system_wait_event 334 * 335 * PARAMETERS: time_desc - The 'time to delay' object descriptor 336 * obj_desc - The object descriptor for this op 337 * 338 * RETURN: Status 339 * 340 * DESCRIPTION: Provides an access point to perform synchronization operations 341 * within the AML. This operation is a request to wait for an 342 * event. 343 * 344 ******************************************************************************/ 345 346acpi_status 347acpi_ex_system_wait_event(union acpi_operand_object *time_desc, 348 union acpi_operand_object *obj_desc) 349{ 350 acpi_status status = AE_OK; 351 352 ACPI_FUNCTION_TRACE(ex_system_wait_event); 353 354 if (obj_desc) { 355 status = 356 acpi_ex_system_wait_semaphore(obj_desc->event.os_semaphore, 357 (u16) time_desc->integer. 358 value); 359 } 360 361 return_ACPI_STATUS(status); 362} 363 364/******************************************************************************* 365 * 366 * FUNCTION: acpi_ex_system_reset_event 367 * 368 * PARAMETERS: obj_desc - The object descriptor for this op 369 * 370 * RETURN: Status 371 * 372 * DESCRIPTION: Reset an event to a known state. 373 * 374 ******************************************************************************/ 375 376acpi_status acpi_ex_system_reset_event(union acpi_operand_object *obj_desc) 377{ 378 acpi_status status = AE_OK; 379 acpi_semaphore temp_semaphore; 380 381 ACPI_FUNCTION_ENTRY(); 382 383 /* 384 * We are going to simply delete the existing semaphore and 385 * create a new one! 386 */ 387 status = 388 acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore); 389 if (ACPI_SUCCESS(status)) { 390 (void)acpi_os_delete_semaphore(obj_desc->event.os_semaphore); 391 obj_desc->event.os_semaphore = temp_semaphore; 392 } 393 394 return (status); 395}