aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/evmisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpica/evmisc.c')
-rw-r--r--drivers/acpi/acpica/evmisc.c291
1 files changed, 1 insertions, 290 deletions
diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c
index df0aea9a8cfd..d0b331844427 100644
--- a/drivers/acpi/acpica/evmisc.c
+++ b/drivers/acpi/acpica/evmisc.c
@@ -5,7 +5,7 @@
5 *****************************************************************************/ 5 *****************************************************************************/
6 6
7/* 7/*
8 * Copyright (C) 2000 - 2010, Intel Corp. 8 * Copyright (C) 2000 - 2011, Intel Corp.
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
@@ -45,7 +45,6 @@
45#include "accommon.h" 45#include "accommon.h"
46#include "acevents.h" 46#include "acevents.h"
47#include "acnamesp.h" 47#include "acnamesp.h"
48#include "acinterp.h"
49 48
50#define _COMPONENT ACPI_EVENTS 49#define _COMPONENT ACPI_EVENTS
51ACPI_MODULE_NAME("evmisc") 50ACPI_MODULE_NAME("evmisc")
@@ -53,10 +52,6 @@ ACPI_MODULE_NAME("evmisc")
53/* Local prototypes */ 52/* Local prototypes */
54static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context); 53static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context);
55 54
56static u32 acpi_ev_global_lock_handler(void *context);
57
58static acpi_status acpi_ev_remove_global_lock_handler(void);
59
60/******************************************************************************* 55/*******************************************************************************
61 * 56 *
62 * FUNCTION: acpi_ev_is_notify_object 57 * FUNCTION: acpi_ev_is_notify_object
@@ -275,290 +270,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
275 acpi_ut_delete_generic_state(notify_info); 270 acpi_ut_delete_generic_state(notify_info);
276} 271}
277 272
278/*******************************************************************************
279 *
280 * FUNCTION: acpi_ev_global_lock_handler
281 *
282 * PARAMETERS: Context - From thread interface, not used
283 *
284 * RETURN: ACPI_INTERRUPT_HANDLED
285 *
286 * DESCRIPTION: Invoked directly from the SCI handler when a global lock
287 * release interrupt occurs. Attempt to acquire the global lock,
288 * if successful, signal the thread waiting for the lock.
289 *
290 * NOTE: Assumes that the semaphore can be signaled from interrupt level. If
291 * this is not possible for some reason, a separate thread will have to be
292 * scheduled to do this.
293 *
294 ******************************************************************************/
295
296static u32 acpi_ev_global_lock_handler(void *context)
297{
298 u8 acquired = FALSE;
299
300 /*
301 * Attempt to get the lock.
302 *
303 * If we don't get it now, it will be marked pending and we will
304 * take another interrupt when it becomes free.
305 */
306 ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired);
307 if (acquired) {
308
309 /* Got the lock, now wake all threads waiting for it */
310
311 acpi_gbl_global_lock_acquired = TRUE;
312 /* Send a unit to the semaphore */
313
314 if (ACPI_FAILURE
315 (acpi_os_signal_semaphore
316 (acpi_gbl_global_lock_semaphore, 1))) {
317 ACPI_ERROR((AE_INFO,
318 "Could not signal Global Lock semaphore"));
319 }
320 }
321
322 return (ACPI_INTERRUPT_HANDLED);
323}
324
325/*******************************************************************************
326 *
327 * FUNCTION: acpi_ev_init_global_lock_handler
328 *
329 * PARAMETERS: None
330 *
331 * RETURN: Status
332 *
333 * DESCRIPTION: Install a handler for the global lock release event
334 *
335 ******************************************************************************/
336
337acpi_status acpi_ev_init_global_lock_handler(void)
338{
339 acpi_status status;
340
341 ACPI_FUNCTION_TRACE(ev_init_global_lock_handler);
342
343 /* Attempt installation of the global lock handler */
344
345 status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL,
346 acpi_ev_global_lock_handler,
347 NULL);
348
349 /*
350 * If the global lock does not exist on this platform, the attempt to
351 * enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick).
352 * Map to AE_OK, but mark global lock as not present. Any attempt to
353 * actually use the global lock will be flagged with an error.
354 */
355 if (status == AE_NO_HARDWARE_RESPONSE) {
356 ACPI_ERROR((AE_INFO,
357 "No response from Global Lock hardware, disabling lock"));
358
359 acpi_gbl_global_lock_present = FALSE;
360 return_ACPI_STATUS(AE_OK);
361 }
362
363 acpi_gbl_global_lock_present = TRUE;
364 return_ACPI_STATUS(status);
365}
366
367/*******************************************************************************
368 *
369 * FUNCTION: acpi_ev_remove_global_lock_handler
370 *
371 * PARAMETERS: None
372 *
373 * RETURN: Status
374 *
375 * DESCRIPTION: Remove the handler for the Global Lock
376 *
377 ******************************************************************************/
378
379static acpi_status acpi_ev_remove_global_lock_handler(void)
380{
381 acpi_status status;
382
383 ACPI_FUNCTION_TRACE(ev_remove_global_lock_handler);
384
385 acpi_gbl_global_lock_present = FALSE;
386 status = acpi_remove_fixed_event_handler(ACPI_EVENT_GLOBAL,
387 acpi_ev_global_lock_handler);
388
389 return_ACPI_STATUS(status);
390}
391
392/******************************************************************************
393 *
394 * FUNCTION: acpi_ev_acquire_global_lock
395 *
396 * PARAMETERS: Timeout - Max time to wait for the lock, in millisec.
397 *
398 * RETURN: Status
399 *
400 * DESCRIPTION: Attempt to gain ownership of the Global Lock.
401 *
402 * MUTEX: Interpreter must be locked
403 *
404 * Note: The original implementation allowed multiple threads to "acquire" the
405 * Global Lock, and the OS would hold the lock until the last thread had
406 * released it. However, this could potentially starve the BIOS out of the
407 * lock, especially in the case where there is a tight handshake between the
408 * Embedded Controller driver and the BIOS. Therefore, this implementation
409 * allows only one thread to acquire the HW Global Lock at a time, and makes
410 * the global lock appear as a standard mutex on the OS side.
411 *
412 *****************************************************************************/
413static acpi_thread_id acpi_ev_global_lock_thread_id;
414static int acpi_ev_global_lock_acquired;
415
416acpi_status acpi_ev_acquire_global_lock(u16 timeout)
417{
418 acpi_status status = AE_OK;
419 u8 acquired = FALSE;
420
421 ACPI_FUNCTION_TRACE(ev_acquire_global_lock);
422
423 /*
424 * Only one thread can acquire the GL at a time, the global_lock_mutex
425 * enforces this. This interface releases the interpreter if we must wait.
426 */
427 status = acpi_ex_system_wait_mutex(
428 acpi_gbl_global_lock_mutex->mutex.os_mutex, 0);
429 if (status == AE_TIME) {
430 if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) {
431 acpi_ev_global_lock_acquired++;
432 return AE_OK;
433 }
434 }
435
436 if (ACPI_FAILURE(status)) {
437 status = acpi_ex_system_wait_mutex(
438 acpi_gbl_global_lock_mutex->mutex.os_mutex,
439 timeout);
440 }
441 if (ACPI_FAILURE(status)) {
442 return_ACPI_STATUS(status);
443 }
444
445 acpi_ev_global_lock_thread_id = acpi_os_get_thread_id();
446 acpi_ev_global_lock_acquired++;
447
448 /*
449 * Update the global lock handle and check for wraparound. The handle is
450 * only used for the external global lock interfaces, but it is updated
451 * here to properly handle the case where a single thread may acquire the
452 * lock via both the AML and the acpi_acquire_global_lock interfaces. The
453 * handle is therefore updated on the first acquire from a given thread
454 * regardless of where the acquisition request originated.
455 */
456 acpi_gbl_global_lock_handle++;
457 if (acpi_gbl_global_lock_handle == 0) {
458 acpi_gbl_global_lock_handle = 1;
459 }
460
461 /*
462 * Make sure that a global lock actually exists. If not, just treat the
463 * lock as a standard mutex.
464 */
465 if (!acpi_gbl_global_lock_present) {
466 acpi_gbl_global_lock_acquired = TRUE;
467 return_ACPI_STATUS(AE_OK);
468 }
469
470 /* Attempt to acquire the actual hardware lock */
471
472 ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired);
473 if (acquired) {
474
475 /* We got the lock */
476
477 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
478 "Acquired hardware Global Lock\n"));
479
480 acpi_gbl_global_lock_acquired = TRUE;
481 return_ACPI_STATUS(AE_OK);
482 }
483
484 /*
485 * Did not get the lock. The pending bit was set above, and we must now
486 * wait until we get the global lock released interrupt.
487 */
488 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n"));
489
490 /*
491 * Wait for handshake with the global lock interrupt handler.
492 * This interface releases the interpreter if we must wait.
493 */
494 status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore,
495 ACPI_WAIT_FOREVER);
496
497 return_ACPI_STATUS(status);
498}
499
500/*******************************************************************************
501 *
502 * FUNCTION: acpi_ev_release_global_lock
503 *
504 * PARAMETERS: None
505 *
506 * RETURN: Status
507 *
508 * DESCRIPTION: Releases ownership of the Global Lock.
509 *
510 ******************************************************************************/
511
512acpi_status acpi_ev_release_global_lock(void)
513{
514 u8 pending = FALSE;
515 acpi_status status = AE_OK;
516
517 ACPI_FUNCTION_TRACE(ev_release_global_lock);
518
519 /* Lock must be already acquired */
520
521 if (!acpi_gbl_global_lock_acquired) {
522 ACPI_WARNING((AE_INFO,
523 "Cannot release the ACPI Global Lock, it has not been acquired"));
524 return_ACPI_STATUS(AE_NOT_ACQUIRED);
525 }
526
527 acpi_ev_global_lock_acquired--;
528 if (acpi_ev_global_lock_acquired > 0) {
529 return AE_OK;
530 }
531
532 if (acpi_gbl_global_lock_present) {
533
534 /* Allow any thread to release the lock */
535
536 ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_FACS, pending);
537
538 /*
539 * If the pending bit was set, we must write GBL_RLS to the control
540 * register
541 */
542 if (pending) {
543 status =
544 acpi_write_bit_register
545 (ACPI_BITREG_GLOBAL_LOCK_RELEASE,
546 ACPI_ENABLE_EVENT);
547 }
548
549 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
550 "Released hardware Global Lock\n"));
551 }
552
553 acpi_gbl_global_lock_acquired = FALSE;
554
555 /* Release the local GL mutex */
556 acpi_ev_global_lock_thread_id = NULL;
557 acpi_ev_global_lock_acquired = 0;
558 acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex);
559 return_ACPI_STATUS(status);
560}
561
562/****************************************************************************** 273/******************************************************************************
563 * 274 *
564 * FUNCTION: acpi_ev_terminate 275 * FUNCTION: acpi_ev_terminate